2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 #include <pulse/utf8.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/util.h>
35 #include <pulsecore/sample-util.h>
36 #include <pulsecore/core-subscribe.h>
37 #include <pulsecore/log.h>
38 #include <pulsecore/play-memblockq.h>
39 #include <pulsecore/namereg.h>
40 #include <pulsecore/core-util.h>
41 #include <pulse/timeval.h>
43 #include "sink-input.h"
45 #define MEMBLOCKQ_MAXLENGTH (32*1024*1024)
46 #define CONVERT_BUFFER_LENGTH (PA_PAGE_SIZE)
48 PA_DEFINE_PUBLIC_CLASS(pa_sink_input
, pa_msgobject
);
50 static void sink_input_free(pa_object
*o
);
51 static void set_real_ratio(pa_sink_input
*i
, const pa_cvolume
*v
);
52 static void sink_input_set_ramping_info(pa_sink_input
* i
, pa_volume_t pre_virtual_volume
, pa_volume_t target_virtual_volume
, pa_usec_t t
);
53 static void sink_input_set_ramping_info_for_mute(pa_sink_input
* i
, pa_bool_t mute
, pa_usec_t t
);
54 static void sink_input_volume_ramping(pa_sink_input
* i
, pa_memchunk
* chunk
);
55 static void sink_input_rewind_ramp_info(pa_sink_input
*i
, size_t nbytes
);
56 static void sink_input_release_envelope(pa_sink_input
*i
);
58 static int check_passthrough_connection(pa_sink_input_flags_t flags
, pa_sink
*dest
) {
60 if (dest
->flags
& PA_SINK_PASSTHROUGH
) {
62 if (pa_idxset_size(dest
->inputs
) > 0) {
67 alt_i
= pa_idxset_first(dest
->inputs
, &idx
);
69 /* only need to check the first input is not PASSTHROUGH */
70 if (alt_i
->flags
& PA_SINK_INPUT_PASSTHROUGH
) {
71 pa_log_warn("Sink is already connected to PASSTHROUGH input");
75 /* Current inputs are PCM, check new input is not PASSTHROUGH */
76 if (flags
& PA_SINK_INPUT_PASSTHROUGH
) {
77 pa_log_warn("Sink is already connected, cannot accept new PASSTHROUGH INPUT");
83 if (flags
& PA_SINK_INPUT_PASSTHROUGH
) {
84 pa_log_warn("Cannot connect PASSTHROUGH sink input to sink without PASSTHROUGH capabilities");
85 return -PA_ERR_INVALID
;
91 pa_sink_input_new_data
* pa_sink_input_new_data_init(pa_sink_input_new_data
*data
) {
95 data
->resample_method
= PA_RESAMPLER_INVALID
;
96 data
->proplist
= pa_proplist_new();
101 void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data
*data
, const pa_sample_spec
*spec
) {
104 if ((data
->sample_spec_is_set
= !!spec
))
105 data
->sample_spec
= *spec
;
108 void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data
*data
, const pa_channel_map
*map
) {
111 if ((data
->channel_map_is_set
= !!map
))
112 data
->channel_map
= *map
;
115 pa_bool_t
pa_sink_input_new_data_is_volume_writable(pa_sink_input_new_data
*data
) {
118 return !(data
->flags
& PA_SINK_INPUT_PASSTHROUGH
);
121 void pa_sink_input_new_data_set_volume(pa_sink_input_new_data
*data
, const pa_cvolume
*volume
) {
123 pa_assert(pa_sink_input_new_data_is_volume_writable(data
));
125 if ((data
->volume_is_set
= !!volume
))
126 data
->volume
= *volume
;
129 void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data
*data
, const pa_cvolume
*volume_factor
) {
131 pa_assert(volume_factor
);
133 if (data
->volume_factor_is_set
)
134 pa_sw_cvolume_multiply(&data
->volume_factor
, &data
->volume_factor
, volume_factor
);
136 data
->volume_factor_is_set
= TRUE
;
137 data
->volume_factor
= *volume_factor
;
141 void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data
*data
, const pa_cvolume
*volume_factor
) {
143 pa_assert(volume_factor
);
145 if (data
->volume_factor_sink_is_set
)
146 pa_sw_cvolume_multiply(&data
->volume_factor_sink
, &data
->volume_factor_sink
, volume_factor
);
148 data
->volume_factor_sink_is_set
= TRUE
;
149 data
->volume_factor_sink
= *volume_factor
;
153 void pa_sink_input_new_data_set_muted(pa_sink_input_new_data
*data
, pa_bool_t mute
) {
156 data
->muted_is_set
= TRUE
;
157 data
->muted
= !!mute
;
160 void pa_sink_input_new_data_done(pa_sink_input_new_data
*data
) {
163 pa_proplist_free(data
->proplist
);
166 /* Called from main context */
167 static void reset_callbacks(pa_sink_input
*i
) {
171 i
->process_rewind
= NULL
;
172 i
->update_max_rewind
= NULL
;
173 i
->update_max_request
= NULL
;
174 i
->update_sink_requested_latency
= NULL
;
175 i
->update_sink_latency_range
= NULL
;
176 i
->update_sink_fixed_latency
= NULL
;
180 i
->suspend_within_thread
= NULL
;
183 i
->get_latency
= NULL
;
184 i
->state_change
= NULL
;
185 i
->may_move_to
= NULL
;
186 i
->send_event
= NULL
;
187 i
->volume_changed
= NULL
;
188 i
->mute_changed
= NULL
;
191 /* Called from main context */
192 int pa_sink_input_new(
195 pa_sink_input_new_data
*data
) {
198 pa_resampler
*resampler
= NULL
;
199 char st
[PA_SAMPLE_SPEC_SNPRINT_MAX
], cm
[PA_CHANNEL_MAP_SNPRINT_MAX
];
200 pa_channel_map original_cm
;
207 pa_assert_ctl_context();
210 pa_proplist_update(data
->proplist
, PA_UPDATE_MERGE
, data
->client
->proplist
);
212 if ((r
= pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SINK_INPUT_NEW
], data
)) < 0)
215 pa_assert(!data
->volume_is_set
|| pa_sink_input_new_data_is_volume_writable(data
));
216 pa_return_val_if_fail(!data
->driver
|| pa_utf8_valid(data
->driver
), -PA_ERR_INVALID
);
219 data
->sink
= pa_namereg_get(core
, NULL
, PA_NAMEREG_SINK
);
220 data
->save_sink
= FALSE
;
223 pa_return_val_if_fail(data
->sink
, -PA_ERR_NOENTITY
);
224 pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data
->sink
)), -PA_ERR_BADSTATE
);
225 pa_return_val_if_fail(!data
->sync_base
|| (data
->sync_base
->sink
== data
->sink
&& pa_sink_input_get_state(data
->sync_base
) == PA_SINK_INPUT_CORKED
), -PA_ERR_INVALID
);
227 r
= check_passthrough_connection(data
->flags
, data
->sink
);
228 pa_return_val_if_fail(r
== PA_OK
, r
);
230 if (!data
->sample_spec_is_set
)
231 data
->sample_spec
= data
->sink
->sample_spec
;
233 pa_return_val_if_fail(pa_sample_spec_valid(&data
->sample_spec
), -PA_ERR_INVALID
);
235 if (!data
->channel_map_is_set
) {
236 if (pa_channel_map_compatible(&data
->sink
->channel_map
, &data
->sample_spec
))
237 data
->channel_map
= data
->sink
->channel_map
;
239 pa_channel_map_init_extend(&data
->channel_map
, data
->sample_spec
.channels
, PA_CHANNEL_MAP_DEFAULT
);
242 pa_return_val_if_fail(pa_channel_map_compatible(&data
->channel_map
, &data
->sample_spec
), -PA_ERR_INVALID
);
244 if (!data
->volume_is_set
) {
245 pa_cvolume_reset(&data
->volume
, data
->sample_spec
.channels
);
246 data
->volume_is_absolute
= FALSE
;
247 data
->save_volume
= FALSE
;
250 pa_return_val_if_fail(pa_cvolume_compatible(&data
->volume
, &data
->sample_spec
), -PA_ERR_INVALID
);
252 if (!data
->volume_factor_is_set
)
253 pa_cvolume_reset(&data
->volume_factor
, data
->sample_spec
.channels
);
255 pa_return_val_if_fail(pa_cvolume_compatible(&data
->volume_factor
, &data
->sample_spec
), -PA_ERR_INVALID
);
257 if (!data
->volume_factor_sink_is_set
)
258 pa_cvolume_reset(&data
->volume_factor_sink
, data
->sink
->sample_spec
.channels
);
260 pa_return_val_if_fail(pa_cvolume_compatible(&data
->volume_factor_sink
, &data
->sink
->sample_spec
), -PA_ERR_INVALID
);
262 if (!data
->muted_is_set
)
265 if (data
->flags
& PA_SINK_INPUT_FIX_FORMAT
)
266 data
->sample_spec
.format
= data
->sink
->sample_spec
.format
;
268 if (data
->flags
& PA_SINK_INPUT_FIX_RATE
)
269 data
->sample_spec
.rate
= data
->sink
->sample_spec
.rate
;
271 original_cm
= data
->channel_map
;
273 if (data
->flags
& PA_SINK_INPUT_FIX_CHANNELS
) {
274 data
->sample_spec
.channels
= data
->sink
->sample_spec
.channels
;
275 data
->channel_map
= data
->sink
->channel_map
;
278 pa_assert(pa_sample_spec_valid(&data
->sample_spec
));
279 pa_assert(pa_channel_map_valid(&data
->channel_map
));
281 /* Due to the fixing of the sample spec the volume might not match anymore */
282 pa_cvolume_remap(&data
->volume
, &original_cm
, &data
->channel_map
);
284 if (data
->resample_method
== PA_RESAMPLER_INVALID
)
285 data
->resample_method
= core
->resample_method
;
287 pa_return_val_if_fail(data
->resample_method
< PA_RESAMPLER_MAX
, -PA_ERR_INVALID
);
289 if ((r
= pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SINK_INPUT_FIXATE
], data
)) < 0)
292 if ((data
->flags
& PA_SINK_INPUT_NO_CREATE_ON_SUSPEND
) &&
293 pa_sink_get_state(data
->sink
) == PA_SINK_SUSPENDED
) {
294 pa_log_warn("Failed to create sink input: sink is suspended.");
295 return -PA_ERR_BADSTATE
;
298 if (pa_idxset_size(data
->sink
->inputs
) >= PA_MAX_INPUTS_PER_SINK
) {
299 pa_log_warn("Failed to create sink input: too many inputs per sink.");
300 return -PA_ERR_TOOLARGE
;
303 if ((data
->flags
& PA_SINK_INPUT_VARIABLE_RATE
) ||
304 !pa_sample_spec_equal(&data
->sample_spec
, &data
->sink
->sample_spec
) ||
305 !pa_channel_map_equal(&data
->channel_map
, &data
->sink
->channel_map
)) {
307 if (!(resampler
= pa_resampler_new(
309 &data
->sample_spec
, &data
->channel_map
,
310 &data
->sink
->sample_spec
, &data
->sink
->channel_map
,
311 data
->resample_method
,
312 ((data
->flags
& PA_SINK_INPUT_VARIABLE_RATE
) ? PA_RESAMPLER_VARIABLE_RATE
: 0) |
313 ((data
->flags
& PA_SINK_INPUT_NO_REMAP
) ? PA_RESAMPLER_NO_REMAP
: 0) |
314 (core
->disable_remixing
|| (data
->flags
& PA_SINK_INPUT_NO_REMIX
) ? PA_RESAMPLER_NO_REMIX
: 0) |
315 (core
->disable_lfe_remixing
? PA_RESAMPLER_NO_LFE
: 0)))) {
316 pa_log_warn("Unsupported resampling operation.");
317 return -PA_ERR_NOTSUPPORTED
;
321 i
= pa_msgobject_new(pa_sink_input
);
322 i
->parent
.parent
.free
= sink_input_free
;
323 i
->parent
.process_msg
= pa_sink_input_process_msg
;
326 i
->state
= PA_SINK_INPUT_INIT
;
327 i
->flags
= data
->flags
;
328 i
->proplist
= pa_proplist_copy(data
->proplist
);
329 i
->driver
= pa_xstrdup(pa_path_get_filename(data
->driver
));
330 i
->module
= data
->module
;
331 i
->sink
= data
->sink
;
332 i
->origin_sink
= data
->origin_sink
;
333 i
->client
= data
->client
;
335 i
->requested_resample_method
= data
->resample_method
;
336 i
->actual_resample_method
= resampler
? pa_resampler_get_method(resampler
) : PA_RESAMPLER_INVALID
;
337 i
->sample_spec
= data
->sample_spec
;
338 i
->channel_map
= data
->channel_map
;
340 if ((i
->sink
->flags
& PA_SINK_FLAT_VOLUME
) && !data
->volume_is_absolute
) {
343 /* When the 'absolute' bool is not set then we'll treat the volume
344 * as relative to the sink volume even in flat volume mode */
345 remapped
= data
->sink
->reference_volume
;
346 pa_cvolume_remap(&remapped
, &data
->sink
->channel_map
, &data
->channel_map
);
347 pa_sw_cvolume_multiply(&i
->volume
, &data
->volume
, &remapped
);
349 i
->volume
= data
->volume
;
351 i
->volume_factor
= data
->volume_factor
;
352 i
->volume_factor_sink
= data
->volume_factor_sink
;
353 i
->real_ratio
= i
->reference_ratio
= data
->volume
;
354 pa_cvolume_reset(&i
->soft_volume
, i
->sample_spec
.channels
);
355 pa_cvolume_reset(&i
->real_ratio
, i
->sample_spec
.channels
);
356 i
->save_volume
= data
->save_volume
;
357 i
->save_sink
= data
->save_sink
;
358 i
->save_muted
= data
->save_muted
;
360 i
->muted
= data
->muted
;
362 if (data
->sync_base
) {
363 i
->sync_next
= data
->sync_base
->sync_next
;
364 i
->sync_prev
= data
->sync_base
;
366 if (data
->sync_base
->sync_next
)
367 data
->sync_base
->sync_next
->sync_prev
= i
;
368 data
->sync_base
->sync_next
= i
;
370 i
->sync_next
= i
->sync_prev
= NULL
;
372 i
->direct_outputs
= pa_idxset_new(NULL
, NULL
);
377 /* Set Ramping info */
378 i
->thread_info
.ramp_info
.is_ramping
= FALSE
;
379 i
->thread_info
.ramp_info
.envelope_dead
= TRUE
;
380 i
->thread_info
.ramp_info
.envelope
= NULL
;
381 i
->thread_info
.ramp_info
.item
= NULL
;
382 i
->thread_info
.ramp_info
.envelope_dying
= 0;
384 pa_atomic_store(&i
->before_ramping_v
, 0);
385 pa_atomic_store(&i
->before_ramping_m
, 0);
387 i
->thread_info
.state
= i
->state
;
388 i
->thread_info
.attached
= FALSE
;
389 pa_atomic_store(&i
->thread_info
.drained
, 1);
390 i
->thread_info
.sample_spec
= i
->sample_spec
;
391 i
->thread_info
.resampler
= resampler
;
392 i
->thread_info
.soft_volume
= i
->soft_volume
;
393 i
->thread_info
.muted
= i
->muted
;
394 i
->thread_info
.requested_sink_latency
= (pa_usec_t
) -1;
395 i
->thread_info
.rewrite_nbytes
= 0;
396 i
->thread_info
.rewrite_flush
= FALSE
;
397 i
->thread_info
.dont_rewind_render
= FALSE
;
398 i
->thread_info
.underrun_for
= (uint64_t) -1;
399 i
->thread_info
.playing_for
= 0;
400 i
->thread_info
.direct_outputs
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
402 i
->thread_info
.render_memblockq
= pa_memblockq_new(
406 pa_frame_size(&i
->sink
->sample_spec
),
412 pa_assert_se(pa_idxset_put(core
->sink_inputs
, i
, &i
->index
) == 0);
413 pa_assert_se(pa_idxset_put(i
->sink
->inputs
, pa_sink_input_ref(i
), NULL
) == 0);
416 pa_assert_se(pa_idxset_put(i
->client
->sink_inputs
, i
, NULL
) >= 0);
418 pt
= pa_proplist_to_string_sep(i
->proplist
, "\n ");
419 pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
421 pa_strnull(pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
)),
423 pa_sample_spec_snprint(st
, sizeof(st
), &i
->sample_spec
),
424 pa_channel_map_snprint(cm
, sizeof(cm
), &i
->channel_map
),
428 /* Don't forget to call pa_sink_input_put! */
434 /* Called from main context */
435 static void update_n_corked(pa_sink_input
*i
, pa_sink_input_state_t state
) {
437 pa_assert_ctl_context();
442 if (i
->state
== PA_SINK_INPUT_CORKED
&& state
!= PA_SINK_INPUT_CORKED
)
443 pa_assert_se(i
->sink
->n_corked
-- >= 1);
444 else if (i
->state
!= PA_SINK_INPUT_CORKED
&& state
== PA_SINK_INPUT_CORKED
)
448 /* Called from main context */
449 static void sink_input_set_state(pa_sink_input
*i
, pa_sink_input_state_t state
) {
450 pa_sink_input
*ssync
;
452 pa_assert_ctl_context();
454 if (state
== PA_SINK_INPUT_DRAINED
)
455 state
= PA_SINK_INPUT_RUNNING
;
457 if (i
->state
== state
)
460 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_SET_STATE
, PA_UINT_TO_PTR(state
), 0, NULL
) == 0);
462 update_n_corked(i
, state
);
465 for (ssync
= i
->sync_prev
; ssync
; ssync
= ssync
->sync_prev
) {
466 update_n_corked(ssync
, state
);
467 ssync
->state
= state
;
469 for (ssync
= i
->sync_next
; ssync
; ssync
= ssync
->sync_next
) {
470 update_n_corked(ssync
, state
);
471 ssync
->state
= state
;
474 if (state
!= PA_SINK_INPUT_UNLINKED
) {
475 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED
], i
);
477 for (ssync
= i
->sync_prev
; ssync
; ssync
= ssync
->sync_prev
)
478 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED
], ssync
);
480 for (ssync
= i
->sync_next
; ssync
; ssync
= ssync
->sync_next
)
481 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED
], ssync
);
483 if (PA_SINK_INPUT_IS_LINKED(state
))
484 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
487 pa_sink_update_status(i
->sink
);
490 /* Called from main context */
491 void pa_sink_input_unlink(pa_sink_input
*i
) {
493 pa_source_output
*o
, *p
= NULL
;
496 pa_assert_ctl_context();
498 /* See pa_sink_unlink() for a couple of comments how this function
501 pa_sink_input_ref(i
);
503 linked
= PA_SINK_INPUT_IS_LINKED(i
->state
);
506 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_UNLINK
], i
);
509 i
->sync_prev
->sync_next
= i
->sync_next
;
511 i
->sync_next
->sync_prev
= i
->sync_prev
;
513 i
->sync_prev
= i
->sync_next
= NULL
;
515 pa_idxset_remove_by_data(i
->core
->sink_inputs
, i
, NULL
);
518 if (pa_idxset_remove_by_data(i
->sink
->inputs
, i
, NULL
))
519 pa_sink_input_unref(i
);
522 pa_idxset_remove_by_data(i
->client
->sink_inputs
, i
, NULL
);
524 while ((o
= pa_idxset_first(i
->direct_outputs
, NULL
))) {
526 pa_source_output_kill(o
);
530 update_n_corked(i
, PA_SINK_INPUT_UNLINKED
);
531 i
->state
= PA_SINK_INPUT_UNLINKED
;
533 if (linked
&& i
->sink
) {
534 /* We might need to update the sink's volume if we are in flat volume mode. */
535 if (i
->sink
->flags
& PA_SINK_FLAT_VOLUME
)
536 pa_sink_set_volume(i
->sink
, NULL
, FALSE
, FALSE
);
538 if (i
->sink
->asyncmsgq
)
539 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
->sink
), PA_SINK_MESSAGE_REMOVE_INPUT
, i
, 0, NULL
) == 0);
545 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_REMOVE
, i
->index
);
546 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST
], i
);
550 pa_sink_update_status(i
->sink
);
554 pa_core_maybe_vacuum(i
->core
);
556 pa_sink_input_unref(i
);
559 /* Called from main context */
560 static void sink_input_free(pa_object
*o
) {
561 pa_sink_input
* i
= PA_SINK_INPUT(o
);
564 pa_assert_ctl_context();
565 pa_assert(pa_sink_input_refcnt(i
) == 0);
567 if (PA_SINK_INPUT_IS_LINKED(i
->state
))
568 pa_sink_input_unlink(i
);
570 pa_log_info("Freeing input %u \"%s\"", i
->index
, pa_strnull(pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
)));
572 /* Side note: this function must be able to destruct properly any
573 * kind of sink input in any state, even those which are
574 * "half-moved" or are connected to sinks that have no asyncmsgq
575 * and are hence half-destructed themselves! */
577 if (i
->thread_info
.ramp_info
.envelope
) {
578 pa_log_debug ("Freeing envelope\n");
579 pa_envelope_free(i
->thread_info
.ramp_info
.envelope
);
580 i
->thread_info
.ramp_info
.envelope
= NULL
;
583 if (i
->thread_info
.render_memblockq
)
584 pa_memblockq_free(i
->thread_info
.render_memblockq
);
586 if (i
->thread_info
.resampler
)
587 pa_resampler_free(i
->thread_info
.resampler
);
590 pa_proplist_free(i
->proplist
);
592 if (i
->direct_outputs
)
593 pa_idxset_free(i
->direct_outputs
, NULL
, NULL
);
595 if (i
->thread_info
.direct_outputs
)
596 pa_hashmap_free(i
->thread_info
.direct_outputs
, NULL
, NULL
);
602 /* Called from main context */
603 void pa_sink_input_put(pa_sink_input
*i
) {
604 pa_sink_input_state_t state
;
606 pa_sink_input_assert_ref(i
);
607 pa_assert_ctl_context();
609 pa_assert(i
->state
== PA_SINK_INPUT_INIT
);
611 /* The following fields must be initialized properly */
613 pa_assert(i
->process_rewind
);
616 state
= i
->flags
& PA_SINK_INPUT_START_CORKED
? PA_SINK_INPUT_CORKED
: PA_SINK_INPUT_RUNNING
;
618 update_n_corked(i
, state
);
621 /* We might need to update the sink's volume if we are in flat volume mode. */
622 if (i
->sink
->flags
& PA_SINK_FLAT_VOLUME
)
623 pa_sink_set_volume(i
->sink
, NULL
, FALSE
, i
->save_volume
);
625 set_real_ratio(i
, &i
->volume
);
627 i
->thread_info
.soft_volume
= i
->soft_volume
;
628 i
->thread_info
.muted
= i
->muted
;
630 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
->sink
), PA_SINK_MESSAGE_ADD_INPUT
, i
, 0, NULL
) == 0);
632 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_NEW
, i
->index
);
633 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_PUT
], i
);
635 pa_sink_update_status(i
->sink
);
638 /* Called from main context */
639 void pa_sink_input_kill(pa_sink_input
*i
) {
640 pa_sink_input_assert_ref(i
);
641 pa_assert_ctl_context();
642 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
647 /* Called from main context */
648 pa_usec_t
pa_sink_input_get_latency(pa_sink_input
*i
, pa_usec_t
*sink_latency
) {
649 pa_usec_t r
[2] = { 0, 0 };
651 pa_sink_input_assert_ref(i
);
652 pa_assert_ctl_context();
653 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
655 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_GET_LATENCY
, r
, 0, NULL
) == 0);
658 r
[0] += i
->get_latency(i
);
661 *sink_latency
= r
[1];
666 /* Called from thread context */
667 void pa_sink_input_peek(pa_sink_input
*i
, size_t slength
/* in sink frames */, pa_memchunk
*chunk
, pa_cvolume
*volume
) {
668 pa_bool_t do_volume_adj_here
, need_volume_factor_sink
;
669 pa_bool_t volume_is_norm
;
671 size_t block_size_max_sink
, block_size_max_sink_input
;
674 pa_sink_input_assert_ref(i
);
675 pa_sink_input_assert_io_context(i
);
676 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->thread_info
.state
));
677 pa_assert(pa_frame_aligned(slength
, &i
->sink
->sample_spec
));
681 /* pa_log_debug("peek"); */
683 pa_assert(i
->thread_info
.state
== PA_SINK_INPUT_RUNNING
||
684 i
->thread_info
.state
== PA_SINK_INPUT_CORKED
||
685 i
->thread_info
.state
== PA_SINK_INPUT_DRAINED
);
687 block_size_max_sink_input
= i
->thread_info
.resampler
?
688 pa_resampler_max_block_size(i
->thread_info
.resampler
) :
689 pa_frame_align(pa_mempool_block_size_max(i
->core
->mempool
), &i
->sample_spec
);
691 block_size_max_sink
= pa_frame_align(pa_mempool_block_size_max(i
->core
->mempool
), &i
->sink
->sample_spec
);
693 /* Default buffer size */
695 slength
= pa_frame_align(CONVERT_BUFFER_LENGTH
, &i
->sink
->sample_spec
);
697 if (slength
> block_size_max_sink
)
698 slength
= block_size_max_sink
;
700 if (i
->thread_info
.resampler
) {
701 ilength
= pa_resampler_request(i
->thread_info
.resampler
, slength
);
704 ilength
= pa_frame_align(CONVERT_BUFFER_LENGTH
, &i
->sample_spec
);
708 if (ilength
> block_size_max_sink_input
)
709 ilength
= block_size_max_sink_input
;
711 /* If the channel maps of the sink and this stream differ, we need
712 * to adjust the volume *before* we resample. Otherwise we can do
713 * it after and leave it for the sink code */
715 do_volume_adj_here
= !pa_channel_map_equal(&i
->channel_map
, &i
->sink
->channel_map
) || i
->thread_info
.ramp_info
.is_ramping
;
716 volume_is_norm
= pa_cvolume_is_norm(&i
->thread_info
.soft_volume
) && !i
->thread_info
.muted
;
717 need_volume_factor_sink
= !pa_cvolume_is_norm(&i
->volume_factor_sink
);
719 while (!pa_memblockq_is_readable(i
->thread_info
.render_memblockq
)) {
722 /* There's nothing in our render queue. We need to fill it up
723 * with data from the implementor. */
725 if (i
->thread_info
.state
== PA_SINK_INPUT_CORKED
||
726 i
->pop(i
, ilength
, &tchunk
) < 0) {
728 /* OK, we're corked or the implementor didn't give us any
729 * data, so let's just hand out silence */
730 pa_atomic_store(&i
->thread_info
.drained
, 1);
732 pa_memblockq_seek(i
->thread_info
.render_memblockq
, (int64_t) slength
, PA_SEEK_RELATIVE
, TRUE
);
733 i
->thread_info
.playing_for
= 0;
734 if (i
->thread_info
.underrun_for
!= (uint64_t) -1)
735 i
->thread_info
.underrun_for
+= ilength
;
739 pa_atomic_store(&i
->thread_info
.drained
, 0);
741 pa_assert(tchunk
.length
> 0);
742 pa_assert(tchunk
.memblock
);
744 i
->thread_info
.underrun_for
= 0;
745 i
->thread_info
.playing_for
+= tchunk
.length
;
747 while (tchunk
.length
> 0) {
749 pa_bool_t nvfs
= need_volume_factor_sink
;
752 pa_memblock_ref(wchunk
.memblock
);
754 if (wchunk
.length
> block_size_max_sink_input
)
755 wchunk
.length
= block_size_max_sink_input
;
757 /* It might be necessary to adjust the volume here */
758 if (do_volume_adj_here
&& !volume_is_norm
&& !i
->thread_info
.ramp_info
.is_ramping
) {
759 pa_memchunk_make_writable(&wchunk
, 0);
761 if (i
->thread_info
.muted
) {
762 pa_silence_memchunk(&wchunk
, &i
->thread_info
.sample_spec
);
765 } else if (!i
->thread_info
.resampler
&& nvfs
) {
768 /* If we don't need a resampler we can merge the
769 * post and the pre volume adjustment into one */
771 pa_sw_cvolume_multiply(&v
, &i
->thread_info
.soft_volume
, &i
->volume_factor_sink
);
772 pa_volume_memchunk(&wchunk
, &i
->thread_info
.sample_spec
, &v
);
776 pa_volume_memchunk(&wchunk
, &i
->thread_info
.sample_spec
, &i
->thread_info
.soft_volume
);
779 if (!i
->thread_info
.resampler
) {
782 pa_memchunk_make_writable(&wchunk
, 0);
783 pa_volume_memchunk(&wchunk
, &i
->sink
->sample_spec
, &i
->volume_factor_sink
);
786 pa_memblockq_push_align(i
->thread_info
.render_memblockq
, &wchunk
);
789 pa_resampler_run(i
->thread_info
.resampler
, &wchunk
, &rchunk
);
791 /* pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */
793 if (rchunk
.memblock
) {
796 pa_memchunk_make_writable(&rchunk
, 0);
797 pa_volume_memchunk(&rchunk
, &i
->sink
->sample_spec
, &i
->volume_factor_sink
);
800 pa_memblockq_push_align(i
->thread_info
.render_memblockq
, &rchunk
);
801 pa_memblock_unref(rchunk
.memblock
);
805 pa_memblock_unref(wchunk
.memblock
);
807 tchunk
.index
+= wchunk
.length
;
808 tchunk
.length
-= wchunk
.length
;
811 pa_memblock_unref(tchunk
.memblock
);
814 pa_assert_se(pa_memblockq_peek(i
->thread_info
.render_memblockq
, chunk
) >= 0);
816 pa_assert(chunk
->length
> 0);
817 pa_assert(chunk
->memblock
);
819 /* pa_log_debug("peeking %lu", (unsigned long) chunk->length); */
821 if (chunk
->length
> block_size_max_sink
)
822 chunk
->length
= block_size_max_sink
;
824 ramping
= i
->thread_info
.ramp_info
.is_ramping
;
826 sink_input_volume_ramping(i
, chunk
);
828 if (!i
->thread_info
.ramp_info
.envelope_dead
) {
829 i
->thread_info
.ramp_info
.envelope_dying
+= chunk
->length
;
830 pa_log_debug("Envelope dying is %d, chunk length is %zu, dead thresholder is %lu\n", i
->thread_info
.ramp_info
.envelope_dying
,
832 i
->sink
->thread_info
.max_rewind
+ pa_envelope_length(i
->thread_info
.ramp_info
.envelope
));
834 if (i
->thread_info
.ramp_info
.envelope_dying
>= (int32_t) (i
->sink
->thread_info
.max_rewind
+ pa_envelope_length(i
->thread_info
.ramp_info
.envelope
))) {
835 pa_log_debug("RELEASE Envelop");
836 i
->thread_info
.ramp_info
.envelope_dead
= TRUE
;
837 sink_input_release_envelope(i
);
841 /* Let's see if we had to apply the volume adjustment ourselves,
842 * or if this can be done by the sink for us */
844 if (do_volume_adj_here
)
845 /* We had different channel maps, so we already did the adjustment */
846 pa_cvolume_reset(volume
, i
->sink
->sample_spec
.channels
);
847 else if (i
->thread_info
.muted
)
848 /* We've both the same channel map, so let's have the sink do the adjustment for us*/
849 pa_cvolume_mute(volume
, i
->sink
->sample_spec
.channels
);
851 *volume
= i
->thread_info
.soft_volume
;
854 /* Called from thread context */
855 void pa_sink_input_drop(pa_sink_input
*i
, size_t nbytes
/* in sink sample spec */) {
857 pa_sink_input_assert_ref(i
);
858 pa_sink_input_assert_io_context(i
);
859 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->thread_info
.state
));
860 pa_assert(pa_frame_aligned(nbytes
, &i
->sink
->sample_spec
));
861 pa_assert(nbytes
> 0);
863 /* pa_log_debug("dropping %lu", (unsigned long) nbytes); */
865 pa_memblockq_drop(i
->thread_info
.render_memblockq
, nbytes
);
868 /* Called from thread context */
869 void pa_sink_input_process_rewind(pa_sink_input
*i
, size_t nbytes
/* in sink sample spec */) {
871 pa_bool_t called
= FALSE
;
873 pa_sink_input_assert_ref(i
);
874 pa_sink_input_assert_io_context(i
);
875 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->thread_info
.state
));
876 pa_assert(pa_frame_aligned(nbytes
, &i
->sink
->sample_spec
));
878 /* pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes); */
880 lbq
= pa_memblockq_get_length(i
->thread_info
.render_memblockq
);
882 if (nbytes
> 0 && !i
->thread_info
.dont_rewind_render
) {
883 pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes
);
884 pa_memblockq_rewind(i
->thread_info
.render_memblockq
, nbytes
);
885 sink_input_rewind_ramp_info(i
, nbytes
);
888 if (i
->thread_info
.rewrite_nbytes
== (size_t) -1) {
890 /* We were asked to drop all buffered data, and rerequest new
891 * data from implementor the next time push() is called */
893 pa_memblockq_flush_write(i
->thread_info
.render_memblockq
, TRUE
);
895 } else if (i
->thread_info
.rewrite_nbytes
> 0) {
896 size_t max_rewrite
, amount
;
898 /* Calculate how much make sense to rewrite at most */
899 max_rewrite
= nbytes
+ lbq
;
901 /* Transform into local domain */
902 if (i
->thread_info
.resampler
)
903 max_rewrite
= pa_resampler_request(i
->thread_info
.resampler
, max_rewrite
);
905 /* Calculate how much of the rewinded data should actually be rewritten */
906 amount
= PA_MIN(i
->thread_info
.rewrite_nbytes
, max_rewrite
);
909 pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount
);
911 /* Tell the implementor */
912 if (i
->process_rewind
)
913 i
->process_rewind(i
, amount
);
916 /* Convert back to to sink domain */
917 if (i
->thread_info
.resampler
)
918 amount
= pa_resampler_result(i
->thread_info
.resampler
, amount
);
921 /* Ok, now update the write pointer */
922 pa_memblockq_seek(i
->thread_info
.render_memblockq
, - ((int64_t) amount
), PA_SEEK_RELATIVE
, TRUE
);
924 if (i
->thread_info
.rewrite_flush
)
925 pa_memblockq_silence(i
->thread_info
.render_memblockq
);
927 /* And reset the resampler */
928 if (i
->thread_info
.resampler
)
929 pa_resampler_reset(i
->thread_info
.resampler
);
934 if (i
->process_rewind
)
935 i
->process_rewind(i
, 0);
937 i
->thread_info
.rewrite_nbytes
= 0;
938 i
->thread_info
.rewrite_flush
= FALSE
;
939 i
->thread_info
.dont_rewind_render
= FALSE
;
942 /* Called from thread context */
943 size_t pa_sink_input_get_max_rewind(pa_sink_input
*i
) {
944 pa_sink_input_assert_ref(i
);
945 pa_sink_input_assert_io_context(i
);
947 return i
->thread_info
.resampler
? pa_resampler_request(i
->thread_info
.resampler
, i
->sink
->thread_info
.max_rewind
) : i
->sink
->thread_info
.max_rewind
;
950 /* Called from thread context */
951 size_t pa_sink_input_get_max_request(pa_sink_input
*i
) {
952 pa_sink_input_assert_ref(i
);
953 pa_sink_input_assert_io_context(i
);
955 /* We're not verifying the status here, to allow this to be called
956 * in the state change handler between _INIT and _RUNNING */
958 return i
->thread_info
.resampler
? pa_resampler_request(i
->thread_info
.resampler
, i
->sink
->thread_info
.max_request
) : i
->sink
->thread_info
.max_request
;
961 /* Called from thread context */
962 void pa_sink_input_update_max_rewind(pa_sink_input
*i
, size_t nbytes
/* in the sink's sample spec */) {
963 pa_sink_input_assert_ref(i
);
964 pa_sink_input_assert_io_context(i
);
965 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->thread_info
.state
));
966 pa_assert(pa_frame_aligned(nbytes
, &i
->sink
->sample_spec
));
968 pa_memblockq_set_maxrewind(i
->thread_info
.render_memblockq
, nbytes
);
970 if (i
->update_max_rewind
)
971 i
->update_max_rewind(i
, i
->thread_info
.resampler
? pa_resampler_request(i
->thread_info
.resampler
, nbytes
) : nbytes
);
974 /* Called from thread context */
975 void pa_sink_input_update_max_request(pa_sink_input
*i
, size_t nbytes
/* in the sink's sample spec */) {
976 pa_sink_input_assert_ref(i
);
977 pa_sink_input_assert_io_context(i
);
978 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->thread_info
.state
));
979 pa_assert(pa_frame_aligned(nbytes
, &i
->sink
->sample_spec
));
981 if (i
->update_max_request
)
982 i
->update_max_request(i
, i
->thread_info
.resampler
? pa_resampler_request(i
->thread_info
.resampler
, nbytes
) : nbytes
);
985 /* Called from thread context */
986 pa_usec_t
pa_sink_input_set_requested_latency_within_thread(pa_sink_input
*i
, pa_usec_t usec
) {
987 pa_sink_input_assert_ref(i
);
988 pa_sink_input_assert_io_context(i
);
990 if (!(i
->sink
->flags
& PA_SINK_DYNAMIC_LATENCY
))
991 usec
= i
->sink
->thread_info
.fixed_latency
;
993 if (usec
!= (pa_usec_t
) -1)
994 usec
= PA_CLAMP(usec
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
996 i
->thread_info
.requested_sink_latency
= usec
;
997 pa_sink_invalidate_requested_latency(i
->sink
, TRUE
);
1002 /* Called from main context */
1003 pa_usec_t
pa_sink_input_set_requested_latency(pa_sink_input
*i
, pa_usec_t usec
) {
1004 pa_sink_input_assert_ref(i
);
1005 pa_assert_ctl_context();
1007 if (PA_SINK_INPUT_IS_LINKED(i
->state
) && i
->sink
) {
1008 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY
, &usec
, 0, NULL
) == 0);
1012 /* If this sink input is not realized yet or we are being moved,
1013 * we have to touch the thread info data directly */
1016 if (!(i
->sink
->flags
& PA_SINK_DYNAMIC_LATENCY
))
1017 usec
= pa_sink_get_fixed_latency(i
->sink
);
1019 if (usec
!= (pa_usec_t
) -1) {
1020 pa_usec_t min_latency
, max_latency
;
1021 pa_sink_get_latency_range(i
->sink
, &min_latency
, &max_latency
);
1022 usec
= PA_CLAMP(usec
, min_latency
, max_latency
);
1026 i
->thread_info
.requested_sink_latency
= usec
;
1031 /* Called from main context */
1032 pa_usec_t
pa_sink_input_get_requested_latency(pa_sink_input
*i
) {
1033 pa_sink_input_assert_ref(i
);
1034 pa_assert_ctl_context();
1036 if (PA_SINK_INPUT_IS_LINKED(i
->state
) && i
->sink
) {
1038 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY
, &usec
, 0, NULL
) == 0);
1042 /* If this sink input is not realized yet or we are being moved,
1043 * we have to touch the thread info data directly */
1045 return i
->thread_info
.requested_sink_latency
;
1048 /* Called from main context */
1049 static void set_real_ratio(pa_sink_input
*i
, const pa_cvolume
*v
) {
1050 pa_sink_input_assert_ref(i
);
1051 pa_assert_ctl_context();
1052 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1053 pa_assert(!v
|| pa_cvolume_compatible(v
, &i
->sample_spec
));
1055 /* This basically calculates:
1057 * i->real_ratio := v
1058 * i->soft_volume := i->real_ratio * i->volume_factor */
1063 pa_cvolume_reset(&i
->real_ratio
, i
->sample_spec
.channels
);
1065 pa_sw_cvolume_multiply(&i
->soft_volume
, &i
->real_ratio
, &i
->volume_factor
);
1066 /* We don't copy the data to the thread_info data. That's left for someone else to do */
1069 /* Called from main context */
1070 pa_bool_t
pa_sink_input_is_volume_readable(pa_sink_input
*i
) {
1071 pa_sink_input_assert_ref(i
);
1072 pa_assert_ctl_context();
1074 return !(i
->flags
& PA_SINK_INPUT_PASSTHROUGH
);
1077 /* Called from main context */
1078 pa_bool_t
pa_sink_input_is_volume_writable(pa_sink_input
*i
) {
1079 pa_sink_input_assert_ref(i
);
1080 pa_assert_ctl_context();
1082 return !(i
->flags
& PA_SINK_INPUT_PASSTHROUGH
);
1085 /* Called from main context */
1086 void pa_sink_input_set_volume(pa_sink_input
*i
, const pa_cvolume
*volume
, pa_bool_t save
, pa_bool_t absolute
) {
1087 /* test ramping -> return pa_sink_input_set_volume_with_ramping(i, volume, save, absolute, 2000 * PA_USEC_PER_MSEC); */
1088 return pa_sink_input_set_volume_with_ramping(i
, volume
, save
, absolute
, 0);
1091 /* Called from main context */
1092 pa_cvolume
*pa_sink_input_get_volume(pa_sink_input
*i
, pa_cvolume
*volume
, pa_bool_t absolute
) {
1093 pa_sink_input_assert_ref(i
);
1094 pa_assert_ctl_context();
1095 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1096 pa_assert(pa_sink_input_is_volume_readable(i
));
1098 if (absolute
|| !(i
->sink
->flags
& PA_SINK_FLAT_VOLUME
))
1099 *volume
= i
->volume
;
1101 *volume
= i
->reference_ratio
;
1106 /* Called from main context */
1107 void pa_sink_input_set_mute(pa_sink_input
*i
, pa_bool_t mute
, pa_bool_t save
) {
1108 /* test ramping -> return pa_sink_input_set_mute_with_ramping(i, mute, save, 2000 * PA_USEC_PER_MSEC); */
1109 return pa_sink_input_set_mute_with_ramping(i
, mute
, save
, 0);
1112 /* Called from main context */
1113 pa_bool_t
pa_sink_input_get_mute(pa_sink_input
*i
) {
1114 pa_sink_input_assert_ref(i
);
1115 pa_assert_ctl_context();
1116 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1121 /* Called from main thread */
1122 void pa_sink_input_update_proplist(pa_sink_input
*i
, pa_update_mode_t mode
, pa_proplist
*p
) {
1123 pa_sink_input_assert_ref(i
);
1124 pa_assert_ctl_context();
1127 pa_proplist_update(i
->proplist
, mode
, p
);
1129 if (PA_SINK_INPUT_IS_LINKED(i
->state
)) {
1130 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED
], i
);
1131 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1135 /* Called from main context */
1136 void pa_sink_input_cork(pa_sink_input
*i
, pa_bool_t b
) {
1137 pa_sink_input_assert_ref(i
);
1138 pa_assert_ctl_context();
1139 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1141 sink_input_set_state(i
, b
? PA_SINK_INPUT_CORKED
: PA_SINK_INPUT_RUNNING
);
1144 /* Called from main context */
1145 int pa_sink_input_set_rate(pa_sink_input
*i
, uint32_t rate
) {
1146 pa_sink_input_assert_ref(i
);
1147 pa_assert_ctl_context();
1148 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1149 pa_return_val_if_fail(i
->thread_info
.resampler
, -PA_ERR_BADSTATE
);
1151 if (i
->sample_spec
.rate
== rate
)
1154 i
->sample_spec
.rate
= rate
;
1156 pa_asyncmsgq_post(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_SET_RATE
, PA_UINT_TO_PTR(rate
), 0, NULL
, NULL
);
1158 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1162 /* Called from main context */
1163 void pa_sink_input_set_name(pa_sink_input
*i
, const char *name
) {
1165 pa_sink_input_assert_ref(i
);
1166 pa_assert_ctl_context();
1168 if (!name
&& !pa_proplist_contains(i
->proplist
, PA_PROP_MEDIA_NAME
))
1171 old
= pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
);
1173 if (old
&& name
&& pa_streq(old
, name
))
1177 pa_proplist_sets(i
->proplist
, PA_PROP_MEDIA_NAME
, name
);
1179 pa_proplist_unset(i
->proplist
, PA_PROP_MEDIA_NAME
);
1181 if (PA_SINK_INPUT_IS_LINKED(i
->state
)) {
1182 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED
], i
);
1183 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1187 /* Called from main context */
1188 pa_resample_method_t
pa_sink_input_get_resample_method(pa_sink_input
*i
) {
1189 pa_sink_input_assert_ref(i
);
1190 pa_assert_ctl_context();
1192 return i
->actual_resample_method
;
1195 /* Called from main context */
1196 pa_bool_t
pa_sink_input_may_move(pa_sink_input
*i
) {
1197 pa_sink_input_assert_ref(i
);
1198 pa_assert_ctl_context();
1199 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1201 if (i
->flags
& PA_SINK_INPUT_DONT_MOVE
)
1204 if (i
->sync_next
|| i
->sync_prev
) {
1205 pa_log_warn("Moving synchronized streams not supported.");
1212 /* Called from main context */
1213 pa_bool_t
pa_sink_input_may_move_to(pa_sink_input
*i
, pa_sink
*dest
) {
1214 pa_sink_input_assert_ref(i
);
1215 pa_assert_ctl_context();
1216 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1217 pa_sink_assert_ref(dest
);
1219 if (dest
== i
->sink
)
1222 if (!pa_sink_input_may_move(i
))
1225 if (pa_idxset_size(dest
->inputs
) >= PA_MAX_INPUTS_PER_SINK
) {
1226 pa_log_warn("Failed to move sink input: too many inputs per sink.");
1230 if (check_passthrough_connection(i
->flags
, dest
) < 0)
1234 if (!i
->may_move_to(i
, dest
))
1240 /* Called from main context */
1241 int pa_sink_input_start_move(pa_sink_input
*i
) {
1242 pa_source_output
*o
, *p
= NULL
;
1245 pa_sink_input_assert_ref(i
);
1246 pa_assert_ctl_context();
1247 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1250 if (!pa_sink_input_may_move(i
))
1251 return -PA_ERR_NOTSUPPORTED
;
1253 if ((r
= pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_MOVE_START
], i
)) < 0)
1256 /* Kill directly connected outputs */
1257 while ((o
= pa_idxset_first(i
->direct_outputs
, NULL
))) {
1259 pa_source_output_kill(o
);
1262 pa_assert(pa_idxset_isempty(i
->direct_outputs
));
1264 pa_idxset_remove_by_data(i
->sink
->inputs
, i
, NULL
);
1266 if (pa_sink_input_get_state(i
) == PA_SINK_INPUT_CORKED
)
1267 pa_assert_se(i
->sink
->n_corked
-- >= 1);
1269 if (i
->sink
->flags
& PA_SINK_FLAT_VOLUME
)
1270 /* We might need to update the sink's volume if we are in flat
1272 pa_sink_set_volume(i
->sink
, NULL
, FALSE
, FALSE
);
1274 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
->sink
), PA_SINK_MESSAGE_START_MOVE
, i
, 0, NULL
) == 0);
1276 pa_sink_update_status(i
->sink
);
1277 pa_cvolume_remap(&i
->volume_factor_sink
, &i
->sink
->channel_map
, &i
->channel_map
);
1280 pa_sink_input_unref(i
);
1285 /* Called from main context */
1286 int pa_sink_input_finish_move(pa_sink_input
*i
, pa_sink
*dest
, pa_bool_t save
) {
1287 pa_resampler
*new_resampler
;
1289 pa_sink_input_assert_ref(i
);
1290 pa_assert_ctl_context();
1291 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1292 pa_assert(!i
->sink
);
1293 pa_sink_assert_ref(dest
);
1295 if (!pa_sink_input_may_move_to(i
, dest
))
1296 return -PA_ERR_NOTSUPPORTED
;
1298 if (i
->thread_info
.resampler
&&
1299 pa_sample_spec_equal(pa_resampler_output_sample_spec(i
->thread_info
.resampler
), &dest
->sample_spec
) &&
1300 pa_channel_map_equal(pa_resampler_output_channel_map(i
->thread_info
.resampler
), &dest
->channel_map
))
1302 /* Try to reuse the old resampler if possible */
1303 new_resampler
= i
->thread_info
.resampler
;
1305 else if ((i
->flags
& PA_SINK_INPUT_VARIABLE_RATE
) ||
1306 !pa_sample_spec_equal(&i
->sample_spec
, &dest
->sample_spec
) ||
1307 !pa_channel_map_equal(&i
->channel_map
, &dest
->channel_map
)) {
1309 /* Okey, we need a new resampler for the new sink */
1311 if (!(new_resampler
= pa_resampler_new(
1313 &i
->sample_spec
, &i
->channel_map
,
1314 &dest
->sample_spec
, &dest
->channel_map
,
1315 i
->requested_resample_method
,
1316 ((i
->flags
& PA_SINK_INPUT_VARIABLE_RATE
) ? PA_RESAMPLER_VARIABLE_RATE
: 0) |
1317 ((i
->flags
& PA_SINK_INPUT_NO_REMAP
) ? PA_RESAMPLER_NO_REMAP
: 0) |
1318 (i
->core
->disable_remixing
|| (i
->flags
& PA_SINK_INPUT_NO_REMIX
) ? PA_RESAMPLER_NO_REMIX
: 0)))) {
1319 pa_log_warn("Unsupported resampling operation.");
1320 return -PA_ERR_NOTSUPPORTED
;
1323 new_resampler
= NULL
;
1329 i
->save_sink
= save
;
1330 pa_idxset_put(dest
->inputs
, pa_sink_input_ref(i
), NULL
);
1332 pa_cvolume_remap(&i
->volume_factor_sink
, &i
->channel_map
, &i
->sink
->channel_map
);
1334 if (pa_sink_input_get_state(i
) == PA_SINK_INPUT_CORKED
)
1335 i
->sink
->n_corked
++;
1337 /* Replace resampler and render queue */
1338 if (new_resampler
!= i
->thread_info
.resampler
) {
1340 if (i
->thread_info
.resampler
)
1341 pa_resampler_free(i
->thread_info
.resampler
);
1342 i
->thread_info
.resampler
= new_resampler
;
1344 pa_memblockq_free(i
->thread_info
.render_memblockq
);
1346 i
->thread_info
.render_memblockq
= pa_memblockq_new(
1348 MEMBLOCKQ_MAXLENGTH
,
1350 pa_frame_size(&i
->sink
->sample_spec
),
1356 pa_sink_update_status(dest
);
1358 if (i
->sink
->flags
& PA_SINK_FLAT_VOLUME
) {
1359 pa_cvolume remapped
;
1361 /* Make relative volumes absolute */
1362 remapped
= dest
->reference_volume
;
1363 pa_cvolume_remap(&remapped
, &dest
->channel_map
, &i
->channel_map
);
1364 pa_sw_cvolume_multiply(&i
->volume
, &i
->reference_ratio
, &remapped
);
1366 /* We might need to update the sink's volume if we are in flat volume mode. */
1367 pa_sink_set_volume(i
->sink
, NULL
, FALSE
, i
->save_volume
);
1370 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
->sink
), PA_SINK_MESSAGE_FINISH_MOVE
, i
, 0, NULL
) == 0);
1372 pa_log_debug("Successfully moved sink input %i to %s.", i
->index
, dest
->name
);
1374 /* Notify everyone */
1375 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH
], i
);
1377 if (i
->volume_changed
)
1378 i
->volume_changed(i
);
1380 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1385 /* Called from main context */
1386 void pa_sink_input_fail_move(pa_sink_input
*i
) {
1388 pa_sink_input_assert_ref(i
);
1389 pa_assert_ctl_context();
1390 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1391 pa_assert(!i
->sink
);
1393 /* Check if someone wants this sink input? */
1394 if (pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL
], i
) == PA_HOOK_STOP
)
1400 pa_sink_input_kill(i
);
1403 /* Called from main context */
1404 int pa_sink_input_move_to(pa_sink_input
*i
, pa_sink
*dest
, pa_bool_t save
) {
1407 pa_sink_input_assert_ref(i
);
1408 pa_assert_ctl_context();
1409 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1411 pa_sink_assert_ref(dest
);
1413 if (dest
== i
->sink
)
1416 if (!pa_sink_input_may_move_to(i
, dest
))
1417 return -PA_ERR_NOTSUPPORTED
;
1419 pa_sink_input_ref(i
);
1421 if ((r
= pa_sink_input_start_move(i
)) < 0) {
1422 pa_sink_input_unref(i
);
1426 if ((r
= pa_sink_input_finish_move(i
, dest
, save
)) < 0) {
1427 pa_sink_input_fail_move(i
);
1428 pa_sink_input_unref(i
);
1432 pa_sink_input_unref(i
);
1437 /* Called from IO thread context */
1438 void pa_sink_input_set_state_within_thread(pa_sink_input
*i
, pa_sink_input_state_t state
) {
1439 pa_bool_t corking
, uncorking
;
1441 pa_sink_input_assert_ref(i
);
1442 pa_sink_input_assert_io_context(i
);
1444 if (state
== i
->thread_info
.state
)
1447 if ((state
== PA_SINK_INPUT_DRAINED
|| state
== PA_SINK_INPUT_RUNNING
) &&
1448 !(i
->thread_info
.state
== PA_SINK_INPUT_DRAINED
|| i
->thread_info
.state
!= PA_SINK_INPUT_RUNNING
))
1449 pa_atomic_store(&i
->thread_info
.drained
, 1);
1451 corking
= state
== PA_SINK_INPUT_CORKED
&& i
->thread_info
.state
== PA_SINK_INPUT_RUNNING
;
1452 uncorking
= i
->thread_info
.state
== PA_SINK_INPUT_CORKED
&& state
== PA_SINK_INPUT_RUNNING
;
1454 if (i
->state_change
)
1455 i
->state_change(i
, state
);
1457 i
->thread_info
.state
= state
;
1461 pa_log_debug("Requesting rewind due to corking");
1463 /* This will tell the implementing sink input driver to rewind
1464 * so that the unplayed already mixed data is not lost */
1465 pa_sink_input_request_rewind(i
, 0, TRUE
, TRUE
, FALSE
);
1467 } else if (uncorking
) {
1469 i
->thread_info
.underrun_for
= (uint64_t) -1;
1470 i
->thread_info
.playing_for
= 0;
1472 pa_log_debug("Requesting rewind due to uncorking");
1474 /* OK, we're being uncorked. Make sure we're not rewound when
1475 * the hw buffer is remixed and request a remix. */
1476 pa_sink_input_request_rewind(i
, 0, FALSE
, TRUE
, TRUE
);
1480 /* Called from thread context, except when it is not. */
1481 int pa_sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1482 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1483 pa_sink_input_assert_ref(i
);
1487 case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME
:
1488 if (pa_atomic_load(&i
->before_ramping_v
))
1489 i
->thread_info
.future_soft_volume
= i
->soft_volume
;
1491 if (!pa_cvolume_equal(&i
->thread_info
.soft_volume
, &i
->soft_volume
)) {
1492 if (!pa_atomic_load(&i
->before_ramping_v
))
1493 i
->thread_info
.soft_volume
= i
->soft_volume
;
1494 pa_sink_input_request_rewind(i
, 0, TRUE
, FALSE
, FALSE
);
1498 case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE
:
1499 if (pa_atomic_load(&i
->before_ramping_m
))
1500 i
->thread_info
.future_muted
= i
->muted
;
1502 if (i
->thread_info
.muted
!= i
->muted
) {
1503 if (!pa_atomic_load(&i
->before_ramping_m
))
1504 i
->thread_info
.muted
= i
->muted
;
1505 pa_sink_input_request_rewind(i
, 0, TRUE
, FALSE
, FALSE
);
1509 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1510 pa_usec_t
*r
= userdata
;
1512 r
[0] += pa_bytes_to_usec(pa_memblockq_get_length(i
->thread_info
.render_memblockq
), &i
->sink
->sample_spec
);
1513 r
[1] += pa_sink_get_latency_within_thread(i
->sink
);
1518 case PA_SINK_INPUT_MESSAGE_SET_RATE
:
1520 i
->thread_info
.sample_spec
.rate
= PA_PTR_TO_UINT(userdata
);
1521 pa_resampler_set_input_rate(i
->thread_info
.resampler
, PA_PTR_TO_UINT(userdata
));
1525 case PA_SINK_INPUT_MESSAGE_SET_STATE
: {
1526 pa_sink_input
*ssync
;
1528 pa_sink_input_set_state_within_thread(i
, PA_PTR_TO_UINT(userdata
));
1530 for (ssync
= i
->thread_info
.sync_prev
; ssync
; ssync
= ssync
->thread_info
.sync_prev
)
1531 pa_sink_input_set_state_within_thread(ssync
, PA_PTR_TO_UINT(userdata
));
1533 for (ssync
= i
->thread_info
.sync_next
; ssync
; ssync
= ssync
->thread_info
.sync_next
)
1534 pa_sink_input_set_state_within_thread(ssync
, PA_PTR_TO_UINT(userdata
));
1539 case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY
: {
1540 pa_usec_t
*usec
= userdata
;
1542 *usec
= pa_sink_input_set_requested_latency_within_thread(i
, *usec
);
1546 case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY
: {
1547 pa_usec_t
*r
= userdata
;
1549 *r
= i
->thread_info
.requested_sink_latency
;
1553 case PA_SINK_INPUT_MESSAGE_SET_ENVELOPE
: {
1554 if (!i
->thread_info
.ramp_info
.envelope
)
1555 i
->thread_info
.ramp_info
.envelope
= pa_envelope_new(&i
->sink
->sample_spec
);
1557 if (i
->thread_info
.ramp_info
.envelope
&& i
->thread_info
.ramp_info
.item
) {
1558 pa_envelope_remove(i
->thread_info
.ramp_info
.envelope
, i
->thread_info
.ramp_info
.item
);
1559 i
->thread_info
.ramp_info
.item
= NULL
;
1562 i
->thread_info
.ramp_info
.item
= pa_envelope_add(i
->thread_info
.ramp_info
.envelope
, &i
->using_def
);
1563 i
->thread_info
.ramp_info
.is_ramping
= TRUE
;
1564 i
->thread_info
.ramp_info
.envelope_dead
= FALSE
;
1565 i
->thread_info
.ramp_info
.envelope_dying
= 0;
1567 if (i
->thread_info
.ramp_info
.envelope
)
1568 pa_envelope_restart(i
->thread_info
.ramp_info
.envelope
);
1574 return -PA_ERR_NOTIMPLEMENTED
;
1577 /* Called from main thread */
1578 pa_sink_input_state_t
pa_sink_input_get_state(pa_sink_input
*i
) {
1579 pa_sink_input_assert_ref(i
);
1580 pa_assert_ctl_context();
1582 if (i
->state
== PA_SINK_INPUT_RUNNING
|| i
->state
== PA_SINK_INPUT_DRAINED
)
1583 return pa_atomic_load(&i
->thread_info
.drained
) ? PA_SINK_INPUT_DRAINED
: PA_SINK_INPUT_RUNNING
;
1588 /* Called from IO context */
1589 pa_bool_t
pa_sink_input_safe_to_remove(pa_sink_input
*i
) {
1590 pa_sink_input_assert_ref(i
);
1591 pa_sink_input_assert_io_context(i
);
1593 if (PA_SINK_INPUT_IS_LINKED(i
->thread_info
.state
))
1594 return pa_memblockq_is_empty(i
->thread_info
.render_memblockq
);
1599 /* Called from IO context */
1600 void pa_sink_input_request_rewind(
1602 size_t nbytes
/* in our sample spec */,
1605 pa_bool_t dont_rewind_render
) {
1609 /* If 'rewrite' is TRUE the sink is rewound as far as requested
1610 * and possible and the exact value of this is passed back the
1611 * implementor via process_rewind(). If 'flush' is also TRUE all
1612 * already rendered data is also dropped.
1614 * If 'rewrite' is FALSE the sink is rewound as far as requested
1615 * and possible and the already rendered data is dropped so that
1616 * in the next iteration we read new data from the
1617 * implementor. This implies 'flush' is TRUE. If
1618 * dont_rewind_render is TRUE then the render memblockq is not
1621 /* nbytes = 0 means maximum rewind request */
1623 pa_sink_input_assert_ref(i
);
1624 pa_sink_input_assert_io_context(i
);
1625 pa_assert(rewrite
|| flush
);
1626 pa_assert(!dont_rewind_render
|| !rewrite
);
1628 /* We don't take rewind requests while we are corked */
1629 if (i
->thread_info
.state
== PA_SINK_INPUT_CORKED
)
1632 nbytes
= PA_MAX(i
->thread_info
.rewrite_nbytes
, nbytes
);
1634 /* pa_log_debug("request rewrite %zu", nbytes); */
1636 /* Calculate how much we can rewind locally without having to
1639 lbq
= pa_memblockq_get_length(i
->thread_info
.render_memblockq
);
1643 /* Check if rewinding for the maximum is requested, and if so, fix up */
1646 /* Calculate maximum number of bytes that could be rewound in theory */
1647 nbytes
= i
->sink
->thread_info
.max_rewind
+ lbq
;
1649 /* Transform from sink domain */
1650 if (i
->thread_info
.resampler
)
1651 nbytes
= pa_resampler_request(i
->thread_info
.resampler
, nbytes
);
1654 /* Remember how much we actually want to rewrite */
1655 if (i
->thread_info
.rewrite_nbytes
!= (size_t) -1) {
1657 /* Make sure to not overwrite over underruns */
1658 if (nbytes
> i
->thread_info
.playing_for
)
1659 nbytes
= (size_t) i
->thread_info
.playing_for
;
1661 i
->thread_info
.rewrite_nbytes
= nbytes
;
1663 i
->thread_info
.rewrite_nbytes
= (size_t) -1;
1666 i
->thread_info
.rewrite_flush
=
1667 i
->thread_info
.rewrite_flush
||
1668 (flush
&& i
->thread_info
.rewrite_nbytes
!= 0);
1670 i
->thread_info
.dont_rewind_render
=
1671 i
->thread_info
.dont_rewind_render
||
1674 if (nbytes
!= (size_t) -1) {
1676 /* Transform to sink domain */
1677 if (i
->thread_info
.resampler
)
1678 nbytes
= pa_resampler_result(i
->thread_info
.resampler
, nbytes
);
1681 pa_sink_request_rewind(i
->sink
, nbytes
- lbq
);
1683 /* This call will make sure process_rewind() is called later */
1684 pa_sink_request_rewind(i
->sink
, 0);
1688 /* Called from main context */
1689 pa_memchunk
* pa_sink_input_get_silence(pa_sink_input
*i
, pa_memchunk
*ret
) {
1690 pa_sink_input_assert_ref(i
);
1691 pa_assert_ctl_context();
1694 /* FIXME: Shouldn't access resampler object from main context! */
1696 pa_silence_memchunk_get(
1697 &i
->core
->silence_cache
,
1701 i
->thread_info
.resampler
? pa_resampler_max_block_size(i
->thread_info
.resampler
) : 0);
1706 /* Called from main context */
1707 void pa_sink_input_send_event(pa_sink_input
*i
, const char *event
, pa_proplist
*data
) {
1708 pa_proplist
*pl
= NULL
;
1709 pa_sink_input_send_event_hook_data hook_data
;
1711 pa_sink_input_assert_ref(i
);
1712 pa_assert_ctl_context();
1719 data
= pl
= pa_proplist_new();
1721 hook_data
.sink_input
= i
;
1722 hook_data
.data
= data
;
1723 hook_data
.event
= event
;
1725 if (pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT
], &hook_data
) < 0)
1728 i
->send_event(i
, event
, data
);
1732 pa_proplist_free(pl
);
1735 /* Called from IO context */
1736 static void sink_input_volume_ramping(pa_sink_input
* i
, pa_memchunk
* chunk
) {
1739 pa_assert(chunk
->memblock
);
1740 pa_assert(i
->thread_info
.ramp_info
.is_ramping
);
1742 /* Volume is adjusted with ramping effect here */
1743 pa_envelope_apply(i
->thread_info
.ramp_info
.envelope
, chunk
);
1745 if (pa_envelope_is_finished(i
->thread_info
.ramp_info
.envelope
)) {
1746 i
->thread_info
.ramp_info
.is_ramping
= FALSE
;
1747 if (pa_atomic_load(&i
->before_ramping_v
)) {
1748 i
->thread_info
.soft_volume
= i
->thread_info
.future_soft_volume
;
1749 pa_atomic_store(&i
->before_ramping_v
, 0);
1751 else if (pa_atomic_load(&i
->before_ramping_m
)) {
1752 i
->thread_info
.muted
= i
->thread_info
.future_muted
;
1753 pa_atomic_store(&i
->before_ramping_m
, 0);
1759 * Called from main context
1760 * This function should be called inside pa_sink_input_set_volume_with_ramping
1761 * should be called after soft_volume of sink_input and sink are all adjusted
1763 static void sink_input_set_ramping_info(pa_sink_input
* i
, pa_volume_t pre_virtual_volume
, pa_volume_t target_virtual_volume
, pa_usec_t t
) {
1765 int32_t target_abs_vol
, target_apply_vol
, pre_apply_vol
;
1768 pa_log_debug("Sink input's soft volume is %d= %f ", pa_cvolume_avg(&i
->soft_volume
), pa_sw_volume_to_linear(pa_cvolume_avg(&i
->soft_volume
)));
1770 /* Calculation formula are target_abs_vol := i->soft_volume
1771 * target_apply_vol := lrint(pa_sw_volume_to_linear(target_abs_vol) * 0x10000)
1772 * pre_apply_vol := ( previous_virtual_volume / target_virtual_volume ) * target_apply_vol
1774 * Will do volume adjustment inside pa_sink_input_peek
1776 target_abs_vol
= pa_cvolume_avg(&i
->soft_volume
);
1777 target_apply_vol
= (int32_t) lrint(pa_sw_volume_to_linear(target_abs_vol
) * 0x10000);
1778 pre_apply_vol
= (int32_t) ((pa_sw_volume_to_linear(pre_virtual_volume
) / pa_sw_volume_to_linear(target_virtual_volume
)) * target_apply_vol
);
1780 i
->using_def
.n_points
= 2;
1781 i
->using_def
.points_x
[0] = 0;
1782 i
->using_def
.points_x
[1] = t
;
1783 i
->using_def
.points_y
.i
[0] = pre_apply_vol
;
1784 i
->using_def
.points_y
.i
[1] = target_apply_vol
;
1785 i
->using_def
.points_y
.f
[0] = ((float) i
->using_def
.points_y
.i
[0]) /0x10000;
1786 i
->using_def
.points_y
.f
[1] = ((float) i
->using_def
.points_y
.i
[1]) /0x10000;
1788 pa_log_debug("Volume Ramping: Point 1 is %d=%f, Point 2 is %d=%f\n", i
->using_def
.points_y
.i
[0], i
->using_def
.points_y
.f
[0],
1789 i
->using_def
.points_y
.i
[1], i
->using_def
.points_y
.f
[1]);
1791 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_SET_ENVELOPE
, NULL
, 0, NULL
) == 0);
1794 /* Called from main context */
1795 static void sink_input_set_ramping_info_for_mute(pa_sink_input
* i
, pa_bool_t mute
, pa_usec_t t
) {
1800 i
->using_def
.n_points
= 2;
1801 i
->using_def
.points_x
[0] = 0;
1802 i
->using_def
.points_x
[1] = t
;
1803 cur_vol
= (int32_t) lrint( pa_sw_volume_to_linear(pa_cvolume_avg(&i
->soft_volume
)) * 0x10000);
1806 i
->using_def
.points_y
.i
[0] = cur_vol
;
1807 i
->using_def
.points_y
.i
[1] = 0;
1809 i
->using_def
.points_y
.i
[0] = 0;
1810 i
->using_def
.points_y
.i
[1] = cur_vol
;
1813 i
->using_def
.points_y
.f
[0] = ((float) i
->using_def
.points_y
.i
[0]) /0x10000;
1814 i
->using_def
.points_y
.f
[1] = ((float) i
->using_def
.points_y
.i
[1]) /0x10000;
1816 pa_log_debug("Mute Ramping: Point 1 is %d=%f, Point 2 is %d=%f\n", i
->using_def
.points_y
.i
[0], i
->using_def
.points_y
.f
[0],
1817 i
->using_def
.points_y
.i
[1], i
->using_def
.points_y
.f
[1]);
1819 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_SET_ENVELOPE
, NULL
, 0, NULL
) == 0);
1822 /* Called from IO context */
1823 static void sink_input_release_envelope(pa_sink_input
*i
) {
1825 pa_assert(!i
->thread_info
.ramp_info
.is_ramping
);
1826 pa_assert(i
->thread_info
.ramp_info
.envelope_dead
);
1828 pa_envelope_free(i
->thread_info
.ramp_info
.envelope
);
1829 i
->thread_info
.ramp_info
.envelope
= NULL
;
1830 i
->thread_info
.ramp_info
.item
= NULL
;
1833 /* Called from IO context */
1834 static void sink_input_rewind_ramp_info(pa_sink_input
*i
, size_t nbytes
) {
1837 if (!i
->thread_info
.ramp_info
.envelope_dead
) {
1838 int32_t envelope_length
;
1840 pa_assert(i
->thread_info
.ramp_info
.envelope
);
1842 envelope_length
= pa_envelope_length(i
->thread_info
.ramp_info
.envelope
);
1844 if (i
->thread_info
.ramp_info
.envelope_dying
> envelope_length
) {
1845 if ((int32_t) (i
->thread_info
.ramp_info
.envelope_dying
- nbytes
) < envelope_length
) {
1846 pa_log_debug("Envelope Become Alive");
1847 pa_envelope_rewind(i
->thread_info
.ramp_info
.envelope
, envelope_length
- (i
->thread_info
.ramp_info
.envelope_dying
- nbytes
));
1848 i
->thread_info
.ramp_info
.is_ramping
= TRUE
;
1850 } else if (i
->thread_info
.ramp_info
.envelope_dying
< envelope_length
) {
1851 if ((i
->thread_info
.ramp_info
.envelope_dying
- (ssize_t
) nbytes
) <= 0) {
1852 pa_log_debug("Envelope Restart");
1853 pa_envelope_restart(i
->thread_info
.ramp_info
.envelope
);
1856 pa_log_debug("Envelope Simple Rewind");
1857 pa_envelope_rewind(i
->thread_info
.ramp_info
.envelope
, nbytes
);
1861 i
->thread_info
.ramp_info
.envelope_dying
-= nbytes
;
1862 if (i
->thread_info
.ramp_info
.envelope_dying
<= 0)
1863 i
->thread_info
.ramp_info
.envelope_dying
= 0;
1867 void pa_sink_input_set_volume_with_ramping(pa_sink_input
*i
, const pa_cvolume
*volume
, pa_bool_t save
, pa_bool_t absolute
, pa_usec_t t
){
1869 pa_volume_t previous_virtual_volume
, target_virtual_volume
;
1871 pa_sink_input_assert_ref(i
);
1872 pa_assert_ctl_context();
1873 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1875 pa_assert(pa_cvolume_valid(volume
));
1876 pa_assert(volume
->channels
== 1 || pa_cvolume_compatible(volume
, &i
->sample_spec
));
1877 pa_assert(pa_sink_input_is_volume_writable(i
));
1879 if ((i
->sink
->flags
& PA_SINK_FLAT_VOLUME
) && !absolute
) {
1880 v
= i
->sink
->reference_volume
;
1881 pa_cvolume_remap(&v
, &i
->sink
->channel_map
, &i
->channel_map
);
1883 if (pa_cvolume_compatible(volume
, &i
->sample_spec
))
1884 volume
= pa_sw_cvolume_multiply(&v
, &v
, volume
);
1886 volume
= pa_sw_cvolume_multiply_scalar(&v
, &v
, pa_cvolume_max(volume
));
1889 if (!pa_cvolume_compatible(volume
, &i
->sample_spec
)) {
1891 volume
= pa_cvolume_scale(&v
, pa_cvolume_max(volume
));
1895 if (pa_cvolume_equal(volume
, &i
->volume
)) {
1896 i
->save_volume
= i
->save_volume
|| save
;
1900 previous_virtual_volume
= pa_cvolume_avg(&i
->volume
);
1901 target_virtual_volume
= pa_cvolume_avg(volume
);
1903 if (t
> 0 && target_virtual_volume
> 0)
1904 pa_log_debug("SetVolumeWithRamping: Virtual Volume From %u=%f to %u=%f\n", previous_virtual_volume
, pa_sw_volume_to_linear(previous_virtual_volume
),
1905 target_virtual_volume
, pa_sw_volume_to_linear(target_virtual_volume
));
1907 i
->volume
= *volume
;
1908 i
->save_volume
= save
;
1910 /* Set this flag before the following code modify i->thread_info.soft_volume */
1911 if (t
> 0 && target_virtual_volume
> 0)
1912 pa_atomic_store(&i
->before_ramping_v
, 1);
1914 if (i
->sink
->flags
& PA_SINK_FLAT_VOLUME
) {
1915 /* We are in flat volume mode, so let's update all sink input
1916 * volumes and update the flat volume of the sink */
1918 pa_sink_set_volume(i
->sink
, NULL
, TRUE
, save
);
1921 /* OK, we are in normal volume mode. The volume only affects
1923 set_real_ratio(i
, volume
);
1925 /* Copy the new soft_volume to the thread_info struct */
1926 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME
, NULL
, 0, NULL
) == 0);
1929 if (t
> 0 && target_virtual_volume
> 0)
1930 sink_input_set_ramping_info(i
, previous_virtual_volume
, target_virtual_volume
, t
);
1932 /* The volume changed, let's tell people so */
1933 if (i
->volume_changed
)
1934 i
->volume_changed(i
);
1936 /* The virtual volume changed, let's tell people so */
1937 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1940 void pa_sink_input_set_mute_with_ramping(pa_sink_input
*i
, pa_bool_t mute
, pa_bool_t save
, pa_usec_t t
){
1942 pa_sink_input_assert_ref(i
);
1943 pa_assert_ctl_context();
1944 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1946 if (!i
->muted
== !mute
) {
1947 i
->save_muted
= i
->save_muted
|| mute
;
1952 i
->save_muted
= save
;
1954 /* Set this flag before the following code modify i->thread_info.muted, otherwise distortion will be heard */
1956 pa_atomic_store(&i
->before_ramping_m
, 1);
1958 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE
, NULL
, 0, NULL
) == 0);
1961 sink_input_set_ramping_info_for_mute(i
, mute
, t
);
1963 /* The mute status changed, let's tell people so */
1964 if (i
->mute_changed
)
1967 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);