From 5c680333ba676d86dfd66ca4e12e87868bef67f6 Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Sun, 16 Aug 2015 15:21:51 -0400 Subject: [PATCH] directsoundsink: allow specifying audio playback device https://bugzilla.gnome.org/show_bug.cgi?id=753670 --- configure.ac | 5 +-- sys/directsound/gstdirectsoundsink.c | 68 ++++++++++++++++++++++++++++++++++-- sys/directsound/gstdirectsoundsink.h | 3 ++ 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index b16d99c..97e3e75 100644 --- a/configure.ac +++ b/configure.ac @@ -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 @@ -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) diff --git a/sys/directsound/gstdirectsoundsink.c b/sys/directsound/gstdirectsoundsink.c index bee96d1..39cb092 100644 --- a/sys/directsound/gstdirectsoundsink.c +++ b/sys/directsound/gstdirectsoundsink.c @@ -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); +} diff --git a/sys/directsound/gstdirectsoundsink.h b/sys/directsound/gstdirectsoundsink.h index 3a83181..c9f5879 100644 --- a/sys/directsound/gstdirectsoundsink.h +++ b/sys/directsound/gstdirectsoundsink.h @@ -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 */ -- 2.7.4