On 06/28/2013 09:48 AM, Tanu Kaskinen wrote: > --- > src/pulsecore/sink-input.c | 45 +++++++++++++++++++++++++++++++++++++++++-- > src/pulsecore/sink-input.h | 6 ++++++ > src/pulsecore/source-output.c | 42 +++++++++++++++++++++++++++++++++++++++- > src/pulsecore/source-output.h | 6 ++++++ > 4 files changed, 96 insertions(+), 3 deletions(-) > > diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c > index 4863f15..a79aa4e 100644 > --- a/src/pulsecore/sink-input.c > +++ b/src/pulsecore/sink-input.c > @@ -109,9 +109,11 @@ pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data > data->resample_method = PA_RESAMPLER_INVALID; > data->proplist = pa_proplist_new(); > data->volume_writable = TRUE; > - > data->volume_factor_items = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); > data->volume_factor_sink_items = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); > + pa_node_new_data_init(&data->node_data); > + pa_node_new_data_set_type(&data->node_data, PA_NODE_TYPE_SINK_INPUT); > + pa_node_new_data_set_direction(&data->node_data, PA_DIRECTION_INPUT); > > return data; > } > @@ -229,9 +231,17 @@ pa_bool_t pa_sink_input_new_data_set_formats(pa_sink_input_new_data *data, pa_id > return TRUE; > } > > +void pa_sink_input_new_data_set_create_node(pa_sink_input_new_data *data, bool create) { > + pa_assert(data); > + > + data->create_node = create; > +} I tried to think of a use case where sink inputs would not have nodes, but failed (but I'm not sure how this would work with virtual sinks). If not, is there a reason to have this - can't we just always create the node? > + > void pa_sink_input_new_data_done(pa_sink_input_new_data *data) { > pa_assert(data); > > + pa_node_new_data_done(&data->node_data); > + > if (data->req_formats) > pa_idxset_free(data->req_formats, (pa_free_cb_t) pa_format_info_free); > > @@ -282,7 +292,7 @@ int pa_sink_input_new( > pa_core *core, > pa_sink_input_new_data *data) { > > - pa_sink_input *i; > + pa_sink_input *i = NULL; > pa_resampler *resampler = NULL; > char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], fmt[PA_FORMAT_INFO_SNPRINT_MAX]; > pa_channel_map original_cm; > @@ -291,6 +301,7 @@ int pa_sink_input_new( > char *memblockq_name; > pa_sample_spec ss; > pa_channel_map map; > + int ret = 0; > > pa_assert(_i); > pa_assert(core); > @@ -580,6 +591,19 @@ int pa_sink_input_new( > &i->sink->silence); > pa_xfree(memblockq_name); > > + if (data->create_node) { > + if (!data->node_data.description) > + pa_node_new_data_set_description(&data->node_data, pa_sink_input_get_description(i)); > + > + if (!(i->node = pa_node_new(i->core, &data->node_data))) { > + pa_log("Failed to create a node for sink input \"%s\".", pa_sink_input_get_description(i)); > + ret = -PA_ERR_INTERNAL; > + goto fail; > + } > + > + i->node->owner = i; > + } > + > pt = pa_proplist_to_string_sep(i->proplist, "\n "); > pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n %s", > i->index, > @@ -594,6 +618,14 @@ int pa_sink_input_new( > > *_i = i; > return 0; > + > +fail: > + if (i) { > + pa_sink_input_unlink(i); > + pa_sink_input_unref(i); > + } > + > + return ret; > } > > /* Called from main context */ > @@ -677,6 +709,9 @@ void pa_sink_input_unlink(pa_sink_input *i) { > if (linked) > pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i); > > + if (i->node) > + pa_node_unlink(i->node); > + > if (i->sync_prev) > i->sync_prev->sync_next = i->sync_next; > if (i->sync_next) > @@ -751,6 +786,9 @@ static void sink_input_free(pa_object *o) { > * "half-moved" or are connected to sinks that have no asyncmsgq > * and are hence half-destructed themselves! */ > > + if (i->node) > + pa_node_free(i->node); > + > if (i->thread_info.render_memblockq) > pa_memblockq_free(i->thread_info.render_memblockq); > > @@ -818,6 +856,9 @@ void pa_sink_input_put(pa_sink_input *i) { > > pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0); > > + if (i->node) > + pa_node_put(i->node); > + > pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); > pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i); > > diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h > index bece745..7c11452 100644 > --- a/src/pulsecore/sink-input.h > +++ b/src/pulsecore/sink-input.h > @@ -70,6 +70,8 @@ struct pa_sink_input { > uint32_t index; > pa_core *core; > > + pa_node *node; > + > /* Please note that this state should only be read with > * pa_sink_input_get_state(). That function will transparently > * merge the thread_info.drained value in. */ > @@ -314,6 +316,9 @@ typedef struct pa_sink_input_new_data { > pa_bool_t volume_writable:1; > > pa_bool_t save_sink:1, save_volume:1, save_muted:1; > + > + bool create_node; > + pa_node_new_data node_data; > } pa_sink_input_new_data; > > pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data); > @@ -326,6 +331,7 @@ void pa_sink_input_new_data_add_volume_factor_sink(pa_sink_input_new_data *data, > void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute); > pa_bool_t pa_sink_input_new_data_set_sink(pa_sink_input_new_data *data, pa_sink *s, pa_bool_t save); > pa_bool_t pa_sink_input_new_data_set_formats(pa_sink_input_new_data *data, pa_idxset *formats); > +void pa_sink_input_new_data_set_create_node(pa_sink_input_new_data *data, bool create); > void pa_sink_input_new_data_done(pa_sink_input_new_data *data); > > /* To be called by the implementing module only */ > diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c > index 75f02ff..127ef52 100644 > --- a/src/pulsecore/source-output.c > +++ b/src/pulsecore/source-output.c > @@ -55,6 +55,9 @@ pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_d > data->resample_method = PA_RESAMPLER_INVALID; > data->proplist = pa_proplist_new(); > data->volume_writable = TRUE; > + pa_node_new_data_init(&data->node_data); > + pa_node_new_data_set_type(&data->node_data, PA_NODE_TYPE_SOURCE_OUTPUT); > + pa_node_new_data_set_direction(&data->node_data, PA_DIRECTION_OUTPUT); > > return data; > } > @@ -174,9 +177,17 @@ pa_bool_t pa_source_output_new_data_set_formats(pa_source_output_new_data *data, > return TRUE; > } > > +void pa_source_output_new_data_set_create_node(pa_source_output_new_data *data, bool create) { > + pa_assert(data); > + > + data->create_node = create; > +} > + > void pa_source_output_new_data_done(pa_source_output_new_data *data) { > pa_assert(data); > > + pa_node_new_data_done(&data->node_data); > + > if (data->req_formats) > pa_idxset_free(data->req_formats, (pa_free_cb_t) pa_format_info_free); > > @@ -219,7 +230,7 @@ int pa_source_output_new( > pa_core *core, > pa_source_output_new_data *data) { > > - pa_source_output *o; > + pa_source_output *o = NULL; > pa_resampler *resampler = NULL; > char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; > pa_channel_map original_cm; > @@ -227,6 +238,7 @@ int pa_source_output_new( > char *pt; > pa_sample_spec ss; > pa_channel_map map; > + int ret = 0; > > pa_assert(_o); > pa_assert(core); > @@ -489,6 +501,17 @@ int pa_source_output_new( > if (o->direct_on_input) > pa_assert_se(pa_idxset_put(o->direct_on_input->direct_outputs, o, NULL) == 0); > > + if (data->create_node) { > + if (!data->node_data.description) > + pa_node_new_data_set_description(&data->node_data, pa_source_output_get_description(o)); > + > + if (!(o->node = pa_node_new(o->core, &data->node_data))) { > + pa_log("Failed to create a node for source output \"%s\".", pa_source_output_get_description(o)); > + ret = -PA_ERR_INTERNAL; > + goto fail; > + } > + } > + > pt = pa_proplist_to_string_sep(o->proplist, "\n "); > pa_log_info("Created output %u \"%s\" on %s with sample spec %s and channel map %s\n %s", > o->index, > @@ -503,6 +526,14 @@ int pa_source_output_new( > > *_o = o; > return 0; > + > +fail: > + if (o) { > + pa_source_output_unlink(o); > + pa_source_output_unref(o); > + } > + > + return ret; > } > > /* Called from main context */ > @@ -566,6 +597,9 @@ void pa_source_output_unlink(pa_source_output*o) { > if (linked) > pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o); > > + if (o->node) > + pa_node_unlink(o->node); > + > if (o->direct_on_input) > pa_idxset_remove_by_data(o->direct_on_input->direct_outputs, o, NULL); > > @@ -625,6 +659,9 @@ static void source_output_free(pa_object* mo) { > > pa_log_info("Freeing output %u \"%s\"", o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME))); > > + if (o->node) > + pa_node_free(o->node); > + > if (o->thread_info.delay_memblockq) > pa_memblockq_free(o->thread_info.delay_memblockq); > > @@ -679,6 +716,9 @@ void pa_source_output_put(pa_source_output *o) { > > pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL) == 0); > > + if (o->node) > + pa_node_put(o->node); > + > pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index); > pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], o); > > diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h > index fd95c3e..e4e093d 100644 > --- a/src/pulsecore/source-output.h > +++ b/src/pulsecore/source-output.h > @@ -68,6 +68,8 @@ struct pa_source_output { > uint32_t index; > pa_core *core; > > + pa_node *node; > + > pa_source_output_state_t state; > pa_source_output_flags_t flags; > > @@ -270,6 +272,9 @@ typedef struct pa_source_output_new_data { > pa_bool_t volume_writable:1; > > pa_bool_t save_source:1, save_volume:1, save_muted:1; > + > + bool create_node; > + pa_node_new_data node_data; > } pa_source_output_new_data; > > pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data); > @@ -282,6 +287,7 @@ void pa_source_output_new_data_apply_volume_factor_source(pa_source_output_new_d > void pa_source_output_new_data_set_muted(pa_source_output_new_data *data, pa_bool_t mute); > pa_bool_t pa_source_output_new_data_set_source(pa_source_output_new_data *data, pa_source *s, pa_bool_t save); > pa_bool_t pa_source_output_new_data_set_formats(pa_source_output_new_data *data, pa_idxset *formats); > +void pa_source_output_new_data_set_create_node(pa_source_output_new_data *data, bool create); > void pa_source_output_new_data_done(pa_source_output_new_data *data); > > /* To be called by the implementing module only */ > -- David Henningsson, Canonical Ltd. https://launchpad.net/~diwic