mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 08:44:04 +02:00
Fix subtle errors with device enumeration on most backends.
This commit is contained in:
@@ -4446,34 +4446,42 @@ static mal_result mal_enumerate_devices__winmm(mal_context* pContext, mal_device
|
|||||||
if (type == mal_device_type_playback) {
|
if (type == mal_device_type_playback) {
|
||||||
UINT deviceCount = ((MAL_PFN_waveOutGetNumDevs)pContext->winmm.waveOutGetNumDevs)();
|
UINT deviceCount = ((MAL_PFN_waveOutGetNumDevs)pContext->winmm.waveOutGetNumDevs)();
|
||||||
for (UINT iDevice = 0; iDevice < deviceCount; ++iDevice) {
|
for (UINT iDevice = 0; iDevice < deviceCount; ++iDevice) {
|
||||||
if (pInfo != NULL && *pCount < infoSize) {
|
if (pInfo != NULL) {
|
||||||
mal_uint32 iInfo = *pCount;
|
if (infoSize > 0) {
|
||||||
|
WAVEOUTCAPSA caps;
|
||||||
|
MMRESULT result = ((MAL_PFN_waveOutGetDevCapsA)pContext->winmm.waveOutGetDevCapsA)(iDevice, &caps, sizeof(caps));
|
||||||
|
if (result == MMSYSERR_NOERROR) {
|
||||||
|
pInfo->id.winmm = iDevice;
|
||||||
|
mal_strncpy_s(pInfo->name, sizeof(pInfo->name), caps.szPname, (size_t)-1);
|
||||||
|
}
|
||||||
|
|
||||||
WAVEOUTCAPSA caps;
|
pInfo += 1;
|
||||||
MMRESULT result = ((MAL_PFN_waveOutGetDevCapsA)pContext->winmm.waveOutGetDevCapsA)(iDevice, &caps, sizeof(caps));
|
infoSize -= 1;
|
||||||
if (result == MMSYSERR_NOERROR) {
|
*pCount += 1;
|
||||||
pInfo[iInfo].id.winmm = iDevice;
|
|
||||||
mal_strncpy_s(pInfo[iInfo].name, sizeof(pInfo[iInfo].name), caps.szPname, (size_t)-1);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
*pCount += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pCount += 1;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UINT deviceCount = ((MAL_PFN_waveInGetNumDevs)pContext->winmm.waveInGetNumDevs)();
|
UINT deviceCount = ((MAL_PFN_waveInGetNumDevs)pContext->winmm.waveInGetNumDevs)();
|
||||||
for (UINT iDevice = 0; iDevice < deviceCount; ++iDevice) {
|
for (UINT iDevice = 0; iDevice < deviceCount; ++iDevice) {
|
||||||
if (pInfo != NULL && *pCount < infoSize) {
|
if (pInfo != NULL) {
|
||||||
mal_uint32 iInfo = *pCount;
|
if (infoSize > 0) {
|
||||||
|
WAVEINCAPSA caps;
|
||||||
|
MMRESULT result = ((MAL_PFN_waveInGetDevCapsA)pContext->winmm.waveInGetDevCapsA)(iDevice, &caps, sizeof(caps));
|
||||||
|
if (result == MMSYSERR_NOERROR) {
|
||||||
|
pInfo->id.winmm = iDevice;
|
||||||
|
mal_strncpy_s(pInfo->name, sizeof(pInfo->name), caps.szPname, (size_t)-1);
|
||||||
|
}
|
||||||
|
|
||||||
WAVEINCAPSA caps;
|
pInfo += 1;
|
||||||
MMRESULT result = ((MAL_PFN_waveInGetDevCapsA)pContext->winmm.waveInGetDevCapsA)(iDevice, &caps, sizeof(caps));
|
infoSize -= 1;
|
||||||
if (result == MMSYSERR_NOERROR) {
|
*pCount += 1;
|
||||||
pInfo[iInfo].id.winmm = iDevice;
|
|
||||||
mal_strncpy_s(pInfo[iInfo].name, sizeof(pInfo[iInfo].name), caps.szPname, (size_t)-1);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
*pCount += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pCount += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5704,7 +5712,7 @@ static mal_result mal_enumerate_devices__alsa(mal_context* pContext, mal_device_
|
|||||||
// device type and sharing mode.
|
// device type and sharing mode.
|
||||||
char* dst = hwid;
|
char* dst = hwid;
|
||||||
char* src = hwid+2;
|
char* src = hwid+2;
|
||||||
while (*dst++ = *src++);
|
while ((*dst++ = *src++));
|
||||||
} else {
|
} else {
|
||||||
// Conversion to "hw:%d,%d" failed. Just use the name as-is.
|
// Conversion to "hw:%d,%d" failed. Just use the name as-is.
|
||||||
mal_strncpy_s(hwid, sizeof(hwid), NAME, (size_t)-1);
|
mal_strncpy_s(hwid, sizeof(hwid), NAME, (size_t)-1);
|
||||||
@@ -6286,37 +6294,46 @@ static mal_result mal_enumerate_devices__oss(mal_context* pContext, mal_device_t
|
|||||||
|
|
||||||
if (includeThisDevice) {
|
if (includeThisDevice) {
|
||||||
if (ai.devnode[0] != '\0') { // <-- Can be blank, according to documentation.
|
if (ai.devnode[0] != '\0') { // <-- Can be blank, according to documentation.
|
||||||
if (pInfo != NULL && *pCount < infoSize) {
|
if (pInfo != NULL) {
|
||||||
mal_uint32 iInfo = *pCount;
|
if (infoSize > 0) {
|
||||||
mal_strncpy_s(pInfo[iInfo].id.oss, sizeof(pInfo[iInfo].id.oss), ai.devnode, (size_t)-1);
|
mal_strncpy_s(pInfo->id.oss, sizeof(pInfo->id.oss), ai.devnode, (size_t)-1);
|
||||||
|
|
||||||
// The human readable device name should be in the "ai.handle" variable, but it can
|
// The human readable device name should be in the "ai.handle" variable, but it can
|
||||||
// sometimes be empty in which case we just fall back to "ai.name" which is less user
|
// sometimes be empty in which case we just fall back to "ai.name" which is less user
|
||||||
// friendly, but usually has a value.
|
// friendly, but usually has a value.
|
||||||
if (ai.handle[0] != '\0') {
|
if (ai.handle[0] != '\0') {
|
||||||
mal_strncpy_s(pInfo[iInfo].name, sizeof(pInfo[iInfo].name), ai.handle, (size_t)-1);
|
mal_strncpy_s(pInfo->name, sizeof(pInfo->name), ai.handle, (size_t)-1);
|
||||||
} else {
|
} else {
|
||||||
mal_strncpy_s(pInfo[iInfo].name, sizeof(pInfo[iInfo].name), ai.name, (size_t)-1);
|
mal_strncpy_s(pInfo->name, sizeof(pInfo->name), ai.name, (size_t)-1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
*pCount += 1;
|
pInfo += 1;
|
||||||
|
infoSize -= 1;
|
||||||
|
*pCount += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*pCount += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Failed to retrieve the system information. Just return a default device for both playback and capture.
|
// Failed to retrieve the system information. Just return a default device for both playback and capture.
|
||||||
if (pInfo != NULL && infoSize >= 1) {
|
if (pInfo != NULL) {
|
||||||
mal_strncpy_s(pInfo[0].id.oss, sizeof(pInfo[0].id.oss), "/dev/dsp", (size_t)-1);
|
if (infoSize > 0) {
|
||||||
if (type == mal_device_type_playback) {
|
mal_strncpy_s(pInfo[0].id.oss, sizeof(pInfo[0].id.oss), "/dev/dsp", (size_t)-1);
|
||||||
mal_strncpy_s(pInfo[0].name, sizeof(pInfo[0].name), "Default Playback Device", (size_t)-1);
|
if (type == mal_device_type_playback) {
|
||||||
} else {
|
mal_strncpy_s(pInfo[0].name, sizeof(pInfo[0].name), "Default Playback Device", (size_t)-1);
|
||||||
mal_strncpy_s(pInfo[0].name, sizeof(pInfo[0].name), "Default Capture Device", (size_t)-1);
|
} else {
|
||||||
}
|
mal_strncpy_s(pInfo[0].name, sizeof(pInfo[0].name), "Default Capture Device", (size_t)-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
*pCount = 1;
|
*pCount = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*pCount = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
@@ -7533,7 +7550,7 @@ mal_result mal_context_uninit__openal(mal_context* pContext)
|
|||||||
|
|
||||||
mal_result mal_enumerate_devices__openal(mal_context* pContext, mal_device_type type, mal_uint32* pCount, mal_device_info* pInfo)
|
mal_result mal_enumerate_devices__openal(mal_context* pContext, mal_device_type type, mal_uint32* pCount, mal_device_info* pInfo)
|
||||||
{
|
{
|
||||||
mal_uint32 infoCapacity = *pCount;
|
mal_uint32 infoSize = *pCount;
|
||||||
*pCount = 0;
|
*pCount = 0;
|
||||||
|
|
||||||
const mal_ALCchar* pDeviceNames = ((MAL_LPALCGETSTRING)pContext->openal.alcGetString)(NULL, (type == mal_device_type_playback) ? MAL_ALC_DEVICE_SPECIFIER : MAL_ALC_CAPTURE_DEVICE_SPECIFIER);
|
const mal_ALCchar* pDeviceNames = ((MAL_LPALCGETSTRING)pContext->openal.alcGetString)(NULL, (type == mal_device_type_playback) ? MAL_ALC_DEVICE_SPECIFIER : MAL_ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||||
@@ -7543,15 +7560,18 @@ mal_result mal_enumerate_devices__openal(mal_context* pContext, mal_device_type
|
|||||||
|
|
||||||
// Each device is stored in pDeviceNames, separated by a null-terminator. The string itself is double-null-terminated.
|
// Each device is stored in pDeviceNames, separated by a null-terminator. The string itself is double-null-terminated.
|
||||||
const mal_ALCchar* pNextDeviceName = pDeviceNames;
|
const mal_ALCchar* pNextDeviceName = pDeviceNames;
|
||||||
for (;;) {
|
while (pNextDeviceName[0] != '\0') {
|
||||||
*pCount += 1;
|
if (pInfo != NULL) {
|
||||||
|
if (infoSize > 0) {
|
||||||
|
mal_strncpy_s(pInfo->id.openal, sizeof(pInfo->id.openal), (const char*)pNextDeviceName, (size_t)-1);
|
||||||
|
mal_strncpy_s(pInfo->name, sizeof(pInfo->name), (const char*)pNextDeviceName, (size_t)-1);
|
||||||
|
|
||||||
if (pInfo != NULL && infoCapacity > 0) {
|
pInfo += 1;
|
||||||
mal_strncpy_s(pInfo->id.openal, sizeof(pInfo->id.openal), (const char*)pNextDeviceName, (size_t)-1);
|
infoSize -= 1;
|
||||||
mal_strncpy_s(pInfo->name, sizeof(pInfo->name), (const char*)pNextDeviceName, (size_t)-1);
|
*pCount += 1;
|
||||||
|
}
|
||||||
pInfo += 1;
|
} else {
|
||||||
infoCapacity -= 1;
|
*pCount += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to the next device name.
|
// Move to the next device name.
|
||||||
@@ -7559,11 +7579,8 @@ mal_result mal_enumerate_devices__openal(mal_context* pContext, mal_device_type
|
|||||||
pNextDeviceName += 1;
|
pNextDeviceName += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've reached the double-null-terminator, we're done.
|
// Skip past the null terminator.
|
||||||
pNextDeviceName += 1;
|
pNextDeviceName += 1;
|
||||||
if (*pNextDeviceName == '\0') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return MAL_SUCCESS;
|
return MAL_SUCCESS;
|
||||||
@@ -10228,7 +10245,7 @@ void mal_pcm_f32_to_s32(int* pOut, const float* pIn, unsigned int count)
|
|||||||
// which is by design.
|
// which is by design.
|
||||||
// - ALSA: Add support for excluding the "null" device using the alsa.excludeNullDevice context config variable.
|
// - ALSA: Add support for excluding the "null" device using the alsa.excludeNullDevice context config variable.
|
||||||
// - ALSA: Fix a bug with channel mapping which causes an assertion to fail.
|
// - ALSA: Fix a bug with channel mapping which causes an assertion to fail.
|
||||||
// - WASAPI: Fix device enumeration when passing NULL to the pInfo parameter.
|
// - Fix errors with enumeration when pInfo is set to NULL.
|
||||||
//
|
//
|
||||||
// v0.4 - 2017-11-05
|
// v0.4 - 2017-11-05
|
||||||
// - API CHANGE: The log callback is now per-context rather than per-device and as is thus now passed to
|
// - API CHANGE: The log callback is now per-context rather than per-device and as is thus now passed to
|
||||||
|
|||||||
Reference in New Issue
Block a user