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 ABSOLUTE_MIN_LATENCY (500)
52 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
54 static PA_DEFINE_CHECK_TYPE(pa_sink
, pa_msgobject
);
56 static void sink_free(pa_object
*s
);
58 pa_sink_new_data
* pa_sink_new_data_init(pa_sink_new_data
*data
) {
61 memset(data
, 0, sizeof(*data
));
62 data
->proplist
= pa_proplist_new();
67 void pa_sink_new_data_set_name(pa_sink_new_data
*data
, const char *name
) {
71 data
->name
= pa_xstrdup(name
);
74 void pa_sink_new_data_set_sample_spec(pa_sink_new_data
*data
, const pa_sample_spec
*spec
) {
77 if ((data
->sample_spec_is_set
= !!spec
))
78 data
->sample_spec
= *spec
;
81 void pa_sink_new_data_set_channel_map(pa_sink_new_data
*data
, const pa_channel_map
*map
) {
84 if ((data
->channel_map_is_set
= !!map
))
85 data
->channel_map
= *map
;
88 void pa_sink_new_data_set_volume(pa_sink_new_data
*data
, const pa_cvolume
*volume
) {
91 if ((data
->volume_is_set
= !!volume
))
92 data
->volume
= *volume
;
95 void pa_sink_new_data_set_muted(pa_sink_new_data
*data
, pa_bool_t mute
) {
98 data
->muted_is_set
= TRUE
;
102 void pa_sink_new_data_done(pa_sink_new_data
*data
) {
105 pa_xfree(data
->name
);
106 pa_proplist_free(data
->proplist
);
109 /* Called from main context */
110 static void reset_callbacks(pa_sink
*s
) {
114 s
->get_volume
= NULL
;
115 s
->set_volume
= NULL
;
118 s
->request_rewind
= NULL
;
119 s
->update_requested_latency
= NULL
;
122 /* Called from main context */
123 pa_sink
* pa_sink_new(
125 pa_sink_new_data
*data
,
126 pa_sink_flags_t flags
) {
130 char st
[PA_SAMPLE_SPEC_SNPRINT_MAX
], cm
[PA_CHANNEL_MAP_SNPRINT_MAX
];
131 pa_source_new_data source_data
;
137 pa_assert(data
->name
);
139 s
= pa_msgobject_new(pa_sink
);
141 if (!(name
= pa_namereg_register(core
, data
->name
, PA_NAMEREG_SINK
, s
, data
->namereg_fail
))) {
146 pa_sink_new_data_set_name(data
, name
);
148 if (pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SINK_NEW
], data
) < 0) {
150 pa_namereg_unregister(core
, name
);
154 pa_return_null_if_fail(!data
->driver
|| pa_utf8_valid(data
->driver
));
155 pa_return_null_if_fail(data
->name
&& pa_utf8_valid(data
->name
) && data
->name
[0]);
157 pa_return_null_if_fail(data
->sample_spec_is_set
&& pa_sample_spec_valid(&data
->sample_spec
));
159 if (!data
->channel_map_is_set
)
160 pa_return_null_if_fail(pa_channel_map_init_auto(&data
->channel_map
, data
->sample_spec
.channels
, PA_CHANNEL_MAP_DEFAULT
));
162 pa_return_null_if_fail(pa_channel_map_valid(&data
->channel_map
));
163 pa_return_null_if_fail(data
->channel_map
.channels
== data
->sample_spec
.channels
);
165 if (!data
->volume_is_set
)
166 pa_cvolume_reset(&data
->volume
, data
->sample_spec
.channels
);
168 pa_return_null_if_fail(pa_cvolume_valid(&data
->volume
));
169 pa_return_null_if_fail(data
->volume
.channels
== data
->sample_spec
.channels
);
171 if (!data
->muted_is_set
)
175 pa_proplist_update(data
->proplist
, PA_UPDATE_MERGE
, data
->card
->proplist
);
177 pa_device_init_description(data
->proplist
);
178 pa_device_init_icon(data
->proplist
, TRUE
);
180 if (pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SINK_FIXATE
], data
) < 0) {
182 pa_namereg_unregister(core
, name
);
186 s
->parent
.parent
.free
= sink_free
;
187 s
->parent
.process_msg
= pa_sink_process_msg
;
190 s
->state
= PA_SINK_INIT
;
192 s
->name
= pa_xstrdup(name
);
193 s
->proplist
= pa_proplist_copy(data
->proplist
);
194 s
->driver
= pa_xstrdup(pa_path_get_filename(data
->driver
));
195 s
->module
= data
->module
;
196 s
->card
= data
->card
;
198 s
->sample_spec
= data
->sample_spec
;
199 s
->channel_map
= data
->channel_map
;
201 s
->inputs
= pa_idxset_new(NULL
, NULL
);
204 s
->virtual_volume
= data
->volume
;
205 pa_cvolume_reset(&s
->soft_volume
, s
->sample_spec
.channels
);
206 s
->base_volume
= PA_VOLUME_NORM
;
207 s
->n_volume_steps
= PA_VOLUME_NORM
+1;
208 s
->muted
= data
->muted
;
209 s
->refresh_volume
= s
->refresh_muted
= FALSE
;
217 pa_silence_memchunk_get(
218 &core
->silence_cache
,
224 s
->thread_info
.inputs
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
225 s
->thread_info
.soft_volume
= s
->soft_volume
;
226 s
->thread_info
.soft_muted
= s
->muted
;
227 s
->thread_info
.state
= s
->state
;
228 s
->thread_info
.rewind_nbytes
= 0;
229 s
->thread_info
.rewind_requested
= FALSE
;
230 s
->thread_info
.max_rewind
= 0;
231 s
->thread_info
.max_request
= 0;
232 s
->thread_info
.requested_latency_valid
= FALSE
;
233 s
->thread_info
.requested_latency
= 0;
234 s
->thread_info
.min_latency
= ABSOLUTE_MIN_LATENCY
;
235 s
->thread_info
.max_latency
= ABSOLUTE_MAX_LATENCY
;
237 pa_assert_se(pa_idxset_put(core
->sinks
, s
, &s
->index
) >= 0);
240 pa_assert_se(pa_idxset_put(s
->card
->sinks
, s
, NULL
) >= 0);
242 pt
= pa_proplist_to_string_sep(s
->proplist
, "\n ");
243 pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s\n %s",
246 pa_sample_spec_snprint(st
, sizeof(st
), &s
->sample_spec
),
247 pa_channel_map_snprint(cm
, sizeof(cm
), &s
->channel_map
),
251 pa_source_new_data_init(&source_data
);
252 pa_source_new_data_set_sample_spec(&source_data
, &s
->sample_spec
);
253 pa_source_new_data_set_channel_map(&source_data
, &s
->channel_map
);
254 source_data
.name
= pa_sprintf_malloc("%s.monitor", name
);
255 source_data
.driver
= data
->driver
;
256 source_data
.module
= data
->module
;
257 source_data
.card
= data
->card
;
259 dn
= pa_proplist_gets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
260 pa_proplist_setf(source_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "Monitor of %s", dn
? dn
: s
->name
);
261 pa_proplist_sets(source_data
.proplist
, PA_PROP_DEVICE_CLASS
, "monitor");
263 s
->monitor_source
= pa_source_new(core
, &source_data
, PA_SOURCE_LATENCY
);
265 pa_source_new_data_done(&source_data
);
267 if (!s
->monitor_source
) {
273 s
->monitor_source
->monitor_of
= s
;
275 pa_source_set_latency_range(s
->monitor_source
, s
->thread_info
.min_latency
, s
->thread_info
.max_latency
);
276 pa_source_set_max_rewind(s
->monitor_source
, s
->thread_info
.max_rewind
);
281 /* Called from main context */
282 static int sink_set_state(pa_sink
*s
, pa_sink_state_t state
) {
284 pa_bool_t suspend_change
;
285 pa_sink_state_t original_state
;
289 if (s
->state
== state
)
292 original_state
= s
->state
;
295 (original_state
== PA_SINK_SUSPENDED
&& PA_SINK_IS_OPENED(state
)) ||
296 (PA_SINK_IS_OPENED(original_state
) && state
== PA_SINK_SUSPENDED
);
299 if ((ret
= s
->set_state(s
, state
)) < 0)
303 if ((ret
= pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_STATE
, PA_UINT_TO_PTR(state
), 0, NULL
)) < 0) {
306 s
->set_state(s
, original_state
);
313 if (state
!= PA_SINK_UNLINKED
) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
314 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_STATE_CHANGED
], s
);
315 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
| PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
318 if (suspend_change
) {
322 /* We're suspending or resuming, tell everyone about it */
324 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
)))
325 if (s
->state
== PA_SINK_SUSPENDED
&&
326 (i
->flags
& PA_SINK_INPUT_FAIL_ON_SUSPEND
))
327 pa_sink_input_kill(i
);
329 i
->suspend(i
, state
== PA_SINK_SUSPENDED
);
331 if (s
->monitor_source
)
332 pa_source_sync_suspend(s
->monitor_source
);
338 /* Called from main context */
339 void pa_sink_put(pa_sink
* s
) {
340 pa_sink_assert_ref(s
);
342 pa_assert(s
->state
== PA_SINK_INIT
);
344 /* The following fields must be initialized properly when calling _put() */
345 pa_assert(s
->asyncmsgq
);
346 pa_assert(s
->rtpoll
);
347 pa_assert(s
->thread_info
.min_latency
<= s
->thread_info
.max_latency
);
349 if (!(s
->flags
& PA_SINK_HW_VOLUME_CTRL
)) {
350 s
->flags
|= PA_SINK_DECIBEL_VOLUME
;
352 s
->thread_info
.soft_volume
= s
->soft_volume
;
353 s
->thread_info
.soft_muted
= s
->muted
;
356 if (s
->flags
& PA_SINK_DECIBEL_VOLUME
)
357 s
->n_volume_steps
= PA_VOLUME_NORM
+1;
359 if (s
->core
->flat_volumes
)
360 if (s
->flags
& PA_SINK_DECIBEL_VOLUME
)
361 s
->flags
|= PA_SINK_FLAT_VOLUME
;
363 pa_assert_se(sink_set_state(s
, PA_SINK_IDLE
) == 0);
365 pa_source_put(s
->monitor_source
);
367 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
| PA_SUBSCRIPTION_EVENT_NEW
, s
->index
);
368 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_PUT
], s
);
371 /* Called from main context */
372 void pa_sink_unlink(pa_sink
* s
) {
374 pa_sink_input
*i
, *j
= NULL
;
378 /* Please note that pa_sink_unlink() does more than simply
379 * reversing pa_sink_put(). It also undoes the registrations
380 * already done in pa_sink_new()! */
382 /* All operations here shall be idempotent, i.e. pa_sink_unlink()
383 * may be called multiple times on the same sink without bad
386 linked
= PA_SINK_IS_LINKED(s
->state
);
389 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_UNLINK
], s
);
391 if (s
->state
!= PA_SINK_UNLINKED
)
392 pa_namereg_unregister(s
->core
, s
->name
);
393 pa_idxset_remove_by_data(s
->core
->sinks
, s
, NULL
);
396 pa_idxset_remove_by_data(s
->card
->sinks
, s
, NULL
);
398 while ((i
= pa_idxset_first(s
->inputs
, NULL
))) {
400 pa_sink_input_kill(i
);
405 sink_set_state(s
, PA_SINK_UNLINKED
);
407 s
->state
= PA_SINK_UNLINKED
;
411 if (s
->monitor_source
)
412 pa_source_unlink(s
->monitor_source
);
415 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
| PA_SUBSCRIPTION_EVENT_REMOVE
, s
->index
);
416 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_UNLINK_POST
], s
);
420 /* Called from main context */
421 static void sink_free(pa_object
*o
) {
422 pa_sink
*s
= PA_SINK(o
);
426 pa_assert(pa_sink_refcnt(s
) == 0);
428 if (PA_SINK_IS_LINKED(s
->state
))
431 pa_log_info("Freeing sink %u \"%s\"", s
->index
, s
->name
);
433 if (s
->monitor_source
) {
434 pa_source_unref(s
->monitor_source
);
435 s
->monitor_source
= NULL
;
438 pa_idxset_free(s
->inputs
, NULL
, NULL
);
440 while ((i
= pa_hashmap_steal_first(s
->thread_info
.inputs
)))
441 pa_sink_input_unref(i
);
443 pa_hashmap_free(s
->thread_info
.inputs
, NULL
, NULL
);
445 if (s
->silence
.memblock
)
446 pa_memblock_unref(s
->silence
.memblock
);
452 pa_proplist_free(s
->proplist
);
457 /* Called from main context */
458 void pa_sink_set_asyncmsgq(pa_sink
*s
, pa_asyncmsgq
*q
) {
459 pa_sink_assert_ref(s
);
463 if (s
->monitor_source
)
464 pa_source_set_asyncmsgq(s
->monitor_source
, q
);
467 /* Called from main context */
468 void pa_sink_set_rtpoll(pa_sink
*s
, pa_rtpoll
*p
) {
469 pa_sink_assert_ref(s
);
472 if (s
->monitor_source
)
473 pa_source_set_rtpoll(s
->monitor_source
, p
);
476 /* Called from main context */
477 int pa_sink_update_status(pa_sink
*s
) {
478 pa_sink_assert_ref(s
);
479 pa_assert(PA_SINK_IS_LINKED(s
->state
));
481 if (s
->state
== PA_SINK_SUSPENDED
)
484 return sink_set_state(s
, pa_sink_used_by(s
) ? PA_SINK_RUNNING
: PA_SINK_IDLE
);
487 /* Called from main context */
488 int pa_sink_suspend(pa_sink
*s
, pa_bool_t suspend
) {
489 pa_sink_assert_ref(s
);
490 pa_assert(PA_SINK_IS_LINKED(s
->state
));
493 return sink_set_state(s
, PA_SINK_SUSPENDED
);
495 return sink_set_state(s
, pa_sink_used_by(s
) ? PA_SINK_RUNNING
: PA_SINK_IDLE
);
498 /* Called from main context */
499 pa_queue
*pa_sink_move_all_start(pa_sink
*s
) {
501 pa_sink_input
*i
, *n
;
504 pa_sink_assert_ref(s
);
505 pa_assert(PA_SINK_IS_LINKED(s
->state
));
509 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= n
) {
510 n
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
));
512 if (pa_sink_input_start_move(i
) >= 0)
513 pa_queue_push(q
, pa_sink_input_ref(i
));
519 /* Called from main context */
520 void pa_sink_move_all_finish(pa_sink
*s
, pa_queue
*q
, pa_bool_t save
) {
523 pa_sink_assert_ref(s
);
524 pa_assert(PA_SINK_IS_LINKED(s
->state
));
527 while ((i
= PA_SINK_INPUT(pa_queue_pop(q
)))) {
528 if (pa_sink_input_finish_move(i
, s
, save
) < 0)
529 pa_sink_input_kill(i
);
531 pa_sink_input_unref(i
);
534 pa_queue_free(q
, NULL
, NULL
);
537 /* Called from main context */
538 void pa_sink_move_all_fail(pa_queue
*q
) {
542 while ((i
= PA_SINK_INPUT(pa_queue_pop(q
)))) {
543 if (pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL
], i
) == PA_HOOK_OK
) {
544 pa_sink_input_kill(i
);
545 pa_sink_input_unref(i
);
549 pa_queue_free(q
, NULL
, NULL
);
552 /* Called from IO thread context */
553 void pa_sink_process_rewind(pa_sink
*s
, size_t nbytes
) {
556 pa_sink_assert_ref(s
);
557 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
559 /* If nobody requested this and this is actually no real rewind
560 * then we can short cut this */
561 if (!s
->thread_info
.rewind_requested
&& nbytes
<= 0)
564 s
->thread_info
.rewind_nbytes
= 0;
565 s
->thread_info
.rewind_requested
= FALSE
;
567 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
)
571 pa_log_debug("Processing rewind...");
573 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
))) {
574 pa_sink_input_assert_ref(i
);
575 pa_sink_input_process_rewind(i
, nbytes
);
579 if (s
->monitor_source
&& PA_SOURCE_IS_LINKED(s
->monitor_source
->thread_info
.state
))
580 pa_source_process_rewind(s
->monitor_source
, nbytes
);
583 /* Called from IO thread context */
584 static unsigned fill_mix_info(pa_sink
*s
, size_t *length
, pa_mix_info
*info
, unsigned maxinfo
) {
588 size_t mixlength
= *length
;
590 pa_sink_assert_ref(s
);
593 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)) && maxinfo
> 0) {
594 pa_sink_input_assert_ref(i
);
596 pa_sink_input_peek(i
, *length
, &info
->chunk
, &info
->volume
);
598 if (mixlength
== 0 || info
->chunk
.length
< mixlength
)
599 mixlength
= info
->chunk
.length
;
601 if (pa_memblock_is_silence(info
->chunk
.memblock
)) {
602 pa_memblock_unref(info
->chunk
.memblock
);
606 info
->userdata
= pa_sink_input_ref(i
);
608 pa_assert(info
->chunk
.memblock
);
609 pa_assert(info
->chunk
.length
> 0);
622 /* Called from IO thread context */
623 static void inputs_drop(pa_sink
*s
, pa_mix_info
*info
, unsigned n
, pa_memchunk
*result
) {
627 unsigned n_unreffed
= 0;
629 pa_sink_assert_ref(s
);
631 pa_assert(result
->memblock
);
632 pa_assert(result
->length
> 0);
634 /* We optimize for the case where the order of the inputs has not changed */
636 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
))) {
638 pa_mix_info
* m
= NULL
;
640 pa_sink_input_assert_ref(i
);
642 /* Let's try to find the matching entry info the pa_mix_info array */
643 for (j
= 0; j
< n
; j
++) {
645 if (info
[p
].userdata
== i
) {
656 pa_sink_input_drop(i
, result
->length
);
658 if (s
->monitor_source
&& PA_SOURCE_IS_LINKED(s
->monitor_source
->thread_info
.state
)) {
660 if (pa_hashmap_size(i
->thread_info
.direct_outputs
) > 0) {
665 if (m
&& m
->chunk
.memblock
) {
667 pa_memblock_ref(c
.memblock
);
668 pa_assert(result
->length
<= c
.length
);
669 c
.length
= result
->length
;
671 pa_memchunk_make_writable(&c
, 0);
672 pa_volume_memchunk(&c
, &s
->sample_spec
, &m
->volume
);
675 pa_memblock_ref(c
.memblock
);
676 pa_assert(result
->length
<= c
.length
);
677 c
.length
= result
->length
;
680 while ((o
= pa_hashmap_iterate(i
->thread_info
.direct_outputs
, &ostate
, NULL
))) {
681 pa_source_output_assert_ref(o
);
682 pa_assert(o
->direct_on_input
== i
);
683 pa_source_post_direct(s
->monitor_source
, o
, &c
);
686 pa_memblock_unref(c
.memblock
);
691 if (m
->chunk
.memblock
)
692 pa_memblock_unref(m
->chunk
.memblock
);
693 pa_memchunk_reset(&m
->chunk
);
695 pa_sink_input_unref(m
->userdata
);
702 /* Now drop references to entries that are included in the
703 * pa_mix_info array but don't exist anymore */
705 if (n_unreffed
< n
) {
706 for (; n
> 0; info
++, n
--) {
708 pa_sink_input_unref(info
->userdata
);
709 if (info
->chunk
.memblock
)
710 pa_memblock_unref(info
->chunk
.memblock
);
714 if (s
->monitor_source
&& PA_SOURCE_IS_LINKED(s
->monitor_source
->thread_info
.state
))
715 pa_source_post(s
->monitor_source
, result
);
718 /* Called from IO thread context */
719 void pa_sink_render(pa_sink
*s
, size_t length
, pa_memchunk
*result
) {
720 pa_mix_info info
[MAX_MIX_CHANNELS
];
722 size_t block_size_max
;
724 pa_sink_assert_ref(s
);
725 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
726 pa_assert(pa_frame_aligned(length
, &s
->sample_spec
));
731 pa_assert(!s
->thread_info
.rewind_requested
);
732 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
734 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
) {
735 result
->memblock
= pa_memblock_ref(s
->silence
.memblock
);
736 result
->index
= s
->silence
.index
;
737 result
->length
= PA_MIN(s
->silence
.length
, length
);
742 length
= pa_frame_align(MIX_BUFFER_LENGTH
, &s
->sample_spec
);
744 block_size_max
= pa_mempool_block_size_max(s
->core
->mempool
);
745 if (length
> block_size_max
)
746 length
= pa_frame_align(block_size_max
, &s
->sample_spec
);
748 pa_assert(length
> 0);
750 n
= fill_mix_info(s
, &length
, info
, MAX_MIX_CHANNELS
);
754 *result
= s
->silence
;
755 pa_memblock_ref(result
->memblock
);
757 if (result
->length
> length
)
758 result
->length
= length
;
763 *result
= info
[0].chunk
;
764 pa_memblock_ref(result
->memblock
);
766 if (result
->length
> length
)
767 result
->length
= length
;
769 pa_sw_cvolume_multiply(&volume
, &s
->thread_info
.soft_volume
, &info
[0].volume
);
771 if (s
->thread_info
.soft_muted
|| !pa_cvolume_is_norm(&volume
)) {
772 pa_memchunk_make_writable(result
, 0);
773 if (s
->thread_info
.soft_muted
|| pa_cvolume_is_muted(&volume
))
774 pa_silence_memchunk(result
, &s
->sample_spec
);
776 pa_volume_memchunk(result
, &s
->sample_spec
, &volume
);
780 result
->memblock
= pa_memblock_new(s
->core
->mempool
, length
);
782 ptr
= pa_memblock_acquire(result
->memblock
);
783 result
->length
= pa_mix(info
, n
,
786 &s
->thread_info
.soft_volume
,
787 s
->thread_info
.soft_muted
);
788 pa_memblock_release(result
->memblock
);
793 inputs_drop(s
, info
, n
, result
);
798 /* Called from IO thread context */
799 void pa_sink_render_into(pa_sink
*s
, pa_memchunk
*target
) {
800 pa_mix_info info
[MAX_MIX_CHANNELS
];
802 size_t length
, block_size_max
;
804 pa_sink_assert_ref(s
);
805 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
807 pa_assert(target
->memblock
);
808 pa_assert(target
->length
> 0);
809 pa_assert(pa_frame_aligned(target
->length
, &s
->sample_spec
));
813 pa_assert(!s
->thread_info
.rewind_requested
);
814 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
816 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
) {
817 pa_silence_memchunk(target
, &s
->sample_spec
);
821 length
= target
->length
;
822 block_size_max
= pa_mempool_block_size_max(s
->core
->mempool
);
823 if (length
> block_size_max
)
824 length
= pa_frame_align(block_size_max
, &s
->sample_spec
);
826 pa_assert(length
> 0);
828 n
= fill_mix_info(s
, &length
, info
, MAX_MIX_CHANNELS
);
831 if (target
->length
> length
)
832 target
->length
= length
;
834 pa_silence_memchunk(target
, &s
->sample_spec
);
838 if (target
->length
> length
)
839 target
->length
= length
;
841 pa_sw_cvolume_multiply(&volume
, &s
->thread_info
.soft_volume
, &info
[0].volume
);
843 if (s
->thread_info
.soft_muted
|| pa_cvolume_is_muted(&volume
))
844 pa_silence_memchunk(target
, &s
->sample_spec
);
848 vchunk
= info
[0].chunk
;
849 pa_memblock_ref(vchunk
.memblock
);
851 if (vchunk
.length
> length
)
852 vchunk
.length
= length
;
854 if (!pa_cvolume_is_norm(&volume
)) {
855 pa_memchunk_make_writable(&vchunk
, 0);
856 pa_volume_memchunk(&vchunk
, &s
->sample_spec
, &volume
);
859 pa_memchunk_memcpy(target
, &vchunk
);
860 pa_memblock_unref(vchunk
.memblock
);
866 ptr
= pa_memblock_acquire(target
->memblock
);
868 target
->length
= pa_mix(info
, n
,
869 (uint8_t*) ptr
+ target
->index
, length
,
871 &s
->thread_info
.soft_volume
,
872 s
->thread_info
.soft_muted
);
874 pa_memblock_release(target
->memblock
);
877 inputs_drop(s
, info
, n
, target
);
882 /* Called from IO thread context */
883 void pa_sink_render_into_full(pa_sink
*s
, pa_memchunk
*target
) {
887 pa_sink_assert_ref(s
);
888 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
890 pa_assert(target
->memblock
);
891 pa_assert(target
->length
> 0);
892 pa_assert(pa_frame_aligned(target
->length
, &s
->sample_spec
));
896 pa_assert(!s
->thread_info
.rewind_requested
);
897 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
906 pa_sink_render_into(s
, &chunk
);
915 /* Called from IO thread context */
916 void pa_sink_render_full(pa_sink
*s
, size_t length
, pa_memchunk
*result
) {
917 pa_sink_assert_ref(s
);
918 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
919 pa_assert(length
> 0);
920 pa_assert(pa_frame_aligned(length
, &s
->sample_spec
));
923 pa_assert(!s
->thread_info
.rewind_requested
);
924 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
926 /*** This needs optimization ***/
929 result
->length
= length
;
930 result
->memblock
= pa_memblock_new(s
->core
->mempool
, length
);
932 pa_sink_render_into_full(s
, result
);
935 /* Called from main thread */
936 pa_usec_t
pa_sink_get_latency(pa_sink
*s
) {
939 pa_sink_assert_ref(s
);
940 pa_assert(PA_SINK_IS_LINKED(s
->state
));
942 /* The returned value is supposed to be in the time domain of the sound card! */
944 if (s
->state
== PA_SINK_SUSPENDED
)
947 if (!(s
->flags
& PA_SINK_LATENCY
))
950 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) == 0);
955 /* Called from main thread */
956 void pa_sink_update_flat_volume(pa_sink
*s
, pa_cvolume
*new_volume
) {
960 pa_sink_assert_ref(s
);
961 pa_assert(new_volume
);
962 pa_assert(PA_SINK_IS_LINKED(s
->state
));
963 pa_assert(s
->flags
& PA_SINK_FLAT_VOLUME
);
965 /* This is called whenever a sink input volume changes and we
966 * might need to fix up the sink volume accordingly. Please note
967 * that we don't actually update the sinks volume here, we only
968 * return how it needs to be updated. The caller should then call
969 * pa_sink_set_flat_volume().*/
971 if (pa_idxset_isempty(s
->inputs
)) {
972 /* In the special case that we have no sink input we leave the
973 * volume unmodified. */
974 *new_volume
= s
->virtual_volume
;
978 pa_cvolume_mute(new_volume
, s
->channel_map
.channels
);
980 /* First let's determine the new maximum volume of all inputs
981 * connected to this sink */
982 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
984 pa_cvolume remapped_volume
;
986 remapped_volume
= i
->virtual_volume
;
987 pa_cvolume_remap(&remapped_volume
, &i
->channel_map
, &s
->channel_map
);
989 for (c
= 0; c
< new_volume
->channels
; c
++)
990 if (remapped_volume
.values
[c
] > new_volume
->values
[c
])
991 new_volume
->values
[c
] = remapped_volume
.values
[c
];
994 /* Then, let's update the soft volumes of all inputs connected
996 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
997 pa_cvolume remapped_new_volume
;
999 remapped_new_volume
= *new_volume
;
1000 pa_cvolume_remap(&remapped_new_volume
, &s
->channel_map
, &i
->channel_map
);
1001 pa_sw_cvolume_divide(&i
->soft_volume
, &i
->virtual_volume
, &remapped_new_volume
);
1002 pa_sw_cvolume_multiply(&i
->soft_volume
, &i
->soft_volume
, &i
->volume_factor
);
1004 /* Hooks have the ability to play games with i->soft_volume */
1005 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME
], i
);
1007 /* We don't issue PA_SINK_INPUT_MESSAGE_SET_VOLUME because
1008 * we want the update to have atomically with the sink
1009 * volume update, hence we do it within the
1010 * pa_sink_set_flat_volume() call below*/
1014 /* Called from main thread */
1015 void pa_sink_propagate_flat_volume(pa_sink
*s
, const pa_cvolume
*old_volume
) {
1019 pa_sink_assert_ref(s
);
1020 pa_assert(old_volume
);
1021 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1022 pa_assert(s
->flags
& PA_SINK_FLAT_VOLUME
);
1024 /* This is called whenever the sink volume changes that is not
1025 * caused by a sink input volume change. We need to fix up the
1026 * sink input volumes accordingly */
1028 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
1029 pa_cvolume remapped_old_volume
, remapped_new_volume
, fixed_volume
;
1032 remapped_new_volume
= s
->virtual_volume
;
1033 pa_cvolume_remap(&remapped_new_volume
, &s
->channel_map
, &i
->channel_map
);
1035 remapped_old_volume
= *old_volume
;
1036 pa_cvolume_remap(&remapped_old_volume
, &s
->channel_map
, &i
->channel_map
);
1038 for (c
= 0; c
< i
->sample_spec
.channels
; c
++)
1040 if (remapped_old_volume
.values
[c
] == PA_VOLUME_MUTED
)
1041 fixed_volume
.values
[c
] = PA_VOLUME_MUTED
;
1043 fixed_volume
.values
[c
] = (pa_volume_t
)
1044 ((uint64_t) i
->virtual_volume
.values
[c
] *
1045 (uint64_t) remapped_new_volume
.values
[c
] /
1046 (uint64_t) remapped_old_volume
.values
[c
]);
1048 fixed_volume
.channels
= i
->virtual_volume
.channels
;
1050 if (!pa_cvolume_equal(&fixed_volume
, &i
->virtual_volume
)) {
1051 i
->virtual_volume
= fixed_volume
;
1053 /* The virtual volume changed, let's tell people so */
1054 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1059 /* Called from main thread */
1060 void pa_sink_set_volume(pa_sink
*s
, const pa_cvolume
*volume
, pa_bool_t propagate
, pa_bool_t sendmsg
) {
1061 pa_cvolume old_virtual_volume
;
1062 pa_bool_t virtual_volume_changed
;
1064 pa_sink_assert_ref(s
);
1065 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1067 pa_assert(pa_cvolume_valid(volume
));
1068 pa_assert(pa_cvolume_compatible(volume
, &s
->sample_spec
));
1070 old_virtual_volume
= s
->virtual_volume
;
1071 s
->virtual_volume
= *volume
;
1072 virtual_volume_changed
= !pa_cvolume_equal(&old_virtual_volume
, &s
->virtual_volume
);
1074 /* Propagate this volume change back to the inputs */
1075 if (virtual_volume_changed
)
1076 if (propagate
&& (s
->flags
& PA_SINK_FLAT_VOLUME
))
1077 pa_sink_propagate_flat_volume(s
, &old_virtual_volume
);
1079 if (s
->set_volume
) {
1080 /* If we have a function set_volume(), then we do not apply a
1081 * soft volume by default. However, set_volume() is apply one
1082 * to s->soft_volume */
1084 pa_cvolume_reset(&s
->soft_volume
, s
->sample_spec
.channels
);
1088 /* If we have no function set_volume(), then the soft volume
1089 * becomes the virtual volume */
1090 s
->soft_volume
= s
->virtual_volume
;
1092 /* This tells the sink that soft and/or virtual volume changed */
1094 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
) == 0);
1096 if (virtual_volume_changed
)
1097 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1100 /* Called from main thread. Only to be called by sink implementor */
1101 void pa_sink_set_soft_volume(pa_sink
*s
, const pa_cvolume
*volume
) {
1102 pa_sink_assert_ref(s
);
1105 s
->soft_volume
= *volume
;
1107 if (PA_SINK_IS_LINKED(s
->state
))
1108 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
) == 0);
1110 s
->thread_info
.soft_volume
= *volume
;
1113 /* Called from main thread */
1114 const pa_cvolume
*pa_sink_get_volume(pa_sink
*s
, pa_bool_t force_refresh
) {
1115 pa_sink_assert_ref(s
);
1117 if (s
->refresh_volume
|| force_refresh
) {
1118 struct pa_cvolume old_virtual_volume
= s
->virtual_volume
;
1123 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_VOLUME
, NULL
, 0, NULL
) == 0);
1125 if (!pa_cvolume_equal(&old_virtual_volume
, &s
->virtual_volume
)) {
1127 if (s
->flags
& PA_SINK_FLAT_VOLUME
)
1128 pa_sink_propagate_flat_volume(s
, &old_virtual_volume
);
1130 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1134 return &s
->virtual_volume
;
1137 /* Called from main thread */
1138 void pa_sink_volume_changed(pa_sink
*s
, const pa_cvolume
*new_volume
) {
1139 pa_sink_assert_ref(s
);
1141 /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1143 if (pa_cvolume_equal(&s
->virtual_volume
, new_volume
))
1146 s
->virtual_volume
= *new_volume
;
1147 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1150 /* Called from main thread */
1151 void pa_sink_set_mute(pa_sink
*s
, pa_bool_t mute
) {
1152 pa_bool_t old_muted
;
1154 pa_sink_assert_ref(s
);
1155 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1157 old_muted
= s
->muted
;
1163 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_MUTE
, NULL
, 0, NULL
) == 0);
1165 if (old_muted
!= s
->muted
)
1166 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1169 /* Called from main thread */
1170 pa_bool_t
pa_sink_get_mute(pa_sink
*s
, pa_bool_t force_refresh
) {
1172 pa_sink_assert_ref(s
);
1174 if (s
->refresh_muted
|| force_refresh
) {
1175 pa_bool_t old_muted
= s
->muted
;
1180 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_MUTE
, NULL
, 0, NULL
) == 0);
1182 if (old_muted
!= s
->muted
)
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_mute_changed(pa_sink
*s
, pa_bool_t new_muted
) {
1191 pa_sink_assert_ref(s
);
1193 /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1195 if (s
->muted
== new_muted
)
1198 s
->muted
= new_muted
;
1199 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1202 /* Called from main thread */
1203 pa_bool_t
pa_sink_update_proplist(pa_sink
*s
, pa_update_mode_t mode
, pa_proplist
*p
) {
1204 pa_sink_assert_ref(s
);
1207 pa_proplist_update(s
->proplist
, mode
, p
);
1209 if (PA_SINK_IS_LINKED(s
->state
)) {
1210 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_PROPLIST_CHANGED
], s
);
1211 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1217 /* Called from main thread */
1218 void pa_sink_set_description(pa_sink
*s
, const char *description
) {
1220 pa_sink_assert_ref(s
);
1222 if (!description
&& !pa_proplist_contains(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
))
1225 old
= pa_proplist_gets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1227 if (old
&& description
&& !strcmp(old
, description
))
1231 pa_proplist_sets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
, description
);
1233 pa_proplist_unset(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1235 if (s
->monitor_source
) {
1238 n
= pa_sprintf_malloc("Monitor Source of %s", description
? description
: s
->name
);
1239 pa_source_set_description(s
->monitor_source
, n
);
1243 if (PA_SINK_IS_LINKED(s
->state
)) {
1244 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1245 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_PROPLIST_CHANGED
], s
);
1249 /* Called from main thread */
1250 unsigned pa_sink_linked_by(pa_sink
*s
) {
1253 pa_sink_assert_ref(s
);
1254 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1256 ret
= pa_idxset_size(s
->inputs
);
1258 /* We add in the number of streams connected to us here. Please
1259 * note the asymmmetry to pa_sink_used_by()! */
1261 if (s
->monitor_source
)
1262 ret
+= pa_source_linked_by(s
->monitor_source
);
1267 /* Called from main thread */
1268 unsigned pa_sink_used_by(pa_sink
*s
) {
1271 pa_sink_assert_ref(s
);
1272 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1274 ret
= pa_idxset_size(s
->inputs
);
1275 pa_assert(ret
>= s
->n_corked
);
1277 /* Streams connected to our monitor source do not matter for
1278 * pa_sink_used_by()!.*/
1280 return ret
- s
->n_corked
;
1283 /* Called from main thread */
1284 unsigned pa_sink_check_suspend(pa_sink
*s
) {
1289 pa_sink_assert_ref(s
);
1291 if (!PA_SINK_IS_LINKED(s
->state
))
1296 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
1297 pa_sink_input_state_t st
;
1299 st
= pa_sink_input_get_state(i
);
1300 pa_assert(PA_SINK_INPUT_IS_LINKED(st
));
1302 if (st
== PA_SINK_INPUT_CORKED
)
1305 if (i
->flags
& PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
)
1311 if (s
->monitor_source
)
1312 ret
+= pa_source_check_suspend(s
->monitor_source
);
1317 /* Called from the IO thread */
1318 static void sync_input_volumes_within_thread(pa_sink
*s
) {
1322 pa_sink_assert_ref(s
);
1324 while ((i
= PA_SINK_INPUT(pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))) {
1325 if (pa_cvolume_equal(&i
->thread_info
.soft_volume
, &i
->soft_volume
))
1328 i
->thread_info
.soft_volume
= i
->soft_volume
;
1329 pa_sink_input_request_rewind(i
, 0, TRUE
, FALSE
, FALSE
);
1333 /* Called from IO thread, except when it is not */
1334 int pa_sink_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1335 pa_sink
*s
= PA_SINK(o
);
1336 pa_sink_assert_ref(s
);
1338 switch ((pa_sink_message_t
) code
) {
1340 case PA_SINK_MESSAGE_ADD_INPUT
: {
1341 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1343 /* If you change anything here, make sure to change the
1344 * sink input handling a few lines down at
1345 * PA_SINK_MESSAGE_FINISH_MOVE, too. */
1347 pa_hashmap_put(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
), pa_sink_input_ref(i
));
1349 /* Since the caller sleeps in pa_sink_input_put(), we can
1350 * safely access data outside of thread_info even though
1353 if ((i
->thread_info
.sync_prev
= i
->sync_prev
)) {
1354 pa_assert(i
->sink
== i
->thread_info
.sync_prev
->sink
);
1355 pa_assert(i
->sync_prev
->sync_next
== i
);
1356 i
->thread_info
.sync_prev
->thread_info
.sync_next
= i
;
1359 if ((i
->thread_info
.sync_next
= i
->sync_next
)) {
1360 pa_assert(i
->sink
== i
->thread_info
.sync_next
->sink
);
1361 pa_assert(i
->sync_next
->sync_prev
== i
);
1362 i
->thread_info
.sync_next
->thread_info
.sync_prev
= i
;
1365 pa_assert(!i
->thread_info
.attached
);
1366 i
->thread_info
.attached
= TRUE
;
1371 pa_sink_input_set_state_within_thread(i
, i
->state
);
1373 /* The requested latency of the sink input needs to be
1374 * fixed up and then configured on the sink */
1376 if (i
->thread_info
.requested_sink_latency
!= (pa_usec_t
) -1)
1377 pa_sink_input_set_requested_latency_within_thread(i
, i
->thread_info
.requested_sink_latency
);
1379 pa_sink_input_update_max_rewind(i
, s
->thread_info
.max_rewind
);
1380 pa_sink_input_update_max_request(i
, s
->thread_info
.max_request
);
1382 /* We don't rewind here automatically. This is left to the
1383 * sink input implementor because some sink inputs need a
1384 * slow start, i.e. need some time to buffer client
1385 * samples before beginning streaming. */
1387 /* In flat volume mode we need to update the volume as
1389 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1392 case PA_SINK_MESSAGE_REMOVE_INPUT
: {
1393 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1395 /* If you change anything here, make sure to change the
1396 * sink input handling a few lines down at
1397 * PA_SINK_MESSAGE_PREPAPRE_MOVE, too. */
1402 pa_sink_input_set_state_within_thread(i
, i
->state
);
1404 pa_assert(i
->thread_info
.attached
);
1405 i
->thread_info
.attached
= FALSE
;
1407 /* Since the caller sleeps in pa_sink_input_unlink(),
1408 * we can safely access data outside of thread_info even
1409 * though it is mutable */
1411 pa_assert(!i
->sync_prev
);
1412 pa_assert(!i
->sync_next
);
1414 if (i
->thread_info
.sync_prev
) {
1415 i
->thread_info
.sync_prev
->thread_info
.sync_next
= i
->thread_info
.sync_prev
->sync_next
;
1416 i
->thread_info
.sync_prev
= NULL
;
1419 if (i
->thread_info
.sync_next
) {
1420 i
->thread_info
.sync_next
->thread_info
.sync_prev
= i
->thread_info
.sync_next
->sync_prev
;
1421 i
->thread_info
.sync_next
= NULL
;
1424 if (pa_hashmap_remove(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
)))
1425 pa_sink_input_unref(i
);
1427 pa_sink_invalidate_requested_latency(s
);
1428 pa_sink_request_rewind(s
, (size_t) -1);
1430 /* In flat volume mode we need to update the volume as
1432 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1435 case PA_SINK_MESSAGE_START_MOVE
: {
1436 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1438 /* We don't support moving synchronized streams. */
1439 pa_assert(!i
->sync_prev
);
1440 pa_assert(!i
->sync_next
);
1441 pa_assert(!i
->thread_info
.sync_next
);
1442 pa_assert(!i
->thread_info
.sync_prev
);
1444 if (i
->thread_info
.state
!= PA_SINK_INPUT_CORKED
) {
1446 size_t sink_nbytes
, total_nbytes
;
1448 /* Get the latency of the sink */
1449 if (!(s
->flags
& PA_SINK_LATENCY
) ||
1450 PA_MSGOBJECT(s
)->process_msg(PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) < 0)
1453 sink_nbytes
= pa_usec_to_bytes(usec
, &s
->sample_spec
);
1454 total_nbytes
= sink_nbytes
+ pa_memblockq_get_length(i
->thread_info
.render_memblockq
);
1456 if (total_nbytes
> 0) {
1457 i
->thread_info
.rewrite_nbytes
= i
->thread_info
.resampler
? pa_resampler_request(i
->thread_info
.resampler
, total_nbytes
) : total_nbytes
;
1458 i
->thread_info
.rewrite_flush
= TRUE
;
1459 pa_sink_input_process_rewind(i
, sink_nbytes
);
1466 pa_assert(i
->thread_info
.attached
);
1467 i
->thread_info
.attached
= FALSE
;
1469 /* Let's remove the sink input ...*/
1470 if (pa_hashmap_remove(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
)))
1471 pa_sink_input_unref(i
);
1473 pa_sink_invalidate_requested_latency(s
);
1475 pa_log_debug("Requesting rewind due to started move");
1476 pa_sink_request_rewind(s
, (size_t) -1);
1478 /* In flat volume mode we need to update the volume as
1480 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1483 case PA_SINK_MESSAGE_FINISH_MOVE
: {
1484 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1486 /* We don't support moving synchronized streams. */
1487 pa_assert(!i
->sync_prev
);
1488 pa_assert(!i
->sync_next
);
1489 pa_assert(!i
->thread_info
.sync_next
);
1490 pa_assert(!i
->thread_info
.sync_prev
);
1492 pa_hashmap_put(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
), pa_sink_input_ref(i
));
1494 pa_assert(!i
->thread_info
.attached
);
1495 i
->thread_info
.attached
= TRUE
;
1500 if (i
->thread_info
.requested_sink_latency
!= (pa_usec_t
) -1)
1501 pa_sink_input_set_requested_latency_within_thread(i
, i
->thread_info
.requested_sink_latency
);
1503 pa_sink_input_update_max_rewind(i
, s
->thread_info
.max_rewind
);
1504 pa_sink_input_update_max_request(i
, s
->thread_info
.max_request
);
1506 if (i
->thread_info
.state
!= PA_SINK_INPUT_CORKED
) {
1510 /* Get the latency of the sink */
1511 if (!(s
->flags
& PA_SINK_LATENCY
) ||
1512 PA_MSGOBJECT(s
)->process_msg(PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) < 0)
1515 nbytes
= pa_usec_to_bytes(usec
, &s
->sample_spec
);
1518 pa_sink_input_drop(i
, nbytes
);
1520 pa_log_debug("Requesting rewind due to finished move");
1521 pa_sink_request_rewind(s
, nbytes
);
1524 /* In flat volume mode we need to update the volume as
1526 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1529 case PA_SINK_MESSAGE_SET_VOLUME
:
1531 if (!pa_cvolume_equal(&s
->thread_info
.soft_volume
, &s
->soft_volume
)) {
1532 s
->thread_info
.soft_volume
= s
->soft_volume
;
1533 pa_sink_request_rewind(s
, (size_t) -1);
1536 if (s
->flags
& PA_SINK_FLAT_VOLUME
)
1537 sync_input_volumes_within_thread(s
);
1541 case PA_SINK_MESSAGE_GET_VOLUME
:
1544 case PA_SINK_MESSAGE_SET_MUTE
:
1546 if (s
->thread_info
.soft_muted
!= s
->muted
) {
1547 s
->thread_info
.soft_muted
= s
->muted
;
1548 pa_sink_request_rewind(s
, (size_t) -1);
1553 case PA_SINK_MESSAGE_GET_MUTE
:
1556 case PA_SINK_MESSAGE_SET_STATE
:
1558 s
->thread_info
.state
= PA_PTR_TO_UINT(userdata
);
1560 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
) {
1561 s
->thread_info
.rewind_nbytes
= 0;
1562 s
->thread_info
.rewind_requested
= FALSE
;
1567 case PA_SINK_MESSAGE_DETACH
:
1569 /* Detach all streams */
1570 pa_sink_detach_within_thread(s
);
1573 case PA_SINK_MESSAGE_ATTACH
:
1575 /* Reattach all streams */
1576 pa_sink_attach_within_thread(s
);
1579 case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY
: {
1581 pa_usec_t
*usec
= userdata
;
1582 *usec
= pa_sink_get_requested_latency_within_thread(s
);
1584 if (*usec
== (pa_usec_t
) -1)
1585 *usec
= s
->thread_info
.max_latency
;
1590 case PA_SINK_MESSAGE_SET_LATENCY_RANGE
: {
1591 pa_usec_t
*r
= userdata
;
1593 pa_sink_set_latency_range_within_thread(s
, r
[0], r
[1]);
1598 case PA_SINK_MESSAGE_GET_LATENCY_RANGE
: {
1599 pa_usec_t
*r
= userdata
;
1601 r
[0] = s
->thread_info
.min_latency
;
1602 r
[1] = s
->thread_info
.max_latency
;
1607 case PA_SINK_MESSAGE_GET_MAX_REWIND
:
1609 *((size_t*) userdata
) = s
->thread_info
.max_rewind
;
1612 case PA_SINK_MESSAGE_GET_MAX_REQUEST
:
1614 *((size_t*) userdata
) = s
->thread_info
.max_request
;
1617 case PA_SINK_MESSAGE_SET_MAX_REWIND
:
1619 pa_sink_set_max_rewind_within_thread(s
, (size_t) offset
);
1622 case PA_SINK_MESSAGE_SET_MAX_REQUEST
:
1624 pa_sink_set_max_request_within_thread(s
, (size_t) offset
);
1627 case PA_SINK_MESSAGE_GET_LATENCY
:
1628 case PA_SINK_MESSAGE_MAX
:
1635 /* Called from main thread */
1636 int pa_sink_suspend_all(pa_core
*c
, pa_bool_t suspend
) {
1641 pa_core_assert_ref(c
);
1643 for (sink
= PA_SINK(pa_idxset_first(c
->sinks
, &idx
)); sink
; sink
= PA_SINK(pa_idxset_next(c
->sinks
, &idx
))) {
1646 if ((r
= pa_sink_suspend(sink
, suspend
)) < 0)
1653 /* Called from main thread */
1654 void pa_sink_detach(pa_sink
*s
) {
1655 pa_sink_assert_ref(s
);
1656 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1658 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_DETACH
, NULL
, 0, NULL
) == 0);
1661 /* Called from main thread */
1662 void pa_sink_attach(pa_sink
*s
) {
1663 pa_sink_assert_ref(s
);
1664 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1666 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_ATTACH
, NULL
, 0, NULL
) == 0);
1669 /* Called from IO thread */
1670 void pa_sink_detach_within_thread(pa_sink
*s
) {
1674 pa_sink_assert_ref(s
);
1675 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
1677 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1681 if (s
->monitor_source
)
1682 pa_source_detach_within_thread(s
->monitor_source
);
1685 /* Called from IO thread */
1686 void pa_sink_attach_within_thread(pa_sink
*s
) {
1690 pa_sink_assert_ref(s
);
1691 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
1693 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1697 if (s
->monitor_source
)
1698 pa_source_attach_within_thread(s
->monitor_source
);
1701 /* Called from IO thread */
1702 void pa_sink_request_rewind(pa_sink
*s
, size_t nbytes
) {
1703 pa_sink_assert_ref(s
);
1704 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
1706 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
)
1709 if (nbytes
== (size_t) -1)
1710 nbytes
= s
->thread_info
.max_rewind
;
1712 nbytes
= PA_MIN(nbytes
, s
->thread_info
.max_rewind
);
1714 if (s
->thread_info
.rewind_requested
&&
1715 nbytes
<= s
->thread_info
.rewind_nbytes
)
1718 s
->thread_info
.rewind_nbytes
= nbytes
;
1719 s
->thread_info
.rewind_requested
= TRUE
;
1721 if (s
->request_rewind
)
1722 s
->request_rewind(s
);
1725 /* Called from IO thread */
1726 pa_usec_t
pa_sink_get_requested_latency_within_thread(pa_sink
*s
) {
1727 pa_usec_t result
= (pa_usec_t
) -1;
1730 pa_usec_t monitor_latency
;
1732 pa_sink_assert_ref(s
);
1734 if (s
->thread_info
.requested_latency_valid
)
1735 return s
->thread_info
.requested_latency
;
1737 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1739 if (i
->thread_info
.requested_sink_latency
!= (pa_usec_t
) -1 &&
1740 (result
== (pa_usec_t
) -1 || result
> i
->thread_info
.requested_sink_latency
))
1741 result
= i
->thread_info
.requested_sink_latency
;
1743 monitor_latency
= pa_source_get_requested_latency_within_thread(s
->monitor_source
);
1745 if (monitor_latency
!= (pa_usec_t
) -1 &&
1746 (result
== (pa_usec_t
) -1 || result
> monitor_latency
))
1747 result
= monitor_latency
;
1749 if (result
!= (pa_usec_t
) -1) {
1750 if (result
> s
->thread_info
.max_latency
)
1751 result
= s
->thread_info
.max_latency
;
1753 if (result
< s
->thread_info
.min_latency
)
1754 result
= s
->thread_info
.min_latency
;
1757 s
->thread_info
.requested_latency
= result
;
1758 s
->thread_info
.requested_latency_valid
= TRUE
;
1763 /* Called from main thread */
1764 pa_usec_t
pa_sink_get_requested_latency(pa_sink
*s
) {
1767 pa_sink_assert_ref(s
);
1768 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1770 if (s
->state
== PA_SINK_SUSPENDED
)
1773 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY
, &usec
, 0, NULL
) == 0);
1777 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
1778 void pa_sink_set_max_rewind_within_thread(pa_sink
*s
, size_t max_rewind
) {
1782 pa_sink_assert_ref(s
);
1784 if (max_rewind
== s
->thread_info
.max_rewind
)
1787 s
->thread_info
.max_rewind
= max_rewind
;
1789 if (PA_SINK_IS_LINKED(s
->thread_info
.state
)) {
1790 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1791 pa_sink_input_update_max_rewind(i
, s
->thread_info
.max_rewind
);
1794 if (s
->monitor_source
)
1795 pa_source_set_max_rewind(s
->monitor_source
, s
->thread_info
.max_rewind
);
1798 /* Called from main thread */
1799 void pa_sink_set_max_rewind(pa_sink
*s
, size_t max_rewind
) {
1800 pa_sink_assert_ref(s
);
1802 if (PA_SINK_IS_LINKED(s
->state
))
1803 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_MAX_REWIND
, NULL
, max_rewind
, NULL
) == 0);
1805 pa_sink_set_max_rewind_within_thread(s
, max_rewind
);
1808 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
1809 void pa_sink_set_max_request_within_thread(pa_sink
*s
, size_t max_request
) {
1812 pa_sink_assert_ref(s
);
1814 if (max_request
== s
->thread_info
.max_request
)
1817 s
->thread_info
.max_request
= max_request
;
1819 if (PA_SINK_IS_LINKED(s
->thread_info
.state
)) {
1822 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1823 pa_sink_input_update_max_request(i
, s
->thread_info
.max_request
);
1827 /* Called from main thread */
1828 void pa_sink_set_max_request(pa_sink
*s
, size_t max_request
) {
1829 pa_sink_assert_ref(s
);
1831 if (PA_SINK_IS_LINKED(s
->state
))
1832 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_MAX_REQUEST
, NULL
, max_request
, NULL
) == 0);
1834 pa_sink_set_max_request_within_thread(s
, max_request
);
1837 /* Called from IO thread */
1838 void pa_sink_invalidate_requested_latency(pa_sink
*s
) {
1842 pa_sink_assert_ref(s
);
1844 s
->thread_info
.requested_latency_valid
= FALSE
;
1846 if (s
->update_requested_latency
)
1847 s
->update_requested_latency(s
);
1849 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1850 if (i
->update_sink_requested_latency
)
1851 i
->update_sink_requested_latency(i
);
1854 /* Called from main thread */
1855 void pa_sink_set_latency_range(pa_sink
*s
, pa_usec_t min_latency
, pa_usec_t max_latency
) {
1856 pa_sink_assert_ref(s
);
1858 /* min_latency == 0: no limit
1859 * min_latency anything else: specified limit
1861 * Similar for max_latency */
1863 if (min_latency
< ABSOLUTE_MIN_LATENCY
)
1864 min_latency
= ABSOLUTE_MIN_LATENCY
;
1866 if (max_latency
<= 0 ||
1867 max_latency
> ABSOLUTE_MAX_LATENCY
)
1868 max_latency
= ABSOLUTE_MAX_LATENCY
;
1870 pa_assert(min_latency
<= max_latency
);
1872 if (PA_SINK_IS_LINKED(s
->state
)) {
1878 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_LATENCY_RANGE
, r
, 0, NULL
) == 0);
1880 s
->thread_info
.min_latency
= min_latency
;
1881 s
->thread_info
.max_latency
= max_latency
;
1883 s
->monitor_source
->thread_info
.min_latency
= min_latency
;
1884 s
->monitor_source
->thread_info
.max_latency
= max_latency
;
1886 s
->thread_info
.requested_latency_valid
= s
->monitor_source
->thread_info
.requested_latency_valid
= FALSE
;
1890 /* Called from main thread */
1891 void pa_sink_get_latency_range(pa_sink
*s
, pa_usec_t
*min_latency
, pa_usec_t
*max_latency
) {
1892 pa_sink_assert_ref(s
);
1893 pa_assert(min_latency
);
1894 pa_assert(max_latency
);
1896 if (PA_SINK_IS_LINKED(s
->state
)) {
1897 pa_usec_t r
[2] = { 0, 0 };
1899 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY_RANGE
, r
, 0, NULL
) == 0);
1901 *min_latency
= r
[0];
1902 *max_latency
= r
[1];
1904 *min_latency
= s
->thread_info
.min_latency
;
1905 *max_latency
= s
->thread_info
.max_latency
;
1909 /* Called from IO thread */
1910 void pa_sink_set_latency_range_within_thread(pa_sink
*s
, pa_usec_t min_latency
, pa_usec_t max_latency
) {
1914 pa_sink_assert_ref(s
);
1916 pa_assert(min_latency
>= ABSOLUTE_MIN_LATENCY
);
1917 pa_assert(max_latency
<= ABSOLUTE_MAX_LATENCY
);
1918 pa_assert(min_latency
<= max_latency
);
1920 s
->thread_info
.min_latency
= min_latency
;
1921 s
->thread_info
.max_latency
= max_latency
;
1923 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1924 if (i
->update_sink_latency_range
)
1925 i
->update_sink_latency_range(i
);
1927 pa_sink_invalidate_requested_latency(s
);
1929 pa_source_set_latency_range_within_thread(s
->monitor_source
, min_latency
, max_latency
);
1932 /* Called from main context */
1933 size_t pa_sink_get_max_rewind(pa_sink
*s
) {
1935 pa_sink_assert_ref(s
);
1937 if (!PA_SINK_IS_LINKED(s
->state
))
1938 return s
->thread_info
.max_rewind
;
1940 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_MAX_REWIND
, &r
, 0, NULL
) == 0);
1945 /* Called from main context */
1946 size_t pa_sink_get_max_request(pa_sink
*s
) {
1948 pa_sink_assert_ref(s
);
1950 if (!PA_SINK_IS_LINKED(s
->state
))
1951 return s
->thread_info
.max_request
;
1953 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_MAX_REQUEST
, &r
, 0, NULL
) == 0);
1958 /* Called from main context */
1959 pa_bool_t
pa_device_init_icon(pa_proplist
*p
, pa_bool_t is_sink
) {
1960 const char *ff
, *c
, *t
= NULL
, *s
= "", *profile
, *bus
;
1964 if (pa_proplist_contains(p
, PA_PROP_DEVICE_ICON_NAME
))
1967 if ((ff
= pa_proplist_gets(p
, PA_PROP_DEVICE_FORM_FACTOR
))) {
1969 if (pa_streq(ff
, "microphone"))
1970 t
= "audio-input-microphone";
1971 else if (pa_streq(ff
, "webcam"))
1973 else if (pa_streq(ff
, "computer"))
1975 else if (pa_streq(ff
, "handset"))
1977 else if (pa_streq(ff
, "portable"))
1978 t
= "multimedia-player";
1979 else if (pa_streq(ff
, "tv"))
1980 t
= "video-display";
1984 if ((c
= pa_proplist_gets(p
, PA_PROP_DEVICE_CLASS
)))
1985 if (pa_streq(c
, "modem"))
1992 t
= "audio-input-microphone";
1995 if ((profile
= pa_proplist_gets(p
, PA_PROP_DEVICE_PROFILE_NAME
))) {
1996 if (strstr(profile
, "analog"))
1998 else if (strstr(profile
, "iec958"))
2000 else if (strstr(profile
, "hdmi"))
2004 bus
= pa_proplist_gets(p
, PA_PROP_DEVICE_BUS
);
2006 pa_proplist_setf(p
, PA_PROP_DEVICE_ICON_NAME
, "%s%s%s%s", t
, pa_strempty(s
), bus
? "-" : "", pa_strempty(bus
));
2011 pa_bool_t
pa_device_init_description(pa_proplist
*p
) {
2015 if (pa_proplist_contains(p
, PA_PROP_DEVICE_DESCRIPTION
))
2018 if ((s
= pa_proplist_gets(p
, PA_PROP_DEVICE_FORM_FACTOR
)))
2019 if (pa_streq(s
, "internal")) {
2020 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, _("Internal Audio"));
2024 if ((s
= pa_proplist_gets(p
, PA_PROP_DEVICE_CLASS
)))
2025 if (pa_streq(s
, "modem")) {
2026 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, _("Modem"));
2030 if ((s
= pa_proplist_gets(p
, PA_PROP_DEVICE_PRODUCT_NAME
))) {
2031 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);