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