mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
osxaudiosrc: Support a device as both input and output
osxaudiodeviceprovider now probes devices more than once to determine if the device can function as both an input AND and output device. Previously, if the device provider detected that a device had any output capabilities, it was treated solely as an Audio/Sink. This causes issues that have both input and output capabilities (for example, USB interfaces for professional audio have both input and output channels). Such devices are now listed as both an Audio/Sink as well as an Audio/Source. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1385>
This commit is contained in:
parent
2fc91717cb
commit
630dbea94c
1 changed files with 85 additions and 29 deletions
|
@ -150,10 +150,40 @@ _audio_device_has_output (AudioDeviceID device_id)
|
||||||
|
|
||||||
status = AudioObjectGetPropertyDataSize (device_id,
|
status = AudioObjectGetPropertyDataSize (device_id,
|
||||||
&streamsAddress, 0, NULL, &propertySize);
|
&streamsAddress, 0, NULL, &propertySize);
|
||||||
|
|
||||||
if (status != noErr) {
|
if (status != noErr) {
|
||||||
|
GST_WARNING ("failed getting device property: %d", (int) status);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (propertySize == 0) {
|
if (propertySize == 0) {
|
||||||
|
GST_DEBUG ("property size was 0; device has no output channels");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
_audio_device_has_input (AudioDeviceID device_id)
|
||||||
|
{
|
||||||
|
OSStatus status = noErr;
|
||||||
|
UInt32 propertySize;
|
||||||
|
|
||||||
|
AudioObjectPropertyAddress streamsAddress = {
|
||||||
|
kAudioDevicePropertyStreams,
|
||||||
|
kAudioDevicePropertyScopeInput,
|
||||||
|
kAudioObjectPropertyElementMaster
|
||||||
|
};
|
||||||
|
|
||||||
|
status = AudioObjectGetPropertyDataSize (device_id,
|
||||||
|
&streamsAddress, 0, NULL, &propertySize);
|
||||||
|
|
||||||
|
if (status != noErr) {
|
||||||
|
GST_WARNING ("failed getting device property: %d", (int) status);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (propertySize == 0) {
|
||||||
|
GST_DEBUG ("property size was 0; device has no input channels");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,14 +227,63 @@ _audio_system_get_devices (gint * ndevices)
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_osx_audio_device_provider_probe_internal (GstOsxAudioDeviceProvider * self,
|
||||||
|
gboolean is_src, AudioDeviceID * osx_devices, gint ndevices,
|
||||||
|
GList ** devices)
|
||||||
|
{
|
||||||
|
|
||||||
|
gint i = 0;
|
||||||
|
GstOsxAudioDeviceType type = GST_OSX_AUDIO_DEVICE_TYPE_INVALID;
|
||||||
|
GstOsxAudioDevice *device = NULL;
|
||||||
|
|
||||||
|
if (is_src) {
|
||||||
|
type = GST_OSX_AUDIO_DEVICE_TYPE_SOURCE;
|
||||||
|
} else {
|
||||||
|
type = GST_OSX_AUDIO_DEVICE_TYPE_SINK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ndevices; i++) {
|
||||||
|
gchar *device_name;
|
||||||
|
|
||||||
|
if ((device_name = _audio_device_get_name (osx_devices[i], FALSE))) {
|
||||||
|
gboolean has_output = _audio_device_has_output (osx_devices[i]);
|
||||||
|
gboolean has_input = _audio_device_has_input (osx_devices[i]);
|
||||||
|
|
||||||
|
if (is_src && !has_input) {
|
||||||
|
goto cleanup;
|
||||||
|
} else if (!is_src && !has_output) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
device =
|
||||||
|
gst_osx_audio_device_provider_probe_device (self, osx_devices[i],
|
||||||
|
device_name, type);
|
||||||
|
if (device) {
|
||||||
|
if (is_src) {
|
||||||
|
GST_DEBUG ("Input Device ID: %u Name: %s",
|
||||||
|
(unsigned) osx_devices[i], device_name);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG ("Output Device ID: %u Name: %s",
|
||||||
|
(unsigned) osx_devices[i], device_name);
|
||||||
|
}
|
||||||
|
gst_object_ref_sink (device);
|
||||||
|
*devices = g_list_prepend (*devices, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
g_free (device_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
gst_osx_audio_device_provider_probe (GstDeviceProvider * provider)
|
gst_osx_audio_device_provider_probe (GstDeviceProvider * provider)
|
||||||
{
|
{
|
||||||
GstOsxAudioDeviceProvider *self = GST_OSX_AUDIO_DEVICE_PROVIDER (provider);
|
GstOsxAudioDeviceProvider *self = GST_OSX_AUDIO_DEVICE_PROVIDER (provider);
|
||||||
GList *devices = NULL;
|
GList *devices = NULL;
|
||||||
GstOsxAudioDevice *device = NULL;
|
|
||||||
AudioDeviceID *osx_devices = NULL;
|
AudioDeviceID *osx_devices = NULL;
|
||||||
gint i, ndevices = 0;
|
gint ndevices = 0;
|
||||||
|
|
||||||
osx_devices = _audio_system_get_devices (&ndevices);
|
osx_devices = _audio_system_get_devices (&ndevices);
|
||||||
|
|
||||||
|
@ -215,33 +294,10 @@ gst_osx_audio_device_provider_probe (GstDeviceProvider * provider)
|
||||||
|
|
||||||
GST_INFO ("found %d audio device(s)", ndevices);
|
GST_INFO ("found %d audio device(s)", ndevices);
|
||||||
|
|
||||||
for (i = 0; i < ndevices; i++) {
|
gst_osx_audio_device_provider_probe_internal (self, TRUE, osx_devices,
|
||||||
gchar *device_name;
|
ndevices, &devices);
|
||||||
GstOsxAudioDeviceType type = GST_OSX_AUDIO_DEVICE_TYPE_INVALID;
|
gst_osx_audio_device_provider_probe_internal (self, FALSE, osx_devices,
|
||||||
|
ndevices, &devices);
|
||||||
if ((device_name = _audio_device_get_name (osx_devices[i], FALSE))) {
|
|
||||||
if (!_audio_device_has_output (osx_devices[i])) {
|
|
||||||
GST_DEBUG ("Input Device ID: %u Name: %s",
|
|
||||||
(unsigned) osx_devices[i], device_name);
|
|
||||||
type = GST_OSX_AUDIO_DEVICE_TYPE_SOURCE;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
GST_DEBUG ("Output Device ID: %u Name: %s",
|
|
||||||
(unsigned) osx_devices[i], device_name);
|
|
||||||
type = GST_OSX_AUDIO_DEVICE_TYPE_SINK;
|
|
||||||
}
|
|
||||||
|
|
||||||
device =
|
|
||||||
gst_osx_audio_device_provider_probe_device (self, osx_devices[i],
|
|
||||||
device_name, type);
|
|
||||||
if (device) {
|
|
||||||
gst_object_ref_sink (device);
|
|
||||||
devices = g_list_prepend (devices, device);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (device_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
g_free (osx_devices);
|
g_free (osx_devices);
|
||||||
|
|
Loading…
Reference in a new issue