mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
wasapi: Implement a device provider for probing
Currently only does probing and does not handle messages from endpoints/devices. In the future we want to do proper monitoring which is well-supported in WASAPI. https://bugzilla.gnome.org/show_bug.cgi?id=792897
This commit is contained in:
parent
d6d31064b4
commit
ec6a10ed06
6 changed files with 451 additions and 17 deletions
|
@ -3,7 +3,8 @@ plugin_LTLIBRARIES = libgstwasapi.la
|
|||
libgstwasapi_la_SOURCES = gstwasapi.c \
|
||||
gstwasapisrc.c \
|
||||
gstwasapisink.c \
|
||||
gstwasapiutil.c
|
||||
gstwasapiutil.c \
|
||||
gstwasapidevice.c
|
||||
|
||||
libgstwasapi_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) -DCOBJMACROS=1
|
||||
libgstwasapi_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_API_VERSION) \
|
||||
|
@ -13,5 +14,5 @@ libgstwasapi_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
|||
|
||||
noinst_HEADERS = gstwasapisrc.h \
|
||||
gstwasapisink.h \
|
||||
gstwasapiutil.h
|
||||
|
||||
gstwasapiutil.h \
|
||||
gstwasapidevice.h
|
||||
|
|
|
@ -23,15 +23,22 @@
|
|||
|
||||
#include "gstwasapisink.h"
|
||||
#include "gstwasapisrc.h"
|
||||
#include "gstwasapidevice.h"
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
gst_element_register (plugin, "wasapisink", GST_RANK_NONE,
|
||||
GST_TYPE_WASAPI_SINK);
|
||||
gst_element_register (plugin, "wasapisrc", GST_RANK_NONE,
|
||||
GST_TYPE_WASAPI_SRC);
|
||||
if (!gst_element_register (plugin, "wasapisink", GST_RANK_NONE,
|
||||
GST_TYPE_WASAPI_SINK))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_element_register (plugin, "wasapisrc", GST_RANK_NONE,
|
||||
GST_TYPE_WASAPI_SRC))
|
||||
return FALSE;
|
||||
|
||||
if (!gst_device_provider_register (plugin, "wasapideviceprovider",
|
||||
GST_RANK_PRIMARY, GST_TYPE_WASAPI_DEVICE_PROVIDER))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
167
sys/wasapi/gstwasapidevice.c
Normal file
167
sys/wasapi/gstwasapidevice.c
Normal file
|
@ -0,0 +1,167 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2018 Nirbheek Chauhan <nirbheek@centricular.com>
|
||||
*
|
||||
* 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 "gstwasapidevice.h"
|
||||
|
||||
G_DEFINE_TYPE (GstWasapiDeviceProvider, gst_wasapi_device_provider,
|
||||
GST_TYPE_DEVICE_PROVIDER);
|
||||
|
||||
static void gst_wasapi_device_provider_finalize (GObject * object);
|
||||
static GList *gst_wasapi_device_provider_probe (GstDeviceProvider *
|
||||
provider);
|
||||
|
||||
static void
|
||||
gst_wasapi_device_provider_class_init (GstWasapiDeviceProviderClass *
|
||||
klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstDeviceProviderClass *dm_class = GST_DEVICE_PROVIDER_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = gst_wasapi_device_provider_finalize;
|
||||
|
||||
dm_class->probe = gst_wasapi_device_provider_probe;
|
||||
|
||||
gst_device_provider_class_set_static_metadata (dm_class,
|
||||
"WASAPI (Windows Audio Session API) Device Provider",
|
||||
"Source/Sink/Audio", "List WASAPI source and sink devices",
|
||||
"Nirbheek Chauhan <nirbheek@centricular.com>");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wasapi_device_provider_init (GstWasapiDeviceProvider * provider)
|
||||
{
|
||||
CoInitialize (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wasapi_device_provider_finalize (GObject * object)
|
||||
{
|
||||
CoUninitialize ();
|
||||
}
|
||||
|
||||
static GList *
|
||||
gst_wasapi_device_provider_probe (GstDeviceProvider * provider)
|
||||
{
|
||||
GstWasapiDeviceProvider *self = GST_WASAPI_DEVICE_PROVIDER (provider);
|
||||
GList *devices = NULL;
|
||||
|
||||
if (!gst_wasapi_util_get_devices (GST_ELEMENT (self), TRUE, &devices))
|
||||
GST_ERROR_OBJECT (self, "Failed to enumerate devices");
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
/* GstWasapiDevice begins */
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_DEVICE_STRID = 1,
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GstWasapiDevice, gst_wasapi_device, GST_TYPE_DEVICE);
|
||||
|
||||
static void gst_wasapi_device_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec);
|
||||
static void gst_wasapi_device_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||
static void gst_wasapi_device_finalize (GObject * object);
|
||||
static GstElement *gst_wasapi_device_create_element (GstDevice * device,
|
||||
const gchar * name);
|
||||
|
||||
static void
|
||||
gst_wasapi_device_class_init (GstWasapiDeviceClass * klass)
|
||||
{
|
||||
GstDeviceClass *dev_class = GST_DEVICE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
dev_class->create_element = gst_wasapi_device_create_element;
|
||||
|
||||
object_class->get_property = gst_wasapi_device_get_property;
|
||||
object_class->set_property = gst_wasapi_device_set_property;
|
||||
object_class->finalize = gst_wasapi_device_finalize;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_DEVICE_STRID,
|
||||
g_param_spec_string ("device", "Device string ID",
|
||||
"Device strId", NULL,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wasapi_device_init (GstWasapiDevice * device)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wasapi_device_finalize (GObject * object)
|
||||
{
|
||||
GstWasapiDevice *device = GST_WASAPI_DEVICE (object);
|
||||
|
||||
g_free (device->strid);
|
||||
|
||||
G_OBJECT_CLASS (gst_wasapi_device_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static GstElement *
|
||||
gst_wasapi_device_create_element (GstDevice * device, const gchar * name)
|
||||
{
|
||||
GstWasapiDevice *wasapi_dev = GST_WASAPI_DEVICE (device);
|
||||
GstElement *elem;
|
||||
|
||||
elem = gst_element_factory_make (wasapi_dev->element, name);
|
||||
|
||||
g_object_set (elem, "device", wasapi_dev->strid, NULL);
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wasapi_device_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstWasapiDevice *device = GST_WASAPI_DEVICE_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DEVICE_STRID:
|
||||
g_value_set_string (value, device->strid);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wasapi_device_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstWasapiDevice *device = GST_WASAPI_DEVICE_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DEVICE_STRID:
|
||||
device->strid = g_value_dup_string (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
75
sys/wasapi/gstwasapidevice.h
Normal file
75
sys/wasapi/gstwasapidevice.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2018 Nirbheek Chauhan <nirbheek@centricular.com>
|
||||
*
|
||||
* 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_WASAPI_DEVICE_H__
|
||||
#define __GST_WASAPI_DEVICE_H__
|
||||
|
||||
#include "gstwasapiutil.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GstWasapiDeviceProvider GstWasapiDeviceProvider;
|
||||
typedef struct _GstWasapiDeviceProviderClass GstWasapiDeviceProviderClass;
|
||||
|
||||
#define GST_TYPE_WASAPI_DEVICE_PROVIDER (gst_wasapi_device_provider_get_type())
|
||||
#define GST_IS_WASAPI_DEVICE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WASAPI_DEVICE_PROVIDER))
|
||||
#define GST_IS_WASAPI_DEVICE_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WASAPI_DEVICE_PROVIDER))
|
||||
#define GST_WASAPI_DEVICE_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WASAPI_DEVICE_PROVIDER, GstWasapiDeviceProviderClass))
|
||||
#define GST_WASAPI_DEVICE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WASAPI_DEVICE_PROVIDER, GstWasapiDeviceProvider))
|
||||
#define GST_WASAPI_DEVICE_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE_PROVIDER, GstWasapiDeviceProviderClass))
|
||||
#define GST_WASAPI_DEVICE_PROVIDER_CAST(obj) ((GstWasapiDeviceProvider *)(obj))
|
||||
|
||||
struct _GstWasapiDeviceProvider {
|
||||
GstDeviceProvider parent;
|
||||
};
|
||||
|
||||
struct _GstWasapiDeviceProviderClass {
|
||||
GstDeviceProviderClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_wasapi_device_provider_get_type (void);
|
||||
|
||||
|
||||
typedef struct _GstWasapiDevice GstWasapiDevice;
|
||||
typedef struct _GstWasapiDeviceClass GstWasapiDeviceClass;
|
||||
|
||||
#define GST_TYPE_WASAPI_DEVICE (gst_wasapi_device_get_type())
|
||||
#define GST_IS_WASAPI_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WASAPI_DEVICE))
|
||||
#define GST_IS_WASAPI_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WASAPI_DEVICE))
|
||||
#define GST_WASAPI_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WASAPI_DEVICE, GstWasapiDeviceClass))
|
||||
#define GST_WASAPI_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WASAPI_DEVICE, GstWasapiDevice))
|
||||
#define GST_WASAPI_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE, GstWasapiDeviceClass))
|
||||
#define GST_WASAPI_DEVICE_CAST(obj) ((GstWasapiDevice *)(obj))
|
||||
|
||||
struct _GstWasapiDevice {
|
||||
GstDevice parent;
|
||||
|
||||
gchar *strid;
|
||||
const gchar *element;
|
||||
};
|
||||
|
||||
struct _GstWasapiDeviceClass {
|
||||
GstDeviceClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_wasapi_device_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_WASAPI_DEVICE_H__ */
|
|
@ -23,12 +23,25 @@
|
|||
#endif
|
||||
|
||||
#include "gstwasapiutil.h"
|
||||
#include "gstwasapidevice.h"
|
||||
|
||||
#include <mmdeviceapi.h>
|
||||
|
||||
/* This was only added to MinGW in ~2015 and our Cerbero toolchain is too old */
|
||||
#if defined(_MSC_VER)
|
||||
#include <functiondiscoverykeys_devpkey.h>
|
||||
#elif !defined(PKEY_Device_FriendlyName)
|
||||
#include <initguid.h>
|
||||
#include <propkey.h>
|
||||
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
|
||||
DEFINE_PROPERTYKEY(PKEY_AudioEngine_DeviceFormat, 0xf19f064d, 0x82c, 0x4e27, 0xbc, 0x73, 0x68, 0x82, 0xa1, 0xbb, 0x8e, 0x4c, 0);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __uuidof
|
||||
const CLSID CLSID_MMDeviceEnumerator = __uuidof (MMDeviceEnumerator);
|
||||
const IID IID_IMMDeviceEnumerator = __uuidof (IMMDeviceEnumerator);
|
||||
const IID IID_IMMEndpoint = __uuidof (IMMEndpoint);
|
||||
const IID IID_IAudioClient = __uuidof (IAudioClient);
|
||||
const IID IID_IAudioRenderClient = __uuidof (IAudioRenderClient);
|
||||
const IID IID_IAudioCaptureClient = __uuidof (IAudioCaptureClient);
|
||||
|
@ -44,6 +57,10 @@ const IID IID_IMMDeviceEnumerator = { 0xa95664d2, 0x9614, 0x4f35,
|
|||
{0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6}
|
||||
};
|
||||
|
||||
const IID IID_IMMEndpoint = { 0x1be09788, 0x6894, 0x4089,
|
||||
{0x85, 0x86, 0x9a, 0x2a, 0x6c, 0x26, 0x5a, 0xc5}
|
||||
};
|
||||
|
||||
const IID IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32,
|
||||
{0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2}
|
||||
};
|
||||
|
@ -235,6 +252,176 @@ gst_wasapi_util_hresult_to_string (HRESULT hr)
|
|||
return s;
|
||||
}
|
||||
|
||||
static IMMDeviceEnumerator*
|
||||
gst_wasapi_util_get_device_enumerator (GstElement * element)
|
||||
{
|
||||
HRESULT hr;
|
||||
IMMDeviceEnumerator *enumerator = NULL;
|
||||
|
||||
hr = CoCreateInstance (&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
|
||||
&IID_IMMDeviceEnumerator, (void **) &enumerator);
|
||||
if (hr != S_OK) {
|
||||
GST_ERROR_OBJECT (element, "CoCreateInstance (MMDeviceEnumerator) failed"
|
||||
": %s", gst_wasapi_util_hresult_to_string (hr));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_wasapi_util_get_devices (GstElement * element, gboolean active,
|
||||
GList ** devices)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
static GstStaticCaps scaps = GST_STATIC_CAPS (GST_WASAPI_STATIC_CAPS);
|
||||
DWORD dwStateMask = active ? DEVICE_STATE_ACTIVE : DEVICE_STATEMASK_ALL;
|
||||
IMMDeviceCollection *device_collection = NULL;
|
||||
IMMDeviceEnumerator *enumerator = NULL;
|
||||
const gchar *device_class, *element_name;
|
||||
guint ii, count;
|
||||
HRESULT hr;
|
||||
|
||||
*devices = NULL;
|
||||
|
||||
enumerator = gst_wasapi_util_get_device_enumerator (element);
|
||||
if (!enumerator)
|
||||
return FALSE;
|
||||
|
||||
hr = IMMDeviceEnumerator_EnumAudioEndpoints (enumerator, eAll, dwStateMask,
|
||||
&device_collection);
|
||||
if (hr != S_OK) {
|
||||
GST_ERROR_OBJECT (element, "IMMDeviceEnumerator::EnumAudioEndpoints "
|
||||
"failed: %s", gst_wasapi_util_hresult_to_string (hr));
|
||||
goto err;
|
||||
}
|
||||
|
||||
hr = IMMDeviceCollection_GetCount (device_collection, &count);
|
||||
if (hr != S_OK) {
|
||||
GST_ERROR_OBJECT (element, "Failed to count devices: %s",
|
||||
gst_wasapi_util_hresult_to_string (hr));
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Create a GList of GstDevices* to return */
|
||||
for (ii = 0; ii < count; ii++) {
|
||||
IMMDevice *item = NULL;
|
||||
IMMEndpoint *endpoint = NULL;
|
||||
IAudioClient *client = NULL;
|
||||
IPropertyStore *prop_store = NULL;
|
||||
WAVEFORMATEX *format = NULL;
|
||||
gchar *description = NULL;
|
||||
gchar *strid = NULL;
|
||||
EDataFlow dataflow;
|
||||
PROPVARIANT var;
|
||||
wchar_t *wstrid;
|
||||
GstDevice *device;
|
||||
GstStructure *props;
|
||||
GstCaps *caps;
|
||||
|
||||
hr = IMMDeviceCollection_Item (device_collection, ii, &item);
|
||||
if (hr != S_OK)
|
||||
continue;
|
||||
|
||||
hr = IMMDevice_QueryInterface (item, &IID_IMMEndpoint, (void **) &endpoint);
|
||||
if (hr != S_OK)
|
||||
goto next;
|
||||
|
||||
hr = IMMEndpoint_GetDataFlow (endpoint, &dataflow);
|
||||
if (hr != S_OK)
|
||||
goto next;
|
||||
|
||||
if (dataflow == eRender) {
|
||||
device_class = "Audio/Sink";
|
||||
element_name = "wasapisink";
|
||||
} else {
|
||||
device_class = "Audio/Source";
|
||||
element_name = "wasapisrc";
|
||||
}
|
||||
|
||||
PropVariantInit (&var);
|
||||
|
||||
hr = IMMDevice_GetId (item, &wstrid);
|
||||
if (hr != S_OK)
|
||||
goto next;
|
||||
strid = g_utf16_to_utf8 (wstrid, -1, NULL, NULL, NULL);
|
||||
CoTaskMemFree (wstrid);
|
||||
|
||||
hr = IMMDevice_OpenPropertyStore (item, STGM_READ, &prop_store);
|
||||
if (hr != S_OK)
|
||||
goto next;
|
||||
|
||||
/* NOTE: More properties can be added as needed from here:
|
||||
* https://msdn.microsoft.com/en-us/library/windows/desktop/dd370794(v=vs.85).aspx */
|
||||
hr = IPropertyStore_GetValue (prop_store, &PKEY_Device_FriendlyName, &var);
|
||||
if (hr != S_OK)
|
||||
goto next;
|
||||
description = g_utf16_to_utf8 (var.pwszVal, -1, NULL, NULL, NULL);
|
||||
PropVariantClear (&var);
|
||||
|
||||
/* Get the audio client so we can fetch the mix format for shared mode
|
||||
* to get the device format for exclusive mode (or something close to that)
|
||||
* fetch PKEY_AudioEngine_DeviceFormat from the property store. */
|
||||
hr = IMMDevice_Activate (item, &IID_IAudioClient, CLSCTX_ALL, NULL,
|
||||
(void **) &client);
|
||||
if (hr != S_OK) {
|
||||
GST_ERROR_OBJECT (element, "IMMDevice::Activate (IID_IAudioClient) failed"
|
||||
"on %s: %s", strid, gst_wasapi_util_hresult_to_string (hr));
|
||||
goto next;
|
||||
}
|
||||
|
||||
hr = IAudioClient_GetMixFormat (client, &format);
|
||||
if (hr != S_OK || format == NULL) {
|
||||
GST_ERROR_OBJECT ("GetMixFormat failed on %s: %s", strid,
|
||||
gst_wasapi_util_hresult_to_string (hr));
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (!gst_wasapi_util_parse_waveformatex ((WAVEFORMATEXTENSIBLE *) format,
|
||||
gst_static_caps_get (&scaps), &caps, NULL))
|
||||
goto next;
|
||||
|
||||
/* Set some useful properties */
|
||||
props = gst_structure_new ("wasapi-proplist",
|
||||
"device.api", G_TYPE_STRING, "wasapi",
|
||||
"device.strid", G_TYPE_STRING, GST_STR_NULL (strid),
|
||||
"wasapi.device.description", G_TYPE_STRING, description, NULL);
|
||||
|
||||
device = g_object_new (GST_TYPE_WASAPI_DEVICE, "device", strid,
|
||||
"display-name", description, "caps", caps,
|
||||
"device-class", device_class, "properties", props, NULL);
|
||||
GST_WASAPI_DEVICE(device)->element = element_name;
|
||||
|
||||
gst_structure_free (props);
|
||||
gst_caps_unref (caps);
|
||||
*devices = g_list_prepend (*devices, device);
|
||||
|
||||
next:
|
||||
PropVariantClear (&var);
|
||||
if (prop_store)
|
||||
IUnknown_Release (prop_store);
|
||||
if (endpoint)
|
||||
IUnknown_Release (endpoint);
|
||||
if (client)
|
||||
IUnknown_Release (client);
|
||||
if (item)
|
||||
IUnknown_Release (item);
|
||||
if (description)
|
||||
g_free (description);
|
||||
if (strid)
|
||||
g_free (strid);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
err:
|
||||
if (enumerator)
|
||||
IUnknown_Release (enumerator);
|
||||
if (device_collection)
|
||||
IUnknown_Release (device_collection);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_wasapi_util_get_device_client (GstElement * element,
|
||||
gboolean capture, gint role, const wchar_t * device_strid,
|
||||
|
@ -246,13 +433,8 @@ gst_wasapi_util_get_device_client (GstElement * element,
|
|||
IMMDevice *device = NULL;
|
||||
IAudioClient *client = NULL;
|
||||
|
||||
hr = CoCreateInstance (&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
|
||||
&IID_IMMDeviceEnumerator, (void **) &enumerator);
|
||||
if (hr != S_OK) {
|
||||
GST_ERROR_OBJECT (element, "CoCreateInstance (MMDeviceEnumerator) failed"
|
||||
": %s", gst_wasapi_util_hresult_to_string (hr));
|
||||
if (!(enumerator = gst_wasapi_util_get_device_enumerator (element)))
|
||||
goto beach;
|
||||
}
|
||||
|
||||
if (!device_strid) {
|
||||
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint (enumerator,
|
||||
|
|
|
@ -52,10 +52,12 @@ gint gst_wasapi_erole_to_device_role (gint erole);
|
|||
|
||||
const gchar *gst_wasapi_util_hresult_to_string (HRESULT hr);
|
||||
|
||||
gboolean
|
||||
gst_wasapi_util_get_device_client (GstElement * element,
|
||||
gboolean capture,
|
||||
gint role, const wchar_t * device_name, IAudioClient ** ret_client);
|
||||
gboolean gst_wasapi_util_get_devices (GstElement * element, gboolean active,
|
||||
GList ** devices);
|
||||
|
||||
gboolean gst_wasapi_util_get_device_client (GstElement * element,
|
||||
gboolean capture, gint role, const wchar_t * device_strid,
|
||||
IAudioClient ** ret_client);
|
||||
|
||||
gboolean gst_wasapi_util_get_render_client (GstElement * element,
|
||||
IAudioClient * client, IAudioRenderClient ** ret_render_client);
|
||||
|
|
Loading…
Reference in a new issue