summaryrefslogtreecommitdiff
path: root/frontend
diff options
context:
space:
mode:
authorneonloop2021-04-18 18:52:49 +0000
committerneonloop2021-04-18 18:52:49 +0000
commit960d776dfcd5d2f071107be1ff08b1a16d275a3f (patch)
tree502aa07b52717efb422de8b147c9e3114041e8cc /frontend
parent6dcf2d4e43b8951183025dc0b2f12b1568e62d62 (diff)
downloadpicogpsp-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.h49
-rw-r--r--frontend/plat_trimui.c9
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) {