From 191f8934b194f2728e175b228f1931f28c1ab8fa Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Thu, 18 Feb 2010 18:05:32 +0000 Subject: key listening update so as the sound menu will digest the appropriate actions --- src/indicator-sound.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/indicator-sound.c b/src/indicator-sound.c index 8e79db6..acacddc 100644 --- a/src/indicator-sound.c +++ b/src/indicator-sound.c @@ -432,8 +432,7 @@ key_press_cb: **/ static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data) { - if (current_state == STATE_MUTED) - return FALSE; + gboolean digested = FALSE; GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider); GtkRange* range = (GtkRange*)slider; @@ -444,6 +443,7 @@ static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer dat switch(event->keyval) { case GDK_Right: + digested = TRUE; if(event->state & GDK_CONTROL_MASK) { new_value = 100; @@ -454,6 +454,7 @@ static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer dat } break; case GDK_Left: + digested = TRUE; if(event->state & GDK_CONTROL_MASK) { new_value = 0; @@ -464,22 +465,24 @@ static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer dat } break; case GDK_plus: - new_value = current_value + five_percent; + digested = TRUE; + new_value = current_value + five_percent; break; case GDK_minus: - new_value = current_value - five_percent; + digested = TRUE; + new_value = current_value - five_percent; break; default: break; } new_value = CLAMP(new_value, 0, 100); - if(new_value != current_value) + if(new_value != current_value && current_state != STATE_MUTED) { g_debug("Attempting to set the range from the key listener to %f", new_value); gtk_range_set_value(range, new_value); } - return FALSE; + return digested; } /** -- cgit v1.2.3 From 11f1982a7b23d55be2306ab6da80879d2f9d8e03 Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Fri, 26 Feb 2010 12:29:16 +0000 Subject: handles pulseaudio flapping without memory leaks - solid --- src/pulse-manager.c | 43 +++++++++++++++++++++++++++++++++------ src/sound-service.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/pulse-manager.c b/src/pulse-manager.c index 9b9d7cd..4436561 100644 --- a/src/pulse-manager.c +++ b/src/pulse-manager.c @@ -31,7 +31,6 @@ with this program. If not, see . static GHashTable *sink_hash = NULL; static SoundServiceDbus *dbus_service = NULL; -// Until we find a satisfactory default sink this index should remain < 0 static gint DEFAULT_SINK_INDEX = -1; static gboolean pa_server_available = FALSE; // PA related @@ -46,6 +45,7 @@ static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, v static void pulse_source_info_callback(pa_context *c, const pa_source_info *i, int eol, void *userdata); static void destroy_sink_info(void *value); static gboolean determine_sink_availability(); +static void reconnect_to_pulse(); /** @@ -65,14 +65,19 @@ void establish_pulse_activities(SoundServiceDbus *service) g_assert(pulse_context); sink_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, destroy_sink_info); + // Establish event callback registration pa_context_set_state_callback(pulse_context, context_state_callback, NULL); - pa_context_connect(pulse_context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); + // BUILD MENU ANYWHO - it will be updated + update_pa_state(FALSE, FALSE, FALSE, 0); + + pa_context_connect(pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL); } void close_pulse_activites() { - if (pulse_context){ + if (pulse_context != NULL){ + g_debug("freeing the pulse context"); pa_context_unref(pulse_context); pulse_context = NULL; } @@ -82,6 +87,30 @@ void close_pulse_activites() g_debug("I just closed communication with Pulse"); } +/** +reconnect_to_pulse() +In the event of Pulseaudio flapping in the wind handle gracefully without +memory leaks ! +*/ +static void reconnect_to_pulse() +{ + // reset + if (pulse_context != NULL){ + g_debug("freeing the pulse context"); + pa_context_unref(pulse_context); + pulse_context = NULL; + } + g_hash_table_destroy(sink_hash); + + // reconnect + pulse_context = pa_context_new(pa_glib_mainloop_get_api(pa_main_loop), "ayatana.indicator.sound"); + g_assert(pulse_context); + sink_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, destroy_sink_info); + // Establish event callback registration + pa_context_set_state_callback(pulse_context, context_state_callback, NULL); + update_pa_state(FALSE, FALSE, FALSE, 0); + pa_context_connect(pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL); +} static void destroy_sink_info(void *value) { @@ -186,6 +215,8 @@ Use the base volume stored in the sink struct to calculate actual linear volumes */ void set_sink_volume(gdouble percent) { + if(pa_server_available == FALSE) + return; g_debug("in the pulse manager:set_sink_volume with percent %f", percent); if(DEFAULT_SINK_INDEX < 0) { @@ -474,7 +505,7 @@ static void context_state_callback(pa_context *c, void *userdata) { g_debug("unconnected"); break; case PA_CONTEXT_CONNECTING: - g_debug("connecting"); + g_debug("connecting - waiting for the server to become available"); break; case PA_CONTEXT_AUTHORIZING: g_debug("authorizing"); @@ -484,8 +515,8 @@ static void context_state_callback(pa_context *c, void *userdata) { break; case PA_CONTEXT_FAILED: g_warning("FAILED to retrieve context - Is PulseAudio Daemon running ?"); - //Update the indicator to show PA either is not ready or has no available sink - update_pa_state(FALSE, FALSE, TRUE, 0); + pa_server_available = FALSE; + reconnect_to_pulse(); break; case PA_CONTEXT_TERMINATED: g_debug("context terminated"); diff --git a/src/sound-service.c b/src/sound-service.c index 62f6bc6..e3153e9 100644 --- a/src/sound-service.c +++ b/src/sound-service.c @@ -37,12 +37,13 @@ static SoundServiceDbus *dbus_interface = NULL; static gboolean b_sink_available = FALSE; static gboolean b_all_muted = FALSE; static gboolean b_pulse_ready = FALSE; +static gboolean b_startup = TRUE; static gdouble volume_percent = 0.0; static void set_global_mute_from_ui(); static gboolean idle_routine (gpointer data); static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service); - +static void refresh_menu(); /**********************************************************************************************************************/ // Init functions (GTK and DBUS) @@ -70,6 +71,7 @@ Build the DBus menu items. For now Mute all/Unmute is the only available option **/ static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service) { + g_debug("rebuilding the sound menu - should i be doing this - it only should happen once !"); // Mute button mute_all_menuitem = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _(b_all_muted == FALSE ? "Mute All" : "Unmute")); @@ -80,10 +82,20 @@ static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service volume_slider_menuitem = slider_menu_item_new(b_sink_available, volume_percent); dbusmenu_menuitem_child_append(root, mute_all_menuitem); dbusmenu_menuitem_child_append(root, DBUSMENU_MENUITEM(volume_slider_menuitem)); - + // Enable/Disable, show/hide slider depending on sink availability + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_ENABLED, + b_sink_available); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_VISIBLE, + b_sink_available); + + // Separator DbusmenuMenuitem *separator = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); dbusmenu_menuitem_child_append(root, separator); + + // Sound preferences dialog DbusmenuMenuitem *settings_mi = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(settings_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Sound Preferences...")); @@ -127,8 +139,8 @@ service_shutdown (IndicatorService *service, gpointer user_data) if (mainloop != NULL) { g_debug("Service shutdown !"); // TODO: uncomment for release !! - close_pulse_activites(); - g_main_loop_quit(mainloop); +/* close_pulse_activites();*/ +/* g_main_loop_quit(mainloop);*/ } return; } @@ -140,12 +152,44 @@ void update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_m b_pulse_ready = pa_state; volume_percent = percent; g_debug("update pa state with state %i, availability of %i, mute value of %i and a volume percent is %f", pa_state, sink_available, sink_muted, volume_percent); + // Only rebuild the menu on start up... + if(b_startup == TRUE){ + rebuild_sound_menu(root_menuitem, dbus_interface); + b_startup = FALSE; + } + else{ + refresh_menu(); + } + // Emit the signals after the menus are setup/torn down sound_service_dbus_update_sink_volume(dbus_interface, percent); sound_service_dbus_update_sink_mute(dbus_interface, sink_muted); - // Only rebuild the menu on start up... - if(volume_slider_menuitem == NULL) - rebuild_sound_menu(root_menuitem, dbus_interface); +} + +static void refresh_menu() +{ + if(b_sink_available == FALSE || b_pulse_ready == FALSE) + { + + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_ENABLED, + FALSE); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_VISIBLE, + FALSE); + dbusmenu_menuitem_property_set_bool(mute_all_menuitem, + DBUSMENU_MENUITEM_PROP_ENABLED, + FALSE); + + } + else if(b_sink_available == TRUE && b_pulse_ready == TRUE){ + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_VISIBLE, + TRUE); + dbusmenu_menuitem_property_set_bool(mute_all_menuitem, + DBUSMENU_MENUITEM_PROP_ENABLED, + TRUE); + } } -- cgit v1.2.3 From 8ab71867cb6d028ade4e72ee6efeb563fba07c9a Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Fri, 26 Feb 2010 14:40:28 +0000 Subject: new sink inserts are now cached in our hash --- src/pulse-manager.c | 20 ++++++++++++++------ src/sound-service.c | 17 ++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/pulse-manager.c b/src/pulse-manager.c index 4436561..d5377bf 100644 --- a/src/pulse-manager.c +++ b/src/pulse-manager.c @@ -397,12 +397,20 @@ static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, v } else { - // TODO ADD new sink - part of big refactor - g_debug("attempting to add new sink with name %s", info->name); - //sink_info *s; - //s = g_new0(sink_info, 1); - //update the sinks hash with new sink. - } + sink_info *value; + value = g_new0(sink_info, 1); + value->index = value->device_index = info->index; + value->name = g_strdup(info->name); + value->description = g_strdup(info->description); + value->icon_name = g_strdup(pa_proplist_gets(info->proplist, PA_PROP_DEVICE_ICON_NAME)); + value->active_port = (info->active_port != NULL); + value->mute = !!info->mute; + value->volume = info->volume; + value->base_volume = info->base_volume; + value->channel_map = info->channel_map; + g_hash_table_insert(sink_hash, GINT_TO_POINTER(value->index), value); + g_debug("pulse-manager:update_sink_info -> After adding a new sink to our hash"); + } } diff --git a/src/sound-service.c b/src/sound-service.c index e3153e9..af1f1e9 100644 --- a/src/sound-service.c +++ b/src/sound-service.c @@ -67,11 +67,11 @@ static void show_sound_settings_dialog (DbusmenuMenuitem *mi, gpointer user_data } } /** -Build the DBus menu items. For now Mute all/Unmute is the only available option +rebuild_sound_menu: +Build the DBus menu items, mute/unmute, slider, separator and sound preferences 'link' **/ static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service) { - g_debug("rebuilding the sound menu - should i be doing this - it only should happen once !"); // Mute button mute_all_menuitem = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _(b_all_muted == FALSE ? "Mute All" : "Unmute")); @@ -82,14 +82,12 @@ static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service volume_slider_menuitem = slider_menu_item_new(b_sink_available, volume_percent); dbusmenu_menuitem_child_append(root, mute_all_menuitem); dbusmenu_menuitem_child_append(root, DBUSMENU_MENUITEM(volume_slider_menuitem)); - // Enable/Disable, show/hide slider depending on sink availability dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), DBUSMENU_MENUITEM_PROP_ENABLED, - b_sink_available); + b_sink_available); dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), - DBUSMENU_MENUITEM_PROP_VISIBLE, - b_sink_available); - + DBUSMENU_MENUITEM_PROP_VISIBLE, + b_sink_available); // Separator DbusmenuMenuitem *separator = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); @@ -168,6 +166,7 @@ void update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_m static void refresh_menu() { + g_debug("in the refresh menu method"); if(b_sink_available == FALSE || b_pulse_ready == FALSE) { @@ -183,6 +182,10 @@ static void refresh_menu() } else if(b_sink_available == TRUE && b_pulse_ready == TRUE){ + + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_ENABLED, + TRUE); dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); -- cgit v1.2.3 From 87478982de012b8322090f40a747ab42f7dd838c Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Wed, 3 Mar 2010 16:46:30 +0000 Subject: Test menuitem name. --- src/indicator-sound.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/indicator-sound.c b/src/indicator-sound.c index acacddc..49c02fa 100644 --- a/src/indicator-sound.c +++ b/src/indicator-sound.c @@ -439,6 +439,10 @@ static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer dat gdouble current_value = gtk_range_get_value(range); gdouble new_value = current_value; const gdouble five_percent = 5; + GtkWidget *menuitem; + + menuitem = gtk_menu_get_active (GTK_MENU (widget)); + g_print (g_type_name (menuitem)); switch(event->keyval) { -- cgit v1.2.3 From eb3df565591fb7474aa5290db83ca601a7edd1ee Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Wed, 3 Mar 2010 17:23:08 +0000 Subject: fixes the key listener problems --- src/indicator-sound.c | 86 ++++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/indicator-sound.c b/src/indicator-sound.c index 49c02fa..63d48aa 100644 --- a/src/indicator-sound.c +++ b/src/indicator-sound.c @@ -441,51 +441,53 @@ static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer dat const gdouble five_percent = 5; GtkWidget *menuitem; - menuitem = gtk_menu_get_active (GTK_MENU (widget)); - g_print (g_type_name (menuitem)); - - switch(event->keyval) - { - case GDK_Right: - digested = TRUE; - if(event->state & GDK_CONTROL_MASK) - { - new_value = 100; - } - else - { - new_value = current_value + five_percent; - } - break; - case GDK_Left: - digested = TRUE; - if(event->state & GDK_CONTROL_MASK) - { - new_value = 0; - } - else + menuitem = GTK_MENU_SHELL (widget)->active_menu_item; +/* g_print ("object (%p) name should be %s", menuitem, G_OBJECT_TYPE_NAME(menuitem));*/ + if(IDO_IS_SCALE_MENU_ITEM(menuitem) == TRUE) + { + switch(event->keyval) { + case GDK_Right: + digested = TRUE; + if(event->state & GDK_CONTROL_MASK) + { + new_value = 100; + } + else + { + new_value = current_value + five_percent; + } + break; + case GDK_Left: + digested = TRUE; + if(event->state & GDK_CONTROL_MASK) + { + new_value = 0; + } + else + { + new_value = current_value - five_percent; + } + break; + case GDK_plus: + digested = TRUE; + new_value = current_value + five_percent; + break; + case GDK_minus: + digested = TRUE; new_value = current_value - five_percent; + break; + default: + break; + } + + new_value = CLAMP(new_value, 0, 100); + if(new_value != current_value && current_state != STATE_MUTED) + { + g_debug("Attempting to set the range from the key listener to %f", new_value); + gtk_range_set_value(range, new_value); } - break; - case GDK_plus: - digested = TRUE; - new_value = current_value + five_percent; - break; - case GDK_minus: - digested = TRUE; - new_value = current_value - five_percent; - break; - default: - break; - } - - new_value = CLAMP(new_value, 0, 100); - if(new_value != current_value && current_state != STATE_MUTED) - { - g_debug("Attempting to set the range from the key listener to %f", new_value); - gtk_range_set_value(range, new_value); - } + } return digested; } -- cgit v1.2.3 From 55fe3e5a44992862735b4ef2208300dbfccacebb Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Wed, 3 Mar 2010 17:33:28 +0000 Subject: removed trace and made sure the service closes down probably --- src/indicator-sound.c | 1 - src/sound-service.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/indicator-sound.c b/src/indicator-sound.c index 63d48aa..1301916 100644 --- a/src/indicator-sound.c +++ b/src/indicator-sound.c @@ -442,7 +442,6 @@ static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer dat GtkWidget *menuitem; menuitem = GTK_MENU_SHELL (widget)->active_menu_item; -/* g_print ("object (%p) name should be %s", menuitem, G_OBJECT_TYPE_NAME(menuitem));*/ if(IDO_IS_SCALE_MENU_ITEM(menuitem) == TRUE) { switch(event->keyval) diff --git a/src/sound-service.c b/src/sound-service.c index af1f1e9..91b5af3 100644 --- a/src/sound-service.c +++ b/src/sound-service.c @@ -137,8 +137,8 @@ service_shutdown (IndicatorService *service, gpointer user_data) if (mainloop != NULL) { g_debug("Service shutdown !"); // TODO: uncomment for release !! -/* close_pulse_activites();*/ -/* g_main_loop_quit(mainloop);*/ + close_pulse_activites(); + g_main_loop_quit(mainloop); } return; } -- cgit v1.2.3