From d168a7d192e839545aab0f066ab24c731f585eda Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 10 Nov 2015 04:22:03 -0700 Subject: [PATCH] ALSA: better device detection * Don't suppress sysdefault. * If default and sysdefault are missing, use the first device as the default device. * In sio_record example, don't segfault when device not found or probe error. * Workaround for Raspberry Pi driver that incorrectly reports itself as Output when it is actually Input. See #44. --- example/sio_record.c | 9 ++++++++ src/alsa.c | 50 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/example/sio_record.c b/example/sio_record.c index 4e6133d..29c07ef 100644 --- a/example/sio_record.c +++ b/example/sio_record.c @@ -203,10 +203,19 @@ int main(int argc, char **argv) { } else { int device_index = soundio_default_input_device_index(soundio); selected_device = soundio_get_input_device(soundio, device_index); + if (!selected_device) { + fprintf(stderr, "No input devices available.\n"); + return 1; + } } fprintf(stderr, "Device: %s\n", selected_device->name); + if (selected_device->probe_error) { + fprintf(stderr, "Unable to probe device: %s\n", soundio_strerror(selected_device->probe_error)); + return 1; + } + soundio_device_sort_channel_layouts(selected_device); int sample_rate = 0; diff --git a/src/alsa.c b/src/alsa.c index 88a199d..421b3f4 100644 --- a/src/alsa.c +++ b/src/alsa.c @@ -480,15 +480,16 @@ static int refresh_devices(struct SoundIoPrivate *si) { return SoundIoErrorNoMem; } + int default_output_index = -1; + int sysdefault_output_index = -1; + int default_input_index = -1; + int sysdefault_input_index = -1; + for (void **hint_ptr = hints; *hint_ptr; hint_ptr += 1) { char *name = snd_device_name_get_hint(*hint_ptr, "NAME"); // null - libsoundio has its own dummy backend. API clients should use // that instead of alsa null device. if (strcmp(name, "null") == 0 || - // sysdefault is confusing - the name and description is identical - // to default, and my best guess for what it does is ignore ~/.asoundrc - // which is just an accident waiting to happen. - str_has_prefix(name, "sysdefault:") || // all these surround devices are clutter str_has_prefix(name, "front:") || str_has_prefix(name, "surround21:") || @@ -508,7 +509,20 @@ static int refresh_devices(struct SoundIoPrivate *si) { char *io = snd_device_name_get_hint(*hint_ptr, "IOID"); bool is_playback; bool is_capture; - if (io) { + + // Workaround for Raspberry Pi driver bug, reporting itself as output + // when really it is input. + if (descr && strcmp(descr, "bcm2835 ALSA, bcm2835 ALSA") == 0 && + descr1 && strcmp(descr1, "Direct sample snooping device") == 0) + { + is_playback = false; + is_capture = true; + } else if (descr && strcmp(descr, "bcm2835 ALSA, bcm2835 IEC958/HDMI") == 0 && + descr1 && strcmp(descr1, "Direct sample snooping device") == 0) + { + is_playback = false; + is_capture = true; + } else if (io) { if (strcmp(io, "Input") == 0) { is_playback = false; is_capture = true; @@ -561,16 +575,26 @@ static int refresh_devices(struct SoundIoPrivate *si) { struct SoundIoListDevicePtr *device_list; bool is_default = str_has_prefix(name, "default:") || strcmp(name, "default") == 0; + bool is_sysdefault = str_has_prefix(name, "sysdefault:") || strcmp(name, "sysdefault") == 0; + if (stream == SND_PCM_STREAM_PLAYBACK) { device->aim = SoundIoDeviceAimOutput; device_list = &devices_info->output_devices; - if (devices_info->default_output_index < 0 && is_default) + if (is_default) + default_output_index = device_list->length; + if (is_sysdefault) + sysdefault_output_index = device_list->length; + if (devices_info->default_output_index == -1) devices_info->default_output_index = device_list->length; } else { assert(stream == SND_PCM_STREAM_CAPTURE); device->aim = SoundIoDeviceAimInput; device_list = &devices_info->input_devices; - if (devices_info->default_input_index < 0 && is_default) + if (is_default) + default_input_index = device_list->length; + if (is_sysdefault) + sysdefault_input_index = device_list->length; + if (devices_info->default_input_index == -1) devices_info->default_input_index = device_list->length; } @@ -590,6 +614,18 @@ static int refresh_devices(struct SoundIoPrivate *si) { free(descr); } + if (default_input_index >= 0) { + devices_info->default_input_index = default_input_index; + } else if (sysdefault_input_index >= 0) { + devices_info->default_input_index = sysdefault_input_index; + } + + if (default_output_index >= 0) { + devices_info->default_output_index = default_output_index; + } else if (sysdefault_output_index >= 0) { + devices_info->default_output_index = sysdefault_output_index; + } + snd_device_name_free_hint(hints); int card_index = -1;