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