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 if ((pa_source_get_state(s) == PA_SOURCE_SUSPENDED) == !!s->suspend_cause)
447 pa_log_debug("Suspend cause of source %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming");
450 return source_set_state(s, PA_SOURCE_SUSPENDED);
452 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
455 /* Called from main context */
456 int pa_source_sync_suspend(pa_source *s) {
457 pa_sink_state_t state;
459 pa_source_assert_ref(s);
460 pa_assert(PA_SOURCE_IS_LINKED(s->state));
461 pa_assert(s->monitor_of);
463 state = pa_sink_get_state(s->monitor_of);
465 if (state == PA_SINK_SUSPENDED)
466 return source_set_state(s, PA_SOURCE_SUSPENDED);
468 pa_assert(PA_SINK_IS_OPENED(state));
470 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
473 /* Called from main context */
474 pa_queue *pa_source_move_all_start(pa_source *s) {
476 pa_source_output *o, *n;
479 pa_source_assert_ref(s);
480 pa_assert(PA_SOURCE_IS_LINKED(s->state));
484 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = n) {
485 n = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx));
487 pa_source_output_ref(o);
489 if (pa_source_output_start_move(o) >= 0)
492 pa_source_output_unref(o);
498 /* Called from main context */
499 void pa_source_move_all_finish(pa_source *s, pa_queue *q, pa_bool_t save) {
502 pa_source_assert_ref(s);
503 pa_assert(PA_SOURCE_IS_LINKED(s->state));
506 while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
507 if (pa_source_output_finish_move(o, s, save) < 0)
508 pa_source_output_kill(o);
510 pa_source_output_unref(o);
513 pa_queue_free(q, NULL, NULL);
516 /* Called from main context */
517 void pa_source_move_all_fail(pa_queue *q) {
521 while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
522 if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], o) == PA_HOOK_OK) {
523 pa_source_output_kill(o);
524 pa_source_output_unref(o);
528 pa_queue_free(q, NULL, NULL);
531 /* Called from IO thread context */
532 void pa_source_process_rewind(pa_source *s, size_t nbytes) {
536 pa_source_assert_ref(s);
537 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
539 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
545 pa_log_debug("Processing rewind...");
547 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
548 pa_source_output_assert_ref(o);
549 pa_source_output_process_rewind(o, nbytes);
553 /* Called from IO thread context */
554 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
558 pa_source_assert_ref(s);
559 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
562 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
565 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
566 pa_memchunk vchunk = *chunk;
568 pa_memblock_ref(vchunk.memblock);
569 pa_memchunk_make_writable(&vchunk, 0);
571 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
572 pa_silence_memchunk(&vchunk, &s->sample_spec);
574 pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
576 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
577 pa_source_output_assert_ref(o);
579 if (!o->thread_info.direct_on_input)
580 pa_source_output_push(o, &vchunk);
583 pa_memblock_unref(vchunk.memblock);
586 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
587 pa_source_output_assert_ref(o);
589 if (!o->thread_info.direct_on_input)
590 pa_source_output_push(o, chunk);
595 /* Called from IO thread context */
596 void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk *chunk) {
597 pa_source_assert_ref(s);
598 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
599 pa_source_output_assert_ref(o);
600 pa_assert(o->thread_info.direct_on_input);
603 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
606 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
607 pa_memchunk vchunk = *chunk;
609 pa_memblock_ref(vchunk.memblock);
610 pa_memchunk_make_writable(&vchunk, 0);
612 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
613 pa_silence_memchunk(&vchunk, &s->sample_spec);
615 pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
617 pa_source_output_push(o, &vchunk);
619 pa_memblock_unref(vchunk.memblock);
621 pa_source_output_push(o, chunk);
624 /* Called from main thread */
625 pa_usec_t pa_source_get_latency(pa_source *s) {
628 pa_source_assert_ref(s);
629 pa_assert(PA_SOURCE_IS_LINKED(s->state));
631 if (s->state == PA_SOURCE_SUSPENDED)
634 if (!(s->flags & PA_SOURCE_LATENCY))
637 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
642 /* Called from IO thread */
643 pa_usec_t pa_source_get_latency_within_thread(pa_source *s) {
647 pa_source_assert_ref(s);
648 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
650 /* The returned value is supposed to be in the time domain of the sound card! */
652 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
655 if (!(s->flags & PA_SOURCE_LATENCY))
660 /* We probably should make this a proper vtable callback instead of going through process_msg() */
662 if (o->process_msg(o, PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
668 /* Called from main thread */
669 void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
670 pa_cvolume old_virtual_volume;
671 pa_bool_t virtual_volume_changed;
673 pa_source_assert_ref(s);
674 pa_assert(PA_SOURCE_IS_LINKED(s->state));
676 pa_assert(pa_cvolume_valid(volume));
677 pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
679 old_virtual_volume = s->virtual_volume;
680 s->virtual_volume = *volume;
681 virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume);
684 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
687 s->soft_volume = s->virtual_volume;
689 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
691 if (virtual_volume_changed)
692 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
695 /* Called from main thread. Only to be called by source implementor */
696 void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume) {
697 pa_source_assert_ref(s);
700 if (PA_SOURCE_IS_LINKED(s->state))
701 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
703 s->thread_info.soft_volume = *volume;
706 /* Called from main thread */
707 const pa_cvolume *pa_source_get_volume(pa_source *s, pa_bool_t force_refresh) {
708 pa_source_assert_ref(s);
709 pa_assert(PA_SOURCE_IS_LINKED(s->state));
711 if (s->refresh_volume || force_refresh) {
712 pa_cvolume old_virtual_volume = s->virtual_volume;
717 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
719 if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume))
720 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
723 return &s->virtual_volume;
726 /* Called from main thread */
727 void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume) {
728 pa_source_assert_ref(s);
730 /* The source implementor may call this if the volume changed to make sure everyone is notified */
732 if (pa_cvolume_equal(&s->virtual_volume, new_volume))
735 s->virtual_volume = *new_volume;
736 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
739 /* Called from main thread */
740 void pa_source_set_mute(pa_source *s, pa_bool_t mute) {
743 pa_source_assert_ref(s);
744 pa_assert(PA_SOURCE_IS_LINKED(s->state));
746 old_muted = s->muted;
752 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
754 if (old_muted != s->muted)
755 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
758 /* Called from main thread */
759 pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
760 pa_source_assert_ref(s);
761 pa_assert(PA_SOURCE_IS_LINKED(s->state));
763 if (s->refresh_muted || force_refresh) {
764 pa_bool_t old_muted = s->muted;
769 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
771 if (old_muted != s->muted) {
772 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
774 /* Make sure the soft mute status stays in sync */
775 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
782 /* Called from main thread */
783 void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted) {
784 pa_source_assert_ref(s);
786 /* The source implementor may call this if the mute state changed to make sure everyone is notified */
788 if (s->muted == new_muted)
791 s->muted = new_muted;
792 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
795 /* Called from main thread */
796 pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p) {
797 pa_source_assert_ref(s);
800 pa_proplist_update(s->proplist, mode, p);
802 if (PA_SOURCE_IS_LINKED(s->state)) {
803 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
804 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
810 /* Called from main thread */
811 void pa_source_set_description(pa_source *s, const char *description) {
813 pa_source_assert_ref(s);
815 if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
818 old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
820 if (old && description && !strcmp(old, description))
824 pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
826 pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
828 if (PA_SOURCE_IS_LINKED(s->state)) {
829 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
830 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
834 /* Called from main thread */
835 unsigned pa_source_linked_by(pa_source *s) {
836 pa_source_assert_ref(s);
837 pa_assert(PA_SOURCE_IS_LINKED(s->state));
839 return pa_idxset_size(s->outputs);
842 /* Called from main thread */
843 unsigned pa_source_used_by(pa_source *s) {
846 pa_source_assert_ref(s);
847 pa_assert(PA_SOURCE_IS_LINKED(s->state));
849 ret = pa_idxset_size(s->outputs);
850 pa_assert(ret >= s->n_corked);
852 return ret - s->n_corked;
855 /* Called from main thread */
856 unsigned pa_source_check_suspend(pa_source *s) {
861 pa_source_assert_ref(s);
863 if (!PA_SOURCE_IS_LINKED(s->state))
868 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx))) {
869 pa_source_output_state_t st;
871 st = pa_source_output_get_state(o);
872 pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(st));
874 if (st == PA_SOURCE_OUTPUT_CORKED)
877 if (o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND)
886 /* Called from IO thread, except when it is not */
887 int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
888 pa_source *s = PA_SOURCE(object);
889 pa_source_assert_ref(s);
891 switch ((pa_source_message_t) code) {
893 case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
894 pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
896 pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
898 if (o->direct_on_input) {
899 o->thread_info.direct_on_input = o->direct_on_input;
900 pa_hashmap_put(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index), o);
903 pa_assert(!o->thread_info.attached);
904 o->thread_info.attached = TRUE;
909 pa_source_output_set_state_within_thread(o, o->state);
911 if (o->thread_info.requested_source_latency != (pa_usec_t) -1)
912 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
914 pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
916 /* We don't just invalidate the requested latency here,
917 * because if we are in a move we might need to fix up the
918 * requested latency. */
919 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
924 case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
925 pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
927 pa_source_output_set_state_within_thread(o, o->state);
932 pa_assert(o->thread_info.attached);
933 o->thread_info.attached = FALSE;
935 if (o->thread_info.direct_on_input) {
936 pa_hashmap_remove(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index));
937 o->thread_info.direct_on_input = NULL;
940 if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
941 pa_source_output_unref(o);
943 pa_source_invalidate_requested_latency(s);
948 case PA_SOURCE_MESSAGE_SET_VOLUME:
949 s->thread_info.soft_volume = s->soft_volume;
952 case PA_SOURCE_MESSAGE_GET_VOLUME:
955 case PA_SOURCE_MESSAGE_SET_MUTE:
956 s->thread_info.soft_muted = s->muted;
959 case PA_SOURCE_MESSAGE_GET_MUTE:
962 case PA_SOURCE_MESSAGE_SET_STATE: {
964 pa_bool_t suspend_change =
965 (s->thread_info.state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(PA_PTR_TO_UINT(userdata))) ||
966 (PA_SOURCE_IS_OPENED(s->thread_info.state) && PA_PTR_TO_UINT(userdata) == PA_SOURCE_SUSPENDED);
968 s->thread_info.state = PA_PTR_TO_UINT(userdata);
970 if (suspend_change) {
974 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
975 if (o->suspend_within_thread)
976 o->suspend_within_thread(o, s->thread_info.state == PA_SOURCE_SUSPENDED);
983 case PA_SOURCE_MESSAGE_DETACH:
985 /* Detach all streams */
986 pa_source_detach_within_thread(s);
989 case PA_SOURCE_MESSAGE_ATTACH:
991 /* Reattach all streams */
992 pa_source_attach_within_thread(s);
995 case PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY: {
997 pa_usec_t *usec = userdata;
998 *usec = pa_source_get_requested_latency_within_thread(s);
1000 if (*usec == (pa_usec_t) -1)
1001 *usec = s->thread_info.max_latency;
1006 case PA_SOURCE_MESSAGE_SET_LATENCY_RANGE: {
1007 pa_usec_t *r = userdata;
1009 pa_source_set_latency_range_within_thread(s, r[0], r[1]);
1014 case PA_SOURCE_MESSAGE_GET_LATENCY_RANGE: {
1015 pa_usec_t *r = userdata;
1017 r[0] = s->thread_info.min_latency;
1018 r[1] = s->thread_info.max_latency;
1023 case PA_SOURCE_MESSAGE_GET_MAX_REWIND:
1025 *((size_t*) userdata) = s->thread_info.max_rewind;
1028 case PA_SOURCE_MESSAGE_SET_MAX_REWIND:
1030 pa_source_set_max_rewind_within_thread(s, (size_t) offset);
1033 case PA_SOURCE_MESSAGE_GET_LATENCY:
1035 if (s->monitor_of) {
1036 *((pa_usec_t*) userdata) = 0;
1040 /* Implementors need to overwrite this implementation! */
1043 case PA_SOURCE_MESSAGE_MAX:
1050 /* Called from main thread */
1051 int pa_source_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause) {
1056 pa_core_assert_ref(c);
1057 pa_assert(cause != 0);
1059 for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx))) {
1062 if (source->monitor_of)
1065 if ((r = pa_source_suspend(source, suspend, cause)) < 0)
1072 /* Called from main thread */
1073 void pa_source_detach(pa_source *s) {
1074 pa_source_assert_ref(s);
1075 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1077 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL) == 0);
1080 /* Called from main thread */
1081 void pa_source_attach(pa_source *s) {
1082 pa_source_assert_ref(s);
1083 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1085 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
1088 /* Called from IO thread */
1089 void pa_source_detach_within_thread(pa_source *s) {
1090 pa_source_output *o;
1093 pa_source_assert_ref(s);
1094 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1096 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1101 /* Called from IO thread */
1102 void pa_source_attach_within_thread(pa_source *s) {
1103 pa_source_output *o;
1106 pa_source_assert_ref(s);
1107 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1109 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1114 /* Called from IO thread */
1115 pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
1116 pa_usec_t result = (pa_usec_t) -1;
1117 pa_source_output *o;
1120 pa_source_assert_ref(s);
1122 if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
1123 return PA_CLAMP(s->fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
1125 if (s->thread_info.requested_latency_valid)
1126 return s->thread_info.requested_latency;
1128 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1130 if (o->thread_info.requested_source_latency != (pa_usec_t) -1 &&
1131 (result == (pa_usec_t) -1 || result > o->thread_info.requested_source_latency))
1132 result = o->thread_info.requested_source_latency;
1134 if (result != (pa_usec_t) -1)
1135 result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
1137 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1138 /* Only cache this if we are fully set up */
1139 s->thread_info.requested_latency = result;
1140 s->thread_info.requested_latency_valid = TRUE;
1146 /* Called from main thread */
1147 pa_usec_t pa_source_get_requested_latency(pa_source *s) {
1150 pa_source_assert_ref(s);
1151 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1153 if (s->state == PA_SOURCE_SUSPENDED)
1156 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1161 /* Called from IO thread */
1162 void pa_source_set_max_rewind_within_thread(pa_source *s, size_t max_rewind) {
1163 pa_source_output *o;
1166 pa_source_assert_ref(s);
1168 if (max_rewind == s->thread_info.max_rewind)
1171 s->thread_info.max_rewind = max_rewind;
1173 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1174 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1175 pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
1179 /* Called from main thread */
1180 void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
1181 pa_source_assert_ref(s);
1183 if (PA_SOURCE_IS_LINKED(s->state))
1184 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
1186 pa_source_set_max_rewind_within_thread(s, max_rewind);
1189 /* Called from IO thread */
1190 void pa_source_invalidate_requested_latency(pa_source *s) {
1191 pa_source_output *o;
1194 pa_source_assert_ref(s);
1196 if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
1199 s->thread_info.requested_latency_valid = FALSE;
1201 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1203 if (s->update_requested_latency)
1204 s->update_requested_latency(s);
1206 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1207 if (o->update_source_requested_latency)
1208 o->update_source_requested_latency(o);
1212 pa_sink_invalidate_requested_latency(s->monitor_of);
1215 /* Called from main thread */
1216 void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1217 pa_source_assert_ref(s);
1219 /* min_latency == 0: no limit
1220 * min_latency anything else: specified limit
1222 * Similar for max_latency */
1224 if (min_latency < ABSOLUTE_MIN_LATENCY)
1225 min_latency = ABSOLUTE_MIN_LATENCY;
1227 if (max_latency <= 0 ||
1228 max_latency > ABSOLUTE_MAX_LATENCY)
1229 max_latency = ABSOLUTE_MAX_LATENCY;
1231 pa_assert(min_latency <= max_latency);
1233 /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1234 pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
1235 max_latency == ABSOLUTE_MAX_LATENCY) ||
1236 (s->flags & PA_SOURCE_DYNAMIC_LATENCY));
1238 if (PA_SOURCE_IS_LINKED(s->state)) {
1244 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
1246 pa_source_set_latency_range_within_thread(s, min_latency, max_latency);
1249 /* Called from main thread */
1250 void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
1251 pa_source_assert_ref(s);
1252 pa_assert(min_latency);
1253 pa_assert(max_latency);
1255 if (PA_SOURCE_IS_LINKED(s->state)) {
1256 pa_usec_t r[2] = { 0, 0 };
1258 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
1260 *min_latency = r[0];
1261 *max_latency = r[1];
1263 *min_latency = s->thread_info.min_latency;
1264 *max_latency = s->thread_info.max_latency;
1268 /* Called from IO thread, and from main thread before pa_source_put() is called */
1269 void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1272 pa_source_assert_ref(s);
1274 pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
1275 pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
1276 pa_assert(min_latency <= max_latency);
1278 /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1279 pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
1280 max_latency == ABSOLUTE_MAX_LATENCY) ||
1281 (s->flags & PA_SOURCE_DYNAMIC_LATENCY) ||
1284 s->thread_info.min_latency = min_latency;
1285 s->thread_info.max_latency = max_latency;
1287 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1288 pa_source_output *o;
1290 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1291 if (o->update_source_latency_range)
1292 o->update_source_latency_range(o);
1295 pa_source_invalidate_requested_latency(s);
1298 /* Called from main thread, before the source is put */
1299 void pa_source_set_fixed_latency(pa_source *s, pa_usec_t latency) {
1300 pa_source_assert_ref(s);
1302 pa_assert(pa_source_get_state(s) == PA_SOURCE_INIT);
1304 if (latency < ABSOLUTE_MIN_LATENCY)
1305 latency = ABSOLUTE_MIN_LATENCY;
1307 if (latency > ABSOLUTE_MAX_LATENCY)
1308 latency = ABSOLUTE_MAX_LATENCY;
1310 s->fixed_latency = latency;
1313 /* Called from main thread */
1314 size_t pa_source_get_max_rewind(pa_source *s) {
1316 pa_source_assert_ref(s);
1318 if (!PA_SOURCE_IS_LINKED(s->state))
1319 return s->thread_info.max_rewind;
1321 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);