Don't allow suspending of monitor sources.
[platform/upstream/pulseaudio.git] / src / pulsecore / source.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20   USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <pulse/utf8.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
35
36 #include <pulsecore/source-output.h>
37 #include <pulsecore/namereg.h>
38 #include <pulsecore/core-subscribe.h>
39 #include <pulsecore/log.h>
40 #include <pulsecore/sample-util.h>
41
42 #include "source.h"
43
44 #define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
45
46 static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
47
48 static void source_free(pa_object *o);
49
50 pa_source_new_data* pa_source_new_data_init(pa_source_new_data *data) {
51     pa_assert(data);
52
53     memset(data, 0, sizeof(*data));
54     data->proplist = pa_proplist_new();
55
56     return data;
57 }
58
59 void pa_source_new_data_set_name(pa_source_new_data *data, const char *name) {
60     pa_assert(data);
61
62     pa_xfree(data->name);
63     data->name = pa_xstrdup(name);
64 }
65
66 void pa_source_new_data_set_sample_spec(pa_source_new_data *data, const pa_sample_spec *spec) {
67     pa_assert(data);
68
69     if ((data->sample_spec_is_set = !!spec))
70         data->sample_spec = *spec;
71 }
72
73 void pa_source_new_data_set_channel_map(pa_source_new_data *data, const pa_channel_map *map) {
74     pa_assert(data);
75
76     if ((data->channel_map_is_set = !!map))
77         data->channel_map = *map;
78 }
79
80 void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume) {
81     pa_assert(data);
82
83     if ((data->volume_is_set = !!volume))
84         data->volume = *volume;
85 }
86
87 void pa_source_new_data_set_muted(pa_source_new_data *data, pa_bool_t mute) {
88     pa_assert(data);
89
90     data->muted_is_set = TRUE;
91     data->muted = !!mute;
92 }
93
94 void pa_source_new_data_done(pa_source_new_data *data) {
95     pa_assert(data);
96
97     pa_xfree(data->name);
98     pa_proplist_free(data->proplist);
99 }
100
101 /* Called from main context */
102 static void reset_callbacks(pa_source *s) {
103     pa_assert(s);
104
105     s->set_state = NULL;
106     s->get_volume = NULL;
107     s->set_volume = NULL;
108     s->get_mute = NULL;
109     s->set_mute = NULL;
110     s->update_requested_latency = NULL;
111 }
112
113 /* Called from main context */
114 pa_source* pa_source_new(
115         pa_core *core,
116         pa_source_new_data *data,
117         pa_source_flags_t flags) {
118
119     pa_source *s;
120     const char *name;
121     char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
122     char *pt;
123
124     pa_assert(core);
125     pa_assert(data);
126     pa_assert(data->name);
127
128     s = pa_msgobject_new(pa_source);
129
130     if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) {
131         pa_xfree(s);
132         return NULL;
133     }
134
135     pa_source_new_data_set_name(data, name);
136
137     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0) {
138         pa_xfree(s);
139         pa_namereg_unregister(core, name);
140         return NULL;
141     }
142
143     pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
144     pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
145
146     pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
147
148     if (!data->channel_map_is_set)
149         pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
150
151     pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
152     pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
153
154     if (!data->volume_is_set)
155         pa_cvolume_reset(&data->volume, data->sample_spec.channels);
156
157     pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
158     pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
159
160     if (!data->muted_is_set)
161         data->muted = FALSE;
162
163     if (data->card)
164         pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
165
166     pa_device_init_description(data->proplist);
167     pa_device_init_icon(data->proplist, FALSE);
168
169     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) {
170         pa_xfree(s);
171         pa_namereg_unregister(core, name);
172         return NULL;
173     }
174
175     s->parent.parent.free = source_free;
176     s->parent.process_msg = pa_source_process_msg;
177
178     s->core = core;
179     s->state = PA_SOURCE_INIT;
180     s->flags = flags;
181     s->name = pa_xstrdup(name);
182     s->proplist = pa_proplist_copy(data->proplist);
183     s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
184     s->module = data->module;
185     s->card = data->card;
186
187     s->sample_spec = data->sample_spec;
188     s->channel_map = data->channel_map;
189
190     s->outputs = pa_idxset_new(NULL, NULL);
191     s->n_corked = 0;
192     s->monitor_of = NULL;
193
194     s->virtual_volume = data->volume;
195     pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
196     s->base_volume = PA_VOLUME_NORM;
197     s->n_volume_steps = PA_VOLUME_NORM+1;
198     s->muted = data->muted;
199     s->refresh_volume = s->refresh_muted = FALSE;
200
201     reset_callbacks(s);
202     s->userdata = NULL;
203
204     s->asyncmsgq = NULL;
205     s->rtpoll = NULL;
206
207     pa_silence_memchunk_get(
208             &core->silence_cache,
209             core->mempool,
210             &s->silence,
211             &s->sample_spec,
212             0);
213
214     s->thread_info.outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
215     s->thread_info.soft_volume = s->soft_volume;
216     s->thread_info.soft_muted = s->muted;
217     s->thread_info.state = s->state;
218     s->thread_info.max_rewind = 0;
219     s->thread_info.requested_latency_valid = FALSE;
220     s->thread_info.requested_latency = 0;
221     s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
222     s->thread_info.max_latency = 0;
223
224     pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
225
226     if (s->card)
227         pa_assert_se(pa_idxset_put(s->card->sources, s, NULL) >= 0);
228
229     pt = pa_proplist_to_string_sep(s->proplist, "\n    ");
230     pa_log_info("Created source %u \"%s\" with sample spec %s and channel map %s\n    %s",
231                 s->index,
232                 s->name,
233                 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
234                 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
235                 pt);
236     pa_xfree(pt);
237
238     return s;
239 }
240
241 /* Called from main context */
242 static int source_set_state(pa_source *s, pa_source_state_t state) {
243     int ret;
244     pa_bool_t suspend_change;
245     pa_source_state_t original_state;
246
247     pa_assert(s);
248
249     if (s->state == state)
250         return 0;
251
252     original_state = s->state;
253
254     suspend_change =
255         (original_state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(state)) ||
256         (PA_SOURCE_IS_OPENED(original_state) && state == PA_SOURCE_SUSPENDED);
257
258     if (s->set_state)
259         if ((ret = s->set_state(s, state)) < 0)
260             return ret;
261
262     if (s->asyncmsgq)
263         if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
264
265             if (s->set_state)
266                 s->set_state(s, original_state);
267
268             return ret;
269         }
270
271     s->state = state;
272
273     if (state != PA_SOURCE_UNLINKED) { /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
274         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
275         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
276     }
277
278     if (suspend_change) {
279         pa_source_output *o;
280         uint32_t idx;
281
282         /* We're suspending or resuming, tell everyone about it */
283
284         for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx)))
285             if (s->state == PA_SOURCE_SUSPENDED &&
286                 (o->flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND))
287                 pa_source_output_kill(o);
288             else if (o->suspend)
289                 o->suspend(o, state == PA_SOURCE_SUSPENDED);
290     }
291
292
293     return 0;
294 }
295
296 /* Called from main context */
297 void pa_source_put(pa_source *s) {
298     pa_source_assert_ref(s);
299
300     pa_assert(s->state == PA_SOURCE_INIT);
301
302     /* The following fields must be initialized properly when calling _put() */
303     pa_assert(s->asyncmsgq);
304     pa_assert(s->rtpoll);
305     pa_assert(!s->thread_info.min_latency || !s->thread_info.max_latency ||
306               s->thread_info.min_latency <= s->thread_info.max_latency);
307
308     if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL)) {
309         s->flags |= PA_SOURCE_DECIBEL_VOLUME;
310
311         s->thread_info.soft_volume = s->soft_volume;
312         s->thread_info.soft_muted = s->muted;
313     }
314
315     if (s->flags & PA_SOURCE_DECIBEL_VOLUME)
316         s->n_volume_steps = PA_VOLUME_NORM+1;
317
318     pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
319
320     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
321     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s);
322 }
323
324 /* Called from main context */
325 void pa_source_unlink(pa_source *s) {
326     pa_bool_t linked;
327     pa_source_output *o, *j = NULL;
328
329     pa_assert(s);
330
331     /* See pa_sink_unlink() for a couple of comments how this function
332      * works. */
333
334     linked = PA_SOURCE_IS_LINKED(s->state);
335
336     if (linked)
337         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
338
339     if (s->state != PA_SOURCE_UNLINKED)
340         pa_namereg_unregister(s->core, s->name);
341     pa_idxset_remove_by_data(s->core->sources, s, NULL);
342
343     if (s->card)
344         pa_idxset_remove_by_data(s->card->sources, s, NULL);
345
346     while ((o = pa_idxset_first(s->outputs, NULL))) {
347         pa_assert(o != j);
348         pa_source_output_kill(o);
349         j = o;
350     }
351
352     if (linked)
353         source_set_state(s, PA_SOURCE_UNLINKED);
354     else
355         s->state = PA_SOURCE_UNLINKED;
356
357     reset_callbacks(s);
358
359     if (linked) {
360         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
361         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s);
362     }
363 }
364
365 /* Called from main context */
366 static void source_free(pa_object *o) {
367     pa_source_output *so;
368     pa_source *s = PA_SOURCE(o);
369
370     pa_assert(s);
371     pa_assert(pa_source_refcnt(s) == 0);
372
373     if (PA_SOURCE_IS_LINKED(s->state))
374         pa_source_unlink(s);
375
376     pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
377
378     pa_idxset_free(s->outputs, NULL, NULL);
379
380     while ((so = pa_hashmap_steal_first(s->thread_info.outputs)))
381         pa_source_output_unref(so);
382
383     pa_hashmap_free(s->thread_info.outputs, NULL, NULL);
384
385     if (s->silence.memblock)
386         pa_memblock_unref(s->silence.memblock);
387
388     pa_xfree(s->name);
389     pa_xfree(s->driver);
390
391     if (s->proplist)
392         pa_proplist_free(s->proplist);
393
394     pa_xfree(s);
395 }
396
397 /* Called from main context */
398 void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) {
399     pa_source_assert_ref(s);
400
401     s->asyncmsgq = q;
402 }
403
404 /* Called from main context */
405 void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) {
406     pa_source_assert_ref(s);
407
408     s->rtpoll = p;
409 }
410
411 /* Called from main context */
412 int pa_source_update_status(pa_source*s) {
413     pa_source_assert_ref(s);
414     pa_assert(PA_SOURCE_IS_LINKED(s->state));
415
416     if (s->state == PA_SOURCE_SUSPENDED)
417         return 0;
418
419     return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
420 }
421
422 /* Called from main context */
423 int pa_source_suspend(pa_source *s, pa_bool_t suspend) {
424     pa_source_assert_ref(s);
425     pa_assert(PA_SOURCE_IS_LINKED(s->state));
426
427     if (s->monitor_of)
428         return -PA_ERR_NOTSUPPORTED;
429
430     if (suspend)
431         return source_set_state(s, PA_SOURCE_SUSPENDED);
432     else
433         return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
434 }
435
436 /* Called from main context */
437 pa_queue *pa_source_move_all_start(pa_source *s) {
438     pa_queue *q;
439     pa_source_output *o, *n;
440     uint32_t idx;
441
442     pa_source_assert_ref(s);
443     pa_assert(PA_SOURCE_IS_LINKED(s->state));
444
445     q = pa_queue_new();
446
447     for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = n) {
448         n = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx));
449
450         if (pa_source_output_start_move(o) >= 0)
451             pa_queue_push(q, pa_source_output_ref(o));
452     }
453
454     return q;
455 }
456
457 /* Called from main context */
458 void pa_source_move_all_finish(pa_source *s, pa_queue *q, pa_bool_t save) {
459     pa_source_output *o;
460
461     pa_source_assert_ref(s);
462     pa_assert(PA_SOURCE_IS_LINKED(s->state));
463     pa_assert(q);
464
465     while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
466         if (pa_source_output_finish_move(o, s, save) < 0)
467             pa_source_output_kill(o);
468
469         pa_source_output_unref(o);
470     }
471
472     pa_queue_free(q, NULL, NULL);
473 }
474
475 /* Called from main context */
476 void pa_source_move_all_fail(pa_queue *q) {
477     pa_source_output *o;
478     pa_assert(q);
479
480     while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
481         if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], o) == PA_HOOK_OK) {
482             pa_source_output_kill(o);
483             pa_source_output_unref(o);
484         }
485     }
486
487     pa_queue_free(q, NULL, NULL);
488 }
489
490 /* Called from IO thread context */
491 void pa_source_process_rewind(pa_source *s, size_t nbytes) {
492     pa_source_output *o;
493     void *state = NULL;
494
495     pa_source_assert_ref(s);
496     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
497
498     if (s->thread_info.state == PA_SOURCE_SUSPENDED)
499         return;
500
501     if (nbytes <= 0)
502         return;
503
504     pa_log_debug("Processing rewind...");
505
506     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
507         pa_source_output_assert_ref(o);
508         pa_source_output_process_rewind(o, nbytes);
509     }
510 }
511
512 /* Called from IO thread context */
513 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
514     pa_source_output *o;
515     void *state = NULL;
516
517     pa_source_assert_ref(s);
518     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
519     pa_assert(chunk);
520
521     if (s->thread_info.state == PA_SOURCE_SUSPENDED)
522         return;
523
524     if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
525         pa_memchunk vchunk = *chunk;
526
527         pa_memblock_ref(vchunk.memblock);
528         pa_memchunk_make_writable(&vchunk, 0);
529
530         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
531             pa_silence_memchunk(&vchunk, &s->sample_spec);
532         else
533             pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
534
535         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
536             pa_source_output_assert_ref(o);
537
538             if (!o->thread_info.direct_on_input)
539                 pa_source_output_push(o, &vchunk);
540         }
541
542         pa_memblock_unref(vchunk.memblock);
543     } else {
544
545         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
546             pa_source_output_assert_ref(o);
547
548             if (!o->thread_info.direct_on_input)
549                 pa_source_output_push(o, chunk);
550         }
551     }
552 }
553
554 /* Called from IO thread context */
555 void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk *chunk) {
556     pa_source_assert_ref(s);
557     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
558     pa_source_output_assert_ref(o);
559     pa_assert(o->thread_info.direct_on_input);
560     pa_assert(chunk);
561
562     if (s->thread_info.state == PA_SOURCE_SUSPENDED)
563         return;
564
565     if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
566         pa_memchunk vchunk = *chunk;
567
568         pa_memblock_ref(vchunk.memblock);
569         pa_memchunk_make_writable(&vchunk, 0);
570
571         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
572             pa_silence_memchunk(&vchunk, &s->sample_spec);
573         else
574             pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
575
576         pa_source_output_push(o, &vchunk);
577
578         pa_memblock_unref(vchunk.memblock);
579     } else
580         pa_source_output_push(o, chunk);
581 }
582
583 /* Called from main thread */
584 pa_usec_t pa_source_get_latency(pa_source *s) {
585     pa_usec_t usec;
586
587     pa_source_assert_ref(s);
588     pa_assert(PA_SOURCE_IS_LINKED(s->state));
589
590     if (s->state == PA_SOURCE_SUSPENDED)
591         return 0;
592
593     if (!(s->flags & PA_SOURCE_LATENCY))
594         return 0;
595
596     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
597
598     return usec;
599 }
600
601 /* Called from main thread */
602 void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
603     pa_cvolume old_virtual_volume;
604     pa_bool_t virtual_volume_changed;
605
606     pa_source_assert_ref(s);
607     pa_assert(PA_SOURCE_IS_LINKED(s->state));
608     pa_assert(volume);
609     pa_assert(pa_cvolume_valid(volume));
610     pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
611
612     old_virtual_volume = s->virtual_volume;
613     s->virtual_volume = *volume;
614     virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume);
615
616     if (s->set_volume) {
617         pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
618         s->set_volume(s);
619     } else
620         s->soft_volume = s->virtual_volume;
621
622     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
623
624     if (virtual_volume_changed)
625         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
626 }
627
628 /* Called from main thread. Only to be called by source implementor */
629 void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume) {
630     pa_source_assert_ref(s);
631     pa_assert(volume);
632
633     if (PA_SOURCE_IS_LINKED(s->state))
634         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
635     else
636         s->thread_info.soft_volume = *volume;
637 }
638
639 /* Called from main thread */
640 const pa_cvolume *pa_source_get_volume(pa_source *s, pa_bool_t force_refresh) {
641     pa_source_assert_ref(s);
642     pa_assert(PA_SOURCE_IS_LINKED(s->state));
643
644     if (s->refresh_volume || force_refresh) {
645         pa_cvolume old_virtual_volume = s->virtual_volume;
646
647         if (s->get_volume)
648             s->get_volume(s);
649
650         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
651
652         if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume))
653             pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
654     }
655
656     return &s->virtual_volume;
657 }
658
659 /* Called from main thread */
660 void pa_source_set_mute(pa_source *s, pa_bool_t mute) {
661     pa_bool_t old_muted;
662
663     pa_source_assert_ref(s);
664     pa_assert(PA_SOURCE_IS_LINKED(s->state));
665
666     old_muted = s->muted;
667     s->muted = mute;
668
669     if (s->set_mute)
670         s->set_mute(s);
671
672     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
673
674     if (old_muted != s->muted)
675         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
676 }
677
678 /* Called from main thread */
679 pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
680
681     pa_source_assert_ref(s);
682     pa_assert(PA_SOURCE_IS_LINKED(s->state));
683
684     if (s->refresh_muted || force_refresh) {
685         pa_bool_t old_muted = s->muted;
686
687         if (s->get_mute)
688             s->get_mute(s);
689
690         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
691
692         if (old_muted != s->muted)
693             pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
694     }
695
696     return s->muted;
697 }
698
699 /* Called from main thread */
700 pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p) {
701     pa_source_assert_ref(s);
702     pa_assert(p);
703
704     pa_proplist_update(s->proplist, mode, p);
705
706     if (PA_SOURCE_IS_LINKED(s->state)) {
707         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
708         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
709     }
710
711     return TRUE;
712 }
713
714 /* Called from main thread */
715 void pa_source_set_description(pa_source *s, const char *description) {
716     const char *old;
717     pa_source_assert_ref(s);
718
719     if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
720         return;
721
722     old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
723
724     if (old && description && !strcmp(old, description))
725         return;
726
727     if (description)
728         pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
729     else
730         pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
731
732     if (PA_SOURCE_IS_LINKED(s->state)) {
733         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
734         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
735     }
736 }
737
738 /* Called from main thread */
739 unsigned pa_source_linked_by(pa_source *s) {
740     pa_source_assert_ref(s);
741     pa_assert(PA_SOURCE_IS_LINKED(s->state));
742
743     return pa_idxset_size(s->outputs);
744 }
745
746 /* Called from main thread */
747 unsigned pa_source_used_by(pa_source *s) {
748     unsigned ret;
749
750     pa_source_assert_ref(s);
751     pa_assert(PA_SOURCE_IS_LINKED(s->state));
752
753     ret = pa_idxset_size(s->outputs);
754     pa_assert(ret >= s->n_corked);
755
756     return ret - s->n_corked;
757 }
758
759 /* Called from main thread */
760 unsigned pa_source_check_suspend(pa_source *s) {
761     unsigned ret;
762     pa_source_output *o;
763     uint32_t idx;
764
765     pa_source_assert_ref(s);
766
767     if (!PA_SOURCE_IS_LINKED(s->state))
768         return 0;
769
770     ret = 0;
771
772     for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx))) {
773         pa_source_output_state_t st;
774
775         st = pa_source_output_get_state(o);
776         pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(st));
777
778         if (st == PA_SOURCE_OUTPUT_CORKED)
779             continue;
780
781         if (o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND)
782             continue;
783
784         ret ++;
785     }
786
787     return ret;
788 }
789
790 /* Called from IO thread, except when it is not */
791 int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
792     pa_source *s = PA_SOURCE(object);
793     pa_source_assert_ref(s);
794
795     switch ((pa_source_message_t) code) {
796
797         case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
798             pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
799
800             pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
801
802             if (o->direct_on_input) {
803                 o->thread_info.direct_on_input = o->direct_on_input;
804                 pa_hashmap_put(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index), o);
805             }
806
807             pa_assert(!o->thread_info.attached);
808             o->thread_info.attached = TRUE;
809
810             if (o->attach)
811                 o->attach(o);
812
813             pa_source_output_set_state_within_thread(o, o->state);
814
815             if (o->thread_info.requested_source_latency != (pa_usec_t) -1)
816                 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
817
818             pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
819
820             /* We don't just invalidate the requested latency here,
821              * because if we are in a move we might need to fix up the
822              * requested latency. */
823             pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
824
825             return 0;
826         }
827
828         case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
829             pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
830
831             pa_source_output_set_state_within_thread(o, o->state);
832
833             if (o->detach)
834                 o->detach(o);
835
836             pa_assert(o->thread_info.attached);
837             o->thread_info.attached = FALSE;
838
839             if (o->thread_info.direct_on_input) {
840                 pa_hashmap_remove(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index));
841                 o->thread_info.direct_on_input = NULL;
842             }
843
844             if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
845                 pa_source_output_unref(o);
846
847             pa_source_invalidate_requested_latency(s);
848
849             return 0;
850         }
851
852         case PA_SOURCE_MESSAGE_SET_VOLUME:
853             s->thread_info.soft_volume = s->soft_volume;
854             return 0;
855
856         case PA_SOURCE_MESSAGE_GET_VOLUME:
857             return 0;
858
859         case PA_SOURCE_MESSAGE_SET_MUTE:
860             s->thread_info.soft_muted = s->muted;
861             return 0;
862
863         case PA_SOURCE_MESSAGE_GET_MUTE:
864             return 0;
865
866         case PA_SOURCE_MESSAGE_SET_STATE:
867             s->thread_info.state = PA_PTR_TO_UINT(userdata);
868             return 0;
869
870         case PA_SOURCE_MESSAGE_DETACH:
871
872             /* Detach all streams */
873             pa_source_detach_within_thread(s);
874             return 0;
875
876         case PA_SOURCE_MESSAGE_ATTACH:
877
878             /* Reattach all streams */
879             pa_source_attach_within_thread(s);
880             return 0;
881
882         case PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY: {
883
884             pa_usec_t *usec = userdata;
885             *usec = pa_source_get_requested_latency_within_thread(s);
886
887             if (*usec == (pa_usec_t) -1)
888                 *usec = s->thread_info.max_latency;
889
890             return 0;
891         }
892
893         case PA_SOURCE_MESSAGE_SET_LATENCY_RANGE: {
894             pa_usec_t *r = userdata;
895
896             pa_source_update_latency_range(s, r[0], r[1]);
897
898             return 0;
899         }
900
901         case PA_SOURCE_MESSAGE_GET_LATENCY_RANGE: {
902             pa_usec_t *r = userdata;
903
904             r[0] = s->thread_info.min_latency;
905             r[1] = s->thread_info.max_latency;
906
907             return 0;
908         }
909
910         case PA_SOURCE_MESSAGE_GET_MAX_REWIND:
911
912             *((size_t*) userdata) = s->thread_info.max_rewind;
913             return 0;
914
915         case PA_SOURCE_MESSAGE_GET_LATENCY:
916
917             if (s->monitor_of) {
918                 *((pa_usec_t*) userdata) = 0;
919                 return 0;
920             }
921
922             /* Implementors need to overwrite this implementation! */
923             return -1;
924
925         case PA_SOURCE_MESSAGE_MAX:
926             ;
927     }
928
929     return -1;
930 }
931
932 /* Called from main thread */
933 int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) {
934     uint32_t idx;
935     pa_source *source;
936     int ret = 0;
937
938     pa_core_assert_ref(c);
939
940     for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx)))
941         ret -= pa_source_suspend(source, suspend) < 0;
942
943     return ret;
944 }
945
946 /* Called from main thread */
947 void pa_source_detach(pa_source *s) {
948     pa_source_assert_ref(s);
949     pa_assert(PA_SOURCE_IS_LINKED(s->state));
950
951     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL) == 0);
952 }
953
954 /* Called from main thread */
955 void pa_source_attach(pa_source *s) {
956     pa_source_assert_ref(s);
957     pa_assert(PA_SOURCE_IS_LINKED(s->state));
958
959     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
960 }
961
962 /* Called from IO thread */
963 void pa_source_detach_within_thread(pa_source *s) {
964     pa_source_output *o;
965     void *state = NULL;
966
967     pa_source_assert_ref(s);
968     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
969
970     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
971         if (o->detach)
972             o->detach(o);
973 }
974
975 /* Called from IO thread */
976 void pa_source_attach_within_thread(pa_source *s) {
977     pa_source_output *o;
978     void *state = NULL;
979
980     pa_source_assert_ref(s);
981     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
982
983     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
984         if (o->attach)
985             o->attach(o);
986 }
987
988 /* Called from IO thread */
989 pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
990     pa_usec_t result = (pa_usec_t) -1;
991     pa_source_output *o;
992     void *state = NULL;
993
994     pa_source_assert_ref(s);
995
996     if (s->thread_info.requested_latency_valid)
997         return s->thread_info.requested_latency;
998
999     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1000
1001         if (o->thread_info.requested_source_latency != (pa_usec_t) -1 &&
1002             (result == (pa_usec_t) -1 || result > o->thread_info.requested_source_latency))
1003             result = o->thread_info.requested_source_latency;
1004
1005     if (result != (pa_usec_t) -1) {
1006         if (s->thread_info.max_latency > 0 && result > s->thread_info.max_latency)
1007             result = s->thread_info.max_latency;
1008
1009         if (s->thread_info.min_latency > 0 && result < s->thread_info.min_latency)
1010             result = s->thread_info.min_latency;
1011     }
1012
1013     s->thread_info.requested_latency = result;
1014     s->thread_info.requested_latency_valid = TRUE;
1015
1016     return result;
1017 }
1018
1019 /* Called from main thread */
1020 pa_usec_t pa_source_get_requested_latency(pa_source *s) {
1021     pa_usec_t usec;
1022
1023     pa_source_assert_ref(s);
1024     pa_assert(PA_SOURCE_IS_LINKED(s->state));
1025
1026     if (s->state == PA_SOURCE_SUSPENDED)
1027         return 0;
1028
1029     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1030
1031     return usec;
1032 }
1033
1034 /* Called from IO thread */
1035 void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
1036     pa_source_output *o;
1037     void *state = NULL;
1038
1039     pa_source_assert_ref(s);
1040
1041     if (max_rewind == s->thread_info.max_rewind)
1042         return;
1043
1044     s->thread_info.max_rewind = max_rewind;
1045
1046     if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1047         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1048             pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
1049     }
1050 }
1051
1052 void pa_source_invalidate_requested_latency(pa_source *s) {
1053     pa_source_output *o;
1054     void *state = NULL;
1055
1056     pa_source_assert_ref(s);
1057
1058     s->thread_info.requested_latency_valid = FALSE;
1059
1060     if (s->update_requested_latency)
1061         s->update_requested_latency(s);
1062
1063     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1064         if (o->update_source_requested_latency)
1065             o->update_source_requested_latency(o);
1066
1067     if (s->monitor_of)
1068         pa_sink_invalidate_requested_latency(s->monitor_of);
1069 }
1070
1071 void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1072     pa_source_assert_ref(s);
1073
1074     /* min_latency == 0:           no limit
1075      * min_latency == (size_t) -1: default limit
1076      * min_latency anything else:  specified limit
1077      *
1078      * Similar for max_latency */
1079
1080     if (min_latency == (pa_usec_t) -1)
1081         min_latency = DEFAULT_MIN_LATENCY;
1082
1083     if (max_latency == (pa_usec_t) -1)
1084         max_latency = min_latency;
1085
1086     pa_assert(!min_latency || !max_latency ||
1087               min_latency <= max_latency);
1088
1089     if (PA_SOURCE_IS_LINKED(s->state)) {
1090         pa_usec_t r[2];
1091
1092         r[0] = min_latency;
1093         r[1] = max_latency;
1094
1095         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
1096     } else {
1097         s->thread_info.min_latency = min_latency;
1098         s->thread_info.max_latency = max_latency;
1099
1100         s->thread_info.requested_latency_valid = FALSE;
1101     }
1102 }
1103
1104 void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
1105    pa_source_assert_ref(s);
1106    pa_assert(min_latency);
1107    pa_assert(max_latency);
1108
1109    if (PA_SOURCE_IS_LINKED(s->state)) {
1110        pa_usec_t r[2] = { 0, 0 };
1111
1112        pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
1113
1114        *min_latency = r[0];
1115        *max_latency = r[1];
1116    } else {
1117        *min_latency = s->thread_info.min_latency;
1118        *max_latency = s->thread_info.max_latency;
1119    }
1120 }
1121
1122 /* Called from IO thread */
1123 void pa_source_update_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1124     pa_source_output *o;
1125     void *state = NULL;
1126
1127     pa_source_assert_ref(s);
1128
1129     pa_assert(!min_latency || !max_latency ||
1130               min_latency <= max_latency);
1131
1132     s->thread_info.min_latency = min_latency;
1133     s->thread_info.max_latency = max_latency;
1134
1135     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1136         if (o->update_source_latency_range)
1137             o->update_source_latency_range(o);
1138
1139     pa_source_invalidate_requested_latency(s);
1140 }
1141
1142 size_t pa_source_get_max_rewind(pa_source *s) {
1143     size_t r;
1144     pa_source_assert_ref(s);
1145
1146     if (!PA_SOURCE_IS_LINKED(s->state))
1147         return s->thread_info.max_rewind;
1148
1149     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
1150
1151     return r;
1152 }