diff options
Diffstat (limited to 'src')
29 files changed, 1456 insertions, 640 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index db2117986..42485b7d1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,10 +3,12 @@ include $(top_srcdir)/tools/flymake.mk AM_CPPFLAGS = \ -I$(top_srcdir) \ + -DG_LOG_DOMAIN=\"empathy\" \ $(EMPATHY_CFLAGS) \ $(LIBNOTIFY_CFLAGS) \ $(LIBCHAMPLAIN_CFLAGS) \ - $(DISABLE_DEPRECATED) + $(DISABLE_DEPRECATED) \ + $(WEBKIT_CFLAGS) \ $(WARN_CFLAGS) LDADD = \ @@ -15,7 +17,8 @@ LDADD = \ $(top_builddir)/extensions/libemp-extensions.la \ $(LIBNOTIFY_LIBS) \ $(EMPATHY_LIBS) \ - $(LIBCHAMPLAIN_LIBS) + $(LIBCHAMPLAIN_LIBS) \ + $(WEBKIT_LIBS) bin_PROGRAMS = \ empathy \ @@ -75,12 +78,22 @@ ui_DATA = \ empathy-preferences.ui \ empathy-status-icon.ui +EXTRA_DIST = \ + $(autostart_DATA) \ + $(ui_DATA) + if HAVE_LIBCHAMPLAIN -empathy_SOURCES += \ - empathy-map-view.c empathy-map-view.h +empathy_handwritten_source += \ + empathy-map-view.c \ + empathy-map-view.h ui_DATA += \ empathy-map-view.ui +else +EXTRA_DIST += \ + empathy-map-view.c \ + empathy-map-view.h \ + empathy-map-view.ui endif dist_man_MANS = \ @@ -104,9 +117,5 @@ dist_man_MANS = \ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ $< > $@ -EXTRA_DIST = \ - $(autostart_DATA) \ - $(ui_DATA) - CLEANFILES = $(BUILT_SOURCES) diff --git a/src/empathy-about-dialog.c b/src/empathy-about-dialog.c index 62c545864..dd30e3aed 100644 --- a/src/empathy-about-dialog.c +++ b/src/empathy-about-dialog.c @@ -25,8 +25,7 @@ #include <config.h> #include <glib/gi18n.h> -#include <gtk/gtkaboutdialog.h> -#include <gtk/gtksizegroup.h> +#include <gtk/gtk.h> #include <libempathy-gtk/empathy-ui-utils.h> diff --git a/src/empathy-about-dialog.h b/src/empathy-about-dialog.h index 3e8f40531..a290b3243 100644 --- a/src/empathy-about-dialog.h +++ b/src/empathy-about-dialog.h @@ -25,7 +25,7 @@ #ifndef __EMPATHY_ABOUT_DIALOG_H__ #define __EMPATHY_ABOUT_DIALOG_H__ -#include <gtk/gtkwindow.h> +#include <gtk/gtk.h> G_BEGIN_DECLS diff --git a/src/empathy-accounts-dialog.c b/src/empathy-accounts-dialog.c index dcf6bcc96..4cf391108 100644 --- a/src/empathy-accounts-dialog.c +++ b/src/empathy-accounts-dialog.c @@ -72,7 +72,8 @@ typedef struct { GtkWidget *hbox_type; GtkWidget *button_create; GtkWidget *button_back; - GtkWidget *checkbutton_register; + GtkWidget *radiobutton_reuse; + GtkWidget *radiobutton_register; GtkWidget *image_type; GtkWidget *label_name; @@ -396,7 +397,7 @@ accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog) g_signal_connect (cell, "toggled", G_CALLBACK (accounts_dialog_enable_toggled_cb), dialog); - + /* Account column */ column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (column, _("Accounts")); @@ -416,6 +417,7 @@ accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog) cell = gtk_cell_renderer_text_new (); g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, + "width-chars", 25, "editable", TRUE, NULL); gtk_tree_view_column_pack_start (column, cell, TRUE); @@ -439,7 +441,7 @@ accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog) /* select first */ view = GTK_TREE_VIEW (dialog->treeview); model = gtk_tree_view_get_model (view); - + if (gtk_tree_model_get_iter_first (model, &iter)) { selection = gtk_tree_view_get_selection (view); gtk_tree_selection_select_iter (selection, &iter); @@ -509,7 +511,7 @@ accounts_dialog_get_account_iter (EmpathyAccountsDialog *dialog, GtkTreeSelection *selection; GtkTreeModel *model; gboolean ok; - + /* Update the status in the model */ view = GTK_TREE_VIEW (dialog->treeview); selection = gtk_tree_view_get_selection (view); @@ -729,7 +731,7 @@ accounts_dialog_connection_changed_cb (EmpathyAccountManager *manager, GtkTreeModel *model; GtkTreeIter iter; gboolean found; - + /* Update the status in the model */ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); @@ -842,8 +844,8 @@ accounts_dialog_button_create_clicked_cb (GtkWidget *button, if (cap & MC_PROFILE_CAPABILITY_REGISTRATION_UI) { gboolean active; - active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_register)); - if (!active) { + active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radiobutton_register)); + if (active) { mc_account_set_param_boolean (account, "register", TRUE); } } @@ -877,9 +879,11 @@ accounts_dialog_profile_changed_cb (GtkWidget *widget, cap = mc_profile_get_capabilities (profile); if (cap & MC_PROFILE_CAPABILITY_REGISTRATION_UI) { - gtk_widget_show (dialog->checkbutton_register); + gtk_widget_show (dialog->radiobutton_register); + gtk_widget_show (dialog->radiobutton_reuse); } else { - gtk_widget_hide (dialog->checkbutton_register); + gtk_widget_hide (dialog->radiobutton_register); + gtk_widget_hide (dialog->radiobutton_reuse); } g_object_unref (profile); } @@ -910,8 +914,8 @@ accounts_dialog_button_add_clicked_cb (GtkWidget *button, gtk_widget_hide (dialog->button_back); } - accounts_dialog_profile_changed_cb (dialog->checkbutton_register, dialog); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_register), + accounts_dialog_profile_changed_cb (dialog->radiobutton_register, dialog); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->radiobutton_reuse), TRUE); gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->combobox_profile), 0); gtk_widget_grab_focus (dialog->combobox_profile); @@ -1038,7 +1042,7 @@ accounts_dialog_destroy_cb (GtkWidget *widget, g_object_unref (dialog->account_manager); g_object_unref (dialog->mc); - + g_free (dialog); } @@ -1071,7 +1075,8 @@ empathy_accounts_dialog_show (GtkWindow *parent, "hbox_type", &dialog->hbox_type, "button_create", &dialog->button_create, "button_back", &dialog->button_back, - "checkbutton_register", &dialog->checkbutton_register, + "radiobutton_reuse", &dialog->radiobutton_reuse, + "radiobutton_register", &dialog->radiobutton_register, "image_type", &dialog->image_type, "label_name", &dialog->label_name, "button_add", &dialog->button_add, diff --git a/src/empathy-accounts-dialog.h b/src/empathy-accounts-dialog.h index 40ea24f3e..b8c3d3691 100644 --- a/src/empathy-accounts-dialog.h +++ b/src/empathy-accounts-dialog.h @@ -25,7 +25,7 @@ #ifndef __EMPATHY_ACCOUNTS_DIALOG_H__ #define __EMPATHY_ACCOUNTS_DIALOG_H__ -#include <gtk/gtkwidget.h> +#include <gtk/gtk.h> #include <libmissioncontrol/mc-account.h> diff --git a/src/empathy-accounts-dialog.ui b/src/empathy-accounts-dialog.ui index 49862d853..cf1b23ef4 100644 --- a/src/empathy-accounts-dialog.ui +++ b/src/empathy-accounts-dialog.ui @@ -23,15 +23,14 @@ <property name="spacing">6</property> <child> <object class="GtkScrolledWindow" id="scrolledwindow17"> + <property name="height_request">200</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="hscrollbar_policy">automatic</property> + <property name="hscrollbar_policy">never</property> <property name="vscrollbar_policy">automatic</property> <property name="shadow_type">in</property> <child> <object class="GtkTreeView" id="treeview"> - <property name="width_request">250</property> - <property name="height_request">200</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="enable_search">False</property> @@ -143,7 +142,6 @@ </child> <child> <object class="GtkVBox" id="vbox214"> - <property name="width_request">415</property> <property name="visible">True</property> <property name="spacing">18</property> <child> @@ -158,8 +156,11 @@ <object class="GtkLabel" id="label_name"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label"><big><b>Gmail</b></big></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Gmail</property> + <attributes> + <attribute name="weight" value="bold"/> + <attribute name="scale" value="1.2"/> + </attributes> <property name="selectable">True</property> </object> <packing> @@ -204,8 +205,10 @@ <child type="label"> <object class="GtkLabel" id="label599"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Settings</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Settings</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> </child> </object> @@ -255,14 +258,38 @@ </packing> </child> <child> - <object class="GtkCheckButton" id="checkbutton_register"> - <property name="label" translatable="yes">I already have an account I want to use</property> + <object class="GtkVBox" id="vbox2"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkRadioButton" id="radiobutton_reuse"> + <property name="label" translatable="yes">_Reuse an existing account</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="radiobutton_register"> + <property name="label" translatable="yes">_Create a new account</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <property name="group">radiobutton_reuse</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> </object> <packing> <property name="position">2</property> @@ -273,6 +300,21 @@ <property name="visible">True</property> <property name="spacing">6</property> <child> + <object class="GtkButton" id="button_back"> + <property name="label">gtk-cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">end</property> + <property name="position">1</property> + </packing> + </child> + <child> <object class="GtkButton" id="button_create"> <property name="visible">True</property> <property name="can_focus">True</property> @@ -318,21 +360,6 @@ <property name="expand">False</property> <property name="fill">False</property> <property name="pack_type">end</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_back"> - <property name="label">gtk-cancel</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_stock">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="pack_type">end</property> <property name="position">0</property> </packing> </child> @@ -351,8 +378,10 @@ <child type="label"> <object class="GtkLabel" id="label643"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>New Account</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Add Account</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> </child> </object> @@ -382,8 +411,10 @@ <child type="label"> <object class="GtkLabel" id="label_no_protocol"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>No protocol installed</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">No protocol installed</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> </child> </object> diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c index 08c0e7ea2..a71e9c8be 100644 --- a/src/empathy-call-window.c +++ b/src/empathy-call-window.c @@ -32,6 +32,7 @@ #include <telepathy-farsight/channel.h> #include <libempathy/empathy-tp-contact-factory.h> +#include <libempathy/empathy-call-factory.h> #include <libempathy/empathy-utils.h> #include <libempathy-gtk/empathy-avatar-image.h> #include <libempathy-gtk/empathy-video-widget.h> @@ -39,9 +40,9 @@ #include <libempathy-gtk/empathy-audio-sink.h> #include <libempathy-gtk/empathy-video-src.h> #include <libempathy-gtk/empathy-ui-utils.h> +#include <libempathy-gtk/empathy-sound.h> #include "empathy-call-window.h" - #include "empathy-call-window-fullscreen.h" #include "empathy-sidebar.h" @@ -59,6 +60,12 @@ #define REMOTE_CONTACT_AVATAR_DEFAULT_WIDTH EMPATHY_VIDEO_WIDGET_DEFAULT_HEIGHT #define REMOTE_CONTACT_AVATAR_DEFAULT_HEIGHT EMPATHY_VIDEO_WIDGET_DEFAULT_HEIGHT +/* If an video input error occurs, the error message will start with "v4l" */ +#define VIDEO_INPUT_ERROR_PREFIX "v4l" + +/* The time interval in milliseconds between 2 outgoing rings */ +#define MS_BETWEEN_RING 500 + G_DEFINE_TYPE(EmpathyCallWindow, empathy_call_window, GTK_TYPE_WINDOW) /* signal enum */ @@ -75,6 +82,13 @@ enum { PROP_CALL_HANDLER = 1, }; +typedef enum { + CONNECTING, + CONNECTED, + DISCONNECTED, + REDIALING +} CallState; + /* private structure */ typedef struct _EmpathyCallWindowPriv EmpathyCallWindowPriv; @@ -84,7 +98,8 @@ struct _EmpathyCallWindowPriv EmpathyCallHandler *handler; EmpathyContact *contact; - gboolean connected; + guint call_state; + gboolean outgoing; GtkUIManager *ui_manager; GtkWidget *video_output; @@ -95,24 +110,36 @@ struct _EmpathyCallWindowPriv GtkWidget *sidebar_button; GtkWidget *statusbar; GtkWidget *volume_button; + GtkWidget *redial_button; GtkWidget *mic_button; GtkWidget *camera_button; GtkWidget *toolbar; GtkWidget *pane; + GtkAction *show_preview; GtkAction *send_video; + GtkAction *redial; GtkAction *menu_fullscreen; + /* The frames and boxes that contain self and remote avatar and video + input/output. When we redial, we destroy and re-create the boxes */ + GtkWidget *remote_user_output_frame; + GtkWidget *self_user_output_frame; + GtkWidget *remote_user_output_hbox; + GtkWidget *self_user_output_hbox; + /* We keep a reference on the hbox which contains the main content so we can easilly repack everything when toggling fullscreen */ GtkWidget *content_hbox; - /* This vbox is contained in the content_hbox. When toggling fullscreen, + /* This vbox is contained in the content_hbox and it contains the + self_user_output_frame and the sidebar button. When toggling fullscreen, it needs to be repacked. We keep a reference on it for easier access. */ GtkWidget *vbox; gulong video_output_motion_handler_id; gdouble volume; + GtkWidget *volume_progress_bar; GtkAdjustment *audio_input_adj; GtkWidget *dtmf_panel; @@ -168,6 +195,9 @@ static void empathy_call_window_sidebar_toggled_cb (GtkToggleButton *toggle, static void empathy_call_window_camera_toggled_cb (GtkToggleToolButton *toggle, EmpathyCallWindow *window); +static void empathy_call_window_set_send_video (EmpathyCallWindow *window, + gboolean send); + static void empathy_call_window_send_video_toggled_cb (GtkToggleAction *toggle, EmpathyCallWindow *window); @@ -203,9 +233,17 @@ static gboolean empathy_call_window_video_output_motion_notify (GtkWidget *widge static void empathy_call_window_video_menu_popup (EmpathyCallWindow *window, guint button); +static void empathy_call_window_redial_cb (gpointer object, + EmpathyCallWindow *window); + +static void empathy_call_window_restart_call (EmpathyCallWindow *window); + static void empathy_call_window_status_message (EmpathyCallWindow *window, gchar *message); +static void empathy_call_window_update_avatars_visibility (EmpathyTpCall *call, + EmpathyCallWindow *window); + static gboolean empathy_call_window_bus_message (GstBus *bus, GstMessage *message, gpointer user_data); @@ -455,7 +493,7 @@ empathy_call_window_mic_volume_changed_cb (GtkAdjustment *adj, priv->volume = volume; /* Ensure that the toggle button is active if the volume is > 0 and inactive - * if it's smaller then 0 */ + * if it's smaller than 0 */ if ((volume > 0) != gtk_toggle_tool_button_get_active ( GTK_TOGGLE_TOOL_BUTTON (priv->mic_button))) gtk_toggle_tool_button_set_active ( @@ -467,19 +505,20 @@ empathy_call_window_mic_volume_changed_cb (GtkAdjustment *adj, static void empathy_call_window_audio_input_level_changed_cb (EmpathyGstAudioSrc *src, - gdouble level, GtkProgressBar *bar) + gdouble level, EmpathyCallWindow *window) { gdouble value; + EmpathyCallWindowPriv *priv = GET_PRIV (window); value = CLAMP (pow (10, level / 20), 0.0, 1.0); - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (bar), value); + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->volume_progress_bar), value); } static GtkWidget * empathy_call_window_create_audio_input (EmpathyCallWindow *self) { EmpathyCallWindowPriv *priv = GET_PRIV (self); - GtkWidget *hbox, *vbox, *scale, *progress, *label; + GtkWidget *hbox, *vbox, *scale, *label; GtkAdjustment *adj; hbox = gtk_hbox_new (TRUE, 3); @@ -502,17 +541,130 @@ empathy_call_window_create_audio_input (EmpathyCallWindow *self) gtk_box_pack_start (GTK_BOX (vbox), scale, TRUE, TRUE, 3); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 3); - progress = gtk_progress_bar_new (); - gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (progress), - GTK_PROGRESS_BOTTOM_TO_TOP); - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress), 0); + priv->volume_progress_bar = gtk_progress_bar_new (); + gtk_progress_bar_set_orientation ( + GTK_PROGRESS_BAR (priv->volume_progress_bar), GTK_PROGRESS_BOTTOM_TO_TOP); + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->volume_progress_bar), + 0); + + gtk_box_pack_start (GTK_BOX (hbox), priv->volume_progress_bar, FALSE, FALSE, + 3); + + return hbox; +} + +static void +empathy_call_window_setup_remote_frame (GstBus *bus, EmpathyCallWindow *self) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (self); + + /* Initializing all the content (UI and output gst elements) related to the + remote contact */ + priv->remote_user_output_hbox = gtk_hbox_new (FALSE, 0); + + priv->remote_user_avatar_widget = gtk_image_new (); + gtk_box_pack_start (GTK_BOX (priv->remote_user_output_hbox), + priv->remote_user_avatar_widget, TRUE, TRUE, 0); + + priv->video_output = empathy_video_widget_new (bus); + gtk_box_pack_start (GTK_BOX (priv->remote_user_output_hbox), + priv->video_output, TRUE, TRUE, 0); + + gtk_widget_add_events (priv->video_output, + GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); + g_signal_connect (G_OBJECT (priv->video_output), "button-press-event", + G_CALLBACK (empathy_call_window_video_button_press_cb), self); + + gtk_container_add (GTK_CONTAINER (priv->remote_user_output_frame), + priv->remote_user_output_hbox); + + priv->audio_output = empathy_audio_sink_new (); + gst_object_ref (priv->audio_output); + gst_object_sink (priv->audio_output); +} + +static void +empathy_call_window_setup_self_frame (GstBus *bus, EmpathyCallWindow *self) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (self); + + /* Initializing all the content (UI and input gst elements) related to the + self contact, except for the video preview widget. This widget is only + initialized when the "show video preview" option is activated */ + priv->self_user_output_hbox = gtk_hbox_new (FALSE, 0); + + priv->self_user_avatar_widget = gtk_image_new (); + gtk_box_pack_start (GTK_BOX (priv->self_user_output_hbox), + priv->self_user_avatar_widget, TRUE, TRUE, 0); + + gtk_container_add (GTK_CONTAINER (priv->self_user_output_frame), + priv->self_user_output_hbox); + + priv->video_input = empathy_video_src_new (); + gst_object_ref (priv->video_input); + gst_object_sink (priv->video_input); + + priv->audio_input = empathy_audio_src_new (); + gst_object_ref (priv->audio_input); + gst_object_sink (priv->audio_input); g_signal_connect (priv->audio_input, "peak-level-changed", - G_CALLBACK (empathy_call_window_audio_input_level_changed_cb), progress); + G_CALLBACK (empathy_call_window_audio_input_level_changed_cb), self); +} + +static void +empathy_call_window_setup_video_preview (EmpathyCallWindow *window) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + GstElement *preview; + GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline)); - gtk_box_pack_start (GTK_BOX (hbox), progress, FALSE, FALSE, 3); + if (priv->video_preview != NULL) + { + /* Since the video preview and the video tee are initialized and freed + at the same time, if one is initialized, then the other one should + be too. */ + g_assert (priv->video_tee != NULL); + return; + } - return hbox; + g_assert (priv->video_tee == NULL); + + priv->video_tee = gst_element_factory_make ("tee", NULL); + gst_object_ref (priv->video_tee); + gst_object_sink (priv->video_tee); + + priv->video_preview = empathy_video_widget_new_with_size (bus, + SELF_VIDEO_SECTION_WIDTH, SELF_VIDEO_SECTION_HEIGTH); + g_object_set (priv->video_preview, "sync", FALSE, "async", TRUE, NULL); + gtk_box_pack_start (GTK_BOX (priv->self_user_output_hbox), + priv->video_preview, TRUE, TRUE, 0); + + preview = empathy_video_widget_get_element ( + EMPATHY_VIDEO_WIDGET (priv->video_preview)); + gst_bin_add_many (GST_BIN (priv->pipeline), priv->video_input, + priv->video_tee, preview, NULL); + gst_element_link_many (priv->video_input, priv->video_tee, + preview, NULL); + + g_object_unref (bus); + + gst_element_set_state (preview, GST_STATE_PLAYING); + gst_element_set_state (priv->video_input, GST_STATE_PLAYING); + gst_element_set_state (priv->video_tee, GST_STATE_PLAYING); +} + +static void +empathy_call_window_set_state_connecting (EmpathyCallWindow *window) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + empathy_call_window_status_message (window, _("Connecting...")); + priv->call_state = CONNECTING; + + if (priv->outgoing) + empathy_sound_start_playing (GTK_WIDGET (window), + EMPATHY_SOUND_PHONE_OUTGOING, MS_BETWEEN_RING); } static void @@ -524,8 +676,6 @@ empathy_call_window_init (EmpathyCallWindow *self) GtkWidget *h; GtkWidget *arrow; GtkWidget *page; - GtkWidget *remote_user_output_frame, *self_user_output_frame; - GtkWidget *remote_user_output_hbox, *self_user_output_hbox; GstBus *bus; gchar *filename; @@ -534,10 +684,13 @@ empathy_call_window_init (EmpathyCallWindow *self) "call_window_vbox", &top_vbox, "pane", &priv->pane, "statusbar", &priv->statusbar, + "redial", &priv->redial_button, "microphone", &priv->mic_button, "camera", &priv->camera_button, "toolbar", &priv->toolbar, "send_video", &priv->send_video, + "menuredial", &priv->redial, + "show_preview", &priv->show_preview, "ui_manager", &priv->ui_manager, "menufullscreen", &priv->menu_fullscreen, NULL); @@ -545,6 +698,8 @@ empathy_call_window_init (EmpathyCallWindow *self) empathy_builder_connect (gui, self, "menuhangup", "activate", empathy_call_window_hangup_cb, "hangup", "clicked", empathy_call_window_hangup_cb, + "menuredial", "activate", empathy_call_window_redial_cb, + "redial", "clicked", empathy_call_window_redial_cb, "microphone", "toggled", empathy_call_window_mic_toggled_cb, "camera", "toggled", empathy_call_window_camera_toggled_cb, "send_video", "toggled", empathy_call_window_send_video_toggled_cb, @@ -558,80 +713,33 @@ empathy_call_window_init (EmpathyCallWindow *self) empathy_call_window_setup_toolbar (self); - priv->pipeline = gst_pipeline_new (NULL); - priv->content_hbox = gtk_hbox_new (FALSE, CONTENT_HBOX_SPACING); gtk_container_set_border_width (GTK_CONTAINER (priv->content_hbox), CONTENT_HBOX_BORDER_WIDTH); gtk_paned_pack1 (GTK_PANED (priv->pane), priv->content_hbox, TRUE, FALSE); + priv->pipeline = gst_pipeline_new (NULL); bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline)); - gst_bus_add_watch (bus, empathy_call_window_bus_message, self); - remote_user_output_frame = gtk_frame_new (NULL); - gtk_widget_set_size_request (remote_user_output_frame, + priv->remote_user_output_frame = gtk_frame_new (NULL); + gtk_widget_set_size_request (priv->remote_user_output_frame, EMPATHY_VIDEO_WIDGET_DEFAULT_WIDTH, EMPATHY_VIDEO_WIDGET_DEFAULT_HEIGHT); - remote_user_output_hbox = gtk_hbox_new (FALSE, 0); - - priv->remote_user_avatar_widget = gtk_image_new (); - gtk_box_pack_start (GTK_BOX (remote_user_output_hbox), - priv->remote_user_avatar_widget, TRUE, TRUE, 0); - - priv->video_output = empathy_video_widget_new (bus); - gtk_box_pack_start (GTK_BOX (remote_user_output_hbox), - priv->video_output, TRUE, TRUE, 0); - - gtk_container_add (GTK_CONTAINER (remote_user_output_frame), - remote_user_output_hbox); - - gtk_widget_add_events (priv->video_output, - GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); - g_signal_connect (G_OBJECT (priv->video_output), "button-press-event", - G_CALLBACK (empathy_call_window_video_button_press_cb), self); - gtk_box_pack_start (GTK_BOX (priv->content_hbox), remote_user_output_frame, - TRUE, TRUE, CONTENT_HBOX_CHILDREN_PACKING_PADDING); + gtk_box_pack_start (GTK_BOX (priv->content_hbox), + priv->remote_user_output_frame, TRUE, TRUE, + CONTENT_HBOX_CHILDREN_PACKING_PADDING); + empathy_call_window_setup_remote_frame (bus, self); - priv->video_tee = gst_element_factory_make ("tee", NULL); - gst_object_ref (priv->video_tee); - gst_object_sink (priv->video_tee); + priv->self_user_output_frame = gtk_frame_new (NULL); + gtk_widget_set_size_request (priv->self_user_output_frame, + SELF_VIDEO_SECTION_WIDTH, SELF_VIDEO_SECTION_HEIGTH); priv->vbox = gtk_vbox_new (FALSE, 3); gtk_box_pack_start (GTK_BOX (priv->content_hbox), priv->vbox, - FALSE, FALSE, CONTENT_HBOX_CHILDREN_PACKING_PADDING); - - self_user_output_frame = gtk_frame_new (NULL); - gtk_widget_set_size_request (self_user_output_frame, SELF_VIDEO_SECTION_WIDTH, - SELF_VIDEO_SECTION_HEIGTH); - self_user_output_hbox = gtk_hbox_new (FALSE, 0); - - priv->self_user_avatar_widget = gtk_image_new (); - gtk_box_pack_start (GTK_BOX (self_user_output_hbox), - priv->self_user_avatar_widget, TRUE, TRUE, 0); - - priv->video_preview = empathy_video_widget_new_with_size (bus, - SELF_VIDEO_SECTION_WIDTH, SELF_VIDEO_SECTION_HEIGTH); - g_object_set (priv->video_preview, "sync", FALSE, "async", TRUE, NULL); - gtk_box_pack_start (GTK_BOX (self_user_output_hbox), priv->video_preview, - TRUE, TRUE, 0); - - gtk_container_add (GTK_CONTAINER (self_user_output_frame), - self_user_output_hbox); - - gtk_box_pack_start (GTK_BOX (priv->vbox), self_user_output_frame, FALSE, + FALSE, FALSE, CONTENT_HBOX_CHILDREN_PACKING_PADDING); + gtk_box_pack_start (GTK_BOX (priv->vbox), priv->self_user_output_frame, FALSE, FALSE, 0); - - priv->video_input = empathy_video_src_new (); - gst_object_ref (priv->video_input); - gst_object_sink (priv->video_input); - - priv->audio_input = empathy_audio_src_new (); - gst_object_ref (priv->audio_input); - gst_object_sink (priv->audio_input); - - priv->audio_output = empathy_audio_sink_new (); - gst_object_ref (priv->audio_output); - gst_object_sink (priv->audio_output); + empathy_call_window_setup_self_frame (bus, self); g_object_unref (bus); @@ -688,8 +796,6 @@ empathy_call_window_init (EmpathyCallWindow *self) g_signal_connect (G_OBJECT (self), "key-press-event", G_CALLBACK (empathy_call_window_key_press_cb), self); - empathy_call_window_status_message (self, _("Connecting...")); - priv->timer = g_timer_new (); g_object_ref (priv->ui_manager); @@ -764,14 +870,12 @@ empathy_call_window_got_self_contact_cb (EmpathyTpContactFactory *factory, } static void -empathy_call_window_constructed (GObject *object) +empathy_call_window_setup_avatars (EmpathyCallWindow *self, + EmpathyCallHandler *handler) { - EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (object); EmpathyCallWindowPriv *priv = GET_PRIV (self); - g_assert (priv->handler != NULL); - - g_object_get (priv->handler, "contact", &(priv->contact), NULL); + g_object_get (handler, "contact", &(priv->contact), NULL); if (priv->contact != NULL) { @@ -811,15 +915,42 @@ empathy_call_window_constructed (GObject *object) priv->remote_user_avatar_widget, MIN (REMOTE_CONTACT_AVATAR_DEFAULT_WIDTH, REMOTE_CONTACT_AVATAR_DEFAULT_HEIGHT)); - /* We hide the self avatar. It will be shown if a problem is - encountered when we try to send video. As for the remote avatar, it - is shown by default and will be hidden when we receive video from - the remote side. */ - gtk_widget_hide (priv->self_user_avatar_widget); + /* The remote avatar is shown by default and will be hidden when we receive + video from the remote side. */ gtk_widget_hide (priv->video_output); gtk_widget_show (priv->remote_user_avatar_widget); } +static void +empathy_call_window_setup_video_preview_visibility (EmpathyCallWindow *self, + EmpathyCallHandler *handler) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (self); + gboolean initial_video = empathy_call_handler_has_initial_video (priv->handler); + + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->show_preview), + initial_video); +} + +static void +empathy_call_window_constructed (GObject *object) +{ + EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (object); + EmpathyCallWindowPriv *priv = GET_PRIV (self); + EmpathyTpCall *call; + + g_assert (priv->handler != NULL); + + g_object_get (priv->handler, "tp-call", &call, NULL); + priv->outgoing = (call == NULL); + if (call != NULL) + g_object_unref (call); + + empathy_call_window_setup_avatars (self, priv->handler); + empathy_call_window_setup_video_preview_visibility (self, priv->handler); + empathy_call_window_set_state_connecting (self); +} + static void empathy_call_window_dispose (GObject *object); static void empathy_call_window_finalize (GObject *object); @@ -878,12 +1009,19 @@ empathy_call_window_class_init ( G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CALL_HANDLER, param_spec); +} +static void +empathy_call_window_video_stream_changed_cb (EmpathyTpCall *call, + GParamSpec *property, EmpathyCallWindow *self) +{ + empathy_call_window_update_avatars_visibility (call, self); } void empathy_call_window_dispose (GObject *object) { + EmpathyTpCall *call; EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (object); EmpathyCallWindowPriv *priv = GET_PRIV (self); @@ -892,6 +1030,16 @@ empathy_call_window_dispose (GObject *object) priv->dispose_has_run = TRUE; + g_object_get (priv->handler, "tp-call", &call, NULL); + + if (call != NULL) + { + g_signal_handlers_disconnect_by_func (call, + empathy_call_window_video_stream_changed_cb, object); + } + + g_object_unref (call); + if (priv->handler != NULL) g_object_unref (priv->handler); @@ -996,26 +1144,116 @@ empathy_call_window_request_resource_cb (EmpathyCallHandler *handler, return priv->video_input != NULL; } -static void +static gboolean +empathy_call_window_reset_pipeline (EmpathyCallWindow *self) +{ + GstStateChangeReturn state_change_return; + EmpathyCallWindowPriv *priv = GET_PRIV (self); + + if (priv->pipeline == NULL) + return TRUE; + + state_change_return = gst_element_set_state (priv->pipeline, GST_STATE_NULL); + + if (state_change_return == GST_STATE_CHANGE_SUCCESS || + state_change_return == GST_STATE_CHANGE_NO_PREROLL) + { + if (priv->pipeline != NULL) + g_object_unref (priv->pipeline); + priv->pipeline = NULL; + + if (priv->video_input != NULL) + g_object_unref (priv->video_input); + priv->video_input = NULL; + + if (priv->audio_input != NULL) + g_object_unref (priv->audio_input); + priv->audio_input = NULL; + + if (priv->audio_output != NULL) + g_object_unref (priv->audio_output); + priv->audio_output = NULL; + + if (priv->video_tee != NULL) + g_object_unref (priv->video_tee); + priv->video_tee = NULL; + + if (priv->video_preview != NULL) + gtk_widget_destroy (priv->video_preview); + priv->video_preview = NULL; + + priv->liveadder = NULL; + priv->funnel = NULL; + + return TRUE; + } + else + { + g_message ("Error: could not destroy pipeline. Closing call window"); + gtk_widget_destroy (GTK_WIDGET (self)); + + return FALSE; + } +} + +static gboolean empathy_call_window_disconnected (EmpathyCallWindow *self) { + gboolean could_disconnect = FALSE; EmpathyCallWindowPriv *priv = GET_PRIV (self); + gboolean could_reset_pipeline = empathy_call_window_reset_pipeline (self); - g_mutex_lock (priv->lock); + if (priv->call_state == CONNECTING) + empathy_sound_stop (EMPATHY_SOUND_PHONE_OUTGOING); - g_timer_stop (priv->timer); + if (priv->call_state != REDIALING) + priv->call_state = DISCONNECTED; - if (priv->timer_id != 0) - g_source_remove (priv->timer_id); - priv->timer_id = 0; + if (could_reset_pipeline) + { + gboolean initial_video = empathy_call_handler_has_initial_video ( + priv->handler); + g_mutex_lock (priv->lock); - g_mutex_unlock (priv->lock); + g_timer_stop (priv->timer); - empathy_call_window_status_message (self, _("Disconnected")); + if (priv->timer_id != 0) + g_source_remove (priv->timer_id); + priv->timer_id = 0; - gtk_widget_set_sensitive (priv->camera_button, FALSE); - gtk_action_set_sensitive (priv->send_video, FALSE); - priv->sending_video = FALSE; + g_mutex_unlock (priv->lock); + + empathy_call_window_status_message (self, _("Disconnected")); + + gtk_action_set_sensitive (priv->redial, TRUE); + gtk_widget_set_sensitive (priv->redial_button, TRUE); + + /* Reseting the send_video, camera_buton and mic_button to their + initial state */ + gtk_widget_set_sensitive (priv->camera_button, FALSE); + gtk_widget_set_sensitive (priv->mic_button, FALSE); + gtk_action_set_sensitive (priv->send_video, FALSE); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->send_video), + initial_video); + gtk_toggle_tool_button_set_active ( + GTK_TOGGLE_TOOL_BUTTON (priv->camera_button), initial_video); + gtk_toggle_tool_button_set_active ( + GTK_TOGGLE_TOOL_BUTTON (priv->mic_button), TRUE); + + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->show_preview), + FALSE); + gtk_action_set_sensitive (priv->show_preview, FALSE); + + gtk_widget_hide (priv->video_output); + gtk_widget_show (priv->remote_user_avatar_widget); + + priv->sending_video = FALSE; + priv->call_started = FALSE; + + could_disconnect = TRUE; + } + + return could_disconnect; } @@ -1023,8 +1261,10 @@ static void empathy_call_window_channel_closed_cb (TfChannel *channel, gpointer user_data) { EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (user_data); + EmpathyCallWindowPriv *priv = GET_PRIV (self); - empathy_call_window_disconnected (self); + if (empathy_call_window_disconnected (self) && priv->call_state == REDIALING) + empathy_call_window_restart_call (self); } /* Called with global lock held */ @@ -1110,14 +1350,35 @@ empathy_call_window_connected (gpointer user_data) g_object_get (priv->handler, "tp-call", &call, NULL); + g_signal_connect (call, "notify::video-stream", + G_CALLBACK (empathy_call_window_video_stream_changed_cb), self); + if (empathy_tp_call_has_dtmf (call)) gtk_widget_set_sensitive (priv->dtmf_panel, TRUE); - if (priv->video_input != NULL) - { - gtk_widget_set_sensitive (priv->camera_button, TRUE); - gtk_action_set_sensitive (priv->send_video, TRUE); - } + if (priv->video_input == NULL) + empathy_call_window_set_send_video (self, FALSE); + + priv->sending_video = empathy_tp_call_is_sending_video (call); + + gtk_action_set_sensitive (priv->show_preview, TRUE); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->show_preview), + priv->sending_video + || gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (priv->show_preview))); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->send_video), + priv->sending_video && priv->video_input != NULL); + gtk_toggle_tool_button_set_active ( + GTK_TOGGLE_TOOL_BUTTON (priv->camera_button), + priv->sending_video && priv->video_input != NULL); + gtk_widget_set_sensitive (priv->camera_button, priv->video_input != NULL); + gtk_action_set_sensitive (priv->send_video, priv->video_input != NULL); + + gtk_action_set_sensitive (priv->redial, FALSE); + gtk_widget_set_sensitive (priv->redial_button, FALSE); + + gtk_widget_set_sensitive (priv->mic_button, TRUE); + + empathy_call_window_update_avatars_visibility (call, self); g_object_unref (call); @@ -1146,11 +1407,12 @@ empathy_call_window_src_added_cb (EmpathyCallHandler *handler, g_mutex_lock (priv->lock); - if (priv->connected == FALSE) + if (priv->call_state != CONNECTED) { g_timer_start (priv->timer); priv->timer_id = g_idle_add (empathy_call_window_connected, self); - priv->connected = TRUE; + priv->call_state = CONNECTED; + empathy_sound_stop (EMPATHY_SOUND_PHONE_OUTGOING); } switch (media_type) @@ -1195,53 +1457,34 @@ empathy_call_window_sink_added_cb (EmpathyCallHandler *handler, case TP_MEDIA_STREAM_TYPE_VIDEO: if (priv->video_input != NULL) { - pad = gst_element_get_request_pad (priv->video_tee, "src%d"); - gst_pad_link (pad, sink); - } - break; - default: - g_assert_not_reached (); - } + EmpathyTpCall *call; + g_object_get (priv->handler, "tp-call", &call, NULL); -} + if (empathy_tp_call_is_sending_video (call)) + { + empathy_call_window_setup_video_preview (self); -static gboolean -empathy_gst_bin_has_child (GstBin *bin, GstElement *element) -{ - GstIterator *it; - gboolean ret = FALSE; - GstElement *item; + gtk_toggle_action_set_active ( + GTK_TOGGLE_ACTION (priv->show_preview), TRUE); - it = gst_bin_iterate_recurse (bin); + if (priv->video_preview != NULL) + gtk_widget_show (priv->video_preview); + gtk_widget_hide (priv->self_user_avatar_widget); + } - for (;;) - { - switch (gst_iterator_next (it, (gpointer *)&item)) - { - case GST_ITERATOR_OK: - if (item == element) - { - gst_object_unref (GST_OBJECT (item)); - ret = TRUE; - goto out; - } - gst_object_unref (GST_OBJECT (item)); - break; - case GST_ITERATOR_RESYNC: - gst_iterator_resync (it); - break; - case GST_ITERATOR_ERROR: - g_assert_not_reached (); - /* fallthrough */ - case GST_ITERATOR_DONE: - goto out; - break; - } + g_object_unref (call); + + if (priv->video_tee != NULL) + { + pad = gst_element_get_request_pad (priv->video_tee, "src%d"); + gst_pad_link (pad, sink); + } + } + break; + default: + g_assert_not_reached (); } - gst_iterator_free (it); -out: - return ret; } static void @@ -1264,8 +1507,15 @@ empathy_call_window_remove_video_input (EmpathyCallWindow *self) priv->video_input = NULL; g_object_unref (priv->video_tee); priv->video_tee = NULL; + gtk_widget_destroy (priv->video_preview); + priv->video_preview = NULL; + + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->send_video), FALSE); + gtk_toggle_tool_button_set_active ( + GTK_TOGGLE_TOOL_BUTTON (priv->camera_button), FALSE); + gtk_widget_set_sensitive (priv->camera_button, FALSE); + gtk_action_set_sensitive (priv->send_video, FALSE); - gtk_widget_hide (priv->video_preview); gtk_widget_show (priv->self_user_avatar_widget); } @@ -1304,23 +1554,24 @@ empathy_call_window_bus_message (GstBus *bus, GstMessage *message, case GST_MESSAGE_ERROR: { GError *error = NULL; + GstElement *gst_error; gchar *debug; gst_message_parse_error (message, &error, &debug); + gst_error = GST_ELEMENT (GST_MESSAGE_SRC (message)); g_message ("Element error: %s -- %s\n", error->message, debug); - if (priv->video_input != NULL && - empathy_gst_bin_has_child (GST_BIN (priv->video_input), - GST_ELEMENT (GST_MESSAGE_SRC (message)))) + if (g_str_has_prefix (gst_element_get_name (gst_error), + VIDEO_INPUT_ERROR_PREFIX)) { /* Remove the video input and continue */ - empathy_call_window_remove_video_input (self); - gst_element_set_state (priv->pipeline, GST_STATE_PAUSED); + if (priv->video_input != NULL) + empathy_call_window_remove_video_input (self); + gst_element_set_state (priv->pipeline, GST_STATE_PLAYING); } else { - gst_element_set_state (priv->pipeline, GST_STATE_NULL); empathy_call_window_disconnected (self); } g_error_free (error); @@ -1334,10 +1585,51 @@ empathy_call_window_bus_message (GstBus *bus, GstMessage *message, } static void +empathy_call_window_update_self_avatar_visibility (EmpathyCallWindow *window) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (priv->show_preview))) + { + if (priv->video_preview != NULL) + { + gtk_widget_hide (priv->self_user_avatar_widget); + gtk_widget_show (priv->video_preview); + } + else + { + if (priv->video_preview != NULL) + gtk_widget_hide (priv->video_preview); + + gtk_widget_show (priv->self_user_avatar_widget); + } + } +} + +static void +empathy_call_window_update_avatars_visibility (EmpathyTpCall *call, + EmpathyCallWindow *window) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + if (empathy_tp_call_is_receiving_video (call)) + { + gtk_widget_hide (priv->remote_user_avatar_widget); + gtk_widget_show (priv->video_output); + } + else + { + gtk_widget_hide (priv->video_output); + gtk_widget_show (priv->remote_user_avatar_widget); + } + + empathy_call_window_update_self_avatar_visibility (window); +} + +static void empathy_call_window_realized_cb (GtkWidget *widget, EmpathyCallWindow *window) { EmpathyCallWindowPriv *priv = GET_PRIV (window); - GstElement *preview; g_signal_connect (priv->handler, "conference-added", G_CALLBACK (empathy_call_window_conference_added_cb), window); @@ -1350,15 +1642,6 @@ empathy_call_window_realized_cb (GtkWidget *widget, EmpathyCallWindow *window) g_signal_connect (priv->handler, "sink-pad-added", G_CALLBACK (empathy_call_window_sink_added_cb), window); - - preview = empathy_video_widget_get_element ( - EMPATHY_VIDEO_WIDGET (priv->video_preview)); - - gst_bin_add_many (GST_BIN (priv->pipeline), priv->video_input, - priv->video_tee, preview, NULL); - gst_element_link_many (priv->video_input, priv->video_tee, - preview, NULL); - gst_element_set_state (priv->pipeline, GST_STATE_PAUSED); } @@ -1368,7 +1651,11 @@ empathy_call_window_delete_cb (GtkWidget *widget, GdkEvent*event, { EmpathyCallWindowPriv *priv = GET_PRIV (window); - gst_element_set_state (priv->pipeline, GST_STATE_NULL); + if (priv->pipeline != NULL) + gst_element_set_state (priv->pipeline, GST_STATE_NULL); + + if (priv->call_state == CONNECTING) + empathy_sound_stop (EMPATHY_SOUND_PHONE_OUTGOING); return FALSE; } @@ -1514,6 +1801,17 @@ empathy_call_window_set_send_video (EmpathyCallWindow *window, EmpathyCallWindowPriv *priv = GET_PRIV (window); EmpathyTpCall *call; + priv->sending_video = send; + + /* When we start sending video, we want to show the video preview by + default. */ + if (send) + { + empathy_call_window_setup_video_preview (window); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->show_preview), + TRUE); + } + g_object_get (priv->handler, "tp-call", &call, NULL); empathy_tp_call_request_video_stream_direction (call, send); g_object_unref (call); @@ -1526,11 +1824,13 @@ empathy_call_window_camera_toggled_cb (GtkToggleToolButton *toggle, EmpathyCallWindowPriv *priv = GET_PRIV (window); gboolean active; + if (priv->call_state != CONNECTED) + return; + active = (gtk_toggle_tool_button_get_active (toggle)); if (priv->sending_video == active) return; - priv->sending_video = active; empathy_call_window_set_send_video (window, active); gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->send_video), active); @@ -1543,11 +1843,13 @@ empathy_call_window_send_video_toggled_cb (GtkToggleAction *toggle, EmpathyCallWindowPriv *priv = GET_PRIV (window); gboolean active; + if (priv->call_state != CONNECTED) + return; + active = (gtk_toggle_action_get_active (toggle)); if (priv->sending_video == active) return; - priv->sending_video = active; empathy_call_window_set_send_video (window, active); gtk_toggle_tool_button_set_active ( @@ -1558,7 +1860,21 @@ static void empathy_call_window_show_preview_toggled_cb (GtkToggleAction *toggle, EmpathyCallWindow *window) { - /* FIXME: Not implemented */ + gboolean show_preview_toggled; + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + show_preview_toggled = gtk_toggle_action_get_active (toggle); + + if (show_preview_toggled) + { + empathy_call_window_setup_video_preview (window); + gtk_widget_show (priv->self_user_output_frame); + empathy_call_window_update_self_avatar_visibility (window); + } + else + { + gtk_widget_hide (priv->self_user_output_frame); + } } static void @@ -1568,6 +1884,9 @@ empathy_call_window_mic_toggled_cb (GtkToggleToolButton *toggle, EmpathyCallWindowPriv *priv = GET_PRIV (window); gboolean active; + if (priv->audio_input == NULL) + return; + active = (gtk_toggle_tool_button_get_active (toggle)); if (active) @@ -1613,10 +1932,58 @@ static void empathy_call_window_hangup_cb (gpointer object, EmpathyCallWindow *window) { + if (empathy_call_window_disconnected (window)) + gtk_widget_destroy (GTK_WIDGET (window)); +} + +static void +empathy_call_window_restart_call (EmpathyCallWindow *window) +{ + GstBus *bus; + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + gtk_widget_destroy (priv->remote_user_output_hbox); + gtk_widget_destroy (priv->self_user_output_hbox); + + priv->pipeline = gst_pipeline_new (NULL); + bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline)); + gst_bus_add_watch (bus, empathy_call_window_bus_message, window); + + empathy_call_window_setup_remote_frame (bus, window); + empathy_call_window_setup_self_frame (bus, window); + + g_object_unref (bus); + + gtk_widget_show_all (priv->content_hbox); + + if (!empathy_call_handler_has_initial_video (priv->handler)) + gtk_widget_hide (priv->self_user_output_frame); + + priv->outgoing = TRUE; + empathy_call_window_set_state_connecting (window); + + priv->call_started = TRUE; + empathy_call_handler_start_call (priv->handler); + empathy_call_window_setup_avatars (window, priv->handler); + gst_element_set_state (priv->pipeline, GST_STATE_PLAYING); + + gtk_action_set_sensitive (priv->redial, FALSE); + gtk_widget_set_sensitive (priv->redial_button, FALSE); +} + +static void +empathy_call_window_redial_cb (gpointer object, + EmpathyCallWindow *window) +{ EmpathyCallWindowPriv *priv = GET_PRIV (window); - gst_element_set_state (priv->pipeline, GST_STATE_NULL); - gtk_widget_destroy (GTK_WIDGET (window)); + if (priv->call_state == CONNECTED) + priv->call_state = REDIALING; + + empathy_call_handler_stop_call (priv->handler); + + if (priv->call_state != CONNECTED) + empathy_call_window_restart_call (window); } static void @@ -1678,7 +2045,6 @@ empathy_call_window_video_output_motion_notify (GtkWidget *widget, empathy_call_window_fullscreen_show_popup (priv->fullscreen); return TRUE; } - return FALSE; } diff --git a/src/empathy-call-window.ui b/src/empathy-call-window.ui index a0e1e1304..9e7c0962d 100644 --- a/src/empathy-call-window.ui +++ b/src/empathy-call-window.ui @@ -19,12 +19,20 @@ </child> <child> <object class="GtkAction" id="menuhangup"> - <property name="stock_id">gtk-cancel</property> + <property name="icon_name">call-stop</property> <property name="name">menuhangup</property> <property name="label" translatable="yes">Hang up</property> </object> </child> <child> + <object class="GtkAction" id="menuredial"> + <property name="stock_id">gtk-refresh</property> + <property name="name">menuredial</property> + <property name="label" translatable="yes">Redial</property> + <property name="sensitive">False</property> + </object> + </child> + <child> <object class="GtkAction" id="view"> <property name="name">view</property> <property name="label" translatable="yes">_View</property> @@ -34,6 +42,7 @@ <object class="GtkToggleAction" id="show_preview"> <property name="name">show_preview</property> <property name="label" translatable="yes">Video preview</property> + <property name="active">True</property> </object> </child> <child> @@ -50,6 +59,7 @@ <menu action="call"> <menuitem action="send_video"/> <menuitem action="menuhangup"/> + <menuitem action="menuredial"/> </menu> <menu action="view"> <menuitem action="show_preview"/> @@ -79,7 +89,19 @@ <property name="visible">True</property> <property name="is_important">True</property> <property name="label" translatable="yes">Hang up</property> - <property name="stock_id">gtk-cancel</property> + <property name="icon_name">call-stop</property> + </object> + <packing> + <property name="homogeneous">True</property> + </packing> + </child> + <child> + <object class="GtkToolButton" id="redial"> + <property name="visible">True</property> + <property name="is_important">True</property> + <property name="label" translatable="yes">Redial</property> + <property name="stock_id">gtk-refresh</property> + <property name="sensitive">False</property> </object> <packing> <property name="homogeneous">True</property> diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c index 9c2dbc490..424d148ac 100644 --- a/src/empathy-chat-window.c +++ b/src/empathy-chat-window.c @@ -50,6 +50,7 @@ #include <libempathy-gtk/empathy-log-window.h> #include <libempathy-gtk/empathy-geometry.h> #include <libempathy-gtk/empathy-smiley-manager.h> +#include <libempathy-gtk/empathy-sound.h> #include <libempathy-gtk/empathy-ui-utils.h> #include "empathy-chat-window.h" @@ -77,6 +78,7 @@ typedef struct { GtkUIManager *ui_manager; GtkAction *menu_conv_insert_smiley; GtkAction *menu_conv_favorite; + GtkAction *menu_conv_toggle_contacts; GtkAction *menu_edit_cut; GtkAction *menu_edit_copy; @@ -547,6 +549,8 @@ chat_window_conv_activate_cb (GtkAction *action, { EmpathyChatWindowPriv *priv = GET_PRIV (window); gboolean is_room; + gboolean active; + EmpathyContact *remote_contact = NULL; /* Favorite room menu */ is_room = empathy_chat_is_room (priv->current_chat); @@ -565,6 +569,22 @@ chat_window_conv_activate_cb (GtkAction *action, GTK_TOGGLE_ACTION (priv->menu_conv_favorite), found); } gtk_action_set_visible (priv->menu_conv_favorite, is_room); + + /* Show contacts menu */ + g_object_get (priv->current_chat, + "remote-contact", &remote_contact, + "show-contacts", &active, + NULL); + if (remote_contact == NULL) { + gtk_toggle_action_set_active ( + GTK_TOGGLE_ACTION (priv->menu_conv_toggle_contacts), + active); + } + gtk_action_set_visible (priv->menu_conv_toggle_contacts, + (remote_contact == NULL)); + if (remote_contact != NULL) { + g_object_unref (remote_contact); + } } static void @@ -602,12 +622,24 @@ chat_window_favorite_toggled_cb (GtkToggleAction *toggle_action, g_object_unref (chatroom); return; } - + if (!active && chatroom) { empathy_chatroom_manager_remove (priv->chatroom_manager, chatroom); } } +static void +chat_window_contacts_toggled_cb (GtkToggleAction *toggle_action, + EmpathyChatWindow *window) +{ + EmpathyChatWindowPriv *priv = GET_PRIV (window); + gboolean active; + + active = gtk_toggle_action_get_active (toggle_action); + + empathy_chat_set_show_contacts (priv->current_chat, active); +} + static const gchar * chat_get_window_id_for_geometry (EmpathyChat *chat) { @@ -910,7 +942,8 @@ chat_window_show_or_update_notification (EmpathyChatWindow *window, EmpathyChat *chat) { EmpathyContact *sender; - char *header, *escaped; + const gchar *header; + char *escaped; const char *body; GdkPixbuf *pixbuf; NotificationData *cb_data; @@ -932,8 +965,7 @@ chat_window_show_or_update_notification (EmpathyChatWindow *window, cb_data->window = window; sender = empathy_message_get_sender (message); - header = g_strdup_printf (_("New message from %s"), - empathy_contact_get_name (sender)); + header = empathy_contact_get_name (sender); body = empathy_message_get_body (message); escaped = g_markup_escape_text (body, -1); @@ -955,7 +987,6 @@ chat_window_show_or_update_notification (EmpathyChatWindow *window, notify_notification_show (priv->notification, NULL); g_object_unref (pixbuf); - g_free (header); g_free (escaped); } @@ -1180,7 +1211,7 @@ chat_window_focus_in_event_cb (GtkWidget *widget, priv->chats_new_msg = g_list_remove (priv->chats_new_msg, priv->current_chat); chat_window_set_urgency_hint (window, FALSE); - + /* Update the title, since we now mark all unread messages as read. */ chat_window_update_chat_tab (priv->current_chat); @@ -1209,7 +1240,7 @@ chat_window_drag_data_received (GtkWidget *widget, id = (const gchar*) selection->data; DEBUG ("DND contact from roster with id:'%s'", id); - + strv = g_strsplit (id, "/", 2); account_id = strv[0]; contact_id = strv[1]; @@ -1237,18 +1268,18 @@ chat_window_drag_data_received (GtkWidget *widget, g_object_unref (account); g_strfreev (strv); - old_window = chat_window_find_chat (chat); + old_window = chat_window_find_chat (chat); if (old_window) { if (old_window == window) { gtk_drag_finish (context, TRUE, FALSE, time); return; } - + empathy_chat_window_move_chat (old_window, window, chat); } else { empathy_chat_window_add_chat (window, chat); } - + /* Added to take care of any outstanding chat events */ empathy_chat_window_present_chat (chat); @@ -1279,7 +1310,7 @@ chat_window_drag_data_received (GtkWidget *widget, gtk_drag_finish (context, TRUE, FALSE, time); return; } - + priv->dnd_same_window = FALSE; } @@ -1369,6 +1400,7 @@ empathy_chat_window_init (EmpathyChatWindow *window) "ui_manager", &priv->ui_manager, "menu_conv_insert_smiley", &priv->menu_conv_insert_smiley, "menu_conv_favorite", &priv->menu_conv_favorite, + "menu_conv_toggle_contacts", &priv->menu_conv_toggle_contacts, "menu_edit_cut", &priv->menu_edit_cut, "menu_edit_copy", &priv->menu_edit_copy, "menu_edit_paste", &priv->menu_edit_paste, @@ -1385,6 +1417,7 @@ empathy_chat_window_init (EmpathyChatWindow *window) "menu_conv", "activate", chat_window_conv_activate_cb, "menu_conv_clear", "activate", chat_window_clear_activate_cb, "menu_conv_favorite", "toggled", chat_window_favorite_toggled_cb, + "menu_conv_toggle_contacts", "toggled", chat_window_contacts_toggled_cb, "menu_conv_close", "activate", chat_window_close_activate_cb, "menu_edit", "activate", chat_window_edit_activate_cb, "menu_edit_cut", "activate", chat_window_cut_activate_cb, @@ -1566,14 +1599,14 @@ empathy_chat_window_add_chat (EmpathyChatWindow *window, /* If this window has just been created, position it */ if (priv->chats == NULL) { empathy_geometry_load (chat_get_window_id_for_geometry (chat), &x, &y, &w, &h); - + if (x >= 0 && y >= 0) { /* Let the window manager position it if we don't have * good x, y coordinates. */ gtk_window_move (GTK_WINDOW (priv->dialog), x, y); } - + if (w > 0 && h > 0) { /* Use the defaults from the ui file if we don't have * good w, h geometry. diff --git a/src/empathy-chat-window.h b/src/empathy-chat-window.h index 835d67296..c46ef8fc4 100644 --- a/src/empathy-chat-window.h +++ b/src/empathy-chat-window.h @@ -29,7 +29,7 @@ #define __EMPATHY_CHAT_WINDOW_H__ #include <glib-object.h> -#include <gtk/gtkwidget.h> +#include <gtk/gtk.h> #include <libmissioncontrol/mc-account.h> #include <libempathy-gtk/empathy-chat.h> diff --git a/src/empathy-chat-window.ui b/src/empathy-chat-window.ui index 0d5a83180..8c8ea7d00 100644 --- a/src/empathy-chat-window.ui +++ b/src/empathy-chat-window.ui @@ -32,6 +32,13 @@ </object> </child> <child> + <object class="GtkToggleAction" id="menu_conv_toggle_contacts"> + <property name="name">menu_conv_toggle_contacts</property> + <property name="active">TRUE</property> + <property name="label" translatable="yes">_Show Contact List</property> + </object> + </child> + <child> <object class="GtkAction" id="menu_conv_close"> <property name="stock_id">gtk-close</property> <property name="name">menu_conv_close</property> @@ -137,6 +144,7 @@ <menuitem action="menu_conv_clear"/> <menuitem action="menu_conv_insert_smiley"/> <menuitem action="menu_conv_favorite"/> + <menuitem action="menu_conv_toggle_contacts"/> <separator/> <menuitem action="menu_conv_close"/> </menu> diff --git a/src/empathy-debug-dialog.c b/src/empathy-debug-dialog.c index f6fe6e8b2..cd0d925f9 100644 --- a/src/empathy-debug-dialog.c +++ b/src/empathy-debug-dialog.c @@ -430,8 +430,6 @@ debug_dialog_get_name_owner_cb (TpDBusDaemon *proxy, COL_CM_NAME, data->cm_name, COL_CM_UNIQUE_NAME, out, -1); - - gtk_combo_box_set_active (GTK_COMBO_BOX (priv->cm_chooser), 0); } OUT: @@ -568,6 +566,7 @@ debug_dialog_fill_cm_chooser (EmpathyDebugDialog *debug_dialog) { EmpathyDebugDialogPriv *priv = GET_PRIV (debug_dialog); GError *error = NULL; + GtkTreeIter iter; priv->dbus = tp_dbus_daemon_dup (&error); @@ -578,6 +577,15 @@ debug_dialog_fill_cm_chooser (EmpathyDebugDialog *debug_dialog) return; } + /* Add empathy */ + gtk_list_store_append (priv->cms, &iter); + gtk_list_store_set (priv->cms, &iter, + COL_CM_NAME, "empathy", + COL_CM_UNIQUE_NAME, "org.gnome.Empathy", + -1); + gtk_combo_box_set_active (GTK_COMBO_BOX (priv->cm_chooser), 0); + + /* Add CMs to list */ tp_list_connection_names (priv->dbus, debug_dialog_list_connection_names_cb, debug_dialog, NULL, NULL); diff --git a/src/empathy-event-manager.c b/src/empathy-event-manager.c index 81d98ef74..a80aad236 100644 --- a/src/empathy-event-manager.c +++ b/src/empathy-event-manager.c @@ -26,6 +26,7 @@ #include <telepathy-glib/util.h> +#include <libempathy/empathy-account-manager.h> #include <libempathy/empathy-dispatcher.h> #include <libempathy/empathy-tp-contact-factory.h> #include <libempathy/empathy-contact-manager.h> @@ -37,9 +38,10 @@ #include <extensions/extensions.h> +#include <libempathy-gtk/empathy-conf.h> #include <libempathy-gtk/empathy-images.h> #include <libempathy-gtk/empathy-contact-dialogs.h> -#include <libempathy-gtk/empathy-ui-utils.h> +#include <libempathy-gtk/empathy-sound.h> #include "empathy-event-manager.h" #include "empathy-main-window.h" @@ -50,6 +52,11 @@ #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyEventManager) +#define NOTIFICATION_TIMEOUT 2 /* seconds */ + +/* The time interval in milliseconds between 2 incoming rings */ +#define MS_BETWEEN_RING 500 + typedef struct { EmpathyEventManager *manager; EmpathyDispatchOperation *operation; @@ -74,8 +81,6 @@ typedef struct { /* Ongoing approvals */ GSList *approvals; - /* voip ringing sound */ - guint voip_timeout; gint ringing; } EmpathyEventManagerPriv; @@ -161,81 +166,6 @@ event_free (EventPriv *event) g_slice_free (EventPriv, event); } -static void event_manager_ringing_finished_cb (ca_context *c, guint id, - int error_code, gpointer user_data); - -static gboolean -event_manager_ringing_timeout_cb (gpointer data) -{ - EmpathyEventManager *manager = EMPATHY_EVENT_MANAGER (data); - EmpathyEventManagerPriv *priv = GET_PRIV (manager); - - priv->voip_timeout = 0; - - empathy_sound_play_full (empathy_main_window_get (), - EMPATHY_SOUND_PHONE_INCOMING, event_manager_ringing_finished_cb, - manager); - - return FALSE; -} - -static gboolean -event_manager_ringing_idle_cb (gpointer data) -{ - EmpathyEventManager *manager = EMPATHY_EVENT_MANAGER (data); - EmpathyEventManagerPriv *priv = GET_PRIV (manager); - - if (priv->ringing > 0) - priv->voip_timeout = g_timeout_add (500, event_manager_ringing_timeout_cb, - data); - - return FALSE; -} - -static void -event_manager_ringing_finished_cb (ca_context *c, guint id, int error_code, - gpointer user_data) -{ - if (error_code == CA_ERROR_CANCELED) - return; - - g_idle_add (event_manager_ringing_idle_cb, user_data); -} - -static void -event_manager_start_ringing (EmpathyEventManager *manager) -{ - EmpathyEventManagerPriv *priv = GET_PRIV (manager); - - priv->ringing++; - - if (priv->ringing == 1) - { - empathy_sound_play_full (empathy_main_window_get (), - EMPATHY_SOUND_PHONE_INCOMING, event_manager_ringing_finished_cb, - manager); - } -} - -static void -event_manager_stop_ringing (EmpathyEventManager *manager) -{ - EmpathyEventManagerPriv *priv = GET_PRIV (manager); - - priv->ringing--; - - if (priv->ringing > 0) - return; - - empathy_sound_stop (EMPATHY_SOUND_PHONE_INCOMING); - - if (priv->voip_timeout != 0) - { - g_source_remove (priv->voip_timeout); - priv->voip_timeout = 0; - } -} - static void event_remove (EventPriv *event) { @@ -247,6 +177,13 @@ event_remove (EventPriv *event) event_free (event); } +static gboolean +autoremove_event_timeout_cb (EventPriv *event) +{ + event_remove (event); + return FALSE; +} + static void event_manager_add (EmpathyEventManager *manager, EmpathyContact *contact, const gchar *icon_name, const gchar *header, const gchar *message, @@ -260,6 +197,7 @@ event_manager_add (EmpathyEventManager *manager, EmpathyContact *contact, event->public.icon_name = g_strdup (icon_name); event->public.header = g_strdup (header); event->public.message = g_strdup (message); + event->public.must_ack = (func != NULL); event->inhibit = FALSE; event->func = func; event->user_data = user_data; @@ -269,6 +207,12 @@ event_manager_add (EmpathyEventManager *manager, EmpathyContact *contact, DEBUG ("Adding event %p", event); priv->events = g_slist_prepend (priv->events, event); g_signal_emit (event->manager, signals[EVENT_ADDED], 0, event); + + if (!event->public.must_ack) + { + g_timeout_add_seconds (NOTIFICATION_TIMEOUT, + (GSourceFunc) autoremove_event_timeout_cb, event); + } } static void @@ -409,7 +353,7 @@ event_manager_chat_message_received_cb (EmpathyTpChat *tp_chat, EmpathyMessage *message, EventManagerApproval *approval) { EmpathyContact *sender; - gchar *header; + const gchar *header; const gchar *msg; TpChannel *channel; EventPriv *event; @@ -426,8 +370,7 @@ event_manager_chat_message_received_cb (EmpathyTpChat *tp_chat, } sender = empathy_message_get_sender (message); - header = g_strdup_printf (_("New message from %s"), - empathy_contact_get_name (sender)); + header = empathy_contact_get_name (sender); msg = empathy_message_get_body (message); channel = empathy_tp_chat_get_channel (tp_chat); @@ -438,7 +381,6 @@ event_manager_chat_message_received_cb (EmpathyTpChat *tp_chat, event_manager_add (approval->manager, sender, EMPATHY_IMAGE_NEW_MESSAGE, header, msg, approval, event_text_channel_process_func, NULL); - g_free (header); empathy_sound_play (empathy_main_window_get (), EMPATHY_SOUND_CONVERSATION_NEW); } @@ -457,7 +399,9 @@ event_manager_approval_done (EventManagerApproval *approval) approval->operation); if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA) { - event_manager_stop_ringing (approval->manager); + priv->ringing--; + if (priv->ringing == 0) + empathy_sound_stop (EMPATHY_SOUND_PHONE_INCOMING); } } @@ -502,6 +446,7 @@ event_manager_operation_invalidated_cb (EmpathyDispatchOperation *operation, static void event_manager_media_channel_got_contact (EventManagerApproval *approval) { + EmpathyEventManagerPriv *priv = GET_PRIV (approval->manager); gchar *header; header = g_strdup_printf (_("Incoming call from %s"), @@ -512,7 +457,11 @@ event_manager_media_channel_got_contact (EventManagerApproval *approval) approval, event_channel_process_voip_func, NULL); g_free (header); - event_manager_start_ringing (approval->manager); + + priv->ringing++; + if (priv->ringing == 1) + empathy_sound_start_playing (empathy_main_window_get (), + EMPATHY_SOUND_PHONE_INCOMING, MS_BETWEEN_RING); } static void @@ -958,6 +907,65 @@ event_manager_pendings_changed_cb (EmpathyContactList *list, g_free (header); } +static void +event_manager_presence_changed_cb (EmpathyContactMonitor *monitor, + EmpathyContact *contact, + TpConnectionPresenceType current, + TpConnectionPresenceType previous, + EmpathyEventManager *manager) +{ + McAccount *account; + gboolean just_connected; + EmpathyAccountManager *account_manager; + gchar *header = NULL; + gboolean preference = FALSE; + + account = empathy_contact_get_account (contact); + account_manager = empathy_account_manager_dup_singleton (); + just_connected = empathy_account_manager_is_account_just_connected ( + account_manager, account); + + g_object_unref (account_manager); + if (just_connected) + return; + + if (tp_connection_presence_type_cmp_availability (previous, + TP_CONNECTION_PRESENCE_TYPE_OFFLINE) > 0) + { + /* contact was online */ + empathy_conf_get_bool (empathy_conf_get (), + EMPATHY_PREFS_NOTIFICATIONS_CONTACT_SIGNOUT, &preference); + if (preference && tp_connection_presence_type_cmp_availability (current, + TP_CONNECTION_PRESENCE_TYPE_OFFLINE) <= 0) + { + /* someone is logging off */ + header = g_strdup_printf (_("%s is now offline."), + empathy_contact_get_name (contact)); + + event_manager_add (manager, contact, GTK_STOCK_DIALOG_INFO, header, + NULL, NULL, NULL, NULL); + } + } + else + { + /* contact was offline */ + empathy_conf_get_bool (empathy_conf_get (), + EMPATHY_PREFS_NOTIFICATIONS_CONTACT_SIGNIN, &preference); + if (preference && tp_connection_presence_type_cmp_availability (current, + TP_CONNECTION_PRESENCE_TYPE_OFFLINE) > 0) + { + /* someone is logging in */ + header = g_strdup_printf (_("%s is now online."), + empathy_contact_get_name (contact)); + + event_manager_add (manager, contact, GTK_STOCK_DIALOG_INFO, header, + NULL, NULL, NULL, NULL); + } + } + g_free (header); +} + + static GObject * event_manager_constructor (GType type, guint n_props, @@ -983,6 +991,9 @@ event_manager_finalize (GObject *object) { EmpathyEventManagerPriv *priv = GET_PRIV (object); + if (priv->ringing > 0) + empathy_sound_stop (EMPATHY_SOUND_PHONE_INCOMING); + g_slist_foreach (priv->events, (GFunc) event_free, NULL); g_slist_free (priv->events); g_slist_foreach (priv->approvals, (GFunc) event_manager_approval_free, NULL); @@ -1036,6 +1047,12 @@ empathy_event_manager_init (EmpathyEventManager *manager) { EmpathyEventManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, EMPATHY_TYPE_EVENT_MANAGER, EmpathyEventManagerPriv); + EmpathyContactMonitor *monitor; + EmpathyContactList *list_iface; + + list_iface = EMPATHY_CONTACT_LIST (empathy_contact_manager_dup_singleton ()); + monitor = empathy_contact_list_get_monitor (list_iface); + g_object_unref (list_iface); manager->priv = priv; @@ -1045,6 +1062,8 @@ empathy_event_manager_init (EmpathyEventManager *manager) G_CALLBACK (event_manager_approve_channel_cb), manager); g_signal_connect (priv->contact_manager, "pendings-changed", G_CALLBACK (event_manager_pendings_changed_cb), manager); + g_signal_connect (monitor, "contact-presence-changed", + G_CALLBACK (event_manager_presence_changed_cb), manager); } EmpathyEventManager * @@ -1095,4 +1114,3 @@ empathy_event_inhibit_updates (EmpathyEvent *event_public) event->inhibit = TRUE; } - diff --git a/src/empathy-event-manager.h b/src/empathy-event-manager.h index 42fd0c090..af73c8ea7 100644 --- a/src/empathy-event-manager.h +++ b/src/empathy-event-manager.h @@ -53,6 +53,7 @@ typedef struct { gchar *icon_name; gchar *header; gchar *message; + gboolean must_ack; } EmpathyEvent; GType empathy_event_manager_get_type (void) G_GNUC_CONST; diff --git a/src/empathy-ft-manager.ui b/src/empathy-ft-manager.ui index 1e3c4af7d..fa72af949 100644 --- a/src/empathy-ft-manager.ui +++ b/src/empathy-ft-manager.ui @@ -5,7 +5,7 @@ <property name="width_request">620</property> <property name="height_request">250</property> <property name="border_width">5</property> - <property name="title" translatable="yes">File transfers</property> + <property name="title" translatable="yes">File Transfers</property> <property name="role">empathy-ft-manager</property> <property name="icon_name">document-send</property> <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> diff --git a/src/empathy-main-window.c b/src/empathy-main-window.c index 5830d2b71..0da037beb 100644 --- a/src/empathy-main-window.c +++ b/src/empathy-main-window.c @@ -37,16 +37,17 @@ #include <libempathy/empathy-contact-manager.h> #include <libempathy/empathy-status-presets.h> +#include <libempathy-gtk/empathy-conf.h> #include <libempathy-gtk/empathy-contact-dialogs.h> #include <libempathy-gtk/empathy-contact-list-store.h> #include <libempathy-gtk/empathy-contact-list-view.h> -#include <libempathy-gtk/empathy-presence-chooser.h> -#include <libempathy-gtk/empathy-ui-utils.h> #include <libempathy-gtk/empathy-geometry.h> -#include <libempathy-gtk/empathy-conf.h> -#include <libempathy-gtk/empathy-log-window.h> -#include <libempathy-gtk/empathy-new-message-dialog.h> #include <libempathy-gtk/empathy-gtk-enum-types.h> +#include <libempathy-gtk/empathy-new-message-dialog.h> +#include <libempathy-gtk/empathy-log-window.h> +#include <libempathy-gtk/empathy-presence-chooser.h> +#include <libempathy-gtk/empathy-sound.h> +#include <libempathy-gtk/empathy-ui-utils.h> #include <libmissioncontrol/mission-control.h> @@ -197,7 +198,7 @@ main_window_flash_cb (EmpathyMainWindow *window) events = empathy_event_manager_get_events (window->event_manager); for (l = events; l; l = l->next) { data.event = l->data; - if (!data.event->contact) { + if (!data.event->contact || !data.event->must_ack) { continue; } diff --git a/src/empathy-main-window.h b/src/empathy-main-window.h index 562fa12c6..3d34e6c6b 100644 --- a/src/empathy-main-window.h +++ b/src/empathy-main-window.h @@ -24,7 +24,7 @@ #ifndef __EMPATHY_MAIN_WINDOW_H__ #define __EMPATHY_MAIN_WINDOW_H__ -#include <gtk/gtkwidget.h> +#include <gtk/gtk.h> G_BEGIN_DECLS diff --git a/src/empathy-map-view.c b/src/empathy-map-view.c index b8a32885c..86e15bdff 100644 --- a/src/empathy-map-view.c +++ b/src/empathy-map-view.c @@ -40,6 +40,7 @@ #include <libempathy-gtk/empathy-ui-utils.h> #include "empathy-map-view.h" +#include "ephy-spinner.h" #define DEBUG_FLAG EMPATHY_DEBUG_LOCATION #include <libempathy/empathy-debug.h> @@ -50,117 +51,23 @@ typedef struct { GtkWidget *window; GtkWidget *zoom_in; GtkWidget *zoom_out; + GtkWidget *throbber; ChamplainView *map_view; ChamplainLayer *layer; } EmpathyMapView; -static void map_view_destroy_cb (GtkWidget *widget, - EmpathyMapView *window); -static gboolean map_view_contacts_foreach (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data); -static void map_view_zoom_in_cb (GtkWidget *widget, - EmpathyMapView *window); -static void map_view_zoom_out_cb (GtkWidget *widget, - EmpathyMapView *window); -static void map_view_contact_location_notify (GObject *gobject, - GParamSpec *arg1, - gpointer user_data); - -GtkWidget * -empathy_map_view_show (void) -{ - static EmpathyMapView *window = NULL; - GtkBuilder *gui; - GtkWidget *sw; - GtkWidget *embed; - gchar *filename; - GtkTreeModel *model; - EmpathyContactList *list_iface; - EmpathyContactListStore *list_store; - - if (window) - { - empathy_window_present (GTK_WINDOW (window->window), TRUE); - return window->window; - } - - window = g_slice_new0 (EmpathyMapView); - - /* Set up interface */ - filename = empathy_file_lookup ("empathy-map-view.ui", "src"); - gui = empathy_builder_get_file (filename, - "map_view", &window->window, - "zoom_in", &window->zoom_in, - "zoom_out", &window->zoom_out, - "map_scrolledwindow", &sw, - NULL); - g_free (filename); - - empathy_builder_connect (gui, window, - "map_view", "destroy", map_view_destroy_cb, - "zoom_in", "clicked", map_view_zoom_in_cb, - "zoom_out", "clicked", map_view_zoom_out_cb, - NULL); - - g_object_unref (gui); - - /* Clear the static pointer to window if the dialog is destroyed */ - g_object_add_weak_pointer (G_OBJECT (window->window), (gpointer *) &window); - - list_iface = EMPATHY_CONTACT_LIST (empathy_contact_manager_dup_singleton ()); - list_store = empathy_contact_list_store_new (list_iface); - empathy_contact_list_store_set_show_groups (list_store, FALSE); - empathy_contact_list_store_set_show_avatars (list_store, TRUE); - g_object_unref (list_iface); - - window->list_store = list_store; - - /* Set up map view */ - window->map_view = CHAMPLAIN_VIEW (champlain_view_new ()); - g_object_set (G_OBJECT (window->map_view), "zoom-level", 1, - "scroll-mode", CHAMPLAIN_SCROLL_MODE_KINETIC, NULL); - champlain_view_center_on (window->map_view, 36, 0); - - embed = champlain_view_embed_new (window->map_view); - gtk_container_add (GTK_CONTAINER (sw), - GTK_WIDGET (embed)); - gtk_widget_show_all (embed); - - window->layer = g_object_ref (champlain_layer_new ()); - champlain_view_add_layer (window->map_view, window->layer); - - /* Set up contact list. */ - model = GTK_TREE_MODEL (window->list_store); - gtk_tree_model_foreach (model, map_view_contacts_foreach, window); - - empathy_window_present (GTK_WINDOW (window->window), TRUE); - return window->window; -} - static void -map_view_destroy_cb (GtkWidget *widget, +map_view_state_changed (ChamplainView *view, + GParamSpec *gobject, EmpathyMapView *window) { - GList *item; - - item = clutter_container_get_children (window->layer); - while (item != NULL) - { - EmpathyContact *contact; - ChamplainMarker *marker; + ChamplainState state; - marker = CHAMPLAIN_MARKER (item->data); - contact = g_object_get_data (G_OBJECT (marker), "contact"); - g_signal_handlers_disconnect_by_func (contact, map_view_contact_location_notify, marker); - - item = g_list_next (item); - } - - g_object_unref (window->list_store); - g_object_unref (window->layer); - g_slice_free (EmpathyMapView, window); + g_object_get (G_OBJECT (view), "state", &state, NULL); + if (state == CHAMPLAIN_STATE_LOADING) + ephy_spinner_start (EPHY_SPINNER (window->throbber)); + else + ephy_spinner_stop (EPHY_SPINNER (window->throbber)); } static void @@ -201,22 +108,60 @@ map_view_marker_update_position (ChamplainMarker *marker, } static void -map_view_contact_location_notify (GObject *gobject, +map_view_contact_location_notify (EmpathyContact *contact, GParamSpec *arg1, - gpointer user_data) + ChamplainMarker *marker) { - ChamplainMarker *marker = CHAMPLAIN_MARKER (user_data); - EmpathyContact *contact = EMPATHY_CONTACT (gobject); map_view_marker_update_position (marker, contact); } +static void +map_view_zoom_in_cb (GtkWidget *widget, + EmpathyMapView *window) +{ + champlain_view_zoom_in (window->map_view); +} + +static void +map_view_zoom_out_cb (GtkWidget *widget, + EmpathyMapView *window) +{ + champlain_view_zoom_out (window->map_view); +} + +static gboolean +marker_clicked_cb (ChamplainMarker *marker, + ClutterButtonEvent *event, + EmpathyContact *contact) +{ + GtkWidget *menu; + + if (event->button != 3) + return FALSE; + + menu = empathy_contact_menu_new (contact, + EMPATHY_CONTACT_FEATURE_CHAT | + EMPATHY_CONTACT_FEATURE_CALL | + EMPATHY_CONTACT_FEATURE_LOG | + EMPATHY_CONTACT_FEATURE_INFO); + + if (menu == NULL) + return FALSE; + + gtk_widget_show (menu); + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, + event->button, event->time); + + return FALSE; +} + static gboolean map_view_contacts_foreach (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) { - EmpathyMapView *window = (EmpathyMapView*) user_data; + EmpathyMapView *window = (EmpathyMapView *) user_data; EmpathyContact *contact; ClutterActor *marker; ClutterActor *texture; @@ -269,11 +214,16 @@ map_view_contacts_foreach (GtkTreeModel *model, champlain_marker_set_text (CHAMPLAIN_MARKER (marker), label); g_free (label); + clutter_actor_set_reactive (CLUTTER_ACTOR (marker), TRUE); + g_signal_connect (marker, "button-release-event", + G_CALLBACK (marker_clicked_cb), contact); + clutter_container_add (CLUTTER_CONTAINER (window->layer), marker, NULL); g_signal_connect (contact, "notify::location", G_CALLBACK (map_view_contact_location_notify), marker); - g_object_set_data_full (G_OBJECT (marker), "contact", g_object_ref (contact), g_object_unref); + g_object_set_data_full (G_OBJECT (marker), "contact", + g_object_ref (contact), g_object_unref); map_view_marker_update_position (CHAMPLAIN_MARKER (marker), contact); @@ -282,15 +232,108 @@ map_view_contacts_foreach (GtkTreeModel *model, } static void -map_view_zoom_in_cb (GtkWidget *widget, +map_view_destroy_cb (GtkWidget *widget, EmpathyMapView *window) { - champlain_view_zoom_in (window->map_view); + GList *item; + + item = clutter_container_get_children (CLUTTER_CONTAINER (window->layer)); + while (item != NULL) + { + EmpathyContact *contact; + ChamplainMarker *marker; + + marker = CHAMPLAIN_MARKER (item->data); + contact = g_object_get_data (G_OBJECT (marker), "contact"); + g_signal_handlers_disconnect_by_func (contact, + map_view_contact_location_notify, marker); + + item = g_list_next (item); + } + + g_object_unref (window->list_store); + g_object_unref (window->layer); + g_slice_free (EmpathyMapView, window); } -static void -map_view_zoom_out_cb (GtkWidget *widget, - EmpathyMapView *window) +GtkWidget * +empathy_map_view_show (void) { - champlain_view_zoom_out (window->map_view); + static EmpathyMapView *window = NULL; + GtkBuilder *gui; + GtkWidget *sw; + GtkWidget *embed; + GtkWidget *throbber_holder; + gchar *filename; + GtkTreeModel *model; + EmpathyContactList *list_iface; + EmpathyContactListStore *list_store; + + if (window) + { + empathy_window_present (GTK_WINDOW (window->window), TRUE); + return window->window; + } + + window = g_slice_new0 (EmpathyMapView); + + /* Set up interface */ + filename = empathy_file_lookup ("empathy-map-view.ui", "src"); + gui = empathy_builder_get_file (filename, + "map_view", &window->window, + "zoom_in", &window->zoom_in, + "zoom_out", &window->zoom_out, + "map_scrolledwindow", &sw, + "throbber", &throbber_holder, + NULL); + g_free (filename); + + empathy_builder_connect (gui, window, + "map_view", "destroy", map_view_destroy_cb, + "zoom_in", "clicked", map_view_zoom_in_cb, + "zoom_out", "clicked", map_view_zoom_out_cb, + NULL); + + g_object_unref (gui); + + /* Clear the static pointer to window if the dialog is destroyed */ + g_object_add_weak_pointer (G_OBJECT (window->window), (gpointer *) &window); + + list_iface = EMPATHY_CONTACT_LIST (empathy_contact_manager_dup_singleton ()); + list_store = empathy_contact_list_store_new (list_iface); + empathy_contact_list_store_set_show_groups (list_store, FALSE); + empathy_contact_list_store_set_show_avatars (list_store, TRUE); + g_object_unref (list_iface); + + window->throbber = ephy_spinner_new (); + ephy_spinner_set_size (EPHY_SPINNER (window->throbber), + GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_widget_show (window->throbber); + gtk_container_add (GTK_CONTAINER (throbber_holder), window->throbber); + + window->list_store = list_store; + + /* Set up map view */ + embed = gtk_champlain_embed_new (); + window->map_view = gtk_champlain_embed_get_view (GTK_CHAMPLAIN_EMBED (embed)); + g_object_set (G_OBJECT (window->map_view), "zoom-level", 1, + "scroll-mode", CHAMPLAIN_SCROLL_MODE_KINETIC, NULL); + champlain_view_center_on (window->map_view, 36, 0); + + gtk_container_add (GTK_CONTAINER (sw), embed); + gtk_widget_show_all (embed); + + window->layer = g_object_ref (champlain_layer_new ()); + champlain_view_add_layer (window->map_view, window->layer); + + g_signal_connect (window->map_view, "notify::state", + G_CALLBACK (map_view_state_changed), window); + + /* Set up contact list. */ + model = GTK_TREE_MODEL (window->list_store); + gtk_tree_model_foreach (model, map_view_contacts_foreach, window); + + empathy_window_present (GTK_WINDOW (window->window), TRUE); + return window->window; } + diff --git a/src/empathy-map-view.h b/src/empathy-map-view.h index 80a05a129..6628f1e08 100644 --- a/src/empathy-map-view.h +++ b/src/empathy-map-view.h @@ -21,7 +21,7 @@ #ifndef __EMPATHY_MAP_VIEW_H__ #define __EMPATHY_MAP_VIEW_H__ -#include <gtk/gtkwidget.h> +#include <gtk/gtk.h> G_BEGIN_DECLS diff --git a/src/empathy-map-view.ui b/src/empathy-map-view.ui index f1140399b..545136d4d 100644 --- a/src/empathy-map-view.ui +++ b/src/empathy-map-view.ui @@ -34,6 +34,33 @@ <property name="homogeneous">True</property> </packing> </child> + <child> + <object class="GtkToolItem" id="toolbutton1"> + <property name="visible">True</property> + <child> + <object class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + </packing> + </child> + <child> + <object class="GtkToolItem" id="throbber"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + </packing> + </child> </object> <packing> <property name="expand">False</property> diff --git a/src/empathy-new-chatroom-dialog.c b/src/empathy-new-chatroom-dialog.c index 563665932..da90cbb49 100644 --- a/src/empathy-new-chatroom-dialog.c +++ b/src/empathy-new-chatroom-dialog.c @@ -362,7 +362,7 @@ new_chatroom_dialog_update_widgets (EmpathyNewChatroomDialog *dialog) McProfile *profile; const gchar *protocol; const gchar *room; - + account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser); account = empathy_account_chooser_dup_account (account_chooser); profile = mc_account_get_profile (account); @@ -545,7 +545,7 @@ new_chatroom_dialog_listing_cb (EmpathyTpRoomlist *room_list, /* Update the throbber */ if (listing) { - ephy_spinner_start (EPHY_SPINNER (dialog->throbber)); + ephy_spinner_start (EPHY_SPINNER (dialog->throbber)); } else { ephy_spinner_stop (EPHY_SPINNER (dialog->throbber)); } @@ -572,7 +572,7 @@ new_chatroom_dialog_model_row_activated_cb (GtkTreeView *tree_view, static void new_chatroom_dialog_model_selection_changed (GtkTreeSelection *selection, EmpathyNewChatroomDialog *dialog) -{ +{ GtkTreeModel *model; GtkTreeIter iter; gchar *room = NULL; diff --git a/src/empathy-preferences.c b/src/empathy-preferences.c index 406db4c9f..0e2299cac 100644 --- a/src/empathy-preferences.c +++ b/src/empathy-preferences.c @@ -38,6 +38,10 @@ #include <libempathy-gtk/empathy-contact-list-store.h> #include <libempathy-gtk/empathy-gtk-enum-types.h> +#ifdef HAVE_WEBKIT +#include <libempathy-gtk/empathy-theme-adium.h> +#endif + #include "empathy-preferences.h" typedef struct { @@ -48,7 +52,11 @@ typedef struct { GtkWidget *checkbutton_show_avatars; GtkWidget *checkbutton_compact_contact_list; GtkWidget *checkbutton_show_smileys; + GtkWidget *checkbutton_show_contacts_in_rooms; GtkWidget *combobox_chat_theme; + GtkWidget *hbox_adium_theme; + GtkWidget *filechooserbutton_adium_theme; + GtkWidget *label_invalid_adium_theme; GtkWidget *checkbutton_separate_chat_windows; GtkWidget *checkbutton_autoconnect; GtkWidget *radiobutton_contact_list_sort_by_name; @@ -61,6 +69,8 @@ typedef struct { GtkWidget *checkbutton_notifications_enabled; GtkWidget *checkbutton_notifications_disabled_away; GtkWidget *checkbutton_notifications_focus; + GtkWidget *checkbutton_notifications_contact_signin; + GtkWidget *checkbutton_notifications_contact_signout; GtkWidget *treeview_spell_checker; @@ -89,19 +99,13 @@ static gboolean preferences_languages_load_foreach (GtkTreeModel static void preferences_languages_cell_toggled_cb (GtkCellRendererToggle *cell, gchar *path_string, EmpathyPreferences *preferences); -static void preferences_themes_setup (EmpathyPreferences *preferences); static void preferences_widget_sync_bool (const gchar *key, GtkWidget *widget); static void preferences_widget_sync_string (const gchar *key, GtkWidget *widget); -static void preferences_widget_sync_string_combo (const gchar *key, - GtkWidget *widget); static void preferences_notify_string_cb (EmpathyConf *conf, const gchar *key, gpointer user_data); -static void preferences_notify_string_combo_cb (EmpathyConf *conf, - const gchar *key, - gpointer user_data); static void preferences_notify_bool_cb (EmpathyConf *conf, const gchar *key, gpointer user_data); @@ -114,9 +118,6 @@ static void preferences_hookup_toggle_button (EmpathyPreferences static void preferences_hookup_radio_button (EmpathyPreferences *preferences, const gchar *key, GtkWidget *widget); -static void preferences_hookup_string_combo (EmpathyPreferences *preferences, - const gchar *key, - GtkWidget *widget); static void preferences_hookup_sensitivity (EmpathyPreferences *preferences, const gchar *key, GtkWidget *widget); @@ -124,8 +125,6 @@ static void preferences_toggle_button_toggled_cb (GtkWidget gpointer user_data); static void preferences_radio_button_toggled_cb (GtkWidget *button, gpointer user_data); -static void preferences_string_combo_changed_cb (GtkWidget *button, - gpointer user_data); static void preferences_destroy_cb (GtkWidget *widget, EmpathyPreferences *preferences); static void preferences_response_cb (GtkWidget *widget, @@ -203,6 +202,12 @@ preferences_setup_widgets (EmpathyPreferences *preferences) preferences_hookup_toggle_button (preferences, EMPATHY_PREFS_NOTIFICATIONS_FOCUS, preferences->checkbutton_notifications_focus); + preferences_hookup_toggle_button (preferences, + EMPATHY_PREFS_NOTIFICATIONS_CONTACT_SIGNIN, + preferences->checkbutton_notifications_contact_signin); + preferences_hookup_toggle_button (preferences, + EMPATHY_PREFS_NOTIFICATIONS_CONTACT_SIGNOUT, + preferences->checkbutton_notifications_contact_signout); preferences_hookup_sensitivity (preferences, EMPATHY_PREFS_NOTIFICATIONS_ENABLED, @@ -210,6 +215,12 @@ preferences_setup_widgets (EmpathyPreferences *preferences) preferences_hookup_sensitivity (preferences, EMPATHY_PREFS_NOTIFICATIONS_ENABLED, preferences->checkbutton_notifications_focus); + preferences_hookup_sensitivity (preferences, + EMPATHY_PREFS_NOTIFICATIONS_ENABLED, + preferences->checkbutton_notifications_contact_signin); + preferences_hookup_sensitivity (preferences, + EMPATHY_PREFS_NOTIFICATIONS_ENABLED, + preferences->checkbutton_notifications_contact_signout); preferences_hookup_toggle_button (preferences, EMPATHY_PREFS_SOUNDS_ENABLED, @@ -241,9 +252,9 @@ preferences_setup_widgets (EmpathyPreferences *preferences) EMPATHY_PREFS_CHAT_SHOW_SMILEYS, preferences->checkbutton_show_smileys); - preferences_hookup_string_combo (preferences, - EMPATHY_PREFS_CHAT_THEME, - preferences->combobox_chat_theme); + preferences_hookup_toggle_button (preferences, + EMPATHY_PREFS_CHAT_SHOW_CONTACTS_IN_ROOMS, + preferences->checkbutton_show_contacts_in_rooms); preferences_hookup_radio_button (preferences, EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM, @@ -465,7 +476,7 @@ preferences_languages_add (EmpathyPreferences *preferences) codes != NULL); if (!codes) { gtk_widget_set_sensitive (preferences->treeview_spell_checker, FALSE); - } + } for (l = codes; l; l = l->next) { GtkTreeIter iter; @@ -639,43 +650,6 @@ preferences_languages_cell_toggled_cb (GtkCellRendererToggle *cell, } static void -preferences_themes_setup (EmpathyPreferences *preferences) -{ - GtkComboBox *combo; - GtkCellLayout *cell_layout; - GtkCellRenderer *renderer; - GtkListStore *store; - const gchar **themes; - gint i; - - combo = GTK_COMBO_BOX (preferences->combobox_chat_theme); - cell_layout = GTK_CELL_LAYOUT (combo); - - /* Create the model */ - store = gtk_list_store_new (COL_COMBO_COUNT, - G_TYPE_STRING, /* Display name */ - G_TYPE_STRING); /* Theme name */ - - /* Fill the model */ - themes = empathy_theme_manager_get_themes (); - for (i = 0; themes[i]; i += 2) { - gtk_list_store_insert_with_values (store, NULL, -1, - COL_COMBO_VISIBLE_NAME, _(themes[i + 1]), - COL_COMBO_NAME, themes[i], - -1); - } - - /* Add cell renderer */ - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (cell_layout, renderer, TRUE); - gtk_cell_layout_set_attributes (cell_layout, renderer, - "text", COL_COMBO_VISIBLE_NAME, NULL); - - gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store)); - g_object_unref (store); -} - -static void preferences_widget_sync_bool (const gchar *key, GtkWidget *widget) { gboolean value; @@ -700,12 +674,12 @@ preferences_widget_sync_string (const gchar *key, GtkWidget *widget) GEnumValue *enum_value; GSList *list; GtkWidget *toggle_widget; - + /* Get index from new string */ type = empathy_contact_list_store_sort_get_type (); enum_class = G_ENUM_CLASS (g_type_class_peek (type)); enum_value = g_enum_get_value_by_nick (enum_class, value); - + if (enum_value) { list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget)); toggle_widget = g_slist_nth_data (list, enum_value->value); @@ -721,48 +695,6 @@ preferences_widget_sync_string (const gchar *key, GtkWidget *widget) } static void -preferences_widget_sync_string_combo (const gchar *key, GtkWidget *widget) -{ - gchar *value; - GtkTreeModel *model; - GtkTreeIter iter; - gboolean found; - - if (!empathy_conf_get_string (empathy_conf_get (), key, &value)) { - return; - } - - model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget)); - - found = FALSE; - if (value && gtk_tree_model_get_iter_first (model, &iter)) { - - do { - gchar *name; - gtk_tree_model_get (model, &iter, - COL_COMBO_NAME, &name, - -1); - - if (strcmp (name, value) == 0) { - found = TRUE; - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter); - } - - g_free (name); - } while (!found && gtk_tree_model_iter_next (model, &iter)); - } - - /* Fallback to the first one. */ - if (!found) { - if (gtk_tree_model_get_iter_first (model, &iter)) { - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter); - } - } - - g_free (value); -} - -static void preferences_notify_string_cb (EmpathyConf *conf, const gchar *key, gpointer user_data) @@ -770,13 +702,6 @@ preferences_notify_string_cb (EmpathyConf *conf, preferences_widget_sync_string (key, user_data); } -static void -preferences_notify_string_combo_cb (EmpathyConf *conf, - const gchar *key, - gpointer user_data) -{ - preferences_widget_sync_string_combo (key, user_data); -} static void preferences_notify_bool_cb (EmpathyConf *conf, @@ -816,7 +741,7 @@ preferences_notify_int_cb (EmpathyConf *conf, const gchar *key, gpointer user_data) { - preferences_widget_sync_int (key, user_data); + preferences_widget_sync_int (key, user_data); } static void @@ -955,32 +880,6 @@ preferences_hookup_radio_button (EmpathyPreferences *preferences, } static void -preferences_hookup_string_combo (EmpathyPreferences *preferences, - const gchar *key, - GtkWidget *widget) -{ - guint id; - - preferences_widget_sync_string_combo (key, widget); - - g_object_set_data_full (G_OBJECT (widget), "key", - g_strdup (key), g_free); - - g_signal_connect (widget, - "changed", - G_CALLBACK (preferences_string_combo_changed_cb), - NULL); - - id = empathy_conf_notify_add (empathy_conf_get (), - key, - preferences_notify_string_combo_cb, - widget); - if (id) { - preferences_add_id (preferences, id); - } -} - -static void preferences_hookup_sensitivity (EmpathyPreferences *preferences, const gchar *key, GtkWidget *widget) @@ -1032,14 +931,14 @@ preferences_radio_button_toggled_cb (GtkWidget *button, GType type; GEnumClass *enum_class; GEnumValue *enum_value; - + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)); - + /* Get string from index */ type = empathy_contact_list_store_sort_get_type (); enum_class = G_ENUM_CLASS (g_type_class_peek (type)); enum_value = g_enum_get_value (enum_class, g_slist_index (group, button)); - + if (!enum_value) { g_warning ("No GEnumValue for EmpathyContactListSort with GtkRadioButton index:%d", g_slist_index (group, button)); @@ -1054,29 +953,216 @@ preferences_radio_button_toggled_cb (GtkWidget *button, empathy_conf_set_string (empathy_conf_get (), key, value); } + static void -preferences_string_combo_changed_cb (GtkWidget *combo, - gpointer user_data) +preferences_theme_adium_update_visibility (EmpathyPreferences *preferences, + const gchar *name) +{ + if (name && strcmp (name, "adium") == 0) { + gtk_widget_show (preferences->hbox_adium_theme); + } else { + gtk_widget_hide (preferences->hbox_adium_theme); + gtk_widget_hide (preferences->label_invalid_adium_theme); + } +} + +static void +preferences_theme_adium_update_validity (EmpathyPreferences *preferences, + const gchar *path) +{ +#ifdef HAVE_WEBKIT + if (empathy_adium_path_is_valid (path)) { + gtk_widget_hide (preferences->label_invalid_adium_theme); + } else { + gtk_widget_show (preferences->label_invalid_adium_theme); + } +#endif +} + +static void +preferences_theme_adium_path_notify_cb (EmpathyConf *conf, + const gchar *key, + gpointer user_data) +{ + EmpathyPreferences *preferences = user_data; + GtkFileChooser *chooser; + gchar *value; + const gchar *path; + + if (!empathy_conf_get_string (conf, key, &value)) { + return; + } + + if (EMP_STR_EMPTY (value)) { + path = g_get_home_dir (); + } else { + path = value; + } + + chooser = GTK_FILE_CHOOSER (preferences->filechooserbutton_adium_theme); + gtk_file_chooser_set_current_folder (chooser, path); + preferences_theme_adium_update_validity (preferences, path); + g_free (value); +} + +static void +preferences_theme_adium_file_set_cb (GtkFileChooser *chooser, + EmpathyPreferences *preferences) +{ + gchar *path; + + path = gtk_file_chooser_get_current_folder (chooser); + empathy_conf_set_string (empathy_conf_get (), + EMPATHY_PREFS_CHAT_ADIUM_PATH, + path); + preferences_theme_adium_update_validity (preferences, path); + + g_free (path); +} + +static void +preferences_theme_notify_cb (EmpathyConf *conf, + const gchar *key, + gpointer user_data) +{ + EmpathyPreferences *preferences = user_data; + GtkComboBox *combo; + gchar *value; + GtkTreeModel *model; + GtkTreeIter iter; + gboolean found = FALSE; + + if (!empathy_conf_get_string (conf, key, &value)) { + return; + } + + preferences_theme_adium_update_visibility (preferences, value); + + combo = GTK_COMBO_BOX (preferences->combobox_chat_theme); + model = gtk_combo_box_get_model (combo); + if (value && gtk_tree_model_get_iter_first (model, &iter)) { + gchar *name; + + do { + gtk_tree_model_get (model, &iter, + COL_COMBO_NAME, &name, + -1); + + if (strcmp (name, value) == 0) { + found = TRUE; + gtk_combo_box_set_active_iter (combo, &iter); + break; + } + + g_free (name); + } while (gtk_tree_model_iter_next (model, &iter)); + } + + /* Fallback to the first one. */ + if (!found) { + if (gtk_tree_model_get_iter_first (model, &iter)) { + gtk_combo_box_set_active_iter (combo, &iter); + } + } + + g_free (value); +} + +static void +preferences_theme_changed_cb (GtkComboBox *combo, + EmpathyPreferences *preferences) { - const gchar *key; GtkTreeModel *model; GtkTreeIter iter; gchar *name; - key = g_object_get_data (G_OBJECT (combo), "key"); - - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) { - model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); + if (gtk_combo_box_get_active_iter (combo, &iter)) { + model = gtk_combo_box_get_model (combo); gtk_tree_model_get (model, &iter, COL_COMBO_NAME, &name, -1); - empathy_conf_set_string (empathy_conf_get (), key, name); + + preferences_theme_adium_update_visibility (preferences, name); + + empathy_conf_set_string (empathy_conf_get (), + EMPATHY_PREFS_CHAT_THEME, + name); g_free (name); } } static void +preferences_themes_setup (EmpathyPreferences *preferences) +{ + GtkComboBox *combo; + GtkCellLayout *cell_layout; + GtkCellRenderer *renderer; + GtkListStore *store; + const gchar **themes; + gint i; + guint id; + + combo = GTK_COMBO_BOX (preferences->combobox_chat_theme); + cell_layout = GTK_CELL_LAYOUT (combo); + + /* Create the model */ + store = gtk_list_store_new (COL_COMBO_COUNT, + G_TYPE_STRING, /* Display name */ + G_TYPE_STRING); /* Theme name */ + + /* Fill the model */ + themes = empathy_theme_manager_get_themes (); + for (i = 0; themes[i]; i += 2) { + gtk_list_store_insert_with_values (store, NULL, -1, + COL_COMBO_VISIBLE_NAME, _(themes[i + 1]), + COL_COMBO_NAME, themes[i], + -1); + } + + /* Add cell renderer */ + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (cell_layout, renderer, TRUE); + gtk_cell_layout_set_attributes (cell_layout, renderer, + "text", COL_COMBO_VISIBLE_NAME, NULL); + + gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store)); + g_object_unref (store); + + g_signal_connect (combo, "changed", + G_CALLBACK (preferences_theme_changed_cb), + preferences); + + /* Select the theme from the gconf key and track changes */ + preferences_theme_notify_cb (empathy_conf_get (), + EMPATHY_PREFS_CHAT_THEME, + preferences); + id = empathy_conf_notify_add (empathy_conf_get (), + EMPATHY_PREFS_CHAT_THEME, + preferences_theme_notify_cb, + preferences); + if (id) { + preferences_add_id (preferences, id); + } + + g_signal_connect (preferences->filechooserbutton_adium_theme, + "file-set", + G_CALLBACK (preferences_theme_adium_file_set_cb), + preferences); + /* Select the adium path from the gconf key and track changes */ + preferences_theme_adium_path_notify_cb (empathy_conf_get (), + EMPATHY_PREFS_CHAT_ADIUM_PATH, + preferences); + id = empathy_conf_notify_add (empathy_conf_get (), + EMPATHY_PREFS_CHAT_ADIUM_PATH, + preferences_theme_adium_path_notify_cb, + preferences); + if (id) { + preferences_add_id (preferences, id); + } +} + +static void preferences_response_cb (GtkWidget *widget, gint response, EmpathyPreferences *preferences) @@ -1123,7 +1209,11 @@ empathy_preferences_show (GtkWindow *parent) "checkbutton_show_avatars", &preferences->checkbutton_show_avatars, "checkbutton_compact_contact_list", &preferences->checkbutton_compact_contact_list, "checkbutton_show_smileys", &preferences->checkbutton_show_smileys, + "checkbutton_show_contacts_in_rooms", &preferences->checkbutton_show_contacts_in_rooms, "combobox_chat_theme", &preferences->combobox_chat_theme, + "hbox_adium_theme", &preferences->hbox_adium_theme, + "filechooserbutton_adium_theme", &preferences->filechooserbutton_adium_theme, + "label_invalid_adium_theme", &preferences->label_invalid_adium_theme, "checkbutton_separate_chat_windows", &preferences->checkbutton_separate_chat_windows, "checkbutton_autoconnect", &preferences->checkbutton_autoconnect, "radiobutton_contact_list_sort_by_name", &preferences->radiobutton_contact_list_sort_by_name, @@ -1131,6 +1221,8 @@ empathy_preferences_show (GtkWindow *parent) "checkbutton_notifications_enabled", &preferences->checkbutton_notifications_enabled, "checkbutton_notifications_disabled_away", &preferences->checkbutton_notifications_disabled_away, "checkbutton_notifications_focus", &preferences->checkbutton_notifications_focus, + "checkbutton_notifications_contact_signin", &preferences->checkbutton_notifications_contact_signin, + "checkbutton_notifications_contact_signout", &preferences->checkbutton_notifications_contact_signout, "checkbutton_sounds_enabled", &preferences->checkbutton_sounds_enabled, "checkbutton_sounds_disabled_away", &preferences->checkbutton_sounds_disabled_away, "treeview_sounds", &preferences->treeview_sounds, diff --git a/src/empathy-preferences.h b/src/empathy-preferences.h index 6cc86d1d6..aba58828e 100644 --- a/src/empathy-preferences.h +++ b/src/empathy-preferences.h @@ -25,7 +25,7 @@ #ifndef __EMPATHY_PREFERENCES_H__ #define __EMPATHY_PREFERENCES_H__ -#include <gtk/gtkwindow.h> +#include <gtk/gtk.h> G_BEGIN_DECLS diff --git a/src/empathy-preferences.ui b/src/empathy-preferences.ui index d92fc8f88..38cfd3419 100644 --- a/src/empathy-preferences.ui +++ b/src/empathy-preferences.ui @@ -37,7 +37,6 @@ <child> <object class="GtkVBox" id="vbox199"> <property name="visible">True</property> - <property name="spacing">6</property> <child> <object class="GtkCheckButton" id="checkbutton_compact_contact_list"> <property name="label" translatable="yes">Show co_mpact contact list</property> @@ -86,6 +85,22 @@ <property name="position">2</property> </packing> </child> + <child> + <object class="GtkCheckButton" id="checkbutton_show_contacts_in_rooms"> + <property name="label" translatable="yes">Show contact _list in rooms</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> </object> </child> </object> @@ -93,8 +108,10 @@ <child type="label"> <object class="GtkLabel" id="label611"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Appearance</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Appearance</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> </child> </object> @@ -153,8 +170,10 @@ <child type="label"> <object class="GtkLabel" id="label612"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Behavior</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Behavior</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> </child> </object> @@ -215,8 +234,10 @@ <child type="label"> <object class="GtkLabel" id="label644"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Contact List</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Contact List</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> </child> </object> @@ -289,6 +310,32 @@ <property name="position">1</property> </packing> </child> + <child> + <object class="GtkCheckButton" id="checkbutton_notifications_contact_signin"> + <property name="label" translatable="yes">Enable notifications when a contact comes online</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="checkbutton_notifications_contact_signout"> + <property name="label" translatable="yes">Enable notifications when a contact goes offline</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> </object> </child> </object> @@ -369,8 +416,10 @@ <object class="GtkLabel" id="label645"> <property name="visible">True</property> <property name="xalign">0</property> - <property name="label" translatable="yes"><b>Play sound for events</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Play sound for events</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> <packing> <property name="expand">False</property> @@ -478,9 +527,11 @@ <object class="GtkLabel" id="label6"> <property name="visible">True</property> <property name="xalign">0</property> - <property name="label" translatable="yes"><small>Reduced location accuracy means that nothing more precise than your city, state and country will be published. GPS coordinates will have a random value added (±0.25°).</small></property> - <property name="use_markup">True</property> <property name="wrap">True</property> + <property name="label" translatable="yes">Reduced location accuracy means that nothing more precise than your city, state and country will be published. GPS coordinates will have a random value added (±0.25°).</property> + <attributes> + <attribute name="scale" value="0.8"/> + </attributes> </object> <packing> <property name="position">1</property> @@ -515,8 +566,10 @@ <child type="label"> <object class="GtkLabel" id="label3"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Privacy</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Privacy</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> </child> </object> @@ -594,8 +647,10 @@ <child type="label"> <object class="GtkLabel" id="label5"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Geoclue Settings</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Geoclue Settings</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> </child> </object> @@ -693,9 +748,11 @@ <object class="GtkLabel" id="label616"> <property name="visible">True</property> <property name="xalign">0</property> - <property name="label" translatable="yes"><small>The list of languages reflects only the languages for which you have a dictionary installed.</small></property> - <property name="use_markup">True</property> <property name="wrap">True</property> + <property name="label" translatable="yes">The list of languages reflects only the languages for which you have a dictionary installed.</property> + <attributes> + <attribute name="scale" value="0.8"/> + </attributes> </object> <packing> <property name="position">1</property> @@ -714,8 +771,10 @@ <child type="label"> <object class="GtkLabel" id="label615"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Enable spell checking for languages:</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Enable spell checking for languages:</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> </child> </object> @@ -792,6 +851,50 @@ <property name="position">0</property> </packing> </child> + <child> + <object class="GtkHBox" id="hbox_adium_theme"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label587"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Adium theme to use:</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <object class="GtkFileChooserButton" id="filechooserbutton_adium_theme"> + <property name="visible">True</property> + <property name="preview_widget_active">False</property> + <property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_invalid_adium_theme"> + <property name="visible">True</property> + <property name="label" translatable="yes">Not a valid adium theme</property> + <attributes> + <attribute name="foreground" value="red"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> </object> </child> </object> @@ -799,8 +902,10 @@ <child type="label"> <object class="GtkLabel" id="label626"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Appearance</b></property> - <property name="use_markup">True</property> + <property name="label" translatable="yes">Appearance</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> </object> </child> </object> diff --git a/src/empathy-sidebar.c b/src/empathy-sidebar.c index caca6b5e3..7b70229e2 100644 --- a/src/empathy-sidebar.c +++ b/src/empathy-sidebar.c @@ -165,7 +165,7 @@ empathy_sidebar_set_property (GObject *object, switch (prop_id) { case PROP_CURRENT_PAGE: - empathy_sidebar_set_page (sidebar, g_value_get_object (value)); + empathy_sidebar_set_page (sidebar, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); diff --git a/src/empathy-status-icon.c b/src/empathy-status-icon.c index 9c2194880..d6520ff7c 100644 --- a/src/empathy-status-icon.c +++ b/src/empathy-status-icon.c @@ -229,13 +229,14 @@ status_icon_event_added_cb (EmpathyEventManager *manager, DEBUG ("New event %p", event); priv->event = event; - priv->showing_event_icon = TRUE; - - status_icon_update_icon (icon); - status_icon_update_tooltip (icon); + if (event->must_ack) { + priv->showing_event_icon = TRUE; + status_icon_update_icon (icon); + status_icon_update_tooltip (icon); + } status_icon_update_notification (icon); - if (!priv->blink_timeout) { + if (!priv->blink_timeout && priv->showing_event_icon) { priv->blink_timeout = g_timeout_add (BLINK_TIMEOUT, (GSourceFunc) status_icon_blink_timeout_cb, icon); @@ -260,7 +261,7 @@ status_icon_event_removed_cb (EmpathyEventManager *manager, /* update notification anyway, as it's safe and we might have been * changed presence in the meanwhile - */ + */ status_icon_update_notification (icon); if (!priv->event && priv->blink_timeout) { @@ -378,7 +379,7 @@ status_icon_key_press_event_cb (GtkWidget *window, } return FALSE; } - + static void status_icon_activate_cb (GtkStatusIcon *status_icon, EmpathyStatusIcon *icon) diff --git a/src/empathy.c b/src/empathy.c index d5be4df8d..85124d1e9 100644 --- a/src/empathy.c +++ b/src/empathy.c @@ -38,6 +38,7 @@ #include <libebook/e-book.h> #include <libnotify/notify.h> +#include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> #include <libmissioncontrol/mc-account.h> #include <libmissioncontrol/mission-control.h> @@ -47,6 +48,7 @@ #include <libempathy/empathy-call-factory.h> #include <libempathy/empathy-chatroom-manager.h> #include <libempathy/empathy-account-manager.h> +#include <libempathy/empathy-debugger.h> #include <libempathy/empathy-dispatcher.h> #include <libempathy/empathy-dispatch-operation.h> #include <libempathy/empathy-log-manager.h> @@ -284,13 +286,13 @@ create_salut_account (void) account = mc_account_create (profile); mc_account_set_display_name (account, _("People nearby")); - + nickname = e_contact_get (contact, E_CONTACT_NICKNAME); first_name = e_contact_get (contact, E_CONTACT_GIVEN_NAME); last_name = e_contact_get (contact, E_CONTACT_FAMILY_NAME); email = e_contact_get (contact, E_CONTACT_EMAIL_1); jid = e_contact_get (contact, E_CONTACT_IM_JABBER_HOME_1); - + if (!tp_strdiff (nickname, "nickname")) { g_free (nickname); nickname = NULL; @@ -449,6 +451,31 @@ new_call_handler_cb (EmpathyCallFactory *factory, EmpathyCallHandler *handler, gtk_widget_show (GTK_WIDGET (window)); } +#ifdef ENABLE_DEBUG +static void +default_log_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + g_log_default_handler (log_domain, log_level, message, NULL); + + /* G_LOG_DOMAIN = "empathy". No need to send empathy messages to the + * debugger as they already have in empathy_debug. */ + if (log_level != G_LOG_LEVEL_DEBUG + || tp_strdiff (log_domain, G_LOG_DOMAIN)) { + EmpathyDebugger *dbg; + GTimeVal now; + + dbg = empathy_debugger_get_singleton (); + g_get_current_time (&now); + + empathy_debugger_add_message (dbg, &now, log_domain, + log_level, message); + } +} +#endif /* ENABLE_DEBUG */ + int main (int argc, char *argv[]) { @@ -470,6 +497,7 @@ main (int argc, char *argv[]) gboolean hide_contact_list = FALSE; gboolean accounts_dialog = FALSE; GError *error = NULL; + TpDBusDaemon *dbus_daemon; GOptionEntry options[] = { { "no-connect", 'n', 0, G_OPTION_ARG_NONE, &no_connect, @@ -512,6 +540,11 @@ main (int argc, char *argv[]) gtk_window_set_default_icon_name ("empathy"); textdomain (GETTEXT_PACKAGE); +#ifdef ENABLE_DEBUG + /* Set up debugger */ + g_log_set_default_handler (default_log_handler, NULL); +#endif + /* Setting up the bacon connection */ startup_timestamp = get_startup_timestamp (); connection = bacon_message_connection_new ("empathy"); @@ -547,6 +580,23 @@ main (int argc, char *argv[]) g_warning ("Cannot create the 'empathy' bacon connection."); } + /* Take well-known name */ + dbus_daemon = tp_dbus_daemon_dup (&error); + if (error == NULL) { + if (!tp_dbus_daemon_request_name (dbus_daemon, + "org.gnome.Empathy", + TRUE, &error)) { + DEBUG ("Failed to request well-known name: %s", + error ? error->message : "no message"); + g_clear_error (&error); + } + g_object_unref (dbus_daemon); + } else { + DEBUG ("Failed to dup dbus daemon: %s", + error ? error->message : "no message"); + g_clear_error (&error); + } + /* Setting up MC */ mc = empathy_mission_control_dup_singleton (); g_signal_connect (mc, "ServiceEnded", @@ -584,7 +634,7 @@ main (int argc, char *argv[]) (idle), TP_CONNECTION_PRESENCE_TYPE_OFFLINE) <= 0) { empathy_idle_set_state (idle, MC_PRESENCE_AVAILABLE); } - + create_salut_account (); /* Setting up UI */ diff --git a/src/ephy-spinner.c b/src/ephy-spinner.c index be82ca71b..30ffa57c1 100644 --- a/src/ephy-spinner.c +++ b/src/ephy-spinner.c @@ -34,9 +34,7 @@ #define STOP_PROFILER(name) #include <gdk-pixbuf/gdk-pixbuf.h> -#include <gtk/gtkicontheme.h> -#include <gtk/gtkiconfactory.h> -#include <gtk/gtksettings.h> +#include <gtk/gtk.h> /* Spinner cache implementation */ diff --git a/src/ephy-spinner.h b/src/ephy-spinner.h index 4435fe371..769d54a3d 100644 --- a/src/ephy-spinner.h +++ b/src/ephy-spinner.h @@ -25,8 +25,7 @@ #ifndef EPHY_SPINNER_H #define EPHY_SPINNER_H -#include <gtk/gtkwidget.h> -#include <gtk/gtkenums.h> +#include <gtk/gtk.h> G_BEGIN_DECLS |