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