mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
loopback: Enable routing on loopback streams
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.
This commit is contained in:
parent
750a5c187a
commit
c6d8d1d7c1
1 changed files with 89 additions and 26 deletions
|
|
@ -647,15 +647,18 @@ 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;
|
||||
pa_sample_spec ss;
|
||||
pa_channel_map map;
|
||||
bool format_set = false;
|
||||
bool rate_set = false;
|
||||
bool channels_set = false;
|
||||
pa_memchunk silence;
|
||||
uint32_t adjust_time_sec;
|
||||
const char *n;
|
||||
|
|
@ -668,12 +671,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,13 +688,45 @@ 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;
|
||||
format_set = true;
|
||||
rate_set = true;
|
||||
channels_set = true;
|
||||
} else if (source) {
|
||||
ss = source->sample_spec;
|
||||
map = source->channel_map;
|
||||
format_set = true;
|
||||
rate_set = true;
|
||||
channels_set = true;
|
||||
} else {
|
||||
/* FIXME: Dummy stream format, needed because pa_sink_input_new()
|
||||
* requires valid sample spec and channel map even when all the FIX_*
|
||||
* stream flags are specified. pa_sink_input_new() should be changed
|
||||
* to ignore the sample spec and channel map when the FIX_* flags are
|
||||
* present. */
|
||||
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;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value(ma, "format", NULL))
|
||||
format_set = true;
|
||||
|
||||
if (pa_modargs_get_value(ma, "rate", NULL))
|
||||
rate_set = true;
|
||||
|
||||
if (pa_modargs_get_value(ma, "channels", NULL) || pa_modargs_get_value(ma, "channel_map", NULL))
|
||||
channels_set = true;
|
||||
|
||||
latency_msec = DEFAULT_LATENCY_MSEC;
|
||||
if (pa_modargs_get_value_u32(ma, "latency_msec", &latency_msec) < 0 || latency_msec < 1 || latency_msec > 2000) {
|
||||
pa_log("Invalid latency specification");
|
||||
|
|
@ -715,7 +752,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 +762,24 @@ 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);
|
||||
sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE;
|
||||
|
||||
if (!remix)
|
||||
sink_input_data.flags |= PA_SINK_INPUT_NO_REMIX;
|
||||
|
||||
if (!format_set)
|
||||
sink_input_data.flags |= PA_SINK_INPUT_FIX_FORMAT;
|
||||
|
||||
if (!rate_set)
|
||||
sink_input_data.flags |= PA_SINK_INPUT_FIX_RATE;
|
||||
|
||||
if (!channels_set)
|
||||
sink_input_data.flags |= 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 +813,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 +822,23 @@ 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 (!remix)
|
||||
source_output_data.flags |= PA_SOURCE_OUTPUT_NO_REMIX;
|
||||
|
||||
if (!format_set)
|
||||
source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_FORMAT;
|
||||
|
||||
if (!rate_set)
|
||||
source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_RATE;
|
||||
|
||||
if (!channels_set)
|
||||
source_output_data.flags |= 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 +883,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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue