aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/empathy-accounts-dialog.c2
-rw-r--r--src/empathy-call-window.c494
-rw-r--r--src/empathy-call-window.ui93
-rw-r--r--src/empathy-chat-window.c95
-rw-r--r--src/empathy-chatrooms-window.c15
-rw-r--r--src/empathy-debug-window.c2
-rw-r--r--src/empathy-event-manager.c4
7 files changed, 501 insertions, 204 deletions
diff --git a/src/empathy-accounts-dialog.c b/src/empathy-accounts-dialog.c
index daae3d874..ec410050b 100644
--- a/src/empathy-accounts-dialog.c
+++ b/src/empathy-accounts-dialog.c
@@ -1224,7 +1224,7 @@ accounts_dialog_add_account (EmpathyAccountsDialog *dialog,
accounts_dialog_connection_changed_cb (account,
0,
status,
- TP_CONNECTION_STATUS_DISCONNECTED,
+ TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED,
NULL,
NULL,
dialog);
diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c
index e1f8cd268..6cd437553 100644
--- a/src/empathy-call-window.c
+++ b/src/empathy-call-window.c
@@ -44,6 +44,9 @@
#include <libempathy-gtk/empathy-ui-utils.h>
#include <libempathy-gtk/empathy-sound.h>
+#define DEBUG_FLAG EMPATHY_DEBUG_VOIP
+#include <libempathy/empathy-debug.h>
+
#include "empathy-call-window.h"
#include "empathy-call-window-fullscreen.h"
#include "empathy-sidebar.h"
@@ -92,6 +95,12 @@ typedef enum {
REDIALING
} CallState;
+typedef enum {
+ CAMERA_STATE_OFF = 0,
+ CAMERA_STATE_PREVIEW,
+ CAMERA_STATE_ON,
+} CameraState;
+
/* private structure */
typedef struct _EmpathyCallWindowPriv EmpathyCallWindowPriv;
@@ -116,13 +125,15 @@ struct _EmpathyCallWindowPriv
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;
+ GtkAction *action_camera;
+ GtkAction *action_camera_preview;
+ GtkWidget *tool_button_camera_off;
+ GtkWidget *tool_button_camera_preview;
+ GtkWidget *tool_button_camera_on;
/* The frames and boxes that contain self and remote avatar and video
input/output. When we redial, we destroy and re-create the boxes */
@@ -173,6 +184,7 @@ struct _EmpathyCallWindowPriv
GMutex *lock;
gboolean call_started;
gboolean sending_video;
+ CameraState camera_state;
EmpathyCallWindowFullscreen *fullscreen;
gboolean is_fullscreen;
@@ -200,18 +212,9 @@ static gboolean empathy_call_window_state_event_cb (GtkWidget *widget,
static void empathy_call_window_sidebar_toggled_cb (GtkToggleButton *toggle,
EmpathyCallWindow *window);
-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);
-
-static void empathy_call_window_show_preview_toggled_cb (
- GtkToggleAction *toggle, EmpathyCallWindow *window);
-
static void empathy_call_window_mic_toggled_cb (
GtkToggleToolButton *toggle, EmpathyCallWindow *window);
@@ -259,11 +262,32 @@ static void
empathy_call_window_volume_changed_cb (GtkScaleButton *button,
gdouble value, EmpathyCallWindow *window);
+static void block_camera_control_signals (EmpathyCallWindow *self);
+static void unblock_camera_control_signals (EmpathyCallWindow *self);
+
static void
empathy_call_window_setup_toolbar (EmpathyCallWindow *self)
{
EmpathyCallWindowPriv *priv = GET_PRIV (self);
GtkToolItem *tool_item;
+ GtkWidget *camera_off_icon;
+ GdkPixbuf *pixbuf, *modded_pixbuf;
+
+ /* set the icon of the 'camera off' button by greying off the webcam icon */
+ pixbuf = empathy_pixbuf_from_icon_name ("camera-web",
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+ modded_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf));
+
+ gdk_pixbuf_saturate_and_pixelate (pixbuf, modded_pixbuf, 1.0, TRUE);
+ g_object_unref (pixbuf);
+
+ camera_off_icon = gtk_image_new_from_pixbuf (modded_pixbuf);
+ g_object_unref (modded_pixbuf);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (
+ priv->tool_button_camera_off), camera_off_icon);
/* Add an empty expanded GtkToolItem so the volume button is at the end of
* the toolbar. */
@@ -642,6 +666,7 @@ empathy_call_window_setup_video_preview (EmpathyCallWindow *window)
return;
}
+ DEBUG ("Create video preview");
g_assert (priv->video_tee == NULL);
priv->video_tee = gst_element_factory_make ("tee", NULL);
@@ -669,6 +694,33 @@ empathy_call_window_setup_video_preview (EmpathyCallWindow *window)
}
static void
+display_video_preview (EmpathyCallWindow *self,
+ gboolean display)
+{
+ EmpathyCallWindowPriv *priv = GET_PRIV (self);
+
+ if (display)
+ {
+ /* Display the preview and hide the self avatar */
+ DEBUG ("Show video preview");
+
+ if (priv->video_preview == NULL)
+ empathy_call_window_setup_video_preview (self);
+ gtk_widget_show (priv->video_preview);
+ gtk_widget_hide (priv->self_user_avatar_widget);
+ }
+ else
+ {
+ /* Display the self avatar and hide the preview */
+ DEBUG ("Show self avatar");
+
+ if (priv->video_preview != NULL)
+ gtk_widget_hide (priv->video_preview);
+ gtk_widget_show (priv->self_user_avatar_widget);
+ }
+}
+
+static void
empathy_call_window_set_state_connecting (EmpathyCallWindow *window)
{
EmpathyCallWindowPriv *priv = GET_PRIV (window);
@@ -682,6 +734,188 @@ empathy_call_window_set_state_connecting (EmpathyCallWindow *window)
}
static void
+disable_camera (EmpathyCallWindow *self)
+{
+ EmpathyCallWindowPriv *priv = GET_PRIV (self);
+
+ if (priv->camera_state == CAMERA_STATE_OFF)
+ return;
+
+ DEBUG ("Disable camera");
+
+ display_video_preview (self, FALSE);
+
+ if (priv->camera_state == CAMERA_STATE_ON)
+ empathy_call_window_set_send_video (self, FALSE);
+
+ block_camera_control_signals (self);
+ gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (
+ priv->tool_button_camera_on), FALSE);
+ gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (
+ priv->tool_button_camera_preview), FALSE);
+
+ gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (
+ priv->tool_button_camera_off), TRUE);
+ gtk_radio_action_set_current_value (GTK_RADIO_ACTION (priv->action_camera),
+ CAMERA_STATE_OFF);
+ unblock_camera_control_signals (self);
+
+ priv->camera_state = CAMERA_STATE_OFF;
+}
+
+static void
+tool_button_camera_off_toggled_cb (GtkToggleToolButton *toggle,
+ EmpathyCallWindow *self)
+{
+ EmpathyCallWindowPriv *priv = GET_PRIV (self);
+
+ if (!gtk_toggle_tool_button_get_active (toggle))
+ {
+ if (priv->camera_state == CAMERA_STATE_OFF)
+ {
+ /* We can't change the state by disabling the button */
+ block_camera_control_signals (self);
+ gtk_toggle_tool_button_set_active (toggle, TRUE);
+ unblock_camera_control_signals (self);
+ }
+
+ return;
+ }
+
+ disable_camera (self);
+}
+
+static void
+enable_preview (EmpathyCallWindow *self)
+{
+ EmpathyCallWindowPriv *priv = GET_PRIV (self);
+
+ if (priv->camera_state == CAMERA_STATE_PREVIEW)
+ return;
+
+ DEBUG ("Enable preview");
+
+ if (priv->camera_state == CAMERA_STATE_ON)
+ /* preview is already displayed so we just have to stop sending */
+ empathy_call_window_set_send_video (self, FALSE);
+
+ display_video_preview (self, TRUE);
+
+ block_camera_control_signals (self);
+ gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (
+ priv->tool_button_camera_off), FALSE);
+ gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (
+ priv->tool_button_camera_on), FALSE);
+
+ gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (
+ priv->tool_button_camera_preview), TRUE);
+ gtk_radio_action_set_current_value (GTK_RADIO_ACTION (priv->action_camera),
+ CAMERA_STATE_PREVIEW);
+ unblock_camera_control_signals (self);
+
+ priv->camera_state = CAMERA_STATE_PREVIEW;
+}
+
+static void
+tool_button_camera_preview_toggled_cb (GtkToggleToolButton *toggle,
+ EmpathyCallWindow *self)
+{
+ EmpathyCallWindowPriv *priv = GET_PRIV (self);
+
+ if (!gtk_toggle_tool_button_get_active (toggle))
+ {
+ if (priv->camera_state == CAMERA_STATE_PREVIEW)
+ {
+ /* We can't change the state by disabling the button */
+ block_camera_control_signals (self);
+ gtk_toggle_tool_button_set_active (toggle, TRUE);
+ unblock_camera_control_signals (self);
+ }
+
+ return;
+ }
+
+ enable_preview (self);
+}
+
+static void
+enable_camera (EmpathyCallWindow *self)
+{
+ EmpathyCallWindowPriv *priv = GET_PRIV (self);
+
+ if (priv->camera_state == CAMERA_STATE_ON)
+ return;
+
+ DEBUG ("Enable camera");
+
+ empathy_call_window_set_send_video (self, TRUE);
+
+ block_camera_control_signals (self);
+ gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (
+ priv->tool_button_camera_off), FALSE);
+ gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (
+ priv->tool_button_camera_preview), FALSE);
+
+ gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (
+ priv->tool_button_camera_on), TRUE);
+ gtk_radio_action_set_current_value (GTK_RADIO_ACTION (priv->action_camera),
+ CAMERA_STATE_ON);
+ unblock_camera_control_signals (self);
+
+ priv->camera_state = CAMERA_STATE_ON;
+}
+
+static void
+tool_button_camera_on_toggled_cb (GtkToggleToolButton *toggle,
+ EmpathyCallWindow *self)
+{
+ EmpathyCallWindowPriv *priv = GET_PRIV (self);
+
+ if (!gtk_toggle_tool_button_get_active (toggle))
+ {
+ if (priv->camera_state == CAMERA_STATE_ON)
+ {
+ /* We can't change the state by disabling the button */
+ block_camera_control_signals (self);
+ gtk_toggle_tool_button_set_active (toggle, TRUE);
+ unblock_camera_control_signals (self);
+ }
+
+ return;
+ }
+
+ enable_camera (self);
+}
+
+static void
+action_camera_change_cb (GtkRadioAction *action,
+ GtkRadioAction *current,
+ EmpathyCallWindow *self)
+{
+ CameraState state;
+
+ state = gtk_radio_action_get_current_value (current);
+
+ switch (state)
+ {
+ case CAMERA_STATE_OFF:
+ disable_camera (self);
+ break;
+
+ case CAMERA_STATE_PREVIEW:
+ enable_preview (self);
+ break;
+
+ case CAMERA_STATE_ON:
+ enable_camera (self);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
empathy_call_window_init (EmpathyCallWindow *self)
{
EmpathyCallWindowPriv *priv = GET_PRIV (self);
@@ -703,13 +937,15 @@ empathy_call_window_init (EmpathyCallWindow *self)
"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,
+ "camera_off", &priv->tool_button_camera_off,
+ "camera_preview", &priv->tool_button_camera_preview,
+ "camera_on", &priv->tool_button_camera_on,
+ "action_camera_off", &priv->action_camera,
+ "action_camera_preview", &priv->action_camera_preview,
NULL);
g_free (filename);
@@ -719,10 +955,11 @@ empathy_call_window_init (EmpathyCallWindow *self)
"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,
- "show_preview", "toggled", empathy_call_window_show_preview_toggled_cb,
"menufullscreen", "activate", empathy_call_window_fullscreen_cb,
+ "camera_off", "toggled", tool_button_camera_off_toggled_cb,
+ "camera_preview", "toggled", tool_button_camera_preview_toggled_cb,
+ "camera_on", "toggled", tool_button_camera_on_toggled_cb,
+ "action_camera_off", "changed", action_camera_change_cb,
NULL);
priv->lock = g_mutex_new ();
@@ -975,18 +1212,6 @@ empathy_call_window_setup_avatars (EmpathyCallWindow *self,
}
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);
@@ -1001,8 +1226,21 @@ empathy_call_window_constructed (GObject *object)
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);
+
+ if (empathy_call_handler_has_initial_video (priv->handler))
+ {
+ /* Enable 'send video' buttons and display the preview */
+ gtk_toggle_tool_button_set_active (
+ GTK_TOGGLE_TOOL_BUTTON (priv->tool_button_camera_on), TRUE);
+
+ display_video_preview (self, TRUE);
+ }
+ else
+ {
+ gtk_toggle_tool_button_set_active (
+ GTK_TOGGLE_TOOL_BUTTON (priv->tool_button_camera_off), TRUE);
+ }
}
static void empathy_call_window_dispose (GObject *object);
@@ -1069,6 +1307,7 @@ static void
empathy_call_window_video_stream_changed_cb (EmpathyTpCall *call,
GParamSpec *property, EmpathyCallWindow *self)
{
+ DEBUG ("video stream changed");
empathy_call_window_update_avatars_visibility (call, self);
}
@@ -1282,8 +1521,6 @@ empathy_call_window_disconnected (EmpathyCallWindow *self)
if (could_reset_pipeline)
{
- gboolean initial_video = empathy_call_handler_has_initial_video (
- priv->handler);
g_mutex_lock (priv->lock);
g_timer_stop (priv->timer);
@@ -1301,19 +1538,19 @@ empathy_call_window_disconnected (EmpathyCallWindow *self)
/* 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->tool_button_camera_on, 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 (priv->tool_button_camera_off), TRUE);
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);
+ /* FIXME: This is to workaround the fact that the pipeline has been
+ * destroyed and so we can't display preview until a new call (and so a
+ * new pipeline) is created. We should fix this properly by refactoring
+ * the code managing the pipeline. This is bug #602937 */
+ gtk_widget_set_sensitive (priv->tool_button_camera_preview, FALSE);
+ gtk_action_set_sensitive (priv->action_camera_preview, FALSE);
gtk_progress_bar_set_fraction (
GTK_PROGRESS_BAR (priv->volume_progress_bar), 0);
@@ -1325,6 +1562,9 @@ empathy_call_window_disconnected (EmpathyCallWindow *self)
priv->call_started = FALSE;
could_disconnect = TRUE;
+
+ /* TODO: display the self avatar of the preview (depends if the "Always
+ * Show Video Preview" is enabled or not) */
}
return could_disconnect;
@@ -1674,24 +1914,21 @@ empathy_call_window_connected (gpointer user_data)
priv->sending_video = can_send_video ?
empathy_tp_call_is_sending_video (call) : FALSE;
- 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),
+ GTK_TOGGLE_TOOL_BUTTON (priv->tool_button_camera_on),
priv->sending_video && priv->video_input != NULL);
- gtk_widget_set_sensitive (priv->camera_button, can_send_video);
- gtk_action_set_sensitive (priv->send_video, can_send_video);
+ gtk_widget_set_sensitive (priv->tool_button_camera_on, can_send_video);
gtk_action_set_sensitive (priv->redial, FALSE);
gtk_widget_set_sensitive (priv->redial_button, FALSE);
gtk_widget_set_sensitive (priv->mic_button, TRUE);
+ /* FIXME: this should won't be needed once bug #602937 is fixed
+ * (see empathy_call_window_disconnected for details) */
+ gtk_widget_set_sensitive (priv->tool_button_camera_preview, TRUE);
+ gtk_action_set_sensitive (priv->action_camera_preview, TRUE);
+
empathy_call_window_update_avatars_visibility (call, self);
g_object_unref (call);
@@ -1770,23 +2007,6 @@ empathy_call_window_sink_added_cb (EmpathyCallHandler *handler,
case TP_MEDIA_STREAM_TYPE_VIDEO:
if (priv->video_input != NULL)
{
- 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);
-
- gtk_toggle_action_set_active (
- GTK_TOGGLE_ACTION (priv->show_preview), TRUE);
-
- if (priv->video_preview != NULL)
- gtk_widget_show (priv->video_preview);
- gtk_widget_hide (priv->self_user_avatar_widget);
- }
-
- g_object_unref (call);
-
if (priv->video_tee != NULL)
{
pad = gst_element_get_request_pad (priv->video_tee, "src%d");
@@ -1806,6 +2026,7 @@ empathy_call_window_remove_video_input (EmpathyCallWindow *self)
EmpathyCallWindowPriv *priv = GET_PRIV (self);
GstElement *preview;
+ DEBUG ("remove video input");
preview = empathy_video_widget_get_element (
EMPATHY_VIDEO_WIDGET (priv->video_preview));
@@ -1823,11 +2044,9 @@ empathy_call_window_remove_video_input (EmpathyCallWindow *self)
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_TOGGLE_TOOL_BUTTON (priv->tool_button_camera_on), FALSE);
+ gtk_widget_set_sensitive (priv->tool_button_camera_on, FALSE);
gtk_widget_show (priv->self_user_avatar_widget);
}
@@ -1898,28 +2117,6 @@ 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)
{
@@ -1935,8 +2132,6 @@ empathy_call_window_update_avatars_visibility (EmpathyTpCall *call,
gtk_widget_hide (priv->video_output);
gtk_widget_show (priv->remote_user_avatar_widget);
}
-
- empathy_call_window_update_self_avatar_visibility (window);
}
static void
@@ -2176,76 +2371,15 @@ empathy_call_window_set_send_video (EmpathyCallWindow *window,
/* 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);
-}
-
-static void
-empathy_call_window_camera_toggled_cb (GtkToggleToolButton *toggle,
- EmpathyCallWindow *window)
-{
- EmpathyCallWindowPriv *priv = GET_PRIV (window);
- gboolean active;
+ display_video_preview (window, send);
if (priv->call_state != CONNECTED)
return;
- active = (gtk_toggle_tool_button_get_active (toggle));
-
- if (priv->sending_video == active)
- return;
-
- empathy_call_window_set_send_video (window, active);
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->send_video), active);
-}
-
-static void
-empathy_call_window_send_video_toggled_cb (GtkToggleAction *toggle,
- EmpathyCallWindow *window)
-{
- 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;
-
- empathy_call_window_set_send_video (window, active);
- gtk_toggle_tool_button_set_active (
- GTK_TOGGLE_TOOL_BUTTON (priv->camera_button), active);
-}
-
-static void
-empathy_call_window_show_preview_toggled_cb (GtkToggleAction *toggle,
- EmpathyCallWindow *window)
-{
- 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);
- }
+ g_object_get (priv->handler, "tp-call", &call, NULL);
+ DEBUG ("%s sending video", send ? "start": "stop");
+ empathy_tp_call_request_video_stream_direction (call, send);
+ g_object_unref (call);
}
static void
@@ -2336,9 +2470,6 @@ empathy_call_window_restart_call (EmpathyCallWindow *window)
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);
@@ -2474,3 +2605,36 @@ empathy_call_window_volume_changed_cb (GtkScaleButton *button,
empathy_audio_sink_set_volume (EMPATHY_GST_AUDIO_SINK (priv->audio_output),
value);
}
+
+/* block all the signals related to camera control widgets. This is useful
+ * when we are manually updating the UI and so don't want to fire the
+ * callbacks */
+static void
+block_camera_control_signals (EmpathyCallWindow *self)
+{
+ EmpathyCallWindowPriv *priv = GET_PRIV (self);
+
+ g_signal_handlers_block_by_func (priv->tool_button_camera_off,
+ tool_button_camera_off_toggled_cb, self);
+ g_signal_handlers_block_by_func (priv->tool_button_camera_preview,
+ tool_button_camera_preview_toggled_cb, self);
+ g_signal_handlers_block_by_func (priv->tool_button_camera_on,
+ tool_button_camera_on_toggled_cb, self);
+ g_signal_handlers_block_by_func (priv->action_camera,
+ tool_button_camera_on_toggled_cb, self);
+}
+
+static void
+unblock_camera_control_signals (EmpathyCallWindow *self)
+{
+ EmpathyCallWindowPriv *priv = GET_PRIV (self);
+
+ g_signal_handlers_unblock_by_func (priv->tool_button_camera_off,
+ tool_button_camera_off_toggled_cb, self);
+ g_signal_handlers_unblock_by_func (priv->tool_button_camera_preview,
+ tool_button_camera_preview_toggled_cb, self);
+ g_signal_handlers_unblock_by_func (priv->tool_button_camera_on,
+ tool_button_camera_on_toggled_cb, self);
+ g_signal_handlers_unblock_by_func (priv->action_camera,
+ tool_button_camera_on_toggled_cb, self);
+}
diff --git a/src/empathy-call-window.ui b/src/empathy-call-window.ui
index 64e87e040..94d2fba83 100644
--- a/src/empathy-call-window.ui
+++ b/src/empathy-call-window.ui
@@ -11,13 +11,6 @@
</object>
</child>
<child>
- <object class="GtkToggleAction" id="send_video">
- <property name="name">send_video</property>
- <property name="label" translatable="yes">Send video</property>
- <property name="sensitive">False</property>
- </object>
- </child>
- <child>
<object class="GtkAction" id="menuhangup">
<property name="icon_name">call-stop</property>
<property name="name">menuhangup</property>
@@ -33,16 +26,45 @@
</object>
</child>
<child>
- <object class="GtkAction" id="view">
- <property name="name">view</property>
- <property name="label" translatable="yes">_View</property>
+ <object class="GtkAction" id="camera">
+ <property name="name">camera</property>
+ <property name="label" translatable="yes">V_ideo</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkRadioAction" id="action_camera_off">
+ <property name="name">action_camera_off</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Video Off</property>
+ <property name="draw_as_radio">True</property>
+ <property name="value">0</property>
+ <property name="current-value">0</property>
</object>
</child>
<child>
- <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 class="GtkRadioAction" id="action_camera_preview">
+ <property name="name">action_camera_preview</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Video Preview</property>
+ <property name="draw_as_radio">True</property>
+ <property name="group">action_camera_off</property>
+ <property name="value">1</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkRadioAction" id="action_camera_on">
+ <property name="name">action_camera_on</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Video On</property>
+ <property name="draw_as_radio">True</property>
+ <property name="group">action_camera_off</property>
+ <property name="value">2</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkAction" id="view">
+ <property name="name">view</property>
+ <property name="label" translatable="yes">_View</property>
</object>
</child>
<child>
@@ -57,12 +79,15 @@
<ui>
<menubar name="menubar1">
<menu action="call">
- <menuitem action="send_video"/>
<menuitem action="menuhangup"/>
<menuitem action="menuredial"/>
</menu>
+ <menu action="camera">
+ <menuitem action="action_camera_off"/>
+ <menuitem action="action_camera_preview"/>
+ <menuitem action="action_camera_on"/>
+ </menu>
<menu action="view">
- <menuitem action="show_preview"/>
<menuitem action="menufullscreen"/>
</menu>
</menubar>
@@ -127,11 +152,43 @@
</packing>
</child>
<child>
- <object class="GtkToggleToolButton" id="camera">
+ <object class="GtkSeparatorToolItem" id="camera_separator">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleToolButton" id="camera_off">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Camera Off</property>
+ <property name="sensitive">True</property>
+ <property name="tooltip_text" translatable="yes">Disable camera and stop sending video</property>
+ </object>
+ <packing>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleToolButton" id="camera_preview">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Preview</property>
+ <property name="icon_name">stock_person</property>
+ <property name="sensitive">True</property>
+ <property name="tooltip_text" translatable="yes">Enable camera but don't send video</property>
+ </object>
+ <packing>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleToolButton" id="camera_on">
<property name="visible">True</property>
- <property name="label" translatable="yes">Send video</property>
+ <property name="label" translatable="yes">Camera On</property>
<property name="icon_name">camera-web</property>
<property name="sensitive">False</property>
+ <property name="tooltip_text" translatable="yes">Enable camera and send video</property>
</object>
<packing>
<property name="homogeneous">True</property>
diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c
index fb04e7c3e..ea63f29aa 100644
--- a/src/empathy-chat-window.c
+++ b/src/empathy-chat-window.c
@@ -369,16 +369,97 @@ chat_window_contact_menu_update (EmpathyChatWindowPriv *priv,
}
}
+static guint
+get_all_unread_messages (EmpathyChatWindowPriv *priv)
+{
+ GList *l;
+ guint nb = 0;
+
+ for (l = priv->chats_new_msg; l != NULL; l = g_list_next (l)) {
+ EmpathyChat *chat = l->data;
+
+ nb += empathy_chat_get_nb_unread_messages (chat);
+ }
+
+ return nb;
+}
+
+static gchar *
+get_window_title_name (EmpathyChatWindowPriv *priv)
+{
+ const gchar *active_name;
+ guint nb_chats;
+ guint current_unread_msgs;
+
+ nb_chats = g_list_length (priv->chats);
+ g_assert (nb_chats > 0);
+
+ active_name = empathy_chat_get_name (priv->current_chat);
+
+ current_unread_msgs = empathy_chat_get_nb_unread_messages (
+ priv->current_chat);
+
+ if (nb_chats == 1) {
+ /* only one tab */
+ if (current_unread_msgs == 0)
+ return g_strdup (active_name);
+ else
+ return g_strdup_printf (ngettext (
+ "%s (%d unread)",
+ "%s (%d unread)", current_unread_msgs),
+ active_name, current_unread_msgs);
+ } else {
+ guint nb_others = nb_chats - 1;
+ guint all_unread_msgs;
+
+ all_unread_msgs = get_all_unread_messages (priv);
+
+ if (all_unread_msgs == 0) {
+ /* no unread message */
+ return g_strdup_printf (ngettext (
+ "%s (and %u other)",
+ "%s (and %u others)", nb_others),
+ active_name, nb_others);
+ }
+
+ else if (all_unread_msgs == current_unread_msgs) {
+ /* unread messages are in the current tab */
+ return g_strdup_printf (ngettext (
+ "%s (%d unread)",
+ "%s (%d unread)", current_unread_msgs),
+ active_name, current_unread_msgs);
+ }
+
+ else if (current_unread_msgs == 0) {
+ /* unread messages are in other tabs */
+ return g_strdup_printf (ngettext (
+ "%s (%d unread from others)",
+ "%s (%d unread from others)",
+ all_unread_msgs),
+ active_name, all_unread_msgs);
+ }
+
+ else {
+ /* unread messages are in all the tabs */
+ return g_strdup_printf (ngettext (
+ "%s (%d unread from all)",
+ "%s (%d unread from all)",
+ all_unread_msgs),
+ active_name, all_unread_msgs);
+ }
+ }
+}
+
static void
chat_window_title_update (EmpathyChatWindowPriv *priv)
{
- const gchar *name;
-
- name = empathy_chat_get_name (priv->current_chat);
+ gchar *name;
DEBUG ("Update window : Title");
+ name = get_window_title_name (priv);
gtk_window_set_title (GTK_WINDOW (priv->dialog), name);
+ g_free (name);
}
static void
@@ -1127,6 +1208,8 @@ chat_window_new_message_cb (EmpathyChat *chat,
}
if (has_focus && priv->current_chat == chat) {
+ /* window and tab are focused so consider the message to be read */
+ empathy_chat_messages_read (chat);
return;
}
@@ -1157,6 +1240,9 @@ chat_window_new_message_cb (EmpathyChat *chat,
EMPATHY_SOUND_MESSAGE_INCOMING);
chat_window_show_or_update_notification (window, message, chat);
}
+
+ /* update the number of unread messages */
+ chat_window_title_update (priv);
}
static GtkNotebook *
@@ -1213,6 +1299,7 @@ chat_window_page_switched_cb (GtkNotebook *notebook,
priv->current_chat = chat;
priv->chats_new_msg = g_list_remove (priv->chats_new_msg, chat);
+ empathy_chat_messages_read (chat);
chat_window_update_chat_tab (chat);
}
@@ -1304,6 +1391,7 @@ chat_window_page_removed_cb (GtkNotebook *notebook,
/* Keep list of chats up to date */
priv->chats = g_list_remove (priv->chats, chat);
priv->chats_new_msg = g_list_remove (priv->chats_new_msg, chat);
+ empathy_chat_messages_read (chat);
priv->chats_composing = g_list_remove (priv->chats_composing, chat);
if (priv->chats == NULL) {
@@ -1325,6 +1413,7 @@ chat_window_focus_in_event_cb (GtkWidget *widget,
priv = GET_PRIV (window);
priv->chats_new_msg = g_list_remove (priv->chats_new_msg, priv->current_chat);
+ empathy_chat_messages_read (priv->current_chat);
chat_window_set_urgency_hint (window, FALSE);
diff --git a/src/empathy-chatrooms-window.c b/src/empathy-chatrooms-window.c
index 6f2c8c24c..aae8aac32 100644
--- a/src/empathy-chatrooms-window.c
+++ b/src/empathy-chatrooms-window.c
@@ -52,8 +52,6 @@ typedef struct {
GtkWidget *button_remove;
GtkWidget *button_edit;
GtkWidget *button_close;
-
- gint room_column;
} EmpathyChatroomsWindow;
static void chatrooms_window_destroy_cb (GtkWidget *widget,
@@ -278,7 +276,6 @@ chatrooms_window_model_add_columns (EmpathyChatroomsWindow *window)
NULL);
count = gtk_tree_view_append_column (view, column);
gtk_tree_view_column_set_sort_column_id (column, count - 1);
- window->room_column = count - 1;
/* Chatroom auto connect */
cell = gtk_cell_renderer_toggle_new ();
@@ -306,7 +303,6 @@ chatrooms_window_model_refresh_data (EmpathyChatroomsWindow *window,
GtkTreeModel *model;
GtkListStore *store;
GtkTreeIter iter;
- GtkTreeViewColumn *column;
EmpathyAccountChooser *account_chooser;
TpAccount *account;
GList *chatrooms, *l;
@@ -322,17 +318,6 @@ chatrooms_window_model_refresh_data (EmpathyChatroomsWindow *window,
chatrooms = empathy_chatroom_manager_get_chatrooms (window->manager, account);
- /* Sort out columns, we only show the server column for
- * selected protocol types, such as Jabber.
- */
- if (account) {
- column = gtk_tree_view_get_column (view, window->room_column);
- gtk_tree_view_column_set_visible (column, TRUE);
- } else {
- column = gtk_tree_view_get_column (view, window->room_column);
- gtk_tree_view_column_set_visible (column, FALSE);
- }
-
/* Clean out the store */
gtk_list_store_clear (store);
diff --git a/src/empathy-debug-window.c b/src/empathy-debug-window.c
index e4c1445e6..4c34e6808 100644
--- a/src/empathy-debug-window.c
+++ b/src/empathy-debug-window.c
@@ -31,6 +31,7 @@
#include <libempathy/empathy-utils.h>
#include <libempathy-gtk/empathy-account-chooser.h>
+#include <libempathy-gtk/empathy-geometry.h>
#include <telepathy-glib/dbus.h>
#include <telepathy-glib/util.h>
@@ -1163,6 +1164,7 @@ debug_window_constructor (GType type,
gtk_window_set_title (GTK_WINDOW (object), _("Debug Window"));
gtk_window_set_default_size (GTK_WINDOW (object), 800, 400);
+ empathy_geometry_bind (GTK_WINDOW (object), "debug-window");
g_signal_connect (object, "key-press-event",
G_CALLBACK (debug_window_key_press_event_cb), NULL);
diff --git a/src/empathy-event-manager.c b/src/empathy-event-manager.c
index 0992dd243..86956e7f9 100644
--- a/src/empathy-event-manager.c
+++ b/src/empathy-event-manager.c
@@ -944,7 +944,7 @@ event_manager_presence_changed_cb (EmpathyContactMonitor *monitor,
empathy_contact_get_name (contact));
event_manager_add (manager, contact, EMPATHY_EVENT_TYPE_PRESENCE,
- GTK_STOCK_DIALOG_INFO, header, NULL, NULL, NULL, NULL);
+ "stock_person", header, NULL, NULL, NULL, NULL);
}
}
else
@@ -960,7 +960,7 @@ event_manager_presence_changed_cb (EmpathyContactMonitor *monitor,
empathy_contact_get_name (contact));
event_manager_add (manager, contact, EMPATHY_EVENT_TYPE_PRESENCE,
- GTK_STOCK_DIALOG_INFO, header, NULL, NULL, NULL, NULL);
+ "stock_person", header, NULL, NULL, NULL, NULL);
}
}
g_free (header);