aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am25
-rw-r--r--src/empathy-about-dialog.c3
-rw-r--r--src/empathy-about-dialog.h2
-rw-r--r--src/empathy-accounts-dialog.c31
-rw-r--r--src/empathy-accounts-dialog.h2
-rw-r--r--src/empathy-accounts-dialog.ui99
-rw-r--r--src/empathy-call-window.c710
-rw-r--r--src/empathy-call-window.ui26
-rw-r--r--src/empathy-chat-window.c59
-rw-r--r--src/empathy-chat-window.h2
-rw-r--r--src/empathy-chat-window.ui8
-rw-r--r--src/empathy-debug-dialog.c12
-rw-r--r--src/empathy-event-manager.c188
-rw-r--r--src/empathy-event-manager.h1
-rw-r--r--src/empathy-ft-manager.ui2
-rw-r--r--src/empathy-main-window.c13
-rw-r--r--src/empathy-main-window.h2
-rw-r--r--src/empathy-map-view.c273
-rw-r--r--src/empathy-map-view.h2
-rw-r--r--src/empathy-map-view.ui27
-rw-r--r--src/empathy-new-chatroom-dialog.c6
-rw-r--r--src/empathy-preferences.c374
-rw-r--r--src/empathy-preferences.h2
-rw-r--r--src/empathy-preferences.ui147
-rw-r--r--src/empathy-sidebar.c2
-rw-r--r--src/empathy-status-icon.c15
-rw-r--r--src/empathy.c56
-rw-r--r--src/ephy-spinner.c4
-rw-r--r--src/ephy-spinner.h3
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">&lt;big&gt;&lt;b&gt;Gmail&lt;/b&gt;&lt;/big&gt;</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">&lt;b&gt;Settings&lt;/b&gt;</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">&lt;b&gt;New Account&lt;/b&gt;</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">&lt;b&gt;No protocol installed&lt;/b&gt;</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">&lt;b&gt;Appearance&lt;/b&gt;</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">&lt;b&gt;Behavior&lt;/b&gt;</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">&lt;b&gt;Contact List&lt;/b&gt;</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">&lt;b&gt;Play sound for events&lt;/b&gt;</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">&lt;small&gt;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 (&#xB1;0.25&#xB0;).&lt;/small&gt;</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 (&#xB1;0.25&#xB0;).</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">&lt;b&gt;Privacy&lt;/b&gt;</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">&lt;b&gt;Geoclue Settings&lt;/b&gt;</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">&lt;small&gt;The list of languages reflects only the languages for which you have a dictionary installed.&lt;/small&gt;</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">&lt;b&gt;Enable spell checking for languages:&lt;/b&gt;</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">&lt;b&gt;Appearance&lt;/b&gt;</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