udev-detect, alsa-card: Adopt avoid resampling option from daemon.conf
[platform/upstream/pulseaudio.git] / src / pulsecore / sink.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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/>.
19 ***/
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #ifdef TIZEN_PCM_DUMP
29 #include <time.h>
30 #endif
31
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>
40
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>
52
53 #include "sink.h"
54
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)
60
61 PA_DEFINE_PUBLIC_CLASS(pa_sink, pa_msgobject);
62
63 struct pa_sink_volume_change {
64     pa_usec_t at;
65     pa_cvolume hw_volume;
66
67     PA_LLIST_FIELDS(pa_sink_volume_change);
68 };
69
70 struct sink_message_set_port {
71     pa_device_port *port;
72     int ret;
73 };
74
75 static void sink_free(pa_object *s);
76
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);
80
81 #ifdef TIZEN_PCM_DUMP
82 static void pa_sink_write_pcm_dump(pa_sink *s, pa_memchunk *chunk)
83 {
84     char *dump_time = NULL, *dump_path_surfix = NULL;
85     const char *s_device_api_str, *card_name_str, *device_idx_str;
86     struct timeval now;
87     struct tm tm;
88     char datetime[7];
89
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);
97
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));
103             } else {
104                 dump_path_surfix = pa_sprintf_malloc("%s", s_device_api_str);
105             }
106         } else {
107             dump_path_surfix = pa_sprintf_malloc("%s", s->name);
108         }
109
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);
112         if (s->dump_path) {
113             s->pcm_dump_fp = fopen(s->dump_path, "w");
114             if (!s->pcm_dump_fp)
115                 pa_log_warn("%s open failed", s->dump_path);
116             else
117                 pa_log_info("%s opened", s->dump_path);
118         }
119         pa_xfree(dump_time);
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;
127     }
128
129     /* dump pcm */
130     if (s->pcm_dump_fp) {
131         void *ptr = NULL;
132
133         ptr = pa_memblock_acquire(chunk->memblock);
134         if (ptr)
135             fwrite((uint8_t *)ptr + chunk->index, 1, chunk->length, s->pcm_dump_fp);
136         else
137             pa_log_warn("pa_memblock_acquire is failed. ptr is NULL");
138
139         pa_memblock_release(chunk->memblock);
140     }
141 }
142 #endif
143
144 pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data) {
145     pa_assert(data);
146
147     pa_zero(*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);
150
151     return data;
152 }
153
154 void pa_sink_new_data_set_name(pa_sink_new_data *data, const char *name) {
155     pa_assert(data);
156
157     pa_xfree(data->name);
158     data->name = pa_xstrdup(name);
159 }
160
161 void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_spec *spec) {
162     pa_assert(data);
163
164     if ((data->sample_spec_is_set = !!spec))
165         data->sample_spec = *spec;
166 }
167
168 void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map) {
169     pa_assert(data);
170
171     if ((data->channel_map_is_set = !!map))
172         data->channel_map = *map;
173 }
174
175 void pa_sink_new_data_set_alternate_sample_rate(pa_sink_new_data *data, const uint32_t alternate_sample_rate) {
176     pa_assert(data);
177
178     data->alternate_sample_rate_is_set = true;
179     data->alternate_sample_rate = alternate_sample_rate;
180 }
181
182 void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume) {
183     pa_assert(data);
184
185     if ((data->volume_is_set = !!volume))
186         data->volume = *volume;
187 }
188
189 void pa_sink_new_data_set_muted(pa_sink_new_data *data, bool mute) {
190     pa_assert(data);
191
192     data->muted_is_set = true;
193     data->muted = mute;
194 }
195
196 void pa_sink_new_data_set_port(pa_sink_new_data *data, const char *port) {
197     pa_assert(data);
198
199     pa_xfree(data->active_port);
200     data->active_port = pa_xstrdup(port);
201 }
202
203 void pa_sink_new_data_done(pa_sink_new_data *data) {
204     pa_assert(data);
205
206     pa_proplist_free(data->proplist);
207
208     if (data->ports)
209         pa_hashmap_free(data->ports);
210
211     pa_xfree(data->name);
212     pa_xfree(data->active_port);
213 }
214
215 /* Called from main context */
216 static void reset_callbacks(pa_sink *s) {
217     pa_assert(s);
218
219     s->set_state = NULL;
220     s->get_volume = NULL;
221     s->set_volume = NULL;
222     s->write_volume = NULL;
223     s->get_mute = NULL;
224     s->set_mute = NULL;
225     s->request_rewind = NULL;
226     s->update_requested_latency = NULL;
227     s->set_port = NULL;
228     s->get_formats = NULL;
229     s->set_formats = NULL;
230     s->reconfigure = NULL;
231 }
232
233 /* Called from main context */
234 pa_sink* pa_sink_new(
235         pa_core *core,
236         pa_sink_new_data *data,
237         pa_sink_flags_t flags) {
238
239     pa_sink *s;
240     const char *name;
241     char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
242     pa_source_new_data source_data;
243     const char *dn;
244     char *pt;
245
246     pa_assert(core);
247     pa_assert(data);
248     pa_assert(data->name);
249     pa_assert_ctl_context();
250
251     s = pa_msgobject_new(pa_sink);
252
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);
255         pa_xfree(s);
256         return NULL;
257     }
258
259     pa_sink_new_data_set_name(data, name);
260
261     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW], data) < 0) {
262         pa_xfree(s);
263         pa_namereg_unregister(core, name);
264         return NULL;
265     }
266
267     /* FIXME, need to free s here on failure */
268
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]);
271
272     pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
273
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));
276
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);
279
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));
283
284     if (!data->volume_is_set) {
285         pa_cvolume_reset(&data->volume, data->sample_spec.channels);
286         data->save_volume = false;
287     }
288
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));
291
292     if (!data->muted_is_set)
293         data->muted = false;
294
295     if (data->card)
296         pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
297
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);
301
302     if (!data->active_port) {
303         pa_device_port *p = pa_device_port_find_best(data->ports);
304         if (p)
305             pa_sink_new_data_set_port(data, p->name);
306     }
307
308     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {
309         pa_xfree(s);
310         pa_namereg_unregister(core, name);
311         return NULL;
312     }
313
314     s->parent.parent.free = sink_free;
315     s->parent.process_msg = pa_sink_process_msg;
316
317     s->core = core;
318     s->state = PA_SINK_INIT;
319     s->flags = flags;
320     s->priority = 0;
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;
328
329     s->priority = pa_device_init_priority(s->proplist);
330
331     s->sample_spec = data->sample_spec;
332     s->channel_map = data->channel_map;
333     s->default_sample_rate = s->sample_spec.rate;
334
335     if (data->alternate_sample_rate_is_set)
336         s->alternate_sample_rate = data->alternate_sample_rate;
337     else
338         s->alternate_sample_rate = s->core->alternate_sample_rate;
339 #ifdef __TIZEN__
340     s->avoid_resampling = data->avoid_resampling;
341 #endif
342
343     s->inputs = pa_idxset_new(NULL, NULL);
344     s->n_corked = 0;
345     s->input_to_master = NULL;
346
347     s->reference_volume = s->real_volume = data->volume;
348     pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
349     s->base_volume = PA_VOLUME_NORM;
350     s->n_volume_steps = PA_VOLUME_NORM+1;
351     s->muted = data->muted;
352     s->refresh_volume = s->refresh_muted = false;
353
354     reset_callbacks(s);
355     s->userdata = NULL;
356
357     s->asyncmsgq = NULL;
358
359     /* As a minor optimization we just steal the list instead of
360      * copying it here */
361     s->ports = data->ports;
362     data->ports = NULL;
363
364     s->active_port = NULL;
365     s->save_port = false;
366
367     if (data->active_port)
368         if ((s->active_port = pa_hashmap_get(s->ports, data->active_port)))
369             s->save_port = data->save_port;
370
371     /* Hopefully the active port has already been assigned in the previous call
372        to pa_device_port_find_best, but better safe than sorry */
373     if (!s->active_port)
374         s->active_port = pa_device_port_find_best(s->ports);
375
376     if (s->active_port)
377         s->port_latency_offset = s->active_port->latency_offset;
378     else
379         s->port_latency_offset = 0;
380
381     s->save_volume = data->save_volume;
382     s->save_muted = data->save_muted;
383 #ifdef TIZEN_PCM_DUMP
384     s->pcm_dump_fp = NULL;
385     s->dump_path = NULL;
386 #endif
387
388     pa_silence_memchunk_get(
389             &core->silence_cache,
390             core->mempool,
391             &s->silence,
392             &s->sample_spec,
393             0);
394
395     s->thread_info.rtpoll = NULL;
396     s->thread_info.inputs = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL,
397                                                 (pa_free_cb_t) pa_sink_input_unref);
398     s->thread_info.soft_volume =  s->soft_volume;
399     s->thread_info.soft_muted = s->muted;
400     s->thread_info.state = s->state;
401     s->thread_info.rewind_nbytes = 0;
402     s->thread_info.rewind_requested = false;
403     s->thread_info.max_rewind = 0;
404     s->thread_info.max_request = 0;
405     s->thread_info.requested_latency_valid = false;
406     s->thread_info.requested_latency = 0;
407     s->thread_info.min_latency = ABSOLUTE_MIN_LATENCY;
408     s->thread_info.max_latency = ABSOLUTE_MAX_LATENCY;
409     s->thread_info.fixed_latency = flags & PA_SINK_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
410
411     PA_LLIST_HEAD_INIT(pa_sink_volume_change, s->thread_info.volume_changes);
412     s->thread_info.volume_changes_tail = NULL;
413     pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
414     s->thread_info.volume_change_safety_margin = core->deferred_volume_safety_margin_usec;
415     s->thread_info.volume_change_extra_delay = core->deferred_volume_extra_delay_usec;
416     s->thread_info.port_latency_offset = s->port_latency_offset;
417
418     /* FIXME: This should probably be moved to pa_sink_put() */
419     pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
420
421     if (s->card)
422         pa_assert_se(pa_idxset_put(s->card->sinks, s, NULL) >= 0);
423
424     pt = pa_proplist_to_string_sep(s->proplist, "\n    ");
425     pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s\n    %s",
426                 s->index,
427                 s->name,
428                 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
429                 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
430                 pt);
431     pa_xfree(pt);
432
433     pa_source_new_data_init(&source_data);
434     pa_source_new_data_set_sample_spec(&source_data, &s->sample_spec);
435     pa_source_new_data_set_channel_map(&source_data, &s->channel_map);
436     pa_source_new_data_set_alternate_sample_rate(&source_data, s->alternate_sample_rate);
437     source_data.name = pa_sprintf_malloc("%s.monitor", name);
438     source_data.driver = data->driver;
439     source_data.module = data->module;
440     source_data.card = data->card;
441
442     dn = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
443     pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
444     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
445
446     s->monitor_source = pa_source_new(core, &source_data,
447                                       ((flags & PA_SINK_LATENCY) ? PA_SOURCE_LATENCY : 0) |
448                                       ((flags & PA_SINK_DYNAMIC_LATENCY) ? PA_SOURCE_DYNAMIC_LATENCY : 0));
449
450     pa_source_new_data_done(&source_data);
451
452     if (!s->monitor_source) {
453         pa_sink_unlink(s);
454         pa_sink_unref(s);
455         return NULL;
456     }
457
458     s->monitor_source->monitor_of = s;
459
460     pa_source_set_latency_range(s->monitor_source, s->thread_info.min_latency, s->thread_info.max_latency);
461     pa_source_set_fixed_latency(s->monitor_source, s->thread_info.fixed_latency);
462     pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
463
464     return s;
465 }
466
467 /* Called from main context */
468 static int sink_set_state(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) {
469     int ret = 0;
470     bool state_changed;
471     bool suspend_cause_changed;
472     bool suspending;
473     bool resuming;
474
475     pa_assert(s);
476     pa_assert_ctl_context();
477
478     state_changed = state != s->state;
479     suspend_cause_changed = suspend_cause != s->suspend_cause;
480
481     if (!state_changed && !suspend_cause_changed)
482         return 0;
483
484     suspending = PA_SINK_IS_OPENED(s->state) && state == PA_SINK_SUSPENDED;
485     resuming = s->state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state);
486
487     /* If we are resuming, suspend_cause must be 0. */
488     pa_assert(!resuming || !suspend_cause);
489
490     /* Here's something to think about: what to do with the suspend cause if
491      * resuming the sink fails? The old suspend cause will be incorrect, so we
492      * can't use that. On the other hand, if we set no suspend cause (as is the
493      * case currently), then it looks strange to have a sink suspended without
494      * any cause. It might be a good idea to add a new "resume failed" suspend
495      * cause, or it might just add unnecessary complexity, given that the
496      * current approach of not setting any suspend cause works well enough. */
497
498     if (s->set_state && state_changed) {
499         ret = s->set_state(s, state);
500         /* set_state() is allowed to fail only when resuming. */
501         pa_assert(ret >= 0 || resuming);
502     }
503
504     if (ret >= 0 && s->asyncmsgq && state_changed)
505         if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
506             /* SET_STATE is allowed to fail only when resuming. */
507             pa_assert(resuming);
508
509             if (s->set_state)
510                 s->set_state(s, PA_SINK_SUSPENDED);
511         }
512
513 #ifdef TIZEN_PCM_DUMP
514     /* close file for dump pcm */
515     if (s->pcm_dump_fp && (s->core->pcm_dump_option & PA_PCM_DUMP_OPTION_SEPARATED) && suspending) {
516         fclose(s->pcm_dump_fp);
517         pa_log_info("%s closed", s->dump_path);
518         pa_xfree(s->dump_path);
519         s->pcm_dump_fp = NULL;
520     }
521 #endif
522     if (suspend_cause_changed) {
523         char old_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
524         char new_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
525
526         pa_log_debug("%s: suspend_cause: %s -> %s", s->name, pa_suspend_cause_to_string(s->suspend_cause, old_cause_buf),
527                      pa_suspend_cause_to_string(suspend_cause, new_cause_buf));
528         s->suspend_cause = suspend_cause;
529     }
530
531     if (ret < 0)
532         goto finish;
533
534     if (state_changed) {
535         pa_log_debug("%s: state: %s -> %s", s->name, pa_sink_state_to_string(s->state), pa_sink_state_to_string(state));
536         s->state = state;
537
538         /* If we enter UNLINKED state, then we don't send change notifications.
539          * pa_sink_unlink() will send unlink notifications instead. */
540         if (state != PA_SINK_UNLINKED) {
541             pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
542             pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
543         }
544     }
545
546     if (suspending || resuming) {
547         pa_sink_input *i;
548         uint32_t idx;
549
550         /* We're suspending or resuming, tell everyone about it */
551
552         PA_IDXSET_FOREACH(i, s->inputs, idx)
553             if (s->state == PA_SINK_SUSPENDED &&
554                 (i->flags & PA_SINK_INPUT_KILL_ON_SUSPEND))
555                 pa_sink_input_kill(i);
556             else if (i->suspend)
557                 i->suspend(i, state == PA_SINK_SUSPENDED);
558     }
559
560 finish:
561     if ((suspending || resuming || suspend_cause_changed) && s->monitor_source && state != PA_SINK_UNLINKED)
562         pa_source_sync_suspend(s->monitor_source);
563
564     return ret;
565 }
566
567 void pa_sink_set_get_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
568     pa_assert(s);
569
570     s->get_volume = cb;
571 }
572
573 void pa_sink_set_set_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
574     pa_sink_flags_t flags;
575
576     pa_assert(s);
577     pa_assert(!s->write_volume || cb);
578
579     s->set_volume = cb;
580
581     /* Save the current flags so we can tell if they've changed */
582     flags = s->flags;
583
584     if (cb) {
585         /* The sink implementor is responsible for setting decibel volume support */
586         s->flags |= PA_SINK_HW_VOLUME_CTRL;
587     } else {
588         s->flags &= ~PA_SINK_HW_VOLUME_CTRL;
589         /* See note below in pa_sink_put() about volume sharing and decibel volumes */
590         pa_sink_enable_decibel_volume(s, !(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
591     }
592
593     /* If the flags have changed after init, let any clients know via a change event */
594     if (s->state != PA_SINK_INIT && flags != s->flags)
595         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
596 }
597
598 void pa_sink_set_write_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
599     pa_sink_flags_t flags;
600
601     pa_assert(s);
602     pa_assert(!cb || s->set_volume);
603
604     s->write_volume = cb;
605
606     /* Save the current flags so we can tell if they've changed */
607     flags = s->flags;
608
609     if (cb)
610         s->flags |= PA_SINK_DEFERRED_VOLUME;
611     else
612         s->flags &= ~PA_SINK_DEFERRED_VOLUME;
613
614     /* If the flags have changed after init, let any clients know via a change event */
615     if (s->state != PA_SINK_INIT && flags != s->flags)
616         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
617 }
618
619 void pa_sink_set_get_mute_callback(pa_sink *s, pa_sink_get_mute_cb_t cb) {
620     pa_assert(s);
621
622     s->get_mute = cb;
623 }
624
625 void pa_sink_set_set_mute_callback(pa_sink *s, pa_sink_cb_t cb) {
626     pa_sink_flags_t flags;
627
628     pa_assert(s);
629
630     s->set_mute = cb;
631
632     /* Save the current flags so we can tell if they've changed */
633     flags = s->flags;
634
635     if (cb)
636         s->flags |= PA_SINK_HW_MUTE_CTRL;
637     else
638         s->flags &= ~PA_SINK_HW_MUTE_CTRL;
639
640     /* If the flags have changed after init, let any clients know via a change event */
641     if (s->state != PA_SINK_INIT && flags != s->flags)
642         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
643 }
644
645 static void enable_flat_volume(pa_sink *s, bool enable) {
646     pa_sink_flags_t flags;
647
648     pa_assert(s);
649
650     /* Always follow the overall user preference here */
651     enable = enable && s->core->flat_volumes;
652
653     /* Save the current flags so we can tell if they've changed */
654     flags = s->flags;
655
656     if (enable)
657         s->flags |= PA_SINK_FLAT_VOLUME;
658     else
659         s->flags &= ~PA_SINK_FLAT_VOLUME;
660
661     /* If the flags have changed after init, let any clients know via a change event */
662     if (s->state != PA_SINK_INIT && flags != s->flags)
663         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
664 }
665
666 void pa_sink_enable_decibel_volume(pa_sink *s, bool enable) {
667     pa_sink_flags_t flags;
668
669     pa_assert(s);
670
671     /* Save the current flags so we can tell if they've changed */
672     flags = s->flags;
673
674     if (enable) {
675         s->flags |= PA_SINK_DECIBEL_VOLUME;
676         enable_flat_volume(s, true);
677     } else {
678         s->flags &= ~PA_SINK_DECIBEL_VOLUME;
679         enable_flat_volume(s, false);
680     }
681
682     /* If the flags have changed after init, let any clients know via a change event */
683     if (s->state != PA_SINK_INIT && flags != s->flags)
684         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
685 }
686
687 /* Called from main context */
688 void pa_sink_put(pa_sink* s) {
689     pa_sink_assert_ref(s);
690     pa_assert_ctl_context();
691
692     pa_assert(s->state == PA_SINK_INIT);
693     pa_assert(!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER) || pa_sink_is_filter(s));
694
695     /* The following fields must be initialized properly when calling _put() */
696     pa_assert(s->asyncmsgq);
697     pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
698
699     /* Generally, flags should be initialized via pa_sink_new(). As a
700      * special exception we allow some volume related flags to be set
701      * between _new() and _put() by the callback setter functions above.
702      *
703      * Thus we implement a couple safeguards here which ensure the above
704      * setters were used (or at least the implementor made manual changes
705      * in a compatible way).
706      *
707      * Note: All of these flags set here can change over the life time
708      * of the sink. */
709     pa_assert(!(s->flags & PA_SINK_HW_VOLUME_CTRL) || s->set_volume);
710     pa_assert(!(s->flags & PA_SINK_DEFERRED_VOLUME) || s->write_volume);
711     pa_assert(!(s->flags & PA_SINK_HW_MUTE_CTRL) || s->set_mute);
712
713     /* XXX: Currently decibel volume is disabled for all sinks that use volume
714      * sharing. When the master sink supports decibel volume, it would be good
715      * to have the flag also in the filter sink, but currently we don't do that
716      * so that the flags of the filter sink never change when it's moved from
717      * a master sink to another. One solution for this problem would be to
718      * remove user-visible volume altogether from filter sinks when volume
719      * sharing is used, but the current approach was easier to implement... */
720     /* We always support decibel volumes in software, otherwise we leave it to
721      * the sink implementor to set this flag as needed.
722      *
723      * Note: This flag can also change over the life time of the sink. */
724     if (!(s->flags & PA_SINK_HW_VOLUME_CTRL) && !(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
725         pa_sink_enable_decibel_volume(s, true);
726         s->soft_volume = s->reference_volume;
727     }
728
729     /* If the sink implementor support DB volumes by itself, we should always
730      * try and enable flat volumes too */
731     if ((s->flags & PA_SINK_DECIBEL_VOLUME))
732         enable_flat_volume(s, true);
733
734     if (s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER) {
735         pa_sink *root_sink = pa_sink_get_master(s);
736
737         pa_assert(root_sink);
738
739         s->reference_volume = root_sink->reference_volume;
740         pa_cvolume_remap(&s->reference_volume, &root_sink->channel_map, &s->channel_map);
741
742         s->real_volume = root_sink->real_volume;
743         pa_cvolume_remap(&s->real_volume, &root_sink->channel_map, &s->channel_map);
744     } else
745         /* We assume that if the sink implementor changed the default
746          * volume he did so in real_volume, because that is the usual
747          * place where he is supposed to place his changes.  */
748         s->reference_volume = s->real_volume;
749
750     s->thread_info.soft_volume = s->soft_volume;
751     s->thread_info.soft_muted = s->muted;
752     pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
753
754     pa_assert((s->flags & PA_SINK_HW_VOLUME_CTRL)
755               || (s->base_volume == PA_VOLUME_NORM
756                   && ((s->flags & PA_SINK_DECIBEL_VOLUME || (s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)))));
757     pa_assert(!(s->flags & PA_SINK_DECIBEL_VOLUME) || s->n_volume_steps == PA_VOLUME_NORM+1);
758     pa_assert(!(s->flags & PA_SINK_DYNAMIC_LATENCY) == !(s->thread_info.fixed_latency == 0));
759     pa_assert(!(s->flags & PA_SINK_LATENCY) == !(s->monitor_source->flags & PA_SOURCE_LATENCY));
760     pa_assert(!(s->flags & PA_SINK_DYNAMIC_LATENCY) == !(s->monitor_source->flags & PA_SOURCE_DYNAMIC_LATENCY));
761
762     pa_assert(s->monitor_source->thread_info.fixed_latency == s->thread_info.fixed_latency);
763     pa_assert(s->monitor_source->thread_info.min_latency == s->thread_info.min_latency);
764     pa_assert(s->monitor_source->thread_info.max_latency == s->thread_info.max_latency);
765
766     if (s->suspend_cause)
767         pa_assert_se(sink_set_state(s, PA_SINK_SUSPENDED, s->suspend_cause) == 0);
768     else
769         pa_assert_se(sink_set_state(s, PA_SINK_IDLE, 0) == 0);
770
771     pa_source_put(s->monitor_source);
772
773     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
774     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s);
775
776     /* This function must be called after the PA_CORE_HOOK_SINK_PUT hook,
777      * because module-switch-on-connect needs to know the old default sink */
778     pa_core_update_default_sink(s->core);
779 }
780
781 /* Called from main context */
782 void pa_sink_unlink(pa_sink* s) {
783     bool linked;
784     pa_sink_input *i, PA_UNUSED *j = NULL;
785
786     pa_sink_assert_ref(s);
787     pa_assert_ctl_context();
788
789     /* Please note that pa_sink_unlink() does more than simply
790      * reversing pa_sink_put(). It also undoes the registrations
791      * already done in pa_sink_new()! */
792
793     if (s->unlink_requested)
794         return;
795
796     s->unlink_requested = true;
797
798     linked = PA_SINK_IS_LINKED(s->state);
799
800     if (linked)
801         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
802
803     if (s->state != PA_SINK_UNLINKED)
804         pa_namereg_unregister(s->core, s->name);
805     pa_idxset_remove_by_data(s->core->sinks, s, NULL);
806
807     pa_core_update_default_sink(s->core);
808
809     if (s->card)
810         pa_idxset_remove_by_data(s->card->sinks, s, NULL);
811
812     while ((i = pa_idxset_first(s->inputs, NULL))) {
813         pa_assert(i != j);
814         pa_sink_input_kill(i);
815         j = i;
816     }
817
818     if (linked)
819         sink_set_state(s, PA_SINK_UNLINKED, 0);
820     else
821         s->state = PA_SINK_UNLINKED;
822
823     reset_callbacks(s);
824
825     if (s->monitor_source)
826         pa_source_unlink(s->monitor_source);
827
828     if (linked) {
829         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
830         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
831     }
832 }
833
834 /* Called from main context */
835 static void sink_free(pa_object *o) {
836     pa_sink *s = PA_SINK(o);
837
838     pa_assert(s);
839     pa_assert_ctl_context();
840     pa_assert(pa_sink_refcnt(s) == 0);
841     pa_assert(!PA_SINK_IS_LINKED(s->state));
842
843     pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
844
845     pa_sink_volume_change_flush(s);
846
847     if (s->monitor_source) {
848         pa_source_unref(s->monitor_source);
849         s->monitor_source = NULL;
850     }
851
852     pa_idxset_free(s->inputs, NULL);
853     pa_hashmap_free(s->thread_info.inputs);
854
855     if (s->silence.memblock)
856         pa_memblock_unref(s->silence.memblock);
857
858     pa_xfree(s->name);
859     pa_xfree(s->driver);
860
861     if (s->proplist)
862         pa_proplist_free(s->proplist);
863
864     if (s->ports)
865         pa_hashmap_free(s->ports);
866
867 #ifdef TIZEN_PCM_DUMP
868     /* close file for dump pcm */
869     if (s->pcm_dump_fp) {
870         fclose(s->pcm_dump_fp);
871         pa_log_info("%s closed", s->dump_path);
872         pa_xfree(s->dump_path);
873         s->pcm_dump_fp = NULL;
874     }
875 #endif
876     pa_xfree(s);
877 }
878
879 /* Called from main context, and not while the IO thread is active, please */
880 void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
881     pa_sink_assert_ref(s);
882     pa_assert_ctl_context();
883
884     s->asyncmsgq = q;
885
886     if (s->monitor_source)
887         pa_source_set_asyncmsgq(s->monitor_source, q);
888 }
889
890 /* Called from main context, and not while the IO thread is active, please */
891 void pa_sink_update_flags(pa_sink *s, pa_sink_flags_t mask, pa_sink_flags_t value) {
892     pa_sink_flags_t old_flags;
893     pa_sink_input *input;
894     uint32_t idx;
895
896     pa_sink_assert_ref(s);
897     pa_assert_ctl_context();
898
899     /* For now, allow only a minimal set of flags to be changed. */
900     pa_assert((mask & ~(PA_SINK_DYNAMIC_LATENCY|PA_SINK_LATENCY)) == 0);
901
902     old_flags = s->flags;
903     s->flags = (s->flags & ~mask) | (value & mask);
904
905     if (s->flags == old_flags)
906         return;
907
908     if ((s->flags & PA_SINK_LATENCY) != (old_flags & PA_SINK_LATENCY))
909         pa_log_debug("Sink %s: LATENCY flag %s.", s->name, (s->flags & PA_SINK_LATENCY) ? "enabled" : "disabled");
910
911     if ((s->flags & PA_SINK_DYNAMIC_LATENCY) != (old_flags & PA_SINK_DYNAMIC_LATENCY))
912         pa_log_debug("Sink %s: DYNAMIC_LATENCY flag %s.",
913                      s->name, (s->flags & PA_SINK_DYNAMIC_LATENCY) ? "enabled" : "disabled");
914
915     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
916     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_FLAGS_CHANGED], s);
917
918     if (s->monitor_source)
919         pa_source_update_flags(s->monitor_source,
920                                ((mask & PA_SINK_LATENCY) ? PA_SOURCE_LATENCY : 0) |
921                                ((mask & PA_SINK_DYNAMIC_LATENCY) ? PA_SOURCE_DYNAMIC_LATENCY : 0),
922                                ((value & PA_SINK_LATENCY) ? PA_SOURCE_LATENCY : 0) |
923                                ((value & PA_SINK_DYNAMIC_LATENCY) ? PA_SOURCE_DYNAMIC_LATENCY : 0));
924
925     PA_IDXSET_FOREACH(input, s->inputs, idx) {
926         if (input->origin_sink)
927             pa_sink_update_flags(input->origin_sink, mask, value);
928     }
929 }
930
931 /* Called from IO context, or before _put() from main context */
932 void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
933     pa_sink_assert_ref(s);
934     pa_sink_assert_io_context(s);
935
936     s->thread_info.rtpoll = p;
937
938     if (s->monitor_source)
939         pa_source_set_rtpoll(s->monitor_source, p);
940 }
941
942 /* Called from main context */
943 int pa_sink_update_status(pa_sink*s) {
944     pa_sink_assert_ref(s);
945     pa_assert_ctl_context();
946     pa_assert(PA_SINK_IS_LINKED(s->state));
947
948     if (s->state == PA_SINK_SUSPENDED)
949         return 0;
950
951     return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE, 0);
952 }
953
954 /* Called from any context - must be threadsafe */
955 void pa_sink_set_mixer_dirty(pa_sink *s, bool is_dirty) {
956     pa_atomic_store(&s->mixer_dirty, is_dirty ? 1 : 0);
957 }
958
959 /* Called from main context */
960 int pa_sink_suspend(pa_sink *s, bool suspend, pa_suspend_cause_t cause) {
961     pa_suspend_cause_t merged_cause;
962
963     pa_sink_assert_ref(s);
964     pa_assert_ctl_context();
965     pa_assert(PA_SINK_IS_LINKED(s->state));
966     pa_assert(cause != 0);
967
968     if (suspend)
969         merged_cause = s->suspend_cause | cause;
970     else
971         merged_cause = s->suspend_cause & ~cause;
972
973     if (!(merged_cause & PA_SUSPEND_SESSION) && (pa_atomic_load(&s->mixer_dirty) != 0)) {
974         /* This might look racy but isn't: If somebody sets mixer_dirty exactly here,
975            it'll be handled just fine. */
976         pa_sink_set_mixer_dirty(s, false);
977         pa_log_debug("Mixer is now accessible. Updating alsa mixer settings.");
978         if (s->active_port && s->set_port) {
979             if (s->flags & PA_SINK_DEFERRED_VOLUME) {
980                 struct sink_message_set_port msg = { .port = s->active_port, .ret = 0 };
981                 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT, &msg, 0, NULL) == 0);
982             }
983             else
984                 s->set_port(s, s->active_port);
985         }
986         else {
987             if (s->set_mute)
988                 s->set_mute(s);
989             if (s->set_volume)
990                 s->set_volume(s);
991         }
992     }
993
994     if (merged_cause)
995         return sink_set_state(s, PA_SINK_SUSPENDED, merged_cause);
996     else
997         return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE, 0);
998 }
999
1000 /* Called from main context */
1001 pa_queue *pa_sink_move_all_start(pa_sink *s, pa_queue *q) {
1002     pa_sink_input *i, *n;
1003     uint32_t idx;
1004
1005     pa_sink_assert_ref(s);
1006     pa_assert_ctl_context();
1007     pa_assert(PA_SINK_IS_LINKED(s->state));
1008
1009     if (!q)
1010         q = pa_queue_new();
1011
1012     for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = n) {
1013         n = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx));
1014
1015         pa_sink_input_ref(i);
1016
1017         if (pa_sink_input_start_move(i) >= 0)
1018             pa_queue_push(q, i);
1019         else
1020             pa_sink_input_unref(i);
1021     }
1022
1023     return q;
1024 }
1025
1026 /* Called from main context */
1027 void pa_sink_move_all_finish(pa_sink *s, pa_queue *q, bool save) {
1028     pa_sink_input *i;
1029
1030     pa_sink_assert_ref(s);
1031     pa_assert_ctl_context();
1032     pa_assert(PA_SINK_IS_LINKED(s->state));
1033     pa_assert(q);
1034
1035     while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
1036         if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1037             if (pa_sink_input_finish_move(i, s, save) < 0)
1038                 pa_sink_input_fail_move(i);
1039
1040         }
1041         pa_sink_input_unref(i);
1042     }
1043
1044     pa_queue_free(q, NULL);
1045 }
1046
1047 /* Called from main context */
1048 void pa_sink_move_all_fail(pa_queue *q) {
1049     pa_sink_input *i;
1050
1051     pa_assert_ctl_context();
1052     pa_assert(q);
1053
1054     while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
1055         pa_sink_input_fail_move(i);
1056         pa_sink_input_unref(i);
1057     }
1058
1059     pa_queue_free(q, NULL);
1060 }
1061
1062  /* Called from IO thread context */
1063 size_t pa_sink_process_input_underruns(pa_sink *s, size_t left_to_play) {
1064     pa_sink_input *i;
1065     void *state = NULL;
1066     size_t result = 0;
1067
1068     pa_sink_assert_ref(s);
1069     pa_sink_assert_io_context(s);
1070
1071     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
1072         size_t uf = i->thread_info.underrun_for_sink;
1073
1074         /* Propagate down the filter tree */
1075         if (i->origin_sink) {
1076             size_t filter_result, left_to_play_origin;
1077
1078             /* The recursive call works in the origin sink domain ... */
1079             left_to_play_origin = pa_convert_size(left_to_play, &i->sink->sample_spec, &i->origin_sink->sample_spec);
1080
1081             /* .. and returns the time to sleep before waking up. We need the
1082              * underrun duration for comparisons, so we undo the subtraction on
1083              * the return value... */
1084             filter_result = left_to_play_origin - pa_sink_process_input_underruns(i->origin_sink, left_to_play_origin);
1085
1086             /* ... and convert it back to the master sink domain */
1087             filter_result = pa_convert_size(filter_result, &i->origin_sink->sample_spec, &i->sink->sample_spec);
1088
1089             /* Remember the longest underrun so far */
1090             if (filter_result > result)
1091                 result = filter_result;
1092         }
1093
1094         if (uf == 0) {
1095             /* No underrun here, move on */
1096             continue;
1097         } else if (uf >= left_to_play) {
1098             /* The sink has possibly consumed all the data the sink input provided */
1099             pa_sink_input_process_underrun(i);
1100         } else if (uf > result) {
1101             /* Remember the longest underrun so far */
1102             result = uf;
1103         }
1104     }
1105
1106     if (result > 0)
1107         pa_log_debug("%s: Found underrun %ld bytes ago (%ld bytes ahead in playback buffer)", s->name,
1108                 (long) result, (long) left_to_play - result);
1109     return left_to_play - result;
1110 }
1111
1112 /* Called from IO thread context */
1113 void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
1114     pa_sink_input *i;
1115     void *state = NULL;
1116
1117     pa_sink_assert_ref(s);
1118     pa_sink_assert_io_context(s);
1119     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1120
1121     /* If nobody requested this and this is actually no real rewind
1122      * then we can short cut this. Please note that this means that
1123      * not all rewind requests triggered upstream will always be
1124      * translated in actual requests! */
1125     if (!s->thread_info.rewind_requested && nbytes <= 0)
1126         return;
1127
1128     s->thread_info.rewind_nbytes = 0;
1129     s->thread_info.rewind_requested = false;
1130
1131     if (nbytes > 0) {
1132         pa_log_debug("Processing rewind...");
1133         if (s->flags & PA_SINK_DEFERRED_VOLUME)
1134             pa_sink_volume_change_rewind(s, nbytes);
1135 #ifdef TIZEN_PCM_DUMP
1136         /* rewind pcm */
1137         if (s->pcm_dump_fp)
1138             fseeko(s->pcm_dump_fp, (off_t)nbytes * (-1), SEEK_CUR);
1139 #endif
1140     }
1141
1142     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
1143         pa_sink_input_assert_ref(i);
1144         pa_sink_input_process_rewind(i, nbytes);
1145     }
1146
1147     if (nbytes > 0) {
1148         if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
1149             pa_source_process_rewind(s->monitor_source, nbytes);
1150     }
1151 }
1152
1153 /* Called from IO thread context */
1154 static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxinfo) {
1155     pa_sink_input *i;
1156     unsigned n = 0;
1157     void *state = NULL;
1158     size_t mixlength = *length;
1159
1160     pa_sink_assert_ref(s);
1161     pa_sink_assert_io_context(s);
1162     pa_assert(info);
1163
1164     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
1165         pa_sink_input_assert_ref(i);
1166
1167         pa_sink_input_peek(i, *length, &info->chunk, &info->volume);
1168
1169         if (mixlength == 0 || info->chunk.length < mixlength)
1170             mixlength = info->chunk.length;
1171
1172         if (pa_memblock_is_silence(info->chunk.memblock)) {
1173             pa_memblock_unref(info->chunk.memblock);
1174             continue;
1175         }
1176
1177         info->userdata = pa_sink_input_ref(i);
1178
1179         pa_assert(info->chunk.memblock);
1180         pa_assert(info->chunk.length > 0);
1181
1182         info++;
1183         n++;
1184         maxinfo--;
1185     }
1186
1187     if (mixlength > 0)
1188         *length = mixlength;
1189
1190     return n;
1191 }
1192
1193 /* Called from IO thread context */
1194 static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *result) {
1195     pa_sink_input *i;
1196     void *state;
1197     unsigned p = 0;
1198     unsigned n_unreffed = 0;
1199
1200     pa_sink_assert_ref(s);
1201     pa_sink_assert_io_context(s);
1202     pa_assert(result);
1203     pa_assert(result->memblock);
1204     pa_assert(result->length > 0);
1205
1206     /* We optimize for the case where the order of the inputs has not changed */
1207
1208     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
1209         unsigned j;
1210         pa_mix_info* m = NULL;
1211
1212         pa_sink_input_assert_ref(i);
1213
1214         /* Let's try to find the matching entry info the pa_mix_info array */
1215         for (j = 0; j < n; j ++) {
1216
1217             if (info[p].userdata == i) {
1218                 m = info + p;
1219                 break;
1220             }
1221
1222             p++;
1223             if (p >= n)
1224                 p = 0;
1225         }
1226
1227         /* Drop read data */
1228         pa_sink_input_drop(i, result->length);
1229
1230         if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state)) {
1231
1232             if (pa_hashmap_size(i->thread_info.direct_outputs) > 0) {
1233                 void *ostate = NULL;
1234                 pa_source_output *o;
1235                 pa_memchunk c;
1236
1237                 if (m && m->chunk.memblock) {
1238                     c = m->chunk;
1239                     pa_memblock_ref(c.memblock);
1240                     pa_assert(result->length <= c.length);
1241                     c.length = result->length;
1242
1243                     pa_memchunk_make_writable(&c, 0);
1244                     pa_volume_memchunk(&c, &s->sample_spec, &m->volume);
1245                 } else {
1246                     c = s->silence;
1247                     pa_memblock_ref(c.memblock);
1248                     pa_assert(result->length <= c.length);
1249                     c.length = result->length;
1250                 }
1251
1252                 while ((o = pa_hashmap_iterate(i->thread_info.direct_outputs, &ostate, NULL))) {
1253                     pa_source_output_assert_ref(o);
1254                     pa_assert(o->direct_on_input == i);
1255                     pa_source_post_direct(s->monitor_source, o, &c);
1256                 }
1257
1258                 pa_memblock_unref(c.memblock);
1259             }
1260         }
1261
1262         if (m) {
1263             if (m->chunk.memblock) {
1264                 pa_memblock_unref(m->chunk.memblock);
1265                 pa_memchunk_reset(&m->chunk);
1266             }
1267
1268             pa_sink_input_unref(m->userdata);
1269             m->userdata = NULL;
1270
1271             n_unreffed += 1;
1272         }
1273     }
1274
1275     /* Now drop references to entries that are included in the
1276      * pa_mix_info array but don't exist anymore */
1277
1278     if (n_unreffed < n) {
1279         for (; n > 0; info++, n--) {
1280             if (info->userdata)
1281                 pa_sink_input_unref(info->userdata);
1282             if (info->chunk.memblock)
1283                 pa_memblock_unref(info->chunk.memblock);
1284         }
1285     }
1286
1287     if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
1288         pa_source_post(s->monitor_source, result);
1289 }
1290
1291 /* Called from IO thread context */
1292 void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
1293     pa_mix_info info[MAX_MIX_CHANNELS];
1294     unsigned n;
1295     size_t block_size_max;
1296
1297     pa_sink_assert_ref(s);
1298     pa_sink_assert_io_context(s);
1299     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1300     pa_assert(pa_frame_aligned(length, &s->sample_spec));
1301     pa_assert(result);
1302
1303     pa_assert(!s->thread_info.rewind_requested);
1304     pa_assert(s->thread_info.rewind_nbytes == 0);
1305
1306     if (s->thread_info.state == PA_SINK_SUSPENDED) {
1307         result->memblock = pa_memblock_ref(s->silence.memblock);
1308         result->index = s->silence.index;
1309         result->length = PA_MIN(s->silence.length, length);
1310         return;
1311     }
1312
1313     pa_sink_ref(s);
1314
1315     if (length <= 0)
1316         length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
1317
1318     block_size_max = pa_mempool_block_size_max(s->core->mempool);
1319     if (length > block_size_max)
1320         length = pa_frame_align(block_size_max, &s->sample_spec);
1321
1322     pa_assert(length > 0);
1323
1324     n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
1325
1326     if (n == 0) {
1327
1328         *result = s->silence;
1329         pa_memblock_ref(result->memblock);
1330
1331         if (result->length > length)
1332             result->length = length;
1333
1334     } else if (n == 1) {
1335         pa_cvolume volume;
1336
1337         *result = info[0].chunk;
1338         pa_memblock_ref(result->memblock);
1339
1340         if (result->length > length)
1341             result->length = length;
1342
1343         pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
1344
1345         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) {
1346             pa_memblock_unref(result->memblock);
1347             pa_silence_memchunk_get(&s->core->silence_cache,
1348                                     s->core->mempool,
1349                                     result,
1350                                     &s->sample_spec,
1351                                     result->length);
1352         } else if (!pa_cvolume_is_norm(&volume)) {
1353             pa_memchunk_make_writable(result, 0);
1354             pa_volume_memchunk(result, &s->sample_spec, &volume);
1355         }
1356     } else {
1357         void *ptr;
1358         result->memblock = pa_memblock_new(s->core->mempool, length);
1359
1360         ptr = pa_memblock_acquire(result->memblock);
1361         result->length = pa_mix(info, n,
1362                                 ptr, length,
1363                                 &s->sample_spec,
1364                                 &s->thread_info.soft_volume,
1365                                 s->thread_info.soft_muted);
1366         pa_memblock_release(result->memblock);
1367
1368         result->index = 0;
1369     }
1370
1371     inputs_drop(s, info, n, result);
1372
1373 #ifdef TIZEN_PCM_DUMP
1374     pa_sink_write_pcm_dump(s, result);
1375 #endif
1376     pa_sink_unref(s);
1377 }
1378
1379 /* Called from IO thread context */
1380 void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
1381     pa_mix_info info[MAX_MIX_CHANNELS];
1382     unsigned n;
1383     size_t length, block_size_max;
1384
1385     pa_sink_assert_ref(s);
1386     pa_sink_assert_io_context(s);
1387     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1388     pa_assert(target);
1389     pa_assert(target->memblock);
1390     pa_assert(target->length > 0);
1391     pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
1392
1393     pa_assert(!s->thread_info.rewind_requested);
1394     pa_assert(s->thread_info.rewind_nbytes == 0);
1395
1396     if (s->thread_info.state == PA_SINK_SUSPENDED) {
1397         pa_silence_memchunk(target, &s->sample_spec);
1398         return;
1399     }
1400
1401     pa_sink_ref(s);
1402
1403     length = target->length;
1404     block_size_max = pa_mempool_block_size_max(s->core->mempool);
1405     if (length > block_size_max)
1406         length = pa_frame_align(block_size_max, &s->sample_spec);
1407
1408     pa_assert(length > 0);
1409
1410     n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
1411
1412     if (n == 0) {
1413         if (target->length > length)
1414             target->length = length;
1415
1416         pa_silence_memchunk(target, &s->sample_spec);
1417     } else if (n == 1) {
1418         pa_cvolume volume;
1419
1420         if (target->length > length)
1421             target->length = length;
1422
1423         pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
1424
1425         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
1426             pa_silence_memchunk(target, &s->sample_spec);
1427         else {
1428             pa_memchunk vchunk;
1429
1430             vchunk = info[0].chunk;
1431             pa_memblock_ref(vchunk.memblock);
1432
1433             if (vchunk.length > length)
1434                 vchunk.length = length;
1435
1436             if (!pa_cvolume_is_norm(&volume)) {
1437                 pa_memchunk_make_writable(&vchunk, 0);
1438                 pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
1439             }
1440
1441             pa_memchunk_memcpy(target, &vchunk);
1442             pa_memblock_unref(vchunk.memblock);
1443         }
1444
1445     } else {
1446         void *ptr;
1447
1448         ptr = pa_memblock_acquire(target->memblock);
1449
1450         target->length = pa_mix(info, n,
1451                                 (uint8_t*) ptr + target->index, length,
1452                                 &s->sample_spec,
1453                                 &s->thread_info.soft_volume,
1454                                 s->thread_info.soft_muted);
1455
1456         pa_memblock_release(target->memblock);
1457     }
1458
1459     inputs_drop(s, info, n, target);
1460
1461 #ifdef TIZEN_PCM_DUMP
1462     pa_sink_write_pcm_dump(s, target);
1463 #endif
1464     pa_sink_unref(s);
1465 }
1466
1467 /* Called from IO thread context */
1468 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
1469     pa_memchunk chunk;
1470     size_t l, d;
1471
1472     pa_sink_assert_ref(s);
1473     pa_sink_assert_io_context(s);
1474     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1475     pa_assert(target);
1476     pa_assert(target->memblock);
1477     pa_assert(target->length > 0);
1478     pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
1479
1480     pa_assert(!s->thread_info.rewind_requested);
1481     pa_assert(s->thread_info.rewind_nbytes == 0);
1482
1483     if (s->thread_info.state == PA_SINK_SUSPENDED) {
1484         pa_silence_memchunk(target, &s->sample_spec);
1485         return;
1486     }
1487
1488     pa_sink_ref(s);
1489
1490     l = target->length;
1491     d = 0;
1492     while (l > 0) {
1493         chunk = *target;
1494         chunk.index += d;
1495         chunk.length -= d;
1496
1497         pa_sink_render_into(s, &chunk);
1498
1499         d += chunk.length;
1500         l -= chunk.length;
1501     }
1502
1503     pa_sink_unref(s);
1504 }
1505
1506 /* Called from IO thread context */
1507 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
1508     pa_sink_assert_ref(s);
1509     pa_sink_assert_io_context(s);
1510     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1511     pa_assert(length > 0);
1512     pa_assert(pa_frame_aligned(length, &s->sample_spec));
1513     pa_assert(result);
1514
1515     pa_assert(!s->thread_info.rewind_requested);
1516     pa_assert(s->thread_info.rewind_nbytes == 0);
1517
1518     pa_sink_ref(s);
1519
1520     pa_sink_render(s, length, result);
1521
1522     if (result->length < length) {
1523         pa_memchunk chunk;
1524
1525         pa_memchunk_make_writable(result, length);
1526
1527         chunk.memblock = result->memblock;
1528         chunk.index = result->index + result->length;
1529         chunk.length = length - result->length;
1530
1531         pa_sink_render_into_full(s, &chunk);
1532
1533         result->length = length;
1534     }
1535
1536     pa_sink_unref(s);
1537 }
1538
1539 /* Called from main thread */
1540 int pa_sink_reconfigure(pa_sink *s, pa_sample_spec *spec, bool passthrough) {
1541     int ret = -1;
1542     pa_sample_spec desired_spec;
1543     uint32_t default_rate = s->default_sample_rate;
1544     uint32_t alternate_rate = s->alternate_sample_rate;
1545     uint32_t idx;
1546     pa_sink_input *i;
1547     bool default_rate_is_usable = false;
1548     bool alternate_rate_is_usable = false;
1549 #ifdef __TIZEN__
1550     bool avoid_resampling = s->avoid_resampling;
1551 #else
1552     bool avoid_resampling = s->core->avoid_resampling;
1553 #endif
1554
1555     /* We currently only try to reconfigure the sample rate */
1556
1557     if (pa_sample_spec_equal(spec, &s->sample_spec))
1558         return 0;
1559
1560     if (!s->reconfigure)
1561         return -1;
1562
1563     if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough && !avoid_resampling)) {
1564         pa_log_debug("Default and alternate sample rates are the same, so there is no point in switching.");
1565         return -1;
1566     }
1567
1568     if (PA_SINK_IS_RUNNING(s->state)) {
1569         pa_log_info("Cannot update rate, SINK_IS_RUNNING, will keep using %u Hz",
1570                     s->sample_spec.rate);
1571         return -1;
1572     }
1573
1574     if (s->monitor_source) {
1575         if (PA_SOURCE_IS_RUNNING(s->monitor_source->state) == true) {
1576             pa_log_info("Cannot update rate, monitor source is RUNNING");
1577             return -1;
1578         }
1579     }
1580
1581     if (PA_UNLIKELY(!pa_sample_spec_valid(spec)))
1582         return -1;
1583
1584     desired_spec = s->sample_spec;
1585
1586     if (passthrough) {
1587         /* We have to try to use the sink input rate */
1588         desired_spec.rate = spec->rate;
1589
1590     } else if (avoid_resampling && (spec->rate >= default_rate || spec->rate >= alternate_rate)) {
1591         /* We just try to set the sink input's sample rate if it's not too low */
1592         desired_spec.rate = spec->rate;
1593
1594     } else if (default_rate == spec->rate || alternate_rate == spec->rate) {
1595         /* We can directly try to use this rate */
1596         desired_spec.rate = spec->rate;
1597
1598     } else {
1599         /* See if we can pick a rate that results in less resampling effort */
1600         if (default_rate % 11025 == 0 && spec->rate % 11025 == 0)
1601             default_rate_is_usable = true;
1602         if (default_rate % 4000 == 0 && spec->rate % 4000 == 0)
1603             default_rate_is_usable = true;
1604         if (alternate_rate % 11025 == 0 && spec->rate % 11025 == 0)
1605             alternate_rate_is_usable = true;
1606         if (alternate_rate % 4000 == 0 && spec->rate % 4000 == 0)
1607             alternate_rate_is_usable = true;
1608
1609         if (alternate_rate_is_usable && !default_rate_is_usable)
1610             desired_spec.rate = alternate_rate;
1611         else
1612             desired_spec.rate = default_rate;
1613     }
1614
1615     if (pa_sample_spec_equal(&desired_spec, &s->sample_spec) && passthrough == pa_sink_is_passthrough(s))
1616         return -1;
1617
1618     if (!passthrough && pa_sink_used_by(s) > 0)
1619         return -1;
1620
1621 #ifdef __TIZEN__
1622     pa_log_debug("Suspending sink %s due to changing format, desired rate = %u", s->name, desired_spec.rate);
1623 #else
1624     pa_log_debug("Suspending sink %s due to changing format", s->name);
1625 #endif
1626     pa_sink_suspend(s, true, PA_SUSPEND_INTERNAL);
1627
1628     if (s->reconfigure(s, &desired_spec, passthrough) >= 0) {
1629         /* update monitor source as well */
1630         if (s->monitor_source && !passthrough)
1631             pa_source_reconfigure(s->monitor_source, &desired_spec, false);
1632         pa_log_info("Changed format successfully");
1633
1634         PA_IDXSET_FOREACH(i, s->inputs, idx) {
1635             if (i->state == PA_SINK_INPUT_CORKED)
1636                 pa_sink_input_update_rate(i);
1637         }
1638
1639         ret = 0;
1640     }
1641
1642     pa_sink_suspend(s, false, PA_SUSPEND_INTERNAL);
1643
1644     return ret;
1645 }
1646
1647 /* Called from main thread */
1648 pa_usec_t pa_sink_get_latency(pa_sink *s) {
1649     int64_t usec = 0;
1650
1651     pa_sink_assert_ref(s);
1652     pa_assert_ctl_context();
1653     pa_assert(PA_SINK_IS_LINKED(s->state));
1654
1655     /* The returned value is supposed to be in the time domain of the sound card! */
1656
1657     if (s->state == PA_SINK_SUSPENDED)
1658         return 0;
1659
1660     if (!(s->flags & PA_SINK_LATENCY))
1661         return 0;
1662
1663     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
1664
1665     /* the return value is unsigned, so check that the offset can be added to usec without
1666      * underflowing. */
1667     if (-s->port_latency_offset <= usec)
1668         usec += s->port_latency_offset;
1669     else
1670         usec = 0;
1671
1672     return (pa_usec_t)usec;
1673 }
1674
1675 /* Called from IO thread */
1676 int64_t pa_sink_get_latency_within_thread(pa_sink *s, bool allow_negative) {
1677     int64_t usec = 0;
1678     pa_msgobject *o;
1679
1680     pa_sink_assert_ref(s);
1681     pa_sink_assert_io_context(s);
1682     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1683
1684     /* The returned value is supposed to be in the time domain of the sound card! */
1685
1686     if (s->thread_info.state == PA_SINK_SUSPENDED)
1687         return 0;
1688
1689     if (!(s->flags & PA_SINK_LATENCY))
1690         return 0;
1691
1692     o = PA_MSGOBJECT(s);
1693
1694     /* FIXME: We probably should make this a proper vtable callback instead of going through process_msg() */
1695
1696     o->process_msg(o, PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL);
1697
1698     /* If allow_negative is false, the call should only return positive values, */
1699     usec += s->thread_info.port_latency_offset;
1700     if (!allow_negative && usec < 0)
1701         usec = 0;
1702
1703     return usec;
1704 }
1705
1706 /* Called from the main thread (and also from the IO thread while the main
1707  * thread is waiting).
1708  *
1709  * When a sink uses volume sharing, it never has the PA_SINK_FLAT_VOLUME flag
1710  * set. Instead, flat volume mode is detected by checking whether the root sink
1711  * has the flag set. */
1712 bool pa_sink_flat_volume_enabled(pa_sink *s) {
1713     pa_sink_assert_ref(s);
1714
1715     s = pa_sink_get_master(s);
1716
1717     if (PA_LIKELY(s))
1718         return (s->flags & PA_SINK_FLAT_VOLUME);
1719     else
1720         return false;
1721 }
1722
1723 /* Called from the main thread (and also from the IO thread while the main
1724  * thread is waiting). */
1725 pa_sink *pa_sink_get_master(pa_sink *s) {
1726     pa_sink_assert_ref(s);
1727
1728     while (s && (s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1729         if (PA_UNLIKELY(!s->input_to_master))
1730             return NULL;
1731
1732         s = s->input_to_master->sink;
1733     }
1734
1735     return s;
1736 }
1737
1738 /* Called from main context */
1739 bool pa_sink_is_filter(pa_sink *s) {
1740     pa_sink_assert_ref(s);
1741
1742     return (s->input_to_master != NULL);
1743 }
1744
1745 /* Called from main context */
1746 bool pa_sink_is_passthrough(pa_sink *s) {
1747     pa_sink_input *alt_i;
1748     uint32_t idx;
1749
1750     pa_sink_assert_ref(s);
1751
1752     /* one and only one PASSTHROUGH input can possibly be connected */
1753     if (pa_idxset_size(s->inputs) == 1) {
1754         alt_i = pa_idxset_first(s->inputs, &idx);
1755
1756         if (pa_sink_input_is_passthrough(alt_i))
1757             return true;
1758     }
1759
1760     return false;
1761 }
1762
1763 /* Called from main context */
1764 void pa_sink_enter_passthrough(pa_sink *s) {
1765     pa_cvolume volume;
1766
1767     /* The sink implementation is reconfigured for passthrough in
1768      * pa_sink_reconfigure(). This function sets the PA core objects to
1769      * passthrough mode. */
1770
1771     /* disable the monitor in passthrough mode */
1772     if (s->monitor_source) {
1773         pa_log_debug("Suspending monitor source %s, because the sink is entering the passthrough mode.", s->monitor_source->name);
1774         pa_source_suspend(s->monitor_source, true, PA_SUSPEND_PASSTHROUGH);
1775     }
1776
1777     /* set the volume to NORM */
1778     s->saved_volume = *pa_sink_get_volume(s, true);
1779     s->saved_save_volume = s->save_volume;
1780
1781     pa_cvolume_set(&volume, s->sample_spec.channels, PA_MIN(s->base_volume, PA_VOLUME_NORM));
1782     pa_sink_set_volume(s, &volume, true, false);
1783
1784     pa_log_debug("Suspending/Restarting sink %s to enter passthrough mode", s->name);
1785 }
1786
1787 /* Called from main context */
1788 void pa_sink_leave_passthrough(pa_sink *s) {
1789     /* Unsuspend monitor */
1790     if (s->monitor_source) {
1791         pa_log_debug("Resuming monitor source %s, because the sink is leaving the passthrough mode.", s->monitor_source->name);
1792         pa_source_suspend(s->monitor_source, false, PA_SUSPEND_PASSTHROUGH);
1793     }
1794
1795     /* Restore sink volume to what it was before we entered passthrough mode */
1796     pa_sink_set_volume(s, &s->saved_volume, true, s->saved_save_volume);
1797
1798     pa_cvolume_init(&s->saved_volume);
1799     s->saved_save_volume = false;
1800
1801 }
1802
1803 /* Called from main context. */
1804 static void compute_reference_ratio(pa_sink_input *i) {
1805     unsigned c = 0;
1806     pa_cvolume remapped;
1807     pa_cvolume ratio;
1808
1809     pa_assert(i);
1810     pa_assert(pa_sink_flat_volume_enabled(i->sink));
1811
1812     /*
1813      * Calculates the reference ratio from the sink's reference
1814      * volume. This basically calculates:
1815      *
1816      * i->reference_ratio = i->volume / i->sink->reference_volume
1817      */
1818
1819     remapped = i->sink->reference_volume;
1820     pa_cvolume_remap(&remapped, &i->sink->channel_map, &i->channel_map);
1821
1822     ratio = i->reference_ratio;
1823
1824     for (c = 0; c < i->sample_spec.channels; c++) {
1825
1826         /* We don't update when the sink volume is 0 anyway */
1827         if (remapped.values[c] <= PA_VOLUME_MUTED)
1828             continue;
1829
1830         /* Don't update the reference ratio unless necessary */
1831         if (pa_sw_volume_multiply(
1832                     ratio.values[c],
1833                     remapped.values[c]) == i->volume.values[c])
1834             continue;
1835
1836         ratio.values[c] = pa_sw_volume_divide(
1837                 i->volume.values[c],
1838                 remapped.values[c]);
1839     }
1840
1841     pa_sink_input_set_reference_ratio(i, &ratio);
1842 }
1843
1844 /* Called from main context. Only called for the root sink in volume sharing
1845  * cases, except for internal recursive calls. */
1846 static void compute_reference_ratios(pa_sink *s) {
1847     uint32_t idx;
1848     pa_sink_input *i;
1849
1850     pa_sink_assert_ref(s);
1851     pa_assert_ctl_context();
1852     pa_assert(PA_SINK_IS_LINKED(s->state));
1853     pa_assert(pa_sink_flat_volume_enabled(s));
1854
1855     PA_IDXSET_FOREACH(i, s->inputs, idx) {
1856         compute_reference_ratio(i);
1857
1858         if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
1859                 && PA_SINK_IS_LINKED(i->origin_sink->state))
1860             compute_reference_ratios(i->origin_sink);
1861     }
1862 }
1863
1864 /* Called from main context. Only called for the root sink in volume sharing
1865  * cases, except for internal recursive calls. */
1866 static void compute_real_ratios(pa_sink *s) {
1867     pa_sink_input *i;
1868     uint32_t idx;
1869
1870     pa_sink_assert_ref(s);
1871     pa_assert_ctl_context();
1872     pa_assert(PA_SINK_IS_LINKED(s->state));
1873     pa_assert(pa_sink_flat_volume_enabled(s));
1874
1875     PA_IDXSET_FOREACH(i, s->inputs, idx) {
1876         unsigned c;
1877         pa_cvolume remapped;
1878
1879         if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1880             /* The origin sink uses volume sharing, so this input's real ratio
1881              * is handled as a special case - the real ratio must be 0 dB, and
1882              * as a result i->soft_volume must equal i->volume_factor. */
1883             pa_cvolume_reset(&i->real_ratio, i->real_ratio.channels);
1884             i->soft_volume = i->volume_factor;
1885
1886             if (PA_SINK_IS_LINKED(i->origin_sink->state))
1887                 compute_real_ratios(i->origin_sink);
1888
1889             continue;
1890         }
1891
1892         /*
1893          * This basically calculates:
1894          *
1895          * i->real_ratio := i->volume / s->real_volume
1896          * i->soft_volume := i->real_ratio * i->volume_factor
1897          */
1898
1899         remapped = s->real_volume;
1900         pa_cvolume_remap(&remapped, &s->channel_map, &i->channel_map);
1901
1902         i->real_ratio.channels = i->sample_spec.channels;
1903         i->soft_volume.channels = i->sample_spec.channels;
1904
1905         for (c = 0; c < i->sample_spec.channels; c++) {
1906
1907             if (remapped.values[c] <= PA_VOLUME_MUTED) {
1908                 /* We leave i->real_ratio untouched */
1909                 i->soft_volume.values[c] = PA_VOLUME_MUTED;
1910                 continue;
1911             }
1912
1913             /* Don't lose accuracy unless necessary */
1914             if (pa_sw_volume_multiply(
1915                         i->real_ratio.values[c],
1916                         remapped.values[c]) != i->volume.values[c])
1917
1918                 i->real_ratio.values[c] = pa_sw_volume_divide(
1919                         i->volume.values[c],
1920                         remapped.values[c]);
1921
1922             i->soft_volume.values[c] = pa_sw_volume_multiply(
1923                     i->real_ratio.values[c],
1924                     i->volume_factor.values[c]);
1925         }
1926
1927         /* We don't copy the soft_volume to the thread_info data
1928          * here. That must be done by the caller */
1929     }
1930 }
1931
1932 static pa_cvolume *cvolume_remap_minimal_impact(
1933         pa_cvolume *v,
1934         const pa_cvolume *template,
1935         const pa_channel_map *from,
1936         const pa_channel_map *to) {
1937
1938     pa_cvolume t;
1939
1940     pa_assert(v);
1941     pa_assert(template);
1942     pa_assert(from);
1943     pa_assert(to);
1944     pa_assert(pa_cvolume_compatible_with_channel_map(v, from));
1945     pa_assert(pa_cvolume_compatible_with_channel_map(template, to));
1946
1947     /* Much like pa_cvolume_remap(), but tries to minimize impact when
1948      * mapping from sink input to sink volumes:
1949      *
1950      * If template is a possible remapping from v it is used instead
1951      * of remapping anew.
1952      *
1953      * If the channel maps don't match we set an all-channel volume on
1954      * the sink to ensure that changing a volume on one stream has no
1955      * effect that cannot be compensated for in another stream that
1956      * does not have the same channel map as the sink. */
1957
1958     if (pa_channel_map_equal(from, to))
1959         return v;
1960
1961     t = *template;
1962     if (pa_cvolume_equal(pa_cvolume_remap(&t, to, from), v)) {
1963         *v = *template;
1964         return v;
1965     }
1966
1967     pa_cvolume_set(v, to->channels, pa_cvolume_max(v));
1968     return v;
1969 }
1970
1971 /* Called from main thread. Only called for the root sink in volume sharing
1972  * cases, except for internal recursive calls. */
1973 static void get_maximum_input_volume(pa_sink *s, pa_cvolume *max_volume, const pa_channel_map *channel_map) {
1974     pa_sink_input *i;
1975     uint32_t idx;
1976
1977     pa_sink_assert_ref(s);
1978     pa_assert(max_volume);
1979     pa_assert(channel_map);
1980     pa_assert(pa_sink_flat_volume_enabled(s));
1981
1982     PA_IDXSET_FOREACH(i, s->inputs, idx) {
1983         pa_cvolume remapped;
1984
1985         if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1986             if (PA_SINK_IS_LINKED(i->origin_sink->state))
1987                 get_maximum_input_volume(i->origin_sink, max_volume, channel_map);
1988
1989             /* Ignore this input. The origin sink uses volume sharing, so this
1990              * input's volume will be set to be equal to the root sink's real
1991              * volume. Obviously this input's current volume must not then
1992              * affect what the root sink's real volume will be. */
1993             continue;
1994         }
1995
1996         remapped = i->volume;
1997         cvolume_remap_minimal_impact(&remapped, max_volume, &i->channel_map, channel_map);
1998         pa_cvolume_merge(max_volume, max_volume, &remapped);
1999     }
2000 }
2001
2002 /* Called from main thread. Only called for the root sink in volume sharing
2003  * cases, except for internal recursive calls. */
2004 static bool has_inputs(pa_sink *s) {
2005     pa_sink_input *i;
2006     uint32_t idx;
2007
2008     pa_sink_assert_ref(s);
2009
2010     PA_IDXSET_FOREACH(i, s->inputs, idx) {
2011         if (!i->origin_sink || !(i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER) || has_inputs(i->origin_sink))
2012             return true;
2013     }
2014
2015     return false;
2016 }
2017
2018 /* Called from main thread. Only called for the root sink in volume sharing
2019  * cases, except for internal recursive calls. */
2020 static void update_real_volume(pa_sink *s, const pa_cvolume *new_volume, pa_channel_map *channel_map) {
2021     pa_sink_input *i;
2022     uint32_t idx;
2023
2024     pa_sink_assert_ref(s);
2025     pa_assert(new_volume);
2026     pa_assert(channel_map);
2027
2028     s->real_volume = *new_volume;
2029     pa_cvolume_remap(&s->real_volume, channel_map, &s->channel_map);
2030
2031     PA_IDXSET_FOREACH(i, s->inputs, idx) {
2032         if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
2033             if (pa_sink_flat_volume_enabled(s)) {
2034                 pa_cvolume new_input_volume;
2035
2036                 /* Follow the root sink's real volume. */
2037                 new_input_volume = *new_volume;
2038                 pa_cvolume_remap(&new_input_volume, channel_map, &i->channel_map);
2039                 pa_sink_input_set_volume_direct(i, &new_input_volume);
2040                 compute_reference_ratio(i);
2041             }
2042
2043             if (PA_SINK_IS_LINKED(i->origin_sink->state))
2044                 update_real_volume(i->origin_sink, new_volume, channel_map);
2045         }
2046     }
2047 }
2048
2049 /* Called from main thread. Only called for the root sink in shared volume
2050  * cases. */
2051 static void compute_real_volume(pa_sink *s) {
2052     pa_sink_assert_ref(s);
2053     pa_assert_ctl_context();
2054     pa_assert(PA_SINK_IS_LINKED(s->state));
2055     pa_assert(pa_sink_flat_volume_enabled(s));
2056     pa_assert(!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
2057
2058     /* This determines the maximum volume of all streams and sets
2059      * s->real_volume accordingly. */
2060
2061     if (!has_inputs(s)) {
2062         /* In the special case that we have no sink inputs we leave the
2063          * volume unmodified. */
2064         update_real_volume(s, &s->reference_volume, &s->channel_map);
2065         return;
2066     }
2067
2068     pa_cvolume_mute(&s->real_volume, s->channel_map.channels);
2069
2070     /* First let's determine the new maximum volume of all inputs
2071      * connected to this sink */
2072     get_maximum_input_volume(s, &s->real_volume, &s->channel_map);
2073     update_real_volume(s, &s->real_volume, &s->channel_map);
2074
2075     /* Then, let's update the real ratios/soft volumes of all inputs
2076      * connected to this sink */
2077     compute_real_ratios(s);
2078 }
2079
2080 /* Called from main thread. Only called for the root sink in shared volume
2081  * cases, except for internal recursive calls. */
2082 static void propagate_reference_volume(pa_sink *s) {
2083     pa_sink_input *i;
2084     uint32_t idx;
2085
2086     pa_sink_assert_ref(s);
2087     pa_assert_ctl_context();
2088     pa_assert(PA_SINK_IS_LINKED(s->state));
2089     pa_assert(pa_sink_flat_volume_enabled(s));
2090
2091     /* This is called whenever the sink volume changes that is not
2092      * caused by a sink input volume change. We need to fix up the
2093      * sink input volumes accordingly */
2094
2095     PA_IDXSET_FOREACH(i, s->inputs, idx) {
2096         pa_cvolume new_volume;
2097
2098         if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
2099             if (PA_SINK_IS_LINKED(i->origin_sink->state))
2100                 propagate_reference_volume(i->origin_sink);
2101
2102             /* Since the origin sink uses volume sharing, this input's volume
2103              * needs to be updated to match the root sink's real volume, but
2104              * that will be done later in update_real_volume(). */
2105             continue;
2106         }
2107
2108         /* This basically calculates:
2109          *
2110          * i->volume := s->reference_volume * i->reference_ratio  */
2111
2112         new_volume = s->reference_volume;
2113         pa_cvolume_remap(&new_volume, &s->channel_map, &i->channel_map);
2114         pa_sw_cvolume_multiply(&new_volume, &new_volume, &i->reference_ratio);
2115         pa_sink_input_set_volume_direct(i, &new_volume);
2116     }
2117 }
2118
2119 /* Called from main thread. Only called for the root sink in volume sharing
2120  * cases, except for internal recursive calls. The return value indicates
2121  * whether any reference volume actually changed. */
2122 static bool update_reference_volume(pa_sink *s, const pa_cvolume *v, const pa_channel_map *channel_map, bool save) {
2123     pa_cvolume volume;
2124     bool reference_volume_changed;
2125     pa_sink_input *i;
2126     uint32_t idx;
2127
2128     pa_sink_assert_ref(s);
2129     pa_assert(PA_SINK_IS_LINKED(s->state));
2130     pa_assert(v);
2131     pa_assert(channel_map);
2132     pa_assert(pa_cvolume_valid(v));
2133
2134     volume = *v;
2135     pa_cvolume_remap(&volume, channel_map, &s->channel_map);
2136
2137     reference_volume_changed = !pa_cvolume_equal(&volume, &s->reference_volume);
2138     pa_sink_set_reference_volume_direct(s, &volume);
2139
2140     s->save_volume = (!reference_volume_changed && s->save_volume) || save;
2141
2142     if (!reference_volume_changed && !(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
2143         /* If the root sink's volume doesn't change, then there can't be any
2144          * changes in the other sinks in the sink tree either.
2145          *
2146          * It's probably theoretically possible that even if the root sink's
2147          * volume changes slightly, some filter sink doesn't change its volume
2148          * due to rounding errors. If that happens, we still want to propagate
2149          * the changed root sink volume to the sinks connected to the
2150          * intermediate sink that didn't change its volume. This theoretical
2151          * possibility is the reason why we have that !(s->flags &
2152          * PA_SINK_SHARE_VOLUME_WITH_MASTER) condition. Probably nobody would
2153          * notice even if we returned here false always if
2154          * reference_volume_changed is false. */
2155         return false;
2156
2157     PA_IDXSET_FOREACH(i, s->inputs, idx) {
2158         if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
2159                 && PA_SINK_IS_LINKED(i->origin_sink->state))
2160             update_reference_volume(i->origin_sink, v, channel_map, false);
2161     }
2162
2163     return true;
2164 }
2165
2166 /* Called from main thread */
2167 void pa_sink_set_volume(
2168         pa_sink *s,
2169         const pa_cvolume *volume,
2170         bool send_msg,
2171         bool save) {
2172
2173     pa_cvolume new_reference_volume;
2174     pa_sink *root_sink;
2175
2176     pa_sink_assert_ref(s);
2177     pa_assert_ctl_context();
2178     pa_assert(PA_SINK_IS_LINKED(s->state));
2179     pa_assert(!volume || pa_cvolume_valid(volume));
2180     pa_assert(volume || pa_sink_flat_volume_enabled(s));
2181     pa_assert(!volume || volume->channels == 1 || pa_cvolume_compatible(volume, &s->sample_spec));
2182
2183     /* make sure we don't change the volume when a PASSTHROUGH input is connected ...
2184      * ... *except* if we're being invoked to reset the volume to ensure 0 dB gain */
2185     if (pa_sink_is_passthrough(s) && (!volume || !pa_cvolume_is_norm(volume))) {
2186         pa_log_warn("Cannot change volume, Sink is connected to PASSTHROUGH input");
2187         return;
2188     }
2189
2190     /* In case of volume sharing, the volume is set for the root sink first,
2191      * from which it's then propagated to the sharing sinks. */
2192     root_sink = pa_sink_get_master(s);
2193
2194     if (PA_UNLIKELY(!root_sink))
2195         return;
2196
2197     /* As a special exception we accept mono volumes on all sinks --
2198      * even on those with more complex channel maps */
2199
2200     if (volume) {
2201         if (pa_cvolume_compatible(volume, &s->sample_spec))
2202             new_reference_volume = *volume;
2203         else {
2204             new_reference_volume = s->reference_volume;
2205             pa_cvolume_scale(&new_reference_volume, pa_cvolume_max(volume));
2206         }
2207
2208         pa_cvolume_remap(&new_reference_volume, &s->channel_map, &root_sink->channel_map);
2209
2210         if (update_reference_volume(root_sink, &new_reference_volume, &root_sink->channel_map, save)) {
2211             if (pa_sink_flat_volume_enabled(root_sink)) {
2212                 /* OK, propagate this volume change back to the inputs */
2213                 propagate_reference_volume(root_sink);
2214
2215                 /* And now recalculate the real volume */
2216                 compute_real_volume(root_sink);
2217             } else
2218                 update_real_volume(root_sink, &root_sink->reference_volume, &root_sink->channel_map);
2219         }
2220
2221     } else {
2222         /* If volume is NULL we synchronize the sink's real and
2223          * reference volumes with the stream volumes. */
2224
2225         pa_assert(pa_sink_flat_volume_enabled(root_sink));
2226
2227         /* Ok, let's determine the new real volume */
2228         compute_real_volume(root_sink);
2229
2230         /* Let's 'push' the reference volume if necessary */
2231         pa_cvolume_merge(&new_reference_volume, &s->reference_volume, &root_sink->real_volume);
2232         /* If the sink and its root don't have the same number of channels, we need to remap */
2233         if (s != root_sink && !pa_channel_map_equal(&s->channel_map, &root_sink->channel_map))
2234             pa_cvolume_remap(&new_reference_volume, &s->channel_map, &root_sink->channel_map);
2235         update_reference_volume(root_sink, &new_reference_volume, &root_sink->channel_map, save);
2236
2237         /* Now that the reference volume is updated, we can update the streams'
2238          * reference ratios. */
2239         compute_reference_ratios(root_sink);
2240     }
2241
2242     if (root_sink->set_volume) {
2243         /* If we have a function set_volume(), then we do not apply a
2244          * soft volume by default. However, set_volume() is free to
2245          * apply one to root_sink->soft_volume */
2246
2247         pa_cvolume_reset(&root_sink->soft_volume, root_sink->sample_spec.channels);
2248         if (!(root_sink->flags & PA_SINK_DEFERRED_VOLUME))
2249             root_sink->set_volume(root_sink);
2250
2251     } else
2252         /* If we have no function set_volume(), then the soft volume
2253          * becomes the real volume */
2254         root_sink->soft_volume = root_sink->real_volume;
2255
2256     /* This tells the sink that soft volume and/or real volume changed */
2257     if (send_msg)
2258         pa_assert_se(pa_asyncmsgq_send(root_sink->asyncmsgq, PA_MSGOBJECT(root_sink), PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL) == 0);
2259 }
2260
2261 /* Called from the io thread if sync volume is used, otherwise from the main thread.
2262  * Only to be called by sink implementor */
2263 void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) {
2264
2265     pa_sink_assert_ref(s);
2266     pa_assert(!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
2267
2268     if (s->flags & PA_SINK_DEFERRED_VOLUME)
2269         pa_sink_assert_io_context(s);
2270     else
2271         pa_assert_ctl_context();
2272
2273     if (!volume)
2274         pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
2275     else
2276         s->soft_volume = *volume;
2277
2278     if (PA_SINK_IS_LINKED(s->state) && !(s->flags & PA_SINK_DEFERRED_VOLUME))
2279         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
2280     else
2281         s->thread_info.soft_volume = s->soft_volume;
2282 }
2283
2284 /* Called from the main thread. Only called for the root sink in volume sharing
2285  * cases, except for internal recursive calls. */
2286 static void propagate_real_volume(pa_sink *s, const pa_cvolume *old_real_volume) {
2287     pa_sink_input *i;
2288     uint32_t idx;
2289
2290     pa_sink_assert_ref(s);
2291     pa_assert(old_real_volume);
2292     pa_assert_ctl_context();
2293     pa_assert(PA_SINK_IS_LINKED(s->state));
2294
2295     /* This is called when the hardware's real volume changes due to
2296      * some external event. We copy the real volume into our
2297      * reference volume and then rebuild the stream volumes based on
2298      * i->real_ratio which should stay fixed. */
2299
2300     if (!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
2301         if (pa_cvolume_equal(old_real_volume, &s->real_volume))
2302             return;
2303
2304         /* 1. Make the real volume the reference volume */
2305         update_reference_volume(s, &s->real_volume, &s->channel_map, true);
2306     }
2307
2308     if (pa_sink_flat_volume_enabled(s)) {
2309
2310         PA_IDXSET_FOREACH(i, s->inputs, idx) {
2311             pa_cvolume new_volume;
2312
2313             /* 2. Since the sink's reference and real volumes are equal
2314              * now our ratios should be too. */
2315             pa_sink_input_set_reference_ratio(i, &i->real_ratio);
2316
2317             /* 3. Recalculate the new stream reference volume based on the
2318              * reference ratio and the sink's reference volume.
2319              *
2320              * This basically calculates:
2321              *
2322              * i->volume = s->reference_volume * i->reference_ratio
2323              *
2324              * This is identical to propagate_reference_volume() */
2325             new_volume = s->reference_volume;
2326             pa_cvolume_remap(&new_volume, &s->channel_map, &i->channel_map);
2327             pa_sw_cvolume_multiply(&new_volume, &new_volume, &i->reference_ratio);
2328             pa_sink_input_set_volume_direct(i, &new_volume);
2329
2330             if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
2331                     && PA_SINK_IS_LINKED(i->origin_sink->state))
2332                 propagate_real_volume(i->origin_sink, old_real_volume);
2333         }
2334     }
2335
2336     /* Something got changed in the hardware. It probably makes sense
2337      * to save changed hw settings given that hw volume changes not
2338      * triggered by PA are almost certainly done by the user. */
2339     if (!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
2340         s->save_volume = true;
2341 }
2342
2343 /* Called from io thread */
2344 void pa_sink_update_volume_and_mute(pa_sink *s) {
2345     pa_assert(s);
2346     pa_sink_assert_io_context(s);
2347
2348     pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE, NULL, 0, NULL, NULL);
2349 }
2350
2351 /* Called from main thread */
2352 const pa_cvolume *pa_sink_get_volume(pa_sink *s, bool force_refresh) {
2353     pa_sink_assert_ref(s);
2354     pa_assert_ctl_context();
2355     pa_assert(PA_SINK_IS_LINKED(s->state));
2356
2357     if (s->refresh_volume || force_refresh) {
2358         struct pa_cvolume old_real_volume;
2359
2360         pa_assert(!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
2361
2362         old_real_volume = s->real_volume;
2363
2364         if (!(s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_volume)
2365             s->get_volume(s);
2366
2367         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
2368
2369         update_real_volume(s, &s->real_volume, &s->channel_map);
2370         propagate_real_volume(s, &old_real_volume);
2371     }
2372
2373     return &s->reference_volume;
2374 }
2375
2376 /* Called from main thread. In volume sharing cases, only the root sink may
2377  * call this. */
2378 void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_real_volume) {
2379     pa_cvolume old_real_volume;
2380
2381     pa_sink_assert_ref(s);
2382     pa_assert_ctl_context();
2383     pa_assert(PA_SINK_IS_LINKED(s->state));
2384     pa_assert(!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER));
2385
2386     /* The sink implementor may call this if the volume changed to make sure everyone is notified */
2387
2388     old_real_volume = s->real_volume;
2389     update_real_volume(s, new_real_volume, &s->channel_map);
2390     propagate_real_volume(s, &old_real_volume);
2391 }
2392
2393 /* Called from main thread */
2394 void pa_sink_set_mute(pa_sink *s, bool mute, bool save) {
2395     bool old_muted;
2396
2397     pa_sink_assert_ref(s);
2398     pa_assert_ctl_context();
2399
2400     old_muted = s->muted;
2401
2402     if (mute == old_muted) {
2403         s->save_muted |= save;
2404         return;
2405     }
2406
2407     s->muted = mute;
2408     s->save_muted = save;
2409
2410     if (!(s->flags & PA_SINK_DEFERRED_VOLUME) && s->set_mute) {
2411         s->set_mute_in_progress = true;
2412         s->set_mute(s);
2413         s->set_mute_in_progress = false;
2414     }
2415
2416     if (!PA_SINK_IS_LINKED(s->state))
2417         return;
2418
2419     pa_log_debug("The mute of sink %s changed from %s to %s.", s->name, pa_yes_no(old_muted), pa_yes_no(mute));
2420     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
2421     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
2422     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_MUTE_CHANGED], s);
2423 }
2424
2425 /* Called from main thread */
2426 bool pa_sink_get_mute(pa_sink *s, bool force_refresh) {
2427
2428     pa_sink_assert_ref(s);
2429     pa_assert_ctl_context();
2430     pa_assert(PA_SINK_IS_LINKED(s->state));
2431
2432     if ((s->refresh_muted || force_refresh) && s->get_mute) {
2433         bool mute;
2434
2435         if (s->flags & PA_SINK_DEFERRED_VOLUME) {
2436             if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &mute, 0, NULL) >= 0)
2437                 pa_sink_mute_changed(s, mute);
2438         } else {
2439             if (s->get_mute(s, &mute) >= 0)
2440                 pa_sink_mute_changed(s, mute);
2441         }
2442     }
2443
2444     return s->muted;
2445 }
2446
2447 /* Called from main thread */
2448 void pa_sink_mute_changed(pa_sink *s, bool new_muted) {
2449     pa_sink_assert_ref(s);
2450     pa_assert_ctl_context();
2451     pa_assert(PA_SINK_IS_LINKED(s->state));
2452
2453     if (s->set_mute_in_progress)
2454         return;
2455
2456     /* pa_sink_set_mute() does this same check, so this may appear redundant,
2457      * but we must have this here also, because the save parameter of
2458      * pa_sink_set_mute() would otherwise have unintended side effects (saving
2459      * the mute state when it shouldn't be saved). */
2460     if (new_muted == s->muted)
2461         return;
2462
2463     pa_sink_set_mute(s, new_muted, true);
2464 }
2465
2466 /* Called from main thread */
2467 bool pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p) {
2468     pa_sink_assert_ref(s);
2469     pa_assert_ctl_context();
2470
2471     if (p)
2472         pa_proplist_update(s->proplist, mode, p);
2473
2474     if (PA_SINK_IS_LINKED(s->state)) {
2475         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
2476         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
2477     }
2478
2479     return true;
2480 }
2481
2482 /* Called from main thread */
2483 /* FIXME -- this should be dropped and be merged into pa_sink_update_proplist() */
2484 void pa_sink_set_description(pa_sink *s, const char *description) {
2485     const char *old;
2486     pa_sink_assert_ref(s);
2487     pa_assert_ctl_context();
2488
2489     if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
2490         return;
2491
2492     old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
2493
2494     if (old && description && pa_streq(old, description))
2495         return;
2496
2497     if (description)
2498         pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
2499     else
2500         pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
2501
2502     if (s->monitor_source) {
2503         char *n;
2504
2505         n = pa_sprintf_malloc("Monitor Source of %s", description ? description : s->name);
2506         pa_source_set_description(s->monitor_source, n);
2507         pa_xfree(n);
2508     }
2509
2510     if (PA_SINK_IS_LINKED(s->state)) {
2511         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
2512         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
2513     }
2514 }
2515
2516 /* Called from main thread */
2517 unsigned pa_sink_linked_by(pa_sink *s) {
2518     unsigned ret;
2519
2520     pa_sink_assert_ref(s);
2521     pa_assert_ctl_context();
2522     pa_assert(PA_SINK_IS_LINKED(s->state));
2523
2524     ret = pa_idxset_size(s->inputs);
2525
2526     /* We add in the number of streams connected to us here. Please
2527      * note the asymmetry to pa_sink_used_by()! */
2528
2529     if (s->monitor_source)
2530         ret += pa_source_linked_by(s->monitor_source);
2531
2532     return ret;
2533 }
2534
2535 /* Called from main thread */
2536 unsigned pa_sink_used_by(pa_sink *s) {
2537     unsigned ret;
2538
2539     pa_sink_assert_ref(s);
2540     pa_assert_ctl_context();
2541     pa_assert(PA_SINK_IS_LINKED(s->state));
2542
2543     ret = pa_idxset_size(s->inputs);
2544     pa_assert(ret >= s->n_corked);
2545
2546     /* Streams connected to our monitor source do not matter for
2547      * pa_sink_used_by()!.*/
2548
2549     return ret - s->n_corked;
2550 }
2551
2552 /* Called from main thread */
2553 unsigned pa_sink_check_suspend(pa_sink *s, pa_sink_input *ignore_input, pa_source_output *ignore_output) {
2554     unsigned ret;
2555     pa_sink_input *i;
2556     uint32_t idx;
2557
2558     pa_sink_assert_ref(s);
2559     pa_assert_ctl_context();
2560
2561     if (!PA_SINK_IS_LINKED(s->state))
2562         return 0;
2563
2564     ret = 0;
2565
2566     PA_IDXSET_FOREACH(i, s->inputs, idx) {
2567         pa_sink_input_state_t st;
2568
2569         if (i == ignore_input)
2570             continue;
2571
2572         st = pa_sink_input_get_state(i);
2573
2574         /* We do not assert here. It is perfectly valid for a sink input to
2575          * be in the INIT state (i.e. created, marked done but not yet put)
2576          * and we should not care if it's unlinked as it won't contribute
2577          * towards our busy status.
2578          */
2579         if (!PA_SINK_INPUT_IS_LINKED(st))
2580             continue;
2581
2582         if (st == PA_SINK_INPUT_CORKED)
2583             continue;
2584
2585         if (i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND)
2586             continue;
2587
2588         ret ++;
2589     }
2590
2591     if (s->monitor_source)
2592         ret += pa_source_check_suspend(s->monitor_source, ignore_output);
2593
2594     return ret;
2595 }
2596
2597 const char *pa_sink_state_to_string(pa_sink_state_t state) {
2598     switch (state) {
2599         case PA_SINK_INIT:          return "INIT";
2600         case PA_SINK_IDLE:          return "IDLE";
2601         case PA_SINK_RUNNING:       return "RUNNING";
2602         case PA_SINK_SUSPENDED:     return "SUSPENDED";
2603         case PA_SINK_UNLINKED:      return "UNLINKED";
2604         case PA_SINK_INVALID_STATE: return "INVALID_STATE";
2605     }
2606
2607     pa_assert_not_reached();
2608 }
2609
2610 /* Called from the IO thread */
2611 static void sync_input_volumes_within_thread(pa_sink *s) {
2612     pa_sink_input *i;
2613     void *state = NULL;
2614
2615     pa_sink_assert_ref(s);
2616     pa_sink_assert_io_context(s);
2617
2618     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
2619         if (pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume))
2620             continue;
2621
2622         i->thread_info.soft_volume = i->soft_volume;
2623         pa_sink_input_request_rewind(i, 0, true, false, false);
2624     }
2625 }
2626
2627 /* Called from the IO thread. Only called for the root sink in volume sharing
2628  * cases, except for internal recursive calls. */
2629 static void set_shared_volume_within_thread(pa_sink *s) {
2630     pa_sink_input *i = NULL;
2631     void *state = NULL;
2632
2633     pa_sink_assert_ref(s);
2634
2635     PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME_SYNCED, NULL, 0, NULL);
2636
2637     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
2638         if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
2639             set_shared_volume_within_thread(i->origin_sink);
2640     }
2641 }
2642
2643 /* Called from IO thread, except when it is not */
2644 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
2645     pa_sink *s = PA_SINK(o);
2646     pa_sink_assert_ref(s);
2647
2648     switch ((pa_sink_message_t) code) {
2649
2650         case PA_SINK_MESSAGE_ADD_INPUT: {
2651             pa_sink_input *i = PA_SINK_INPUT(userdata);
2652
2653             /* If you change anything here, make sure to change the
2654              * sink input handling a few lines down at
2655              * PA_SINK_MESSAGE_FINISH_MOVE, too. */
2656
2657             pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
2658
2659             /* Since the caller sleeps in pa_sink_input_put(), we can
2660              * safely access data outside of thread_info even though
2661              * it is mutable */
2662
2663             if ((i->thread_info.sync_prev = i->sync_prev)) {
2664                 pa_assert(i->sink == i->thread_info.sync_prev->sink);
2665                 pa_assert(i->sync_prev->sync_next == i);
2666                 i->thread_info.sync_prev->thread_info.sync_next = i;
2667             }
2668
2669             if ((i->thread_info.sync_next = i->sync_next)) {
2670                 pa_assert(i->sink == i->thread_info.sync_next->sink);
2671                 pa_assert(i->sync_next->sync_prev == i);
2672                 i->thread_info.sync_next->thread_info.sync_prev = i;
2673             }
2674
2675             pa_sink_input_attach(i);
2676
2677             pa_sink_input_set_state_within_thread(i, i->state);
2678
2679             /* The requested latency of the sink input needs to be fixed up and
2680              * then configured on the sink. If this causes the sink latency to
2681              * go down, the sink implementor is responsible for doing a rewind
2682              * in the update_requested_latency() callback to ensure that the
2683              * sink buffer doesn't contain more data than what the new latency
2684              * allows.
2685              *
2686              * XXX: Does it really make sense to push this responsibility to
2687              * the sink implementors? Wouldn't it be better to do it once in
2688              * the core than many times in the modules? */
2689
2690             if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
2691                 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
2692
2693             pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
2694             pa_sink_input_update_max_request(i, s->thread_info.max_request);
2695
2696             /* We don't rewind here automatically. This is left to the
2697              * sink input implementor because some sink inputs need a
2698              * slow start, i.e. need some time to buffer client
2699              * samples before beginning streaming.
2700              *
2701              * XXX: Does it really make sense to push this functionality to
2702              * the sink implementors? Wouldn't it be better to do it once in
2703              * the core than many times in the modules? */
2704
2705             /* In flat volume mode we need to update the volume as
2706              * well */
2707             return o->process_msg(o, PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL);
2708         }
2709
2710         case PA_SINK_MESSAGE_REMOVE_INPUT: {
2711             pa_sink_input *i = PA_SINK_INPUT(userdata);
2712
2713             /* If you change anything here, make sure to change the
2714              * sink input handling a few lines down at
2715              * PA_SINK_MESSAGE_START_MOVE, too. */
2716
2717             pa_sink_input_detach(i);
2718
2719             pa_sink_input_set_state_within_thread(i, i->state);
2720
2721             /* Since the caller sleeps in pa_sink_input_unlink(),
2722              * we can safely access data outside of thread_info even
2723              * though it is mutable */
2724
2725             pa_assert(!i->sync_prev);
2726             pa_assert(!i->sync_next);
2727
2728             if (i->thread_info.sync_prev) {
2729                 i->thread_info.sync_prev->thread_info.sync_next = i->thread_info.sync_prev->sync_next;
2730                 i->thread_info.sync_prev = NULL;
2731             }
2732
2733             if (i->thread_info.sync_next) {
2734                 i->thread_info.sync_next->thread_info.sync_prev = i->thread_info.sync_next->sync_prev;
2735                 i->thread_info.sync_next = NULL;
2736             }
2737
2738             pa_hashmap_remove_and_free(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
2739             pa_sink_invalidate_requested_latency(s, true);
2740             pa_sink_request_rewind(s, (size_t) -1);
2741
2742             /* In flat volume mode we need to update the volume as
2743              * well */
2744             return o->process_msg(o, PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL);
2745         }
2746
2747         case PA_SINK_MESSAGE_START_MOVE: {
2748             pa_sink_input *i = PA_SINK_INPUT(userdata);
2749
2750             /* We don't support moving synchronized streams. */
2751             pa_assert(!i->sync_prev);
2752             pa_assert(!i->sync_next);
2753             pa_assert(!i->thread_info.sync_next);
2754             pa_assert(!i->thread_info.sync_prev);
2755
2756             if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
2757                 pa_usec_t usec = 0;
2758                 size_t sink_nbytes, total_nbytes;
2759
2760                 /* The old sink probably has some audio from this
2761                  * stream in its buffer. We want to "take it back" as
2762                  * much as possible and play it to the new sink. We
2763                  * don't know at this point how much the old sink can
2764                  * rewind. We have to pick something, and that
2765                  * something is the full latency of the old sink here.
2766                  * So we rewind the stream buffer by the sink latency
2767                  * amount, which may be more than what we should
2768                  * rewind. This can result in a chunk of audio being
2769                  * played both to the old sink and the new sink.
2770                  *
2771                  * FIXME: Fix this code so that we don't have to make
2772                  * guesses about how much the sink will actually be
2773                  * able to rewind. If someone comes up with a solution
2774                  * for this, something to note is that the part of the
2775                  * latency that the old sink couldn't rewind should
2776                  * ideally be compensated after the stream has moved
2777                  * to the new sink by adding silence. The new sink
2778                  * most likely can't start playing the moved stream
2779                  * immediately, and that gap should be removed from
2780                  * the "compensation silence" (at least at the time of
2781                  * writing this, the move finish code will actually
2782                  * already take care of dropping the new sink's
2783                  * unrewindable latency, so taking into account the
2784                  * unrewindable latency of the old sink is the only
2785                  * problem).
2786                  *
2787                  * The render_memblockq contents are discarded,
2788                  * because when the sink changes, the format of the
2789                  * audio stored in the render_memblockq may change
2790                  * too, making the stored audio invalid. FIXME:
2791                  * However, the read and write indices are moved back
2792                  * the same amount, so if they are not the same now,
2793                  * they won't be the same after the rewind either. If
2794                  * the write index of the render_memblockq is ahead of
2795                  * the read index, then the render_memblockq will feed
2796                  * the new sink some silence first, which it shouldn't
2797                  * do. The write index should be flushed to be the
2798                  * same as the read index. */
2799
2800                 /* Get the latency of the sink */
2801                 usec = pa_sink_get_latency_within_thread(s, false);
2802                 sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
2803                 total_nbytes = sink_nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq);
2804
2805                 if (total_nbytes > 0) {
2806                     i->thread_info.rewrite_nbytes = i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, total_nbytes) : total_nbytes;
2807                     i->thread_info.rewrite_flush = true;
2808                     pa_sink_input_process_rewind(i, sink_nbytes);
2809                 }
2810             }
2811
2812             pa_sink_input_detach(i);
2813
2814             /* Let's remove the sink input ...*/
2815             pa_hashmap_remove_and_free(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
2816
2817             pa_sink_invalidate_requested_latency(s, true);
2818
2819             pa_log_debug("Requesting rewind due to started move");
2820             pa_sink_request_rewind(s, (size_t) -1);
2821
2822             /* In flat volume mode we need to update the volume as
2823              * well */
2824             return o->process_msg(o, PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL);
2825         }
2826
2827         case PA_SINK_MESSAGE_FINISH_MOVE: {
2828             pa_sink_input *i = PA_SINK_INPUT(userdata);
2829
2830             /* We don't support moving synchronized streams. */
2831             pa_assert(!i->sync_prev);
2832             pa_assert(!i->sync_next);
2833             pa_assert(!i->thread_info.sync_next);
2834             pa_assert(!i->thread_info.sync_prev);
2835
2836             pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
2837
2838             pa_sink_input_attach(i);
2839
2840             if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
2841                 pa_usec_t usec = 0;
2842                 size_t nbytes;
2843
2844                 /* In the ideal case the new sink would start playing
2845                  * the stream immediately. That requires the sink to
2846                  * be able to rewind all of its latency, which usually
2847                  * isn't possible, so there will probably be some gap
2848                  * before the moved stream becomes audible. We then
2849                  * have two possibilities: 1) start playing the stream
2850                  * from where it is now, or 2) drop the unrewindable
2851                  * latency of the sink from the stream. With option 1
2852                  * we won't lose any audio but the stream will have a
2853                  * pause. With option 2 we may lose some audio but the
2854                  * stream time will be somewhat in sync with the wall
2855                  * clock. Lennart seems to have chosen option 2 (one
2856                  * of the reasons might have been that option 1 is
2857                  * actually much harder to implement), so we drop the
2858                  * latency of the new sink from the moved stream and
2859                  * hope that the sink will undo most of that in the
2860                  * rewind. */
2861
2862                 /* Get the latency of the sink */
2863                 usec = pa_sink_get_latency_within_thread(s, false);
2864                 nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
2865
2866                 if (nbytes > 0)
2867                     pa_sink_input_drop(i, nbytes);
2868
2869                 pa_log_debug("Requesting rewind due to finished move");
2870                 pa_sink_request_rewind(s, nbytes);
2871             }
2872
2873             /* Updating the requested sink latency has to be done
2874              * after the sink rewind request, not before, because
2875              * otherwise the sink may limit the rewind amount
2876              * needlessly. */
2877
2878             if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
2879                 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
2880
2881             pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
2882             pa_sink_input_update_max_request(i, s->thread_info.max_request);
2883
2884             return o->process_msg(o, PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL);
2885         }
2886
2887         case PA_SINK_MESSAGE_SET_SHARED_VOLUME: {
2888             pa_sink *root_sink = pa_sink_get_master(s);
2889
2890             if (PA_LIKELY(root_sink))
2891                 set_shared_volume_within_thread(root_sink);
2892
2893             return 0;
2894         }
2895
2896         case PA_SINK_MESSAGE_SET_VOLUME_SYNCED:
2897
2898             if (s->flags & PA_SINK_DEFERRED_VOLUME) {
2899                 s->set_volume(s);
2900                 pa_sink_volume_change_push(s);
2901             }
2902             /* Fall through ... */
2903
2904         case PA_SINK_MESSAGE_SET_VOLUME:
2905
2906             if (!pa_cvolume_equal(&s->thread_info.soft_volume, &s->soft_volume)) {
2907                 s->thread_info.soft_volume = s->soft_volume;
2908                 pa_sink_request_rewind(s, (size_t) -1);
2909             }
2910
2911             /* Fall through ... */
2912
2913         case PA_SINK_MESSAGE_SYNC_VOLUMES:
2914             sync_input_volumes_within_thread(s);
2915             return 0;
2916
2917         case PA_SINK_MESSAGE_GET_VOLUME:
2918
2919             if ((s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_volume) {
2920                 s->get_volume(s);
2921                 pa_sink_volume_change_flush(s);
2922                 pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
2923             }
2924
2925             /* In case sink implementor reset SW volume. */
2926             if (!pa_cvolume_equal(&s->thread_info.soft_volume, &s->soft_volume)) {
2927                 s->thread_info.soft_volume = s->soft_volume;
2928                 pa_sink_request_rewind(s, (size_t) -1);
2929             }
2930
2931             return 0;
2932
2933         case PA_SINK_MESSAGE_SET_MUTE:
2934
2935             if (s->thread_info.soft_muted != s->muted) {
2936                 s->thread_info.soft_muted = s->muted;
2937                 pa_sink_request_rewind(s, (size_t) -1);
2938             }
2939
2940             if (s->flags & PA_SINK_DEFERRED_VOLUME && s->set_mute)
2941                 s->set_mute(s);
2942
2943             return 0;
2944
2945         case PA_SINK_MESSAGE_GET_MUTE:
2946
2947             if (s->flags & PA_SINK_DEFERRED_VOLUME && s->get_mute)
2948                 return s->get_mute(s, userdata);
2949
2950             return 0;
2951
2952         case PA_SINK_MESSAGE_SET_STATE: {
2953
2954             bool suspend_change =
2955                 (s->thread_info.state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(PA_PTR_TO_UINT(userdata))) ||
2956                 (PA_SINK_IS_OPENED(s->thread_info.state) && PA_PTR_TO_UINT(userdata) == PA_SINK_SUSPENDED);
2957
2958             s->thread_info.state = PA_PTR_TO_UINT(userdata);
2959
2960             if (s->thread_info.state == PA_SINK_SUSPENDED) {
2961                 s->thread_info.rewind_nbytes = 0;
2962                 s->thread_info.rewind_requested = false;
2963             }
2964
2965             if (suspend_change) {
2966                 pa_sink_input *i;
2967                 void *state = NULL;
2968
2969                 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
2970                     if (i->suspend_within_thread)
2971                         i->suspend_within_thread(i, s->thread_info.state == PA_SINK_SUSPENDED);
2972             }
2973
2974             return 0;
2975         }
2976
2977         case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: {
2978
2979             pa_usec_t *usec = userdata;
2980             *usec = pa_sink_get_requested_latency_within_thread(s);
2981
2982             /* Yes, that's right, the IO thread will see -1 when no
2983              * explicit requested latency is configured, the main
2984              * thread will see max_latency */
2985             if (*usec == (pa_usec_t) -1)
2986                 *usec = s->thread_info.max_latency;
2987
2988             return 0;
2989         }
2990
2991         case PA_SINK_MESSAGE_SET_LATENCY_RANGE: {
2992             pa_usec_t *r = userdata;
2993
2994             pa_sink_set_latency_range_within_thread(s, r[0], r[1]);
2995
2996             return 0;
2997         }
2998
2999         case PA_SINK_MESSAGE_GET_LATENCY_RANGE: {
3000             pa_usec_t *r = userdata;
3001
3002             r[0] = s->thread_info.min_latency;
3003             r[1] = s->thread_info.max_latency;
3004
3005             return 0;
3006         }
3007
3008         case PA_SINK_MESSAGE_GET_FIXED_LATENCY:
3009
3010             *((pa_usec_t*) userdata) = s->thread_info.fixed_latency;
3011             return 0;
3012
3013         case PA_SINK_MESSAGE_SET_FIXED_LATENCY:
3014
3015             pa_sink_set_fixed_latency_within_thread(s, (pa_usec_t) offset);
3016             return 0;
3017
3018         case PA_SINK_MESSAGE_GET_MAX_REWIND:
3019
3020             *((size_t*) userdata) = s->thread_info.max_rewind;
3021             return 0;
3022
3023         case PA_SINK_MESSAGE_GET_MAX_REQUEST:
3024
3025             *((size_t*) userdata) = s->thread_info.max_request;
3026             return 0;
3027
3028         case PA_SINK_MESSAGE_SET_MAX_REWIND:
3029
3030             pa_sink_set_max_rewind_within_thread(s, (size_t) offset);
3031             return 0;
3032
3033         case PA_SINK_MESSAGE_SET_MAX_REQUEST:
3034
3035             pa_sink_set_max_request_within_thread(s, (size_t) offset);
3036             return 0;
3037
3038         case PA_SINK_MESSAGE_SET_PORT:
3039
3040             pa_assert(userdata);
3041             if (s->set_port) {
3042                 struct sink_message_set_port *msg_data = userdata;
3043                 msg_data->ret = s->set_port(s, msg_data->port);
3044             }
3045             return 0;
3046
3047         case PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE:
3048             /* This message is sent from IO-thread and handled in main thread. */
3049             pa_assert_ctl_context();
3050
3051             /* Make sure we're not messing with main thread when no longer linked */
3052             if (!PA_SINK_IS_LINKED(s->state))
3053                 return 0;
3054
3055             pa_sink_get_volume(s, true);
3056             pa_sink_get_mute(s, true);
3057             return 0;
3058
3059         case PA_SINK_MESSAGE_SET_PORT_LATENCY_OFFSET:
3060             s->thread_info.port_latency_offset = offset;
3061             return 0;
3062
3063         case PA_SINK_MESSAGE_GET_LATENCY:
3064         case PA_SINK_MESSAGE_MAX:
3065             ;
3066     }
3067
3068     return -1;
3069 }
3070
3071 /* Called from main thread */
3072 int pa_sink_suspend_all(pa_core *c, bool suspend, pa_suspend_cause_t cause) {
3073     pa_sink *sink;
3074     uint32_t idx;
3075     int ret = 0;
3076
3077     pa_core_assert_ref(c);
3078     pa_assert_ctl_context();
3079     pa_assert(cause != 0);
3080
3081     PA_IDXSET_FOREACH(sink, c->sinks, idx) {
3082         int r;
3083
3084         if ((r = pa_sink_suspend(sink, suspend, cause)) < 0)
3085             ret = r;
3086     }
3087
3088     return ret;
3089 }
3090
3091 /* Called from IO thread */
3092 void pa_sink_detach_within_thread(pa_sink *s) {
3093     pa_sink_input *i;
3094     void *state = NULL;
3095
3096     pa_sink_assert_ref(s);
3097     pa_sink_assert_io_context(s);
3098     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
3099
3100     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3101         pa_sink_input_detach(i);
3102
3103     if (s->monitor_source)
3104         pa_source_detach_within_thread(s->monitor_source);
3105 }
3106
3107 /* Called from IO thread */
3108 void pa_sink_attach_within_thread(pa_sink *s) {
3109     pa_sink_input *i;
3110     void *state = NULL;
3111
3112     pa_sink_assert_ref(s);
3113     pa_sink_assert_io_context(s);
3114     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
3115
3116     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3117         pa_sink_input_attach(i);
3118
3119     if (s->monitor_source)
3120         pa_source_attach_within_thread(s->monitor_source);
3121 }
3122
3123 /* Called from IO thread */
3124 void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
3125     pa_sink_assert_ref(s);
3126     pa_sink_assert_io_context(s);
3127     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
3128
3129     if (nbytes == (size_t) -1)
3130         nbytes = s->thread_info.max_rewind;
3131
3132     nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
3133
3134     if (s->thread_info.rewind_requested &&
3135         nbytes <= s->thread_info.rewind_nbytes)
3136         return;
3137
3138     s->thread_info.rewind_nbytes = nbytes;
3139     s->thread_info.rewind_requested = true;
3140
3141     if (s->request_rewind)
3142         s->request_rewind(s);
3143 }
3144
3145 /* Called from IO thread */
3146 pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
3147     pa_usec_t result = (pa_usec_t) -1;
3148     pa_sink_input *i;
3149     void *state = NULL;
3150     pa_usec_t monitor_latency;
3151
3152     pa_sink_assert_ref(s);
3153     pa_sink_assert_io_context(s);
3154
3155     if (!(s->flags & PA_SINK_DYNAMIC_LATENCY))
3156         return PA_CLAMP(s->thread_info.fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
3157
3158     if (s->thread_info.requested_latency_valid)
3159         return s->thread_info.requested_latency;
3160
3161     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3162         if (i->thread_info.requested_sink_latency != (pa_usec_t) -1 &&
3163             (result == (pa_usec_t) -1 || result > i->thread_info.requested_sink_latency))
3164             result = i->thread_info.requested_sink_latency;
3165
3166     monitor_latency = pa_source_get_requested_latency_within_thread(s->monitor_source);
3167
3168     if (monitor_latency != (pa_usec_t) -1 &&
3169         (result == (pa_usec_t) -1 || result > monitor_latency))
3170         result = monitor_latency;
3171
3172     if (result != (pa_usec_t) -1)
3173         result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
3174
3175     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
3176         /* Only cache if properly initialized */
3177         s->thread_info.requested_latency = result;
3178         s->thread_info.requested_latency_valid = true;
3179     }
3180
3181     return result;
3182 }
3183
3184 /* Called from main thread */
3185 pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
3186     pa_usec_t usec = 0;
3187
3188     pa_sink_assert_ref(s);
3189     pa_assert_ctl_context();
3190     pa_assert(PA_SINK_IS_LINKED(s->state));
3191
3192     if (s->state == PA_SINK_SUSPENDED)
3193         return 0;
3194
3195     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
3196
3197     return usec;
3198 }
3199
3200 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
3201 void pa_sink_set_max_rewind_within_thread(pa_sink *s, size_t max_rewind) {
3202     pa_sink_input *i;
3203     void *state = NULL;
3204
3205     pa_sink_assert_ref(s);
3206     pa_sink_assert_io_context(s);
3207
3208     if (max_rewind == s->thread_info.max_rewind)
3209         return;
3210
3211     s->thread_info.max_rewind = max_rewind;
3212
3213     if (PA_SINK_IS_LINKED(s->thread_info.state))
3214         PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3215             pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
3216
3217     if (s->monitor_source)
3218         pa_source_set_max_rewind_within_thread(s->monitor_source, s->thread_info.max_rewind);
3219 }
3220
3221 /* Called from main thread */
3222 void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
3223     pa_sink_assert_ref(s);
3224     pa_assert_ctl_context();
3225
3226     if (PA_SINK_IS_LINKED(s->state))
3227         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
3228     else
3229         pa_sink_set_max_rewind_within_thread(s, max_rewind);
3230 }
3231
3232 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
3233 void pa_sink_set_max_request_within_thread(pa_sink *s, size_t max_request) {
3234     void *state = NULL;
3235
3236     pa_sink_assert_ref(s);
3237     pa_sink_assert_io_context(s);
3238
3239     if (max_request == s->thread_info.max_request)
3240         return;
3241
3242     s->thread_info.max_request = max_request;
3243
3244     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
3245         pa_sink_input *i;
3246
3247         PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3248             pa_sink_input_update_max_request(i, s->thread_info.max_request);
3249     }
3250 }
3251
3252 /* Called from main thread */
3253 void pa_sink_set_max_request(pa_sink *s, size_t max_request) {
3254     pa_sink_assert_ref(s);
3255     pa_assert_ctl_context();
3256
3257     if (PA_SINK_IS_LINKED(s->state))
3258         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MAX_REQUEST, NULL, max_request, NULL) == 0);
3259     else
3260         pa_sink_set_max_request_within_thread(s, max_request);
3261 }
3262
3263 /* Called from IO thread */
3264 void pa_sink_invalidate_requested_latency(pa_sink *s, bool dynamic) {
3265     pa_sink_input *i;
3266     void *state = NULL;
3267
3268     pa_sink_assert_ref(s);
3269     pa_sink_assert_io_context(s);
3270
3271     if ((s->flags & PA_SINK_DYNAMIC_LATENCY))
3272         s->thread_info.requested_latency_valid = false;
3273     else if (dynamic)
3274         return;
3275
3276     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
3277
3278         if (s->update_requested_latency)
3279             s->update_requested_latency(s);
3280
3281         PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3282             if (i->update_sink_requested_latency)
3283                 i->update_sink_requested_latency(i);
3284     }
3285 }
3286
3287 /* Called from main thread */
3288 void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
3289     pa_sink_assert_ref(s);
3290     pa_assert_ctl_context();
3291
3292     /* min_latency == 0:           no limit
3293      * min_latency anything else:  specified limit
3294      *
3295      * Similar for max_latency */
3296
3297     if (min_latency < ABSOLUTE_MIN_LATENCY)
3298         min_latency = ABSOLUTE_MIN_LATENCY;
3299
3300     if (max_latency <= 0 ||
3301         max_latency > ABSOLUTE_MAX_LATENCY)
3302         max_latency = ABSOLUTE_MAX_LATENCY;
3303
3304     pa_assert(min_latency <= max_latency);
3305
3306     /* Hmm, let's see if someone forgot to set PA_SINK_DYNAMIC_LATENCY here... */
3307     pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
3308                max_latency == ABSOLUTE_MAX_LATENCY) ||
3309               (s->flags & PA_SINK_DYNAMIC_LATENCY));
3310
3311     if (PA_SINK_IS_LINKED(s->state)) {
3312         pa_usec_t r[2];
3313
3314         r[0] = min_latency;
3315         r[1] = max_latency;
3316
3317         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
3318     } else
3319         pa_sink_set_latency_range_within_thread(s, min_latency, max_latency);
3320 }
3321
3322 /* Called from main thread */
3323 void pa_sink_get_latency_range(pa_sink *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
3324     pa_sink_assert_ref(s);
3325     pa_assert_ctl_context();
3326     pa_assert(min_latency);
3327     pa_assert(max_latency);
3328
3329     if (PA_SINK_IS_LINKED(s->state)) {
3330         pa_usec_t r[2] = { 0, 0 };
3331
3332         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
3333
3334         *min_latency = r[0];
3335         *max_latency = r[1];
3336     } else {
3337         *min_latency = s->thread_info.min_latency;
3338         *max_latency = s->thread_info.max_latency;
3339     }
3340 }
3341
3342 /* Called from IO thread */
3343 void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
3344     pa_sink_assert_ref(s);
3345     pa_sink_assert_io_context(s);
3346
3347     pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
3348     pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
3349     pa_assert(min_latency <= max_latency);
3350
3351     /* Hmm, let's see if someone forgot to set PA_SINK_DYNAMIC_LATENCY here... */
3352     pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
3353                max_latency == ABSOLUTE_MAX_LATENCY) ||
3354               (s->flags & PA_SINK_DYNAMIC_LATENCY));
3355
3356     if (s->thread_info.min_latency == min_latency &&
3357         s->thread_info.max_latency == max_latency)
3358         return;
3359
3360     s->thread_info.min_latency = min_latency;
3361     s->thread_info.max_latency = max_latency;
3362
3363     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
3364         pa_sink_input *i;
3365         void *state = NULL;
3366
3367         PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3368             if (i->update_sink_latency_range)
3369                 i->update_sink_latency_range(i);
3370     }
3371
3372     pa_sink_invalidate_requested_latency(s, false);
3373
3374     pa_source_set_latency_range_within_thread(s->monitor_source, min_latency, max_latency);
3375 }
3376
3377 /* Called from main thread */
3378 void pa_sink_set_fixed_latency(pa_sink *s, pa_usec_t latency) {
3379     pa_sink_assert_ref(s);
3380     pa_assert_ctl_context();
3381
3382     if (s->flags & PA_SINK_DYNAMIC_LATENCY) {
3383         pa_assert(latency == 0);
3384         return;
3385     }
3386
3387     if (latency < ABSOLUTE_MIN_LATENCY)
3388         latency = ABSOLUTE_MIN_LATENCY;
3389
3390     if (latency > ABSOLUTE_MAX_LATENCY)
3391         latency = ABSOLUTE_MAX_LATENCY;
3392
3393     if (PA_SINK_IS_LINKED(s->state))
3394         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_FIXED_LATENCY, NULL, (int64_t) latency, NULL) == 0);
3395     else
3396         s->thread_info.fixed_latency = latency;
3397
3398     pa_source_set_fixed_latency(s->monitor_source, latency);
3399 }
3400
3401 /* Called from main thread */
3402 pa_usec_t pa_sink_get_fixed_latency(pa_sink *s) {
3403     pa_usec_t latency;
3404
3405     pa_sink_assert_ref(s);
3406     pa_assert_ctl_context();
3407
3408     if (s->flags & PA_SINK_DYNAMIC_LATENCY)
3409         return 0;
3410
3411     if (PA_SINK_IS_LINKED(s->state))
3412         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_FIXED_LATENCY, &latency, 0, NULL) == 0);
3413     else
3414         latency = s->thread_info.fixed_latency;
3415
3416     return latency;
3417 }
3418
3419 /* Called from IO thread */
3420 void pa_sink_set_fixed_latency_within_thread(pa_sink *s, pa_usec_t latency) {
3421     pa_sink_assert_ref(s);
3422     pa_sink_assert_io_context(s);
3423
3424     if (s->flags & PA_SINK_DYNAMIC_LATENCY) {
3425         pa_assert(latency == 0);
3426         s->thread_info.fixed_latency = 0;
3427
3428         if (s->monitor_source)
3429             pa_source_set_fixed_latency_within_thread(s->monitor_source, 0);
3430
3431         return;
3432     }
3433
3434     pa_assert(latency >= ABSOLUTE_MIN_LATENCY);
3435     pa_assert(latency <= ABSOLUTE_MAX_LATENCY);
3436
3437     if (s->thread_info.fixed_latency == latency)
3438         return;
3439
3440     s->thread_info.fixed_latency = latency;
3441
3442     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
3443         pa_sink_input *i;
3444         void *state = NULL;
3445
3446         PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
3447             if (i->update_sink_fixed_latency)
3448                 i->update_sink_fixed_latency(i);
3449     }
3450
3451     pa_sink_invalidate_requested_latency(s, false);
3452
3453     pa_source_set_fixed_latency_within_thread(s->monitor_source, latency);
3454 }
3455
3456 /* Called from main context */
3457 void pa_sink_set_port_latency_offset(pa_sink *s, int64_t offset) {
3458     pa_sink_assert_ref(s);
3459
3460     s->port_latency_offset = offset;
3461
3462     if (PA_SINK_IS_LINKED(s->state))
3463         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT_LATENCY_OFFSET, NULL, offset, NULL) == 0);
3464     else
3465         s->thread_info.port_latency_offset = offset;
3466
3467     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PORT_LATENCY_OFFSET_CHANGED], s);
3468 }
3469
3470 /* Called from main context */
3471 size_t pa_sink_get_max_rewind(pa_sink *s) {
3472     size_t r;
3473     pa_assert_ctl_context();
3474     pa_sink_assert_ref(s);
3475
3476     if (!PA_SINK_IS_LINKED(s->state))
3477         return s->thread_info.max_rewind;
3478
3479     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
3480
3481     return r;
3482 }
3483
3484 /* Called from main context */
3485 size_t pa_sink_get_max_request(pa_sink *s) {
3486     size_t r;
3487     pa_sink_assert_ref(s);
3488     pa_assert_ctl_context();
3489
3490     if (!PA_SINK_IS_LINKED(s->state))
3491         return s->thread_info.max_request;
3492
3493     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REQUEST, &r, 0, NULL) == 0);
3494
3495     return r;
3496 }
3497
3498 /* Called from main context */
3499 int pa_sink_set_port(pa_sink *s, const char *name, bool save) {
3500     pa_device_port *port;
3501     int ret;
3502
3503     pa_sink_assert_ref(s);
3504     pa_assert_ctl_context();
3505
3506     if (!s->set_port) {
3507         pa_log_debug("set_port() operation not implemented for sink %u \"%s\"", s->index, s->name);
3508         return -PA_ERR_NOTIMPLEMENTED;
3509     }
3510
3511     if (!name)
3512         return -PA_ERR_NOENTITY;
3513
3514     if (!(port = pa_hashmap_get(s->ports, name)))
3515         return -PA_ERR_NOENTITY;
3516
3517     if (s->active_port == port) {
3518         s->save_port = s->save_port || save;
3519         return 0;
3520     }
3521
3522     if (s->flags & PA_SINK_DEFERRED_VOLUME) {
3523         struct sink_message_set_port msg = { .port = port, .ret = 0 };
3524         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT, &msg, 0, NULL) == 0);
3525         ret = msg.ret;
3526     }
3527     else
3528         ret = s->set_port(s, port);
3529
3530     if (ret < 0)
3531         return -PA_ERR_NOENTITY;
3532
3533     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
3534
3535     pa_log_info("Changed port of sink %u \"%s\" to %s", s->index, s->name, port->name);
3536
3537     s->active_port = port;
3538     s->save_port = save;
3539
3540     pa_sink_set_port_latency_offset(s, s->active_port->latency_offset);
3541
3542     /* The active port affects the default sink selection. */
3543     pa_core_update_default_sink(s->core);
3544
3545     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], s);
3546
3547     return 0;
3548 }
3549
3550 bool pa_device_init_icon(pa_proplist *p, bool is_sink) {
3551     const char *ff, *c, *t = NULL, *s = "", *profile, *bus;
3552
3553     pa_assert(p);
3554
3555     if (pa_proplist_contains(p, PA_PROP_DEVICE_ICON_NAME))
3556         return true;
3557
3558     if ((ff = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) {
3559
3560         if (pa_streq(ff, "microphone"))
3561             t = "audio-input-microphone";
3562         else if (pa_streq(ff, "webcam"))
3563             t = "camera-web";
3564         else if (pa_streq(ff, "computer"))
3565             t = "computer";
3566         else if (pa_streq(ff, "handset"))
3567             t = "phone";
3568         else if (pa_streq(ff, "portable"))
3569             t = "multimedia-player";
3570         else if (pa_streq(ff, "tv"))
3571             t = "video-display";
3572
3573         /*
3574          * The following icons are not part of the icon naming spec,
3575          * because Rodney Dawes sucks as the maintainer of that spec.
3576          *
3577          * http://lists.freedesktop.org/archives/xdg/2009-May/010397.html
3578          */
3579         else if (pa_streq(ff, "headset"))
3580             t = "audio-headset";
3581         else if (pa_streq(ff, "headphone"))
3582             t = "audio-headphones";
3583         else if (pa_streq(ff, "speaker"))
3584             t = "audio-speakers";
3585         else if (pa_streq(ff, "hands-free"))
3586             t = "audio-handsfree";
3587     }
3588
3589     if (!t)
3590         if ((c = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
3591             if (pa_streq(c, "modem"))
3592                 t = "modem";
3593
3594     if (!t) {
3595         if (is_sink)
3596             t = "audio-card";
3597         else
3598             t = "audio-input-microphone";
3599     }
3600
3601     if ((profile = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
3602         if (strstr(profile, "analog"))
3603             s = "-analog";
3604         else if (strstr(profile, "iec958"))
3605             s = "-iec958";
3606         else if (strstr(profile, "hdmi"))
3607             s = "-hdmi";
3608     }
3609
3610     bus = pa_proplist_gets(p, PA_PROP_DEVICE_BUS);
3611
3612     pa_proplist_setf(p, PA_PROP_DEVICE_ICON_NAME, "%s%s%s%s", t, pa_strempty(s), bus ? "-" : "", pa_strempty(bus));
3613
3614     return true;
3615 }
3616
3617 bool pa_device_init_description(pa_proplist *p, pa_card *card) {
3618     const char *s, *d = NULL, *k;
3619     pa_assert(p);
3620
3621     if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
3622         return true;
3623
3624     if (card)
3625         if ((s = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_DESCRIPTION)))
3626             d = s;
3627
3628     if (!d)
3629         if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
3630             if (pa_streq(s, "internal"))
3631                 d = _("Built-in Audio");
3632
3633     if (!d)
3634         if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
3635             if (pa_streq(s, "modem"))
3636                 d = _("Modem");
3637
3638     if (!d)
3639         d = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME);
3640
3641     if (!d)
3642         return false;
3643
3644     k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
3645
3646     if (d && k)
3647         pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s %s", d, k);
3648     else if (d)
3649         pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
3650
3651     return true;
3652 }
3653
3654 bool pa_device_init_intended_roles(pa_proplist *p) {
3655     const char *s;
3656     pa_assert(p);
3657
3658     if (pa_proplist_contains(p, PA_PROP_DEVICE_INTENDED_ROLES))
3659         return true;
3660
3661     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
3662         if (pa_streq(s, "handset") || pa_streq(s, "hands-free")
3663             || pa_streq(s, "headset")) {
3664             pa_proplist_sets(p, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
3665             return true;
3666         }
3667
3668     return false;
3669 }
3670
3671 unsigned pa_device_init_priority(pa_proplist *p) {
3672     const char *s;
3673     unsigned priority = 0;
3674
3675     pa_assert(p);
3676
3677     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS))) {
3678
3679         if (pa_streq(s, "sound"))
3680             priority += 9000;
3681         else if (!pa_streq(s, "modem"))
3682             priority += 1000;
3683     }
3684
3685     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) {
3686
3687         if (pa_streq(s, "headphone"))
3688             priority += 900;
3689         else if (pa_streq(s, "hifi"))
3690             priority += 600;
3691         else if (pa_streq(s, "speaker"))
3692             priority += 500;
3693         else if (pa_streq(s, "portable"))
3694             priority += 450;
3695     }
3696
3697     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_BUS))) {
3698
3699         if (pa_streq(s, "bluetooth"))
3700             priority += 50;
3701         else if (pa_streq(s, "usb"))
3702             priority += 40;
3703         else if (pa_streq(s, "pci"))
3704             priority += 30;
3705     }
3706
3707     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
3708
3709         if (pa_startswith(s, "analog-"))
3710             priority += 9;
3711         else if (pa_startswith(s, "iec958-"))
3712             priority += 8;
3713     }
3714
3715     return priority;
3716 }
3717
3718 PA_STATIC_FLIST_DECLARE(pa_sink_volume_change, 0, pa_xfree);
3719
3720 /* Called from the IO thread. */
3721 static pa_sink_volume_change *pa_sink_volume_change_new(pa_sink *s) {
3722     pa_sink_volume_change *c;
3723     if (!(c = pa_flist_pop(PA_STATIC_FLIST_GET(pa_sink_volume_change))))
3724         c = pa_xnew(pa_sink_volume_change, 1);
3725
3726     PA_LLIST_INIT(pa_sink_volume_change, c);
3727     c->at = 0;
3728     pa_cvolume_reset(&c->hw_volume, s->sample_spec.channels);
3729     return c;
3730 }
3731
3732 /* Called from the IO thread. */
3733 static void pa_sink_volume_change_free(pa_sink_volume_change *c) {
3734     pa_assert(c);
3735     if (pa_flist_push(PA_STATIC_FLIST_GET(pa_sink_volume_change), c) < 0)
3736         pa_xfree(c);
3737 }
3738
3739 /* Called from the IO thread. */
3740 void pa_sink_volume_change_push(pa_sink *s) {
3741     pa_sink_volume_change *c = NULL;
3742     pa_sink_volume_change *nc = NULL;
3743     pa_sink_volume_change *pc = NULL;
3744     uint32_t safety_margin = s->thread_info.volume_change_safety_margin;
3745
3746     const char *direction = NULL;
3747
3748     pa_assert(s);
3749     nc = pa_sink_volume_change_new(s);
3750
3751     /* NOTE: There is already more different volumes in pa_sink that I can remember.
3752      *       Adding one more volume for HW would get us rid of this, but I am trying
3753      *       to survive with the ones we already have. */
3754     pa_sw_cvolume_divide(&nc->hw_volume, &s->real_volume, &s->soft_volume);
3755
3756     if (!s->thread_info.volume_changes && pa_cvolume_equal(&nc->hw_volume, &s->thread_info.current_hw_volume)) {
3757         pa_log_debug("Volume not changing");
3758         pa_sink_volume_change_free(nc);
3759         return;
3760     }
3761
3762     nc->at = pa_sink_get_latency_within_thread(s, false);
3763     nc->at += pa_rtclock_now() + s->thread_info.volume_change_extra_delay;
3764
3765     if (s->thread_info.volume_changes_tail) {
3766         for (c = s->thread_info.volume_changes_tail; c; c = c->prev) {
3767             /* If volume is going up let's do it a bit late. If it is going
3768              * down let's do it a bit early. */
3769             if (pa_cvolume_avg(&nc->hw_volume) > pa_cvolume_avg(&c->hw_volume)) {
3770                 if (nc->at + safety_margin > c->at) {
3771                     nc->at += safety_margin;
3772                     direction = "up";
3773                     break;
3774                 }
3775             }
3776             else if (nc->at - safety_margin > c->at) {
3777                     nc->at -= safety_margin;
3778                     direction = "down";
3779                     break;
3780             }
3781         }
3782     }
3783
3784     if (c == NULL) {
3785         if (pa_cvolume_avg(&nc->hw_volume) > pa_cvolume_avg(&s->thread_info.current_hw_volume)) {
3786             nc->at += safety_margin;
3787             direction = "up";
3788         } else {
3789             nc->at -= safety_margin;
3790             direction = "down";
3791         }
3792         PA_LLIST_PREPEND(pa_sink_volume_change, s->thread_info.volume_changes, nc);
3793     }
3794     else {
3795         PA_LLIST_INSERT_AFTER(pa_sink_volume_change, s->thread_info.volume_changes, c, nc);
3796     }
3797
3798     pa_log_debug("Volume going %s to %d at %llu", direction, pa_cvolume_avg(&nc->hw_volume), (long long unsigned) nc->at);
3799
3800     /* We can ignore volume events that came earlier but should happen later than this. */
3801     PA_LLIST_FOREACH_SAFE(c, pc, nc->next) {
3802         pa_log_debug("Volume change to %d at %llu was dropped", pa_cvolume_avg(&c->hw_volume), (long long unsigned) c->at);
3803         pa_sink_volume_change_free(c);
3804     }
3805     nc->next = NULL;
3806     s->thread_info.volume_changes_tail = nc;
3807 }
3808
3809 /* Called from the IO thread. */
3810 static void pa_sink_volume_change_flush(pa_sink *s) {
3811     pa_sink_volume_change *c = s->thread_info.volume_changes;
3812     pa_assert(s);
3813     s->thread_info.volume_changes = NULL;
3814     s->thread_info.volume_changes_tail = NULL;
3815     while (c) {
3816         pa_sink_volume_change *next = c->next;
3817         pa_sink_volume_change_free(c);
3818         c = next;
3819     }
3820 }
3821
3822 /* Called from the IO thread. */
3823 bool pa_sink_volume_change_apply(pa_sink *s, pa_usec_t *usec_to_next) {
3824     pa_usec_t now;
3825     bool ret = false;
3826
3827     pa_assert(s);
3828
3829     if (!s->thread_info.volume_changes || !PA_SINK_IS_LINKED(s->state)) {
3830         if (usec_to_next)
3831             *usec_to_next = 0;
3832         return ret;
3833     }
3834
3835     pa_assert(s->write_volume);
3836
3837     now = pa_rtclock_now();
3838
3839     while (s->thread_info.volume_changes && now >= s->thread_info.volume_changes->at) {
3840         pa_sink_volume_change *c = s->thread_info.volume_changes;
3841         PA_LLIST_REMOVE(pa_sink_volume_change, s->thread_info.volume_changes, c);
3842         pa_log_debug("Volume change to %d at %llu was written %llu usec late",
3843                      pa_cvolume_avg(&c->hw_volume), (long long unsigned) c->at, (long long unsigned) (now - c->at));
3844         ret = true;
3845         s->thread_info.current_hw_volume = c->hw_volume;
3846         pa_sink_volume_change_free(c);
3847     }
3848
3849     if (ret)
3850         s->write_volume(s);
3851
3852     if (s->thread_info.volume_changes) {
3853         if (usec_to_next)
3854             *usec_to_next = s->thread_info.volume_changes->at - now;
3855         if (pa_log_ratelimit(PA_LOG_DEBUG))
3856             pa_log_debug("Next volume change in %lld usec", (long long) (s->thread_info.volume_changes->at - now));
3857     }
3858     else {
3859         if (usec_to_next)
3860             *usec_to_next = 0;
3861         s->thread_info.volume_changes_tail = NULL;
3862     }
3863     return ret;
3864 }
3865
3866 /* Called from the IO thread. */
3867 static void pa_sink_volume_change_rewind(pa_sink *s, size_t nbytes) {
3868     /* All the queued volume events later than current latency are shifted to happen earlier. */
3869     pa_sink_volume_change *c;
3870     pa_volume_t prev_vol = pa_cvolume_avg(&s->thread_info.current_hw_volume);
3871     pa_usec_t rewound = pa_bytes_to_usec(nbytes, &s->sample_spec);
3872     pa_usec_t limit = pa_sink_get_latency_within_thread(s, false);
3873
3874     pa_log_debug("latency = %lld", (long long) limit);
3875     limit += pa_rtclock_now() + s->thread_info.volume_change_extra_delay;
3876
3877     PA_LLIST_FOREACH(c, s->thread_info.volume_changes) {
3878         pa_usec_t modified_limit = limit;
3879         if (prev_vol > pa_cvolume_avg(&c->hw_volume))
3880             modified_limit -= s->thread_info.volume_change_safety_margin;
3881         else
3882             modified_limit += s->thread_info.volume_change_safety_margin;
3883         if (c->at > modified_limit) {
3884             c->at -= rewound;
3885             if (c->at < modified_limit)
3886                 c->at = modified_limit;
3887         }
3888         prev_vol = pa_cvolume_avg(&c->hw_volume);
3889     }
3890     pa_sink_volume_change_apply(s, NULL);
3891 }
3892
3893 /* Called from the main thread */
3894 /* Gets the list of formats supported by the sink. The members and idxset must
3895  * be freed by the caller. */
3896 pa_idxset* pa_sink_get_formats(pa_sink *s) {
3897     pa_idxset *ret;
3898
3899     pa_assert(s);
3900
3901     if (s->get_formats) {
3902         /* Sink supports format query, all is good */
3903         ret = s->get_formats(s);
3904     } else {
3905         /* Sink doesn't support format query, so assume it does PCM */
3906         pa_format_info *f = pa_format_info_new();
3907         f->encoding = PA_ENCODING_PCM;
3908
3909         ret = pa_idxset_new(NULL, NULL);
3910         pa_idxset_put(ret, f, NULL);
3911     }
3912
3913     return ret;
3914 }
3915
3916 /* Called from the main thread */
3917 /* Allows an external source to set what formats a sink supports if the sink
3918  * permits this. The function makes a copy of the formats on success. */
3919 bool pa_sink_set_formats(pa_sink *s, pa_idxset *formats) {
3920     pa_assert(s);
3921     pa_assert(formats);
3922
3923     if (s->set_formats)
3924         /* Sink supports setting formats -- let's give it a shot */
3925         return s->set_formats(s, formats);
3926     else
3927         /* Sink doesn't support setting this -- bail out */
3928         return false;
3929 }
3930
3931 /* Called from the main thread */
3932 /* Checks if the sink can accept this format */
3933 bool pa_sink_check_format(pa_sink *s, pa_format_info *f) {
3934     pa_idxset *formats = NULL;
3935     bool ret = false;
3936
3937     pa_assert(s);
3938     pa_assert(f);
3939
3940     formats = pa_sink_get_formats(s);
3941
3942     if (formats) {
3943         pa_format_info *finfo_device;
3944         uint32_t i;
3945
3946         PA_IDXSET_FOREACH(finfo_device, formats, i) {
3947             if (pa_format_info_is_compatible(finfo_device, f)) {
3948                 ret = true;
3949                 break;
3950             }
3951         }
3952
3953         pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
3954     }
3955
3956     return ret;
3957 }
3958
3959 /* Called from the main thread */
3960 /* Calculates the intersection between formats supported by the sink and
3961  * in_formats, and returns these, in the order of the sink's formats. */
3962 pa_idxset* pa_sink_check_formats(pa_sink *s, pa_idxset *in_formats) {
3963     pa_idxset *out_formats = pa_idxset_new(NULL, NULL), *sink_formats = NULL;
3964     pa_format_info *f_sink, *f_in;
3965     uint32_t i, j;
3966
3967     pa_assert(s);
3968
3969     if (!in_formats || pa_idxset_isempty(in_formats))
3970         goto done;
3971
3972     sink_formats = pa_sink_get_formats(s);
3973
3974     PA_IDXSET_FOREACH(f_sink, sink_formats, i) {
3975         PA_IDXSET_FOREACH(f_in, in_formats, j) {
3976             if (pa_format_info_is_compatible(f_sink, f_in))
3977                 pa_idxset_put(out_formats, pa_format_info_copy(f_in), NULL);
3978         }
3979     }
3980
3981 done:
3982     if (sink_formats)
3983         pa_idxset_free(sink_formats, (pa_free_cb_t) pa_format_info_free);
3984
3985     return out_formats;
3986 }
3987
3988 /* Called from the main thread. */
3989 void pa_sink_set_reference_volume_direct(pa_sink *s, const pa_cvolume *volume) {
3990     pa_cvolume old_volume;
3991     char old_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
3992     char new_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
3993
3994     pa_assert(s);
3995     pa_assert(volume);
3996
3997     old_volume = s->reference_volume;
3998
3999     if (pa_cvolume_equal(volume, &old_volume))
4000         return;
4001
4002     s->reference_volume = *volume;
4003     pa_log_debug("The reference volume of sink %s changed from %s to %s.", s->name,
4004                  pa_cvolume_snprint_verbose(old_volume_str, sizeof(old_volume_str), &old_volume, &s->channel_map,
4005                                             s->flags & PA_SINK_DECIBEL_VOLUME),
4006                  pa_cvolume_snprint_verbose(new_volume_str, sizeof(new_volume_str), volume, &s->channel_map,
4007                                             s->flags & PA_SINK_DECIBEL_VOLUME));
4008
4009     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
4010     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], s);
4011 }