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