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