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