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 DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
53 static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
55 static void sink_free(pa_object *s);
57 pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data) {
60 memset(data, 0, sizeof(*data));
61 data->proplist = pa_proplist_new();
66 void pa_sink_new_data_set_name(pa_sink_new_data *data, const char *name) {
70 data->name = pa_xstrdup(name);
73 void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_spec *spec) {
76 if ((data->sample_spec_is_set = !!spec))
77 data->sample_spec = *spec;
80 void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map) {
83 if ((data->channel_map_is_set = !!map))
84 data->channel_map = *map;
87 void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume) {
90 if ((data->volume_is_set = !!volume))
91 data->volume = *volume;
94 void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute) {
97 data->muted_is_set = TRUE;
101 void pa_sink_new_data_done(pa_sink_new_data *data) {
104 pa_xfree(data->name);
105 pa_proplist_free(data->proplist);
108 /* Called from main context */
109 static void reset_callbacks(pa_sink *s) {
113 s->get_volume = NULL;
114 s->set_volume = NULL;
117 s->request_rewind = NULL;
118 s->update_requested_latency = NULL;
121 /* Called from main context */
122 pa_sink* pa_sink_new(
124 pa_sink_new_data *data,
125 pa_sink_flags_t flags) {
129 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
130 pa_source_new_data source_data;
136 pa_assert(data->name);
138 s = pa_msgobject_new(pa_sink);
140 if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) {
145 pa_sink_new_data_set_name(data, name);
147 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW], data) < 0) {
149 pa_namereg_unregister(core, name);
153 pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
154 pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
156 pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
158 if (!data->channel_map_is_set)
159 pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
161 pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
162 pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
164 if (!data->volume_is_set)
165 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
167 pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
168 pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
170 if (!data->muted_is_set)
174 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
176 pa_device_init_description(data->proplist);
177 pa_device_init_icon(data->proplist, TRUE);
179 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {
181 pa_namereg_unregister(core, name);
185 s->parent.parent.free = sink_free;
186 s->parent.process_msg = pa_sink_process_msg;
189 s->state = PA_SINK_INIT;
191 s->name = pa_xstrdup(name);
192 s->proplist = pa_proplist_copy(data->proplist);
193 s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
194 s->module = data->module;
195 s->card = data->card;
197 s->sample_spec = data->sample_spec;
198 s->channel_map = data->channel_map;
200 s->inputs = pa_idxset_new(NULL, NULL);
203 s->virtual_volume = data->volume;
204 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
205 s->base_volume = PA_VOLUME_NORM;
206 s->n_volume_steps = PA_VOLUME_NORM+1;
207 s->muted = data->muted;
208 s->refresh_volume = s->refresh_muted = FALSE;
216 pa_silence_memchunk_get(
217 &core->silence_cache,
223 s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
224 s->thread_info.soft_volume = s->soft_volume;
225 s->thread_info.soft_muted = s->muted;
226 s->thread_info.state = s->state;
227 s->thread_info.rewind_nbytes = 0;
228 s->thread_info.rewind_requested = FALSE;
229 s->thread_info.max_rewind = 0;
230 s->thread_info.max_request = 0;
231 s->thread_info.requested_latency_valid = FALSE;
232 s->thread_info.requested_latency = 0;
233 s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
234 s->thread_info.max_latency = 0;
236 pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
239 pa_assert_se(pa_idxset_put(s->card->sinks, s, NULL) >= 0);
241 pt = pa_proplist_to_string_sep(s->proplist, "\n ");
242 pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s\n %s",
245 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
246 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
250 pa_source_new_data_init(&source_data);
251 pa_source_new_data_set_sample_spec(&source_data, &s->sample_spec);
252 pa_source_new_data_set_channel_map(&source_data, &s->channel_map);
253 source_data.name = pa_sprintf_malloc("%s.monitor", name);
254 source_data.driver = data->driver;
255 source_data.module = data->module;
256 source_data.card = data->card;
258 dn = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
259 pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
260 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
262 s->monitor_source = pa_source_new(core, &source_data, PA_SOURCE_LATENCY);
264 pa_source_new_data_done(&source_data);
266 if (!s->monitor_source) {
272 s->monitor_source->monitor_of = s;
274 pa_source_set_latency_range(s->monitor_source, s->thread_info.min_latency, s->thread_info.max_latency);
275 pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
280 /* Called from main context */
281 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
283 pa_bool_t suspend_change;
284 pa_sink_state_t original_state;
288 if (s->state == state)
291 original_state = s->state;
294 (original_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state)) ||
295 (PA_SINK_IS_OPENED(original_state) && state == PA_SINK_SUSPENDED);
298 if ((ret = s->set_state(s, state)) < 0)
302 if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
305 s->set_state(s, original_state);
312 if (state != PA_SINK_UNLINKED) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
313 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
314 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
317 if (suspend_change) {
321 /* We're suspending or resuming, tell everyone about it */
323 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx)))
324 if (s->state == PA_SINK_SUSPENDED &&
325 (i->flags & PA_SINK_INPUT_FAIL_ON_SUSPEND))
326 pa_sink_input_kill(i);
328 i->suspend(i, state == PA_SINK_SUSPENDED);
330 if (s->monitor_source)
331 pa_source_sync_suspend(s->monitor_source);
337 /* Called from main context */
338 void pa_sink_put(pa_sink* s) {
339 pa_sink_assert_ref(s);
341 pa_assert(s->state == PA_SINK_INIT);
343 /* The following fields must be initialized properly when calling _put() */
344 pa_assert(s->asyncmsgq);
345 pa_assert(s->rtpoll);
346 pa_assert(!s->thread_info.min_latency || !s->thread_info.max_latency ||
347 s->thread_info.min_latency <= s->thread_info.max_latency);
349 if (!(s->flags & PA_SINK_HW_VOLUME_CTRL)) {
350 s->flags |= PA_SINK_DECIBEL_VOLUME;
352 s->thread_info.soft_volume = s->soft_volume;
353 s->thread_info.soft_muted = s->muted;
356 if (s->flags & PA_SINK_DECIBEL_VOLUME)
357 s->n_volume_steps = PA_VOLUME_NORM+1;
359 if (s->core->flat_volumes)
360 if (s->flags & PA_SINK_DECIBEL_VOLUME)
361 s->flags |= PA_SINK_FLAT_VOLUME;
363 pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
365 pa_source_put(s->monitor_source);
367 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
368 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s);
371 /* Called from main context */
372 void pa_sink_unlink(pa_sink* s) {
374 pa_sink_input *i, *j = NULL;
378 /* Please note that pa_sink_unlink() does more than simply
379 * reversing pa_sink_put(). It also undoes the registrations
380 * already done in pa_sink_new()! */
382 /* All operations here shall be idempotent, i.e. pa_sink_unlink()
383 * may be called multiple times on the same sink without bad
386 linked = PA_SINK_IS_LINKED(s->state);
389 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
391 if (s->state != PA_SINK_UNLINKED)
392 pa_namereg_unregister(s->core, s->name);
393 pa_idxset_remove_by_data(s->core->sinks, s, NULL);
396 pa_idxset_remove_by_data(s->card->sinks, s, NULL);
398 while ((i = pa_idxset_first(s->inputs, NULL))) {
400 pa_sink_input_kill(i);
405 sink_set_state(s, PA_SINK_UNLINKED);
407 s->state = PA_SINK_UNLINKED;
411 if (s->monitor_source)
412 pa_source_unlink(s->monitor_source);
415 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
416 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
420 /* Called from main context */
421 static void sink_free(pa_object *o) {
422 pa_sink *s = PA_SINK(o);
426 pa_assert(pa_sink_refcnt(s) == 0);
428 if (PA_SINK_IS_LINKED(s->state))
431 pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
433 if (s->monitor_source) {
434 pa_source_unref(s->monitor_source);
435 s->monitor_source = NULL;
438 pa_idxset_free(s->inputs, NULL, NULL);
440 while ((i = pa_hashmap_steal_first(s->thread_info.inputs)))
441 pa_sink_input_unref(i);
443 pa_hashmap_free(s->thread_info.inputs, NULL, NULL);
445 if (s->silence.memblock)
446 pa_memblock_unref(s->silence.memblock);
452 pa_proplist_free(s->proplist);
457 /* Called from main context */
458 void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
459 pa_sink_assert_ref(s);
463 if (s->monitor_source)
464 pa_source_set_asyncmsgq(s->monitor_source, q);
467 /* Called from main context */
468 void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
469 pa_sink_assert_ref(s);
472 if (s->monitor_source)
473 pa_source_set_rtpoll(s->monitor_source, p);
476 /* Called from main context */
477 int pa_sink_update_status(pa_sink*s) {
478 pa_sink_assert_ref(s);
479 pa_assert(PA_SINK_IS_LINKED(s->state));
481 if (s->state == PA_SINK_SUSPENDED)
484 return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
487 /* Called from main context */
488 int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
489 pa_sink_assert_ref(s);
490 pa_assert(PA_SINK_IS_LINKED(s->state));
493 return sink_set_state(s, PA_SINK_SUSPENDED);
495 return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
498 /* Called from main context */
499 pa_queue *pa_sink_move_all_start(pa_sink *s) {
501 pa_sink_input *i, *n;
504 pa_sink_assert_ref(s);
505 pa_assert(PA_SINK_IS_LINKED(s->state));
509 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = n) {
510 n = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx));
512 if (pa_sink_input_start_move(i) >= 0)
513 pa_queue_push(q, pa_sink_input_ref(i));
519 /* Called from main context */
520 void pa_sink_move_all_finish(pa_sink *s, pa_queue *q, pa_bool_t save) {
523 pa_sink_assert_ref(s);
524 pa_assert(PA_SINK_IS_LINKED(s->state));
527 while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
528 if (pa_sink_input_finish_move(i, s, save) < 0)
529 pa_sink_input_kill(i);
531 pa_sink_input_unref(i);
534 pa_queue_free(q, NULL, NULL);
537 /* Called from main context */
538 void pa_sink_move_all_fail(pa_queue *q) {
542 while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
543 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_OK) {
544 pa_sink_input_kill(i);
545 pa_sink_input_unref(i);
549 pa_queue_free(q, NULL, NULL);
552 /* Called from IO thread context */
553 void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
556 pa_sink_assert_ref(s);
557 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
559 /* If nobody requested this and this is actually no real rewind
560 * then we can short cut this */
561 if (!s->thread_info.rewind_requested && nbytes <= 0)
564 s->thread_info.rewind_nbytes = 0;
565 s->thread_info.rewind_requested = FALSE;
567 if (s->thread_info.state == PA_SINK_SUSPENDED)
571 pa_log_debug("Processing rewind...");
573 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
574 pa_sink_input_assert_ref(i);
575 pa_sink_input_process_rewind(i, nbytes);
579 if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
580 pa_source_process_rewind(s->monitor_source, nbytes);
583 /* Called from IO thread context */
584 static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxinfo) {
588 size_t mixlength = *length;
590 pa_sink_assert_ref(s);
593 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
594 pa_sink_input_assert_ref(i);
596 pa_sink_input_peek(i, *length, &info->chunk, &info->volume);
598 if (mixlength == 0 || info->chunk.length < mixlength)
599 mixlength = info->chunk.length;
601 if (pa_memblock_is_silence(info->chunk.memblock)) {
602 pa_memblock_unref(info->chunk.memblock);
606 info->userdata = pa_sink_input_ref(i);
608 pa_assert(info->chunk.memblock);
609 pa_assert(info->chunk.length > 0);
622 /* Called from IO thread context */
623 static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *result) {
627 unsigned n_unreffed = 0;
629 pa_sink_assert_ref(s);
631 pa_assert(result->memblock);
632 pa_assert(result->length > 0);
634 /* We optimize for the case where the order of the inputs has not changed */
636 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
638 pa_mix_info* m = NULL;
640 pa_sink_input_assert_ref(i);
642 /* Let's try to find the matching entry info the pa_mix_info array */
643 for (j = 0; j < n; j ++) {
645 if (info[p].userdata == i) {
656 pa_sink_input_drop(i, result->length);
658 if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state)) {
660 if (pa_hashmap_size(i->thread_info.direct_outputs) > 0) {
665 if (m && m->chunk.memblock) {
667 pa_memblock_ref(c.memblock);
668 pa_assert(result->length <= c.length);
669 c.length = result->length;
671 pa_memchunk_make_writable(&c, 0);
672 pa_volume_memchunk(&c, &s->sample_spec, &m->volume);
675 pa_memblock_ref(c.memblock);
676 pa_assert(result->length <= c.length);
677 c.length = result->length;
680 while ((o = pa_hashmap_iterate(i->thread_info.direct_outputs, &ostate, NULL))) {
681 pa_source_output_assert_ref(o);
682 pa_assert(o->direct_on_input == i);
683 pa_source_post_direct(s->monitor_source, o, &c);
686 pa_memblock_unref(c.memblock);
691 if (m->chunk.memblock)
692 pa_memblock_unref(m->chunk.memblock);
693 pa_memchunk_reset(&m->chunk);
695 pa_sink_input_unref(m->userdata);
702 /* Now drop references to entries that are included in the
703 * pa_mix_info array but don't exist anymore */
705 if (n_unreffed < n) {
706 for (; n > 0; info++, n--) {
708 pa_sink_input_unref(info->userdata);
709 if (info->chunk.memblock)
710 pa_memblock_unref(info->chunk.memblock);
714 if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
715 pa_source_post(s->monitor_source, result);
718 /* Called from IO thread context */
719 void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
720 pa_mix_info info[MAX_MIX_CHANNELS];
722 size_t block_size_max;
724 pa_sink_assert_ref(s);
725 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
726 pa_assert(pa_frame_aligned(length, &s->sample_spec));
731 pa_assert(!s->thread_info.rewind_requested);
732 pa_assert(s->thread_info.rewind_nbytes == 0);
734 if (s->thread_info.state == PA_SINK_SUSPENDED) {
735 result->memblock = pa_memblock_ref(s->silence.memblock);
736 result->index = s->silence.index;
737 result->length = PA_MIN(s->silence.length, length);
742 length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
744 block_size_max = pa_mempool_block_size_max(s->core->mempool);
745 if (length > block_size_max)
746 length = pa_frame_align(block_size_max, &s->sample_spec);
748 pa_assert(length > 0);
750 n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
754 *result = s->silence;
755 pa_memblock_ref(result->memblock);
757 if (result->length > length)
758 result->length = length;
763 *result = info[0].chunk;
764 pa_memblock_ref(result->memblock);
766 if (result->length > length)
767 result->length = length;
769 pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
771 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) {
772 pa_memchunk_make_writable(result, 0);
773 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
774 pa_silence_memchunk(result, &s->sample_spec);
776 pa_volume_memchunk(result, &s->sample_spec, &volume);
780 result->memblock = pa_memblock_new(s->core->mempool, length);
782 ptr = pa_memblock_acquire(result->memblock);
783 result->length = pa_mix(info, n,
786 &s->thread_info.soft_volume,
787 s->thread_info.soft_muted);
788 pa_memblock_release(result->memblock);
793 inputs_drop(s, info, n, result);
798 /* Called from IO thread context */
799 void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
800 pa_mix_info info[MAX_MIX_CHANNELS];
802 size_t length, block_size_max;
804 pa_sink_assert_ref(s);
805 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
807 pa_assert(target->memblock);
808 pa_assert(target->length > 0);
809 pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
813 pa_assert(!s->thread_info.rewind_requested);
814 pa_assert(s->thread_info.rewind_nbytes == 0);
816 if (s->thread_info.state == PA_SINK_SUSPENDED) {
817 pa_silence_memchunk(target, &s->sample_spec);
821 length = target->length;
822 block_size_max = pa_mempool_block_size_max(s->core->mempool);
823 if (length > block_size_max)
824 length = pa_frame_align(block_size_max, &s->sample_spec);
826 pa_assert(length > 0);
828 n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
831 if (target->length > length)
832 target->length = length;
834 pa_silence_memchunk(target, &s->sample_spec);
838 if (target->length > length)
839 target->length = length;
841 pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
843 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
844 pa_silence_memchunk(target, &s->sample_spec);
848 vchunk = info[0].chunk;
849 pa_memblock_ref(vchunk.memblock);
851 if (vchunk.length > length)
852 vchunk.length = length;
854 if (!pa_cvolume_is_norm(&volume)) {
855 pa_memchunk_make_writable(&vchunk, 0);
856 pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
859 pa_memchunk_memcpy(target, &vchunk);
860 pa_memblock_unref(vchunk.memblock);
866 ptr = pa_memblock_acquire(target->memblock);
868 target->length = pa_mix(info, n,
869 (uint8_t*) ptr + target->index, length,
871 &s->thread_info.soft_volume,
872 s->thread_info.soft_muted);
874 pa_memblock_release(target->memblock);
877 inputs_drop(s, info, n, target);
882 /* Called from IO thread context */
883 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
887 pa_sink_assert_ref(s);
888 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
890 pa_assert(target->memblock);
891 pa_assert(target->length > 0);
892 pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
896 pa_assert(!s->thread_info.rewind_requested);
897 pa_assert(s->thread_info.rewind_nbytes == 0);
906 pa_sink_render_into(s, &chunk);
915 /* Called from IO thread context */
916 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
917 pa_sink_assert_ref(s);
918 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
919 pa_assert(length > 0);
920 pa_assert(pa_frame_aligned(length, &s->sample_spec));
923 pa_assert(!s->thread_info.rewind_requested);
924 pa_assert(s->thread_info.rewind_nbytes == 0);
926 /*** This needs optimization ***/
929 result->length = length;
930 result->memblock = pa_memblock_new(s->core->mempool, length);
932 pa_sink_render_into_full(s, result);
935 /* Called from main thread */
936 pa_usec_t pa_sink_get_latency(pa_sink *s) {
939 pa_sink_assert_ref(s);
940 pa_assert(PA_SINK_IS_LINKED(s->state));
942 /* The returned value is supposed to be in the time domain of the sound card! */
944 if (s->state == PA_SINK_SUSPENDED)
947 if (!(s->flags & PA_SINK_LATENCY))
950 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
955 /* Called from main thread */
956 void pa_sink_update_flat_volume(pa_sink *s, pa_cvolume *new_volume) {
960 pa_sink_assert_ref(s);
961 pa_assert(new_volume);
962 pa_assert(PA_SINK_IS_LINKED(s->state));
963 pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
965 /* This is called whenever a sink input volume changes and we
966 * might need to fix up the sink volume accordingly. Please note
967 * that we don't actually update the sinks volume here, we only
968 * return how it needs to be updated. The caller should then call
969 * pa_sink_set_flat_volume().*/
971 if (pa_idxset_isempty(s->inputs)) {
972 /* In the special case that we have no sink input we leave the
973 * volume unmodified. */
974 *new_volume = s->virtual_volume;
978 pa_cvolume_mute(new_volume, s->channel_map.channels);
980 /* First let's determine the new maximum volume of all inputs
981 * connected to this sink */
982 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
984 pa_cvolume remapped_volume;
986 remapped_volume = i->virtual_volume;
987 pa_cvolume_remap(&remapped_volume, &i->channel_map, &s->channel_map);
989 for (c = 0; c < new_volume->channels; c++)
990 if (remapped_volume.values[c] > new_volume->values[c])
991 new_volume->values[c] = remapped_volume.values[c];
994 /* Then, let's update the soft volumes of all inputs connected
996 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
997 pa_cvolume remapped_new_volume;
999 remapped_new_volume = *new_volume;
1000 pa_cvolume_remap(&remapped_new_volume, &s->channel_map, &i->channel_map);
1001 pa_sw_cvolume_divide(&i->soft_volume, &i->virtual_volume, &remapped_new_volume);
1002 pa_sw_cvolume_multiply(&i->soft_volume, &i->soft_volume, &i->volume_factor);
1004 /* Hooks have the ability to play games with i->soft_volume */
1005 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], i);
1007 /* We don't issue PA_SINK_INPUT_MESSAGE_SET_VOLUME because
1008 * we want the update to have atomically with the sink
1009 * volume update, hence we do it within the
1010 * pa_sink_set_flat_volume() call below*/
1014 /* Called from main thread */
1015 void pa_sink_propagate_flat_volume(pa_sink *s, const pa_cvolume *old_volume) {
1019 pa_sink_assert_ref(s);
1020 pa_assert(old_volume);
1021 pa_assert(PA_SINK_IS_LINKED(s->state));
1022 pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
1024 /* This is called whenever the sink volume changes that is not
1025 * caused by a sink input volume change. We need to fix up the
1026 * sink input volumes accordingly */
1028 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
1029 pa_cvolume remapped_old_volume, remapped_new_volume, fixed_volume;
1032 remapped_new_volume = s->virtual_volume;
1033 pa_cvolume_remap(&remapped_new_volume, &s->channel_map, &i->channel_map);
1035 remapped_old_volume = *old_volume;
1036 pa_cvolume_remap(&remapped_old_volume, &s->channel_map, &i->channel_map);
1038 for (c = 0; c < i->sample_spec.channels; c++)
1040 if (remapped_old_volume.values[c] == PA_VOLUME_MUTED)
1041 fixed_volume.values[c] = PA_VOLUME_MUTED;
1043 fixed_volume.values[c] = (pa_volume_t)
1044 ((uint64_t) i->virtual_volume.values[c] *
1045 (uint64_t) remapped_new_volume.values[c] /
1046 (uint64_t) remapped_old_volume.values[c]);
1048 fixed_volume.channels = i->virtual_volume.channels;
1050 if (!pa_cvolume_equal(&fixed_volume, &i->virtual_volume)) {
1051 i->virtual_volume = fixed_volume;
1053 /* The virtual volume changed, let's tell people so */
1054 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1059 /* Called from main thread */
1060 void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg) {
1061 pa_cvolume old_virtual_volume;
1062 pa_bool_t virtual_volume_changed;
1064 pa_sink_assert_ref(s);
1065 pa_assert(PA_SINK_IS_LINKED(s->state));
1067 pa_assert(pa_cvolume_valid(volume));
1068 pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
1070 old_virtual_volume = s->virtual_volume;
1071 s->virtual_volume = *volume;
1072 virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume);
1074 /* Propagate this volume change back to the inputs */
1075 if (virtual_volume_changed)
1076 if (propagate && (s->flags & PA_SINK_FLAT_VOLUME))
1077 pa_sink_propagate_flat_volume(s, &old_virtual_volume);
1079 if (s->set_volume) {
1080 /* If we have a function set_volume(), then we do not apply a
1081 * soft volume by default. However, set_volume() is apply one
1082 * to s->soft_volume */
1084 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
1088 /* If we have no function set_volume(), then the soft volume
1089 * becomes the virtual volume */
1090 s->soft_volume = s->virtual_volume;
1092 /* This tells the sink that soft and/or virtual volume changed */
1094 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
1096 if (virtual_volume_changed)
1097 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1100 /* Called from main thread. Only to be called by sink implementor */
1101 void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) {
1102 pa_sink_assert_ref(s);
1105 s->soft_volume = *volume;
1107 if (PA_SINK_IS_LINKED(s->state))
1108 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
1110 s->thread_info.soft_volume = *volume;
1113 /* Called from main thread */
1114 const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) {
1115 pa_sink_assert_ref(s);
1117 if (s->refresh_volume || force_refresh) {
1118 struct pa_cvolume old_virtual_volume = s->virtual_volume;
1123 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
1125 if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume)) {
1127 if (s->flags & PA_SINK_FLAT_VOLUME)
1128 pa_sink_propagate_flat_volume(s, &old_virtual_volume);
1130 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1134 return &s->virtual_volume;
1137 /* Called from main thread */
1138 void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume) {
1139 pa_sink_assert_ref(s);
1141 /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1143 if (pa_cvolume_equal(&s->virtual_volume, new_volume))
1146 s->virtual_volume = *new_volume;
1147 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1150 /* Called from main thread */
1151 void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) {
1152 pa_bool_t old_muted;
1154 pa_sink_assert_ref(s);
1155 pa_assert(PA_SINK_IS_LINKED(s->state));
1157 old_muted = s->muted;
1163 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
1165 if (old_muted != s->muted)
1166 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1169 /* Called from main thread */
1170 pa_bool_t pa_sink_get_mute(pa_sink *s, pa_bool_t force_refresh) {
1172 pa_sink_assert_ref(s);
1174 if (s->refresh_muted || force_refresh) {
1175 pa_bool_t old_muted = s->muted;
1180 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
1182 if (old_muted != s->muted)
1183 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1189 /* Called from main thread */
1190 void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted) {
1191 pa_sink_assert_ref(s);
1193 /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1195 if (s->muted == new_muted)
1198 s->muted = new_muted;
1199 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1202 /* Called from main thread */
1203 pa_bool_t pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p) {
1205 pa_sink_assert_ref(s);
1208 pa_proplist_update(s->proplist, mode, p);
1210 if (PA_SINK_IS_LINKED(s->state)) {
1211 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
1212 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1218 /* Called from main thread */
1219 void pa_sink_set_description(pa_sink *s, const char *description) {
1221 pa_sink_assert_ref(s);
1223 if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
1226 old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
1228 if (old && description && !strcmp(old, description))
1232 pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
1234 pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
1236 if (s->monitor_source) {
1239 n = pa_sprintf_malloc("Monitor Source of %s", description ? description : s->name);
1240 pa_source_set_description(s->monitor_source, n);
1244 if (PA_SINK_IS_LINKED(s->state)) {
1245 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1246 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
1250 /* Called from main thread */
1251 unsigned pa_sink_linked_by(pa_sink *s) {
1254 pa_sink_assert_ref(s);
1255 pa_assert(PA_SINK_IS_LINKED(s->state));
1257 ret = pa_idxset_size(s->inputs);
1259 /* We add in the number of streams connected to us here. Please
1260 * note the asymmmetry to pa_sink_used_by()! */
1262 if (s->monitor_source)
1263 ret += pa_source_linked_by(s->monitor_source);
1268 /* Called from main thread */
1269 unsigned pa_sink_used_by(pa_sink *s) {
1272 pa_sink_assert_ref(s);
1273 pa_assert(PA_SINK_IS_LINKED(s->state));
1275 ret = pa_idxset_size(s->inputs);
1276 pa_assert(ret >= s->n_corked);
1278 /* Streams connected to our monitor source do not matter for
1279 * pa_sink_used_by()!.*/
1281 return ret - s->n_corked;
1284 /* Called from main thread */
1285 unsigned pa_sink_check_suspend(pa_sink *s) {
1290 pa_sink_assert_ref(s);
1292 if (!PA_SINK_IS_LINKED(s->state))
1297 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
1298 pa_sink_input_state_t st;
1300 st = pa_sink_input_get_state(i);
1301 pa_assert(PA_SINK_INPUT_IS_LINKED(st));
1303 if (st == PA_SINK_INPUT_CORKED)
1306 if (i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND)
1312 if (s->monitor_source)
1313 ret += pa_source_check_suspend(s->monitor_source);
1318 /* Called from the IO thread */
1319 static void sync_input_volumes_within_thread(pa_sink *s) {
1323 pa_sink_assert_ref(s);
1325 while ((i = PA_SINK_INPUT(pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))) {
1326 if (pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume))
1329 i->thread_info.soft_volume = i->soft_volume;
1330 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1334 /* Called from IO thread, except when it is not */
1335 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1336 pa_sink *s = PA_SINK(o);
1337 pa_sink_assert_ref(s);
1339 switch ((pa_sink_message_t) code) {
1341 case PA_SINK_MESSAGE_ADD_INPUT: {
1342 pa_sink_input *i = PA_SINK_INPUT(userdata);
1344 /* If you change anything here, make sure to change the
1345 * sink input handling a few lines down at
1346 * PA_SINK_MESSAGE_FINISH_MOVE, too. */
1348 pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
1350 /* Since the caller sleeps in pa_sink_input_put(), we can
1351 * safely access data outside of thread_info even though
1354 if ((i->thread_info.sync_prev = i->sync_prev)) {
1355 pa_assert(i->sink == i->thread_info.sync_prev->sink);
1356 pa_assert(i->sync_prev->sync_next == i);
1357 i->thread_info.sync_prev->thread_info.sync_next = i;
1360 if ((i->thread_info.sync_next = i->sync_next)) {
1361 pa_assert(i->sink == i->thread_info.sync_next->sink);
1362 pa_assert(i->sync_next->sync_prev == i);
1363 i->thread_info.sync_next->thread_info.sync_prev = i;
1366 pa_assert(!i->thread_info.attached);
1367 i->thread_info.attached = TRUE;
1372 pa_sink_input_set_state_within_thread(i, i->state);
1374 /* The requested latency of the sink input needs to be
1375 * fixed up and then configured on the sink */
1377 if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
1378 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
1380 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1381 pa_sink_input_update_max_request(i, s->thread_info.max_request);
1383 /* We don't rewind here automatically. This is left to the
1384 * sink input implementor because some sink inputs need a
1385 * slow start, i.e. need some time to buffer client
1386 * samples before beginning streaming. */
1388 /* In flat volume mode we need to update the volume as
1390 return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1393 case PA_SINK_MESSAGE_REMOVE_INPUT: {
1394 pa_sink_input *i = PA_SINK_INPUT(userdata);
1396 /* If you change anything here, make sure to change the
1397 * sink input handling a few lines down at
1398 * PA_SINK_MESSAGE_PREPAPRE_MOVE, too. */
1403 pa_sink_input_set_state_within_thread(i, i->state);
1405 pa_assert(i->thread_info.attached);
1406 i->thread_info.attached = FALSE;
1408 /* Since the caller sleeps in pa_sink_input_unlink(),
1409 * we can safely access data outside of thread_info even
1410 * though it is mutable */
1412 pa_assert(!i->sync_prev);
1413 pa_assert(!i->sync_next);
1415 if (i->thread_info.sync_prev) {
1416 i->thread_info.sync_prev->thread_info.sync_next = i->thread_info.sync_prev->sync_next;
1417 i->thread_info.sync_prev = NULL;
1420 if (i->thread_info.sync_next) {
1421 i->thread_info.sync_next->thread_info.sync_prev = i->thread_info.sync_next->sync_prev;
1422 i->thread_info.sync_next = NULL;
1425 if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
1426 pa_sink_input_unref(i);
1428 pa_sink_invalidate_requested_latency(s);
1429 pa_sink_request_rewind(s, (size_t) -1);
1431 /* In flat volume mode we need to update the volume as
1433 return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1436 case PA_SINK_MESSAGE_START_MOVE: {
1437 pa_sink_input *i = PA_SINK_INPUT(userdata);
1439 /* We don't support moving synchronized streams. */
1440 pa_assert(!i->sync_prev);
1441 pa_assert(!i->sync_next);
1442 pa_assert(!i->thread_info.sync_next);
1443 pa_assert(!i->thread_info.sync_prev);
1445 if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
1447 size_t sink_nbytes, total_nbytes;
1449 /* Get the latency of the sink */
1450 if (!(s->flags & PA_SINK_LATENCY) ||
1451 PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
1454 sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
1455 total_nbytes = sink_nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq);
1457 if (total_nbytes > 0) {
1458 i->thread_info.rewrite_nbytes = i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, total_nbytes) : total_nbytes;
1459 i->thread_info.rewrite_flush = TRUE;
1460 pa_sink_input_process_rewind(i, sink_nbytes);
1467 pa_assert(i->thread_info.attached);
1468 i->thread_info.attached = FALSE;
1470 /* Let's remove the sink input ...*/
1471 if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
1472 pa_sink_input_unref(i);
1474 pa_sink_invalidate_requested_latency(s);
1476 pa_log_debug("Requesting rewind due to started move");
1477 pa_sink_request_rewind(s, (size_t) -1);
1479 /* In flat volume mode we need to update the volume as
1481 return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1484 case PA_SINK_MESSAGE_FINISH_MOVE: {
1485 pa_sink_input *i = PA_SINK_INPUT(userdata);
1487 /* We don't support moving synchronized streams. */
1488 pa_assert(!i->sync_prev);
1489 pa_assert(!i->sync_next);
1490 pa_assert(!i->thread_info.sync_next);
1491 pa_assert(!i->thread_info.sync_prev);
1493 pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
1495 pa_assert(!i->thread_info.attached);
1496 i->thread_info.attached = TRUE;
1501 if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
1502 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
1504 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1505 pa_sink_input_update_max_request(i, s->thread_info.max_request);
1507 if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
1511 /* Get the latency of the sink */
1512 if (!(s->flags & PA_SINK_LATENCY) ||
1513 PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
1516 nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
1519 pa_sink_input_drop(i, nbytes);
1521 pa_log_debug("Requesting rewind due to finished move");
1522 pa_sink_request_rewind(s, nbytes);
1525 /* In flat volume mode we need to update the volume as
1527 return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1530 case PA_SINK_MESSAGE_SET_VOLUME:
1532 if (!pa_cvolume_equal(&s->thread_info.soft_volume, &s->soft_volume)) {
1533 s->thread_info.soft_volume = s->soft_volume;
1534 pa_sink_request_rewind(s, (size_t) -1);
1537 if (s->flags & PA_SINK_FLAT_VOLUME)
1538 sync_input_volumes_within_thread(s);
1542 case PA_SINK_MESSAGE_GET_VOLUME:
1545 case PA_SINK_MESSAGE_SET_MUTE:
1547 if (s->thread_info.soft_muted != s->muted) {
1548 s->thread_info.soft_muted = s->muted;
1549 pa_sink_request_rewind(s, (size_t) -1);
1554 case PA_SINK_MESSAGE_GET_MUTE:
1557 case PA_SINK_MESSAGE_SET_STATE:
1559 s->thread_info.state = PA_PTR_TO_UINT(userdata);
1561 if (s->thread_info.state == PA_SINK_SUSPENDED) {
1562 s->thread_info.rewind_nbytes = 0;
1563 s->thread_info.rewind_requested = FALSE;
1568 case PA_SINK_MESSAGE_DETACH:
1570 /* Detach all streams */
1571 pa_sink_detach_within_thread(s);
1574 case PA_SINK_MESSAGE_ATTACH:
1576 /* Reattach all streams */
1577 pa_sink_attach_within_thread(s);
1580 case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: {
1582 pa_usec_t *usec = userdata;
1583 *usec = pa_sink_get_requested_latency_within_thread(s);
1585 if (*usec == (pa_usec_t) -1)
1586 *usec = s->thread_info.max_latency;
1591 case PA_SINK_MESSAGE_SET_LATENCY_RANGE: {
1592 pa_usec_t *r = userdata;
1594 pa_sink_update_latency_range(s, r[0], r[1]);
1599 case PA_SINK_MESSAGE_GET_LATENCY_RANGE: {
1600 pa_usec_t *r = userdata;
1602 r[0] = s->thread_info.min_latency;
1603 r[1] = s->thread_info.max_latency;
1608 case PA_SINK_MESSAGE_GET_MAX_REWIND:
1610 *((size_t*) userdata) = s->thread_info.max_rewind;
1613 case PA_SINK_MESSAGE_GET_MAX_REQUEST:
1615 *((size_t*) userdata) = s->thread_info.max_request;
1618 case PA_SINK_MESSAGE_GET_LATENCY:
1619 case PA_SINK_MESSAGE_MAX:
1626 /* Called from main thread */
1627 int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) {
1632 pa_core_assert_ref(c);
1634 for (sink = PA_SINK(pa_idxset_first(c->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(c->sinks, &idx))) {
1637 if ((r = pa_sink_suspend(sink, suspend)) < 0)
1644 /* Called from main thread */
1645 void pa_sink_detach(pa_sink *s) {
1646 pa_sink_assert_ref(s);
1647 pa_assert(PA_SINK_IS_LINKED(s->state));
1649 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL) == 0);
1652 /* Called from main thread */
1653 void pa_sink_attach(pa_sink *s) {
1654 pa_sink_assert_ref(s);
1655 pa_assert(PA_SINK_IS_LINKED(s->state));
1657 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
1660 /* Called from IO thread */
1661 void pa_sink_detach_within_thread(pa_sink *s) {
1665 pa_sink_assert_ref(s);
1666 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1668 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1672 if (s->monitor_source)
1673 pa_source_detach_within_thread(s->monitor_source);
1676 /* Called from IO thread */
1677 void pa_sink_attach_within_thread(pa_sink *s) {
1681 pa_sink_assert_ref(s);
1682 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1684 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1688 if (s->monitor_source)
1689 pa_source_attach_within_thread(s->monitor_source);
1692 /* Called from IO thread */
1693 void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
1694 pa_sink_assert_ref(s);
1695 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1697 if (s->thread_info.state == PA_SINK_SUSPENDED)
1700 if (nbytes == (size_t) -1)
1701 nbytes = s->thread_info.max_rewind;
1703 nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
1705 if (s->thread_info.rewind_requested &&
1706 nbytes <= s->thread_info.rewind_nbytes)
1709 s->thread_info.rewind_nbytes = nbytes;
1710 s->thread_info.rewind_requested = TRUE;
1712 if (s->request_rewind)
1713 s->request_rewind(s);
1716 /* Called from IO thread */
1717 pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
1718 pa_usec_t result = (pa_usec_t) -1;
1721 pa_usec_t monitor_latency;
1723 pa_sink_assert_ref(s);
1725 if (s->thread_info.requested_latency_valid)
1726 return s->thread_info.requested_latency;
1728 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1730 if (i->thread_info.requested_sink_latency != (pa_usec_t) -1 &&
1731 (result == (pa_usec_t) -1 || result > i->thread_info.requested_sink_latency))
1732 result = i->thread_info.requested_sink_latency;
1734 monitor_latency = pa_source_get_requested_latency_within_thread(s->monitor_source);
1736 if (monitor_latency != (pa_usec_t) -1 &&
1737 (result == (pa_usec_t) -1 || result > monitor_latency))
1738 result = monitor_latency;
1740 if (result != (pa_usec_t) -1) {
1741 if (s->thread_info.max_latency > 0 && result > s->thread_info.max_latency)
1742 result = s->thread_info.max_latency;
1744 if (s->thread_info.min_latency > 0 && result < s->thread_info.min_latency)
1745 result = s->thread_info.min_latency;
1748 s->thread_info.requested_latency = result;
1749 s->thread_info.requested_latency_valid = TRUE;
1754 /* Called from main thread */
1755 pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
1758 pa_sink_assert_ref(s);
1759 pa_assert(PA_SINK_IS_LINKED(s->state));
1761 if (s->state == PA_SINK_SUSPENDED)
1764 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1768 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
1769 void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
1773 pa_sink_assert_ref(s);
1775 if (max_rewind == s->thread_info.max_rewind)
1778 s->thread_info.max_rewind = max_rewind;
1780 if (PA_SINK_IS_LINKED(s->thread_info.state)) {
1781 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1782 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1785 if (s->monitor_source)
1786 pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
1789 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
1790 void pa_sink_set_max_request(pa_sink *s, size_t max_request) {
1793 pa_sink_assert_ref(s);
1795 if (max_request == s->thread_info.max_request)
1798 s->thread_info.max_request = max_request;
1800 if (PA_SINK_IS_LINKED(s->thread_info.state)) {
1803 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1804 pa_sink_input_update_max_request(i, s->thread_info.max_request);
1808 /* Called from IO thread */
1809 void pa_sink_invalidate_requested_latency(pa_sink *s) {
1813 pa_sink_assert_ref(s);
1815 s->thread_info.requested_latency_valid = FALSE;
1817 if (s->update_requested_latency)
1818 s->update_requested_latency(s);
1820 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1821 if (i->update_sink_requested_latency)
1822 i->update_sink_requested_latency(i);
1825 /* Called from main thread */
1826 void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1827 pa_sink_assert_ref(s);
1829 /* min_latency == 0: no limit
1830 * min_latency == (size_t) -1: default limit
1831 * min_latency anything else: specified limit
1833 * Similar for max_latency */
1835 if (min_latency == (pa_usec_t) -1)
1836 min_latency = DEFAULT_MIN_LATENCY;
1838 if (max_latency == (pa_usec_t) -1)
1839 max_latency = min_latency;
1841 pa_assert(!min_latency || !max_latency ||
1842 min_latency <= max_latency);
1844 if (PA_SINK_IS_LINKED(s->state)) {
1850 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
1852 s->thread_info.min_latency = min_latency;
1853 s->thread_info.max_latency = max_latency;
1855 s->monitor_source->thread_info.min_latency = min_latency;
1856 s->monitor_source->thread_info.max_latency = max_latency;
1858 s->thread_info.requested_latency_valid = s->monitor_source->thread_info.requested_latency_valid = FALSE;
1862 /* Called from main thread */
1863 void pa_sink_get_latency_range(pa_sink *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
1864 pa_sink_assert_ref(s);
1865 pa_assert(min_latency);
1866 pa_assert(max_latency);
1868 if (PA_SINK_IS_LINKED(s->state)) {
1869 pa_usec_t r[2] = { 0, 0 };
1871 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
1873 *min_latency = r[0];
1874 *max_latency = r[1];
1876 *min_latency = s->thread_info.min_latency;
1877 *max_latency = s->thread_info.max_latency;
1881 /* Called from IO thread */
1882 void pa_sink_update_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1886 pa_sink_assert_ref(s);
1888 pa_assert(!min_latency || !max_latency ||
1889 min_latency <= max_latency);
1891 s->thread_info.min_latency = min_latency;
1892 s->thread_info.max_latency = max_latency;
1894 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1895 if (i->update_sink_latency_range)
1896 i->update_sink_latency_range(i);
1898 pa_sink_invalidate_requested_latency(s);
1900 pa_source_update_latency_range(s->monitor_source, min_latency, max_latency);
1903 /* Called from main context */
1904 size_t pa_sink_get_max_rewind(pa_sink *s) {
1906 pa_sink_assert_ref(s);
1908 if (!PA_SINK_IS_LINKED(s->state))
1909 return s->thread_info.max_rewind;
1911 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
1916 /* Called from main context */
1917 size_t pa_sink_get_max_request(pa_sink *s) {
1919 pa_sink_assert_ref(s);
1921 if (!PA_SINK_IS_LINKED(s->state))
1922 return s->thread_info.max_request;
1924 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REQUEST, &r, 0, NULL) == 0);
1929 /* Called from main context */
1930 pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink) {
1931 const char *ff, *c, *t = NULL, *s = "", *profile, *bus;
1935 if (pa_proplist_contains(p, PA_PROP_DEVICE_ICON_NAME))
1938 if ((ff = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) {
1940 if (pa_streq(ff, "microphone"))
1941 t = "audio-input-microphone";
1942 else if (pa_streq(ff, "webcam"))
1944 else if (pa_streq(ff, "computer"))
1946 else if (pa_streq(ff, "handset"))
1948 else if (pa_streq(ff, "portable"))
1949 t = "multimedia-player";
1950 else if (pa_streq(ff, "tv"))
1951 t = "video-display";
1955 if ((c = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
1956 if (pa_streq(c, "modem"))
1963 t = "audio-input-microphone";
1966 if ((profile = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
1967 if (strstr(profile, "analog"))
1969 else if (strstr(profile, "iec958"))
1971 else if (strstr(profile, "hdmi"))
1975 bus = pa_proplist_gets(p, PA_PROP_DEVICE_BUS);
1977 pa_proplist_setf(p, PA_PROP_DEVICE_ICON_NAME, "%s%s%s%s", t, pa_strempty(s), bus ? "-" : "", pa_strempty(bus));
1982 pa_bool_t pa_device_init_description(pa_proplist *p) {
1986 if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
1989 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
1990 if (pa_streq(s, "internal")) {
1991 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Internal Audio"));
1995 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
1996 if (pa_streq(s, "modem")) {
1997 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Modem"));
2001 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME))) {
2002 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);