diff options
author | neonloop | 2021-04-18 18:52:49 +0000 |
---|---|---|
committer | neonloop | 2021-04-18 18:52:49 +0000 |
commit | 960d776dfcd5d2f071107be1ff08b1a16d275a3f (patch) | |
tree | 502aa07b52717efb422de8b147c9e3114041e8cc /frontend | |
parent | 6dcf2d4e43b8951183025dc0b2f12b1568e62d62 (diff) | |
download | picogpsp-960d776dfcd5d2f071107be1ff08b1a16d275a3f.tar.gz picogpsp-960d776dfcd5d2f071107be1ff08b1a16d275a3f.tar.bz2 picogpsp-960d776dfcd5d2f071107be1ff08b1a16d275a3f.zip |
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.
Diffstat (limited to 'frontend')
-rw-r--r-- | frontend/audio_hotplug.h | 49 | ||||
-rw-r--r-- | frontend/plat_trimui.c | 9 |
2 files changed, 58 insertions, 0 deletions
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 <stdio.h> +#include <stdbool.h> +#include <unistd.h> + +/* 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 <SDL/SDL.h> #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) { |