[pulseaudio-discuss] [PATCH 10/11] skoa-router: Implement a stream rescue policy for profile switch situations
Tanu Kaskinen
tanu.kaskinen at linux.intel.com
Sat Nov 23 21:58:07 PST 2013
The implemented logic is copied from module-alsa-card. Now the same
logic works across all card implementations, not just ALSA.
The policy in short: the goal is to keep streams connected to the same
card before and after a profile switch.
---
src/modules/module-skoa-router.c | 84 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/src/modules/module-skoa-router.c b/src/modules/module-skoa-router.c
index 9406fef..32dafda 100644
--- a/src/modules/module-skoa-router.c
+++ b/src/modules/module-skoa-router.c
@@ -25,6 +25,7 @@
#include "module-skoa-router-symdef.h"
+#include <pulsecore/device-prototype.h>
#include <pulsecore/i18n.h>
#include <pulsecore/module.h>
#include <pulsecore/router.h>
@@ -38,6 +39,87 @@ struct userdata {
pa_router *router;
};
+static int router_set_card_profile_cb(pa_router *router, pa_card *card, pa_card_profile *profile, bool save) {
+ pa_device_prototype *prototype;
+ void *state;
+ pa_queue *sink_inputs = NULL;
+ pa_queue *source_outputs = NULL;
+ int r;
+
+ pa_assert(router);
+ pa_assert(card);
+ pa_assert(profile);
+
+ /* When the profile changes, the sinks and sources of the old profile are
+ * removed (at least if they aren't part of the new profile too), and this
+ * raises the question what happens to streams that are connected to the
+ * removed devices. Here we implement a policy to move those streams to the
+ * devices of the new profile if possible. It's unclear whether this is
+ * actually a good policy, but that's what we have historically been doing
+ * (previously in the ALSA card code), and nothing better has been
+ * proposed. */
+
+ PA_HASHMAP_FOREACH(prototype, card->active_profile->device_prototypes, state) {
+ if (!card->recreate_devices_on_profile_switch && pa_hashmap_get(profile->device_prototypes, prototype))
+ /* This device is a part of both the old and new profile, so
+ * there's no need to rescue any streams from this device. */
+ continue;
+
+ if (prototype->sink) {
+ sink_inputs = pa_sink_move_all_start(prototype->sink, sink_inputs);
+
+ if (!pa_queue_isempty(sink_inputs))
+ pa_log_debug("Started to move sink inputs away from sink %s.", prototype->sink->name);
+ }
+
+ if (prototype->source) {
+ source_outputs = pa_source_move_all_start(prototype->source, source_outputs);
+
+ if (!pa_queue_isempty(source_outputs))
+ pa_log_debug("Started to move source outputs away from source %s.", prototype->source->name);
+ }
+ }
+
+ r = pa_card_set_profile(card, profile, save, true);
+
+ if (r >= 0 && (sink_inputs || source_outputs)) {
+ PA_HASHMAP_FOREACH(prototype, profile->device_prototypes, state) {
+ if (prototype->sink && sink_inputs && !pa_queue_isempty(sink_inputs)) {
+ pa_sink_move_all_finish(prototype->sink, sink_inputs, false);
+ pa_log_debug("Finished moving sink inputs to sink %s.", prototype->sink->name);
+ sink_inputs = NULL;
+ }
+
+ if (prototype->source && source_outputs && !pa_queue_isempty(source_outputs)) {
+ pa_source_move_all_finish(prototype->source, source_outputs, false);
+ pa_log_debug("Finished moving source outputs to source %s.", prototype->source->name);
+ source_outputs = NULL;
+ }
+
+ if (!sink_inputs && !source_outputs)
+ break;
+ }
+ }
+
+ if (sink_inputs) {
+ if (!pa_queue_isempty(sink_inputs))
+ pa_log_debug("Profile change failed or there are no sinks in the new profile, "
+ "have to fail the sink input rescue operation.");
+
+ pa_sink_move_all_fail(sink_inputs);
+ }
+
+ if (source_outputs) {
+ if (!pa_queue_isempty(source_outputs))
+ pa_log_debug("Profile change failed or there are no sources in the new profile, "
+ "have to fail the source output rescue operation.");
+
+ pa_source_move_all_fail(source_outputs);
+ }
+
+ return r;
+}
+
int pa__init(pa_module *module) {
struct userdata *u;
int r;
@@ -50,6 +132,8 @@ int pa__init(pa_module *module) {
if (!u->router)
goto fail;
+ u->router->set_card_profile = router_set_card_profile_cb;
+
r = pa_router_put(u->router);
if (r < 0)
--
1.8.3.1
More information about the pulseaudio-discuss
mailing list