[alsa-devel] [PATCH 3/3] pulse: Add fallback option

Takashi Iwai tiwai at suse.de
Tue Jul 26 14:36:11 CEST 2011


[Patch to alsa-plugins]

Added "fallback" option to give the PCM / controller name as a fallback
when connecting to PA server fails.

Signed-off-by: Takashi Iwai <tiwai at suse.de>
---
 doc/README-pulse  |   19 +++++++++++++++++++
 pulse/ctl_pulse.c |   17 ++++++++++++++++-
 pulse/pcm_pulse.c |   17 ++++++++++++++++-
 pulse/pulse.c     |    7 ++++---
 pulse/pulse.h     |    2 +-
 5 files changed, 56 insertions(+), 6 deletions(-)

diff --git a/doc/README-pulse b/doc/README-pulse
index d5431b4..5b119f9 100644
--- a/doc/README-pulse
+++ b/doc/README-pulse
@@ -39,3 +39,22 @@ you need to do this with PCM:s then specify two PCM:s with different "device".
 
 If you do not specify any source and/or sink, then the server's defaults will
 be used.
+
+When "fallback" option is set, the plugin will try to open the given PCM
+(or control) automatically when connecting to PA server fails.  Typically,
+it should point to "sysdefault", which was introduced recently in alsa-lib,
+so that the system-default setup is used even when you overwrite "default"
+PCM and control definitions.
+
+    pcm.pulse {
+        type pulse
+        fallback "sysdefault"
+    }
+
+    ctl.pulse {
+        type pulse
+        fallback "sysdefault"
+    }
+
+   pcm.!default "pulse"
+   ctl.!default "pulse"
diff --git a/pulse/ctl_pulse.c b/pulse/ctl_pulse.c
index 85863ed..8b5ff9e 100644
--- a/pulse/ctl_pulse.c
+++ b/pulse/ctl_pulse.c
@@ -647,6 +647,7 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse)
 	const char *device = NULL;
 	const char *source = NULL;
 	const char *sink = NULL;
+	const char *fallback_name = NULL;
 	int err;
 	snd_ctl_pulse_t *ctl;
 	pa_operation *o;
@@ -687,10 +688,20 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse)
 			}
 			continue;
 		}
+		if (strcmp(id, "fallback") == 0) {
+			if (snd_config_get_string(n, &fallback_name) < 0) {
+				SNDERR("Invalid value for %s", id);
+				return -EINVAL;
+			}
+			continue;
+		}
 		SNDERR("Unknown field %s", id);
 		return -EINVAL;
 	}
 
+	if (fallback_name && name && !strcmp(name, fallback_name))
+		fallback_name = NULL; /* no fallback for the same name */
+
 	ctl = calloc(1, sizeof(*ctl));
 	if (!ctl)
 		return -ENOMEM;
@@ -701,7 +712,7 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pulse)
 		goto error;
 	}
 
-	err = pulse_connect(ctl->p, server);
+	err = pulse_connect(ctl->p, server, !fallback_name);
 	if (err < 0)
 		goto error;
 
@@ -794,6 +805,10 @@ error:
 	free(ctl->sink);
 	free(ctl);
 
+	if (fallback_name)
+		return snd_ctl_open_fallback(handlep, root,
+					     fallback_name, name, mode);
+
 	return err;
 }
 
diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c
index 9105d4d..15b29e0 100644
--- a/pulse/pcm_pulse.c
+++ b/pulse/pcm_pulse.c
@@ -982,6 +982,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse)
 	snd_config_iterator_t i, next;
 	const char *server = NULL;
 	const char *device = NULL;
+	const char *fallback_name = NULL;
 	int handle_underrun = 0;
 	int err;
 	snd_pcm_pulse_t *pcm;
@@ -1016,10 +1017,20 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse)
 			handle_underrun = err;
 			continue;
 		}
+		if (strcmp(id, "fallback") == 0) {
+			if (snd_config_get_string(n, &fallback_name) < 0) {
+				SNDERR("Invalid value for %s", id);
+				return -EINVAL;
+			}
+			continue;
+		}
 		SNDERR("Unknown field %s", id);
 		return -EINVAL;
 	}
 
+	if (fallback_name && name && !strcmp(name, fallback_name))
+		fallback_name = NULL; /* no fallback for the same name */
+
 	pcm = calloc(1, sizeof(*pcm));
 	if (!pcm)
 		return -ENOMEM;
@@ -1041,7 +1052,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse)
 
 	pcm->handle_underrun = handle_underrun;
 
-	err = pulse_connect(pcm->p, server);
+	err = pulse_connect(pcm->p, server, !fallback_name);
 	if (err < 0)
 		goto error;
 
@@ -1074,6 +1085,10 @@ error:
 	free(pcm->device);
 	free(pcm);
 
+	if (fallback_name)
+		return snd_pcm_open_fallback(pcmp, root, fallback_name, name,
+					     stream, mode);
+
 	return err;
 }
 
diff --git a/pulse/pulse.c b/pulse/pulse.c
index f26363a..6d9613d 100644
--- a/pulse/pulse.c
+++ b/pulse/pulse.c
@@ -188,7 +188,7 @@ void pulse_free(snd_pulse_t * p)
 	free(p);
 }
 
-int pulse_connect(snd_pulse_t * p, const char *server)
+int pulse_connect(snd_pulse_t * p, const char *server, int show_error)
 {
 	int err;
 	pa_context_state_t state;
@@ -225,8 +225,9 @@ int pulse_connect(snd_pulse_t * p, const char *server)
 	return 0;
 
       error:
-	SNDERR("PulseAudio: Unable to connect: %s\n",
-		pa_strerror(pa_context_errno(p->context)));
+	if (show_error)
+		SNDERR("PulseAudio: Unable to connect: %s\n",
+		       pa_strerror(pa_context_errno(p->context)));
 
 	pa_threaded_mainloop_unlock(p->mainloop);
 
diff --git a/pulse/pulse.h b/pulse/pulse.h
index e98124f..9f32a7f 100644
--- a/pulse/pulse.h
+++ b/pulse/pulse.h
@@ -42,7 +42,7 @@ int pulse_wait_operation(snd_pulse_t * p, pa_operation * o);
 snd_pulse_t *pulse_new(void);
 void pulse_free(snd_pulse_t * p);
 
-int pulse_connect(snd_pulse_t * p, const char *server);
+int pulse_connect(snd_pulse_t * p, const char *server, int show_error);
 
 void pulse_poll_activate(snd_pulse_t * p);
 void pulse_poll_deactivate(snd_pulse_t * p);
-- 
1.7.6



More information about the Alsa-devel mailing list