X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/3d374e9f678133638e661cadf73d4ef7ddcfe6eb..fa499dad06ba6558111cdef64c18f2401e803cff:/polyp/source-output.c diff --git a/polyp/source-output.c b/polyp/source-output.c index c53831c7..e339d4ac 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. @@ -23,6 +23,7 @@ #include #endif +#include #include #include #include @@ -30,18 +31,29 @@ #include "source-output.h" #include "xmalloc.h" #include "subscribe.h" +#include "log.h" -struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec) { +struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec, int resample_method) { struct pa_source_output *o; struct pa_resampler *resampler = NULL; int r; assert(s && spec); + if (pa_idxset_ncontents(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { + pa_log(__FILE__": Failed to create source output: too many outputs per source.\n"); + return NULL; + } + + if (resample_method < 0) + resample_method = s->core->resample_method; + if (!pa_sample_spec_equal(&s->sample_spec, spec)) - if (!(resampler = pa_resampler_new(&s->sample_spec, spec))) + if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat, resample_method))) return NULL; o = pa_xmalloc(sizeof(struct pa_source_output)); + o->ref = 1; + o->state = PA_SOURCE_OUTPUT_RUNNING; o->name = pa_xstrdup(name); o->client = NULL; o->owner = NULL; @@ -51,6 +63,8 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n o->push = NULL; o->kill = NULL; o->userdata = NULL; + o->get_latency = NULL; + o->resampler = resampler; assert(s->core); @@ -64,33 +78,64 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n return o; } -void pa_source_output_free(struct pa_source_output* o) { - assert(o); - - assert(o->source && o->source->core); +void pa_source_output_disconnect(struct pa_source_output*o) { + assert(o && o->state != PA_SOURCE_OUTPUT_DISCONNECTED && o->source && o->source->core); + pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL); pa_idxset_remove_by_data(o->source->outputs, o, NULL); + pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index); + o->source = NULL; + + o->push = NULL; + o->kill = NULL; + + + o->state = PA_SOURCE_OUTPUT_DISCONNECTED; +} + +static void source_output_free(struct pa_source_output* o) { + assert(o); + + if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED) + pa_source_output_disconnect(o); + if (o->resampler) pa_resampler_free(o->resampler); - pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index); - pa_xfree(o->name); pa_xfree(o); } -void pa_source_output_kill(struct pa_source_output*i) { - assert(i); - if (i->kill) - i->kill(i); +void pa_source_output_unref(struct pa_source_output* o) { + assert(o && o->ref >= 1); + + if (!(--o->ref)) + source_output_free(o); +} + +struct pa_source_output* pa_source_output_ref(struct pa_source_output *o) { + assert(o && o->ref >= 1); + o->ref++; + return o; +} + + +void pa_source_output_kill(struct pa_source_output*o) { + assert(o && o->ref >= 1); + + if (o->kill) + o->kill(o); } void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk *chunk) { struct pa_memchunk rchunk; assert(o && chunk && chunk->length && o->push); + if (o->state == PA_SOURCE_OUTPUT_CORKED) + return; + if (!o->resampler) { o->push(o, chunk); return; @@ -104,3 +149,29 @@ void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk o->push(o, &rchunk); pa_memblock_unref(rchunk.memblock); } + +void pa_source_output_set_name(struct pa_source_output *o, const char *name) { + assert(o && o->ref >= 1); + pa_xfree(o->name); + o->name = pa_xstrdup(name); + + pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); +} + +pa_usec_t pa_source_output_get_latency(struct pa_source_output *o) { + assert(o && o->ref >= 1); + + if (o->get_latency) + return o->get_latency(o); + + return 0; +} + +void pa_source_output_cork(struct pa_source_output *o, int b) { + assert(o && o->ref >= 1); + + if (o->state == PA_SOURCE_OUTPUT_DISCONNECTED) + return; + + o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING; +}