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 if (data->flags & PA_SINK_INPUT_PASSTHROUGH)
121 if (data->origin_sink && (data->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
127 void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) {
129 pa_assert(pa_sink_input_new_data_is_volume_writable(data));
131 if ((data->volume_is_set = !!volume))
132 data->volume = *volume;
135 void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
137 pa_assert(volume_factor);
139 if (data->volume_factor_is_set)
140 pa_sw_cvolume_multiply(&data->volume_factor, &data->volume_factor, volume_factor);
142 data->volume_factor_is_set = TRUE;
143 data->volume_factor = *volume_factor;
147 void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
149 pa_assert(volume_factor);
151 if (data->volume_factor_sink_is_set)
152 pa_sw_cvolume_multiply(&data->volume_factor_sink, &data->volume_factor_sink, volume_factor);
154 data->volume_factor_sink_is_set = TRUE;
155 data->volume_factor_sink = *volume_factor;
159 void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
162 data->muted_is_set = TRUE;
163 data->muted = !!mute;
166 void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
169 pa_proplist_free(data->proplist);
172 /* Called from main context */
173 static void reset_callbacks(pa_sink_input *i) {
177 i->process_rewind = NULL;
178 i->update_max_rewind = NULL;
179 i->update_max_request = NULL;
180 i->update_sink_requested_latency = NULL;
181 i->update_sink_latency_range = NULL;
182 i->update_sink_fixed_latency = NULL;
186 i->suspend_within_thread = NULL;
189 i->get_latency = NULL;
190 i->state_change = NULL;
191 i->may_move_to = NULL;
192 i->send_event = NULL;
193 i->volume_changed = NULL;
194 i->mute_changed = NULL;
197 /* Called from main context */
198 int pa_sink_input_new(
201 pa_sink_input_new_data *data) {
204 pa_resampler *resampler = NULL;
205 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
206 pa_channel_map original_cm;
213 pa_assert_ctl_context();
216 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
218 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0)
221 pa_assert(!data->volume_is_set || pa_sink_input_new_data_is_volume_writable(data));
222 pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
225 data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK);
226 data->save_sink = FALSE;
229 pa_return_val_if_fail(data->sink, -PA_ERR_NOENTITY);
230 pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)), -PA_ERR_BADSTATE);
231 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);
233 r = check_passthrough_connection(data->flags, data->sink);
234 pa_return_val_if_fail(r == PA_OK, r);
236 if (!data->sample_spec_is_set)
237 data->sample_spec = data->sink->sample_spec;
239 pa_return_val_if_fail(pa_sample_spec_valid(&data->sample_spec), -PA_ERR_INVALID);
241 if (!data->channel_map_is_set) {
242 if (pa_channel_map_compatible(&data->sink->channel_map, &data->sample_spec))
243 data->channel_map = data->sink->channel_map;
245 pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
248 pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
250 if (!data->volume_is_set) {
251 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
252 data->volume_is_absolute = FALSE;
253 data->save_volume = FALSE;
256 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec), -PA_ERR_INVALID);
258 if (!data->volume_factor_is_set)
259 pa_cvolume_reset(&data->volume_factor, data->sample_spec.channels);
261 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor, &data->sample_spec), -PA_ERR_INVALID);
263 if (!data->volume_factor_sink_is_set)
264 pa_cvolume_reset(&data->volume_factor_sink, data->sink->sample_spec.channels);
266 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor_sink, &data->sink->sample_spec), -PA_ERR_INVALID);
268 if (!data->muted_is_set)
271 if (data->flags & PA_SINK_INPUT_FIX_FORMAT)
272 data->sample_spec.format = data->sink->sample_spec.format;
274 if (data->flags & PA_SINK_INPUT_FIX_RATE)
275 data->sample_spec.rate = data->sink->sample_spec.rate;
277 original_cm = data->channel_map;
279 if (data->flags & PA_SINK_INPUT_FIX_CHANNELS) {
280 data->sample_spec.channels = data->sink->sample_spec.channels;
281 data->channel_map = data->sink->channel_map;
284 pa_assert(pa_sample_spec_valid(&data->sample_spec));
285 pa_assert(pa_channel_map_valid(&data->channel_map));
287 /* Due to the fixing of the sample spec the volume might not match anymore */
288 pa_cvolume_remap(&data->volume, &original_cm, &data->channel_map);
290 if (data->resample_method == PA_RESAMPLER_INVALID)
291 data->resample_method = core->resample_method;
293 pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
295 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
298 if ((data->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND) &&
299 pa_sink_get_state(data->sink) == PA_SINK_SUSPENDED) {
300 pa_log_warn("Failed to create sink input: sink is suspended.");
301 return -PA_ERR_BADSTATE;
304 if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) {
305 pa_log_warn("Failed to create sink input: too many inputs per sink.");
306 return -PA_ERR_TOOLARGE;
309 if ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
310 !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) ||
311 !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) {
313 if (!(resampler = pa_resampler_new(
315 &data->sample_spec, &data->channel_map,
316 &data->sink->sample_spec, &data->sink->channel_map,
317 data->resample_method,
318 ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
319 ((data->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
320 (core->disable_remixing || (data->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
321 (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
322 pa_log_warn("Unsupported resampling operation.");
323 return -PA_ERR_NOTSUPPORTED;
327 i = pa_msgobject_new(pa_sink_input);
328 i->parent.parent.free = sink_input_free;
329 i->parent.process_msg = pa_sink_input_process_msg;
332 i->state = PA_SINK_INPUT_INIT;
333 i->flags = data->flags;
334 i->proplist = pa_proplist_copy(data->proplist);
335 i->driver = pa_xstrdup(pa_path_get_filename(data->driver));
336 i->module = data->module;
337 i->sink = data->sink;
338 i->origin_sink = data->origin_sink;
339 i->client = data->client;
341 i->requested_resample_method = data->resample_method;
342 i->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID;
343 i->sample_spec = data->sample_spec;
344 i->channel_map = data->channel_map;
346 if (!data->volume_is_absolute && pa_sink_flat_volume_enabled(i->sink)) {
349 /* When the 'absolute' bool is not set then we'll treat the volume
350 * as relative to the sink volume even in flat volume mode */
351 remapped = data->sink->reference_volume;
352 pa_cvolume_remap(&remapped, &data->sink->channel_map, &data->channel_map);
353 pa_sw_cvolume_multiply(&i->volume, &data->volume, &remapped);
355 i->volume = data->volume;
357 i->volume_factor = data->volume_factor;
358 i->volume_factor_sink = data->volume_factor_sink;
359 i->real_ratio = i->reference_ratio = data->volume;
360 pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
361 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
362 i->save_volume = data->save_volume;
363 i->save_sink = data->save_sink;
364 i->save_muted = data->save_muted;
366 i->muted = data->muted;
368 if (data->sync_base) {
369 i->sync_next = data->sync_base->sync_next;
370 i->sync_prev = data->sync_base;
372 if (data->sync_base->sync_next)
373 data->sync_base->sync_next->sync_prev = i;
374 data->sync_base->sync_next = i;
376 i->sync_next = i->sync_prev = NULL;
378 i->direct_outputs = pa_idxset_new(NULL, NULL);
383 /* Set Ramping info */
384 i->thread_info.ramp_info.is_ramping = FALSE;
385 i->thread_info.ramp_info.envelope_dead = TRUE;
386 i->thread_info.ramp_info.envelope = NULL;
387 i->thread_info.ramp_info.item = NULL;
388 i->thread_info.ramp_info.envelope_dying = 0;
390 pa_atomic_store(&i->before_ramping_v, 0);
391 pa_atomic_store(&i->before_ramping_m, 0);
393 i->thread_info.state = i->state;
394 i->thread_info.attached = FALSE;
395 pa_atomic_store(&i->thread_info.drained, 1);
396 i->thread_info.sample_spec = i->sample_spec;
397 i->thread_info.resampler = resampler;
398 i->thread_info.soft_volume = i->soft_volume;
399 i->thread_info.muted = i->muted;
400 i->thread_info.requested_sink_latency = (pa_usec_t) -1;
401 i->thread_info.rewrite_nbytes = 0;
402 i->thread_info.rewrite_flush = FALSE;
403 i->thread_info.dont_rewind_render = FALSE;
404 i->thread_info.underrun_for = (uint64_t) -1;
405 i->thread_info.playing_for = 0;
406 i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
408 i->thread_info.render_memblockq = pa_memblockq_new(
412 pa_frame_size(&i->sink->sample_spec),
418 pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
419 pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0);
422 pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
424 pt = pa_proplist_to_string_sep(i->proplist, "\n ");
425 pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
427 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
429 pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
430 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
434 /* Don't forget to call pa_sink_input_put! */
440 /* Called from main context */
441 static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
443 pa_assert_ctl_context();
448 if (i->state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED)
449 pa_assert_se(i->sink->n_corked -- >= 1);
450 else if (i->state != PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_CORKED)
454 /* Called from main context */
455 static void sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
456 pa_sink_input *ssync;
458 pa_assert_ctl_context();
460 if (state == PA_SINK_INPUT_DRAINED)
461 state = PA_SINK_INPUT_RUNNING;
463 if (i->state == state)
466 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);
468 update_n_corked(i, state);
471 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev) {
472 update_n_corked(ssync, state);
473 ssync->state = state;
475 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) {
476 update_n_corked(ssync, state);
477 ssync->state = state;
480 if (state != PA_SINK_INPUT_UNLINKED) {
481 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
483 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev)
484 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
486 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next)
487 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
489 if (PA_SINK_INPUT_IS_LINKED(state))
490 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
493 pa_sink_update_status(i->sink);
496 /* Called from main context */
497 void pa_sink_input_unlink(pa_sink_input *i) {
499 pa_source_output *o, *p = NULL;
502 pa_assert_ctl_context();
504 /* See pa_sink_unlink() for a couple of comments how this function
507 pa_sink_input_ref(i);
509 linked = PA_SINK_INPUT_IS_LINKED(i->state);
512 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
515 i->sync_prev->sync_next = i->sync_next;
517 i->sync_next->sync_prev = i->sync_prev;
519 i->sync_prev = i->sync_next = NULL;
521 pa_idxset_remove_by_data(i->core->sink_inputs, i, NULL);
524 if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
525 pa_sink_input_unref(i);
528 pa_idxset_remove_by_data(i->client->sink_inputs, i, NULL);
530 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
532 pa_source_output_kill(o);
536 update_n_corked(i, PA_SINK_INPUT_UNLINKED);
537 i->state = PA_SINK_INPUT_UNLINKED;
539 if (linked && i->sink) {
540 /* We might need to update the sink's volume if we are in flat volume mode. */
541 if (pa_sink_flat_volume_enabled(i->sink))
542 pa_sink_set_volume(i->sink, NULL, FALSE, FALSE);
544 if (i->sink->asyncmsgq)
545 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL) == 0);
551 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
552 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
556 pa_sink_update_status(i->sink);
560 pa_core_maybe_vacuum(i->core);
562 pa_sink_input_unref(i);
565 /* Called from main context */
566 static void sink_input_free(pa_object *o) {
567 pa_sink_input* i = PA_SINK_INPUT(o);
570 pa_assert_ctl_context();
571 pa_assert(pa_sink_input_refcnt(i) == 0);
573 if (PA_SINK_INPUT_IS_LINKED(i->state))
574 pa_sink_input_unlink(i);
576 pa_log_info("Freeing input %u \"%s\"", i->index, pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)));
578 /* Side note: this function must be able to destruct properly any
579 * kind of sink input in any state, even those which are
580 * "half-moved" or are connected to sinks that have no asyncmsgq
581 * and are hence half-destructed themselves! */
583 if (i->thread_info.ramp_info.envelope) {
584 pa_log_debug ("Freeing envelope\n");
585 pa_envelope_free(i->thread_info.ramp_info.envelope);
586 i->thread_info.ramp_info.envelope = NULL;
589 if (i->thread_info.render_memblockq)
590 pa_memblockq_free(i->thread_info.render_memblockq);
592 if (i->thread_info.resampler)
593 pa_resampler_free(i->thread_info.resampler);
596 pa_proplist_free(i->proplist);
598 if (i->direct_outputs)
599 pa_idxset_free(i->direct_outputs, NULL, NULL);
601 if (i->thread_info.direct_outputs)
602 pa_hashmap_free(i->thread_info.direct_outputs, NULL, NULL);
608 /* Called from main context */
609 void pa_sink_input_put(pa_sink_input *i) {
610 pa_sink_input_state_t state;
612 pa_sink_input_assert_ref(i);
613 pa_assert_ctl_context();
615 pa_assert(i->state == PA_SINK_INPUT_INIT);
617 /* The following fields must be initialized properly */
619 pa_assert(i->process_rewind);
622 state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
624 update_n_corked(i, state);
627 /* We might need to update the sink's volume if we are in flat volume mode. */
628 if (pa_sink_flat_volume_enabled(i->sink))
629 pa_sink_set_volume(i->sink, NULL, FALSE, i->save_volume);
631 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
632 pa_assert(pa_cvolume_is_norm(&i->volume));
633 pa_assert(pa_cvolume_is_norm(&i->reference_ratio));
636 set_real_ratio(i, &i->volume);
639 i->thread_info.soft_volume = i->soft_volume;
640 i->thread_info.muted = i->muted;
642 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0);
644 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
645 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
647 pa_sink_update_status(i->sink);
650 /* Called from main context */
651 void pa_sink_input_kill(pa_sink_input*i) {
652 pa_sink_input_assert_ref(i);
653 pa_assert_ctl_context();
654 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
659 /* Called from main context */
660 pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
661 pa_usec_t r[2] = { 0, 0 };
663 pa_sink_input_assert_ref(i);
664 pa_assert_ctl_context();
665 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
667 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, r, 0, NULL) == 0);
670 r[0] += i->get_latency(i);
673 *sink_latency = r[1];
678 /* Called from thread context */
679 void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
680 pa_bool_t do_volume_adj_here, need_volume_factor_sink;
681 pa_bool_t volume_is_norm;
683 size_t block_size_max_sink, block_size_max_sink_input;
686 pa_sink_input_assert_ref(i);
687 pa_sink_input_assert_io_context(i);
688 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
689 pa_assert(pa_frame_aligned(slength, &i->sink->sample_spec));
693 /* pa_log_debug("peek"); */
695 pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING ||
696 i->thread_info.state == PA_SINK_INPUT_CORKED ||
697 i->thread_info.state == PA_SINK_INPUT_DRAINED);
699 block_size_max_sink_input = i->thread_info.resampler ?
700 pa_resampler_max_block_size(i->thread_info.resampler) :
701 pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sample_spec);
703 block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sink->sample_spec);
705 /* Default buffer size */
707 slength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec);
709 if (slength > block_size_max_sink)
710 slength = block_size_max_sink;
712 if (i->thread_info.resampler) {
713 ilength = pa_resampler_request(i->thread_info.resampler, slength);
716 ilength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
720 if (ilength > block_size_max_sink_input)
721 ilength = block_size_max_sink_input;
723 /* If the channel maps of the sink and this stream differ, we need
724 * to adjust the volume *before* we resample. Otherwise we can do
725 * it after and leave it for the sink code */
727 do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map) || i->thread_info.ramp_info.is_ramping;
728 volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
729 need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);
731 while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
734 /* There's nothing in our render queue. We need to fill it up
735 * with data from the implementor. */
737 if (i->thread_info.state == PA_SINK_INPUT_CORKED ||
738 i->pop(i, ilength, &tchunk) < 0) {
740 /* OK, we're corked or the implementor didn't give us any
741 * data, so let's just hand out silence */
742 pa_atomic_store(&i->thread_info.drained, 1);
744 pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE, TRUE);
745 i->thread_info.playing_for = 0;
746 if (i->thread_info.underrun_for != (uint64_t) -1)
747 i->thread_info.underrun_for += ilength;
751 pa_atomic_store(&i->thread_info.drained, 0);
753 pa_assert(tchunk.length > 0);
754 pa_assert(tchunk.memblock);
756 i->thread_info.underrun_for = 0;
757 i->thread_info.playing_for += tchunk.length;
759 while (tchunk.length > 0) {
761 pa_bool_t nvfs = need_volume_factor_sink;
764 pa_memblock_ref(wchunk.memblock);
766 if (wchunk.length > block_size_max_sink_input)
767 wchunk.length = block_size_max_sink_input;
769 /* It might be necessary to adjust the volume here */
770 if (do_volume_adj_here && !volume_is_norm && !i->thread_info.ramp_info.is_ramping) {
771 pa_memchunk_make_writable(&wchunk, 0);
773 if (i->thread_info.muted) {
774 pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
777 } else if (!i->thread_info.resampler && nvfs) {
780 /* If we don't need a resampler we can merge the
781 * post and the pre volume adjustment into one */
783 pa_sw_cvolume_multiply(&v, &i->thread_info.soft_volume, &i->volume_factor_sink);
784 pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &v);
788 pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);
791 if (!i->thread_info.resampler) {
794 pa_memchunk_make_writable(&wchunk, 0);
795 pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
798 pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
801 pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
803 /* pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */
805 if (rchunk.memblock) {
808 pa_memchunk_make_writable(&rchunk, 0);
809 pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
812 pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
813 pa_memblock_unref(rchunk.memblock);
817 pa_memblock_unref(wchunk.memblock);
819 tchunk.index += wchunk.length;
820 tchunk.length -= wchunk.length;
823 pa_memblock_unref(tchunk.memblock);
826 pa_assert_se(pa_memblockq_peek(i->thread_info.render_memblockq, chunk) >= 0);
828 pa_assert(chunk->length > 0);
829 pa_assert(chunk->memblock);
831 /* pa_log_debug("peeking %lu", (unsigned long) chunk->length); */
833 if (chunk->length > block_size_max_sink)
834 chunk->length = block_size_max_sink;
836 ramping = i->thread_info.ramp_info.is_ramping;
838 sink_input_volume_ramping(i, chunk);
840 if (!i->thread_info.ramp_info.envelope_dead) {
841 i->thread_info.ramp_info.envelope_dying += chunk->length;
842 pa_log_debug("Envelope dying is %d, chunk length is %zu, dead thresholder is %lu\n", i->thread_info.ramp_info.envelope_dying,
844 i->sink->thread_info.max_rewind + pa_envelope_length(i->thread_info.ramp_info.envelope));
846 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))) {
847 pa_log_debug("RELEASE Envelop");
848 i->thread_info.ramp_info.envelope_dead = TRUE;
849 sink_input_release_envelope(i);
853 /* Let's see if we had to apply the volume adjustment ourselves,
854 * or if this can be done by the sink for us */
856 if (do_volume_adj_here)
857 /* We had different channel maps, so we already did the adjustment */
858 pa_cvolume_reset(volume, i->sink->sample_spec.channels);
859 else if (i->thread_info.muted)
860 /* We've both the same channel map, so let's have the sink do the adjustment for us*/
861 pa_cvolume_mute(volume, i->sink->sample_spec.channels);
863 *volume = i->thread_info.soft_volume;
866 /* Called from thread context */
867 void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
869 pa_sink_input_assert_ref(i);
870 pa_sink_input_assert_io_context(i);
871 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
872 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
873 pa_assert(nbytes > 0);
875 /* pa_log_debug("dropping %lu", (unsigned long) nbytes); */
877 pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
880 /* Called from thread context */
881 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
883 pa_bool_t called = FALSE;
885 pa_sink_input_assert_ref(i);
886 pa_sink_input_assert_io_context(i);
887 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
888 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
890 /* pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes); */
892 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
894 if (nbytes > 0 && !i->thread_info.dont_rewind_render) {
895 pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
896 pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
897 sink_input_rewind_ramp_info(i, nbytes);
900 if (i->thread_info.rewrite_nbytes == (size_t) -1) {
902 /* We were asked to drop all buffered data, and rerequest new
903 * data from implementor the next time push() is called */
905 pa_memblockq_flush_write(i->thread_info.render_memblockq, TRUE);
907 } else if (i->thread_info.rewrite_nbytes > 0) {
908 size_t max_rewrite, amount;
910 /* Calculate how much make sense to rewrite at most */
911 max_rewrite = nbytes + lbq;
913 /* Transform into local domain */
914 if (i->thread_info.resampler)
915 max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
917 /* Calculate how much of the rewinded data should actually be rewritten */
918 amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
921 pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
923 /* Tell the implementor */
924 if (i->process_rewind)
925 i->process_rewind(i, amount);
928 /* Convert back to to sink domain */
929 if (i->thread_info.resampler)
930 amount = pa_resampler_result(i->thread_info.resampler, amount);
933 /* Ok, now update the write pointer */
934 pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE, TRUE);
936 if (i->thread_info.rewrite_flush)
937 pa_memblockq_silence(i->thread_info.render_memblockq);
939 /* And reset the resampler */
940 if (i->thread_info.resampler)
941 pa_resampler_reset(i->thread_info.resampler);
946 if (i->process_rewind)
947 i->process_rewind(i, 0);
949 i->thread_info.rewrite_nbytes = 0;
950 i->thread_info.rewrite_flush = FALSE;
951 i->thread_info.dont_rewind_render = FALSE;
954 /* Called from thread context */
955 size_t pa_sink_input_get_max_rewind(pa_sink_input *i) {
956 pa_sink_input_assert_ref(i);
957 pa_sink_input_assert_io_context(i);
959 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_rewind) : i->sink->thread_info.max_rewind;
962 /* Called from thread context */
963 size_t pa_sink_input_get_max_request(pa_sink_input *i) {
964 pa_sink_input_assert_ref(i);
965 pa_sink_input_assert_io_context(i);
967 /* We're not verifying the status here, to allow this to be called
968 * in the state change handler between _INIT and _RUNNING */
970 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_request) : i->sink->thread_info.max_request;
973 /* Called from thread context */
974 void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
975 pa_sink_input_assert_ref(i);
976 pa_sink_input_assert_io_context(i);
977 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
978 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
980 pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
982 if (i->update_max_rewind)
983 i->update_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
986 /* Called from thread context */
987 void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
988 pa_sink_input_assert_ref(i);
989 pa_sink_input_assert_io_context(i);
990 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
991 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
993 if (i->update_max_request)
994 i->update_max_request(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
997 /* Called from thread context */
998 pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
999 pa_sink_input_assert_ref(i);
1000 pa_sink_input_assert_io_context(i);
1002 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1003 usec = i->sink->thread_info.fixed_latency;
1005 if (usec != (pa_usec_t) -1)
1006 usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
1008 i->thread_info.requested_sink_latency = usec;
1009 pa_sink_invalidate_requested_latency(i->sink, TRUE);
1014 /* Called from main context */
1015 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
1016 pa_sink_input_assert_ref(i);
1017 pa_assert_ctl_context();
1019 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1020 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1024 /* If this sink input is not realized yet or we are being moved,
1025 * we have to touch the thread info data directly */
1028 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1029 usec = pa_sink_get_fixed_latency(i->sink);
1031 if (usec != (pa_usec_t) -1) {
1032 pa_usec_t min_latency, max_latency;
1033 pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
1034 usec = PA_CLAMP(usec, min_latency, max_latency);
1038 i->thread_info.requested_sink_latency = usec;
1043 /* Called from main context */
1044 pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
1045 pa_sink_input_assert_ref(i);
1046 pa_assert_ctl_context();
1048 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1050 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1054 /* If this sink input is not realized yet or we are being moved,
1055 * we have to touch the thread info data directly */
1057 return i->thread_info.requested_sink_latency;
1060 /* Called from main context */
1061 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {
1062 pa_sink_input_assert_ref(i);
1063 pa_assert_ctl_context();
1064 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1065 pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
1067 /* This basically calculates:
1069 * i->real_ratio := v
1070 * i->soft_volume := i->real_ratio * i->volume_factor */
1075 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
1077 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1078 /* We don't copy the data to the thread_info data. That's left for someone else to do */
1081 /* Called from main context */
1082 pa_bool_t pa_sink_input_is_volume_readable(pa_sink_input *i) {
1083 pa_sink_input_assert_ref(i);
1084 pa_assert_ctl_context();
1086 return !(i->flags & PA_SINK_INPUT_PASSTHROUGH);
1089 /* Called from main context */
1090 pa_bool_t pa_sink_input_is_volume_writable(pa_sink_input *i) {
1091 pa_sink_input_assert_ref(i);
1092 pa_assert_ctl_context();
1094 if (i->flags & PA_SINK_INPUT_PASSTHROUGH)
1097 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
1103 /* Called from main context */
1104 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute) {
1105 /* test ramping -> return pa_sink_input_set_volume_with_ramping(i, volume, save, absolute, 2000 * PA_USEC_PER_MSEC); */
1106 return pa_sink_input_set_volume_with_ramping(i, volume, save, absolute, 0);
1109 /* Called from main context */
1110 pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, pa_bool_t absolute) {
1111 pa_sink_input_assert_ref(i);
1112 pa_assert_ctl_context();
1113 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1114 pa_assert(pa_sink_input_is_volume_readable(i));
1116 if (absolute || !pa_sink_flat_volume_enabled(i->sink))
1117 *volume = i->volume;
1119 *volume = i->reference_ratio;
1124 /* Called from main context */
1125 void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save) {
1126 /* test ramping -> return pa_sink_input_set_mute_with_ramping(i, mute, save, 2000 * PA_USEC_PER_MSEC); */
1127 return pa_sink_input_set_mute_with_ramping(i, mute, save, 0);
1130 /* Called from main context */
1131 pa_bool_t pa_sink_input_get_mute(pa_sink_input *i) {
1132 pa_sink_input_assert_ref(i);
1133 pa_assert_ctl_context();
1134 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1139 /* Called from main thread */
1140 void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
1141 pa_sink_input_assert_ref(i);
1142 pa_assert_ctl_context();
1145 pa_proplist_update(i->proplist, mode, p);
1147 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1148 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1149 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1153 /* Called from main context */
1154 void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) {
1155 pa_sink_input_assert_ref(i);
1156 pa_assert_ctl_context();
1157 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1159 sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
1162 /* Called from main context */
1163 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
1164 pa_sink_input_assert_ref(i);
1165 pa_assert_ctl_context();
1166 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1167 pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE);
1169 if (i->sample_spec.rate == rate)
1172 i->sample_spec.rate = rate;
1174 pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
1176 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1180 /* Called from main context */
1181 void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
1183 pa_sink_input_assert_ref(i);
1184 pa_assert_ctl_context();
1186 if (!name && !pa_proplist_contains(i->proplist, PA_PROP_MEDIA_NAME))
1189 old = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME);
1191 if (old && name && pa_streq(old, name))
1195 pa_proplist_sets(i->proplist, PA_PROP_MEDIA_NAME, name);
1197 pa_proplist_unset(i->proplist, PA_PROP_MEDIA_NAME);
1199 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1200 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1201 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1205 /* Called from main context */
1206 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
1207 pa_sink_input_assert_ref(i);
1208 pa_assert_ctl_context();
1210 return i->actual_resample_method;
1213 /* Called from main context */
1214 pa_bool_t pa_sink_input_may_move(pa_sink_input *i) {
1215 pa_sink_input_assert_ref(i);
1216 pa_assert_ctl_context();
1217 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1219 if (i->flags & PA_SINK_INPUT_DONT_MOVE)
1222 if (i->sync_next || i->sync_prev) {
1223 pa_log_warn("Moving synchronized streams not supported.");
1230 /* Called from main context */
1231 pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
1232 pa_sink_input_assert_ref(i);
1233 pa_assert_ctl_context();
1234 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1235 pa_sink_assert_ref(dest);
1237 if (dest == i->sink)
1240 if (!pa_sink_input_may_move(i))
1243 if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
1244 pa_log_warn("Failed to move sink input: too many inputs per sink.");
1248 if (check_passthrough_connection(i->flags, dest) < 0)
1252 if (!i->may_move_to(i, dest))
1258 /* Called from main context */
1259 int pa_sink_input_start_move(pa_sink_input *i) {
1260 pa_source_output *o, *p = NULL;
1263 pa_sink_input_assert_ref(i);
1264 pa_assert_ctl_context();
1265 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1268 if (!pa_sink_input_may_move(i))
1269 return -PA_ERR_NOTSUPPORTED;
1271 if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
1274 /* Kill directly connected outputs */
1275 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
1277 pa_source_output_kill(o);
1280 pa_assert(pa_idxset_isempty(i->direct_outputs));
1282 pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
1284 if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
1285 pa_assert_se(i->sink->n_corked-- >= 1);
1287 if (pa_sink_flat_volume_enabled(i->sink))
1288 /* We might need to update the sink's volume if we are in flat
1290 pa_sink_set_volume(i->sink, NULL, FALSE, FALSE);
1292 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
1294 pa_sink_update_status(i->sink);
1295 pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
1298 pa_sink_input_unref(i);
1303 /* Called from main context. If i has an origin sink that uses volume sharing,
1304 * then also the origin sink and all streams connected to it need to update
1305 * their volume - this function does all that by using recursion. */
1306 static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) {
1307 pa_cvolume old_volume;
1311 pa_assert(i->sink); /* The destination sink should already be set. */
1313 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1314 pa_sink *root_sink = i->sink;
1315 pa_sink_input *origin_sink_input;
1318 while (root_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
1319 root_sink = root_sink->input_to_master->sink;
1321 if (pa_sink_flat_volume_enabled(i->sink)) {
1322 /* Ok, so the origin sink uses volume sharing, and flat volume is
1323 * enabled. The volume will have to be updated as follows:
1325 * i->volume := i->sink->real_volume
1326 * (handled later by pa_sink_set_volume)
1327 * i->reference_ratio := i->volume / i->sink->reference_volume
1328 * (handled later by pa_sink_set_volume)
1329 * i->real_ratio stays unchanged
1330 * (streams whose origin sink uses volume sharing should
1331 * always have real_ratio of 0 dB)
1332 * i->soft_volume stays unchanged
1333 * (streams whose origin sink uses volume sharing should
1334 * always have volume_factor as soft_volume, so no change
1335 * should be needed) */
1337 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
1338 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
1340 /* Notifications will be sent by pa_sink_set_volume(). */
1343 /* Ok, so the origin sink uses volume sharing, and flat volume is
1344 * disabled. The volume will have to be updated as follows:
1347 * i->reference_ratio := 0 dB
1348 * i->real_ratio stays unchanged
1349 * (streams whose origin sink uses volume sharing should
1350 * always have real_ratio of 0 dB)
1351 * i->soft_volume stays unchanged
1352 * (streams whose origin sink uses volume sharing should
1353 * always have volume_factor as soft_volume, so no change
1354 * should be needed) */
1356 old_volume = i->volume;
1357 pa_cvolume_reset(&i->volume, i->volume.channels);
1358 pa_cvolume_reset(&i->reference_ratio, i->reference_ratio.channels);
1359 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
1360 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
1362 /* Notify others about the changed sink input volume. */
1363 if (!pa_cvolume_equal(&i->volume, &old_volume)) {
1364 if (i->volume_changed)
1365 i->volume_changed(i);
1367 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1371 /* Additionally, the origin sink volume needs updating:
1373 * i->origin_sink->reference_volume := root_sink->reference_volume
1374 * i->origin_sink->real_volume := root_sink->real_volume
1375 * i->origin_sink->soft_volume stays unchanged
1376 * (sinks that use volume sharing should always have
1377 * soft_volume of 0 dB) */
1379 old_volume = i->origin_sink->reference_volume;
1381 i->origin_sink->reference_volume = root_sink->reference_volume;
1382 pa_cvolume_remap(&i->origin_sink->reference_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
1384 i->origin_sink->real_volume = root_sink->real_volume;
1385 pa_cvolume_remap(&i->origin_sink->real_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
1387 pa_assert(pa_cvolume_is_norm(&i->origin_sink->soft_volume));
1389 /* Notify others about the changed sink volume. If you wonder whether
1390 * i->origin_sink->set_volume() should be called somewhere, that's not
1391 * the case, because sinks that use volume sharing shouldn't have any
1392 * internal volume that set_volume() would update. If you wonder
1393 * whether the thread_info variables should be synced, yes, they
1394 * should, and it's done by the PA_SINK_MESSAGE_FINISH_MOVE message
1396 if (!pa_cvolume_equal(&i->origin_sink->reference_volume, &old_volume))
1397 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, i->origin_sink->index);
1399 /* Recursively update origin sink inputs. */
1400 PA_IDXSET_FOREACH(origin_sink_input, i->origin_sink->inputs, idx)
1401 update_volume_due_to_moving(origin_sink_input, dest);
1404 old_volume = i->volume;
1406 if (pa_sink_flat_volume_enabled(i->sink)) {
1407 /* Ok, so this is a regular stream, and flat volume is enabled. The
1408 * volume will have to be updated as follows:
1410 * i->volume := i->reference_ratio * i->sink->reference_volume
1411 * i->reference_ratio stays unchanged
1412 * i->real_ratio := i->volume / i->sink->real_volume
1413 * (handled later by pa_sink_set_volume)
1414 * i->soft_volume := i->real_ratio * i->volume_factor
1415 * (handled later by pa_sink_set_volume) */
1417 i->volume = i->sink->reference_volume;
1418 pa_cvolume_remap(&i->volume, &i->sink->channel_map, &i->channel_map);
1419 pa_sw_cvolume_multiply(&i->volume, &i->volume, &i->reference_ratio);
1422 /* Ok, so this is a regular stream, and flat volume is disabled.
1423 * The volume will have to be updated as follows:
1425 * i->volume := i->reference_ratio
1426 * i->reference_ratio stays unchanged
1427 * i->real_ratio := i->reference_ratio
1428 * i->soft_volume := i->real_ratio * i->volume_factor */
1430 i->volume = i->reference_ratio;
1431 i->real_ratio = i->reference_ratio;
1432 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1435 /* Notify others about the changed sink input volume. */
1436 if (!pa_cvolume_equal(&i->volume, &old_volume)) {
1437 /* XXX: In case i->sink has flat volume enabled, then real_ratio
1438 * and soft_volume are not updated yet. Let's hope that the
1439 * callback implementation doesn't care about those variables... */
1440 if (i->volume_changed)
1441 i->volume_changed(i);
1443 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1447 /* If i->sink == dest, then recursion has finished, and we can finally call
1448 * pa_sink_set_volume(), which will do the rest of the updates. */
1449 if ((i->sink == dest) && pa_sink_flat_volume_enabled(i->sink))
1450 pa_sink_set_volume(i->sink, NULL, FALSE, i->save_volume);
1453 /* Called from main context */
1454 int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
1455 pa_resampler *new_resampler;
1457 pa_sink_input_assert_ref(i);
1458 pa_assert_ctl_context();
1459 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1460 pa_assert(!i->sink);
1461 pa_sink_assert_ref(dest);
1463 if (!pa_sink_input_may_move_to(i, dest))
1464 return -PA_ERR_NOTSUPPORTED;
1466 if (i->thread_info.resampler &&
1467 pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &dest->sample_spec) &&
1468 pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &dest->channel_map))
1470 /* Try to reuse the old resampler if possible */
1471 new_resampler = i->thread_info.resampler;
1473 else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
1474 !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) ||
1475 !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) {
1477 /* Okey, we need a new resampler for the new sink */
1479 if (!(new_resampler = pa_resampler_new(
1481 &i->sample_spec, &i->channel_map,
1482 &dest->sample_spec, &dest->channel_map,
1483 i->requested_resample_method,
1484 ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
1485 ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
1486 (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
1487 pa_log_warn("Unsupported resampling operation.");
1488 return -PA_ERR_NOTSUPPORTED;
1491 new_resampler = NULL;
1497 i->save_sink = save;
1498 pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
1500 pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
1502 if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
1503 i->sink->n_corked++;
1505 /* Replace resampler and render queue */
1506 if (new_resampler != i->thread_info.resampler) {
1508 if (i->thread_info.resampler)
1509 pa_resampler_free(i->thread_info.resampler);
1510 i->thread_info.resampler = new_resampler;
1512 pa_memblockq_free(i->thread_info.render_memblockq);
1514 i->thread_info.render_memblockq = pa_memblockq_new(
1516 MEMBLOCKQ_MAXLENGTH,
1518 pa_frame_size(&i->sink->sample_spec),
1524 pa_sink_update_status(dest);
1526 update_volume_due_to_moving(i, dest);
1528 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
1530 pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
1532 /* Notify everyone */
1533 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
1535 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1540 /* Called from main context */
1541 void pa_sink_input_fail_move(pa_sink_input *i) {
1543 pa_sink_input_assert_ref(i);
1544 pa_assert_ctl_context();
1545 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1546 pa_assert(!i->sink);
1548 /* Check if someone wants this sink input? */
1549 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_STOP)
1555 pa_sink_input_kill(i);
1558 /* Called from main context */
1559 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
1562 pa_sink_input_assert_ref(i);
1563 pa_assert_ctl_context();
1564 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1566 pa_sink_assert_ref(dest);
1568 if (dest == i->sink)
1571 if (!pa_sink_input_may_move_to(i, dest))
1572 return -PA_ERR_NOTSUPPORTED;
1574 pa_sink_input_ref(i);
1576 if ((r = pa_sink_input_start_move(i)) < 0) {
1577 pa_sink_input_unref(i);
1581 if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
1582 pa_sink_input_fail_move(i);
1583 pa_sink_input_unref(i);
1587 pa_sink_input_unref(i);
1592 /* Called from IO thread context */
1593 void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
1594 pa_bool_t corking, uncorking;
1596 pa_sink_input_assert_ref(i);
1597 pa_sink_input_assert_io_context(i);
1599 if (state == i->thread_info.state)
1602 if ((state == PA_SINK_INPUT_DRAINED || state == PA_SINK_INPUT_RUNNING) &&
1603 !(i->thread_info.state == PA_SINK_INPUT_DRAINED || i->thread_info.state != PA_SINK_INPUT_RUNNING))
1604 pa_atomic_store(&i->thread_info.drained, 1);
1606 corking = state == PA_SINK_INPUT_CORKED && i->thread_info.state == PA_SINK_INPUT_RUNNING;
1607 uncorking = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
1609 if (i->state_change)
1610 i->state_change(i, state);
1612 i->thread_info.state = state;
1616 pa_log_debug("Requesting rewind due to corking");
1618 /* This will tell the implementing sink input driver to rewind
1619 * so that the unplayed already mixed data is not lost */
1620 pa_sink_input_request_rewind(i, 0, TRUE, TRUE, FALSE);
1622 } else if (uncorking) {
1624 i->thread_info.underrun_for = (uint64_t) -1;
1625 i->thread_info.playing_for = 0;
1627 pa_log_debug("Requesting rewind due to uncorking");
1629 /* OK, we're being uncorked. Make sure we're not rewound when
1630 * the hw buffer is remixed and request a remix. */
1631 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
1635 /* Called from thread context, except when it is not. */
1636 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1637 pa_sink_input *i = PA_SINK_INPUT(o);
1638 pa_sink_input_assert_ref(i);
1642 case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
1643 if (pa_atomic_load(&i->before_ramping_v))
1644 i->thread_info.future_soft_volume = i->soft_volume;
1646 if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
1647 if (!pa_atomic_load(&i->before_ramping_v))
1648 i->thread_info.soft_volume = i->soft_volume;
1649 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1653 case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
1654 if (pa_atomic_load(&i->before_ramping_m))
1655 i->thread_info.future_muted = i->muted;
1657 if (i->thread_info.muted != i->muted) {
1658 if (!pa_atomic_load(&i->before_ramping_m))
1659 i->thread_info.muted = i->muted;
1660 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1664 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1665 pa_usec_t *r = userdata;
1667 r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
1668 r[1] += pa_sink_get_latency_within_thread(i->sink);
1673 case PA_SINK_INPUT_MESSAGE_SET_RATE:
1675 i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
1676 pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
1680 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1681 pa_sink_input *ssync;
1683 pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
1685 for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
1686 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
1688 for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
1689 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
1694 case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
1695 pa_usec_t *usec = userdata;
1697 *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
1701 case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
1702 pa_usec_t *r = userdata;
1704 *r = i->thread_info.requested_sink_latency;
1708 case PA_SINK_INPUT_MESSAGE_SET_ENVELOPE: {
1709 if (!i->thread_info.ramp_info.envelope)
1710 i->thread_info.ramp_info.envelope = pa_envelope_new(&i->sink->sample_spec);
1712 if (i->thread_info.ramp_info.envelope && i->thread_info.ramp_info.item) {
1713 pa_envelope_remove(i->thread_info.ramp_info.envelope, i->thread_info.ramp_info.item);
1714 i->thread_info.ramp_info.item = NULL;
1717 i->thread_info.ramp_info.item = pa_envelope_add(i->thread_info.ramp_info.envelope, &i->using_def);
1718 i->thread_info.ramp_info.is_ramping = TRUE;
1719 i->thread_info.ramp_info.envelope_dead = FALSE;
1720 i->thread_info.ramp_info.envelope_dying = 0;
1722 if (i->thread_info.ramp_info.envelope)
1723 pa_envelope_restart(i->thread_info.ramp_info.envelope);
1729 return -PA_ERR_NOTIMPLEMENTED;
1732 /* Called from main thread */
1733 pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
1734 pa_sink_input_assert_ref(i);
1735 pa_assert_ctl_context();
1737 if (i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED)
1738 return pa_atomic_load(&i->thread_info.drained) ? PA_SINK_INPUT_DRAINED : PA_SINK_INPUT_RUNNING;
1743 /* Called from IO context */
1744 pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
1745 pa_sink_input_assert_ref(i);
1746 pa_sink_input_assert_io_context(i);
1748 if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
1749 return pa_memblockq_is_empty(i->thread_info.render_memblockq);
1754 /* Called from IO context */
1755 void pa_sink_input_request_rewind(
1757 size_t nbytes /* in our sample spec */,
1760 pa_bool_t dont_rewind_render) {
1764 /* If 'rewrite' is TRUE the sink is rewound as far as requested
1765 * and possible and the exact value of this is passed back the
1766 * implementor via process_rewind(). If 'flush' is also TRUE all
1767 * already rendered data is also dropped.
1769 * If 'rewrite' is FALSE the sink is rewound as far as requested
1770 * and possible and the already rendered data is dropped so that
1771 * in the next iteration we read new data from the
1772 * implementor. This implies 'flush' is TRUE. If
1773 * dont_rewind_render is TRUE then the render memblockq is not
1776 /* nbytes = 0 means maximum rewind request */
1778 pa_sink_input_assert_ref(i);
1779 pa_sink_input_assert_io_context(i);
1780 pa_assert(rewrite || flush);
1781 pa_assert(!dont_rewind_render || !rewrite);
1783 /* We don't take rewind requests while we are corked */
1784 if (i->thread_info.state == PA_SINK_INPUT_CORKED)
1787 nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
1789 /* pa_log_debug("request rewrite %zu", nbytes); */
1791 /* Calculate how much we can rewind locally without having to
1794 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
1798 /* Check if rewinding for the maximum is requested, and if so, fix up */
1801 /* Calculate maximum number of bytes that could be rewound in theory */
1802 nbytes = i->sink->thread_info.max_rewind + lbq;
1804 /* Transform from sink domain */
1805 if (i->thread_info.resampler)
1806 nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
1809 /* Remember how much we actually want to rewrite */
1810 if (i->thread_info.rewrite_nbytes != (size_t) -1) {
1812 /* Make sure to not overwrite over underruns */
1813 if (nbytes > i->thread_info.playing_for)
1814 nbytes = (size_t) i->thread_info.playing_for;
1816 i->thread_info.rewrite_nbytes = nbytes;
1818 i->thread_info.rewrite_nbytes = (size_t) -1;
1821 i->thread_info.rewrite_flush =
1822 i->thread_info.rewrite_flush ||
1823 (flush && i->thread_info.rewrite_nbytes != 0);
1825 i->thread_info.dont_rewind_render =
1826 i->thread_info.dont_rewind_render ||
1829 if (nbytes != (size_t) -1) {
1831 /* Transform to sink domain */
1832 if (i->thread_info.resampler)
1833 nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
1836 pa_sink_request_rewind(i->sink, nbytes - lbq);
1838 /* This call will make sure process_rewind() is called later */
1839 pa_sink_request_rewind(i->sink, 0);
1843 /* Called from main context */
1844 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
1845 pa_sink_input_assert_ref(i);
1846 pa_assert_ctl_context();
1849 /* FIXME: Shouldn't access resampler object from main context! */
1851 pa_silence_memchunk_get(
1852 &i->core->silence_cache,
1856 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
1861 /* Called from main context */
1862 void pa_sink_input_send_event(pa_sink_input *i, const char *event, pa_proplist *data) {
1863 pa_proplist *pl = NULL;
1864 pa_sink_input_send_event_hook_data hook_data;
1866 pa_sink_input_assert_ref(i);
1867 pa_assert_ctl_context();
1874 data = pl = pa_proplist_new();
1876 hook_data.sink_input = i;
1877 hook_data.data = data;
1878 hook_data.event = event;
1880 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
1883 i->send_event(i, event, data);
1887 pa_proplist_free(pl);
1890 /* Called from IO context */
1891 static void sink_input_volume_ramping(pa_sink_input* i, pa_memchunk* chunk) {
1894 pa_assert(chunk->memblock);
1895 pa_assert(i->thread_info.ramp_info.is_ramping);
1897 /* Volume is adjusted with ramping effect here */
1898 pa_envelope_apply(i->thread_info.ramp_info.envelope, chunk);
1900 if (pa_envelope_is_finished(i->thread_info.ramp_info.envelope)) {
1901 i->thread_info.ramp_info.is_ramping = FALSE;
1902 if (pa_atomic_load(&i->before_ramping_v)) {
1903 i->thread_info.soft_volume = i->thread_info.future_soft_volume;
1904 pa_atomic_store(&i->before_ramping_v, 0);
1906 else if (pa_atomic_load(&i->before_ramping_m)) {
1907 i->thread_info.muted = i->thread_info.future_muted;
1908 pa_atomic_store(&i->before_ramping_m, 0);
1914 * Called from main context
1915 * This function should be called inside pa_sink_input_set_volume_with_ramping
1916 * should be called after soft_volume of sink_input and sink are all adjusted
1918 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) {
1920 int32_t target_abs_vol, target_apply_vol, pre_apply_vol;
1923 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)));
1925 /* Calculation formula are target_abs_vol := i->soft_volume
1926 * target_apply_vol := lrint(pa_sw_volume_to_linear(target_abs_vol) * 0x10000)
1927 * pre_apply_vol := ( previous_virtual_volume / target_virtual_volume ) * target_apply_vol
1929 * Will do volume adjustment inside pa_sink_input_peek
1931 target_abs_vol = pa_cvolume_avg(&i->soft_volume);
1932 target_apply_vol = (int32_t) lrint(pa_sw_volume_to_linear(target_abs_vol) * 0x10000);
1933 pre_apply_vol = (int32_t) ((pa_sw_volume_to_linear(pre_virtual_volume) / pa_sw_volume_to_linear(target_virtual_volume)) * target_apply_vol);
1935 i->using_def.n_points = 2;
1936 i->using_def.points_x[0] = 0;
1937 i->using_def.points_x[1] = t;
1938 i->using_def.points_y.i[0] = pre_apply_vol;
1939 i->using_def.points_y.i[1] = target_apply_vol;
1940 i->using_def.points_y.f[0] = ((float) i->using_def.points_y.i[0]) /0x10000;
1941 i->using_def.points_y.f[1] = ((float) i->using_def.points_y.i[1]) /0x10000;
1943 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],
1944 i->using_def.points_y.i[1], i->using_def.points_y.f[1]);
1946 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_ENVELOPE, NULL, 0, NULL) == 0);
1949 /* Called from main context */
1950 static void sink_input_set_ramping_info_for_mute(pa_sink_input* i, pa_bool_t mute, pa_usec_t t) {
1955 i->using_def.n_points = 2;
1956 i->using_def.points_x[0] = 0;
1957 i->using_def.points_x[1] = t;
1958 cur_vol = (int32_t) lrint( pa_sw_volume_to_linear(pa_cvolume_avg(&i->soft_volume)) * 0x10000);
1961 i->using_def.points_y.i[0] = cur_vol;
1962 i->using_def.points_y.i[1] = 0;
1964 i->using_def.points_y.i[0] = 0;
1965 i->using_def.points_y.i[1] = cur_vol;
1968 i->using_def.points_y.f[0] = ((float) i->using_def.points_y.i[0]) /0x10000;
1969 i->using_def.points_y.f[1] = ((float) i->using_def.points_y.i[1]) /0x10000;
1971 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],
1972 i->using_def.points_y.i[1], i->using_def.points_y.f[1]);
1974 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_ENVELOPE, NULL, 0, NULL) == 0);
1977 /* Called from IO context */
1978 static void sink_input_release_envelope(pa_sink_input *i) {
1980 pa_assert(!i->thread_info.ramp_info.is_ramping);
1981 pa_assert(i->thread_info.ramp_info.envelope_dead);
1983 pa_envelope_free(i->thread_info.ramp_info.envelope);
1984 i->thread_info.ramp_info.envelope = NULL;
1985 i->thread_info.ramp_info.item = NULL;
1988 /* Called from IO context */
1989 static void sink_input_rewind_ramp_info(pa_sink_input *i, size_t nbytes) {
1992 if (!i->thread_info.ramp_info.envelope_dead) {
1993 int32_t envelope_length;
1995 pa_assert(i->thread_info.ramp_info.envelope);
1997 envelope_length = pa_envelope_length(i->thread_info.ramp_info.envelope);
1999 if (i->thread_info.ramp_info.envelope_dying > envelope_length) {
2000 if ((int32_t) (i->thread_info.ramp_info.envelope_dying - nbytes) < envelope_length) {
2001 pa_log_debug("Envelope Become Alive");
2002 pa_envelope_rewind(i->thread_info.ramp_info.envelope, envelope_length - (i->thread_info.ramp_info.envelope_dying - nbytes));
2003 i->thread_info.ramp_info.is_ramping = TRUE;
2005 } else if (i->thread_info.ramp_info.envelope_dying < envelope_length) {
2006 if ((i->thread_info.ramp_info.envelope_dying - nbytes) <= 0) {
2007 pa_log_debug("Envelope Restart");
2008 pa_envelope_restart(i->thread_info.ramp_info.envelope);
2011 pa_log_debug("Envelope Simple Rewind");
2012 pa_envelope_rewind(i->thread_info.ramp_info.envelope, nbytes);
2016 i->thread_info.ramp_info.envelope_dying -= nbytes;
2017 if (i->thread_info.ramp_info.envelope_dying <= 0)
2018 i->thread_info.ramp_info.envelope_dying = 0;
2022 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){
2024 pa_volume_t previous_virtual_volume, target_virtual_volume;
2026 pa_sink_input_assert_ref(i);
2027 pa_assert_ctl_context();
2028 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2030 pa_assert(pa_cvolume_valid(volume));
2031 pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
2032 pa_assert(pa_sink_input_is_volume_writable(i));
2034 if (!absolute && pa_sink_flat_volume_enabled(i->sink)) {
2035 v = i->sink->reference_volume;
2036 pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
2038 if (pa_cvolume_compatible(volume, &i->sample_spec))
2039 volume = pa_sw_cvolume_multiply(&v, &v, volume);
2041 volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume));
2044 if (!pa_cvolume_compatible(volume, &i->sample_spec)) {
2046 volume = pa_cvolume_scale(&v, pa_cvolume_max(volume));
2050 if (pa_cvolume_equal(volume, &i->volume)) {
2051 i->save_volume = i->save_volume || save;
2055 previous_virtual_volume = pa_cvolume_avg(&i->volume);
2056 target_virtual_volume = pa_cvolume_avg(volume);
2058 if (t > 0 && target_virtual_volume > 0)
2059 pa_log_debug("SetVolumeWithRamping: Virtual Volume From %u=%f to %u=%f\n", previous_virtual_volume, pa_sw_volume_to_linear(previous_virtual_volume),
2060 target_virtual_volume, pa_sw_volume_to_linear(target_virtual_volume));
2062 i->volume = *volume;
2063 i->save_volume = save;
2065 /* Set this flag before the following code modify i->thread_info.soft_volume */
2066 if (t > 0 && target_virtual_volume > 0)
2067 pa_atomic_store(&i->before_ramping_v, 1);
2069 if (pa_sink_flat_volume_enabled(i->sink)) {
2070 /* We are in flat volume mode, so let's update all sink input
2071 * volumes and update the flat volume of the sink */
2073 pa_sink_set_volume(i->sink, NULL, TRUE, save);
2076 /* OK, we are in normal volume mode. The volume only affects
2078 i->reference_ratio = *volume;
2079 set_real_ratio(i, volume);
2081 /* Copy the new soft_volume to the thread_info struct */
2082 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
2085 if (t > 0 && target_virtual_volume > 0)
2086 sink_input_set_ramping_info(i, previous_virtual_volume, target_virtual_volume, t);
2088 /* The volume changed, let's tell people so */
2089 if (i->volume_changed)
2090 i->volume_changed(i);
2092 /* The virtual volume changed, let's tell people so */
2093 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2096 void pa_sink_input_set_mute_with_ramping(pa_sink_input *i, pa_bool_t mute, pa_bool_t save, pa_usec_t t){
2098 pa_sink_input_assert_ref(i);
2099 pa_assert_ctl_context();
2100 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2102 if (!i->muted == !mute) {
2103 i->save_muted = i->save_muted || mute;
2108 i->save_muted = save;
2110 /* Set this flag before the following code modify i->thread_info.muted, otherwise distortion will be heard */
2112 pa_atomic_store(&i->before_ramping_m, 1);
2114 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
2117 sink_input_set_ramping_info_for_mute(i, mute, t);
2119 /* The mute status changed, let's tell people so */
2120 if (i->mute_changed)
2123 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);