4 This file is part of polypaudio.
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
32 #include "sink-input.h"
35 #include "sample-util.h"
37 #define MAX_MIX_CHANNELS 32
39 struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) {
44 assert(core && name && spec);
46 s = malloc(sizeof(struct pa_sink));
49 if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) {
54 s->name = strdup(name);
55 s->description = NULL;
59 s->sample_spec = *spec;
60 s->inputs = pa_idxset_new(NULL, NULL);
62 n = pa_sprintf_malloc("%s_monitor", name);
63 s->monitor_source = pa_source_new(core, n, 0, spec);
64 assert(s->monitor_source);
66 s->monitor_source->monitor_of = s;
68 s->volume = PA_VOLUME_NORM;
71 s->get_latency = NULL;
74 r = pa_idxset_put(core->sinks, s, &s->index);
75 assert(s->index != PA_IDXSET_INVALID && r >= 0);
77 pa_sample_snprint(st, sizeof(st), spec);
78 fprintf(stderr, "sink: created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st);
83 void pa_sink_free(struct pa_sink *s) {
84 struct pa_sink_input *i, *j = NULL;
87 pa_namereg_unregister(s->core, s->name);
89 while ((i = pa_idxset_first(s->inputs, NULL))) {
91 pa_sink_input_kill(i);
94 pa_idxset_free(s->inputs, NULL, NULL);
96 pa_source_free(s->monitor_source);
97 pa_idxset_remove_by_data(s->core->sinks, s, NULL);
99 fprintf(stderr, "sink: freed %u \"%s\"\n", s->index, s->name);
102 free(s->description);
106 void pa_sink_notify(struct pa_sink*s) {
113 static unsigned fill_mix_info(struct pa_sink *s, struct pa_mix_info *info, unsigned maxinfo) {
114 uint32_t index = PA_IDXSET_INVALID;
115 struct pa_sink_input *i;
120 for (i = pa_idxset_first(s->inputs, &index); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &index)) {
121 if (pa_sink_input_peek(i, &info->chunk) < 0)
124 info->volume = i->volume;
126 assert(info->chunk.memblock && info->chunk.memblock->data && info->chunk.length);
137 static void inputs_drop(struct pa_sink *s, struct pa_mix_info *info, unsigned maxinfo, size_t length) {
140 for (; maxinfo > 0; maxinfo--, info++) {
141 struct pa_sink_input *i = info->userdata;
142 assert(i && info->chunk.memblock);
144 pa_memblock_unref(info->chunk.memblock);
145 pa_sink_input_drop(i, length);
149 int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) {
150 struct pa_mix_info info[MAX_MIX_CHANNELS];
153 assert(s && length && result);
155 n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
161 uint32_t volume = PA_VOLUME_NORM;
162 struct pa_sink_input *i = info[0].userdata;
164 *result = info[0].chunk;
165 pa_memblock_ref(result->memblock);
167 if (result->length > length)
168 result->length = length;
172 if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM)
173 volume = pa_volume_multiply(s->volume, info[0].volume);
175 if (volume != PA_VOLUME_NORM) {
176 pa_memchunk_make_writable(result);
177 pa_volume_memchunk(result, &s->sample_spec, volume);
180 result->memblock = pa_memblock_new(length);
181 assert(result->memblock);
183 result->length = l = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, s->volume);
189 inputs_drop(s, info, n, l);
191 assert(s->monitor_source);
192 pa_source_post(s->monitor_source, result);
197 int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) {
198 struct pa_mix_info info[MAX_MIX_CHANNELS];
201 assert(s && target && target->length && target->memblock && target->memblock->data);
203 n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
209 uint32_t volume = PA_VOLUME_NORM;
210 struct pa_sink_info *i = info[0].userdata;
214 if (l > info[0].chunk.length)
215 l = info[0].chunk.length;
217 memcpy(target->memblock->data+target->index, info[0].chunk.memblock->data + info[0].chunk.index, l);
220 if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM)
221 volume = pa_volume_multiply(s->volume, info[0].volume);
223 if (volume != PA_VOLUME_NORM)
224 pa_volume_memchunk(target, &s->sample_spec, volume);
226 target->length = l = pa_mix(info, n, target->memblock->data+target->index, target->length, &s->sample_spec, s->volume);
229 inputs_drop(s, info, n, l);
231 assert(s->monitor_source);
232 pa_source_post(s->monitor_source, target);
237 void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target) {
238 struct pa_memchunk chunk;
240 assert(s && target && target->memblock && target->length && target->memblock->data);
249 if (pa_sink_render_into(s, &chunk) < 0)
260 pa_silence_memchunk(&chunk, &s->sample_spec);
264 uint32_t pa_sink_get_latency(struct pa_sink *s) {
270 return s->get_latency(s);
273 struct pa_sink* pa_sink_get_default(struct pa_core *c) {
274 struct pa_sink *sink;
277 if ((sink = pa_idxset_get_by_index(c->sinks, c->default_sink_index)))
280 if (!(sink = pa_idxset_first(c->sinks, &c->default_sink_index)))
283 fprintf(stderr, "core: default sink vanished, setting to %u.\n", sink->index);
287 void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) {
290 if (sink->monitor_source)
291 pa_source_set_owner(sink->monitor_source, m);