From: Danielle Madeley Date: Fri, 14 Oct 2011 04:27:12 +0000 (+1100) Subject: Merge remote-tracking branch 'pochu/misc-fixes' X-Git-Url: https://git.0d.be/?p=empathy.git;a=commitdiff_plain;h=7b6b8da406493311445f6c2470a005a542972693;hp=-c Merge remote-tracking branch 'pochu/misc-fixes' --- 7b6b8da406493311445f6c2470a005a542972693 diff --combined libempathy-gtk/empathy-call-utils.c index 399647a6,0926230e..adf4987b --- a/libempathy-gtk/empathy-call-utils.c +++ b/libempathy-gtk/empathy-call-utils.c @@@ -55,6 -55,8 +55,8 @@@ get_error_display_message (GError *erro return _("The specified contact is not valid"); case TP_ERROR_EMERGENCY_CALLS_NOT_SUPPORTED: return _("Emergency calls are not supported on this protocol"); + case TP_ERROR_INSUFFICIENT_BALANCE: + return _("You don't have enough credit in order to place this call"); } return _("There was an error starting the call"); @@@ -132,7 -134,6 +134,7 @@@ create_streamed_media_channel_cb (GObje } } +#ifdef HAVE_CALL static void create_call_channel_cb (GObject *source, GAsyncResult *result, @@@ -164,9 -165,8 +166,9 @@@ NULL); } -void -empathy_call_new_with_streams (const gchar *contact, +/* Try to request a Call channel and fallback to StreamedMedia if that fails */ +static void +call_new_with_streams (const gchar *contact, TpAccount *account, gboolean initial_audio, gboolean initial_video, @@@ -175,78 -175,28 +177,78 @@@ GHashTable *call_request, *streamed_media_request; TpAccountChannelRequest *call_req, *streamed_media_req; + /* Call */ call_request = empathy_call_create_call_request (contact, initial_audio, initial_video); + call_req = tp_account_channel_request_new (account, call_request, timestamp); + + g_hash_table_unref (call_request); + + /* StreamedMedia */ streamed_media_request = empathy_call_create_streamed_media_request ( contact, initial_audio, initial_video); - call_req = tp_account_channel_request_new (account, call_request, timestamp); streamed_media_req = tp_account_channel_request_new (account, streamed_media_request, timestamp); + g_hash_table_unref (streamed_media_request); + tp_account_channel_request_create_channel_async (call_req, EMPATHY_CALL_BUS_NAME, NULL, create_call_channel_cb, streamed_media_req); - g_hash_table_unref (call_request); - g_hash_table_unref (streamed_media_request); g_object_unref (call_req); } +#else /* HAVE_CALL */ + +static void +sm_new_with_streams (const gchar *contact, + TpAccount *account, + gboolean initial_audio, + gboolean initial_video, + gint64 timestamp) +{ + GHashTable *streamed_media_request; + TpAccountChannelRequest *streamed_media_req; + + /* StreamedMedia */ + streamed_media_request = empathy_call_create_streamed_media_request ( + contact, initial_audio, initial_video); + + streamed_media_req = tp_account_channel_request_new (account, + streamed_media_request, + timestamp); + + g_hash_table_unref (streamed_media_request); + + tp_account_channel_request_create_channel_async (streamed_media_req, + EMPATHY_AV_BUS_NAME, NULL, create_streamed_media_channel_cb, NULL); + + g_object_unref (streamed_media_req); +} +#endif /* HAVE_CALL */ + +void +empathy_call_new_with_streams (const gchar *contact, + TpAccount *account, + gboolean initial_audio, + gboolean initial_video, + gint64 timestamp) +{ +#ifdef HAVE_CALL + call_new_with_streams (contact, account, initial_audio, initial_video, + timestamp); +#else + sm_new_with_streams (contact, account, initial_audio, initial_video, + timestamp); +#endif +} + void empathy_call_set_stream_properties (GstElement *element) { diff --combined libempathy-gtk/empathy-ui-utils.c index 3fde9e3e,8822ccdf..32ad451a --- a/libempathy-gtk/empathy-ui-utils.c +++ b/libempathy-gtk/empathy-ui-utils.c @@@ -947,6 -947,9 +947,9 @@@ empathy_filename_from_icon_name (const } icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size, 0); + if (icon_info == NULL) + return NULL; + ret = g_strdup (gtk_icon_info_get_filename (icon_info)); gtk_icon_info_free (icon_info); @@@ -1759,8 -1762,7 +1762,8 @@@ empathy_send_file (EmpathyContact *cont factory = empathy_ft_factory_dup_singleton (); - empathy_ft_factory_new_transfer_outgoing (factory, contact, file); + empathy_ft_factory_new_transfer_outgoing (factory, contact, file, + empathy_get_current_action_time ()); uri = g_file_get_uri (file); manager = gtk_recent_manager_get_default (); diff --combined src/empathy-call-window.c index 0a130c4f,05f63e2f..2a92e947 --- a/src/empathy-call-window.c +++ b/src/empathy-call-window.c @@@ -43,7 -43,6 +43,7 @@@ #include #include #include +#include #include #include @@@ -104,12 -103,11 +104,12 @@@ enum }; typedef enum { - CONNECTING, - CONNECTED, - HELD, - DISCONNECTED, - REDIALING + RINGING, /* Incoming call */ + CONNECTING, /* Outgoing call */ + CONNECTED, /* Connected */ + HELD, /* Connected, but on hold */ + DISCONNECTED, /* Disconnected */ + REDIALING /* Redialing (special case of CONNECTING) */ } CallState; typedef enum { @@@ -154,8 -152,6 +154,8 @@@ struct _EmpathyCallWindowPri ClutterActor *preview_rectangle_box2; ClutterActor *preview_rectangle_box3; ClutterActor *preview_rectangle_box4; + ClutterActor *preview_spinner_actor; + GtkWidget *preview_spinner_widget; GtkWidget *video_container; GtkWidget *remote_user_avatar_widget; GtkWidget *remote_user_avatar_toolbar; @@@ -188,22 -184,11 +188,22 @@@ easilly repack everything when toggling fullscreen */ GtkWidget *content_hbox; + /* These are used to accept or reject an incoming call when the status + is RINGING. */ + GtkWidget *incoming_call_dialog; + TpyCallChannel *pending_channel; + TpChannelDispatchOperation *pending_cdo; + TpAddDispatchOperationContext *pending_context; + gulong video_output_motion_handler_id; guint bus_message_source_id; gdouble volume; + /* String that contains the queued tones to send after the current ones + are sent */ + GString *tones; + gboolean sending_tones; GtkWidget *dtmf_panel; /* Details vbox */ @@@ -308,8 -293,6 +308,8 @@@ static gboolean empathy_call_window_vid static void empathy_call_window_video_menu_popup (EmpathyCallWindow *window, guint button); +static void empathy_call_window_connect_handler (EmpathyCallWindow *self); + static void empathy_call_window_dialpad_cb (GtkToggleToolButton *button, EmpathyCallWindow *window); @@@ -352,72 -335,35 +352,72 @@@ empathy_call_window_video_call_cb (GtkT } static void -dtmf_button_pressed_cb (GtkButton *button, EmpathyCallWindow *window) +empathy_call_window_emit_tones (EmpathyCallWindow *self) { - EmpathyCallWindowPriv *priv = GET_PRIV (window); - TpyCallChannel *call; + TpChannel *channel; + + if (tp_str_empty (self->priv->tones->str)) + return; + + g_object_get (self->priv->handler, "call-channel", &channel, NULL); + + DEBUG ("Emitting multiple tones: %s", self->priv->tones->str); + + tp_cli_channel_interface_dtmf_call_multiple_tones (channel, -1, + self->priv->tones->str, + NULL, NULL, NULL, NULL); + + self->priv->sending_tones = TRUE; + + g_string_set_size (self->priv->tones, 0); + + g_object_unref (channel); +} + +static void +empathy_call_window_maybe_emit_tones (EmpathyCallWindow *self) +{ + if (self->priv->sending_tones) + return; + + empathy_call_window_emit_tones (self); +} + +static void +empathy_call_window_tones_stopped_cb (TpChannel *proxy, + gboolean arg_cancelled, + gpointer user_data, + GObject *weak_object) +{ + EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (user_data); + + self->priv->sending_tones = FALSE; + + empathy_call_window_emit_tones (self); +} + +static void +dtmf_button_pressed_cb (GtkButton *button, + EmpathyCallWindow *self) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (self); GQuark button_quark; TpDTMFEvent event; - g_object_get (priv->handler, "call-channel", &call, NULL); - button_quark = g_quark_from_static_string (EMPATHY_DTMF_BUTTON_ID); event = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (button), button_quark)); - tpy_call_channel_dtmf_start_tone (call, event); + g_string_append_c (priv->tones, tp_dtmf_event_to_char (event)); - g_object_unref (call); + empathy_call_window_maybe_emit_tones (self); } +/* empathy_create_dtmf_dialpad() requires a callback, even if empty */ static void -dtmf_button_released_cb (GtkButton *button, EmpathyCallWindow *window) +dtmf_button_released_cb (GtkButton *button, + EmpathyCallWindow *self) { - EmpathyCallWindowPriv *priv = GET_PRIV (window); - TpyCallChannel *call; - - g_object_get (priv->handler, "call-channel", &call, NULL); - - tpy_call_channel_dtmf_stop_tone (call); - - g_object_unref (call); } static void @@@ -754,55 -700,6 +754,55 @@@ empathy_call_window_show_preview_rectan g_object_set (self->priv->preview_rectangle4, "visible", show, NULL); } +static void +empathy_call_window_get_preview_coordinates (EmpathyCallWindow *self, + PreviewPosition pos, + guint *x, + guint *y) +{ + guint ret_x = 0, ret_y = 0; + ClutterGeometry box; + + if (!clutter_actor_has_allocation (self->priv->video_box)) + goto out; + + clutter_actor_get_geometry (self->priv->video_box, &box); + + switch (pos) + { + case PREVIEW_POS_TOP_LEFT: + ret_x = ret_y = SELF_VIDEO_SECTION_MARGIN; + break; + case PREVIEW_POS_TOP_RIGHT: + ret_x = box.width - SELF_VIDEO_SECTION_MARGIN + - SELF_VIDEO_SECTION_WIDTH; + ret_y = SELF_VIDEO_SECTION_MARGIN; + break; + case PREVIEW_POS_BOTTOM_LEFT: + ret_x = SELF_VIDEO_SECTION_MARGIN; + ret_y = box.height - SELF_VIDEO_SECTION_MARGIN + - SELF_VIDEO_SECTION_HEIGHT + - FLOATING_TOOLBAR_HEIGHT - FLOATING_TOOLBAR_SPACING; + break; + case PREVIEW_POS_BOTTOM_RIGHT: + ret_x = box.width - SELF_VIDEO_SECTION_MARGIN + - SELF_VIDEO_SECTION_WIDTH; + ret_y = box.height - SELF_VIDEO_SECTION_MARGIN + - SELF_VIDEO_SECTION_HEIGHT - FLOATING_TOOLBAR_HEIGHT + - FLOATING_TOOLBAR_SPACING; + break; + default: + g_warn_if_reached (); + } + +out: + if (x != NULL) + *x = ret_x; + + if (y != NULL) + *y = ret_y; +} + static PreviewPosition empathy_call_window_get_preview_position (EmpathyCallWindow *self, gfloat event_x, @@@ -1002,13 -899,6 +1002,13 @@@ empathy_call_window_preview_on_drag_beg empathy_call_window_darken_preview_rectangles (self); } +static void +empathy_call_window_on_animation_completed_cb (ClutterAnimation *animation, + ClutterActor *actor) +{ + clutter_actor_set_opacity (actor, 255); +} + static void empathy_call_window_preview_on_drag_end_cb (ClutterDragAction *action, ClutterActor *actor, @@@ -1018,30 -908,18 +1018,30 @@@ EmpathyCallWindow *self) { PreviewPosition pos; + guint x, y; /* Get the position before destroying the drag actor, otherwise the * preview_box allocation won't be valid and we won't be able to * calculate the position. */ pos = empathy_call_window_get_preview_position (self, event_x, event_y); - /* Destroy the video preview copy that we were dragging */ - clutter_actor_destroy (self->priv->drag_preview); - self->priv->drag_preview = NULL; + empathy_call_window_get_preview_coordinates (self, + pos != PREVIEW_POS_NONE ? pos : self->priv->preview_pos, + &x, &y); + + /* Move the preview to the destination and destroy it afterwards */ + clutter_actor_animate (self->priv->drag_preview, CLUTTER_LINEAR, 500, + "x", (gfloat) x, + "y", (gfloat) y, + "signal-swapped-after::completed", + clutter_actor_destroy, self->priv->drag_preview, + "signal-swapped-after::completed", + clutter_actor_show, self->priv->preview_shown_button, + "signal::completed", + empathy_call_window_on_animation_completed_cb, actor, + NULL); - clutter_actor_set_opacity (actor, 255); - clutter_actor_show (self->priv->preview_shown_button); + self->priv->drag_preview = NULL; if (pos != PREVIEW_POS_NONE) empathy_call_window_move_video_preview (self, pos); @@@ -1115,7 -993,6 +1115,7 @@@ create_video_preview (EmpathyCallWindo ClutterAction *action; GtkWidget *button; PreviewPosition pos; + GdkRGBA transparent = { 0., 0., 0., 0. }; g_assert (priv->video_preview == NULL); @@@ -1136,28 -1013,6 +1136,28 @@@ SELF_VIDEO_SECTION_HEIGHT + 2 * SELF_VIDEO_SECTION_MARGIN + FLOATING_TOOLBAR_HEIGHT + FLOATING_TOOLBAR_SPACING); + /* Spinner for when changing the camera device */ + priv->preview_spinner_widget = gtk_spinner_new (); + priv->preview_spinner_actor = empathy_rounded_actor_new (); + empathy_rounded_actor_set_round_factor ( + EMPATHY_ROUNDED_ACTOR (priv->preview_spinner_actor), 16); + + g_object_set (priv->preview_spinner_widget, "expand", TRUE, NULL); + gtk_widget_override_background_color ( + gtk_clutter_actor_get_widget ( + GTK_CLUTTER_ACTOR (priv->preview_spinner_actor)), + GTK_STATE_FLAG_NORMAL, &transparent); + gtk_widget_show (priv->preview_spinner_widget); + + gtk_container_add ( + GTK_CONTAINER (gtk_clutter_actor_get_widget ( + GTK_CLUTTER_ACTOR (priv->preview_spinner_actor))), + priv->preview_spinner_widget); + clutter_actor_set_size (priv->preview_spinner_actor, + SELF_VIDEO_SECTION_WIDTH, SELF_VIDEO_SECTION_HEIGHT); + clutter_actor_set_opacity (priv->preview_spinner_actor, 128); + clutter_actor_hide (priv->preview_spinner_actor); + /* We have a box with the margins and the video in the middle inside * a bigger box with an extra bottom margin so we're not on top of * the floating toolbar. */ @@@ -1169,8 -1024,6 +1169,8 @@@ SELF_VIDEO_SECTION_HEIGHT + 2 * SELF_VIDEO_SECTION_MARGIN); clutter_container_add_actor (CLUTTER_CONTAINER (box), preview); + clutter_container_add_actor (CLUTTER_CONTAINER (box), + priv->preview_spinner_actor); clutter_container_add_actor (CLUTTER_CONTAINER (priv->video_preview), box); g_object_set (priv->video_preview_sink, @@@ -1249,43 -1102,24 +1249,43 @@@ clutter_actor_set_reactive (priv->preview_shown_button, TRUE); } +static void +empathy_call_window_start_camera_spinning (EmpathyCallWindow *self) +{ + clutter_actor_show (self->priv->preview_spinner_actor); + gtk_spinner_start (GTK_SPINNER (self->priv->preview_spinner_widget)); +} + +static void +empathy_call_window_stop_camera_spinning (EmpathyCallWindow *self) +{ + clutter_actor_hide (self->priv->preview_spinner_actor); + gtk_spinner_stop (GTK_SPINNER (self->priv->preview_spinner_widget)); +} + void -empathy_call_window_play_camera (EmpathyCallWindow *window, +empathy_call_window_play_camera (EmpathyCallWindow *self, gboolean play) { - EmpathyCallWindowPriv *priv = GET_PRIV (window); + EmpathyCallWindowPriv *priv = GET_PRIV (self); GstElement *preview; GstState state; if (priv->video_preview == NULL) { - create_video_preview (window); - add_video_preview_to_pipeline (window); + create_video_preview (self); + add_video_preview_to_pipeline (self); } if (play) - state = GST_STATE_PLAYING; + { + state = GST_STATE_PLAYING; + } else - state = GST_STATE_NULL; + { + empathy_call_window_start_camera_spinning (self); + state = GST_STATE_NULL; + } preview = priv->video_preview_sink; @@@ -1523,105 -1357,6 +1523,105 @@@ empathy_call_window_stage_allocation_ch FLOATING_TOOLBAR_SPACING - FLOATING_TOOLBAR_HEIGHT); } +static void +empathy_call_window_incoming_call_response_cb (GtkDialog *dialog, + gint response_id, + EmpathyCallWindow *self) +{ + switch (response_id) + { + case GTK_RESPONSE_ACCEPT: + tp_channel_dispatch_operation_handle_with_async ( + self->priv->pending_cdo, EMPATHY_CALL_BUS_NAME, NULL, NULL); + + tp_clear_object (&self->priv->pending_cdo); + tp_clear_object (&self->priv->pending_channel); + tp_clear_object (&self->priv->pending_context); + + break; + case GTK_RESPONSE_CANCEL: + tp_channel_dispatch_operation_close_channels_async ( + self->priv->pending_cdo, NULL, NULL); + + empathy_call_window_status_message (self, _("Disconnected")); + self->priv->call_state = DISCONNECTED; + break; + default: + g_warn_if_reached (); + } +} + +static void +empathy_call_window_set_state_ringing (EmpathyCallWindow *self) +{ + gboolean video; + + g_assert (self->priv->call_state != CONNECTED); + + video = tpy_call_channel_has_initial_video (self->priv->pending_channel); + + empathy_call_window_status_message (self, _("Incoming call")); + self->priv->call_state = RINGING; + + self->priv->incoming_call_dialog = gtk_message_dialog_new ( + GTK_WINDOW (self), GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, + video ? _("Incoming video call from %s") : _("Incoming call from %s"), + empathy_contact_get_alias (self->priv->contact)); + + gtk_dialog_add_buttons (GTK_DIALOG (self->priv->incoming_call_dialog), + _("Reject"), GTK_RESPONSE_CANCEL, + _("Answer"), GTK_RESPONSE_ACCEPT, + NULL); + + g_signal_connect (self->priv->incoming_call_dialog, "response", + G_CALLBACK (empathy_call_window_incoming_call_response_cb), self); + gtk_widget_show (self->priv->incoming_call_dialog); +} + +static void +empathy_call_window_cdo_invalidated_cb (TpProxy *channel, + guint domain, + gint code, + gchar *message, + EmpathyCallWindow *self) +{ + tp_clear_object (&self->priv->pending_cdo); + tp_clear_object (&self->priv->pending_channel); + tp_clear_object (&self->priv->pending_context); + + /* We don't know if the incoming call has been accepted or not, so we + * assume it hasn't and if it has, we'll set the proper status when + * we get the new handler. */ + empathy_call_window_status_message (self, _("Disconnected")); + self->priv->call_state = DISCONNECTED; + + gtk_widget_destroy (self->priv->incoming_call_dialog); + self->priv->incoming_call_dialog = NULL; +} + +void +empathy_call_window_start_ringing (EmpathyCallWindow *self, + TpyCallChannel *channel, + TpChannelDispatchOperation *dispatch_operation, + TpAddDispatchOperationContext *context) +{ + g_assert (self->priv->pending_channel == NULL); + g_assert (self->priv->pending_context == NULL); + g_assert (self->priv->pending_cdo == NULL); + + /* Start ringing and delay until the user answers or hangs. */ + self->priv->pending_channel = g_object_ref (channel); + self->priv->pending_context = g_object_ref (context); + self->priv->pending_cdo = g_object_ref (dispatch_operation); + + g_signal_connect (self->priv->pending_cdo, "invalidated", + G_CALLBACK (empathy_call_window_cdo_invalidated_cb), self); + + empathy_call_window_set_state_ringing (self); + tp_add_dispatch_operation_context_accept (context); +} + static void empathy_call_window_init (EmpathyCallWindow *self) { @@@ -1638,8 -1373,6 +1638,8 @@@ priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_CALL_WINDOW, EmpathyCallWindowPriv); + priv->settings = g_settings_new (EMPATHY_PREFS_CALL_SCHEMA); + filename = empathy_file_lookup ("empathy-call-window.ui", "src"); gui = empathy_builder_get_file (filename, "call_window_vbox", &top_vbox, @@@ -1823,8 -1556,6 +1823,8 @@@ G_CALLBACK (dtmf_button_pressed_cb), G_CALLBACK (dtmf_button_released_cb)); + priv->tones = g_string_new (""); + gtk_box_pack_start (GTK_BOX (priv->pane), priv->dtmf_panel, FALSE, FALSE, 6); @@@ -1877,6 -1608,8 +1877,6 @@@ empathy_call_window_show_hangup_button (self, TRUE); - priv->settings = g_settings_new (EMPATHY_PREFS_CALL_SCHEMA); - /* Retrieve initial volume */ priv->volume = g_settings_get_double (priv->settings, EMPATHY_PREFS_CALL_SOUND_VOLUME) / 100.0; @@@ -2260,13 -1993,14 +2260,14 @@@ empathy_call_window_constructed (GObjec EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (object); EmpathyCallWindowPriv *priv = GET_PRIV (self); TpyCallChannel *call; + TpyCallState state; g_assert (priv->handler != NULL); g_object_get (priv->handler, "call-channel", &call, NULL); - priv->outgoing = (call == NULL); - if (call != NULL) - g_object_unref (call); + state = tpy_call_channel_get_state (call, NULL, NULL); + priv->outgoing = (state == TPY_CALL_STATE_PENDING_INITIATOR); + tp_clear_object (&call); g_object_get (priv->handler, "target-contact", &priv->contact, NULL); g_assert (priv->contact != NULL); @@@ -2455,8 -2189,6 +2456,8 @@@ empathy_call_window_finalize (GObject * g_timer_destroy (priv->timer); + g_string_free (priv->tones, TRUE); + G_OBJECT_CLASS (empathy_call_window_parent_class)->finalize (object); } @@@ -2468,20 -2200,6 +2469,20 @@@ empathy_call_window_new (EmpathyCallHan g_object_new (EMPATHY_TYPE_CALL_WINDOW, "handler", handler, NULL)); } +void +empathy_call_window_present (EmpathyCallWindow *self, + EmpathyCallHandler *handler) +{ + g_return_if_fail (EMPATHY_IS_CALL_HANDLER (handler)); + + tp_clear_object (&self->priv->handler); + self->priv->handler = g_object_ref (handler); + empathy_call_window_connect_handler (self); + + empathy_window_present (GTK_WINDOW (self)); + empathy_call_window_restart_call (self); +} + static void empathy_call_window_conference_added_cb (EmpathyCallHandler *handler, GstElement *conference, gpointer user_data) @@@ -2607,9 -2325,6 +2608,9 @@@ empathy_call_window_disconnected (Empat gtk_action_set_sensitive (priv->menu_fullscreen, FALSE); gtk_widget_set_sensitive (priv->dtmf_panel, FALSE); + priv->sending_tones = FALSE; + g_string_set_size (priv->tones, 0); + could_reset_pipeline = empathy_call_window_reset_pipeline (self); if (priv->call_state == CONNECTING) @@@ -3426,7 -3141,7 +3427,7 @@@ empathy_call_window_bus_message (GstBu { EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (user_data); EmpathyCallWindowPriv *priv = GET_PRIV (self); - GstState newstate; + GstState newstate, pending; empathy_call_handler_bus_message (priv->handler, bus, message); @@@ -3450,15 -3165,6 +3451,15 @@@ start_call (self); } } + if (GST_MESSAGE_SRC (message) == GST_OBJECT (priv->video_preview_sink)) + { + gst_message_parse_state_changed (message, NULL, &newstate, + &pending); + + if (newstate == GST_STATE_PLAYING && + pending == GST_STATE_VOID_PENDING) + empathy_call_window_stop_camera_spinning (self); + } break; case GST_MESSAGE_ERROR: { @@@ -3563,63 -3269,50 +3564,63 @@@ call_handler_notify_call_cb (EmpathyCal tp_g_signal_connect_object (call, "members-changed", G_CALLBACK (empathy_call_window_members_changed_cb), self, 0); + tp_cli_channel_interface_dtmf_connect_to_stopped_tones (TP_CHANNEL (call), + empathy_call_window_tones_stopped_cb, self, NULL, + G_OBJECT (call), NULL); + g_object_unref (call); } static void -empathy_call_window_realized_cb (GtkWidget *widget, EmpathyCallWindow *window) +empathy_call_window_connect_handler (EmpathyCallWindow *self) { - EmpathyCallWindowPriv *priv = GET_PRIV (window); + EmpathyCallWindowPriv *priv = GET_PRIV (self); TpyCallChannel *call; - gint width; - - /* Make the hangup button twice as wide */ - width = gtk_widget_get_allocated_width (priv->hangup_button); - gtk_widget_set_size_request (priv->hangup_button, width * 2, -1); g_signal_connect (priv->handler, "state-changed", - G_CALLBACK (empathy_call_window_state_changed_cb), window); + G_CALLBACK (empathy_call_window_state_changed_cb), self); g_signal_connect (priv->handler, "conference-added", - G_CALLBACK (empathy_call_window_conference_added_cb), window); + G_CALLBACK (empathy_call_window_conference_added_cb), self); g_signal_connect (priv->handler, "conference-removed", - G_CALLBACK (empathy_call_window_conference_removed_cb), window); + G_CALLBACK (empathy_call_window_conference_removed_cb), self); g_signal_connect (priv->handler, "closed", - G_CALLBACK (empathy_call_window_channel_closed_cb), window); + G_CALLBACK (empathy_call_window_channel_closed_cb), self); g_signal_connect (priv->handler, "src-pad-added", - G_CALLBACK (empathy_call_window_src_added_cb), window); + G_CALLBACK (empathy_call_window_src_added_cb), self); g_signal_connect (priv->handler, "sink-pad-added", - G_CALLBACK (empathy_call_window_sink_added_cb), window); + G_CALLBACK (empathy_call_window_sink_added_cb), self); g_signal_connect (priv->handler, "sink-pad-removed", - G_CALLBACK (empathy_call_window_sink_removed_cb), window); + G_CALLBACK (empathy_call_window_sink_removed_cb), self); + + /* We connect to ::call-channel unconditionally since we'll + * get new channels if we hangup and redial or if we reuse the + * call window. */ + g_signal_connect (priv->handler, "notify::call-channel", + G_CALLBACK (call_handler_notify_call_cb), self); g_object_get (priv->handler, "call-channel", &call, NULL); if (call != NULL) { - call_handler_notify_call_cb (priv->handler, NULL, window); + /* We won't get notify::call-channel for this channel, so + * directly call the callback. */ + call_handler_notify_call_cb (priv->handler, NULL, self); g_object_unref (call); } - else - { - /* call-channel doesn't exist yet, we'll connect signals once it has been - * set */ - g_signal_connect (priv->handler, "notify::call-channel", - G_CALLBACK (call_handler_notify_call_cb), window); - } +} + +static void +empathy_call_window_realized_cb (GtkWidget *widget, + EmpathyCallWindow *self) +{ + gint width; + + /* Make the hangup button twice as wide */ + width = gtk_widget_get_allocated_width (self->priv->hangup_button); + gtk_widget_set_size_request (self->priv->hangup_button, width * 2, -1); + + empathy_call_window_connect_handler (self); - gst_element_set_state (priv->pipeline, GST_STATE_PAUSED); + gst_element_set_state (self->priv->pipeline, GST_STATE_PAUSED); } static gboolean