[pulseaudio-discuss] [PATCH 18/30] skoa-router: Rescue streams on port changes
Tanu Kaskinen
tanu.kaskinen at linux.intel.com
Thu Jan 16 07:02:44 PST 2014
In the future, when port changes on a device, streams connected to
that device will be killed, unless a router module rescues the streams
first. This patch implements that rescue logic in module-skoa-router.
---
src/modules/module-skoa-router.c | 59 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/src/modules/module-skoa-router.c b/src/modules/module-skoa-router.c
index d532e54..23796cf 100644
--- a/src/modules/module-skoa-router.c
+++ b/src/modules/module-skoa-router.c
@@ -35,6 +35,7 @@ PA_MODULE_LOAD_ONCE(true);
struct userdata {
pa_hook_slot *card_set_profile_slot;
+ pa_hook_slot *device_set_port_slot;
};
static pa_hook_result_t card_set_profile_cb(void *hook_data, void *call_data, void *userdata) {
@@ -140,6 +141,59 @@ static pa_hook_result_t card_set_profile_cb(void *hook_data, void *call_data, vo
return PA_HOOK_OK;
}
+static pa_hook_result_t device_set_port_cb(void *hook_data, void *call_data, void *userdata) {
+ pa_device_set_port_hook_data *data = call_data;
+ pa_sink *sink = NULL;
+ pa_source *source = NULL;
+ const char *device_name;
+ pa_queue *streams = NULL;
+
+ pa_assert(data);
+
+ /* When the port changes, streams connected to the device are killed. Here
+ * we prevent that by detaching the streams before the port switch, and
+ * attaching them to the same device after the port switch. */
+
+ if (data->port->direction == PA_DIRECTION_OUTPUT) {
+ sink = data->port->device;
+ device_name = sink->name;
+ streams = pa_sink_move_all_start(sink, streams);
+ } else {
+ source = data->port->device;
+ device_name = source->name;
+ streams = pa_source_move_all_start(source, streams);
+ }
+
+ if (!pa_queue_isempty(streams))
+ pa_log_debug("Started to move streams away from device %s.", device_name);
+
+ if (sink)
+ data->ret = pa_sink_set_port(sink, data->port, data->save, true);
+ else
+ data->ret = pa_source_set_port(source, data->port, data->save, true);
+
+ data->ret_valid = true;
+
+ if (data->ret >= 0) {
+ if (sink)
+ pa_sink_move_all_finish(sink, streams, false);
+ else
+ pa_source_move_all_finish(source, streams, false);
+
+ pa_log_debug("Finished moving streams to device %s.", device_name);
+ } else {
+ if (!pa_queue_isempty(streams))
+ pa_log("Port change failed, have to fail the stream rescue operation.");
+
+ if (sink)
+ pa_sink_move_all_fail(streams);
+ else
+ pa_source_move_all_fail(streams);
+ }
+
+ return PA_HOOK_OK;
+}
+
int pa__init(pa_module *module) {
struct userdata *u;
@@ -148,6 +202,8 @@ int pa__init(pa_module *module) {
module->userdata = u = pa_xnew0(struct userdata, 1);
u->card_set_profile_slot = pa_hook_connect(&module->core->hooks[PA_CORE_HOOK_CARD_SET_PROFILE], PA_HOOK_NORMAL,
card_set_profile_cb, NULL);
+ u->device_set_port_slot = pa_hook_connect(&module->core->hooks[PA_CORE_HOOK_DEVICE_SET_PORT], PA_HOOK_NORMAL,
+ device_set_port_cb, NULL);
return 0;
}
@@ -160,6 +216,9 @@ void pa__done(pa_module *module) {
if (!(u = module->userdata))
return;
+ if (u->device_set_port_slot)
+ pa_hook_slot_free(u->device_set_port_slot);
+
if (u->card_set_profile_slot)
pa_hook_slot_free(u->card_set_profile_slot);
--
1.8.3.1
More information about the pulseaudio-discuss
mailing list