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 DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
53 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
55 static PA_DEFINE_CHECK_TYPE(pa_sink
, pa_msgobject
);
57 static void sink_free(pa_object
*s
);
59 pa_sink_new_data
* pa_sink_new_data_init(pa_sink_new_data
*data
) {
62 memset(data
, 0, sizeof(*data
));
63 data
->proplist
= pa_proplist_new();
68 void pa_sink_new_data_set_name(pa_sink_new_data
*data
, const char *name
) {
72 data
->name
= pa_xstrdup(name
);
75 void pa_sink_new_data_set_sample_spec(pa_sink_new_data
*data
, const pa_sample_spec
*spec
) {
78 if ((data
->sample_spec_is_set
= !!spec
))
79 data
->sample_spec
= *spec
;
82 void pa_sink_new_data_set_channel_map(pa_sink_new_data
*data
, const pa_channel_map
*map
) {
85 if ((data
->channel_map_is_set
= !!map
))
86 data
->channel_map
= *map
;
89 void pa_sink_new_data_set_volume(pa_sink_new_data
*data
, const pa_cvolume
*volume
) {
92 if ((data
->volume_is_set
= !!volume
))
93 data
->volume
= *volume
;
96 void pa_sink_new_data_set_muted(pa_sink_new_data
*data
, pa_bool_t mute
) {
99 data
->muted_is_set
= TRUE
;
100 data
->muted
= !!mute
;
103 void pa_sink_new_data_done(pa_sink_new_data
*data
) {
106 pa_xfree(data
->name
);
107 pa_proplist_free(data
->proplist
);
110 /* Called from main context */
111 static void reset_callbacks(pa_sink
*s
) {
115 s
->get_volume
= NULL
;
116 s
->set_volume
= NULL
;
119 s
->request_rewind
= NULL
;
120 s
->update_requested_latency
= NULL
;
123 /* Called from main context */
124 pa_sink
* pa_sink_new(
126 pa_sink_new_data
*data
,
127 pa_sink_flags_t flags
) {
131 char st
[PA_SAMPLE_SPEC_SNPRINT_MAX
], cm
[PA_CHANNEL_MAP_SNPRINT_MAX
];
132 pa_source_new_data source_data
;
138 pa_assert(data
->name
);
140 s
= pa_msgobject_new(pa_sink
);
142 if (!(name
= pa_namereg_register(core
, data
->name
, PA_NAMEREG_SINK
, s
, data
->namereg_fail
))) {
147 pa_sink_new_data_set_name(data
, name
);
149 if (pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SINK_NEW
], data
) < 0) {
151 pa_namereg_unregister(core
, name
);
155 pa_return_null_if_fail(!data
->driver
|| pa_utf8_valid(data
->driver
));
156 pa_return_null_if_fail(data
->name
&& pa_utf8_valid(data
->name
) && data
->name
[0]);
158 pa_return_null_if_fail(data
->sample_spec_is_set
&& pa_sample_spec_valid(&data
->sample_spec
));
160 if (!data
->channel_map_is_set
)
161 pa_return_null_if_fail(pa_channel_map_init_auto(&data
->channel_map
, data
->sample_spec
.channels
, PA_CHANNEL_MAP_DEFAULT
));
163 pa_return_null_if_fail(pa_channel_map_valid(&data
->channel_map
));
164 pa_return_null_if_fail(data
->channel_map
.channels
== data
->sample_spec
.channels
);
166 if (!data
->volume_is_set
)
167 pa_cvolume_reset(&data
->volume
, data
->sample_spec
.channels
);
169 pa_return_null_if_fail(pa_cvolume_valid(&data
->volume
));
170 pa_return_null_if_fail(data
->volume
.channels
== data
->sample_spec
.channels
);
172 if (!data
->muted_is_set
)
176 pa_proplist_update(data
->proplist
, PA_UPDATE_MERGE
, data
->card
->proplist
);
178 pa_device_init_description(data
->proplist
);
179 pa_device_init_icon(data
->proplist
, TRUE
);
181 if (pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SINK_FIXATE
], data
) < 0) {
183 pa_namereg_unregister(core
, name
);
187 s
->parent
.parent
.free
= sink_free
;
188 s
->parent
.process_msg
= pa_sink_process_msg
;
191 s
->state
= PA_SINK_INIT
;
193 s
->name
= pa_xstrdup(name
);
194 s
->proplist
= pa_proplist_copy(data
->proplist
);
195 s
->driver
= pa_xstrdup(pa_path_get_filename(data
->driver
));
196 s
->module
= data
->module
;
197 s
->card
= data
->card
;
199 s
->sample_spec
= data
->sample_spec
;
200 s
->channel_map
= data
->channel_map
;
202 s
->inputs
= pa_idxset_new(NULL
, NULL
);
205 s
->virtual_volume
= data
->volume
;
206 pa_cvolume_reset(&s
->soft_volume
, s
->sample_spec
.channels
);
207 s
->base_volume
= PA_VOLUME_NORM
;
208 s
->n_volume_steps
= PA_VOLUME_NORM
+1;
209 s
->muted
= data
->muted
;
210 s
->refresh_volume
= s
->refresh_muted
= FALSE
;
218 pa_silence_memchunk_get(
219 &core
->silence_cache
,
225 s
->thread_info
.inputs
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
226 s
->thread_info
.soft_volume
= s
->soft_volume
;
227 s
->thread_info
.soft_muted
= s
->muted
;
228 s
->thread_info
.state
= s
->state
;
229 s
->thread_info
.rewind_nbytes
= 0;
230 s
->thread_info
.rewind_requested
= FALSE
;
231 s
->thread_info
.max_rewind
= 0;
232 s
->thread_info
.max_request
= 0;
233 s
->thread_info
.requested_latency_valid
= FALSE
;
234 s
->thread_info
.requested_latency
= 0;
235 s
->thread_info
.min_latency
= DEFAULT_MIN_LATENCY
;
236 s
->thread_info
.max_latency
= DEFAULT_MIN_LATENCY
;
238 pa_assert_se(pa_idxset_put(core
->sinks
, s
, &s
->index
) >= 0);
241 pa_assert_se(pa_idxset_put(s
->card
->sinks
, s
, NULL
) >= 0);
243 pt
= pa_proplist_to_string_sep(s
->proplist
, "\n ");
244 pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s\n %s",
247 pa_sample_spec_snprint(st
, sizeof(st
), &s
->sample_spec
),
248 pa_channel_map_snprint(cm
, sizeof(cm
), &s
->channel_map
),
252 pa_source_new_data_init(&source_data
);
253 pa_source_new_data_set_sample_spec(&source_data
, &s
->sample_spec
);
254 pa_source_new_data_set_channel_map(&source_data
, &s
->channel_map
);
255 source_data
.name
= pa_sprintf_malloc("%s.monitor", name
);
256 source_data
.driver
= data
->driver
;
257 source_data
.module
= data
->module
;
258 source_data
.card
= data
->card
;
260 dn
= pa_proplist_gets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
261 pa_proplist_setf(source_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "Monitor of %s", dn
? dn
: s
->name
);
262 pa_proplist_sets(source_data
.proplist
, PA_PROP_DEVICE_CLASS
, "monitor");
264 s
->monitor_source
= pa_source_new(core
, &source_data
, PA_SOURCE_LATENCY
);
266 pa_source_new_data_done(&source_data
);
268 if (!s
->monitor_source
) {
274 s
->monitor_source
->monitor_of
= s
;
276 pa_source_set_latency_range(s
->monitor_source
, s
->thread_info
.min_latency
, s
->thread_info
.max_latency
);
277 pa_source_set_max_rewind(s
->monitor_source
, s
->thread_info
.max_rewind
);
282 /* Called from main context */
283 static int sink_set_state(pa_sink
*s
, pa_sink_state_t state
) {
285 pa_bool_t suspend_change
;
286 pa_sink_state_t original_state
;
290 if (s
->state
== state
)
293 original_state
= s
->state
;
296 (original_state
== PA_SINK_SUSPENDED
&& PA_SINK_IS_OPENED(state
)) ||
297 (PA_SINK_IS_OPENED(original_state
) && state
== PA_SINK_SUSPENDED
);
300 if ((ret
= s
->set_state(s
, state
)) < 0)
304 if ((ret
= pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_STATE
, PA_UINT_TO_PTR(state
), 0, NULL
)) < 0) {
307 s
->set_state(s
, original_state
);
314 if (state
!= PA_SINK_UNLINKED
) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
315 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_STATE_CHANGED
], s
);
316 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
| PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
319 if (suspend_change
) {
323 /* We're suspending or resuming, tell everyone about it */
325 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
)))
326 if (s
->state
== PA_SINK_SUSPENDED
&&
327 (i
->flags
& PA_SINK_INPUT_FAIL_ON_SUSPEND
))
328 pa_sink_input_kill(i
);
330 i
->suspend(i
, state
== PA_SINK_SUSPENDED
);
332 if (s
->monitor_source
)
333 pa_source_sync_suspend(s
->monitor_source
);
339 /* Called from main context */
340 void pa_sink_put(pa_sink
* s
) {
341 pa_sink_assert_ref(s
);
343 pa_assert(s
->state
== PA_SINK_INIT
);
345 /* The following fields must be initialized properly when calling _put() */
346 pa_assert(s
->asyncmsgq
);
347 pa_assert(s
->rtpoll
);
348 pa_assert(s
->thread_info
.min_latency
<= s
->thread_info
.max_latency
);
350 if (!(s
->flags
& PA_SINK_HW_VOLUME_CTRL
)) {
351 s
->flags
|= PA_SINK_DECIBEL_VOLUME
;
353 s
->thread_info
.soft_volume
= s
->soft_volume
;
354 s
->thread_info
.soft_muted
= s
->muted
;
357 if (s
->flags
& PA_SINK_DECIBEL_VOLUME
)
358 s
->n_volume_steps
= PA_VOLUME_NORM
+1;
360 if (s
->core
->flat_volumes
)
361 if (s
->flags
& PA_SINK_DECIBEL_VOLUME
)
362 s
->flags
|= PA_SINK_FLAT_VOLUME
;
364 pa_assert_se(sink_set_state(s
, PA_SINK_IDLE
) == 0);
366 pa_source_put(s
->monitor_source
);
368 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
| PA_SUBSCRIPTION_EVENT_NEW
, s
->index
);
369 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_PUT
], s
);
372 /* Called from main context */
373 void pa_sink_unlink(pa_sink
* s
) {
375 pa_sink_input
*i
, *j
= NULL
;
379 /* Please note that pa_sink_unlink() does more than simply
380 * reversing pa_sink_put(). It also undoes the registrations
381 * already done in pa_sink_new()! */
383 /* All operations here shall be idempotent, i.e. pa_sink_unlink()
384 * may be called multiple times on the same sink without bad
387 linked
= PA_SINK_IS_LINKED(s
->state
);
390 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_UNLINK
], s
);
392 if (s
->state
!= PA_SINK_UNLINKED
)
393 pa_namereg_unregister(s
->core
, s
->name
);
394 pa_idxset_remove_by_data(s
->core
->sinks
, s
, NULL
);
397 pa_idxset_remove_by_data(s
->card
->sinks
, s
, NULL
);
399 while ((i
= pa_idxset_first(s
->inputs
, NULL
))) {
401 pa_sink_input_kill(i
);
406 sink_set_state(s
, PA_SINK_UNLINKED
);
408 s
->state
= PA_SINK_UNLINKED
;
412 if (s
->monitor_source
)
413 pa_source_unlink(s
->monitor_source
);
416 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
| PA_SUBSCRIPTION_EVENT_REMOVE
, s
->index
);
417 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_UNLINK_POST
], s
);
421 /* Called from main context */
422 static void sink_free(pa_object
*o
) {
423 pa_sink
*s
= PA_SINK(o
);
427 pa_assert(pa_sink_refcnt(s
) == 0);
429 if (PA_SINK_IS_LINKED(s
->state
))
432 pa_log_info("Freeing sink %u \"%s\"", s
->index
, s
->name
);
434 if (s
->monitor_source
) {
435 pa_source_unref(s
->monitor_source
);
436 s
->monitor_source
= NULL
;
439 pa_idxset_free(s
->inputs
, NULL
, NULL
);
441 while ((i
= pa_hashmap_steal_first(s
->thread_info
.inputs
)))
442 pa_sink_input_unref(i
);
444 pa_hashmap_free(s
->thread_info
.inputs
, NULL
, NULL
);
446 if (s
->silence
.memblock
)
447 pa_memblock_unref(s
->silence
.memblock
);
453 pa_proplist_free(s
->proplist
);
458 /* Called from main context */
459 void pa_sink_set_asyncmsgq(pa_sink
*s
, pa_asyncmsgq
*q
) {
460 pa_sink_assert_ref(s
);
464 if (s
->monitor_source
)
465 pa_source_set_asyncmsgq(s
->monitor_source
, q
);
468 /* Called from main context */
469 void pa_sink_set_rtpoll(pa_sink
*s
, pa_rtpoll
*p
) {
470 pa_sink_assert_ref(s
);
473 if (s
->monitor_source
)
474 pa_source_set_rtpoll(s
->monitor_source
, p
);
477 /* Called from main context */
478 int pa_sink_update_status(pa_sink
*s
) {
479 pa_sink_assert_ref(s
);
480 pa_assert(PA_SINK_IS_LINKED(s
->state
));
482 if (s
->state
== PA_SINK_SUSPENDED
)
485 return sink_set_state(s
, pa_sink_used_by(s
) ? PA_SINK_RUNNING
: PA_SINK_IDLE
);
488 /* Called from main context */
489 int pa_sink_suspend(pa_sink
*s
, pa_bool_t suspend
) {
490 pa_sink_assert_ref(s
);
491 pa_assert(PA_SINK_IS_LINKED(s
->state
));
494 return sink_set_state(s
, PA_SINK_SUSPENDED
);
496 return sink_set_state(s
, pa_sink_used_by(s
) ? PA_SINK_RUNNING
: PA_SINK_IDLE
);
499 /* Called from main context */
500 pa_queue
*pa_sink_move_all_start(pa_sink
*s
) {
502 pa_sink_input
*i
, *n
;
505 pa_sink_assert_ref(s
);
506 pa_assert(PA_SINK_IS_LINKED(s
->state
));
510 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= n
) {
511 n
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
));
513 if (pa_sink_input_start_move(i
) >= 0)
514 pa_queue_push(q
, pa_sink_input_ref(i
));
520 /* Called from main context */
521 void pa_sink_move_all_finish(pa_sink
*s
, pa_queue
*q
, pa_bool_t save
) {
524 pa_sink_assert_ref(s
);
525 pa_assert(PA_SINK_IS_LINKED(s
->state
));
528 while ((i
= PA_SINK_INPUT(pa_queue_pop(q
)))) {
529 if (pa_sink_input_finish_move(i
, s
, save
) < 0)
530 pa_sink_input_kill(i
);
532 pa_sink_input_unref(i
);
535 pa_queue_free(q
, NULL
, NULL
);
538 /* Called from main context */
539 void pa_sink_move_all_fail(pa_queue
*q
) {
543 while ((i
= PA_SINK_INPUT(pa_queue_pop(q
)))) {
544 if (pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL
], i
) == PA_HOOK_OK
) {
545 pa_sink_input_kill(i
);
546 pa_sink_input_unref(i
);
550 pa_queue_free(q
, NULL
, NULL
);
553 /* Called from IO thread context */
554 void pa_sink_process_rewind(pa_sink
*s
, size_t nbytes
) {
557 pa_sink_assert_ref(s
);
558 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
560 /* If nobody requested this and this is actually no real rewind
561 * then we can short cut this */
562 if (!s
->thread_info
.rewind_requested
&& nbytes
<= 0)
565 s
->thread_info
.rewind_nbytes
= 0;
566 s
->thread_info
.rewind_requested
= FALSE
;
568 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
)
572 pa_log_debug("Processing rewind...");
574 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
))) {
575 pa_sink_input_assert_ref(i
);
576 pa_sink_input_process_rewind(i
, nbytes
);
580 if (s
->monitor_source
&& PA_SOURCE_IS_LINKED(s
->monitor_source
->thread_info
.state
))
581 pa_source_process_rewind(s
->monitor_source
, nbytes
);
584 /* Called from IO thread context */
585 static unsigned fill_mix_info(pa_sink
*s
, size_t *length
, pa_mix_info
*info
, unsigned maxinfo
) {
589 size_t mixlength
= *length
;
591 pa_sink_assert_ref(s
);
594 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)) && maxinfo
> 0) {
595 pa_sink_input_assert_ref(i
);
597 pa_sink_input_peek(i
, *length
, &info
->chunk
, &info
->volume
);
599 if (mixlength
== 0 || info
->chunk
.length
< mixlength
)
600 mixlength
= info
->chunk
.length
;
602 if (pa_memblock_is_silence(info
->chunk
.memblock
)) {
603 pa_memblock_unref(info
->chunk
.memblock
);
607 info
->userdata
= pa_sink_input_ref(i
);
609 pa_assert(info
->chunk
.memblock
);
610 pa_assert(info
->chunk
.length
> 0);
623 /* Called from IO thread context */
624 static void inputs_drop(pa_sink
*s
, pa_mix_info
*info
, unsigned n
, pa_memchunk
*result
) {
628 unsigned n_unreffed
= 0;
630 pa_sink_assert_ref(s
);
632 pa_assert(result
->memblock
);
633 pa_assert(result
->length
> 0);
635 /* We optimize for the case where the order of the inputs has not changed */
637 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
))) {
639 pa_mix_info
* m
= NULL
;
641 pa_sink_input_assert_ref(i
);
643 /* Let's try to find the matching entry info the pa_mix_info array */
644 for (j
= 0; j
< n
; j
++) {
646 if (info
[p
].userdata
== i
) {
657 pa_sink_input_drop(i
, result
->length
);
659 if (s
->monitor_source
&& PA_SOURCE_IS_LINKED(s
->monitor_source
->thread_info
.state
)) {
661 if (pa_hashmap_size(i
->thread_info
.direct_outputs
) > 0) {
666 if (m
&& m
->chunk
.memblock
) {
668 pa_memblock_ref(c
.memblock
);
669 pa_assert(result
->length
<= c
.length
);
670 c
.length
= result
->length
;
672 pa_memchunk_make_writable(&c
, 0);
673 pa_volume_memchunk(&c
, &s
->sample_spec
, &m
->volume
);
676 pa_memblock_ref(c
.memblock
);
677 pa_assert(result
->length
<= c
.length
);
678 c
.length
= result
->length
;
681 while ((o
= pa_hashmap_iterate(i
->thread_info
.direct_outputs
, &ostate
, NULL
))) {
682 pa_source_output_assert_ref(o
);
683 pa_assert(o
->direct_on_input
== i
);
684 pa_source_post_direct(s
->monitor_source
, o
, &c
);
687 pa_memblock_unref(c
.memblock
);
692 if (m
->chunk
.memblock
)
693 pa_memblock_unref(m
->chunk
.memblock
);
694 pa_memchunk_reset(&m
->chunk
);
696 pa_sink_input_unref(m
->userdata
);
703 /* Now drop references to entries that are included in the
704 * pa_mix_info array but don't exist anymore */
706 if (n_unreffed
< n
) {
707 for (; n
> 0; info
++, n
--) {
709 pa_sink_input_unref(info
->userdata
);
710 if (info
->chunk
.memblock
)
711 pa_memblock_unref(info
->chunk
.memblock
);
715 if (s
->monitor_source
&& PA_SOURCE_IS_LINKED(s
->monitor_source
->thread_info
.state
))
716 pa_source_post(s
->monitor_source
, result
);
719 /* Called from IO thread context */
720 void pa_sink_render(pa_sink
*s
, size_t length
, pa_memchunk
*result
) {
721 pa_mix_info info
[MAX_MIX_CHANNELS
];
723 size_t block_size_max
;
725 pa_sink_assert_ref(s
);
726 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
727 pa_assert(pa_frame_aligned(length
, &s
->sample_spec
));
732 pa_assert(!s
->thread_info
.rewind_requested
);
733 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
735 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
) {
736 result
->memblock
= pa_memblock_ref(s
->silence
.memblock
);
737 result
->index
= s
->silence
.index
;
738 result
->length
= PA_MIN(s
->silence
.length
, length
);
743 length
= pa_frame_align(MIX_BUFFER_LENGTH
, &s
->sample_spec
);
745 block_size_max
= pa_mempool_block_size_max(s
->core
->mempool
);
746 if (length
> block_size_max
)
747 length
= pa_frame_align(block_size_max
, &s
->sample_spec
);
749 pa_assert(length
> 0);
751 n
= fill_mix_info(s
, &length
, info
, MAX_MIX_CHANNELS
);
755 *result
= s
->silence
;
756 pa_memblock_ref(result
->memblock
);
758 if (result
->length
> length
)
759 result
->length
= length
;
764 *result
= info
[0].chunk
;
765 pa_memblock_ref(result
->memblock
);
767 if (result
->length
> length
)
768 result
->length
= length
;
770 pa_sw_cvolume_multiply(&volume
, &s
->thread_info
.soft_volume
, &info
[0].volume
);
772 if (s
->thread_info
.soft_muted
|| !pa_cvolume_is_norm(&volume
)) {
773 pa_memchunk_make_writable(result
, 0);
774 if (s
->thread_info
.soft_muted
|| pa_cvolume_is_muted(&volume
))
775 pa_silence_memchunk(result
, &s
->sample_spec
);
777 pa_volume_memchunk(result
, &s
->sample_spec
, &volume
);
781 result
->memblock
= pa_memblock_new(s
->core
->mempool
, length
);
783 ptr
= pa_memblock_acquire(result
->memblock
);
784 result
->length
= pa_mix(info
, n
,
787 &s
->thread_info
.soft_volume
,
788 s
->thread_info
.soft_muted
);
789 pa_memblock_release(result
->memblock
);
794 inputs_drop(s
, info
, n
, result
);
799 /* Called from IO thread context */
800 void pa_sink_render_into(pa_sink
*s
, pa_memchunk
*target
) {
801 pa_mix_info info
[MAX_MIX_CHANNELS
];
803 size_t length
, block_size_max
;
805 pa_sink_assert_ref(s
);
806 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
808 pa_assert(target
->memblock
);
809 pa_assert(target
->length
> 0);
810 pa_assert(pa_frame_aligned(target
->length
, &s
->sample_spec
));
814 pa_assert(!s
->thread_info
.rewind_requested
);
815 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
817 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
) {
818 pa_silence_memchunk(target
, &s
->sample_spec
);
822 length
= target
->length
;
823 block_size_max
= pa_mempool_block_size_max(s
->core
->mempool
);
824 if (length
> block_size_max
)
825 length
= pa_frame_align(block_size_max
, &s
->sample_spec
);
827 pa_assert(length
> 0);
829 n
= fill_mix_info(s
, &length
, info
, MAX_MIX_CHANNELS
);
832 if (target
->length
> length
)
833 target
->length
= length
;
835 pa_silence_memchunk(target
, &s
->sample_spec
);
839 if (target
->length
> length
)
840 target
->length
= length
;
842 pa_sw_cvolume_multiply(&volume
, &s
->thread_info
.soft_volume
, &info
[0].volume
);
844 if (s
->thread_info
.soft_muted
|| pa_cvolume_is_muted(&volume
))
845 pa_silence_memchunk(target
, &s
->sample_spec
);
849 vchunk
= info
[0].chunk
;
850 pa_memblock_ref(vchunk
.memblock
);
852 if (vchunk
.length
> length
)
853 vchunk
.length
= length
;
855 if (!pa_cvolume_is_norm(&volume
)) {
856 pa_memchunk_make_writable(&vchunk
, 0);
857 pa_volume_memchunk(&vchunk
, &s
->sample_spec
, &volume
);
860 pa_memchunk_memcpy(target
, &vchunk
);
861 pa_memblock_unref(vchunk
.memblock
);
867 ptr
= pa_memblock_acquire(target
->memblock
);
869 target
->length
= pa_mix(info
, n
,
870 (uint8_t*) ptr
+ target
->index
, length
,
872 &s
->thread_info
.soft_volume
,
873 s
->thread_info
.soft_muted
);
875 pa_memblock_release(target
->memblock
);
878 inputs_drop(s
, info
, n
, target
);
883 /* Called from IO thread context */
884 void pa_sink_render_into_full(pa_sink
*s
, pa_memchunk
*target
) {
888 pa_sink_assert_ref(s
);
889 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
891 pa_assert(target
->memblock
);
892 pa_assert(target
->length
> 0);
893 pa_assert(pa_frame_aligned(target
->length
, &s
->sample_spec
));
897 pa_assert(!s
->thread_info
.rewind_requested
);
898 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
907 pa_sink_render_into(s
, &chunk
);
916 /* Called from IO thread context */
917 void pa_sink_render_full(pa_sink
*s
, size_t length
, pa_memchunk
*result
) {
918 pa_sink_assert_ref(s
);
919 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
920 pa_assert(length
> 0);
921 pa_assert(pa_frame_aligned(length
, &s
->sample_spec
));
924 pa_assert(!s
->thread_info
.rewind_requested
);
925 pa_assert(s
->thread_info
.rewind_nbytes
== 0);
927 /*** This needs optimization ***/
930 result
->length
= length
;
931 result
->memblock
= pa_memblock_new(s
->core
->mempool
, length
);
933 pa_sink_render_into_full(s
, result
);
936 /* Called from main thread */
937 pa_usec_t
pa_sink_get_latency(pa_sink
*s
) {
940 pa_sink_assert_ref(s
);
941 pa_assert(PA_SINK_IS_LINKED(s
->state
));
943 /* The returned value is supposed to be in the time domain of the sound card! */
945 if (s
->state
== PA_SINK_SUSPENDED
)
948 if (!(s
->flags
& PA_SINK_LATENCY
))
951 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) == 0);
956 /* Called from main thread */
957 void pa_sink_update_flat_volume(pa_sink
*s
, pa_cvolume
*new_volume
) {
961 pa_sink_assert_ref(s
);
962 pa_assert(new_volume
);
963 pa_assert(PA_SINK_IS_LINKED(s
->state
));
964 pa_assert(s
->flags
& PA_SINK_FLAT_VOLUME
);
966 /* This is called whenever a sink input volume changes and we
967 * might need to fix up the sink volume accordingly. Please note
968 * that we don't actually update the sinks volume here, we only
969 * return how it needs to be updated. The caller should then call
970 * pa_sink_set_flat_volume().*/
972 if (pa_idxset_isempty(s
->inputs
)) {
973 /* In the special case that we have no sink input we leave the
974 * volume unmodified. */
975 *new_volume
= s
->virtual_volume
;
979 pa_cvolume_mute(new_volume
, s
->channel_map
.channels
);
981 /* First let's determine the new maximum volume of all inputs
982 * connected to this sink */
983 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
985 pa_cvolume remapped_volume
;
987 remapped_volume
= i
->virtual_volume
;
988 pa_cvolume_remap(&remapped_volume
, &i
->channel_map
, &s
->channel_map
);
990 for (c
= 0; c
< new_volume
->channels
; c
++)
991 if (remapped_volume
.values
[c
] > new_volume
->values
[c
])
992 new_volume
->values
[c
] = remapped_volume
.values
[c
];
995 /* Then, let's update the soft volumes of all inputs connected
997 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
998 pa_cvolume remapped_new_volume
;
1000 remapped_new_volume
= *new_volume
;
1001 pa_cvolume_remap(&remapped_new_volume
, &s
->channel_map
, &i
->channel_map
);
1002 pa_sw_cvolume_divide(&i
->soft_volume
, &i
->virtual_volume
, &remapped_new_volume
);
1003 pa_sw_cvolume_multiply(&i
->soft_volume
, &i
->soft_volume
, &i
->volume_factor
);
1005 /* Hooks have the ability to play games with i->soft_volume */
1006 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME
], i
);
1008 /* We don't issue PA_SINK_INPUT_MESSAGE_SET_VOLUME because
1009 * we want the update to have atomically with the sink
1010 * volume update, hence we do it within the
1011 * pa_sink_set_flat_volume() call below*/
1015 /* Called from main thread */
1016 void pa_sink_propagate_flat_volume(pa_sink
*s
, const pa_cvolume
*old_volume
) {
1020 pa_sink_assert_ref(s
);
1021 pa_assert(old_volume
);
1022 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1023 pa_assert(s
->flags
& PA_SINK_FLAT_VOLUME
);
1025 /* This is called whenever the sink volume changes that is not
1026 * caused by a sink input volume change. We need to fix up the
1027 * sink input volumes accordingly */
1029 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
1030 pa_cvolume remapped_old_volume
, remapped_new_volume
, fixed_volume
;
1033 remapped_new_volume
= s
->virtual_volume
;
1034 pa_cvolume_remap(&remapped_new_volume
, &s
->channel_map
, &i
->channel_map
);
1036 remapped_old_volume
= *old_volume
;
1037 pa_cvolume_remap(&remapped_old_volume
, &s
->channel_map
, &i
->channel_map
);
1039 for (c
= 0; c
< i
->sample_spec
.channels
; c
++)
1041 if (remapped_old_volume
.values
[c
] == PA_VOLUME_MUTED
)
1042 fixed_volume
.values
[c
] = PA_VOLUME_MUTED
;
1044 fixed_volume
.values
[c
] = (pa_volume_t
)
1045 ((uint64_t) i
->virtual_volume
.values
[c
] *
1046 (uint64_t) remapped_new_volume
.values
[c
] /
1047 (uint64_t) remapped_old_volume
.values
[c
]);
1049 fixed_volume
.channels
= i
->virtual_volume
.channels
;
1051 if (!pa_cvolume_equal(&fixed_volume
, &i
->virtual_volume
)) {
1052 i
->virtual_volume
= fixed_volume
;
1054 /* The virtual volume changed, let's tell people so */
1055 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1060 /* Called from main thread */
1061 void pa_sink_set_volume(pa_sink
*s
, const pa_cvolume
*volume
, pa_bool_t propagate
, pa_bool_t sendmsg
) {
1062 pa_cvolume old_virtual_volume
;
1063 pa_bool_t virtual_volume_changed
;
1065 pa_sink_assert_ref(s
);
1066 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1068 pa_assert(pa_cvolume_valid(volume
));
1069 pa_assert(pa_cvolume_compatible(volume
, &s
->sample_spec
));
1071 old_virtual_volume
= s
->virtual_volume
;
1072 s
->virtual_volume
= *volume
;
1073 virtual_volume_changed
= !pa_cvolume_equal(&old_virtual_volume
, &s
->virtual_volume
);
1075 /* Propagate this volume change back to the inputs */
1076 if (virtual_volume_changed
)
1077 if (propagate
&& (s
->flags
& PA_SINK_FLAT_VOLUME
))
1078 pa_sink_propagate_flat_volume(s
, &old_virtual_volume
);
1080 if (s
->set_volume
) {
1081 /* If we have a function set_volume(), then we do not apply a
1082 * soft volume by default. However, set_volume() is apply one
1083 * to s->soft_volume */
1085 pa_cvolume_reset(&s
->soft_volume
, s
->sample_spec
.channels
);
1089 /* If we have no function set_volume(), then the soft volume
1090 * becomes the virtual volume */
1091 s
->soft_volume
= s
->virtual_volume
;
1093 /* This tells the sink that soft and/or virtual volume changed */
1095 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
) == 0);
1097 if (virtual_volume_changed
)
1098 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1101 /* Called from main thread. Only to be called by sink implementor */
1102 void pa_sink_set_soft_volume(pa_sink
*s
, const pa_cvolume
*volume
) {
1103 pa_sink_assert_ref(s
);
1106 s
->soft_volume
= *volume
;
1108 if (PA_SINK_IS_LINKED(s
->state
))
1109 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
) == 0);
1111 s
->thread_info
.soft_volume
= *volume
;
1114 /* Called from main thread */
1115 const pa_cvolume
*pa_sink_get_volume(pa_sink
*s
, pa_bool_t force_refresh
) {
1116 pa_sink_assert_ref(s
);
1118 if (s
->refresh_volume
|| force_refresh
) {
1119 struct pa_cvolume old_virtual_volume
= s
->virtual_volume
;
1124 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_VOLUME
, NULL
, 0, NULL
) == 0);
1126 if (!pa_cvolume_equal(&old_virtual_volume
, &s
->virtual_volume
)) {
1128 if (s
->flags
& PA_SINK_FLAT_VOLUME
)
1129 pa_sink_propagate_flat_volume(s
, &old_virtual_volume
);
1131 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1135 return &s
->virtual_volume
;
1138 /* Called from main thread */
1139 void pa_sink_volume_changed(pa_sink
*s
, const pa_cvolume
*new_volume
) {
1140 pa_sink_assert_ref(s
);
1142 /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1144 if (pa_cvolume_equal(&s
->virtual_volume
, new_volume
))
1147 s
->virtual_volume
= *new_volume
;
1148 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1151 /* Called from main thread */
1152 void pa_sink_set_mute(pa_sink
*s
, pa_bool_t mute
) {
1153 pa_bool_t old_muted
;
1155 pa_sink_assert_ref(s
);
1156 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1158 old_muted
= s
->muted
;
1164 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_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
);
1170 /* Called from main thread */
1171 pa_bool_t
pa_sink_get_mute(pa_sink
*s
, pa_bool_t force_refresh
) {
1173 pa_sink_assert_ref(s
);
1175 if (s
->refresh_muted
|| force_refresh
) {
1176 pa_bool_t old_muted
= s
->muted
;
1181 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_MUTE
, NULL
, 0, NULL
) == 0);
1183 if (old_muted
!= s
->muted
)
1184 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1190 /* Called from main thread */
1191 void pa_sink_mute_changed(pa_sink
*s
, pa_bool_t new_muted
) {
1192 pa_sink_assert_ref(s
);
1194 /* The sink implementor may call this if the volume changed to make sure everyone is notified */
1196 if (s
->muted
== new_muted
)
1199 s
->muted
= new_muted
;
1200 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1203 /* Called from main thread */
1204 pa_bool_t
pa_sink_update_proplist(pa_sink
*s
, pa_update_mode_t mode
, pa_proplist
*p
) {
1206 pa_sink_assert_ref(s
);
1209 pa_proplist_update(s
->proplist
, mode
, p
);
1211 if (PA_SINK_IS_LINKED(s
->state
)) {
1212 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_PROPLIST_CHANGED
], s
);
1213 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1219 /* Called from main thread */
1220 void pa_sink_set_description(pa_sink
*s
, const char *description
) {
1222 pa_sink_assert_ref(s
);
1224 if (!description
&& !pa_proplist_contains(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
))
1227 old
= pa_proplist_gets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1229 if (old
&& description
&& !strcmp(old
, description
))
1233 pa_proplist_sets(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
, description
);
1235 pa_proplist_unset(s
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1237 if (s
->monitor_source
) {
1240 n
= pa_sprintf_malloc("Monitor Source of %s", description
? description
: s
->name
);
1241 pa_source_set_description(s
->monitor_source
, n
);
1245 if (PA_SINK_IS_LINKED(s
->state
)) {
1246 pa_subscription_post(s
->core
, PA_SUBSCRIPTION_EVENT_SINK
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->index
);
1247 pa_hook_fire(&s
->core
->hooks
[PA_CORE_HOOK_SINK_PROPLIST_CHANGED
], s
);
1251 /* Called from main thread */
1252 unsigned pa_sink_linked_by(pa_sink
*s
) {
1255 pa_sink_assert_ref(s
);
1256 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1258 ret
= pa_idxset_size(s
->inputs
);
1260 /* We add in the number of streams connected to us here. Please
1261 * note the asymmmetry to pa_sink_used_by()! */
1263 if (s
->monitor_source
)
1264 ret
+= pa_source_linked_by(s
->monitor_source
);
1269 /* Called from main thread */
1270 unsigned pa_sink_used_by(pa_sink
*s
) {
1273 pa_sink_assert_ref(s
);
1274 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1276 ret
= pa_idxset_size(s
->inputs
);
1277 pa_assert(ret
>= s
->n_corked
);
1279 /* Streams connected to our monitor source do not matter for
1280 * pa_sink_used_by()!.*/
1282 return ret
- s
->n_corked
;
1285 /* Called from main thread */
1286 unsigned pa_sink_check_suspend(pa_sink
*s
) {
1291 pa_sink_assert_ref(s
);
1293 if (!PA_SINK_IS_LINKED(s
->state
))
1298 for (i
= PA_SINK_INPUT(pa_idxset_first(s
->inputs
, &idx
)); i
; i
= PA_SINK_INPUT(pa_idxset_next(s
->inputs
, &idx
))) {
1299 pa_sink_input_state_t st
;
1301 st
= pa_sink_input_get_state(i
);
1302 pa_assert(PA_SINK_INPUT_IS_LINKED(st
));
1304 if (st
== PA_SINK_INPUT_CORKED
)
1307 if (i
->flags
& PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
)
1313 if (s
->monitor_source
)
1314 ret
+= pa_source_check_suspend(s
->monitor_source
);
1319 /* Called from the IO thread */
1320 static void sync_input_volumes_within_thread(pa_sink
*s
) {
1324 pa_sink_assert_ref(s
);
1326 while ((i
= PA_SINK_INPUT(pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))) {
1327 if (pa_cvolume_equal(&i
->thread_info
.soft_volume
, &i
->soft_volume
))
1330 i
->thread_info
.soft_volume
= i
->soft_volume
;
1331 pa_sink_input_request_rewind(i
, 0, TRUE
, FALSE
, FALSE
);
1335 /* Called from IO thread, except when it is not */
1336 int pa_sink_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1337 pa_sink
*s
= PA_SINK(o
);
1338 pa_sink_assert_ref(s
);
1340 switch ((pa_sink_message_t
) code
) {
1342 case PA_SINK_MESSAGE_ADD_INPUT
: {
1343 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1345 /* If you change anything here, make sure to change the
1346 * sink input handling a few lines down at
1347 * PA_SINK_MESSAGE_FINISH_MOVE, too. */
1349 pa_hashmap_put(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
), pa_sink_input_ref(i
));
1351 /* Since the caller sleeps in pa_sink_input_put(), we can
1352 * safely access data outside of thread_info even though
1355 if ((i
->thread_info
.sync_prev
= i
->sync_prev
)) {
1356 pa_assert(i
->sink
== i
->thread_info
.sync_prev
->sink
);
1357 pa_assert(i
->sync_prev
->sync_next
== i
);
1358 i
->thread_info
.sync_prev
->thread_info
.sync_next
= i
;
1361 if ((i
->thread_info
.sync_next
= i
->sync_next
)) {
1362 pa_assert(i
->sink
== i
->thread_info
.sync_next
->sink
);
1363 pa_assert(i
->sync_next
->sync_prev
== i
);
1364 i
->thread_info
.sync_next
->thread_info
.sync_prev
= i
;
1367 pa_assert(!i
->thread_info
.attached
);
1368 i
->thread_info
.attached
= TRUE
;
1373 pa_sink_input_set_state_within_thread(i
, i
->state
);
1375 /* The requested latency of the sink input needs to be
1376 * fixed up and then configured on the sink */
1378 if (i
->thread_info
.requested_sink_latency
!= (pa_usec_t
) -1)
1379 pa_sink_input_set_requested_latency_within_thread(i
, i
->thread_info
.requested_sink_latency
);
1381 pa_sink_input_update_max_rewind(i
, s
->thread_info
.max_rewind
);
1382 pa_sink_input_update_max_request(i
, s
->thread_info
.max_request
);
1384 /* We don't rewind here automatically. This is left to the
1385 * sink input implementor because some sink inputs need a
1386 * slow start, i.e. need some time to buffer client
1387 * samples before beginning streaming. */
1389 /* In flat volume mode we need to update the volume as
1391 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1394 case PA_SINK_MESSAGE_REMOVE_INPUT
: {
1395 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1397 /* If you change anything here, make sure to change the
1398 * sink input handling a few lines down at
1399 * PA_SINK_MESSAGE_PREPAPRE_MOVE, too. */
1404 pa_sink_input_set_state_within_thread(i
, i
->state
);
1406 pa_assert(i
->thread_info
.attached
);
1407 i
->thread_info
.attached
= FALSE
;
1409 /* Since the caller sleeps in pa_sink_input_unlink(),
1410 * we can safely access data outside of thread_info even
1411 * though it is mutable */
1413 pa_assert(!i
->sync_prev
);
1414 pa_assert(!i
->sync_next
);
1416 if (i
->thread_info
.sync_prev
) {
1417 i
->thread_info
.sync_prev
->thread_info
.sync_next
= i
->thread_info
.sync_prev
->sync_next
;
1418 i
->thread_info
.sync_prev
= NULL
;
1421 if (i
->thread_info
.sync_next
) {
1422 i
->thread_info
.sync_next
->thread_info
.sync_prev
= i
->thread_info
.sync_next
->sync_prev
;
1423 i
->thread_info
.sync_next
= NULL
;
1426 if (pa_hashmap_remove(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
)))
1427 pa_sink_input_unref(i
);
1429 pa_sink_invalidate_requested_latency(s
);
1430 pa_sink_request_rewind(s
, (size_t) -1);
1432 /* In flat volume mode we need to update the volume as
1434 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1437 case PA_SINK_MESSAGE_START_MOVE
: {
1438 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1440 /* We don't support moving synchronized streams. */
1441 pa_assert(!i
->sync_prev
);
1442 pa_assert(!i
->sync_next
);
1443 pa_assert(!i
->thread_info
.sync_next
);
1444 pa_assert(!i
->thread_info
.sync_prev
);
1446 if (i
->thread_info
.state
!= PA_SINK_INPUT_CORKED
) {
1448 size_t sink_nbytes
, total_nbytes
;
1450 /* Get the latency of the sink */
1451 if (!(s
->flags
& PA_SINK_LATENCY
) ||
1452 PA_MSGOBJECT(s
)->process_msg(PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) < 0)
1455 sink_nbytes
= pa_usec_to_bytes(usec
, &s
->sample_spec
);
1456 total_nbytes
= sink_nbytes
+ pa_memblockq_get_length(i
->thread_info
.render_memblockq
);
1458 if (total_nbytes
> 0) {
1459 i
->thread_info
.rewrite_nbytes
= i
->thread_info
.resampler
? pa_resampler_request(i
->thread_info
.resampler
, total_nbytes
) : total_nbytes
;
1460 i
->thread_info
.rewrite_flush
= TRUE
;
1461 pa_sink_input_process_rewind(i
, sink_nbytes
);
1468 pa_assert(i
->thread_info
.attached
);
1469 i
->thread_info
.attached
= FALSE
;
1471 /* Let's remove the sink input ...*/
1472 if (pa_hashmap_remove(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
)))
1473 pa_sink_input_unref(i
);
1475 pa_sink_invalidate_requested_latency(s
);
1477 pa_log_debug("Requesting rewind due to started move");
1478 pa_sink_request_rewind(s
, (size_t) -1);
1480 /* In flat volume mode we need to update the volume as
1482 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1485 case PA_SINK_MESSAGE_FINISH_MOVE
: {
1486 pa_sink_input
*i
= PA_SINK_INPUT(userdata
);
1488 /* We don't support moving synchronized streams. */
1489 pa_assert(!i
->sync_prev
);
1490 pa_assert(!i
->sync_next
);
1491 pa_assert(!i
->thread_info
.sync_next
);
1492 pa_assert(!i
->thread_info
.sync_prev
);
1494 pa_hashmap_put(s
->thread_info
.inputs
, PA_UINT32_TO_PTR(i
->index
), pa_sink_input_ref(i
));
1496 pa_assert(!i
->thread_info
.attached
);
1497 i
->thread_info
.attached
= TRUE
;
1502 if (i
->thread_info
.requested_sink_latency
!= (pa_usec_t
) -1)
1503 pa_sink_input_set_requested_latency_within_thread(i
, i
->thread_info
.requested_sink_latency
);
1505 pa_sink_input_update_max_rewind(i
, s
->thread_info
.max_rewind
);
1506 pa_sink_input_update_max_request(i
, s
->thread_info
.max_request
);
1508 if (i
->thread_info
.state
!= PA_SINK_INPUT_CORKED
) {
1512 /* Get the latency of the sink */
1513 if (!(s
->flags
& PA_SINK_LATENCY
) ||
1514 PA_MSGOBJECT(s
)->process_msg(PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY
, &usec
, 0, NULL
) < 0)
1517 nbytes
= pa_usec_to_bytes(usec
, &s
->sample_spec
);
1520 pa_sink_input_drop(i
, nbytes
);
1522 pa_log_debug("Requesting rewind due to finished move");
1523 pa_sink_request_rewind(s
, nbytes
);
1526 /* In flat volume mode we need to update the volume as
1528 return o
->process_msg(o
, PA_SINK_MESSAGE_SET_VOLUME
, NULL
, 0, NULL
);
1531 case PA_SINK_MESSAGE_SET_VOLUME
:
1533 if (!pa_cvolume_equal(&s
->thread_info
.soft_volume
, &s
->soft_volume
)) {
1534 s
->thread_info
.soft_volume
= s
->soft_volume
;
1535 pa_sink_request_rewind(s
, (size_t) -1);
1538 if (s
->flags
& PA_SINK_FLAT_VOLUME
)
1539 sync_input_volumes_within_thread(s
);
1543 case PA_SINK_MESSAGE_GET_VOLUME
:
1546 case PA_SINK_MESSAGE_SET_MUTE
:
1548 if (s
->thread_info
.soft_muted
!= s
->muted
) {
1549 s
->thread_info
.soft_muted
= s
->muted
;
1550 pa_sink_request_rewind(s
, (size_t) -1);
1555 case PA_SINK_MESSAGE_GET_MUTE
:
1558 case PA_SINK_MESSAGE_SET_STATE
:
1560 s
->thread_info
.state
= PA_PTR_TO_UINT(userdata
);
1562 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
) {
1563 s
->thread_info
.rewind_nbytes
= 0;
1564 s
->thread_info
.rewind_requested
= FALSE
;
1569 case PA_SINK_MESSAGE_DETACH
:
1571 /* Detach all streams */
1572 pa_sink_detach_within_thread(s
);
1575 case PA_SINK_MESSAGE_ATTACH
:
1577 /* Reattach all streams */
1578 pa_sink_attach_within_thread(s
);
1581 case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY
: {
1583 pa_usec_t
*usec
= userdata
;
1584 *usec
= pa_sink_get_requested_latency_within_thread(s
);
1586 if (*usec
== (pa_usec_t
) -1)
1587 *usec
= s
->thread_info
.max_latency
;
1592 case PA_SINK_MESSAGE_SET_LATENCY_RANGE
: {
1593 pa_usec_t
*r
= userdata
;
1595 pa_sink_set_latency_range_within_thread(s
, r
[0], r
[1]);
1600 case PA_SINK_MESSAGE_GET_LATENCY_RANGE
: {
1601 pa_usec_t
*r
= userdata
;
1603 r
[0] = s
->thread_info
.min_latency
;
1604 r
[1] = s
->thread_info
.max_latency
;
1609 case PA_SINK_MESSAGE_GET_MAX_REWIND
:
1611 *((size_t*) userdata
) = s
->thread_info
.max_rewind
;
1614 case PA_SINK_MESSAGE_GET_MAX_REQUEST
:
1616 *((size_t*) userdata
) = s
->thread_info
.max_request
;
1619 case PA_SINK_MESSAGE_SET_MAX_REWIND
:
1621 pa_sink_set_max_rewind_within_thread(s
, (size_t) offset
);
1624 case PA_SINK_MESSAGE_SET_MAX_REQUEST
:
1626 pa_sink_set_max_request_within_thread(s
, (size_t) offset
);
1629 case PA_SINK_MESSAGE_GET_LATENCY
:
1630 case PA_SINK_MESSAGE_MAX
:
1637 /* Called from main thread */
1638 int pa_sink_suspend_all(pa_core
*c
, pa_bool_t suspend
) {
1643 pa_core_assert_ref(c
);
1645 for (sink
= PA_SINK(pa_idxset_first(c
->sinks
, &idx
)); sink
; sink
= PA_SINK(pa_idxset_next(c
->sinks
, &idx
))) {
1648 if ((r
= pa_sink_suspend(sink
, suspend
)) < 0)
1655 /* Called from main thread */
1656 void pa_sink_detach(pa_sink
*s
) {
1657 pa_sink_assert_ref(s
);
1658 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1660 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_DETACH
, NULL
, 0, NULL
) == 0);
1663 /* Called from main thread */
1664 void pa_sink_attach(pa_sink
*s
) {
1665 pa_sink_assert_ref(s
);
1666 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1668 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_ATTACH
, NULL
, 0, NULL
) == 0);
1671 /* Called from IO thread */
1672 void pa_sink_detach_within_thread(pa_sink
*s
) {
1676 pa_sink_assert_ref(s
);
1677 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
1679 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1683 if (s
->monitor_source
)
1684 pa_source_detach_within_thread(s
->monitor_source
);
1687 /* Called from IO thread */
1688 void pa_sink_attach_within_thread(pa_sink
*s
) {
1692 pa_sink_assert_ref(s
);
1693 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
1695 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1699 if (s
->monitor_source
)
1700 pa_source_attach_within_thread(s
->monitor_source
);
1703 /* Called from IO thread */
1704 void pa_sink_request_rewind(pa_sink
*s
, size_t nbytes
) {
1705 pa_sink_assert_ref(s
);
1706 pa_assert(PA_SINK_IS_LINKED(s
->thread_info
.state
));
1708 if (s
->thread_info
.state
== PA_SINK_SUSPENDED
)
1711 if (nbytes
== (size_t) -1)
1712 nbytes
= s
->thread_info
.max_rewind
;
1714 nbytes
= PA_MIN(nbytes
, s
->thread_info
.max_rewind
);
1716 if (s
->thread_info
.rewind_requested
&&
1717 nbytes
<= s
->thread_info
.rewind_nbytes
)
1720 s
->thread_info
.rewind_nbytes
= nbytes
;
1721 s
->thread_info
.rewind_requested
= TRUE
;
1723 if (s
->request_rewind
)
1724 s
->request_rewind(s
);
1727 /* Called from IO thread */
1728 pa_usec_t
pa_sink_get_requested_latency_within_thread(pa_sink
*s
) {
1729 pa_usec_t result
= (pa_usec_t
) -1;
1732 pa_usec_t monitor_latency
;
1734 pa_sink_assert_ref(s
);
1736 if (s
->thread_info
.requested_latency_valid
)
1737 return s
->thread_info
.requested_latency
;
1739 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1741 if (i
->thread_info
.requested_sink_latency
!= (pa_usec_t
) -1 &&
1742 (result
== (pa_usec_t
) -1 || result
> i
->thread_info
.requested_sink_latency
))
1743 result
= i
->thread_info
.requested_sink_latency
;
1745 monitor_latency
= pa_source_get_requested_latency_within_thread(s
->monitor_source
);
1747 if (monitor_latency
!= (pa_usec_t
) -1 &&
1748 (result
== (pa_usec_t
) -1 || result
> monitor_latency
))
1749 result
= monitor_latency
;
1751 if (result
!= (pa_usec_t
) -1) {
1752 if (result
> s
->thread_info
.max_latency
)
1753 result
= s
->thread_info
.max_latency
;
1755 if (result
< s
->thread_info
.min_latency
)
1756 result
= s
->thread_info
.min_latency
;
1759 s
->thread_info
.requested_latency
= result
;
1760 s
->thread_info
.requested_latency_valid
= TRUE
;
1765 /* Called from main thread */
1766 pa_usec_t
pa_sink_get_requested_latency(pa_sink
*s
) {
1769 pa_sink_assert_ref(s
);
1770 pa_assert(PA_SINK_IS_LINKED(s
->state
));
1772 if (s
->state
== PA_SINK_SUSPENDED
)
1775 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY
, &usec
, 0, NULL
) == 0);
1779 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
1780 void pa_sink_set_max_rewind_within_thread(pa_sink
*s
, size_t max_rewind
) {
1784 pa_sink_assert_ref(s
);
1786 if (max_rewind
== s
->thread_info
.max_rewind
)
1789 s
->thread_info
.max_rewind
= max_rewind
;
1791 if (PA_SINK_IS_LINKED(s
->thread_info
.state
)) {
1792 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1793 pa_sink_input_update_max_rewind(i
, s
->thread_info
.max_rewind
);
1796 if (s
->monitor_source
)
1797 pa_source_set_max_rewind(s
->monitor_source
, s
->thread_info
.max_rewind
);
1800 /* Called from main thread */
1801 void pa_sink_set_max_rewind(pa_sink
*s
, size_t max_rewind
) {
1802 pa_sink_assert_ref(s
);
1804 if (PA_SINK_IS_LINKED(s
->state
))
1805 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_MAX_REWIND
, NULL
, max_rewind
, NULL
) == 0);
1807 pa_sink_set_max_rewind_within_thread(s
, max_rewind
);
1810 /* Called from IO as well as the main thread -- the latter only before the IO thread started up */
1811 void pa_sink_set_max_request_within_thread(pa_sink
*s
, size_t max_request
) {
1814 pa_sink_assert_ref(s
);
1816 if (max_request
== s
->thread_info
.max_request
)
1819 s
->thread_info
.max_request
= max_request
;
1821 if (PA_SINK_IS_LINKED(s
->thread_info
.state
)) {
1824 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1825 pa_sink_input_update_max_request(i
, s
->thread_info
.max_request
);
1829 /* Called from main thread */
1830 void pa_sink_set_max_request(pa_sink
*s
, size_t max_request
) {
1831 pa_sink_assert_ref(s
);
1833 if (PA_SINK_IS_LINKED(s
->state
))
1834 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_MAX_REQUEST
, NULL
, max_request
, NULL
) == 0);
1836 pa_sink_set_max_request_within_thread(s
, max_request
);
1839 /* Called from IO thread */
1840 void pa_sink_invalidate_requested_latency(pa_sink
*s
) {
1844 pa_sink_assert_ref(s
);
1846 s
->thread_info
.requested_latency_valid
= FALSE
;
1848 if (s
->update_requested_latency
)
1849 s
->update_requested_latency(s
);
1851 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1852 if (i
->update_sink_requested_latency
)
1853 i
->update_sink_requested_latency(i
);
1856 /* Called from main thread */
1857 void pa_sink_set_latency_range(pa_sink
*s
, pa_usec_t min_latency
, pa_usec_t max_latency
) {
1858 pa_sink_assert_ref(s
);
1860 /* min_latency == 0: no limit
1861 * min_latency == (size_t) -1: default limit
1862 * min_latency anything else: specified limit
1864 * Similar for max_latency */
1866 if (min_latency
== (pa_usec_t
) -1)
1867 min_latency
= DEFAULT_MIN_LATENCY
;
1869 if (min_latency
< ABSOLUTE_MIN_LATENCY
)
1870 min_latency
= ABSOLUTE_MIN_LATENCY
;
1872 if (max_latency
== (pa_usec_t
) -1)
1873 max_latency
= min_latency
;
1875 if (max_latency
> ABSOLUTE_MAX_LATENCY
|| max_latency
<= 0)
1876 max_latency
= ABSOLUTE_MAX_LATENCY
;
1878 pa_assert(min_latency
<= max_latency
);
1880 if (PA_SINK_IS_LINKED(s
->state
)) {
1886 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_SET_LATENCY_RANGE
, r
, 0, NULL
) == 0);
1888 s
->thread_info
.min_latency
= min_latency
;
1889 s
->thread_info
.max_latency
= max_latency
;
1891 s
->monitor_source
->thread_info
.min_latency
= min_latency
;
1892 s
->monitor_source
->thread_info
.max_latency
= max_latency
;
1894 s
->thread_info
.requested_latency_valid
= s
->monitor_source
->thread_info
.requested_latency_valid
= FALSE
;
1898 /* Called from main thread */
1899 void pa_sink_get_latency_range(pa_sink
*s
, pa_usec_t
*min_latency
, pa_usec_t
*max_latency
) {
1900 pa_sink_assert_ref(s
);
1901 pa_assert(min_latency
);
1902 pa_assert(max_latency
);
1904 if (PA_SINK_IS_LINKED(s
->state
)) {
1905 pa_usec_t r
[2] = { 0, 0 };
1907 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_LATENCY_RANGE
, r
, 0, NULL
) == 0);
1909 *min_latency
= r
[0];
1910 *max_latency
= r
[1];
1912 *min_latency
= s
->thread_info
.min_latency
;
1913 *max_latency
= s
->thread_info
.max_latency
;
1917 /* Called from IO thread */
1918 void pa_sink_set_latency_range_within_thread(pa_sink
*s
, pa_usec_t min_latency
, pa_usec_t max_latency
) {
1922 pa_sink_assert_ref(s
);
1924 pa_assert(min_latency
>= ABSOLUTE_MIN_LATENCY
);
1925 pa_assert(max_latency
<= ABSOLUTE_MAX_LATENCY
);
1926 pa_assert(min_latency
<= max_latency
);
1928 s
->thread_info
.min_latency
= min_latency
;
1929 s
->thread_info
.max_latency
= max_latency
;
1931 while ((i
= pa_hashmap_iterate(s
->thread_info
.inputs
, &state
, NULL
)))
1932 if (i
->update_sink_latency_range
)
1933 i
->update_sink_latency_range(i
);
1935 pa_sink_invalidate_requested_latency(s
);
1937 pa_source_set_latency_range_within_thread(s
->monitor_source
, min_latency
, max_latency
);
1940 /* Called from main context */
1941 size_t pa_sink_get_max_rewind(pa_sink
*s
) {
1943 pa_sink_assert_ref(s
);
1945 if (!PA_SINK_IS_LINKED(s
->state
))
1946 return s
->thread_info
.max_rewind
;
1948 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_MAX_REWIND
, &r
, 0, NULL
) == 0);
1953 /* Called from main context */
1954 size_t pa_sink_get_max_request(pa_sink
*s
) {
1956 pa_sink_assert_ref(s
);
1958 if (!PA_SINK_IS_LINKED(s
->state
))
1959 return s
->thread_info
.max_request
;
1961 pa_assert_se(pa_asyncmsgq_send(s
->asyncmsgq
, PA_MSGOBJECT(s
), PA_SINK_MESSAGE_GET_MAX_REQUEST
, &r
, 0, NULL
) == 0);
1966 /* Called from main context */
1967 pa_bool_t
pa_device_init_icon(pa_proplist
*p
, pa_bool_t is_sink
) {
1968 const char *ff
, *c
, *t
= NULL
, *s
= "", *profile
, *bus
;
1972 if (pa_proplist_contains(p
, PA_PROP_DEVICE_ICON_NAME
))
1975 if ((ff
= pa_proplist_gets(p
, PA_PROP_DEVICE_FORM_FACTOR
))) {
1977 if (pa_streq(ff
, "microphone"))
1978 t
= "audio-input-microphone";
1979 else if (pa_streq(ff
, "webcam"))
1981 else if (pa_streq(ff
, "computer"))
1983 else if (pa_streq(ff
, "handset"))
1985 else if (pa_streq(ff
, "portable"))
1986 t
= "multimedia-player";
1987 else if (pa_streq(ff
, "tv"))
1988 t
= "video-display";
1992 if ((c
= pa_proplist_gets(p
, PA_PROP_DEVICE_CLASS
)))
1993 if (pa_streq(c
, "modem"))
2000 t
= "audio-input-microphone";
2003 if ((profile
= pa_proplist_gets(p
, PA_PROP_DEVICE_PROFILE_NAME
))) {
2004 if (strstr(profile
, "analog"))
2006 else if (strstr(profile
, "iec958"))
2008 else if (strstr(profile
, "hdmi"))
2012 bus
= pa_proplist_gets(p
, PA_PROP_DEVICE_BUS
);
2014 pa_proplist_setf(p
, PA_PROP_DEVICE_ICON_NAME
, "%s%s%s%s", t
, pa_strempty(s
), bus
? "-" : "", pa_strempty(bus
));
2019 pa_bool_t
pa_device_init_description(pa_proplist
*p
) {
2023 if (pa_proplist_contains(p
, PA_PROP_DEVICE_DESCRIPTION
))
2026 if ((s
= pa_proplist_gets(p
, PA_PROP_DEVICE_FORM_FACTOR
)))
2027 if (pa_streq(s
, "internal")) {
2028 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, _("Internal Audio"));
2032 if ((s
= pa_proplist_gets(p
, PA_PROP_DEVICE_CLASS
)))
2033 if (pa_streq(s
, "modem")) {
2034 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, _("Modem"));
2038 if ((s
= pa_proplist_gets(p
, PA_PROP_DEVICE_PRODUCT_NAME
))) {
2039 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);