Merge commit 'origin/master-tx'
[platform/upstream/pulseaudio.git] / src / pulsecore / source.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20   USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <pulse/utf8.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
35
36 #include <pulsecore/source-output.h>
37 #include <pulsecore/namereg.h>
38 #include <pulsecore/core-subscribe.h>
39 #include <pulsecore/log.h>
40 #include <pulsecore/sample-util.h>
41
42 #include "source.h"
43
44 #define ABSOLUTE_MIN_LATENCY (500)
45 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
46 #define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
47
48 static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
49
50 static void source_free(pa_object *o);
51
52 pa_source_new_data* pa_source_new_data_init(pa_source_new_data *data) {
53     pa_assert(data);
54
55     memset(data, 0, sizeof(*data));
56     data->proplist = pa_proplist_new();
57
58     return data;
59 }
60
61 void pa_source_new_data_set_name(pa_source_new_data *data, const char *name) {
62     pa_assert(data);
63
64     pa_xfree(data->name);
65     data->name = pa_xstrdup(name);
66 }
67
68 void pa_source_new_data_set_sample_spec(pa_source_new_data *data, const pa_sample_spec *spec) {
69     pa_assert(data);
70
71     if ((data->sample_spec_is_set = !!spec))
72         data->sample_spec = *spec;
73 }
74
75 void pa_source_new_data_set_channel_map(pa_source_new_data *data, const pa_channel_map *map) {
76     pa_assert(data);
77
78     if ((data->channel_map_is_set = !!map))
79         data->channel_map = *map;
80 }
81
82 void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume) {
83     pa_assert(data);
84
85     if ((data->volume_is_set = !!volume))
86         data->volume = *volume;
87 }
88
89 void pa_source_new_data_set_muted(pa_source_new_data *data, pa_bool_t mute) {
90     pa_assert(data);
91
92     data->muted_is_set = TRUE;
93     data->muted = !!mute;
94 }
95
96 void pa_source_new_data_set_port(pa_source_new_data *data, const char *port) {
97     pa_assert(data);
98
99     pa_xfree(data->active_port);
100     data->active_port = pa_xstrdup(port);
101 }
102
103 void pa_source_new_data_done(pa_source_new_data *data) {
104     pa_assert(data);
105
106     pa_proplist_free(data->proplist);
107
108     if (data->ports) {
109         pa_device_port *p;
110
111         while ((p = pa_hashmap_steal_first(data->ports)))
112             pa_device_port_free(p);
113
114         pa_hashmap_free(data->ports, NULL, NULL);
115     }
116
117     pa_xfree(data->name);
118     pa_xfree(data->active_port);
119 }
120
121 /* Called from main context */
122 static void reset_callbacks(pa_source *s) {
123     pa_assert(s);
124
125     s->set_state = NULL;
126     s->get_volume = NULL;
127     s->set_volume = NULL;
128     s->get_mute = NULL;
129     s->set_mute = NULL;
130     s->update_requested_latency = NULL;
131     s->set_port = NULL;
132 }
133
134 /* Called from main context */
135 pa_source* pa_source_new(
136         pa_core *core,
137         pa_source_new_data *data,
138         pa_source_flags_t flags) {
139
140     pa_source *s;
141     const char *name;
142     char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
143     char *pt;
144
145     pa_assert(core);
146     pa_assert(data);
147     pa_assert(data->name);
148
149     s = pa_msgobject_new(pa_source);
150
151     if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) {
152         pa_xfree(s);
153         return NULL;
154     }
155
156     pa_source_new_data_set_name(data, name);
157
158     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0) {
159         pa_xfree(s);
160         pa_namereg_unregister(core, name);
161         return NULL;
162     }
163
164     /* FIXME, need to free s here on failure */
165
166     pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
167     pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
168
169     pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
170
171     if (!data->channel_map_is_set)
172         pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
173
174     pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
175     pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
176
177     if (!data->volume_is_set)
178         pa_cvolume_reset(&data->volume, data->sample_spec.channels);
179
180     pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
181     pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
182
183     if (!data->muted_is_set)
184         data->muted = FALSE;
185
186     if (data->card)
187         pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
188
189     pa_device_init_description(data->proplist);
190     pa_device_init_icon(data->proplist, FALSE);
191     pa_device_init_intended_roles(data->proplist);
192
193     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) {
194         pa_xfree(s);
195         pa_namereg_unregister(core, name);
196         return NULL;
197     }
198
199     s->parent.parent.free = source_free;
200     s->parent.process_msg = pa_source_process_msg;
201
202     s->core = core;
203     s->state = PA_SOURCE_INIT;
204     s->flags = flags;
205     s->suspend_cause = 0;
206     s->name = pa_xstrdup(name);
207     s->proplist = pa_proplist_copy(data->proplist);
208     s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
209     s->module = data->module;
210     s->card = data->card;
211
212     s->sample_spec = data->sample_spec;
213     s->channel_map = data->channel_map;
214
215     s->outputs = pa_idxset_new(NULL, NULL);
216     s->n_corked = 0;
217     s->monitor_of = NULL;
218
219     s->virtual_volume = data->volume;
220     pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
221     s->base_volume = PA_VOLUME_NORM;
222     s->n_volume_steps = PA_VOLUME_NORM+1;
223     s->muted = data->muted;
224     s->refresh_volume = s->refresh_muted = FALSE;
225
226     s->fixed_latency = flags & PA_SOURCE_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
227
228     reset_callbacks(s);
229     s->userdata = NULL;
230
231     s->asyncmsgq = NULL;
232     s->rtpoll = NULL;
233
234     /* As a minor optimization we just steal the list instead of
235      * copying it here */
236     s->ports = data->ports;
237     data->ports = NULL;
238
239     s->active_port = NULL;
240     s->save_port = FALSE;
241
242     if (data->active_port && s->ports)
243         if ((s->active_port = pa_hashmap_get(s->ports, data->active_port)))
244             s->save_port = data->save_port;
245
246     if (!s->active_port && s->ports) {
247         void *state;
248         pa_device_port *p;
249
250         PA_HASHMAP_FOREACH(p, s->ports, state)
251             if (!s->active_port || p->priority > s->active_port->priority)
252                 s->active_port = p;
253     }
254
255     s->save_volume = data->save_volume;
256     s->save_muted = data->save_muted;
257
258     pa_silence_memchunk_get(
259             &core->silence_cache,
260             core->mempool,
261             &s->silence,
262             &s->sample_spec,
263             0);
264
265     s->thread_info.outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
266     s->thread_info.soft_volume = s->soft_volume;
267     s->thread_info.soft_muted = s->muted;
268     s->thread_info.state = s->state;
269     s->thread_info.max_rewind = 0;
270     s->thread_info.requested_latency_valid = FALSE;
271     s->thread_info.requested_latency = 0;
272     s->thread_info.min_latency = ABSOLUTE_MIN_LATENCY;
273     s->thread_info.max_latency = ABSOLUTE_MAX_LATENCY;
274
275     pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
276
277     if (s->card)
278         pa_assert_se(pa_idxset_put(s->card->sources, s, NULL) >= 0);
279
280     pt = pa_proplist_to_string_sep(s->proplist, "\n    ");
281     pa_log_info("Created source %u \"%s\" with sample spec %s and channel map %s\n    %s",
282                 s->index,
283                 s->name,
284                 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
285                 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
286                 pt);
287     pa_xfree(pt);
288
289     return s;
290 }
291
292 /* Called from main context */
293 static int source_set_state(pa_source *s, pa_source_state_t state) {
294     int ret;
295     pa_bool_t suspend_change;
296     pa_source_state_t original_state;
297
298     pa_assert(s);
299
300     if (s->state == state)
301         return 0;
302
303     original_state = s->state;
304
305     suspend_change =
306         (original_state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(state)) ||
307         (PA_SOURCE_IS_OPENED(original_state) && state == PA_SOURCE_SUSPENDED);
308
309     if (s->set_state)
310         if ((ret = s->set_state(s, state)) < 0)
311             return ret;
312
313     if (s->asyncmsgq)
314         if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
315
316             if (s->set_state)
317                 s->set_state(s, original_state);
318
319             return ret;
320         }
321
322     s->state = state;
323
324     if (state != PA_SOURCE_UNLINKED) { /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
325         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
326         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
327     }
328
329     if (suspend_change) {
330         pa_source_output *o;
331         uint32_t idx;
332
333         /* We're suspending or resuming, tell everyone about it */
334
335         for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx)))
336             if (s->state == PA_SOURCE_SUSPENDED &&
337                 (o->flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND))
338                 pa_source_output_kill(o);
339             else if (o->suspend)
340                 o->suspend(o, state == PA_SOURCE_SUSPENDED);
341     }
342
343
344     return 0;
345 }
346
347 /* Called from main context */
348 void pa_source_put(pa_source *s) {
349     pa_source_assert_ref(s);
350
351     pa_assert(s->state == PA_SOURCE_INIT);
352
353     /* The following fields must be initialized properly when calling _put() */
354     pa_assert(s->asyncmsgq);
355     pa_assert(s->rtpoll);
356     pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
357
358     /* Generally, flags should be initialized via pa_source_new(). As
359      * a special exception we allow volume related flags to be set
360      * between _new() and _put(). */
361
362     if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL))
363         s->flags |= PA_SOURCE_DECIBEL_VOLUME;
364
365     s->thread_info.soft_volume = s->soft_volume;
366     s->thread_info.soft_muted = s->muted;
367
368     pa_assert((s->flags & PA_SOURCE_HW_VOLUME_CTRL) || (s->base_volume == PA_VOLUME_NORM && s->flags & PA_SOURCE_DECIBEL_VOLUME));
369     pa_assert(!(s->flags & PA_SOURCE_DECIBEL_VOLUME) || s->n_volume_steps == PA_VOLUME_NORM+1);
370     pa_assert(!(s->flags & PA_SOURCE_DYNAMIC_LATENCY) == (s->fixed_latency != 0));
371
372     pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
373
374     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
375     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s);
376 }
377
378 /* Called from main context */
379 void pa_source_unlink(pa_source *s) {
380     pa_bool_t linked;
381     pa_source_output *o, *j = NULL;
382
383     pa_assert(s);
384
385     /* See pa_sink_unlink() for a couple of comments how this function
386      * works. */
387
388     linked = PA_SOURCE_IS_LINKED(s->state);
389
390     if (linked)
391         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
392
393     if (s->state != PA_SOURCE_UNLINKED)
394         pa_namereg_unregister(s->core, s->name);
395     pa_idxset_remove_by_data(s->core->sources, s, NULL);
396
397     if (s->card)
398         pa_idxset_remove_by_data(s->card->sources, s, NULL);
399
400     while ((o = pa_idxset_first(s->outputs, NULL))) {
401         pa_assert(o != j);
402         pa_source_output_kill(o);
403         j = o;
404     }
405
406     if (linked)
407         source_set_state(s, PA_SOURCE_UNLINKED);
408     else
409         s->state = PA_SOURCE_UNLINKED;
410
411     reset_callbacks(s);
412
413     if (linked) {
414         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
415         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s);
416     }
417 }
418
419 /* Called from main context */
420 static void source_free(pa_object *o) {
421     pa_source_output *so;
422     pa_source *s = PA_SOURCE(o);
423
424     pa_assert(s);
425     pa_assert(pa_source_refcnt(s) == 0);
426
427     if (PA_SOURCE_IS_LINKED(s->state))
428         pa_source_unlink(s);
429
430     pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
431
432     pa_idxset_free(s->outputs, NULL, NULL);
433
434     while ((so = pa_hashmap_steal_first(s->thread_info.outputs)))
435         pa_source_output_unref(so);
436
437     pa_hashmap_free(s->thread_info.outputs, NULL, NULL);
438
439     if (s->silence.memblock)
440         pa_memblock_unref(s->silence.memblock);
441
442     pa_xfree(s->name);
443     pa_xfree(s->driver);
444
445     if (s->proplist)
446         pa_proplist_free(s->proplist);
447
448     if (s->ports) {
449         pa_device_port *p;
450
451         while ((p = pa_hashmap_steal_first(s->ports)))
452             pa_device_port_free(p);
453
454         pa_hashmap_free(s->ports, NULL, NULL);
455     }
456
457     pa_xfree(s);
458 }
459
460 /* Called from main context */
461 void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) {
462     pa_source_assert_ref(s);
463
464     s->asyncmsgq = q;
465 }
466
467 /* Called from main context */
468 void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) {
469     pa_source_assert_ref(s);
470
471     s->rtpoll = p;
472 }
473
474 /* Called from main context */
475 int pa_source_update_status(pa_source*s) {
476     pa_source_assert_ref(s);
477     pa_assert(PA_SOURCE_IS_LINKED(s->state));
478
479     if (s->state == PA_SOURCE_SUSPENDED)
480         return 0;
481
482     return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
483 }
484
485 /* Called from main context */
486 int pa_source_suspend(pa_source *s, pa_bool_t suspend, pa_suspend_cause_t cause) {
487     pa_source_assert_ref(s);
488     pa_assert(PA_SOURCE_IS_LINKED(s->state));
489     pa_assert(cause != 0);
490
491     if (s->monitor_of)
492         return -PA_ERR_NOTSUPPORTED;
493
494     if (suspend)
495         s->suspend_cause |= cause;
496     else
497         s->suspend_cause &= ~cause;
498
499     if ((pa_source_get_state(s) == PA_SOURCE_SUSPENDED) == !!s->suspend_cause)
500         return 0;
501
502     pa_log_debug("Suspend cause of source %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming");
503
504     if (suspend)
505         return source_set_state(s, PA_SOURCE_SUSPENDED);
506     else
507         return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
508 }
509
510 /* Called from main context */
511 int pa_source_sync_suspend(pa_source *s) {
512     pa_sink_state_t state;
513
514     pa_source_assert_ref(s);
515     pa_assert(PA_SOURCE_IS_LINKED(s->state));
516     pa_assert(s->monitor_of);
517
518     state = pa_sink_get_state(s->monitor_of);
519
520     if (state == PA_SINK_SUSPENDED)
521         return source_set_state(s, PA_SOURCE_SUSPENDED);
522
523     pa_assert(PA_SINK_IS_OPENED(state));
524
525     return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
526 }
527
528 /* Called from main context */
529 pa_queue *pa_source_move_all_start(pa_source *s, pa_queue *q) {
530     pa_source_output *o, *n;
531     uint32_t idx;
532
533     pa_source_assert_ref(s);
534     pa_assert(PA_SOURCE_IS_LINKED(s->state));
535
536     if (!q)
537         q = pa_queue_new();
538
539     for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = n) {
540         n = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx));
541
542         pa_source_output_ref(o);
543
544         if (pa_source_output_start_move(o) >= 0)
545             pa_queue_push(q, o);
546         else
547             pa_source_output_unref(o);
548     }
549
550     return q;
551 }
552
553 /* Called from main context */
554 void pa_source_move_all_finish(pa_source *s, pa_queue *q, pa_bool_t save) {
555     pa_source_output *o;
556
557     pa_source_assert_ref(s);
558     pa_assert(PA_SOURCE_IS_LINKED(s->state));
559     pa_assert(q);
560
561     while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
562         if (pa_source_output_finish_move(o, s, save) < 0)
563             pa_source_output_kill(o);
564
565         pa_source_output_unref(o);
566     }
567
568     pa_queue_free(q, NULL, NULL);
569 }
570
571 /* Called from main context */
572 void pa_source_move_all_fail(pa_queue *q) {
573     pa_source_output *o;
574     pa_assert(q);
575
576     while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
577         if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], o) == PA_HOOK_OK) {
578             pa_source_output_kill(o);
579             pa_source_output_unref(o);
580         }
581     }
582
583     pa_queue_free(q, NULL, NULL);
584 }
585
586 /* Called from IO thread context */
587 void pa_source_process_rewind(pa_source *s, size_t nbytes) {
588     pa_source_output *o;
589     void *state = NULL;
590
591     pa_source_assert_ref(s);
592     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
593
594     if (s->thread_info.state == PA_SOURCE_SUSPENDED)
595         return;
596
597     if (nbytes <= 0)
598         return;
599
600     pa_log_debug("Processing rewind...");
601
602     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
603         pa_source_output_assert_ref(o);
604         pa_source_output_process_rewind(o, nbytes);
605     }
606 }
607
608 /* Called from IO thread context */
609 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
610     pa_source_output *o;
611     void *state = NULL;
612
613     pa_source_assert_ref(s);
614     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
615     pa_assert(chunk);
616
617     if (s->thread_info.state == PA_SOURCE_SUSPENDED)
618         return;
619
620     if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
621         pa_memchunk vchunk = *chunk;
622
623         pa_memblock_ref(vchunk.memblock);
624         pa_memchunk_make_writable(&vchunk, 0);
625
626         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
627             pa_silence_memchunk(&vchunk, &s->sample_spec);
628         else
629             pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
630
631         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
632             pa_source_output_assert_ref(o);
633
634             if (!o->thread_info.direct_on_input)
635                 pa_source_output_push(o, &vchunk);
636         }
637
638         pa_memblock_unref(vchunk.memblock);
639     } else {
640
641         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
642             pa_source_output_assert_ref(o);
643
644             if (!o->thread_info.direct_on_input)
645                 pa_source_output_push(o, chunk);
646         }
647     }
648 }
649
650 /* Called from IO thread context */
651 void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk *chunk) {
652     pa_source_assert_ref(s);
653     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
654     pa_source_output_assert_ref(o);
655     pa_assert(o->thread_info.direct_on_input);
656     pa_assert(chunk);
657
658     if (s->thread_info.state == PA_SOURCE_SUSPENDED)
659         return;
660
661     if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
662         pa_memchunk vchunk = *chunk;
663
664         pa_memblock_ref(vchunk.memblock);
665         pa_memchunk_make_writable(&vchunk, 0);
666
667         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
668             pa_silence_memchunk(&vchunk, &s->sample_spec);
669         else
670             pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
671
672         pa_source_output_push(o, &vchunk);
673
674         pa_memblock_unref(vchunk.memblock);
675     } else
676         pa_source_output_push(o, chunk);
677 }
678
679 /* Called from main thread */
680 pa_usec_t pa_source_get_latency(pa_source *s) {
681     pa_usec_t usec;
682
683     pa_source_assert_ref(s);
684     pa_assert(PA_SOURCE_IS_LINKED(s->state));
685
686     if (s->state == PA_SOURCE_SUSPENDED)
687         return 0;
688
689     if (!(s->flags & PA_SOURCE_LATENCY))
690         return 0;
691
692     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
693
694     return usec;
695 }
696
697 /* Called from IO thread */
698 pa_usec_t pa_source_get_latency_within_thread(pa_source *s) {
699     pa_usec_t usec = 0;
700     pa_msgobject *o;
701
702     pa_source_assert_ref(s);
703     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
704
705     /* The returned value is supposed to be in the time domain of the sound card! */
706
707     if (s->thread_info.state == PA_SOURCE_SUSPENDED)
708         return 0;
709
710     if (!(s->flags & PA_SOURCE_LATENCY))
711         return 0;
712
713     o = PA_MSGOBJECT(s);
714
715     /* We probably should make this a proper vtable callback instead of going through process_msg() */
716
717     if (o->process_msg(o, PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
718         return -1;
719
720     return usec;
721 }
722
723 /* Called from main thread */
724 void pa_source_set_volume(pa_source *s, const pa_cvolume *volume, pa_bool_t save) {
725     pa_cvolume old_virtual_volume;
726     pa_bool_t virtual_volume_changed;
727
728     pa_source_assert_ref(s);
729     pa_assert(PA_SOURCE_IS_LINKED(s->state));
730     pa_assert(volume);
731     pa_assert(pa_cvolume_valid(volume));
732     pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
733
734     old_virtual_volume = s->virtual_volume;
735     s->virtual_volume = *volume;
736     virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume);
737     s->save_volume = (!virtual_volume_changed && s->save_volume) || save;
738
739     if (s->set_volume) {
740         pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
741         s->set_volume(s);
742     } else
743         s->soft_volume = s->virtual_volume;
744
745     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
746
747     if (virtual_volume_changed)
748         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
749 }
750
751 /* Called from main thread. Only to be called by source implementor */
752 void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume) {
753     pa_source_assert_ref(s);
754     pa_assert(volume);
755
756     if (PA_SOURCE_IS_LINKED(s->state))
757         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
758     else
759         s->thread_info.soft_volume = *volume;
760 }
761
762 /* Called from main thread */
763 const pa_cvolume *pa_source_get_volume(pa_source *s, pa_bool_t force_refresh) {
764     pa_source_assert_ref(s);
765     pa_assert(PA_SOURCE_IS_LINKED(s->state));
766
767     if (s->refresh_volume || force_refresh) {
768         pa_cvolume old_virtual_volume = s->virtual_volume;
769
770         if (s->get_volume)
771             s->get_volume(s);
772
773         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
774
775         if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume))
776             pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
777     }
778
779     return &s->virtual_volume;
780 }
781
782 /* Called from main thread */
783 void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume, pa_bool_t save) {
784     pa_source_assert_ref(s);
785
786     /* The source implementor may call this if the volume changed to make sure everyone is notified */
787
788     if (pa_cvolume_equal(&s->virtual_volume, new_volume)) {
789         s->save_volume = s->save_volume || save;
790         return;
791     }
792
793     s->virtual_volume = *new_volume;
794     s->save_volume = save;
795
796     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
797 }
798
799 /* Called from main thread */
800 void pa_source_set_mute(pa_source *s, pa_bool_t mute, pa_bool_t save) {
801     pa_bool_t old_muted;
802
803     pa_source_assert_ref(s);
804     pa_assert(PA_SOURCE_IS_LINKED(s->state));
805
806     old_muted = s->muted;
807     s->muted = mute;
808     s->save_muted = (old_muted == s->muted && s->save_muted) || save;
809
810     if (s->set_mute)
811         s->set_mute(s);
812
813     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
814
815     if (old_muted != s->muted)
816         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
817 }
818
819 /* Called from main thread */
820 pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
821     pa_source_assert_ref(s);
822     pa_assert(PA_SOURCE_IS_LINKED(s->state));
823
824     if (s->refresh_muted || force_refresh) {
825         pa_bool_t old_muted = s->muted;
826
827         if (s->get_mute)
828             s->get_mute(s);
829
830         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
831
832         if (old_muted != s->muted) {
833             pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
834
835             /* Make sure the soft mute status stays in sync */
836             pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
837         }
838     }
839
840     return s->muted;
841 }
842
843 /* Called from main thread */
844 void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted, pa_bool_t save) {
845     pa_source_assert_ref(s);
846
847     /* The source implementor may call this if the mute state changed to make sure everyone is notified */
848
849     if (s->muted == new_muted) {
850         s->save_muted = s->save_muted || save;
851         return;
852     }
853
854     s->muted = new_muted;
855     s->save_muted = save;
856
857     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
858 }
859
860 /* Called from main thread */
861 pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p) {
862     pa_source_assert_ref(s);
863
864     if (p)
865         pa_proplist_update(s->proplist, mode, p);
866
867     if (PA_SOURCE_IS_LINKED(s->state)) {
868         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
869         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
870     }
871
872     return TRUE;
873 }
874
875 /* Called from main thread */
876 void pa_source_set_description(pa_source *s, const char *description) {
877     const char *old;
878     pa_source_assert_ref(s);
879
880     if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
881         return;
882
883     old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
884
885     if (old && description && !strcmp(old, description))
886         return;
887
888     if (description)
889         pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
890     else
891         pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
892
893     if (PA_SOURCE_IS_LINKED(s->state)) {
894         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
895         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
896     }
897 }
898
899 /* Called from main thread */
900 unsigned pa_source_linked_by(pa_source *s) {
901     pa_source_assert_ref(s);
902     pa_assert(PA_SOURCE_IS_LINKED(s->state));
903
904     return pa_idxset_size(s->outputs);
905 }
906
907 /* Called from main thread */
908 unsigned pa_source_used_by(pa_source *s) {
909     unsigned ret;
910
911     pa_source_assert_ref(s);
912     pa_assert(PA_SOURCE_IS_LINKED(s->state));
913
914     ret = pa_idxset_size(s->outputs);
915     pa_assert(ret >= s->n_corked);
916
917     return ret - s->n_corked;
918 }
919
920 /* Called from main thread */
921 unsigned pa_source_check_suspend(pa_source *s) {
922     unsigned ret;
923     pa_source_output *o;
924     uint32_t idx;
925
926     pa_source_assert_ref(s);
927
928     if (!PA_SOURCE_IS_LINKED(s->state))
929         return 0;
930
931     ret = 0;
932
933     PA_IDXSET_FOREACH(o, s->outputs, idx) {
934         pa_source_output_state_t st;
935
936         st = pa_source_output_get_state(o);
937         pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(st));
938
939         if (st == PA_SOURCE_OUTPUT_CORKED)
940             continue;
941
942         if (o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND)
943             continue;
944
945         ret ++;
946     }
947
948     return ret;
949 }
950
951 /* Called from IO thread, except when it is not */
952 int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
953     pa_source *s = PA_SOURCE(object);
954     pa_source_assert_ref(s);
955
956     switch ((pa_source_message_t) code) {
957
958         case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
959             pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
960
961             pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
962
963             if (o->direct_on_input) {
964                 o->thread_info.direct_on_input = o->direct_on_input;
965                 pa_hashmap_put(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index), o);
966             }
967
968             pa_assert(!o->thread_info.attached);
969             o->thread_info.attached = TRUE;
970
971             if (o->attach)
972                 o->attach(o);
973
974             pa_source_output_set_state_within_thread(o, o->state);
975
976             if (o->thread_info.requested_source_latency != (pa_usec_t) -1)
977                 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
978
979             pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
980
981             /* We don't just invalidate the requested latency here,
982              * because if we are in a move we might need to fix up the
983              * requested latency. */
984             pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
985
986             return 0;
987         }
988
989         case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
990             pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
991
992             pa_source_output_set_state_within_thread(o, o->state);
993
994             if (o->detach)
995                 o->detach(o);
996
997             pa_assert(o->thread_info.attached);
998             o->thread_info.attached = FALSE;
999
1000             if (o->thread_info.direct_on_input) {
1001                 pa_hashmap_remove(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index));
1002                 o->thread_info.direct_on_input = NULL;
1003             }
1004
1005             if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
1006                 pa_source_output_unref(o);
1007
1008             pa_source_invalidate_requested_latency(s);
1009
1010             return 0;
1011         }
1012
1013         case PA_SOURCE_MESSAGE_SET_VOLUME:
1014             s->thread_info.soft_volume = s->soft_volume;
1015             return 0;
1016
1017         case PA_SOURCE_MESSAGE_GET_VOLUME:
1018             return 0;
1019
1020         case PA_SOURCE_MESSAGE_SET_MUTE:
1021             s->thread_info.soft_muted = s->muted;
1022             return 0;
1023
1024         case PA_SOURCE_MESSAGE_GET_MUTE:
1025             return 0;
1026
1027         case PA_SOURCE_MESSAGE_SET_STATE: {
1028
1029             pa_bool_t suspend_change =
1030                 (s->thread_info.state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(PA_PTR_TO_UINT(userdata))) ||
1031                 (PA_SOURCE_IS_OPENED(s->thread_info.state) && PA_PTR_TO_UINT(userdata) == PA_SOURCE_SUSPENDED);
1032
1033             s->thread_info.state = PA_PTR_TO_UINT(userdata);
1034
1035             if (suspend_change) {
1036                 pa_source_output *o;
1037                 void *state = NULL;
1038
1039                 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1040                     if (o->suspend_within_thread)
1041                         o->suspend_within_thread(o, s->thread_info.state == PA_SOURCE_SUSPENDED);
1042             }
1043
1044
1045             return 0;
1046         }
1047
1048         case PA_SOURCE_MESSAGE_DETACH:
1049
1050             /* Detach all streams */
1051             pa_source_detach_within_thread(s);
1052             return 0;
1053
1054         case PA_SOURCE_MESSAGE_ATTACH:
1055
1056             /* Reattach all streams */
1057             pa_source_attach_within_thread(s);
1058             return 0;
1059
1060         case PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY: {
1061
1062             pa_usec_t *usec = userdata;
1063             *usec = pa_source_get_requested_latency_within_thread(s);
1064
1065             if (*usec == (pa_usec_t) -1)
1066                 *usec = s->thread_info.max_latency;
1067
1068             return 0;
1069         }
1070
1071         case PA_SOURCE_MESSAGE_SET_LATENCY_RANGE: {
1072             pa_usec_t *r = userdata;
1073
1074             pa_source_set_latency_range_within_thread(s, r[0], r[1]);
1075
1076             return 0;
1077         }
1078
1079         case PA_SOURCE_MESSAGE_GET_LATENCY_RANGE: {
1080             pa_usec_t *r = userdata;
1081
1082             r[0] = s->thread_info.min_latency;
1083             r[1] = s->thread_info.max_latency;
1084
1085             return 0;
1086         }
1087
1088         case PA_SOURCE_MESSAGE_GET_MAX_REWIND:
1089
1090             *((size_t*) userdata) = s->thread_info.max_rewind;
1091             return 0;
1092
1093         case PA_SOURCE_MESSAGE_SET_MAX_REWIND:
1094
1095             pa_source_set_max_rewind_within_thread(s, (size_t) offset);
1096             return 0;
1097
1098         case PA_SOURCE_MESSAGE_GET_LATENCY:
1099
1100             if (s->monitor_of) {
1101                 *((pa_usec_t*) userdata) = 0;
1102                 return 0;
1103             }
1104
1105             /* Implementors need to overwrite this implementation! */
1106             return -1;
1107
1108         case PA_SOURCE_MESSAGE_MAX:
1109             ;
1110     }
1111
1112     return -1;
1113 }
1114
1115 /* Called from main thread */
1116 int pa_source_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause) {
1117     uint32_t idx;
1118     pa_source *source;
1119     int ret = 0;
1120
1121     pa_core_assert_ref(c);
1122     pa_assert(cause != 0);
1123
1124     for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx))) {
1125         int r;
1126
1127         if (source->monitor_of)
1128             continue;
1129
1130         if ((r = pa_source_suspend(source, suspend, cause)) < 0)
1131             ret = r;
1132     }
1133
1134     return ret;
1135 }
1136
1137 /* Called from main thread */
1138 void pa_source_detach(pa_source *s) {
1139     pa_source_assert_ref(s);
1140     pa_assert(PA_SOURCE_IS_LINKED(s->state));
1141
1142     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL) == 0);
1143 }
1144
1145 /* Called from main thread */
1146 void pa_source_attach(pa_source *s) {
1147     pa_source_assert_ref(s);
1148     pa_assert(PA_SOURCE_IS_LINKED(s->state));
1149
1150     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
1151 }
1152
1153 /* Called from IO thread */
1154 void pa_source_detach_within_thread(pa_source *s) {
1155     pa_source_output *o;
1156     void *state = NULL;
1157
1158     pa_source_assert_ref(s);
1159     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1160
1161     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1162         if (o->detach)
1163             o->detach(o);
1164 }
1165
1166 /* Called from IO thread */
1167 void pa_source_attach_within_thread(pa_source *s) {
1168     pa_source_output *o;
1169     void *state = NULL;
1170
1171     pa_source_assert_ref(s);
1172     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1173
1174     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1175         if (o->attach)
1176             o->attach(o);
1177 }
1178
1179 /* Called from IO thread */
1180 pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
1181     pa_usec_t result = (pa_usec_t) -1;
1182     pa_source_output *o;
1183     void *state = NULL;
1184
1185     pa_source_assert_ref(s);
1186
1187     if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
1188         return PA_CLAMP(s->fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
1189
1190     if (s->thread_info.requested_latency_valid)
1191         return s->thread_info.requested_latency;
1192
1193     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1194
1195         if (o->thread_info.requested_source_latency != (pa_usec_t) -1 &&
1196             (result == (pa_usec_t) -1 || result > o->thread_info.requested_source_latency))
1197             result = o->thread_info.requested_source_latency;
1198
1199     if (result != (pa_usec_t) -1)
1200         result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
1201
1202     if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1203         /* Only cache this if we are fully set up */
1204         s->thread_info.requested_latency = result;
1205         s->thread_info.requested_latency_valid = TRUE;
1206     }
1207
1208     return result;
1209 }
1210
1211 /* Called from main thread */
1212 pa_usec_t pa_source_get_requested_latency(pa_source *s) {
1213     pa_usec_t usec = 0;
1214
1215     pa_source_assert_ref(s);
1216     pa_assert(PA_SOURCE_IS_LINKED(s->state));
1217
1218     if (s->state == PA_SOURCE_SUSPENDED)
1219         return 0;
1220
1221     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1222
1223     return usec;
1224 }
1225
1226 /* Called from IO thread */
1227 void pa_source_set_max_rewind_within_thread(pa_source *s, size_t max_rewind) {
1228     pa_source_output *o;
1229     void *state = NULL;
1230
1231     pa_source_assert_ref(s);
1232
1233     if (max_rewind == s->thread_info.max_rewind)
1234         return;
1235
1236     s->thread_info.max_rewind = max_rewind;
1237
1238     if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1239         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1240             pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
1241     }
1242 }
1243
1244 /* Called from main thread */
1245 void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
1246     pa_source_assert_ref(s);
1247
1248     if (PA_SOURCE_IS_LINKED(s->state))
1249         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
1250     else
1251         pa_source_set_max_rewind_within_thread(s, max_rewind);
1252 }
1253
1254 /* Called from IO thread */
1255 void pa_source_invalidate_requested_latency(pa_source *s) {
1256     pa_source_output *o;
1257     void *state = NULL;
1258
1259     pa_source_assert_ref(s);
1260
1261     if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
1262         return;
1263
1264     s->thread_info.requested_latency_valid = FALSE;
1265
1266     if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1267
1268         if (s->update_requested_latency)
1269             s->update_requested_latency(s);
1270
1271         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1272             if (o->update_source_requested_latency)
1273                 o->update_source_requested_latency(o);
1274     }
1275
1276     if (s->monitor_of)
1277         pa_sink_invalidate_requested_latency(s->monitor_of);
1278 }
1279
1280 /* Called from main thread */
1281 void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1282     pa_source_assert_ref(s);
1283
1284     /* min_latency == 0:           no limit
1285      * min_latency anything else:  specified limit
1286      *
1287      * Similar for max_latency */
1288
1289     if (min_latency < ABSOLUTE_MIN_LATENCY)
1290         min_latency = ABSOLUTE_MIN_LATENCY;
1291
1292     if (max_latency <= 0 ||
1293         max_latency > ABSOLUTE_MAX_LATENCY)
1294         max_latency = ABSOLUTE_MAX_LATENCY;
1295
1296     pa_assert(min_latency <= max_latency);
1297
1298     /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1299     pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
1300                max_latency == ABSOLUTE_MAX_LATENCY) ||
1301               (s->flags & PA_SOURCE_DYNAMIC_LATENCY));
1302
1303     if (PA_SOURCE_IS_LINKED(s->state)) {
1304         pa_usec_t r[2];
1305
1306         r[0] = min_latency;
1307         r[1] = max_latency;
1308
1309         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
1310     } else
1311         pa_source_set_latency_range_within_thread(s, min_latency, max_latency);
1312 }
1313
1314 /* Called from main thread */
1315 void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
1316    pa_source_assert_ref(s);
1317    pa_assert(min_latency);
1318    pa_assert(max_latency);
1319
1320    if (PA_SOURCE_IS_LINKED(s->state)) {
1321        pa_usec_t r[2] = { 0, 0 };
1322
1323        pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
1324
1325        *min_latency = r[0];
1326        *max_latency = r[1];
1327    } else {
1328        *min_latency = s->thread_info.min_latency;
1329        *max_latency = s->thread_info.max_latency;
1330    }
1331 }
1332
1333 /* Called from IO thread, and from main thread before pa_source_put() is called */
1334 void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1335     void *state = NULL;
1336
1337     pa_source_assert_ref(s);
1338
1339     pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
1340     pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
1341     pa_assert(min_latency <= max_latency);
1342
1343     /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1344     pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
1345                max_latency == ABSOLUTE_MAX_LATENCY) ||
1346               (s->flags & PA_SOURCE_DYNAMIC_LATENCY) ||
1347               s->monitor_of);
1348
1349     s->thread_info.min_latency = min_latency;
1350     s->thread_info.max_latency = max_latency;
1351
1352     if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1353         pa_source_output *o;
1354
1355         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1356             if (o->update_source_latency_range)
1357                 o->update_source_latency_range(o);
1358     }
1359
1360     pa_source_invalidate_requested_latency(s);
1361 }
1362
1363 /* Called from main thread, before the source is put */
1364 void pa_source_set_fixed_latency(pa_source *s, pa_usec_t latency) {
1365     pa_source_assert_ref(s);
1366
1367     pa_assert(pa_source_get_state(s) == PA_SOURCE_INIT);
1368
1369     if (latency < ABSOLUTE_MIN_LATENCY)
1370         latency = ABSOLUTE_MIN_LATENCY;
1371
1372     if (latency > ABSOLUTE_MAX_LATENCY)
1373         latency = ABSOLUTE_MAX_LATENCY;
1374
1375     s->fixed_latency = latency;
1376 }
1377
1378 /* Called from main thread */
1379 size_t pa_source_get_max_rewind(pa_source *s) {
1380     size_t r;
1381     pa_source_assert_ref(s);
1382
1383     if (!PA_SOURCE_IS_LINKED(s->state))
1384         return s->thread_info.max_rewind;
1385
1386     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
1387
1388     return r;
1389 }
1390
1391 /* Called from main context */
1392 int pa_source_set_port(pa_source *s, const char *name, pa_bool_t save) {
1393     pa_device_port *port;
1394
1395     pa_assert(s);
1396
1397     if (!s->set_port) {
1398         pa_log_debug("set_port() operation not implemented for sink %u \"%s\"", s->index, s->name);
1399         return -PA_ERR_NOTIMPLEMENTED;
1400     }
1401
1402     if (!s->ports)
1403         return -PA_ERR_NOENTITY;
1404
1405     if (!(port = pa_hashmap_get(s->ports, name)))
1406         return -PA_ERR_NOENTITY;
1407
1408     if (s->active_port == port) {
1409         s->save_port = s->save_port || save;
1410         return 0;
1411     }
1412
1413     if ((s->set_port(s, port)) < 0)
1414         return -PA_ERR_NOENTITY;
1415
1416     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1417
1418     pa_log_info("Changed port of source %u \"%s\" to %s", s->index, s->name, port->name);
1419
1420     s->active_port = port;
1421     s->save_port = save;
1422
1423     return 0;
1424 }