SDL: pulseaudio: Optionally add "monitor" sources to device list.

From 736a424ff470334a5657d44054c03717b0116dec Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Tue, 27 Jul 2021 13:12:57 -0400
Subject: [PATCH] pulseaudio: Optionally add "monitor" sources to device list.

There's a new hint to enable this.

Fixes #2917.
---
 include/SDL_hints.h                   | 19 +++++++++++++++++++
 src/audio/pulseaudio/SDL_pulseaudio.c | 10 ++++++++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 549ed66261..ba043acf23 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -1675,6 +1675,25 @@ extern "C" {
  */
 #define SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING "SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING"
 
+/**
+ *  \brief  A variable that causes SDL to not ignore audio "monitors"
+ *
+ *  This is currently only used for PulseAudio and ignored elsewhere.
+ *
+ *  By default, SDL ignores audio devices that aren't associated with physical
+ *  hardware. Changing this hint to "1" will expose anything SDL sees that
+ *  appears to be an audio source or sink. This will add "devices" to the list
+ *  that the user probably doesn't want or need, but it can be useful in
+ *  scenarios where you want to hook up SDL to some sort of virtual device,
+ *  etc.
+ *
+ *  The default value is "0".  This hint must be set before SDL_Init().
+ *
+ *  This hint is available since SDL 2.0.16. Before then, virtual devices are
+ *  always ignored.
+ */
+#define SDL_HINT_AUDIO_INCLUDE_MONITORS "SDL_AUDIO_INCLUDE_MONITORS"
+
 
 /**
  *  \brief  An enumeration of hint priorities
diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c
index bb5997ed16..c97f15681c 100644
--- a/src/audio/pulseaudio/SDL_pulseaudio.c
+++ b/src/audio/pulseaudio/SDL_pulseaudio.c
@@ -46,6 +46,10 @@
 #include "SDL_loadso.h"
 #include "../../thread/SDL_systhread.h"
 
+/* should we include monitors in the device list? Set at SDL_Init time */
+static SDL_bool include_monitors = SDL_FALSE;
+
+
 #if (PA_API_VERSION < 12)
 /** Return non-zero if the passed state is one of the connected states */
 static SDL_INLINE int PA_CONTEXT_IS_GOOD(pa_context_state_t x) {
@@ -744,8 +748,8 @@ SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *da
 {
     SDL_AudioSpec spec;
     if (i) {
-        /* Skip "monitor" sources. These are just output from other sinks. */
-        if (i->monitor_of_sink == PA_INVALID_INDEX) {
+        /* Maybe skip "monitor" sources. These are just output from other sinks. */
+        if (include_monitors || (i->monitor_of_sink == PA_INVALID_INDEX)) {
             spec.freq = i->sample_spec.rate;
             spec.channels = i->sample_spec.channels;
             spec.format = PulseFormatToSDLFormat(i->sample_spec.format);
@@ -834,6 +838,8 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
         return 0;
     }
 
+    include_monitors = SDL_GetHintBoolean(SDL_HINT_AUDIO_INCLUDE_MONITORS, SDL_FALSE);
+
     /* Set the function pointers */
     impl->DetectDevices = PULSEAUDIO_DetectDevices;
     impl->OpenDevice = PULSEAUDIO_OpenDevice;