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