[gnome-flashback] implement audio device selection dialog



commit 46ca3b5173265f0e2d70b60221f4d22280a39188
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Wed Mar 30 22:39:34 2016 +0300

    implement audio device selection dialog

 configure.ac                                       |    4 +-
 data/schemas/org.gnome.gnome-flashback.gschema.xml |    2 +-
 gnome-flashback/Makefile.am                        |    4 +-
 gnome-flashback/gf-application.c                   |    8 +-
 .../libaudio-device-selection/Makefile.am          |   57 ++++
 .../gf-audio-device-selection-dialog.c             |  315 ++++++++++++++++++++
 .../gf-audio-device-selection-dialog.h}            |   33 +--
 .../gf-audio-device-selection.c                    |  234 +++++++++++++++
 .../gf-audio-device-selection.h}                   |   12 +-
 .../org.gnome.Shell.AudioDeviceSelection.xml       |   19 ++
 gnome-flashback/libaudio-selection/Makefile.am     |   31 --
 po/POTFILES.in                                     |    1 +
 12 files changed, 654 insertions(+), 66 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 51170ec..52bf3e1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -120,7 +120,7 @@ PKG_CHECK_MODULES([GNOME_FLASHBACK], [
   gtk+-3.0 >= $GTK_REQUIRED
 ])
 
-PKG_CHECK_MODULES([AUDIO_SELECTION], [
+PKG_CHECK_MODULES([AUDIO_DEVICE_SELECTION], [
   gtk+-3.0 >= $GTK_REQUIRED
   glib-2.0 >= $GLIB_REQUIRED
 ])
@@ -285,7 +285,7 @@ AC_CONFIG_FILES([
   data/xsessions/Makefile
 
   gnome-flashback/Makefile
-  gnome-flashback/libaudio-selection/Makefile
+  gnome-flashback/libaudio-device-selection/Makefile
   gnome-flashback/libautomount-manager/Makefile
   gnome-flashback/libbluetooth-applet/Makefile
   gnome-flashback/libcommon/Makefile
diff --git a/data/schemas/org.gnome.gnome-flashback.gschema.xml 
b/data/schemas/org.gnome.gnome-flashback.gschema.xml
index 899d2be..3598757 100644
--- a/data/schemas/org.gnome.gnome-flashback.gschema.xml
+++ b/data/schemas/org.gnome.gnome-flashback.gschema.xml
@@ -1,7 +1,7 @@
 <schemalist gettext-domain="gnome-flashback">
   <schema id="org.gnome.gnome-flashback" path="/org/gnome/gnome-flashback/">
 
-    <key name="audio-selection" type="b">
+    <key name="audio-device-selection" type="b">
       <default>true</default>
       <summary>Audio device selection</summary>
       <description>If set to true, then GNOME Flashback application will be used to provide the audio device 
selection dialog.</description>
diff --git a/gnome-flashback/Makefile.am b/gnome-flashback/Makefile.am
index fdd632c..4b783d9 100644
--- a/gnome-flashback/Makefile.am
+++ b/gnome-flashback/Makefile.am
@@ -1,7 +1,7 @@
 NULL =
 
 SUBDIRS = \
-       libaudio-selection \
+       libaudio-device-selection \
        libautomount-manager \
        libbluetooth-applet \
        libcommon \
@@ -53,7 +53,7 @@ gnome_flashback_LDFLAGS = \
 
 gnome_flashback_LDADD = \
        $(GNOME_FLASHBACK_LIBS) \
-       $(top_builddir)/gnome-flashback/libaudio-selection/libaudio-selection.la \
+       $(top_builddir)/gnome-flashback/libaudio-device-selection/libaudio-device-selection.la \
        $(top_builddir)/gnome-flashback/libautomount-manager/libautomount-manager.la \
        $(top_builddir)/gnome-flashback/libbluetooth-applet/libbluetooth-applet.la \
        $(top_builddir)/gnome-flashback/libdesktop-background/libdesktop-background.la \
diff --git a/gnome-flashback/gf-application.c b/gnome-flashback/gf-application.c
index f204e6c..6ba338e 100644
--- a/gnome-flashback/gf-application.c
+++ b/gnome-flashback/gf-application.c
@@ -21,7 +21,7 @@
 #include <gtk/gtk.h>
 
 #include "gf-application.h"
-#include "libaudio-selection/gf-audio-selection.h"
+#include "libaudio-device-selection/gf-audio-device-selection.h"
 #include "libautomount-manager/gsd-automount-manager.h"
 #include "libbluetooth-applet/gf-bluetooth-applet.h"
 #include "libdesktop-background/gf-desktop-background.h"
@@ -58,7 +58,7 @@ struct _GfApplication
   FlashbackIdleMonitor   *idle_monitor;
   FlashbackPolkit        *polkit;
   FlashbackShell         *shell;
-  GfAudioSelection       *audio_selection;
+  GfAudioDeviceSelection *audio_device_selection;
   GfBluetoothApplet      *bluetooth;
   GfDesktopBackground    *background;
   GfEndSessionDialog     *dialog;
@@ -156,7 +156,7 @@ settings_changed (GSettings   *settings,
   SETTING_CHANGED (idle_monitor, "idle-monitor", flashback_idle_monitor_new)
   SETTING_CHANGED (polkit, "polkit", flashback_polkit_new)
   SETTING_CHANGED (shell, "shell", flashback_shell_new)
-  SETTING_CHANGED (audio_selection, "audio-selection", gf_audio_selection_new)
+  SETTING_CHANGED (audio_device_selection, "audio-device-selection", gf_audio_device_selection_new)
   SETTING_CHANGED (bluetooth, "bluetooth-applet", gf_bluetooth_applet_new)
   SETTING_CHANGED (background, "desktop-background", gf_desktop_background_new)
   SETTING_CHANGED (dialog, "end-session-dialog", gf_end_session_dialog_new)
@@ -201,7 +201,7 @@ gf_application_dispose (GObject *object)
   g_clear_object (&application->idle_monitor);
   g_clear_object (&application->polkit);
   g_clear_object (&application->shell);
-  g_clear_object (&application->audio_selection);
+  g_clear_object (&application->audio_device_selection);
   g_clear_object (&application->bluetooth);
   g_clear_object (&application->background);
   g_clear_object (&application->dialog);
diff --git a/gnome-flashback/libaudio-device-selection/Makefile.am 
b/gnome-flashback/libaudio-device-selection/Makefile.am
new file mode 100644
index 0000000..2d33db5
--- /dev/null
+++ b/gnome-flashback/libaudio-device-selection/Makefile.am
@@ -0,0 +1,57 @@
+NULL =
+
+noinst_LTLIBRARIES = \
+       libaudio-device-selection.la \
+       $(NULL)
+
+libaudio_device_selection_la_CPPFLAGS = \
+       -I$(top_builddir)/gnome-flashback/libaudio-device-selection \
+       $(NULL)
+
+libaudio_device_selection_la_CFLAGS = \
+       $(AUDIO_DEVICE_SELECTION_CFLAGS) \
+       $(WARN_CFLAGS) \
+       $(AM_CFLAGS) \
+       $(NULL)
+
+libaudio_device_selection_la_SOURCES = \
+       gf-audio-device-selection.c \
+       gf-audio-device-selection.h \
+       gf-audio-device-selection-dialog.c \
+       gf-audio-device-selection-dialog.h \
+       $(BUILT_SOURCES) \
+       $(NULL)
+
+libaudio_device_selection_la_LDFLAGS = \
+       $(WARN_LDFLAGS) \
+       $(AM_LDFLAGS) \
+       $(NULL)
+
+libaudio_device_selection_la_LIBADD = \
+       $(AUDIO_DEVICE_SELECTION_LIBS) \
+       $(NULL)
+
+gf-audio-device-selection-gen.h:
+gf-audio-device-selection-gen.c: org.gnome.Shell.AudioDeviceSelection.xml
+       $(AM_V_GEN) $(GDBUS_CODEGEN) \
+               --interface-prefix org.gnome.Shell.AudioDeviceSelection. \
+               --generate-c-code gf-audio-device-selection-gen \
+               --c-namespace Gf \
+               --annotate "org.gnome.Shell.AudioDeviceSelection" \
+                          "org.gtk.GDBus.C.Name" AudioDeviceSelectionGen \
+               $(srcdir)/org.gnome.Shell.AudioDeviceSelection.xml
+
+BUILT_SOURCES = \
+       gf-audio-device-selection-gen.c \
+       gf-audio-device-selection-gen.h \
+       $(NULL)
+
+EXTRA_DIST = \
+       org.gnome.Shell.AudioDeviceSelection.xml \
+       $(NULL)
+
+CLEANFILES = \
+       $(BUILT_SOURCES) \
+       $(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/gnome-flashback/libaudio-device-selection/gf-audio-device-selection-dialog.c 
b/gnome-flashback/libaudio-device-selection/gf-audio-device-selection-dialog.c
new file mode 100644
index 0000000..99d9aa7
--- /dev/null
+++ b/gnome-flashback/libaudio-device-selection/gf-audio-device-selection-dialog.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "gf-audio-device-selection-dialog.h"
+
+typedef enum
+{
+  GF_AUDIO_DEVICE_HEADPHONES = 1 << 0,
+  GF_AUDIO_DEVICE_HEADSET    = 1 << 1,
+  GF_AUDIO_DEVICE_MICROPHONE = 1 << 2
+} GfAudioDevice;
+
+struct _GfAudioDeviceSelectionDialog
+{
+  GtkWindow  parent;
+
+  gchar     *sender;
+
+  GtkWidget *selection_box;
+};
+
+enum
+{
+  CLOSE,
+  SELECTED,
+
+  LAST_SIGNAL
+};
+
+static guint dialog_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GfAudioDeviceSelectionDialog, gf_audio_device_selection_dialog, GTK_TYPE_WINDOW)
+
+static const gchar *
+get_device_from_enum (GfAudioDevice device)
+{
+  switch (device)
+    {
+      case GF_AUDIO_DEVICE_HEADPHONES:
+        return "headphones";
+
+      case GF_AUDIO_DEVICE_HEADSET:
+        return "headset";
+
+      case GF_AUDIO_DEVICE_MICROPHONE:
+        return "microphone";
+
+      default:
+        return NULL;
+    }
+}
+
+static void
+clicked_cb (GtkButton                    *button,
+            GfAudioDeviceSelectionDialog *dialog)
+{
+  gpointer tmp;
+  const gchar *audio_device;
+
+  tmp = g_object_get_data (G_OBJECT (button), "device");
+  audio_device = get_device_from_enum (GPOINTER_TO_INT (tmp));
+
+  g_signal_emit (dialog, dialog_signals[SELECTED], 0, audio_device);
+}
+
+static const gchar *
+get_device_icon (GfAudioDevice device)
+{
+  switch (device)
+    {
+      case GF_AUDIO_DEVICE_HEADPHONES:
+        return "audio-headphones";
+
+      case GF_AUDIO_DEVICE_HEADSET:
+        return "audio-headset";
+
+      case GF_AUDIO_DEVICE_MICROPHONE:
+        return "audio-input-microphone";
+
+      default:
+        return NULL;
+    }
+}
+
+static const gchar *
+get_device_label (GfAudioDevice device)
+{
+  switch (device)
+    {
+      case GF_AUDIO_DEVICE_HEADPHONES:
+        return _("Headphones");
+
+      case GF_AUDIO_DEVICE_HEADSET:
+        return _("Headset");
+
+      case GF_AUDIO_DEVICE_MICROPHONE:
+        return _("Microphone");
+
+      default:
+        return NULL;
+    }
+}
+
+static void
+add_device (GfAudioDeviceSelectionDialog *dialog,
+            GfAudioDevice                 device)
+{
+  const gchar *icon;
+  const gchar *label;
+  GtkWidget *button;
+  GtkWidget *image;
+
+  icon = get_device_icon (device);
+  label = get_device_label (device);
+
+  button = gtk_button_new_with_label (label);
+  gtk_box_pack_start (GTK_BOX (dialog->selection_box), button, TRUE, TRUE, 0);
+  gtk_widget_show (button);
+
+  g_object_set_data (G_OBJECT (button), "device", GINT_TO_POINTER (device));
+
+  image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_DIALOG);
+  gtk_widget_show (image);
+
+  gtk_button_set_always_show_image (GTK_BUTTON (button), TRUE);
+  gtk_button_set_image_position (GTK_BUTTON (button), GTK_POS_TOP);
+  gtk_button_set_image (GTK_BUTTON (button), image);
+
+  g_signal_connect (button, "clicked", G_CALLBACK (clicked_cb), dialog);
+}
+
+static void
+settings_clicked_cb (GtkButton                    *button,
+                     GfAudioDeviceSelectionDialog *dialog)
+{
+  GdkDisplay *display;
+  GdkAppLaunchContext *context;
+  GAppInfoCreateFlags flags;
+  GError *error;
+  GAppInfo *app_info;
+
+  display = gdk_display_get_default ();
+  context = gdk_display_get_app_launch_context (display);
+
+  flags = G_APP_INFO_CREATE_NONE;
+  error = NULL;
+
+  app_info = g_app_info_create_from_commandline ("gnome-control-center sound",
+                                                 "Sound preferences", flags,
+                                                 &error);
+
+  if (app_info)
+    {
+      g_signal_emit (dialog, dialog_signals[CLOSE], 0);
+      g_app_info_launch (app_info, NULL, G_APP_LAUNCH_CONTEXT (context), &error);
+    }
+
+  if (error != NULL)
+    {
+      g_warning (_("Failed to start Sound Preferences: %s"), error->message);
+      g_error_free (error);
+    }
+
+  g_clear_object (&app_info);
+  g_object_unref (context);
+}
+
+static void
+cancel_clicked_cb (GtkButton                    *button,
+                   GfAudioDeviceSelectionDialog *dialog)
+{
+  g_signal_emit (dialog, dialog_signals[CLOSE], 0);
+}
+
+static void
+gf_audio_device_selection_dialog_finalize (GObject *object)
+{
+  GfAudioDeviceSelectionDialog *dialog;
+
+  dialog = GF_AUDIO_DEVICE_SELECTION_DIALOG (object);
+
+  g_free (dialog->sender);
+
+  G_OBJECT_CLASS (gf_audio_device_selection_dialog_parent_class)->finalize (object);
+}
+
+static void
+gf_audio_device_selection_dialog_class_init (GfAudioDeviceSelectionDialogClass *dialog_class)
+{
+  GObjectClass *object_class;
+  GtkBindingSet *binding_set;
+
+  object_class = G_OBJECT_CLASS (dialog_class);
+
+  object_class->finalize = gf_audio_device_selection_dialog_finalize;
+
+  dialog_signals[CLOSE] =
+    g_signal_new ("close", G_OBJECT_CLASS_TYPE (dialog_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
+  dialog_signals[SELECTED] =
+    g_signal_new ("selected", G_OBJECT_CLASS_TYPE (dialog_class),
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 1, G_TYPE_STRING);
+
+  binding_set = gtk_binding_set_by_class (dialog_class);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
+}
+
+static void
+gf_audio_device_selection_dialog_init (GfAudioDeviceSelectionDialog *dialog)
+{
+  GtkWidget *vbox1;
+  GtkWidget *vbox2;
+  GtkWidget *label;
+  GtkWidget *button_box;
+  GtkWidget *button;
+
+  gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
+
+  vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  gtk_container_add (GTK_CONTAINER (dialog), vbox1);
+  gtk_widget_show (vbox1);
+
+  vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, FALSE, 6);
+  gtk_widget_show (vbox2);
+
+  label = gtk_label_new (_("What kind of device did you plug in?"));
+  gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+
+  dialog->selection_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_box_pack_start (GTK_BOX (vbox2), dialog->selection_box, TRUE, TRUE, 0);
+  gtk_widget_show (dialog->selection_box);
+
+  gtk_box_set_homogeneous (GTK_BOX (dialog->selection_box), TRUE);
+
+  button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
+  gtk_box_pack_start (GTK_BOX (vbox1), button_box, FALSE, FALSE, 0);
+  gtk_widget_show (button_box);
+
+  button = gtk_button_new_with_label (_("Sound Settings"));
+  gtk_box_pack_start (GTK_BOX (button_box), button, TRUE, TRUE, 0);
+  gtk_widget_show (button);
+
+  g_signal_connect (button, "clicked",
+                    G_CALLBACK (settings_clicked_cb), dialog);
+
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_box_pack_start (GTK_BOX (button_box), button, TRUE, TRUE, 0);
+  gtk_widget_show (button);
+
+  g_signal_connect (button, "clicked",
+                    G_CALLBACK (cancel_clicked_cb), dialog);
+}
+
+GtkWidget *
+gf_audio_device_selection_dialog_new (const gchar        *sender,
+                                      const gchar *const *devices)
+{
+  GfAudioDeviceSelectionDialog *dialog;
+  gint i;
+
+  dialog = g_object_new (GF_TYPE_AUDIO_DEVICE_SELECTION_DIALOG,
+                         "title", _("Unknown Audio Device"),
+                         "window-position", GTK_WIN_POS_CENTER,
+                         "resizable", FALSE,
+                         NULL);
+
+  dialog->sender = g_strdup (sender);
+
+  for (i = 0; devices[i] != NULL; i++)
+    {
+      GfAudioDevice device;
+
+      if (g_strcmp0 (devices[i], "headphones") == 0)
+        device = GF_AUDIO_DEVICE_HEADPHONES;
+      else if (g_strcmp0 (devices[i], "headset") == 0)
+        device = GF_AUDIO_DEVICE_HEADSET;
+      else if (g_strcmp0 (devices[i], "microphone") == 0)
+        device = GF_AUDIO_DEVICE_MICROPHONE;
+      else
+        g_assert_not_reached ();
+
+      add_device (dialog, device);
+    }
+
+  return GTK_WIDGET (dialog);
+}
+
+const gchar *
+gf_audio_device_selection_dialog_get_sender (GfAudioDeviceSelectionDialog *dialog)
+{
+  return dialog->sender;
+}
diff --git a/gnome-flashback/libaudio-selection/gf-audio-selection.c 
b/gnome-flashback/libaudio-device-selection/gf-audio-device-selection-dialog.h
similarity index 50%
rename from gnome-flashback/libaudio-selection/gf-audio-selection.c
rename to gnome-flashback/libaudio-device-selection/gf-audio-device-selection-dialog.h
index e02ad76..ca82526 100644
--- a/gnome-flashback/libaudio-selection/gf-audio-selection.c
+++ b/gnome-flashback/libaudio-device-selection/gf-audio-device-selection-dialog.h
@@ -15,29 +15,22 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "config.h"
+#ifndef GF_AUDIO_DEVICE_SELECTION_DIALOG_H
+#define GF_AUDIO_DEVICE_SELECTION_DIALOG_H
 
-#include "gf-audio-selection.h"
+#include <gtk/gtk.h>
 
-struct _GfAudioSelection
-{
-  GObject parent;
-};
+G_BEGIN_DECLS
 
-G_DEFINE_TYPE (GfAudioSelection, gf_audio_selection, G_TYPE_OBJECT)
+#define GF_TYPE_AUDIO_DEVICE_SELECTION_DIALOG gf_audio_device_selection_dialog_get_type ()
+G_DECLARE_FINAL_TYPE (GfAudioDeviceSelectionDialog, gf_audio_device_selection_dialog,
+                      GF, AUDIO_DEVICE_SELECTION_DIALOG, GtkWindow)
 
-static void
-gf_audio_selection_class_init (GfAudioSelectionClass *audio_selection_class)
-{
-}
+GtkWidget   *gf_audio_device_selection_dialog_new        (const gchar                  *sender,
+                                                          const gchar *const           *devices);
 
-static void
-gf_audio_selection_init (GfAudioSelection *audio_selection)
-{
-}
+const gchar *gf_audio_device_selection_dialog_get_sender (GfAudioDeviceSelectionDialog *dialog);
 
-GfAudioSelection *
-gf_audio_selection_new (void)
-{
-  return g_object_new (GF_TYPE_AUDIO_SELECTION, NULL);
-}
+G_END_DECLS
+
+#endif
diff --git a/gnome-flashback/libaudio-device-selection/gf-audio-device-selection.c 
b/gnome-flashback/libaudio-device-selection/gf-audio-device-selection.c
new file mode 100644
index 0000000..00fcb6f
--- /dev/null
+++ b/gnome-flashback/libaudio-device-selection/gf-audio-device-selection.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gf-audio-device-selection.h"
+#include "gf-audio-device-selection-dialog.h"
+#include "gf-audio-device-selection-gen.h"
+
+#define AUDIO_DEVICE_SELECTION_DBUS_NAME "org.gnome.Shell.AudioDeviceSelection"
+#define AUDIO_DEVICE_SELECTION_DBUS_PATH "/org/gnome/Shell/AudioDeviceSelection"
+
+struct _GfAudioDeviceSelection
+{
+  GObject                    parent;
+
+  GfAudioDeviceSelectionGen *selection;
+  gint                       bus_name_id;
+
+  GtkWidget                 *dialog;
+};
+
+G_DEFINE_TYPE (GfAudioDeviceSelection, gf_audio_device_selection, G_TYPE_OBJECT)
+
+static void
+close_cb (GfAudioDeviceSelectionDialog *dialog,
+          GfAudioDeviceSelection       *ads)
+{
+  gtk_widget_destroy (ads->dialog);
+  ads->dialog = NULL;
+}
+
+static void
+selected_cb (GfAudioDeviceSelectionDialog *dialog,
+             const gchar                  *device,
+             GfAudioDeviceSelection       *ads)
+{
+  gf_audio_device_selection_gen_emit_device_selected (ads->selection, device);
+  close_cb (dialog, ads);
+}
+
+static gboolean
+delete_event_cb (GtkWidget              *widget,
+                 GdkEvent               *event,
+                 GfAudioDeviceSelection *ads)
+{
+  ads->dialog = NULL;
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+handle_close_cb (GfAudioDeviceSelectionGen *object,
+                 GDBusMethodInvocation     *invocation,
+                 GfAudioDeviceSelection    *ads)
+{
+  if (ads->dialog)
+    {
+      GfAudioDeviceSelectionDialog *dialog;
+      const gchar *invocation_sender;
+      const gchar *dialog_sender;
+
+      dialog = GF_AUDIO_DEVICE_SELECTION_DIALOG (ads->dialog);
+
+      invocation_sender = g_dbus_method_invocation_get_sender (invocation);
+      dialog_sender = gf_audio_device_selection_dialog_get_sender (dialog);
+
+      if (g_strcmp0 (invocation_sender, dialog_sender) == 0)
+        {
+          gtk_widget_destroy (ads->dialog);
+          ads->dialog = NULL;
+        }
+    }
+
+  gf_audio_device_selection_gen_complete_close (object, invocation);
+
+  return TRUE;
+}
+
+static gboolean
+handle_open_cb (GfAudioDeviceSelectionGen *object,
+                GDBusMethodInvocation     *invocation,
+                const gchar *const        *devices,
+                GfAudioDeviceSelection    *ads)
+{
+  const gchar *sender;
+
+  if (ads->dialog)
+    {
+      gf_audio_device_selection_gen_complete_open (object, invocation);
+
+      return TRUE;
+    }
+
+  sender = g_dbus_method_invocation_get_sender (invocation);
+  ads->dialog = gf_audio_device_selection_dialog_new (sender, devices);
+
+  g_signal_connect (ads->dialog, "close", G_CALLBACK (close_cb), ads);
+  g_signal_connect (ads->dialog, "selected", G_CALLBACK (selected_cb), ads);
+
+  g_signal_connect (ads->dialog, "delete-event",
+                    G_CALLBACK (delete_event_cb), ads);
+
+  gtk_window_present (GTK_WINDOW (ads->dialog));
+
+  gf_audio_device_selection_gen_complete_open (object, invocation);
+
+  return TRUE;
+}
+
+static void
+bus_acquired_handler (GDBusConnection *connection,
+                      const gchar     *name,
+                      gpointer         user_data)
+{
+  GfAudioDeviceSelection *ads;
+  GDBusInterfaceSkeleton *skeleton;
+  GError *error;
+  gboolean exported;
+
+  ads = GF_AUDIO_DEVICE_SELECTION (user_data);
+  skeleton = G_DBUS_INTERFACE_SKELETON (ads->selection);
+
+  g_signal_connect (ads->selection, "handle-close",
+                    G_CALLBACK (handle_close_cb), ads);
+  g_signal_connect (ads->selection, "handle-open",
+                    G_CALLBACK (handle_open_cb), ads);
+
+  error = NULL;
+  exported = g_dbus_interface_skeleton_export (skeleton, connection,
+                                               AUDIO_DEVICE_SELECTION_DBUS_PATH,
+                                               &error);
+
+  if (!exported)
+    {
+      g_warning ("Failed to export interface: %s", error->message);
+      g_error_free (error);
+
+      return;
+    }
+}
+
+static void
+test (GfAudioDeviceSelection *ads)
+{
+  const gchar *devices[] = { "headphones", "headset", "microphone", NULL };
+  ads->dialog = gf_audio_device_selection_dialog_new (NULL, devices);
+
+  g_signal_connect (ads->dialog, "close", G_CALLBACK (close_cb), ads);
+  g_signal_connect (ads->dialog, "selected", G_CALLBACK (selected_cb), ads);
+
+  g_signal_connect (ads->dialog, "delete-event",
+                    G_CALLBACK (delete_event_cb), ads);
+
+  gtk_window_present (GTK_WINDOW (ads->dialog));
+}
+
+static void
+gf_audio_device_selection_dispose (GObject *object)
+{
+  GfAudioDeviceSelection *ads;
+  GDBusInterfaceSkeleton *skeleton;
+
+  ads = GF_AUDIO_DEVICE_SELECTION (object);
+
+  if (ads->bus_name_id)
+    {
+      g_bus_unown_name (ads->bus_name_id);
+      ads->bus_name_id = 0;
+    }
+
+  if (ads->selection)
+    {
+      skeleton = G_DBUS_INTERFACE_SKELETON (ads->selection);
+
+      g_dbus_interface_skeleton_unexport (skeleton);
+      g_clear_object (&ads->selection);
+    }
+
+  if (ads->dialog)
+    {
+      gtk_widget_destroy (ads->dialog);
+      ads->dialog = NULL;
+    }
+
+  G_OBJECT_CLASS (gf_audio_device_selection_parent_class)->dispose (object);
+}
+
+static void
+gf_audio_device_selection_class_init (GfAudioDeviceSelectionClass *ads_class)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (ads_class);
+
+  object_class->dispose = gf_audio_device_selection_dispose;
+}
+
+static void
+gf_audio_device_selection_init (GfAudioDeviceSelection *ads)
+{
+  GBusNameOwnerFlags flags;
+
+  flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT;
+  flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE;
+
+  ads->selection = gf_audio_device_selection_gen_skeleton_new ();
+  ads->bus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+                                     AUDIO_DEVICE_SELECTION_DBUS_NAME,
+                                     flags, bus_acquired_handler,
+                                     NULL, NULL, ads, NULL);
+
+  test (ads);
+}
+
+GfAudioDeviceSelection *
+gf_audio_device_selection_new (void)
+{
+  return g_object_new (GF_TYPE_AUDIO_DEVICE_SELECTION, NULL);
+}
diff --git a/gnome-flashback/libaudio-selection/gf-audio-selection.h 
b/gnome-flashback/libaudio-device-selection/gf-audio-device-selection.h
similarity index 68%
rename from gnome-flashback/libaudio-selection/gf-audio-selection.h
rename to gnome-flashback/libaudio-device-selection/gf-audio-device-selection.h
index 8a55cfe..d90b53b 100644
--- a/gnome-flashback/libaudio-selection/gf-audio-selection.h
+++ b/gnome-flashback/libaudio-device-selection/gf-audio-device-selection.h
@@ -15,18 +15,18 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef GF_AUDIO_SELECTION_H
-#define GF_AUDIO_SELECTION_H
+#ifndef GF_AUDIO_DEVICE_SELECTION_H
+#define GF_AUDIO_DEVICE_SELECTION_H
 
 #include <glib-object.h>
 
 G_BEGIN_DECLS
 
-#define GF_TYPE_AUDIO_SELECTION gf_audio_selection_get_type ()
-G_DECLARE_FINAL_TYPE (GfAudioSelection, gf_audio_selection,
-                      GF, AUDIO_SELECTION, GObject)
+#define GF_TYPE_AUDIO_DEVICE_SELECTION gf_audio_device_selection_get_type ()
+G_DECLARE_FINAL_TYPE (GfAudioDeviceSelection, gf_audio_device_selection,
+                      GF, AUDIO_DEVICE_SELECTION, GObject)
 
-GfAudioSelection *gf_audio_selection_new (void);
+GfAudioDeviceSelection *gf_audio_device_selection_new (void);
 
 G_END_DECLS
 
diff --git a/gnome-flashback/libaudio-device-selection/org.gnome.Shell.AudioDeviceSelection.xml 
b/gnome-flashback/libaudio-device-selection/org.gnome.Shell.AudioDeviceSelection.xml
new file mode 100644
index 0000000..19f4c56
--- /dev/null
+++ b/gnome-flashback/libaudio-device-selection/org.gnome.Shell.AudioDeviceSelection.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+<node>
+  <interface name="org.gnome.Shell.AudioDeviceSelection">
+
+    <method name="Close">
+    </method>
+
+    <method name="Open">
+      <arg name="devices" direction="in" type="as" />
+    </method>
+
+    <signal name="DeviceSelected">
+      <arg name="device" type="s" />
+    </signal>
+
+  </interface>
+</node>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 692387b..c76d5ff 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -10,6 +10,7 @@ data/schemas/org.gnome.gnome-flashback.gschema.xml
 data/xsessions/gnome-flashback-compiz.desktop.in.in
 data/xsessions/gnome-flashback-metacity.desktop.in.in
 gnome-flashback/gf-main.c
+gnome-flashback/libaudio-device-selection/gf-audio-device-selection-dialog.c
 gnome-flashback/libautomount-manager/gsd-automount-manager.c
 gnome-flashback/libautomount-manager/gsd-autorun.c
 gnome-flashback/libbluetooth-applet/gf-bluetooth-applet.c


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