]> code.delx.au - pulseaudio/blob - src/pulsecore/sink.c
if no latency was configure for a sink/source, fill in the max latency automatically
[pulseaudio] / src / pulsecore / sink.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
13
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32
33 #include <pulse/introspect.h>
34 #include <pulse/utf8.h>
35 #include <pulse/xmalloc.h>
36 #include <pulse/timeval.h>
37
38 #include <pulsecore/sink-input.h>
39 #include <pulsecore/namereg.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/sample-util.h>
42 #include <pulsecore/core-subscribe.h>
43 #include <pulsecore/log.h>
44 #include <pulsecore/macro.h>
45 #include <pulsecore/play-memblockq.h>
46
47 #include "sink.h"
48
49 #define MAX_MIX_CHANNELS 32
50 #define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
51 #define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
52
53 static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
54
55 static void sink_free(pa_object *s);
56
57 pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data) {
58 pa_assert(data);
59
60 memset(data, 0, sizeof(*data));
61 data->proplist = pa_proplist_new();
62
63 return data;
64 }
65
66 void pa_sink_new_data_set_name(pa_sink_new_data *data, const char *name) {
67 pa_assert(data);
68
69 pa_xfree(data->name);
70 data->name = pa_xstrdup(name);
71 }
72
73 void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_spec *spec) {
74 pa_assert(data);
75
76 if ((data->sample_spec_is_set = !!spec))
77 data->sample_spec = *spec;
78 }
79
80 void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map) {
81 pa_assert(data);
82
83 if ((data->channel_map_is_set = !!map))
84 data->channel_map = *map;
85 }
86
87 void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume) {
88 pa_assert(data);
89
90 if ((data->volume_is_set = !!volume))
91 data->volume = *volume;
92 }
93
94 void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute) {
95 pa_assert(data);
96
97 data->muted_is_set = TRUE;
98 data->muted = !!mute;
99 }
100
101 void pa_sink_new_data_done(pa_sink_new_data *data) {
102 pa_assert(data);
103
104 pa_xfree(data->name);
105 pa_proplist_free(data->proplist);
106 }
107
108 static void reset_callbacks(pa_sink *s) {
109 pa_assert(s);
110
111 s->set_state = NULL;
112 s->get_volume = NULL;
113 s->set_volume = NULL;
114 s->get_mute = NULL;
115 s->set_mute = NULL;
116 s->get_latency = NULL;
117 s->request_rewind = NULL;
118 s->update_requested_latency = NULL;
119 }
120
121 pa_sink* pa_sink_new(
122 pa_core *core,
123 pa_sink_new_data *data,
124 pa_sink_flags_t flags) {
125
126 pa_sink *s;
127 const char *name;
128 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
129 pa_source_new_data source_data;
130 const char *dn;
131
132 pa_assert(core);
133 pa_assert(data);
134 pa_assert(data->name);
135
136 s = pa_msgobject_new(pa_sink);
137
138 if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) {
139 pa_xfree(s);
140 return NULL;
141 }
142
143 pa_sink_new_data_set_name(data, name);
144
145 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW], data) < 0) {
146 pa_xfree(s);
147 pa_namereg_unregister(core, name);
148 return NULL;
149 }
150
151 pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
152 pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
153
154 pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
155
156 if (!data->channel_map_is_set)
157 pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
158
159 pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
160 pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
161
162 if (!data->volume_is_set)
163 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
164
165 pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
166 pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
167
168 if (!data->muted_is_set)
169 data->muted = FALSE;
170
171 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {
172 pa_xfree(s);
173 pa_namereg_unregister(core, name);
174 return NULL;
175 }
176
177 s->parent.parent.free = sink_free;
178 s->parent.process_msg = pa_sink_process_msg;
179
180 s->core = core;
181 s->state = PA_SINK_INIT;
182 s->flags = flags;
183 s->name = pa_xstrdup(name);
184 s->proplist = pa_proplist_copy(data->proplist);
185 s->driver = pa_xstrdup(data->driver);
186 s->module = data->module;
187
188 s->sample_spec = data->sample_spec;
189 s->channel_map = data->channel_map;
190
191 s->inputs = pa_idxset_new(NULL, NULL);
192 s->n_corked = 0;
193
194 s->volume = data->volume;
195 s->muted = data->muted;
196 s->refresh_volume = s->refresh_mute = FALSE;
197
198 reset_callbacks(s);
199 s->userdata = NULL;
200
201 s->asyncmsgq = NULL;
202 s->rtpoll = NULL;
203
204 pa_silence_memchunk_get(
205 &core->silence_cache,
206 core->mempool,
207 &s->silence,
208 &s->sample_spec,
209 0);
210
211 s->min_latency = DEFAULT_MIN_LATENCY;
212 s->max_latency = s->min_latency;
213
214 s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
215 s->thread_info.soft_volume = s->volume;
216 s->thread_info.soft_muted = s->muted;
217 s->thread_info.state = s->state;
218 s->thread_info.rewind_nbytes = 0;
219 s->thread_info.max_rewind = 0;
220 s->thread_info.requested_latency_valid = FALSE;
221 s->thread_info.requested_latency = 0;
222
223 pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
224
225 pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s",
226 s->index,
227 s->name,
228 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
229 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map));
230
231 pa_source_new_data_init(&source_data);
232 pa_source_new_data_set_sample_spec(&source_data, &s->sample_spec);
233 pa_source_new_data_set_channel_map(&source_data, &s->channel_map);
234 source_data.name = pa_sprintf_malloc("%s.monitor", name);
235 source_data.driver = data->driver;
236 source_data.module = data->module;
237
238 dn = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
239 pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
240 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
241
242 s->monitor_source = pa_source_new(core, &source_data, 0);
243
244 pa_source_new_data_done(&source_data);
245
246 if (!s->monitor_source) {
247 pa_sink_unlink(s);
248 pa_sink_unref(s);
249 return NULL;
250 }
251
252 s->monitor_source->monitor_of = s;
253 pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
254
255 return s;
256 }
257
258 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
259 int ret;
260 pa_bool_t suspend_change;
261
262 pa_assert(s);
263
264 if (s->state == state)
265 return 0;
266
267 suspend_change =
268 (s->state == PA_SINK_SUSPENDED && PA_SINK_OPENED(state)) ||
269 (PA_SINK_OPENED(s->state) && state == PA_SINK_SUSPENDED);
270
271 if (s->set_state)
272 if ((ret = s->set_state(s, state)) < 0)
273 return -1;
274
275 if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0)
276 return -1;
277
278 s->state = state;
279
280 if (suspend_change) {
281 pa_sink_input *i;
282 uint32_t idx;
283
284 /* We're suspending or resuming, tell everyone about it */
285
286 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx)))
287 if (i->suspend)
288 i->suspend(i, state == PA_SINK_SUSPENDED);
289 }
290
291 if (state != PA_SINK_UNLINKED) /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
292 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
293
294 return 0;
295 }
296
297 void pa_sink_put(pa_sink* s) {
298 pa_sink_assert_ref(s);
299
300 pa_assert(s->state == PA_SINK_INIT);
301 pa_assert(s->asyncmsgq);
302 pa_assert(s->rtpoll);
303
304 pa_assert(!s->min_latency || !s->max_latency || s->min_latency <= s->max_latency);
305
306 if (!(s->flags & PA_SINK_HW_VOLUME_CTRL))
307 s->flags |= PA_SINK_DECIBEL_VOLUME;
308
309 pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
310
311 pa_source_put(s->monitor_source);
312
313 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
314 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s);
315 }
316
317 void pa_sink_unlink(pa_sink* s) {
318 pa_bool_t linked;
319 pa_sink_input *i, *j = NULL;
320
321 pa_assert(s);
322
323 /* Please note that pa_sink_unlink() does more than simply
324 * reversing pa_sink_put(). It also undoes the registrations
325 * already done in pa_sink_new()! */
326
327 /* All operations here shall be idempotent, i.e. pa_sink_unlink()
328 * may be called multiple times on the same sink without bad
329 * effects. */
330
331 linked = PA_SINK_LINKED(s->state);
332
333 if (linked)
334 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
335
336 if (s->state != PA_SINK_UNLINKED)
337 pa_namereg_unregister(s->core, s->name);
338 pa_idxset_remove_by_data(s->core->sinks, s, NULL);
339
340 while ((i = pa_idxset_first(s->inputs, NULL))) {
341 pa_assert(i != j);
342 pa_sink_input_kill(i);
343 j = i;
344 }
345
346 if (linked)
347 sink_set_state(s, PA_SINK_UNLINKED);
348 else
349 s->state = PA_SINK_UNLINKED;
350
351 reset_callbacks(s);
352
353 if (s->monitor_source)
354 pa_source_unlink(s->monitor_source);
355
356 if (linked) {
357 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
358 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
359 }
360 }
361
362 static void sink_free(pa_object *o) {
363 pa_sink *s = PA_SINK(o);
364 pa_sink_input *i;
365
366 pa_assert(s);
367 pa_assert(pa_sink_refcnt(s) == 0);
368
369 if (PA_SINK_LINKED(s->state))
370 pa_sink_unlink(s);
371
372 pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
373
374 if (s->monitor_source) {
375 pa_source_unref(s->monitor_source);
376 s->monitor_source = NULL;
377 }
378
379 pa_idxset_free(s->inputs, NULL, NULL);
380
381 while ((i = pa_hashmap_steal_first(s->thread_info.inputs)))
382 pa_sink_input_unref(i);
383
384 pa_hashmap_free(s->thread_info.inputs, NULL, NULL);
385
386 if (s->silence.memblock)
387 pa_memblock_unref(s->silence.memblock);
388
389 pa_xfree(s->name);
390 pa_xfree(s->driver);
391
392 if (s->proplist)
393 pa_proplist_free(s->proplist);
394
395 pa_xfree(s);
396 }
397
398 void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
399 pa_sink_assert_ref(s);
400 pa_assert(q);
401
402 s->asyncmsgq = q;
403
404 if (s->monitor_source)
405 pa_source_set_asyncmsgq(s->monitor_source, q);
406 }
407
408 void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
409 pa_sink_assert_ref(s);
410 pa_assert(p);
411
412 s->rtpoll = p;
413 if (s->monitor_source)
414 pa_source_set_rtpoll(s->monitor_source, p);
415 }
416
417 int pa_sink_update_status(pa_sink*s) {
418 pa_sink_assert_ref(s);
419 pa_assert(PA_SINK_LINKED(s->state));
420
421 if (s->state == PA_SINK_SUSPENDED)
422 return 0;
423
424 return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
425 }
426
427 int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
428 pa_sink_assert_ref(s);
429 pa_assert(PA_SINK_LINKED(s->state));
430
431 if (suspend)
432 return sink_set_state(s, PA_SINK_SUSPENDED);
433 else
434 return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
435 }
436
437 void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
438 pa_sink_input *i;
439 void *state = NULL;
440 pa_sink_assert_ref(s);
441 pa_assert(PA_SINK_LINKED(s->state));
442
443 if (nbytes <= 0)
444 return;
445
446 pa_log_debug("Processing rewind...");
447
448 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
449 pa_sink_input_assert_ref(i);
450 pa_sink_input_process_rewind(i, nbytes);
451 }
452
453 if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
454 pa_source_process_rewind(s->monitor_source, nbytes);
455 }
456
457 static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxinfo) {
458 pa_sink_input *i;
459 unsigned n = 0;
460 void *state = NULL;
461 size_t mixlength = *length;
462
463 pa_sink_assert_ref(s);
464 pa_assert(info);
465
466 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
467 pa_sink_input_assert_ref(i);
468
469 if (pa_sink_input_peek(i, *length, &info->chunk, &info->volume) < 0)
470 continue;
471
472 if (mixlength == 0 || info->chunk.length < mixlength)
473 mixlength = info->chunk.length;
474
475 if (pa_memblock_is_silence(info->chunk.memblock)) {
476 pa_memblock_unref(info->chunk.memblock);
477 continue;
478 }
479
480 info->userdata = pa_sink_input_ref(i);
481
482 pa_assert(info->chunk.memblock);
483 pa_assert(info->chunk.length > 0);
484
485 info++;
486 n++;
487 maxinfo--;
488 }
489
490 if (mixlength > 0)
491 *length = mixlength;
492
493 return n;
494 }
495
496 static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length) {
497 pa_sink_input *i;
498 void *state = NULL;
499 unsigned p = 0;
500 unsigned n_unreffed = 0;
501
502 pa_sink_assert_ref(s);
503
504 /* We optimize for the case where the order of the inputs has not changed */
505
506 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
507 unsigned j;
508 pa_mix_info* m;
509
510 pa_sink_input_assert_ref(i);
511
512 m = NULL;
513
514 /* Let's try to find the matching entry info the pa_mix_info array */
515 for (j = 0; j < n; j ++) {
516
517 if (info[p].userdata == i) {
518 m = info + p;
519 break;
520 }
521
522 p++;
523 if (p >= n)
524 p = 0;
525 }
526
527 /* Drop read data */
528 pa_sink_input_drop(i, length);
529
530 if (m) {
531 pa_sink_input_unref(m->userdata);
532 m->userdata = NULL;
533 if (m->chunk.memblock)
534 pa_memblock_unref(m->chunk.memblock);
535 pa_memchunk_reset(&m->chunk);
536
537 n_unreffed += 1;
538 }
539 }
540
541 /* Now drop references to entries that are included in the
542 * pa_mix_info array but don't exist anymore */
543
544 if (n_unreffed < n) {
545 for (; n > 0; info++, n--) {
546 if (info->userdata)
547 pa_sink_input_unref(info->userdata);
548 if (info->chunk.memblock)
549 pa_memblock_unref(info->chunk.memblock);
550 }
551 }
552 }
553
554 void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
555 pa_mix_info info[MAX_MIX_CHANNELS];
556 unsigned n;
557 size_t block_size_max;
558
559 pa_sink_assert_ref(s);
560 pa_assert(PA_SINK_OPENED(s->thread_info.state));
561 pa_assert(pa_frame_aligned(length, &s->sample_spec));
562 pa_assert(result);
563
564 pa_sink_ref(s);
565
566 s->thread_info.rewind_nbytes = 0;
567
568 if (length <= 0)
569 length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
570
571 block_size_max = pa_mempool_block_size_max(s->core->mempool);
572 if (length > block_size_max)
573 length = pa_frame_align(block_size_max, &s->sample_spec);
574
575 pa_assert(length > 0);
576
577 n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, &length, info, MAX_MIX_CHANNELS) : 0;
578
579 if (n == 0) {
580
581 *result = s->silence;
582 pa_memblock_ref(result->memblock);
583
584 if (result->length > length)
585 result->length = length;
586
587 } else if (n == 1) {
588 pa_cvolume volume;
589
590 *result = info[0].chunk;
591 pa_memblock_ref(result->memblock);
592
593 if (result->length > length)
594 result->length = length;
595
596 pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
597
598 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) {
599 pa_log("adjusting volume ");
600 pa_memchunk_make_writable(result, 0);
601 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
602 pa_silence_memchunk(result, &s->sample_spec);
603 else
604 pa_volume_memchunk(result, &s->sample_spec, &volume);
605 }
606 } else {
607 void *ptr;
608 result->memblock = pa_memblock_new(s->core->mempool, length);
609
610 ptr = pa_memblock_acquire(result->memblock);
611 result->length = pa_mix(info, n,
612 ptr, length,
613 &s->sample_spec,
614 &s->thread_info.soft_volume,
615 s->thread_info.soft_muted);
616 pa_memblock_release(result->memblock);
617
618 result->index = 0;
619 }
620
621 if (s->thread_info.state == PA_SINK_RUNNING)
622 inputs_drop(s, info, n, result->length);
623
624 if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
625 pa_source_post(s->monitor_source, result);
626
627 pa_sink_unref(s);
628 }
629
630 void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
631 pa_mix_info info[MAX_MIX_CHANNELS];
632 unsigned n;
633 size_t length, block_size_max;
634
635 pa_sink_assert_ref(s);
636 pa_assert(PA_SINK_OPENED(s->thread_info.state));
637 pa_assert(target);
638 pa_assert(target->memblock);
639 pa_assert(target->length > 0);
640 pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
641
642 pa_sink_ref(s);
643
644 s->thread_info.rewind_nbytes = 0;
645
646 length = target->length;
647 block_size_max = pa_mempool_block_size_max(s->core->mempool);
648 if (length > block_size_max)
649 length = pa_frame_align(block_size_max, &s->sample_spec);
650
651 n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, &length, info, MAX_MIX_CHANNELS) : 0;
652
653 if (n == 0) {
654 if (target->length > length)
655 target->length = length;
656
657 pa_silence_memchunk(target, &s->sample_spec);
658 } else if (n == 1) {
659 pa_cvolume volume;
660
661 if (target->length > length)
662 target->length = length;
663
664 pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
665
666 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
667 pa_silence_memchunk(target, &s->sample_spec);
668 else {
669 pa_memchunk vchunk;
670
671 vchunk = info[0].chunk;
672 pa_memblock_ref(vchunk.memblock);
673
674 if (vchunk.length > target->length)
675 vchunk.length = target->length;
676
677 if (!pa_cvolume_is_norm(&volume)) {
678 pa_memchunk_make_writable(&vchunk, 0);
679 pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
680 }
681
682 pa_memchunk_memcpy(target, &vchunk);
683 pa_memblock_unref(vchunk.memblock);
684 }
685
686 } else {
687 void *ptr;
688
689 ptr = pa_memblock_acquire(target->memblock);
690
691 target->length = pa_mix(info, n,
692 (uint8_t*) ptr + target->index, length,
693 &s->sample_spec,
694 &s->thread_info.soft_volume,
695 s->thread_info.soft_muted);
696
697 pa_memblock_release(target->memblock);
698 }
699
700 if (s->thread_info.state == PA_SINK_RUNNING)
701 inputs_drop(s, info, n, target->length);
702
703 if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
704 pa_source_post(s->monitor_source, target);
705
706 pa_sink_unref(s);
707 }
708
709 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
710 pa_memchunk chunk;
711 size_t l, d;
712
713 pa_sink_assert_ref(s);
714 pa_assert(PA_SINK_OPENED(s->thread_info.state));
715 pa_assert(target);
716 pa_assert(target->memblock);
717 pa_assert(target->length > 0);
718 pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
719
720 pa_sink_ref(s);
721
722 s->thread_info.rewind_nbytes = 0;
723
724 l = target->length;
725 d = 0;
726 while (l > 0) {
727 chunk = *target;
728 chunk.index += d;
729 chunk.length -= d;
730
731 pa_sink_render_into(s, &chunk);
732
733 d += chunk.length;
734 l -= chunk.length;
735 }
736
737 pa_sink_unref(s);
738 }
739
740 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
741 pa_sink_assert_ref(s);
742 pa_assert(PA_SINK_OPENED(s->thread_info.state));
743 pa_assert(length > 0);
744 pa_assert(pa_frame_aligned(length, &s->sample_spec));
745 pa_assert(result);
746
747 s->thread_info.rewind_nbytes = 0;
748
749 /*** This needs optimization ***/
750
751 result->index = 0;
752 result->length = length;
753 result->memblock = pa_memblock_new(s->core->mempool, length);
754
755 pa_sink_render_into_full(s, result);
756 }
757
758 void pa_sink_skip(pa_sink *s, size_t length) {
759 pa_sink_input *i;
760 void *state = NULL;
761
762 pa_sink_assert_ref(s);
763 pa_assert(PA_SINK_OPENED(s->thread_info.state));
764 pa_assert(length > 0);
765 pa_assert(pa_frame_aligned(length, &s->sample_spec));
766
767 s->thread_info.rewind_nbytes = 0;
768
769 if (pa_source_used_by(s->monitor_source)) {
770 pa_memchunk chunk;
771
772 /* If something is connected to our monitor source, we have to
773 * pass valid data to it */
774
775 while (length > 0) {
776 pa_sink_render(s, length, &chunk);
777 pa_memblock_unref(chunk.memblock);
778
779 pa_assert(chunk.length <= length);
780 length -= chunk.length;
781 }
782
783 } else {
784 /* Ok, noone cares about the rendered data, so let's not even render it */
785
786 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
787 pa_sink_input_assert_ref(i);
788 pa_sink_input_drop(i, length);
789 }
790 }
791 }
792
793 pa_usec_t pa_sink_get_latency(pa_sink *s) {
794 pa_usec_t usec = 0;
795
796 pa_sink_assert_ref(s);
797 pa_assert(PA_SINK_LINKED(s->state));
798
799 /* The returned value is supposed to be in the time domain of the sound card! */
800
801 if (!PA_SINK_OPENED(s->state))
802 return 0;
803
804 if (s->get_latency)
805 return s->get_latency(s);
806
807 if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
808 return 0;
809
810 return usec;
811 }
812
813 void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) {
814 int changed;
815
816 pa_sink_assert_ref(s);
817 pa_assert(PA_SINK_LINKED(s->state));
818 pa_assert(volume);
819
820 changed = !pa_cvolume_equal(volume, &s->volume);
821 s->volume = *volume;
822
823 if (s->set_volume && s->set_volume(s) < 0)
824 s->set_volume = NULL;
825
826 if (!s->set_volume)
827 pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree);
828
829 if (changed)
830 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
831 }
832
833 const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
834 struct pa_cvolume old_volume;
835
836 pa_sink_assert_ref(s);
837 pa_assert(PA_SINK_LINKED(s->state));
838
839 old_volume = s->volume;
840
841 if (s->get_volume && s->get_volume(s) < 0)
842 s->get_volume = NULL;
843
844 if (!s->get_volume && s->refresh_volume)
845 pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, &s->volume, 0, NULL);
846
847 if (!pa_cvolume_equal(&old_volume, &s->volume))
848 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
849
850 return &s->volume;
851 }
852
853 void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) {
854 int changed;
855
856 pa_sink_assert_ref(s);
857 pa_assert(PA_SINK_LINKED(s->state));
858
859 changed = s->muted != mute;
860 s->muted = mute;
861
862 if (s->set_mute && s->set_mute(s) < 0)
863 s->set_mute = NULL;
864
865 if (!s->set_mute)
866 pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 0, NULL, NULL);
867
868 if (changed)
869 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
870 }
871
872 pa_bool_t pa_sink_get_mute(pa_sink *s) {
873 pa_bool_t old_muted;
874
875 pa_sink_assert_ref(s);
876 pa_assert(PA_SINK_LINKED(s->state));
877
878 old_muted = s->muted;
879
880 if (s->get_mute && s->get_mute(s) < 0)
881 s->get_mute = NULL;
882
883 if (!s->get_mute && s->refresh_mute)
884 pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &s->muted, 0, NULL);
885
886 if (old_muted != s->muted)
887 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
888
889 return s->muted;
890 }
891
892 void pa_sink_set_description(pa_sink *s, const char *description) {
893 const char *old;
894 pa_sink_assert_ref(s);
895
896 if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
897 return;
898
899 old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
900
901 if (old && description && !strcmp(old, description))
902 return;
903
904 if (description)
905 pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
906 else
907 pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
908
909 if (s->monitor_source) {
910 char *n;
911
912 n = pa_sprintf_malloc("Monitor Source of %s", description ? description : s->name);
913 pa_source_set_description(s->monitor_source, n);
914 pa_xfree(n);
915 }
916
917 if (PA_SINK_LINKED(s->state)) {
918 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
919 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
920 }
921 }
922
923 unsigned pa_sink_linked_by(pa_sink *s) {
924 unsigned ret;
925
926 pa_sink_assert_ref(s);
927 pa_assert(PA_SINK_LINKED(s->state));
928
929 ret = pa_idxset_size(s->inputs);
930
931 /* We add in the number of streams connected to us here. Please
932 * not the asymmmetry to pa_sink_used_by()! */
933
934 if (s->monitor_source)
935 ret += pa_source_linked_by(s->monitor_source);
936
937 return ret;
938 }
939
940 unsigned pa_sink_used_by(pa_sink *s) {
941 unsigned ret;
942
943 pa_sink_assert_ref(s);
944 pa_assert(PA_SINK_LINKED(s->state));
945
946 ret = pa_idxset_size(s->inputs);
947 pa_assert(ret >= s->n_corked);
948
949 /* Streams connected to our monitor source do not matter for
950 * pa_sink_used_by()!.*/
951
952 return ret - s->n_corked;
953 }
954
955 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
956 pa_sink *s = PA_SINK(o);
957 pa_sink_assert_ref(s);
958 pa_assert(s->thread_info.state != PA_SINK_UNLINKED);
959
960 switch ((pa_sink_message_t) code) {
961
962 case PA_SINK_MESSAGE_ADD_INPUT: {
963 pa_sink_input *i = PA_SINK_INPUT(userdata);
964
965 pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
966
967 /* Since the caller sleeps in pa_sink_input_put(), we can
968 * safely access data outside of thread_info even though
969 * it is mutable */
970
971 if ((i->thread_info.sync_prev = i->sync_prev)) {
972 pa_assert(i->sink == i->thread_info.sync_prev->sink);
973 pa_assert(i->sync_prev->sync_next == i);
974 i->thread_info.sync_prev->thread_info.sync_next = i;
975 }
976
977 if ((i->thread_info.sync_next = i->sync_next)) {
978 pa_assert(i->sink == i->thread_info.sync_next->sink);
979 pa_assert(i->sync_next->sync_prev == i);
980 i->thread_info.sync_next->thread_info.sync_prev = i;
981 }
982
983 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
984
985 pa_assert(!i->thread_info.attached);
986 i->thread_info.attached = TRUE;
987
988 if (i->attach)
989 i->attach(i);
990
991 /* If you change anything here, make sure to change the
992 * ghost sink input handling a few lines down at
993 * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */
994
995 pa_sink_invalidate_requested_latency(s);
996
997 /* Make sure we're not rewound when the hw buffer is remixed and request a remix*/
998 i->thread_info.ignore_rewind = TRUE;
999 i->thread_info.since_underrun = 0;
1000 pa_sink_request_rewind(s, 0);
1001
1002 return 0;
1003 }
1004
1005 case PA_SINK_MESSAGE_REMOVE_INPUT: {
1006 pa_sink_input *i = PA_SINK_INPUT(userdata);
1007
1008 /* If you change anything here, make sure to change the
1009 * sink input handling a few lines down at
1010 * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */
1011
1012 if (i->detach)
1013 i->detach(i);
1014
1015 pa_assert(i->thread_info.attached);
1016 i->thread_info.attached = FALSE;
1017
1018 /* Since the caller sleeps in pa_sink_input_unlink(),
1019 * we can safely access data outside of thread_info even
1020 * though it is mutable */
1021
1022 pa_assert(!i->thread_info.sync_prev);
1023 pa_assert(!i->thread_info.sync_next);
1024
1025 if (i->thread_info.sync_prev) {
1026 i->thread_info.sync_prev->thread_info.sync_next = i->thread_info.sync_prev->sync_next;
1027 i->thread_info.sync_prev = NULL;
1028 }
1029
1030 if (i->thread_info.sync_next) {
1031 i->thread_info.sync_next->thread_info.sync_prev = i->thread_info.sync_next->sync_prev;
1032 i->thread_info.sync_next = NULL;
1033 }
1034
1035 if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
1036 pa_sink_input_unref(i);
1037
1038 pa_sink_invalidate_requested_latency(s);
1039
1040 pa_sink_request_rewind(s, 0);
1041
1042 return 0;
1043 }
1044
1045 case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: {
1046 pa_sink_input_move_info *info = userdata;
1047 int volume_is_norm;
1048
1049 /* We don't support moving synchronized streams. */
1050 pa_assert(!info->sink_input->sync_prev);
1051 pa_assert(!info->sink_input->sync_next);
1052 pa_assert(!info->sink_input->thread_info.sync_next);
1053 pa_assert(!info->sink_input->thread_info.sync_prev);
1054
1055 if (info->sink_input->detach)
1056 info->sink_input->detach(info->sink_input);
1057
1058 pa_assert(info->sink_input->thread_info.attached);
1059 info->sink_input->thread_info.attached = FALSE;
1060 pa_sink_invalidate_requested_latency(info->sink_input->sink);
1061
1062 if (info->ghost_sink_input) {
1063 pa_assert(info->buffer_bytes > 0);
1064 pa_assert(info->buffer);
1065
1066 volume_is_norm = pa_cvolume_is_norm(&info->sink_input->thread_info.volume);
1067
1068 pa_log_debug("Buffering %lu bytes ...", (unsigned long) info->buffer_bytes);
1069
1070 while (info->buffer_bytes > 0) {
1071 pa_memchunk memchunk;
1072 pa_cvolume volume;
1073 size_t n;
1074
1075 if (pa_sink_input_peek(info->sink_input, info->buffer_bytes, &memchunk, &volume) < 0)
1076 break;
1077
1078 n = memchunk.length > info->buffer_bytes ? info->buffer_bytes : memchunk.length;
1079 pa_sink_input_drop(info->sink_input, n);
1080 memchunk.length = n;
1081
1082 if (!volume_is_norm) {
1083 pa_memchunk_make_writable(&memchunk, 0);
1084 pa_volume_memchunk(&memchunk, &s->sample_spec, &volume);
1085 }
1086
1087 if (pa_memblockq_push(info->buffer, &memchunk) < 0) {
1088 pa_memblock_unref(memchunk.memblock);
1089 break;
1090 }
1091
1092 pa_memblock_unref(memchunk.memblock);
1093 info->buffer_bytes -= n;
1094 }
1095
1096 /* Add the remaining already resampled chunks to the buffer */
1097 pa_memblockq_splice(info->buffer, info->sink_input->thread_info.render_memblockq);
1098
1099 pa_memblockq_sink_input_set_queue(info->ghost_sink_input, info->buffer);
1100
1101 pa_log_debug("Buffered %lu bytes ...", (unsigned long) pa_memblockq_get_length(info->buffer));
1102 }
1103
1104 /* Let's remove the sink input ...*/
1105 if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(info->sink_input->index)))
1106 pa_sink_input_unref(info->sink_input);
1107
1108 /* .. and add the ghost sink input instead */
1109 if (info->ghost_sink_input) {
1110 pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(info->ghost_sink_input->index), pa_sink_input_ref(info->ghost_sink_input));
1111 info->ghost_sink_input->thread_info.sync_prev = info->ghost_sink_input->thread_info.sync_next = NULL;
1112
1113 pa_sink_input_update_max_rewind(info->ghost_sink_input, s->thread_info.max_rewind);
1114
1115 pa_assert(!info->ghost_sink_input->thread_info.attached);
1116 info->ghost_sink_input->thread_info.attached = TRUE;
1117
1118 if (info->ghost_sink_input->attach)
1119 info->ghost_sink_input->attach(info->ghost_sink_input);
1120
1121 }
1122
1123 pa_sink_invalidate_requested_latency(s);
1124
1125 pa_sink_request_rewind(s, 0);
1126
1127 return 0;
1128 }
1129
1130 case PA_SINK_MESSAGE_SET_VOLUME:
1131 s->thread_info.soft_volume = *((pa_cvolume*) userdata);
1132
1133 pa_sink_request_rewind(s, 0);
1134 return 0;
1135
1136 case PA_SINK_MESSAGE_SET_MUTE:
1137 s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata);
1138
1139 pa_sink_request_rewind(s, 0);
1140 return 0;
1141
1142 case PA_SINK_MESSAGE_GET_VOLUME:
1143 *((pa_cvolume*) userdata) = s->thread_info.soft_volume;
1144 return 0;
1145
1146 case PA_SINK_MESSAGE_GET_MUTE:
1147 *((pa_bool_t*) userdata) = s->thread_info.soft_muted;
1148 return 0;
1149
1150 case PA_SINK_MESSAGE_SET_STATE:
1151
1152 s->thread_info.state = PA_PTR_TO_UINT(userdata);
1153 return 0;
1154
1155 case PA_SINK_MESSAGE_DETACH:
1156
1157 /* We're detaching all our input streams so that the
1158 * asyncmsgq and rtpoll fields can be changed without
1159 * problems */
1160 pa_sink_detach_within_thread(s);
1161 return 0;
1162
1163 case PA_SINK_MESSAGE_ATTACH:
1164
1165 /* Reattach all streams */
1166 pa_sink_attach_within_thread(s);
1167 return 0;
1168
1169 case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: {
1170
1171 pa_usec_t *usec = userdata;
1172 *usec = pa_sink_get_requested_latency_within_thread(s);
1173 return 0;
1174 }
1175
1176 case PA_SINK_MESSAGE_GET_LATENCY:
1177 case PA_SINK_MESSAGE_MAX:
1178 ;
1179 }
1180
1181 return -1;
1182 }
1183
1184 int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) {
1185 pa_sink *sink;
1186 uint32_t idx;
1187 int ret = 0;
1188
1189 pa_core_assert_ref(c);
1190
1191 for (sink = PA_SINK(pa_idxset_first(c->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(c->sinks, &idx)))
1192 ret -= pa_sink_suspend(sink, suspend) < 0;
1193
1194 return ret;
1195 }
1196
1197 void pa_sink_detach(pa_sink *s) {
1198 pa_sink_assert_ref(s);
1199 pa_assert(PA_SINK_LINKED(s->state));
1200
1201 pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL);
1202 }
1203
1204 void pa_sink_attach(pa_sink *s) {
1205 pa_sink_assert_ref(s);
1206 pa_assert(PA_SINK_LINKED(s->state));
1207
1208 pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL);
1209 }
1210
1211 void pa_sink_detach_within_thread(pa_sink *s) {
1212 pa_sink_input *i;
1213 void *state = NULL;
1214
1215 pa_sink_assert_ref(s);
1216 pa_assert(PA_SINK_LINKED(s->thread_info.state));
1217
1218 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1219 if (i->detach)
1220 i->detach(i);
1221
1222 if (s->monitor_source)
1223 pa_source_detach_within_thread(s->monitor_source);
1224 }
1225
1226 void pa_sink_attach_within_thread(pa_sink *s) {
1227 pa_sink_input *i;
1228 void *state = NULL;
1229
1230 pa_sink_assert_ref(s);
1231 pa_assert(PA_SINK_LINKED(s->thread_info.state));
1232
1233 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1234 if (i->attach)
1235 i->attach(i);
1236
1237 if (s->monitor_source)
1238 pa_source_attach_within_thread(s->monitor_source);
1239 }
1240
1241 void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
1242 pa_sink_assert_ref(s);
1243 pa_assert(PA_SINK_LINKED(s->thread_info.state));
1244
1245 if (nbytes <= 0)
1246 nbytes = s->thread_info.max_rewind;
1247
1248 nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
1249
1250 if (nbytes <= s->thread_info.rewind_nbytes)
1251 return;
1252
1253 s->thread_info.rewind_nbytes = nbytes;
1254
1255 if (s->request_rewind)
1256 s->request_rewind(s);
1257 }
1258
1259 pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
1260 pa_usec_t result = (pa_usec_t) -1;
1261 pa_sink_input *i;
1262 void *state = NULL;
1263
1264 pa_sink_assert_ref(s);
1265
1266 if (s->thread_info.requested_latency_valid)
1267 return s->thread_info.requested_latency;
1268
1269 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1270
1271 if (i->thread_info.requested_sink_latency != (pa_usec_t) -1 &&
1272 (result == (pa_usec_t) -1 || result > i->thread_info.requested_sink_latency))
1273 result = i->thread_info.requested_sink_latency;
1274
1275 if (result != (pa_usec_t) -1) {
1276 if (s->max_latency > 0 && result > s->max_latency)
1277 result = s->max_latency;
1278
1279 if (s->min_latency > 0 && result < s->min_latency)
1280 result = s->min_latency;
1281 }
1282
1283 s->thread_info.requested_latency = result;
1284 s->thread_info.requested_latency_valid = TRUE;
1285
1286 return result;
1287 }
1288
1289 pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
1290 pa_usec_t usec = 0;
1291
1292 pa_sink_assert_ref(s);
1293 pa_assert(PA_SINK_LINKED(s->state));
1294
1295 if (!PA_SINK_OPENED(s->state))
1296 return 0;
1297
1298 if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) < 0)
1299 return 0;
1300
1301 if (usec == (pa_usec_t) -1)
1302 usec = s->max_latency;
1303
1304 return usec;
1305 }
1306
1307 void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
1308 pa_sink_input *i;
1309 void *state = NULL;
1310
1311 pa_sink_assert_ref(s);
1312
1313 if (max_rewind == s->thread_info.max_rewind)
1314 return;
1315
1316 s->thread_info.max_rewind = max_rewind;
1317
1318 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1319 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1320
1321 if (s->monitor_source)
1322 pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
1323 }
1324
1325 void pa_sink_invalidate_requested_latency(pa_sink *s) {
1326
1327 pa_sink_assert_ref(s);
1328 pa_assert(PA_SINK_LINKED(s->thread_info.state));
1329
1330 if (!s->thread_info.requested_latency_valid)
1331 return;
1332
1333 s->thread_info.requested_latency_valid = FALSE;
1334
1335 if (s->update_requested_latency)
1336 s->update_requested_latency(s);
1337 }