[gnome-settings-daemon] media-keys: Use new gvc and g-s APIs for audio device selection
- From: Rui Matos <rtcm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon] media-keys: Use new gvc and g-s APIs for audio device selection
- Date: Tue, 16 Feb 2016 16:39:21 +0000 (UTC)
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]