directsoundsink: allow specifying audio playback device
authorDustin Spicuzza <dustin@virtualroadside.com>
Sun, 16 Aug 2015 19:21:51 +0000 (15:21 -0400)
committerSebastian Dröge <sebastian@centricular.com>
Mon, 17 Aug 2015 11:57:56 +0000 (13:57 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=753670

configure.ac
sys/directsound/gstdirectsoundsink.c
sys/directsound/gstdirectsoundsink.h

index b16d99c..97e3e75 100644 (file)
@@ -388,7 +388,7 @@ AG_GST_CHECK_FEATURE(DIRECTSOUND, [DirectSound plug-in], directsoundsink, [
   save_LIBS="$LIBS"
   CFLAGS="$CFLAGS $DIRECTSOUND_CFLAGS"
   LDFLAGS="$LDFLAGS $DIRECTSOUND_LDFLAGS"
-  LIBS="$LIBS -ldsound -ldxerr9 -luser32"
+  LIBS="$LIBS -ldsound -ldxerr9 -luser32 -lole32"
   AC_MSG_CHECKING(for DirectSound LDFLAGS)
   AC_LINK_IFELSE([AC_LANG_PROGRAM([[
 #include <windows.h>
@@ -397,6 +397,7 @@ AG_GST_CHECK_FEATURE(DIRECTSOUND, [DirectSound plug-in], directsoundsink, [
 ]], [[
   DXGetErrorString9 (0);
   DirectSoundCreate(NULL, NULL, NULL);
+  CLSIDFromString(NULL, NULL);
 ]])
 ],
     [HAVE_DIRECTSOUND="yes"],
@@ -408,7 +409,7 @@ AG_GST_CHECK_FEATURE(DIRECTSOUND, [DirectSound plug-in], directsoundsink, [
 
   if test "x$HAVE_DIRECTSOUND" = "xyes";  then
     dnl this is much more than we want
-    DIRECTSOUND_LIBS="-ldsound -ldxerr9 -luser32"
+    DIRECTSOUND_LIBS="-ldsound -ldxerr9 -luser32 -lole32"
     AC_SUBST(DIRECTSOUND_CFLAGS)
     AC_SUBST(DIRECTSOUND_LDFLAGS)
     AC_SUBST(DIRECTSOUND_LIBS)
index bee96d1..39cb092 100644 (file)
@@ -101,6 +101,10 @@ static gdouble gst_directsound_sink_get_volume (GstDirectSoundSink * sink);
 static void gst_directsound_sink_set_mute (GstDirectSoundSink * sink,
     gboolean mute);
 static gboolean gst_directsound_sink_get_mute (GstDirectSoundSink * sink);
+static const gchar *gst_directsound_sink_get_device (GstDirectSoundSink *
+    dsoundsink);
+static void gst_directsound_sink_set_device (GstDirectSoundSink * dsoundsink,
+    const gchar * device_id);
 
 static gboolean gst_directsound_sink_is_spdif_format (GstAudioRingBufferSpec *
     spec);
@@ -124,7 +128,8 @@ enum
 {
   PROP_0,
   PROP_VOLUME,
-  PROP_MUTE
+  PROP_MUTE,
+  PROP_DEVICE
 };
 
 #define gst_directsound_sink_parent_class parent_class
@@ -137,6 +142,9 @@ gst_directsound_sink_finalize (GObject * object)
 {
   GstDirectSoundSink *dsoundsink = GST_DIRECTSOUND_SINK (object);
 
+  g_free (dsoundsink->device_id);
+  dsoundsink->device_id = NULL;
+
   g_mutex_clear (&dsoundsink->dsound_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -189,6 +197,12 @@ gst_directsound_sink_class_init (GstDirectSoundSinkClass * klass)
           "Mute state of this stream", DEFAULT_MUTE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class,
+      PROP_DEVICE,
+      g_param_spec_string ("device", "Device",
+          "DirectSound playback device as a GUID string",
+          NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gst_element_class_set_static_metadata (element_class,
       "Direct Sound Audio Sink", "Sink/Audio",
       "Output to a sound card via Direct Sound",
@@ -203,6 +217,7 @@ gst_directsound_sink_init (GstDirectSoundSink * dsoundsink)
 {
   dsoundsink->volume = 100;
   dsoundsink->mute = FALSE;
+  dsoundsink->device_id = NULL;
   dsoundsink->pDS = NULL;
   dsoundsink->cached_caps = NULL;
   dsoundsink->pDSBSecondary = NULL;
@@ -226,6 +241,9 @@ gst_directsound_sink_set_property (GObject * object,
     case PROP_MUTE:
       gst_directsound_sink_set_mute (sink, g_value_get_boolean (value));
       break;
+    case PROP_DEVICE:
+      gst_directsound_sink_set_device (sink, g_value_get_string (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -245,6 +263,9 @@ gst_directsound_sink_get_property (GObject * object,
     case PROP_MUTE:
       g_value_set_boolean (value, gst_directsound_sink_get_mute (sink));
       break;
+    case PROP_DEVICE:
+      g_value_set_string (value, gst_directsound_sink_get_device (sink));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -378,22 +399,51 @@ gst_directsound_sink_query (GstBaseSink * sink, GstQuery * query)
   return res;
 }
 
+static LPGUID
+string_to_guid (const gchar * str)
+{
+  HRESULT ret;
+  gunichar2 *wstr;
+  LPGUID out;
+
+  wstr = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL);
+  if (!wstr)
+    return NULL;
+
+  out = g_new (GUID, 1);
+  ret = CLSIDFromString ((LPOLESTR) wstr, out);
+  g_free (wstr);
+  if (ret != NOERROR) {
+    g_free (out);
+    return NULL;
+  }
+
+  return out;
+}
+
 static gboolean
 gst_directsound_sink_open (GstAudioSink * asink)
 {
   GstDirectSoundSink *dsoundsink;
   HRESULT hRes;
+  LPGUID lpGuid = NULL;
 
   dsoundsink = GST_DIRECTSOUND_SINK (asink);
 
+  if (dsoundsink->device_id)
+    lpGuid = string_to_guid (dsoundsink->device_id);
+
   /* create and initialize a DirecSound object */
-  if (FAILED (hRes = DirectSoundCreate (NULL, &dsoundsink->pDS, NULL))) {
+  if (FAILED (hRes = DirectSoundCreate (lpGuid, &dsoundsink->pDS, NULL))) {
     GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ,
         ("gst_directsound_sink_open: DirectSoundCreate: %s",
             DXGetErrorString9 (hRes)), (NULL));
+    g_free (lpGuid);
     return FALSE;
   }
 
+  g_free (lpGuid);
+
   if (FAILED (hRes = IDirectSound_SetCooperativeLevel (dsoundsink->pDS,
               GetDesktopWindow (), DSSCL_PRIORITY))) {
     GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ,
@@ -874,3 +924,17 @@ gst_directsound_sink_get_mute (GstDirectSoundSink * dsoundsink)
 {
   return FALSE;
 }
+
+static const gchar *
+gst_directsound_sink_get_device (GstDirectSoundSink * dsoundsink)
+{
+  return dsoundsink->device_id;
+}
+
+static void
+gst_directsound_sink_set_device (GstDirectSoundSink * dsoundsink,
+    const gchar * device_id)
+{
+  g_free (dsoundsink->device_id);
+  dsoundsink->device_id = g_strdup (device_id);
+}
index 3a83181..c9f5879 100644 (file)
@@ -74,6 +74,9 @@ struct _GstDirectSoundSink
   /* current volume setup by mixer interface */
   glong volume;
   gboolean mute;
+  
+  /* current directsound device ID */
+  gchar * device_id;
 
   GstCaps *cached_caps;
   /* lock used to protect writes and resets */