← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~cjcurran/indicator-sound/reconnect-bug into lp:indicator-sound

 

Conor Curran has proposed merging lp:~cjcurran/indicator-sound/reconnect-bug into lp:indicator-sound.

Requested reviews:
  Indicator Applet Developers (indicator-applet-developers)
Related bugs:
  #662296 sound applet volume slider has no effect if pulseaudio is restarted
  https://bugs.launchpad.net/bugs/662296


fixes the bug attached. 
when the daemon dies, the state callback should be notified at which point it should schedule a reconnect request after a 5 second delay. 
once the pulse context has been renewed it should try to connect again. If this does not work then it should wait idle until pulse decides to start again. 
-- 
https://code.launchpad.net/~cjcurran/indicator-sound/reconnect-bug/+merge/39987
Your team ayatana-commits is subscribed to branch lp:indicator-sound.
=== modified file 'src/pulse-manager.c'
--- src/pulse-manager.c	2010-10-05 16:15:34 +0000
+++ src/pulse-manager.c	2010-11-03 16:32:56 +0000
@@ -20,7 +20,6 @@
 with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 #include <pulse/glib-mainloop.h>
 #include <pulse/error.h>
 #include <pulse/gccmacro.h>
@@ -28,14 +27,18 @@
 #include "pulse-manager.h"
 #include "dbus-menu-manager.h"
 
+#define RECONNECT_DELAY 5
+
 static GHashTable *sink_hash = NULL;
 static SoundServiceDbus *dbus_service = NULL;
 static gint DEFAULT_SINK_INDEX = -1;
 static gboolean pa_server_available = FALSE;
-// PA related
+static gint reconnect_idle_id = 0;
 static pa_context *pulse_context = NULL;
 static pa_glib_mainloop *pa_main_loop = NULL;
+
 static void context_state_callback(pa_context *c, void *userdata);
+static gboolean reconnect_to_pulse();
 static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink_info, int eol, void *userdata);
 static void context_success_callback(pa_context *c, int success, void *userdata);
 static void pulse_sink_input_info_callback(pa_context *c, const pa_sink_input_info *info, int eol, void *userdata);
@@ -61,15 +64,19 @@
   dbus_service = service;
   pa_main_loop = pa_glib_mainloop_new(g_main_context_default());
   g_assert(pa_main_loop);
-  pulse_context = pa_context_new(pa_glib_mainloop_get_api(pa_main_loop), "ayatana.indicator.sound");
+  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);
+  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);
-  dbus_menu_manager_update_pa_state(FALSE, FALSE, FALSE, 0);
-  pa_context_connect(pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL);
+  pa_context_set_state_callback (pulse_context, context_state_callback, NULL);
+  dbus_menu_manager_update_pa_state (FALSE, FALSE, FALSE, 0);
+  pa_context_connect (pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL);
 }
 
 /**
@@ -81,6 +88,41 @@
   return pulse_context;
 }
 
+static gboolean
+reconnect_to_pulse()
+{
+  g_debug("Attempt to reconnect to pulse");
+  // reset
+  if (pulse_context != NULL) {
+    pa_context_unref(pulse_context);
+    pulse_context = NULL;
+  }
+
+  if (sink_hash != NULL) {
+   g_hash_table_destroy(sink_hash);
+    sink_hash = NULL;
+  }
+  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);
+  int result = pa_context_connect (pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL);
+
+  if (result < 0) {
+    g_warning ("Failed to connect context: %s",
+               pa_strerror (pa_context_errno (pulse_context)));
+  }
+  // we always want to cancel any continious callbacks with the existing timeout
+  // if the connection failed the new context created above will catch any updates
+  // to do with the state of pulse and thus take care of business.
+  reconnect_idle_id = 0;  
+  return FALSE;
+}
+
 /**
 close_pulse_activites()
 Gracefully close our connection with the Pulse async library.
@@ -294,9 +336,6 @@
 static void pulse_default_sink_info_callback(pa_context *c, const pa_sink_info *info, int eol, void *userdata)
 {
   if (eol > 0) {
-    if (pa_context_errno(c) == PA_ERR_NOENTITY)
-      return;
-    g_warning("Default Sink info callback failure");
     return;
   } else {
     DEFAULT_SINK_INDEX = info->index;
@@ -416,7 +455,9 @@
 }
 
 
-static void pulse_server_info_callback(pa_context *c, const pa_server_info *info, void *userdata)
+static void pulse_server_info_callback(pa_context *c,
+                                       const pa_server_info *info,
+                                       void *userdata)
 {
   /*    g_debug("server info callback");*/
   pa_operation *operation;
@@ -428,7 +469,10 @@
   }
   pa_server_available = TRUE;
   if (info->default_sink_name != NULL) {
-    if (!(operation = pa_context_get_sink_info_by_name(c, info->default_sink_name, pulse_default_sink_info_callback, userdata))) {
+    if (!(operation = pa_context_get_sink_info_by_name(c,
+                                                       info->default_sink_name,
+                                                       pulse_default_sink_info_callback,
+                                                       userdata))) {
       g_warning("pa_context_get_sink_info_by_name() failed");
     } else {
       pa_operation_unref(operation);
@@ -502,16 +546,26 @@
     /*			g_debug("context setting name");*/
     break;
   case PA_CONTEXT_FAILED:
-    g_warning("FAILED to retrieve context - Is PulseAudio Daemon running ?");
+    g_warning("PA_CONTEXT_FAILED - Is PulseAudio Daemon running ?");
     pa_server_available = FALSE;
+    dbus_menu_manager_update_pa_state(TRUE,
+                                      pa_server_available,
+                                      default_sink_is_muted(),
+                                      get_default_sink_volume());
+      
+    if (reconnect_idle_id == 0){
+      reconnect_idle_id = g_timeout_add_seconds (RECONNECT_DELAY,
+                                                 reconnect_to_pulse,
+                                                 NULL);                                                      
+    }     
     break;
   case PA_CONTEXT_TERMINATED:
     /*			g_debug("context terminated");*/
     break;
   case PA_CONTEXT_READY:
-    g_debug("PA daemon is ready");
+    g_debug("PA_CONTEXT_READY");
     pa_operation *o;
-
+            
     pa_context_set_subscribe_callback(c, subscribed_events_callback, userdata);
 
     if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)


Follow ups