mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
ALSA: Have the id of enumerated devices be returned in "hw:%d,%d" format.
The rationale for this change is that during testing I noticed that snd_pcm_open() would sometimes fail with "Invalid value for card" when using the "NAME" hint returned by snd_device_name_get_hint() verbatim. Using "hw:%d,%d" seems to fix this problem.
This commit is contained in:
@@ -485,7 +485,7 @@ mal_uint32 mal_get_sample_size_in_bytes(mal_format format);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MAL_ENABLE_ALSA
|
#ifdef MAL_ENABLE_ALSA
|
||||||
#include <stdio.h> // Needed for printf() which is used for "hw:%d,%d" formatting. TODO: Remove this later.
|
#include <stdio.h> // Needed for sprintf() which is used for "hw:%d,%d" formatting. TODO: Remove this later.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(MAL_64BIT) && !defined(MAL_32BIT)
|
#if !defined(MAL_64BIT) && !defined(MAL_32BIT)
|
||||||
@@ -2121,6 +2121,12 @@ static mal_result mal_enumerate_devices__alsa(mal_device_type type, mal_uint32*
|
|||||||
//
|
//
|
||||||
// An alternative enumeration technique is to use snd_card_next() and family. The problem with this
|
// An alternative enumeration technique is to use snd_card_next() and family. The problem with this
|
||||||
// one, which is significant, is that it does _not_ include user-space devices.
|
// one, which is significant, is that it does _not_ include user-space devices.
|
||||||
|
//
|
||||||
|
// ---
|
||||||
|
//
|
||||||
|
// During my testing I have discovered that snd_pcm_open() can fail on names returned by the "NAME"
|
||||||
|
// hint returned by snd_device_name_get_hint(). To resolve this I have needed to parse the NAME
|
||||||
|
// string and convert it to "hw:%d,%d" format.
|
||||||
|
|
||||||
char** ppDeviceHints;
|
char** ppDeviceHints;
|
||||||
if (snd_device_name_hint(-1, "pcm", (void***)&ppDeviceHints) < 0) {
|
if (snd_device_name_hint(-1, "pcm", (void***)&ppDeviceHints) < 0) {
|
||||||
@@ -2149,10 +2155,55 @@ static mal_result mal_enumerate_devices__alsa(mal_device_type type, mal_uint32*
|
|||||||
// NAME is the ID.
|
// NAME is the ID.
|
||||||
mal_strncpy_s(pInfo->id.str, sizeof(pInfo->id.str), NAME ? NAME : "", (size_t)-1);
|
mal_strncpy_s(pInfo->id.str, sizeof(pInfo->id.str), NAME ? NAME : "", (size_t)-1);
|
||||||
|
|
||||||
|
// NAME -> "hw:%d,%d"
|
||||||
|
if (colonPos != -1 && NAME != NULL) {
|
||||||
|
// We need to convert the NAME string to "hw:%d,%d" format.
|
||||||
|
char* cardStr = NAME + 3;
|
||||||
|
for (;;) {
|
||||||
|
if (cardStr[0] == '\0') {
|
||||||
|
cardStr = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cardStr[0] == 'C' && cardStr[1] == 'A' && cardStr[2] == 'R' && cardStr[3] == 'D' && cardStr[4] == '=') {
|
||||||
|
cardStr = cardStr + 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cardStr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cardStr != NULL) {
|
||||||
|
char* deviceStr = cardStr + 1;
|
||||||
|
for (;;) {
|
||||||
|
if (deviceStr[0] == '\0') {
|
||||||
|
deviceStr = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (deviceStr[0] == ',') {
|
||||||
|
deviceStr[0] = '\0'; // This is the comma after the "CARD=###" part.
|
||||||
|
} else {
|
||||||
|
if (deviceStr[0] == 'D' && deviceStr[1] == 'E' && deviceStr[2] == 'V' && deviceStr[3] == '=') {
|
||||||
|
deviceStr = deviceStr + 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceStr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceStr != NULL) {
|
||||||
|
int cardIndex = snd_card_get_index(cardStr);
|
||||||
|
if (cardIndex >= 0) {
|
||||||
|
sprintf(pInfo->id.str, "hw:%d,%s", cardIndex, deviceStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// DESC is the name, followed by the description on a new line.
|
// DESC is the name, followed by the description on a new line.
|
||||||
int lfPos = 0;
|
int lfPos = 0;
|
||||||
mal_find_char(DESC, '\n', &lfPos);
|
mal_find_char(DESC, '\n', &lfPos);
|
||||||
|
|
||||||
mal_strncpy_s(pInfo->name, sizeof(pInfo->name), DESC ? DESC : "", (lfPos != -1) ? (size_t)lfPos : (size_t)-1);
|
mal_strncpy_s(pInfo->name, sizeof(pInfo->name), DESC ? DESC : "", (lfPos != -1) ? (size_t)lfPos : (size_t)-1);
|
||||||
|
|
||||||
pInfo += 1;
|
pInfo += 1;
|
||||||
@@ -2225,7 +2276,7 @@ static mal_result mal_device_init__alsa(mal_device* pDevice, mal_device_type typ
|
|||||||
if (snd_pcm_open((snd_pcm_t**)&pDevice->alsa.pPCM, deviceName, (type == mal_device_type_playback) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, 0) < 0) {
|
if (snd_pcm_open((snd_pcm_t**)&pDevice->alsa.pPCM, deviceName, (type == mal_device_type_playback) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, 0) < 0) {
|
||||||
if (mal_strcmp(deviceName, "default") == 0 || mal_strcmp(deviceName, "pulse") == 0) {
|
if (mal_strcmp(deviceName, "default") == 0 || mal_strcmp(deviceName, "pulse") == 0) {
|
||||||
// We may have failed to open the "default" or "pulse" device, in which case try falling back to "plughw:0,0".
|
// We may have failed to open the "default" or "pulse" device, in which case try falling back to "plughw:0,0".
|
||||||
mal_strncpy_s(deviceName, "plughw:0,0");
|
mal_strncpy_s(deviceName, sizeof(deviceName), "plughw:0,0", (size_t)-1);
|
||||||
if (snd_pcm_open((snd_pcm_t**)&pDevice->alsa.pPCM, deviceName, (type == mal_device_type_playback) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, 0) < 0) {
|
if (snd_pcm_open((snd_pcm_t**)&pDevice->alsa.pPCM, deviceName, (type == mal_device_type_playback) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, 0) < 0) {
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] snd_pcm_open() failed.", MAL_ALSA_FAILED_TO_OPEN_DEVICE);
|
return mal_post_error(pDevice, "[ALSA] snd_pcm_open() failed.", MAL_ALSA_FAILED_TO_OPEN_DEVICE);
|
||||||
|
|||||||
Reference in New Issue
Block a user