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