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/core-util.h>
37 #include <pulsecore/source-output.h>
38 #include <pulsecore/namereg.h>
39 #include <pulsecore/core-subscribe.h>
40 #include <pulsecore/log.h>
41 #include <pulsecore/sample-util.h>
45 #define ABSOLUTE_MIN_LATENCY (500)
46 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
47 #define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
49 static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
51 static void source_free(pa_object *o);
53 pa_source_new_data* pa_source_new_data_init(pa_source_new_data *data) {
57 data->proplist = pa_proplist_new();
62 void pa_source_new_data_set_name(pa_source_new_data *data, const char *name) {
66 data->name = pa_xstrdup(name);
69 void pa_source_new_data_set_sample_spec(pa_source_new_data *data, const pa_sample_spec *spec) {
72 if ((data->sample_spec_is_set = !!spec))
73 data->sample_spec = *spec;
76 void pa_source_new_data_set_channel_map(pa_source_new_data *data, const pa_channel_map *map) {
79 if ((data->channel_map_is_set = !!map))
80 data->channel_map = *map;
83 void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume) {
86 if ((data->volume_is_set = !!volume))
87 data->volume = *volume;
90 void pa_source_new_data_set_muted(pa_source_new_data *data, pa_bool_t mute) {
93 data->muted_is_set = TRUE;
97 void pa_source_new_data_set_port(pa_source_new_data *data, const char *port) {
100 pa_xfree(data->active_port);
101 data->active_port = pa_xstrdup(port);
104 void pa_source_new_data_done(pa_source_new_data *data) {
107 pa_proplist_free(data->proplist);
112 while ((p = pa_hashmap_steal_first(data->ports)))
113 pa_device_port_free(p);
115 pa_hashmap_free(data->ports, NULL, NULL);
118 pa_xfree(data->name);
119 pa_xfree(data->active_port);
122 /* Called from main context */
123 static void reset_callbacks(pa_source *s) {
127 s->get_volume = NULL;
128 s->set_volume = NULL;
131 s->update_requested_latency = NULL;
135 /* Called from main context */
136 pa_source* pa_source_new(
138 pa_source_new_data *data,
139 pa_source_flags_t flags) {
143 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
148 pa_assert(data->name);
149 pa_assert_ctl_context();
151 s = pa_msgobject_new(pa_source);
153 if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) {
154 pa_log_debug("Failed to register name %s.", data->name);
159 pa_source_new_data_set_name(data, name);
161 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0) {
163 pa_namereg_unregister(core, name);
167 /* FIXME, need to free s here on failure */
169 pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
170 pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
172 pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
174 if (!data->channel_map_is_set)
175 pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
177 pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
178 pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
180 if (!data->volume_is_set)
181 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
183 pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
184 pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
186 if (!data->muted_is_set)
190 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
192 pa_device_init_description(data->proplist);
193 pa_device_init_icon(data->proplist, FALSE);
194 pa_device_init_intended_roles(data->proplist);
196 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) {
198 pa_namereg_unregister(core, name);
202 s->parent.parent.free = source_free;
203 s->parent.process_msg = pa_source_process_msg;
206 s->state = PA_SOURCE_INIT;
208 s->suspend_cause = 0;
209 s->name = pa_xstrdup(name);
210 s->proplist = pa_proplist_copy(data->proplist);
211 s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
212 s->module = data->module;
213 s->card = data->card;
215 s->sample_spec = data->sample_spec;
216 s->channel_map = data->channel_map;
218 s->outputs = pa_idxset_new(NULL, NULL);
220 s->monitor_of = NULL;
222 s->virtual_volume = data->volume;
223 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
224 s->base_volume = PA_VOLUME_NORM;
225 s->n_volume_steps = PA_VOLUME_NORM+1;
226 s->muted = data->muted;
227 s->refresh_volume = s->refresh_muted = FALSE;
229 s->fixed_latency = flags & PA_SOURCE_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
237 /* As a minor optimization we just steal the list instead of
239 s->ports = data->ports;
242 s->active_port = NULL;
243 s->save_port = FALSE;
245 if (data->active_port && s->ports)
246 if ((s->active_port = pa_hashmap_get(s->ports, data->active_port)))
247 s->save_port = data->save_port;
249 if (!s->active_port && s->ports) {
253 PA_HASHMAP_FOREACH(p, s->ports, state)
254 if (!s->active_port || p->priority > s->active_port->priority)
258 s->save_volume = data->save_volume;
259 s->save_muted = data->save_muted;
261 pa_silence_memchunk_get(
262 &core->silence_cache,
268 s->thread_info.outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
269 s->thread_info.soft_volume = s->soft_volume;
270 s->thread_info.soft_muted = s->muted;
271 s->thread_info.state = s->state;
272 s->thread_info.max_rewind = 0;
273 s->thread_info.requested_latency_valid = FALSE;
274 s->thread_info.requested_latency = 0;
275 s->thread_info.min_latency = ABSOLUTE_MIN_LATENCY;
276 s->thread_info.max_latency = ABSOLUTE_MAX_LATENCY;
278 pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
281 pa_assert_se(pa_idxset_put(s->card->sources, s, NULL) >= 0);
283 pt = pa_proplist_to_string_sep(s->proplist, "\n ");
284 pa_log_info("Created source %u \"%s\" with sample spec %s and channel map %s\n %s",
287 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
288 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
295 /* Called from main context */
296 static int source_set_state(pa_source *s, pa_source_state_t state) {
298 pa_bool_t suspend_change;
299 pa_source_state_t original_state;
302 pa_assert_ctl_context();
304 if (s->state == state)
307 original_state = s->state;
310 (original_state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(state)) ||
311 (PA_SOURCE_IS_OPENED(original_state) && state == PA_SOURCE_SUSPENDED);
314 if ((ret = s->set_state(s, state)) < 0)
318 if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
321 s->set_state(s, original_state);
328 if (state != PA_SOURCE_UNLINKED) { /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
329 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
330 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
333 if (suspend_change) {
337 /* We're suspending or resuming, tell everyone about it */
339 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx)))
340 if (s->state == PA_SOURCE_SUSPENDED &&
341 (o->flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND))
342 pa_source_output_kill(o);
344 o->suspend(o, state == PA_SOURCE_SUSPENDED);
351 /* Called from main context */
352 void pa_source_put(pa_source *s) {
353 pa_source_assert_ref(s);
354 pa_assert_ctl_context();
356 pa_assert(s->state == PA_SOURCE_INIT);
358 /* The following fields must be initialized properly when calling _put() */
359 pa_assert(s->asyncmsgq);
360 pa_assert(s->rtpoll);
361 pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
363 /* Generally, flags should be initialized via pa_source_new(). As
364 * a special exception we allow volume related flags to be set
365 * between _new() and _put(). */
367 if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL))
368 s->flags |= PA_SOURCE_DECIBEL_VOLUME;
370 s->thread_info.soft_volume = s->soft_volume;
371 s->thread_info.soft_muted = s->muted;
373 pa_assert((s->flags & PA_SOURCE_HW_VOLUME_CTRL) || (s->base_volume == PA_VOLUME_NORM && s->flags & PA_SOURCE_DECIBEL_VOLUME));
374 pa_assert(!(s->flags & PA_SOURCE_DECIBEL_VOLUME) || s->n_volume_steps == PA_VOLUME_NORM+1);
375 pa_assert(!(s->flags & PA_SOURCE_DYNAMIC_LATENCY) == (s->fixed_latency != 0));
377 pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
379 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
380 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s);
383 /* Called from main context */
384 void pa_source_unlink(pa_source *s) {
386 pa_source_output *o, *j = NULL;
389 pa_assert_ctl_context();
391 /* See pa_sink_unlink() for a couple of comments how this function
394 linked = PA_SOURCE_IS_LINKED(s->state);
397 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
399 if (s->state != PA_SOURCE_UNLINKED)
400 pa_namereg_unregister(s->core, s->name);
401 pa_idxset_remove_by_data(s->core->sources, s, NULL);
404 pa_idxset_remove_by_data(s->card->sources, s, NULL);
406 while ((o = pa_idxset_first(s->outputs, NULL))) {
408 pa_source_output_kill(o);
413 source_set_state(s, PA_SOURCE_UNLINKED);
415 s->state = PA_SOURCE_UNLINKED;
420 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
421 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s);
425 /* Called from main context */
426 static void source_free(pa_object *o) {
427 pa_source_output *so;
428 pa_source *s = PA_SOURCE(o);
431 pa_assert_ctl_context();
432 pa_assert(pa_source_refcnt(s) == 0);
434 if (PA_SOURCE_IS_LINKED(s->state))
437 pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
439 pa_idxset_free(s->outputs, NULL, NULL);
441 while ((so = pa_hashmap_steal_first(s->thread_info.outputs)))
442 pa_source_output_unref(so);
444 pa_hashmap_free(s->thread_info.outputs, NULL, NULL);
446 if (s->silence.memblock)
447 pa_memblock_unref(s->silence.memblock);
453 pa_proplist_free(s->proplist);
458 while ((p = pa_hashmap_steal_first(s->ports)))
459 pa_device_port_free(p);
461 pa_hashmap_free(s->ports, NULL, NULL);
467 /* Called from main context */
468 void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) {
469 pa_assert_ctl_context();
470 pa_source_assert_ref(s);
475 /* Called from main context */
476 void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) {
477 pa_assert_ctl_context();
478 pa_source_assert_ref(s);
483 /* Called from main context */
484 int pa_source_update_status(pa_source*s) {
485 pa_source_assert_ref(s);
486 pa_assert_ctl_context();
487 pa_assert(PA_SOURCE_IS_LINKED(s->state));
489 if (s->state == PA_SOURCE_SUSPENDED)
492 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
495 /* Called from main context */
496 int pa_source_suspend(pa_source *s, pa_bool_t suspend, pa_suspend_cause_t cause) {
497 pa_source_assert_ref(s);
498 pa_assert_ctl_context();
499 pa_assert(PA_SOURCE_IS_LINKED(s->state));
500 pa_assert(cause != 0);
503 return -PA_ERR_NOTSUPPORTED;
506 s->suspend_cause |= cause;
508 s->suspend_cause &= ~cause;
510 if ((pa_source_get_state(s) == PA_SOURCE_SUSPENDED) == !!s->suspend_cause)
513 pa_log_debug("Suspend cause of source %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming");
516 return source_set_state(s, PA_SOURCE_SUSPENDED);
518 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
521 /* Called from main context */
522 int pa_source_sync_suspend(pa_source *s) {
523 pa_sink_state_t state;
525 pa_source_assert_ref(s);
526 pa_assert_ctl_context();
527 pa_assert(PA_SOURCE_IS_LINKED(s->state));
528 pa_assert(s->monitor_of);
530 state = pa_sink_get_state(s->monitor_of);
532 if (state == PA_SINK_SUSPENDED)
533 return source_set_state(s, PA_SOURCE_SUSPENDED);
535 pa_assert(PA_SINK_IS_OPENED(state));
537 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
540 /* Called from main context */
541 pa_queue *pa_source_move_all_start(pa_source *s, pa_queue *q) {
542 pa_source_output *o, *n;
545 pa_source_assert_ref(s);
546 pa_assert_ctl_context();
547 pa_assert(PA_SOURCE_IS_LINKED(s->state));
552 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = n) {
553 n = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx));
555 pa_source_output_ref(o);
557 if (pa_source_output_start_move(o) >= 0)
560 pa_source_output_unref(o);
566 /* Called from main context */
567 void pa_source_move_all_finish(pa_source *s, pa_queue *q, pa_bool_t save) {
570 pa_source_assert_ref(s);
571 pa_assert_ctl_context();
572 pa_assert(PA_SOURCE_IS_LINKED(s->state));
575 while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
576 if (pa_source_output_finish_move(o, s, save) < 0)
577 pa_source_output_fail_move(o);
579 pa_source_output_unref(o);
582 pa_queue_free(q, NULL, NULL);
585 /* Called from main context */
586 void pa_source_move_all_fail(pa_queue *q) {
589 pa_assert_ctl_context();
592 while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
593 pa_source_output_fail_move(o);
594 pa_source_output_unref(o);
597 pa_queue_free(q, NULL, NULL);
600 /* Called from IO thread context */
601 void pa_source_process_rewind(pa_source *s, size_t nbytes) {
605 pa_source_assert_ref(s);
606 pa_source_assert_io_context(s);
607 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
612 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
615 pa_log_debug("Processing rewind...");
617 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state) {
618 pa_source_output_assert_ref(o);
619 pa_source_output_process_rewind(o, nbytes);
623 /* Called from IO thread context */
624 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
628 pa_source_assert_ref(s);
629 pa_source_assert_io_context(s);
630 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
633 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
636 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
637 pa_memchunk vchunk = *chunk;
639 pa_memblock_ref(vchunk.memblock);
640 pa_memchunk_make_writable(&vchunk, 0);
642 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
643 pa_silence_memchunk(&vchunk, &s->sample_spec);
645 pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
647 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
648 pa_source_output_assert_ref(o);
650 if (!o->thread_info.direct_on_input)
651 pa_source_output_push(o, &vchunk);
654 pa_memblock_unref(vchunk.memblock);
657 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
658 pa_source_output_assert_ref(o);
660 if (!o->thread_info.direct_on_input)
661 pa_source_output_push(o, chunk);
666 /* Called from IO thread context */
667 void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk *chunk) {
668 pa_source_assert_ref(s);
669 pa_source_assert_io_context(s);
670 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
671 pa_source_output_assert_ref(o);
672 pa_assert(o->thread_info.direct_on_input);
675 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
678 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
679 pa_memchunk vchunk = *chunk;
681 pa_memblock_ref(vchunk.memblock);
682 pa_memchunk_make_writable(&vchunk, 0);
684 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
685 pa_silence_memchunk(&vchunk, &s->sample_spec);
687 pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
689 pa_source_output_push(o, &vchunk);
691 pa_memblock_unref(vchunk.memblock);
693 pa_source_output_push(o, chunk);
696 /* Called from main thread */
697 pa_usec_t pa_source_get_latency(pa_source *s) {
700 pa_source_assert_ref(s);
701 pa_assert_ctl_context();
702 pa_assert(PA_SOURCE_IS_LINKED(s->state));
704 if (s->state == PA_SOURCE_SUSPENDED)
707 if (!(s->flags & PA_SOURCE_LATENCY))
710 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
715 /* Called from IO thread */
716 pa_usec_t pa_source_get_latency_within_thread(pa_source *s) {
720 pa_source_assert_ref(s);
721 pa_source_assert_io_context(s);
722 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
724 /* The returned value is supposed to be in the time domain of the sound card! */
726 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
729 if (!(s->flags & PA_SOURCE_LATENCY))
734 /* We probably should make this a proper vtable callback instead of going through process_msg() */
736 if (o->process_msg(o, PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
742 /* Called from main thread */
743 void pa_source_set_volume(pa_source *s, const pa_cvolume *volume, pa_bool_t save) {
744 pa_cvolume old_virtual_volume;
745 pa_bool_t virtual_volume_changed;
747 pa_source_assert_ref(s);
748 pa_assert_ctl_context();
749 pa_assert(PA_SOURCE_IS_LINKED(s->state));
751 pa_assert(pa_cvolume_valid(volume));
752 pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
754 old_virtual_volume = s->virtual_volume;
755 s->virtual_volume = *volume;
756 virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume);
757 s->save_volume = (!virtual_volume_changed && s->save_volume) || save;
760 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
763 s->soft_volume = s->virtual_volume;
765 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
767 if (virtual_volume_changed)
768 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
771 /* Called from main thread. Only to be called by source implementor */
772 void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume) {
773 pa_source_assert_ref(s);
774 pa_assert_ctl_context();
777 if (PA_SOURCE_IS_LINKED(s->state))
778 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
780 s->thread_info.soft_volume = *volume;
783 /* Called from main thread */
784 const pa_cvolume *pa_source_get_volume(pa_source *s, pa_bool_t force_refresh) {
785 pa_source_assert_ref(s);
786 pa_assert_ctl_context();
787 pa_assert(PA_SOURCE_IS_LINKED(s->state));
789 if (s->refresh_volume || force_refresh) {
790 pa_cvolume old_virtual_volume = s->virtual_volume;
795 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
797 if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume)) {
798 s->save_volume = TRUE;
799 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
803 return &s->virtual_volume;
806 /* Called from main thread */
807 void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume) {
808 pa_source_assert_ref(s);
809 pa_assert_ctl_context();
810 pa_assert(PA_SOURCE_IS_LINKED(s->state));
812 /* The source implementor may call this if the volume changed to make sure everyone is notified */
814 if (pa_cvolume_equal(&s->virtual_volume, new_volume))
817 s->virtual_volume = *new_volume;
818 s->save_volume = TRUE;
820 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
823 /* Called from main thread */
824 void pa_source_set_mute(pa_source *s, pa_bool_t mute, pa_bool_t save) {
827 pa_source_assert_ref(s);
828 pa_assert_ctl_context();
829 pa_assert(PA_SOURCE_IS_LINKED(s->state));
831 old_muted = s->muted;
833 s->save_muted = (old_muted == s->muted && s->save_muted) || save;
838 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
840 if (old_muted != s->muted)
841 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
844 /* Called from main thread */
845 pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
846 pa_source_assert_ref(s);
847 pa_assert_ctl_context();
848 pa_assert(PA_SOURCE_IS_LINKED(s->state));
850 if (s->refresh_muted || force_refresh) {
851 pa_bool_t old_muted = s->muted;
856 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
858 if (old_muted != s->muted) {
859 s->save_muted = TRUE;
861 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
863 /* Make sure the soft mute status stays in sync */
864 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
871 /* Called from main thread */
872 void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted) {
873 pa_source_assert_ref(s);
874 pa_assert_ctl_context();
875 pa_assert(PA_SOURCE_IS_LINKED(s->state));
877 /* The source implementor may call this if the mute state changed to make sure everyone is notified */
879 if (s->muted == new_muted)
882 s->muted = new_muted;
883 s->save_muted = TRUE;
885 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
888 /* Called from main thread */
889 pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p) {
890 pa_source_assert_ref(s);
891 pa_assert_ctl_context();
894 pa_proplist_update(s->proplist, mode, p);
896 if (PA_SOURCE_IS_LINKED(s->state)) {
897 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
898 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
904 /* Called from main thread */
905 /* FIXME -- this should be dropped and be merged into pa_source_update_proplist() */
906 void pa_source_set_description(pa_source *s, const char *description) {
908 pa_source_assert_ref(s);
909 pa_assert_ctl_context();
911 if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
914 old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
916 if (old && description && pa_streq(old, description))
920 pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
922 pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
924 if (PA_SOURCE_IS_LINKED(s->state)) {
925 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
926 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
930 /* Called from main thread */
931 unsigned pa_source_linked_by(pa_source *s) {
932 pa_source_assert_ref(s);
933 pa_assert(PA_SOURCE_IS_LINKED(s->state));
934 pa_assert_ctl_context();
936 return pa_idxset_size(s->outputs);
939 /* Called from main thread */
940 unsigned pa_source_used_by(pa_source *s) {
943 pa_source_assert_ref(s);
944 pa_assert(PA_SOURCE_IS_LINKED(s->state));
945 pa_assert_ctl_context();
947 ret = pa_idxset_size(s->outputs);
948 pa_assert(ret >= s->n_corked);
950 return ret - s->n_corked;
953 /* Called from main thread */
954 unsigned pa_source_check_suspend(pa_source *s) {
959 pa_source_assert_ref(s);
960 pa_assert_ctl_context();
962 if (!PA_SOURCE_IS_LINKED(s->state))
967 PA_IDXSET_FOREACH(o, s->outputs, idx) {
968 pa_source_output_state_t st;
970 st = pa_source_output_get_state(o);
971 pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(st));
973 if (st == PA_SOURCE_OUTPUT_CORKED)
976 if (o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND)
985 /* Called from IO thread, except when it is not */
986 int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
987 pa_source *s = PA_SOURCE(object);
988 pa_source_assert_ref(s);
990 switch ((pa_source_message_t) code) {
992 case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
993 pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
995 pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
997 if (o->direct_on_input) {
998 o->thread_info.direct_on_input = o->direct_on_input;
999 pa_hashmap_put(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index), o);
1002 pa_assert(!o->thread_info.attached);
1003 o->thread_info.attached = TRUE;
1008 pa_source_output_set_state_within_thread(o, o->state);
1010 if (o->thread_info.requested_source_latency != (pa_usec_t) -1)
1011 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
1013 pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
1015 /* We don't just invalidate the requested latency here,
1016 * because if we are in a move we might need to fix up the
1017 * requested latency. */
1018 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
1023 case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
1024 pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
1026 pa_source_output_set_state_within_thread(o, o->state);
1031 pa_assert(o->thread_info.attached);
1032 o->thread_info.attached = FALSE;
1034 if (o->thread_info.direct_on_input) {
1035 pa_hashmap_remove(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index));
1036 o->thread_info.direct_on_input = NULL;
1039 if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
1040 pa_source_output_unref(o);
1042 pa_source_invalidate_requested_latency(s);
1047 case PA_SOURCE_MESSAGE_SET_VOLUME:
1048 s->thread_info.soft_volume = s->soft_volume;
1051 case PA_SOURCE_MESSAGE_GET_VOLUME:
1054 case PA_SOURCE_MESSAGE_SET_MUTE:
1055 s->thread_info.soft_muted = s->muted;
1058 case PA_SOURCE_MESSAGE_GET_MUTE:
1061 case PA_SOURCE_MESSAGE_SET_STATE: {
1063 pa_bool_t suspend_change =
1064 (s->thread_info.state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(PA_PTR_TO_UINT(userdata))) ||
1065 (PA_SOURCE_IS_OPENED(s->thread_info.state) && PA_PTR_TO_UINT(userdata) == PA_SOURCE_SUSPENDED);
1067 s->thread_info.state = PA_PTR_TO_UINT(userdata);
1069 if (suspend_change) {
1070 pa_source_output *o;
1073 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1074 if (o->suspend_within_thread)
1075 o->suspend_within_thread(o, s->thread_info.state == PA_SOURCE_SUSPENDED);
1082 case PA_SOURCE_MESSAGE_DETACH:
1084 /* Detach all streams */
1085 pa_source_detach_within_thread(s);
1088 case PA_SOURCE_MESSAGE_ATTACH:
1090 /* Reattach all streams */
1091 pa_source_attach_within_thread(s);
1094 case PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY: {
1096 pa_usec_t *usec = userdata;
1097 *usec = pa_source_get_requested_latency_within_thread(s);
1099 if (*usec == (pa_usec_t) -1)
1100 *usec = s->thread_info.max_latency;
1105 case PA_SOURCE_MESSAGE_SET_LATENCY_RANGE: {
1106 pa_usec_t *r = userdata;
1108 pa_source_set_latency_range_within_thread(s, r[0], r[1]);
1113 case PA_SOURCE_MESSAGE_GET_LATENCY_RANGE: {
1114 pa_usec_t *r = userdata;
1116 r[0] = s->thread_info.min_latency;
1117 r[1] = s->thread_info.max_latency;
1122 case PA_SOURCE_MESSAGE_GET_MAX_REWIND:
1124 *((size_t*) userdata) = s->thread_info.max_rewind;
1127 case PA_SOURCE_MESSAGE_SET_MAX_REWIND:
1129 pa_source_set_max_rewind_within_thread(s, (size_t) offset);
1132 case PA_SOURCE_MESSAGE_GET_LATENCY:
1134 if (s->monitor_of) {
1135 *((pa_usec_t*) userdata) = 0;
1139 /* Implementors need to overwrite this implementation! */
1142 case PA_SOURCE_MESSAGE_MAX:
1149 /* Called from main thread */
1150 int pa_source_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause) {
1155 pa_core_assert_ref(c);
1156 pa_assert_ctl_context();
1157 pa_assert(cause != 0);
1159 for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx))) {
1162 if (source->monitor_of)
1165 if ((r = pa_source_suspend(source, suspend, cause)) < 0)
1172 /* Called from main thread */
1173 void pa_source_detach(pa_source *s) {
1174 pa_source_assert_ref(s);
1175 pa_assert_ctl_context();
1176 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1178 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL) == 0);
1181 /* Called from main thread */
1182 void pa_source_attach(pa_source *s) {
1183 pa_source_assert_ref(s);
1184 pa_assert_ctl_context();
1185 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1187 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
1190 /* Called from IO thread */
1191 void pa_source_detach_within_thread(pa_source *s) {
1192 pa_source_output *o;
1195 pa_source_assert_ref(s);
1196 pa_source_assert_io_context(s);
1197 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1199 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state)
1204 /* Called from IO thread */
1205 void pa_source_attach_within_thread(pa_source *s) {
1206 pa_source_output *o;
1209 pa_source_assert_ref(s);
1210 pa_source_assert_io_context(s);
1211 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1213 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state)
1218 /* Called from IO thread */
1219 pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
1220 pa_usec_t result = (pa_usec_t) -1;
1221 pa_source_output *o;
1224 pa_source_assert_ref(s);
1225 pa_source_assert_io_context(s);
1227 if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
1228 return PA_CLAMP(s->fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
1230 if (s->thread_info.requested_latency_valid)
1231 return s->thread_info.requested_latency;
1233 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1235 if (o->thread_info.requested_source_latency != (pa_usec_t) -1 &&
1236 (result == (pa_usec_t) -1 || result > o->thread_info.requested_source_latency))
1237 result = o->thread_info.requested_source_latency;
1239 if (result != (pa_usec_t) -1)
1240 result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
1242 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1243 /* Only cache this if we are fully set up */
1244 s->thread_info.requested_latency = result;
1245 s->thread_info.requested_latency_valid = TRUE;
1251 /* Called from main thread */
1252 pa_usec_t pa_source_get_requested_latency(pa_source *s) {
1255 pa_source_assert_ref(s);
1256 pa_assert_ctl_context();
1257 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1259 if (s->state == PA_SOURCE_SUSPENDED)
1262 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1267 /* Called from IO thread */
1268 void pa_source_set_max_rewind_within_thread(pa_source *s, size_t max_rewind) {
1269 pa_source_output *o;
1272 pa_source_assert_ref(s);
1273 pa_source_assert_io_context(s);
1275 if (max_rewind == s->thread_info.max_rewind)
1278 s->thread_info.max_rewind = max_rewind;
1280 if (PA_SOURCE_IS_LINKED(s->thread_info.state))
1281 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state)
1282 pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
1285 /* Called from main thread */
1286 void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
1287 pa_source_assert_ref(s);
1288 pa_assert_ctl_context();
1290 if (PA_SOURCE_IS_LINKED(s->state))
1291 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
1293 pa_source_set_max_rewind_within_thread(s, max_rewind);
1296 /* Called from IO thread */
1297 void pa_source_invalidate_requested_latency(pa_source *s) {
1298 pa_source_output *o;
1301 pa_source_assert_ref(s);
1302 pa_source_assert_io_context(s);
1304 if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
1307 s->thread_info.requested_latency_valid = FALSE;
1309 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1311 if (s->update_requested_latency)
1312 s->update_requested_latency(s);
1314 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1315 if (o->update_source_requested_latency)
1316 o->update_source_requested_latency(o);
1320 pa_sink_invalidate_requested_latency(s->monitor_of);
1323 /* Called from main thread */
1324 void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1325 pa_source_assert_ref(s);
1326 pa_assert_ctl_context();
1328 /* min_latency == 0: no limit
1329 * min_latency anything else: specified limit
1331 * Similar for max_latency */
1333 if (min_latency < ABSOLUTE_MIN_LATENCY)
1334 min_latency = ABSOLUTE_MIN_LATENCY;
1336 if (max_latency <= 0 ||
1337 max_latency > ABSOLUTE_MAX_LATENCY)
1338 max_latency = ABSOLUTE_MAX_LATENCY;
1340 pa_assert(min_latency <= max_latency);
1342 /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1343 pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
1344 max_latency == ABSOLUTE_MAX_LATENCY) ||
1345 (s->flags & PA_SOURCE_DYNAMIC_LATENCY));
1347 if (PA_SOURCE_IS_LINKED(s->state)) {
1353 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
1355 pa_source_set_latency_range_within_thread(s, min_latency, max_latency);
1358 /* Called from main thread */
1359 void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
1360 pa_source_assert_ref(s);
1361 pa_assert_ctl_context();
1362 pa_assert(min_latency);
1363 pa_assert(max_latency);
1365 if (PA_SOURCE_IS_LINKED(s->state)) {
1366 pa_usec_t r[2] = { 0, 0 };
1368 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
1370 *min_latency = r[0];
1371 *max_latency = r[1];
1373 *min_latency = s->thread_info.min_latency;
1374 *max_latency = s->thread_info.max_latency;
1378 /* Called from IO thread, and from main thread before pa_source_put() is called */
1379 void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1382 pa_source_assert_ref(s);
1383 pa_source_assert_io_context(s);
1385 pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
1386 pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
1387 pa_assert(min_latency <= max_latency);
1389 /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1390 pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
1391 max_latency == ABSOLUTE_MAX_LATENCY) ||
1392 (s->flags & PA_SOURCE_DYNAMIC_LATENCY) ||
1395 s->thread_info.min_latency = min_latency;
1396 s->thread_info.max_latency = max_latency;
1398 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1399 pa_source_output *o;
1401 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1402 if (o->update_source_latency_range)
1403 o->update_source_latency_range(o);
1406 pa_source_invalidate_requested_latency(s);
1409 /* Called from main thread, before the source is put */
1410 void pa_source_set_fixed_latency(pa_source *s, pa_usec_t latency) {
1411 pa_source_assert_ref(s);
1412 pa_assert_ctl_context();
1414 pa_assert(pa_source_get_state(s) == PA_SOURCE_INIT);
1416 if (latency < ABSOLUTE_MIN_LATENCY)
1417 latency = ABSOLUTE_MIN_LATENCY;
1419 if (latency > ABSOLUTE_MAX_LATENCY)
1420 latency = ABSOLUTE_MAX_LATENCY;
1422 s->fixed_latency = latency;
1425 /* Called from main thread */
1426 size_t pa_source_get_max_rewind(pa_source *s) {
1428 pa_assert_ctl_context();
1429 pa_source_assert_ref(s);
1431 if (!PA_SOURCE_IS_LINKED(s->state))
1432 return s->thread_info.max_rewind;
1434 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
1439 /* Called from main context */
1440 int pa_source_set_port(pa_source *s, const char *name, pa_bool_t save) {
1441 pa_device_port *port;
1444 pa_assert_ctl_context();
1447 pa_log_debug("set_port() operation not implemented for source %u \"%s\"", s->index, s->name);
1448 return -PA_ERR_NOTIMPLEMENTED;
1452 return -PA_ERR_NOENTITY;
1454 if (!(port = pa_hashmap_get(s->ports, name)))
1455 return -PA_ERR_NOENTITY;
1457 if (s->active_port == port) {
1458 s->save_port = s->save_port || save;
1462 if ((s->set_port(s, port)) < 0)
1463 return -PA_ERR_NOENTITY;
1465 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1467 pa_log_info("Changed port of source %u \"%s\" to %s", s->index, s->name, port->name);
1469 s->active_port = port;
1470 s->save_port = save;