]> code.delx.au - pulseaudio/blob - src/pulsecore/sink.c
rename sink_input->rewind to process_rewind() and set_max_rewind to update_max_rewind()
[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 char *d;
128 const char *name;
129 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
130 pa_source_new_data source_data;
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 = TRUE;
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 d = pa_sprintf_malloc("Monitor Source of %s", s->name);
239 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, d);
240 pa_xfree(d);
241 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
242
243 s->monitor_source = pa_source_new(core, &source_data, 0);
244
245 pa_source_new_data_done(&source_data);
246
247 if (!s->monitor_source) {
248 pa_sink_unlink(s);
249 pa_sink_unref(s);
250 return NULL;
251 }
252
253 s->monitor_source->monitor_of = s;
254 pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
255
256 return s;
257 }
258
259 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
260 int ret;
261 pa_bool_t suspend_change;
262
263 pa_assert(s);
264
265 if (s->state == state)
266 return 0;
267
268 suspend_change =
269 (s->state == PA_SINK_SUSPENDED && PA_SINK_OPENED(state)) ||
270 (PA_SINK_OPENED(s->state) && state == PA_SINK_SUSPENDED);
271
272 if (s->set_state)
273 if ((ret = s->set_state(s, state)) < 0)
274 return -1;
275
276 if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0)
277 return -1;
278
279 s->state = state;
280
281 if (suspend_change) {
282 pa_sink_input *i;
283 uint32_t idx;
284
285 /* We're suspending or resuming, tell everyone about it */
286
287 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx)))
288 if (i->suspend)
289 i->suspend(i, state == PA_SINK_SUSPENDED);
290 }
291
292 if (state != PA_SINK_UNLINKED) /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
293 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
294
295 return 0;
296 }
297
298 void pa_sink_put(pa_sink* s) {
299 pa_sink_assert_ref(s);
300
301 pa_assert(s->state == PA_SINK_INIT);
302 pa_assert(s->asyncmsgq);
303 pa_assert(s->rtpoll);
304
305 pa_assert(!s->min_latency || !s->max_latency || s->min_latency <= s->max_latency);
306
307 if (!(s->flags & PA_SINK_HW_VOLUME_CTRL))
308 s->flags |= PA_SINK_DECIBEL_VOLUME;
309
310 pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
311
312 pa_source_put(s->monitor_source);
313
314 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
315 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s);
316 }
317
318 void pa_sink_unlink(pa_sink* s) {
319 pa_bool_t linked;
320 pa_sink_input *i, *j = NULL;
321
322 pa_assert(s);
323
324 /* Please note that pa_sink_unlink() does more than simply
325 * reversing pa_sink_put(). It also undoes the registrations
326 * already done in pa_sink_new()! */
327
328 /* All operations here shall be idempotent, i.e. pa_sink_unlink()
329 * may be called multiple times on the same sink without bad
330 * effects. */
331
332 linked = PA_SINK_LINKED(s->state);
333
334 if (linked)
335 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
336
337 if (s->state != PA_SINK_UNLINKED)
338 pa_namereg_unregister(s->core, s->name);
339 pa_idxset_remove_by_data(s->core->sinks, s, NULL);
340
341 while ((i = pa_idxset_first(s->inputs, NULL))) {
342 pa_assert(i != j);
343 pa_sink_input_kill(i);
344 j = i;
345 }
346
347 if (linked)
348 sink_set_state(s, PA_SINK_UNLINKED);
349 else
350 s->state = PA_SINK_UNLINKED;
351
352 reset_callbacks(s);
353
354 if (s->monitor_source)
355 pa_source_unlink(s->monitor_source);
356
357 if (linked) {
358 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
359 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
360 }
361 }
362
363 static void sink_free(pa_object *o) {
364 pa_sink *s = PA_SINK(o);
365 pa_sink_input *i;
366
367 pa_assert(s);
368 pa_assert(pa_sink_refcnt(s) == 0);
369
370 if (PA_SINK_LINKED(s->state))
371 pa_sink_unlink(s);
372
373 pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
374
375 if (s->monitor_source) {
376 pa_source_unref(s->monitor_source);
377 s->monitor_source = NULL;
378 }
379
380 pa_idxset_free(s->inputs, NULL, NULL);
381
382 while ((i = pa_hashmap_steal_first(s->thread_info.inputs)))
383 pa_sink_input_unref(i);
384
385 pa_hashmap_free(s->thread_info.inputs, NULL, NULL);
386
387 if (s->silence.memblock)
388 pa_memblock_unref(s->silence.memblock);
389
390 pa_xfree(s->name);
391 pa_xfree(s->driver);
392
393 if (s->proplist)
394 pa_proplist_free(s->proplist);
395
396 pa_xfree(s);
397 }
398
399 void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
400 pa_sink_assert_ref(s);
401 pa_assert(q);
402
403 s->asyncmsgq = q;
404
405 if (s->monitor_source)
406 pa_source_set_asyncmsgq(s->monitor_source, q);
407 }
408
409 void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
410 pa_sink_assert_ref(s);
411 pa_assert(p);
412
413 s->rtpoll = p;
414 if (s->monitor_source)
415 pa_source_set_rtpoll(s->monitor_source, p);
416 }
417
418 int pa_sink_update_status(pa_sink*s) {
419 pa_sink_assert_ref(s);
420 pa_assert(PA_SINK_LINKED(s->state));
421
422 if (s->state == PA_SINK_SUSPENDED)
423 return 0;
424
425 return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
426 }
427
428 int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
429 pa_sink_assert_ref(s);
430 pa_assert(PA_SINK_LINKED(s->state));
431
432 if (suspend)
433 return sink_set_state(s, PA_SINK_SUSPENDED);
434 else
435 return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
436 }
437
438 void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
439 pa_sink_input *i;
440 void *state = NULL;
441 pa_sink_assert_ref(s);
442 pa_assert(PA_SINK_LINKED(s->state));
443
444 if (nbytes <= 0)
445 return;
446
447 pa_log_debug("Processing rewind...");
448
449 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
450 pa_sink_input_assert_ref(i);
451 pa_sink_input_process_rewind(i, nbytes);
452 }
453
454 if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
455 pa_source_process_rewind(s->monitor_source, nbytes);
456 }
457
458 static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxinfo) {
459 pa_sink_input *i;
460 unsigned n = 0;
461 void *state = NULL;
462 size_t mixlength = *length;
463
464 pa_sink_assert_ref(s);
465 pa_assert(info);
466
467 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
468 pa_sink_input_assert_ref(i);
469
470 if (pa_sink_input_peek(i, *length, &info->chunk, &info->volume) < 0)
471 continue;
472
473 if (mixlength == 0 || info->chunk.length < mixlength)
474 mixlength = info->chunk.length;
475
476 if (pa_memblock_is_silence(info->chunk.memblock)) {
477 pa_memblock_unref(info->chunk.memblock);
478 continue;
479 }
480
481 info->userdata = pa_sink_input_ref(i);
482
483 pa_assert(info->chunk.memblock);
484 pa_assert(info->chunk.length > 0);
485
486 info++;
487 n++;
488 maxinfo--;
489 }
490
491 if (mixlength > 0)
492 *length = mixlength;
493
494 return n;
495 }
496
497 static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length) {
498 pa_sink_input *i;
499 void *state = NULL;
500 unsigned p = 0;
501 unsigned n_unreffed = 0;
502
503 pa_sink_assert_ref(s);
504
505 /* We optimize for the case where the order of the inputs has not changed */
506
507 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
508 unsigned j;
509 pa_mix_info* m;
510
511 pa_sink_input_assert_ref(i);
512
513 m = NULL;
514
515 /* Let's try to find the matching entry info the pa_mix_info array */
516 for (j = 0; j < n; j ++) {
517
518 if (info[p].userdata == i) {
519 m = info + p;
520 break;
521 }
522
523 p++;
524 if (p >= n)
525 p = 0;
526 }
527
528 /* Drop read data */
529 pa_sink_input_drop(i, length);
530
531 if (m) {
532 pa_sink_input_unref(m->userdata);
533 m->userdata = NULL;
534 if (m->chunk.memblock)
535 pa_memblock_unref(m->chunk.memblock);
536 pa_memchunk_reset(&m->chunk);
537
538 n_unreffed += 1;
539 }
540 }
541
542 /* Now drop references to entries that are included in the
543 * pa_mix_info array but don't exist anymore */
544
545 if (n_unreffed < n) {
546 for (; n > 0; info++, n--) {
547 if (info->userdata)
548 pa_sink_input_unref(info->userdata);
549 if (info->chunk.memblock)
550 pa_memblock_unref(info->chunk.memblock);
551 }
552 }
553 }
554
555 void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
556 pa_mix_info info[MAX_MIX_CHANNELS];
557 unsigned n;
558 size_t block_size_max;
559
560 pa_sink_assert_ref(s);
561 pa_assert(PA_SINK_OPENED(s->thread_info.state));
562 pa_assert(pa_frame_aligned(length, &s->sample_spec));
563 pa_assert(result);
564
565 pa_sink_ref(s);
566
567 s->thread_info.rewind_nbytes = 0;
568
569 if (length <= 0)
570 length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
571
572 block_size_max = pa_mempool_block_size_max(s->core->mempool);
573 if (length > block_size_max)
574 length = pa_frame_align(block_size_max, &s->sample_spec);
575
576 pa_assert(length > 0);
577
578 n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, &length, info, MAX_MIX_CHANNELS) : 0;
579
580 if (n == 0) {
581
582 *result = s->silence;
583 pa_memblock_ref(result->memblock);
584
585 if (result->length > length)
586 result->length = length;
587
588 } else if (n == 1) {
589 pa_cvolume volume;
590
591 *result = info[0].chunk;
592 pa_memblock_ref(result->memblock);
593
594 if (result->length > length)
595 result->length = length;
596
597 pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
598
599 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) {
600 pa_log("adjusting volume ");
601 pa_memchunk_make_writable(result, 0);
602 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
603 pa_silence_memchunk(result, &s->sample_spec);
604 else
605 pa_volume_memchunk(result, &s->sample_spec, &volume);
606 }
607 } else {
608 void *ptr;
609 result->memblock = pa_memblock_new(s->core->mempool, length);
610
611 ptr = pa_memblock_acquire(result->memblock);
612 result->length = pa_mix(info, n,
613 ptr, length,
614 &s->sample_spec,
615 &s->thread_info.soft_volume,
616 s->thread_info.soft_muted);
617 pa_memblock_release(result->memblock);
618
619 result->index = 0;
620 }
621
622 if (s->thread_info.state == PA_SINK_RUNNING)
623 inputs_drop(s, info, n, result->length);
624
625 if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
626 pa_source_post(s->monitor_source, result);
627
628 pa_sink_unref(s);
629 }
630
631 void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
632 pa_mix_info info[MAX_MIX_CHANNELS];
633 unsigned n;
634 size_t length, block_size_max;
635
636 pa_sink_assert_ref(s);
637 pa_assert(PA_SINK_OPENED(s->thread_info.state));
638 pa_assert(target);
639 pa_assert(target->memblock);
640 pa_assert(target->length > 0);
641 pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
642
643 pa_sink_ref(s);
644
645 s->thread_info.rewind_nbytes = 0;
646
647 length = target->length;
648 block_size_max = pa_mempool_block_size_max(s->core->mempool);
649 if (length > block_size_max)
650 length = pa_frame_align(block_size_max, &s->sample_spec);
651
652 n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, &length, info, MAX_MIX_CHANNELS) : 0;
653
654 if (n == 0) {
655 if (target->length > length)
656 target->length = length;
657
658 pa_silence_memchunk(target, &s->sample_spec);
659 } else if (n == 1) {
660 pa_cvolume volume;
661
662 if (target->length > length)
663 target->length = length;
664
665 pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
666
667 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
668 pa_silence_memchunk(target, &s->sample_spec);
669 else {
670 pa_memchunk vchunk;
671
672 vchunk = info[0].chunk;
673 pa_memblock_ref(vchunk.memblock);
674
675 if (vchunk.length > target->length)
676 vchunk.length = target->length;
677
678 if (!pa_cvolume_is_norm(&volume)) {
679 pa_memchunk_make_writable(&vchunk, 0);
680 pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
681 }
682
683 pa_memchunk_memcpy(target, &vchunk);
684 pa_memblock_unref(vchunk.memblock);
685 }
686
687 } else {
688 void *ptr;
689
690 ptr = pa_memblock_acquire(target->memblock);
691
692 target->length = pa_mix(info, n,
693 (uint8_t*) ptr + target->index, length,
694 &s->sample_spec,
695 &s->thread_info.soft_volume,
696 s->thread_info.soft_muted);
697
698 pa_memblock_release(target->memblock);
699 }
700
701 if (s->thread_info.state == PA_SINK_RUNNING)
702 inputs_drop(s, info, n, target->length);
703
704 if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
705 pa_source_post(s->monitor_source, target);
706
707 pa_sink_unref(s);
708 }
709
710 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
711 pa_memchunk chunk;
712 size_t l, d;
713
714 pa_sink_assert_ref(s);
715 pa_assert(PA_SINK_OPENED(s->thread_info.state));
716 pa_assert(target);
717 pa_assert(target->memblock);
718 pa_assert(target->length > 0);
719 pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
720
721 pa_sink_ref(s);
722
723 s->thread_info.rewind_nbytes = 0;
724
725 l = target->length;
726 d = 0;
727 while (l > 0) {
728 chunk = *target;
729 chunk.index += d;
730 chunk.length -= d;
731
732 pa_sink_render_into(s, &chunk);
733
734 d += chunk.length;
735 l -= chunk.length;
736 }
737
738 pa_sink_unref(s);
739 }
740
741 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
742 pa_sink_assert_ref(s);
743 pa_assert(PA_SINK_OPENED(s->thread_info.state));
744 pa_assert(length > 0);
745 pa_assert(pa_frame_aligned(length, &s->sample_spec));
746 pa_assert(result);
747
748 s->thread_info.rewind_nbytes = 0;
749
750 /*** This needs optimization ***/
751
752 result->index = 0;
753 result->length = length;
754 result->memblock = pa_memblock_new(s->core->mempool, length);
755
756 pa_sink_render_into_full(s, result);
757 }
758
759 void pa_sink_skip(pa_sink *s, size_t length) {
760 pa_sink_input *i;
761 void *state = NULL;
762
763 pa_sink_assert_ref(s);
764 pa_assert(PA_SINK_OPENED(s->thread_info.state));
765 pa_assert(length > 0);
766 pa_assert(pa_frame_aligned(length, &s->sample_spec));
767
768 s->thread_info.rewind_nbytes = 0;
769
770 if (pa_source_used_by(s->monitor_source)) {
771 pa_memchunk chunk;
772
773 /* If something is connected to our monitor source, we have to
774 * pass valid data to it */
775
776 while (length > 0) {
777 pa_sink_render(s, length, &chunk);
778 pa_memblock_unref(chunk.memblock);
779
780 pa_assert(chunk.length <= length);
781 length -= chunk.length;
782 }
783
784 } else {
785 /* Ok, noone cares about the rendered data, so let's not even render it */
786
787 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
788 pa_sink_input_assert_ref(i);
789 pa_sink_input_drop(i, length);
790 }
791 }
792 }
793
794 pa_usec_t pa_sink_get_latency(pa_sink *s) {
795 pa_usec_t usec = 0;
796
797 pa_sink_assert_ref(s);
798 pa_assert(PA_SINK_LINKED(s->state));
799
800 /* The returned value is supposed to be in the time domain of the sound card! */
801
802 if (!PA_SINK_OPENED(s->state))
803 return 0;
804
805 if (s->get_latency)
806 return s->get_latency(s);
807
808 if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
809 return 0;
810
811 return usec;
812 }
813
814 void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) {
815 int changed;
816
817 pa_sink_assert_ref(s);
818 pa_assert(PA_SINK_LINKED(s->state));
819 pa_assert(volume);
820
821 changed = !pa_cvolume_equal(volume, &s->volume);
822 s->volume = *volume;
823
824 if (s->set_volume && s->set_volume(s) < 0)
825 s->set_volume = NULL;
826
827 if (!s->set_volume)
828 pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree);
829
830 if (changed)
831 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
832 }
833
834 const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
835 struct pa_cvolume old_volume;
836
837 pa_sink_assert_ref(s);
838 pa_assert(PA_SINK_LINKED(s->state));
839
840 old_volume = s->volume;
841
842 if (s->get_volume && s->get_volume(s) < 0)
843 s->get_volume = NULL;
844
845 if (!s->get_volume && s->refresh_volume)
846 pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, &s->volume, 0, NULL);
847
848 if (!pa_cvolume_equal(&old_volume, &s->volume))
849 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
850
851 return &s->volume;
852 }
853
854 void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) {
855 int changed;
856
857 pa_sink_assert_ref(s);
858 pa_assert(PA_SINK_LINKED(s->state));
859
860 changed = s->muted != mute;
861 s->muted = mute;
862
863 if (s->set_mute && s->set_mute(s) < 0)
864 s->set_mute = NULL;
865
866 if (!s->set_mute)
867 pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 0, NULL, NULL);
868
869 if (changed)
870 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
871 }
872
873 pa_bool_t pa_sink_get_mute(pa_sink *s) {
874 pa_bool_t old_muted;
875
876 pa_sink_assert_ref(s);
877 pa_assert(PA_SINK_LINKED(s->state));
878
879 old_muted = s->muted;
880
881 if (s->get_mute && s->get_mute(s) < 0)
882 s->get_mute = NULL;
883
884 if (!s->get_mute && s->refresh_mute)
885 pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &s->muted, 0, NULL);
886
887 if (old_muted != s->muted)
888 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
889
890 return s->muted;
891 }
892
893 void pa_sink_set_description(pa_sink *s, const char *description) {
894 const char *old;
895 pa_sink_assert_ref(s);
896
897 if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
898 return;
899
900 old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
901
902 if (old && description && !strcmp(old, description))
903 return;
904
905 if (description)
906 pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
907 else
908 pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
909
910 if (s->monitor_source) {
911 char *n;
912
913 n = pa_sprintf_malloc("Monitor Source of %s", description ? description : s->name);
914 pa_source_set_description(s->monitor_source, n);
915 pa_xfree(n);
916 }
917
918 if (PA_SINK_LINKED(s->state)) {
919 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
920 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
921 }
922 }
923
924 unsigned pa_sink_linked_by(pa_sink *s) {
925 unsigned ret;
926
927 pa_sink_assert_ref(s);
928 pa_assert(PA_SINK_LINKED(s->state));
929
930 ret = pa_idxset_size(s->inputs);
931
932 /* We add in the number of streams connected to us here. Please
933 * not the asymmmetry to pa_sink_used_by()! */
934
935 if (s->monitor_source)
936 ret += pa_source_linked_by(s->monitor_source);
937
938 return ret;
939 }
940
941 unsigned pa_sink_used_by(pa_sink *s) {
942 unsigned ret;
943
944 pa_sink_assert_ref(s);
945 pa_assert(PA_SINK_LINKED(s->state));
946
947 ret = pa_idxset_size(s->inputs);
948 pa_assert(ret >= s->n_corked);
949
950 /* Streams connected to our monitor source do not matter for
951 * pa_sink_used_by()!.*/
952
953 return ret - s->n_corked;
954 }
955
956 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
957 pa_sink *s = PA_SINK(o);
958 pa_sink_assert_ref(s);
959 pa_assert(s->thread_info.state != PA_SINK_UNLINKED);
960
961 switch ((pa_sink_message_t) code) {
962
963 case PA_SINK_MESSAGE_ADD_INPUT: {
964 pa_sink_input *i = PA_SINK_INPUT(userdata);
965
966 pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
967
968 /* Since the caller sleeps in pa_sink_input_put(), we can
969 * safely access data outside of thread_info even though
970 * it is mutable */
971
972 if ((i->thread_info.sync_prev = i->sync_prev)) {
973 pa_assert(i->sink == i->thread_info.sync_prev->sink);
974 pa_assert(i->sync_prev->sync_next == i);
975 i->thread_info.sync_prev->thread_info.sync_next = i;
976 }
977
978 if ((i->thread_info.sync_next = i->sync_next)) {
979 pa_assert(i->sink == i->thread_info.sync_next->sink);
980 pa_assert(i->sync_next->sync_prev == i);
981 i->thread_info.sync_next->thread_info.sync_prev = i;
982 }
983
984 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
985
986 pa_assert(!i->thread_info.attached);
987 i->thread_info.attached = TRUE;
988
989 if (i->attach)
990 i->attach(i);
991
992 /* If you change anything here, make sure to change the
993 * ghost sink input handling a few lines down at
994 * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */
995
996 pa_sink_invalidate_requested_latency(s);
997
998 /* Make sure we're not rewound when the hw buffer is remixed and request a remix*/
999 i->thread_info.ignore_rewind = TRUE;
1000 i->thread_info.since_underrun = 0;
1001 pa_sink_request_rewind(s, 0);
1002
1003 return 0;
1004 }
1005
1006 case PA_SINK_MESSAGE_REMOVE_INPUT: {
1007 pa_sink_input *i = PA_SINK_INPUT(userdata);
1008
1009 /* If you change anything here, make sure to change the
1010 * sink input handling a few lines down at
1011 * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */
1012
1013 if (i->detach)
1014 i->detach(i);
1015
1016 pa_assert(i->thread_info.attached);
1017 i->thread_info.attached = FALSE;
1018
1019 /* Since the caller sleeps in pa_sink_input_unlink(),
1020 * we can safely access data outside of thread_info even
1021 * though it is mutable */
1022
1023 pa_assert(!i->thread_info.sync_prev);
1024 pa_assert(!i->thread_info.sync_next);
1025
1026 if (i->thread_info.sync_prev) {
1027 i->thread_info.sync_prev->thread_info.sync_next = i->thread_info.sync_prev->sync_next;
1028 i->thread_info.sync_prev = NULL;
1029 }
1030
1031 if (i->thread_info.sync_next) {
1032 i->thread_info.sync_next->thread_info.sync_prev = i->thread_info.sync_next->sync_prev;
1033 i->thread_info.sync_next = NULL;
1034 }
1035
1036 if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
1037 pa_sink_input_unref(i);
1038
1039 pa_sink_invalidate_requested_latency(s);
1040
1041 pa_sink_request_rewind(s, 0);
1042
1043 return 0;
1044 }
1045
1046 case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: {
1047 pa_sink_input_move_info *info = userdata;
1048 int volume_is_norm;
1049
1050 /* We don't support moving synchronized streams. */
1051 pa_assert(!info->sink_input->sync_prev);
1052 pa_assert(!info->sink_input->sync_next);
1053 pa_assert(!info->sink_input->thread_info.sync_next);
1054 pa_assert(!info->sink_input->thread_info.sync_prev);
1055
1056 if (info->sink_input->detach)
1057 info->sink_input->detach(info->sink_input);
1058
1059 pa_assert(info->sink_input->thread_info.attached);
1060 info->sink_input->thread_info.attached = FALSE;
1061 pa_sink_invalidate_requested_latency(info->sink_input->sink);
1062
1063 if (info->ghost_sink_input) {
1064 pa_assert(info->buffer_bytes > 0);
1065 pa_assert(info->buffer);
1066
1067 volume_is_norm = pa_cvolume_is_norm(&info->sink_input->thread_info.volume);
1068
1069 pa_log_debug("Buffering %lu bytes ...", (unsigned long) info->buffer_bytes);
1070
1071 while (info->buffer_bytes > 0) {
1072 pa_memchunk memchunk;
1073 pa_cvolume volume;
1074 size_t n;
1075
1076 if (pa_sink_input_peek(info->sink_input, info->buffer_bytes, &memchunk, &volume) < 0)
1077 break;
1078
1079 n = memchunk.length > info->buffer_bytes ? info->buffer_bytes : memchunk.length;
1080 pa_sink_input_drop(info->sink_input, n);
1081 memchunk.length = n;
1082
1083 if (!volume_is_norm) {
1084 pa_memchunk_make_writable(&memchunk, 0);
1085 pa_volume_memchunk(&memchunk, &s->sample_spec, &volume);
1086 }
1087
1088 if (pa_memblockq_push(info->buffer, &memchunk) < 0) {
1089 pa_memblock_unref(memchunk.memblock);
1090 break;
1091 }
1092
1093 pa_memblock_unref(memchunk.memblock);
1094 info->buffer_bytes -= n;
1095 }
1096
1097 /* Add the remaining already resampled chunks to the buffer */
1098 pa_memblockq_splice(info->buffer, info->sink_input->thread_info.render_memblockq);
1099
1100 pa_memblockq_sink_input_set_queue(info->ghost_sink_input, info->buffer);
1101
1102 pa_log_debug("Buffered %lu bytes ...", (unsigned long) pa_memblockq_get_length(info->buffer));
1103 }
1104
1105 /* Let's remove the sink input ...*/
1106 if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(info->sink_input->index)))
1107 pa_sink_input_unref(info->sink_input);
1108
1109 /* .. and add the ghost sink input instead */
1110 if (info->ghost_sink_input) {
1111 pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(info->ghost_sink_input->index), pa_sink_input_ref(info->ghost_sink_input));
1112 info->ghost_sink_input->thread_info.sync_prev = info->ghost_sink_input->thread_info.sync_next = NULL;
1113
1114 pa_sink_input_update_max_rewind(info->ghost_sink_input, s->thread_info.max_rewind);
1115
1116 pa_assert(!info->ghost_sink_input->thread_info.attached);
1117 info->ghost_sink_input->thread_info.attached = TRUE;
1118
1119 if (info->ghost_sink_input->attach)
1120 info->ghost_sink_input->attach(info->ghost_sink_input);
1121
1122 }
1123
1124 pa_sink_invalidate_requested_latency(s);
1125
1126 pa_sink_request_rewind(s, 0);
1127
1128 return 0;
1129 }
1130
1131 case PA_SINK_MESSAGE_SET_VOLUME:
1132 s->thread_info.soft_volume = *((pa_cvolume*) userdata);
1133
1134 pa_sink_request_rewind(s, 0);
1135 return 0;
1136
1137 case PA_SINK_MESSAGE_SET_MUTE:
1138 s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata);
1139
1140 pa_sink_request_rewind(s, 0);
1141 return 0;
1142
1143 case PA_SINK_MESSAGE_GET_VOLUME:
1144 *((pa_cvolume*) userdata) = s->thread_info.soft_volume;
1145 return 0;
1146
1147 case PA_SINK_MESSAGE_GET_MUTE:
1148 *((pa_bool_t*) userdata) = s->thread_info.soft_muted;
1149 return 0;
1150
1151 case PA_SINK_MESSAGE_SET_STATE:
1152
1153 s->thread_info.state = PA_PTR_TO_UINT(userdata);
1154 return 0;
1155
1156 case PA_SINK_MESSAGE_DETACH:
1157
1158 /* We're detaching all our input streams so that the
1159 * asyncmsgq and rtpoll fields can be changed without
1160 * problems */
1161 pa_sink_detach_within_thread(s);
1162 return 0;
1163
1164 case PA_SINK_MESSAGE_ATTACH:
1165
1166 /* Reattach all streams */
1167 pa_sink_attach_within_thread(s);
1168 return 0;
1169
1170 case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: {
1171
1172 pa_usec_t *usec = userdata;
1173 *usec = pa_sink_get_requested_latency_within_thread(s);
1174 return 0;
1175 }
1176
1177 case PA_SINK_MESSAGE_GET_LATENCY:
1178 case PA_SINK_MESSAGE_MAX:
1179 ;
1180 }
1181
1182 return -1;
1183 }
1184
1185 int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) {
1186 pa_sink *sink;
1187 uint32_t idx;
1188 int ret = 0;
1189
1190 pa_core_assert_ref(c);
1191
1192 for (sink = PA_SINK(pa_idxset_first(c->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(c->sinks, &idx)))
1193 ret -= pa_sink_suspend(sink, suspend) < 0;
1194
1195 return ret;
1196 }
1197
1198 void pa_sink_detach(pa_sink *s) {
1199 pa_sink_assert_ref(s);
1200 pa_assert(PA_SINK_LINKED(s->state));
1201
1202 pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL);
1203 }
1204
1205 void pa_sink_attach(pa_sink *s) {
1206 pa_sink_assert_ref(s);
1207 pa_assert(PA_SINK_LINKED(s->state));
1208
1209 pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL);
1210 }
1211
1212 void pa_sink_detach_within_thread(pa_sink *s) {
1213 pa_sink_input *i;
1214 void *state = NULL;
1215
1216 pa_sink_assert_ref(s);
1217 pa_assert(PA_SINK_LINKED(s->thread_info.state));
1218
1219 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1220 if (i->detach)
1221 i->detach(i);
1222
1223 if (s->monitor_source)
1224 pa_source_detach_within_thread(s->monitor_source);
1225 }
1226
1227 void pa_sink_attach_within_thread(pa_sink *s) {
1228 pa_sink_input *i;
1229 void *state = NULL;
1230
1231 pa_sink_assert_ref(s);
1232 pa_assert(PA_SINK_LINKED(s->thread_info.state));
1233
1234 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1235 if (i->attach)
1236 i->attach(i);
1237
1238 if (s->monitor_source)
1239 pa_source_attach_within_thread(s->monitor_source);
1240 }
1241
1242 void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
1243 pa_sink_assert_ref(s);
1244 pa_assert(PA_SINK_LINKED(s->thread_info.state));
1245
1246 if (nbytes <= 0)
1247 nbytes = s->thread_info.max_rewind;
1248
1249 nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
1250
1251 if (nbytes <= s->thread_info.rewind_nbytes)
1252 return;
1253
1254 s->thread_info.rewind_nbytes = nbytes;
1255
1256 if (s->request_rewind)
1257 s->request_rewind(s);
1258 }
1259
1260 pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
1261 pa_usec_t result = 0;
1262 pa_sink_input *i;
1263 void *state = NULL;
1264
1265 pa_sink_assert_ref(s);
1266
1267 if (s->thread_info.requested_latency_valid)
1268 return s->thread_info.requested_latency;
1269
1270 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1271
1272 if (i->thread_info.requested_sink_latency > 0 &&
1273 (!result || result > i->thread_info.requested_sink_latency))
1274 result = i->thread_info.requested_sink_latency;
1275
1276 if (result > 0) {
1277 if (s->max_latency > 0 && result > s->max_latency)
1278 result = s->max_latency;
1279
1280 if (s->min_latency > 0 && result < s->min_latency)
1281 result = s->min_latency;
1282 }
1283
1284 s->thread_info.requested_latency = result;
1285 s->thread_info.requested_latency_valid = TRUE;
1286
1287 return result;
1288 }
1289
1290 pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
1291 pa_usec_t usec = 0;
1292
1293 pa_sink_assert_ref(s);
1294 pa_assert(PA_SINK_LINKED(s->state));
1295
1296 if (!PA_SINK_OPENED(s->state))
1297 return 0;
1298
1299 if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) < 0)
1300 return 0;
1301
1302 return usec;
1303 }
1304
1305 void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
1306 pa_sink_input *i;
1307 void *state = NULL;
1308
1309 pa_sink_assert_ref(s);
1310
1311 if (max_rewind == s->thread_info.max_rewind)
1312 return;
1313
1314 s->thread_info.max_rewind = max_rewind;
1315
1316 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1317 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1318
1319 if (s->monitor_source)
1320 pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
1321 }
1322
1323 void pa_sink_invalidate_requested_latency(pa_sink *s) {
1324
1325 pa_sink_assert_ref(s);
1326 pa_assert(PA_SINK_LINKED(s->thread_info.state));
1327
1328 if (!s->thread_info.requested_latency_valid)
1329 return;
1330
1331 s->thread_info.requested_latency_valid = FALSE;
1332
1333 if (s->update_requested_latency)
1334 s->update_requested_latency(s);
1335 }