Commit 8601996fbc50a58211190eea7432ef6474ba4476

Ryan C. Gordon 2020-05-03T22:13:48

hints: Allow specifying audio device metadata. This is only supported on PulseAudio. You can set a description when opening your audio device that will show up in pauvcontrol, which lets you set per-stream volume levels. Fixes Bugzilla #4801.

diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 67f776a..28cf544 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -1307,6 +1307,48 @@ extern "C" {
 #define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS"
 
 /**
+ *  \brief Specify an application name for an audio device.
+ *
+ * Some audio backends (such as PulseAudio) allow you to describe your audio
+ * stream. Among other things, this description might show up in a system
+ * control panel that lets the user adjust the volume on specific audio
+ * streams instead of using one giant master volume slider.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your program ("My Game 2: The Revenge")
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: probably the application's name or "SDL Application" if SDL
+ * doesn't have any better information.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_APP_NAME "SDL_AUDIO_DEVICE_APP_NAME"
+
+/**
+ *  \brief Specify an application name for an audio device.
+ *
+ * Some audio backends (such as PulseAudio) allow you to describe your audio
+ * stream. Among other things, this description might show up in a system
+ * control panel that lets the user adjust the volume on specific audio
+ * streams instead of using one giant master volume slider.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your what your program is playing ("audio stream" is
+ * probably sufficient in many cases, but this could be useful for something
+ * like "team chat" if you have a headset playing VoIP audio separately).
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: "audio stream" or something similar.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_STREAM_NAME "SDL_AUDIO_DEVICE_STREAM_NAME"
+
+
+/**
  *  \brief  An enumeration of hint priorities
  */
 typedef enum
diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c
index a279da5..829acc3 100644
--- a/src/audio/pulseaudio/SDL_pulseaudio.c
+++ b/src/audio/pulseaudio/SDL_pulseaudio.c
@@ -27,6 +27,7 @@
 */
 #include "../../SDL_internal.h"
 #include "SDL_assert.h"
+#include "SDL_hints.h"
 
 #if SDL_AUDIO_DRIVER_PULSEAUDIO
 
@@ -237,16 +238,20 @@ squashVersion(const int major, const int minor, const int patch)
 static const char *
 getAppName(void)
 {
-    const char *verstr = PULSEAUDIO_pa_get_library_version();
-    if (verstr != NULL) {
-        int maj, min, patch;
-        if (SDL_sscanf(verstr, "%d.%d.%d", &maj, &min, &patch) == 3) {
-            if (squashVersion(maj, min, patch) >= squashVersion(0, 9, 15)) {
-                return NULL;  /* 0.9.15+ handles NULL correctly. */
+    const char *retval = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME);
+    if (!retval || !*retval) {
+        const char *verstr = PULSEAUDIO_pa_get_library_version();
+        retval = "SDL Application";  /* the "oh well" default. */
+        if (verstr != NULL) {
+            int maj, min, patch;
+            if (SDL_sscanf(verstr, "%d.%d.%d", &maj, &min, &patch) == 3) {
+                if (squashVersion(maj, min, patch) >= squashVersion(0, 9, 15)) {
+                    retval = NULL;  /* 0.9.15+ handles NULL correctly. */
+                }
             }
         }
     }
-    return "SDL Application";  /* oh well. */
+    return retval;
 }
 
 static void
@@ -513,6 +518,7 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     pa_buffer_attr paattr;
     pa_channel_map pacmap;
     pa_stream_flags_t flags = 0;
+    const char *name = NULL;
     int state = 0;
     int rc = 0;
 
@@ -615,9 +621,11 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     PULSEAUDIO_pa_channel_map_init_auto(&pacmap, this->spec.channels,
                                         PA_CHANNEL_MAP_WAVEEX);
 
+    name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
+
     h->stream = PULSEAUDIO_pa_stream_new(
         h->context,
-        "Simple DirectMedia Layer", /* stream description */
+        (name && *name) ? name : "Audio Stream", /* stream description */
         &paspec,    /* sample format spec */
         &pacmap     /* channel map */
         );