From 2bc90d21060cf641604d7a46f9ab03e49943859d Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 6 Jul 2023 13:50:17 -0700 Subject: [PATCH] Add lovr.audio.getDevice; --- src/api/l_audio.c | 23 ++++++++++++++++++----- src/modules/audio/audio.c | 28 ++++++++++++++++++++++++++-- src/modules/audio/audio.h | 10 +++++++++- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/api/l_audio.c b/src/api/l_audio.c index 3beac8a2..c0e25cef 100644 --- a/src/api/l_audio.c +++ b/src/api/l_audio.c @@ -55,15 +55,15 @@ StringEntry lovrVolumeUnit[] = { { 0 } }; -static void onDevice(const void* id, size_t size, const char* name, bool isDefault, void* userdata) { +static void onDevice(AudioDevice* device, void* userdata) { lua_State* L = userdata; lua_createtable(L, 0, 3); - void* p = lua_newuserdata(L, size); - memcpy(p, id, size); + void* p = lua_newuserdata(L, device->idSize); + memcpy(p, device->id, device->idSize); lua_setfield(L, -2, "id"); - lua_pushstring(L, name); + lua_pushstring(L, device->name); lua_setfield(L, -2, "name"); - lua_pushboolean(L, isDefault); + lua_pushboolean(L, device->isDefault); lua_setfield(L, -2, "default"); lua_rawseti(L, -2, luax_len(L, -2) + 1); } @@ -75,6 +75,18 @@ static int l_lovrAudioGetDevices(lua_State *L) { return 1; } +static int l_lovrAudioGetDevice(lua_State* L) { + AudioType type = luax_checkenum(L, 1, AudioType, "playback"); + AudioDevice device; + if (lovrAudioGetDevice(type, &device)) { + lua_pushstring(L, device.name); + void* p = lua_newuserdata(L, device.idSize); + memcpy(p, device.id, device.idSize); + return 2; + } + return 0; +} + static int l_lovrAudioSetDevice(lua_State *L) { AudioType type = luax_checkenum(L, 1, AudioType, "playback"); void* id = lua_touserdata(L, 2); @@ -282,6 +294,7 @@ static int l_lovrAudioNewSource(lua_State* L) { static const luaL_Reg lovrAudio[] = { { "getDevices", l_lovrAudioGetDevices }, + { "getDevice", l_lovrAudioGetDevice }, { "setDevice", l_lovrAudioSetDevice }, { "start", l_lovrAudioStart }, { "stop", l_lovrAudioStop }, diff --git a/src/modules/audio/audio.c b/src/modules/audio/audio.c index 3ba5a0e7..30348893 100644 --- a/src/modules/audio/audio.c +++ b/src/modules/audio/audio.c @@ -45,6 +45,7 @@ static struct { ma_mutex lock; ma_context context; ma_device devices[2]; + ma_device_info* deviceInfo[2]; Sound* sinks[2]; Source* sources[MAX_SOURCES]; uint64_t sourceMask; @@ -228,6 +229,7 @@ void lovrAudioDestroy(void) { if (!state.initialized) return; for (size_t i = 0; i < 2; i++) { ma_device_uninit(&state.devices[i]); + free(state.deviceInfo[i]); } Source* source; FOREACH_SOURCE(source) lovrRelease(source, lovrSourceDestroy); @@ -243,12 +245,14 @@ void lovrAudioDestroy(void) { static AudioDeviceCallback* enumerateCallback; static ma_bool32 enumPlayback(ma_context* context, ma_device_type type, const ma_device_info* info, void* userdata) { - if (type == ma_device_type_playback) enumerateCallback(&info->id, sizeof(info->id), info->name, info->isDefault, userdata); + AudioDevice device = { sizeof(info->id), &info->id, info->name, info->isDefault }; + if (type == ma_device_type_playback) enumerateCallback(&device, userdata); return MA_TRUE; } static ma_bool32 enumCapture(ma_context* context, ma_device_type type, const ma_device_info* info, void* userdata) { - if (type == ma_device_type_capture) enumerateCallback(&info->id, sizeof(info->id), info->name, info->isDefault, userdata); + AudioDevice device = { sizeof(info->id), &info->id, info->name, info->isDefault }; + if (type == ma_device_type_capture) enumerateCallback(&device, userdata); return MA_TRUE; } @@ -257,6 +261,26 @@ void lovrAudioEnumerateDevices(AudioType type, AudioDeviceCallback* callback, vo ma_context_enumerate_devices(&state.context, type == AUDIO_PLAYBACK ? enumPlayback : enumCapture, userdata); } +bool lovrAudioGetDevice(AudioType type, AudioDevice* device) { + if (!state.devices[type].pContext) { + return false; + } + + if (!state.deviceInfo[type]) { + state.deviceInfo[type] = malloc(sizeof(ma_device_info)); + lovrAssert(state.deviceInfo[type], "Out of memory"); + } + + ma_device_info* info = state.deviceInfo[type]; + ma_device_type deviceType = type == AUDIO_PLAYBACK ? ma_device_type_playback : ma_device_type_capture; + ma_result result = ma_device_get_info(&state.devices[type], deviceType, info); + device->idSize = sizeof(ma_device_id); + device->id = &info->id; + device->name = info->name; + device->isDefault = info->isDefault; + return result == MA_SUCCESS; +} + bool lovrAudioSetDevice(AudioType type, void* id, size_t size, Sound* sink, AudioShareMode shareMode) { if (id && size != sizeof(ma_device_id)) return false; diff --git a/src/modules/audio/audio.h b/src/modules/audio/audio.h index fec344ea..4c707992 100644 --- a/src/modules/audio/audio.h +++ b/src/modules/audio/audio.h @@ -39,6 +39,13 @@ typedef enum { AUDIO_EXCLUSIVE } AudioShareMode; +typedef struct { + size_t idSize; + const void* id; + const char* name; + bool isDefault; +} AudioDevice; + typedef enum { AUDIO_PLAYBACK, AUDIO_CAPTURE @@ -54,11 +61,12 @@ typedef enum { UNIT_DECIBELS } VolumeUnit; -typedef void AudioDeviceCallback(const void* id, size_t size, const char* name, bool isDefault, void* userdata); +typedef void AudioDeviceCallback(AudioDevice* device, void* userdata); bool lovrAudioInit(const char* spatializer, uint32_t sampleRate); void lovrAudioDestroy(void); void lovrAudioEnumerateDevices(AudioType type, AudioDeviceCallback* callback, void* userdata); +bool lovrAudioGetDevice(AudioType type, AudioDevice* device); bool lovrAudioSetDevice(AudioType type, void* id, size_t size, struct Sound* sink, AudioShareMode shareMode); bool lovrAudioStart(AudioType type); bool lovrAudioStop(AudioType type);