2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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
31 #include <pulse/utf8.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
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>
44 #define ABSOLUTE_MIN_LATENCY (500)
45 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
46 #define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
48 static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
50 static void source_free(pa_object *o);
52 pa_source_new_data* pa_source_new_data_init(pa_source_new_data *data) {
55 memset(data, 0, sizeof(*data));
56 data->proplist = pa_proplist_new();
61 void pa_source_new_data_set_name(pa_source_new_data *data, const char *name) {
65 data->name = pa_xstrdup(name);
68 void pa_source_new_data_set_sample_spec(pa_source_new_data *data, const pa_sample_spec *spec) {
71 if ((data->sample_spec_is_set = !!spec))
72 data->sample_spec = *spec;
75 void pa_source_new_data_set_channel_map(pa_source_new_data *data, const pa_channel_map *map) {
78 if ((data->channel_map_is_set = !!map))
79 data->channel_map = *map;
82 void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume) {
85 if ((data->volume_is_set = !!volume))
86 data->volume = *volume;
89 void pa_source_new_data_set_muted(pa_source_new_data *data, pa_bool_t mute) {
92 data->muted_is_set = TRUE;
96 void pa_source_new_data_done(pa_source_new_data *data) {
100 pa_proplist_free(data->proplist);
103 /* Called from main context */
104 static void reset_callbacks(pa_source *s) {
108 s->get_volume = NULL;
109 s->set_volume = NULL;
112 s->update_requested_latency = NULL;
115 /* Called from main context */
116 pa_source* pa_source_new(
118 pa_source_new_data *data,
119 pa_source_flags_t flags) {
123 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
128 pa_assert(data->name);
130 s = pa_msgobject_new(pa_source);
132 if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) {
137 pa_source_new_data_set_name(data, name);
139 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0) {
141 pa_namereg_unregister(core, name);
145 pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
146 pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
148 pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
150 if (!data->channel_map_is_set)
151 pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
153 pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
154 pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
156 if (!data->volume_is_set)
157 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
159 pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
160 pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
162 if (!data->muted_is_set)
166 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
168 pa_device_init_description(data->proplist);
169 pa_device_init_icon(data->proplist, FALSE);
171 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) {
173 pa_namereg_unregister(core, name);
177 s->parent.parent.free = source_free;
178 s->parent.process_msg = pa_source_process_msg;
181 s->state = PA_SOURCE_INIT;
183 s->suspend_cause = 0;
184 s->name = pa_xstrdup(name);
185 s->proplist = pa_proplist_copy(data->proplist);
186 s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
187 s->module = data->module;
188 s->card = data->card;
190 s->sample_spec = data->sample_spec;
191 s->channel_map = data->channel_map;
193 s->outputs = pa_idxset_new(NULL, NULL);
195 s->monitor_of = NULL;
197 s->virtual_volume = data->volume;
198 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
199 s->base_volume = PA_VOLUME_NORM;
200 s->n_volume_steps = PA_VOLUME_NORM+1;
201 s->muted = data->muted;
202 s->refresh_volume = s->refresh_muted = FALSE;
204 s->fixed_latency = flags & PA_SOURCE_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
212 pa_silence_memchunk_get(
213 &core->silence_cache,
219 s->thread_info.outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
220 s->thread_info.soft_volume = s->soft_volume;
221 s->thread_info.soft_muted = s->muted;
222 s->thread_info.state = s->state;
223 s->thread_info.max_rewind = 0;
224 s->thread_info.requested_latency_valid = FALSE;
225 s->thread_info.requested_latency = 0;
226 s->thread_info.min_latency = ABSOLUTE_MIN_LATENCY;
227 s->thread_info.max_latency = ABSOLUTE_MAX_LATENCY;
229 pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
232 pa_assert_se(pa_idxset_put(s->card->sources, s, NULL) >= 0);
234 pt = pa_proplist_to_string_sep(s->proplist, "\n ");
235 pa_log_info("Created source %u \"%s\" with sample spec %s and channel map %s\n %s",
238 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
239 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
246 /* Called from main context */
247 static int source_set_state(pa_source *s, pa_source_state_t state) {
249 pa_bool_t suspend_change;
250 pa_source_state_t original_state;
254 if (s->state == state)
257 original_state = s->state;
260 (original_state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(state)) ||
261 (PA_SOURCE_IS_OPENED(original_state) && state == PA_SOURCE_SUSPENDED);
264 if ((ret = s->set_state(s, state)) < 0)
268 if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
271 s->set_state(s, original_state);
278 if (state != PA_SOURCE_UNLINKED) { /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
279 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
280 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
283 if (suspend_change) {
287 /* We're suspending or resuming, tell everyone about it */
289 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx)))
290 if (s->state == PA_SOURCE_SUSPENDED &&
291 (o->flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND))
292 pa_source_output_kill(o);
294 o->suspend(o, state == PA_SOURCE_SUSPENDED);
301 /* Called from main context */
302 void pa_source_put(pa_source *s) {
303 pa_source_assert_ref(s);
305 pa_assert(s->state == PA_SOURCE_INIT);
307 /* The following fields must be initialized properly when calling _put() */
308 pa_assert(s->asyncmsgq);
309 pa_assert(s->rtpoll);
310 pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
312 /* Generally, flags should be initialized via pa_source_new(). As
313 * a special exception we allow volume related flags to be set
314 * between _new() and _put(). */
316 if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL))
317 s->flags |= PA_SOURCE_DECIBEL_VOLUME;
319 s->thread_info.soft_volume = s->soft_volume;
320 s->thread_info.soft_muted = s->muted;
322 pa_assert((s->flags & PA_SOURCE_HW_VOLUME_CTRL) || (s->base_volume == PA_VOLUME_NORM && s->flags & PA_SOURCE_DECIBEL_VOLUME));
323 pa_assert(!(s->flags & PA_SOURCE_DECIBEL_VOLUME) || s->n_volume_steps == PA_VOLUME_NORM+1);
324 pa_assert(!(s->flags & PA_SOURCE_DYNAMIC_LATENCY) == (s->fixed_latency != 0));
326 pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
328 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
329 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s);
332 /* Called from main context */
333 void pa_source_unlink(pa_source *s) {
335 pa_source_output *o, *j = NULL;
339 /* See pa_sink_unlink() for a couple of comments how this function
342 linked = PA_SOURCE_IS_LINKED(s->state);
345 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
347 if (s->state != PA_SOURCE_UNLINKED)
348 pa_namereg_unregister(s->core, s->name);
349 pa_idxset_remove_by_data(s->core->sources, s, NULL);
352 pa_idxset_remove_by_data(s->card->sources, s, NULL);
354 while ((o = pa_idxset_first(s->outputs, NULL))) {
356 pa_source_output_kill(o);
361 source_set_state(s, PA_SOURCE_UNLINKED);
363 s->state = PA_SOURCE_UNLINKED;
368 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
369 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s);
373 /* Called from main context */
374 static void source_free(pa_object *o) {
375 pa_source_output *so;
376 pa_source *s = PA_SOURCE(o);
379 pa_assert(pa_source_refcnt(s) == 0);
381 if (PA_SOURCE_IS_LINKED(s->state))
384 pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
386 pa_idxset_free(s->outputs, NULL, NULL);
388 while ((so = pa_hashmap_steal_first(s->thread_info.outputs)))
389 pa_source_output_unref(so);
391 pa_hashmap_free(s->thread_info.outputs, NULL, NULL);
393 if (s->silence.memblock)
394 pa_memblock_unref(s->silence.memblock);
400 pa_proplist_free(s->proplist);
405 /* Called from main context */
406 void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) {
407 pa_source_assert_ref(s);
412 /* Called from main context */
413 void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) {
414 pa_source_assert_ref(s);
419 /* Called from main context */
420 int pa_source_update_status(pa_source*s) {
421 pa_source_assert_ref(s);
422 pa_assert(PA_SOURCE_IS_LINKED(s->state));
424 if (s->state == PA_SOURCE_SUSPENDED)
427 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
430 /* Called from main context */
431 int pa_source_suspend(pa_source *s, pa_bool_t suspend, pa_suspend_cause_t cause) {
432 pa_source_assert_ref(s);
433 pa_assert(PA_SOURCE_IS_LINKED(s->state));
434 pa_assert(cause != 0);
437 return -PA_ERR_NOTSUPPORTED;
440 s->suspend_cause |= cause;
442 s->suspend_cause &= ~cause;
444 pa_log_debug("Suspend cause of source %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming");
447 return source_set_state(s, PA_SOURCE_SUSPENDED);
449 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
452 /* Called from main context */
453 int pa_source_sync_suspend(pa_source *s) {
454 pa_sink_state_t state;
456 pa_source_assert_ref(s);
457 pa_assert(PA_SOURCE_IS_LINKED(s->state));
458 pa_assert(s->monitor_of);
460 state = pa_sink_get_state(s->monitor_of);
462 if (state == PA_SINK_SUSPENDED)
463 return source_set_state(s, PA_SOURCE_SUSPENDED);
465 pa_assert(PA_SINK_IS_OPENED(state));
467 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
470 /* Called from main context */
471 pa_queue *pa_source_move_all_start(pa_source *s) {
473 pa_source_output *o, *n;
476 pa_source_assert_ref(s);
477 pa_assert(PA_SOURCE_IS_LINKED(s->state));
481 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = n) {
482 n = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx));
484 pa_source_output_ref(o);
486 if (pa_source_output_start_move(o) >= 0)
489 pa_source_output_unref(o);
495 /* Called from main context */
496 void pa_source_move_all_finish(pa_source *s, pa_queue *q, pa_bool_t save) {
499 pa_source_assert_ref(s);
500 pa_assert(PA_SOURCE_IS_LINKED(s->state));
503 while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
504 if (pa_source_output_finish_move(o, s, save) < 0)
505 pa_source_output_kill(o);
507 pa_source_output_unref(o);
510 pa_queue_free(q, NULL, NULL);
513 /* Called from main context */
514 void pa_source_move_all_fail(pa_queue *q) {
518 while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
519 if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], o) == PA_HOOK_OK) {
520 pa_source_output_kill(o);
521 pa_source_output_unref(o);
525 pa_queue_free(q, NULL, NULL);
528 /* Called from IO thread context */
529 void pa_source_process_rewind(pa_source *s, size_t nbytes) {
533 pa_source_assert_ref(s);
534 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
536 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
542 pa_log_debug("Processing rewind...");
544 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
545 pa_source_output_assert_ref(o);
546 pa_source_output_process_rewind(o, nbytes);
550 /* Called from IO thread context */
551 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
555 pa_source_assert_ref(s);
556 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
559 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
562 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
563 pa_memchunk vchunk = *chunk;
565 pa_memblock_ref(vchunk.memblock);
566 pa_memchunk_make_writable(&vchunk, 0);
568 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
569 pa_silence_memchunk(&vchunk, &s->sample_spec);
571 pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
573 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
574 pa_source_output_assert_ref(o);
576 if (!o->thread_info.direct_on_input)
577 pa_source_output_push(o, &vchunk);
580 pa_memblock_unref(vchunk.memblock);
583 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
584 pa_source_output_assert_ref(o);
586 if (!o->thread_info.direct_on_input)
587 pa_source_output_push(o, chunk);
592 /* Called from IO thread context */
593 void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk *chunk) {
594 pa_source_assert_ref(s);
595 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
596 pa_source_output_assert_ref(o);
597 pa_assert(o->thread_info.direct_on_input);
600 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
603 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
604 pa_memchunk vchunk = *chunk;
606 pa_memblock_ref(vchunk.memblock);
607 pa_memchunk_make_writable(&vchunk, 0);
609 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
610 pa_silence_memchunk(&vchunk, &s->sample_spec);
612 pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
614 pa_source_output_push(o, &vchunk);
616 pa_memblock_unref(vchunk.memblock);
618 pa_source_output_push(o, chunk);
621 /* Called from main thread */
622 pa_usec_t pa_source_get_latency(pa_source *s) {
625 pa_source_assert_ref(s);
626 pa_assert(PA_SOURCE_IS_LINKED(s->state));
628 if (s->state == PA_SOURCE_SUSPENDED)
631 if (!(s->flags & PA_SOURCE_LATENCY))
634 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
639 /* Called from IO thread */
640 pa_usec_t pa_source_get_latency_within_thread(pa_source *s) {
644 pa_source_assert_ref(s);
645 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
647 /* The returned value is supposed to be in the time domain of the sound card! */
649 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
652 if (!(s->flags & PA_SOURCE_LATENCY))
657 /* We probably should make this a proper vtable callback instead of going through process_msg() */
659 if (o->process_msg(o, PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
665 /* Called from main thread */
666 void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
667 pa_cvolume old_virtual_volume;
668 pa_bool_t virtual_volume_changed;
670 pa_source_assert_ref(s);
671 pa_assert(PA_SOURCE_IS_LINKED(s->state));
673 pa_assert(pa_cvolume_valid(volume));
674 pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
676 old_virtual_volume = s->virtual_volume;
677 s->virtual_volume = *volume;
678 virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume);
681 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
684 s->soft_volume = s->virtual_volume;
686 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
688 if (virtual_volume_changed)
689 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
692 /* Called from main thread. Only to be called by source implementor */
693 void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume) {
694 pa_source_assert_ref(s);
697 if (PA_SOURCE_IS_LINKED(s->state))
698 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
700 s->thread_info.soft_volume = *volume;
703 /* Called from main thread */
704 const pa_cvolume *pa_source_get_volume(pa_source *s, pa_bool_t force_refresh) {
705 pa_source_assert_ref(s);
706 pa_assert(PA_SOURCE_IS_LINKED(s->state));
708 if (s->refresh_volume || force_refresh) {
709 pa_cvolume old_virtual_volume = s->virtual_volume;
714 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
716 if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume))
717 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
720 return &s->virtual_volume;
723 /* Called from main thread */
724 void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume) {
725 pa_source_assert_ref(s);
727 /* The source implementor may call this if the volume changed to make sure everyone is notified */
729 if (pa_cvolume_equal(&s->virtual_volume, new_volume))
732 s->virtual_volume = *new_volume;
733 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
736 /* Called from main thread */
737 void pa_source_set_mute(pa_source *s, pa_bool_t mute) {
740 pa_source_assert_ref(s);
741 pa_assert(PA_SOURCE_IS_LINKED(s->state));
743 old_muted = s->muted;
749 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
751 if (old_muted != s->muted)
752 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
755 /* Called from main thread */
756 pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
757 pa_source_assert_ref(s);
758 pa_assert(PA_SOURCE_IS_LINKED(s->state));
760 if (s->refresh_muted || force_refresh) {
761 pa_bool_t old_muted = s->muted;
766 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
768 if (old_muted != s->muted)
769 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
775 /* Called from main thread */
776 void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted) {
777 pa_source_assert_ref(s);
779 /* The source implementor may call this if the mute state changed to make sure everyone is notified */
781 if (s->muted == new_muted)
784 s->muted = new_muted;
785 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
788 /* Called from main thread */
789 pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p) {
790 pa_source_assert_ref(s);
793 pa_proplist_update(s->proplist, mode, p);
795 if (PA_SOURCE_IS_LINKED(s->state)) {
796 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
797 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
803 /* Called from main thread */
804 void pa_source_set_description(pa_source *s, const char *description) {
806 pa_source_assert_ref(s);
808 if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
811 old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
813 if (old && description && !strcmp(old, description))
817 pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
819 pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
821 if (PA_SOURCE_IS_LINKED(s->state)) {
822 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
823 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
827 /* Called from main thread */
828 unsigned pa_source_linked_by(pa_source *s) {
829 pa_source_assert_ref(s);
830 pa_assert(PA_SOURCE_IS_LINKED(s->state));
832 return pa_idxset_size(s->outputs);
835 /* Called from main thread */
836 unsigned pa_source_used_by(pa_source *s) {
839 pa_source_assert_ref(s);
840 pa_assert(PA_SOURCE_IS_LINKED(s->state));
842 ret = pa_idxset_size(s->outputs);
843 pa_assert(ret >= s->n_corked);
845 return ret - s->n_corked;
848 /* Called from main thread */
849 unsigned pa_source_check_suspend(pa_source *s) {
854 pa_source_assert_ref(s);
856 if (!PA_SOURCE_IS_LINKED(s->state))
861 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx))) {
862 pa_source_output_state_t st;
864 st = pa_source_output_get_state(o);
865 pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(st));
867 if (st == PA_SOURCE_OUTPUT_CORKED)
870 if (o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND)
879 /* Called from IO thread, except when it is not */
880 int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
881 pa_source *s = PA_SOURCE(object);
882 pa_source_assert_ref(s);
884 switch ((pa_source_message_t) code) {
886 case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
887 pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
889 pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
891 if (o->direct_on_input) {
892 o->thread_info.direct_on_input = o->direct_on_input;
893 pa_hashmap_put(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index), o);
896 pa_assert(!o->thread_info.attached);
897 o->thread_info.attached = TRUE;
902 pa_source_output_set_state_within_thread(o, o->state);
904 if (o->thread_info.requested_source_latency != (pa_usec_t) -1)
905 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
907 pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
909 /* We don't just invalidate the requested latency here,
910 * because if we are in a move we might need to fix up the
911 * requested latency. */
912 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
917 case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
918 pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
920 pa_source_output_set_state_within_thread(o, o->state);
925 pa_assert(o->thread_info.attached);
926 o->thread_info.attached = FALSE;
928 if (o->thread_info.direct_on_input) {
929 pa_hashmap_remove(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index));
930 o->thread_info.direct_on_input = NULL;
933 if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
934 pa_source_output_unref(o);
936 pa_source_invalidate_requested_latency(s);
941 case PA_SOURCE_MESSAGE_SET_VOLUME:
942 s->thread_info.soft_volume = s->soft_volume;
945 case PA_SOURCE_MESSAGE_GET_VOLUME:
948 case PA_SOURCE_MESSAGE_SET_MUTE:
949 s->thread_info.soft_muted = s->muted;
952 case PA_SOURCE_MESSAGE_GET_MUTE:
955 case PA_SOURCE_MESSAGE_SET_STATE: {
957 pa_bool_t suspend_change =
958 (s->thread_info.state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(PA_PTR_TO_UINT(userdata))) ||
959 (PA_SOURCE_IS_OPENED(s->thread_info.state) && PA_PTR_TO_UINT(userdata) == PA_SOURCE_SUSPENDED);
961 s->thread_info.state = PA_PTR_TO_UINT(userdata);
963 if (suspend_change) {
967 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
968 if (o->suspend_within_thread)
969 o->suspend_within_thread(o, s->thread_info.state == PA_SOURCE_SUSPENDED);
976 case PA_SOURCE_MESSAGE_DETACH:
978 /* Detach all streams */
979 pa_source_detach_within_thread(s);
982 case PA_SOURCE_MESSAGE_ATTACH:
984 /* Reattach all streams */
985 pa_source_attach_within_thread(s);
988 case PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY: {
990 pa_usec_t *usec = userdata;
991 *usec = pa_source_get_requested_latency_within_thread(s);
993 if (*usec == (pa_usec_t) -1)
994 *usec = s->thread_info.max_latency;
999 case PA_SOURCE_MESSAGE_SET_LATENCY_RANGE: {
1000 pa_usec_t *r = userdata;
1002 pa_source_set_latency_range_within_thread(s, r[0], r[1]);
1007 case PA_SOURCE_MESSAGE_GET_LATENCY_RANGE: {
1008 pa_usec_t *r = userdata;
1010 r[0] = s->thread_info.min_latency;
1011 r[1] = s->thread_info.max_latency;
1016 case PA_SOURCE_MESSAGE_GET_MAX_REWIND:
1018 *((size_t*) userdata) = s->thread_info.max_rewind;
1021 case PA_SOURCE_MESSAGE_SET_MAX_REWIND:
1023 pa_source_set_max_rewind_within_thread(s, (size_t) offset);
1026 case PA_SOURCE_MESSAGE_GET_LATENCY:
1028 if (s->monitor_of) {
1029 *((pa_usec_t*) userdata) = 0;
1033 /* Implementors need to overwrite this implementation! */
1036 case PA_SOURCE_MESSAGE_MAX:
1043 /* Called from main thread */
1044 int pa_source_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause) {
1049 pa_core_assert_ref(c);
1050 pa_assert(cause != 0);
1052 for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx))) {
1055 if (source->monitor_of)
1058 if ((r = pa_source_suspend(source, suspend, cause)) < 0)
1065 /* Called from main thread */
1066 void pa_source_detach(pa_source *s) {
1067 pa_source_assert_ref(s);
1068 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1070 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL) == 0);
1073 /* Called from main thread */
1074 void pa_source_attach(pa_source *s) {
1075 pa_source_assert_ref(s);
1076 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1078 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
1081 /* Called from IO thread */
1082 void pa_source_detach_within_thread(pa_source *s) {
1083 pa_source_output *o;
1086 pa_source_assert_ref(s);
1087 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1089 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1094 /* Called from IO thread */
1095 void pa_source_attach_within_thread(pa_source *s) {
1096 pa_source_output *o;
1099 pa_source_assert_ref(s);
1100 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1102 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1107 /* Called from IO thread */
1108 pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
1109 pa_usec_t result = (pa_usec_t) -1;
1110 pa_source_output *o;
1113 pa_source_assert_ref(s);
1115 if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
1116 return PA_CLAMP(s->fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
1118 if (s->thread_info.requested_latency_valid)
1119 return s->thread_info.requested_latency;
1121 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1123 if (o->thread_info.requested_source_latency != (pa_usec_t) -1 &&
1124 (result == (pa_usec_t) -1 || result > o->thread_info.requested_source_latency))
1125 result = o->thread_info.requested_source_latency;
1127 if (result != (pa_usec_t) -1)
1128 result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
1130 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1131 /* Only cache this if we are fully set up */
1132 s->thread_info.requested_latency = result;
1133 s->thread_info.requested_latency_valid = TRUE;
1139 /* Called from main thread */
1140 pa_usec_t pa_source_get_requested_latency(pa_source *s) {
1143 pa_source_assert_ref(s);
1144 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1146 if (s->state == PA_SOURCE_SUSPENDED)
1149 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1154 /* Called from IO thread */
1155 void pa_source_set_max_rewind_within_thread(pa_source *s, size_t max_rewind) {
1156 pa_source_output *o;
1159 pa_source_assert_ref(s);
1161 if (max_rewind == s->thread_info.max_rewind)
1164 s->thread_info.max_rewind = max_rewind;
1166 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1167 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1168 pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
1172 /* Called from main thread */
1173 void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
1174 pa_source_assert_ref(s);
1176 if (PA_SOURCE_IS_LINKED(s->state))
1177 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
1179 pa_source_set_max_rewind_within_thread(s, max_rewind);
1182 /* Called from IO thread */
1183 void pa_source_invalidate_requested_latency(pa_source *s) {
1184 pa_source_output *o;
1187 pa_source_assert_ref(s);
1189 if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
1192 s->thread_info.requested_latency_valid = FALSE;
1194 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1196 if (s->update_requested_latency)
1197 s->update_requested_latency(s);
1199 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1200 if (o->update_source_requested_latency)
1201 o->update_source_requested_latency(o);
1205 pa_sink_invalidate_requested_latency(s->monitor_of);
1208 /* Called from main thread */
1209 void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1210 pa_source_assert_ref(s);
1212 /* min_latency == 0: no limit
1213 * min_latency anything else: specified limit
1215 * Similar for max_latency */
1217 if (min_latency < ABSOLUTE_MIN_LATENCY)
1218 min_latency = ABSOLUTE_MIN_LATENCY;
1220 if (max_latency <= 0 ||
1221 max_latency > ABSOLUTE_MAX_LATENCY)
1222 max_latency = ABSOLUTE_MAX_LATENCY;
1224 pa_assert(min_latency <= max_latency);
1226 /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1227 pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
1228 max_latency == ABSOLUTE_MAX_LATENCY) ||
1229 (s->flags & PA_SOURCE_DYNAMIC_LATENCY));
1231 if (PA_SOURCE_IS_LINKED(s->state)) {
1237 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
1239 pa_source_set_latency_range_within_thread(s, min_latency, max_latency);
1242 /* Called from main thread */
1243 void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
1244 pa_source_assert_ref(s);
1245 pa_assert(min_latency);
1246 pa_assert(max_latency);
1248 if (PA_SOURCE_IS_LINKED(s->state)) {
1249 pa_usec_t r[2] = { 0, 0 };
1251 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
1253 *min_latency = r[0];
1254 *max_latency = r[1];
1256 *min_latency = s->thread_info.min_latency;
1257 *max_latency = s->thread_info.max_latency;
1261 /* Called from IO thread, and from main thread before pa_source_put() is called */
1262 void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1265 pa_source_assert_ref(s);
1267 pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
1268 pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
1269 pa_assert(min_latency <= max_latency);
1271 /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1272 pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
1273 max_latency == ABSOLUTE_MAX_LATENCY) ||
1274 (s->flags & PA_SOURCE_DYNAMIC_LATENCY) ||
1277 s->thread_info.min_latency = min_latency;
1278 s->thread_info.max_latency = max_latency;
1280 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1281 pa_source_output *o;
1283 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1284 if (o->update_source_latency_range)
1285 o->update_source_latency_range(o);
1288 pa_source_invalidate_requested_latency(s);
1291 /* Called from main thread, before the source is put */
1292 void pa_source_set_fixed_latency(pa_source *s, pa_usec_t latency) {
1293 pa_source_assert_ref(s);
1295 pa_assert(pa_source_get_state(s) == PA_SOURCE_INIT);
1297 if (latency < ABSOLUTE_MIN_LATENCY)
1298 latency = ABSOLUTE_MIN_LATENCY;
1300 if (latency > ABSOLUTE_MAX_LATENCY)
1301 latency = ABSOLUTE_MAX_LATENCY;
1303 s->fixed_latency = latency;
1306 /* Called from main thread */
1307 size_t pa_source_get_max_rewind(pa_source *s) {
1309 pa_source_assert_ref(s);
1311 if (!PA_SOURCE_IS_LINKED(s->state))
1312 return s->thread_info.max_rewind;
1314 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);