2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 #include <pulse/introspect.h>
32 #include <pulse/utf8.h>
33 #include <pulse/xmalloc.h>
34 #include <pulse/timeval.h>
35 #include <pulse/util.h>
36 #include <pulse/i18n.h>
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>
49 #define MAX_MIX_CHANNELS 32
50 #define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
51 #define ABSOLUTE_MIN_LATENCY (500)
52 #define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
53 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
55 static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
57 static void sink_free(pa_object *s);
59 pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data) {
62 memset(data, 0, sizeof(*data));
63 data->proplist = pa_proplist_new();
68 void pa_sink_new_data_set_name(pa_sink_new_data *data, const char *name) {
72 data->name = pa_xstrdup(name);
75 void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_spec *spec) {
78 if ((data->sample_spec_is_set = !!spec))
79 data->sample_spec = *spec;
82 void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map) {
85 if ((data->channel_map_is_set = !!map))
86 data->channel_map = *map;
89 void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume) {
92 if ((data->volume_is_set = !!volume))
93 data->volume = *volume;
96 void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute) {
99 data->muted_is_set = TRUE;
100 data->muted = !!mute;
103 void pa_sink_new_data_done(pa_sink_new_data *data) {
106 pa_xfree(data->name);
107 pa_proplist_free(data->proplist);
110 /* Called from main context */
111 static void reset_callbacks(pa_sink *s) {
115 s->get_volume = NULL;
116 s->set_volume = NULL;
119 s->request_rewind = NULL;
120 s->update_requested_latency = NULL;
123 /* Called from main context */
124 pa_sink* pa_sink_new(
126 pa_sink_new_data *data,
127 pa_sink_flags_t flags) {
131 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
132 pa_source_new_data source_data;
138 pa_assert(data->name);
140 s = pa_msgobject_new(pa_sink);
142 if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) {
147 pa_sink_new_data_set_name(data, name);
149 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW], data) < 0) {
151 pa_namereg_unregister(core, name);
155 pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
156 pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
158 pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
160 if (!data->channel_map_is_set)
161 pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
163 pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
164 pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
166 if (!data->volume_is_set)
167 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
169 pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
170 pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
172 if (!data->muted_is_set)
176 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
178 pa_device_init_description(data->proplist);
179 pa_device_init_icon(data->proplist, TRUE);
181 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {
183 pa_namereg_unregister(core, name);
187 s->parent.parent.free = sink_free;
188 s->parent.process_msg = pa_sink_process_msg;
191 s->state = PA_SINK_INIT;
193 s->name = pa_xstrdup(name);
194 s->proplist = pa_proplist_copy(data->proplist);
195 s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
196 s->module = data->module;
197 s->card = data->card;
199 s->sample_spec = data->sample_spec;
200 s->channel_map = data->channel_map;
202 s->inputs = pa_idxset_new(NULL, NULL);
205 s->virtual_volume = data->volume;
206 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
207 s->base_volume = PA_VOLUME_NORM;
208 s->n_volume_steps = PA_VOLUME_NORM+1;
209 s->muted = data->muted;
210 s->refresh_volume = s->refresh_muted = FALSE;
218 pa_silence_memchunk_get(
219 &core->silence_cache,
225 s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
226 s->thread_info.soft_volume = s->soft_volume;
227 s->thread_info.soft_muted = s->muted;
228 s->thread_info.state = s->state;
229 s->thread_info.rewind_nbytes = 0;
230 s->thread_info.rewind_requested = FALSE;
231 s->thread_info.max_rewind = 0;
232 s->thread_info.max_request = 0;
233 s->thread_info.requested_latency_valid = FALSE;
234 s->thread_info.requested_latency = 0;
235 s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
236 s->thread_info.max_latency = DEFAULT_MIN_LATENCY;
238 pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
241 pa_assert_se(pa_idxset_put(s->card->sinks, s, NULL) >= 0);
243 pt = pa_proplist_to_string_sep(s->proplist, "\n ");
244 pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s\n %s",
247 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
248 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
252 pa_source_new_data_init(&source_data);
253 pa_source_new_data_set_sample_spec(&source_data, &s->sample_spec);
254 pa_source_new_data_set_channel_map(&source_data, &s->channel_map);
255 source_data.name = pa_sprintf_malloc("%s.monitor", name);
256 source_data.driver = data->driver;
257 source_data.module = data->module;
258 source_data.card = data->card;
260 dn = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
261 pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
262 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
264 s->monitor_source = pa_source_new(core, &source_data, PA_SOURCE_LATENCY);
266 pa_source_new_data_done(&source_data);
268 if (!s->monitor_source) {
274 s->monitor_source->monitor_of = s;
276 pa_source_set_latency_range(s->monitor_source, s->thread_info.min_latency, s->thread_info.max_latency);
277 pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
282 /* Called from main context */
283 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
285 pa_bool_t suspend_change;
286 pa_sink_state_t original_state;
290 if (s->state == state)
293 original_state = s->state;
296 (original_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state)) ||
297 (PA_SINK_IS_OPENED(original_state) && state == PA_SINK_SUSPENDED);
300 if ((ret = s->set_state(s, state)) < 0)
304 if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
307 s->set_state(s, original_state);
314 if (state != PA_SINK_UNLINKED) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
315 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
316 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
319 if (suspend_change) {
323 /* We're suspending or resuming, tell everyone about it */
325 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx)))
326 if (s->state == PA_SINK_SUSPENDED &&
327 (i->flags & PA_SINK_INPUT_FAIL_ON_SUSPEND))
328 pa_sink_input_kill(i);
330 i->suspend(i, state == PA_SINK_SUSPENDED);
332 if (s->monitor_source)
333 pa_source_sync_suspend(s->monitor_source);
339 /* Called from main context */
340 void pa_sink_put(pa_sink* s) {
341 pa_sink_assert_ref(s);
343 pa_assert(s->state == PA_SINK_INIT);
345 /* The following fields must be initialized properly when calling _put() */
346 pa_assert(s->asyncmsgq);
347 pa_assert(s->rtpoll);
348 pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
350 if (!(s->flags & PA_SINK_HW_VOLUME_CTRL)) {
351 s->flags |= PA_SINK_DECIBEL_VOLUME;
353 s->thread_info.soft_volume = s->soft_volume;
354 s->thread_info.soft_muted = s->muted;
357 if (s->flags & PA_SINK_DECIBEL_VOLUME)
358 s->n_volume_steps = PA_VOLUME_NORM+1;
360 if (s->core->flat_volumes)
361 if (s->flags & PA_SINK_DECIBEL_VOLUME)
362 s->flags |= PA_SINK_FLAT_VOLUME;
364 pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
366 pa_source_put(s->monitor_source);
368 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
369 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s);
372 /* Called from main context */
373 void pa_sink_unlink(pa_sink* s) {
375 pa_sink_input *i, *j = NULL;
379 /* Please note that pa_sink_unlink() does more than simply
380 * reversing pa_sink_put(). It also undoes the registrations
381 * already done in pa_sink_new()! */
383 /* All operations here shall be idempotent, i.e. pa_sink_unlink()
384 * may be called multiple times on the same sink without bad
387 linked = PA_SINK_IS_LINKED(s->state);
390 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
392 if (s->state != PA_SINK_UNLINKED)
393 pa_namereg_unregister(s->core, s->name);
394 pa_idxset_remove_by_data(s->core->sinks, s, NULL);
397 pa_idxset_remove_by_data(s->card->sinks, s, NULL);
399 while ((i = pa_idxset_first(s->inputs, NULL))) {
401 pa_sink_input_kill(i);
406 sink_set_state(s, PA_SINK_UNLINKED);
408 s->state = PA_SINK_UNLINKED;
412 if (s->monitor_source)
413 pa_source_unlink(s->monitor_source);
416 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
417 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
421 /* Called from main context */
422 static void sink_free(pa_object *o) {
423 pa_sink *s = PA_SINK(o);
427 pa_assert(pa_sink_refcnt(s) == 0);
429 if (PA_SINK_IS_LINKED(s->state))
432 pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
434 if (s->monitor_source) {
435 pa_source_unref(s->monitor_source);
436 s->monitor_source = NULL;
439 pa_idxset_free(s->inputs, NULL, NULL);
441 while ((i = pa_hashmap_steal_first(s->thread_info.inputs)))
442 pa_sink_input_unref(i);
444 pa_hashmap_free(s->thread_info.inputs, NULL, NULL);
446 if (s->silence.memblock)
447 pa_memblock_unref(s->silence.memblock);
453 pa_proplist_free(s->proplist);
458 /* Called from main context */
459 void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
460 pa_sink_assert_ref(s);
464 if (s->monitor_source)
465 pa_source_set_asyncmsgq(s->monitor_source, q);
468 /* Called from main context */
469 void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
470 pa_sink_assert_ref(s);
473 if (s->monitor_source)
474 pa_source_set_rtpoll(s->monitor_source, p);
477 /* Called from main context */
478 int pa_sink_update_status(pa_sink*s) {
479 pa_sink_assert_ref(s);
480 pa_assert(PA_SINK_IS_LINKED(s->state));
482 if (s->state == PA_SINK_SUSPENDED)
485 return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
488 /* Called from main context */
489 int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
490 pa_sink_assert_ref(s);
491 pa_assert(PA_SINK_IS_LINKED(s->state));
494 return sink_set_state(s, PA_SINK_SUSPENDED);
496 return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
499 /* Called from main context */
500 pa_queue *pa_sink_move_all_start(pa_sink *s) {
502 pa_sink_input *i, *n;
505 pa_sink_assert_ref(s);
506 pa_assert(PA_SINK_IS_LINKED(s->state));
510 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = n) {
511 n = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx));
513 if (pa_sink_input_start_move(i) >= 0)
514 pa_queue_push(q, pa_sink_input_ref(i));
520 /* Called from main context */
521 void pa_sink_move_all_finish(pa_sink *s, pa_queue *q, pa_bool_t save) {
524 pa_sink_assert_ref(s);
525 pa_assert(PA_SINK_IS_LINKED(s->state));
528 while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
529 if (pa_sink_input_finish_move(i, s, save) < 0)
530 pa_sink_input_kill(i);
532 pa_sink_input_unref(i);
535 pa_queue_free(q, NULL, NULL);
538 /* Called from main context */
539 void pa_sink_move_all_fail(pa_queue *q) {
543 while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
544 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_OK) {
545 pa_sink_input_kill(i);
546 pa_sink_input_unref(i);
550 pa_queue_free(q, NULL, NULL);
553 /* Called from IO thread context */
554 void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
557 pa_sink_assert_ref(s);
558 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
560 /* If nobody requested this and this is actually no real rewind
561 * then we can short cut this */
562 if (!s->thread_info.rewind_requested && nbytes <= 0)
565 s->thread_info.rewind_nbytes = 0;
566 s->thread_info.rewind_requested = FALSE;
568 if (s->thread_info.state == PA_SINK_SUSPENDED)
572 pa_log_debug("Processing rewind...");
574 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
575 pa_sink_input_assert_ref(i);
576 pa_sink_input_process_rewind(i, nbytes);
580 if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
581 pa_source_process_rewind(s->monitor_source, nbytes);
584 /* Called from IO thread context */
585 static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxinfo) {
589 size_t mixlength = *length;
591 pa_sink_assert_ref(s);
594 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
595 pa_sink_input_assert_ref(i);
597 pa_sink_input_peek(i, *length, &info->chunk, &info->volume);
599 if (mixlength == 0 || info->chunk.length < mixlength)
600 mixlength = info->chunk.length;
602 if (pa_memblock_is_silence(info->chunk.memblock)) {
603 pa_memblock_unref(info->chunk.memblock);
607 info->userdata = pa_sink_input_ref(i);
609 pa_assert(info->chunk.memblock);
610 pa_assert(info->chunk.length > 0);
623 /* Called from IO thread context */
624 static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *result) {
628 unsigned n_unreffed = 0;
630 pa_sink_assert_ref(s);
632 pa_assert(result->memblock);
633 pa_assert(result->length > 0);
635 /* We optimize for the case where the order of the inputs has not changed */
637 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
639 pa_mix_info* m = NULL;
641 pa_sink_input_assert_ref(i);
643 /* Let's try to find the matching entry info the pa_mix_info array */
644 for (j = 0; j < n; j ++) {
646 if (info[p].userdata == i) {
657 pa_sink_input_drop(i, result->length);
659 if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state)) {
661 if (pa_hashmap_size(i->thread_info.direct_outputs) > 0) {
666 if (m && m->chunk.memblock) {
668 pa_memblock_ref(c.memblock);
669 pa_assert(result->length <= c.length);
670 c.length = result->length;
672 pa_memchunk_make_writable(&c, 0);
673 pa_volume_memchunk(&c, &s->sample_spec, &m->volume);
676 pa_memblock_ref(c.memblock);
677 pa_assert(result->length <= c.length);
678 c.length = result->length;
681 while ((o = pa_hashmap_iterate(i->thread_info.direct_outputs, &ostate, NULL))) {
682 pa_source_output_assert_ref(o);
683 pa_assert(o->direct_on_input == i);
684 pa_source_post_direct(s->monitor_source, o, &c);
687 pa_memblock_unref(c.memblock);
692 if (m->chunk.memblock)
693 pa_memblock_unref(m->chunk.memblock);
694 pa_memchunk_reset(&m->chunk);
696 pa_sink_input_unref(m->userdata);
703 /* Now drop references to entries that are included in the
704 * pa_mix_info array but don't exist anymore */
706 if (n_unreffed < n) {
707 for (; n > 0; info++, n--) {
709 pa_sink_input_unref(info->userdata);
710 if (info->chunk.memblock)
711 pa_memblock_unref(info->chunk.memblock);
715 if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
716 pa_source_post(s->monitor_source, result);
719 /* Called from IO thread context */
720 void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
721 pa_mix_info info[MAX_MIX_CHANNELS];
723 size_t block_size_max;
725 pa_sink_assert_ref(s);
726 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
727 pa_assert(pa_frame_aligned(length, &s->sample_spec));
732 pa_assert(!s->thread_info.rewind_requested);
733 pa_assert(s->thread_info.rewind_nbytes == 0);
735 if (s->thread_info.state == PA_SINK_SUSPENDED) {
736 result->memblock = pa_memblock_ref(s->silence.memblock);
737 result->index = s->silence.index;
738 result->length = PA_MIN(s->silence.length, length);
743 length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
745 block_size_max = pa_mempool_block_size_max(s->core->mempool);
746 if (length > block_size_max)
747 length = pa_frame_align(block_size_max, &s->sample_spec);
749 pa_assert(length > 0);
751 n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
755 *result = s->silence;
756 pa_memblock_ref(result->memblock);
758 if (result->length > length)
759 result->length = length;
764 *result = info[0].chunk;
765 pa_memblock_ref(result->memblock);
767 if (result->length > length)
768 result->length = length;
770 pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
772 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) {
773 pa_memchunk_make_writable(result, 0);
774 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
775 pa_silence_memchunk(result, &s->sample_spec);
777 pa_volume_memchunk(result, &s->sample_spec, &volume);
781 result->memblock = pa_memblock_new(s->core->mempool, length);
783 ptr = pa_memblock_acquire(result->memblock);
784 result->length = pa_mix(info, n,
787 &s->thread_info.soft_volume,
788 s->thread_info.soft_muted);
789 pa_memblock_release(result->memblock);
794 inputs_drop(s, info, n, result);
799 /* Called from IO thread context */
800 void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
801 pa_mix_info info[MAX_MIX_CHANNELS];
803 size_t length, block_size_max;
805 pa_sink_assert_ref(s);
806 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
808 pa_assert(target->memblock);
809 pa_assert(target->length > 0);
810 pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
814 pa_assert(!s->thread_info.rewind_requested);
815 pa_assert(s->thread_info.rewind_nbytes == 0);
817 if (s->thread_info.state == PA_SINK_SUSPENDED) {
818 pa_silence_memchunk(target, &s->sample_spec);
822 length = target->length;
823 block_size_max = pa_mempool_block_size_max(s->core->mempool);
824 if (length > block_size_max)
825 length = pa_frame_align(block_size_max, &s->sample_spec);
827 pa_assert(length > 0);
829 n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
832 if (target->length > length)
833 target->length = length;
835 pa_silence_memchunk(target, &s->sample_spec);
839 if (target->length > length)
840 target->length = length;
842 pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
844 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
845 pa_silence_memchunk(target, &s->sample_spec);
849 vchunk = info[0].chunk;
850 pa_memblock_ref(vchunk.memblock);
852 if (vchunk.length > length)
853 vchunk.length = length;
855 if (!pa_cvolume_is_norm(&volume)) {
856 pa_memchunk_make_writable(&vchunk, 0);
857 pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
860 pa_memchunk_memcpy(target, &vchunk);
861 pa_memblock_unref(vchunk.memblock);
867 ptr = pa_memblock_acquire(target->memblock);
869 target->length = pa_mix(info, n,
870 (uint8_t*) ptr + target->index, length,
872 &s->thread_info.soft_volume,
873 s->thread_info.soft_muted);
875 pa_memblock_release(target->memblock);
878 inputs_drop(s, info, n, target);
883 /* Called from IO thread context */
884 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
888 pa_sink_assert_ref(s);
889 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
891 pa_assert(target->memblock);
892 pa_assert(target->length > 0);
893 pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
897 pa_assert(!s->thread_info.rewind_requested);
898 pa_assert(s->thread_info.rewind_nbytes == 0);
907 pa_sink_render_into(s, &chunk);
916 /* Called from IO thread context */
917 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
918 pa_sink_assert_ref(s);
919 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
920 pa_assert(length > 0);
921 pa_assert(pa_frame_aligned(length, &s->sample_spec));
924 pa_assert(!s->thread_info.rewind_requested);
925 pa_assert(s->thread_info.rewind_nbytes == 0);
927 /*** This needs optimization ***/
930 result->length = length;
931 result->memblock = pa_memblock_new(s->core->mempool, length);
933 pa_sink_render_into_full(s, result);
936 /* Called from main thread */
937 pa_usec_t pa_sink_get_latency(pa_sink *s) {
940 pa_sink_assert_ref(s);
941 pa_assert(PA_SINK_IS_LINKED(s->state));
943 /* The returned value is supposed to be in the time domain of the sound card! */
945 if (s->state == PA_SINK_SUSPENDED)
948 if (!(s->flags & PA_SINK_LATENCY))
951 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
956 /* Called from main thread */
957 void pa_sink_update_flat_volume(pa_sink *s, pa_cvolume *new_volume) {
961 pa_sink_assert_ref(s);
962 pa_assert(new_volume);
963 pa_assert(PA_SINK_IS_LINKED(s->state));
964 pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
966 /* This is called whenever a sink input volume changes and we
967 * might need to fix up the sink volume accordingly. Please note
968 * that we don't actually update the sinks volume here, we only
969 * return how it needs to be updated. The caller should then call
970 * pa_sink_set_flat_volume().*/
972 if (pa_idxset_isempty(s->inputs)) {
973 /* In the special case that we have no sink input we leave the
974 * volume unmodified. */
975 *new_volume = s->virtual_volume;
979 pa_cvolume_mute(new_volume, s->channel_map.channels);
981 /* First let's determine the new maximum volume of all inputs
982 * connected to this sink */
983 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
985 pa_cvolume remapped_volume;
987 remapped_volume = i->virtual_volume;
988 pa_cvolume_remap(&remapped_volume, &i->channel_map, &s->channel_map);
990 for (c = 0; c < new_volume->channels; c++)
991 if (remapped_volume.values[c] > new_volume->values[c])
992 new_volume->values[c] = remapped_volume.values[c];
995 /* Then, let's update the soft volumes of all inputs connected
997 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
998 pa_cvolume remapped_new_volume;
1000 remapped_new_volume = *new_volume;
1001 pa_cvolume_remap(&remapped_new_volume, &s->channel_map, &i->channel_map);
1002 pa_sw_cvolume_divide(&i->soft_volume, &i->virtual_volume, &remapped_new_volume);
1003 pa_sw_cvolume_multiply(&i->soft_volume, &i->soft_volume, &i->volume_factor);
1005 /* Hooks have the ability to play games with i->soft_volume */
1006 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], i);
1008 /* We don't issue PA_SINK_INPUT_MESSAGE_SET_VOLUME because
1009 * we want the update to have atomically with the sink
1010 * volume update, hence we do it within the
1011 * pa_sink_set_flat_volume() call below*/
1015 /* Called from main thread */
1016 void pa_sink_propagate_flat_volume(pa_sink *s, const pa_cvolume *old_volume) {
1020 pa_sink_assert_ref(s);
1021 pa_assert(old_volume);
1022 pa_assert(PA_SINK_IS_LINKED(s->state));
1023 pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
1025 /* This is called whenever the sink volume changes that is not
1026 * caused by a sink input volume change. We need to fix up the
1027 * sink input volumes accordingly */
1029 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
1030 pa_cvolume remapped_old_volume, remapped_new_volume, fixed_volume;
1033 remapped_new_volume = s->virtual_volume;
1034 pa_cvolume_remap(&remapped_new_volume, &s->channel_map, &i->channel_map);
1036 remapped_old_volume = *old_volume;
1037 pa_cvolume_remap(&remapped_old_volume, &s->channel_map, &i->channel_map);
1039 for (c = 0; c < i->sample_spec.channels; c++)
1041 if (remapped_old_volume.values[c] == PA_VOLUME_MUTED)
1042 fixed_volume.values[c] = PA_VOLUME_MUTED;
1044 fixed_volume.values[c] = (pa_volume_t)
1045 ((uint64_t) i->virtual_volume.values[c] *
1046 (uint64_t) remapped_new_volume.values[c] /
1047 (uint64_t) remapped_old_volume.values[c]);
1049 fixed_volume.channels = i->virtual_volume.channels;
1051 if (!pa_cvolume_equal(&fixed_volume, &i->virtual_volume)) {
1052 i->virtual_volume = fixed_volume;
1054 /* The virtual volume changed, let's tell people so */
1055 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1060 /* Called from main thread */
1061 void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg) {
1062 pa_cvolume old_virtual_volume;
1063 pa_bool_t virtual_volume_changed;
1065 pa_sink_assert_ref(s);
1066 pa_assert(PA_SINK_IS_LINKED(s->state));
1068 pa_assert(pa_cvolume_valid(volume));
1069 pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
1071 old_virtual_volume = s->virtual_volume;
1072 s->virtual_volume = *volume;
1073 virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume);
1075 /* Propagate this volume change back to the inputs */
1076 if (virtual_volume_changed)
1077 if (propagate && (s->flags & PA_SINK_FLAT_VOLUME))
1078 pa_sink_propagate_flat_volume(s, &old_virtual_volume);
1080 if (s->set_volume) {
1081 /* If we have a function set_volume(), then we do not apply a
1082 * soft volume by default. However, set_volume() is apply one
1083 * to s->soft_volume */
1085 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
1089 /* If we have no function set_volume(), then the soft volume
1090 * becomes the virtual volume */
1091 s->soft_volume = s->virtual_volume;
1093 /* This tells the sink that soft and/or virtual volume changed */
1095 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
1097 if (virtual_volume_changed)
1098 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1101 /* Called from main thread. Only to be called by sink implementor */
1102 void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) {
1103 pa_sink_assert_ref(s);
1106 s->soft_volume = *volume;
1108 if (PA_SINK_IS_LINKED(s->state))
1109 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
1111 s->thread_info.soft_volume = *volume;
1114 /* Called from main thread */
1115 const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) {
1116 pa_sink_assert_ref(s);
1118 if (s->refresh_volume || force_refresh) {
1119 struct pa_cvolume old_virtual_volume = s->virtual_volume;
1124 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
1126 if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume)) {
1128 if (s->flags & PA_SINK_FLAT_VOLUME)
1129 pa_sink_propagate_flat_volume(s, &old_virtual_volume);
1131 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1135 return &s->virtual_volume;
1138 /* Called from main thread */
1139 void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume) {
1140 pa_sink_assert_ref(s);
1142 /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1144 if (pa_cvolume_equal(&s->virtual_volume, new_volume))
1147 s->virtual_volume = *new_volume;
1148 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1151 /* Called from main thread */
1152 void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) {
1153 pa_bool_t old_muted;
1155 pa_sink_assert_ref(s);
1156 pa_assert(PA_SINK_IS_LINKED(s->state));
1158 old_muted = s->muted;
1164 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
1166 if (old_muted != s->muted)
1167 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1170 /* Called from main thread */
1171 pa_bool_t pa_sink_get_mute(pa_sink *s, pa_bool_t force_refresh) {
1173 pa_sink_assert_ref(s);
1175 if (s->refresh_muted || force_refresh) {
1176 pa_bool_t old_muted = s->muted;
1181 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
1183 if (old_muted != s->muted)
1184 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1190 /* Called from main thread */
1191 void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted) {
1192 pa_sink_assert_ref(s);
1194 /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1196 if (s->muted == new_muted)
1199 s->muted = new_muted;
1200 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1203 /* Called from main thread */
1204 pa_bool_t pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p) {
1206 pa_sink_assert_ref(s);
1209 pa_proplist_update(s->proplist, mode, p);
1211 if (PA_SINK_IS_LINKED(s->state)) {
1212 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
1213 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1219 /* Called from main thread */
1220 void pa_sink_set_description(pa_sink *s, const char *description) {
1222 pa_sink_assert_ref(s);
1224 if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
1227 old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
1229 if (old && description && !strcmp(old, description))
1233 pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
1235 pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
1237 if (s->monitor_source) {
1240 n = pa_sprintf_malloc("Monitor Source of %s", description ? description : s->name);
1241 pa_source_set_description(s->monitor_source, n);
1245 if (PA_SINK_IS_LINKED(s->state)) {
1246 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1247 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
1251 /* Called from main thread */
1252 unsigned pa_sink_linked_by(pa_sink *s) {
1255 pa_sink_assert_ref(s);
1256 pa_assert(PA_SINK_IS_LINKED(s->state));
1258 ret = pa_idxset_size(s->inputs);
1260 /* We add in the number of streams connected to us here. Please
1261 * note the asymmmetry to pa_sink_used_by()! */
1263 if (s->monitor_source)
1264 ret += pa_source_linked_by(s->monitor_source);
1269 /* Called from main thread */
1270 unsigned pa_sink_used_by(pa_sink *s) {
1273 pa_sink_assert_ref(s);
1274 pa_assert(PA_SINK_IS_LINKED(s->state));
1276 ret = pa_idxset_size(s->inputs);
1277 pa_assert(ret >= s->n_corked);
1279 /* Streams connected to our monitor source do not matter for
1280 * pa_sink_used_by()!.*/
1282 return ret - s->n_corked;
1285 /* Called from main thread */
1286 unsigned pa_sink_check_suspend(pa_sink *s) {
1291 pa_sink_assert_ref(s);
1293 if (!PA_SINK_IS_LINKED(s->state))
1298 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
1299 pa_sink_input_state_t st;
1301 st = pa_sink_input_get_state(i);
1302 pa_assert(PA_SINK_INPUT_IS_LINKED(st));
1304 if (st == PA_SINK_INPUT_CORKED)
1307 if (i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND)
1313 if (s->monitor_source)
1314 ret += pa_source_check_suspend(s->monitor_source);
1319 /* Called from the IO thread */
1320 static void sync_input_volumes_within_thread(pa_sink *s) {
1324 pa_sink_assert_ref(s);
1326 while ((i = PA_SINK_INPUT(pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))) {
1327 if (pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume))
1330 i->thread_info.soft_volume = i->soft_volume;
1331 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1335 /* Called from IO thread, except when it is not */
1336 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1337 pa_sink *s = PA_SINK(o);
1338 pa_sink_assert_ref(s);
1340 switch ((pa_sink_message_t) code) {
1342 case PA_SINK_MESSAGE_ADD_INPUT: {
1343 pa_sink_input *i = PA_SINK_INPUT(userdata);
1345 /* If you change anything here, make sure to change the
1346 * sink input handling a few lines down at
1347 * PA_SINK_MESSAGE_FINISH_MOVE, too. */
1349 pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
1351 /* Since the caller sleeps in pa_sink_input_put(), we can
1352 * safely access data outside of thread_info even though
1355 if ((i->thread_info.sync_prev = i->sync_prev)) {
1356 pa_assert(i->sink == i->thread_info.sync_prev->sink);
1357 pa_assert(i->sync_prev->sync_next == i);
1358 i->thread_info.sync_prev->thread_info.sync_next = i;
1361 if ((i->thread_info.sync_next = i->sync_next)) {
1362 pa_assert(i->sink == i->thread_info.sync_next->sink);
1363 pa_assert(i->sync_next->sync_prev == i);
1364 i->thread_info.sync_next->thread_info.sync_prev = i;
1367 pa_assert(!i->thread_info.attached);
1368 i->thread_info.attached = TRUE;
1373 pa_sink_input_set_state_within_thread(i, i->state);
1375 /* The requested latency of the sink input needs to be
1376 * fixed up and then configured on the sink */
1378 if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
1379 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
1381 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1382 pa_sink_input_update_max_request(i, s->thread_info.max_request);
1384 /* We don't rewind here automatically. This is left to the
1385 * sink input implementor because some sink inputs need a
1386 * slow start, i.e. need some time to buffer client
1387 * samples before beginning streaming. */
1389 /* In flat volume mode we need to update the volume as
1391 return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1394 case PA_SINK_MESSAGE_REMOVE_INPUT: {
1395 pa_sink_input *i = PA_SINK_INPUT(userdata);
1397 /* If you change anything here, make sure to change the
1398 * sink input handling a few lines down at
1399 * PA_SINK_MESSAGE_PREPAPRE_MOVE, too. */
1404 pa_sink_input_set_state_within_thread(i, i->state);
1406 pa_assert(i->thread_info.attached);
1407 i->thread_info.attached = FALSE;
1409 /* Since the caller sleeps in pa_sink_input_unlink(),
1410 * we can safely access data outside of thread_info even
1411 * though it is mutable */
1413 pa_assert(!i->sync_prev);
1414 pa_assert(!i->sync_next);
1416 if (i->thread_info.sync_prev) {
1417 i->thread_info.sync_prev->thread_info.sync_next = i->thread_info.sync_prev->sync_next;
1418 i->thread_info.sync_prev = NULL;
1421 if (i->thread_info.sync_next) {
1422 i->thread_info.sync_next->thread_info.sync_prev = i->thread_info.sync_next->sync_prev;
1423 i->thread_info.sync_next = NULL;
1426 if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
1427 pa_sink_input_unref(i);
1429 pa_sink_invalidate_requested_latency(s);
1430 pa_sink_request_rewind(s, (size_t) -1);
1432 /* In flat volume mode we need to update the volume as
1434 return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1437 case PA_SINK_MESSAGE_START_MOVE: {
1438 pa_sink_input *i = PA_SINK_INPUT(userdata);
1440 /* We don't support moving synchronized streams. */
1441 pa_assert(!i->sync_prev);
1442 pa_assert(!i->sync_next);
1443 pa_assert(!i->thread_info.sync_next);
1444 pa_assert(!i->thread_info.sync_prev);
1446 if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
1448 size_t sink_nbytes, total_nbytes;
1450 /* Get the latency of the sink */
1451 if (!(s->flags & PA_SINK_LATENCY) ||
1452 PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
1455 sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
1456 total_nbytes = sink_nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq);
1458 if (total_nbytes > 0) {
1459 i->thread_info.rewrite_nbytes = i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, total_nbytes) : total_nbytes;
1460 i->thread_info.rewrite_flush = TRUE;
1461 pa_sink_input_process_rewind(i, sink_nbytes);
1468 pa_assert(i->thread_info.attached);
1469 i->thread_info.attached = FALSE;
1471 /* Let's remove the sink input ...*/
1472 if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
1473 pa_sink_input_unref(i);
1475 pa_sink_invalidate_requested_latency(s);
1477 pa_log_debug("Requesting rewind due to started move");
1478 pa_sink_request_rewind(s, (size_t) -1);
1480 /* In flat volume mode we need to update the volume as
1482 return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1485 case PA_SINK_MESSAGE_FINISH_MOVE: {
1486 pa_sink_input *i = PA_SINK_INPUT(userdata);
1488 /* We don't support moving synchronized streams. */
1489 pa_assert(!i->sync_prev);
1490 pa_assert(!i->sync_next);
1491 pa_assert(!i->thread_info.sync_next);
1492 pa_assert(!i->thread_info.sync_prev);
1494 pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
1496 pa_assert(!i->thread_info.attached);
1497 i->thread_info.attached = TRUE;
1502 if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
1503 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
1505 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1506 pa_sink_input_update_max_request(i, s->thread_info.max_request);
1508 if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
1512 /* Get the latency of the sink */
1513 if (!(s->flags & PA_SINK_LATENCY) ||
1514 PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
1517 nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
1520 pa_sink_input_drop(i, nbytes);
1522 pa_log_debug("Requesting rewind due to finished move");
1523 pa_sink_request_rewind(s, nbytes);
1526 /* In flat volume mode we need to update the volume as
1528 return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1531 case PA_SINK_MESSAGE_SET_VOLUME:
1533 if (!pa_cvolume_equal(&s->thread_info.soft_volume, &s->soft_volume)) {
1534 s->thread_info.soft_volume = s->soft_volume;
1535 pa_sink_request_rewind(s, (size_t) -1);
1538 if (s->flags & PA_SINK_FLAT_VOLUME)
1539 sync_input_volumes_within_thread(s);
1543 case PA_SINK_MESSAGE_GET_VOLUME:
1546 case PA_SINK_MESSAGE_SET_MUTE:
1548 if (s->thread_info.soft_muted != s->muted) {
1549 s->thread_info.soft_muted = s->muted;
1550 pa_sink_request_rewind(s, (size_t) -1);
1555 case PA_SINK_MESSAGE_GET_MUTE:
1558 case PA_SINK_MESSAGE_SET_STATE:
1560 s->thread_info.state = PA_PTR_TO_UINT(userdata);
1562 if (s->thread_info.state == PA_SINK_SUSPENDED) {
1563 s->thread_info.rewind_nbytes = 0;
1564 s->thread_info.rewind_requested = FALSE;
1569 case PA_SINK_MESSAGE_DETACH:
1571 /* Detach all streams */
1572 pa_sink_detach_within_thread(s);
1575 case PA_SINK_MESSAGE_ATTACH:
1577 /* Reattach all streams */
1578 pa_sink_attach_within_thread(s);
1581 case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: {
1583 pa_usec_t *usec = userdata;
1584 *usec = pa_sink_get_requested_latency_within_thread(s);
1586 if (*usec == (pa_usec_t) -1)
1587 *usec = s->thread_info.max_latency;
1592 case PA_SINK_MESSAGE_SET_LATENCY_RANGE: {
1593 pa_usec_t *r = userdata;
1595 pa_sink_set_latency_range_within_thread(s, r[0], r[1]);
1600 case PA_SINK_MESSAGE_GET_LATENCY_RANGE: {
1601 pa_usec_t *r = userdata;
1603 r[0] = s->thread_info.min_latency;
1604 r[1] = s->thread_info.max_latency;
1609 case PA_SINK_MESSAGE_GET_MAX_REWIND:
1611 *((size_t*) userdata) = s->thread_info.max_rewind;
1614 case PA_SINK_MESSAGE_GET_MAX_REQUEST:
1616 *((size_t*) userdata) = s->thread_info.max_request;
1619 case PA_SINK_MESSAGE_GET_LATENCY:
1620 case PA_SINK_MESSAGE_MAX:
1627 /* Called from main thread */
1628 int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) {
1633 pa_core_assert_ref(c);
1635 for (sink = PA_SINK(pa_idxset_first(c->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(c->sinks, &idx))) {
1638 if ((r = pa_sink_suspend(sink, suspend)) < 0)
1645 /* Called from main thread */
1646 void pa_sink_detach(pa_sink *s) {
1647 pa_sink_assert_ref(s);
1648 pa_assert(PA_SINK_IS_LINKED(s->state));
1650 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL) == 0);
1653 /* Called from main thread */
1654 void pa_sink_attach(pa_sink *s) {
1655 pa_sink_assert_ref(s);
1656 pa_assert(PA_SINK_IS_LINKED(s->state));
1658 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
1661 /* Called from IO thread */
1662 void pa_sink_detach_within_thread(pa_sink *s) {
1666 pa_sink_assert_ref(s);
1667 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1669 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1673 if (s->monitor_source)
1674 pa_source_detach_within_thread(s->monitor_source);
1677 /* Called from IO thread */
1678 void pa_sink_attach_within_thread(pa_sink *s) {
1682 pa_sink_assert_ref(s);
1683 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1685 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1689 if (s->monitor_source)
1690 pa_source_attach_within_thread(s->monitor_source);
1693 /* Called from IO thread */
1694 void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
1695 pa_sink_assert_ref(s);
1696 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1698 if (s->thread_info.state == PA_SINK_SUSPENDED)
1701 if (nbytes == (size_t) -1)
1702 nbytes = s->thread_info.max_rewind;
1704 nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
1706 if (s->thread_info.rewind_requested &&
1707 nbytes <= s->thread_info.rewind_nbytes)
1710 s->thread_info.rewind_nbytes = nbytes;
1711 s->thread_info.rewind_requested = TRUE;
1713 if (s->request_rewind)
1714 s->request_rewind(s);
1717 /* Called from IO thread */
1718 pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
1719 pa_usec_t result = (pa_usec_t) -1;
1722 pa_usec_t monitor_latency;
1724 pa_sink_assert_ref(s);
1726 if (s->thread_info.requested_latency_valid)
1727 return s->thread_info.requested_latency;
1729 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1731 if (i->thread_info.requested_sink_latency != (pa_usec_t) -1 &&
1732 (result == (pa_usec_t) -1 || result > i->thread_info.requested_sink_latency))
1733 result = i->thread_info.requested_sink_latency;
1735 monitor_latency = pa_source_get_requested_latency_within_thread(s->monitor_source);
1737 if (monitor_latency != (pa_usec_t) -1 &&
1738 (result == (pa_usec_t) -1 || result > monitor_latency))
1739 result = monitor_latency;
1741 if (result != (pa_usec_t) -1) {
1742 if (result > s->thread_info.max_latency)
1743 result = s->thread_info.max_latency;
1745 if (result < s->thread_info.min_latency)
1746 result = s->thread_info.min_latency;
1749 s->thread_info.requested_latency = result;
1750 s->thread_info.requested_latency_valid = TRUE;
1755 /* Called from main thread */
1756 pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
1759 pa_sink_assert_ref(s);
1760 pa_assert(PA_SINK_IS_LINKED(s->state));
1762 if (s->state == PA_SINK_SUSPENDED)
1765 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1769 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
1770 void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
1774 pa_sink_assert_ref(s);
1776 if (max_rewind == s->thread_info.max_rewind)
1779 s->thread_info.max_rewind = max_rewind;
1781 if (PA_SINK_IS_LINKED(s->thread_info.state)) {
1782 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1783 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1786 if (s->monitor_source)
1787 pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
1790 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
1791 void pa_sink_set_max_request(pa_sink *s, size_t max_request) {
1794 pa_sink_assert_ref(s);
1796 if (max_request == s->thread_info.max_request)
1799 s->thread_info.max_request = max_request;
1801 if (PA_SINK_IS_LINKED(s->thread_info.state)) {
1804 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1805 pa_sink_input_update_max_request(i, s->thread_info.max_request);
1809 /* Called from IO thread */
1810 void pa_sink_invalidate_requested_latency(pa_sink *s) {
1814 pa_sink_assert_ref(s);
1816 s->thread_info.requested_latency_valid = FALSE;
1818 if (s->update_requested_latency)
1819 s->update_requested_latency(s);
1821 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1822 if (i->update_sink_requested_latency)
1823 i->update_sink_requested_latency(i);
1826 /* Called from main thread */
1827 void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1828 pa_sink_assert_ref(s);
1830 /* min_latency == 0: no limit
1831 * min_latency == (size_t) -1: default limit
1832 * min_latency anything else: specified limit
1834 * Similar for max_latency */
1836 if (min_latency == (pa_usec_t) -1)
1837 min_latency = DEFAULT_MIN_LATENCY;
1839 if (min_latency < ABSOLUTE_MIN_LATENCY)
1840 min_latency = ABSOLUTE_MIN_LATENCY;
1842 if (max_latency == (pa_usec_t) -1)
1843 max_latency = min_latency;
1845 if (max_latency > ABSOLUTE_MAX_LATENCY || max_latency <= 0)
1846 max_latency = ABSOLUTE_MAX_LATENCY;
1848 pa_assert(min_latency <= max_latency);
1850 if (PA_SINK_IS_LINKED(s->state)) {
1856 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
1858 s->thread_info.min_latency = min_latency;
1859 s->thread_info.max_latency = max_latency;
1861 s->monitor_source->thread_info.min_latency = min_latency;
1862 s->monitor_source->thread_info.max_latency = max_latency;
1864 s->thread_info.requested_latency_valid = s->monitor_source->thread_info.requested_latency_valid = FALSE;
1868 /* Called from main thread */
1869 void pa_sink_get_latency_range(pa_sink *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
1870 pa_sink_assert_ref(s);
1871 pa_assert(min_latency);
1872 pa_assert(max_latency);
1874 if (PA_SINK_IS_LINKED(s->state)) {
1875 pa_usec_t r[2] = { 0, 0 };
1877 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
1879 *min_latency = r[0];
1880 *max_latency = r[1];
1882 *min_latency = s->thread_info.min_latency;
1883 *max_latency = s->thread_info.max_latency;
1887 /* Called from IO thread */
1888 void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1892 pa_sink_assert_ref(s);
1894 pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
1895 pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
1896 pa_assert(min_latency <= max_latency);
1898 s->thread_info.min_latency = min_latency;
1899 s->thread_info.max_latency = max_latency;
1901 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1902 if (i->update_sink_latency_range)
1903 i->update_sink_latency_range(i);
1905 pa_sink_invalidate_requested_latency(s);
1907 pa_source_set_latency_range_within_thread(s->monitor_source, min_latency, max_latency);
1910 /* Called from main context */
1911 size_t pa_sink_get_max_rewind(pa_sink *s) {
1913 pa_sink_assert_ref(s);
1915 if (!PA_SINK_IS_LINKED(s->state))
1916 return s->thread_info.max_rewind;
1918 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
1923 /* Called from main context */
1924 size_t pa_sink_get_max_request(pa_sink *s) {
1926 pa_sink_assert_ref(s);
1928 if (!PA_SINK_IS_LINKED(s->state))
1929 return s->thread_info.max_request;
1931 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REQUEST, &r, 0, NULL) == 0);
1936 /* Called from main context */
1937 pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink) {
1938 const char *ff, *c, *t = NULL, *s = "", *profile, *bus;
1942 if (pa_proplist_contains(p, PA_PROP_DEVICE_ICON_NAME))
1945 if ((ff = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) {
1947 if (pa_streq(ff, "microphone"))
1948 t = "audio-input-microphone";
1949 else if (pa_streq(ff, "webcam"))
1951 else if (pa_streq(ff, "computer"))
1953 else if (pa_streq(ff, "handset"))
1955 else if (pa_streq(ff, "portable"))
1956 t = "multimedia-player";
1957 else if (pa_streq(ff, "tv"))
1958 t = "video-display";
1962 if ((c = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
1963 if (pa_streq(c, "modem"))
1970 t = "audio-input-microphone";
1973 if ((profile = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
1974 if (strstr(profile, "analog"))
1976 else if (strstr(profile, "iec958"))
1978 else if (strstr(profile, "hdmi"))
1982 bus = pa_proplist_gets(p, PA_PROP_DEVICE_BUS);
1984 pa_proplist_setf(p, PA_PROP_DEVICE_ICON_NAME, "%s%s%s%s", t, pa_strempty(s), bus ? "-" : "", pa_strempty(bus));
1989 pa_bool_t pa_device_init_description(pa_proplist *p) {
1993 if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
1996 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
1997 if (pa_streq(s, "internal")) {
1998 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Internal Audio"));
2002 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
2003 if (pa_streq(s, "modem")) {
2004 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Modem"));
2008 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME))) {
2009 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);