Allow calling pa_{sink|source}_update_proplist() without an actual proprlist
[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
38 #include <pulsecore/sink-input.h>
39 #include <pulsecore/namereg.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/sample-util.h>
42 #include <pulsecore/core-subscribe.h>
43 #include <pulsecore/log.h>
44 #include <pulsecore/macro.h>
45 #include <pulsecore/play-memblockq.h>
46
47 #include "sink.h"
48
49 #define MAX_MIX_CHANNELS 32
50 #define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
51 #define ABSOLUTE_MIN_LATENCY (500)
52 #define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
53 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
54
55 static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
56
57 static void sink_free(pa_object *s);
58
59 pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data) {
60     pa_assert(data);
61
62     memset(data, 0, sizeof(*data));
63     data->proplist = pa_proplist_new();
64
65     return data;
66 }
67
68 void pa_sink_new_data_set_name(pa_sink_new_data *data, const char *name) {
69     pa_assert(data);
70
71     pa_xfree(data->name);
72     data->name = pa_xstrdup(name);
73 }
74
75 void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_spec *spec) {
76     pa_assert(data);
77
78     if ((data->sample_spec_is_set = !!spec))
79         data->sample_spec = *spec;
80 }
81
82 void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map) {
83     pa_assert(data);
84
85     if ((data->channel_map_is_set = !!map))
86         data->channel_map = *map;
87 }
88
89 void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume) {
90     pa_assert(data);
91
92     if ((data->volume_is_set = !!volume))
93         data->volume = *volume;
94 }
95
96 void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute) {
97     pa_assert(data);
98
99     data->muted_is_set = TRUE;
100     data->muted = !!mute;
101 }
102
103 void pa_sink_new_data_done(pa_sink_new_data *data) {
104     pa_assert(data);
105
106     pa_xfree(data->name);
107     pa_proplist_free(data->proplist);
108 }
109
110 /* Called from main context */
111 static void reset_callbacks(pa_sink *s) {
112     pa_assert(s);
113
114     s->set_state = NULL;
115     s->get_volume = NULL;
116     s->set_volume = NULL;
117     s->get_mute = NULL;
118     s->set_mute = NULL;
119     s->request_rewind = NULL;
120     s->update_requested_latency = NULL;
121 }
122
123 /* Called from main context */
124 pa_sink* pa_sink_new(
125         pa_core *core,
126         pa_sink_new_data *data,
127         pa_sink_flags_t flags) {
128
129     pa_sink *s;
130     const char *name;
131     char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
132     pa_source_new_data source_data;
133     const char *dn;
134     char *pt;
135
136     pa_assert(core);
137     pa_assert(data);
138     pa_assert(data->name);
139
140     s = pa_msgobject_new(pa_sink);
141
142     if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) {
143         pa_xfree(s);
144         return NULL;
145     }
146
147     pa_sink_new_data_set_name(data, name);
148
149     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW], data) < 0) {
150         pa_xfree(s);
151         pa_namereg_unregister(core, name);
152         return NULL;
153     }
154
155     pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
156     pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
157
158     pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
159
160     if (!data->channel_map_is_set)
161         pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
162
163     pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
164     pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
165
166     if (!data->volume_is_set)
167         pa_cvolume_reset(&data->volume, data->sample_spec.channels);
168
169     pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
170     pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
171
172     if (!data->muted_is_set)
173         data->muted = FALSE;
174
175     if (data->card)
176         pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
177
178     pa_device_init_description(data->proplist);
179     pa_device_init_icon(data->proplist, TRUE);
180
181     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {
182         pa_xfree(s);
183         pa_namereg_unregister(core, name);
184         return NULL;
185     }
186
187     s->parent.parent.free = sink_free;
188     s->parent.process_msg = pa_sink_process_msg;
189
190     s->core = core;
191     s->state = PA_SINK_INIT;
192     s->flags = flags;
193     s->name = pa_xstrdup(name);
194     s->proplist = pa_proplist_copy(data->proplist);
195     s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
196     s->module = data->module;
197     s->card = data->card;
198
199     s->sample_spec = data->sample_spec;
200     s->channel_map = data->channel_map;
201
202     s->inputs = pa_idxset_new(NULL, NULL);
203     s->n_corked = 0;
204
205     s->virtual_volume = data->volume;
206     pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
207     s->base_volume = PA_VOLUME_NORM;
208     s->n_volume_steps = PA_VOLUME_NORM+1;
209     s->muted = data->muted;
210     s->refresh_volume = s->refresh_muted = FALSE;
211
212     reset_callbacks(s);
213     s->userdata = NULL;
214
215     s->asyncmsgq = NULL;
216     s->rtpoll = NULL;
217
218     pa_silence_memchunk_get(
219             &core->silence_cache,
220             core->mempool,
221             &s->silence,
222             &s->sample_spec,
223             0);
224
225     s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
226     s->thread_info.soft_volume =  s->soft_volume;
227     s->thread_info.soft_muted = s->muted;
228     s->thread_info.state = s->state;
229     s->thread_info.rewind_nbytes = 0;
230     s->thread_info.rewind_requested = FALSE;
231     s->thread_info.max_rewind = 0;
232     s->thread_info.max_request = 0;
233     s->thread_info.requested_latency_valid = FALSE;
234     s->thread_info.requested_latency = 0;
235     s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
236     s->thread_info.max_latency = DEFAULT_MIN_LATENCY;
237
238     pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
239
240     if (s->card)
241         pa_assert_se(pa_idxset_put(s->card->sinks, s, NULL) >= 0);
242
243     pt = pa_proplist_to_string_sep(s->proplist, "\n    ");
244     pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s\n    %s",
245                 s->index,
246                 s->name,
247                 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
248                 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
249                 pt);
250     pa_xfree(pt);
251
252     pa_source_new_data_init(&source_data);
253     pa_source_new_data_set_sample_spec(&source_data, &s->sample_spec);
254     pa_source_new_data_set_channel_map(&source_data, &s->channel_map);
255     source_data.name = pa_sprintf_malloc("%s.monitor", name);
256     source_data.driver = data->driver;
257     source_data.module = data->module;
258     source_data.card = data->card;
259
260     dn = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
261     pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
262     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
263
264     s->monitor_source = pa_source_new(core, &source_data, PA_SOURCE_LATENCY);
265
266     pa_source_new_data_done(&source_data);
267
268     if (!s->monitor_source) {
269         pa_sink_unlink(s);
270         pa_sink_unref(s);
271         return NULL;
272     }
273
274     s->monitor_source->monitor_of = s;
275
276     pa_source_set_latency_range(s->monitor_source, s->thread_info.min_latency, s->thread_info.max_latency);
277     pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
278
279     return s;
280 }
281
282 /* Called from main context */
283 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
284     int ret;
285     pa_bool_t suspend_change;
286     pa_sink_state_t original_state;
287
288     pa_assert(s);
289
290     if (s->state == state)
291         return 0;
292
293     original_state = s->state;
294
295     suspend_change =
296         (original_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state)) ||
297         (PA_SINK_IS_OPENED(original_state) && state == PA_SINK_SUSPENDED);
298
299     if (s->set_state)
300         if ((ret = s->set_state(s, state)) < 0)
301             return ret;
302
303     if (s->asyncmsgq)
304         if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
305
306             if (s->set_state)
307                 s->set_state(s, original_state);
308
309             return ret;
310         }
311
312     s->state = state;
313
314     if (state != PA_SINK_UNLINKED) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
315         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
316         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
317     }
318
319     if (suspend_change) {
320         pa_sink_input *i;
321         uint32_t idx;
322
323         /* We're suspending or resuming, tell everyone about it */
324
325         for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx)))
326             if (s->state == PA_SINK_SUSPENDED &&
327                 (i->flags & PA_SINK_INPUT_FAIL_ON_SUSPEND))
328                 pa_sink_input_kill(i);
329             else if (i->suspend)
330                 i->suspend(i, state == PA_SINK_SUSPENDED);
331
332         if (s->monitor_source)
333             pa_source_sync_suspend(s->monitor_source);
334     }
335
336     return 0;
337 }
338
339 /* Called from main context */
340 void pa_sink_put(pa_sink* s) {
341     pa_sink_assert_ref(s);
342
343     pa_assert(s->state == PA_SINK_INIT);
344
345     /* The following fields must be initialized properly when calling _put() */
346     pa_assert(s->asyncmsgq);
347     pa_assert(s->rtpoll);
348     pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
349
350     if (!(s->flags & PA_SINK_HW_VOLUME_CTRL)) {
351         s->flags |= PA_SINK_DECIBEL_VOLUME;
352
353         s->thread_info.soft_volume = s->soft_volume;
354         s->thread_info.soft_muted = s->muted;
355     }
356
357     if (s->flags & PA_SINK_DECIBEL_VOLUME)
358         s->n_volume_steps = PA_VOLUME_NORM+1;
359
360     if (s->core->flat_volumes)
361         if (s->flags & PA_SINK_DECIBEL_VOLUME)
362             s->flags |= PA_SINK_FLAT_VOLUME;
363
364     pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
365
366     pa_source_put(s->monitor_source);
367
368     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
369     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s);
370 }
371
372 /* Called from main context */
373 void pa_sink_unlink(pa_sink* s) {
374     pa_bool_t linked;
375     pa_sink_input *i, *j = NULL;
376
377     pa_assert(s);
378
379     /* Please note that pa_sink_unlink() does more than simply
380      * reversing pa_sink_put(). It also undoes the registrations
381      * already done in pa_sink_new()! */
382
383     /* All operations here shall be idempotent, i.e. pa_sink_unlink()
384      * may be called multiple times on the same sink without bad
385      * effects. */
386
387     linked = PA_SINK_IS_LINKED(s->state);
388
389     if (linked)
390         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
391
392     if (s->state != PA_SINK_UNLINKED)
393         pa_namereg_unregister(s->core, s->name);
394     pa_idxset_remove_by_data(s->core->sinks, s, NULL);
395
396     if (s->card)
397         pa_idxset_remove_by_data(s->card->sinks, s, NULL);
398
399     while ((i = pa_idxset_first(s->inputs, NULL))) {
400         pa_assert(i != j);
401         pa_sink_input_kill(i);
402         j = i;
403     }
404
405     if (linked)
406         sink_set_state(s, PA_SINK_UNLINKED);
407     else
408         s->state = PA_SINK_UNLINKED;
409
410     reset_callbacks(s);
411
412     if (s->monitor_source)
413         pa_source_unlink(s->monitor_source);
414
415     if (linked) {
416         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
417         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
418     }
419 }
420
421 /* Called from main context */
422 static void sink_free(pa_object *o) {
423     pa_sink *s = PA_SINK(o);
424     pa_sink_input *i;
425
426     pa_assert(s);
427     pa_assert(pa_sink_refcnt(s) == 0);
428
429     if (PA_SINK_IS_LINKED(s->state))
430         pa_sink_unlink(s);
431
432     pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
433
434     if (s->monitor_source) {
435         pa_source_unref(s->monitor_source);
436         s->monitor_source = NULL;
437     }
438
439     pa_idxset_free(s->inputs, NULL, NULL);
440
441     while ((i = pa_hashmap_steal_first(s->thread_info.inputs)))
442         pa_sink_input_unref(i);
443
444     pa_hashmap_free(s->thread_info.inputs, NULL, NULL);
445
446     if (s->silence.memblock)
447         pa_memblock_unref(s->silence.memblock);
448
449     pa_xfree(s->name);
450     pa_xfree(s->driver);
451
452     if (s->proplist)
453         pa_proplist_free(s->proplist);
454
455     pa_xfree(s);
456 }
457
458 /* Called from main context */
459 void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
460     pa_sink_assert_ref(s);
461
462     s->asyncmsgq = q;
463
464     if (s->monitor_source)
465         pa_source_set_asyncmsgq(s->monitor_source, q);
466 }
467
468 /* Called from main context */
469 void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
470     pa_sink_assert_ref(s);
471
472     s->rtpoll = p;
473     if (s->monitor_source)
474         pa_source_set_rtpoll(s->monitor_source, p);
475 }
476
477 /* Called from main context */
478 int pa_sink_update_status(pa_sink*s) {
479     pa_sink_assert_ref(s);
480     pa_assert(PA_SINK_IS_LINKED(s->state));
481
482     if (s->state == PA_SINK_SUSPENDED)
483         return 0;
484
485     return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
486 }
487
488 /* Called from main context */
489 int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
490     pa_sink_assert_ref(s);
491     pa_assert(PA_SINK_IS_LINKED(s->state));
492
493     if (suspend)
494         return sink_set_state(s, PA_SINK_SUSPENDED);
495     else
496         return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
497 }
498
499 /* Called from main context */
500 pa_queue *pa_sink_move_all_start(pa_sink *s) {
501     pa_queue *q;
502     pa_sink_input *i, *n;
503     uint32_t idx;
504
505     pa_sink_assert_ref(s);
506     pa_assert(PA_SINK_IS_LINKED(s->state));
507
508     q = pa_queue_new();
509
510     for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = n) {
511         n = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx));
512
513         if (pa_sink_input_start_move(i) >= 0)
514             pa_queue_push(q, pa_sink_input_ref(i));
515     }
516
517     return q;
518 }
519
520 /* Called from main context */
521 void pa_sink_move_all_finish(pa_sink *s, pa_queue *q, pa_bool_t save) {
522     pa_sink_input *i;
523
524     pa_sink_assert_ref(s);
525     pa_assert(PA_SINK_IS_LINKED(s->state));
526     pa_assert(q);
527
528     while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
529         if (pa_sink_input_finish_move(i, s, save) < 0)
530             pa_sink_input_kill(i);
531
532         pa_sink_input_unref(i);
533     }
534
535     pa_queue_free(q, NULL, NULL);
536 }
537
538 /* Called from main context */
539 void pa_sink_move_all_fail(pa_queue *q) {
540     pa_sink_input *i;
541     pa_assert(q);
542
543     while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
544         if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_OK) {
545             pa_sink_input_kill(i);
546             pa_sink_input_unref(i);
547         }
548     }
549
550     pa_queue_free(q, NULL, NULL);
551 }
552
553 /* Called from IO thread context */
554 void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
555     pa_sink_input *i;
556     void *state = NULL;
557     pa_sink_assert_ref(s);
558     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
559
560     /* If nobody requested this and this is actually no real rewind
561      * then we can short cut this */
562     if (!s->thread_info.rewind_requested && nbytes <= 0)
563         return;
564
565     s->thread_info.rewind_nbytes = 0;
566     s->thread_info.rewind_requested = FALSE;
567
568     if (s->thread_info.state == PA_SINK_SUSPENDED)
569         return;
570
571     if (nbytes > 0)
572         pa_log_debug("Processing rewind...");
573
574     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
575         pa_sink_input_assert_ref(i);
576         pa_sink_input_process_rewind(i, nbytes);
577     }
578
579     if (nbytes > 0)
580         if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
581             pa_source_process_rewind(s->monitor_source, nbytes);
582 }
583
584 /* Called from IO thread context */
585 static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxinfo) {
586     pa_sink_input *i;
587     unsigned n = 0;
588     void *state = NULL;
589     size_t mixlength = *length;
590
591     pa_sink_assert_ref(s);
592     pa_assert(info);
593
594     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
595         pa_sink_input_assert_ref(i);
596
597         pa_sink_input_peek(i, *length, &info->chunk, &info->volume);
598
599         if (mixlength == 0 || info->chunk.length < mixlength)
600             mixlength = info->chunk.length;
601
602         if (pa_memblock_is_silence(info->chunk.memblock)) {
603             pa_memblock_unref(info->chunk.memblock);
604             continue;
605         }
606
607         info->userdata = pa_sink_input_ref(i);
608
609         pa_assert(info->chunk.memblock);
610         pa_assert(info->chunk.length > 0);
611
612         info++;
613         n++;
614         maxinfo--;
615     }
616
617     if (mixlength > 0)
618         *length = mixlength;
619
620     return n;
621 }
622
623 /* Called from IO thread context */
624 static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *result) {
625     pa_sink_input *i;
626     void *state = NULL;
627     unsigned p = 0;
628     unsigned n_unreffed = 0;
629
630     pa_sink_assert_ref(s);
631     pa_assert(result);
632     pa_assert(result->memblock);
633     pa_assert(result->length > 0);
634
635     /* We optimize for the case where the order of the inputs has not changed */
636
637     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
638         unsigned j;
639         pa_mix_info* m = NULL;
640
641         pa_sink_input_assert_ref(i);
642
643         /* Let's try to find the matching entry info the pa_mix_info array */
644         for (j = 0; j < n; j ++) {
645
646             if (info[p].userdata == i) {
647                 m = info + p;
648                 break;
649             }
650
651             p++;
652             if (p >= n)
653                 p = 0;
654         }
655
656         /* Drop read data */
657         pa_sink_input_drop(i, result->length);
658
659         if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state)) {
660
661             if (pa_hashmap_size(i->thread_info.direct_outputs) > 0) {
662                 void *ostate = NULL;
663                 pa_source_output *o;
664                 pa_memchunk c;
665
666                 if (m && m->chunk.memblock) {
667                     c = m->chunk;
668                     pa_memblock_ref(c.memblock);
669                     pa_assert(result->length <= c.length);
670                     c.length = result->length;
671
672                     pa_memchunk_make_writable(&c, 0);
673                     pa_volume_memchunk(&c, &s->sample_spec, &m->volume);
674                 } else {
675                     c = s->silence;
676                     pa_memblock_ref(c.memblock);
677                     pa_assert(result->length <= c.length);
678                     c.length = result->length;
679                 }
680
681                 while ((o = pa_hashmap_iterate(i->thread_info.direct_outputs, &ostate, NULL))) {
682                     pa_source_output_assert_ref(o);
683                     pa_assert(o->direct_on_input == i);
684                     pa_source_post_direct(s->monitor_source, o, &c);
685                 }
686
687                 pa_memblock_unref(c.memblock);
688             }
689         }
690
691         if (m) {
692             if (m->chunk.memblock)
693                 pa_memblock_unref(m->chunk.memblock);
694                 pa_memchunk_reset(&m->chunk);
695
696             pa_sink_input_unref(m->userdata);
697             m->userdata = NULL;
698
699             n_unreffed += 1;
700         }
701     }
702
703     /* Now drop references to entries that are included in the
704      * pa_mix_info array but don't exist anymore */
705
706     if (n_unreffed < n) {
707         for (; n > 0; info++, n--) {
708             if (info->userdata)
709                 pa_sink_input_unref(info->userdata);
710             if (info->chunk.memblock)
711                 pa_memblock_unref(info->chunk.memblock);
712         }
713     }
714
715     if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
716         pa_source_post(s->monitor_source, result);
717 }
718
719 /* Called from IO thread context */
720 void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
721     pa_mix_info info[MAX_MIX_CHANNELS];
722     unsigned n;
723     size_t block_size_max;
724
725     pa_sink_assert_ref(s);
726     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
727     pa_assert(pa_frame_aligned(length, &s->sample_spec));
728     pa_assert(result);
729
730     pa_sink_ref(s);
731
732     pa_assert(!s->thread_info.rewind_requested);
733     pa_assert(s->thread_info.rewind_nbytes == 0);
734
735     if (s->thread_info.state == PA_SINK_SUSPENDED) {
736         result->memblock = pa_memblock_ref(s->silence.memblock);
737         result->index = s->silence.index;
738         result->length = PA_MIN(s->silence.length, length);
739         return;
740     }
741
742     if (length <= 0)
743         length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
744
745     block_size_max = pa_mempool_block_size_max(s->core->mempool);
746     if (length > block_size_max)
747         length = pa_frame_align(block_size_max, &s->sample_spec);
748
749     pa_assert(length > 0);
750
751     n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
752
753     if (n == 0) {
754
755         *result = s->silence;
756         pa_memblock_ref(result->memblock);
757
758         if (result->length > length)
759             result->length = length;
760
761     } else if (n == 1) {
762         pa_cvolume volume;
763
764         *result = info[0].chunk;
765         pa_memblock_ref(result->memblock);
766
767         if (result->length > length)
768             result->length = length;
769
770         pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
771
772         if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) {
773             pa_memchunk_make_writable(result, 0);
774             if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
775                 pa_silence_memchunk(result, &s->sample_spec);
776             else
777                 pa_volume_memchunk(result, &s->sample_spec, &volume);
778         }
779     } else {
780         void *ptr;
781         result->memblock = pa_memblock_new(s->core->mempool, length);
782
783         ptr = pa_memblock_acquire(result->memblock);
784         result->length = pa_mix(info, n,
785                                 ptr, length,
786                                 &s->sample_spec,
787                                 &s->thread_info.soft_volume,
788                                 s->thread_info.soft_muted);
789         pa_memblock_release(result->memblock);
790
791         result->index = 0;
792     }
793
794     inputs_drop(s, info, n, result);
795
796     pa_sink_unref(s);
797 }
798
799 /* Called from IO thread context */
800 void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
801     pa_mix_info info[MAX_MIX_CHANNELS];
802     unsigned n;
803     size_t length, block_size_max;
804
805     pa_sink_assert_ref(s);
806     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
807     pa_assert(target);
808     pa_assert(target->memblock);
809     pa_assert(target->length > 0);
810     pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
811
812     pa_sink_ref(s);
813
814     pa_assert(!s->thread_info.rewind_requested);
815     pa_assert(s->thread_info.rewind_nbytes == 0);
816
817     if (s->thread_info.state == PA_SINK_SUSPENDED) {
818         pa_silence_memchunk(target, &s->sample_spec);
819         return;
820     }
821
822     length = target->length;
823     block_size_max = pa_mempool_block_size_max(s->core->mempool);
824     if (length > block_size_max)
825         length = pa_frame_align(block_size_max, &s->sample_spec);
826
827     pa_assert(length > 0);
828
829     n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS);
830
831     if (n == 0) {
832         if (target->length > length)
833             target->length = length;
834
835         pa_silence_memchunk(target, &s->sample_spec);
836     } else if (n == 1) {
837         pa_cvolume volume;
838
839         if (target->length > length)
840             target->length = length;
841
842         pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
843
844         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
845             pa_silence_memchunk(target, &s->sample_spec);
846         else {
847             pa_memchunk vchunk;
848
849             vchunk = info[0].chunk;
850             pa_memblock_ref(vchunk.memblock);
851
852             if (vchunk.length > length)
853                 vchunk.length = length;
854
855             if (!pa_cvolume_is_norm(&volume)) {
856                 pa_memchunk_make_writable(&vchunk, 0);
857                 pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
858             }
859
860             pa_memchunk_memcpy(target, &vchunk);
861             pa_memblock_unref(vchunk.memblock);
862         }
863
864     } else {
865         void *ptr;
866
867         ptr = pa_memblock_acquire(target->memblock);
868
869         target->length = pa_mix(info, n,
870                                 (uint8_t*) ptr + target->index, length,
871                                 &s->sample_spec,
872                                 &s->thread_info.soft_volume,
873                                 s->thread_info.soft_muted);
874
875         pa_memblock_release(target->memblock);
876     }
877
878     inputs_drop(s, info, n, target);
879
880     pa_sink_unref(s);
881 }
882
883 /* Called from IO thread context */
884 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
885     pa_memchunk chunk;
886     size_t l, d;
887
888     pa_sink_assert_ref(s);
889     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
890     pa_assert(target);
891     pa_assert(target->memblock);
892     pa_assert(target->length > 0);
893     pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
894
895     pa_sink_ref(s);
896
897     pa_assert(!s->thread_info.rewind_requested);
898     pa_assert(s->thread_info.rewind_nbytes == 0);
899
900     l = target->length;
901     d = 0;
902     while (l > 0) {
903         chunk = *target;
904         chunk.index += d;
905         chunk.length -= d;
906
907         pa_sink_render_into(s, &chunk);
908
909         d += chunk.length;
910         l -= chunk.length;
911     }
912
913     pa_sink_unref(s);
914 }
915
916 /* Called from IO thread context */
917 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
918     pa_sink_assert_ref(s);
919     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
920     pa_assert(length > 0);
921     pa_assert(pa_frame_aligned(length, &s->sample_spec));
922     pa_assert(result);
923
924     pa_assert(!s->thread_info.rewind_requested);
925     pa_assert(s->thread_info.rewind_nbytes == 0);
926
927     /*** This needs optimization ***/
928
929     result->index = 0;
930     result->length = length;
931     result->memblock = pa_memblock_new(s->core->mempool, length);
932
933     pa_sink_render_into_full(s, result);
934 }
935
936 /* Called from main thread */
937 pa_usec_t pa_sink_get_latency(pa_sink *s) {
938     pa_usec_t usec = 0;
939
940     pa_sink_assert_ref(s);
941     pa_assert(PA_SINK_IS_LINKED(s->state));
942
943     /* The returned value is supposed to be in the time domain of the sound card! */
944
945     if (s->state == PA_SINK_SUSPENDED)
946         return 0;
947
948     if (!(s->flags & PA_SINK_LATENCY))
949         return 0;
950
951     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
952
953     return usec;
954 }
955
956 /* Called from main thread */
957 void pa_sink_update_flat_volume(pa_sink *s, pa_cvolume *new_volume) {
958     pa_sink_input *i;
959     uint32_t idx;
960
961     pa_sink_assert_ref(s);
962     pa_assert(new_volume);
963     pa_assert(PA_SINK_IS_LINKED(s->state));
964     pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
965
966     /* This is called whenever a sink input volume changes and we
967      * might need to fix up the sink volume accordingly. Please note
968      * that we don't actually update the sinks volume here, we only
969      * return how it needs to be updated. The caller should then call
970      * pa_sink_set_flat_volume().*/
971
972     if (pa_idxset_isempty(s->inputs)) {
973         /* In the special case that we have no sink input we leave the
974          * volume unmodified. */
975         *new_volume = s->virtual_volume;
976         return;
977     }
978
979     pa_cvolume_mute(new_volume, s->channel_map.channels);
980
981     /* First let's determine the new maximum volume of all inputs
982      * connected to this sink */
983     for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
984         unsigned c;
985         pa_cvolume remapped_volume;
986
987         remapped_volume = i->virtual_volume;
988         pa_cvolume_remap(&remapped_volume, &i->channel_map, &s->channel_map);
989
990         for (c = 0; c < new_volume->channels; c++)
991             if (remapped_volume.values[c] > new_volume->values[c])
992                 new_volume->values[c] = remapped_volume.values[c];
993     }
994
995     /* Then, let's update the soft volumes of all inputs connected
996      * to this sink */
997     for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
998         pa_cvolume remapped_new_volume;
999
1000         remapped_new_volume = *new_volume;
1001         pa_cvolume_remap(&remapped_new_volume, &s->channel_map, &i->channel_map);
1002         pa_sw_cvolume_divide(&i->soft_volume, &i->virtual_volume, &remapped_new_volume);
1003         pa_sw_cvolume_multiply(&i->soft_volume, &i->soft_volume, &i->volume_factor);
1004
1005         /* Hooks have the ability to play games with i->soft_volume */
1006         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], i);
1007
1008         /* We don't issue PA_SINK_INPUT_MESSAGE_SET_VOLUME because
1009          * we want the update to have atomically with the sink
1010          * volume update, hence we do it within the
1011          * pa_sink_set_flat_volume() call below*/
1012     }
1013 }
1014
1015 /* Called from main thread */
1016 void pa_sink_propagate_flat_volume(pa_sink *s, const pa_cvolume *old_volume) {
1017     pa_sink_input *i;
1018     uint32_t idx;
1019
1020     pa_sink_assert_ref(s);
1021     pa_assert(old_volume);
1022     pa_assert(PA_SINK_IS_LINKED(s->state));
1023     pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
1024
1025     /* This is called whenever the sink volume changes that is not
1026      * caused by a sink input volume change. We need to fix up the
1027      * sink input volumes accordingly */
1028
1029     for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
1030         pa_cvolume remapped_old_volume, remapped_new_volume, fixed_volume;
1031         unsigned c;
1032
1033         remapped_new_volume = s->virtual_volume;
1034         pa_cvolume_remap(&remapped_new_volume, &s->channel_map, &i->channel_map);
1035
1036         remapped_old_volume = *old_volume;
1037         pa_cvolume_remap(&remapped_old_volume, &s->channel_map, &i->channel_map);
1038
1039         for (c = 0; c < i->sample_spec.channels; c++)
1040
1041             if (remapped_old_volume.values[c] == PA_VOLUME_MUTED)
1042                 fixed_volume.values[c] = PA_VOLUME_MUTED;
1043             else
1044                 fixed_volume.values[c] = (pa_volume_t)
1045                     ((uint64_t) i->virtual_volume.values[c] *
1046                      (uint64_t) remapped_new_volume.values[c] /
1047                      (uint64_t) remapped_old_volume.values[c]);
1048
1049         fixed_volume.channels = i->virtual_volume.channels;
1050
1051         if (!pa_cvolume_equal(&fixed_volume, &i->virtual_volume)) {
1052             i->virtual_volume = fixed_volume;
1053
1054             /* The virtual volume changed, let's tell people so */
1055             pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1056         }
1057     }
1058 }
1059
1060 /* Called from main thread */
1061 void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg) {
1062     pa_cvolume old_virtual_volume;
1063     pa_bool_t virtual_volume_changed;
1064
1065     pa_sink_assert_ref(s);
1066     pa_assert(PA_SINK_IS_LINKED(s->state));
1067     pa_assert(volume);
1068     pa_assert(pa_cvolume_valid(volume));
1069     pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
1070
1071     old_virtual_volume = s->virtual_volume;
1072     s->virtual_volume = *volume;
1073     virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume);
1074
1075     /* Propagate this volume change back to the inputs */
1076     if (virtual_volume_changed)
1077         if (propagate && (s->flags & PA_SINK_FLAT_VOLUME))
1078             pa_sink_propagate_flat_volume(s, &old_virtual_volume);
1079
1080     if (s->set_volume) {
1081         /* If we have a function set_volume(), then we do not apply a
1082          * soft volume by default. However, set_volume() is apply one
1083          * to s->soft_volume */
1084
1085         pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
1086         s->set_volume(s);
1087
1088     } else
1089         /* If we have no function set_volume(), then the soft volume
1090          * becomes the virtual volume */
1091         s->soft_volume = s->virtual_volume;
1092
1093     /* This tells the sink that soft and/or virtual volume changed */
1094     if (sendmsg)
1095         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
1096
1097     if (virtual_volume_changed)
1098         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1099 }
1100
1101 /* Called from main thread. Only to be called by sink implementor */
1102 void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) {
1103     pa_sink_assert_ref(s);
1104     pa_assert(volume);
1105
1106     s->soft_volume = *volume;
1107
1108     if (PA_SINK_IS_LINKED(s->state))
1109         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
1110     else
1111         s->thread_info.soft_volume = *volume;
1112 }
1113
1114 /* Called from main thread */
1115 const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) {
1116     pa_sink_assert_ref(s);
1117
1118     if (s->refresh_volume || force_refresh) {
1119         struct pa_cvolume old_virtual_volume = s->virtual_volume;
1120
1121         if (s->get_volume)
1122             s->get_volume(s);
1123
1124         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
1125
1126         if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume)) {
1127
1128             if (s->flags & PA_SINK_FLAT_VOLUME)
1129                 pa_sink_propagate_flat_volume(s, &old_virtual_volume);
1130
1131             pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1132         }
1133     }
1134
1135     return &s->virtual_volume;
1136 }
1137
1138 /* Called from main thread */
1139 void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume) {
1140     pa_sink_assert_ref(s);
1141
1142     /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1143
1144     if (pa_cvolume_equal(&s->virtual_volume, new_volume))
1145         return;
1146
1147     s->virtual_volume = *new_volume;
1148     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1149 }
1150
1151 /* Called from main thread */
1152 void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) {
1153     pa_bool_t old_muted;
1154
1155     pa_sink_assert_ref(s);
1156     pa_assert(PA_SINK_IS_LINKED(s->state));
1157
1158     old_muted = s->muted;
1159     s->muted = mute;
1160
1161     if (s->set_mute)
1162         s->set_mute(s);
1163
1164     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
1165
1166     if (old_muted != s->muted)
1167         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1168 }
1169
1170 /* Called from main thread */
1171 pa_bool_t pa_sink_get_mute(pa_sink *s, pa_bool_t force_refresh) {
1172
1173     pa_sink_assert_ref(s);
1174
1175     if (s->refresh_muted || force_refresh) {
1176         pa_bool_t old_muted = s->muted;
1177
1178         if (s->get_mute)
1179             s->get_mute(s);
1180
1181         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
1182
1183         if (old_muted != s->muted)
1184             pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1185     }
1186
1187     return s->muted;
1188 }
1189
1190 /* Called from main thread */
1191 void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted) {
1192     pa_sink_assert_ref(s);
1193
1194     /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1195
1196     if (s->muted == new_muted)
1197         return;
1198
1199     s->muted = new_muted;
1200     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1201 }
1202
1203 /* Called from main thread */
1204 pa_bool_t pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p) {
1205     pa_sink_assert_ref(s);
1206
1207     if (p)
1208         pa_proplist_update(s->proplist, mode, p);
1209
1210     if (PA_SINK_IS_LINKED(s->state)) {
1211         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
1212         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1213     }
1214
1215     return TRUE;
1216 }
1217
1218 /* Called from main thread */
1219 void pa_sink_set_description(pa_sink *s, const char *description) {
1220     const char *old;
1221     pa_sink_assert_ref(s);
1222
1223     if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
1224         return;
1225
1226     old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
1227
1228     if (old && description && !strcmp(old, description))
1229         return;
1230
1231     if (description)
1232         pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
1233     else
1234         pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
1235
1236     if (s->monitor_source) {
1237         char *n;
1238
1239         n = pa_sprintf_malloc("Monitor Source of %s", description ? description : s->name);
1240         pa_source_set_description(s->monitor_source, n);
1241         pa_xfree(n);
1242     }
1243
1244     if (PA_SINK_IS_LINKED(s->state)) {
1245         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1246         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
1247     }
1248 }
1249
1250 /* Called from main thread */
1251 unsigned pa_sink_linked_by(pa_sink *s) {
1252     unsigned ret;
1253
1254     pa_sink_assert_ref(s);
1255     pa_assert(PA_SINK_IS_LINKED(s->state));
1256
1257     ret = pa_idxset_size(s->inputs);
1258
1259     /* We add in the number of streams connected to us here. Please
1260      * note the asymmmetry to pa_sink_used_by()! */
1261
1262     if (s->monitor_source)
1263         ret += pa_source_linked_by(s->monitor_source);
1264
1265     return ret;
1266 }
1267
1268 /* Called from main thread */
1269 unsigned pa_sink_used_by(pa_sink *s) {
1270     unsigned ret;
1271
1272     pa_sink_assert_ref(s);
1273     pa_assert(PA_SINK_IS_LINKED(s->state));
1274
1275     ret = pa_idxset_size(s->inputs);
1276     pa_assert(ret >= s->n_corked);
1277
1278     /* Streams connected to our monitor source do not matter for
1279      * pa_sink_used_by()!.*/
1280
1281     return ret - s->n_corked;
1282 }
1283
1284 /* Called from main thread */
1285 unsigned pa_sink_check_suspend(pa_sink *s) {
1286     unsigned ret;
1287     pa_sink_input *i;
1288     uint32_t idx;
1289
1290     pa_sink_assert_ref(s);
1291
1292     if (!PA_SINK_IS_LINKED(s->state))
1293         return 0;
1294
1295     ret = 0;
1296
1297     for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
1298         pa_sink_input_state_t st;
1299
1300         st = pa_sink_input_get_state(i);
1301         pa_assert(PA_SINK_INPUT_IS_LINKED(st));
1302
1303         if (st == PA_SINK_INPUT_CORKED)
1304             continue;
1305
1306         if (i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND)
1307             continue;
1308
1309         ret ++;
1310     }
1311
1312     if (s->monitor_source)
1313         ret += pa_source_check_suspend(s->monitor_source);
1314
1315     return ret;
1316 }
1317
1318 /* Called from the IO thread */
1319 static void sync_input_volumes_within_thread(pa_sink *s) {
1320     pa_sink_input *i;
1321     void *state = NULL;
1322
1323     pa_sink_assert_ref(s);
1324
1325     while ((i = PA_SINK_INPUT(pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))) {
1326         if (pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume))
1327             continue;
1328
1329         i->thread_info.soft_volume = i->soft_volume;
1330         pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1331     }
1332 }
1333
1334 /* Called from IO thread, except when it is not */
1335 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1336     pa_sink *s = PA_SINK(o);
1337     pa_sink_assert_ref(s);
1338
1339     switch ((pa_sink_message_t) code) {
1340
1341         case PA_SINK_MESSAGE_ADD_INPUT: {
1342             pa_sink_input *i = PA_SINK_INPUT(userdata);
1343
1344             /* If you change anything here, make sure to change the
1345              * sink input handling a few lines down at
1346              * PA_SINK_MESSAGE_FINISH_MOVE, too. */
1347
1348             pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
1349
1350             /* Since the caller sleeps in pa_sink_input_put(), we can
1351              * safely access data outside of thread_info even though
1352              * it is mutable */
1353
1354             if ((i->thread_info.sync_prev = i->sync_prev)) {
1355                 pa_assert(i->sink == i->thread_info.sync_prev->sink);
1356                 pa_assert(i->sync_prev->sync_next == i);
1357                 i->thread_info.sync_prev->thread_info.sync_next = i;
1358             }
1359
1360             if ((i->thread_info.sync_next = i->sync_next)) {
1361                 pa_assert(i->sink == i->thread_info.sync_next->sink);
1362                 pa_assert(i->sync_next->sync_prev == i);
1363                 i->thread_info.sync_next->thread_info.sync_prev = i;
1364             }
1365
1366             pa_assert(!i->thread_info.attached);
1367             i->thread_info.attached = TRUE;
1368
1369             if (i->attach)
1370                 i->attach(i);
1371
1372             pa_sink_input_set_state_within_thread(i, i->state);
1373
1374             /* The requested latency of the sink input needs to be
1375              * fixed up and then configured on the sink */
1376
1377             if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
1378                 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
1379
1380             pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1381             pa_sink_input_update_max_request(i, s->thread_info.max_request);
1382
1383             /* We don't rewind here automatically. This is left to the
1384              * sink input implementor because some sink inputs need a
1385              * slow start, i.e. need some time to buffer client
1386              * samples before beginning streaming. */
1387
1388             /* In flat volume mode we need to update the volume as
1389              * well */
1390             return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1391         }
1392
1393         case PA_SINK_MESSAGE_REMOVE_INPUT: {
1394             pa_sink_input *i = PA_SINK_INPUT(userdata);
1395
1396             /* If you change anything here, make sure to change the
1397              * sink input handling a few lines down at
1398              * PA_SINK_MESSAGE_PREPAPRE_MOVE, too. */
1399
1400             if (i->detach)
1401                 i->detach(i);
1402
1403             pa_sink_input_set_state_within_thread(i, i->state);
1404
1405             pa_assert(i->thread_info.attached);
1406             i->thread_info.attached = FALSE;
1407
1408             /* Since the caller sleeps in pa_sink_input_unlink(),
1409              * we can safely access data outside of thread_info even
1410              * though it is mutable */
1411
1412             pa_assert(!i->sync_prev);
1413             pa_assert(!i->sync_next);
1414
1415             if (i->thread_info.sync_prev) {
1416                 i->thread_info.sync_prev->thread_info.sync_next = i->thread_info.sync_prev->sync_next;
1417                 i->thread_info.sync_prev = NULL;
1418             }
1419
1420             if (i->thread_info.sync_next) {
1421                 i->thread_info.sync_next->thread_info.sync_prev = i->thread_info.sync_next->sync_prev;
1422                 i->thread_info.sync_next = NULL;
1423             }
1424
1425             if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
1426                 pa_sink_input_unref(i);
1427
1428             pa_sink_invalidate_requested_latency(s);
1429             pa_sink_request_rewind(s, (size_t) -1);
1430
1431             /* In flat volume mode we need to update the volume as
1432              * well */
1433             return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1434         }
1435
1436         case PA_SINK_MESSAGE_START_MOVE: {
1437             pa_sink_input *i = PA_SINK_INPUT(userdata);
1438
1439             /* We don't support moving synchronized streams. */
1440             pa_assert(!i->sync_prev);
1441             pa_assert(!i->sync_next);
1442             pa_assert(!i->thread_info.sync_next);
1443             pa_assert(!i->thread_info.sync_prev);
1444
1445             if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
1446                 pa_usec_t usec = 0;
1447                 size_t sink_nbytes, total_nbytes;
1448
1449                 /* Get the latency of the sink */
1450                 if (!(s->flags & PA_SINK_LATENCY) ||
1451                     PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
1452                     usec = 0;
1453
1454                 sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
1455                 total_nbytes = sink_nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq);
1456
1457                 if (total_nbytes > 0) {
1458                     i->thread_info.rewrite_nbytes = i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, total_nbytes) : total_nbytes;
1459                     i->thread_info.rewrite_flush = TRUE;
1460                     pa_sink_input_process_rewind(i, sink_nbytes);
1461                 }
1462             }
1463
1464             if (i->detach)
1465                 i->detach(i);
1466
1467             pa_assert(i->thread_info.attached);
1468             i->thread_info.attached = FALSE;
1469
1470             /* Let's remove the sink input ...*/
1471             if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
1472                 pa_sink_input_unref(i);
1473
1474             pa_sink_invalidate_requested_latency(s);
1475
1476             pa_log_debug("Requesting rewind due to started move");
1477             pa_sink_request_rewind(s, (size_t) -1);
1478
1479             /* In flat volume mode we need to update the volume as
1480              * well */
1481             return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1482         }
1483
1484         case PA_SINK_MESSAGE_FINISH_MOVE: {
1485             pa_sink_input *i = PA_SINK_INPUT(userdata);
1486
1487             /* We don't support moving synchronized streams. */
1488             pa_assert(!i->sync_prev);
1489             pa_assert(!i->sync_next);
1490             pa_assert(!i->thread_info.sync_next);
1491             pa_assert(!i->thread_info.sync_prev);
1492
1493             pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
1494
1495             pa_assert(!i->thread_info.attached);
1496             i->thread_info.attached = TRUE;
1497
1498             if (i->attach)
1499                 i->attach(i);
1500
1501             if (i->thread_info.requested_sink_latency != (pa_usec_t) -1)
1502                 pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
1503
1504             pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1505             pa_sink_input_update_max_request(i, s->thread_info.max_request);
1506
1507             if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
1508                 pa_usec_t usec = 0;
1509                 size_t nbytes;
1510
1511                 /* Get the latency of the sink */
1512                 if (!(s->flags & PA_SINK_LATENCY) ||
1513                     PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
1514                     usec = 0;
1515
1516                 nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
1517
1518                 if (nbytes > 0)
1519                     pa_sink_input_drop(i, nbytes);
1520
1521                 pa_log_debug("Requesting rewind due to finished move");
1522                 pa_sink_request_rewind(s, nbytes);
1523             }
1524
1525             /* In flat volume mode we need to update the volume as
1526              * well */
1527             return o->process_msg(o, PA_SINK_MESSAGE_SET_VOLUME, NULL, 0, NULL);
1528         }
1529
1530         case PA_SINK_MESSAGE_SET_VOLUME:
1531
1532             if (!pa_cvolume_equal(&s->thread_info.soft_volume, &s->soft_volume)) {
1533                 s->thread_info.soft_volume = s->soft_volume;
1534                 pa_sink_request_rewind(s, (size_t) -1);
1535             }
1536
1537             if (s->flags & PA_SINK_FLAT_VOLUME)
1538                 sync_input_volumes_within_thread(s);
1539
1540             return 0;
1541
1542         case PA_SINK_MESSAGE_GET_VOLUME:
1543             return 0;
1544
1545         case PA_SINK_MESSAGE_SET_MUTE:
1546
1547             if (s->thread_info.soft_muted != s->muted) {
1548                 s->thread_info.soft_muted = s->muted;
1549                 pa_sink_request_rewind(s, (size_t) -1);
1550             }
1551
1552             return 0;
1553
1554         case PA_SINK_MESSAGE_GET_MUTE:
1555             return 0;
1556
1557         case PA_SINK_MESSAGE_SET_STATE:
1558
1559             s->thread_info.state = PA_PTR_TO_UINT(userdata);
1560
1561             if (s->thread_info.state == PA_SINK_SUSPENDED) {
1562                 s->thread_info.rewind_nbytes = 0;
1563                 s->thread_info.rewind_requested = FALSE;
1564             }
1565
1566             return 0;
1567
1568         case PA_SINK_MESSAGE_DETACH:
1569
1570             /* Detach all streams */
1571             pa_sink_detach_within_thread(s);
1572             return 0;
1573
1574         case PA_SINK_MESSAGE_ATTACH:
1575
1576             /* Reattach all streams */
1577             pa_sink_attach_within_thread(s);
1578             return 0;
1579
1580         case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: {
1581
1582             pa_usec_t *usec = userdata;
1583             *usec = pa_sink_get_requested_latency_within_thread(s);
1584
1585             if (*usec == (pa_usec_t) -1)
1586                 *usec = s->thread_info.max_latency;
1587
1588             return 0;
1589         }
1590
1591         case PA_SINK_MESSAGE_SET_LATENCY_RANGE: {
1592             pa_usec_t *r = userdata;
1593
1594             pa_sink_set_latency_range_within_thread(s, r[0], r[1]);
1595
1596             return 0;
1597         }
1598
1599         case PA_SINK_MESSAGE_GET_LATENCY_RANGE: {
1600             pa_usec_t *r = userdata;
1601
1602             r[0] = s->thread_info.min_latency;
1603             r[1] = s->thread_info.max_latency;
1604
1605             return 0;
1606         }
1607
1608         case PA_SINK_MESSAGE_GET_MAX_REWIND:
1609
1610             *((size_t*) userdata) = s->thread_info.max_rewind;
1611             return 0;
1612
1613         case PA_SINK_MESSAGE_GET_MAX_REQUEST:
1614
1615             *((size_t*) userdata) = s->thread_info.max_request;
1616             return 0;
1617
1618         case PA_SINK_MESSAGE_SET_MAX_REWIND:
1619
1620             pa_sink_set_max_rewind_within_thread(s, (size_t) offset);
1621             return 0;
1622
1623         case PA_SINK_MESSAGE_SET_MAX_REQUEST:
1624
1625             pa_sink_set_max_request_within_thread(s, (size_t) offset);
1626             return 0;
1627
1628         case PA_SINK_MESSAGE_GET_LATENCY:
1629         case PA_SINK_MESSAGE_MAX:
1630             ;
1631     }
1632
1633     return -1;
1634 }
1635
1636 /* Called from main thread */
1637 int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) {
1638     pa_sink *sink;
1639     uint32_t idx;
1640     int ret = 0;
1641
1642     pa_core_assert_ref(c);
1643
1644     for (sink = PA_SINK(pa_idxset_first(c->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(c->sinks, &idx))) {
1645         int r;
1646
1647         if ((r = pa_sink_suspend(sink, suspend)) < 0)
1648             ret = r;
1649     }
1650
1651     return ret;
1652 }
1653
1654 /* Called from main thread */
1655 void pa_sink_detach(pa_sink *s) {
1656     pa_sink_assert_ref(s);
1657     pa_assert(PA_SINK_IS_LINKED(s->state));
1658
1659     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL) == 0);
1660 }
1661
1662 /* Called from main thread */
1663 void pa_sink_attach(pa_sink *s) {
1664     pa_sink_assert_ref(s);
1665     pa_assert(PA_SINK_IS_LINKED(s->state));
1666
1667     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
1668 }
1669
1670 /* Called from IO thread */
1671 void pa_sink_detach_within_thread(pa_sink *s) {
1672     pa_sink_input *i;
1673     void *state = NULL;
1674
1675     pa_sink_assert_ref(s);
1676     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1677
1678     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1679         if (i->detach)
1680             i->detach(i);
1681
1682     if (s->monitor_source)
1683         pa_source_detach_within_thread(s->monitor_source);
1684 }
1685
1686 /* Called from IO thread */
1687 void pa_sink_attach_within_thread(pa_sink *s) {
1688     pa_sink_input *i;
1689     void *state = NULL;
1690
1691     pa_sink_assert_ref(s);
1692     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1693
1694     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1695         if (i->attach)
1696             i->attach(i);
1697
1698     if (s->monitor_source)
1699         pa_source_attach_within_thread(s->monitor_source);
1700 }
1701
1702 /* Called from IO thread */
1703 void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
1704     pa_sink_assert_ref(s);
1705     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
1706
1707     if (s->thread_info.state == PA_SINK_SUSPENDED)
1708         return;
1709
1710     if (nbytes == (size_t) -1)
1711         nbytes = s->thread_info.max_rewind;
1712
1713     nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
1714
1715     if (s->thread_info.rewind_requested &&
1716         nbytes <= s->thread_info.rewind_nbytes)
1717         return;
1718
1719     s->thread_info.rewind_nbytes = nbytes;
1720     s->thread_info.rewind_requested = TRUE;
1721
1722     if (s->request_rewind)
1723         s->request_rewind(s);
1724 }
1725
1726 /* Called from IO thread */
1727 pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
1728     pa_usec_t result = (pa_usec_t) -1;
1729     pa_sink_input *i;
1730     void *state = NULL;
1731     pa_usec_t monitor_latency;
1732
1733     pa_sink_assert_ref(s);
1734
1735     if (s->thread_info.requested_latency_valid)
1736         return s->thread_info.requested_latency;
1737
1738     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1739
1740         if (i->thread_info.requested_sink_latency != (pa_usec_t) -1 &&
1741             (result == (pa_usec_t) -1 || result > i->thread_info.requested_sink_latency))
1742             result = i->thread_info.requested_sink_latency;
1743
1744     monitor_latency = pa_source_get_requested_latency_within_thread(s->monitor_source);
1745
1746     if (monitor_latency != (pa_usec_t) -1 &&
1747         (result == (pa_usec_t) -1 || result > monitor_latency))
1748         result = monitor_latency;
1749
1750     if (result != (pa_usec_t) -1) {
1751         if (result > s->thread_info.max_latency)
1752             result = s->thread_info.max_latency;
1753
1754         if (result < s->thread_info.min_latency)
1755             result = s->thread_info.min_latency;
1756     }
1757
1758     s->thread_info.requested_latency = result;
1759     s->thread_info.requested_latency_valid = TRUE;
1760
1761     return result;
1762 }
1763
1764 /* Called from main thread */
1765 pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
1766     pa_usec_t usec = 0;
1767
1768     pa_sink_assert_ref(s);
1769     pa_assert(PA_SINK_IS_LINKED(s->state));
1770
1771     if (s->state == PA_SINK_SUSPENDED)
1772         return 0;
1773
1774     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1775     return usec;
1776 }
1777
1778 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
1779 void pa_sink_set_max_rewind_within_thread(pa_sink *s, size_t max_rewind) {
1780     pa_sink_input *i;
1781     void *state = NULL;
1782
1783     pa_sink_assert_ref(s);
1784
1785     if (max_rewind == s->thread_info.max_rewind)
1786         return;
1787
1788     s->thread_info.max_rewind = max_rewind;
1789
1790     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
1791         while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1792             pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
1793     }
1794
1795     if (s->monitor_source)
1796         pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
1797 }
1798
1799 /* Called from main thread */
1800 void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
1801     pa_sink_assert_ref(s);
1802
1803     if (PA_SINK_IS_LINKED(s->state))
1804         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
1805     else
1806         pa_sink_set_max_rewind_within_thread(s, max_rewind);
1807 }
1808
1809 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
1810 void pa_sink_set_max_request_within_thread(pa_sink *s, size_t max_request) {
1811     void *state = NULL;
1812
1813     pa_sink_assert_ref(s);
1814
1815     if (max_request == s->thread_info.max_request)
1816         return;
1817
1818     s->thread_info.max_request = max_request;
1819
1820     if (PA_SINK_IS_LINKED(s->thread_info.state)) {
1821         pa_sink_input *i;
1822
1823         while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1824             pa_sink_input_update_max_request(i, s->thread_info.max_request);
1825     }
1826 }
1827
1828 /* Called from main thread */
1829 void pa_sink_set_max_request(pa_sink *s, size_t max_request) {
1830     pa_sink_assert_ref(s);
1831
1832     if (PA_SINK_IS_LINKED(s->state))
1833         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MAX_REQUEST, NULL, max_request, NULL) == 0);
1834     else
1835         pa_sink_set_max_request_within_thread(s, max_request);
1836 }
1837
1838 /* Called from IO thread */
1839 void pa_sink_invalidate_requested_latency(pa_sink *s) {
1840     pa_sink_input *i;
1841     void *state = NULL;
1842
1843     pa_sink_assert_ref(s);
1844
1845     s->thread_info.requested_latency_valid = FALSE;
1846
1847     if (s->update_requested_latency)
1848         s->update_requested_latency(s);
1849
1850     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1851         if (i->update_sink_requested_latency)
1852             i->update_sink_requested_latency(i);
1853 }
1854
1855 /* Called from main thread */
1856 void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1857     pa_sink_assert_ref(s);
1858
1859     /* min_latency == 0:           no limit
1860      * min_latency == (size_t) -1: default limit
1861      * min_latency anything else:  specified limit
1862      *
1863      * Similar for max_latency */
1864
1865     if (min_latency == (pa_usec_t) -1)
1866         min_latency = DEFAULT_MIN_LATENCY;
1867
1868     if (min_latency < ABSOLUTE_MIN_LATENCY)
1869         min_latency = ABSOLUTE_MIN_LATENCY;
1870
1871     if (max_latency == (pa_usec_t) -1)
1872         max_latency = min_latency;
1873
1874     if (max_latency > ABSOLUTE_MAX_LATENCY || max_latency <= 0)
1875         max_latency = ABSOLUTE_MAX_LATENCY;
1876
1877     pa_assert(min_latency <= max_latency);
1878
1879     if (PA_SINK_IS_LINKED(s->state)) {
1880         pa_usec_t r[2];
1881
1882         r[0] = min_latency;
1883         r[1] = max_latency;
1884
1885         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
1886     } else {
1887         s->thread_info.min_latency = min_latency;
1888         s->thread_info.max_latency = max_latency;
1889
1890         s->monitor_source->thread_info.min_latency = min_latency;
1891         s->monitor_source->thread_info.max_latency = max_latency;
1892
1893         s->thread_info.requested_latency_valid = s->monitor_source->thread_info.requested_latency_valid = FALSE;
1894     }
1895 }
1896
1897 /* Called from main thread */
1898 void pa_sink_get_latency_range(pa_sink *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
1899    pa_sink_assert_ref(s);
1900    pa_assert(min_latency);
1901    pa_assert(max_latency);
1902
1903    if (PA_SINK_IS_LINKED(s->state)) {
1904        pa_usec_t r[2] = { 0, 0 };
1905
1906        pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
1907
1908        *min_latency = r[0];
1909        *max_latency = r[1];
1910    } else {
1911        *min_latency = s->thread_info.min_latency;
1912        *max_latency = s->thread_info.max_latency;
1913    }
1914 }
1915
1916 /* Called from IO thread */
1917 void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1918     pa_sink_input *i;
1919     void *state = NULL;
1920
1921     pa_sink_assert_ref(s);
1922
1923     pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
1924     pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
1925     pa_assert(min_latency <= max_latency);
1926
1927     s->thread_info.min_latency = min_latency;
1928     s->thread_info.max_latency = max_latency;
1929
1930     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
1931         if (i->update_sink_latency_range)
1932             i->update_sink_latency_range(i);
1933
1934     pa_sink_invalidate_requested_latency(s);
1935
1936     pa_source_set_latency_range_within_thread(s->monitor_source, min_latency, max_latency);
1937 }
1938
1939 /* Called from main context */
1940 size_t pa_sink_get_max_rewind(pa_sink *s) {
1941     size_t r;
1942     pa_sink_assert_ref(s);
1943
1944     if (!PA_SINK_IS_LINKED(s->state))
1945         return s->thread_info.max_rewind;
1946
1947     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
1948
1949     return r;
1950 }
1951
1952 /* Called from main context */
1953 size_t pa_sink_get_max_request(pa_sink *s) {
1954     size_t r;
1955     pa_sink_assert_ref(s);
1956
1957     if (!PA_SINK_IS_LINKED(s->state))
1958         return s->thread_info.max_request;
1959
1960     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REQUEST, &r, 0, NULL) == 0);
1961
1962     return r;
1963 }
1964
1965 /* Called from main context */
1966 pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink) {
1967     const char *ff, *c, *t = NULL, *s = "", *profile, *bus;
1968
1969     pa_assert(p);
1970
1971     if (pa_proplist_contains(p, PA_PROP_DEVICE_ICON_NAME))
1972         return TRUE;
1973
1974     if ((ff = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) {
1975
1976         if (pa_streq(ff, "microphone"))
1977             t = "audio-input-microphone";
1978         else if (pa_streq(ff, "webcam"))
1979             t = "camera-web";
1980         else if (pa_streq(ff, "computer"))
1981             t = "computer";
1982         else if (pa_streq(ff, "handset"))
1983             t = "phone";
1984         else if (pa_streq(ff, "portable"))
1985             t = "multimedia-player";
1986         else if (pa_streq(ff, "tv"))
1987             t = "video-display";
1988     }
1989
1990     if (!t)
1991         if ((c = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
1992             if (pa_streq(c, "modem"))
1993                 t = "modem";
1994
1995     if (!t) {
1996         if (is_sink)
1997             t = "audio-card";
1998         else
1999             t = "audio-input-microphone";
2000     }
2001
2002     if ((profile = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
2003         if (strstr(profile, "analog"))
2004             s = "-analog";
2005         else if (strstr(profile, "iec958"))
2006             s = "-iec958";
2007         else if (strstr(profile, "hdmi"))
2008             s = "-hdmi";
2009     }
2010
2011     bus = pa_proplist_gets(p, PA_PROP_DEVICE_BUS);
2012
2013     pa_proplist_setf(p, PA_PROP_DEVICE_ICON_NAME, "%s%s%s%s", t, pa_strempty(s), bus ? "-" : "", pa_strempty(bus));
2014
2015     return TRUE;
2016 }
2017
2018 pa_bool_t pa_device_init_description(pa_proplist *p) {
2019     const char *s;
2020     pa_assert(p);
2021
2022     if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
2023         return TRUE;
2024
2025     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
2026         if (pa_streq(s, "internal")) {
2027             pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Internal Audio"));
2028             return TRUE;
2029         }
2030
2031     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
2032         if (pa_streq(s, "modem")) {
2033             pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Modem"));
2034             return TRUE;
2035         }
2036
2037     if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME))) {
2038         pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
2039         return TRUE;
2040     }
2041
2042     return FALSE;
2043 }