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>
35 #include <pulse/internal.h>
37 #include <pulsecore/core-util.h>
38 #include <pulsecore/source-output.h>
39 #include <pulsecore/namereg.h>
40 #include <pulsecore/core-subscribe.h>
41 #include <pulsecore/log.h>
42 #include <pulsecore/sample-util.h>
46 #define ABSOLUTE_MIN_LATENCY (500)
47 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
48 #define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
50 PA_DEFINE_PUBLIC_CLASS(pa_source
, pa_msgobject
);
52 static void source_free(pa_object
*o
);
54 pa_source_new_data
* pa_source_new_data_init(pa_source_new_data
*data
) {
58 data
->proplist
= pa_proplist_new();
63 void pa_source_new_data_set_name(pa_source_new_data
*data
, const char *name
) {
67 data
->name
= pa_xstrdup(name
);
70 void pa_source_new_data_set_sample_spec(pa_source_new_data
*data
, const pa_sample_spec
*spec
) {
73 if ((data
->sample_spec_is_set
= !!spec
))
74 data
->sample_spec
= *spec
;
77 void pa_source_new_data_set_channel_map(pa_source_new_data
*data
, const pa_channel_map
*map
) {
80 if ((data
->channel_map_is_set
= !!map
))
81 data
->channel_map
= *map
;
84 void pa_source_new_data_set_volume(pa_source_new_data
*data
, const pa_cvolume
*volume
) {
87 if ((data
->volume_is_set
= !!volume
))
88 data
->volume
= *volume
;
91 void pa_source_new_data_set_muted(pa_source_new_data
*data
, pa_bool_t mute
) {
94 data
->muted_is_set
= TRUE
;
98 void pa_source_new_data_set_port(pa_source_new_data
*data
, const char *port
) {
101 pa_xfree(data
->active_port
);
102 data
->active_port
= pa_xstrdup(port
);
105 void pa_source_new_data_done(pa_source_new_data
*data
) {
108 pa_proplist_free(data
->proplist
);
113 while ((p
= pa_hashmap_steal_first(data
->ports
)))
114 pa_device_port_free(p
);
116 pa_hashmap_free(data
->ports
, NULL
, NULL
);
119 pa_xfree(data
->name
);
120 pa_xfree(data
->active_port
);
123 /* Called from main context */
124 static void reset_callbacks(pa_source
*s
) {
128 s
->get_volume
= NULL
;
129 s
->set_volume
= NULL
;
132 s
->update_requested_latency
= NULL
;
134 s
->get_formats
= NULL
;
137 /* Called from main context */
138 pa_source
* pa_source_new(
140 pa_source_new_data
*data
,
141 pa_source_flags_t flags
) {
145 char st
[PA_SAMPLE_SPEC_SNPRINT_MAX
], cm
[PA_CHANNEL_MAP_SNPRINT_MAX
];
150 pa_assert(data
->name
);
151 pa_assert_ctl_context();
153 s
= pa_msgobject_new(pa_source
);
155 if (!(name
= pa_namereg_register(core
, data
->name
, PA_NAMEREG_SOURCE
, s
, data
->namereg_fail
))) {
156 pa_log_debug("Failed to register name %s.", data
->name
);
161 pa_source_new_data_set_name(data
, name
);
163 if (pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SOURCE_NEW
], data
) < 0) {
165 pa_namereg_unregister(core
, name
);
169 /* FIXME, need to free s here on failure */
171 pa_return_null_if_fail(!data
->driver
|| pa_utf8_valid(data
->driver
));
172 pa_return_null_if_fail(data
->name
&& pa_utf8_valid(data
->name
) && data
->name
[0]);
174 pa_return_null_if_fail(data
->sample_spec_is_set
&& pa_sample_spec_valid(&data
->sample_spec
));
176 if (!data
->channel_map_is_set
)
177 pa_return_null_if_fail(pa_channel_map_init_auto(&data
->channel_map
, data
->sample_spec
.channels
, PA_CHANNEL_MAP_DEFAULT
));
179 pa_return_null_if_fail(pa_channel_map_valid(&data
->channel_map
));
180 pa_return_null_if_fail(data
->channel_map
.channels
== data
->sample_spec
.channels
);
182 if (!data
->volume_is_set
)
183 pa_cvolume_reset(&data
->volume
, data
->sample_spec
.channels
);
185 pa_return_null_if_fail(pa_cvolume_valid(&data
->volume
));
186 pa_return_null_if_fail(pa_cvolume_compatible(&data
->volume
, &data
->sample_spec
));
188 if (!data
->muted_is_set
)
192 pa_proplist_update(data
->proplist
, PA_UPDATE_MERGE
, data
->card
->proplist
);
194 pa_device_init_description(data
->proplist
);
195 pa_device_init_icon(data
->proplist
, FALSE
);
196 pa_device_init_intended_roles(data
->proplist
);
198 if (pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SOURCE_FIXATE
], data
) < 0) {
200 pa_namereg_unregister(core
, name
);
204 s
->parent
.parent
.free
= source_free
;
205 s
->parent
.process_msg
= pa_source_process_msg
;
208 s
->state
= PA_SOURCE_INIT
;
211 s
->suspend_cause
= 0;
212 s
->name
= pa_xstrdup(name
);
213 s
->proplist
= pa_proplist_copy(data
->proplist
);
214 s
->driver
= pa_xstrdup(pa_path_get_filename(data
->driver
));
215 s
->module
= data
->module
;
216 s
->card
= data
->card
;
218 s
->priority
= pa_device_init_priority(s
->proplist
);
220 s
->sample_spec
= data
->sample_spec
;
221 s
->channel_map
= data
->channel_map
;
223 s
->outputs
= pa_idxset_new(NULL
, NULL
);
225 s
->monitor_of
= NULL
;
226 s
->output_from_master
= NULL
;
228 s
->volume
= data
->volume
;
229 pa_cvolume_reset(&s
->soft_volume
, s
->sample_spec
.channels
);
230 s
->base_volume
= PA_VOLUME_NORM
;
231 s
->n_volume_steps
= PA_VOLUME_NORM
+1;
232 s
->muted
= data
->muted
;
233 s
->refresh_volume
= s
->refresh_muted
= FALSE
;
240 /* As a minor optimization we just steal the list instead of
242 s
->ports
= data
->ports
;
245 s
->active_port
= NULL
;
246 s
->save_port
= FALSE
;
248 if (data
->active_port
&& s
->ports
)
249 if ((s
->active_port
= pa_hashmap_get(s
->ports
, data
->active_port
)))
250 s
->save_port
= data
->save_port
;
252 if (!s
->active_port
&& s
->ports
) {
256 PA_HASHMAP_FOREACH(p
, s
->ports
, state
)
257 if (!s
->active_port
|| p
->priority
> s
->active_port
->priority
)
261 s
->save_volume
= data
->save_volume
;
262 s
->save_muted
= data
->save_muted
;
264 pa_silence_memchunk_get(
265 &core
->silence_cache
,
271 s
->thread_info
.rtpoll
= NULL
;
272 s
->thread_info
.outputs
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
273 s
->thread_info
.soft_volume
= s
->soft_volume
;
274 s
->thread_info
.soft_muted
= s
->muted
;
275 s
->thread_info
.state
= s
->state
;
276 s
->thread_info
.max_rewind
= 0;
277 s
->thread_info
.requested_latency_valid
= FALSE
;
278 s
->thread_info
.requested_latency
= 0;
279 s
->thread_info
.min_latency
= ABSOLUTE_MIN_LATENCY
;
280 s
->thread_info
.max_latency
= ABSOLUTE_MAX_LATENCY
;
281 s
->thread_info
.fixed_latency
= flags
& PA_SOURCE_DYNAMIC_LATENCY
? 0 : DEFAULT_FIXED_LATENCY
;
283 pa_assert_se(pa_idxset_put(core
->sources
, s
, &s
->index
) >= 0);
286 pa_assert_se(pa_idxset_put(s
->card
->sources
, s
, NULL
) >= 0);
288 pt
= pa_proplist_to_string_sep(s
->proplist
, "\n ");
289 pa_log_info("Created source %u \"%s\" with sample spec %s and channel map %s\n %s",
292 pa_sample_spec_snprint(st
, sizeof(st
), &s
->sample_spec
),
293 pa_channel_map_snprint(cm
, sizeof(cm
), &s
->channel_map
),
300 /* Called from main context */
301 static int source_set_state(pa_source
*s
, pa_source_state_t state
) {
303 pa_bool_t suspend_change
;
304 pa_source_state_t original_state
;
307 pa_assert_ctl_context();
309 if (s
->state
== state
)
312 original_state
= s
->state
;
315 (original_state
== PA_SOURCE_SUSPENDED
&& PA_SOURCE_IS_OPENED(state
)) ||
316 (PA_SOURCE_IS_OPENED(original_state
) && state
== PA_SOURCE_SUSPENDED
);
319 if ((ret
= s
->set_state(s
, state
)) < 0)
323 if ((ret
= pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_SET_STATE
, PA_UINT_TO_PTR(state
), 0, NULL
)) < 0) {
326 s
->set_state(s
, original_state
);
333 if (state
!= PA_SOURCE_UNLINKED
) { /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
334 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SOURCE_STATE_CHANGED
], s
);
335 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
| PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
338 if (suspend_change
) {
342 /* We're suspending or resuming, tell everyone about it */
344 PA_IDXSET_FOREACH(o
, s
->outputs
, idx
)
345 if (s
->state
== PA_SOURCE_SUSPENDED
&&
346 (o
->flags
& PA_SOURCE_OUTPUT_KILL_ON_SUSPEND
))
347 pa_source_output_kill(o
);
349 o
->suspend(o
, state
== PA_SOURCE_SUSPENDED
);
355 /* Called from main context */
356 void pa_source_put(pa_source
*s
) {
357 pa_source_assert_ref(s
);
358 pa_assert_ctl_context();
360 pa_assert(s
->state
== PA_SOURCE_INIT
);
362 /* The following fields must be initialized properly when calling _put() */
363 pa_assert(s
->asyncmsgq
);
364 pa_assert(s
->thread_info
.min_latency
<= s
->thread_info
.max_latency
);
366 /* Generally, flags should be initialized via pa_source_new(). As
367 * a special exception we allow volume related flags to be set
368 * between _new() and _put(). */
370 if (!(s
->flags
& PA_SOURCE_HW_VOLUME_CTRL
))
371 s
->flags
|= PA_SOURCE_DECIBEL_VOLUME
;
373 s
->thread_info
.soft_volume
= s
->soft_volume
;
374 s
->thread_info
.soft_muted
= s
->muted
;
376 pa_assert((s
->flags
& PA_SOURCE_HW_VOLUME_CTRL
) || (s
->base_volume
== PA_VOLUME_NORM
&& s
->flags
& PA_SOURCE_DECIBEL_VOLUME
));
377 pa_assert(!(s
->flags
& PA_SOURCE_DECIBEL_VOLUME
) || s
->n_volume_steps
== PA_VOLUME_NORM
+1);
378 pa_assert(!(s
->flags
& PA_SOURCE_DYNAMIC_LATENCY
) == (s
->thread_info
.fixed_latency
!= 0));
380 pa_assert_se(source_set_state(s
, PA_SOURCE_IDLE
) == 0);
382 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
| PA_SUBSCRIPTION_EVENT_NEW
, s
->index
);
383 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SOURCE_PUT
], s
);
386 /* Called from main context */
387 void pa_source_unlink(pa_source
*s
) {
389 pa_source_output
*o
, *j
= NULL
;
392 pa_assert_ctl_context();
394 /* See pa_sink_unlink() for a couple of comments how this function
397 linked
= PA_SOURCE_IS_LINKED(s
->state
);
400 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SOURCE_UNLINK
], s
);
402 if (s
->state
!= PA_SOURCE_UNLINKED
)
403 pa_namereg_unregister(s
->core
, s
->name
);
404 pa_idxset_remove_by_data(s
->core
->sources
, s
, NULL
);
407 pa_idxset_remove_by_data(s
->card
->sources
, s
, NULL
);
409 while ((o
= pa_idxset_first(s
->outputs
, NULL
))) {
411 pa_source_output_kill(o
);
416 source_set_state(s
, PA_SOURCE_UNLINKED
);
418 s
->state
= PA_SOURCE_UNLINKED
;
423 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
| PA_SUBSCRIPTION_EVENT_REMOVE
, s
->index
);
424 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SOURCE_UNLINK_POST
], s
);
428 /* Called from main context */
429 static void source_free(pa_object
*o
) {
430 pa_source_output
*so
;
431 pa_source
*s
= PA_SOURCE(o
);
434 pa_assert_ctl_context();
435 pa_assert(pa_source_refcnt(s
) == 0);
437 if (PA_SOURCE_IS_LINKED(s
->state
))
440 pa_log_info("Freeing source %u \"%s\"", s
->index
, s
->name
);
442 pa_idxset_free(s
->outputs
, NULL
, NULL
);
444 while ((so
= pa_hashmap_steal_first(s
->thread_info
.outputs
)))
445 pa_source_output_unref(so
);
447 pa_hashmap_free(s
->thread_info
.outputs
, NULL
, NULL
);
449 if (s
->silence
.memblock
)
450 pa_memblock_unref(s
->silence
.memblock
);
456 pa_proplist_free(s
->proplist
);
461 while ((p
= pa_hashmap_steal_first(s
->ports
)))
462 pa_device_port_free(p
);
464 pa_hashmap_free(s
->ports
, NULL
, NULL
);
470 /* Called from main context, and not while the IO thread is active, please */
471 void pa_source_set_asyncmsgq(pa_source
*s
, pa_asyncmsgq
*q
) {
472 pa_source_assert_ref(s
);
473 pa_assert_ctl_context();
478 /* Called from main context, and not while the IO thread is active, please */
479 void pa_source_update_flags(pa_source
*s
, pa_source_flags_t mask
, pa_source_flags_t value
) {
480 pa_source_assert_ref(s
);
481 pa_assert_ctl_context();
486 /* For now, allow only a minimal set of flags to be changed. */
487 pa_assert((mask
& ~(PA_SOURCE_DYNAMIC_LATENCY
|PA_SOURCE_LATENCY
)) == 0);
489 s
->flags
= (s
->flags
& ~mask
) | (value
& mask
);
492 /* Called from IO context, or before _put() from main context */
493 void pa_source_set_rtpoll(pa_source
*s
, pa_rtpoll
*p
) {
494 pa_source_assert_ref(s
);
495 pa_source_assert_io_context(s
);
497 s
->thread_info
.rtpoll
= p
;
500 /* Called from main context */
501 int pa_source_update_status(pa_source
*s
) {
502 pa_source_assert_ref(s
);
503 pa_assert_ctl_context();
504 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
506 if (s
->state
== PA_SOURCE_SUSPENDED
)
509 return source_set_state(s
, pa_source_used_by(s
) ? PA_SOURCE_RUNNING
: PA_SOURCE_IDLE
);
512 /* Called from main context */
513 int pa_source_suspend(pa_source
*s
, pa_bool_t suspend
, pa_suspend_cause_t cause
) {
514 pa_source_assert_ref(s
);
515 pa_assert_ctl_context();
516 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
517 pa_assert(cause
!= 0);
519 if (s
->monitor_of
&& cause
!= PA_SUSPEND_PASSTHROUGH
)
520 return -PA_ERR_NOTSUPPORTED
;
523 s
->suspend_cause
|= cause
;
525 s
->suspend_cause
&= ~cause
;
527 if ((pa_source_get_state(s
) == PA_SOURCE_SUSPENDED
) == !!s
->suspend_cause
)
530 pa_log_debug("Suspend cause of source %s is 0x%04x, %s", s
->name
, s
->suspend_cause
, s
->suspend_cause
? "suspending" : "resuming");
533 return source_set_state(s
, PA_SOURCE_SUSPENDED
);
535 return source_set_state(s
, pa_source_used_by(s
) ? PA_SOURCE_RUNNING
: PA_SOURCE_IDLE
);
538 /* Called from main context */
539 int pa_source_sync_suspend(pa_source
*s
) {
540 pa_sink_state_t state
;
542 pa_source_assert_ref(s
);
543 pa_assert_ctl_context();
544 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
545 pa_assert(s
->monitor_of
);
547 state
= pa_sink_get_state(s
->monitor_of
);
549 if (state
== PA_SINK_SUSPENDED
)
550 return source_set_state(s
, PA_SOURCE_SUSPENDED
);
552 pa_assert(PA_SINK_IS_OPENED(state
));
554 return source_set_state(s
, pa_source_used_by(s
) ? PA_SOURCE_RUNNING
: PA_SOURCE_IDLE
);
557 /* Called from main context */
558 pa_queue
*pa_source_move_all_start(pa_source
*s
, pa_queue
*q
) {
559 pa_source_output
*o
, *n
;
562 pa_source_assert_ref(s
);
563 pa_assert_ctl_context();
564 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
569 for (o
= PA_SOURCE_OUTPUT(pa_idxset_first(s
->outputs
, &idx
)); o
; o
= n
) {
570 n
= PA_SOURCE_OUTPUT(pa_idxset_next(s
->outputs
, &idx
));
572 pa_source_output_ref(o
);
574 if (pa_source_output_start_move(o
) >= 0)
577 pa_source_output_unref(o
);
583 /* Called from main context */
584 void pa_source_move_all_finish(pa_source
*s
, pa_queue
*q
, pa_bool_t save
) {
587 pa_source_assert_ref(s
);
588 pa_assert_ctl_context();
589 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
592 while ((o
= PA_SOURCE_OUTPUT(pa_queue_pop(q
)))) {
593 if (pa_source_output_finish_move(o
, s
, save
) < 0)
594 pa_source_output_fail_move(o
);
596 pa_source_output_unref(o
);
599 pa_queue_free(q
, NULL
, NULL
);
602 /* Called from main context */
603 void pa_source_move_all_fail(pa_queue
*q
) {
606 pa_assert_ctl_context();
609 while ((o
= PA_SOURCE_OUTPUT(pa_queue_pop(q
)))) {
610 pa_source_output_fail_move(o
);
611 pa_source_output_unref(o
);
614 pa_queue_free(q
, NULL
, NULL
);
617 /* Called from IO thread context */
618 void pa_source_process_rewind(pa_source
*s
, size_t nbytes
) {
622 pa_source_assert_ref(s
);
623 pa_source_assert_io_context(s
);
624 pa_assert(PA_SOURCE_IS_LINKED(s
->thread_info
.state
));
629 if (s
->thread_info
.state
== PA_SOURCE_SUSPENDED
)
632 pa_log_debug("Processing rewind...");
634 PA_HASHMAP_FOREACH(o
, s
->thread_info
.outputs
, state
) {
635 pa_source_output_assert_ref(o
);
636 pa_source_output_process_rewind(o
, nbytes
);
640 /* Called from IO thread context */
641 void pa_source_post(pa_source
*s
, const pa_memchunk
*chunk
) {
645 pa_source_assert_ref(s
);
646 pa_source_assert_io_context(s
);
647 pa_assert(PA_SOURCE_IS_LINKED(s
->thread_info
.state
));
650 if (s
->thread_info
.state
== PA_SOURCE_SUSPENDED
)
653 if (s
->thread_info
.soft_muted
|| !pa_cvolume_is_norm(&s
->thread_info
.soft_volume
)) {
654 pa_memchunk vchunk
= *chunk
;
656 pa_memblock_ref(vchunk
.memblock
);
657 pa_memchunk_make_writable(&vchunk
, 0);
659 if (s
->thread_info
.soft_muted
|| pa_cvolume_is_muted(&s
->thread_info
.soft_volume
))
660 pa_silence_memchunk(&vchunk
, &s
->sample_spec
);
662 pa_volume_memchunk(&vchunk
, &s
->sample_spec
, &s
->thread_info
.soft_volume
);
664 while ((o
= pa_hashmap_iterate(s
->thread_info
.outputs
, &state
, NULL
))) {
665 pa_source_output_assert_ref(o
);
667 if (!o
->thread_info
.direct_on_input
)
668 pa_source_output_push(o
, &vchunk
);
671 pa_memblock_unref(vchunk
.memblock
);
674 while ((o
= pa_hashmap_iterate(s
->thread_info
.outputs
, &state
, NULL
))) {
675 pa_source_output_assert_ref(o
);
677 if (!o
->thread_info
.direct_on_input
)
678 pa_source_output_push(o
, chunk
);
683 /* Called from IO thread context */
684 void pa_source_post_direct(pa_source
*s
, pa_source_output
*o
, const pa_memchunk
*chunk
) {
685 pa_source_assert_ref(s
);
686 pa_source_assert_io_context(s
);
687 pa_assert(PA_SOURCE_IS_LINKED(s
->thread_info
.state
));
688 pa_source_output_assert_ref(o
);
689 pa_assert(o
->thread_info
.direct_on_input
);
692 if (s
->thread_info
.state
== PA_SOURCE_SUSPENDED
)
695 if (s
->thread_info
.soft_muted
|| !pa_cvolume_is_norm(&s
->thread_info
.soft_volume
)) {
696 pa_memchunk vchunk
= *chunk
;
698 pa_memblock_ref(vchunk
.memblock
);
699 pa_memchunk_make_writable(&vchunk
, 0);
701 if (s
->thread_info
.soft_muted
|| pa_cvolume_is_muted(&s
->thread_info
.soft_volume
))
702 pa_silence_memchunk(&vchunk
, &s
->sample_spec
);
704 pa_volume_memchunk(&vchunk
, &s
->sample_spec
, &s
->thread_info
.soft_volume
);
706 pa_source_output_push(o
, &vchunk
);
708 pa_memblock_unref(vchunk
.memblock
);
710 pa_source_output_push(o
, chunk
);
713 /* Called from main thread */
714 pa_usec_t
pa_source_get_latency(pa_source
*s
) {
717 pa_source_assert_ref(s
);
718 pa_assert_ctl_context();
719 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
721 if (s
->state
== PA_SOURCE_SUSPENDED
)
724 if (!(s
->flags
& PA_SOURCE_LATENCY
))
727 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) == 0);
732 /* Called from IO thread */
733 pa_usec_t
pa_source_get_latency_within_thread(pa_source
*s
) {
737 pa_source_assert_ref(s
);
738 pa_source_assert_io_context(s
);
739 pa_assert(PA_SOURCE_IS_LINKED(s
->thread_info
.state
));
741 /* The returned value is supposed to be in the time domain of the sound card! */
743 if (s
->thread_info
.state
== PA_SOURCE_SUSPENDED
)
746 if (!(s
->flags
& PA_SOURCE_LATENCY
))
751 /* We probably should make this a proper vtable callback instead of going through process_msg() */
753 if (o
->process_msg(o
, PA_SOURCE_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) < 0)
759 /* Called from main context */
760 pa_bool_t
pa_source_is_passthrough(pa_source
*s
) {
762 pa_source_assert_ref(s
);
764 /* NB Currently only monitor sources support passthrough mode */
765 return (s
->monitor_of
&& pa_sink_is_passthrough(s
->monitor_of
));
768 /* Called from main thread */
769 void pa_source_set_volume(
771 const pa_cvolume
*volume
,
774 pa_bool_t real_changed
;
775 pa_cvolume old_volume
;
777 pa_source_assert_ref(s
);
778 pa_assert_ctl_context();
779 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
780 pa_assert(pa_cvolume_valid(volume
));
781 pa_assert(volume
->channels
== 1 || pa_cvolume_compatible(volume
, &s
->sample_spec
));
783 old_volume
= s
->volume
;
785 if (pa_cvolume_compatible(volume
, &s
->sample_spec
))
788 pa_cvolume_scale(&s
->volume
, pa_cvolume_max(volume
));
790 real_changed
= !pa_cvolume_equal(&old_volume
, &s
->volume
);
791 s
->save_volume
= (!real_changed
&& s
->save_volume
) || save
;
794 pa_cvolume_reset(&s
->soft_volume
, s
->sample_spec
.channels
);
797 s
->soft_volume
= s
->volume
;
799 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
) == 0);
802 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
805 /* Called from main thread. Only to be called by source implementor */
806 void pa_source_set_soft_volume(pa_source
*s
, const pa_cvolume
*volume
) {
807 pa_source_assert_ref(s
);
808 pa_assert_ctl_context();
811 pa_cvolume_reset(&s
->soft_volume
, s
->sample_spec
.channels
);
813 s
->soft_volume
= *volume
;
815 if (PA_SOURCE_IS_LINKED(s
->state
))
816 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
) == 0);
818 s
->thread_info
.soft_volume
= s
->soft_volume
;
821 /* Called from main thread */
822 const pa_cvolume
*pa_source_get_volume(pa_source
*s
, pa_bool_t force_refresh
) {
823 pa_source_assert_ref(s
);
824 pa_assert_ctl_context();
825 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
827 if (s
->refresh_volume
|| force_refresh
) {
828 pa_cvolume old_volume
;
830 old_volume
= s
->volume
;
835 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_GET_VOLUME
, NULL
, 0, NULL
) == 0);
837 if (!pa_cvolume_equal(&old_volume
, &s
->volume
)) {
838 s
->save_volume
= TRUE
;
839 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
846 /* Called from main thread */
847 void pa_source_volume_changed(pa_source
*s
, const pa_cvolume
*new_volume
) {
848 pa_source_assert_ref(s
);
849 pa_assert_ctl_context();
850 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
852 /* The source implementor may call this if the volume changed to make sure everyone is notified */
854 if (pa_cvolume_equal(&s
->volume
, new_volume
))
857 s
->volume
= *new_volume
;
858 s
->save_volume
= TRUE
;
860 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
863 /* Called from main thread */
864 void pa_source_set_mute(pa_source
*s
, pa_bool_t mute
, pa_bool_t save
) {
867 pa_source_assert_ref(s
);
868 pa_assert_ctl_context();
869 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
871 old_muted
= s
->muted
;
873 s
->save_muted
= (old_muted
== s
->muted
&& s
->save_muted
) || save
;
878 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_SET_MUTE
, NULL
, 0, NULL
) == 0);
880 if (old_muted
!= s
->muted
)
881 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
884 /* Called from main thread */
885 pa_bool_t
pa_source_get_mute(pa_source
*s
, pa_bool_t force_refresh
) {
886 pa_source_assert_ref(s
);
887 pa_assert_ctl_context();
888 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
890 if (s
->refresh_muted
|| force_refresh
) {
891 pa_bool_t old_muted
= s
->muted
;
896 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_GET_MUTE
, NULL
, 0, NULL
) == 0);
898 if (old_muted
!= s
->muted
) {
899 s
->save_muted
= TRUE
;
901 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
903 /* Make sure the soft mute status stays in sync */
904 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_SET_MUTE
, NULL
, 0, NULL
) == 0);
911 /* Called from main thread */
912 void pa_source_mute_changed(pa_source
*s
, pa_bool_t new_muted
) {
913 pa_source_assert_ref(s
);
914 pa_assert_ctl_context();
915 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
917 /* The source implementor may call this if the mute state changed to make sure everyone is notified */
919 if (s
->muted
== new_muted
)
922 s
->muted
= new_muted
;
923 s
->save_muted
= TRUE
;
925 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
928 /* Called from main thread */
929 pa_bool_t
pa_source_update_proplist(pa_source
*s
, pa_update_mode_t mode
, pa_proplist
*p
) {
930 pa_source_assert_ref(s
);
931 pa_assert_ctl_context();
934 pa_proplist_update(s
->proplist
, mode
, p
);
936 if (PA_SOURCE_IS_LINKED(s
->state
)) {
937 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED
], s
);
938 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
944 /* Called from main thread */
945 /* FIXME -- this should be dropped and be merged into pa_source_update_proplist() */
946 void pa_source_set_description(pa_source
*s
, const char *description
) {
948 pa_source_assert_ref(s
);
949 pa_assert_ctl_context();
951 if (!description
&& !pa_proplist_contains(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
))
954 old
= pa_proplist_gets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
956 if (old
&& description
&& pa_streq(old
, description
))
960 pa_proplist_sets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
, description
);
962 pa_proplist_unset(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
964 if (PA_SOURCE_IS_LINKED(s
->state
)) {
965 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
966 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED
], s
);
970 /* Called from main thread */
971 unsigned pa_source_linked_by(pa_source
*s
) {
972 pa_source_assert_ref(s
);
973 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
974 pa_assert_ctl_context();
976 return pa_idxset_size(s
->outputs
);
979 /* Called from main thread */
980 unsigned pa_source_used_by(pa_source
*s
) {
983 pa_source_assert_ref(s
);
984 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
985 pa_assert_ctl_context();
987 ret
= pa_idxset_size(s
->outputs
);
988 pa_assert(ret
>= s
->n_corked
);
990 return ret
- s
->n_corked
;
993 /* Called from main thread */
994 unsigned pa_source_check_suspend(pa_source
*s
) {
999 pa_source_assert_ref(s
);
1000 pa_assert_ctl_context();
1002 if (!PA_SOURCE_IS_LINKED(s
->state
))
1007 PA_IDXSET_FOREACH(o
, s
->outputs
, idx
) {
1008 pa_source_output_state_t st
;
1010 st
= pa_source_output_get_state(o
);
1012 /* We do not assert here. It is perfectly valid for a source output to
1013 * be in the INIT state (i.e. created, marked done but not yet put)
1014 * and we should not care if it's unlinked as it won't contribute
1015 * towarards our busy status.
1017 if (!PA_SOURCE_OUTPUT_IS_LINKED(st
))
1020 if (st
== PA_SOURCE_OUTPUT_CORKED
)
1023 if (o
->flags
& PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND
)
1032 /* Called from IO thread, except when it is not */
1033 int pa_source_process_msg(pa_msgobject
*object
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1034 pa_source
*s
= PA_SOURCE(object
);
1035 pa_source_assert_ref(s
);
1037 switch ((pa_source_message_t
) code
) {
1039 case PA_SOURCE_MESSAGE_ADD_OUTPUT
: {
1040 pa_source_output
*o
= PA_SOURCE_OUTPUT(userdata
);
1042 pa_hashmap_put(s
->thread_info
.outputs
, PA_UINT32_TO_PTR(o
->index
), pa_source_output_ref(o
));
1044 if (o
->direct_on_input
) {
1045 o
->thread_info
.direct_on_input
= o
->direct_on_input
;
1046 pa_hashmap_put(o
->thread_info
.direct_on_input
->thread_info
.direct_outputs
, PA_UINT32_TO_PTR(o
->index
), o
);
1049 pa_assert(!o
->thread_info
.attached
);
1050 o
->thread_info
.attached
= TRUE
;
1055 pa_source_output_set_state_within_thread(o
, o
->state
);
1057 if (o
->thread_info
.requested_source_latency
!= (pa_usec_t
) -1)
1058 pa_source_output_set_requested_latency_within_thread(o
, o
->thread_info
.requested_source_latency
);
1060 pa_source_output_update_max_rewind(o
, s
->thread_info
.max_rewind
);
1062 /* We don't just invalidate the requested latency here,
1063 * because if we are in a move we might need to fix up the
1064 * requested latency. */
1065 pa_source_output_set_requested_latency_within_thread(o
, o
->thread_info
.requested_source_latency
);
1070 case PA_SOURCE_MESSAGE_REMOVE_OUTPUT
: {
1071 pa_source_output
*o
= PA_SOURCE_OUTPUT(userdata
);
1073 pa_source_output_set_state_within_thread(o
, o
->state
);
1078 pa_assert(o
->thread_info
.attached
);
1079 o
->thread_info
.attached
= FALSE
;
1081 if (o
->thread_info
.direct_on_input
) {
1082 pa_hashmap_remove(o
->thread_info
.direct_on_input
->thread_info
.direct_outputs
, PA_UINT32_TO_PTR(o
->index
));
1083 o
->thread_info
.direct_on_input
= NULL
;
1086 if (pa_hashmap_remove(s
->thread_info
.outputs
, PA_UINT32_TO_PTR(o
->index
)))
1087 pa_source_output_unref(o
);
1089 pa_source_invalidate_requested_latency(s
, TRUE
);
1094 case PA_SOURCE_MESSAGE_SET_VOLUME
:
1095 s
->thread_info
.soft_volume
= s
->soft_volume
;
1098 case PA_SOURCE_MESSAGE_GET_VOLUME
:
1101 case PA_SOURCE_MESSAGE_SET_MUTE
:
1102 s
->thread_info
.soft_muted
= s
->muted
;
1105 case PA_SOURCE_MESSAGE_GET_MUTE
:
1108 case PA_SOURCE_MESSAGE_SET_STATE
: {
1110 pa_bool_t suspend_change
=
1111 (s
->thread_info
.state
== PA_SOURCE_SUSPENDED
&& PA_SOURCE_IS_OPENED(PA_PTR_TO_UINT(userdata
))) ||
1112 (PA_SOURCE_IS_OPENED(s
->thread_info
.state
) && PA_PTR_TO_UINT(userdata
) == PA_SOURCE_SUSPENDED
);
1114 s
->thread_info
.state
= PA_PTR_TO_UINT(userdata
);
1116 if (suspend_change
) {
1117 pa_source_output
*o
;
1120 while ((o
= pa_hashmap_iterate(s
->thread_info
.outputs
, &state
, NULL
)))
1121 if (o
->suspend_within_thread
)
1122 o
->suspend_within_thread(o
, s
->thread_info
.state
== PA_SOURCE_SUSPENDED
);
1129 case PA_SOURCE_MESSAGE_DETACH
:
1131 /* Detach all streams */
1132 pa_source_detach_within_thread(s
);
1135 case PA_SOURCE_MESSAGE_ATTACH
:
1137 /* Reattach all streams */
1138 pa_source_attach_within_thread(s
);
1141 case PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY
: {
1143 pa_usec_t
*usec
= userdata
;
1144 *usec
= pa_source_get_requested_latency_within_thread(s
);
1146 if (*usec
== (pa_usec_t
) -1)
1147 *usec
= s
->thread_info
.max_latency
;
1152 case PA_SOURCE_MESSAGE_SET_LATENCY_RANGE
: {
1153 pa_usec_t
*r
= userdata
;
1155 pa_source_set_latency_range_within_thread(s
, r
[0], r
[1]);
1160 case PA_SOURCE_MESSAGE_GET_LATENCY_RANGE
: {
1161 pa_usec_t
*r
= userdata
;
1163 r
[0] = s
->thread_info
.min_latency
;
1164 r
[1] = s
->thread_info
.max_latency
;
1169 case PA_SOURCE_MESSAGE_GET_FIXED_LATENCY
:
1171 *((pa_usec_t
*) userdata
) = s
->thread_info
.fixed_latency
;
1174 case PA_SOURCE_MESSAGE_SET_FIXED_LATENCY
:
1176 pa_source_set_fixed_latency_within_thread(s
, (pa_usec_t
) offset
);
1179 case PA_SOURCE_MESSAGE_GET_MAX_REWIND
:
1181 *((size_t*) userdata
) = s
->thread_info
.max_rewind
;
1184 case PA_SOURCE_MESSAGE_SET_MAX_REWIND
:
1186 pa_source_set_max_rewind_within_thread(s
, (size_t) offset
);
1189 case PA_SOURCE_MESSAGE_GET_LATENCY
:
1191 if (s
->monitor_of
) {
1192 *((pa_usec_t
*) userdata
) = 0;
1196 /* Implementors need to overwrite this implementation! */
1199 case PA_SOURCE_MESSAGE_MAX
:
1206 /* Called from main thread */
1207 int pa_source_suspend_all(pa_core
*c
, pa_bool_t suspend
, pa_suspend_cause_t cause
) {
1212 pa_core_assert_ref(c
);
1213 pa_assert_ctl_context();
1214 pa_assert(cause
!= 0);
1216 for (source
= PA_SOURCE(pa_idxset_first(c
->sources
, &idx
)); source
; source
= PA_SOURCE(pa_idxset_next(c
->sources
, &idx
))) {
1219 if (source
->monitor_of
)
1222 if ((r
= pa_source_suspend(source
, suspend
, cause
)) < 0)
1229 /* Called from main thread */
1230 void pa_source_detach(pa_source
*s
) {
1231 pa_source_assert_ref(s
);
1232 pa_assert_ctl_context();
1233 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
1235 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_DETACH
, NULL
, 0, NULL
) == 0);
1238 /* Called from main thread */
1239 void pa_source_attach(pa_source
*s
) {
1240 pa_source_assert_ref(s
);
1241 pa_assert_ctl_context();
1242 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
1244 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_ATTACH
, NULL
, 0, NULL
) == 0);
1247 /* Called from IO thread */
1248 void pa_source_detach_within_thread(pa_source
*s
) {
1249 pa_source_output
*o
;
1252 pa_source_assert_ref(s
);
1253 pa_source_assert_io_context(s
);
1254 pa_assert(PA_SOURCE_IS_LINKED(s
->thread_info
.state
));
1256 PA_HASHMAP_FOREACH(o
, s
->thread_info
.outputs
, state
)
1261 /* Called from IO thread */
1262 void pa_source_attach_within_thread(pa_source
*s
) {
1263 pa_source_output
*o
;
1266 pa_source_assert_ref(s
);
1267 pa_source_assert_io_context(s
);
1268 pa_assert(PA_SOURCE_IS_LINKED(s
->thread_info
.state
));
1270 PA_HASHMAP_FOREACH(o
, s
->thread_info
.outputs
, state
)
1275 /* Called from IO thread */
1276 pa_usec_t
pa_source_get_requested_latency_within_thread(pa_source
*s
) {
1277 pa_usec_t result
= (pa_usec_t
) -1;
1278 pa_source_output
*o
;
1281 pa_source_assert_ref(s
);
1282 pa_source_assert_io_context(s
);
1284 if (!(s
->flags
& PA_SOURCE_DYNAMIC_LATENCY
))
1285 return PA_CLAMP(s
->thread_info
.fixed_latency
, s
->thread_info
.min_latency
, s
->thread_info
.max_latency
);
1287 if (s
->thread_info
.requested_latency_valid
)
1288 return s
->thread_info
.requested_latency
;
1290 PA_HASHMAP_FOREACH(o
, s
->thread_info
.outputs
, state
)
1291 if (o
->thread_info
.requested_source_latency
!= (pa_usec_t
) -1 &&
1292 (result
== (pa_usec_t
) -1 || result
> o
->thread_info
.requested_source_latency
))
1293 result
= o
->thread_info
.requested_source_latency
;
1295 if (result
!= (pa_usec_t
) -1)
1296 result
= PA_CLAMP(result
, s
->thread_info
.min_latency
, s
->thread_info
.max_latency
);
1298 if (PA_SOURCE_IS_LINKED(s
->thread_info
.state
)) {
1299 /* Only cache this if we are fully set up */
1300 s
->thread_info
.requested_latency
= result
;
1301 s
->thread_info
.requested_latency_valid
= TRUE
;
1307 /* Called from main thread */
1308 pa_usec_t
pa_source_get_requested_latency(pa_source
*s
) {
1311 pa_source_assert_ref(s
);
1312 pa_assert_ctl_context();
1313 pa_assert(PA_SOURCE_IS_LINKED(s
->state
));
1315 if (s
->state
== PA_SOURCE_SUSPENDED
)
1318 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY
, &usec
, 0, NULL
) == 0);
1323 /* Called from IO thread */
1324 void pa_source_set_max_rewind_within_thread(pa_source
*s
, size_t max_rewind
) {
1325 pa_source_output
*o
;
1328 pa_source_assert_ref(s
);
1329 pa_source_assert_io_context(s
);
1331 if (max_rewind
== s
->thread_info
.max_rewind
)
1334 s
->thread_info
.max_rewind
= max_rewind
;
1336 if (PA_SOURCE_IS_LINKED(s
->thread_info
.state
))
1337 PA_HASHMAP_FOREACH(o
, s
->thread_info
.outputs
, state
)
1338 pa_source_output_update_max_rewind(o
, s
->thread_info
.max_rewind
);
1341 /* Called from main thread */
1342 void pa_source_set_max_rewind(pa_source
*s
, size_t max_rewind
) {
1343 pa_source_assert_ref(s
);
1344 pa_assert_ctl_context();
1346 if (PA_SOURCE_IS_LINKED(s
->state
))
1347 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_SET_MAX_REWIND
, NULL
, max_rewind
, NULL
) == 0);
1349 pa_source_set_max_rewind_within_thread(s
, max_rewind
);
1352 /* Called from IO thread */
1353 void pa_source_invalidate_requested_latency(pa_source
*s
, pa_bool_t dynamic
) {
1354 pa_source_output
*o
;
1357 pa_source_assert_ref(s
);
1358 pa_source_assert_io_context(s
);
1360 if ((s
->flags
& PA_SOURCE_DYNAMIC_LATENCY
))
1361 s
->thread_info
.requested_latency_valid
= FALSE
;
1365 if (PA_SOURCE_IS_LINKED(s
->thread_info
.state
)) {
1367 if (s
->update_requested_latency
)
1368 s
->update_requested_latency(s
);
1370 while ((o
= pa_hashmap_iterate(s
->thread_info
.outputs
, &state
, NULL
)))
1371 if (o
->update_source_requested_latency
)
1372 o
->update_source_requested_latency(o
);
1376 pa_sink_invalidate_requested_latency(s
->monitor_of
, dynamic
);
1379 /* Called from main thread */
1380 void pa_source_set_latency_range(pa_source
*s
, pa_usec_t min_latency
, pa_usec_t max_latency
) {
1381 pa_source_assert_ref(s
);
1382 pa_assert_ctl_context();
1384 /* min_latency == 0: no limit
1385 * min_latency anything else: specified limit
1387 * Similar for max_latency */
1389 if (min_latency
< ABSOLUTE_MIN_LATENCY
)
1390 min_latency
= ABSOLUTE_MIN_LATENCY
;
1392 if (max_latency
<= 0 ||
1393 max_latency
> ABSOLUTE_MAX_LATENCY
)
1394 max_latency
= ABSOLUTE_MAX_LATENCY
;
1396 pa_assert(min_latency
<= max_latency
);
1398 /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1399 pa_assert((min_latency
== ABSOLUTE_MIN_LATENCY
&&
1400 max_latency
== ABSOLUTE_MAX_LATENCY
) ||
1401 (s
->flags
& PA_SOURCE_DYNAMIC_LATENCY
));
1403 if (PA_SOURCE_IS_LINKED(s
->state
)) {
1409 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_SET_LATENCY_RANGE
, r
, 0, NULL
) == 0);
1411 pa_source_set_latency_range_within_thread(s
, min_latency
, max_latency
);
1414 /* Called from main thread */
1415 void pa_source_get_latency_range(pa_source
*s
, pa_usec_t
*min_latency
, pa_usec_t
*max_latency
) {
1416 pa_source_assert_ref(s
);
1417 pa_assert_ctl_context();
1418 pa_assert(min_latency
);
1419 pa_assert(max_latency
);
1421 if (PA_SOURCE_IS_LINKED(s
->state
)) {
1422 pa_usec_t r
[2] = { 0, 0 };
1424 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_GET_LATENCY_RANGE
, r
, 0, NULL
) == 0);
1426 *min_latency
= r
[0];
1427 *max_latency
= r
[1];
1429 *min_latency
= s
->thread_info
.min_latency
;
1430 *max_latency
= s
->thread_info
.max_latency
;
1434 /* Called from IO thread, and from main thread before pa_source_put() is called */
1435 void pa_source_set_latency_range_within_thread(pa_source
*s
, pa_usec_t min_latency
, pa_usec_t max_latency
) {
1436 pa_source_assert_ref(s
);
1437 pa_source_assert_io_context(s
);
1439 pa_assert(min_latency
>= ABSOLUTE_MIN_LATENCY
);
1440 pa_assert(max_latency
<= ABSOLUTE_MAX_LATENCY
);
1441 pa_assert(min_latency
<= max_latency
);
1443 /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1444 pa_assert((min_latency
== ABSOLUTE_MIN_LATENCY
&&
1445 max_latency
== ABSOLUTE_MAX_LATENCY
) ||
1446 (s
->flags
& PA_SOURCE_DYNAMIC_LATENCY
) ||
1449 if (s
->thread_info
.min_latency
== min_latency
&&
1450 s
->thread_info
.max_latency
== max_latency
)
1453 s
->thread_info
.min_latency
= min_latency
;
1454 s
->thread_info
.max_latency
= max_latency
;
1456 if (PA_SOURCE_IS_LINKED(s
->thread_info
.state
)) {
1457 pa_source_output
*o
;
1460 PA_HASHMAP_FOREACH(o
, s
->thread_info
.outputs
, state
)
1461 if (o
->update_source_latency_range
)
1462 o
->update_source_latency_range(o
);
1465 pa_source_invalidate_requested_latency(s
, FALSE
);
1468 /* Called from main thread, before the source is put */
1469 void pa_source_set_fixed_latency(pa_source
*s
, pa_usec_t latency
) {
1470 pa_source_assert_ref(s
);
1471 pa_assert_ctl_context();
1473 if (s
->flags
& PA_SOURCE_DYNAMIC_LATENCY
) {
1474 pa_assert(latency
== 0);
1478 if (latency
< ABSOLUTE_MIN_LATENCY
)
1479 latency
= ABSOLUTE_MIN_LATENCY
;
1481 if (latency
> ABSOLUTE_MAX_LATENCY
)
1482 latency
= ABSOLUTE_MAX_LATENCY
;
1484 if (PA_SOURCE_IS_LINKED(s
->state
))
1485 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_SET_FIXED_LATENCY
, NULL
, (int64_t) latency
, NULL
) == 0);
1487 s
->thread_info
.fixed_latency
= latency
;
1490 /* Called from main thread */
1491 pa_usec_t
pa_source_get_fixed_latency(pa_source
*s
) {
1494 pa_source_assert_ref(s
);
1495 pa_assert_ctl_context();
1497 if (s
->flags
& PA_SOURCE_DYNAMIC_LATENCY
)
1500 if (PA_SOURCE_IS_LINKED(s
->state
))
1501 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_GET_FIXED_LATENCY
, &latency
, 0, NULL
) == 0);
1503 latency
= s
->thread_info
.fixed_latency
;
1508 /* Called from IO thread */
1509 void pa_source_set_fixed_latency_within_thread(pa_source
*s
, pa_usec_t latency
) {
1510 pa_source_assert_ref(s
);
1511 pa_source_assert_io_context(s
);
1513 if (s
->flags
& PA_SOURCE_DYNAMIC_LATENCY
) {
1514 pa_assert(latency
== 0);
1518 pa_assert(latency
>= ABSOLUTE_MIN_LATENCY
);
1519 pa_assert(latency
<= ABSOLUTE_MAX_LATENCY
);
1521 if (s
->thread_info
.fixed_latency
== latency
)
1524 s
->thread_info
.fixed_latency
= latency
;
1526 if (PA_SOURCE_IS_LINKED(s
->thread_info
.state
)) {
1527 pa_source_output
*o
;
1530 PA_HASHMAP_FOREACH(o
, s
->thread_info
.outputs
, state
)
1531 if (o
->update_source_fixed_latency
)
1532 o
->update_source_fixed_latency(o
);
1535 pa_source_invalidate_requested_latency(s
, FALSE
);
1538 /* Called from main thread */
1539 size_t pa_source_get_max_rewind(pa_source
*s
) {
1541 pa_assert_ctl_context();
1542 pa_source_assert_ref(s
);
1544 if (!PA_SOURCE_IS_LINKED(s
->state
))
1545 return s
->thread_info
.max_rewind
;
1547 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SOURCE_MESSAGE_GET_MAX_REWIND
, &r
, 0, NULL
) == 0);
1552 /* Called from main context */
1553 int pa_source_set_port(pa_source
*s
, const char *name
, pa_bool_t save
) {
1554 pa_device_port
*port
;
1557 pa_assert_ctl_context();
1560 pa_log_debug("set_port() operation not implemented for source %u \"%s\"", s
->index
, s
->name
);
1561 return -PA_ERR_NOTIMPLEMENTED
;
1565 return -PA_ERR_NOENTITY
;
1567 if (!(port
= pa_hashmap_get(s
->ports
, name
)))
1568 return -PA_ERR_NOENTITY
;
1570 if (s
->active_port
== port
) {
1571 s
->save_port
= s
->save_port
|| save
;
1575 if ((s
->set_port(s
, port
)) < 0)
1576 return -PA_ERR_NOENTITY
;
1578 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SOURCE
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1580 pa_log_info("Changed port of source %u \"%s\" to %s", s
->index
, s
->name
, port
->name
);
1582 s
->active_port
= port
;
1583 s
->save_port
= save
;
1585 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SOURCE_PORT_CHANGED
], s
);
1590 /* Called from the main thread */
1591 /* Gets the list of formats supported by the source. The members and idxset must
1592 * be freed by the caller. */
1593 pa_idxset
* pa_source_get_formats(pa_source
*s
) {
1598 if (s
->get_formats
) {
1599 /* Source supports format query, all is good */
1600 ret
= s
->get_formats(s
);
1602 /* Source doesn't support format query, so assume it does PCM */
1603 pa_format_info
*f
= pa_format_info_new();
1604 f
->encoding
= PA_ENCODING_PCM
;
1606 ret
= pa_idxset_new(NULL
, NULL
);
1607 pa_idxset_put(ret
, f
, NULL
);
1613 /* Called from the main thread */
1614 /* Checks if the source can accept this format */
1615 pa_bool_t
pa_source_check_format(pa_source
*s
, pa_format_info
*f
)
1617 pa_idxset
*formats
= NULL
;
1618 pa_bool_t ret
= FALSE
;
1623 formats
= pa_source_get_formats(s
);
1626 pa_format_info
*finfo_device
;
1629 PA_IDXSET_FOREACH(finfo_device
, formats
, i
) {
1630 if (pa_format_info_is_compatible(finfo_device
, f
)) {
1636 pa_idxset_free(formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);
1642 /* Called from the main thread */
1643 /* Calculates the intersection between formats supported by the source and
1644 * in_formats, and returns these, in the order of the source's formats. */
1645 pa_idxset
* pa_source_check_formats(pa_source
*s
, pa_idxset
*in_formats
) {
1646 pa_idxset
*out_formats
= pa_idxset_new(NULL
, NULL
), *source_formats
= NULL
;
1647 pa_format_info
*f_source
, *f_in
;
1652 if (!in_formats
|| pa_idxset_isempty(in_formats
))
1655 source_formats
= pa_source_get_formats(s
);
1657 PA_IDXSET_FOREACH(f_source
, source_formats
, i
) {
1658 PA_IDXSET_FOREACH(f_in
, in_formats
, j
) {
1659 if (pa_format_info_is_compatible(f_source
, f_in
))
1660 pa_idxset_put(out_formats
, pa_format_info_copy(f_in
), NULL
);
1666 pa_idxset_free(source_formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);