[gnome-settings-daemon/gnome-3-32] Fix MPRIS issues with disconnecting clients



commit 5bd33c8155427c09cfb6e4963b79d70972ad95f9
Author: Benjamin Berg <bberg redhat com>
Date:   Mon Dec 10 18:42:38 2018 +0100

    Fix MPRIS issues with disconnecting clients
    
    When clients disconnected and they were not the active client they would
    not be removed from the list. This caused the controller to create a
    proxy for non-existing clients, causing a bad state. The "connecting"
    boolean was also not reset, meaning that a new MPRIS client would never
    be used.
    
    Also, there seems to have been a race caused by the fact that we
    destroyed the DBus proxy from the vanished signal. Change the DBus proxy
    to be removed when its g-name-owner property becomes NULL.
    
    Fixes #45
    
    (cherry picked from commit 162379ed515a7af7601207b664b7003c4ca6fe02)

 plugins/media-keys/mpris-controller.c | 86 +++++++++++++++++++++++++----------
 1 file changed, 61 insertions(+), 25 deletions(-)
---
diff --git a/plugins/media-keys/mpris-controller.c b/plugins/media-keys/mpris-controller.c
index f2baef2d..d5fddef6 100644
--- a/plugins/media-keys/mpris-controller.c
+++ b/plugins/media-keys/mpris-controller.c
@@ -40,6 +40,8 @@ struct _MprisControllerPrivate
 };
 
 
+static void mpris_player_try_connect (MprisController *self);
+
 static void
 mpris_controller_dispose (GObject *object)
 {
@@ -101,6 +103,24 @@ mpris_controller_key (MprisController *self, const gchar *key)
   return TRUE;
 }
 
+static void
+mpris_client_notify_name_owner_cb (GDBusProxy      *proxy,
+                                   GParamSpec      *pspec,
+                                   MprisController *self)
+{
+  g_autofree gchar *name_owner = NULL;
+
+  /* Owner changed, but the proxy is still valid. */
+  name_owner = g_dbus_proxy_get_name_owner (proxy);
+  if (name_owner)
+    return;
+
+  g_clear_object (&self->priv->mpris_client_proxy);
+  g_object_notify (G_OBJECT (self), "has-active-player");
+
+  mpris_player_try_connect (self);
+}
+
 static void
 mpris_proxy_ready_cb (GObject      *object,
                       GAsyncResult *res,
@@ -115,7 +135,13 @@ mpris_proxy_ready_cb (GObject      *object,
   if (!proxy)
     {
       if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-        g_warning ("Error connecting to mpris interface %s", error->message);
+        {
+          g_warning ("Error connecting to mpris interface %s", error->message);
+
+          priv->connecting = FALSE;
+
+          mpris_player_try_connect (MPRIS_CONTROLLER (user_data));
+        }
       g_clear_error (&error);
       return;
     }
@@ -124,6 +150,9 @@ mpris_proxy_ready_cb (GObject      *object,
   priv->mpris_client_proxy = proxy;
   priv->connecting = FALSE;
 
+  g_signal_connect (proxy, "notify::g-name-owner",
+                    G_CALLBACK (mpris_client_notify_name_owner_cb), user_data);
+
   g_object_notify (user_data, "has-active-player");
 }
 
@@ -145,6 +174,29 @@ start_mpris_proxy (MprisController *self, const gchar *name)
   priv->connecting = TRUE;
 }
 
+static void
+mpris_player_try_connect (MprisController *self)
+{
+  MprisControllerPrivate *priv = MPRIS_CONTROLLER (self)->priv;
+  GSList *first;
+  gchar *name;
+
+  if (priv->connecting || priv->mpris_client_proxy)
+    return;
+
+  if (!priv->other_players)
+    return;
+
+  first = priv->other_players;
+  name = first->data;
+
+  start_mpris_proxy (self, name);
+
+  priv->other_players = priv->other_players->next;
+  g_free (name);
+  g_slist_free_1 (first);
+}
+
 static void
 mpris_player_appeared (GDBusConnection *connection,
                        const gchar     *name,
@@ -154,10 +206,8 @@ mpris_player_appeared (GDBusConnection *connection,
   MprisController *self = user_data;
   MprisControllerPrivate *priv = MPRIS_CONTROLLER (self)->priv;
 
-  if (priv->mpris_client_proxy == NULL && !priv->connecting)
-    start_mpris_proxy (self, name);
-  else
-    self->priv->other_players = g_slist_prepend (self->priv->other_players, g_strdup (name));
+  priv->other_players = g_slist_prepend (priv->other_players, g_strdup (name));
+  mpris_player_try_connect (self);
 }
 
 static void
@@ -167,28 +217,14 @@ mpris_player_vanished (GDBusConnection *connection,
 {
   MprisController *self = user_data;
   MprisControllerPrivate *priv = MPRIS_CONTROLLER (self)->priv;
+  GSList *elem;
 
-  if (priv->mpris_client_proxy &&
-      g_strcmp0 (name, g_dbus_proxy_get_name (priv->mpris_client_proxy)) == 0)
+  elem = g_slist_find_custom (priv->other_players, name, (GCompareFunc) g_strcmp0);
+  if (elem)
     {
-      g_clear_object (&priv->mpris_client_proxy);
-      g_object_notify (user_data, "has-active-player");
-
-      /* take the next one if there's one */
-      if (self->priv->other_players && !priv->connecting)
-        {
-          GSList *first;
-          gchar *name;
-
-          first = self->priv->other_players;
-          name = first->data;
-
-          start_mpris_proxy (self, name);
-
-          self->priv->other_players = self->priv->other_players->next;
-          g_free (name);
-          g_slist_free_1 (first);
-        }
+      priv->other_players = g_slist_remove_link (priv->other_players, elem);
+      g_free (elem->data);
+      g_slist_free_1 (elem);
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]