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, see <http://www.gnu.org/licenses/>.
32 #include <pulse/introspect.h>
33 #include <pulse/format.h>
34 #include <pulse/utf8.h>
35 #include <pulse/xmalloc.h>
36 #include <pulse/timeval.h>
37 #include <pulse/util.h>
38 #include <pulse/rtclock.h>
39 #include <pulse/internal.h>
41 #include <pulsecore/i18n.h>
42 #include <pulsecore/sink-input.h>
43 #include <pulsecore/namereg.h>
44 #include <pulsecore/core-util.h>
45 #include <pulsecore/sample-util.h>
46 #include <pulsecore/mix.h>
47 #include <pulsecore/core-subscribe.h>
48 #include <pulsecore/log.h>
49 #include <pulsecore/macro.h>
50 #include <pulsecore/play-memblockq.h>
51 #include <pulsecore/flist.h>
55 #define MAX_MIX_CHANNELS 32
56 #define MIX_BUFFER_LENGTH (pa_page_size())
57 #define ABSOLUTE_MIN_LATENCY (500)
58 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
59 #define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
61 PA_DEFINE_PUBLIC_CLASS(pa_sink, pa_msgobject);
63 struct pa_sink_volume_change {
67 PA_LLIST_FIELDS(pa_sink_volume_change);
70 struct sink_message_set_port {
75 static void sink_free(pa_object *s);
77 static void pa_sink_volume_change_push(pa_sink *s);
78 static void pa_sink_volume_change_flush(pa_sink *s);
79 static void pa_sink_volume_change_rewind(pa_sink *s, size_t nbytes);
82 static void pa_sink_write_pcm_dump(pa_sink *s, pa_memchunk *chunk)
84 char *dump_time = NULL, *dump_path_surfix = NULL;
85 const char *s_device_api_str, *card_name_str, *device_idx_str;
90 /* open file for dump pcm */
91 if (s->core->pcm_dump & PA_PCM_DUMP_PA_SINK && !s->pcm_dump_fp && s->state == PA_SINK_RUNNING) {
92 pa_gettimeofday(&now);
93 localtime_r(&now.tv_sec, &tm);
94 memset(&datetime[0], 0x00, sizeof(datetime));
95 strftime(&datetime[0], sizeof(datetime), "%H%M%S", &tm);
96 dump_time = pa_sprintf_malloc("%s.%03ld", &datetime[0], now.tv_usec / 1000);
98 if ((s_device_api_str = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_API))) {
99 if (pa_streq(s_device_api_str, "alsa")) {
100 card_name_str = pa_proplist_gets(s->proplist, "alsa.card_name");
101 device_idx_str = pa_proplist_gets(s->proplist, "alsa.device");
102 dump_path_surfix = pa_sprintf_malloc("%s.%s", pa_strnull(card_name_str), pa_strnull(device_idx_str));
104 dump_path_surfix = pa_sprintf_malloc("%s", s_device_api_str);
107 dump_path_surfix = pa_sprintf_malloc("%s", s->name);
110 s->dump_path = pa_sprintf_malloc("%s_%s_pa-sink%d-%s_%dch_%d.raw", PA_PCM_DUMP_PATH_PREFIX, pa_strempty(dump_time),
111 s->index, pa_strempty(dump_path_surfix), s->sample_spec.channels, s->sample_spec.rate);
113 s->pcm_dump_fp = fopen(s->dump_path, "w");
115 pa_log_warn("%s open failed", s->dump_path);
117 pa_log_info("%s opened", s->dump_path);
120 pa_xfree(dump_path_surfix);
121 /* close file for dump pcm when config is changed */
122 } else if (~s->core->pcm_dump & PA_PCM_DUMP_PA_SINK && s->pcm_dump_fp) {
123 fclose(s->pcm_dump_fp);
124 pa_log_info("%s closed", s->dump_path);
125 pa_xfree(s->dump_path);
126 s->pcm_dump_fp = NULL;
130 if (s->pcm_dump_fp) {
133 ptr = pa_memblock_acquire(chunk->memblock);
135 fwrite((uint8_t *)ptr + chunk->index, 1, chunk->length, s->pcm_dump_fp);
137 pa_log_warn("pa_memblock_acquire is failed. ptr is NULL");
139 pa_memblock_release(chunk->memblock);
144 pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data) {
148 data->proplist = pa_proplist_new();
149 data->ports = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) pa_device_port_unref);
154 void pa_sink_new_data_set_name(pa_sink_new_data *data, const char *name) {
157 pa_xfree(data->name);
158 data->name = pa_xstrdup(name);
161 void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_spec *spec) {
164 if ((data->sample_spec_is_set = !!spec))
165 data->sample_spec = *spec;
168 void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map) {
171 if ((data->channel_map_is_set = !!map))
172 data->channel_map = *map;
175 void pa_sink_new_data_set_alternate_sample_rate(pa_sink_new_data *data, const uint32_t alternate_sample_rate) {
178 data->alternate_sample_rate_is_set = true;
179 data->alternate_sample_rate = alternate_sample_rate;
182 void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume) {
185 if ((data->volume_is_set = !!volume))
186 data->volume = *volume;
189 void pa_sink_new_data_set_muted(pa_sink_new_data *data, bool mute) {
192 data->muted_is_set = true;
196 void pa_sink_new_data_set_port(pa_sink_new_data *data, const char *port) {
199 pa_xfree(data->active_port);
200 data->active_port = pa_xstrdup(port);
203 void pa_sink_new_data_done(pa_sink_new_data *data) {
206 pa_proplist_free(data->proplist);
209 pa_hashmap_free(data->ports);
211 pa_xfree(data->name);
212 pa_xfree(data->active_port);
215 /* Called from main context */
216 static void reset_callbacks(pa_sink *s) {
220 s->get_volume = NULL;
221 s->set_volume = NULL;
222 s->write_volume = NULL;
225 s->request_rewind = NULL;
226 s->update_requested_latency = NULL;
228 s->get_formats = NULL;
229 s->set_formats = NULL;
230 s->reconfigure = NULL;
233 /* Called from main context */
234 pa_sink* pa_sink_new(
236 pa_sink_new_data *data,
237 pa_sink_flags_t flags) {
241 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
242 pa_source_new_data source_data;
248 pa_assert(data->name);
249 pa_assert_ctl_context();
251 s = pa_msgobject_new(pa_sink);
253 if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) {
254 pa_log_debug("Failed to register name %s.", data->name);
259 pa_sink_new_data_set_name(data, name);
261 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW], data) < 0) {
263 pa_namereg_unregister(core, name);
267 /* FIXME, need to free s here on failure */
269 pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
270 pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
272 pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
274 if (!data->channel_map_is_set)
275 pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
277 pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
278 pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
280 /* FIXME: There should probably be a general function for checking whether
281 * the sink volume is allowed to be set, like there is for sink inputs. */
282 pa_assert(!data->volume_is_set || !(flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
284 if (!data->volume_is_set) {
285 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
286 data->save_volume = false;
289 pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
290 pa_return_null_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec));
292 if (!data->muted_is_set)
296 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
298 pa_device_init_description(data->proplist, data->card);
299 pa_device_init_icon(data->proplist, true);
300 pa_device_init_intended_roles(data->proplist);
302 if (!data->active_port) {
303 pa_device_port *p = pa_device_port_find_best(data->ports);
305 pa_sink_new_data_set_port(data, p->name);
308 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {
310 pa_namereg_unregister(core, name);
314 s->parent.parent.free = sink_free;
315 s->parent.process_msg = pa_sink_process_msg;
318 s->state = PA_SINK_INIT;
321 s->suspend_cause = data->suspend_cause;
322 pa_sink_set_mixer_dirty(s, false);
323 s->name = pa_xstrdup(name);
324 s->proplist = pa_proplist_copy(data->proplist);
325 s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
326 s->module = data->module;
327 s->card = data->card;
329 s->priority = pa_device_init_priority(s->proplist);
331 s->sample_spec = data->sample_spec;
332 s->channel_map = data->channel_map;
333 s->default_sample_rate = s->sample_spec.rate;
335 if (data->alternate_sample_rate_is_set)
336 s->alternate_sample_rate = data->alternate_sample_rate;
338 s->alternate_sample_rate = s->core->alternate_sample_rate;
340 if (s->sample_spec.rate == s->alternate_sample_rate) {
341 pa_log_warn("Default and alternate sample rates are the same.");
342 s->alternate_sample_rate = 0;
345 s->inputs = pa_idxset_new(NULL, NULL);
347 s->input_to_master = NULL;
349 s->reference_volume = s->real_volume = data->volume;
350 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
351 s->base_volume = PA_VOLUME_NORM;
352 s->n_volume_steps = PA_VOLUME_NORM+1;
353 s->muted = data->muted;
354 s->refresh_volume = s->refresh_muted = false;
361 /* As a minor optimization we just steal the list instead of
363 s->ports = data->ports;
366 s->active_port = NULL;
367 s->save_port = false;
369 if (data->active_port)
370 if ((s->active_port = pa_hashmap_get(s->ports, data->active_port)))
371 s->save_port = data->save_port;
373 /* Hopefully the active port has already been assigned in the previous call
374 to pa_device_port_find_best, but better safe than sorry */
376 s->active_port = pa_device_port_find_best(s->ports);
379 s->port_latency_offset = s->active_port->latency_offset;
381 s->port_latency_offset = 0;
383 s->save_volume = data->save_volume;
384 s->save_muted = data->save_muted;
385 #ifdef TIZEN_PCM_DUMP
386 s->pcm_dump_fp = NULL;
390 pa_silence_memchunk_get(
391 &core->silence_cache,
397 s->thread_info.rtpoll = NULL;
398 s->thread_info.inputs = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL,
399 (pa_free_cb_t) pa_sink_input_unref);
400 s->thread_info.soft_volume = s->soft_volume;
401 s->thread_info.soft_muted = s->muted;
402 s->thread_info.state = s->state;
403 s->thread_info.rewind_nbytes = 0;
404 s->thread_info.rewind_requested = false;
405 s->thread_info.max_rewind = 0;
406 s->thread_info.max_request = 0;
407 s->thread_info.requested_latency_valid = false;
408 s->thread_info.requested_latency = 0;
409 s->thread_info.min_latency = ABSOLUTE_MIN_LATENCY;
410 s->thread_info.max_latency = ABSOLUTE_MAX_LATENCY;
411 s->thread_info.fixed_latency = flags & PA_SINK_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
413 PA_LLIST_HEAD_INIT(pa_sink_volume_change, s->thread_info.volume_changes);
414 s->thread_info.volume_changes_tail = NULL;
415 pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
416 s->thread_info.volume_change_safety_margin = core->deferred_volume_safety_margin_usec;
417 s->thread_info.volume_change_extra_delay = core->deferred_volume_extra_delay_usec;
418 s->thread_info.port_latency_offset = s->port_latency_offset;
420 /* FIXME: This should probably be moved to pa_sink_put() */
421 pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
424 pa_assert_se(pa_idxset_put(s->card->sinks, s, NULL) >= 0);
426 pt = pa_proplist_to_string_sep(s->proplist, "\n ");
427 pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s\n %s",
430 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
431 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
435 pa_source_new_data_init(&source_data);
436 pa_source_new_data_set_sample_spec(&source_data, &s->sample_spec);
437 pa_source_new_data_set_channel_map(&source_data, &s->channel_map);
438 pa_source_new_data_set_alternate_sample_rate(&source_data, s->alternate_sample_rate);
439 source_data.name = pa_sprintf_malloc("%s.monitor", name);
440 source_data.driver = data->driver;
441 source_data.module = data->module;
442 source_data.card = data->card;
444 dn = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
445 pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
446 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
448 s->monitor_source = pa_source_new(core, &source_data,
449 ((flags & PA_SINK_LATENCY) ? PA_SOURCE_LATENCY : 0) |
450 ((flags & PA_SINK_DYNAMIC_LATENCY) ? PA_SOURCE_DYNAMIC_LATENCY : 0));
452 pa_source_new_data_done(&source_data);
454 if (!s->monitor_source) {
460 s->monitor_source->monitor_of = s;
462 pa_source_set_latency_range(s->monitor_source, s->thread_info.min_latency, s->thread_info.max_latency);
463 pa_source_set_fixed_latency(s->monitor_source, s->thread_info.fixed_latency);
464 pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
469 /* Called from main context */
470 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
473 pa_sink_state_t original_state;
476 pa_assert_ctl_context();
478 if (s->state == state)
481 original_state = s->state;
484 (original_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state)) ||
485 (PA_SINK_IS_OPENED(original_state) && state == PA_SINK_SUSPENDED);
488 if ((ret = s->set_state(s, state)) < 0)
492 if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
495 s->set_state(s, original_state);
500 pa_log_debug("%s: state: %s -> %s", s->name, pa_sink_state_to_string(s->state), pa_sink_state_to_string(state));
502 #ifdef TIZEN_PCM_DUMP
503 /* close file for dump pcm */
504 if (s->pcm_dump_fp && (s->core->pcm_dump_option & PA_PCM_DUMP_OPTION_SEPARATED) &&
505 state == PA_SINK_IDLE && original_state == PA_SINK_RUNNING) {
506 fclose(s->pcm_dump_fp);
507 pa_log_info("%s closed", s->dump_path);
508 pa_xfree(s->dump_path);
509 s->pcm_dump_fp = NULL;
513 if (state != PA_SINK_UNLINKED) { /* if we enter UNLINKED state pa_sink_unlink() will fire the appropriate events */
514 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
515 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
518 if (suspend_change) {
522 /* We're suspending or resuming, tell everyone about it */
524 PA_IDXSET_FOREACH(i, s->inputs, idx)
525 if (s->state == PA_SINK_SUSPENDED &&
526 (i->flags & PA_SINK_INPUT_KILL_ON_SUSPEND))
527 pa_sink_input_kill(i);
529 i->suspend(i, state == PA_SINK_SUSPENDED);
531 if (s->monitor_source)
532 pa_source_sync_suspend(s->monitor_source);
538 void pa_sink_set_get_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
544 void pa_sink_set_set_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
545 pa_sink_flags_t flags;
548 pa_assert(!s->write_volume || cb);
552 /* Save the current flags so we can tell if they've changed */
556 /* The sink implementor is responsible for setting decibel volume support */
557 s->flags |= PA_SINK_HW_VOLUME_CTRL;
559 s->flags &= ~PA_SINK_HW_VOLUME_CTRL;
560 /* See note below in pa_sink_put() about volume sharing and decibel volumes */
561 pa_sink_enable_decibel_volume(s, !(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
564 /* If the flags have changed after init, let any clients know via a change event */
565 if (s->state != PA_SINK_INIT && flags != s->flags)
566 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
569 void pa_sink_set_write_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
570 pa_sink_flags_t flags;
573 pa_assert(!cb || s->set_volume);
575 s->write_volume = cb;
577 /* Save the current flags so we can tell if they've changed */
581 s->flags |= PA_SINK_DEFERRED_VOLUME;
583 s->flags &= ~PA_SINK_DEFERRED_VOLUME;
585 /* If the flags have changed after init, let any clients know via a change event */
586 if (s->state != PA_SINK_INIT && flags != s->flags)
587 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
590 void pa_sink_set_get_mute_callback(pa_sink *s, pa_sink_get_mute_cb_t cb) {
596 void pa_sink_set_set_mute_callback(pa_sink *s, pa_sink_cb_t cb) {
597 pa_sink_flags_t flags;
603 /* Save the current flags so we can tell if they've changed */
607 s->flags |= PA_SINK_HW_MUTE_CTRL;
609 s->flags &= ~PA_SINK_HW_MUTE_CTRL;
611 /* If the flags have changed after init, let any clients know via a change event */
612 if (s->state != PA_SINK_INIT && flags != s->flags)
613 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
616 static void enable_flat_volume(pa_sink *s, bool enable) {
617 pa_sink_flags_t flags;
621 /* Always follow the overall user preference here */
622 enable = enable && s->core->flat_volumes;
624 /* Save the current flags so we can tell if they've changed */
628 s->flags |= PA_SINK_FLAT_VOLUME;
630 s->flags &= ~PA_SINK_FLAT_VOLUME;
632 /* If the flags have changed after init, let any clients know via a change event */
633 if (s->state != PA_SINK_INIT && flags != s->flags)
634 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
637 void pa_sink_enable_decibel_volume(pa_sink *s, bool enable) {
638 pa_sink_flags_t flags;
642 /* Save the current flags so we can tell if they've changed */
646 s->flags |= PA_SINK_DECIBEL_VOLUME;
647 enable_flat_volume(s, true);
649 s->flags &= ~PA_SINK_DECIBEL_VOLUME;
650 enable_flat_volume(s, false);
653 /* If the flags have changed after init, let any clients know via a change event */
654 if (s->state != PA_SINK_INIT && flags != s->flags)
655 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
658 /* Called from main context */
659 void pa_sink_put(pa_sink* s) {
660 pa_sink_assert_ref(s);
661 pa_assert_ctl_context();
663 pa_assert(s->state == PA_SINK_INIT);
664 pa_assert(!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER) || pa_sink_is_filter(s));
666 /* The following fields must be initialized properly when calling _put() */
667 pa_assert(s->asyncmsgq);
668 pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
670 /* Generally, flags should be initialized via pa_sink_new(). As a
671 * special exception we allow some volume related flags to be set
672 * between _new() and _put() by the callback setter functions above.
674 * Thus we implement a couple safeguards here which ensure the above
675 * setters were used (or at least the implementor made manual changes
676 * in a compatible way).
678 * Note: All of these flags set here can change over the life time
680 pa_assert(!(s->flags & PA_SINK_HW_VOLUME_CTRL) || s->set_volume);
681 pa_assert(!(s->flags & PA_SINK_DEFERRED_VOLUME) || s->write_volume);
682 pa_assert(!(s->flags & PA_SINK_HW_MUTE_CTRL) || s->set_mute);
684 /* XXX: Currently decibel volume is disabled for all sinks that use volume
685 * sharing. When the master sink supports decibel volume, it would be good
686 * to have the flag also in the filter sink, but currently we don't do that
687 * so that the flags of the filter sink never change when it's moved from
688 * a master sink to another. One solution for this problem would be to
689 * remove user-visible volume altogether from filter sinks when volume
690 * sharing is used, but the current approach was easier to implement... */
691 /* We always support decibel volumes in software, otherwise we leave it to
692 * the sink implementor to set this flag as needed.
694 * Note: This flag can also change over the life time of the sink. */
695 if (!(s->flags & PA_SINK_HW_VOLUME_CTRL) && !(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
696 pa_sink_enable_decibel_volume(s, true);
697 s->soft_volume = s->reference_volume;
700 /* If the sink implementor support DB volumes by itself, we should always
701 * try and enable flat volumes too */
702 if ((s->flags & PA_SINK_DECIBEL_VOLUME))
703 enable_flat_volume(s, true);
705 if (s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER) {
706 pa_sink *root_sink = pa_sink_get_master(s);
708 pa_assert(root_sink);
710 s->reference_volume = root_sink->reference_volume;
711 pa_cvolume_remap(&s->reference_volume, &root_sink->channel_map, &s->channel_map);
713 s->real_volume = root_sink->real_volume;
714 pa_cvolume_remap(&s->real_volume, &root_sink->channel_map, &s->channel_map);
716 /* We assume that if the sink implementor changed the default
717 * volume he did so in real_volume, because that is the usual
718 * place where he is supposed to place his changes. */
719 s->reference_volume = s->real_volume;
721 s->thread_info.soft_volume = s->soft_volume;
722 s->thread_info.soft_muted = s->muted;
723 pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
725 pa_assert((s->flags & PA_SINK_HW_VOLUME_CTRL)
726 || (s->base_volume == PA_VOLUME_NORM
727 && ((s->flags & PA_SINK_DECIBEL_VOLUME || (s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)))));
728 pa_assert(!(s->flags & PA_SINK_DECIBEL_VOLUME) || s->n_volume_steps == PA_VOLUME_NORM+1);
729 pa_assert(!(s->flags & PA_SINK_DYNAMIC_LATENCY) == !(s->thread_info.fixed_latency == 0));
730 pa_assert(!(s->flags & PA_SINK_LATENCY) == !(s->monitor_source->flags & PA_SOURCE_LATENCY));
731 pa_assert(!(s->flags & PA_SINK_DYNAMIC_LATENCY) == !(s->monitor_source->flags & PA_SOURCE_DYNAMIC_LATENCY));
733 pa_assert(s->monitor_source->thread_info.fixed_latency == s->thread_info.fixed_latency);
734 pa_assert(s->monitor_source->thread_info.min_latency == s->thread_info.min_latency);
735 pa_assert(s->monitor_source->thread_info.max_latency == s->thread_info.max_latency);
737 if (s->suspend_cause)
738 pa_assert_se(sink_set_state(s, PA_SINK_SUSPENDED) == 0);
740 pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
742 pa_source_put(s->monitor_source);
744 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
745 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s);
747 /* This function must be called after the PA_CORE_HOOK_SINK_PUT hook,
748 * because module-switch-on-connect needs to know the old default sink */
749 pa_core_update_default_sink(s->core);
752 /* Called from main context */
753 void pa_sink_unlink(pa_sink* s) {
755 pa_sink_input *i, PA_UNUSED *j = NULL;
757 pa_sink_assert_ref(s);
758 pa_assert_ctl_context();
760 /* Please note that pa_sink_unlink() does more than simply
761 * reversing pa_sink_put(). It also undoes the registrations
762 * already done in pa_sink_new()! */
764 if (s->unlink_requested)
767 s->unlink_requested = true;
769 linked = PA_SINK_IS_LINKED(s->state);
772 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
774 if (s->state != PA_SINK_UNLINKED)
775 pa_namereg_unregister(s->core, s->name);
776 pa_idxset_remove_by_data(s->core->sinks, s, NULL);
778 pa_core_update_default_sink(s->core);
781 pa_idxset_remove_by_data(s->card->sinks, s, NULL);
783 while ((i = pa_idxset_first(s->inputs, NULL))) {
785 pa_sink_input_kill(i);
790 sink_set_state(s, PA_SINK_UNLINKED);
792 s->state = PA_SINK_UNLINKED;
796 if (s->monitor_source)
797 pa_source_unlink(s->monitor_source);
800 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
801 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
805 /* Called from main context */
806 static void sink_free(pa_object *o) {
807 pa_sink *s = PA_SINK(o);
810 pa_assert_ctl_context();
811 pa_assert(pa_sink_refcnt(s) == 0);
812 pa_assert(!PA_SINK_IS_LINKED(s->state));
814 pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
816 pa_sink_volume_change_flush(s);
818 if (s->monitor_source) {
819 pa_source_unref(s->monitor_source);
820 s->monitor_source = NULL;
823 pa_idxset_free(s->inputs, NULL);
824 pa_hashmap_free(s->thread_info.inputs);
826 if (s->silence.memblock)
827 pa_memblock_unref(s->silence.memblock);
833 pa_proplist_free(s->proplist);
836 pa_hashmap_free(s->ports);
838 #ifdef TIZEN_PCM_DUMP
839 /* close file for dump pcm */
840 if (s->pcm_dump_fp) {
841 fclose(s->pcm_dump_fp);
842 pa_log_info("%s closed", s->dump_path);
843 pa_xfree(s->dump_path);
844 s->pcm_dump_fp = NULL;
850 /* Called from main context, and not while the IO thread is active, please */
851 void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
852 pa_sink_assert_ref(s);
853 pa_assert_ctl_context();
857 if (s->monitor_source)
858 pa_source_set_asyncmsgq(s->monitor_source, q);
861 /* Called from main context, and not while the IO thread is active, please */
862 void pa_sink_update_flags(pa_sink *s, pa_sink_flags_t mask, pa_sink_flags_t value) {
863 pa_sink_flags_t old_flags;
864 pa_sink_input *input;
867 pa_sink_assert_ref(s);
868 pa_assert_ctl_context();
870 /* For now, allow only a minimal set of flags to be changed. */
871 pa_assert((mask & ~(PA_SINK_DYNAMIC_LATENCY|PA_SINK_LATENCY)) == 0);
873 old_flags = s->flags;
874 s->flags = (s->flags & ~mask) | (value & mask);
876 if (s->flags == old_flags)
879 if ((s->flags & PA_SINK_LATENCY) != (old_flags & PA_SINK_LATENCY))
880 pa_log_debug("Sink %s: LATENCY flag %s.", s->name, (s->flags & PA_SINK_LATENCY) ? "enabled" : "disabled");
882 if ((s->flags & PA_SINK_DYNAMIC_LATENCY) != (old_flags & PA_SINK_DYNAMIC_LATENCY))
883 pa_log_debug("Sink %s: DYNAMIC_LATENCY flag %s.",
884 s->name, (s->flags & PA_SINK_DYNAMIC_LATENCY) ? "enabled" : "disabled");
886 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
887 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_FLAGS_CHANGED], s);
889 if (s->monitor_source)
890 pa_source_update_flags(s->monitor_source,
891 ((mask & PA_SINK_LATENCY) ? PA_SOURCE_LATENCY : 0) |
892 ((mask & PA_SINK_DYNAMIC_LATENCY) ? PA_SOURCE_DYNAMIC_LATENCY : 0),
893 ((value & PA_SINK_LATENCY) ? PA_SOURCE_LATENCY : 0) |
894 ((value & PA_SINK_DYNAMIC_LATENCY) ? PA_SOURCE_DYNAMIC_LATENCY : 0));
896 PA_IDXSET_FOREACH(input, s->inputs, idx) {
897 if (input->origin_sink)
898 pa_sink_update_flags(input->origin_sink, mask, value);
902 /* Called from IO context, or before _put() from main context */
903 void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
904 pa_sink_assert_ref(s);
905 pa_sink_assert_io_context(s);
907 s->thread_info.rtpoll = p;
909 if (s->monitor_source)
910 pa_source_set_rtpoll(s->monitor_source, p);
913 /* Called from main context */
914 int pa_sink_update_status(pa_sink*s) {
915 pa_sink_assert_ref(s);
916 pa_assert_ctl_context();
917 pa_assert(PA_SINK_IS_LINKED(s->state));
919 if (s->state == PA_SINK_SUSPENDED)
922 return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
925 /* Called from any context - must be threadsafe */
926 void pa_sink_set_mixer_dirty(pa_sink *s, bool is_dirty) {
927 pa_atomic_store(&s->mixer_dirty, is_dirty ? 1 : 0);
930 /* Called from main context */
931 int pa_sink_suspend(pa_sink *s, bool suspend, pa_suspend_cause_t cause) {
932 pa_suspend_cause_t old_cause;
933 char old_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
934 char new_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
936 pa_sink_assert_ref(s);
937 pa_assert_ctl_context();
938 pa_assert(PA_SINK_IS_LINKED(s->state));
939 pa_assert(cause != 0);
941 old_cause = s->suspend_cause;
944 s->suspend_cause |= cause;
945 s->monitor_source->suspend_cause |= cause;
947 s->suspend_cause &= ~cause;
948 s->monitor_source->suspend_cause &= ~cause;
951 if (s->suspend_cause != old_cause) {
952 pa_log_debug("%s: suspend_cause: %s -> %s", s->name, pa_suspend_cause_to_string(old_cause, old_cause_buf),
953 pa_suspend_cause_to_string(s->suspend_cause, new_cause_buf));
956 if (!(s->suspend_cause & PA_SUSPEND_SESSION) && (pa_atomic_load(&s->mixer_dirty) != 0)) {
957 /* This might look racy but isn't: If somebody sets mixer_dirty exactly here,
958 it'll be handled just fine. */
959 pa_sink_set_mixer_dirty(s, false);
960 pa_log_debug("Mixer is now accessible. Updating alsa mixer settings.");
961 if (s->active_port && s->set_port) {
962 if (s->flags & PA_SINK_DEFERRED_VOLUME) {
963 struct sink_message_set_port msg = { .port = s->active_port, .ret = 0 };
964 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT, &msg, 0, NULL) == 0);
967 s->set_port(s, s->active_port);
977 if ((pa_sink_get_state(s) == PA_SINK_SUSPENDED) == !!s->suspend_cause)
980 if (s->suspend_cause)
981 return sink_set_state(s, PA_SINK_SUSPENDED);
983 return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
986 /* Called from main context */
987 pa_queue *pa_sink_move_all_start(pa_sink *s, pa_queue *q) {
988 pa_sink_input *i, *n;
991 pa_sink_assert_ref(s);
992 pa_assert_ctl_context();
993 pa_assert(PA_SINK_IS_LINKED(s->state));
998 for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = n) {
999 n = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx));
1001 pa_sink_input_ref(i);
1003 if (pa_sink_input_start_move(i) >= 0)
1004 pa_queue_push(q, i);
1006 pa_sink_input_unref(i);
1012 /* Called from main context */
1013 void pa_sink_move_all_finish(pa_sink *s, pa_queue *q, bool save) {
1016 pa_sink_assert_ref(s);
1017 pa_assert_ctl_context();
1018 pa_assert(PA_SINK_IS_LINKED(s->state));
1021 while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
1022 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1023 if (pa_sink_input_finish_move(i, s, save) < 0)
1024 pa_sink_input_fail_move(i);
1027 pa_sink_input_unref(i);
1030 pa_queue_free(q, NULL);
1033 /* Called from main context */
1034 void pa_sink_move_all_fail(pa_queue *q) {
1037 pa_assert_ctl_context();
1040 while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
1041 pa_sink_input_fail_move(i);
1042 pa_sink_input_unref(i);
1045 pa_queue_free(q, NULL);
1048 /* Called from IO thread context */
1049 size_t pa_sink_process_input_underruns(pa_sink *s, size_t left_to_play) {
1054 pa_sink_assert_ref(s);
1055 pa_sink_assert_io_context(s);
1057 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
1058 size_t uf = i->thread_info.underrun_for_sink;
1060 /* Propagate down the filter tree */
1061 if (i->origin_sink) {
1062 size_t filter_result, left_to_play_origin;
1064 /* The recursive call works in the origin sink domain ... */
1065 left_to_play_origin = pa_convert_size(left_to_play, &i->sink->sample_spec, &i->origin_sink->sample_spec);
1067 /* .. and returns the time to sleep before waking up. We need the
1068 * underrun duration for comparisons, so we undo the subtraction on
1069 * the return value... */
1070 filter_result = left_to_play_origin - pa_sink_process_input_underruns(i->origin_sink, left_to_play_origin);
1072 /* ... and convert it back to the master sink domain */
1073 filter_result = pa_convert_size(filter_result, &i->origin_sink->sample_spec, &i->sink->sample_spec);
1075 /* Remember the longest underrun so far */
1076 if (filter_result > result)
1077 result = filter_result;
1081 /* No underrun here, move on */
1083 } else if (uf >= left_to_play) {
1084 /* The sink has possibly consumed all the data the sink input provided */
1085 pa_sink_input_process_underrun(i);
1086 } else if (uf > result) {
1087 /* Remember the longest underrun so far */
1093 pa_log_debug("%s: Found underrun %ld bytes ago (%ld bytes ahead in playback buffer)", s->name,
1094 (long) result, (long) left_to_play - result);
1095 return left_to_play - result;
1098 /* Called from IO thread context */
1099 void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
1103 pa_sink_assert_ref(s);
1104 pa_sink_assert_io_context(s);
1105 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1107 /* If nobody requested this and this is actually no real rewind
1108 * then we can short cut this. Please note that this means that
1109 * not all rewind requests triggered upstream will always be
1110 * translated in actual requests! */
1111 if (!s->thread_info.rewind_requested && nbytes <= 0)
1114 s->thread_info.rewind_nbytes = 0;
1115 s->thread_info.rewind_requested = false;
1118 pa_log_debug("Processing rewind...");
1119 if (s->flags & PA_SINK_DEFERRED_VOLUME)
1120 pa_sink_volume_change_rewind(s, nbytes);
1121 #ifdef TIZEN_PCM_DUMP
1124 fseeko(s->pcm_dump_fp, (off_t)nbytes * (-1), SEEK_CUR);
1128 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
1129 pa_sink_input_assert_ref(i);
1130 pa_sink_input_process_rewind(i, nbytes);
1134 if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
1135 pa_source_process_rewind(s->monitor_source, nbytes);
1139 /* Called from IO thread context */
1140 static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxinfo) {
1144 size_t mixlength = *length;
1146 pa_sink_assert_ref(s);
1147 pa_sink_assert_io_context(s);
1150 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
1151 pa_sink_input_assert_ref(i);
1153 pa_sink_input_peek(i, *length, &info->chunk, &info->volume);
1155 if (mixlength == 0 || info->chunk.length < mixlength)
1156 mixlength = info->chunk.length;
1158 if (pa_memblock_is_silence(info->chunk.memblock)) {
1159 pa_memblock_unref(info->chunk.memblock);
1163 info->userdata = pa_sink_input_ref(i);
1165 pa_assert(info->chunk.memblock);
1166 pa_assert(info->chunk.length > 0);
1174 *length = mixlength;
1179 /* Called from IO thread context */
1180 static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *result) {
1184 unsigned n_unreffed = 0;
1186 pa_sink_assert_ref(s);
1187 pa_sink_assert_io_context(s);
1189 pa_assert(result->memblock);
1190 pa_assert(result->length > 0);
1192 /* We optimize for the case where the order of the inputs has not changed */
1194 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
1196 pa_mix_info* m = NULL;
1198 pa_sink_input_assert_ref(i);
1200 /* Let's try to find the matching entry info the pa_mix_info array */
1201 for (j = 0; j < n; j ++) {
1203 if (info[p].userdata == i) {
1213 /* Drop read data */
1214 pa_sink_input_drop(i, result->length);
1216 if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state)) {
1218 if (pa_hashmap_size(i->thread_info.direct_outputs) > 0) {
1219 void *ostate = NULL;
1220 pa_source_output *o;
1223 if (m && m->chunk.memblock) {
1225 pa_memblock_ref(c.memblock);
1226 pa_assert(result->length <= c.length);
1227 c.length = result->length;
1229 pa_memchunk_make_writable(&c, 0);
1230 pa_volume_memchunk(&c, &s->sample_spec, &m->volume);
1233 pa_memblock_ref(c.memblock);
1234 pa_assert(result->length <= c.length);
1235 c.length = result->length;
1238 while ((o = pa_hashmap_iterate(i->thread_info.direct_outputs, &ostate, NULL))) {
1239 pa_source_output_assert_ref(o);
1240 pa_assert(o->direct_on_input == i);
1241 pa_source_post_direct(s->monitor_source, o, &c);
1244 pa_memblock_unref(c.memblock);
1249 if (m->chunk.memblock) {
1250 pa_memblock_unref(m->chunk.memblock);
1251 pa_memchunk_reset(&m->chunk);
1254 pa_sink_input_unref(m->userdata);
1261 /* Now drop references to entries that are included in the
1262 * pa_mix_info array but don't exist anymore */
1264 if (n_unreffed < n) {
1265 for (; n > 0; info++, n--) {
1267 pa_sink_input_unref(info->userdata);
1268 if (info->chunk.memblock)
1269 pa_memblock_unref(info->chunk.memblock);
1273 if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
1274 pa_source_post(s->monitor_source, result);
1277 /* Called from IO thread context */
1278 void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
1279 pa_mix_info info[MAX_MIX_CHANNELS];
1281 size_t block_size_max;
1283 pa_sink_assert_ref(s);
1284 pa_sink_assert_io_context(s);
1285 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1286 pa_assert(pa_frame_aligned(length, &s->sample_spec));
1289 pa_assert(!s->thread_info.rewind_requested);
1290 pa_assert(s->thread_info.rewind_nbytes == 0);
1292 if (s->thread_info.state == PA_SINK_SUSPENDED) {
1293 result->memblock = pa_memblock_ref(s->silence.memblock);
1294 result->index = s->silence.index;
1295 result->length = PA_MIN(s->silence.length, length);
1302 length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
1304 block_size_max = pa_mempool_block_size_max(s->core->mempool);
1305 if (length > block_size_max)
1306 length = pa_frame_align(block_size_max, &s->sample_spec);
1308 pa_assert(length > 0);
1310 n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
1314 *result = s->silence;
1315 pa_memblock_ref(result->memblock);
1317 if (result->length > length)
1318 result->length = length;
1320 } else if (n == 1) {
1323 *result = info[0].chunk;
1324 pa_memblock_ref(result->memblock);
1326 if (result->length > length)
1327 result->length = length;
1329 pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
1331 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) {
1332 pa_memblock_unref(result->memblock);
1333 pa_silence_memchunk_get(&s->core->silence_cache,
1338 } else if (!pa_cvolume_is_norm(&volume)) {
1339 pa_memchunk_make_writable(result, 0);
1340 pa_volume_memchunk(result, &s->sample_spec, &volume);
1344 result->memblock = pa_memblock_new(s->core->mempool, length);
1346 ptr = pa_memblock_acquire(result->memblock);
1347 result->length = pa_mix(info, n,
1350 &s->thread_info.soft_volume,
1351 s->thread_info.soft_muted);
1352 pa_memblock_release(result->memblock);
1357 inputs_drop(s, info, n, result);
1359 #ifdef TIZEN_PCM_DUMP
1360 pa_sink_write_pcm_dump(s, result);
1365 /* Called from IO thread context */
1366 void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
1367 pa_mix_info info[MAX_MIX_CHANNELS];
1369 size_t length, block_size_max;
1371 pa_sink_assert_ref(s);
1372 pa_sink_assert_io_context(s);
1373 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1375 pa_assert(target->memblock);
1376 pa_assert(target->length > 0);
1377 pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
1379 pa_assert(!s->thread_info.rewind_requested);
1380 pa_assert(s->thread_info.rewind_nbytes == 0);
1382 if (s->thread_info.state == PA_SINK_SUSPENDED) {
1383 pa_silence_memchunk(target, &s->sample_spec);
1389 length = target->length;
1390 block_size_max = pa_mempool_block_size_max(s->core->mempool);
1391 if (length > block_size_max)
1392 length = pa_frame_align(block_size_max, &s->sample_spec);
1394 pa_assert(length > 0);
1396 n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
1399 if (target->length > length)
1400 target->length = length;
1402 pa_silence_memchunk(target, &s->sample_spec);
1403 } else if (n == 1) {
1406 if (target->length > length)
1407 target->length = length;
1409 pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
1411 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
1412 pa_silence_memchunk(target, &s->sample_spec);
1416 vchunk = info[0].chunk;
1417 pa_memblock_ref(vchunk.memblock);
1419 if (vchunk.length > length)
1420 vchunk.length = length;
1422 if (!pa_cvolume_is_norm(&volume)) {
1423 pa_memchunk_make_writable(&vchunk, 0);
1424 pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
1427 pa_memchunk_memcpy(target, &vchunk);
1428 pa_memblock_unref(vchunk.memblock);
1434 ptr = pa_memblock_acquire(target->memblock);
1436 target->length = pa_mix(info, n,
1437 (uint8_t*) ptr + target->index, length,
1439 &s->thread_info.soft_volume,
1440 s->thread_info.soft_muted);
1442 pa_memblock_release(target->memblock);
1445 inputs_drop(s, info, n, target);
1447 #ifdef TIZEN_PCM_DUMP
1448 pa_sink_write_pcm_dump(s, target);
1453 /* Called from IO thread context */
1454 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
1458 pa_sink_assert_ref(s);
1459 pa_sink_assert_io_context(s);
1460 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1462 pa_assert(target->memblock);
1463 pa_assert(target->length > 0);
1464 pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
1466 pa_assert(!s->thread_info.rewind_requested);
1467 pa_assert(s->thread_info.rewind_nbytes == 0);
1469 if (s->thread_info.state == PA_SINK_SUSPENDED) {
1470 pa_silence_memchunk(target, &s->sample_spec);
1483 pa_sink_render_into(s, &chunk);
1492 /* Called from IO thread context */
1493 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
1494 pa_sink_assert_ref(s);
1495 pa_sink_assert_io_context(s);
1496 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1497 pa_assert(length > 0);
1498 pa_assert(pa_frame_aligned(length, &s->sample_spec));
1501 pa_assert(!s->thread_info.rewind_requested);
1502 pa_assert(s->thread_info.rewind_nbytes == 0);
1506 pa_sink_render(s, length, result);
1508 if (result->length < length) {
1511 pa_memchunk_make_writable(result, length);
1513 chunk.memblock = result->memblock;
1514 chunk.index = result->index + result->length;
1515 chunk.length = length - result->length;
1517 pa_sink_render_into_full(s, &chunk);
1519 result->length = length;
1525 /* Called from main thread */
1526 int pa_sink_reconfigure(pa_sink *s, pa_sample_spec *spec, bool passthrough) {
1528 pa_sample_spec desired_spec;
1529 uint32_t default_rate = s->default_sample_rate;
1530 uint32_t alternate_rate = s->alternate_sample_rate;
1533 bool default_rate_is_usable = false;
1534 bool alternate_rate_is_usable = false;
1535 bool avoid_resampling = s->core->avoid_resampling;
1537 /* We currently only try to reconfigure the sample rate */
1539 if (pa_sample_spec_equal(spec, &s->sample_spec))
1542 if (!s->reconfigure)
1545 if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough && !avoid_resampling)) {
1546 pa_log_debug("Default and alternate sample rates are the same, so there is no point in switching.");
1550 if (PA_SINK_IS_RUNNING(s->state)) {
1551 pa_log_info("Cannot update rate, SINK_IS_RUNNING, will keep using %u Hz",
1552 s->sample_spec.rate);
1556 if (s->monitor_source) {
1557 if (PA_SOURCE_IS_RUNNING(s->monitor_source->state) == true) {
1558 pa_log_info("Cannot update rate, monitor source is RUNNING");
1563 if (PA_UNLIKELY(!pa_sample_spec_valid(spec)))
1566 desired_spec = s->sample_spec;
1569 /* We have to try to use the sink input rate */
1570 desired_spec.rate = spec->rate;
1572 } else if (avoid_resampling && (spec->rate >= default_rate || spec->rate >= alternate_rate)) {
1573 /* We just try to set the sink input's sample rate if it's not too low */
1574 desired_spec.rate = spec->rate;
1576 } else if (default_rate == spec->rate || alternate_rate == spec->rate) {
1577 /* We can directly try to use this rate */
1578 desired_spec.rate = spec->rate;
1581 /* See if we can pick a rate that results in less resampling effort */
1582 if (default_rate % 11025 == 0 && spec->rate % 11025 == 0)
1583 default_rate_is_usable = true;
1584 if (default_rate % 4000 == 0 && spec->rate % 4000 == 0)
1585 default_rate_is_usable = true;
1586 if (alternate_rate && alternate_rate % 11025 == 0 && spec->rate % 11025 == 0)
1587 alternate_rate_is_usable = true;
1588 if (alternate_rate && alternate_rate % 4000 == 0 && spec->rate % 4000 == 0)
1589 alternate_rate_is_usable = true;
1591 if (alternate_rate_is_usable && !default_rate_is_usable)
1592 desired_spec.rate = alternate_rate;
1594 desired_spec.rate = default_rate;
1597 if (pa_sample_spec_equal(&desired_spec, &s->sample_spec) && passthrough == pa_sink_is_passthrough(s))
1600 if (!passthrough && pa_sink_used_by(s) > 0)
1603 pa_log_debug("Suspending sink %s due to changing format.", s->name);
1604 pa_sink_suspend(s, true, PA_SUSPEND_INTERNAL);
1606 if (s->reconfigure(s, &desired_spec, passthrough) >= 0) {
1607 /* update monitor source as well */
1608 if (s->monitor_source && !passthrough)
1609 pa_source_reconfigure(s->monitor_source, &desired_spec, false);
1610 pa_log_info("Changed format successfully");
1612 PA_IDXSET_FOREACH(i, s->inputs, idx) {
1613 if (i->state == PA_SINK_INPUT_CORKED)
1614 pa_sink_input_update_rate(i);
1620 pa_sink_suspend(s, false, PA_SUSPEND_INTERNAL);
1625 /* Called from main thread */
1626 pa_usec_t pa_sink_get_latency(pa_sink *s) {
1629 pa_sink_assert_ref(s);
1630 pa_assert_ctl_context();
1631 pa_assert(PA_SINK_IS_LINKED(s->state));
1633 /* The returned value is supposed to be in the time domain of the sound card! */
1635 if (s->state == PA_SINK_SUSPENDED)
1638 if (!(s->flags & PA_SINK_LATENCY))
1641 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
1643 /* the return value is unsigned, so check that the offset can be added to usec without
1645 if (-s->port_latency_offset <= usec)
1646 usec += s->port_latency_offset;
1650 return (pa_usec_t)usec;
1653 /* Called from IO thread */
1654 int64_t pa_sink_get_latency_within_thread(pa_sink *s, bool allow_negative) {
1658 pa_sink_assert_ref(s);
1659 pa_sink_assert_io_context(s);
1660 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1662 /* The returned value is supposed to be in the time domain of the sound card! */
1664 if (s->thread_info.state == PA_SINK_SUSPENDED)
1667 if (!(s->flags & PA_SINK_LATENCY))
1670 o = PA_MSGOBJECT(s);
1672 /* FIXME: We probably should make this a proper vtable callback instead of going through process_msg() */
1674 o->process_msg(o, PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL);
1676 /* If allow_negative is false, the call should only return positive values, */
1677 usec += s->thread_info.port_latency_offset;
1678 if (!allow_negative && usec < 0)
1684 /* Called from the main thread (and also from the IO thread while the main
1685 * thread is waiting).
1687 * When a sink uses volume sharing, it never has the PA_SINK_FLAT_VOLUME flag
1688 * set. Instead, flat volume mode is detected by checking whether the root sink
1689 * has the flag set. */
1690 bool pa_sink_flat_volume_enabled(pa_sink *s) {
1691 pa_sink_assert_ref(s);
1693 s = pa_sink_get_master(s);
1696 return (s->flags & PA_SINK_FLAT_VOLUME);
1701 /* Called from the main thread (and also from the IO thread while the main
1702 * thread is waiting). */
1703 pa_sink *pa_sink_get_master(pa_sink *s) {
1704 pa_sink_assert_ref(s);
1706 while (s && (s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1707 if (PA_UNLIKELY(!s->input_to_master))
1710 s = s->input_to_master->sink;
1716 /* Called from main context */
1717 bool pa_sink_is_filter(pa_sink *s) {
1718 pa_sink_assert_ref(s);
1720 return (s->input_to_master != NULL);
1723 /* Called from main context */
1724 bool pa_sink_is_passthrough(pa_sink *s) {
1725 pa_sink_input *alt_i;
1728 pa_sink_assert_ref(s);
1730 /* one and only one PASSTHROUGH input can possibly be connected */
1731 if (pa_idxset_size(s->inputs) == 1) {
1732 alt_i = pa_idxset_first(s->inputs, &idx);
1734 if (pa_sink_input_is_passthrough(alt_i))
1741 /* Called from main context */
1742 void pa_sink_enter_passthrough(pa_sink *s) {
1745 /* The sink implementation is reconfigured for passthrough in
1746 * pa_sink_reconfigure(). This function sets the PA core objects to
1747 * passthrough mode. */
1749 /* disable the monitor in passthrough mode */
1750 if (s->monitor_source) {
1751 pa_log_debug("Suspending monitor source %s, because the sink is entering the passthrough mode.", s->monitor_source->name);
1752 pa_source_suspend(s->monitor_source, true, PA_SUSPEND_PASSTHROUGH);
1755 /* set the volume to NORM */
1756 s->saved_volume = *pa_sink_get_volume(s, true);
1757 s->saved_save_volume = s->save_volume;
1759 pa_cvolume_set(&volume, s->sample_spec.channels, PA_MIN(s->base_volume, PA_VOLUME_NORM));
1760 pa_sink_set_volume(s, &volume, true, false);
1762 pa_log_debug("Suspending/Restarting sink %s to enter passthrough mode", s->name);
1765 /* Called from main context */
1766 void pa_sink_leave_passthrough(pa_sink *s) {
1767 /* Unsuspend monitor */
1768 if (s->monitor_source) {
1769 pa_log_debug("Resuming monitor source %s, because the sink is leaving the passthrough mode.", s->monitor_source->name);
1770 pa_source_suspend(s->monitor_source, false, PA_SUSPEND_PASSTHROUGH);
1773 /* Restore sink volume to what it was before we entered passthrough mode */
1774 pa_sink_set_volume(s, &s->saved_volume, true, s->saved_save_volume);
1776 pa_cvolume_init(&s->saved_volume);
1777 s->saved_save_volume = false;
1781 /* Called from main context. */
1782 static void compute_reference_ratio(pa_sink_input *i) {
1784 pa_cvolume remapped;
1788 pa_assert(pa_sink_flat_volume_enabled(i->sink));
1791 * Calculates the reference ratio from the sink's reference
1792 * volume. This basically calculates:
1794 * i->reference_ratio = i->volume / i->sink->reference_volume
1797 remapped = i->sink->reference_volume;
1798 pa_cvolume_remap(&remapped, &i->sink->channel_map, &i->channel_map);
1800 ratio = i->reference_ratio;
1802 for (c = 0; c < i->sample_spec.channels; c++) {
1804 /* We don't update when the sink volume is 0 anyway */
1805 if (remapped.values[c] <= PA_VOLUME_MUTED)
1808 /* Don't update the reference ratio unless necessary */
1809 if (pa_sw_volume_multiply(
1811 remapped.values[c]) == i->volume.values[c])
1814 ratio.values[c] = pa_sw_volume_divide(
1815 i->volume.values[c],
1816 remapped.values[c]);
1819 pa_sink_input_set_reference_ratio(i, &ratio);
1822 /* Called from main context. Only called for the root sink in volume sharing
1823 * cases, except for internal recursive calls. */
1824 static void compute_reference_ratios(pa_sink *s) {
1828 pa_sink_assert_ref(s);
1829 pa_assert_ctl_context();
1830 pa_assert(PA_SINK_IS_LINKED(s->state));
1831 pa_assert(pa_sink_flat_volume_enabled(s));
1833 PA_IDXSET_FOREACH(i, s->inputs, idx) {
1834 compute_reference_ratio(i);
1836 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
1837 && PA_SINK_IS_LINKED(i->origin_sink->state))
1838 compute_reference_ratios(i->origin_sink);
1842 /* Called from main context. Only called for the root sink in volume sharing
1843 * cases, except for internal recursive calls. */
1844 static void compute_real_ratios(pa_sink *s) {
1848 pa_sink_assert_ref(s);
1849 pa_assert_ctl_context();
1850 pa_assert(PA_SINK_IS_LINKED(s->state));
1851 pa_assert(pa_sink_flat_volume_enabled(s));
1853 PA_IDXSET_FOREACH(i, s->inputs, idx) {
1855 pa_cvolume remapped;
1857 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1858 /* The origin sink uses volume sharing, so this input's real ratio
1859 * is handled as a special case - the real ratio must be 0 dB, and
1860 * as a result i->soft_volume must equal i->volume_factor. */
1861 pa_cvolume_reset(&i->real_ratio, i->real_ratio.channels);
1862 i->soft_volume = i->volume_factor;
1864 if (PA_SINK_IS_LINKED(i->origin_sink->state))
1865 compute_real_ratios(i->origin_sink);
1871 * This basically calculates:
1873 * i->real_ratio := i->volume / s->real_volume
1874 * i->soft_volume := i->real_ratio * i->volume_factor
1877 remapped = s->real_volume;
1878 pa_cvolume_remap(&remapped, &s->channel_map, &i->channel_map);
1880 i->real_ratio.channels = i->sample_spec.channels;
1881 i->soft_volume.channels = i->sample_spec.channels;
1883 for (c = 0; c < i->sample_spec.channels; c++) {
1885 if (remapped.values[c] <= PA_VOLUME_MUTED) {
1886 /* We leave i->real_ratio untouched */
1887 i->soft_volume.values[c] = PA_VOLUME_MUTED;
1891 /* Don't lose accuracy unless necessary */
1892 if (pa_sw_volume_multiply(
1893 i->real_ratio.values[c],
1894 remapped.values[c]) != i->volume.values[c])
1896 i->real_ratio.values[c] = pa_sw_volume_divide(
1897 i->volume.values[c],
1898 remapped.values[c]);
1900 i->soft_volume.values[c] = pa_sw_volume_multiply(
1901 i->real_ratio.values[c],
1902 i->volume_factor.values[c]);
1905 /* We don't copy the soft_volume to the thread_info data
1906 * here. That must be done by the caller */
1910 static pa_cvolume *cvolume_remap_minimal_impact(
1912 const pa_cvolume *template,
1913 const pa_channel_map *from,
1914 const pa_channel_map *to) {
1919 pa_assert(template);
1922 pa_assert(pa_cvolume_compatible_with_channel_map(v, from));
1923 pa_assert(pa_cvolume_compatible_with_channel_map(template, to));
1925 /* Much like pa_cvolume_remap(), but tries to minimize impact when
1926 * mapping from sink input to sink volumes:
1928 * If template is a possible remapping from v it is used instead
1929 * of remapping anew.
1931 * If the channel maps don't match we set an all-channel volume on
1932 * the sink to ensure that changing a volume on one stream has no
1933 * effect that cannot be compensated for in another stream that
1934 * does not have the same channel map as the sink. */
1936 if (pa_channel_map_equal(from, to))
1940 if (pa_cvolume_equal(pa_cvolume_remap(&t, to, from), v)) {
1945 pa_cvolume_set(v, to->channels, pa_cvolume_max(v));
1949 /* Called from main thread. Only called for the root sink in volume sharing
1950 * cases, except for internal recursive calls. */
1951 static void get_maximum_input_volume(pa_sink *s, pa_cvolume *max_volume, const pa_channel_map *channel_map) {
1955 pa_sink_assert_ref(s);
1956 pa_assert(max_volume);
1957 pa_assert(channel_map);
1958 pa_assert(pa_sink_flat_volume_enabled(s));
1960 PA_IDXSET_FOREACH(i, s->inputs, idx) {
1961 pa_cvolume remapped;
1963 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1964 if (PA_SINK_IS_LINKED(i->origin_sink->state))
1965 get_maximum_input_volume(i->origin_sink, max_volume, channel_map);
1967 /* Ignore this input. The origin sink uses volume sharing, so this
1968 * input's volume will be set to be equal to the root sink's real
1969 * volume. Obviously this input's current volume must not then
1970 * affect what the root sink's real volume will be. */
1974 remapped = i->volume;
1975 cvolume_remap_minimal_impact(&remapped, max_volume, &i->channel_map, channel_map);
1976 pa_cvolume_merge(max_volume, max_volume, &remapped);
1980 /* Called from main thread. Only called for the root sink in volume sharing
1981 * cases, except for internal recursive calls. */
1982 static bool has_inputs(pa_sink *s) {
1986 pa_sink_assert_ref(s);
1988 PA_IDXSET_FOREACH(i, s->inputs, idx) {
1989 if (!i->origin_sink || !(i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER) || has_inputs(i->origin_sink))
1996 /* Called from main thread. Only called for the root sink in volume sharing
1997 * cases, except for internal recursive calls. */
1998 static void update_real_volume(pa_sink *s, const pa_cvolume *new_volume, pa_channel_map *channel_map) {
2002 pa_sink_assert_ref(s);
2003 pa_assert(new_volume);
2004 pa_assert(channel_map);
2006 s->real_volume = *new_volume;
2007 pa_cvolume_remap(&s->real_volume, channel_map, &s->channel_map);
2009 PA_IDXSET_FOREACH(i, s->inputs, idx) {
2010 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
2011 if (pa_sink_flat_volume_enabled(s)) {
2012 pa_cvolume new_input_volume;
2014 /* Follow the root sink's real volume. */
2015 new_input_volume = *new_volume;
2016 pa_cvolume_remap(&new_input_volume, channel_map, &i->channel_map);
2017 pa_sink_input_set_volume_direct(i, &new_input_volume);
2018 compute_reference_ratio(i);
2021 if (PA_SINK_IS_LINKED(i->origin_sink->state))
2022 update_real_volume(i->origin_sink, new_volume, channel_map);
2027 /* Called from main thread. Only called for the root sink in shared volume
2029 static void compute_real_volume(pa_sink *s) {
2030 pa_sink_assert_ref(s);
2031 pa_assert_ctl_context();
2032 pa_assert(PA_SINK_IS_LINKED(s->state));
2033 pa_assert(pa_sink_flat_volume_enabled(s));
2034 pa_assert(!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
2036 /* This determines the maximum volume of all streams and sets
2037 * s->real_volume accordingly. */
2039 if (!has_inputs(s)) {
2040 /* In the special case that we have no sink inputs we leave the
2041 * volume unmodified. */
2042 update_real_volume(s, &s->reference_volume, &s->channel_map);
2046 pa_cvolume_mute(&s->real_volume, s->channel_map.channels);
2048 /* First let's determine the new maximum volume of all inputs
2049 * connected to this sink */
2050 get_maximum_input_volume(s, &s->real_volume, &s->channel_map);
2051 update_real_volume(s, &s->real_volume, &s->channel_map);
2053 /* Then, let's update the real ratios/soft volumes of all inputs
2054 * connected to this sink */
2055 compute_real_ratios(s);
2058 /* Called from main thread. Only called for the root sink in shared volume
2059 * cases, except for internal recursive calls. */
2060 static void propagate_reference_volume(pa_sink *s) {
2064 pa_sink_assert_ref(s);
2065 pa_assert_ctl_context();
2066 pa_assert(PA_SINK_IS_LINKED(s->state));
2067 pa_assert(pa_sink_flat_volume_enabled(s));
2069 /* This is called whenever the sink volume changes that is not
2070 * caused by a sink input volume change. We need to fix up the
2071 * sink input volumes accordingly */
2073 PA_IDXSET_FOREACH(i, s->inputs, idx) {
2074 pa_cvolume new_volume;
2076 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
2077 if (PA_SINK_IS_LINKED(i->origin_sink->state))
2078 propagate_reference_volume(i->origin_sink);
2080 /* Since the origin sink uses volume sharing, this input's volume
2081 * needs to be updated to match the root sink's real volume, but
2082 * that will be done later in update_real_volume(). */
2086 /* This basically calculates:
2088 * i->volume := s->reference_volume * i->reference_ratio */
2090 new_volume = s->reference_volume;
2091 pa_cvolume_remap(&new_volume, &s->channel_map, &i->channel_map);
2092 pa_sw_cvolume_multiply(&new_volume, &new_volume, &i->reference_ratio);
2093 pa_sink_input_set_volume_direct(i, &new_volume);
2097 /* Called from main thread. Only called for the root sink in volume sharing
2098 * cases, except for internal recursive calls. The return value indicates
2099 * whether any reference volume actually changed. */
2100 static bool update_reference_volume(pa_sink *s, const pa_cvolume *v, const pa_channel_map *channel_map, bool save) {
2102 bool reference_volume_changed;
2106 pa_sink_assert_ref(s);
2107 pa_assert(PA_SINK_IS_LINKED(s->state));
2109 pa_assert(channel_map);
2110 pa_assert(pa_cvolume_valid(v));
2113 pa_cvolume_remap(&volume, channel_map, &s->channel_map);
2115 reference_volume_changed = !pa_cvolume_equal(&volume, &s->reference_volume);
2116 pa_sink_set_reference_volume_direct(s, &volume);
2118 s->save_volume = (!reference_volume_changed && s->save_volume) || save;
2120 if (!reference_volume_changed && !(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
2121 /* If the root sink's volume doesn't change, then there can't be any
2122 * changes in the other sinks in the sink tree either.
2124 * It's probably theoretically possible that even if the root sink's
2125 * volume changes slightly, some filter sink doesn't change its volume
2126 * due to rounding errors. If that happens, we still want to propagate
2127 * the changed root sink volume to the sinks connected to the
2128 * intermediate sink that didn't change its volume. This theoretical
2129 * possibility is the reason why we have that !(s->flags &
2130 * PA_SINK_SHARE_VOLUME_WITH_MASTER) condition. Probably nobody would
2131 * notice even if we returned here false always if
2132 * reference_volume_changed is false. */
2135 PA_IDXSET_FOREACH(i, s->inputs, idx) {
2136 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
2137 && PA_SINK_IS_LINKED(i->origin_sink->state))
2138 update_reference_volume(i->origin_sink, v, channel_map, false);
2144 /* Called from main thread */
2145 void pa_sink_set_volume(
2147 const pa_cvolume *volume,
2151 pa_cvolume new_reference_volume;
2154 pa_sink_assert_ref(s);
2155 pa_assert_ctl_context();
2156 pa_assert(PA_SINK_IS_LINKED(s->state));
2157 pa_assert(!volume || pa_cvolume_valid(volume));
2158 pa_assert(volume || pa_sink_flat_volume_enabled(s));
2159 pa_assert(!volume || volume->channels == 1 || pa_cvolume_compatible(volume, &s->sample_spec));
2161 /* make sure we don't change the volume when a PASSTHROUGH input is connected ...
2162 * ... *except* if we're being invoked to reset the volume to ensure 0 dB gain */
2163 if (pa_sink_is_passthrough(s) && (!volume || !pa_cvolume_is_norm(volume))) {
2164 pa_log_warn("Cannot change volume, Sink is connected to PASSTHROUGH input");
2168 /* In case of volume sharing, the volume is set for the root sink first,
2169 * from which it's then propagated to the sharing sinks. */
2170 root_sink = pa_sink_get_master(s);
2172 if (PA_UNLIKELY(!root_sink))
2175 /* As a special exception we accept mono volumes on all sinks --
2176 * even on those with more complex channel maps */
2179 if (pa_cvolume_compatible(volume, &s->sample_spec))
2180 new_reference_volume = *volume;
2182 new_reference_volume = s->reference_volume;
2183 pa_cvolume_scale(&new_reference_volume, pa_cvolume_max(volume));
2186 pa_cvolume_remap(&new_reference_volume, &s->channel_map, &root_sink->channel_map);
2188 if (update_reference_volume(root_sink, &new_reference_volume, &root_sink->channel_map, save)) {
2189 if (pa_sink_flat_volume_enabled(root_sink)) {
2190 /* OK, propagate this volume change back to the inputs */
2191 propagate_reference_volume(root_sink);
2193 /* And now recalculate the real volume */
2194 compute_real_volume(root_sink);
2196 update_real_volume(root_sink, &root_sink->reference_volume, &root_sink->channel_map);
2200 /* If volume is NULL we synchronize the sink's real and
2201 * reference volumes with the stream volumes. */
2203 pa_assert(pa_sink_flat_volume_enabled(root_sink));
2205 /* Ok, let's determine the new real volume */
2206 compute_real_volume(root_sink);
2208 /* Let's 'push' the reference volume if necessary */
2209 pa_cvolume_merge(&new_reference_volume, &s->reference_volume, &root_sink->real_volume);
2210 /* If the sink and its root don't have the same number of channels, we need to remap */
2211 if (s != root_sink && !pa_channel_map_equal(&s->channel_map, &root_sink->channel_map))
2212 pa_cvolume_remap(&new_reference_volume, &s->channel_map, &root_sink->channel_map);
2213 update_reference_volume(root_sink, &new_reference_volume, &root_sink->channel_map, save);
2215 /* Now that the reference volume is updated, we can update the streams'
2216 * reference ratios. */
2217 compute_reference_ratios(root_sink);
2220 if (root_sink->set_volume) {
2221 /* If we have a function set_volume(), then we do not apply a
2222 * soft volume by default. However, set_volume() is free to
2223 * apply one to root_sink->soft_volume */
2225 pa_cvolume_reset(&root_sink->soft_volume, root_sink->sample_spec.channels);
2226 if (!(root_sink->flags & PA_SINK_DEFERRED_VOLUME))
2227 root_sink->set_volume(root_sink);
2230 /* If we have no function set_volume(), then the soft volume
2231 * becomes the real volume */
2232 root_sink->soft_volume = root_sink->real_volume;
2234 /* This tells the sink that soft volume and/or real volume changed */
2236 pa_assert_se(pa_asyncmsgq_send(root_sink->asyncmsgq, PA_MSGOBJECT(root_sink), PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL) == 0);
2239 /* Called from the io thread if sync volume is used, otherwise from the main thread.
2240 * Only to be called by sink implementor */
2241 void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) {
2243 pa_sink_assert_ref(s);
2244 pa_assert(!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
2246 if (s->flags & PA_SINK_DEFERRED_VOLUME)
2247 pa_sink_assert_io_context(s);
2249 pa_assert_ctl_context();
2252 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
2254 s->soft_volume = *volume;
2256 if (PA_SINK_IS_LINKED(s->state) && !(s->flags & PA_SINK_DEFERRED_VOLUME))
2257 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
2259 s->thread_info.soft_volume = s->soft_volume;
2262 /* Called from the main thread. Only called for the root sink in volume sharing
2263 * cases, except for internal recursive calls. */
2264 static void propagate_real_volume(pa_sink *s, const pa_cvolume *old_real_volume) {
2268 pa_sink_assert_ref(s);
2269 pa_assert(old_real_volume);
2270 pa_assert_ctl_context();
2271 pa_assert(PA_SINK_IS_LINKED(s->state));
2273 /* This is called when the hardware's real volume changes due to
2274 * some external event. We copy the real volume into our
2275 * reference volume and then rebuild the stream volumes based on
2276 * i->real_ratio which should stay fixed. */
2278 if (!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
2279 if (pa_cvolume_equal(old_real_volume, &s->real_volume))
2282 /* 1. Make the real volume the reference volume */
2283 update_reference_volume(s, &s->real_volume, &s->channel_map, true);
2286 if (pa_sink_flat_volume_enabled(s)) {
2288 PA_IDXSET_FOREACH(i, s->inputs, idx) {
2289 pa_cvolume new_volume;
2291 /* 2. Since the sink's reference and real volumes are equal
2292 * now our ratios should be too. */
2293 pa_sink_input_set_reference_ratio(i, &i->real_ratio);
2295 /* 3. Recalculate the new stream reference volume based on the
2296 * reference ratio and the sink's reference volume.
2298 * This basically calculates:
2300 * i->volume = s->reference_volume * i->reference_ratio
2302 * This is identical to propagate_reference_volume() */
2303 new_volume = s->reference_volume;
2304 pa_cvolume_remap(&new_volume, &s->channel_map, &i->channel_map);
2305 pa_sw_cvolume_multiply(&new_volume, &new_volume, &i->reference_ratio);
2306 pa_sink_input_set_volume_direct(i, &new_volume);
2308 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
2309 && PA_SINK_IS_LINKED(i->origin_sink->state))
2310 propagate_real_volume(i->origin_sink, old_real_volume);
2314 /* Something got changed in the hardware. It probably makes sense
2315 * to save changed hw settings given that hw volume changes not
2316 * triggered by PA are almost certainly done by the user. */
2317 if (!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
2318 s->save_volume = true;
2321 /* Called from io thread */
2322 void pa_sink_update_volume_and_mute(pa_sink *s) {
2324 pa_sink_assert_io_context(s);
2326 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE, NULL, 0, NULL, NULL);
2329 /* Called from main thread */
2330 const pa_cvolume *pa_sink_get_volume(pa_sink *s, bool force_refresh) {
2331 pa_sink_assert_ref(s);
2332 pa_assert_ctl_context();
2333 pa_assert(PA_SINK_IS_LINKED(s->state));
2335 if (s->refresh_volume || force_refresh) {
2336 struct pa_cvolume old_real_volume;
2338 pa_assert(!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
2340 old_real_volume = s->real_volume;
2342 if (!(s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_volume)
2345 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
2347 update_real_volume(s, &s->real_volume, &s->channel_map);
2348 propagate_real_volume(s, &old_real_volume);
2351 return &s->reference_volume;
2354 /* Called from main thread. In volume sharing cases, only the root sink may
2356 void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_real_volume) {
2357 pa_cvolume old_real_volume;
2359 pa_sink_assert_ref(s);
2360 pa_assert_ctl_context();
2361 pa_assert(PA_SINK_IS_LINKED(s->state));
2362 pa_assert(!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
2364 /* The sink implementor may call this if the volume changed to make sure everyone is notified */
2366 old_real_volume = s->real_volume;
2367 update_real_volume(s, new_real_volume, &s->channel_map);
2368 propagate_real_volume(s, &old_real_volume);
2371 /* Called from main thread */
2372 void pa_sink_set_mute(pa_sink *s, bool mute, bool save) {
2375 pa_sink_assert_ref(s);
2376 pa_assert_ctl_context();
2378 old_muted = s->muted;
2380 if (mute == old_muted) {
2381 s->save_muted |= save;
2386 s->save_muted = save;
2388 if (!(s->flags & PA_SINK_DEFERRED_VOLUME) && s->set_mute) {
2389 s->set_mute_in_progress = true;
2391 s->set_mute_in_progress = false;
2394 if (!PA_SINK_IS_LINKED(s->state))
2397 pa_log_debug("The mute of sink %s changed from %s to %s.", s->name, pa_yes_no(old_muted), pa_yes_no(mute));
2398 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
2399 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
2400 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_MUTE_CHANGED], s);
2403 /* Called from main thread */
2404 bool pa_sink_get_mute(pa_sink *s, bool force_refresh) {
2406 pa_sink_assert_ref(s);
2407 pa_assert_ctl_context();
2408 pa_assert(PA_SINK_IS_LINKED(s->state));
2410 if ((s->refresh_muted || force_refresh) && s->get_mute) {
2413 if (s->flags & PA_SINK_DEFERRED_VOLUME) {
2414 if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &mute, 0, NULL) >= 0)
2415 pa_sink_mute_changed(s, mute);
2417 if (s->get_mute(s, &mute) >= 0)
2418 pa_sink_mute_changed(s, mute);
2425 /* Called from main thread */
2426 void pa_sink_mute_changed(pa_sink *s, bool new_muted) {
2427 pa_sink_assert_ref(s);
2428 pa_assert_ctl_context();
2429 pa_assert(PA_SINK_IS_LINKED(s->state));
2431 if (s->set_mute_in_progress)
2434 /* pa_sink_set_mute() does this same check, so this may appear redundant,
2435 * but we must have this here also, because the save parameter of
2436 * pa_sink_set_mute() would otherwise have unintended side effects (saving
2437 * the mute state when it shouldn't be saved). */
2438 if (new_muted == s->muted)
2441 pa_sink_set_mute(s, new_muted, true);
2444 /* Called from main thread */
2445 bool pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p) {
2446 pa_sink_assert_ref(s);
2447 pa_assert_ctl_context();
2450 pa_proplist_update(s->proplist, mode, p);
2452 if (PA_SINK_IS_LINKED(s->state)) {
2453 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
2454 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
2460 /* Called from main thread */
2461 /* FIXME -- this should be dropped and be merged into pa_sink_update_proplist() */
2462 void pa_sink_set_description(pa_sink *s, const char *description) {
2464 pa_sink_assert_ref(s);
2465 pa_assert_ctl_context();
2467 if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
2470 old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
2472 if (old && description && pa_streq(old, description))
2476 pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
2478 pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
2480 if (s->monitor_source) {
2483 n = pa_sprintf_malloc("Monitor Source of %s", description ? description : s->name);
2484 pa_source_set_description(s->monitor_source, n);
2488 if (PA_SINK_IS_LINKED(s->state)) {
2489 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
2490 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
2494 /* Called from main thread */
2495 unsigned pa_sink_linked_by(pa_sink *s) {
2498 pa_sink_assert_ref(s);
2499 pa_assert_ctl_context();
2500 pa_assert(PA_SINK_IS_LINKED(s->state));
2502 ret = pa_idxset_size(s->inputs);
2504 /* We add in the number of streams connected to us here. Please
2505 * note the asymmetry to pa_sink_used_by()! */
2507 if (s->monitor_source)
2508 ret += pa_source_linked_by(s->monitor_source);
2513 /* Called from main thread */
2514 unsigned pa_sink_used_by(pa_sink *s) {
2517 pa_sink_assert_ref(s);
2518 pa_assert_ctl_context();
2519 pa_assert(PA_SINK_IS_LINKED(s->state));
2521 ret = pa_idxset_size(s->inputs);
2522 pa_assert(ret >= s->n_corked);
2524 /* Streams connected to our monitor source do not matter for
2525 * pa_sink_used_by()!.*/
2527 return ret - s->n_corked;
2530 /* Called from main thread */
2531 unsigned pa_sink_check_suspend(pa_sink *s, pa_sink_input *ignore_input, pa_source_output *ignore_output) {
2536 pa_sink_assert_ref(s);
2537 pa_assert_ctl_context();
2539 if (!PA_SINK_IS_LINKED(s->state))
2544 PA_IDXSET_FOREACH(i, s->inputs, idx) {
2545 pa_sink_input_state_t st;
2547 if (i == ignore_input)
2550 st = pa_sink_input_get_state(i);
2552 /* We do not assert here. It is perfectly valid for a sink input to
2553 * be in the INIT state (i.e. created, marked done but not yet put)
2554 * and we should not care if it's unlinked as it won't contribute
2555 * towards our busy status.
2557 if (!PA_SINK_INPUT_IS_LINKED(st))
2560 if (st == PA_SINK_INPUT_CORKED)
2563 if (i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND)
2569 if (s->monitor_source)
2570 ret += pa_source_check_suspend(s->monitor_source, ignore_output);
2575 const char *pa_sink_state_to_string(pa_sink_state_t state) {
2577 case PA_SINK_INIT: return "INIT";
2578 case PA_SINK_IDLE: return "IDLE";
2579 case PA_SINK_RUNNING: return "RUNNING";
2580 case PA_SINK_SUSPENDED: return "SUSPENDED";
2581 case PA_SINK_UNLINKED: return "UNLINKED";
2582 case PA_SINK_INVALID_STATE: return "INVALID_STATE";
2585 pa_assert_not_reached();
2588 /* Called from the IO thread */
2589 static void sync_input_volumes_within_thread(pa_sink *s) {
2593 pa_sink_assert_ref(s);
2594 pa_sink_assert_io_context(s);
2596 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
2597 if (pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume))
2600 i->thread_info.soft_volume = i->soft_volume;
2601 pa_sink_input_request_rewind(i, 0, true, false, false);
2605 /* Called from the IO thread. Only called for the root sink in volume sharing
2606 * cases, except for internal recursive calls. */
2607 static void set_shared_volume_within_thread(pa_sink *s) {
2608 pa_sink_input *i = NULL;
2611 pa_sink_assert_ref(s);
2613 PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME_SYNCED, NULL, 0, NULL);
2615 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
2616 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
2617 set_shared_volume_within_thread(i->origin_sink);
2621 /* Called from IO thread, except when it is not */
2622 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
2623 pa_sink *s = PA_SINK(o);
2624 pa_sink_assert_ref(s);
2626 switch ((pa_sink_message_t) code) {
2628 case PA_SINK_MESSAGE_ADD_INPUT: {
2629 pa_sink_input *i = PA_SINK_INPUT(userdata);
2631 /* If you change anything here, make sure to change the
2632 * sink input handling a few lines down at
2633 * PA_SINK_MESSAGE_FINISH_MOVE, too. */
2635 pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
2637 /* Since the caller sleeps in pa_sink_input_put(), we can
2638 * safely access data outside of thread_info even though
2641 if ((i->thread_info.sync_prev = i->sync_prev)) {
2642 pa_assert(i->sink == i->thread_info.sync_prev->sink);
2643 pa_assert(i->sync_prev->sync_next == i);
2644 i->thread_info.sync_prev->thread_info.sync_next = i;
2647 if ((i->thread_info.sync_next = i->sync_next)) {
2648 pa_assert(i->sink == i->thread_info.sync_next->sink);
2649 pa_assert(i->sync_next->sync_prev == i);
2650 i->thread_info.sync_next->thread_info.sync_prev = i;
2653 pa_sink_input_attach(i);
2655 pa_sink_input_set_state_within_thread(i, i->state);
2657 /* The requested latency of the sink input needs to be fixed up and
2658 * then configured on the sink. If this causes the sink latency to
2659 * go down, the sink implementor is responsible for doing a rewind
2660 * in the update_requested_latency() callback to ensure that the
2661 * sink buffer doesn't contain more data than what the new latency
2664 * XXX: Does it really make sense to push this responsibility to
2665 * the sink implementors? Wouldn't it be better to do it once in
2666 * the core than many times in the modules? */
2668 if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
2669 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
2671 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
2672 pa_sink_input_update_max_request(i, s->thread_info.max_request);
2674 /* We don't rewind here automatically. This is left to the
2675 * sink input implementor because some sink inputs need a
2676 * slow start, i.e. need some time to buffer client
2677 * samples before beginning streaming.
2679 * XXX: Does it really make sense to push this functionality to
2680 * the sink implementors? Wouldn't it be better to do it once in
2681 * the core than many times in the modules? */
2683 /* In flat volume mode we need to update the volume as
2685 return o->process_msg(o, PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL);
2688 case PA_SINK_MESSAGE_REMOVE_INPUT: {
2689 pa_sink_input *i = PA_SINK_INPUT(userdata);
2691 /* If you change anything here, make sure to change the
2692 * sink input handling a few lines down at
2693 * PA_SINK_MESSAGE_START_MOVE, too. */
2695 pa_sink_input_detach(i);
2697 pa_sink_input_set_state_within_thread(i, i->state);
2699 /* Since the caller sleeps in pa_sink_input_unlink(),
2700 * we can safely access data outside of thread_info even
2701 * though it is mutable */
2703 pa_assert(!i->sync_prev);
2704 pa_assert(!i->sync_next);
2706 if (i->thread_info.sync_prev) {
2707 i->thread_info.sync_prev->thread_info.sync_next = i->thread_info.sync_prev->sync_next;
2708 i->thread_info.sync_prev = NULL;
2711 if (i->thread_info.sync_next) {
2712 i->thread_info.sync_next->thread_info.sync_prev = i->thread_info.sync_next->sync_prev;
2713 i->thread_info.sync_next = NULL;
2716 pa_hashmap_remove_and_free(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
2717 pa_sink_invalidate_requested_latency(s, true);
2718 pa_sink_request_rewind(s, (size_t) -1);
2720 /* In flat volume mode we need to update the volume as
2722 return o->process_msg(o, PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL);
2725 case PA_SINK_MESSAGE_START_MOVE: {
2726 pa_sink_input *i = PA_SINK_INPUT(userdata);
2728 /* We don't support moving synchronized streams. */
2729 pa_assert(!i->sync_prev);
2730 pa_assert(!i->sync_next);
2731 pa_assert(!i->thread_info.sync_next);
2732 pa_assert(!i->thread_info.sync_prev);
2734 if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
2736 size_t sink_nbytes, total_nbytes;
2738 /* The old sink probably has some audio from this
2739 * stream in its buffer. We want to "take it back" as
2740 * much as possible and play it to the new sink. We
2741 * don't know at this point how much the old sink can
2742 * rewind. We have to pick something, and that
2743 * something is the full latency of the old sink here.
2744 * So we rewind the stream buffer by the sink latency
2745 * amount, which may be more than what we should
2746 * rewind. This can result in a chunk of audio being
2747 * played both to the old sink and the new sink.
2749 * FIXME: Fix this code so that we don't have to make
2750 * guesses about how much the sink will actually be
2751 * able to rewind. If someone comes up with a solution
2752 * for this, something to note is that the part of the
2753 * latency that the old sink couldn't rewind should
2754 * ideally be compensated after the stream has moved
2755 * to the new sink by adding silence. The new sink
2756 * most likely can't start playing the moved stream
2757 * immediately, and that gap should be removed from
2758 * the "compensation silence" (at least at the time of
2759 * writing this, the move finish code will actually
2760 * already take care of dropping the new sink's
2761 * unrewindable latency, so taking into account the
2762 * unrewindable latency of the old sink is the only
2765 * The render_memblockq contents are discarded,
2766 * because when the sink changes, the format of the
2767 * audio stored in the render_memblockq may change
2768 * too, making the stored audio invalid. FIXME:
2769 * However, the read and write indices are moved back
2770 * the same amount, so if they are not the same now,
2771 * they won't be the same after the rewind either. If
2772 * the write index of the render_memblockq is ahead of
2773 * the read index, then the render_memblockq will feed
2774 * the new sink some silence first, which it shouldn't
2775 * do. The write index should be flushed to be the
2776 * same as the read index. */
2778 /* Get the latency of the sink */
2779 usec = pa_sink_get_latency_within_thread(s, false);
2780 sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
2781 total_nbytes = sink_nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq);
2783 if (total_nbytes > 0) {
2784 i->thread_info.rewrite_nbytes = i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, total_nbytes) : total_nbytes;
2785 i->thread_info.rewrite_flush = true;
2786 pa_sink_input_process_rewind(i, sink_nbytes);
2790 pa_sink_input_detach(i);
2792 /* Let's remove the sink input ...*/
2793 pa_hashmap_remove_and_free(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
2795 pa_sink_invalidate_requested_latency(s, true);
2797 pa_log_debug("Requesting rewind due to started move");
2798 pa_sink_request_rewind(s, (size_t) -1);
2800 /* In flat volume mode we need to update the volume as
2802 return o->process_msg(o, PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL);
2805 case PA_SINK_MESSAGE_FINISH_MOVE: {
2806 pa_sink_input *i = PA_SINK_INPUT(userdata);
2808 /* We don't support moving synchronized streams. */
2809 pa_assert(!i->sync_prev);
2810 pa_assert(!i->sync_next);
2811 pa_assert(!i->thread_info.sync_next);
2812 pa_assert(!i->thread_info.sync_prev);
2814 pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
2816 pa_sink_input_attach(i);
2818 if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
2822 /* In the ideal case the new sink would start playing
2823 * the stream immediately. That requires the sink to
2824 * be able to rewind all of its latency, which usually
2825 * isn't possible, so there will probably be some gap
2826 * before the moved stream becomes audible. We then
2827 * have two possibilities: 1) start playing the stream
2828 * from where it is now, or 2) drop the unrewindable
2829 * latency of the sink from the stream. With option 1
2830 * we won't lose any audio but the stream will have a
2831 * pause. With option 2 we may lose some audio but the
2832 * stream time will be somewhat in sync with the wall
2833 * clock. Lennart seems to have chosen option 2 (one
2834 * of the reasons might have been that option 1 is
2835 * actually much harder to implement), so we drop the
2836 * latency of the new sink from the moved stream and
2837 * hope that the sink will undo most of that in the
2840 /* Get the latency of the sink */
2841 usec = pa_sink_get_latency_within_thread(s, false);
2842 nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
2845 pa_sink_input_drop(i, nbytes);
2847 pa_log_debug("Requesting rewind due to finished move");
2848 pa_sink_request_rewind(s, nbytes);
2851 /* Updating the requested sink latency has to be done
2852 * after the sink rewind request, not before, because
2853 * otherwise the sink may limit the rewind amount
2856 if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
2857 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
2859 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
2860 pa_sink_input_update_max_request(i, s->thread_info.max_request);
2862 return o->process_msg(o, PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL);
2865 case PA_SINK_MESSAGE_SET_SHARED_VOLUME: {
2866 pa_sink *root_sink = pa_sink_get_master(s);
2868 if (PA_LIKELY(root_sink))
2869 set_shared_volume_within_thread(root_sink);
2874 case PA_SINK_MESSAGE_SET_VOLUME_SYNCED:
2876 if (s->flags & PA_SINK_DEFERRED_VOLUME) {
2878 pa_sink_volume_change_push(s);
2880 /* Fall through ... */
2882 case PA_SINK_MESSAGE_SET_VOLUME:
2884 if (!pa_cvolume_equal(&s->thread_info.soft_volume, &s->soft_volume)) {
2885 s->thread_info.soft_volume = s->soft_volume;
2886 pa_sink_request_rewind(s, (size_t) -1);
2889 /* Fall through ... */
2891 case PA_SINK_MESSAGE_SYNC_VOLUMES:
2892 sync_input_volumes_within_thread(s);
2895 case PA_SINK_MESSAGE_GET_VOLUME:
2897 if ((s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_volume) {
2899 pa_sink_volume_change_flush(s);
2900 pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
2903 /* In case sink implementor reset SW volume. */
2904 if (!pa_cvolume_equal(&s->thread_info.soft_volume, &s->soft_volume)) {
2905 s->thread_info.soft_volume = s->soft_volume;
2906 pa_sink_request_rewind(s, (size_t) -1);
2911 case PA_SINK_MESSAGE_SET_MUTE:
2913 if (s->thread_info.soft_muted != s->muted) {
2914 s->thread_info.soft_muted = s->muted;
2915 pa_sink_request_rewind(s, (size_t) -1);
2918 if (s->flags & PA_SINK_DEFERRED_VOLUME && s->set_mute)
2923 case PA_SINK_MESSAGE_GET_MUTE:
2925 if (s->flags & PA_SINK_DEFERRED_VOLUME && s->get_mute)
2926 return s->get_mute(s, userdata);
2930 case PA_SINK_MESSAGE_SET_STATE: {
2932 bool suspend_change =
2933 (s->thread_info.state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(PA_PTR_TO_UINT(userdata))) ||
2934 (PA_SINK_IS_OPENED(s->thread_info.state) && PA_PTR_TO_UINT(userdata) == PA_SINK_SUSPENDED);
2936 s->thread_info.state = PA_PTR_TO_UINT(userdata);
2938 if (s->thread_info.state == PA_SINK_SUSPENDED) {
2939 s->thread_info.rewind_nbytes = 0;
2940 s->thread_info.rewind_requested = false;
2943 if (suspend_change) {
2947 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
2948 if (i->suspend_within_thread)
2949 i->suspend_within_thread(i, s->thread_info.state == PA_SINK_SUSPENDED);
2955 case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: {
2957 pa_usec_t *usec = userdata;
2958 *usec = pa_sink_get_requested_latency_within_thread(s);
2960 /* Yes, that's right, the IO thread will see -1 when no
2961 * explicit requested latency is configured, the main
2962 * thread will see max_latency */
2963 if (*usec == (pa_usec_t) -1)
2964 *usec = s->thread_info.max_latency;
2969 case PA_SINK_MESSAGE_SET_LATENCY_RANGE: {
2970 pa_usec_t *r = userdata;
2972 pa_sink_set_latency_range_within_thread(s, r[0], r[1]);
2977 case PA_SINK_MESSAGE_GET_LATENCY_RANGE: {
2978 pa_usec_t *r = userdata;
2980 r[0] = s->thread_info.min_latency;
2981 r[1] = s->thread_info.max_latency;
2986 case PA_SINK_MESSAGE_GET_FIXED_LATENCY:
2988 *((pa_usec_t*) userdata) = s->thread_info.fixed_latency;
2991 case PA_SINK_MESSAGE_SET_FIXED_LATENCY:
2993 pa_sink_set_fixed_latency_within_thread(s, (pa_usec_t) offset);
2996 case PA_SINK_MESSAGE_GET_MAX_REWIND:
2998 *((size_t*) userdata) = s->thread_info.max_rewind;
3001 case PA_SINK_MESSAGE_GET_MAX_REQUEST:
3003 *((size_t*) userdata) = s->thread_info.max_request;
3006 case PA_SINK_MESSAGE_SET_MAX_REWIND:
3008 pa_sink_set_max_rewind_within_thread(s, (size_t) offset);
3011 case PA_SINK_MESSAGE_SET_MAX_REQUEST:
3013 pa_sink_set_max_request_within_thread(s, (size_t) offset);
3016 case PA_SINK_MESSAGE_SET_PORT:
3018 pa_assert(userdata);
3020 struct sink_message_set_port *msg_data = userdata;
3021 msg_data->ret = s->set_port(s, msg_data->port);
3025 case PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE:
3026 /* This message is sent from IO-thread and handled in main thread. */
3027 pa_assert_ctl_context();
3029 /* Make sure we're not messing with main thread when no longer linked */
3030 if (!PA_SINK_IS_LINKED(s->state))
3033 pa_sink_get_volume(s, true);
3034 pa_sink_get_mute(s, true);
3037 case PA_SINK_MESSAGE_SET_PORT_LATENCY_OFFSET:
3038 s->thread_info.port_latency_offset = offset;
3041 case PA_SINK_MESSAGE_GET_LATENCY:
3042 case PA_SINK_MESSAGE_MAX:
3049 /* Called from main thread */
3050 int pa_sink_suspend_all(pa_core *c, bool suspend, pa_suspend_cause_t cause) {
3055 pa_core_assert_ref(c);
3056 pa_assert_ctl_context();
3057 pa_assert(cause != 0);
3059 PA_IDXSET_FOREACH(sink, c->sinks, idx) {
3062 if ((r = pa_sink_suspend(sink, suspend, cause)) < 0)
3069 /* Called from IO thread */
3070 void pa_sink_detach_within_thread(pa_sink *s) {
3074 pa_sink_assert_ref(s);
3075 pa_sink_assert_io_context(s);
3076 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
3078 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3079 pa_sink_input_detach(i);
3081 if (s->monitor_source)
3082 pa_source_detach_within_thread(s->monitor_source);
3085 /* Called from IO thread */
3086 void pa_sink_attach_within_thread(pa_sink *s) {
3090 pa_sink_assert_ref(s);
3091 pa_sink_assert_io_context(s);
3092 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
3094 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3095 pa_sink_input_attach(i);
3097 if (s->monitor_source)
3098 pa_source_attach_within_thread(s->monitor_source);
3101 /* Called from IO thread */
3102 void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
3103 pa_sink_assert_ref(s);
3104 pa_sink_assert_io_context(s);
3105 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
3107 if (nbytes == (size_t) -1)
3108 nbytes = s->thread_info.max_rewind;
3110 nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
3112 if (s->thread_info.rewind_requested &&
3113 nbytes <= s->thread_info.rewind_nbytes)
3116 s->thread_info.rewind_nbytes = nbytes;
3117 s->thread_info.rewind_requested = true;
3119 if (s->request_rewind)
3120 s->request_rewind(s);
3123 /* Called from IO thread */
3124 pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
3125 pa_usec_t result = (pa_usec_t) -1;
3128 pa_usec_t monitor_latency;
3130 pa_sink_assert_ref(s);
3131 pa_sink_assert_io_context(s);
3133 if (!(s->flags & PA_SINK_DYNAMIC_LATENCY))
3134 return PA_CLAMP(s->thread_info.fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
3136 if (s->thread_info.requested_latency_valid)
3137 return s->thread_info.requested_latency;
3139 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3140 if (i->thread_info.requested_sink_latency != (pa_usec_t) -1 &&
3141 (result == (pa_usec_t) -1 || result > i->thread_info.requested_sink_latency))
3142 result = i->thread_info.requested_sink_latency;
3144 monitor_latency = pa_source_get_requested_latency_within_thread(s->monitor_source);
3146 if (monitor_latency != (pa_usec_t) -1 &&
3147 (result == (pa_usec_t) -1 || result > monitor_latency))
3148 result = monitor_latency;
3150 if (result != (pa_usec_t) -1)
3151 result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
3153 if (PA_SINK_IS_LINKED(s->thread_info.state)) {
3154 /* Only cache if properly initialized */
3155 s->thread_info.requested_latency = result;
3156 s->thread_info.requested_latency_valid = true;
3162 /* Called from main thread */
3163 pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
3166 pa_sink_assert_ref(s);
3167 pa_assert_ctl_context();
3168 pa_assert(PA_SINK_IS_LINKED(s->state));
3170 if (s->state == PA_SINK_SUSPENDED)
3173 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
3178 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
3179 void pa_sink_set_max_rewind_within_thread(pa_sink *s, size_t max_rewind) {
3183 pa_sink_assert_ref(s);
3184 pa_sink_assert_io_context(s);
3186 if (max_rewind == s->thread_info.max_rewind)
3189 s->thread_info.max_rewind = max_rewind;
3191 if (PA_SINK_IS_LINKED(s->thread_info.state))
3192 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3193 pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
3195 if (s->monitor_source)
3196 pa_source_set_max_rewind_within_thread(s->monitor_source, s->thread_info.max_rewind);
3199 /* Called from main thread */
3200 void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
3201 pa_sink_assert_ref(s);
3202 pa_assert_ctl_context();
3204 if (PA_SINK_IS_LINKED(s->state))
3205 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
3207 pa_sink_set_max_rewind_within_thread(s, max_rewind);
3210 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
3211 void pa_sink_set_max_request_within_thread(pa_sink *s, size_t max_request) {
3214 pa_sink_assert_ref(s);
3215 pa_sink_assert_io_context(s);
3217 if (max_request == s->thread_info.max_request)
3220 s->thread_info.max_request = max_request;
3222 if (PA_SINK_IS_LINKED(s->thread_info.state)) {
3225 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3226 pa_sink_input_update_max_request(i, s->thread_info.max_request);
3230 /* Called from main thread */
3231 void pa_sink_set_max_request(pa_sink *s, size_t max_request) {
3232 pa_sink_assert_ref(s);
3233 pa_assert_ctl_context();
3235 if (PA_SINK_IS_LINKED(s->state))
3236 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MAX_REQUEST, NULL, max_request, NULL) == 0);
3238 pa_sink_set_max_request_within_thread(s, max_request);
3241 /* Called from IO thread */
3242 void pa_sink_invalidate_requested_latency(pa_sink *s, bool dynamic) {
3246 pa_sink_assert_ref(s);
3247 pa_sink_assert_io_context(s);
3249 if ((s->flags & PA_SINK_DYNAMIC_LATENCY))
3250 s->thread_info.requested_latency_valid = false;
3254 if (PA_SINK_IS_LINKED(s->thread_info.state)) {
3256 if (s->update_requested_latency)
3257 s->update_requested_latency(s);
3259 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3260 if (i->update_sink_requested_latency)
3261 i->update_sink_requested_latency(i);
3265 /* Called from main thread */
3266 void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
3267 pa_sink_assert_ref(s);
3268 pa_assert_ctl_context();
3270 /* min_latency == 0: no limit
3271 * min_latency anything else: specified limit
3273 * Similar for max_latency */
3275 if (min_latency < ABSOLUTE_MIN_LATENCY)
3276 min_latency = ABSOLUTE_MIN_LATENCY;
3278 if (max_latency <= 0 ||
3279 max_latency > ABSOLUTE_MAX_LATENCY)
3280 max_latency = ABSOLUTE_MAX_LATENCY;
3282 pa_assert(min_latency <= max_latency);
3284 /* Hmm, let's see if someone forgot to set PA_SINK_DYNAMIC_LATENCY here... */
3285 pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
3286 max_latency == ABSOLUTE_MAX_LATENCY) ||
3287 (s->flags & PA_SINK_DYNAMIC_LATENCY));
3289 if (PA_SINK_IS_LINKED(s->state)) {
3295 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
3297 pa_sink_set_latency_range_within_thread(s, min_latency, max_latency);
3300 /* Called from main thread */
3301 void pa_sink_get_latency_range(pa_sink *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
3302 pa_sink_assert_ref(s);
3303 pa_assert_ctl_context();
3304 pa_assert(min_latency);
3305 pa_assert(max_latency);
3307 if (PA_SINK_IS_LINKED(s->state)) {
3308 pa_usec_t r[2] = { 0, 0 };
3310 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
3312 *min_latency = r[0];
3313 *max_latency = r[1];
3315 *min_latency = s->thread_info.min_latency;
3316 *max_latency = s->thread_info.max_latency;
3320 /* Called from IO thread */
3321 void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
3322 pa_sink_assert_ref(s);
3323 pa_sink_assert_io_context(s);
3325 pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
3326 pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
3327 pa_assert(min_latency <= max_latency);
3329 /* Hmm, let's see if someone forgot to set PA_SINK_DYNAMIC_LATENCY here... */
3330 pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
3331 max_latency == ABSOLUTE_MAX_LATENCY) ||
3332 (s->flags & PA_SINK_DYNAMIC_LATENCY));
3334 if (s->thread_info.min_latency == min_latency &&
3335 s->thread_info.max_latency == max_latency)
3338 s->thread_info.min_latency = min_latency;
3339 s->thread_info.max_latency = max_latency;
3341 if (PA_SINK_IS_LINKED(s->thread_info.state)) {
3345 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3346 if (i->update_sink_latency_range)
3347 i->update_sink_latency_range(i);
3350 pa_sink_invalidate_requested_latency(s, false);
3352 pa_source_set_latency_range_within_thread(s->monitor_source, min_latency, max_latency);
3355 /* Called from main thread */
3356 void pa_sink_set_fixed_latency(pa_sink *s, pa_usec_t latency) {
3357 pa_sink_assert_ref(s);
3358 pa_assert_ctl_context();
3360 if (s->flags & PA_SINK_DYNAMIC_LATENCY) {
3361 pa_assert(latency == 0);
3365 if (latency < ABSOLUTE_MIN_LATENCY)
3366 latency = ABSOLUTE_MIN_LATENCY;
3368 if (latency > ABSOLUTE_MAX_LATENCY)
3369 latency = ABSOLUTE_MAX_LATENCY;
3371 if (PA_SINK_IS_LINKED(s->state))
3372 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_FIXED_LATENCY, NULL, (int64_t) latency, NULL) == 0);
3374 s->thread_info.fixed_latency = latency;
3376 pa_source_set_fixed_latency(s->monitor_source, latency);
3379 /* Called from main thread */
3380 pa_usec_t pa_sink_get_fixed_latency(pa_sink *s) {
3383 pa_sink_assert_ref(s);
3384 pa_assert_ctl_context();
3386 if (s->flags & PA_SINK_DYNAMIC_LATENCY)
3389 if (PA_SINK_IS_LINKED(s->state))
3390 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_FIXED_LATENCY, &latency, 0, NULL) == 0);
3392 latency = s->thread_info.fixed_latency;
3397 /* Called from IO thread */
3398 void pa_sink_set_fixed_latency_within_thread(pa_sink *s, pa_usec_t latency) {
3399 pa_sink_assert_ref(s);
3400 pa_sink_assert_io_context(s);
3402 if (s->flags & PA_SINK_DYNAMIC_LATENCY) {
3403 pa_assert(latency == 0);
3404 s->thread_info.fixed_latency = 0;
3406 if (s->monitor_source)
3407 pa_source_set_fixed_latency_within_thread(s->monitor_source, 0);
3412 pa_assert(latency >= ABSOLUTE_MIN_LATENCY);
3413 pa_assert(latency <= ABSOLUTE_MAX_LATENCY);
3415 if (s->thread_info.fixed_latency == latency)
3418 s->thread_info.fixed_latency = latency;
3420 if (PA_SINK_IS_LINKED(s->thread_info.state)) {
3424 PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3425 if (i->update_sink_fixed_latency)
3426 i->update_sink_fixed_latency(i);
3429 pa_sink_invalidate_requested_latency(s, false);
3431 pa_source_set_fixed_latency_within_thread(s->monitor_source, latency);
3434 /* Called from main context */
3435 void pa_sink_set_port_latency_offset(pa_sink *s, int64_t offset) {
3436 pa_sink_assert_ref(s);
3438 s->port_latency_offset = offset;
3440 if (PA_SINK_IS_LINKED(s->state))
3441 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT_LATENCY_OFFSET, NULL, offset, NULL) == 0);
3443 s->thread_info.port_latency_offset = offset;
3445 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PORT_LATENCY_OFFSET_CHANGED], s);
3448 /* Called from main context */
3449 size_t pa_sink_get_max_rewind(pa_sink *s) {
3451 pa_assert_ctl_context();
3452 pa_sink_assert_ref(s);
3454 if (!PA_SINK_IS_LINKED(s->state))
3455 return s->thread_info.max_rewind;
3457 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
3462 /* Called from main context */
3463 size_t pa_sink_get_max_request(pa_sink *s) {
3465 pa_sink_assert_ref(s);
3466 pa_assert_ctl_context();
3468 if (!PA_SINK_IS_LINKED(s->state))
3469 return s->thread_info.max_request;
3471 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REQUEST, &r, 0, NULL) == 0);
3476 /* Called from main context */
3477 int pa_sink_set_port(pa_sink *s, const char *name, bool save) {
3478 pa_device_port *port;
3481 pa_sink_assert_ref(s);
3482 pa_assert_ctl_context();
3485 pa_log_debug("set_port() operation not implemented for sink %u \"%s\"", s->index, s->name);
3486 return -PA_ERR_NOTIMPLEMENTED;
3490 return -PA_ERR_NOENTITY;
3492 if (!(port = pa_hashmap_get(s->ports, name)))
3493 return -PA_ERR_NOENTITY;
3495 if (s->active_port == port) {
3496 s->save_port = s->save_port || save;
3500 if (s->flags & PA_SINK_DEFERRED_VOLUME) {
3501 struct sink_message_set_port msg = { .port = port, .ret = 0 };
3502 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT, &msg, 0, NULL) == 0);
3506 ret = s->set_port(s, port);
3509 return -PA_ERR_NOENTITY;
3511 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
3513 pa_log_info("Changed port of sink %u \"%s\" to %s", s->index, s->name, port->name);
3515 s->active_port = port;
3516 s->save_port = save;
3518 pa_sink_set_port_latency_offset(s, s->active_port->latency_offset);
3520 /* The active port affects the default sink selection. */
3521 pa_core_update_default_sink(s->core);
3523 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], s);
3528 bool pa_device_init_icon(pa_proplist *p, bool is_sink) {
3529 const char *ff, *c, *t = NULL, *s = "", *profile, *bus;
3533 if (pa_proplist_contains(p, PA_PROP_DEVICE_ICON_NAME))
3536 if ((ff = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) {
3538 if (pa_streq(ff, "microphone"))
3539 t = "audio-input-microphone";
3540 else if (pa_streq(ff, "webcam"))
3542 else if (pa_streq(ff, "computer"))
3544 else if (pa_streq(ff, "handset"))
3546 else if (pa_streq(ff, "portable"))
3547 t = "multimedia-player";
3548 else if (pa_streq(ff, "tv"))
3549 t = "video-display";
3552 * The following icons are not part of the icon naming spec,
3553 * because Rodney Dawes sucks as the maintainer of that spec.
3555 * http://lists.freedesktop.org/archives/xdg/2009-May/010397.html
3557 else if (pa_streq(ff, "headset"))
3558 t = "audio-headset";
3559 else if (pa_streq(ff, "headphone"))
3560 t = "audio-headphones";
3561 else if (pa_streq(ff, "speaker"))
3562 t = "audio-speakers";
3563 else if (pa_streq(ff, "hands-free"))
3564 t = "audio-handsfree";
3568 if ((c = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
3569 if (pa_streq(c, "modem"))
3576 t = "audio-input-microphone";
3579 if ((profile = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
3580 if (strstr(profile, "analog"))
3582 else if (strstr(profile, "iec958"))
3584 else if (strstr(profile, "hdmi"))
3588 bus = pa_proplist_gets(p, PA_PROP_DEVICE_BUS);
3590 pa_proplist_setf(p, PA_PROP_DEVICE_ICON_NAME, "%s%s%s%s", t, pa_strempty(s), bus ? "-" : "", pa_strempty(bus));
3595 bool pa_device_init_description(pa_proplist *p, pa_card *card) {
3596 const char *s, *d = NULL, *k;
3599 if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
3603 if ((s = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_DESCRIPTION)))
3607 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
3608 if (pa_streq(s, "internal"))
3609 d = _("Built-in Audio");
3612 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
3613 if (pa_streq(s, "modem"))
3617 d = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME);
3622 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
3625 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s %s", d, k);
3627 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
3632 bool pa_device_init_intended_roles(pa_proplist *p) {
3636 if (pa_proplist_contains(p, PA_PROP_DEVICE_INTENDED_ROLES))
3639 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
3640 if (pa_streq(s, "handset") || pa_streq(s, "hands-free")
3641 || pa_streq(s, "headset")) {
3642 pa_proplist_sets(p, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
3649 unsigned pa_device_init_priority(pa_proplist *p) {
3651 unsigned priority = 0;
3655 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS))) {
3657 if (pa_streq(s, "sound"))
3659 else if (!pa_streq(s, "modem"))
3663 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) {
3665 if (pa_streq(s, "headphone"))
3667 else if (pa_streq(s, "hifi"))
3669 else if (pa_streq(s, "speaker"))
3671 else if (pa_streq(s, "portable"))
3675 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_BUS))) {
3677 if (pa_streq(s, "bluetooth"))
3679 else if (pa_streq(s, "usb"))
3681 else if (pa_streq(s, "pci"))
3685 if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
3687 if (pa_startswith(s, "analog-"))
3689 else if (pa_startswith(s, "iec958-"))
3696 PA_STATIC_FLIST_DECLARE(pa_sink_volume_change, 0, pa_xfree);
3698 /* Called from the IO thread. */
3699 static pa_sink_volume_change *pa_sink_volume_change_new(pa_sink *s) {
3700 pa_sink_volume_change *c;
3701 if (!(c = pa_flist_pop(PA_STATIC_FLIST_GET(pa_sink_volume_change))))
3702 c = pa_xnew(pa_sink_volume_change, 1);
3704 PA_LLIST_INIT(pa_sink_volume_change, c);
3706 pa_cvolume_reset(&c->hw_volume, s->sample_spec.channels);
3710 /* Called from the IO thread. */
3711 static void pa_sink_volume_change_free(pa_sink_volume_change *c) {
3713 if (pa_flist_push(PA_STATIC_FLIST_GET(pa_sink_volume_change), c) < 0)
3717 /* Called from the IO thread. */
3718 void pa_sink_volume_change_push(pa_sink *s) {
3719 pa_sink_volume_change *c = NULL;
3720 pa_sink_volume_change *nc = NULL;
3721 pa_sink_volume_change *pc = NULL;
3722 uint32_t safety_margin = s->thread_info.volume_change_safety_margin;
3724 const char *direction = NULL;
3727 nc = pa_sink_volume_change_new(s);
3729 /* NOTE: There is already more different volumes in pa_sink that I can remember.
3730 * Adding one more volume for HW would get us rid of this, but I am trying
3731 * to survive with the ones we already have. */
3732 pa_sw_cvolume_divide(&nc->hw_volume, &s->real_volume, &s->soft_volume);
3734 if (!s->thread_info.volume_changes && pa_cvolume_equal(&nc->hw_volume, &s->thread_info.current_hw_volume)) {
3735 pa_log_debug("Volume not changing");
3736 pa_sink_volume_change_free(nc);
3740 nc->at = pa_sink_get_latency_within_thread(s, false);
3741 nc->at += pa_rtclock_now() + s->thread_info.volume_change_extra_delay;
3743 if (s->thread_info.volume_changes_tail) {
3744 for (c = s->thread_info.volume_changes_tail; c; c = c->prev) {
3745 /* If volume is going up let's do it a bit late. If it is going
3746 * down let's do it a bit early. */
3747 if (pa_cvolume_avg(&nc->hw_volume) > pa_cvolume_avg(&c->hw_volume)) {
3748 if (nc->at + safety_margin > c->at) {
3749 nc->at += safety_margin;
3754 else if (nc->at - safety_margin > c->at) {
3755 nc->at -= safety_margin;
3763 if (pa_cvolume_avg(&nc->hw_volume) > pa_cvolume_avg(&s->thread_info.current_hw_volume)) {
3764 nc->at += safety_margin;
3767 nc->at -= safety_margin;
3770 PA_LLIST_PREPEND(pa_sink_volume_change, s->thread_info.volume_changes, nc);
3773 PA_LLIST_INSERT_AFTER(pa_sink_volume_change, s->thread_info.volume_changes, c, nc);
3776 pa_log_debug("Volume going %s to %d at %llu", direction, pa_cvolume_avg(&nc->hw_volume), (long long unsigned) nc->at);
3778 /* We can ignore volume events that came earlier but should happen later than this. */
3779 PA_LLIST_FOREACH_SAFE(c, pc, nc->next) {
3780 pa_log_debug("Volume change to %d at %llu was dropped", pa_cvolume_avg(&c->hw_volume), (long long unsigned) c->at);
3781 pa_sink_volume_change_free(c);
3784 s->thread_info.volume_changes_tail = nc;
3787 /* Called from the IO thread. */
3788 static void pa_sink_volume_change_flush(pa_sink *s) {
3789 pa_sink_volume_change *c = s->thread_info.volume_changes;
3791 s->thread_info.volume_changes = NULL;
3792 s->thread_info.volume_changes_tail = NULL;
3794 pa_sink_volume_change *next = c->next;
3795 pa_sink_volume_change_free(c);
3800 /* Called from the IO thread. */
3801 bool pa_sink_volume_change_apply(pa_sink *s, pa_usec_t *usec_to_next) {
3807 if (!s->thread_info.volume_changes || !PA_SINK_IS_LINKED(s->state)) {
3813 pa_assert(s->write_volume);
3815 now = pa_rtclock_now();
3817 while (s->thread_info.volume_changes && now >= s->thread_info.volume_changes->at) {
3818 pa_sink_volume_change *c = s->thread_info.volume_changes;
3819 PA_LLIST_REMOVE(pa_sink_volume_change, s->thread_info.volume_changes, c);
3820 pa_log_debug("Volume change to %d at %llu was written %llu usec late",
3821 pa_cvolume_avg(&c->hw_volume), (long long unsigned) c->at, (long long unsigned) (now - c->at));
3823 s->thread_info.current_hw_volume = c->hw_volume;
3824 pa_sink_volume_change_free(c);
3830 if (s->thread_info.volume_changes) {
3832 *usec_to_next = s->thread_info.volume_changes->at - now;
3833 if (pa_log_ratelimit(PA_LOG_DEBUG))
3834 pa_log_debug("Next volume change in %lld usec", (long long) (s->thread_info.volume_changes->at - now));
3839 s->thread_info.volume_changes_tail = NULL;
3844 /* Called from the IO thread. */
3845 static void pa_sink_volume_change_rewind(pa_sink *s, size_t nbytes) {
3846 /* All the queued volume events later than current latency are shifted to happen earlier. */
3847 pa_sink_volume_change *c;
3848 pa_volume_t prev_vol = pa_cvolume_avg(&s->thread_info.current_hw_volume);
3849 pa_usec_t rewound = pa_bytes_to_usec(nbytes, &s->sample_spec);
3850 pa_usec_t limit = pa_sink_get_latency_within_thread(s, false);
3852 pa_log_debug("latency = %lld", (long long) limit);
3853 limit += pa_rtclock_now() + s->thread_info.volume_change_extra_delay;
3855 PA_LLIST_FOREACH(c, s->thread_info.volume_changes) {
3856 pa_usec_t modified_limit = limit;
3857 if (prev_vol > pa_cvolume_avg(&c->hw_volume))
3858 modified_limit -= s->thread_info.volume_change_safety_margin;
3860 modified_limit += s->thread_info.volume_change_safety_margin;
3861 if (c->at > modified_limit) {
3863 if (c->at < modified_limit)
3864 c->at = modified_limit;
3866 prev_vol = pa_cvolume_avg(&c->hw_volume);
3868 pa_sink_volume_change_apply(s, NULL);
3871 /* Called from the main thread */
3872 /* Gets the list of formats supported by the sink. The members and idxset must
3873 * be freed by the caller. */
3874 pa_idxset* pa_sink_get_formats(pa_sink *s) {
3879 if (s->get_formats) {
3880 /* Sink supports format query, all is good */
3881 ret = s->get_formats(s);
3883 /* Sink doesn't support format query, so assume it does PCM */
3884 pa_format_info *f = pa_format_info_new();
3885 f->encoding = PA_ENCODING_PCM;
3887 ret = pa_idxset_new(NULL, NULL);
3888 pa_idxset_put(ret, f, NULL);
3894 /* Called from the main thread */
3895 /* Allows an external source to set what formats a sink supports if the sink
3896 * permits this. The function makes a copy of the formats on success. */
3897 bool pa_sink_set_formats(pa_sink *s, pa_idxset *formats) {
3902 /* Sink supports setting formats -- let's give it a shot */
3903 return s->set_formats(s, formats);
3905 /* Sink doesn't support setting this -- bail out */
3909 /* Called from the main thread */
3910 /* Checks if the sink can accept this format */
3911 bool pa_sink_check_format(pa_sink *s, pa_format_info *f) {
3912 pa_idxset *formats = NULL;
3918 formats = pa_sink_get_formats(s);
3921 pa_format_info *finfo_device;
3924 PA_IDXSET_FOREACH(finfo_device, formats, i) {
3925 if (pa_format_info_is_compatible(finfo_device, f)) {
3931 pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
3937 /* Called from the main thread */
3938 /* Calculates the intersection between formats supported by the sink and
3939 * in_formats, and returns these, in the order of the sink's formats. */
3940 pa_idxset* pa_sink_check_formats(pa_sink *s, pa_idxset *in_formats) {
3941 pa_idxset *out_formats = pa_idxset_new(NULL, NULL), *sink_formats = NULL;
3942 pa_format_info *f_sink, *f_in;
3947 if (!in_formats || pa_idxset_isempty(in_formats))
3950 sink_formats = pa_sink_get_formats(s);
3952 PA_IDXSET_FOREACH(f_sink, sink_formats, i) {
3953 PA_IDXSET_FOREACH(f_in, in_formats, j) {
3954 if (pa_format_info_is_compatible(f_sink, f_in))
3955 pa_idxset_put(out_formats, pa_format_info_copy(f_in), NULL);
3961 pa_idxset_free(sink_formats, (pa_free_cb_t) pa_format_info_free);
3966 /* Called from the main thread. */
3967 void pa_sink_set_reference_volume_direct(pa_sink *s, const pa_cvolume *volume) {
3968 pa_cvolume old_volume;
3969 char old_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
3970 char new_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
3975 old_volume = s->reference_volume;
3977 if (pa_cvolume_equal(volume, &old_volume))
3980 s->reference_volume = *volume;
3981 pa_log_debug("The reference volume of sink %s changed from %s to %s.", s->name,
3982 pa_cvolume_snprint_verbose(old_volume_str, sizeof(old_volume_str), &old_volume, &s->channel_map,
3983 s->flags & PA_SINK_DECIBEL_VOLUME),
3984 pa_cvolume_snprint_verbose(new_volume_str, sizeof(new_volume_str), volume, &s->channel_map,
3985 s->flags & PA_SINK_DECIBEL_VOLUME));
3987 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
3988 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], s);