[pulseaudio-discuss] [PATCH v4 1/2] loopback: Enable routing on loopback streams
Frédéric Dalleau
frederic.dalleau at linux.intel.com
Wed Jun 20 08:33:35 PDT 2012
At module-loopback load, if no sink is given, the default sink is used. If the
stream has a media.role property, the property cannot be used because a the
source or sink is forced to default. Both module-intended-roles and
module-device-manager are affected. The same apply to sources.
With this patch, if sink or source is missing, routing modules can be used.
---
src/modules/module-loopback.c | 78 +++++++++++++++++++++++++++--------------
1 file changed, 52 insertions(+), 26 deletions(-)
diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index 1a69445..f3a65c2 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -647,10 +647,10 @@ static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
int pa__init(pa_module *m) {
pa_modargs *ma = NULL;
struct userdata *u;
- pa_sink *sink;
+ pa_sink *sink = NULL;
pa_sink_input_new_data sink_input_data;
pa_bool_t sink_dont_move;
- pa_source *source;
+ pa_source *source = NULL;
pa_source_output_new_data source_output_data;
pa_bool_t source_dont_move;
uint32_t latency_msec;
@@ -668,12 +668,14 @@ int pa__init(pa_module *m) {
goto fail;
}
- if (!(source = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source", NULL), PA_NAMEREG_SOURCE))) {
+ n = pa_modargs_get_value(ma, "source", NULL);
+ if (n && !(source = pa_namereg_get(m->core, n, PA_NAMEREG_SOURCE))) {
pa_log("No such source.");
goto fail;
}
- if (!(sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink", NULL), PA_NAMEREG_SINK))) {
+ n = pa_modargs_get_value(ma, "sink", NULL);
+ if (n && !(sink = pa_namereg_get(m->core, n, PA_NAMEREG_SINK))) {
pa_log("No such sink.");
goto fail;
}
@@ -683,8 +685,21 @@ int pa__init(pa_module *m) {
goto fail;
}
- ss = sink->sample_spec;
- map = sink->channel_map;
+ if (sink) {
+ ss = sink->sample_spec;
+ map = sink->channel_map;
+ } else if (source) {
+ ss = source->sample_spec;
+ map = source->channel_map;
+ } else {
+ /* Dummy sample format */
+ ss.format = PA_SAMPLE_U8;
+ ss.rate = 8000;
+ ss.channels = 1;
+ map.channels = 1;
+ map.map[0] = PA_CHANNEL_POSITION_MONO;
+ }
+
if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
pa_log("Invalid sample format specification or channel map");
goto fail;
@@ -715,7 +730,9 @@ int pa__init(pa_module *m) {
pa_sink_input_new_data_init(&sink_input_data);
sink_input_data.driver = __FILE__;
sink_input_data.module = m;
- pa_sink_input_new_data_set_sink(&sink_input_data, sink, FALSE);
+
+ if (sink)
+ pa_sink_input_new_data_set_sink(&sink_input_data, sink, FALSE);
if (pa_modargs_get_proplist(ma, "sink_input_properties", sink_input_data.proplist, PA_UPDATE_REPLACE) < 0) {
pa_log("Failed to parse the sink_input_properties value.");
@@ -723,20 +740,16 @@ int pa__init(pa_module *m) {
goto fail;
}
- if (!pa_proplist_contains(sink_input_data.proplist, PA_PROP_MEDIA_NAME))
- pa_proplist_setf(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Loopback from %s",
- pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)));
-
if (!pa_proplist_contains(sink_input_data.proplist, PA_PROP_MEDIA_ROLE))
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
- if (!pa_proplist_contains(sink_input_data.proplist, PA_PROP_MEDIA_ICON_NAME)
- && (n = pa_proplist_gets(source->proplist, PA_PROP_DEVICE_ICON_NAME)))
- pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ICON_NAME, n);
-
pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
- sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE | (remix ? 0 : PA_SINK_INPUT_NO_REMIX);
+ if (sink || source) {
+ sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE | (remix ? 0 : PA_SINK_INPUT_NO_REMIX);
+ } else {
+ sink_input_data.flags = PA_SINK_INPUT_FIX_FORMAT | PA_SINK_INPUT_FIX_RATE | PA_SINK_INPUT_FIX_CHANNELS;
+ }
sink_dont_move = FALSE;
if (pa_modargs_get_value_boolean(ma, "sink_dont_move", &sink_dont_move) < 0) {
@@ -770,7 +783,8 @@ int pa__init(pa_module *m) {
pa_source_output_new_data_init(&source_output_data);
source_output_data.driver = __FILE__;
source_output_data.module = m;
- pa_source_output_new_data_set_source(&source_output_data, source, FALSE);
+ if (source)
+ pa_source_output_new_data_set_source(&source_output_data, source, FALSE);
if (pa_modargs_get_proplist(ma, "source_output_properties", source_output_data.proplist, PA_UPDATE_REPLACE) < 0) {
pa_log("Failed to parse the source_output_properties value.");
@@ -778,20 +792,16 @@ int pa__init(pa_module *m) {
goto fail;
}
- if (!pa_proplist_contains(source_output_data.proplist, PA_PROP_MEDIA_NAME))
- pa_proplist_setf(source_output_data.proplist, PA_PROP_MEDIA_NAME, "Loopback to %s",
- pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)));
-
if (!pa_proplist_contains(source_output_data.proplist, PA_PROP_MEDIA_ROLE))
pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
- if (!pa_proplist_contains(source_output_data.proplist, PA_PROP_MEDIA_ICON_NAME)
- && (n = pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_ICON_NAME)))
- pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ICON_NAME, n);
-
pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
pa_source_output_new_data_set_channel_map(&source_output_data, &map);
- source_output_data.flags = (remix ? 0 : PA_SOURCE_OUTPUT_NO_REMIX);
+ if (sink || source) {
+ source_output_data.flags = (remix ? 0 : PA_SOURCE_OUTPUT_NO_REMIX);
+ } else {
+ source_output_data.flags = PA_SOURCE_OUTPUT_FIX_FORMAT | PA_SOURCE_OUTPUT_FIX_RATE | PA_SOURCE_OUTPUT_FIX_CHANNELS;
+ }
source_dont_move = FALSE;
if (pa_modargs_get_value_boolean(ma, "source_dont_move", &source_dont_move) < 0) {
@@ -836,6 +846,22 @@ int pa__init(pa_module *m) {
u->asyncmsgq = pa_asyncmsgq_new(0);
+ if (!pa_proplist_contains(u->source_output->proplist, PA_PROP_MEDIA_NAME))
+ pa_proplist_setf(u->source_output->proplist, PA_PROP_MEDIA_NAME, "Loopback to %s",
+ pa_strnull(pa_proplist_gets(u->sink_input->sink->proplist, PA_PROP_DEVICE_DESCRIPTION)));
+
+ if (!pa_proplist_contains(u->source_output->proplist, PA_PROP_MEDIA_ICON_NAME)
+ && (n = pa_proplist_gets(u->sink_input->sink->proplist, PA_PROP_DEVICE_ICON_NAME)))
+ pa_proplist_sets(u->source_output->proplist, PA_PROP_MEDIA_ICON_NAME, n);
+
+ if (!pa_proplist_contains(u->sink_input->proplist, PA_PROP_MEDIA_NAME))
+ pa_proplist_setf(u->sink_input->proplist, PA_PROP_MEDIA_NAME, "Loopback from %s",
+ pa_strnull(pa_proplist_gets(u->source_output->source->proplist, PA_PROP_DEVICE_DESCRIPTION)));
+
+ if (source && !pa_proplist_contains(u->sink_input->proplist, PA_PROP_MEDIA_ICON_NAME)
+ && (n = pa_proplist_gets(u->source_output->source->proplist, PA_PROP_DEVICE_ICON_NAME)))
+ pa_proplist_sets(u->sink_input->proplist, PA_PROP_MEDIA_ICON_NAME, n);
+
pa_sink_input_put(u->sink_input);
pa_source_output_put(u->source_output);
--
1.7.9.5
More information about the pulseaudio-discuss
mailing list