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 void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) {
118 if ((data->volume_is_set = !!volume))
119 data->volume = *volume;
122 void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
124 pa_assert(volume_factor);
126 if (data->volume_factor_is_set)
127 pa_sw_cvolume_multiply(&data->volume_factor, &data->volume_factor, volume_factor);
129 data->volume_factor_is_set = TRUE;
130 data->volume_factor = *volume_factor;
134 void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
136 pa_assert(volume_factor);
138 if (data->volume_factor_sink_is_set)
139 pa_sw_cvolume_multiply(&data->volume_factor_sink, &data->volume_factor_sink, volume_factor);
141 data->volume_factor_sink_is_set = TRUE;
142 data->volume_factor_sink = *volume_factor;
146 void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
149 data->muted_is_set = TRUE;
150 data->muted = !!mute;
153 void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
156 pa_proplist_free(data->proplist);
159 /* Called from main context */
160 static void reset_callbacks(pa_sink_input *i) {
164 i->process_rewind = NULL;
165 i->update_max_rewind = NULL;
166 i->update_max_request = NULL;
167 i->update_sink_requested_latency = NULL;
168 i->update_sink_latency_range = NULL;
169 i->update_sink_fixed_latency = NULL;
173 i->suspend_within_thread = NULL;
176 i->get_latency = NULL;
177 i->state_change = NULL;
178 i->may_move_to = NULL;
179 i->send_event = NULL;
180 i->volume_changed = NULL;
181 i->mute_changed = NULL;
184 /* Called from main context */
185 int pa_sink_input_new(
188 pa_sink_input_new_data *data) {
191 pa_resampler *resampler = NULL;
192 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
193 pa_channel_map original_cm;
200 pa_assert_ctl_context();
203 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
205 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0)
208 pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
211 data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK);
212 data->save_sink = FALSE;
215 pa_return_val_if_fail(data->sink, -PA_ERR_NOENTITY);
216 pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)), -PA_ERR_BADSTATE);
217 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);
219 r = check_passthrough_connection(data->flags, data->sink);
220 pa_return_val_if_fail(r == PA_OK, r);
222 if (!data->sample_spec_is_set)
223 data->sample_spec = data->sink->sample_spec;
225 pa_return_val_if_fail(pa_sample_spec_valid(&data->sample_spec), -PA_ERR_INVALID);
227 if (!data->channel_map_is_set) {
228 if (pa_channel_map_compatible(&data->sink->channel_map, &data->sample_spec))
229 data->channel_map = data->sink->channel_map;
231 pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
234 pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
236 if (!data->volume_is_set) {
237 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
238 data->volume_is_absolute = FALSE;
239 data->save_volume = FALSE;
242 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec), -PA_ERR_INVALID);
244 if (!data->volume_factor_is_set)
245 pa_cvolume_reset(&data->volume_factor, data->sample_spec.channels);
247 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor, &data->sample_spec), -PA_ERR_INVALID);
249 if (!data->volume_factor_sink_is_set)
250 pa_cvolume_reset(&data->volume_factor_sink, data->sink->sample_spec.channels);
252 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor_sink, &data->sink->sample_spec), -PA_ERR_INVALID);
254 if (!data->muted_is_set)
257 if (data->flags & PA_SINK_INPUT_FIX_FORMAT)
258 data->sample_spec.format = data->sink->sample_spec.format;
260 if (data->flags & PA_SINK_INPUT_FIX_RATE)
261 data->sample_spec.rate = data->sink->sample_spec.rate;
263 original_cm = data->channel_map;
265 if (data->flags & PA_SINK_INPUT_FIX_CHANNELS) {
266 data->sample_spec.channels = data->sink->sample_spec.channels;
267 data->channel_map = data->sink->channel_map;
270 pa_assert(pa_sample_spec_valid(&data->sample_spec));
271 pa_assert(pa_channel_map_valid(&data->channel_map));
273 /* Due to the fixing of the sample spec the volume might not match anymore */
274 pa_cvolume_remap(&data->volume, &original_cm, &data->channel_map);
276 if (data->resample_method == PA_RESAMPLER_INVALID)
277 data->resample_method = core->resample_method;
279 pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
281 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
284 if ((data->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND) &&
285 pa_sink_get_state(data->sink) == PA_SINK_SUSPENDED) {
286 pa_log_warn("Failed to create sink input: sink is suspended.");
287 return -PA_ERR_BADSTATE;
290 if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) {
291 pa_log_warn("Failed to create sink input: too many inputs per sink.");
292 return -PA_ERR_TOOLARGE;
295 if ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
296 !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) ||
297 !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) {
299 if (!(resampler = pa_resampler_new(
301 &data->sample_spec, &data->channel_map,
302 &data->sink->sample_spec, &data->sink->channel_map,
303 data->resample_method,
304 ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
305 ((data->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
306 (core->disable_remixing || (data->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
307 (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
308 pa_log_warn("Unsupported resampling operation.");
309 return -PA_ERR_NOTSUPPORTED;
313 i = pa_msgobject_new(pa_sink_input);
314 i->parent.parent.free = sink_input_free;
315 i->parent.process_msg = pa_sink_input_process_msg;
318 i->state = PA_SINK_INPUT_INIT;
319 i->flags = data->flags;
320 i->proplist = pa_proplist_copy(data->proplist);
321 i->driver = pa_xstrdup(pa_path_get_filename(data->driver));
322 i->module = data->module;
323 i->sink = data->sink;
324 i->origin_sink = data->origin_sink;
325 i->client = data->client;
327 i->requested_resample_method = data->resample_method;
328 i->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID;
329 i->sample_spec = data->sample_spec;
330 i->channel_map = data->channel_map;
332 if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !data->volume_is_absolute) {
335 /* When the 'absolute' bool is not set then we'll treat the volume
336 * as relative to the sink volume even in flat volume mode */
337 remapped = data->sink->reference_volume;
338 pa_cvolume_remap(&remapped, &data->sink->channel_map, &data->channel_map);
339 pa_sw_cvolume_multiply(&i->volume, &data->volume, &remapped);
341 i->volume = data->volume;
343 i->volume_factor = data->volume_factor;
344 i->volume_factor_sink = data->volume_factor_sink;
345 i->real_ratio = i->reference_ratio = data->volume;
346 pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
347 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
348 i->save_volume = data->save_volume;
349 i->save_sink = data->save_sink;
350 i->save_muted = data->save_muted;
352 i->muted = data->muted;
354 if (data->sync_base) {
355 i->sync_next = data->sync_base->sync_next;
356 i->sync_prev = data->sync_base;
358 if (data->sync_base->sync_next)
359 data->sync_base->sync_next->sync_prev = i;
360 data->sync_base->sync_next = i;
362 i->sync_next = i->sync_prev = NULL;
364 i->direct_outputs = pa_idxset_new(NULL, NULL);
369 /* Set Ramping info */
370 i->thread_info.ramp_info.is_ramping = FALSE;
371 i->thread_info.ramp_info.envelope_dead = TRUE;
372 i->thread_info.ramp_info.envelope = NULL;
373 i->thread_info.ramp_info.item = NULL;
374 i->thread_info.ramp_info.envelope_dying = 0;
376 pa_atomic_store(&i->before_ramping_v, 0);
377 pa_atomic_store(&i->before_ramping_m, 0);
379 i->thread_info.state = i->state;
380 i->thread_info.attached = FALSE;
381 pa_atomic_store(&i->thread_info.drained, 1);
382 i->thread_info.sample_spec = i->sample_spec;
383 i->thread_info.resampler = resampler;
384 i->thread_info.soft_volume = i->soft_volume;
385 i->thread_info.muted = i->muted;
386 i->thread_info.requested_sink_latency = (pa_usec_t) -1;
387 i->thread_info.rewrite_nbytes = 0;
388 i->thread_info.rewrite_flush = FALSE;
389 i->thread_info.dont_rewind_render = FALSE;
390 i->thread_info.underrun_for = (uint64_t) -1;
391 i->thread_info.playing_for = 0;
392 i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
394 i->thread_info.render_memblockq = pa_memblockq_new(
398 pa_frame_size(&i->sink->sample_spec),
404 pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
405 pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0);
408 pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
410 pt = pa_proplist_to_string_sep(i->proplist, "\n ");
411 pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
413 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
415 pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
416 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
420 /* Don't forget to call pa_sink_input_put! */
426 /* Called from main context */
427 static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
429 pa_assert_ctl_context();
434 if (i->state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED)
435 pa_assert_se(i->sink->n_corked -- >= 1);
436 else if (i->state != PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_CORKED)
440 /* Called from main context */
441 static void sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
442 pa_sink_input *ssync;
444 pa_assert_ctl_context();
446 if (state == PA_SINK_INPUT_DRAINED)
447 state = PA_SINK_INPUT_RUNNING;
449 if (i->state == state)
452 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);
454 update_n_corked(i, state);
457 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev) {
458 update_n_corked(ssync, state);
459 ssync->state = state;
461 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) {
462 update_n_corked(ssync, state);
463 ssync->state = state;
466 if (state != PA_SINK_INPUT_UNLINKED) {
467 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
469 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev)
470 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
472 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next)
473 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
475 if (PA_SINK_INPUT_IS_LINKED(state))
476 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
479 pa_sink_update_status(i->sink);
482 /* Called from main context */
483 void pa_sink_input_unlink(pa_sink_input *i) {
485 pa_source_output *o, *p = NULL;
488 pa_assert_ctl_context();
490 /* See pa_sink_unlink() for a couple of comments how this function
493 pa_sink_input_ref(i);
495 linked = PA_SINK_INPUT_IS_LINKED(i->state);
498 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
501 i->sync_prev->sync_next = i->sync_next;
503 i->sync_next->sync_prev = i->sync_prev;
505 i->sync_prev = i->sync_next = NULL;
507 pa_idxset_remove_by_data(i->core->sink_inputs, i, NULL);
510 if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
511 pa_sink_input_unref(i);
514 pa_idxset_remove_by_data(i->client->sink_inputs, i, NULL);
516 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
518 pa_source_output_kill(o);
522 update_n_corked(i, PA_SINK_INPUT_UNLINKED);
523 i->state = PA_SINK_INPUT_UNLINKED;
525 if (linked && i->sink) {
526 /* We might need to update the sink's volume if we are in flat volume mode. */
527 if (i->sink->flags & PA_SINK_FLAT_VOLUME)
528 pa_sink_set_volume(i->sink, NULL, FALSE, FALSE);
530 if (i->sink->asyncmsgq)
531 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL) == 0);
537 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
538 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
542 pa_sink_update_status(i->sink);
546 pa_core_maybe_vacuum(i->core);
548 pa_sink_input_unref(i);
551 /* Called from main context */
552 static void sink_input_free(pa_object *o) {
553 pa_sink_input* i = PA_SINK_INPUT(o);
556 pa_assert_ctl_context();
557 pa_assert(pa_sink_input_refcnt(i) == 0);
559 if (PA_SINK_INPUT_IS_LINKED(i->state))
560 pa_sink_input_unlink(i);
562 pa_log_info("Freeing input %u \"%s\"", i->index, pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)));
564 /* Side note: this function must be able to destruct properly any
565 * kind of sink input in any state, even those which are
566 * "half-moved" or are connected to sinks that have no asyncmsgq
567 * and are hence half-destructed themselves! */
569 if (i->thread_info.ramp_info.envelope) {
570 pa_log_debug ("Freeing envelope\n");
571 pa_envelope_free(i->thread_info.ramp_info.envelope);
572 i->thread_info.ramp_info.envelope = NULL;
575 if (i->thread_info.render_memblockq)
576 pa_memblockq_free(i->thread_info.render_memblockq);
578 if (i->thread_info.resampler)
579 pa_resampler_free(i->thread_info.resampler);
582 pa_proplist_free(i->proplist);
584 if (i->direct_outputs)
585 pa_idxset_free(i->direct_outputs, NULL, NULL);
587 if (i->thread_info.direct_outputs)
588 pa_hashmap_free(i->thread_info.direct_outputs, NULL, NULL);
594 /* Called from main context */
595 void pa_sink_input_put(pa_sink_input *i) {
596 pa_sink_input_state_t state;
598 pa_sink_input_assert_ref(i);
599 pa_assert_ctl_context();
601 pa_assert(i->state == PA_SINK_INPUT_INIT);
603 /* The following fields must be initialized properly */
605 pa_assert(i->process_rewind);
608 state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
610 update_n_corked(i, state);
613 /* We might need to update the sink's volume if we are in flat volume mode. */
614 if (i->sink->flags & PA_SINK_FLAT_VOLUME)
615 pa_sink_set_volume(i->sink, NULL, FALSE, i->save_volume);
617 set_real_ratio(i, &i->volume);
619 i->thread_info.soft_volume = i->soft_volume;
620 i->thread_info.muted = i->muted;
622 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0);
624 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
625 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
627 pa_sink_update_status(i->sink);
630 /* Called from main context */
631 void pa_sink_input_kill(pa_sink_input*i) {
632 pa_sink_input_assert_ref(i);
633 pa_assert_ctl_context();
634 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
639 /* Called from main context */
640 pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
641 pa_usec_t r[2] = { 0, 0 };
643 pa_sink_input_assert_ref(i);
644 pa_assert_ctl_context();
645 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
647 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, r, 0, NULL) == 0);
650 r[0] += i->get_latency(i);
653 *sink_latency = r[1];
658 /* Called from thread context */
659 void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
660 pa_bool_t do_volume_adj_here, need_volume_factor_sink;
661 pa_bool_t volume_is_norm;
663 size_t block_size_max_sink, block_size_max_sink_input;
666 pa_sink_input_assert_ref(i);
667 pa_sink_input_assert_io_context(i);
668 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
669 pa_assert(pa_frame_aligned(slength, &i->sink->sample_spec));
673 /* pa_log_debug("peek"); */
675 pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING ||
676 i->thread_info.state == PA_SINK_INPUT_CORKED ||
677 i->thread_info.state == PA_SINK_INPUT_DRAINED);
679 block_size_max_sink_input = i->thread_info.resampler ?
680 pa_resampler_max_block_size(i->thread_info.resampler) :
681 pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sample_spec);
683 block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sink->sample_spec);
685 /* Default buffer size */
687 slength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec);
689 if (slength > block_size_max_sink)
690 slength = block_size_max_sink;
692 if (i->thread_info.resampler) {
693 ilength = pa_resampler_request(i->thread_info.resampler, slength);
696 ilength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
700 if (ilength > block_size_max_sink_input)
701 ilength = block_size_max_sink_input;
703 /* If the channel maps of the sink and this stream differ, we need
704 * to adjust the volume *before* we resample. Otherwise we can do
705 * it after and leave it for the sink code */
707 do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map) || i->thread_info.ramp_info.is_ramping;
708 volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
709 need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);
711 while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
714 /* There's nothing in our render queue. We need to fill it up
715 * with data from the implementor. */
717 if (i->thread_info.state == PA_SINK_INPUT_CORKED ||
718 i->pop(i, ilength, &tchunk) < 0) {
720 /* OK, we're corked or the implementor didn't give us any
721 * data, so let's just hand out silence */
722 pa_atomic_store(&i->thread_info.drained, 1);
724 pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE, TRUE);
725 i->thread_info.playing_for = 0;
726 if (i->thread_info.underrun_for != (uint64_t) -1)
727 i->thread_info.underrun_for += ilength;
731 pa_atomic_store(&i->thread_info.drained, 0);
733 pa_assert(tchunk.length > 0);
734 pa_assert(tchunk.memblock);
736 i->thread_info.underrun_for = 0;
737 i->thread_info.playing_for += tchunk.length;
739 while (tchunk.length > 0) {
741 pa_bool_t nvfs = need_volume_factor_sink;
744 pa_memblock_ref(wchunk.memblock);
746 if (wchunk.length > block_size_max_sink_input)
747 wchunk.length = block_size_max_sink_input;
749 /* It might be necessary to adjust the volume here */
750 if (do_volume_adj_here && !volume_is_norm && !i->thread_info.ramp_info.is_ramping) {
751 pa_memchunk_make_writable(&wchunk, 0);
753 if (i->thread_info.muted) {
754 pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
757 } else if (!i->thread_info.resampler && nvfs) {
760 /* If we don't need a resampler we can merge the
761 * post and the pre volume adjustment into one */
763 pa_sw_cvolume_multiply(&v, &i->thread_info.soft_volume, &i->volume_factor_sink);
764 pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &v);
768 pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);
771 if (!i->thread_info.resampler) {
774 pa_memchunk_make_writable(&wchunk, 0);
775 pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
778 pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
781 pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
783 /* pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */
785 if (rchunk.memblock) {
788 pa_memchunk_make_writable(&rchunk, 0);
789 pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
792 pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
793 pa_memblock_unref(rchunk.memblock);
797 pa_memblock_unref(wchunk.memblock);
799 tchunk.index += wchunk.length;
800 tchunk.length -= wchunk.length;
803 pa_memblock_unref(tchunk.memblock);
806 pa_assert_se(pa_memblockq_peek(i->thread_info.render_memblockq, chunk) >= 0);
808 pa_assert(chunk->length > 0);
809 pa_assert(chunk->memblock);
811 /* pa_log_debug("peeking %lu", (unsigned long) chunk->length); */
813 if (chunk->length > block_size_max_sink)
814 chunk->length = block_size_max_sink;
816 ramping = i->thread_info.ramp_info.is_ramping;
818 sink_input_volume_ramping(i, chunk);
820 if (!i->thread_info.ramp_info.envelope_dead) {
821 i->thread_info.ramp_info.envelope_dying += chunk->length;
822 pa_log_debug("Envelope dying is %d, chunk length is %zu, dead thresholder is %lu\n", i->thread_info.ramp_info.envelope_dying,
824 i->sink->thread_info.max_rewind + pa_envelope_length(i->thread_info.ramp_info.envelope));
826 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))) {
827 pa_log_debug("RELEASE Envelop");
828 i->thread_info.ramp_info.envelope_dead = TRUE;
829 sink_input_release_envelope(i);
833 /* Let's see if we had to apply the volume adjustment ourselves,
834 * or if this can be done by the sink for us */
836 if (do_volume_adj_here)
837 /* We had different channel maps, so we already did the adjustment */
838 pa_cvolume_reset(volume, i->sink->sample_spec.channels);
839 else if (i->thread_info.muted)
840 /* We've both the same channel map, so let's have the sink do the adjustment for us*/
841 pa_cvolume_mute(volume, i->sink->sample_spec.channels);
843 *volume = i->thread_info.soft_volume;
846 /* Called from thread context */
847 void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
849 pa_sink_input_assert_ref(i);
850 pa_sink_input_assert_io_context(i);
851 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
852 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
853 pa_assert(nbytes > 0);
855 /* pa_log_debug("dropping %lu", (unsigned long) nbytes); */
857 pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
860 /* Called from thread context */
861 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
863 pa_bool_t called = FALSE;
865 pa_sink_input_assert_ref(i);
866 pa_sink_input_assert_io_context(i);
867 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
868 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
870 /* pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes); */
872 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
874 if (nbytes > 0 && !i->thread_info.dont_rewind_render) {
875 pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
876 pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
877 sink_input_rewind_ramp_info(i, nbytes);
880 if (i->thread_info.rewrite_nbytes == (size_t) -1) {
882 /* We were asked to drop all buffered data, and rerequest new
883 * data from implementor the next time push() is called */
885 pa_memblockq_flush_write(i->thread_info.render_memblockq, TRUE);
887 } else if (i->thread_info.rewrite_nbytes > 0) {
888 size_t max_rewrite, amount;
890 /* Calculate how much make sense to rewrite at most */
891 max_rewrite = nbytes + lbq;
893 /* Transform into local domain */
894 if (i->thread_info.resampler)
895 max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
897 /* Calculate how much of the rewinded data should actually be rewritten */
898 amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
901 pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
903 /* Tell the implementor */
904 if (i->process_rewind)
905 i->process_rewind(i, amount);
908 /* Convert back to to sink domain */
909 if (i->thread_info.resampler)
910 amount = pa_resampler_result(i->thread_info.resampler, amount);
913 /* Ok, now update the write pointer */
914 pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE, TRUE);
916 if (i->thread_info.rewrite_flush)
917 pa_memblockq_silence(i->thread_info.render_memblockq);
919 /* And reset the resampler */
920 if (i->thread_info.resampler)
921 pa_resampler_reset(i->thread_info.resampler);
926 if (i->process_rewind)
927 i->process_rewind(i, 0);
929 i->thread_info.rewrite_nbytes = 0;
930 i->thread_info.rewrite_flush = FALSE;
931 i->thread_info.dont_rewind_render = FALSE;
934 /* Called from thread context */
935 size_t pa_sink_input_get_max_rewind(pa_sink_input *i) {
936 pa_sink_input_assert_ref(i);
937 pa_sink_input_assert_io_context(i);
939 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_rewind) : i->sink->thread_info.max_rewind;
942 /* Called from thread context */
943 size_t pa_sink_input_get_max_request(pa_sink_input *i) {
944 pa_sink_input_assert_ref(i);
945 pa_sink_input_assert_io_context(i);
947 /* We're not verifying the status here, to allow this to be called
948 * in the state change handler between _INIT and _RUNNING */
950 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_request) : i->sink->thread_info.max_request;
953 /* Called from thread context */
954 void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
955 pa_sink_input_assert_ref(i);
956 pa_sink_input_assert_io_context(i);
957 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
958 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
960 pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
962 if (i->update_max_rewind)
963 i->update_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
966 /* Called from thread context */
967 void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
968 pa_sink_input_assert_ref(i);
969 pa_sink_input_assert_io_context(i);
970 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
971 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
973 if (i->update_max_request)
974 i->update_max_request(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
977 /* Called from thread context */
978 pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
979 pa_sink_input_assert_ref(i);
980 pa_sink_input_assert_io_context(i);
982 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
983 usec = i->sink->thread_info.fixed_latency;
985 if (usec != (pa_usec_t) -1)
986 usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
988 i->thread_info.requested_sink_latency = usec;
989 pa_sink_invalidate_requested_latency(i->sink, TRUE);
994 /* Called from main context */
995 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
996 pa_sink_input_assert_ref(i);
997 pa_assert_ctl_context();
999 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1000 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1004 /* If this sink input is not realized yet or we are being moved,
1005 * we have to touch the thread info data directly */
1008 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1009 usec = pa_sink_get_fixed_latency(i->sink);
1011 if (usec != (pa_usec_t) -1) {
1012 pa_usec_t min_latency, max_latency;
1013 pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
1014 usec = PA_CLAMP(usec, min_latency, max_latency);
1018 i->thread_info.requested_sink_latency = usec;
1023 /* Called from main context */
1024 pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
1025 pa_sink_input_assert_ref(i);
1026 pa_assert_ctl_context();
1028 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1030 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1034 /* If this sink input is not realized yet or we are being moved,
1035 * we have to touch the thread info data directly */
1037 return i->thread_info.requested_sink_latency;
1040 /* Called from main context */
1041 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {
1042 pa_sink_input_assert_ref(i);
1043 pa_assert_ctl_context();
1044 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1045 pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
1047 /* This basically calculates:
1049 * i->real_ratio := v
1050 * i->soft_volume := i->real_ratio * i->volume_factor */
1055 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
1057 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1058 /* We don't copy the data to the thread_info data. That's left for someone else to do */
1061 /* Called from main context */
1062 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute) {
1064 /* Do not allow for volume changes for non-audio types */
1065 if (i->flags & PA_SINK_INPUT_PASSTHROUGH)
1068 /* test ramping -> return pa_sink_input_set_volume_with_ramping(i, volume, save, absolute, 2000 * PA_USEC_PER_MSEC); */
1069 return pa_sink_input_set_volume_with_ramping(i, volume, save, absolute, 0);
1072 /* Called from main context */
1073 pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, pa_bool_t absolute) {
1074 pa_sink_input_assert_ref(i);
1075 pa_assert_ctl_context();
1076 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1078 if (absolute || !(i->sink->flags & PA_SINK_FLAT_VOLUME))
1079 *volume = i->volume;
1081 *volume = i->reference_ratio;
1086 /* Called from main context */
1087 void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save) {
1088 /* test ramping -> return pa_sink_input_set_mute_with_ramping(i, mute, save, 2000 * PA_USEC_PER_MSEC); */
1089 return pa_sink_input_set_mute_with_ramping(i, mute, save, 0);
1092 /* Called from main context */
1093 pa_bool_t pa_sink_input_get_mute(pa_sink_input *i) {
1094 pa_sink_input_assert_ref(i);
1095 pa_assert_ctl_context();
1096 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1101 /* Called from main thread */
1102 void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
1103 pa_sink_input_assert_ref(i);
1104 pa_assert_ctl_context();
1107 pa_proplist_update(i->proplist, mode, p);
1109 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1110 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1111 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1115 /* Called from main context */
1116 void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) {
1117 pa_sink_input_assert_ref(i);
1118 pa_assert_ctl_context();
1119 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1121 sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
1124 /* Called from main context */
1125 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
1126 pa_sink_input_assert_ref(i);
1127 pa_assert_ctl_context();
1128 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1129 pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE);
1131 if (i->sample_spec.rate == rate)
1134 i->sample_spec.rate = rate;
1136 pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
1138 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1142 /* Called from main context */
1143 void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
1145 pa_sink_input_assert_ref(i);
1146 pa_assert_ctl_context();
1148 if (!name && !pa_proplist_contains(i->proplist, PA_PROP_MEDIA_NAME))
1151 old = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME);
1153 if (old && name && pa_streq(old, name))
1157 pa_proplist_sets(i->proplist, PA_PROP_MEDIA_NAME, name);
1159 pa_proplist_unset(i->proplist, PA_PROP_MEDIA_NAME);
1161 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1162 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1163 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1167 /* Called from main context */
1168 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
1169 pa_sink_input_assert_ref(i);
1170 pa_assert_ctl_context();
1172 return i->actual_resample_method;
1175 /* Called from main context */
1176 pa_bool_t pa_sink_input_may_move(pa_sink_input *i) {
1177 pa_sink_input_assert_ref(i);
1178 pa_assert_ctl_context();
1179 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1181 if (i->flags & PA_SINK_INPUT_DONT_MOVE)
1184 if (i->sync_next || i->sync_prev) {
1185 pa_log_warn("Moving synchronized streams not supported.");
1192 /* Called from main context */
1193 pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
1194 pa_sink_input_assert_ref(i);
1195 pa_assert_ctl_context();
1196 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1197 pa_sink_assert_ref(dest);
1199 if (dest == i->sink)
1202 if (!pa_sink_input_may_move(i))
1205 if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
1206 pa_log_warn("Failed to move sink input: too many inputs per sink.");
1210 if (check_passthrough_connection(i->flags, dest) < 0)
1214 if (!i->may_move_to(i, dest))
1220 /* Called from main context */
1221 int pa_sink_input_start_move(pa_sink_input *i) {
1222 pa_source_output *o, *p = NULL;
1225 pa_sink_input_assert_ref(i);
1226 pa_assert_ctl_context();
1227 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1230 if (!pa_sink_input_may_move(i))
1231 return -PA_ERR_NOTSUPPORTED;
1233 if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
1236 /* Kill directly connected outputs */
1237 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
1239 pa_source_output_kill(o);
1242 pa_assert(pa_idxset_isempty(i->direct_outputs));
1244 pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
1246 if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
1247 pa_assert_se(i->sink->n_corked-- >= 1);
1249 if (i->sink->flags & PA_SINK_FLAT_VOLUME)
1250 /* We might need to update the sink's volume if we are in flat
1252 pa_sink_set_volume(i->sink, NULL, FALSE, FALSE);
1254 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
1256 pa_sink_update_status(i->sink);
1257 pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
1260 pa_sink_input_unref(i);
1265 /* Called from main context */
1266 int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
1267 pa_resampler *new_resampler;
1269 pa_sink_input_assert_ref(i);
1270 pa_assert_ctl_context();
1271 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1272 pa_assert(!i->sink);
1273 pa_sink_assert_ref(dest);
1275 if (!pa_sink_input_may_move_to(i, dest))
1276 return -PA_ERR_NOTSUPPORTED;
1278 if (i->thread_info.resampler &&
1279 pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &dest->sample_spec) &&
1280 pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &dest->channel_map))
1282 /* Try to reuse the old resampler if possible */
1283 new_resampler = i->thread_info.resampler;
1285 else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
1286 !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) ||
1287 !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) {
1289 /* Okey, we need a new resampler for the new sink */
1291 if (!(new_resampler = pa_resampler_new(
1293 &i->sample_spec, &i->channel_map,
1294 &dest->sample_spec, &dest->channel_map,
1295 i->requested_resample_method,
1296 ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
1297 ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
1298 (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
1299 pa_log_warn("Unsupported resampling operation.");
1300 return -PA_ERR_NOTSUPPORTED;
1303 new_resampler = NULL;
1309 i->save_sink = save;
1310 pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
1312 pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
1314 if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
1315 i->sink->n_corked++;
1317 /* Replace resampler and render queue */
1318 if (new_resampler != i->thread_info.resampler) {
1320 if (i->thread_info.resampler)
1321 pa_resampler_free(i->thread_info.resampler);
1322 i->thread_info.resampler = new_resampler;
1324 pa_memblockq_free(i->thread_info.render_memblockq);
1326 i->thread_info.render_memblockq = pa_memblockq_new(
1328 MEMBLOCKQ_MAXLENGTH,
1330 pa_frame_size(&i->sink->sample_spec),
1336 pa_sink_update_status(dest);
1338 if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
1339 pa_cvolume remapped;
1341 /* Make relative volumes absolute */
1342 remapped = dest->reference_volume;
1343 pa_cvolume_remap(&remapped, &dest->channel_map, &i->channel_map);
1344 pa_sw_cvolume_multiply(&i->volume, &i->reference_ratio, &remapped);
1346 /* We might need to update the sink's volume if we are in flat volume mode. */
1347 pa_sink_set_volume(i->sink, NULL, FALSE, i->save_volume);
1350 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
1352 pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
1354 /* Notify everyone */
1355 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
1357 if (i->volume_changed)
1358 i->volume_changed(i);
1360 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1365 /* Called from main context */
1366 void pa_sink_input_fail_move(pa_sink_input *i) {
1368 pa_sink_input_assert_ref(i);
1369 pa_assert_ctl_context();
1370 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1371 pa_assert(!i->sink);
1373 /* Check if someone wants this sink input? */
1374 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_STOP)
1380 pa_sink_input_kill(i);
1383 /* Called from main context */
1384 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
1387 pa_sink_input_assert_ref(i);
1388 pa_assert_ctl_context();
1389 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1391 pa_sink_assert_ref(dest);
1393 if (dest == i->sink)
1396 if (!pa_sink_input_may_move_to(i, dest))
1397 return -PA_ERR_NOTSUPPORTED;
1399 pa_sink_input_ref(i);
1401 if ((r = pa_sink_input_start_move(i)) < 0) {
1402 pa_sink_input_unref(i);
1406 if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
1407 pa_sink_input_fail_move(i);
1408 pa_sink_input_unref(i);
1412 pa_sink_input_unref(i);
1417 /* Called from IO thread context */
1418 void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
1419 pa_bool_t corking, uncorking;
1421 pa_sink_input_assert_ref(i);
1422 pa_sink_input_assert_io_context(i);
1424 if (state == i->thread_info.state)
1427 if ((state == PA_SINK_INPUT_DRAINED || state == PA_SINK_INPUT_RUNNING) &&
1428 !(i->thread_info.state == PA_SINK_INPUT_DRAINED || i->thread_info.state != PA_SINK_INPUT_RUNNING))
1429 pa_atomic_store(&i->thread_info.drained, 1);
1431 corking = state == PA_SINK_INPUT_CORKED && i->thread_info.state == PA_SINK_INPUT_RUNNING;
1432 uncorking = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
1434 if (i->state_change)
1435 i->state_change(i, state);
1437 i->thread_info.state = state;
1441 pa_log_debug("Requesting rewind due to corking");
1443 /* This will tell the implementing sink input driver to rewind
1444 * so that the unplayed already mixed data is not lost */
1445 pa_sink_input_request_rewind(i, 0, TRUE, TRUE, FALSE);
1447 } else if (uncorking) {
1449 i->thread_info.underrun_for = (uint64_t) -1;
1450 i->thread_info.playing_for = 0;
1452 pa_log_debug("Requesting rewind due to uncorking");
1454 /* OK, we're being uncorked. Make sure we're not rewound when
1455 * the hw buffer is remixed and request a remix. */
1456 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
1460 /* Called from thread context, except when it is not. */
1461 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1462 pa_sink_input *i = PA_SINK_INPUT(o);
1463 pa_sink_input_assert_ref(i);
1467 case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
1468 if (pa_atomic_load(&i->before_ramping_v))
1469 i->thread_info.future_soft_volume = i->soft_volume;
1471 if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
1472 if (!pa_atomic_load(&i->before_ramping_v))
1473 i->thread_info.soft_volume = i->soft_volume;
1474 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1478 case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
1479 if (pa_atomic_load(&i->before_ramping_m))
1480 i->thread_info.future_muted = i->muted;
1482 if (i->thread_info.muted != i->muted) {
1483 if (!pa_atomic_load(&i->before_ramping_m))
1484 i->thread_info.muted = i->muted;
1485 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1489 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1490 pa_usec_t *r = userdata;
1492 r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
1493 r[1] += pa_sink_get_latency_within_thread(i->sink);
1498 case PA_SINK_INPUT_MESSAGE_SET_RATE:
1500 i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
1501 pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
1505 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1506 pa_sink_input *ssync;
1508 pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
1510 for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
1511 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
1513 for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
1514 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
1519 case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
1520 pa_usec_t *usec = userdata;
1522 *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
1526 case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
1527 pa_usec_t *r = userdata;
1529 *r = i->thread_info.requested_sink_latency;
1533 case PA_SINK_INPUT_MESSAGE_SET_ENVELOPE: {
1534 if (!i->thread_info.ramp_info.envelope)
1535 i->thread_info.ramp_info.envelope = pa_envelope_new(&i->sink->sample_spec);
1537 if (i->thread_info.ramp_info.envelope && i->thread_info.ramp_info.item) {
1538 pa_envelope_remove(i->thread_info.ramp_info.envelope, i->thread_info.ramp_info.item);
1539 i->thread_info.ramp_info.item = NULL;
1542 i->thread_info.ramp_info.item = pa_envelope_add(i->thread_info.ramp_info.envelope, &i->using_def);
1543 i->thread_info.ramp_info.is_ramping = TRUE;
1544 i->thread_info.ramp_info.envelope_dead = FALSE;
1545 i->thread_info.ramp_info.envelope_dying = 0;
1547 if (i->thread_info.ramp_info.envelope)
1548 pa_envelope_restart(i->thread_info.ramp_info.envelope);
1554 return -PA_ERR_NOTIMPLEMENTED;
1557 /* Called from main thread */
1558 pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
1559 pa_sink_input_assert_ref(i);
1560 pa_assert_ctl_context();
1562 if (i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED)
1563 return pa_atomic_load(&i->thread_info.drained) ? PA_SINK_INPUT_DRAINED : PA_SINK_INPUT_RUNNING;
1568 /* Called from IO context */
1569 pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
1570 pa_sink_input_assert_ref(i);
1571 pa_sink_input_assert_io_context(i);
1573 if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
1574 return pa_memblockq_is_empty(i->thread_info.render_memblockq);
1579 /* Called from IO context */
1580 void pa_sink_input_request_rewind(
1582 size_t nbytes /* in our sample spec */,
1585 pa_bool_t dont_rewind_render) {
1589 /* If 'rewrite' is TRUE the sink is rewound as far as requested
1590 * and possible and the exact value of this is passed back the
1591 * implementor via process_rewind(). If 'flush' is also TRUE all
1592 * already rendered data is also dropped.
1594 * If 'rewrite' is FALSE the sink is rewound as far as requested
1595 * and possible and the already rendered data is dropped so that
1596 * in the next iteration we read new data from the
1597 * implementor. This implies 'flush' is TRUE. If
1598 * dont_rewind_render is TRUE then the render memblockq is not
1601 /* nbytes = 0 means maximum rewind request */
1603 pa_sink_input_assert_ref(i);
1604 pa_sink_input_assert_io_context(i);
1605 pa_assert(rewrite || flush);
1606 pa_assert(!dont_rewind_render || !rewrite);
1608 /* We don't take rewind requests while we are corked */
1609 if (i->thread_info.state == PA_SINK_INPUT_CORKED)
1612 nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
1614 /* pa_log_debug("request rewrite %zu", nbytes); */
1616 /* Calculate how much we can rewind locally without having to
1619 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
1623 /* Check if rewinding for the maximum is requested, and if so, fix up */
1626 /* Calculate maximum number of bytes that could be rewound in theory */
1627 nbytes = i->sink->thread_info.max_rewind + lbq;
1629 /* Transform from sink domain */
1630 if (i->thread_info.resampler)
1631 nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
1634 /* Remember how much we actually want to rewrite */
1635 if (i->thread_info.rewrite_nbytes != (size_t) -1) {
1637 /* Make sure to not overwrite over underruns */
1638 if (nbytes > i->thread_info.playing_for)
1639 nbytes = (size_t) i->thread_info.playing_for;
1641 i->thread_info.rewrite_nbytes = nbytes;
1643 i->thread_info.rewrite_nbytes = (size_t) -1;
1646 i->thread_info.rewrite_flush =
1647 i->thread_info.rewrite_flush ||
1648 (flush && i->thread_info.rewrite_nbytes != 0);
1650 i->thread_info.dont_rewind_render =
1651 i->thread_info.dont_rewind_render ||
1654 if (nbytes != (size_t) -1) {
1656 /* Transform to sink domain */
1657 if (i->thread_info.resampler)
1658 nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
1661 pa_sink_request_rewind(i->sink, nbytes - lbq);
1663 /* This call will make sure process_rewind() is called later */
1664 pa_sink_request_rewind(i->sink, 0);
1668 /* Called from main context */
1669 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
1670 pa_sink_input_assert_ref(i);
1671 pa_assert_ctl_context();
1674 /* FIXME: Shouldn't access resampler object from main context! */
1676 pa_silence_memchunk_get(
1677 &i->core->silence_cache,
1681 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
1686 /* Called from main context */
1687 void pa_sink_input_send_event(pa_sink_input *i, const char *event, pa_proplist *data) {
1688 pa_proplist *pl = NULL;
1689 pa_sink_input_send_event_hook_data hook_data;
1691 pa_sink_input_assert_ref(i);
1692 pa_assert_ctl_context();
1699 data = pl = pa_proplist_new();
1701 hook_data.sink_input = i;
1702 hook_data.data = data;
1703 hook_data.event = event;
1705 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
1708 i->send_event(i, event, data);
1712 pa_proplist_free(pl);
1715 /* Called from IO context */
1716 static void sink_input_volume_ramping(pa_sink_input* i, pa_memchunk* chunk) {
1719 pa_assert(chunk->memblock);
1720 pa_assert(i->thread_info.ramp_info.is_ramping);
1722 /* Volume is adjusted with ramping effect here */
1723 pa_envelope_apply(i->thread_info.ramp_info.envelope, chunk);
1725 if (pa_envelope_is_finished(i->thread_info.ramp_info.envelope)) {
1726 i->thread_info.ramp_info.is_ramping = FALSE;
1727 if (pa_atomic_load(&i->before_ramping_v)) {
1728 i->thread_info.soft_volume = i->thread_info.future_soft_volume;
1729 pa_atomic_store(&i->before_ramping_v, 0);
1731 else if (pa_atomic_load(&i->before_ramping_m)) {
1732 i->thread_info.muted = i->thread_info.future_muted;
1733 pa_atomic_store(&i->before_ramping_m, 0);
1739 * Called from main context
1740 * This function should be called inside pa_sink_input_set_volume_with_ramping
1741 * should be called after soft_volume of sink_input and sink are all adjusted
1743 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) {
1745 int32_t target_abs_vol, target_apply_vol, pre_apply_vol;
1748 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)));
1750 /* Calculation formula are target_abs_vol := i->soft_volume
1751 * target_apply_vol := lrint(pa_sw_volume_to_linear(target_abs_vol) * 0x10000)
1752 * pre_apply_vol := ( previous_virtual_volume / target_virtual_volume ) * target_apply_vol
1754 * Will do volume adjustment inside pa_sink_input_peek
1756 target_abs_vol = pa_cvolume_avg(&i->soft_volume);
1757 target_apply_vol = (int32_t) lrint(pa_sw_volume_to_linear(target_abs_vol) * 0x10000);
1758 pre_apply_vol = (int32_t) ((pa_sw_volume_to_linear(pre_virtual_volume) / pa_sw_volume_to_linear(target_virtual_volume)) * target_apply_vol);
1760 i->using_def.n_points = 2;
1761 i->using_def.points_x[0] = 0;
1762 i->using_def.points_x[1] = t;
1763 i->using_def.points_y.i[0] = pre_apply_vol;
1764 i->using_def.points_y.i[1] = target_apply_vol;
1765 i->using_def.points_y.f[0] = ((float) i->using_def.points_y.i[0]) /0x10000;
1766 i->using_def.points_y.f[1] = ((float) i->using_def.points_y.i[1]) /0x10000;
1768 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],
1769 i->using_def.points_y.i[1], i->using_def.points_y.f[1]);
1771 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_ENVELOPE, NULL, 0, NULL) == 0);
1774 /* Called from main context */
1775 static void sink_input_set_ramping_info_for_mute(pa_sink_input* i, pa_bool_t mute, pa_usec_t t) {
1780 i->using_def.n_points = 2;
1781 i->using_def.points_x[0] = 0;
1782 i->using_def.points_x[1] = t;
1783 cur_vol = (int32_t) lrint( pa_sw_volume_to_linear(pa_cvolume_avg(&i->soft_volume)) * 0x10000);
1786 i->using_def.points_y.i[0] = cur_vol;
1787 i->using_def.points_y.i[1] = 0;
1789 i->using_def.points_y.i[0] = 0;
1790 i->using_def.points_y.i[1] = cur_vol;
1793 i->using_def.points_y.f[0] = ((float) i->using_def.points_y.i[0]) /0x10000;
1794 i->using_def.points_y.f[1] = ((float) i->using_def.points_y.i[1]) /0x10000;
1796 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],
1797 i->using_def.points_y.i[1], i->using_def.points_y.f[1]);
1799 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_ENVELOPE, NULL, 0, NULL) == 0);
1802 /* Called from IO context */
1803 static void sink_input_release_envelope(pa_sink_input *i) {
1805 pa_assert(!i->thread_info.ramp_info.is_ramping);
1806 pa_assert(i->thread_info.ramp_info.envelope_dead);
1808 pa_envelope_free(i->thread_info.ramp_info.envelope);
1809 i->thread_info.ramp_info.envelope = NULL;
1810 i->thread_info.ramp_info.item = NULL;
1813 /* Called from IO context */
1814 static void sink_input_rewind_ramp_info(pa_sink_input *i, size_t nbytes) {
1817 if (!i->thread_info.ramp_info.envelope_dead) {
1818 int32_t envelope_length;
1820 pa_assert(i->thread_info.ramp_info.envelope);
1822 envelope_length = pa_envelope_length(i->thread_info.ramp_info.envelope);
1824 if (i->thread_info.ramp_info.envelope_dying > envelope_length) {
1825 if ((int32_t) (i->thread_info.ramp_info.envelope_dying - nbytes) < envelope_length) {
1826 pa_log_debug("Envelope Become Alive");
1827 pa_envelope_rewind(i->thread_info.ramp_info.envelope, envelope_length - (i->thread_info.ramp_info.envelope_dying - nbytes));
1828 i->thread_info.ramp_info.is_ramping = TRUE;
1830 } else if (i->thread_info.ramp_info.envelope_dying < envelope_length) {
1831 if ((i->thread_info.ramp_info.envelope_dying - (ssize_t) nbytes) <= 0) {
1832 pa_log_debug("Envelope Restart");
1833 pa_envelope_restart(i->thread_info.ramp_info.envelope);
1836 pa_log_debug("Envelope Simple Rewind");
1837 pa_envelope_rewind(i->thread_info.ramp_info.envelope, nbytes);
1841 i->thread_info.ramp_info.envelope_dying -= nbytes;
1842 if (i->thread_info.ramp_info.envelope_dying <= 0)
1843 i->thread_info.ramp_info.envelope_dying = 0;
1847 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){
1849 pa_volume_t previous_virtual_volume, target_virtual_volume;
1851 pa_sink_input_assert_ref(i);
1852 pa_assert_ctl_context();
1853 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1855 pa_assert(pa_cvolume_valid(volume));
1856 pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
1858 if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) {
1859 v = i->sink->reference_volume;
1860 pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
1862 if (pa_cvolume_compatible(volume, &i->sample_spec))
1863 volume = pa_sw_cvolume_multiply(&v, &v, volume);
1865 volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume));
1868 if (!pa_cvolume_compatible(volume, &i->sample_spec)) {
1870 volume = pa_cvolume_scale(&v, pa_cvolume_max(volume));
1874 if (pa_cvolume_equal(volume, &i->volume)) {
1875 i->save_volume = i->save_volume || save;
1879 previous_virtual_volume = pa_cvolume_avg(&i->volume);
1880 target_virtual_volume = pa_cvolume_avg(volume);
1882 if (t > 0 && target_virtual_volume > 0)
1883 pa_log_debug("SetVolumeWithRamping: Virtual Volume From %u=%f to %u=%f\n", previous_virtual_volume, pa_sw_volume_to_linear(previous_virtual_volume),
1884 target_virtual_volume, pa_sw_volume_to_linear(target_virtual_volume));
1886 i->volume = *volume;
1887 i->save_volume = save;
1889 /* Set this flag before the following code modify i->thread_info.soft_volume */
1890 if (t > 0 && target_virtual_volume > 0)
1891 pa_atomic_store(&i->before_ramping_v, 1);
1893 if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
1894 /* We are in flat volume mode, so let's update all sink input
1895 * volumes and update the flat volume of the sink */
1897 pa_sink_set_volume(i->sink, NULL, TRUE, save);
1900 /* OK, we are in normal volume mode. The volume only affects
1902 set_real_ratio(i, volume);
1904 /* Copy the new soft_volume to the thread_info struct */
1905 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1908 if (t > 0 && target_virtual_volume > 0)
1909 sink_input_set_ramping_info(i, previous_virtual_volume, target_virtual_volume, t);
1911 /* The volume changed, let's tell people so */
1912 if (i->volume_changed)
1913 i->volume_changed(i);
1915 /* The virtual volume changed, let's tell people so */
1916 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1919 void pa_sink_input_set_mute_with_ramping(pa_sink_input *i, pa_bool_t mute, pa_bool_t save, pa_usec_t t){
1921 pa_sink_input_assert_ref(i);
1922 pa_assert_ctl_context();
1923 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1925 if (!i->muted == !mute) {
1926 i->save_muted = i->save_muted || mute;
1931 i->save_muted = save;
1933 /* Set this flag before the following code modify i->thread_info.muted, otherwise distortion will be heard */
1935 pa_atomic_store(&i->before_ramping_m, 1);
1937 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
1940 sink_input_set_ramping_info_for_mute(i, mute, t);
1942 /* The mute status changed, let's tell people so */
1943 if (i->mute_changed)
1946 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);