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