diff --git a/src/raudio.c b/src/raudio.c index 42ea410c8..acf0f8162 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -47,6 +47,9 @@ * - Mixing channels support * - Raw audio context support * +* Levi Spencer (github: @AllMeatball) (July. 2026) +* - Audio device listing (playback and capture) +* * * LICENSE: zlib/libpng * @@ -378,6 +381,12 @@ struct rAudioProcessor { rAudioProcessor *prev; // Previous audio processor on the list }; +// Audio device id abstraction struct +// NOTE: This could do more in the future, other than storing ma_device_id. +struct rAudioDeviceID { + ma_device_id id; +}; + #define AudioBuffer rAudioBuffer // WARNING: Renamed to avoid symbol collision with CoreAudio (macOS) AudioBuffer type // Audio data context @@ -567,6 +576,95 @@ float GetMasterVolume(void) return volume; } + +// Get list of all audio devices (playback and capture) +bool GetAudioDeviceList(AudioDeviceList *devices) +{ + ma_device_info *playbackDevices = NULL; + ma_uint32 playbackDevicesCount = 0; + + ma_device_info *captureDevices = NULL; + ma_uint32 captureDevicesCount = 0; + + ma_result result = ma_context_get_devices(&AUDIO.System.context, &playbackDevices, &playbackDevicesCount, &captureDevices, &captureDevicesCount); + + // ma_context_get_devices has failed, log that it did so and return false. + if (result != MA_SUCCESS) { + TRACELOG(LOG_WARNING, "AUDIO: Failed to get list of audio devices"); + return false; + } + + // Allocate list of devices. + devices->playbackDevices = RL_CALLOC( playbackDevicesCount, sizeof(AudioDevice) ); + devices->captureDevices = RL_CALLOC( captureDevicesCount, sizeof(AudioDevice) ); + + if (!devices->playbackDevices || !devices->captureDevices) { + TRACELOG(LOG_WARNING, "AUDIO: Failed to get list of audio devices"); + return false; + } + + devices->playbackDevicesCount = playbackDevicesCount; + devices->captureDevicesCount = captureDevicesCount; + + // Add playback devices. + for (unsigned int i = 0; i < playbackDevicesCount; i++) + { + ma_device_info device = playbackDevices[i]; + + rAudioDeviceID *id = RL_MALLOC(sizeof(rAudioDeviceID)); + id->id = device.id; + + devices->playbackDevices[i] = (AudioDevice){ + .id = id, + .name = StringDuplicate(device.name), + .type = AUDIODEVICE_PLAYBACK, + + .isDefault = device.isDefault == MA_TRUE, + }; + } + + // Add capture devices. + for (unsigned int i = 0; i < captureDevicesCount; i++) + { + ma_device_info device = captureDevices[i]; + + rAudioDeviceID *id = RL_MALLOC(sizeof(rAudioDeviceID)); + id->id = device.id; + + devices->playbackDevices[i] = (AudioDevice){ + .id = id, + .name = StringDuplicate(device.name), + .type = AUDIODEVICE_CAPTURE, + + .isDefault = device.isDefault == MA_TRUE, + }; + } + + return true; +} + +// Unload audio device list +void UnloadAudioDeviceList(AudioDeviceList devices) +{ + for (unsigned int i = 0; i < devices.playbackDevicesCount; i++) + { + AudioDevice device = devices.playbackDevices[i]; + RL_FREE(device.id); + RL_FREE(device.name); + } + + for (unsigned int i = 0; i < devices.captureDevicesCount; i++) + { + AudioDevice device = devices.captureDevices[i]; + RL_FREE(device.id); + RL_FREE(device.name); + } + + + RL_FREE(devices.playbackDevices); + RL_FREE(devices.captureDevices); +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Audio Buffer management //---------------------------------------------------------------------------------- diff --git a/src/raylib.h b/src/raylib.h index 33187a4be..a218bf206 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -474,6 +474,26 @@ typedef struct Wave { // NOTE: Actual structs are defined internally in raudio module typedef struct rAudioBuffer rAudioBuffer; typedef struct rAudioProcessor rAudioProcessor; +typedef struct rAudioDeviceID rAudioDeviceID; + +// Audio device, playback or capture +typedef struct AudioDevice { + rAudioDeviceID *id; // Pointer interal audio device id + + char *name; // Audio device name (e.g. Ryzen HD Audio Controller) + unsigned int type; // Audio device type (see AudioDeviceType) + + bool isDefault; // If this audio device is default this should be set as true +} AudioDevice; + +// Audio device list, contains both playback and capture devices (see AudioDevice) +typedef struct AudioDeviceList { + unsigned int playbackDevicesCount; // Playback device entries count + AudioDevice *playbackDevices; // Playback device entries + + unsigned int captureDevicesCount; // Capture device entries count + AudioDevice *captureDevices; // Capture device entries +} AudioDeviceList; // AudioStream, custom audio stream typedef struct AudioStream { @@ -963,6 +983,13 @@ typedef enum { NPATCH_THREE_PATCH_HORIZONTAL // Npatch layout: 3x1 tiles } NPatchLayout; +// Audio device type +typedef enum { + AUDIODEVICE_UNKNOWN = 0, // Unknown or unspecified + AUDIODEVICE_PLAYBACK, // Playback device (e.g. speakers, headphones etc.) + AUDIODEVICE_CAPTURE // Capture device (e.g. microphones, voice changers etc.) +} AudioDeviceType; + // Callbacks to hook some internal functions // WARNING: These callbacks are intended for advanced users typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages @@ -1680,6 +1707,8 @@ RLAPI void CloseAudioDevice(void); // Close t RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully RLAPI void SetMasterVolume(float volume); // Set master volume (listener) RLAPI float GetMasterVolume(void); // Get master volume (listener) +RLAPI bool GetAudioDeviceList(AudioDeviceList *devices); // Get list of all audio devices (playback and capture) +RLAPI void UnloadAudioDeviceList(AudioDeviceList devices); // Unload audio device list // Wave/Sound loading/unloading functions RLAPI Wave LoadWave(const char *fileName); // Load wave data from file