core: Added new hooks: PA_CORE_HOOK_SOURCE_PORT_CHANGED and PA_CORE_HOOK_SINK_PORT_CH...
[platform/upstream/pulseaudio.git] / 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 <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30
31 #include <pulse/introspect.h>
32 #include <pulse/utf8.h>
33 #include <pulse/xmalloc.h>
34 #include <pulse/timeval.h>
35 #include <pulse/util.h>
36 #include <pulse/i18n.h>
37 #include <pulse/rtclock.h>
38
39 #include <pulsecore/sink-input.h>
40 #include <pulsecore/namereg.h>
41 #include <pulsecore/core-util.h>
42 #include <pulsecore/sample-util.h>
43 #include <pulsecore/core-subscribe.h>
44 #include <pulsecore/log.h>
45 #include <pulsecore/macro.h>
46 #include <pulsecore/play-memblockq.h>
47 #include <pulsecore/flist.h>
48
49 #include "sink.h"
50
51 #define MAX_MIX_CHANNELS 32
52 #define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
53 #define ABSOLUTE_MIN_LATENCY (500)
54 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
55 #define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
56
57 PA_DEFINE_PUBLIC_CLASS(pa_sink, pa_msgobject);
58
59 struct pa_sink_volume_change {
60     pa_usec_t at;
61     pa_cvolume hw_volume;
62
63     PA_LLIST_FIELDS(pa_sink_volume_change);
64 };
65
66 struct sink_message_set_port {
67     pa_device_port *port;
68     int ret;
69 };
70
71 static void sink_free(pa_object *s);
72
73 static void pa_sink_volume_change_push(pa_sink *s);
74 static void pa_sink_volume_change_flush(pa_sink *s);
75 static void pa_sink_volume_change_rewind(pa_sink *s, size_t nbytes);
76
77 pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data) {
78     pa_assert(data);
79
80     pa_zero(*data);
81     data->proplist = pa_proplist_new();
82
83     return data;
84 }
85
86 void pa_sink_new_data_set_name(pa_sink_new_data *data, const char *name) {
87     pa_assert(data);
88
89     pa_xfree(data->name);
90     data->name = pa_xstrdup(name);
91 }
92
93 void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_spec *spec) {
94     pa_assert(data);
95
96     if ((data->sample_spec_is_set = !!spec))
97         data->sample_spec = *spec;
98 }
99
100 void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map) {
101     pa_assert(data);
102
103     if ((data->channel_map_is_set = !!map))
104         data->channel_map = *map;
105 }
106
107 void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume) {
108     pa_assert(data);
109
110     if ((data->volume_is_set = !!volume))
111         data->volume = *volume;
112 }
113
114 void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute) {
115     pa_assert(data);
116
117     data->muted_is_set = TRUE;
118     data->muted = !!mute;
119 }
120
121 void pa_sink_new_data_set_port(pa_sink_new_data *data, const char *port) {
122     pa_assert(data);
123
124     pa_xfree(data->active_port);
125     data->active_port = pa_xstrdup(port);
126 }
127
128 void pa_sink_new_data_done(pa_sink_new_data *data) {
129     pa_assert(data);
130
131     pa_proplist_free(data->proplist);
132
133     if (data->ports) {
134         pa_device_port *p;
135
136         while ((p = pa_hashmap_steal_first(data->ports)))
137             pa_device_port_free(p);
138
139         pa_hashmap_free(data->ports, NULL, NULL);
140     }
141
142     pa_xfree(data->name);
143     pa_xfree(data->active_port);
144 }
145
146 pa_device_port *pa_device_port_new(const char *name, const char *description, size_t extra) {
147     pa_device_port *p;
148
149     pa_assert(name);
150
151     p = pa_xmalloc(PA_ALIGN(sizeof(pa_device_port)) + extra);
152     p->name = pa_xstrdup(name);
153     p->description = pa_xstrdup(description);
154
155     p->priority = 0;
156
157     return p;
158 }
159
160 void pa_device_port_free(pa_device_port *p) {
161     pa_assert(p);
162
163     pa_xfree(p->name);
164     pa_xfree(p->description);
165     pa_xfree(p);
166 }
167
168 /* Called from main context */
169 static void reset_callbacks(pa_sink *s) {
170     pa_assert(s);
171
172     s->set_state = NULL;
173     s->get_volume = NULL;
174     s->set_volume = NULL;
175     s->get_mute = NULL;
176     s->set_mute = NULL;
177     s->request_rewind = NULL;
178     s->update_requested_latency = NULL;
179     s->set_port = NULL;
180 }
181
182 /* Called from main context */
183 pa_sink* pa_sink_new(
184         pa_core *core,
185         pa_sink_new_data *data,
186         pa_sink_flags_t flags) {
187
188     pa_sink *s;
189     const char *name;
190     char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
191     pa_source_new_data source_data;
192     const char *dn;
193     char *pt;
194
195     pa_assert(core);
196     pa_assert(data);
197     pa_assert(data->name);
198     pa_assert_ctl_context();
199
200     s = pa_msgobject_new(pa_sink);
201
202     if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) {
203         pa_log_debug("Failed to register name %s.", data->name);
204         pa_xfree(s);
205         return NULL;
206     }
207
208     pa_sink_new_data_set_name(data, name);
209
210     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW], data) < 0) {
211         pa_xfree(s);
212         pa_namereg_unregister(core, name);
213         return NULL;
214     }
215
216     /* FIXME, need to free s here on failure */
217
218     pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
219     pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
220
221     pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
222
223     if (!data->channel_map_is_set)
224         pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
225
226     pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
227     pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
228
229     if (!data->volume_is_set)
230         pa_cvolume_reset(&data->volume, data->sample_spec.channels);
231
232     pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
233     pa_return_null_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec));
234
235     if (!data->muted_is_set)
236         data->muted = FALSE;
237
238     if (data->card)
239         pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
240
241     pa_device_init_description(data->proplist);
242     pa_device_init_icon(data->proplist, TRUE);
243     pa_device_init_intended_roles(data->proplist);
244
245     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {
246         pa_xfree(s);
247         pa_namereg_unregister(core, name);
248         return NULL;
249     }
250
251     s->parent.parent.free = sink_free;
252     s->parent.process_msg = pa_sink_process_msg;
253
254     s->core = core;
255     s->state = PA_SINK_INIT;
256     s->flags = flags;
257     s->priority = 0;
258     s->suspend_cause = 0;
259     s->name = pa_xstrdup(name);
260     s->proplist = pa_proplist_copy(data->proplist);
261     s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
262     s->module = data->module;
263     s->card = data->card;
264
265     s->priority = pa_device_init_priority(s->proplist);
266
267     s->sample_spec = data->sample_spec;
268     s->channel_map = data->channel_map;
269
270     s->inputs = pa_idxset_new(NULL, NULL);
271     s->n_corked = 0;
272     s->input_to_master = NULL;
273
274     s->reference_volume = s->real_volume = data->volume;
275     pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
276     s->base_volume = PA_VOLUME_NORM;
277     s->n_volume_steps = PA_VOLUME_NORM+1;
278     s->muted = data->muted;
279     s->refresh_volume = s->refresh_muted = FALSE;
280
281     reset_callbacks(s);
282     s->userdata = NULL;
283
284     s->asyncmsgq = NULL;
285
286     /* As a minor optimization we just steal the list instead of
287      * copying it here */
288     s->ports = data->ports;
289     data->ports = NULL;
290
291     s->active_port = NULL;
292     s->save_port = FALSE;
293
294     if (data->active_port && s->ports)
295         if ((s->active_port = pa_hashmap_get(s->ports, data->active_port)))
296             s->save_port = data->save_port;
297
298     if (!s->active_port && s->ports) {
299         void *state;
300         pa_device_port *p;
301
302         PA_HASHMAP_FOREACH(p, s->ports, state)
303             if (!s->active_port || p->priority > s->active_port->priority)
304                 s->active_port = p;
305     }
306
307     s->save_volume = data->save_volume;
308     s->save_muted = data->save_muted;
309
310     pa_silence_memchunk_get(
311             &core->silence_cache,
312             core->mempool,
313             &s->silence,
314             &s->sample_spec,
315             0);
316
317     s->thread_info.rtpoll = NULL;
318     s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
319     s->thread_info.soft_volume =  s->soft_volume;
320     s->thread_info.soft_muted = s->muted;
321     s->thread_info.state = s->state;
322     s->thread_info.rewind_nbytes = 0;
323     s->thread_info.rewind_requested = FALSE;
324     s->thread_info.max_rewind = 0;
325     s->thread_info.max_request = 0;
326     s->thread_info.requested_latency_valid = FALSE;
327     s->thread_info.requested_latency = 0;
328     s->thread_info.min_latency = ABSOLUTE_MIN_LATENCY;
329     s->thread_info.max_latency = ABSOLUTE_MAX_LATENCY;
330     s->thread_info.fixed_latency = flags & PA_SINK_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
331
332     PA_LLIST_HEAD_INIT(pa_sink_volume_change, s->thread_info.volume_changes);
333     s->thread_info.volume_changes_tail = NULL;
334     pa_sw_cvolume_multiply(&s->thread_info.current_hw_volume, &s->soft_volume, &s->real_volume);
335     s->thread_info.volume_change_safety_margin = core->sync_volume_safety_margin_usec;
336     s->thread_info.volume_change_extra_delay = core->sync_volume_extra_delay_usec;
337
338     /* FIXME: This should probably be moved to pa_sink_put() */
339     pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
340
341     if (s->card)
342         pa_assert_se(pa_idxset_put(s->card->sinks, s, NULL) >= 0);
343
344     pt = pa_proplist_to_string_sep(s->proplist, "\n    ");
345     pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s\n    %s",
346                 s->index,
347                 s->name,
348                 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
349                 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
350                 pt);
351     pa_xfree(pt);
352
353     pa_source_new_data_init(&source_data);
354     pa_source_new_data_set_sample_spec(&source_data, &s->sample_spec);
355     pa_source_new_data_set_channel_map(&source_data, &s->channel_map);
356     source_data.name = pa_sprintf_malloc("%s.monitor", name);
357     source_data.driver = data->driver;
358     source_data.module = data->module;
359     source_data.card = data->card;
360
361     dn = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
362     pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
363     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
364
365     s->monitor_source = pa_source_new(core, &source_data,
366                                       ((flags & PA_SINK_LATENCY) ? PA_SOURCE_LATENCY : 0) |
367                                       ((flags & PA_SINK_DYNAMIC_LATENCY) ? PA_SOURCE_DYNAMIC_LATENCY : 0));
368
369     pa_source_new_data_done(&source_data);
370
371     if (!s->monitor_source) {
372         pa_sink_unlink(s);
373         pa_sink_unref(s);
374         return NULL;
375     }
376
377     s->monitor_source->monitor_of = s;
378
379     pa_source_set_latency_range(s->monitor_source, s->thread_info.min_latency, s->thread_info.max_latency);
380     pa_source_set_fixed_latency(s->monitor_source, s->thread_info.fixed_latency);
381     pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
382
383     return s;
384 }
385
386 /* Called from main context */
387 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
388     int ret;
389     pa_bool_t suspend_change;
390     pa_sink_state_t original_state;
391
392     pa_assert(s);
393     pa_assert_ctl_context();
394
395     if (s->state == state)
396         return 0;
397
398     original_state = s->state;
399
400     suspend_change =
401         (original_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state)) ||
402         (PA_SINK_IS_OPENED(original_state) && state == PA_SINK_SUSPENDED);
403
404     if (s->set_state)
405         if ((ret = s->set_state(s, state)) < 0)
406             return ret;
407
408     if (s->asyncmsgq)
409         if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
410
411             if (s->set_state)
412                 s->set_state(s, original_state);
413
414             return ret;
415         }
416
417     s->state = state;
418
419     if (state != PA_SINK_UNLINKED) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
420         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
421         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
422     }
423
424     if (suspend_change) {
425         pa_sink_input *i;
426         uint32_t idx;
427
428         /* We're suspending or resuming, tell everyone about it */
429
430         PA_IDXSET_FOREACH(i, s->inputs, idx)
431             if (s->state == PA_SINK_SUSPENDED &&
432                 (i->flags & PA_SINK_INPUT_KILL_ON_SUSPEND))
433                 pa_sink_input_kill(i);
434             else if (i->suspend)
435                 i->suspend(i, state == PA_SINK_SUSPENDED);
436
437         if (s->monitor_source)
438             pa_source_sync_suspend(s->monitor_source);
439     }
440
441     return 0;
442 }
443
444 /* Called from main context */
445 void pa_sink_put(pa_sink* s) {
446     pa_sink_assert_ref(s);
447     pa_assert_ctl_context();
448
449     pa_assert(s->state == PA_SINK_INIT);
450
451     /* The following fields must be initialized properly when calling _put() */
452     pa_assert(s->asyncmsgq);
453     pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
454
455     /* Generally, flags should be initialized via pa_sink_new(). As a
456      * special exception we allow volume related flags to be set
457      * between _new() and _put(). */
458
459     if (!(s->flags & PA_SINK_HW_VOLUME_CTRL))
460         s->flags |= PA_SINK_DECIBEL_VOLUME;
461
462     if ((s->flags & PA_SINK_DECIBEL_VOLUME) && s->core->flat_volumes)
463         s->flags |= PA_SINK_FLAT_VOLUME;
464
465     /* We assume that if the sink implementor changed the default
466      * volume he did so in real_volume, because that is the usual
467      * place where he is supposed to place his changes.  */
468     s->reference_volume = s->real_volume;
469
470     s->thread_info.soft_volume = s->soft_volume;
471     s->thread_info.soft_muted = s->muted;
472     pa_sw_cvolume_multiply(&s->thread_info.current_hw_volume, &s->soft_volume, &s->real_volume);
473
474     pa_assert((s->flags & PA_SINK_HW_VOLUME_CTRL) || (s->base_volume == PA_VOLUME_NORM && s->flags & PA_SINK_DECIBEL_VOLUME));
475     pa_assert(!(s->flags & PA_SINK_DECIBEL_VOLUME) || s->n_volume_steps == PA_VOLUME_NORM+1);
476     pa_assert(!(s->flags & PA_SINK_DYNAMIC_LATENCY) == (s->thread_info.fixed_latency != 0));
477     pa_assert(!(s->flags & PA_SINK_LATENCY) == !(s->monitor_source->flags & PA_SOURCE_LATENCY));
478     pa_assert(!(s->flags & PA_SINK_DYNAMIC_LATENCY) == !(s->monitor_source->flags & PA_SOURCE_DYNAMIC_LATENCY));
479     pa_assert(!(s->flags & PA_SINK_HW_VOLUME_CTRL) || s->set_volume);
480     pa_assert(!(s->flags & PA_SINK_SYNC_VOLUME) || (s->flags & PA_SINK_HW_VOLUME_CTRL));
481     pa_assert(!(s->flags & PA_SINK_SYNC_VOLUME) || s->write_volume);
482     pa_assert(!(s->flags & PA_SINK_HW_MUTE_CTRL) || s->set_mute);
483
484     pa_assert(s->monitor_source->thread_info.fixed_latency == s->thread_info.fixed_latency);
485     pa_assert(s->monitor_source->thread_info.min_latency == s->thread_info.min_latency);
486     pa_assert(s->monitor_source->thread_info.max_latency == s->thread_info.max_latency);
487
488     pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
489
490     pa_source_put(s->monitor_source);
491
492     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
493     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s);
494 }
495
496 /* Called from main context */
497 void pa_sink_unlink(pa_sink* s) {
498     pa_bool_t linked;
499     pa_sink_input *i, *j = NULL;
500
501     pa_assert(s);
502     pa_assert_ctl_context();
503
504     /* Please note that pa_sink_unlink() does more than simply
505      * reversing pa_sink_put(). It also undoes the registrations
506      * already done in pa_sink_new()! */
507
508     /* All operations here shall be idempotent, i.e. pa_sink_unlink()
509      * may be called multiple times on the same sink without bad
510      * effects. */
511
512     linked = PA_SINK_IS_LINKED(s->state);
513
514     if (linked)
515         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
516
517     if (s->state != PA_SINK_UNLINKED)
518         pa_namereg_unregister(s->core, s->name);
519     pa_idxset_remove_by_data(s->core->sinks, s, NULL);
520
521     if (s->card)
522         pa_idxset_remove_by_data(s->card->sinks, s, NULL);
523
524     while ((i = pa_idxset_first(s->inputs, NULL))) {
525         pa_assert(i != j);
526         pa_sink_input_kill(i);
527         j = i;
528     }
529
530     if (linked)
531         sink_set_state(s, PA_SINK_UNLINKED);
532     else
533         s->state = PA_SINK_UNLINKED;
534
535     reset_callbacks(s);
536
537     if (s->monitor_source)
538         pa_source_unlink(s->monitor_source);
539
540     if (linked) {
541         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
542         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
543     }
544 }
545
546 /* Called from main context */
547 static void sink_free(pa_object *o) {
548     pa_sink *s = PA_SINK(o);
549     pa_sink_input *i;
550
551     pa_assert(s);
552     pa_assert_ctl_context();
553     pa_assert(pa_sink_refcnt(s) == 0);
554
555     if (PA_SINK_IS_LINKED(s->state))
556         pa_sink_unlink(s);
557
558     pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
559
560     if (s->monitor_source) {
561         pa_source_unref(s->monitor_source);
562         s->monitor_source = NULL;
563     }
564
565     pa_idxset_free(s->inputs, NULL, NULL);
566
567     while ((i = pa_hashmap_steal_first(s->thread_info.inputs)))
568         pa_sink_input_unref(i);
569
570     pa_hashmap_free(s->thread_info.inputs, NULL, NULL);
571
572     if (s->silence.memblock)
573         pa_memblock_unref(s->silence.memblock);
574
575     pa_xfree(s->name);
576     pa_xfree(s->driver);
577
578     if (s->proplist)
579         pa_proplist_free(s->proplist);
580
581     if (s->ports) {
582         pa_device_port *p;
583
584         while ((p = pa_hashmap_steal_first(s->ports)))
585             pa_device_port_free(p);
586
587         pa_hashmap_free(s->ports, NULL, NULL);
588     }
589
590     pa_xfree(s);
591 }
592
593 /* Called from main context, and not while the IO thread is active, please */
594 void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
595     pa_sink_assert_ref(s);
596     pa_assert_ctl_context();
597
598     s->asyncmsgq = q;
599
600     if (s->monitor_source)
601         pa_source_set_asyncmsgq(s->monitor_source, q);
602 }
603
604 /* Called from main context, and not while the IO thread is active, please */
605 void pa_sink_update_flags(pa_sink *s, pa_sink_flags_t mask, pa_sink_flags_t value) {
606     pa_sink_assert_ref(s);
607     pa_assert_ctl_context();
608
609     if (mask == 0)
610         return;
611
612     /* For now, allow only a minimal set of flags to be changed. */
613     pa_assert((mask & ~(PA_SINK_DYNAMIC_LATENCY|PA_SINK_LATENCY)) == 0);
614
615     s->flags = (s->flags & ~mask) | (value & mask);
616
617     pa_source_update_flags(s->monitor_source,
618                            ((mask & PA_SINK_LATENCY) ? PA_SOURCE_LATENCY : 0) |
619                            ((mask & PA_SINK_DYNAMIC_LATENCY) ? PA_SOURCE_DYNAMIC_LATENCY : 0),
620                            ((value & PA_SINK_LATENCY) ? PA_SOURCE_LATENCY : 0) |
621                            ((value & PA_SINK_DYNAMIC_LATENCY) ? PA_SINK_DYNAMIC_LATENCY : 0));
622 }
623
624 /* Called from IO context, or before _put() from main context */
625 void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
626     pa_sink_assert_ref(s);
627     pa_sink_assert_io_context(s);
628
629     s->thread_info.rtpoll = p;
630
631     if (s->monitor_source)
632         pa_source_set_rtpoll(s->monitor_source, p);
633 }
634
635 /* Called from main context */
636 int pa_sink_update_status(pa_sink*s) {
637     pa_sink_assert_ref(s);
638     pa_assert_ctl_context();
639     pa_assert(PA_SINK_IS_LINKED(s->state));
640
641     if (s->state == PA_SINK_SUSPENDED)
642         return 0;
643
644     return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
645 }
646
647 /* Called from main context */
648 int pa_sink_suspend(pa_sink *s, pa_bool_t suspend, pa_suspend_cause_t cause) {
649     pa_sink_assert_ref(s);
650     pa_assert_ctl_context();
651     pa_assert(PA_SINK_IS_LINKED(s->state));
652     pa_assert(cause != 0);
653
654     if (suspend) {
655         s->suspend_cause |= cause;
656         s->monitor_source->suspend_cause |= cause;
657     } else {
658         s->suspend_cause &= ~cause;
659         s->monitor_source->suspend_cause &= ~cause;
660     }
661
662     if ((pa_sink_get_state(s) == PA_SINK_SUSPENDED) == !!s->suspend_cause)
663         return 0;
664
665     pa_log_debug("Suspend cause of sink %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming");
666
667     if (s->suspend_cause)
668         return sink_set_state(s, PA_SINK_SUSPENDED);
669     else
670         return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
671 }
672
673 /* Called from main context */
674 pa_queue *pa_sink_move_all_start(pa_sink *s, pa_queue *q) {
675     pa_sink_input *i, *n;
676     uint32_t idx;
677
678     pa_sink_assert_ref(s);
679     pa_assert_ctl_context();
680     pa_assert(PA_SINK_IS_LINKED(s->state));
681
682     if (!q)
683         q = pa_queue_new();
684
685     for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = n) {
686         n = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx));
687
688         pa_sink_input_ref(i);
689
690         if (pa_sink_input_start_move(i) >= 0)
691             pa_queue_push(q, i);
692         else
693             pa_sink_input_unref(i);
694     }
695
696     return q;
697 }
698
699 /* Called from main context */
700 void pa_sink_move_all_finish(pa_sink *s, pa_queue *q, pa_bool_t save) {
701     pa_sink_input *i;
702
703     pa_sink_assert_ref(s);
704     pa_assert_ctl_context();
705     pa_assert(PA_SINK_IS_LINKED(s->state));
706     pa_assert(q);
707
708     while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
709         if (pa_sink_input_finish_move(i, s, save) < 0)
710             pa_sink_input_fail_move(i);
711
712         pa_sink_input_unref(i);
713     }
714
715     pa_queue_free(q, NULL, NULL);
716 }
717
718 /* Called from main context */
719 void pa_sink_move_all_fail(pa_queue *q) {
720     pa_sink_input *i;
721
722     pa_assert_ctl_context();
723     pa_assert(q);
724
725     while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
726         pa_sink_input_fail_move(i);
727         pa_sink_input_unref(i);
728     }
729
730     pa_queue_free(q, NULL, NULL);
731 }
732
733 /* Called from IO thread context */
734 void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
735     pa_sink_input *i;
736     void *state = NULL;
737
738     pa_sink_assert_ref(s);
739     pa_sink_assert_io_context(s);
740     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
741
742     /* If nobody requested this and this is actually no real rewind
743      * then we can short cut this. Please note that this means that
744      * not all rewind requests triggered upstream will always be
745      * translated in actual requests! */
746     if (!s->thread_info.rewind_requested && nbytes <= 0)
747         return;
748
749     s->thread_info.rewind_nbytes = 0;
750     s->thread_info.rewind_requested = FALSE;
751
752     if (s->thread_info.state == PA_SINK_SUSPENDED)
753         return;
754
755     if (nbytes > 0) {
756         pa_log_debug("Processing rewind...");
757         if (s->flags & PA_SINK_SYNC_VOLUME)
758             pa_sink_volume_change_rewind(s, nbytes);
759     }
760
761     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
762         pa_sink_input_assert_ref(i);
763         pa_sink_input_process_rewind(i, nbytes);
764     }
765
766     if (nbytes > 0) {
767         if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
768             pa_source_process_rewind(s->monitor_source, nbytes);
769     }
770 }
771
772 /* Called from IO thread context */
773 static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxinfo) {
774     pa_sink_input *i;
775     unsigned n = 0;
776     void *state = NULL;
777     size_t mixlength = *length;
778
779     pa_sink_assert_ref(s);
780     pa_sink_assert_io_context(s);
781     pa_assert(info);
782
783     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
784         pa_sink_input_assert_ref(i);
785
786         pa_sink_input_peek(i, *length, &info->chunk, &info->volume);
787
788         if (mixlength == 0 || info->chunk.length < mixlength)
789             mixlength = info->chunk.length;
790
791         if (pa_memblock_is_silence(info->chunk.memblock)) {
792             pa_memblock_unref(info->chunk.memblock);
793             continue;
794         }
795
796         info->userdata = pa_sink_input_ref(i);
797
798         pa_assert(info->chunk.memblock);
799         pa_assert(info->chunk.length > 0);
800
801         info++;
802         n++;
803         maxinfo--;
804     }
805
806     if (mixlength > 0)
807         *length = mixlength;
808
809     return n;
810 }
811
812 /* Called from IO thread context */
813 static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *result) {
814     pa_sink_input *i;
815     void *state;
816     unsigned p = 0;
817     unsigned n_unreffed = 0;
818
819     pa_sink_assert_ref(s);
820     pa_sink_assert_io_context(s);
821     pa_assert(result);
822     pa_assert(result->memblock);
823     pa_assert(result->length > 0);
824
825     /* We optimize for the case where the order of the inputs has not changed */
826
827     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
828         unsigned j;
829         pa_mix_info* m = NULL;
830
831         pa_sink_input_assert_ref(i);
832
833         /* Let's try to find the matching entry info the pa_mix_info array */
834         for (j = 0; j < n; j ++) {
835
836             if (info[p].userdata == i) {
837                 m = info + p;
838                 break;
839             }
840
841             p++;
842             if (p >= n)
843                 p = 0;
844         }
845
846         /* Drop read data */
847         pa_sink_input_drop(i, result->length);
848
849         if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state)) {
850
851             if (pa_hashmap_size(i->thread_info.direct_outputs) > 0) {
852                 void *ostate = NULL;
853                 pa_source_output *o;
854                 pa_memchunk c;
855
856                 if (m && m->chunk.memblock) {
857                     c = m->chunk;
858                     pa_memblock_ref(c.memblock);
859                     pa_assert(result->length <= c.length);
860                     c.length = result->length;
861
862                     pa_memchunk_make_writable(&c, 0);
863                     pa_volume_memchunk(&c, &s->sample_spec, &m->volume);
864                 } else {
865                     c = s->silence;
866                     pa_memblock_ref(c.memblock);
867                     pa_assert(result->length <= c.length);
868                     c.length = result->length;
869                 }
870
871                 while ((o = pa_hashmap_iterate(i->thread_info.direct_outputs, &ostate, NULL))) {
872                     pa_source_output_assert_ref(o);
873                     pa_assert(o->direct_on_input == i);
874                     pa_source_post_direct(s->monitor_source, o, &c);
875                 }
876
877                 pa_memblock_unref(c.memblock);
878             }
879         }
880
881         if (m) {
882             if (m->chunk.memblock)
883                 pa_memblock_unref(m->chunk.memblock);
884                 pa_memchunk_reset(&m->chunk);
885
886             pa_sink_input_unref(m->userdata);
887             m->userdata = NULL;
888
889             n_unreffed += 1;
890         }
891     }
892
893     /* Now drop references to entries that are included in the
894      * pa_mix_info array but don't exist anymore */
895
896     if (n_unreffed < n) {
897         for (; n > 0; info++, n--) {
898             if (info->userdata)
899                 pa_sink_input_unref(info->userdata);
900             if (info->chunk.memblock)
901                 pa_memblock_unref(info->chunk.memblock);
902         }
903     }
904
905     if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
906         pa_source_post(s->monitor_source, result);
907 }
908
909 /* Called from IO thread context */
910 void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
911     pa_mix_info info[MAX_MIX_CHANNELS];
912     unsigned n;
913     size_t block_size_max;
914
915     pa_sink_assert_ref(s);
916     pa_sink_assert_io_context(s);
917     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
918     pa_assert(pa_frame_aligned(length, &s->sample_spec));
919     pa_assert(result);
920
921     pa_assert(!s->thread_info.rewind_requested);
922     pa_assert(s->thread_info.rewind_nbytes == 0);
923
924     if (s->thread_info.state == PA_SINK_SUSPENDED) {
925         result->memblock = pa_memblock_ref(s->silence.memblock);
926         result->index = s->silence.index;
927         result->length = PA_MIN(s->silence.length, length);
928         return;
929     }
930
931     pa_sink_ref(s);
932
933     if (length <= 0)
934         length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
935
936     block_size_max = pa_mempool_block_size_max(s->core->mempool);
937     if (length > block_size_max)
938         length = pa_frame_align(block_size_max, &s->sample_spec);
939
940     pa_assert(length > 0);
941
942     n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
943
944     if (n == 0) {
945
946         *result = s->silence;
947         pa_memblock_ref(result->memblock);
948
949         if (result->length > length)
950             result->length = length;
951
952     } else if (n == 1) {
953         pa_cvolume volume;
954
955         *result = info[0].chunk;
956         pa_memblock_ref(result->memblock);
957
958         if (result->length > length)
959             result->length = length;
960
961         pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
962
963         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) {
964             pa_memblock_unref(result->memblock);
965             pa_silence_memchunk_get(&s->core->silence_cache,
966                                     s->core->mempool,
967                                     result,
968                                     &s->sample_spec,
969                                     result->length);
970         } else if (!pa_cvolume_is_norm(&volume)) {
971             pa_memchunk_make_writable(result, 0);
972             pa_volume_memchunk(result, &s->sample_spec, &volume);
973         }
974     } else {
975         void *ptr;
976         result->memblock = pa_memblock_new(s->core->mempool, length);
977
978         ptr = pa_memblock_acquire(result->memblock);
979         result->length = pa_mix(info, n,
980                                 ptr, length,
981                                 &s->sample_spec,
982                                 &s->thread_info.soft_volume,
983                                 s->thread_info.soft_muted);
984         pa_memblock_release(result->memblock);
985
986         result->index = 0;
987     }
988
989     inputs_drop(s, info, n, result);
990
991     pa_sink_unref(s);
992 }
993
994 /* Called from IO thread context */
995 void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
996     pa_mix_info info[MAX_MIX_CHANNELS];
997     unsigned n;
998     size_t length, block_size_max;
999
1000     pa_sink_assert_ref(s);
1001     pa_sink_assert_io_context(s);
1002     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1003     pa_assert(target);
1004     pa_assert(target->memblock);
1005     pa_assert(target->length > 0);
1006     pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
1007
1008     pa_assert(!s->thread_info.rewind_requested);
1009     pa_assert(s->thread_info.rewind_nbytes == 0);
1010
1011     if (s->thread_info.state == PA_SINK_SUSPENDED) {
1012         pa_silence_memchunk(target, &s->sample_spec);
1013         return;
1014     }
1015
1016     pa_sink_ref(s);
1017
1018     length = target->length;
1019     block_size_max = pa_mempool_block_size_max(s->core->mempool);
1020     if (length > block_size_max)
1021         length = pa_frame_align(block_size_max, &s->sample_spec);
1022
1023     pa_assert(length > 0);
1024
1025     n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
1026
1027     if (n == 0) {
1028         if (target->length > length)
1029             target->length = length;
1030
1031         pa_silence_memchunk(target, &s->sample_spec);
1032     } else if (n == 1) {
1033         pa_cvolume volume;
1034
1035         if (target->length > length)
1036             target->length = length;
1037
1038         pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
1039
1040         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
1041             pa_silence_memchunk(target, &s->sample_spec);
1042         else {
1043             pa_memchunk vchunk;
1044
1045             vchunk = info[0].chunk;
1046             pa_memblock_ref(vchunk.memblock);
1047
1048             if (vchunk.length > length)
1049                 vchunk.length = length;
1050
1051             if (!pa_cvolume_is_norm(&volume)) {
1052                 pa_memchunk_make_writable(&vchunk, 0);
1053                 pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
1054             }
1055
1056             pa_memchunk_memcpy(target, &vchunk);
1057             pa_memblock_unref(vchunk.memblock);
1058         }
1059
1060     } else {
1061         void *ptr;
1062
1063         ptr = pa_memblock_acquire(target->memblock);
1064
1065         target->length = pa_mix(info, n,
1066                                 (uint8_t*) ptr + target->index, length,
1067                                 &s->sample_spec,
1068                                 &s->thread_info.soft_volume,
1069                                 s->thread_info.soft_muted);
1070
1071         pa_memblock_release(target->memblock);
1072     }
1073
1074     inputs_drop(s, info, n, target);
1075
1076     pa_sink_unref(s);
1077 }
1078
1079 /* Called from IO thread context */
1080 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
1081     pa_memchunk chunk;
1082     size_t l, d;
1083
1084     pa_sink_assert_ref(s);
1085     pa_sink_assert_io_context(s);
1086     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1087     pa_assert(target);
1088     pa_assert(target->memblock);
1089     pa_assert(target->length > 0);
1090     pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
1091
1092     pa_assert(!s->thread_info.rewind_requested);
1093     pa_assert(s->thread_info.rewind_nbytes == 0);
1094
1095     if (s->thread_info.state == PA_SINK_SUSPENDED) {
1096         pa_silence_memchunk(target, &s->sample_spec);
1097         return;
1098     }
1099
1100     pa_sink_ref(s);
1101
1102     l = target->length;
1103     d = 0;
1104     while (l > 0) {
1105         chunk = *target;
1106         chunk.index += d;
1107         chunk.length -= d;
1108
1109         pa_sink_render_into(s, &chunk);
1110
1111         d += chunk.length;
1112         l -= chunk.length;
1113     }
1114
1115     pa_sink_unref(s);
1116 }
1117
1118 /* Called from IO thread context */
1119 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
1120     pa_sink_assert_ref(s);
1121     pa_sink_assert_io_context(s);
1122     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1123     pa_assert(length > 0);
1124     pa_assert(pa_frame_aligned(length, &s->sample_spec));
1125     pa_assert(result);
1126
1127     pa_assert(!s->thread_info.rewind_requested);
1128     pa_assert(s->thread_info.rewind_nbytes == 0);
1129
1130     pa_sink_ref(s);
1131
1132     pa_sink_render(s, length, result);
1133
1134     if (result->length < length) {
1135         pa_memchunk chunk;
1136
1137         pa_memchunk_make_writable(result, length);
1138
1139         chunk.memblock = result->memblock;
1140         chunk.index = result->index + result->length;
1141         chunk.length = length - result->length;
1142
1143         pa_sink_render_into_full(s, &chunk);
1144
1145         result->length = length;
1146     }
1147
1148     pa_sink_unref(s);
1149 }
1150
1151 /* Called from main thread */
1152 pa_usec_t pa_sink_get_latency(pa_sink *s) {
1153     pa_usec_t usec = 0;
1154
1155     pa_sink_assert_ref(s);
1156     pa_assert_ctl_context();
1157     pa_assert(PA_SINK_IS_LINKED(s->state));
1158
1159     /* The returned value is supposed to be in the time domain of the sound card! */
1160
1161     if (s->state == PA_SINK_SUSPENDED)
1162         return 0;
1163
1164     if (!(s->flags & PA_SINK_LATENCY))
1165         return 0;
1166
1167     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
1168
1169     return usec;
1170 }
1171
1172 /* Called from IO thread */
1173 pa_usec_t pa_sink_get_latency_within_thread(pa_sink *s) {
1174     pa_usec_t usec = 0;
1175     pa_msgobject *o;
1176
1177     pa_sink_assert_ref(s);
1178     pa_sink_assert_io_context(s);
1179     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1180
1181     /* The returned value is supposed to be in the time domain of the sound card! */
1182
1183     if (s->thread_info.state == PA_SINK_SUSPENDED)
1184         return 0;
1185
1186     if (!(s->flags & PA_SINK_LATENCY))
1187         return 0;
1188
1189     o = PA_MSGOBJECT(s);
1190
1191     /* FIXME: We probably should make this a proper vtable callback instead of going through process_msg() */
1192
1193     if (o->process_msg(o, PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
1194         return -1;
1195
1196     return usec;
1197 }
1198
1199 static pa_cvolume* cvolume_remap_minimal_impact(
1200         pa_cvolume *v,
1201         const pa_cvolume *template,
1202         const pa_channel_map *from,
1203         const pa_channel_map *to) {
1204
1205     pa_cvolume t;
1206
1207     pa_assert(v);
1208     pa_assert(template);
1209     pa_assert(from);
1210     pa_assert(to);
1211
1212     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, from), NULL);
1213     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(template, to), NULL);
1214
1215     /* Much like pa_cvolume_remap(), but tries to minimize impact when
1216      * mapping from sink input to sink volumes:
1217      *
1218      * If template is a possible remapping from v it is used instead
1219      * of remapping anew.
1220      *
1221      * If the channel maps don't match we set an all-channel volume on
1222      * the sink to ensure that changing a volume on one stream has no
1223      * effect that cannot be compensated for in another stream that
1224      * does not have the same channel map as the sink. */
1225
1226     if (pa_channel_map_equal(from, to))
1227         return v;
1228
1229     t = *template;
1230     if (pa_cvolume_equal(pa_cvolume_remap(&t, to, from), v)) {
1231         *v = *template;
1232         return v;
1233     }
1234
1235     pa_cvolume_set(v, to->channels, pa_cvolume_max(v));
1236     return v;
1237 }
1238
1239 /* Called from main context */
1240 static void compute_reference_ratios(pa_sink *s) {
1241     uint32_t idx;
1242     pa_sink_input *i;
1243
1244     pa_sink_assert_ref(s);
1245     pa_assert_ctl_context();
1246     pa_assert(PA_SINK_IS_LINKED(s->state));
1247     pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
1248
1249     PA_IDXSET_FOREACH(i, s->inputs, idx) {
1250         unsigned c;
1251         pa_cvolume remapped;
1252
1253         /*
1254          * Calculates the reference volume from the sink's reference
1255          * volume. This basically calculates:
1256          *
1257          * i->reference_ratio = i->volume / s->reference_volume
1258          */
1259
1260         remapped = s->reference_volume;
1261         pa_cvolume_remap(&remapped, &s->channel_map, &i->channel_map);
1262
1263         i->reference_ratio.channels = i->sample_spec.channels;
1264
1265         for (c = 0; c < i->sample_spec.channels; c++) {
1266
1267             /* We don't update when the sink volume is 0 anyway */
1268             if (remapped.values[c] <= PA_VOLUME_MUTED)
1269                 continue;
1270
1271             /* Don't update the reference ratio unless necessary */
1272             if (pa_sw_volume_multiply(
1273                         i->reference_ratio.values[c],
1274                         remapped.values[c]) == i->volume.values[c])
1275                 continue;
1276
1277             i->reference_ratio.values[c] = pa_sw_volume_divide(
1278                     i->volume.values[c],
1279                     remapped.values[c]);
1280         }
1281     }
1282 }
1283
1284 /* Called from main context */
1285 static void compute_real_ratios(pa_sink *s) {
1286     pa_sink_input *i;
1287     uint32_t idx;
1288
1289     pa_sink_assert_ref(s);
1290     pa_assert_ctl_context();
1291     pa_assert(PA_SINK_IS_LINKED(s->state));
1292     pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
1293
1294     PA_IDXSET_FOREACH(i, s->inputs, idx) {
1295         unsigned c;
1296         pa_cvolume remapped;
1297
1298         /*
1299          * This basically calculates:
1300          *
1301          * i->real_ratio := i->volume / s->real_volume
1302          * i->soft_volume := i->real_ratio * i->volume_factor
1303          */
1304
1305         remapped = s->real_volume;
1306         pa_cvolume_remap(&remapped, &s->channel_map, &i->channel_map);
1307
1308         i->real_ratio.channels = i->sample_spec.channels;
1309         i->soft_volume.channels = i->sample_spec.channels;
1310
1311         for (c = 0; c < i->sample_spec.channels; c++) {
1312
1313             if (remapped.values[c] <= PA_VOLUME_MUTED) {
1314                 /* We leave i->real_ratio untouched */
1315                 i->soft_volume.values[c] = PA_VOLUME_MUTED;
1316                 continue;
1317             }
1318
1319             /* Don't lose accuracy unless necessary */
1320             if (pa_sw_volume_multiply(
1321                         i->real_ratio.values[c],
1322                         remapped.values[c]) != i->volume.values[c])
1323
1324                 i->real_ratio.values[c] = pa_sw_volume_divide(
1325                         i->volume.values[c],
1326                         remapped.values[c]);
1327
1328             i->soft_volume.values[c] = pa_sw_volume_multiply(
1329                     i->real_ratio.values[c],
1330                     i->volume_factor.values[c]);
1331         }
1332
1333         /* We don't copy the soft_volume to the thread_info data
1334          * here. That must be done by the caller */
1335     }
1336 }
1337
1338 /* Called from main thread */
1339 static void compute_real_volume(pa_sink *s) {
1340     pa_sink_input *i;
1341     uint32_t idx;
1342
1343     pa_sink_assert_ref(s);
1344     pa_assert_ctl_context();
1345     pa_assert(PA_SINK_IS_LINKED(s->state));
1346     pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
1347
1348     /* This determines the maximum volume of all streams and sets
1349      * s->real_volume accordingly. */
1350
1351     if (pa_idxset_isempty(s->inputs)) {
1352         /* In the special case that we have no sink input we leave the
1353          * volume unmodified. */
1354         s->real_volume = s->reference_volume;
1355         return;
1356     }
1357
1358     pa_cvolume_mute(&s->real_volume, s->channel_map.channels);
1359
1360     /* First let's determine the new maximum volume of all inputs
1361      * connected to this sink */
1362     PA_IDXSET_FOREACH(i, s->inputs, idx) {
1363         pa_cvolume remapped;
1364
1365         remapped = i->volume;
1366         cvolume_remap_minimal_impact(&remapped, &s->real_volume, &i->channel_map, &s->channel_map);
1367         pa_cvolume_merge(&s->real_volume, &s->real_volume, &remapped);
1368     }
1369
1370     /* Then, let's update the real ratios/soft volumes of all inputs
1371      * connected to this sink */
1372     compute_real_ratios(s);
1373 }
1374
1375 /* Called from main thread */
1376 static void propagate_reference_volume(pa_sink *s) {
1377     pa_sink_input *i;
1378     uint32_t idx;
1379
1380     pa_sink_assert_ref(s);
1381     pa_assert_ctl_context();
1382     pa_assert(PA_SINK_IS_LINKED(s->state));
1383     pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
1384
1385     /* This is called whenever the sink volume changes that is not
1386      * caused by a sink input volume change. We need to fix up the
1387      * sink input volumes accordingly */
1388
1389     PA_IDXSET_FOREACH(i, s->inputs, idx) {
1390         pa_cvolume old_volume, remapped;
1391
1392         old_volume = i->volume;
1393
1394         /* This basically calculates:
1395          *
1396          * i->volume := s->reference_volume * i->reference_ratio  */
1397
1398         remapped = s->reference_volume;
1399         pa_cvolume_remap(&remapped, &s->channel_map, &i->channel_map);
1400         pa_sw_cvolume_multiply(&i->volume, &remapped, &i->reference_ratio);
1401
1402         /* The volume changed, let's tell people so */
1403         if (!pa_cvolume_equal(&old_volume, &i->volume)) {
1404
1405             if (i->volume_changed)
1406                 i->volume_changed(i);
1407
1408             pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1409         }
1410     }
1411 }
1412
1413 /* Called from main thread */
1414 void pa_sink_set_volume(
1415         pa_sink *s,
1416         const pa_cvolume *volume,
1417         pa_bool_t send_msg,
1418         pa_bool_t save) {
1419
1420     pa_cvolume old_reference_volume;
1421     pa_bool_t reference_changed;
1422
1423     pa_sink_assert_ref(s);
1424     pa_assert_ctl_context();
1425     pa_assert(PA_SINK_IS_LINKED(s->state));
1426     pa_assert(!volume || pa_cvolume_valid(volume));
1427     pa_assert(volume || (s->flags & PA_SINK_FLAT_VOLUME));
1428     pa_assert(!volume || volume->channels == 1 || pa_cvolume_compatible(volume, &s->sample_spec));
1429
1430     /* make sure we don't change the volume when a PASSTHROUGH input is connected */
1431     if (s->flags & PA_SINK_PASSTHROUGH) {
1432         pa_sink_input *alt_i;
1433         uint32_t idx;
1434
1435         /* one and only one PASSTHROUGH input can possibly be connected */
1436         if (pa_idxset_size(s->inputs) == 1) {
1437
1438             alt_i = pa_idxset_first(s->inputs, &idx);
1439
1440             if (alt_i->flags & PA_SINK_INPUT_PASSTHROUGH) {
1441                 /* FIXME: Need to notify client that volume control is disabled */
1442                 pa_log_warn("Cannot change volume, Sink is connected to PASSTHROUGH input");
1443                 return;
1444             }
1445         }
1446     }
1447
1448     /* As a special exception we accept mono volumes on all sinks --
1449      * even on those with more complex channel maps */
1450
1451     /* If volume is NULL we synchronize the sink's real and reference
1452      * volumes with the stream volumes. If it is not NULL we update
1453      * the reference_volume with it. */
1454
1455     old_reference_volume = s->reference_volume;
1456
1457     if (volume) {
1458
1459         if (pa_cvolume_compatible(volume, &s->sample_spec))
1460             s->reference_volume = *volume;
1461         else
1462             pa_cvolume_scale(&s->reference_volume, pa_cvolume_max(volume));
1463
1464         if (s->flags & PA_SINK_FLAT_VOLUME) {
1465             /* OK, propagate this volume change back to the inputs */
1466             propagate_reference_volume(s);
1467
1468             /* And now recalculate the real volume */
1469             compute_real_volume(s);
1470         } else
1471             s->real_volume = s->reference_volume;
1472
1473     } else {
1474         pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
1475
1476         /* Ok, let's determine the new real volume */
1477         compute_real_volume(s);
1478
1479         /* Let's 'push' the reference volume if necessary */
1480         pa_cvolume_merge(&s->reference_volume, &s->reference_volume, &s->real_volume);
1481
1482         /* We need to fix the reference ratios of all streams now that
1483          * we changed the reference volume */
1484         compute_reference_ratios(s);
1485     }
1486
1487     reference_changed = !pa_cvolume_equal(&old_reference_volume, &s->reference_volume);
1488     s->save_volume = (!reference_changed && s->save_volume) || save;
1489
1490     if (s->set_volume) {
1491         /* If we have a function set_volume(), then we do not apply a
1492          * soft volume by default. However, set_volume() is free to
1493          * apply one to s->soft_volume */
1494
1495         pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
1496         if (!(s->flags & PA_SINK_SYNC_VOLUME))
1497             s->set_volume(s);
1498         else
1499             send_msg = TRUE;
1500
1501     } else
1502         /* If we have no function set_volume(), then the soft volume
1503          * becomes the virtual volume */
1504         s->soft_volume = s->real_volume;
1505
1506     /* This tells the sink that soft and/or virtual volume changed */
1507     if (send_msg)
1508         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME_SYNCED, NULL, 0, NULL) == 0);
1509
1510     if (reference_changed)
1511         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1512 }
1513
1514 /* Called from the io thread if sync volume is used, otherwise from the main thread.
1515  * Only to be called by sink implementor */
1516 void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) {
1517     pa_sink_assert_ref(s);
1518     if (s->flags & PA_SINK_SYNC_VOLUME)
1519         pa_sink_assert_io_context(s);
1520     else
1521         pa_assert_ctl_context();
1522
1523     if (!volume)
1524         pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
1525     else
1526         s->soft_volume = *volume;
1527
1528     if (PA_SINK_IS_LINKED(s->state) && !(s->flags & PA_SINK_SYNC_VOLUME))
1529         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
1530     else
1531         s->thread_info.soft_volume = s->soft_volume;
1532 }
1533
1534 static void propagate_real_volume(pa_sink *s, const pa_cvolume *old_real_volume) {
1535     pa_sink_input *i;
1536     uint32_t idx;
1537     pa_cvolume old_reference_volume;
1538
1539     pa_sink_assert_ref(s);
1540     pa_assert_ctl_context();
1541     pa_assert(PA_SINK_IS_LINKED(s->state));
1542
1543     /* This is called when the hardware's real volume changes due to
1544      * some external event. We copy the real volume into our
1545      * reference volume and then rebuild the stream volumes based on
1546      * i->real_ratio which should stay fixed. */
1547
1548     if (old_real_volume && pa_cvolume_equal(old_real_volume, &s->real_volume))
1549         return;
1550
1551     old_reference_volume = s->reference_volume;
1552
1553     /* 1. Make the real volume the reference volume */
1554     s->reference_volume = s->real_volume;
1555
1556     if (s->flags & PA_SINK_FLAT_VOLUME) {
1557
1558         PA_IDXSET_FOREACH(i, s->inputs, idx) {
1559             pa_cvolume old_volume, remapped;
1560
1561             old_volume = i->volume;
1562
1563             /* 2. Since the sink's reference and real volumes are equal
1564              * now our ratios should be too. */
1565             i->reference_ratio = i->real_ratio;
1566
1567             /* 3. Recalculate the new stream reference volume based on the
1568              * reference ratio and the sink's reference volume.
1569              *
1570              * This basically calculates:
1571              *
1572              * i->volume = s->reference_volume * i->reference_ratio
1573              *
1574              * This is identical to propagate_reference_volume() */
1575             remapped = s->reference_volume;
1576             pa_cvolume_remap(&remapped, &s->channel_map, &i->channel_map);
1577             pa_sw_cvolume_multiply(&i->volume, &remapped, &i->reference_ratio);
1578
1579             /* Notify if something changed */
1580             if (!pa_cvolume_equal(&old_volume, &i->volume)) {
1581
1582                 if (i->volume_changed)
1583                     i->volume_changed(i);
1584
1585                 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1586             }
1587         }
1588     }
1589
1590     /* Something got changed in the hardware. It probably makes sense
1591      * to save changed hw settings given that hw volume changes not
1592      * triggered by PA are almost certainly done by the user. */
1593     s->save_volume = TRUE;
1594
1595     if (!pa_cvolume_equal(&old_reference_volume, &s->reference_volume))
1596         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1597 }
1598
1599 /* Called from io thread */
1600 void pa_sink_update_volume_and_mute(pa_sink *s) {
1601     pa_assert(s);
1602     pa_sink_assert_io_context(s);
1603
1604     pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE, NULL, 0, NULL, NULL);
1605 }
1606
1607 /* Called from main thread */
1608 const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) {
1609     pa_sink_assert_ref(s);
1610     pa_assert_ctl_context();
1611     pa_assert(PA_SINK_IS_LINKED(s->state));
1612
1613     if (s->refresh_volume || force_refresh) {
1614         struct pa_cvolume old_real_volume;
1615
1616         old_real_volume = s->real_volume;
1617
1618         if (!(s->flags & PA_SINK_SYNC_VOLUME) && s->get_volume)
1619             s->get_volume(s);
1620
1621         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
1622
1623         propagate_real_volume(s, &old_real_volume);
1624     }
1625
1626     return &s->reference_volume;
1627 }
1628
1629 /* Called from main thread */
1630 void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_real_volume) {
1631     pa_cvolume old_real_volume;
1632
1633     pa_sink_assert_ref(s);
1634     pa_assert_ctl_context();
1635     pa_assert(PA_SINK_IS_LINKED(s->state));
1636
1637     /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1638
1639     old_real_volume = s->real_volume;
1640     s->real_volume = *new_real_volume;
1641
1642     propagate_real_volume(s, &old_real_volume);
1643 }
1644
1645 /* Called from main thread */
1646 void pa_sink_set_mute(pa_sink *s, pa_bool_t mute, pa_bool_t save) {
1647     pa_bool_t old_muted;
1648
1649     pa_sink_assert_ref(s);
1650     pa_assert_ctl_context();
1651     pa_assert(PA_SINK_IS_LINKED(s->state));
1652
1653     old_muted = s->muted;
1654     s->muted = mute;
1655     s->save_muted = (old_muted == s->muted && s->save_muted) || save;
1656
1657     if (!(s->flags & PA_SINK_SYNC_VOLUME) && s->set_mute)
1658         s->set_mute(s);
1659
1660     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
1661
1662     if (old_muted != s->muted)
1663         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1664 }
1665
1666 /* Called from main thread */
1667 pa_bool_t pa_sink_get_mute(pa_sink *s, pa_bool_t force_refresh) {
1668
1669     pa_sink_assert_ref(s);
1670     pa_assert_ctl_context();
1671     pa_assert(PA_SINK_IS_LINKED(s->state));
1672
1673     if (s->refresh_muted || force_refresh) {
1674         pa_bool_t old_muted = s->muted;
1675
1676         if (!(s->flags & PA_SINK_SYNC_VOLUME) && s->get_mute)
1677             s->get_mute(s);
1678
1679         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
1680
1681         if (old_muted != s->muted) {
1682             s->save_muted = TRUE;
1683
1684             pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1685
1686             /* Make sure the soft mute status stays in sync */
1687             pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
1688         }
1689     }
1690
1691     return s->muted;
1692 }
1693
1694 /* Called from main thread */
1695 void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted) {
1696     pa_sink_assert_ref(s);
1697     pa_assert_ctl_context();
1698     pa_assert(PA_SINK_IS_LINKED(s->state));
1699
1700     /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1701
1702     if (s->muted == new_muted)
1703         return;
1704
1705     s->muted = new_muted;
1706     s->save_muted = TRUE;
1707
1708     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1709 }
1710
1711 /* Called from main thread */
1712 pa_bool_t pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p) {
1713     pa_sink_assert_ref(s);
1714     pa_assert_ctl_context();
1715
1716     if (p)
1717         pa_proplist_update(s->proplist, mode, p);
1718
1719     if (PA_SINK_IS_LINKED(s->state)) {
1720         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
1721         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1722     }
1723
1724     return TRUE;
1725 }
1726
1727 /* Called from main thread */
1728 /* FIXME -- this should be dropped and be merged into pa_sink_update_proplist() */
1729 void pa_sink_set_description(pa_sink *s, const char *description) {
1730     const char *old;
1731     pa_sink_assert_ref(s);
1732     pa_assert_ctl_context();
1733
1734     if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
1735         return;
1736
1737     old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
1738
1739     if (old && description && pa_streq(old, description))
1740         return;
1741
1742     if (description)
1743         pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
1744     else
1745         pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
1746
1747     if (s->monitor_source) {
1748         char *n;
1749
1750         n = pa_sprintf_malloc("Monitor Source of %s", description ? description : s->name);
1751         pa_source_set_description(s->monitor_source, n);
1752         pa_xfree(n);
1753     }
1754
1755     if (PA_SINK_IS_LINKED(s->state)) {
1756         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1757         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
1758     }
1759 }
1760
1761 /* Called from main thread */
1762 unsigned pa_sink_linked_by(pa_sink *s) {
1763     unsigned ret;
1764
1765     pa_sink_assert_ref(s);
1766     pa_assert_ctl_context();
1767     pa_assert(PA_SINK_IS_LINKED(s->state));
1768
1769     ret = pa_idxset_size(s->inputs);
1770
1771     /* We add in the number of streams connected to us here. Please
1772      * note the asymmmetry to pa_sink_used_by()! */
1773
1774     if (s->monitor_source)
1775         ret += pa_source_linked_by(s->monitor_source);
1776
1777     return ret;
1778 }
1779
1780 /* Called from main thread */
1781 unsigned pa_sink_used_by(pa_sink *s) {
1782     unsigned ret;
1783
1784     pa_sink_assert_ref(s);
1785     pa_assert_ctl_context();
1786     pa_assert(PA_SINK_IS_LINKED(s->state));
1787
1788     ret = pa_idxset_size(s->inputs);
1789     pa_assert(ret >= s->n_corked);
1790
1791     /* Streams connected to our monitor source do not matter for
1792      * pa_sink_used_by()!.*/
1793
1794     return ret - s->n_corked;
1795 }
1796
1797 /* Called from main thread */
1798 unsigned pa_sink_check_suspend(pa_sink *s) {
1799     unsigned ret;
1800     pa_sink_input *i;
1801     uint32_t idx;
1802
1803     pa_sink_assert_ref(s);
1804     pa_assert_ctl_context();
1805
1806     if (!PA_SINK_IS_LINKED(s->state))
1807         return 0;
1808
1809     ret = 0;
1810
1811     PA_IDXSET_FOREACH(i, s->inputs, idx) {
1812         pa_sink_input_state_t st;
1813
1814         st = pa_sink_input_get_state(i);
1815
1816         /* We do not assert here. It is perfectly valid for a sink input to
1817          * be in the INIT state (i.e. created, marked done but not yet put)
1818          * and we should not care if it's unlinked as it won't contribute
1819          * towarards our busy status.
1820          */
1821         if (!PA_SINK_INPUT_IS_LINKED(st))
1822             continue;
1823
1824         if (st == PA_SINK_INPUT_CORKED)
1825             continue;
1826
1827         if (i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND)
1828             continue;
1829
1830         ret ++;
1831     }
1832
1833     if (s->monitor_source)
1834         ret += pa_source_check_suspend(s->monitor_source);
1835
1836     return ret;
1837 }
1838
1839 /* Called from the IO thread */
1840 static void sync_input_volumes_within_thread(pa_sink *s) {
1841     pa_sink_input *i;
1842     void *state = NULL;
1843
1844     pa_sink_assert_ref(s);
1845     pa_sink_assert_io_context(s);
1846
1847     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
1848         if (pa_atomic_load(&i->before_ramping_v))
1849             i->thread_info.future_soft_volume = i->soft_volume;
1850
1851         if (pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume))
1852             continue;
1853
1854         if (!pa_atomic_load(&i->before_ramping_v))
1855             i->thread_info.soft_volume = i->soft_volume;
1856         pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1857     }
1858 }
1859
1860 /* Called from IO thread, except when it is not */
1861 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1862     pa_sink *s = PA_SINK(o);
1863     pa_sink_assert_ref(s);
1864
1865     switch ((pa_sink_message_t) code) {
1866
1867         case PA_SINK_MESSAGE_ADD_INPUT: {
1868             pa_sink_input *i = PA_SINK_INPUT(userdata);
1869
1870             /* If you change anything here, make sure to change the
1871              * sink input handling a few lines down at
1872              * PA_SINK_MESSAGE_FINISH_MOVE, too. */
1873
1874             pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
1875
1876             /* Since the caller sleeps in pa_sink_input_put(), we can
1877              * safely access data outside of thread_info even though
1878              * it is mutable */
1879
1880             if ((i->thread_info.sync_prev = i->sync_prev)) {
1881                 pa_assert(i->sink == i->thread_info.sync_prev->sink);
1882                 pa_assert(i->sync_prev->sync_next == i);
1883                 i->thread_info.sync_prev->thread_info.sync_next = i;
1884             }
1885
1886             if ((i->thread_info.sync_next = i->sync_next)) {
1887                 pa_assert(i->sink == i->thread_info.sync_next->sink);
1888                 pa_assert(i->sync_next->sync_prev == i);
1889                 i->thread_info.sync_next->thread_info.sync_prev = i;
1890             }
1891
1892             pa_assert(!i->thread_info.attached);
1893             i->thread_info.attached = TRUE;
1894
1895             if (i->attach)
1896                 i->attach(i);
1897
1898             pa_sink_input_set_state_within_thread(i, i->state);
1899
1900             /* The requested latency of the sink input needs to be
1901              * fixed up and then configured on the sink */
1902
1903             if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
1904                 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
1905
1906             pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1907             pa_sink_input_update_max_request(i, s->thread_info.max_request);
1908
1909             /* We don't rewind here automatically. This is left to the
1910              * sink input implementor because some sink inputs need a
1911              * slow start, i.e. need some time to buffer client
1912              * samples before beginning streaming. */
1913
1914             /* In flat volume mode we need to update the volume as
1915              * well */
1916             return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME_SYNCED, NULL, 0, NULL);
1917         }
1918
1919         case PA_SINK_MESSAGE_REMOVE_INPUT: {
1920             pa_sink_input *i = PA_SINK_INPUT(userdata);
1921
1922             /* If you change anything here, make sure to change the
1923              * sink input handling a few lines down at
1924              * PA_SINK_MESSAGE_PREPAPRE_MOVE, too. */
1925
1926             if (i->detach)
1927                 i->detach(i);
1928
1929             pa_sink_input_set_state_within_thread(i, i->state);
1930
1931             pa_assert(i->thread_info.attached);
1932             i->thread_info.attached = FALSE;
1933
1934             /* Since the caller sleeps in pa_sink_input_unlink(),
1935              * we can safely access data outside of thread_info even
1936              * though it is mutable */
1937
1938             pa_assert(!i->sync_prev);
1939             pa_assert(!i->sync_next);
1940
1941             if (i->thread_info.sync_prev) {
1942                 i->thread_info.sync_prev->thread_info.sync_next = i->thread_info.sync_prev->sync_next;
1943                 i->thread_info.sync_prev = NULL;
1944             }
1945
1946             if (i->thread_info.sync_next) {
1947                 i->thread_info.sync_next->thread_info.sync_prev = i->thread_info.sync_next->sync_prev;
1948                 i->thread_info.sync_next = NULL;
1949             }
1950
1951             if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
1952                 pa_sink_input_unref(i);
1953
1954             pa_sink_invalidate_requested_latency(s, TRUE);
1955             pa_sink_request_rewind(s, (size_t) -1);
1956
1957             /* In flat volume mode we need to update the volume as
1958              * well */
1959             return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME_SYNCED, NULL, 0, NULL);
1960         }
1961
1962         case PA_SINK_MESSAGE_START_MOVE: {
1963             pa_sink_input *i = PA_SINK_INPUT(userdata);
1964
1965             /* We don't support moving synchronized streams. */
1966             pa_assert(!i->sync_prev);
1967             pa_assert(!i->sync_next);
1968             pa_assert(!i->thread_info.sync_next);
1969             pa_assert(!i->thread_info.sync_prev);
1970
1971             if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
1972                 pa_usec_t usec = 0;
1973                 size_t sink_nbytes, total_nbytes;
1974
1975                 /* Get the latency of the sink */
1976                 usec = pa_sink_get_latency_within_thread(s);
1977                 sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
1978                 total_nbytes = sink_nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq);
1979
1980                 if (total_nbytes > 0) {
1981                     i->thread_info.rewrite_nbytes = i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, total_nbytes) : total_nbytes;
1982                     i->thread_info.rewrite_flush = TRUE;
1983                     pa_sink_input_process_rewind(i, sink_nbytes);
1984                 }
1985             }
1986
1987             if (i->detach)
1988                 i->detach(i);
1989
1990             pa_assert(i->thread_info.attached);
1991             i->thread_info.attached = FALSE;
1992
1993             /* Let's remove the sink input ...*/
1994             if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
1995                 pa_sink_input_unref(i);
1996
1997             pa_sink_invalidate_requested_latency(s, TRUE);
1998
1999             pa_log_debug("Requesting rewind due to started move");
2000             pa_sink_request_rewind(s, (size_t) -1);
2001
2002             /* In flat volume mode we need to update the volume as
2003              * well */
2004             return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME_SYNCED, NULL, 0, NULL);
2005         }
2006
2007         case PA_SINK_MESSAGE_FINISH_MOVE: {
2008             pa_sink_input *i = PA_SINK_INPUT(userdata);
2009
2010             /* We don't support moving synchronized streams. */
2011             pa_assert(!i->sync_prev);
2012             pa_assert(!i->sync_next);
2013             pa_assert(!i->thread_info.sync_next);
2014             pa_assert(!i->thread_info.sync_prev);
2015
2016             pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
2017
2018             pa_assert(!i->thread_info.attached);
2019             i->thread_info.attached = TRUE;
2020
2021             if (i->attach)
2022                 i->attach(i);
2023
2024             if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
2025                 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
2026
2027             pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
2028             pa_sink_input_update_max_request(i, s->thread_info.max_request);
2029
2030             if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
2031                 pa_usec_t usec = 0;
2032                 size_t nbytes;
2033
2034                 /* Get the latency of the sink */
2035                 usec = pa_sink_get_latency_within_thread(s);
2036                 nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
2037
2038                 if (nbytes > 0)
2039                     pa_sink_input_drop(i, nbytes);
2040
2041                 pa_log_debug("Requesting rewind due to finished move");
2042                 pa_sink_request_rewind(s, nbytes);
2043             }
2044
2045             /* In flat volume mode we need to update the volume as
2046              * well */
2047             return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME_SYNCED, NULL, 0, NULL);
2048         }
2049
2050         case PA_SINK_MESSAGE_SET_VOLUME_SYNCED:
2051
2052             if (s->flags & PA_SINK_SYNC_VOLUME) {
2053                 s->set_volume(s);
2054                 pa_sink_volume_change_push(s);
2055             }
2056             /* Fall through ... */
2057
2058         case PA_SINK_MESSAGE_SET_VOLUME:
2059
2060             if (!pa_cvolume_equal(&s->thread_info.soft_volume, &s->soft_volume)) {
2061                 s->thread_info.soft_volume = s->soft_volume;
2062                 pa_sink_request_rewind(s, (size_t) -1);
2063             }
2064
2065             if (!(s->flags & PA_SINK_FLAT_VOLUME))
2066                 return 0;
2067
2068             /* Fall through ... */
2069
2070         case PA_SINK_MESSAGE_SYNC_VOLUMES:
2071             sync_input_volumes_within_thread(s);
2072             return 0;
2073
2074         case PA_SINK_MESSAGE_GET_VOLUME:
2075
2076             if ((s->flags & PA_SINK_SYNC_VOLUME) && s->get_volume) {
2077                 s->get_volume(s);
2078                 pa_sink_volume_change_flush(s);
2079                 pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
2080             }
2081
2082             /* In case sink implementor reset SW volume. */
2083             if (!pa_cvolume_equal(&s->thread_info.soft_volume, &s->soft_volume)) {
2084                 s->thread_info.soft_volume = s->soft_volume;
2085                 pa_sink_request_rewind(s, (size_t) -1);
2086             }
2087
2088             return 0;
2089
2090         case PA_SINK_MESSAGE_SET_MUTE:
2091
2092             if (s->thread_info.soft_muted != s->muted) {
2093                 s->thread_info.soft_muted = s->muted;
2094                 pa_sink_request_rewind(s, (size_t) -1);
2095             }
2096
2097             if (s->flags & PA_SINK_SYNC_VOLUME && s->set_mute)
2098                 s->set_mute(s);
2099
2100             return 0;
2101
2102         case PA_SINK_MESSAGE_GET_MUTE:
2103
2104             if (s->flags & PA_SINK_SYNC_VOLUME && s->get_mute)
2105                 s->get_mute(s);
2106
2107             return 0;
2108
2109         case PA_SINK_MESSAGE_SET_STATE: {
2110
2111             pa_bool_t suspend_change =
2112                 (s->thread_info.state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(PA_PTR_TO_UINT(userdata))) ||
2113                 (PA_SINK_IS_OPENED(s->thread_info.state) && PA_PTR_TO_UINT(userdata) == PA_SINK_SUSPENDED);
2114
2115             s->thread_info.state = PA_PTR_TO_UINT(userdata);
2116
2117             if (s->thread_info.state == PA_SINK_SUSPENDED) {
2118                 s->thread_info.rewind_nbytes = 0;
2119                 s->thread_info.rewind_requested = FALSE;
2120             }
2121
2122             if (suspend_change) {
2123                 pa_sink_input *i;
2124                 void *state = NULL;
2125
2126                 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
2127                     if (i->suspend_within_thread)
2128                         i->suspend_within_thread(i, s->thread_info.state == PA_SINK_SUSPENDED);
2129             }
2130
2131             return 0;
2132         }
2133
2134         case PA_SINK_MESSAGE_DETACH:
2135
2136             /* Detach all streams */
2137             pa_sink_detach_within_thread(s);
2138             return 0;
2139
2140         case PA_SINK_MESSAGE_ATTACH:
2141
2142             /* Reattach all streams */
2143             pa_sink_attach_within_thread(s);
2144             return 0;
2145
2146         case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: {
2147
2148             pa_usec_t *usec = userdata;
2149             *usec = pa_sink_get_requested_latency_within_thread(s);
2150
2151             /* Yes, that's right, the IO thread will see -1 when no
2152              * explicit requested latency is configured, the main
2153              * thread will see max_latency */
2154             if (*usec == (pa_usec_t) -1)
2155                 *usec = s->thread_info.max_latency;
2156
2157             return 0;
2158         }
2159
2160         case PA_SINK_MESSAGE_SET_LATENCY_RANGE: {
2161             pa_usec_t *r = userdata;
2162
2163             pa_sink_set_latency_range_within_thread(s, r[0], r[1]);
2164
2165             return 0;
2166         }
2167
2168         case PA_SINK_MESSAGE_GET_LATENCY_RANGE: {
2169             pa_usec_t *r = userdata;
2170
2171             r[0] = s->thread_info.min_latency;
2172             r[1] = s->thread_info.max_latency;
2173
2174             return 0;
2175         }
2176
2177         case PA_SINK_MESSAGE_GET_FIXED_LATENCY:
2178
2179             *((pa_usec_t*) userdata) = s->thread_info.fixed_latency;
2180             return 0;
2181
2182         case PA_SINK_MESSAGE_SET_FIXED_LATENCY:
2183
2184             pa_sink_set_fixed_latency_within_thread(s, (pa_usec_t) offset);
2185             return 0;
2186
2187         case PA_SINK_MESSAGE_GET_MAX_REWIND:
2188
2189             *((size_t*) userdata) = s->thread_info.max_rewind;
2190             return 0;
2191
2192         case PA_SINK_MESSAGE_GET_MAX_REQUEST:
2193
2194             *((size_t*) userdata) = s->thread_info.max_request;
2195             return 0;
2196
2197         case PA_SINK_MESSAGE_SET_MAX_REWIND:
2198
2199             pa_sink_set_max_rewind_within_thread(s, (size_t) offset);
2200             return 0;
2201
2202         case PA_SINK_MESSAGE_SET_MAX_REQUEST:
2203
2204             pa_sink_set_max_request_within_thread(s, (size_t) offset);
2205             return 0;
2206
2207         case PA_SINK_MESSAGE_SET_PORT:
2208
2209             pa_assert(userdata);
2210             if (s->set_port) {
2211                 struct sink_message_set_port *msg_data = userdata;
2212                 msg_data->ret = s->set_port(s, msg_data->port);
2213             }
2214             return 0;
2215
2216         case PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE:
2217             /* This message is sent from IO-thread and handled in main thread. */
2218             pa_assert_ctl_context();
2219
2220             pa_sink_get_volume(s, TRUE);
2221             pa_sink_get_mute(s, TRUE);
2222             return 0;
2223
2224         case PA_SINK_MESSAGE_GET_LATENCY:
2225         case PA_SINK_MESSAGE_MAX:
2226             ;
2227     }
2228
2229     return -1;
2230 }
2231
2232 /* Called from main thread */
2233 int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause) {
2234     pa_sink *sink;
2235     uint32_t idx;
2236     int ret = 0;
2237
2238     pa_core_assert_ref(c);
2239     pa_assert_ctl_context();
2240     pa_assert(cause != 0);
2241
2242     PA_IDXSET_FOREACH(sink, c->sinks, idx) {
2243         int r;
2244
2245         if ((r = pa_sink_suspend(sink, suspend, cause)) < 0)
2246             ret = r;
2247     }
2248
2249     return ret;
2250 }
2251
2252 /* Called from main thread */
2253 void pa_sink_detach(pa_sink *s) {
2254     pa_sink_assert_ref(s);
2255     pa_assert_ctl_context();
2256     pa_assert(PA_SINK_IS_LINKED(s->state));
2257
2258     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL) == 0);
2259 }
2260
2261 /* Called from main thread */
2262 void pa_sink_attach(pa_sink *s) {
2263     pa_sink_assert_ref(s);
2264     pa_assert_ctl_context();
2265     pa_assert(PA_SINK_IS_LINKED(s->state));
2266
2267     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
2268 }
2269
2270 /* Called from IO thread */
2271 void pa_sink_detach_within_thread(pa_sink *s) {
2272     pa_sink_input *i;
2273     void *state = NULL;
2274
2275     pa_sink_assert_ref(s);
2276     pa_sink_assert_io_context(s);
2277     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
2278
2279     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
2280         if (i->detach)
2281             i->detach(i);
2282
2283     if (s->monitor_source)
2284         pa_source_detach_within_thread(s->monitor_source);
2285 }
2286
2287 /* Called from IO thread */
2288 void pa_sink_attach_within_thread(pa_sink *s) {
2289     pa_sink_input *i;
2290     void *state = NULL;
2291
2292     pa_sink_assert_ref(s);
2293     pa_sink_assert_io_context(s);
2294     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
2295
2296     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
2297         if (i->attach)
2298             i->attach(i);
2299
2300     if (s->monitor_source)
2301         pa_source_attach_within_thread(s->monitor_source);
2302 }
2303
2304 /* Called from IO thread */
2305 void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
2306     pa_sink_assert_ref(s);
2307     pa_sink_assert_io_context(s);
2308     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
2309
2310     if (s->thread_info.state == PA_SINK_SUSPENDED)
2311         return;
2312
2313     if (nbytes == (size_t) -1)
2314         nbytes = s->thread_info.max_rewind;
2315
2316     nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
2317
2318     if (s->thread_info.rewind_requested &&
2319         nbytes <= s->thread_info.rewind_nbytes)
2320         return;
2321
2322     s->thread_info.rewind_nbytes = nbytes;
2323     s->thread_info.rewind_requested = TRUE;
2324
2325     if (s->request_rewind)
2326         s->request_rewind(s);
2327 }
2328
2329 /* Called from IO thread */
2330 pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
2331     pa_usec_t result = (pa_usec_t) -1;
2332     pa_sink_input *i;
2333     void *state = NULL;
2334     pa_usec_t monitor_latency;
2335
2336     pa_sink_assert_ref(s);
2337     pa_sink_assert_io_context(s);
2338
2339     if (!(s->flags & PA_SINK_DYNAMIC_LATENCY))
2340         return PA_CLAMP(s->thread_info.fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
2341
2342     if (s->thread_info.requested_latency_valid)
2343         return s->thread_info.requested_latency;
2344
2345     PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
2346         if (i->thread_info.requested_sink_latency != (pa_usec_t) -1 &&
2347             (result == (pa_usec_t) -1 || result > i->thread_info.requested_sink_latency))
2348             result = i->thread_info.requested_sink_latency;
2349
2350     monitor_latency = pa_source_get_requested_latency_within_thread(s->monitor_source);
2351
2352     if (monitor_latency != (pa_usec_t) -1 &&
2353         (result == (pa_usec_t) -1 || result > monitor_latency))
2354         result = monitor_latency;
2355
2356     if (result != (pa_usec_t) -1)
2357         result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
2358
2359     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
2360         /* Only cache if properly initialized */
2361         s->thread_info.requested_latency = result;
2362         s->thread_info.requested_latency_valid = TRUE;
2363     }
2364
2365     return result;
2366 }
2367
2368 /* Called from main thread */
2369 pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
2370     pa_usec_t usec = 0;
2371
2372     pa_sink_assert_ref(s);
2373     pa_assert_ctl_context();
2374     pa_assert(PA_SINK_IS_LINKED(s->state));
2375
2376     if (s->state == PA_SINK_SUSPENDED)
2377         return 0;
2378
2379     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
2380     return usec;
2381 }
2382
2383 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
2384 void pa_sink_set_max_rewind_within_thread(pa_sink *s, size_t max_rewind) {
2385     pa_sink_input *i;
2386     void *state = NULL;
2387
2388     pa_sink_assert_ref(s);
2389     pa_sink_assert_io_context(s);
2390
2391     if (max_rewind == s->thread_info.max_rewind)
2392         return;
2393
2394     s->thread_info.max_rewind = max_rewind;
2395
2396     if (PA_SINK_IS_LINKED(s->thread_info.state))
2397         PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
2398             pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
2399
2400     if (s->monitor_source)
2401         pa_source_set_max_rewind_within_thread(s->monitor_source, s->thread_info.max_rewind);
2402 }
2403
2404 /* Called from main thread */
2405 void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
2406     pa_sink_assert_ref(s);
2407     pa_assert_ctl_context();
2408
2409     if (PA_SINK_IS_LINKED(s->state))
2410         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
2411     else
2412         pa_sink_set_max_rewind_within_thread(s, max_rewind);
2413 }
2414
2415 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
2416 void pa_sink_set_max_request_within_thread(pa_sink *s, size_t max_request) {
2417     void *state = NULL;
2418
2419     pa_sink_assert_ref(s);
2420     pa_sink_assert_io_context(s);
2421
2422     if (max_request == s->thread_info.max_request)
2423         return;
2424
2425     s->thread_info.max_request = max_request;
2426
2427     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
2428         pa_sink_input *i;
2429
2430         PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
2431             pa_sink_input_update_max_request(i, s->thread_info.max_request);
2432     }
2433 }
2434
2435 /* Called from main thread */
2436 void pa_sink_set_max_request(pa_sink *s, size_t max_request) {
2437     pa_sink_assert_ref(s);
2438     pa_assert_ctl_context();
2439
2440     if (PA_SINK_IS_LINKED(s->state))
2441         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MAX_REQUEST, NULL, max_request, NULL) == 0);
2442     else
2443         pa_sink_set_max_request_within_thread(s, max_request);
2444 }
2445
2446 /* Called from IO thread */
2447 void pa_sink_invalidate_requested_latency(pa_sink *s, pa_bool_t dynamic) {
2448     pa_sink_input *i;
2449     void *state = NULL;
2450
2451     pa_sink_assert_ref(s);
2452     pa_sink_assert_io_context(s);
2453
2454     if ((s->flags & PA_SINK_DYNAMIC_LATENCY))
2455         s->thread_info.requested_latency_valid = FALSE;
2456     else if (dynamic)
2457         return;
2458
2459     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
2460
2461         if (s->update_requested_latency)
2462             s->update_requested_latency(s);
2463
2464         PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
2465             if (i->update_sink_requested_latency)
2466                 i->update_sink_requested_latency(i);
2467     }
2468 }
2469
2470 /* Called from main thread */
2471 void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
2472     pa_sink_assert_ref(s);
2473     pa_assert_ctl_context();
2474
2475     /* min_latency == 0:           no limit
2476      * min_latency anything else:  specified limit
2477      *
2478      * Similar for max_latency */
2479
2480     if (min_latency < ABSOLUTE_MIN_LATENCY)
2481         min_latency = ABSOLUTE_MIN_LATENCY;
2482
2483     if (max_latency <= 0 ||
2484         max_latency > ABSOLUTE_MAX_LATENCY)
2485         max_latency = ABSOLUTE_MAX_LATENCY;
2486
2487     pa_assert(min_latency <= max_latency);
2488
2489     /* Hmm, let's see if someone forgot to set PA_SINK_DYNAMIC_LATENCY here... */
2490     pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
2491                max_latency == ABSOLUTE_MAX_LATENCY) ||
2492               (s->flags & PA_SINK_DYNAMIC_LATENCY));
2493
2494     if (PA_SINK_IS_LINKED(s->state)) {
2495         pa_usec_t r[2];
2496
2497         r[0] = min_latency;
2498         r[1] = max_latency;
2499
2500         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
2501     } else
2502         pa_sink_set_latency_range_within_thread(s, min_latency, max_latency);
2503 }
2504
2505 /* Called from main thread */
2506 void pa_sink_get_latency_range(pa_sink *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
2507    pa_sink_assert_ref(s);
2508    pa_assert_ctl_context();
2509    pa_assert(min_latency);
2510    pa_assert(max_latency);
2511
2512    if (PA_SINK_IS_LINKED(s->state)) {
2513        pa_usec_t r[2] = { 0, 0 };
2514
2515        pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
2516
2517        *min_latency = r[0];
2518        *max_latency = r[1];
2519    } else {
2520        *min_latency = s->thread_info.min_latency;
2521        *max_latency = s->thread_info.max_latency;
2522    }
2523 }
2524
2525 /* Called from IO thread */
2526 void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
2527     pa_sink_assert_ref(s);
2528     pa_sink_assert_io_context(s);
2529
2530     pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
2531     pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
2532     pa_assert(min_latency <= max_latency);
2533
2534     /* Hmm, let's see if someone forgot to set PA_SINK_DYNAMIC_LATENCY here... */
2535     pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
2536                max_latency == ABSOLUTE_MAX_LATENCY) ||
2537               (s->flags & PA_SINK_DYNAMIC_LATENCY));
2538
2539     if (s->thread_info.min_latency == min_latency &&
2540         s->thread_info.max_latency == max_latency)
2541         return;
2542
2543     s->thread_info.min_latency = min_latency;
2544     s->thread_info.max_latency = max_latency;
2545
2546     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
2547         pa_sink_input *i;
2548         void *state = NULL;
2549
2550         PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
2551             if (i->update_sink_latency_range)
2552                 i->update_sink_latency_range(i);
2553     }
2554
2555     pa_sink_invalidate_requested_latency(s, FALSE);
2556
2557     pa_source_set_latency_range_within_thread(s->monitor_source, min_latency, max_latency);
2558 }
2559
2560 /* Called from main thread */
2561 void pa_sink_set_fixed_latency(pa_sink *s, pa_usec_t latency) {
2562     pa_sink_assert_ref(s);
2563     pa_assert_ctl_context();
2564
2565     if (s->flags & PA_SINK_DYNAMIC_LATENCY) {
2566         pa_assert(latency == 0);
2567         return;
2568     }
2569
2570     if (latency < ABSOLUTE_MIN_LATENCY)
2571         latency = ABSOLUTE_MIN_LATENCY;
2572
2573     if (latency > ABSOLUTE_MAX_LATENCY)
2574         latency = ABSOLUTE_MAX_LATENCY;
2575
2576     if (PA_SINK_IS_LINKED(s->state))
2577         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_FIXED_LATENCY, NULL, (int64_t) latency, NULL) == 0);
2578     else
2579         s->thread_info.fixed_latency = latency;
2580
2581     pa_source_set_fixed_latency(s->monitor_source, latency);
2582 }
2583
2584 /* Called from main thread */
2585 pa_usec_t pa_sink_get_fixed_latency(pa_sink *s) {
2586     pa_usec_t latency;
2587
2588     pa_sink_assert_ref(s);
2589     pa_assert_ctl_context();
2590
2591     if (s->flags & PA_SINK_DYNAMIC_LATENCY)
2592         return 0;
2593
2594     if (PA_SINK_IS_LINKED(s->state))
2595         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_FIXED_LATENCY, &latency, 0, NULL) == 0);
2596     else
2597         latency = s->thread_info.fixed_latency;
2598
2599     return latency;
2600 }
2601
2602 /* Called from IO thread */
2603 void pa_sink_set_fixed_latency_within_thread(pa_sink *s, pa_usec_t latency) {
2604     pa_sink_assert_ref(s);
2605     pa_sink_assert_io_context(s);
2606
2607     if (s->flags & PA_SINK_DYNAMIC_LATENCY) {
2608         pa_assert(latency == 0);
2609         return;
2610     }
2611
2612     pa_assert(latency >= ABSOLUTE_MIN_LATENCY);
2613     pa_assert(latency <= ABSOLUTE_MAX_LATENCY);
2614
2615     if (s->thread_info.fixed_latency == latency)
2616         return;
2617
2618     s->thread_info.fixed_latency = latency;
2619
2620     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
2621         pa_sink_input *i;
2622         void *state = NULL;
2623
2624         PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state)
2625             if (i->update_sink_fixed_latency)
2626                 i->update_sink_fixed_latency(i);
2627     }
2628
2629     pa_sink_invalidate_requested_latency(s, FALSE);
2630
2631     pa_source_set_fixed_latency_within_thread(s->monitor_source, latency);
2632 }
2633
2634 /* Called from main context */
2635 size_t pa_sink_get_max_rewind(pa_sink *s) {
2636     size_t r;
2637     pa_sink_assert_ref(s);
2638     pa_assert_ctl_context();
2639
2640     if (!PA_SINK_IS_LINKED(s->state))
2641         return s->thread_info.max_rewind;
2642
2643     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
2644
2645     return r;
2646 }
2647
2648 /* Called from main context */
2649 size_t pa_sink_get_max_request(pa_sink *s) {
2650     size_t r;
2651     pa_sink_assert_ref(s);
2652     pa_assert_ctl_context();
2653
2654     if (!PA_SINK_IS_LINKED(s->state))
2655         return s->thread_info.max_request;
2656
2657     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REQUEST, &r, 0, NULL) == 0);
2658
2659     return r;
2660 }
2661
2662 /* Called from main context */
2663 int pa_sink_set_port(pa_sink *s, const char *name, pa_bool_t save) {
2664     pa_device_port *port;
2665     int ret;
2666     pa_sink_assert_ref(s);
2667     pa_assert_ctl_context();
2668
2669     if (!s->set_port) {
2670         pa_log_debug("set_port() operation not implemented for sink %u \"%s\"", s->index, s->name);
2671         return -PA_ERR_NOTIMPLEMENTED;
2672     }
2673
2674     if (!s->ports)
2675         return -PA_ERR_NOENTITY;
2676
2677     if (!(port = pa_hashmap_get(s->ports, name)))
2678         return -PA_ERR_NOENTITY;
2679
2680     if (s->active_port == port) {
2681         s->save_port = s->save_port || save;
2682         return 0;
2683     }
2684
2685     if (s->flags & PA_SINK_SYNC_VOLUME) {
2686         struct sink_message_set_port msg = { .port = port, .ret = 0 };
2687         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT, &msg, 0, NULL) == 0);
2688         ret = msg.ret;
2689     }
2690     else
2691         ret = s->set_port(s, port);
2692
2693     if (ret < 0)
2694         return -PA_ERR_NOENTITY;
2695
2696     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
2697
2698     pa_log_info("Changed port of sink %u \"%s\" to %s", s->index, s->name, port->name);
2699
2700     s->active_port = port;
2701     s->save_port = save;
2702
2703     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], s);
2704
2705     return 0;
2706 }
2707
2708 pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink) {
2709     const char *ff, *c, *t = NULL, *s = "", *profile, *bus;
2710
2711     pa_assert(p);
2712
2713     if (pa_proplist_contains(p, PA_PROP_DEVICE_ICON_NAME))
2714         return TRUE;
2715
2716     if ((ff = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) {
2717
2718         if (pa_streq(ff, "microphone"))
2719             t = "audio-input-microphone";
2720         else if (pa_streq(ff, "webcam"))
2721             t = "camera-web";
2722         else if (pa_streq(ff, "computer"))
2723             t = "computer";
2724         else if (pa_streq(ff, "handset"))
2725             t = "phone";
2726         else if (pa_streq(ff, "portable"))
2727             t = "multimedia-player";
2728         else if (pa_streq(ff, "tv"))
2729             t = "video-display";
2730
2731         /*
2732          * The following icons are not part of the icon naming spec,
2733          * because Rodney Dawes sucks as the maintainer of that spec.
2734          *
2735          * http://lists.freedesktop.org/archives/xdg/2009-May/010397.html
2736          */
2737         else if (pa_streq(ff, "headset"))
2738             t = "audio-headset";
2739         else if (pa_streq(ff, "headphone"))
2740             t = "audio-headphones";
2741         else if (pa_streq(ff, "speaker"))
2742             t = "audio-speakers";
2743         else if (pa_streq(ff, "hands-free"))
2744             t = "audio-handsfree";
2745     }
2746
2747     if (!t)
2748         if ((c = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
2749             if (pa_streq(c, "modem"))
2750                 t = "modem";
2751
2752     if (!t) {
2753         if (is_sink)
2754             t = "audio-card";
2755         else
2756             t = "audio-input-microphone";
2757     }
2758
2759     if ((profile = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
2760         if (strstr(profile, "analog"))
2761             s = "-analog";
2762         else if (strstr(profile, "iec958"))
2763             s = "-iec958";
2764         else if (strstr(profile, "hdmi"))
2765             s = "-hdmi";
2766     }
2767
2768     bus = pa_proplist_gets(p, PA_PROP_DEVICE_BUS);
2769
2770     pa_proplist_setf(p, PA_PROP_DEVICE_ICON_NAME, "%s%s%s%s", t, pa_strempty(s), bus ? "-" : "", pa_strempty(bus));
2771
2772     return TRUE;
2773 }
2774
2775 pa_bool_t pa_device_init_description(pa_proplist *p) {
2776     const char *s, *d = NULL, *k;
2777     pa_assert(p);
2778
2779     if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
2780         return TRUE;
2781
2782     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
2783         if (pa_streq(s, "internal"))
2784             d = _("Internal Audio");
2785
2786     if (!d)
2787         if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
2788             if (pa_streq(s, "modem"))
2789                 d = _("Modem");
2790
2791     if (!d)
2792         d = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME);
2793
2794     if (!d)
2795         return FALSE;
2796
2797     k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
2798
2799     if (d && k)
2800         pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, _("%s %s"), d, k);
2801     else if (d)
2802         pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
2803
2804     return TRUE;
2805 }
2806
2807 pa_bool_t pa_device_init_intended_roles(pa_proplist *p) {
2808     const char *s;
2809     pa_assert(p);
2810
2811     if (pa_proplist_contains(p, PA_PROP_DEVICE_INTENDED_ROLES))
2812         return TRUE;
2813
2814     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
2815         if (pa_streq(s, "handset") || pa_streq(s, "hands-free")
2816             || pa_streq(s, "headset")) {
2817             pa_proplist_sets(p, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
2818             return TRUE;
2819         }
2820
2821     return FALSE;
2822 }
2823
2824 unsigned pa_device_init_priority(pa_proplist *p) {
2825     const char *s;
2826     unsigned priority = 0;
2827
2828     pa_assert(p);
2829
2830     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS))) {
2831
2832         if (pa_streq(s, "sound"))
2833             priority += 9000;
2834         else if (!pa_streq(s, "modem"))
2835             priority += 1000;
2836     }
2837
2838     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) {
2839
2840         if (pa_streq(s, "internal"))
2841             priority += 900;
2842         else if (pa_streq(s, "speaker"))
2843             priority += 500;
2844         else if (pa_streq(s, "headphone"))
2845             priority += 400;
2846     }
2847
2848     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_BUS))) {
2849
2850         if (pa_streq(s, "pci"))
2851             priority += 50;
2852         else if (pa_streq(s, "usb"))
2853             priority += 40;
2854         else if (pa_streq(s, "bluetooth"))
2855             priority += 30;
2856     }
2857
2858     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
2859
2860         if (pa_startswith(s, "analog-"))
2861             priority += 9;
2862         else if (pa_startswith(s, "iec958-"))
2863             priority += 8;
2864     }
2865
2866     return priority;
2867 }
2868
2869 PA_STATIC_FLIST_DECLARE(pa_sink_volume_change, 0, pa_xfree);
2870
2871 /* Called from the IO thread. */
2872 static pa_sink_volume_change *pa_sink_volume_change_new(pa_sink *s) {
2873     pa_sink_volume_change *c;
2874     if (!(c = pa_flist_pop(PA_STATIC_FLIST_GET(pa_sink_volume_change))))
2875         c = pa_xnew(pa_sink_volume_change, 1);
2876
2877     PA_LLIST_INIT(pa_sink_volume_change, c);
2878     c->at = 0;
2879     pa_cvolume_reset(&c->hw_volume, s->sample_spec.channels);
2880     return c;
2881 }
2882
2883 /* Called from the IO thread. */
2884 static void pa_sink_volume_change_free(pa_sink_volume_change *c) {
2885     pa_assert(c);
2886     if (pa_flist_push(PA_STATIC_FLIST_GET(pa_sink_volume_change), c) < 0)
2887         pa_xfree(c);
2888 }
2889
2890 /* Called from the IO thread. */
2891 void pa_sink_volume_change_push(pa_sink *s) {
2892     pa_sink_volume_change *c = NULL;
2893     pa_sink_volume_change *nc = NULL;
2894     uint32_t safety_margin = s->thread_info.volume_change_safety_margin;
2895
2896     const char *direction = NULL;
2897
2898     pa_assert(s);
2899     nc = pa_sink_volume_change_new(s);
2900
2901     /* NOTE: There is already more different volumes in pa_sink that I can remember.
2902      *       Adding one more volume for HW would get us rid of this, but I am trying
2903      *       to survive with the ones we already have. */
2904     pa_sw_cvolume_divide(&nc->hw_volume, &s->real_volume, &s->soft_volume);
2905
2906     if (!s->thread_info.volume_changes && pa_cvolume_equal(&nc->hw_volume, &s->thread_info.current_hw_volume)) {
2907         pa_log_debug("Volume not changing");
2908         pa_sink_volume_change_free(nc);
2909         return;
2910     }
2911
2912     nc->at = pa_sink_get_latency_within_thread(s);
2913     nc->at += pa_rtclock_now() + s->thread_info.volume_change_extra_delay;
2914
2915     if (s->thread_info.volume_changes_tail) {
2916         for (c = s->thread_info.volume_changes_tail; c; c = c->prev) {
2917             /* If volume is going up let's do it a bit late. If it is going
2918              * down let's do it a bit early. */
2919             if (pa_cvolume_avg(&nc->hw_volume) > pa_cvolume_avg(&c->hw_volume)) {
2920                 if (nc->at + safety_margin > c->at) {
2921                     nc->at += safety_margin;
2922                     direction = "up";
2923                     break;
2924                 }
2925             }
2926             else if (nc->at - safety_margin > c->at) {
2927                     nc->at -= safety_margin;
2928                     direction = "down";
2929                     break;
2930             }
2931         }
2932     }
2933
2934     if (c == NULL) {
2935         if (pa_cvolume_avg(&nc->hw_volume) > pa_cvolume_avg(&s->thread_info.current_hw_volume)) {
2936             nc->at += safety_margin;
2937             direction = "up";
2938         } else {
2939             nc->at -= safety_margin;
2940             direction = "down";
2941         }
2942         PA_LLIST_PREPEND(pa_sink_volume_change, s->thread_info.volume_changes, nc);
2943     }
2944     else {
2945         PA_LLIST_INSERT_AFTER(pa_sink_volume_change, s->thread_info.volume_changes, c, nc);
2946     }
2947
2948     pa_log_debug("Volume going %s to %d at %llu", direction, pa_cvolume_avg(&nc->hw_volume), nc->at);
2949
2950     /* We can ignore volume events that came earlier but should happen later than this. */
2951     PA_LLIST_FOREACH(c, nc->next) {
2952         pa_log_debug("Volume change to %d at %llu was dropped", pa_cvolume_avg(&c->hw_volume), c->at);
2953         pa_sink_volume_change_free(c);
2954     }
2955     nc->next = NULL;
2956     s->thread_info.volume_changes_tail = nc;
2957 }
2958
2959 /* Called from the IO thread. */
2960 static void pa_sink_volume_change_flush(pa_sink *s) {
2961     pa_sink_volume_change *c = s->thread_info.volume_changes;
2962     pa_assert(s);
2963     s->thread_info.volume_changes = NULL;
2964     s->thread_info.volume_changes_tail = NULL;
2965     while (c) {
2966         pa_sink_volume_change *next = c->next;
2967         pa_sink_volume_change_free(c);
2968         c = next;
2969     }
2970 }
2971
2972 /* Called from the IO thread. */
2973 pa_bool_t pa_sink_volume_change_apply(pa_sink *s, pa_usec_t *usec_to_next) {
2974     pa_usec_t now = pa_rtclock_now();
2975     pa_bool_t ret = FALSE;
2976
2977     pa_assert(s);
2978     pa_assert(s->write_volume);
2979
2980     while (s->thread_info.volume_changes && now >= s->thread_info.volume_changes->at) {
2981         pa_sink_volume_change *c = s->thread_info.volume_changes;
2982         PA_LLIST_REMOVE(pa_sink_volume_change, s->thread_info.volume_changes, c);
2983         pa_log_debug("Volume change to %d at %llu was written %llu usec late", pa_cvolume_avg(&c->hw_volume), c->at, now - c->at);
2984         ret = TRUE;
2985         s->thread_info.current_hw_volume = c->hw_volume;
2986         pa_sink_volume_change_free(c);
2987     }
2988
2989     if (s->write_volume && ret)
2990         s->write_volume(s);
2991
2992     if (s->thread_info.volume_changes) {
2993         if (usec_to_next)
2994             *usec_to_next = s->thread_info.volume_changes->at - now;
2995         if (pa_log_ratelimit(PA_LOG_DEBUG))
2996             pa_log_debug("Next volume change in %lld usec", s->thread_info.volume_changes->at - now);
2997     }
2998     else {
2999         if (usec_to_next)
3000             *usec_to_next = 0;
3001         s->thread_info.volume_changes_tail = NULL;
3002     }
3003     return ret;
3004 }
3005
3006 /* Called from the IO thread. */
3007 static void pa_sink_volume_change_rewind(pa_sink *s, size_t nbytes) {
3008     /* All the queued volume events later than current latency are shifted to happen earlier. */
3009     pa_sink_volume_change *c;
3010     pa_volume_t prev_vol = pa_cvolume_avg(&s->thread_info.current_hw_volume);
3011     pa_usec_t rewound = pa_bytes_to_usec(nbytes, &s->sample_spec);
3012     pa_usec_t limit = pa_sink_get_latency_within_thread(s);
3013
3014     pa_log_debug("latency = %lld", limit);
3015     limit += pa_rtclock_now() + s->thread_info.volume_change_extra_delay;
3016
3017     PA_LLIST_FOREACH(c, s->thread_info.volume_changes) {
3018         pa_usec_t modified_limit = limit;
3019         if (prev_vol > pa_cvolume_avg(&c->hw_volume))
3020             modified_limit -= s->thread_info.volume_change_safety_margin;
3021         else
3022             modified_limit += s->thread_info.volume_change_safety_margin;
3023         if (c->at > modified_limit) {
3024             c->at -= rewound;
3025             if (c->at < modified_limit)
3026                 c->at = modified_limit;
3027         }
3028         prev_vol = pa_cvolume_avg(&c->hw_volume);
3029     }
3030     pa_sink_volume_change_apply(s, NULL);
3031 }