From 960d776dfcd5d2f071107be1ff08b1a16d275a3f Mon Sep 17 00:00:00 2001 From: neonloop Date: Sun, 18 Apr 2021 18:52:49 +0000 Subject: USB headphone detection This checks for USB hotplugging every 60 times audio is written. This can be adjusted to favor performance vs reacting to hotplugs more quickly. There are some errors that appear when unplugging the headset because it tries to write audio to a device that has disappeared. --- frontend/audio_hotplug.h | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ frontend/plat_trimui.c | 9 +++++++++ 2 files changed, 58 insertions(+) create mode 100644 frontend/audio_hotplug.h diff --git a/frontend/audio_hotplug.h b/frontend/audio_hotplug.h new file mode 100644 index 0000000..db4eb59 --- /dev/null +++ b/frontend/audio_hotplug.h @@ -0,0 +1,49 @@ +#ifndef CHECK_AUDIO_H +#define CHECK_AUDIO_H + +#include +#include +#include + +/* Only check once every 60 calls, so this can be called every frame + * without much penalty */ +#define AUDIO_CHECK_THROTTLE 60 + +bool found_usb_audio = false; +bool has_usb_audio = false; + +/* Every AUDIO_CHECK_THROTTLE calls, check to see if the USB audio + * device has been plugged or unplugged. When the status changes, + * calls `reinit_callback` with the new status. */ +void audio_hotplug_check(void (*reinit_callback)(bool has_usb_audio)) { + static int count; + + if (++count < AUDIO_CHECK_THROTTLE) return; + + count = 0; + + if (access("/dev/dsp1", R_OK | W_OK) == 0) { + found_usb_audio = true; + } else { + found_usb_audio = false; + } + + if (!has_usb_audio && found_usb_audio) { + has_usb_audio = true; + reinit_callback(true); + } else if (has_usb_audio && !found_usb_audio) { + has_usb_audio = false; + reinit_callback(false); + } +} + +/* For SDL apps, set audio to the correct device. */ +void audio_hotplug_set_device(bool has_usb_audio) { + if (has_usb_audio) { + SDL_putenv("AUDIODEV=/dev/dsp1"); + } else { + SDL_putenv("AUDIODEV=/dev/dsp"); + } +} + +#endif diff --git a/frontend/plat_trimui.c b/frontend/plat_trimui.c index bdd5a92..2925f5f 100644 --- a/frontend/plat_trimui.c +++ b/frontend/plat_trimui.c @@ -1,6 +1,7 @@ #include #include "common.h" +#include "frontend/audio_hotplug.h" #include "frontend/main.h" #include "frontend/plat.h" #include "frontend/scale.h" @@ -185,6 +186,7 @@ int plat_sound_init(void) if (SDL_OpenAudio(&spec, NULL) < 0) { plat_sound_finish(); + fprintf(stderr, "SDL audio failed to open: %s\n", SDL_GetError()); return -1; } @@ -192,6 +194,12 @@ int plat_sound_init(void) return 0; } +static void plat_sound_reinit(bool has_usb_audio) { + plat_sound_finish(); + audio_hotplug_set_device(has_usb_audio); + plat_sound_init(); +} + float plat_sound_capacity(void) { int buffered = 0; @@ -205,6 +213,7 @@ float plat_sound_capacity(void) void plat_sound_write(void *data, int bytes) { short *sound_data = (short *)data; + audio_hotplug_check(plat_sound_reinit); SDL_LockAudio(); while (bytes > 0) { -- cgit v1.2.3