123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- #include <CoreFoundation/CFString.h>
- #include <CoreAudio/CoreAudio.h>
- #include "../../obs-internal.h"
- #include "../../util/dstr.h"
- #include "../../util/apple/cfstring-utils.h"
- #include "mac-helpers.h"
- static bool obs_enum_audio_monitoring_device(obs_enum_audio_device_cb cb,
- void *data, AudioDeviceID id,
- bool allow_inputs)
- {
- UInt32 size = 0;
- CFStringRef cf_name = NULL;
- CFStringRef cf_uid = NULL;
- char *name = NULL;
- char *uid = NULL;
- OSStatus stat;
- bool cont = true;
- AudioObjectPropertyAddress addr = {kAudioDevicePropertyStreams,
- kAudioDevicePropertyScopeOutput,
- kAudioObjectPropertyElementMain};
- /* Check if the device is capable of audio output. */
- AudioObjectGetPropertyDataSize(id, &addr, 0, NULL, &size);
- if (!allow_inputs && !size)
- return true;
- size = sizeof(CFStringRef);
- addr.mSelector = kAudioDevicePropertyDeviceUID;
- stat = AudioObjectGetPropertyData(id, &addr, 0, NULL, &size, &cf_uid);
- if (!success(stat, "get audio device UID"))
- goto fail;
- addr.mSelector = kAudioDevicePropertyDeviceNameCFString;
- stat = AudioObjectGetPropertyData(id, &addr, 0, NULL, &size, &cf_name);
- if (!success(stat, "get audio device name"))
- goto fail;
- name = cfstr_copy_cstr(cf_name, kCFStringEncodingUTF8);
- if (!name) {
- blog(LOG_WARNING, "%s: failed to convert name", __FUNCTION__);
- goto fail;
- }
- uid = cfstr_copy_cstr(cf_uid, kCFStringEncodingUTF8);
- if (!uid) {
- blog(LOG_WARNING, "%s: failed to convert uid", __FUNCTION__);
- goto fail;
- }
- cont = cb(data, name, uid);
- fail:
- bfree(name);
- bfree(uid);
- if (cf_name)
- CFRelease(cf_name);
- if (cf_uid)
- CFRelease(cf_uid);
- return cont;
- }
- static void enum_audio_devices(obs_enum_audio_device_cb cb, void *data,
- bool allow_inputs)
- {
- AudioObjectPropertyAddress addr = {kAudioHardwarePropertyDevices,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMain};
- UInt32 size = 0;
- UInt32 count;
- OSStatus stat;
- AudioDeviceID *ids;
- stat = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr,
- 0, NULL, &size);
- if (!success(stat, "get data size"))
- return;
- ids = malloc(size);
- count = size / sizeof(AudioDeviceID);
- stat = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0,
- NULL, &size, ids);
- if (success(stat, "get data")) {
- for (UInt32 i = 0; i < count; i++) {
- if (!obs_enum_audio_monitoring_device(cb, data, ids[i],
- allow_inputs))
- break;
- }
- }
- free(ids);
- }
- void obs_enum_audio_monitoring_devices(obs_enum_audio_device_cb cb, void *data)
- {
- enum_audio_devices(cb, data, false);
- }
- static bool alloc_default_id(void *data, const char *name, const char *id)
- {
- char **p_id = data;
- UNUSED_PARAMETER(name);
- *p_id = bstrdup(id);
- return false;
- }
- static void get_default_id(char **p_id)
- {
- AudioObjectPropertyAddress addr = {
- kAudioHardwarePropertyDefaultSystemOutputDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMain};
- if (*p_id)
- return;
- OSStatus stat;
- AudioDeviceID id = 0;
- UInt32 size = sizeof(id);
- stat = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0,
- NULL, &size, &id);
- if (success(stat, "AudioObjectGetPropertyData"))
- obs_enum_audio_monitoring_device(alloc_default_id, p_id, id,
- true);
- if (!*p_id)
- *p_id = bzalloc(1);
- }
- struct device_name_info {
- const char *id;
- char *name;
- };
- static bool enum_device_name(void *data, const char *name, const char *id)
- {
- struct device_name_info *info = data;
- if (strcmp(info->id, id) == 0) {
- info->name = bstrdup(name);
- return false;
- }
- return true;
- }
- bool devices_match(const char *id1, const char *id2)
- {
- struct device_name_info info = {0};
- char *default_id = NULL;
- char *name1 = NULL;
- char *name2 = NULL;
- bool match;
- if (!id1 || !id2)
- return false;
- if (strcmp(id1, "default") == 0) {
- get_default_id(&default_id);
- id1 = default_id;
- }
- if (strcmp(id2, "default") == 0) {
- get_default_id(&default_id);
- id2 = default_id;
- }
- info.id = id1;
- enum_audio_devices(enum_device_name, &info, true);
- name1 = info.name;
- info.name = NULL;
- info.id = id2;
- enum_audio_devices(enum_device_name, &info, true);
- name2 = info.name;
- match = name1 && name2 && strcmp(name1, name2) == 0;
- bfree(default_id);
- bfree(name1);
- bfree(name2);
- return match;
- }
|