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