Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions libobs/audio-monitoring/osx/coreaudio-enum-devices.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,51 @@ bool devices_match(const char *id1, const char *id2)

return match;
}

static inline bool device_is_input(const char *device)
{
return astrstri(device, "soundflower") == NULL && astrstri(device, "wavtap") == NULL &&
astrstri(device, "soundsiphon") == NULL && astrstri(device, "ishowu") == NULL &&
astrstri(device, "blackhole") == NULL && astrstri(device, "loopback") == NULL &&
astrstri(device, "groundcontrol") == NULL && astrstri(device, "vbcable") == NULL;
}

static bool find_loopback_cb(void *param, const char *name, const char *id)
{
UNUSED_PARAMETER(name);
char **p_id = param;

if (!device_is_input(id)) {
*p_id = bstrdup(id);
return false;
}
return true;
}

void get_desktop_default_id(char **p_id)
{
if (*p_id)
return;

AudioObjectPropertyAddress addr = {kAudioHardwarePropertyDefaultSystemOutputDevice,
kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain};

AudioDeviceID id = 0;
UInt32 size = sizeof(id);
OSStatus stat = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &size, &id);

if (success(stat, "AudioObjectGetPropertyData")) {
/* Try system default output first */
obs_enum_audio_monitoring_device(alloc_default_id, p_id, id, false);

/* If not a loopback, try to find a virtual (non-input) device instead */
if (*p_id && device_is_input(*p_id)) {
bfree(*p_id);
*p_id = NULL;
enum_audio_devices(find_loopback_cb, p_id, false);
}
}

if (!*p_id)
*p_id = bzalloc(1);
}
63 changes: 39 additions & 24 deletions libobs/obs-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,37 +48,52 @@ static inline bool is_individual_audio_source(obs_source_t *source)
!(source->info.output_flags & OBS_SOURCE_COMPOSITE);
}

extern bool devices_match(const char *id1, const char *id2);

static inline void check_audio_output_source_is_monitoring_device(obs_source_t *s, void *p)
{
struct obs_core_audio *audio = p;
if (!audio->monitoring_device_name)
return;

if (strcmp(s->info.id, "wasapi_output_capture") == 0 || strcmp(s->info.id, "pulse_output_capture") == 0 ||
strcmp(s->info.id, "coreaudio_output_capture") == 0) {
const char *dev_id = NULL;
obs_data_t *settings = obs_source_get_settings(s);
bool is_pulse = strcmp(s->info.id, "pulse_output_capture") == 0;
if (settings) {
dev_id = obs_data_get_string(settings, "device_id");
bool id_match = strcmp(dev_id, audio->monitoring_device_id) == 0;
if (is_pulse) {
// pulse may append '.monitor'
size_t count = strlen(audio->monitoring_device_id) - 9;
id_match = id_match || strncmp(dev_id, audio->monitoring_device_id, count) == 0;
}
if (id_match) {
audio->prevent_monitoring_duplication = true;
audio->monitoring_duplicating_source = s;
if (!audio->monitoring_duplication_prevented_on_prev_tick)
blog(LOG_INFO,
"Device for 'Audio Output Capture' source is also used for audio"
" monitoring:\nDeduplication logic is being applied to all monitored"
" sources.\n");
}
obs_data_release(settings);
}
const char *id = s->info.id;
if (strcmp(id, "wasapi_output_capture") != 0 && strcmp(id, "pulse_output_capture") != 0 &&
strcmp(id, "coreaudio_output_capture") != 0)
return;

obs_data_t *settings = obs_source_get_settings(s);
if (!settings)
return;

const char *device_id = obs_data_get_string(settings, "device_id");
const char *mon_id = audio->monitoring_device_id;
bool id_match = false;

#ifdef __APPLE__
extern void get_desktop_default_id(char **p_id);
if (device_id && strcmp(device_id, "default") == 0) {
char *def_id = NULL;
get_desktop_default_id(&def_id);
id_match = devices_match(def_id, mon_id);
if (def_id)
bfree(def_id);
} else {
id_match = devices_match(device_id, mon_id);
}
#else
id_match = devices_match(device_id, mon_id);
#endif

if (id_match) {
audio->prevent_monitoring_duplication = true;
audio->monitoring_duplicating_source = s;
if (!audio->monitoring_duplication_prevented_on_prev_tick)
blog(LOG_INFO, "Device for 'Audio Output Capture' source is also used for audio"
" monitoring:\nDeduplication logic is being applied to all monitored"
" sources.\n");
}

obs_data_release(settings);
}

/*
Expand Down