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