From 6e019795bff589ef0a867772975e34da78fffefb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Sep 2004 20:53:25 +0000 Subject: add refernce counting for sinks, sources, sink-inputs and source-outputs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@200 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/sink.c | 119 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 29 deletions(-) (limited to 'polyp/sink.c') diff --git a/polyp/sink.c b/polyp/sink.c index 1fe38e9f..6d3b59c7 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -52,9 +52,12 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co pa_xfree(s); return NULL; } - + s->name = pa_xstrdup(name); s->description = NULL; + + s->ref = 1; + s->state = PA_SINK_RUNNING; s->owner = NULL; s->core = core; @@ -85,9 +88,9 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co return s; } -void pa_sink_free(struct pa_sink *s) { +void pa_sink_disconnect(struct pa_sink* s) { struct pa_sink_input *i, *j = NULL; - assert(s); + assert(s && s->state == PA_SINK_RUNNING); pa_namereg_unregister(s->core, s->name); @@ -96,22 +99,51 @@ void pa_sink_free(struct pa_sink *s) { pa_sink_input_kill(i); j = i; } - pa_idxset_free(s->inputs, NULL, NULL); - pa_source_free(s->monitor_source); + pa_source_disconnect(s->monitor_source); + pa_idxset_remove_by_data(s->core->sinks, s, NULL); + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + + s->notify = NULL; + s->get_latency = NULL; + + s->state = PA_SINK_DISCONNECTED; +} + +static void sink_free(struct pa_sink *s) { + assert(s && s->ref == 0); + + if (s->state != PA_SINK_DISCONNECTED) + pa_sink_disconnect(s); pa_log(__FILE__": freed %u \"%s\"\n", s->index, s->name); - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + pa_source_unref(s->monitor_source); + s->monitor_source = NULL; + pa_idxset_free(s->inputs, NULL, NULL); + pa_xfree(s->name); pa_xfree(s->description); pa_xfree(s); } +void pa_sink_unref(struct pa_sink*s) { + assert(s && s->ref >= 1); + + if (!(--s->ref)) + sink_free(s); +} + +struct pa_sink* pa_sink_ref(struct pa_sink *s) { + assert(s && s->ref >= 1); + s->ref++; + return s; +} + void pa_sink_notify(struct pa_sink*s) { - assert(s); + assert(s && s->ref >= 1); if (s->notify) s->notify(s); @@ -122,16 +154,20 @@ static unsigned fill_mix_info(struct pa_sink *s, struct pa_mix_info *info, unsig struct pa_sink_input *i; unsigned n = 0; - assert(s && info); + assert(s && s->ref >= 1 && info); for (i = pa_idxset_first(s->inputs, &index); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &index)) { - if (pa_sink_input_peek(i, &info->chunk) < 0) + pa_sink_input_ref(i); + + if (pa_sink_input_peek(i, &info->chunk) < 0) { + pa_sink_input_unref(i); continue; + } info->volume = i->volume; + info->userdata = i; assert(info->chunk.memblock && info->chunk.memblock->data && info->chunk.length); - info->userdata = i; info++; maxinfo--; @@ -142,7 +178,7 @@ static unsigned fill_mix_info(struct pa_sink *s, struct pa_mix_info *info, unsig } static void inputs_drop(struct pa_sink *s, struct pa_mix_info *info, unsigned maxinfo, size_t length) { - assert(s && info); + assert(s && s->ref >= 1 && info); for (; maxinfo > 0; maxinfo--, info++) { struct pa_sink_input *i = info->userdata; @@ -150,6 +186,9 @@ static void inputs_drop(struct pa_sink *s, struct pa_mix_info *info, unsigned ma pa_sink_input_drop(i, &info->chunk, length); pa_memblock_unref(info->chunk.memblock); + + pa_sink_input_unref(i); + info->userdata = NULL; } } @@ -157,12 +196,15 @@ int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) struct pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; size_t l; - assert(s && length && result); + int r = -1; + assert(s && s->ref >= 1 && length && result); + pa_sink_ref(s); + n = fill_mix_info(s, info, MAX_MIX_CHANNELS); if (n <= 0) - return -1; + goto finish; if (n == 1) { uint32_t volume = PA_VOLUME_NORM; @@ -198,19 +240,27 @@ int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) assert(s->monitor_source); pa_source_post(s->monitor_source, result); - return 0; + r = 0; + +finish: + pa_sink_unref(s); + + return r; } int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) { struct pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; size_t l; - assert(s && target && target->length && target->memblock && target->memblock->data); + int r = -1; + assert(s && s->ref >= 1 && target && target->length && target->memblock && target->memblock->data); + + pa_sink_ref(s); n = fill_mix_info(s, info, MAX_MIX_CHANNELS); if (n <= 0) - return -1; + goto finish; if (n == 1) { uint32_t volume = PA_VOLUME_NORM; @@ -238,14 +288,21 @@ int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) { assert(s->monitor_source); pa_source_post(s->monitor_source, target); - return 0; + r = 0; + +finish: + pa_sink_unref(s); + + return r; } void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target) { struct pa_memchunk chunk; size_t l, d; - assert(s && target && target->memblock && target->length && target->memblock->data); + assert(s && s->ref >= 1 && target && target->memblock && target->length && target->memblock->data); + pa_sink_ref(s); + l = target->length; d = 0; while (l > 0) { @@ -266,10 +323,12 @@ void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target) { chunk.length -= d; pa_silence_memchunk(&chunk, &s->sample_spec); } + + pa_sink_unref(s); } void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *result) { - assert(s && length && result); + assert(s && s->ref >= 1 && length && result); /*** This needs optimization ***/ @@ -280,7 +339,7 @@ void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *r } pa_usec_t pa_sink_get_latency(struct pa_sink *s) { - assert(s); + assert(s && s->ref >= 1); if (!s->get_latency) return 0; @@ -288,18 +347,20 @@ pa_usec_t pa_sink_get_latency(struct pa_sink *s) { return s->get_latency(s); } -void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) { - sink->owner = m; +void pa_sink_set_owner(struct pa_sink *s, struct pa_module *m) { + assert(s && s->ref >= 1); + + s->owner = m; - if (sink->monitor_source) - pa_source_set_owner(sink->monitor_source, m); + if (s->monitor_source) + pa_source_set_owner(s->monitor_source, m); } -void pa_sink_set_volume(struct pa_sink *sink, pa_volume_t volume) { - assert(sink); +void pa_sink_set_volume(struct pa_sink *s, pa_volume_t volume) { + assert(s && s->ref >= 1); - if (sink->volume != volume) { - sink->volume = volume; - pa_subscription_post(sink->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, sink->index); + if (s->volume != volume) { + s->volume = volume; + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } } -- cgit