diff --git a/sys/directsound/Makefile.am b/sys/directsound/Makefile.am index 044344a4fa..c76edf05e7 100644 --- a/sys/directsound/Makefile.am +++ b/sys/directsound/Makefile.am @@ -1,11 +1,16 @@ plugin_LTLIBRARIES = libgstdirectsoundsrc.la -libgstdirectsoundsrc_la_SOURCES = gstdirectsoundsrc.c gstdirectsoundplugin.c +libgstdirectsoundsrc_la_SOURCES = gstdirectsoundsrc.c gstdirectsounddevice.c gstdirectsoundplugin.c libgstdirectsoundsrc_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \ - $(GST_PLUGINS_BASE_CFLAGS) $(DIRECTX_CFLAGS) + $(GST_PLUGINS_BASE_CFLAGS) $(DIRECTX_CFLAGS) \ + -DGstDirectSoundDeviceProvider=GstDirectSoundSrcDeviceProvider \ + -DGstDirectSoundDeviceProviderClass=GstDirectSoundSrcDeviceProviderClass \ + -DGstDirectSoundDevice=GstDirectSoundSrcDevice \ + -DGstDirectSoundDeviceClass=GstDirectSoundSrcDeviceClass \ + -DGST_DIRECTSOUND_SRC_DEVICE_PROVIDER=1 libgstdirectsoundsrc_la_LIBADD = \ $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_API_VERSION) \ $(DIRECTX_LDFLAGS) $(DIRECTSOUND_LIBS) -lole32 libgstdirectsoundsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -noinst_HEADERS= gstdirectsoundsrc.h +noinst_HEADERS= gstdirectsoundsrc.h gstdirectsounddevice.h diff --git a/sys/directsound/gstdirectsounddevice.c b/sys/directsound/gstdirectsounddevice.c new file mode 100644 index 0000000000..00b021ebb1 --- /dev/null +++ b/sys/directsound/gstdirectsounddevice.c @@ -0,0 +1,266 @@ +/* GStreamer + * Copyright (C) 2018 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstdirectsounddevice.h" + +#include +#include +#include +#include + +#ifdef GST_DIRECTSOUND_SRC_DEVICE_PROVIDER +#include "gstdirectsoundsrc.h" +#else +#include "gstdirectsoundsink.h" +#endif + +G_DEFINE_TYPE (GstDirectSoundDeviceProvider, gst_directsound_device_provider, + GST_TYPE_DEVICE_PROVIDER); + +static GList *gst_directsound_device_provider_probe (GstDeviceProvider * + provider); + +static void +gst_directsound_device_provider_class_init (GstDirectSoundDeviceProviderClass * + klass) +{ + GstDeviceProviderClass *dm_class = GST_DEVICE_PROVIDER_CLASS (klass); + + gst_device_provider_class_set_static_metadata (dm_class, +#ifdef GST_DIRECTSOUND_SRC_DEVICE_PROVIDER + "DirectSound Source Device Provider", "Source/Audio", + "List DirectSound source devices", +#else + "DirectSound Sink Device Provider", "Sink/Audio", + "List DirectSound sink devices", +#endif + "Sebastian Dröge "); + + dm_class->probe = gst_directsound_device_provider_probe; +} + +static void +gst_directsound_device_provider_init (GstDirectSoundDeviceProvider * provider) +{ +} + +static gchar * +guid_to_string (LPGUID guid) +{ + gunichar2 *wstr = NULL; + gchar *str = NULL; + + if (StringFromCLSID (guid, &wstr) == S_OK) { + str = g_utf16_to_utf8 (wstr, -1, NULL, NULL, NULL); + CoTaskMemFree (wstr); + } + + return str; +} + +typedef struct +{ + GstDirectSoundDeviceProvider *self; + GList **devices; +} ProbeData; + +static BOOL CALLBACK +gst_directsound_enum_callback (GUID * pGUID, TCHAR * strDesc, + TCHAR * strDrvName, VOID * pContext) +{ + ProbeData *probe_data = (ProbeData *) (pContext); + gchar *driver, *description, *guid_str; + GstStructure *props; + GstDevice *device; +#ifdef GST_DIRECTSOUND_SRC_DEVICE_PROVIDER + static GstStaticCaps caps = GST_STATIC_CAPS (GST_DIRECTSOUND_SRC_CAPS); +#else + static GstStaticCaps caps = GST_STATIC_CAPS (GST_DIRECTSOUND_SINK_CAPS); +#endif + + description = g_locale_to_utf8 (strDesc, -1, NULL, NULL, NULL); + if (!description) { + GST_ERROR_OBJECT (probe_data->self, + "Failed to convert description from locale encoding to UTF8"); + return TRUE; + } + + driver = g_locale_to_utf8 (strDrvName, -1, NULL, NULL, NULL); + if (!driver) { + GST_ERROR_OBJECT (probe_data->self, + "Failed to convert driver name from locale encoding to UTF8"); + return TRUE; + } + + /* NULL for the primary sound card */ + guid_str = pGUID ? guid_to_string (pGUID) : NULL; + + GST_INFO_OBJECT (probe_data->self, "sound device name: %s, %s (GUID %s)", + description, driver, GST_STR_NULL (guid_str)); + + props = gst_structure_new ("directsound-proplist", + "device.api", G_TYPE_STRING, "directsound", + "device.guid", G_TYPE_STRING, GST_STR_NULL (guid_str), + "directsound.device.driver", G_TYPE_STRING, driver, + "directsound.device.description", G_TYPE_STRING, description, NULL); + +#ifdef GST_DIRECTSOUND_SRC_DEVICE_PROVIDER + device = g_object_new (GST_TYPE_DIRECTSOUND_DEVICE, "device-guid", guid_str, + "display-name", description, "caps", gst_static_caps_get (&caps), + "device-class", "Audio/Source", "properties", props, NULL); +#else + device = g_object_new (GST_TYPE_DIRECTSOUND_DEVICE, "device-guid", guid_str, + "display-name", description, "caps", gst_static_caps_get (&caps), + "device-class", "Audio/Sink", "properties", props, NULL); +#endif + + *probe_data->devices = g_list_prepend (*probe_data->devices, device); + + g_free (description); + g_free (driver); + g_free (guid_str); + + gst_structure_free (props); + + return TRUE; +} + +static GList * +gst_directsound_device_provider_probe (GstDeviceProvider * provider) +{ + GstDirectSoundDeviceProvider *self = + GST_DIRECTSOUND_DEVICE_PROVIDER (provider); + GList *devices = NULL; + ProbeData probe_data = { self, &devices }; + HRESULT hRes; + +#ifdef GST_DIRECTSOUND_SRC_DEVICE_PROVIDER + hRes = DirectSoundCaptureEnumerate ((LPDSENUMCALLBACK) + gst_directsound_enum_callback, (VOID *) & probe_data); +#else + hRes = DirectSoundEnumerate ((LPDSENUMCALLBACK) + gst_directsound_enum_callback, (VOID *) & probe_data); +#endif + + if (FAILED (hRes)) + GST_ERROR_OBJECT (self, "Failed to enumerate devices"); + + return devices; +} + +enum +{ + PROP_DEVICE_GUID = 1, +}; + +G_DEFINE_TYPE (GstDirectSoundDevice, gst_directsound_device, GST_TYPE_DEVICE); + +static void gst_directsound_device_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_directsound_device_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_directsound_device_finalize (GObject * object); +static GstElement *gst_directsound_device_create_element (GstDevice * device, + const gchar * name); + +static void +gst_directsound_device_class_init (GstDirectSoundDeviceClass * klass) +{ + GstDeviceClass *dev_class = GST_DEVICE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + dev_class->create_element = gst_directsound_device_create_element; + + object_class->get_property = gst_directsound_device_get_property; + object_class->set_property = gst_directsound_device_set_property; + object_class->finalize = gst_directsound_device_finalize; + + g_object_class_install_property (object_class, PROP_DEVICE_GUID, + g_param_spec_string ("device-guid", "Device GUID", + "Device GUID", NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +gst_directsound_device_init (GstDirectSoundDevice * device) +{ +} + +static void +gst_directsound_device_finalize (GObject * object) +{ + GstDirectSoundDevice *device = GST_DIRECTSOUND_DEVICE (object); + + g_free (device->guid); + + G_OBJECT_CLASS (gst_directsound_device_parent_class)->finalize (object); +} + +static GstElement * +gst_directsound_device_create_element (GstDevice * device, const gchar * name) +{ + GstDirectSoundDevice *directsound_dev = GST_DIRECTSOUND_DEVICE (device); + GstElement *elem; + +#ifdef GST_DIRECTSOUND_SRC_DEVICE_PROVIDER + elem = gst_element_factory_make ("directsoundsrc", name); +#else + elem = gst_element_factory_make ("directsoundsink", name); +#endif + + g_object_set (elem, "device", directsound_dev->guid, NULL); + + return elem; +} + +static void +gst_directsound_device_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDirectSoundDevice *device = GST_DIRECTSOUND_DEVICE_CAST (object); + + switch (prop_id) { + case PROP_DEVICE_GUID: + g_value_set_string (value, device->guid); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_directsound_device_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDirectSoundDevice *device = GST_DIRECTSOUND_DEVICE_CAST (object); + + switch (prop_id) { + case PROP_DEVICE_GUID: + device->guid = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/sys/directsound/gstdirectsounddevice.h b/sys/directsound/gstdirectsounddevice.h new file mode 100644 index 0000000000..550289337a --- /dev/null +++ b/sys/directsound/gstdirectsounddevice.h @@ -0,0 +1,74 @@ +/* GStreamer + * Copyright (C) 2018 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_DIRECTSOUND_DEVICE_H__ +#define __GST_DIRECTSOUND_DEVICE_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GstDirectSoundDeviceProvider GstDirectSoundDeviceProvider; +typedef struct _GstDirectSoundDeviceProviderClass GstDirectSoundDeviceProviderClass; + +#define GST_TYPE_DIRECTSOUND_DEVICE_PROVIDER (gst_directsound_device_provider_get_type()) +#define GST_IS_DIRECTSOUND_DEVICE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DIRECTSOUND_DEVICE_PROVIDER)) +#define GST_IS_DIRECTSOUND_DEVICE_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DIRECTSOUND_DEVICE_PROVIDER)) +#define GST_DIRECTSOUND_DEVICE_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DIRECTSOUND_DEVICE_PROVIDER, GstDirectSoundDeviceProviderClass)) +#define GST_DIRECTSOUND_DEVICE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DIRECTSOUND_DEVICE_PROVIDER, GstDirectSoundDeviceProvider)) +#define GST_DIRECTSOUND_DEVICE_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE_PROVIDER, GstDirectSoundDeviceProviderClass)) +#define GST_DIRECTSOUND_DEVICE_PROVIDER_CAST(obj) ((GstDirectSoundDeviceProvider *)(obj)) + +struct _GstDirectSoundDeviceProvider { + GstDeviceProvider parent; +}; + +struct _GstDirectSoundDeviceProviderClass { + GstDeviceProviderClass parent_class; +}; + +GType gst_directsound_device_provider_get_type (void); + + +typedef struct _GstDirectSoundDevice GstDirectSoundDevice; +typedef struct _GstDirectSoundDeviceClass GstDirectSoundDeviceClass; + +#define GST_TYPE_DIRECTSOUND_DEVICE (gst_directsound_device_get_type()) +#define GST_IS_DIRECTSOUND_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DIRECTSOUND_DEVICE)) +#define GST_IS_DIRECTSOUND_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DIRECTSOUND_DEVICE)) +#define GST_DIRECTSOUND_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DIRECTSOUND_DEVICE, GstDirectSoundDeviceClass)) +#define GST_DIRECTSOUND_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DIRECTSOUND_DEVICE, GstDirectSoundDevice)) +#define GST_DIRECTSOUND_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE, GstDirectSoundDeviceClass)) +#define GST_DIRECTSOUND_DEVICE_CAST(obj) ((GstDirectSoundDevice *)(obj)) + +struct _GstDirectSoundDevice { + GstDevice parent; + + gchar *guid; +}; + +struct _GstDirectSoundDeviceClass { + GstDeviceClass parent_class; +}; + +GType gst_directsound_device_get_type (void); + +G_END_DECLS + +#endif /* __GST_DIRECTSOUND_DEVICE_H__ */ diff --git a/sys/directsound/gstdirectsoundplugin.c b/sys/directsound/gstdirectsoundplugin.c index ed4f9d75b9..66d6c40cd8 100644 --- a/sys/directsound/gstdirectsoundplugin.c +++ b/sys/directsound/gstdirectsoundplugin.c @@ -30,7 +30,7 @@ #endif #include "gstdirectsoundsrc.h" - +#include "gstdirectsounddevice.h" static gboolean plugin_init (GstPlugin * plugin) @@ -39,6 +39,11 @@ plugin_init (GstPlugin * plugin) GST_TYPE_DIRECTSOUND_SRC)) return FALSE; + if (!gst_device_provider_register (plugin, "directsoundsrcdeviceprovider", + GST_RANK_PRIMARY, GST_TYPE_DIRECTSOUND_DEVICE_PROVIDER)) + return FALSE; + + return TRUE; } diff --git a/sys/directsound/gstdirectsoundsrc.c b/sys/directsound/gstdirectsoundsrc.c index 0df4f4fc56..be6b2c894c 100644 --- a/sys/directsound/gstdirectsoundsrc.c +++ b/sys/directsound/gstdirectsoundsrc.c @@ -138,10 +138,7 @@ static GstStaticPadTemplate directsound_src_src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw, " - "format = (string) { S16LE, S8 }, " - "layout = (string) interleaved, " - "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")); + GST_STATIC_CAPS (GST_DIRECTSOUND_SRC_CAPS)); #define gst_directsound_src_parent_class parent_class G_DEFINE_TYPE_WITH_CODE (GstDirectSoundSrc, gst_directsound_src, @@ -427,7 +424,8 @@ gst_directsound_src_open (GstAudioSrc * asrc) } } /* Create capture object */ - hRes = DirectSoundCaptureCreate (dsoundsrc->device_guid, &dsoundsrc->pDSC, NULL); + hRes = + DirectSoundCaptureCreate (dsoundsrc->device_guid, &dsoundsrc->pDSC, NULL); if (FAILED (hRes)) { diff --git a/sys/directsound/gstdirectsoundsrc.h b/sys/directsound/gstdirectsoundsrc.h index bffb772567..f92fb99137 100644 --- a/sys/directsound/gstdirectsoundsrc.h +++ b/sys/directsound/gstdirectsoundsrc.h @@ -115,6 +115,11 @@ struct _GstDirectSoundSrcClass GType gst_directsound_src_get_type (void); +#define GST_DIRECTSOUND_SRC_CAPS "audio/x-raw, " + "format = (string) { S16LE, S8 }, " + "layout = (string) interleaved, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]" + G_END_DECLS #endif /* __GST_DIRECTSOUNDSRC_H__ */