Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds functions to turn on audio monitoring to allow the user to hear playback of an audio source over the user's speaker. It can be set to turn off monitoring and only output to stream, or it can be set to output only to monitoring, or it can be set to both. On windows, audio monitoring uses WASAPI. Windows also is capable of syncing the audio to the video according to when the video frame itself was played. On mac, it uses AudioQueue. On linux, it's not currently implemented and won't do anything (to be implemented).
- Loading branch information
Showing
13 changed files
with
1,170 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#include "../../obs-internal.h" | ||
|
||
void obs_enum_audio_monitoring_devices(obs_enum_audio_device_cb cb, void *data) | ||
{ | ||
UNUSED_PARAMETER(cb); | ||
UNUSED_PARAMETER(data); | ||
} | ||
|
||
struct audio_monitor *audio_monitor_create(obs_source_t *source) | ||
{ | ||
UNUSED_PARAMETER(source); | ||
return NULL; | ||
} | ||
|
||
void audio_monitor_reset(struct audio_monitor *monitor) | ||
{ | ||
UNUSED_PARAMETER(monitor); | ||
} | ||
|
||
void audio_monitor_destroy(struct audio_monitor *monitor) | ||
{ | ||
UNUSED_PARAMETER(monitor); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#include <CoreFoundation/CFString.h> | ||
#include <CoreAudio/CoreAudio.h> | ||
|
||
#include "../../obs-internal.h" | ||
#include "../../util/dstr.h" | ||
|
||
#include "mac-helpers.h" | ||
|
||
static inline bool cf_to_cstr(CFStringRef ref, char *buf, size_t size) | ||
{ | ||
if (!ref) return false; | ||
return (bool)CFStringGetCString(ref, buf, size, kCFStringEncodingUTF8); | ||
} | ||
|
||
static void obs_enum_audio_monitoring_device(obs_enum_audio_device_cb cb, | ||
void *data, AudioDeviceID id) | ||
{ | ||
UInt32 size = 0; | ||
CFStringRef cf_name = NULL; | ||
CFStringRef cf_uid = NULL; | ||
char name[1024]; | ||
char uid[1024]; | ||
OSStatus stat; | ||
|
||
AudioObjectPropertyAddress addr = { | ||
kAudioDevicePropertyStreams, | ||
kAudioDevicePropertyScopeInput, | ||
kAudioObjectPropertyElementMaster | ||
}; | ||
|
||
/* check to see if it's a mac input device */ | ||
AudioObjectGetPropertyDataSize(id, &addr, 0, NULL, &size); | ||
if (!size) | ||
return; | ||
|
||
size = sizeof(CFStringRef); | ||
|
||
addr.mSelector = kAudioDevicePropertyDeviceUID; | ||
stat = AudioObjectGetPropertyData(id, &addr, 0, NULL, &size, &cf_uid); | ||
if (!success(stat, "get audio device UID")) | ||
return; | ||
|
||
addr.mSelector = kAudioDevicePropertyDeviceNameCFString; | ||
stat = AudioObjectGetPropertyData(id, &addr, 0, NULL, &size, &cf_name); | ||
if (!success(stat, "get audio device name")) | ||
goto fail; | ||
|
||
if (!cf_to_cstr(cf_name, name, sizeof(name))) { | ||
blog(LOG_WARNING, "%s: failed to convert name", __FUNCTION__); | ||
goto fail; | ||
} | ||
|
||
if (!cf_to_cstr(cf_uid, uid, sizeof(uid))) { | ||
blog(LOG_WARNING, "%s: failed to convert uid", __FUNCTION__); | ||
goto fail; | ||
} | ||
|
||
cb(data, name, uid); | ||
|
||
fail: | ||
if (cf_name) | ||
CFRelease(cf_name); | ||
if (cf_uid) | ||
CFRelease(cf_uid); | ||
} | ||
|
||
void obs_enum_audio_monitoring_devices(obs_enum_audio_device_cb cb, void *data) | ||
{ | ||
AudioObjectPropertyAddress addr = { | ||
kAudioHardwarePropertyDevices, | ||
kAudioObjectPropertyScopeGlobal, | ||
kAudioObjectPropertyElementMaster | ||
}; | ||
|
||
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++) | ||
obs_enum_audio_monitoring_device(cb, data, ids[i]); | ||
} | ||
|
||
free(ids); | ||
} |
Oops, something went wrong.