This change doesn't add any functionality in itself, but it will be useful in the future for operating on chains of sinks or sources that are piggy-backing on each other. For example, the PA_PROP_DEVICE_MASTER_DEVICE property could be handled in the core so that each virtual device doesn't have to maintain it separately. By using the origin_sink and destination_source pointers the core is able to see at stream creation time that the stream is created by a virtual device, and then update that device's property list using the name of the master device that the stream is being connected to. The same thing can be done also when the stream is being moved from a device to another, in which case the _MASTER_DEVICE property needs updating. --- src/modules/echo-cancel/module-echo-cancel.c | 6 ++++++ src/modules/module-equalizer-sink.c | 4 +++- src/modules/module-ladspa-sink.c | 3 +++ src/modules/module-remap-sink.c | 3 +++ src/modules/module-virtual-sink.c | 3 +++ src/modules/module-virtual-source.c | 3 +++ src/pulsecore/sink-input.c | 1 + src/pulsecore/sink-input.h | 4 +++- src/pulsecore/sink.c | 1 + src/pulsecore/sink.h | 2 ++ src/pulsecore/source-output.c | 1 + src/pulsecore/source-output.h | 4 +++- src/pulsecore/source.c | 1 + src/pulsecore/source.h | 1 + 14 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c index 611ebb7..0108c31 100644 --- a/src/modules/echo-cancel/module-echo-cancel.c +++ b/src/modules/echo-cancel/module-echo-cancel.c @@ -1502,6 +1502,7 @@ int pa__init(pa_module*m) { source_output_data.driver = __FILE__; source_output_data.module = m; source_output_data.source = source_master; + source_output_data.destination_source = u->source; /* FIXME source_output_data.flags = PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; */ @@ -1531,11 +1532,14 @@ int pa__init(pa_module*m) { u->source_output->moving = source_output_moving_cb; u->source_output->userdata = u; + u->source->output_from_master = u->source_output; + /* Create sink input */ pa_sink_input_new_data_init(&sink_input_data); sink_input_data.driver = __FILE__; sink_input_data.module = m; sink_input_data.sink = sink_master; + sink_input_data.origin_sink = u->sink; pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Echo-Cancel Sink Stream"); pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter"); pa_sink_input_new_data_set_sample_spec(&sink_input_data, &sink_ss); @@ -1566,6 +1570,8 @@ int pa__init(pa_module*m) { u->sink_input->mute_changed = sink_input_mute_changed_cb; u->sink_input->userdata = u; + u->sink->input_to_master = u->sink_input; + pa_sink_input_get_silence(u->sink_input, &silence); u->source_memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c index bc349ce..a28405b 100644 --- a/src/modules/module-equalizer-sink.c +++ b/src/modules/module-equalizer-sink.c @@ -1200,6 +1200,7 @@ int pa__init(pa_module*m) { sink_input_data.driver = __FILE__; sink_input_data.module = m; sink_input_data.sink = master; + sink_input_data.origin_sink = u->sink; pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Equalized Stream"); pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter"); pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss); @@ -1225,9 +1226,10 @@ int pa__init(pa_module*m) { u->sink_input->moving = sink_input_moving_cb; u->sink_input->volume_changed = sink_input_volume_changed_cb; u->sink_input->mute_changed = sink_input_mute_changed_cb; - u->sink_input->userdata = u; + u->sink->input_to_master = u->sink_input; + dbus_init(u); /* default filter to these */ diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c index 88df67e..cdccf1a 100644 --- a/src/modules/module-ladspa-sink.c +++ b/src/modules/module-ladspa-sink.c @@ -832,6 +832,7 @@ int pa__init(pa_module*m) { sink_input_data.driver = __FILE__; sink_input_data.module = m; sink_input_data.sink = master; + sink_input_data.origin_sink = u->sink; pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "LADSPA Stream"); pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter"); pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss); @@ -859,6 +860,8 @@ int pa__init(pa_module*m) { u->sink_input->mute_changed = sink_input_mute_changed_cb; u->sink_input->userdata = u; + u->sink->input_to_master = u->sink_input; + pa_sink_put(u->sink); pa_sink_input_put(u->sink_input); diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c index 43748bd..7f64f30 100644 --- a/src/modules/module-remap-sink.c +++ b/src/modules/module-remap-sink.c @@ -420,6 +420,7 @@ int pa__init(pa_module*m) { sink_input_data.driver = __FILE__; sink_input_data.module = m; sink_input_data.sink = master; + sink_input_data.origin_sink = u->sink; pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Remapped Stream"); pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter"); pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss); @@ -446,6 +447,8 @@ int pa__init(pa_module*m) { u->sink_input->moving = sink_input_moving_cb; u->sink_input->userdata = u; + u->sink->input_to_master = u->sink_input; + pa_sink_put(u->sink); pa_sink_input_put(u->sink_input); diff --git a/src/modules/module-virtual-sink.c b/src/modules/module-virtual-sink.c index fac204d..40bab5a 100644 --- a/src/modules/module-virtual-sink.c +++ b/src/modules/module-virtual-sink.c @@ -556,6 +556,7 @@ int pa__init(pa_module*m) { sink_input_data.driver = __FILE__; sink_input_data.module = m; sink_input_data.sink = master; + sink_input_data.origin_sink = u->sink; pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Virtual Sink Stream"); pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter"); pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss); @@ -583,6 +584,8 @@ int pa__init(pa_module*m) { u->sink_input->mute_changed = sink_input_mute_changed_cb; u->sink_input->userdata = u; + u->sink->input_to_master = u->sink_input; + /* (9) IF YOU REQUIRE A FIXED BLOCK SIZE MAKE SURE TO PASS A * SILENCE MEMBLOCK AS LAST PARAMETER * HERE. pa_sink_input_get_silence() IS USEFUL HERE. */ diff --git a/src/modules/module-virtual-source.c b/src/modules/module-virtual-source.c index fdf89b0..a2b073f 100644 --- a/src/modules/module-virtual-source.c +++ b/src/modules/module-virtual-source.c @@ -629,6 +629,7 @@ int pa__init(pa_module*m) { source_output_data.driver = __FILE__; source_output_data.module = m; source_output_data.source = master; + source_output_data.destination_source = u->source; /* FIXME source_output_data.flags = PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; */ @@ -654,6 +655,8 @@ int pa__init(pa_module*m) { u->source_output->moving = source_output_moving_cb; u->source_output->userdata = u; + u->source->output_from_master = u->source_output; + pa_source_put(u->source); pa_source_output_put(u->source_output); diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 065fd2d..00adc6d 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -321,6 +321,7 @@ int pa_sink_input_new( i->driver = pa_xstrdup(pa_path_get_filename(data->driver)); i->module = data->module; i->sink = data->sink; + i->origin_sink = data->origin_sink; i->client = data->client; i->requested_resample_method = data->resample_method; diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index f81e2d4..e1991a2 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -83,7 +83,8 @@ struct pa_sink_input { pa_module *module; /* may be NULL */ pa_client *client; /* may be NULL */ - pa_sink *sink; /* NULL while we are being moved */ + pa_sink *sink; /* NULL while we are being moved */ + pa_sink *origin_sink; /* only set by filter sinks */ /* A sink input may be connected to multiple source outputs * directly, so that they don't get mixed data of the entire @@ -285,6 +286,7 @@ typedef struct pa_sink_input_new_data { pa_client *client; pa_sink *sink; + pa_sink *origin_sink; pa_resample_method_t resample_method; diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 62000e0..0de544c 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -269,6 +269,7 @@ pa_sink* pa_sink_new( s->inputs = pa_idxset_new(NULL, NULL); s->n_corked = 0; + s->input_to_master = NULL; s->reference_volume = s->real_volume = data->volume; pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels); diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 4d569dd..8a51587 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -44,6 +44,7 @@ typedef struct pa_sink_volume_change pa_sink_volume_change; #include <pulsecore/card.h> #include <pulsecore/queue.h> #include <pulsecore/thread-mq.h> +#include <pulsecore/sink-input.h> #define PA_MAX_INPUTS_PER_SINK 32 @@ -86,6 +87,7 @@ struct pa_sink { pa_idxset *inputs; unsigned n_corked; pa_source *monitor_source; + pa_sink_input *input_to_master; /* non-NULL only for filter sinks */ pa_volume_t base_volume; /* shall be constant */ unsigned n_volume_steps; /* shall be constant */ diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 88731e7..0bb8899 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -208,6 +208,7 @@ int pa_source_output_new( o->driver = pa_xstrdup(pa_path_get_filename(data->driver)); o->module = data->module; o->source = data->source; + o->destination_source = data->destination_source; o->client = data->client; o->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID; diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index 273b78f..f16f952 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -74,7 +74,8 @@ struct pa_source_output { pa_module *module; /* may be NULL */ pa_client *client; /* may be NULL */ - pa_source *source; /* NULL while being moved */ + pa_source *source; /* NULL while being moved */ + pa_source *destination_source; /* only set by filter sources */ /* A source output can monitor just a single input of a sink, in which case we find it here */ pa_sink_input *direct_on_input; /* may be NULL */ @@ -211,6 +212,7 @@ typedef struct pa_source_output_new_data { pa_client *client; pa_source *source; + pa_source *destination_source; pa_resample_method_t resample_method; diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 412a3db..24d0ff6 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -221,6 +221,7 @@ pa_source* pa_source_new( s->outputs = pa_idxset_new(NULL, NULL); s->n_corked = 0; s->monitor_of = NULL; + s->output_from_master = NULL; s->volume = data->volume; pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels); diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index e3e56bc..f3af159 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -75,6 +75,7 @@ struct pa_source { pa_idxset *outputs; unsigned n_corked; pa_sink *monitor_of; /* may be NULL */ + pa_source_output *output_from_master; /* non-NULL only for filter sources */ pa_volume_t base_volume; /* shall be constant */ unsigned n_volume_steps; /* shall be constant */ -- 1.7.3.4