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