2 * Copyright (C) 2021 Seungha Yang <seungha@centricular.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
24 #include "gstasiodeviceprovider.h"
25 #include "gstasioutils.h"
26 #include "gstasioobject.h"
40 const gchar *factory_name;
43 G_DEFINE_TYPE (GstAsioDevice, gst_asio_device, GST_TYPE_DEVICE);
45 static void gst_asio_device_get_property (GObject * object,
46 guint prop_id, GValue * value, GParamSpec * pspec);
47 static void gst_asio_device_set_property (GObject * object,
48 guint prop_id, const GValue * value, GParamSpec * pspec);
49 static void gst_asio_device_finalize (GObject * object);
50 static GstElement *gst_asio_device_create_element (GstDevice * device,
54 gst_asio_device_class_init (GstAsioDeviceClass * klass)
56 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
57 GstDeviceClass *dev_class = GST_DEVICE_CLASS (klass);
59 dev_class->create_element = gst_asio_device_create_element;
61 gobject_class->get_property = gst_asio_device_get_property;
62 gobject_class->set_property = gst_asio_device_set_property;
63 gobject_class->finalize = gst_asio_device_finalize;
65 g_object_class_install_property (gobject_class, PROP_DEVICE_CLSID,
66 g_param_spec_string ("device-clsid", "Device CLSID",
67 "ASIO device CLSID as string including curly brackets", NULL,
68 (GParamFlags) (G_PARAM_READWRITE |
69 G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)));
73 gst_asio_device_init (GstAsioDevice * self)
78 gst_asio_device_finalize (GObject * object)
80 GstAsioDevice *self = GST_ASIO_DEVICE (object);
82 g_free (self->device_clsid);
84 G_OBJECT_CLASS (gst_asio_device_parent_class)->finalize (object);
88 gst_asio_device_create_element (GstDevice * device, const gchar * name)
90 GstAsioDevice *self = GST_ASIO_DEVICE (device);
93 elem = gst_element_factory_make (self->factory_name, name);
95 g_object_set (elem, "device-clsid", self->device_clsid, NULL);
101 gst_asio_device_get_property (GObject * object, guint prop_id,
102 GValue * value, GParamSpec * pspec)
104 GstAsioDevice *self = GST_ASIO_DEVICE (object);
107 case PROP_DEVICE_CLSID:
108 g_value_set_string (value, self->device_clsid);
111 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
117 gst_asio_device_set_property (GObject * object, guint prop_id,
118 const GValue * value, GParamSpec * pspec)
120 GstAsioDevice *self = GST_ASIO_DEVICE (object);
123 case PROP_DEVICE_CLSID:
124 g_free (self->device_clsid);
125 self->device_clsid = g_value_dup_string (value);
128 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
133 struct _GstAsioDeviceProvider
135 GstDeviceProvider parent;
138 G_DEFINE_TYPE (GstAsioDeviceProvider, gst_asio_device_provider,
139 GST_TYPE_DEVICE_PROVIDER);
141 static GList *gst_asio_device_provider_probe (GstDeviceProvider * provider);
144 gst_asio_device_provider_class_init (GstAsioDeviceProviderClass * klass)
146 GstDeviceProviderClass *provider_class = GST_DEVICE_PROVIDER_CLASS (klass);
148 provider_class->probe = GST_DEBUG_FUNCPTR (gst_asio_device_provider_probe);
150 gst_device_provider_class_set_static_metadata (provider_class,
151 "ASIO Device Provider",
152 "Source/Sink/Audio", "List ASIO source and sink devices",
153 "Seungha Yang <seungha@centricular.com>");
157 gst_asio_device_provider_init (GstAsioDeviceProvider * provider)
162 gst_asio_device_provider_probe_internal (GstAsioDeviceProvider * self,
163 gboolean is_src, GList * asio_device_list, GList ** devices)
165 const gchar *device_class, *factory_name;
171 device_class = "Audio/Source";
172 factory_name = "asiosrc";
174 device_class = "Audio/Sink";
175 factory_name = "asiosink";
178 for (iter = asio_device_list; iter; iter = g_list_next (iter)) {
180 GstAsioDeviceInfo *info = (GstAsioDeviceInfo *) iter->data;
182 GstCaps *caps = nullptr;
183 GstStructure *props = nullptr;
187 LPOLESTR clsid_str = nullptr;
188 glong min_buf_size = 0;
189 glong max_buf_size = 0;
190 glong preferred_buf_size = 0;
191 glong buf_size_granularity = 0;
193 obj = gst_asio_object_new (info, FALSE);
197 if (!gst_asio_object_get_max_num_channels (obj, &max_in_ch, &max_out_ch))
200 if (is_src && max_in_ch <= 0)
202 else if (!is_src && max_out_ch <= 0)
206 caps = gst_asio_object_get_caps (obj,
207 GST_ASIO_DEVICE_CLASS_CAPTURE, 1, max_in_ch);
209 caps = gst_asio_object_get_caps (obj,
210 GST_ASIO_DEVICE_CLASS_RENDER, 1, max_out_ch);
215 hr = StringFromIID (info->clsid, &clsid_str);
219 if (!gst_asio_object_get_buffer_size (obj, &min_buf_size, &max_buf_size,
220 &preferred_buf_size, &buf_size_granularity))
223 props = gst_structure_new ("asio-proplist",
224 "device.api", G_TYPE_STRING, "asio",
225 "device.clsid", G_TYPE_STRING, OLE2A (clsid_str),
226 "asio.device.description", G_TYPE_STRING, info->driver_desc,
227 "asio.device.min-buf-size", G_TYPE_LONG, min_buf_size,
228 "asio.device.max-buf-size", G_TYPE_LONG, max_buf_size,
229 "asio.device.preferred-buf-size", G_TYPE_LONG, preferred_buf_size,
230 "asio.device.buf-size-granularity", G_TYPE_LONG, buf_size_granularity,
233 device = (GstDevice *) g_object_new (GST_TYPE_ASIO_DEVICE,
234 "device-clsid", OLE2A (clsid_str),
235 "display-name", info->driver_desc, "caps", caps,
236 "device-class", device_class, "properties", props, nullptr);
237 GST_ASIO_DEVICE (device)->factory_name = factory_name;
239 *devices = g_list_append (*devices, device);
242 gst_clear_caps (&caps);
243 gst_clear_object (&obj);
245 gst_structure_free (props);
252 gst_asio_device_provider_probe (GstDeviceProvider * provider)
254 GstAsioDeviceProvider *self = GST_ASIO_DEVICE_PROVIDER (provider);
255 GList *devices = nullptr;
257 GList *asio_device_list = nullptr;
259 num_device = gst_asio_enum (&asio_device_list);
264 gst_asio_device_provider_probe_internal (self,
265 TRUE, asio_device_list, &devices);
266 gst_asio_device_provider_probe_internal (self,
267 FALSE, asio_device_list, &devices);
269 g_list_free_full (asio_device_list,
270 (GDestroyNotify) gst_asio_device_info_free);