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/introspect.h>
32 #include <pulse/utf8.h>
33 #include <pulse/xmalloc.h>
34 #include <pulse/timeval.h>
35 #include <pulse/util.h>
36 #include <pulse/i18n.h>
38 #include <pulsecore/sink-input.h>
39 #include <pulsecore/namereg.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/sample-util.h>
42 #include <pulsecore/core-subscribe.h>
43 #include <pulsecore/log.h>
44 #include <pulsecore/macro.h>
45 #include <pulsecore/play-memblockq.h>
49 #define MAX_MIX_CHANNELS 32
50 #define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
51 #define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
53 static PA_DEFINE_CHECK_TYPE(pa_sink
, pa_msgobject
);
55 static void sink_free(pa_object
*s
);
57 pa_sink_new_data
* pa_sink_new_data_init(pa_sink_new_data
*data
) {
60 memset(data
, 0, sizeof(*data
));
61 data
->proplist
= pa_proplist_new();
66 void pa_sink_new_data_set_name(pa_sink_new_data
*data
, const char *name
) {
70 data
->name
= pa_xstrdup(name
);
73 void pa_sink_new_data_set_sample_spec(pa_sink_new_data
*data
, const pa_sample_spec
*spec
) {
76 if ((data
->sample_spec_is_set
= !!spec
))
77 data
->sample_spec
= *spec
;
80 void pa_sink_new_data_set_channel_map(pa_sink_new_data
*data
, const pa_channel_map
*map
) {
83 if ((data
->channel_map_is_set
= !!map
))
84 data
->channel_map
= *map
;
87 void pa_sink_new_data_set_volume(pa_sink_new_data
*data
, const pa_cvolume
*volume
) {
90 if ((data
->volume_is_set
= !!volume
))
91 data
->volume
= *volume
;
94 void pa_sink_new_data_set_muted(pa_sink_new_data
*data
, pa_bool_t mute
) {
97 data
->muted_is_set
= TRUE
;
101 void pa_sink_new_data_done(pa_sink_new_data
*data
) {
104 pa_xfree(data
->name
);
105 pa_proplist_free(data
->proplist
);
108 /* Called from main context */
109 static void reset_callbacks(pa_sink
*s
) {
113 s
->get_volume
= NULL
;
114 s
->set_volume
= NULL
;
117 s
->request_rewind
= NULL
;
118 s
->update_requested_latency
= NULL
;
121 /* Called from main context */
122 pa_sink
* pa_sink_new(
124 pa_sink_new_data
*data
,
125 pa_sink_flags_t flags
) {
129 char st
[PA_SAMPLE_SPEC_SNPRINT_MAX
], cm
[PA_CHANNEL_MAP_SNPRINT_MAX
];
130 pa_source_new_data source_data
;
136 pa_assert(data
->name
);
138 s
= pa_msgobject_new(pa_sink
);
140 if (!(name
= pa_namereg_register(core
, data
->name
, PA_NAMEREG_SINK
, s
, data
->namereg_fail
))) {
145 pa_sink_new_data_set_name(data
, name
);
147 if (pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SINK_NEW
], data
) < 0) {
149 pa_namereg_unregister(core
, name
);
153 pa_return_null_if_fail(!data
->driver
|| pa_utf8_valid(data
->driver
));
154 pa_return_null_if_fail(data
->name
&& pa_utf8_valid(data
->name
) && data
->name
[0]);
156 pa_return_null_if_fail(data
->sample_spec_is_set
&& pa_sample_spec_valid(&data
->sample_spec
));
158 if (!data
->channel_map_is_set
)
159 pa_return_null_if_fail(pa_channel_map_init_auto(&data
->channel_map
, data
->sample_spec
.channels
, PA_CHANNEL_MAP_DEFAULT
));
161 pa_return_null_if_fail(pa_channel_map_valid(&data
->channel_map
));
162 pa_return_null_if_fail(data
->channel_map
.channels
== data
->sample_spec
.channels
);
164 if (!data
->volume_is_set
)
165 pa_cvolume_reset(&data
->volume
, data
->sample_spec
.channels
);
167 pa_return_null_if_fail(pa_cvolume_valid(&data
->volume
));
168 pa_return_null_if_fail(data
->volume
.channels
== data
->sample_spec
.channels
);
170 if (!data
->muted_is_set
)
174 pa_proplist_update(data
->proplist
, PA_UPDATE_MERGE
, data
->card
->proplist
);
176 pa_device_init_description(data
->proplist
);
177 pa_device_init_icon(data
->proplist
, TRUE
);
179 if (pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SINK_FIXATE
], data
) < 0) {
181 pa_namereg_unregister(core
, name
);
185 s
->parent
.parent
.free
= sink_free
;
186 s
->parent
.process_msg
= pa_sink_process_msg
;
189 s
->state
= PA_SINK_INIT
;
191 s
->name
= pa_xstrdup(name
);
192 s
->proplist
= pa_proplist_copy(data
->proplist
);
193 s
->driver
= pa_xstrdup(pa_path_get_filename(data
->driver
));
194 s
->module
= data
->module
;
195 s
->card
= data
->card
;
197 s
->sample_spec
= data
->sample_spec
;
198 s
->channel_map
= data
->channel_map
;
200 s
->inputs
= pa_idxset_new(NULL
, NULL
);
203 s
->virtual_volume
= data
->volume
;
204 pa_cvolume_reset(&s
->soft_volume
, s
->sample_spec
.channels
);
205 s
->base_volume
= PA_VOLUME_NORM
;
206 s
->n_volume_steps
= PA_VOLUME_NORM
+1;
207 s
->muted
= data
->muted
;
208 s
->refresh_volume
= s
->refresh_muted
= FALSE
;
216 pa_silence_memchunk_get(
217 &core
->silence_cache
,
223 s
->thread_info
.inputs
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
224 s
->thread_info
.soft_volume
= s
->soft_volume
;
225 s
->thread_info
.soft_muted
= s
->muted
;
226 s
->thread_info
.state
= s
->state
;
227 s
->thread_info
.rewind_nbytes
= 0;
228 s
->thread_info
.rewind_requested
= FALSE
;
229 s
->thread_info
.max_rewind
= 0;
230 s
->thread_info
.max_request
= 0;
231 s
->thread_info
.requested_latency_valid
= FALSE
;
232 s
->thread_info
.requested_latency
= 0;
233 s
->thread_info
.min_latency
= DEFAULT_MIN_LATENCY
;
234 s
->thread_info
.max_latency
= 0;
236 pa_assert_se(pa_idxset_put(core
->sinks
, s
, &s
->index
) >= 0);
239 pa_assert_se(pa_idxset_put(s
->card
->sinks
, s
, NULL
) >= 0);
241 pt
= pa_proplist_to_string_sep(s
->proplist
, "\n ");
242 pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s\n %s",
245 pa_sample_spec_snprint(st
, sizeof(st
), &s
->sample_spec
),
246 pa_channel_map_snprint(cm
, sizeof(cm
), &s
->channel_map
),
250 pa_source_new_data_init(&source_data
);
251 pa_source_new_data_set_sample_spec(&source_data
, &s
->sample_spec
);
252 pa_source_new_data_set_channel_map(&source_data
, &s
->channel_map
);
253 source_data
.name
= pa_sprintf_malloc("%s.monitor", name
);
254 source_data
.driver
= data
->driver
;
255 source_data
.module
= data
->module
;
256 source_data
.card
= data
->card
;
258 dn
= pa_proplist_gets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
259 pa_proplist_setf(source_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "Monitor of %s", dn
? dn
: s
->name
);
260 pa_proplist_sets(source_data
.proplist
, PA_PROP_DEVICE_CLASS
, "monitor");
262 s
->monitor_source
= pa_source_new(core
, &source_data
, PA_SOURCE_LATENCY
);
264 pa_source_new_data_done(&source_data
);
266 if (!s
->monitor_source
) {
272 s
->monitor_source
->monitor_of
= s
;
274 pa_source_set_latency_range(s
->monitor_source
, s
->thread_info
.min_latency
, s
->thread_info
.max_latency
);
275 pa_source_set_max_rewind(s
->monitor_source
, s
->thread_info
.max_rewind
);
280 /* Called from main context */
281 static int sink_set_state(pa_sink
*s
, pa_sink_state_t state
) {
283 pa_bool_t suspend_change
;
284 pa_sink_state_t original_state
;
288 if (s
->state
== state
)
291 original_state
= s
->state
;
294 (original_state
== PA_SINK_SUSPENDED
&& PA_SINK_IS_OPENED(state
)) ||
295 (PA_SINK_IS_OPENED(original_state
) && state
== PA_SINK_SUSPENDED
);
298 if ((ret
= s
->set_state(s
, state
)) < 0)
302 if ((ret
= pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_STATE
, PA_UINT_TO_PTR(state
), 0, NULL
)) < 0) {
305 s
->set_state(s
, original_state
);
312 if (state
!= PA_SINK_UNLINKED
) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
313 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_STATE_CHANGED
], s
);
314 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
| PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
317 if (suspend_change
) {
321 /* We're suspending or resuming, tell everyone about it */
323 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
)))
324 if (s
->state
== PA_SINK_SUSPENDED
&&
325 (i
->flags
& PA_SINK_INPUT_FAIL_ON_SUSPEND
))
326 pa_sink_input_kill(i
);
328 i
->suspend(i
, state
== PA_SINK_SUSPENDED
);
334 /* Called from main context */
335 void pa_sink_put(pa_sink
* s
) {
336 pa_sink_assert_ref(s
);
338 pa_assert(s
->state
== PA_SINK_INIT
);
340 /* The following fields must be initialized properly when calling _put() */
341 pa_assert(s
->asyncmsgq
);
342 pa_assert(s
->rtpoll
);
343 pa_assert(!s
->thread_info
.min_latency
|| !s
->thread_info
.max_latency
||
344 s
->thread_info
.min_latency
<= s
->thread_info
.max_latency
);
346 if (!(s
->flags
& PA_SINK_HW_VOLUME_CTRL
)) {
347 s
->flags
|= PA_SINK_DECIBEL_VOLUME
;
349 s
->thread_info
.soft_volume
= s
->soft_volume
;
350 s
->thread_info
.soft_muted
= s
->muted
;
353 if (s
->flags
& PA_SINK_DECIBEL_VOLUME
)
354 s
->n_volume_steps
= PA_VOLUME_NORM
+1;
356 if (s
->core
->flat_volumes
)
357 if (s
->flags
& PA_SINK_DECIBEL_VOLUME
)
358 s
->flags
|= PA_SINK_FLAT_VOLUME
;
360 pa_assert_se(sink_set_state(s
, PA_SINK_IDLE
) == 0);
362 pa_source_put(s
->monitor_source
);
364 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
| PA_SUBSCRIPTION_EVENT_NEW
, s
->index
);
365 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_PUT
], s
);
368 /* Called from main context */
369 void pa_sink_unlink(pa_sink
* s
) {
371 pa_sink_input
*i
, *j
= NULL
;
375 /* Please note that pa_sink_unlink() does more than simply
376 * reversing pa_sink_put(). It also undoes the registrations
377 * already done in pa_sink_new()! */
379 /* All operations here shall be idempotent, i.e. pa_sink_unlink()
380 * may be called multiple times on the same sink without bad
383 linked
= PA_SINK_IS_LINKED(s
->state
);
386 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_UNLINK
], s
);
388 if (s
->state
!= PA_SINK_UNLINKED
)
389 pa_namereg_unregister(s
->core
, s
->name
);
390 pa_idxset_remove_by_data(s
->core
->sinks
, s
, NULL
);
393 pa_idxset_remove_by_data(s
->card
->sinks
, s
, NULL
);
395 while ((i
= pa_idxset_first(s
->inputs
, NULL
))) {
397 pa_sink_input_kill(i
);
402 sink_set_state(s
, PA_SINK_UNLINKED
);
404 s
->state
= PA_SINK_UNLINKED
;
408 if (s
->monitor_source
)
409 pa_source_unlink(s
->monitor_source
);
412 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
| PA_SUBSCRIPTION_EVENT_REMOVE
, s
->index
);
413 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_UNLINK_POST
], s
);
417 /* Called from main context */
418 static void sink_free(pa_object
*o
) {
419 pa_sink
*s
= PA_SINK(o
);
423 pa_assert(pa_sink_refcnt(s
) == 0);
425 if (PA_SINK_IS_LINKED(s
->state
))
428 pa_log_info("Freeing sink %u \"%s\"", s
->index
, s
->name
);
430 if (s
->monitor_source
) {
431 pa_source_unref(s
->monitor_source
);
432 s
->monitor_source
= NULL
;
435 pa_idxset_free(s
->inputs
, NULL
, NULL
);
437 while ((i
= pa_hashmap_steal_first(s
->thread_info
.inputs
)))
438 pa_sink_input_unref(i
);
440 pa_hashmap_free(s
->thread_info
.inputs
, NULL
, NULL
);
442 if (s
->silence
.memblock
)
443 pa_memblock_unref(s
->silence
.memblock
);
449 pa_proplist_free(s
->proplist
);
454 /* Called from main context */
455 void pa_sink_set_asyncmsgq(pa_sink
*s
, pa_asyncmsgq
*q
) {
456 pa_sink_assert_ref(s
);
460 if (s
->monitor_source
)
461 pa_source_set_asyncmsgq(s
->monitor_source
, q
);
464 /* Called from main context */
465 void pa_sink_set_rtpoll(pa_sink
*s
, pa_rtpoll
*p
) {
466 pa_sink_assert_ref(s
);
469 if (s
->monitor_source
)
470 pa_source_set_rtpoll(s
->monitor_source
, p
);
473 /* Called from main context */
474 int pa_sink_update_status(pa_sink
*s
) {
475 pa_sink_assert_ref(s
);
476 pa_assert(PA_SINK_IS_LINKED(s
->state
));
478 if (s
->state
== PA_SINK_SUSPENDED
)
481 return sink_set_state(s
, pa_sink_used_by(s
) ? PA_SINK_RUNNING
: PA_SINK_IDLE
);
484 /* Called from main context */
485 int pa_sink_suspend(pa_sink
*s
, pa_bool_t suspend
) {
486 pa_sink_assert_ref(s
);
487 pa_assert(PA_SINK_IS_LINKED(s
->state
));
490 return sink_set_state(s
, PA_SINK_SUSPENDED
);
492 return sink_set_state(s
, pa_sink_used_by(s
) ? PA_SINK_RUNNING
: PA_SINK_IDLE
);
495 /* Called from main context */
496 pa_queue
*pa_sink_move_all_start(pa_sink
*s
) {
498 pa_sink_input
*i
, *n
;
501 pa_sink_assert_ref(s
);
502 pa_assert(PA_SINK_IS_LINKED(s
->state
));
506 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= n
) {
507 n
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
));
509 if (pa_sink_input_start_move(i
) >= 0)
510 pa_queue_push(q
, pa_sink_input_ref(i
));
516 /* Called from main context */
517 void pa_sink_move_all_finish(pa_sink
*s
, pa_queue
*q
, pa_bool_t save
) {
520 pa_sink_assert_ref(s
);
521 pa_assert(PA_SINK_IS_LINKED(s
->state
));
524 while ((i
= PA_SINK_INPUT(pa_queue_pop(q
)))) {
525 if (pa_sink_input_finish_move(i
, s
, save
) < 0)
526 pa_sink_input_kill(i
);
528 pa_sink_input_unref(i
);
531 pa_queue_free(q
, NULL
, NULL
);
534 /* Called from main context */
535 void pa_sink_move_all_fail(pa_queue
*q
) {
539 while ((i
= PA_SINK_INPUT(pa_queue_pop(q
)))) {
540 if (pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL
], i
) == PA_HOOK_OK
) {
541 pa_sink_input_kill(i
);
542 pa_sink_input_unref(i
);
546 pa_queue_free(q
, NULL
, NULL
);
549 /* Called from IO thread context */
550 void pa_sink_process_rewind(pa_sink
*s
, size_t nbytes
) {
553 pa_sink_assert_ref(s
);
554 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
556 /* If nobody requested this and this is actually no real rewind
557 * then we can short cut this */
558 if (!s
->thread_info
.rewind_requested
&& nbytes
<= 0)
561 s
->thread_info
.rewind_nbytes
= 0;
562 s
->thread_info
.rewind_requested
= FALSE
;
564 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
)
568 pa_log_debug("Processing rewind...");
570 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
))) {
571 pa_sink_input_assert_ref(i
);
572 pa_sink_input_process_rewind(i
, nbytes
);
576 if (s
->monitor_source
&& PA_SOURCE_IS_LINKED(s
->monitor_source
->thread_info
.state
))
577 pa_source_process_rewind(s
->monitor_source
, nbytes
);
580 /* Called from IO thread context */
581 static unsigned fill_mix_info(pa_sink
*s
, size_t *length
, pa_mix_info
*info
, unsigned maxinfo
) {
585 size_t mixlength
= *length
;
587 pa_sink_assert_ref(s
);
590 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)) && maxinfo
> 0) {
591 pa_sink_input_assert_ref(i
);
593 pa_sink_input_peek(i
, *length
, &info
->chunk
, &info
->volume
);
595 if (mixlength
== 0 || info
->chunk
.length
< mixlength
)
596 mixlength
= info
->chunk
.length
;
598 if (pa_memblock_is_silence(info
->chunk
.memblock
)) {
599 pa_memblock_unref(info
->chunk
.memblock
);
603 info
->userdata
= pa_sink_input_ref(i
);
605 pa_assert(info
->chunk
.memblock
);
606 pa_assert(info
->chunk
.length
> 0);
619 /* Called from IO thread context */
620 static void inputs_drop(pa_sink
*s
, pa_mix_info
*info
, unsigned n
, pa_memchunk
*result
) {
624 unsigned n_unreffed
= 0;
626 pa_sink_assert_ref(s
);
628 pa_assert(result
->memblock
);
629 pa_assert(result
->length
> 0);
631 /* We optimize for the case where the order of the inputs has not changed */
633 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
))) {
635 pa_mix_info
* m
= NULL
;
637 pa_sink_input_assert_ref(i
);
639 /* Let's try to find the matching entry info the pa_mix_info array */
640 for (j
= 0; j
< n
; j
++) {
642 if (info
[p
].userdata
== i
) {
653 pa_sink_input_drop(i
, result
->length
);
655 if (s
->monitor_source
&& PA_SOURCE_IS_LINKED(s
->monitor_source
->thread_info
.state
)) {
657 if (pa_hashmap_size(i
->thread_info
.direct_outputs
) > 0) {
662 if (m
&& m
->chunk
.memblock
) {
664 pa_memblock_ref(c
.memblock
);
665 pa_assert(result
->length
<= c
.length
);
666 c
.length
= result
->length
;
668 pa_memchunk_make_writable(&c
, 0);
669 pa_volume_memchunk(&c
, &s
->sample_spec
, &m
->volume
);
672 pa_memblock_ref(c
.memblock
);
673 pa_assert(result
->length
<= c
.length
);
674 c
.length
= result
->length
;
677 while ((o
= pa_hashmap_iterate(i
->thread_info
.direct_outputs
, &ostate
, NULL
))) {
678 pa_source_output_assert_ref(o
);
679 pa_assert(o
->direct_on_input
== i
);
680 pa_source_post_direct(s
->monitor_source
, o
, &c
);
683 pa_memblock_unref(c
.memblock
);
688 if (m
->chunk
.memblock
)
689 pa_memblock_unref(m
->chunk
.memblock
);
690 pa_memchunk_reset(&m
->chunk
);
692 pa_sink_input_unref(m
->userdata
);
699 /* Now drop references to entries that are included in the
700 * pa_mix_info array but don't exist anymore */
702 if (n_unreffed
< n
) {
703 for (; n
> 0; info
++, n
--) {
705 pa_sink_input_unref(info
->userdata
);
706 if (info
->chunk
.memblock
)
707 pa_memblock_unref(info
->chunk
.memblock
);
711 if (s
->monitor_source
&& PA_SOURCE_IS_LINKED(s
->monitor_source
->thread_info
.state
))
712 pa_source_post(s
->monitor_source
, result
);
715 /* Called from IO thread context */
716 void pa_sink_render(pa_sink
*s
, size_t length
, pa_memchunk
*result
) {
717 pa_mix_info info
[MAX_MIX_CHANNELS
];
719 size_t block_size_max
;
721 pa_sink_assert_ref(s
);
722 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
723 pa_assert(pa_frame_aligned(length
, &s
->sample_spec
));
728 pa_assert(!s
->thread_info
.rewind_requested
);
729 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
731 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
) {
732 result
->memblock
= pa_memblock_ref(s
->silence
.memblock
);
733 result
->index
= s
->silence
.index
;
734 result
->length
= PA_MIN(s
->silence
.length
, length
);
739 length
= pa_frame_align(MIX_BUFFER_LENGTH
, &s
->sample_spec
);
741 block_size_max
= pa_mempool_block_size_max(s
->core
->mempool
);
742 if (length
> block_size_max
)
743 length
= pa_frame_align(block_size_max
, &s
->sample_spec
);
745 pa_assert(length
> 0);
747 n
= fill_mix_info(s
, &length
, info
, MAX_MIX_CHANNELS
);
751 *result
= s
->silence
;
752 pa_memblock_ref(result
->memblock
);
754 if (result
->length
> length
)
755 result
->length
= length
;
760 *result
= info
[0].chunk
;
761 pa_memblock_ref(result
->memblock
);
763 if (result
->length
> length
)
764 result
->length
= length
;
766 pa_sw_cvolume_multiply(&volume
, &s
->thread_info
.soft_volume
, &info
[0].volume
);
768 if (s
->thread_info
.soft_muted
|| !pa_cvolume_is_norm(&volume
)) {
769 pa_memchunk_make_writable(result
, 0);
770 if (s
->thread_info
.soft_muted
|| pa_cvolume_is_muted(&volume
))
771 pa_silence_memchunk(result
, &s
->sample_spec
);
773 pa_volume_memchunk(result
, &s
->sample_spec
, &volume
);
777 result
->memblock
= pa_memblock_new(s
->core
->mempool
, length
);
779 ptr
= pa_memblock_acquire(result
->memblock
);
780 result
->length
= pa_mix(info
, n
,
783 &s
->thread_info
.soft_volume
,
784 s
->thread_info
.soft_muted
);
785 pa_memblock_release(result
->memblock
);
790 inputs_drop(s
, info
, n
, result
);
795 /* Called from IO thread context */
796 void pa_sink_render_into(pa_sink
*s
, pa_memchunk
*target
) {
797 pa_mix_info info
[MAX_MIX_CHANNELS
];
799 size_t length
, block_size_max
;
801 pa_sink_assert_ref(s
);
802 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
804 pa_assert(target
->memblock
);
805 pa_assert(target
->length
> 0);
806 pa_assert(pa_frame_aligned(target
->length
, &s
->sample_spec
));
810 pa_assert(!s
->thread_info
.rewind_requested
);
811 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
813 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
) {
814 pa_silence_memchunk(target
, &s
->sample_spec
);
818 length
= target
->length
;
819 block_size_max
= pa_mempool_block_size_max(s
->core
->mempool
);
820 if (length
> block_size_max
)
821 length
= pa_frame_align(block_size_max
, &s
->sample_spec
);
823 pa_assert(length
> 0);
825 n
= fill_mix_info(s
, &length
, info
, MAX_MIX_CHANNELS
);
828 if (target
->length
> length
)
829 target
->length
= length
;
831 pa_silence_memchunk(target
, &s
->sample_spec
);
835 if (target
->length
> length
)
836 target
->length
= length
;
838 pa_sw_cvolume_multiply(&volume
, &s
->thread_info
.soft_volume
, &info
[0].volume
);
840 if (s
->thread_info
.soft_muted
|| pa_cvolume_is_muted(&volume
))
841 pa_silence_memchunk(target
, &s
->sample_spec
);
845 vchunk
= info
[0].chunk
;
846 pa_memblock_ref(vchunk
.memblock
);
848 if (vchunk
.length
> length
)
849 vchunk
.length
= length
;
851 if (!pa_cvolume_is_norm(&volume
)) {
852 pa_memchunk_make_writable(&vchunk
, 0);
853 pa_volume_memchunk(&vchunk
, &s
->sample_spec
, &volume
);
856 pa_memchunk_memcpy(target
, &vchunk
);
857 pa_memblock_unref(vchunk
.memblock
);
863 ptr
= pa_memblock_acquire(target
->memblock
);
865 target
->length
= pa_mix(info
, n
,
866 (uint8_t*) ptr
+ target
->index
, length
,
868 &s
->thread_info
.soft_volume
,
869 s
->thread_info
.soft_muted
);
871 pa_memblock_release(target
->memblock
);
874 inputs_drop(s
, info
, n
, target
);
879 /* Called from IO thread context */
880 void pa_sink_render_into_full(pa_sink
*s
, pa_memchunk
*target
) {
884 pa_sink_assert_ref(s
);
885 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
887 pa_assert(target
->memblock
);
888 pa_assert(target
->length
> 0);
889 pa_assert(pa_frame_aligned(target
->length
, &s
->sample_spec
));
893 pa_assert(!s
->thread_info
.rewind_requested
);
894 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
903 pa_sink_render_into(s
, &chunk
);
912 /* Called from IO thread context */
913 void pa_sink_render_full(pa_sink
*s
, size_t length
, pa_memchunk
*result
) {
914 pa_sink_assert_ref(s
);
915 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
916 pa_assert(length
> 0);
917 pa_assert(pa_frame_aligned(length
, &s
->sample_spec
));
920 pa_assert(!s
->thread_info
.rewind_requested
);
921 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
923 /*** This needs optimization ***/
926 result
->length
= length
;
927 result
->memblock
= pa_memblock_new(s
->core
->mempool
, length
);
929 pa_sink_render_into_full(s
, result
);
932 /* Called from main thread */
933 pa_usec_t
pa_sink_get_latency(pa_sink
*s
) {
936 pa_sink_assert_ref(s
);
937 pa_assert(PA_SINK_IS_LINKED(s
->state
));
939 /* The returned value is supposed to be in the time domain of the sound card! */
941 if (s
->state
== PA_SINK_SUSPENDED
)
944 if (!(s
->flags
& PA_SINK_LATENCY
))
947 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) == 0);
952 /* Called from main thread */
953 void pa_sink_update_flat_volume(pa_sink
*s
, pa_cvolume
*new_volume
) {
957 pa_sink_assert_ref(s
);
958 pa_assert(new_volume
);
959 pa_assert(PA_SINK_IS_LINKED(s
->state
));
960 pa_assert(s
->flags
& PA_SINK_FLAT_VOLUME
);
962 /* This is called whenever a sink input volume changes and we
963 * might need to fix up the sink volume accordingly. Please note
964 * that we don't actually update the sinks volume here, we only
965 * return how it needs to be updated. The caller should then call
966 * pa_sink_set_flat_volume().*/
968 if (pa_idxset_isempty(s
->inputs
)) {
969 /* In the special case that we have no sink input we leave the
970 * volume unmodified. */
971 *new_volume
= s
->virtual_volume
;
975 pa_cvolume_mute(new_volume
, s
->channel_map
.channels
);
977 /* First let's determine the new maximum volume of all inputs
978 * connected to this sink */
979 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
981 pa_cvolume remapped_volume
;
983 remapped_volume
= i
->virtual_volume
;
984 pa_cvolume_remap(&remapped_volume
, &i
->channel_map
, &s
->channel_map
);
986 for (c
= 0; c
< new_volume
->channels
; c
++)
987 if (remapped_volume
.values
[c
] > new_volume
->values
[c
])
988 new_volume
->values
[c
] = remapped_volume
.values
[c
];
991 /* Then, let's update the soft volumes of all inputs connected
993 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
994 pa_cvolume remapped_new_volume
;
996 remapped_new_volume
= *new_volume
;
997 pa_cvolume_remap(&remapped_new_volume
, &s
->channel_map
, &i
->channel_map
);
998 pa_sw_cvolume_divide(&i
->soft_volume
, &i
->virtual_volume
, &remapped_new_volume
);
999 pa_sw_cvolume_multiply(&i
->soft_volume
, &i
->soft_volume
, &i
->volume_factor
);
1001 /* Hooks have the ability to play games with i->soft_volume */
1002 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME
], i
);
1004 /* We don't issue PA_SINK_INPUT_MESSAGE_SET_VOLUME because
1005 * we want the update to have atomically with the sink
1006 * volume update, hence we do it within the
1007 * pa_sink_set_flat_volume() call below*/
1011 /* Called from main thread */
1012 void pa_sink_propagate_flat_volume(pa_sink
*s
, const pa_cvolume
*old_volume
) {
1016 pa_sink_assert_ref(s
);
1017 pa_assert(old_volume
);
1018 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1019 pa_assert(s
->flags
& PA_SINK_FLAT_VOLUME
);
1021 /* This is called whenever the sink volume changes that is not
1022 * caused by a sink input volume change. We need to fix up the
1023 * sink input volumes accordingly */
1025 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
1026 pa_cvolume remapped_old_volume
, remapped_new_volume
, fixed_volume
;
1029 remapped_new_volume
= s
->virtual_volume
;
1030 pa_cvolume_remap(&remapped_new_volume
, &s
->channel_map
, &i
->channel_map
);
1032 remapped_old_volume
= *old_volume
;
1033 pa_cvolume_remap(&remapped_old_volume
, &s
->channel_map
, &i
->channel_map
);
1035 for (c
= 0; c
< i
->sample_spec
.channels
; c
++)
1037 if (remapped_old_volume
.values
[c
] == PA_VOLUME_MUTED
)
1038 fixed_volume
.values
[c
] = PA_VOLUME_MUTED
;
1040 fixed_volume
.values
[c
] = (pa_volume_t
)
1041 ((uint64_t) i
->virtual_volume
.values
[c
] *
1042 (uint64_t) remapped_new_volume
.values
[c
] /
1043 (uint64_t) remapped_old_volume
.values
[c
]);
1045 fixed_volume
.channels
= i
->virtual_volume
.channels
;
1047 if (!pa_cvolume_equal(&fixed_volume
, &i
->virtual_volume
)) {
1048 i
->virtual_volume
= fixed_volume
;
1050 /* The virtual volume changed, let's tell people so */
1051 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1056 /* Called from main thread */
1057 void pa_sink_set_volume(pa_sink
*s
, const pa_cvolume
*volume
, pa_bool_t propagate
, pa_bool_t sendmsg
) {
1058 pa_cvolume old_virtual_volume
;
1059 pa_bool_t virtual_volume_changed
;
1061 pa_sink_assert_ref(s
);
1062 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1064 pa_assert(pa_cvolume_valid(volume
));
1065 pa_assert(pa_cvolume_compatible(volume
, &s
->sample_spec
));
1067 old_virtual_volume
= s
->virtual_volume
;
1068 s
->virtual_volume
= *volume
;
1069 virtual_volume_changed
= !pa_cvolume_equal(&old_virtual_volume
, &s
->virtual_volume
);
1071 /* Propagate this volume change back to the inputs */
1072 if (virtual_volume_changed
)
1073 if (propagate
&& (s
->flags
& PA_SINK_FLAT_VOLUME
))
1074 pa_sink_propagate_flat_volume(s
, &old_virtual_volume
);
1076 if (s
->set_volume
) {
1077 /* If we have a function set_volume(), then we do not apply a
1078 * soft volume by default. However, set_volume() is apply one
1079 * to s->soft_volume */
1081 pa_cvolume_reset(&s
->soft_volume
, s
->sample_spec
.channels
);
1085 /* If we have no function set_volume(), then the soft volume
1086 * becomes the virtual volume */
1087 s
->soft_volume
= s
->virtual_volume
;
1089 /* This tells the sink that soft and/or virtual volume changed */
1091 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
) == 0);
1093 if (virtual_volume_changed
)
1094 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1097 /* Called from main thread. Only to be called by sink implementor */
1098 void pa_sink_set_soft_volume(pa_sink
*s
, const pa_cvolume
*volume
) {
1099 pa_sink_assert_ref(s
);
1102 s
->soft_volume
= *volume
;
1104 if (PA_SINK_IS_LINKED(s
->state
))
1105 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
) == 0);
1107 s
->thread_info
.soft_volume
= *volume
;
1110 /* Called from main thread */
1111 const pa_cvolume
*pa_sink_get_volume(pa_sink
*s
, pa_bool_t force_refresh
) {
1112 pa_sink_assert_ref(s
);
1114 if (s
->refresh_volume
|| force_refresh
) {
1115 struct pa_cvolume old_virtual_volume
= s
->virtual_volume
;
1120 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_VOLUME
, NULL
, 0, NULL
) == 0);
1122 if (!pa_cvolume_equal(&old_virtual_volume
, &s
->virtual_volume
)) {
1124 if (s
->flags
& PA_SINK_FLAT_VOLUME
)
1125 pa_sink_propagate_flat_volume(s
, &old_virtual_volume
);
1127 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1131 return &s
->virtual_volume
;
1134 /* Called from main thread */
1135 void pa_sink_set_mute(pa_sink
*s
, pa_bool_t mute
) {
1136 pa_bool_t old_muted
;
1138 pa_sink_assert_ref(s
);
1139 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1141 old_muted
= s
->muted
;
1147 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_MUTE
, NULL
, 0, NULL
) == 0);
1149 if (old_muted
!= s
->muted
)
1150 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1153 /* Called from main thread */
1154 pa_bool_t
pa_sink_get_mute(pa_sink
*s
, pa_bool_t force_refresh
) {
1156 pa_sink_assert_ref(s
);
1158 if (s
->refresh_muted
|| force_refresh
) {
1159 pa_bool_t old_muted
= s
->muted
;
1164 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_MUTE
, NULL
, 0, NULL
) == 0);
1166 if (old_muted
!= s
->muted
)
1167 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1173 /* Called from main thread */
1174 pa_bool_t
pa_sink_update_proplist(pa_sink
*s
, pa_update_mode_t mode
, pa_proplist
*p
) {
1176 pa_sink_assert_ref(s
);
1179 pa_proplist_update(s
->proplist
, mode
, p
);
1181 if (PA_SINK_IS_LINKED(s
->state
)) {
1182 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_PROPLIST_CHANGED
], s
);
1183 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1189 /* Called from main thread */
1190 void pa_sink_set_description(pa_sink
*s
, const char *description
) {
1192 pa_sink_assert_ref(s
);
1194 if (!description
&& !pa_proplist_contains(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
))
1197 old
= pa_proplist_gets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1199 if (old
&& description
&& !strcmp(old
, description
))
1203 pa_proplist_sets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
, description
);
1205 pa_proplist_unset(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1207 if (s
->monitor_source
) {
1210 n
= pa_sprintf_malloc("Monitor Source of %s", description
? description
: s
->name
);
1211 pa_source_set_description(s
->monitor_source
, n
);
1215 if (PA_SINK_IS_LINKED(s
->state
)) {
1216 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1217 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_PROPLIST_CHANGED
], s
);
1221 /* Called from main thread */
1222 unsigned pa_sink_linked_by(pa_sink
*s
) {
1225 pa_sink_assert_ref(s
);
1226 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1228 ret
= pa_idxset_size(s
->inputs
);
1230 /* We add in the number of streams connected to us here. Please
1231 * note the asymmmetry to pa_sink_used_by()! */
1233 if (s
->monitor_source
)
1234 ret
+= pa_source_linked_by(s
->monitor_source
);
1239 /* Called from main thread */
1240 unsigned pa_sink_used_by(pa_sink
*s
) {
1243 pa_sink_assert_ref(s
);
1244 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1246 ret
= pa_idxset_size(s
->inputs
);
1247 pa_assert(ret
>= s
->n_corked
);
1249 /* Streams connected to our monitor source do not matter for
1250 * pa_sink_used_by()!.*/
1252 return ret
- s
->n_corked
;
1255 /* Called from main thread */
1256 unsigned pa_sink_check_suspend(pa_sink
*s
) {
1261 pa_sink_assert_ref(s
);
1263 if (!PA_SINK_IS_LINKED(s
->state
))
1268 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
1269 pa_sink_input_state_t st
;
1271 st
= pa_sink_input_get_state(i
);
1272 pa_assert(PA_SINK_INPUT_IS_LINKED(st
));
1274 if (st
== PA_SINK_INPUT_CORKED
)
1277 if (i
->flags
& PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
)
1283 if (s
->monitor_source
)
1284 ret
+= pa_source_check_suspend(s
->monitor_source
);
1289 /* Called from the IO thread */
1290 static void sync_input_volumes_within_thread(pa_sink
*s
) {
1294 pa_sink_assert_ref(s
);
1296 while ((i
= PA_SINK_INPUT(pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))) {
1297 if (pa_cvolume_equal(&i
->thread_info
.soft_volume
, &i
->soft_volume
))
1300 i
->thread_info
.soft_volume
= i
->soft_volume
;
1301 pa_sink_input_request_rewind(i
, 0, TRUE
, FALSE
, FALSE
);
1305 /* Called from IO thread, except when it is not */
1306 int pa_sink_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1307 pa_sink
*s
= PA_SINK(o
);
1308 pa_sink_assert_ref(s
);
1310 switch ((pa_sink_message_t
) code
) {
1312 case PA_SINK_MESSAGE_ADD_INPUT
: {
1313 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1315 /* If you change anything here, make sure to change the
1316 * sink input handling a few lines down at
1317 * PA_SINK_MESSAGE_FINISH_MOVE, too. */
1319 pa_hashmap_put(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
), pa_sink_input_ref(i
));
1321 /* Since the caller sleeps in pa_sink_input_put(), we can
1322 * safely access data outside of thread_info even though
1325 if ((i
->thread_info
.sync_prev
= i
->sync_prev
)) {
1326 pa_assert(i
->sink
== i
->thread_info
.sync_prev
->sink
);
1327 pa_assert(i
->sync_prev
->sync_next
== i
);
1328 i
->thread_info
.sync_prev
->thread_info
.sync_next
= i
;
1331 if ((i
->thread_info
.sync_next
= i
->sync_next
)) {
1332 pa_assert(i
->sink
== i
->thread_info
.sync_next
->sink
);
1333 pa_assert(i
->sync_next
->sync_prev
== i
);
1334 i
->thread_info
.sync_next
->thread_info
.sync_prev
= i
;
1337 pa_assert(!i
->thread_info
.attached
);
1338 i
->thread_info
.attached
= TRUE
;
1343 pa_sink_input_set_state_within_thread(i
, i
->state
);
1345 /* The requested latency of the sink input needs to be
1346 * fixed up and then configured on the sink */
1348 if (i
->thread_info
.requested_sink_latency
!= (pa_usec_t
) -1)
1349 pa_sink_input_set_requested_latency_within_thread(i
, i
->thread_info
.requested_sink_latency
);
1351 pa_sink_input_update_max_rewind(i
, s
->thread_info
.max_rewind
);
1352 pa_sink_input_update_max_request(i
, s
->thread_info
.max_request
);
1354 /* We don't rewind here automatically. This is left to the
1355 * sink input implementor because some sink inputs need a
1356 * slow start, i.e. need some time to buffer client
1357 * samples before beginning streaming. */
1359 /* In flat volume mode we need to update the volume as
1361 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1364 case PA_SINK_MESSAGE_REMOVE_INPUT
: {
1365 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1367 /* If you change anything here, make sure to change the
1368 * sink input handling a few lines down at
1369 * PA_SINK_MESSAGE_PREPAPRE_MOVE, too. */
1374 pa_sink_input_set_state_within_thread(i
, i
->state
);
1376 pa_assert(i
->thread_info
.attached
);
1377 i
->thread_info
.attached
= FALSE
;
1379 /* Since the caller sleeps in pa_sink_input_unlink(),
1380 * we can safely access data outside of thread_info even
1381 * though it is mutable */
1383 pa_assert(!i
->sync_prev
);
1384 pa_assert(!i
->sync_next
);
1386 if (i
->thread_info
.sync_prev
) {
1387 i
->thread_info
.sync_prev
->thread_info
.sync_next
= i
->thread_info
.sync_prev
->sync_next
;
1388 i
->thread_info
.sync_prev
= NULL
;
1391 if (i
->thread_info
.sync_next
) {
1392 i
->thread_info
.sync_next
->thread_info
.sync_prev
= i
->thread_info
.sync_next
->sync_prev
;
1393 i
->thread_info
.sync_next
= NULL
;
1396 if (pa_hashmap_remove(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
)))
1397 pa_sink_input_unref(i
);
1399 pa_sink_invalidate_requested_latency(s
);
1400 pa_sink_request_rewind(s
, (size_t) -1);
1402 /* In flat volume mode we need to update the volume as
1404 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1407 case PA_SINK_MESSAGE_START_MOVE
: {
1408 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1410 /* We don't support moving synchronized streams. */
1411 pa_assert(!i
->sync_prev
);
1412 pa_assert(!i
->sync_next
);
1413 pa_assert(!i
->thread_info
.sync_next
);
1414 pa_assert(!i
->thread_info
.sync_prev
);
1416 if (i
->thread_info
.state
!= PA_SINK_INPUT_CORKED
) {
1418 size_t sink_nbytes
, total_nbytes
;
1420 /* Get the latency of the sink */
1421 if (!(s
->flags
& PA_SINK_LATENCY
) ||
1422 PA_MSGOBJECT(s
)->process_msg(PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) < 0)
1425 sink_nbytes
= pa_usec_to_bytes(usec
, &s
->sample_spec
);
1426 total_nbytes
= sink_nbytes
+ pa_memblockq_get_length(i
->thread_info
.render_memblockq
);
1428 if (total_nbytes
> 0) {
1429 i
->thread_info
.rewrite_nbytes
= i
->thread_info
.resampler
? pa_resampler_request(i
->thread_info
.resampler
, total_nbytes
) : total_nbytes
;
1430 i
->thread_info
.rewrite_flush
= TRUE
;
1431 pa_sink_input_process_rewind(i
, sink_nbytes
);
1438 pa_assert(i
->thread_info
.attached
);
1439 i
->thread_info
.attached
= FALSE
;
1441 /* Let's remove the sink input ...*/
1442 if (pa_hashmap_remove(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
)))
1443 pa_sink_input_unref(i
);
1445 pa_sink_invalidate_requested_latency(s
);
1447 pa_log_debug("Requesting rewind due to started move");
1448 pa_sink_request_rewind(s
, (size_t) -1);
1450 /* In flat volume mode we need to update the volume as
1452 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1455 case PA_SINK_MESSAGE_FINISH_MOVE
: {
1456 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1458 /* We don't support moving synchronized streams. */
1459 pa_assert(!i
->sync_prev
);
1460 pa_assert(!i
->sync_next
);
1461 pa_assert(!i
->thread_info
.sync_next
);
1462 pa_assert(!i
->thread_info
.sync_prev
);
1464 pa_hashmap_put(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
), pa_sink_input_ref(i
));
1466 pa_assert(!i
->thread_info
.attached
);
1467 i
->thread_info
.attached
= TRUE
;
1472 if (i
->thread_info
.requested_sink_latency
!= (pa_usec_t
) -1)
1473 pa_sink_input_set_requested_latency_within_thread(i
, i
->thread_info
.requested_sink_latency
);
1475 pa_sink_input_update_max_rewind(i
, s
->thread_info
.max_rewind
);
1476 pa_sink_input_update_max_request(i
, s
->thread_info
.max_request
);
1478 if (i
->thread_info
.state
!= PA_SINK_INPUT_CORKED
) {
1482 /* Get the latency of the sink */
1483 if (!(s
->flags
& PA_SINK_LATENCY
) ||
1484 PA_MSGOBJECT(s
)->process_msg(PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) < 0)
1487 nbytes
= pa_usec_to_bytes(usec
, &s
->sample_spec
);
1490 pa_sink_input_drop(i
, nbytes
);
1492 pa_log_debug("Requesting rewind due to finished move");
1493 pa_sink_request_rewind(s
, nbytes
);
1496 /* In flat volume mode we need to update the volume as
1498 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1501 case PA_SINK_MESSAGE_SET_VOLUME
:
1503 if (!pa_cvolume_equal(&s
->thread_info
.soft_volume
, &s
->soft_volume
)) {
1504 s
->thread_info
.soft_volume
= s
->soft_volume
;
1505 pa_sink_request_rewind(s
, (size_t) -1);
1508 if (s
->flags
& PA_SINK_FLAT_VOLUME
)
1509 sync_input_volumes_within_thread(s
);
1513 case PA_SINK_MESSAGE_GET_VOLUME
:
1516 case PA_SINK_MESSAGE_SET_MUTE
:
1518 if (s
->thread_info
.soft_muted
!= s
->muted
) {
1519 s
->thread_info
.soft_muted
= s
->muted
;
1520 pa_sink_request_rewind(s
, (size_t) -1);
1525 case PA_SINK_MESSAGE_GET_MUTE
:
1528 case PA_SINK_MESSAGE_SET_STATE
:
1530 s
->thread_info
.state
= PA_PTR_TO_UINT(userdata
);
1532 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
)
1533 s
->thread_info
.rewind_requested
= FALSE
;
1537 case PA_SINK_MESSAGE_DETACH
:
1539 /* Detach all streams */
1540 pa_sink_detach_within_thread(s
);
1543 case PA_SINK_MESSAGE_ATTACH
:
1545 /* Reattach all streams */
1546 pa_sink_attach_within_thread(s
);
1549 case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY
: {
1551 pa_usec_t
*usec
= userdata
;
1552 *usec
= pa_sink_get_requested_latency_within_thread(s
);
1554 if (*usec
== (pa_usec_t
) -1)
1555 *usec
= s
->thread_info
.max_latency
;
1560 case PA_SINK_MESSAGE_SET_LATENCY_RANGE
: {
1561 pa_usec_t
*r
= userdata
;
1563 pa_sink_update_latency_range(s
, r
[0], r
[1]);
1568 case PA_SINK_MESSAGE_GET_LATENCY_RANGE
: {
1569 pa_usec_t
*r
= userdata
;
1571 r
[0] = s
->thread_info
.min_latency
;
1572 r
[1] = s
->thread_info
.max_latency
;
1577 case PA_SINK_MESSAGE_GET_MAX_REWIND
:
1579 *((size_t*) userdata
) = s
->thread_info
.max_rewind
;
1582 case PA_SINK_MESSAGE_GET_MAX_REQUEST
:
1584 *((size_t*) userdata
) = s
->thread_info
.max_request
;
1587 case PA_SINK_MESSAGE_GET_LATENCY
:
1588 case PA_SINK_MESSAGE_MAX
:
1595 /* Called from main thread */
1596 int pa_sink_suspend_all(pa_core
*c
, pa_bool_t suspend
) {
1601 pa_core_assert_ref(c
);
1603 for (sink
= PA_SINK(pa_idxset_first(c
->sinks
, &idx
)); sink
; sink
= PA_SINK(pa_idxset_next(c
->sinks
, &idx
)))
1604 ret
-= pa_sink_suspend(sink
, suspend
) < 0;
1609 /* Called from main thread */
1610 void pa_sink_detach(pa_sink
*s
) {
1611 pa_sink_assert_ref(s
);
1612 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1614 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_DETACH
, NULL
, 0, NULL
) == 0);
1617 /* Called from main thread */
1618 void pa_sink_attach(pa_sink
*s
) {
1619 pa_sink_assert_ref(s
);
1620 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1622 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_ATTACH
, NULL
, 0, NULL
) == 0);
1625 /* Called from IO thread */
1626 void pa_sink_detach_within_thread(pa_sink
*s
) {
1630 pa_sink_assert_ref(s
);
1631 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
1633 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1637 if (s
->monitor_source
)
1638 pa_source_detach_within_thread(s
->monitor_source
);
1641 /* Called from IO thread */
1642 void pa_sink_attach_within_thread(pa_sink
*s
) {
1646 pa_sink_assert_ref(s
);
1647 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
1649 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1653 if (s
->monitor_source
)
1654 pa_source_attach_within_thread(s
->monitor_source
);
1657 /* Called from IO thread */
1658 void pa_sink_request_rewind(pa_sink
*s
, size_t nbytes
) {
1659 pa_sink_assert_ref(s
);
1660 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
1662 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
)
1665 if (nbytes
== (size_t) -1)
1666 nbytes
= s
->thread_info
.max_rewind
;
1668 nbytes
= PA_MIN(nbytes
, s
->thread_info
.max_rewind
);
1670 if (s
->thread_info
.rewind_requested
&&
1671 nbytes
<= s
->thread_info
.rewind_nbytes
)
1674 s
->thread_info
.rewind_nbytes
= nbytes
;
1675 s
->thread_info
.rewind_requested
= TRUE
;
1677 if (s
->request_rewind
)
1678 s
->request_rewind(s
);
1681 /* Called from IO thread */
1682 pa_usec_t
pa_sink_get_requested_latency_within_thread(pa_sink
*s
) {
1683 pa_usec_t result
= (pa_usec_t
) -1;
1686 pa_usec_t monitor_latency
;
1688 pa_sink_assert_ref(s
);
1690 if (s
->thread_info
.requested_latency_valid
)
1691 return s
->thread_info
.requested_latency
;
1693 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1695 if (i
->thread_info
.requested_sink_latency
!= (pa_usec_t
) -1 &&
1696 (result
== (pa_usec_t
) -1 || result
> i
->thread_info
.requested_sink_latency
))
1697 result
= i
->thread_info
.requested_sink_latency
;
1699 monitor_latency
= pa_source_get_requested_latency_within_thread(s
->monitor_source
);
1701 if (monitor_latency
!= (pa_usec_t
) -1 &&
1702 (result
== (pa_usec_t
) -1 || result
> monitor_latency
))
1703 result
= monitor_latency
;
1705 if (result
!= (pa_usec_t
) -1) {
1706 if (s
->thread_info
.max_latency
> 0 && result
> s
->thread_info
.max_latency
)
1707 result
= s
->thread_info
.max_latency
;
1709 if (s
->thread_info
.min_latency
> 0 && result
< s
->thread_info
.min_latency
)
1710 result
= s
->thread_info
.min_latency
;
1713 s
->thread_info
.requested_latency
= result
;
1714 s
->thread_info
.requested_latency_valid
= TRUE
;
1719 /* Called from main thread */
1720 pa_usec_t
pa_sink_get_requested_latency(pa_sink
*s
) {
1723 pa_sink_assert_ref(s
);
1724 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1726 if (s
->state
== PA_SINK_SUSPENDED
)
1729 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY
, &usec
, 0, NULL
) == 0);
1733 /* Called from IO thread */
1734 void pa_sink_set_max_rewind(pa_sink
*s
, size_t max_rewind
) {
1738 pa_sink_assert_ref(s
);
1740 if (max_rewind
== s
->thread_info
.max_rewind
)
1743 s
->thread_info
.max_rewind
= max_rewind
;
1745 if (PA_SINK_IS_LINKED(s
->thread_info
.state
)) {
1746 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1747 pa_sink_input_update_max_rewind(i
, s
->thread_info
.max_rewind
);
1750 if (s
->monitor_source
)
1751 pa_source_set_max_rewind(s
->monitor_source
, s
->thread_info
.max_rewind
);
1754 /* Called from IO thread */
1755 void pa_sink_set_max_request(pa_sink
*s
, size_t max_request
) {
1758 pa_sink_assert_ref(s
);
1760 if (max_request
== s
->thread_info
.max_request
)
1763 s
->thread_info
.max_request
= max_request
;
1765 if (PA_SINK_IS_LINKED(s
->thread_info
.state
)) {
1768 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1769 pa_sink_input_update_max_request(i
, s
->thread_info
.max_request
);
1773 /* Called from IO thread */
1774 void pa_sink_invalidate_requested_latency(pa_sink
*s
) {
1778 pa_sink_assert_ref(s
);
1780 s
->thread_info
.requested_latency_valid
= FALSE
;
1782 if (s
->update_requested_latency
)
1783 s
->update_requested_latency(s
);
1785 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1786 if (i
->update_sink_requested_latency
)
1787 i
->update_sink_requested_latency(i
);
1790 /* Called from main thread */
1791 void pa_sink_set_latency_range(pa_sink
*s
, pa_usec_t min_latency
, pa_usec_t max_latency
) {
1792 pa_sink_assert_ref(s
);
1794 /* min_latency == 0: no limit
1795 * min_latency == (size_t) -1: default limit
1796 * min_latency anything else: specified limit
1798 * Similar for max_latency */
1800 if (min_latency
== (pa_usec_t
) -1)
1801 min_latency
= DEFAULT_MIN_LATENCY
;
1803 if (max_latency
== (pa_usec_t
) -1)
1804 max_latency
= min_latency
;
1806 pa_assert(!min_latency
|| !max_latency
||
1807 min_latency
<= max_latency
);
1809 if (PA_SINK_IS_LINKED(s
->state
)) {
1815 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_LATENCY_RANGE
, r
, 0, NULL
) == 0);
1817 s
->thread_info
.min_latency
= min_latency
;
1818 s
->thread_info
.max_latency
= max_latency
;
1820 s
->monitor_source
->thread_info
.min_latency
= min_latency
;
1821 s
->monitor_source
->thread_info
.max_latency
= max_latency
;
1823 s
->thread_info
.requested_latency_valid
= s
->monitor_source
->thread_info
.requested_latency_valid
= FALSE
;
1827 /* Called from main thread */
1828 void pa_sink_get_latency_range(pa_sink
*s
, pa_usec_t
*min_latency
, pa_usec_t
*max_latency
) {
1829 pa_sink_assert_ref(s
);
1830 pa_assert(min_latency
);
1831 pa_assert(max_latency
);
1833 if (PA_SINK_IS_LINKED(s
->state
)) {
1834 pa_usec_t r
[2] = { 0, 0 };
1836 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY_RANGE
, r
, 0, NULL
) == 0);
1838 *min_latency
= r
[0];
1839 *max_latency
= r
[1];
1841 *min_latency
= s
->thread_info
.min_latency
;
1842 *max_latency
= s
->thread_info
.max_latency
;
1846 /* Called from IO thread */
1847 void pa_sink_update_latency_range(pa_sink
*s
, pa_usec_t min_latency
, pa_usec_t max_latency
) {
1851 pa_sink_assert_ref(s
);
1853 pa_assert(!min_latency
|| !max_latency
||
1854 min_latency
<= max_latency
);
1856 s
->thread_info
.min_latency
= min_latency
;
1857 s
->thread_info
.max_latency
= max_latency
;
1859 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1860 if (i
->update_sink_latency_range
)
1861 i
->update_sink_latency_range(i
);
1863 pa_sink_invalidate_requested_latency(s
);
1865 pa_source_update_latency_range(s
->monitor_source
, min_latency
, max_latency
);
1868 /* Called from main context */
1869 size_t pa_sink_get_max_rewind(pa_sink
*s
) {
1871 pa_sink_assert_ref(s
);
1873 if (!PA_SINK_IS_LINKED(s
->state
))
1874 return s
->thread_info
.max_rewind
;
1876 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_MAX_REWIND
, &r
, 0, NULL
) == 0);
1881 /* Called from main context */
1882 size_t pa_sink_get_max_request(pa_sink
*s
) {
1884 pa_sink_assert_ref(s
);
1886 if (!PA_SINK_IS_LINKED(s
->state
))
1887 return s
->thread_info
.max_request
;
1889 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_MAX_REQUEST
, &r
, 0, NULL
) == 0);
1894 /* Called from main context */
1895 pa_bool_t
pa_device_init_icon(pa_proplist
*p
, pa_bool_t is_sink
) {
1896 const char *ff
, *t
= NULL
, *s
= "", *profile
, *bus
;
1900 if (pa_proplist_contains(p
, PA_PROP_DEVICE_ICON_NAME
))
1903 if ((ff
= pa_proplist_gets(p
, PA_PROP_DEVICE_FORM_FACTOR
))) {
1905 if (pa_streq(ff
, "microphone"))
1906 t
= "audio-input-microphone";
1907 else if (pa_streq(ff
, "webcam"))
1909 else if (pa_streq(ff
, "computer"))
1911 else if (pa_streq(ff
, "handset"))
1919 t
= "audio-input-microphone";
1922 if ((profile
= pa_proplist_gets(p
, PA_PROP_DEVICE_PROFILE_NAME
))) {
1923 if (strstr(profile
, "analog"))
1925 else if (strstr(profile
, "iec958"))
1927 else if (strstr(profile
, "hdmi"))
1931 bus
= pa_proplist_gets(p
, PA_PROP_DEVICE_BUS
);
1933 pa_proplist_setf(p
, PA_PROP_DEVICE_ICON_NAME
, "%s%s%s%s", t
, pa_strempty(s
), bus
? "-" : "", pa_strempty(bus
));
1938 pa_bool_t
pa_device_init_description(pa_proplist
*p
) {
1942 if (pa_proplist_contains(p
, PA_PROP_DEVICE_DESCRIPTION
))
1945 if ((s
= pa_proplist_gets(p
, PA_PROP_DEVICE_FORM_FACTOR
)))
1946 if (pa_streq(s
, "internal")) {
1947 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, _("Internal Audio"));
1951 if ((s
= pa_proplist_gets(p
, PA_PROP_DEVICE_PRODUCT_NAME
))) {
1952 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);