[gnome-settings-daemon] media-keys: Use new gvc and g-s APIs for audio device selection



commit 332836c15337b10d2385ef987a9b400b6ba39a0a
Author: Rui Matos <tiagomatos gmail com>
Date:   Fri Feb 12 18:09:24 2016 +0100

    media-keys: Use new gvc and g-s APIs for audio device selection
    
    When plugging in a headset, or a microphone in some computers, they
    will not be able to detect that there is a new input available (for
    the headset), or that it doesn't have any outputs (for the
    microphone).
    
    Using gvc's new audio-device-selection-needed signal we call into
    gnome-shell to ask the user with a modal dialog what kind of device
    was plugged in and switch the ports according to the user's response.
    
    This adds a dependency on ALSA.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=755062

 configure.ac                                |   22 ++++-
 plugins/media-keys/gsd-media-keys-manager.c |  161 +++++++++++++++++++++++++++
 plugins/media-keys/gvc                      |    2 +-
 3 files changed, 183 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index cbeacdb..11c7f8c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -144,6 +144,26 @@ fi
 AM_CONDITIONAL(HAVE_GUDEV, test x$have_gudev = xyes)
 
 dnl ---------------------------------------------------------------------------
+dnl - ALSA integration (default enabled)
+dnl ---------------------------------------------------------------------------
+ALSA_PKG=""
+AC_ARG_ENABLE(alsa, AS_HELP_STRING([--disable-alsa],[Disable ALSA support (not optional on Linux 
platforms)]), enable_alsa=$enableval)
+if test x$enable_alsa != xno; then
+       PKG_CHECK_MODULES(ALSA, alsa, have_alsa="yes", have_alsa="no")
+       if test "x$have_alsa" = "xyes"; then
+               AC_DEFINE(HAVE_ALSA, 1, [define if ALSA is available])
+               ALSA_PKG="alsa"
+       else
+               if test x$enable_alsa = xyes; then
+                       AC_MSG_ERROR([ALSA enabled but not found])
+               fi
+       fi
+else
+       have_alsa=no
+fi
+AM_CONDITIONAL(HAVE_ALSA, test x$have_alsa = xyes)
+
+dnl ---------------------------------------------------------------------------
 dnl - Check for libwayland-client
 dnl ---------------------------------------------------------------------------
 AC_ARG_ENABLE(wayland,
@@ -197,7 +217,7 @@ dnl - media-keys plugin stuff
 dnl ---------------------------------------------------------------------------
 
 PKG_CHECK_MODULES(MEDIA_KEYS, [gio-unix-2.0 libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG 
libpulse-mainloop-glib >= $PA_REQUIRED_VERSION libcanberra-gtk3 upower-glib >= $UPOWER_REQUIRED_VERSION])
-PKG_CHECK_MODULES(GVC, [gobject-2.0 libpulse >= $PA_REQUIRED_VERSION libpulse-mainloop-glib >= 
$PA_REQUIRED_VERSION])
+PKG_CHECK_MODULES(GVC, [gobject-2.0 libpulse >= $PA_REQUIRED_VERSION libpulse-mainloop-glib >= 
$PA_REQUIRED_VERSION $ALSA_PKG])
 AM_CONDITIONAL(HAVE_INTROSPECTION, false)
 
 dnl ---------------------------------------------------------------------------
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index cc80c5d..076244b 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -112,6 +112,10 @@ static const gchar introspection_xml[] =
 #define SYSTEMD_DBUS_PATH                       "/org/freedesktop/login1"
 #define SYSTEMD_DBUS_INTERFACE                  "org.freedesktop.login1.Manager"
 
+#define AUDIO_SELECTION_DBUS_NAME               "org.gnome.Shell.AudioDeviceSelection"
+#define AUDIO_SELECTION_DBUS_PATH               "/org/gnome/Shell/AudioDeviceSelection"
+#define AUDIO_SELECTION_DBUS_INTERFACE          "org.gnome.Shell.AudioDeviceSelection"
+
 #define GSD_MEDIA_KEYS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), 
GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManagerPrivate))
 
 typedef struct {
@@ -148,6 +152,11 @@ struct GsdMediaKeysManagerPrivate
         GHashTable      *streams; /* key = X device ID, value = stream id */
         GUdevClient     *udev_client;
 #endif /* HAVE_GUDEV */
+        guint            audio_selection_watch_id;
+        guint            audio_selection_signal_id;
+        GDBusConnection *audio_selection_conn;
+        gboolean         audio_selection_requested;
+        guint            audio_selection_device_id;
 
         GSettings       *settings;
         GHashTable      *custom_settings;
@@ -2443,6 +2452,140 @@ update_theme_settings (GSettings           *settings,
        }
 }
 
+typedef struct {
+        GvcHeadsetPortChoice choice;
+        gchar *name;
+} AudioSelectionChoice;
+
+static AudioSelectionChoice audio_selection_choices[] = {
+        { GVC_HEADSET_PORT_CHOICE_HEADPHONES,   "headphones" },
+        { GVC_HEADSET_PORT_CHOICE_HEADSET,      "headset" },
+        { GVC_HEADSET_PORT_CHOICE_MIC,          "microphone" },
+};
+
+static void
+audio_selection_done (GDBusConnection *connection,
+                      const gchar     *sender_name,
+                      const gchar     *object_path,
+                      const gchar     *interface_name,
+                      const gchar     *signal_name,
+                      GVariant        *parameters,
+                      gpointer         data)
+{
+        GsdMediaKeysManagerPrivate *priv = GSD_MEDIA_KEYS_MANAGER (data)->priv;
+        const gchar *choice;
+        guint i;
+
+        if (!priv->audio_selection_requested)
+                return;
+
+        choice = NULL;
+        g_variant_get_child (parameters, 0, "&s", &choice);
+        if (!choice)
+                return;
+
+        for (i = 0; i < G_N_ELEMENTS (audio_selection_choices); ++i) {
+                if (g_str_equal (choice, audio_selection_choices[i].name)) {
+                        gvc_mixer_control_set_headset_port (priv->volume,
+                                                            priv->audio_selection_device_id,
+                                                            audio_selection_choices[i].choice);
+                        break;
+                }
+        }
+
+        priv->audio_selection_requested = FALSE;
+}
+
+static void
+audio_selection_needed (GvcMixerControl      *control,
+                        guint                 id,
+                        gboolean              show_dialog,
+                        GvcHeadsetPortChoice  choices,
+                        GsdMediaKeysManager  *manager)
+{
+        GsdMediaKeysManagerPrivate *priv = manager->priv;
+        gchar *args[G_N_ELEMENTS (audio_selection_choices) + 1];
+        guint i, n;
+
+        if (!priv->audio_selection_conn)
+                return;
+
+        if (priv->audio_selection_requested) {
+                g_dbus_connection_call (priv->audio_selection_conn,
+                                        AUDIO_SELECTION_DBUS_NAME,
+                                        AUDIO_SELECTION_DBUS_PATH,
+                                        AUDIO_SELECTION_DBUS_INTERFACE,
+                                        "Close", NULL, NULL,
+                                        G_DBUS_CALL_FLAGS_NONE,
+                                        -1, NULL, NULL, NULL);
+                priv->audio_selection_requested = FALSE;
+        }
+
+        if (!show_dialog)
+                return;
+
+        n = 0;
+        for (i = 0; i < G_N_ELEMENTS (audio_selection_choices); ++i) {
+                if (choices & audio_selection_choices[i].choice)
+                        args[n++] = audio_selection_choices[i].name;
+        }
+        args[n] = NULL;
+
+        priv->audio_selection_requested = TRUE;
+        priv->audio_selection_device_id = id;
+        g_dbus_connection_call (priv->audio_selection_conn,
+                                AUDIO_SELECTION_DBUS_NAME,
+                                AUDIO_SELECTION_DBUS_PATH,
+                                AUDIO_SELECTION_DBUS_INTERFACE,
+                                "Open",
+                                g_variant_new ("(^as)", args),
+                                NULL,
+                                G_DBUS_CALL_FLAGS_NONE,
+                                -1, NULL, NULL, NULL);
+}
+
+static void
+audio_selection_appeared (GDBusConnection *connection,
+                          const gchar     *name,
+                          const gchar     *name_owner,
+                          gpointer         data)
+{
+        GsdMediaKeysManager *manager = data;
+        manager->priv->audio_selection_conn = connection;
+        manager->priv->audio_selection_signal_id =
+                g_dbus_connection_signal_subscribe (connection,
+                                                    AUDIO_SELECTION_DBUS_NAME,
+                                                    AUDIO_SELECTION_DBUS_INTERFACE,
+                                                    "DeviceSelected",
+                                                    AUDIO_SELECTION_DBUS_PATH,
+                                                    NULL,
+                                                    G_DBUS_SIGNAL_FLAGS_NONE,
+                                                    audio_selection_done,
+                                                    manager,
+                                                    NULL);
+}
+
+static void
+clear_audio_selection (GsdMediaKeysManager *manager)
+{
+        GsdMediaKeysManagerPrivate *priv = manager->priv;
+
+        if (priv->audio_selection_signal_id)
+                g_dbus_connection_signal_unsubscribe (priv->audio_selection_conn,
+                                                      priv->audio_selection_signal_id);
+        priv->audio_selection_signal_id = 0;
+        priv->audio_selection_conn = NULL;
+}
+
+static void
+audio_selection_vanished (GDBusConnection *connection,
+                          const gchar     *name,
+                          gpointer         data)
+{
+        if (connection)
+                clear_audio_selection (data);
+}
+
 static void
 initialize_volume_handler (GsdMediaKeysManager *manager)
 {
@@ -2472,9 +2615,22 @@ initialize_volume_handler (GsdMediaKeysManager *manager)
                           "stream-removed",
                           G_CALLBACK (on_control_stream_removed),
                           manager);
+        g_signal_connect (manager->priv->volume,
+                          "audio-device-selection-needed",
+                          G_CALLBACK (audio_selection_needed),
+                          manager);
 
         gvc_mixer_control_open (manager->priv->volume);
 
+        manager->priv->audio_selection_watch_id =
+                g_bus_watch_name (G_BUS_TYPE_SESSION,
+                                  AUDIO_SELECTION_DBUS_NAME,
+                                  G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                  audio_selection_appeared,
+                                  audio_selection_vanished,
+                                  manager,
+                                  NULL);
+
         gnome_settings_profile_end ("gvc_mixer_control_new");
 }
 
@@ -2759,6 +2915,11 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager)
         }
 
         g_clear_object (&priv->shell_proxy);
+
+        if (priv->audio_selection_watch_id)
+                g_bus_unwatch_name (priv->audio_selection_watch_id);
+        priv->audio_selection_watch_id = 0;
+        clear_audio_selection (manager);
 }
 
 static void
diff --git a/plugins/media-keys/gvc b/plugins/media-keys/gvc
index 03894ef..3af2560 160000
--- a/plugins/media-keys/gvc
+++ b/plugins/media-keys/gvc
@@ -1 +1 @@
-Subproject commit 03894efbcd010faf53bbc6e27256d27485f721b8
+Subproject commit 3af25601db68387e7818f87c2c3144ea4431c14a


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