From 6ad2bc640794ad3d78c401e4e9391169446db619 Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Thu, 17 Feb 2011 16:07:28 +0000 Subject: voip widget added --- src/voip-input-widget.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 src/voip-input-widget.c (limited to 'src/voip-input-widget.c') diff --git a/src/voip-input-widget.c b/src/voip-input-widget.c new file mode 100644 index 0000000..4933d7b --- /dev/null +++ b/src/voip-input-widget.c @@ -0,0 +1,252 @@ + +/* +Copyright 2011 Canonical Ltd. + +Authors: + Conor Curran + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "voip-input-widget.h" +#include "common-defs.h" +#include +//#include "indicator-sound.h" + +typedef struct _VoipInputWidgetPrivate VoipInputWidgetPrivate; + +struct _VoipInputWidgetPrivate +{ + DbusmenuMenuitem* twin_item; + GtkWidget* ido_voip_input_slider; + gboolean grabbed; +}; + +#define VOIP_INPUT_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOIP_INPUT_WIDGET_TYPE, VoipInputWidgetPrivate)) + +/* Prototypes */ +static void voip_input_widget_class_init (VoipInputWidgetClass *klass); +static void voip_input_widget_init (VoipInputWidget *self); +static void voip_input_widget_dispose (GObject *object); +static void voip_input_widget_finalize (GObject *object); +static void voip_input_widget_set_twin_item( VoipInputWidget* self, + DbusmenuMenuitem* twin_item); +static void voip_input_widget_property_update( DbusmenuMenuitem* item, gchar* property, + GVariant* value, gpointer userdata ); + +static gboolean voip_input_widget_change_value_cb (GtkRange *range, + GtkScrollType scroll, + gdouble value, + gpointer user_data); +static gboolean voip_input_widget_value_changed_cb(GtkRange *range, gpointer user_data); +static void voip_input_widget_slider_grabbed(GtkWidget *widget, gpointer user_data); +static void voip_input_widget_slider_released(GtkWidget *widget, gpointer user_data); +static void voip_input_widget_parent_changed (GtkWidget *widget, gpointer user_data); + +G_DEFINE_TYPE (VoipInputWidget, voip_input_widget, G_TYPE_OBJECT); + + +static void +voip_input_widget_class_init (VoipInputWidgetClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (VoipInputWidgetPrivate)); + + gobject_class->dispose = voip_input_widget_dispose; + gobject_class->finalize = voip_input_widget_finalize; +} + +static void +voip_input_widget_init (VoipInputWidget *self) +{ + //g_debug("VoipInputWidget::voip_input_widget_init"); + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self); + + priv->ido_voip_input_slider = ido_scale_menu_item_new_with_range ("VOLUME", IDO_RANGE_STYLE_DEFAULT, 0, 0, 100, 1); + g_object_ref (priv->ido_voip_input_slider); + ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM (priv->ido_voip_input_slider), IDO_SCALE_MENU_ITEM_STYLE_IMAGE); + g_object_set(priv->ido_voip_input_slider, "reverse-scroll-events", TRUE, NULL); + + g_signal_connect (priv->ido_voip_input_slider, + "notify::parent", G_CALLBACK (voip_input_widget_parent_changed), + NULL); + + GtkWidget* voip_input_widget = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); + + g_signal_connect(voip_input_widget, "change-value", G_CALLBACK(voip_input_widget_change_value_cb), self); + g_signal_connect(voip_input_widget, "value-changed", G_CALLBACK(voip_input_widget_value_changed_cb), self); + g_signal_connect(priv->ido_voip_input_slider, "slider-grabbed", G_CALLBACK(voip_input_widget_slider_grabbed), self); + g_signal_connect(priv->ido_voip_input_slider, "slider-released", G_CALLBACK(voip_input_widget_slider_released), self); + + GtkWidget* primary_image = ido_scale_menu_item_get_primary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider); + GIcon * primary_gicon = g_themed_icon_new_with_default_fallbacks("audio-volume-low-zero-panel"); + gtk_image_set_from_gicon(GTK_IMAGE(primary_image), primary_gicon, GTK_ICON_SIZE_MENU); + g_object_unref(primary_gicon); + + GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider); + GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks("audio-volume-high-panel"); + gtk_image_set_from_gicon(GTK_IMAGE(secondary_image), secondary_gicon, GTK_ICON_SIZE_MENU); + g_object_unref(secondary_gicon); + + GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (voip_input_widget)); + gtk_adjustment_set_step_increment(adj, 4); +} + +static void +voip_input_widget_dispose (GObject *object) +{ + G_OBJECT_CLASS (voip_input_widget_parent_class)->dispose (object); +} + +static void +voip_input_widget_finalize (GObject *object) +{ + G_OBJECT_CLASS (voip_input_widget_parent_class)->finalize (object); +} + +static void +voip_input_widget_property_update( DbusmenuMenuitem* item, gchar* property, + GVariant* value, gpointer userdata) +{ + g_return_if_fail (IS_VOIP_INPUT_WIDGET (userdata)); + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(userdata); + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); + //g_debug("scrub-widget::property_update for prop %s", property); + if(g_ascii_strcasecmp(DBUSMENU_VOLUME_MENUITEM_LEVEL, property) == 0){ + if(priv->grabbed == FALSE){ + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); + GtkRange *range = (GtkRange*)slider; + gdouble update = g_variant_get_double (value); + //g_debug("volume-widget - update level with value %f", update); + gtk_range_set_value(range, update); + } + } +} + +static void +voip_input_widget_set_twin_item(VoipInputWidget* self, + DbusmenuMenuitem* twin_item) +{ + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self); + priv->twin_item = twin_item; + g_object_ref(priv->twin_item); + g_signal_connect(G_OBJECT(twin_item), "property-changed", + G_CALLBACK(voip_input_widget_property_update), self); + gdouble initial_level = g_variant_get_double (dbusmenu_menuitem_property_get_variant(twin_item, + DBUSMENU_VOLUME_MENUITEM_LEVEL)); + //g_debug("voip_input_widget_set_twin_item initial level = %f", initial_level); + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); + GtkRange *range = (GtkRange*)slider; + gtk_range_set_value(range, initial_level); +} + +static gboolean +voip_input_widget_change_value_cb (GtkRange *range, + GtkScrollType scroll, + gdouble new_value, + gpointer user_data) +{ + g_return_val_if_fail (IS_VOIP_INPUT_WIDGET (user_data), FALSE); + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data); + voip_input_widget_update(mitem, new_value); + return FALSE; +} + +/* + We only want this callback to catch mouse icon press events + which set the slider to 0 or 100. Ignore all other events. +*/ +static gboolean +voip_input_widget_value_changed_cb(GtkRange *range, gpointer user_data) +{ + g_return_val_if_fail (IS_VOIP_INPUT_WIDGET (user_data), FALSE); + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data); + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); + gdouble current_value = CLAMP(gtk_range_get_value(GTK_RANGE(slider)), 0, 100); + + if(current_value == 0 || current_value == 100){ + voip_input_widget_update(mitem, current_value); + } + return FALSE; +} + +void +voip_input_widget_update(VoipInputWidget* self, gdouble update) +{ + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self); + gdouble clamped = CLAMP(update, 0, 100); + GVariant* new_volume = g_variant_new_double(clamped); + dbusmenu_menuitem_handle_event (priv->twin_item, "update", new_volume, 0); +} + +GtkWidget* +voip_input_widget_get_ido_slider(VoipInputWidget* self) +{ + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self); + return priv->ido_voip_input_slider; +} + +static void +voip_input_widget_parent_changed (GtkWidget *widget, + gpointer user_data) +{ + gtk_widget_set_size_request (widget, 200, -1); + //g_debug("voip_input_widget_parent_changed"); +} + +static void +voip_input_widget_slider_grabbed(GtkWidget *widget, gpointer user_data) +{ + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data); + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); + priv->grabbed = TRUE; +} + +static void +voip_input_widget_slider_released(GtkWidget *widget, gpointer user_data) +{ + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data); + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); + priv->grabbed = FALSE; +} + +void +voip_input_widget_tidy_up (GtkWidget *widget) +{ + VoipInputWidget* mitem = VOIP_INPUT_WIDGET(widget); + VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); + gtk_widget_destroy (priv->ido_voip_input_slider); +} + +/** + * voip_input_widget_new: + * @returns: a new #VoipInputWidget. + **/ +GtkWidget* +voip_input_widget_new(DbusmenuMenuitem *item) +{ + GtkWidget* widget = g_object_new(VOIP_INPUT_WIDGET_TYPE, NULL); + voip_input_widget_set_twin_item((VoipInputWidget*)widget, item); + return widget; +} + + -- cgit v1.2.3 From 4bebcafef41b3dbc6b4f3f3e2f6382d82390335f Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Thu, 17 Feb 2011 18:54:58 +0000 Subject: getting there --- src/voip-input-widget.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/voip-input-widget.c') diff --git a/src/voip-input-widget.c b/src/voip-input-widget.c index 4933d7b..5ce7601 100644 --- a/src/voip-input-widget.c +++ b/src/voip-input-widget.c @@ -130,7 +130,7 @@ voip_input_widget_property_update( DbusmenuMenuitem* item, gchar* property, VoipInputWidget* mitem = VOIP_INPUT_WIDGET(userdata); VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem); //g_debug("scrub-widget::property_update for prop %s", property); - if(g_ascii_strcasecmp(DBUSMENU_VOLUME_MENUITEM_LEVEL, property) == 0){ + if(g_ascii_strcasecmp(DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL, property) == 0){ if(priv->grabbed == FALSE){ GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); GtkRange *range = (GtkRange*)slider; @@ -142,8 +142,8 @@ voip_input_widget_property_update( DbusmenuMenuitem* item, gchar* property, } static void -voip_input_widget_set_twin_item(VoipInputWidget* self, - DbusmenuMenuitem* twin_item) +voip_input_widget_set_twin_item (VoipInputWidget* self, + DbusmenuMenuitem* twin_item) { VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self); priv->twin_item = twin_item; @@ -151,7 +151,7 @@ voip_input_widget_set_twin_item(VoipInputWidget* self, g_signal_connect(G_OBJECT(twin_item), "property-changed", G_CALLBACK(voip_input_widget_property_update), self); gdouble initial_level = g_variant_get_double (dbusmenu_menuitem_property_get_variant(twin_item, - DBUSMENU_VOLUME_MENUITEM_LEVEL)); + DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL)); //g_debug("voip_input_widget_set_twin_item initial level = %f", initial_level); GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); GtkRange *range = (GtkRange*)slider; @@ -160,9 +160,9 @@ voip_input_widget_set_twin_item(VoipInputWidget* self, static gboolean voip_input_widget_change_value_cb (GtkRange *range, - GtkScrollType scroll, - gdouble new_value, - gpointer user_data) + GtkScrollType scroll, + gdouble new_value, + gpointer user_data) { g_return_val_if_fail (IS_VOIP_INPUT_WIDGET (user_data), FALSE); VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data); @@ -170,6 +170,7 @@ voip_input_widget_change_value_cb (GtkRange *range, return FALSE; } + /* We only want this callback to catch mouse icon press events which set the slider to 0 or 100. Ignore all other events. -- cgit v1.2.3 From 8263f9aed8c1c66cfe7a7749a4d78c096165acd3 Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Thu, 17 Feb 2011 19:58:09 +0000 Subject: enough for one day --- src/voip-input-widget.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/voip-input-widget.c') diff --git a/src/voip-input-widget.c b/src/voip-input-widget.c index 5ce7601..fa58d21 100644 --- a/src/voip-input-widget.c +++ b/src/voip-input-widget.c @@ -28,7 +28,6 @@ with this program. If not, see . #include "voip-input-widget.h" #include "common-defs.h" #include -//#include "indicator-sound.h" typedef struct _VoipInputWidgetPrivate VoipInputWidgetPrivate; @@ -102,7 +101,7 @@ voip_input_widget_init (VoipInputWidget *self) g_object_unref(primary_gicon); GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider); - GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks("audio-volume-high-panel"); + GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks("audio-input-microphone"); gtk_image_set_from_gicon(GTK_IMAGE(secondary_image), secondary_gicon, GTK_ICON_SIZE_MENU); g_object_unref(secondary_gicon); -- cgit v1.2.3 From d8cc480485f8f46142298341ef5336a0572be5b4 Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Fri, 18 Feb 2011 13:05:58 +0000 Subject: all working nicely, custom mute behaviour needed --- src/voip-input-widget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/voip-input-widget.c') diff --git a/src/voip-input-widget.c b/src/voip-input-widget.c index fa58d21..de06c7c 100644 --- a/src/voip-input-widget.c +++ b/src/voip-input-widget.c @@ -96,12 +96,12 @@ voip_input_widget_init (VoipInputWidget *self) g_signal_connect(priv->ido_voip_input_slider, "slider-released", G_CALLBACK(voip_input_widget_slider_released), self); GtkWidget* primary_image = ido_scale_menu_item_get_primary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider); - GIcon * primary_gicon = g_themed_icon_new_with_default_fallbacks("audio-volume-low-zero-panel"); + GIcon * primary_gicon = g_themed_icon_new_with_default_fallbacks("audio-input-microphone"); gtk_image_set_from_gicon(GTK_IMAGE(primary_image), primary_gicon, GTK_ICON_SIZE_MENU); g_object_unref(primary_gicon); GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider); - GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks("audio-input-microphone"); + GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks("audio-input-microphone-high"); gtk_image_set_from_gicon(GTK_IMAGE(secondary_image), secondary_gicon, GTK_ICON_SIZE_MENU); g_object_unref(secondary_gicon); -- cgit v1.2.3 From fca4da8d8a9dd24d8abdf2a92cf19a0c6d596e48 Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Fri, 18 Feb 2011 15:38:45 +0000 Subject: fully functional voip feature landed --- src/voip-input-widget.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'src/voip-input-widget.c') diff --git a/src/voip-input-widget.c b/src/voip-input-widget.c index de06c7c..9b29feb 100644 --- a/src/voip-input-widget.c +++ b/src/voip-input-widget.c @@ -76,7 +76,6 @@ voip_input_widget_class_init (VoipInputWidgetClass *klass) static void voip_input_widget_init (VoipInputWidget *self) { - //g_debug("VoipInputWidget::voip_input_widget_init"); VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self); priv->ido_voip_input_slider = ido_scale_menu_item_new_with_range ("VOLUME", IDO_RANGE_STYLE_DEFAULT, 0, 0, 100, 1); @@ -122,8 +121,8 @@ voip_input_widget_finalize (GObject *object) } static void -voip_input_widget_property_update( DbusmenuMenuitem* item, gchar* property, - GVariant* value, gpointer userdata) +voip_input_widget_property_update (DbusmenuMenuitem* item, gchar* property, + GVariant* value, gpointer userdata) { g_return_if_fail (IS_VOIP_INPUT_WIDGET (userdata)); VoipInputWidget* mitem = VOIP_INPUT_WIDGET(userdata); @@ -138,6 +137,24 @@ voip_input_widget_property_update( DbusmenuMenuitem* item, gchar* property, gtk_range_set_value(range, update); } } + if(g_ascii_strcasecmp(DBUSMENU_VOIP_INPUT_MENUITEM_MUTE, property) == 0){ + if(priv->grabbed == FALSE){ + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); + GtkRange *range = (GtkRange*)slider; + gint update = g_variant_get_int32 (value); + gdouble level; + if (update == 1){ + level = 0; + } + else{ + level = g_variant_get_double (dbusmenu_menuitem_property_get_variant (priv->twin_item, + DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL)); + } + gtk_range_set_value(range, level); + + g_debug ("voip-item-widget - update mute with value %i", update); + } + } } static void @@ -155,6 +172,12 @@ voip_input_widget_set_twin_item (VoipInputWidget* self, GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); GtkRange *range = (GtkRange*)slider; gtk_range_set_value(range, initial_level); + + gint mute = g_variant_get_int32 (dbusmenu_menuitem_property_get_variant (priv->twin_item, + DBUSMENU_VOIP_INPUT_MENUITEM_MUTE)); + if (mute == 1){ + gtk_range_set_value (range, 0.0); + } } static gboolean @@ -170,10 +193,12 @@ voip_input_widget_change_value_cb (GtkRange *range, } -/* - We only want this callback to catch mouse icon press events - which set the slider to 0 or 100. Ignore all other events. -*/ +/** + * We only want this callback to catch mouse icon press events which set the + * slider to 0 or 100. Ignore all other events including the new Mute behaviour + * (slider to go to 0 on mute without setting the level to 0 and return to + * previous level on unmute) + **/ static gboolean voip_input_widget_value_changed_cb(GtkRange *range, gpointer user_data) { @@ -183,7 +208,9 @@ voip_input_widget_value_changed_cb(GtkRange *range, gpointer user_data) GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider); gdouble current_value = CLAMP(gtk_range_get_value(GTK_RANGE(slider)), 0, 100); - if(current_value == 0 || current_value == 100){ + gint mute = g_variant_get_int32 (dbusmenu_menuitem_property_get_variant (priv->twin_item, + DBUSMENU_VOIP_INPUT_MENUITEM_MUTE)); + if ((current_value == 0 && mute != 1) || current_value == 100 ){ voip_input_widget_update(mitem, current_value); } return FALSE; -- cgit v1.2.3