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>
34 #include <pulse/internal.h>
36 #include <pulsecore/sample-util.h>
37 #include <pulsecore/core-subscribe.h>
38 #include <pulsecore/log.h>
39 #include <pulsecore/play-memblockq.h>
40 #include <pulsecore/namereg.h>
41 #include <pulsecore/core-util.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);
53 static int check_passthrough_connection(pa_bool_t passthrough, pa_sink *dest) {
54 if (pa_sink_is_passthrough(dest)) {
55 pa_log_warn("Sink is already connected to PASSTHROUGH input");
59 /* If current input(s) exist, check new input is not PASSTHROUGH */
60 if (pa_idxset_size(dest->inputs) > 0 && passthrough) {
61 pa_log_warn("Sink is already connected, cannot accept new PASSTHROUGH INPUT");
68 pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) {
72 data->resample_method = PA_RESAMPLER_INVALID;
73 data->proplist = pa_proplist_new();
74 data->volume_writable = TRUE;
79 void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec) {
82 if ((data->sample_spec_is_set = !!spec))
83 data->sample_spec = *spec;
86 void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map) {
89 if ((data->channel_map_is_set = !!map))
90 data->channel_map = *map;
93 pa_bool_t pa_sink_input_new_data_is_passthrough(pa_sink_input_new_data *data) {
96 if (PA_LIKELY(data->format) && PA_UNLIKELY(!pa_format_info_is_pcm(data->format)))
99 if (PA_UNLIKELY(data->flags & PA_SINK_INPUT_PASSTHROUGH))
105 void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) {
107 pa_assert(data->volume_writable);
109 if ((data->volume_is_set = !!volume))
110 data->volume = *volume;
113 void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
115 pa_assert(volume_factor);
117 if (data->volume_factor_is_set)
118 pa_sw_cvolume_multiply(&data->volume_factor, &data->volume_factor, volume_factor);
120 data->volume_factor_is_set = TRUE;
121 data->volume_factor = *volume_factor;
125 void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
127 pa_assert(volume_factor);
129 if (data->volume_factor_sink_is_set)
130 pa_sw_cvolume_multiply(&data->volume_factor_sink, &data->volume_factor_sink, volume_factor);
132 data->volume_factor_sink_is_set = TRUE;
133 data->volume_factor_sink = *volume_factor;
137 void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
140 data->muted_is_set = TRUE;
141 data->muted = !!mute;
144 pa_bool_t pa_sink_input_new_data_set_sink(pa_sink_input_new_data *data, pa_sink *s, pa_bool_t save) {
145 pa_bool_t ret = TRUE;
146 pa_idxset *formats = NULL;
151 if (!data->req_formats) {
152 /* We're not working with the extended API */
154 data->save_sink = save;
156 /* Extended API: let's see if this sink supports the formats the client can provide */
157 formats = pa_sink_check_formats(s, data->req_formats);
159 if (formats && !pa_idxset_isempty(formats)) {
160 /* Sink supports at least one of the requested formats */
162 data->save_sink = save;
163 if (data->nego_formats)
164 pa_idxset_free(data->nego_formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
165 data->nego_formats = formats;
167 /* Sink doesn't support any of the formats requested by the client */
169 pa_idxset_free(formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
177 pa_bool_t pa_sink_input_new_data_set_formats(pa_sink_input_new_data *data, pa_idxset *formats) {
181 if (data->req_formats)
182 pa_idxset_free(formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
184 data->req_formats = formats;
187 /* Trigger format negotiation */
188 return pa_sink_input_new_data_set_sink(data, data->sink, data->save_sink);
194 void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
197 if (data->req_formats)
198 pa_idxset_free(data->req_formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
200 if (data->nego_formats)
201 pa_idxset_free(data->nego_formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
204 pa_format_info_free(data->format);
206 pa_proplist_free(data->proplist);
209 /* Called from main context */
210 static void reset_callbacks(pa_sink_input *i) {
214 i->process_rewind = NULL;
215 i->update_max_rewind = NULL;
216 i->update_max_request = NULL;
217 i->update_sink_requested_latency = NULL;
218 i->update_sink_latency_range = NULL;
219 i->update_sink_fixed_latency = NULL;
223 i->suspend_within_thread = NULL;
226 i->get_latency = NULL;
227 i->state_change = NULL;
228 i->may_move_to = NULL;
229 i->send_event = NULL;
230 i->volume_changed = NULL;
231 i->mute_changed = NULL;
234 /* Called from main context */
235 int pa_sink_input_new(
238 pa_sink_input_new_data *data) {
241 pa_resampler *resampler = NULL;
242 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
243 pa_channel_map original_cm;
252 pa_assert_ctl_context();
255 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
257 if (data->origin_sink && (data->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
258 data->volume_writable = FALSE;
260 if (!data->req_formats) {
261 /* From this point on, we want to work only with formats, and get back
262 * to using the sample spec and channel map after all decisions w.r.t.
263 * routing are complete. */
264 pa_idxset *tmp = pa_idxset_new(NULL, NULL);
265 pa_format_info *f = pa_format_info_from_sample_spec(&data->sample_spec,
266 data->channel_map_is_set ? &data->channel_map : NULL);
267 pa_idxset_put(tmp, f, NULL);
268 pa_sink_input_new_data_set_formats(data, tmp);
271 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0)
274 pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
277 pa_sink *sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK);
278 pa_return_val_if_fail(sink, -PA_ERR_NOENTITY);
279 pa_sink_input_new_data_set_sink(data, sink, FALSE);
281 /* Routing's done, we have a sink. Now let's fix the format and set up the
284 /* If something didn't pick a format for us, pick the top-most format since
285 * we assume this is sorted in priority order */
286 if (!data->format && data->nego_formats && !pa_idxset_isempty(data->nego_formats))
287 data->format = pa_format_info_copy(pa_idxset_first(data->nego_formats, NULL));
289 pa_return_val_if_fail(data->format, -PA_ERR_NOTSUPPORTED);
291 /* Now populate the sample spec and format according to the final
292 * format that we've negotiated */
293 if (PA_LIKELY(data->format->encoding == PA_ENCODING_PCM)) {
294 pa_return_val_if_fail(pa_format_info_to_sample_spec(data->format, &ss, &map), -PA_ERR_INVALID);
295 pa_sink_input_new_data_set_sample_spec(data, &ss);
296 if (pa_channel_map_valid(&map))
297 pa_sink_input_new_data_set_channel_map(data, &map);
299 pa_return_val_if_fail(pa_format_info_to_sample_spec_fake(data->format, &ss), -PA_ERR_INVALID);
300 pa_sink_input_new_data_set_sample_spec(data, &ss);
303 pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)), -PA_ERR_BADSTATE);
304 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);
306 r = check_passthrough_connection(pa_sink_input_new_data_is_passthrough(data), data->sink);
310 if (!data->sample_spec_is_set)
311 data->sample_spec = data->sink->sample_spec;
313 pa_return_val_if_fail(pa_sample_spec_valid(&data->sample_spec), -PA_ERR_INVALID);
315 if (!data->channel_map_is_set) {
316 if (pa_channel_map_compatible(&data->sink->channel_map, &data->sample_spec))
317 data->channel_map = data->sink->channel_map;
319 pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
322 pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
324 /* Don't restore (or save) stream volume for passthrough streams */
325 if (!pa_format_info_is_pcm(data->format)) {
326 data->volume_is_set = FALSE;
327 data->volume_factor_is_set = FALSE;
330 if (!data->volume_is_set) {
331 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
332 data->volume_is_absolute = FALSE;
333 data->save_volume = FALSE;
336 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec), -PA_ERR_INVALID);
338 if (!data->volume_factor_is_set)
339 pa_cvolume_reset(&data->volume_factor, data->sample_spec.channels);
341 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor, &data->sample_spec), -PA_ERR_INVALID);
343 if (!data->volume_factor_sink_is_set)
344 pa_cvolume_reset(&data->volume_factor_sink, data->sink->sample_spec.channels);
346 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor_sink, &data->sink->sample_spec), -PA_ERR_INVALID);
348 if (!data->muted_is_set)
351 if (data->flags & PA_SINK_INPUT_FIX_FORMAT)
352 data->sample_spec.format = data->sink->sample_spec.format;
354 if (data->flags & PA_SINK_INPUT_FIX_RATE)
355 data->sample_spec.rate = data->sink->sample_spec.rate;
357 original_cm = data->channel_map;
359 if (data->flags & PA_SINK_INPUT_FIX_CHANNELS) {
360 data->sample_spec.channels = data->sink->sample_spec.channels;
361 data->channel_map = data->sink->channel_map;
364 pa_assert(pa_sample_spec_valid(&data->sample_spec));
365 pa_assert(pa_channel_map_valid(&data->channel_map));
367 /* Due to the fixing of the sample spec the volume might not match anymore */
368 pa_cvolume_remap(&data->volume, &original_cm, &data->channel_map);
370 if (data->resample_method == PA_RESAMPLER_INVALID)
371 data->resample_method = core->resample_method;
373 pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
375 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
378 if ((data->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND) &&
379 pa_sink_get_state(data->sink) == PA_SINK_SUSPENDED) {
380 pa_log_warn("Failed to create sink input: sink is suspended.");
381 return -PA_ERR_BADSTATE;
384 if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) {
385 pa_log_warn("Failed to create sink input: too many inputs per sink.");
386 return -PA_ERR_TOOLARGE;
389 if ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
390 !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) ||
391 !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) {
393 /* Note: for passthrough content we need to adjust the output rate to that of the current sink-input */
394 if (!pa_sink_input_new_data_is_passthrough(data)) /* no resampler for passthrough content */
395 if (!(resampler = pa_resampler_new(
397 &data->sample_spec, &data->channel_map,
398 &data->sink->sample_spec, &data->sink->channel_map,
399 data->resample_method,
400 ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
401 ((data->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
402 (core->disable_remixing || (data->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
403 (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
404 pa_log_warn("Unsupported resampling operation.");
405 return -PA_ERR_NOTSUPPORTED;
409 i = pa_msgobject_new(pa_sink_input);
410 i->parent.parent.free = sink_input_free;
411 i->parent.process_msg = pa_sink_input_process_msg;
414 i->state = PA_SINK_INPUT_INIT;
415 i->flags = data->flags;
416 i->proplist = pa_proplist_copy(data->proplist);
417 i->driver = pa_xstrdup(pa_path_get_filename(data->driver));
418 i->module = data->module;
419 i->sink = data->sink;
420 i->origin_sink = data->origin_sink;
421 i->client = data->client;
423 i->requested_resample_method = data->resample_method;
424 i->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID;
425 i->sample_spec = data->sample_spec;
426 i->channel_map = data->channel_map;
427 i->format = pa_format_info_copy(data->format);
429 if (!data->volume_is_absolute && pa_sink_flat_volume_enabled(i->sink)) {
432 /* When the 'absolute' bool is not set then we'll treat the volume
433 * as relative to the sink volume even in flat volume mode */
434 remapped = data->sink->reference_volume;
435 pa_cvolume_remap(&remapped, &data->sink->channel_map, &data->channel_map);
436 pa_sw_cvolume_multiply(&i->volume, &data->volume, &remapped);
438 i->volume = data->volume;
440 i->volume_factor = data->volume_factor;
441 i->volume_factor_sink = data->volume_factor_sink;
442 i->real_ratio = i->reference_ratio = data->volume;
443 pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
444 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
445 i->volume_writable = data->volume_writable;
446 i->save_volume = data->save_volume;
447 i->save_sink = data->save_sink;
448 i->save_muted = data->save_muted;
450 i->muted = data->muted;
452 if (data->sync_base) {
453 i->sync_next = data->sync_base->sync_next;
454 i->sync_prev = data->sync_base;
456 if (data->sync_base->sync_next)
457 data->sync_base->sync_next->sync_prev = i;
458 data->sync_base->sync_next = i;
460 i->sync_next = i->sync_prev = NULL;
462 i->direct_outputs = pa_idxset_new(NULL, NULL);
467 i->thread_info.state = i->state;
468 i->thread_info.attached = FALSE;
469 pa_atomic_store(&i->thread_info.drained, 1);
470 i->thread_info.sample_spec = i->sample_spec;
471 i->thread_info.resampler = resampler;
472 i->thread_info.soft_volume = i->soft_volume;
473 i->thread_info.muted = i->muted;
474 i->thread_info.requested_sink_latency = (pa_usec_t) -1;
475 i->thread_info.rewrite_nbytes = 0;
476 i->thread_info.rewrite_flush = FALSE;
477 i->thread_info.dont_rewind_render = FALSE;
478 i->thread_info.underrun_for = (uint64_t) -1;
479 i->thread_info.playing_for = 0;
480 i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
482 i->thread_info.render_memblockq = pa_memblockq_new(
486 pa_frame_size(&i->sink->sample_spec),
492 pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
493 pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0);
496 pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
498 pt = pa_proplist_to_string_sep(i->proplist, "\n ");
499 pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
501 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
503 pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
504 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
508 /* Don't forget to call pa_sink_input_put! */
514 /* Called from main context */
515 static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
517 pa_assert_ctl_context();
522 if (i->state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED)
523 pa_assert_se(i->sink->n_corked -- >= 1);
524 else if (i->state != PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_CORKED)
528 /* Called from main context */
529 static void sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
530 pa_sink_input *ssync;
532 pa_assert_ctl_context();
534 if (state == PA_SINK_INPUT_DRAINED)
535 state = PA_SINK_INPUT_RUNNING;
537 if (i->state == state)
540 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);
542 update_n_corked(i, state);
545 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev) {
546 update_n_corked(ssync, state);
547 ssync->state = state;
549 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) {
550 update_n_corked(ssync, state);
551 ssync->state = state;
554 if (state != PA_SINK_INPUT_UNLINKED) {
555 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
557 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev)
558 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
560 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next)
561 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
563 if (PA_SINK_INPUT_IS_LINKED(state))
564 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
567 pa_sink_update_status(i->sink);
570 /* Called from main context */
571 void pa_sink_input_unlink(pa_sink_input *i) {
573 pa_source_output *o, *p = NULL;
576 pa_assert_ctl_context();
578 /* See pa_sink_unlink() for a couple of comments how this function
581 pa_sink_input_ref(i);
583 linked = PA_SINK_INPUT_IS_LINKED(i->state);
586 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
589 i->sync_prev->sync_next = i->sync_next;
591 i->sync_next->sync_prev = i->sync_prev;
593 i->sync_prev = i->sync_next = NULL;
595 pa_idxset_remove_by_data(i->core->sink_inputs, i, NULL);
598 if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
599 pa_sink_input_unref(i);
602 pa_idxset_remove_by_data(i->client->sink_inputs, i, NULL);
604 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
606 pa_source_output_kill(o);
610 update_n_corked(i, PA_SINK_INPUT_UNLINKED);
611 i->state = PA_SINK_INPUT_UNLINKED;
613 if (linked && i->sink) {
614 /* We might need to update the sink's volume if we are in flat volume mode. */
615 if (pa_sink_flat_volume_enabled(i->sink))
616 pa_sink_set_volume(i->sink, NULL, FALSE, FALSE);
618 if (i->sink->asyncmsgq)
619 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL) == 0);
621 /* We suspend the monitor if there was a passthrough sink, unsuspend now if required */
622 if (pa_sink_input_is_passthrough(i) && i->sink->monitor_source)
623 pa_source_suspend(i->sink->monitor_source, FALSE, PA_SUSPEND_PASSTHROUGH);
629 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
630 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
634 pa_sink_update_status(i->sink);
638 pa_core_maybe_vacuum(i->core);
640 pa_sink_input_unref(i);
643 /* Called from main context */
644 static void sink_input_free(pa_object *o) {
645 pa_sink_input* i = PA_SINK_INPUT(o);
648 pa_assert_ctl_context();
649 pa_assert(pa_sink_input_refcnt(i) == 0);
651 if (PA_SINK_INPUT_IS_LINKED(i->state))
652 pa_sink_input_unlink(i);
654 pa_log_info("Freeing input %u \"%s\"", i->index, pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)));
656 /* Side note: this function must be able to destruct properly any
657 * kind of sink input in any state, even those which are
658 * "half-moved" or are connected to sinks that have no asyncmsgq
659 * and are hence half-destructed themselves! */
661 if (i->thread_info.render_memblockq)
662 pa_memblockq_free(i->thread_info.render_memblockq);
664 if (i->thread_info.resampler)
665 pa_resampler_free(i->thread_info.resampler);
668 pa_format_info_free(i->format);
671 pa_proplist_free(i->proplist);
673 if (i->direct_outputs)
674 pa_idxset_free(i->direct_outputs, NULL, NULL);
676 if (i->thread_info.direct_outputs)
677 pa_hashmap_free(i->thread_info.direct_outputs, NULL, NULL);
683 /* Called from main context */
684 void pa_sink_input_put(pa_sink_input *i) {
685 pa_sink_input_state_t state;
687 pa_sink_input_assert_ref(i);
688 pa_assert_ctl_context();
690 pa_assert(i->state == PA_SINK_INPUT_INIT);
692 /* The following fields must be initialized properly */
694 pa_assert(i->process_rewind);
697 state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
699 update_n_corked(i, state);
702 /* We might need to update the sink's volume if we are in flat volume mode. */
703 if (pa_sink_flat_volume_enabled(i->sink))
704 pa_sink_set_volume(i->sink, NULL, FALSE, i->save_volume);
706 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
707 pa_assert(pa_cvolume_is_norm(&i->volume));
708 pa_assert(pa_cvolume_is_norm(&i->reference_ratio));
711 set_real_ratio(i, &i->volume);
714 /* If we're entering passthrough mode, disable the monitor */
715 if (pa_sink_input_is_passthrough(i) && i->sink->monitor_source)
716 pa_source_suspend(i->sink->monitor_source, TRUE, PA_SUSPEND_PASSTHROUGH);
718 i->thread_info.soft_volume = i->soft_volume;
719 i->thread_info.muted = i->muted;
721 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0);
723 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
724 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
726 pa_sink_update_status(i->sink);
729 /* Called from main context */
730 void pa_sink_input_kill(pa_sink_input*i) {
731 pa_sink_input_assert_ref(i);
732 pa_assert_ctl_context();
733 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
738 /* Called from main context */
739 pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
740 pa_usec_t r[2] = { 0, 0 };
742 pa_sink_input_assert_ref(i);
743 pa_assert_ctl_context();
744 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
746 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, r, 0, NULL) == 0);
749 r[0] += i->get_latency(i);
752 *sink_latency = r[1];
757 /* Called from thread context */
758 void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
759 pa_bool_t do_volume_adj_here, need_volume_factor_sink;
760 pa_bool_t volume_is_norm;
761 size_t block_size_max_sink, block_size_max_sink_input;
764 pa_sink_input_assert_ref(i);
765 pa_sink_input_assert_io_context(i);
766 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
767 pa_assert(pa_frame_aligned(slength, &i->sink->sample_spec));
771 /* pa_log_debug("peek"); */
773 pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING ||
774 i->thread_info.state == PA_SINK_INPUT_CORKED ||
775 i->thread_info.state == PA_SINK_INPUT_DRAINED);
777 block_size_max_sink_input = i->thread_info.resampler ?
778 pa_resampler_max_block_size(i->thread_info.resampler) :
779 pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sample_spec);
781 block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sink->sample_spec);
783 /* Default buffer size */
785 slength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec);
787 if (slength > block_size_max_sink)
788 slength = block_size_max_sink;
790 if (i->thread_info.resampler) {
791 ilength = pa_resampler_request(i->thread_info.resampler, slength);
794 ilength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
798 if (ilength > block_size_max_sink_input)
799 ilength = block_size_max_sink_input;
801 /* If the channel maps of the sink and this stream differ, we need
802 * to adjust the volume *before* we resample. Otherwise we can do
803 * it after and leave it for the sink code */
805 do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
806 volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
807 need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);
809 while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
812 /* There's nothing in our render queue. We need to fill it up
813 * with data from the implementor. */
815 if (i->thread_info.state == PA_SINK_INPUT_CORKED ||
816 i->pop(i, ilength, &tchunk) < 0) {
818 /* OK, we're corked or the implementor didn't give us any
819 * data, so let's just hand out silence */
820 pa_atomic_store(&i->thread_info.drained, 1);
822 pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE, TRUE);
823 i->thread_info.playing_for = 0;
824 if (i->thread_info.underrun_for != (uint64_t) -1)
825 i->thread_info.underrun_for += ilength;
829 pa_atomic_store(&i->thread_info.drained, 0);
831 pa_assert(tchunk.length > 0);
832 pa_assert(tchunk.memblock);
834 i->thread_info.underrun_for = 0;
835 i->thread_info.playing_for += tchunk.length;
837 while (tchunk.length > 0) {
839 pa_bool_t nvfs = need_volume_factor_sink;
842 pa_memblock_ref(wchunk.memblock);
844 if (wchunk.length > block_size_max_sink_input)
845 wchunk.length = block_size_max_sink_input;
847 /* It might be necessary to adjust the volume here */
848 if (do_volume_adj_here && !volume_is_norm) {
849 pa_memchunk_make_writable(&wchunk, 0);
851 if (i->thread_info.muted) {
852 pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
855 } else if (!i->thread_info.resampler && nvfs) {
858 /* If we don't need a resampler we can merge the
859 * post and the pre volume adjustment into one */
861 pa_sw_cvolume_multiply(&v, &i->thread_info.soft_volume, &i->volume_factor_sink);
862 pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &v);
866 pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);
869 if (!i->thread_info.resampler) {
872 pa_memchunk_make_writable(&wchunk, 0);
873 pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
876 pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
879 pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
881 /* pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */
883 if (rchunk.memblock) {
886 pa_memchunk_make_writable(&rchunk, 0);
887 pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
890 pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
891 pa_memblock_unref(rchunk.memblock);
895 pa_memblock_unref(wchunk.memblock);
897 tchunk.index += wchunk.length;
898 tchunk.length -= wchunk.length;
901 pa_memblock_unref(tchunk.memblock);
904 pa_assert_se(pa_memblockq_peek(i->thread_info.render_memblockq, chunk) >= 0);
906 pa_assert(chunk->length > 0);
907 pa_assert(chunk->memblock);
909 /* pa_log_debug("peeking %lu", (unsigned long) chunk->length); */
911 if (chunk->length > block_size_max_sink)
912 chunk->length = block_size_max_sink;
914 /* Let's see if we had to apply the volume adjustment ourselves,
915 * or if this can be done by the sink for us */
917 if (do_volume_adj_here)
918 /* We had different channel maps, so we already did the adjustment */
919 pa_cvolume_reset(volume, i->sink->sample_spec.channels);
920 else if (i->thread_info.muted)
921 /* We've both the same channel map, so let's have the sink do the adjustment for us*/
922 pa_cvolume_mute(volume, i->sink->sample_spec.channels);
924 *volume = i->thread_info.soft_volume;
927 /* Called from thread context */
928 void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
930 pa_sink_input_assert_ref(i);
931 pa_sink_input_assert_io_context(i);
932 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
933 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
934 pa_assert(nbytes > 0);
936 /* pa_log_debug("dropping %lu", (unsigned long) nbytes); */
938 pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
941 /* Called from thread context */
942 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
944 pa_bool_t called = FALSE;
946 pa_sink_input_assert_ref(i);
947 pa_sink_input_assert_io_context(i);
948 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
949 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
951 /* pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes); */
953 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
955 if (nbytes > 0 && !i->thread_info.dont_rewind_render) {
956 pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
957 pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
960 if (i->thread_info.rewrite_nbytes == (size_t) -1) {
962 /* We were asked to drop all buffered data, and rerequest new
963 * data from implementor the next time push() is called */
965 pa_memblockq_flush_write(i->thread_info.render_memblockq, TRUE);
967 } else if (i->thread_info.rewrite_nbytes > 0) {
968 size_t max_rewrite, amount;
970 /* Calculate how much make sense to rewrite at most */
971 max_rewrite = nbytes + lbq;
973 /* Transform into local domain */
974 if (i->thread_info.resampler)
975 max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
977 /* Calculate how much of the rewinded data should actually be rewritten */
978 amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
981 pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
983 /* Tell the implementor */
984 if (i->process_rewind)
985 i->process_rewind(i, amount);
988 /* Convert back to to sink domain */
989 if (i->thread_info.resampler)
990 amount = pa_resampler_result(i->thread_info.resampler, amount);
993 /* Ok, now update the write pointer */
994 pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE, TRUE);
996 if (i->thread_info.rewrite_flush)
997 pa_memblockq_silence(i->thread_info.render_memblockq);
999 /* And reset the resampler */
1000 if (i->thread_info.resampler)
1001 pa_resampler_reset(i->thread_info.resampler);
1006 if (i->process_rewind)
1007 i->process_rewind(i, 0);
1009 i->thread_info.rewrite_nbytes = 0;
1010 i->thread_info.rewrite_flush = FALSE;
1011 i->thread_info.dont_rewind_render = FALSE;
1014 /* Called from thread context */
1015 size_t pa_sink_input_get_max_rewind(pa_sink_input *i) {
1016 pa_sink_input_assert_ref(i);
1017 pa_sink_input_assert_io_context(i);
1019 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_rewind) : i->sink->thread_info.max_rewind;
1022 /* Called from thread context */
1023 size_t pa_sink_input_get_max_request(pa_sink_input *i) {
1024 pa_sink_input_assert_ref(i);
1025 pa_sink_input_assert_io_context(i);
1027 /* We're not verifying the status here, to allow this to be called
1028 * in the state change handler between _INIT and _RUNNING */
1030 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_request) : i->sink->thread_info.max_request;
1033 /* Called from thread context */
1034 void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
1035 pa_sink_input_assert_ref(i);
1036 pa_sink_input_assert_io_context(i);
1037 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1038 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1040 pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
1042 if (i->update_max_rewind)
1043 i->update_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
1046 /* Called from thread context */
1047 void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
1048 pa_sink_input_assert_ref(i);
1049 pa_sink_input_assert_io_context(i);
1050 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1051 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1053 if (i->update_max_request)
1054 i->update_max_request(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
1057 /* Called from thread context */
1058 pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
1059 pa_sink_input_assert_ref(i);
1060 pa_sink_input_assert_io_context(i);
1062 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1063 usec = i->sink->thread_info.fixed_latency;
1065 if (usec != (pa_usec_t) -1)
1066 usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
1068 i->thread_info.requested_sink_latency = usec;
1069 pa_sink_invalidate_requested_latency(i->sink, TRUE);
1074 /* Called from main context */
1075 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
1076 pa_sink_input_assert_ref(i);
1077 pa_assert_ctl_context();
1079 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1080 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1084 /* If this sink input is not realized yet or we are being moved,
1085 * we have to touch the thread info data directly */
1088 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1089 usec = pa_sink_get_fixed_latency(i->sink);
1091 if (usec != (pa_usec_t) -1) {
1092 pa_usec_t min_latency, max_latency;
1093 pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
1094 usec = PA_CLAMP(usec, min_latency, max_latency);
1098 i->thread_info.requested_sink_latency = usec;
1103 /* Called from main context */
1104 pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
1105 pa_sink_input_assert_ref(i);
1106 pa_assert_ctl_context();
1108 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1110 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1114 /* If this sink input is not realized yet or we are being moved,
1115 * we have to touch the thread info data directly */
1117 return i->thread_info.requested_sink_latency;
1120 /* Called from main context */
1121 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute) {
1124 pa_sink_input_assert_ref(i);
1125 pa_assert_ctl_context();
1126 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1128 pa_assert(pa_cvolume_valid(volume));
1129 pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
1130 pa_assert(i->volume_writable);
1132 if (!absolute && pa_sink_flat_volume_enabled(i->sink)) {
1133 v = i->sink->reference_volume;
1134 pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
1136 if (pa_cvolume_compatible(volume, &i->sample_spec))
1137 volume = pa_sw_cvolume_multiply(&v, &v, volume);
1139 volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume));
1141 if (!pa_cvolume_compatible(volume, &i->sample_spec)) {
1143 volume = pa_cvolume_scale(&v, pa_cvolume_max(volume));
1147 if (pa_cvolume_equal(volume, &i->volume)) {
1148 i->save_volume = i->save_volume || save;
1152 i->volume = *volume;
1153 i->save_volume = save;
1155 if (pa_sink_flat_volume_enabled(i->sink)) {
1156 /* We are in flat volume mode, so let's update all sink input
1157 * volumes and update the flat volume of the sink */
1159 pa_sink_set_volume(i->sink, NULL, TRUE, save);
1162 /* OK, we are in normal volume mode. The volume only affects
1164 set_real_ratio(i, volume);
1166 /* Copy the new soft_volume to the thread_info struct */
1167 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1170 /* The volume changed, let's tell people so */
1171 if (i->volume_changed)
1172 i->volume_changed(i);
1174 /* The virtual volume changed, let's tell people so */
1175 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1178 /* Called from main context */
1179 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {
1180 pa_sink_input_assert_ref(i);
1181 pa_assert_ctl_context();
1182 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1183 pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
1185 /* This basically calculates:
1187 * i->real_ratio := v
1188 * i->soft_volume := i->real_ratio * i->volume_factor */
1193 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
1195 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1196 /* We don't copy the data to the thread_info data. That's left for someone else to do */
1199 /* Called from main or I/O context */
1200 pa_bool_t pa_sink_input_is_passthrough(pa_sink_input *i) {
1201 pa_sink_input_assert_ref(i);
1203 if (PA_UNLIKELY(!pa_format_info_is_pcm(i->format)))
1206 if (PA_UNLIKELY(i->flags & PA_SINK_INPUT_PASSTHROUGH))
1212 /* Called from main context */
1213 pa_bool_t pa_sink_input_is_volume_readable(pa_sink_input *i) {
1214 pa_sink_input_assert_ref(i);
1215 pa_assert_ctl_context();
1217 return !pa_sink_input_is_passthrough(i);
1220 /* Called from main context */
1221 pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, pa_bool_t absolute) {
1222 pa_sink_input_assert_ref(i);
1223 pa_assert_ctl_context();
1224 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1225 pa_assert(pa_sink_input_is_volume_readable(i));
1227 if (absolute || !pa_sink_flat_volume_enabled(i->sink))
1228 *volume = i->volume;
1230 *volume = i->reference_ratio;
1235 /* Called from main context */
1236 void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save) {
1237 pa_sink_input_assert_ref(i);
1238 pa_assert_ctl_context();
1239 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1241 if (!i->muted == !mute) {
1242 i->save_muted = i->save_muted || mute;
1247 i->save_muted = save;
1249 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
1251 /* The mute status changed, let's tell people so */
1252 if (i->mute_changed)
1255 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1258 /* Called from main context */
1259 pa_bool_t pa_sink_input_get_mute(pa_sink_input *i) {
1260 pa_sink_input_assert_ref(i);
1261 pa_assert_ctl_context();
1262 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1267 /* Called from main thread */
1268 void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
1269 pa_sink_input_assert_ref(i);
1270 pa_assert_ctl_context();
1273 pa_proplist_update(i->proplist, mode, p);
1275 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1276 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1277 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1281 /* Called from main context */
1282 void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) {
1283 pa_sink_input_assert_ref(i);
1284 pa_assert_ctl_context();
1285 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1287 sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
1290 /* Called from main context */
1291 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
1292 pa_sink_input_assert_ref(i);
1293 pa_assert_ctl_context();
1294 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1295 pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE);
1297 if (i->sample_spec.rate == rate)
1300 i->sample_spec.rate = rate;
1302 pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
1304 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1308 /* Called from main context */
1309 void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
1311 pa_sink_input_assert_ref(i);
1312 pa_assert_ctl_context();
1314 if (!name && !pa_proplist_contains(i->proplist, PA_PROP_MEDIA_NAME))
1317 old = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME);
1319 if (old && name && pa_streq(old, name))
1323 pa_proplist_sets(i->proplist, PA_PROP_MEDIA_NAME, name);
1325 pa_proplist_unset(i->proplist, PA_PROP_MEDIA_NAME);
1327 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1328 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1329 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1333 /* Called from main context */
1334 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
1335 pa_sink_input_assert_ref(i);
1336 pa_assert_ctl_context();
1338 return i->actual_resample_method;
1341 /* Called from main context */
1342 pa_bool_t pa_sink_input_may_move(pa_sink_input *i) {
1343 pa_sink_input_assert_ref(i);
1344 pa_assert_ctl_context();
1345 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1347 if (i->flags & PA_SINK_INPUT_DONT_MOVE)
1350 if (i->sync_next || i->sync_prev) {
1351 pa_log_warn("Moving synchronized streams not supported.");
1358 /* Called from main context */
1359 pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
1360 pa_sink_input_assert_ref(i);
1361 pa_assert_ctl_context();
1362 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1363 pa_sink_assert_ref(dest);
1365 if (dest == i->sink)
1368 if (!pa_sink_input_may_move(i))
1371 if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
1372 pa_log_warn("Failed to move sink input: too many inputs per sink.");
1376 if (check_passthrough_connection(pa_sink_input_is_passthrough(i), dest) < 0)
1380 if (!i->may_move_to(i, dest))
1386 /* Called from main context */
1387 int pa_sink_input_start_move(pa_sink_input *i) {
1388 pa_source_output *o, *p = NULL;
1391 pa_sink_input_assert_ref(i);
1392 pa_assert_ctl_context();
1393 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1396 if (!pa_sink_input_may_move(i))
1397 return -PA_ERR_NOTSUPPORTED;
1399 if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
1402 /* Kill directly connected outputs */
1403 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
1405 pa_source_output_kill(o);
1408 pa_assert(pa_idxset_isempty(i->direct_outputs));
1410 pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
1412 if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
1413 pa_assert_se(i->sink->n_corked-- >= 1);
1415 if (pa_sink_flat_volume_enabled(i->sink))
1416 /* We might need to update the sink's volume if we are in flat
1418 pa_sink_set_volume(i->sink, NULL, FALSE, FALSE);
1420 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
1422 /* We suspend the monitor if there was a passthrough sink, unsuspend now if required */
1423 if (pa_sink_input_is_passthrough(i) && i->sink->monitor_source)
1424 pa_source_suspend(i->sink->monitor_source, FALSE, PA_SUSPEND_PASSTHROUGH);
1426 pa_sink_update_status(i->sink);
1427 pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
1430 pa_sink_input_unref(i);
1435 /* Called from main context. If i has an origin sink that uses volume sharing,
1436 * then also the origin sink and all streams connected to it need to update
1437 * their volume - this function does all that by using recursion. */
1438 static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) {
1439 pa_cvolume old_volume;
1443 pa_assert(i->sink); /* The destination sink should already be set. */
1445 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1446 pa_sink *root_sink = i->sink;
1447 pa_sink_input *origin_sink_input;
1450 while (root_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
1451 root_sink = root_sink->input_to_master->sink;
1453 if (pa_sink_flat_volume_enabled(i->sink)) {
1454 /* Ok, so the origin sink uses volume sharing, and flat volume is
1455 * enabled. The volume will have to be updated as follows:
1457 * i->volume := i->sink->real_volume
1458 * (handled later by pa_sink_set_volume)
1459 * i->reference_ratio := i->volume / i->sink->reference_volume
1460 * (handled later by pa_sink_set_volume)
1461 * i->real_ratio stays unchanged
1462 * (streams whose origin sink uses volume sharing should
1463 * always have real_ratio of 0 dB)
1464 * i->soft_volume stays unchanged
1465 * (streams whose origin sink uses volume sharing should
1466 * always have volume_factor as soft_volume, so no change
1467 * should be needed) */
1469 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
1470 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
1472 /* Notifications will be sent by pa_sink_set_volume(). */
1475 /* Ok, so the origin sink uses volume sharing, and flat volume is
1476 * disabled. The volume will have to be updated as follows:
1479 * i->reference_ratio := 0 dB
1480 * i->real_ratio stays unchanged
1481 * (streams whose origin sink uses volume sharing should
1482 * always have real_ratio of 0 dB)
1483 * i->soft_volume stays unchanged
1484 * (streams whose origin sink uses volume sharing should
1485 * always have volume_factor as soft_volume, so no change
1486 * should be needed) */
1488 old_volume = i->volume;
1489 pa_cvolume_reset(&i->volume, i->volume.channels);
1490 pa_cvolume_reset(&i->reference_ratio, i->reference_ratio.channels);
1491 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
1492 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
1494 /* Notify others about the changed sink input volume. */
1495 if (!pa_cvolume_equal(&i->volume, &old_volume)) {
1496 if (i->volume_changed)
1497 i->volume_changed(i);
1499 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1503 /* Additionally, the origin sink volume needs updating:
1505 * i->origin_sink->reference_volume := root_sink->reference_volume
1506 * i->origin_sink->real_volume := root_sink->real_volume
1507 * i->origin_sink->soft_volume stays unchanged
1508 * (sinks that use volume sharing should always have
1509 * soft_volume of 0 dB) */
1511 old_volume = i->origin_sink->reference_volume;
1513 i->origin_sink->reference_volume = root_sink->reference_volume;
1514 pa_cvolume_remap(&i->origin_sink->reference_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
1516 i->origin_sink->real_volume = root_sink->real_volume;
1517 pa_cvolume_remap(&i->origin_sink->real_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
1519 pa_assert(pa_cvolume_is_norm(&i->origin_sink->soft_volume));
1521 /* Notify others about the changed sink volume. If you wonder whether
1522 * i->origin_sink->set_volume() should be called somewhere, that's not
1523 * the case, because sinks that use volume sharing shouldn't have any
1524 * internal volume that set_volume() would update. If you wonder
1525 * whether the thread_info variables should be synced, yes, they
1526 * should, and it's done by the PA_SINK_MESSAGE_FINISH_MOVE message
1528 if (!pa_cvolume_equal(&i->origin_sink->reference_volume, &old_volume))
1529 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, i->origin_sink->index);
1531 /* Recursively update origin sink inputs. */
1532 PA_IDXSET_FOREACH(origin_sink_input, i->origin_sink->inputs, idx)
1533 update_volume_due_to_moving(origin_sink_input, dest);
1536 old_volume = i->volume;
1538 if (pa_sink_flat_volume_enabled(i->sink)) {
1539 /* Ok, so this is a regular stream, and flat volume is enabled. The
1540 * volume will have to be updated as follows:
1542 * i->volume := i->reference_ratio * i->sink->reference_volume
1543 * i->reference_ratio stays unchanged
1544 * i->real_ratio := i->volume / i->sink->real_volume
1545 * (handled later by pa_sink_set_volume)
1546 * i->soft_volume := i->real_ratio * i->volume_factor
1547 * (handled later by pa_sink_set_volume) */
1549 i->volume = i->sink->reference_volume;
1550 pa_cvolume_remap(&i->volume, &i->sink->channel_map, &i->channel_map);
1551 pa_sw_cvolume_multiply(&i->volume, &i->volume, &i->reference_ratio);
1554 /* Ok, so this is a regular stream, and flat volume is disabled.
1555 * The volume will have to be updated as follows:
1557 * i->volume := i->reference_ratio
1558 * i->reference_ratio stays unchanged
1559 * i->real_ratio := i->reference_ratio
1560 * i->soft_volume := i->real_ratio * i->volume_factor */
1562 i->volume = i->reference_ratio;
1563 i->real_ratio = i->reference_ratio;
1564 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1567 /* Notify others about the changed sink input volume. */
1568 if (!pa_cvolume_equal(&i->volume, &old_volume)) {
1569 /* XXX: In case i->sink has flat volume enabled, then real_ratio
1570 * and soft_volume are not updated yet. Let's hope that the
1571 * callback implementation doesn't care about those variables... */
1572 if (i->volume_changed)
1573 i->volume_changed(i);
1575 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1579 /* If i->sink == dest, then recursion has finished, and we can finally call
1580 * pa_sink_set_volume(), which will do the rest of the updates. */
1581 if ((i->sink == dest) && pa_sink_flat_volume_enabled(i->sink))
1582 pa_sink_set_volume(i->sink, NULL, FALSE, i->save_volume);
1585 /* Called from main context */
1586 int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
1587 pa_resampler *new_resampler;
1589 pa_sink_input_assert_ref(i);
1590 pa_assert_ctl_context();
1591 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1592 pa_assert(!i->sink);
1593 pa_sink_assert_ref(dest);
1595 if (!pa_sink_input_may_move_to(i, dest))
1596 return -PA_ERR_NOTSUPPORTED;
1598 if (pa_sink_input_is_passthrough(i) && !pa_sink_check_format(dest, i->format)) {
1599 pa_proplist *p = pa_proplist_new();
1600 pa_log_debug("New sink doesn't support stream format, sending format-changed and killing");
1601 /* Tell the client what device we want to be on if it is going to
1603 pa_proplist_sets(p, "device", dest->name);
1604 pa_sink_input_send_event(i, PA_STREAM_EVENT_FORMAT_LOST, p);
1605 pa_proplist_free(p);
1606 return -PA_ERR_NOTSUPPORTED;
1609 if (i->thread_info.resampler &&
1610 pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &dest->sample_spec) &&
1611 pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &dest->channel_map))
1613 /* Try to reuse the old resampler if possible */
1614 new_resampler = i->thread_info.resampler;
1616 else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
1617 !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) ||
1618 !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) {
1620 /* Okay, we need a new resampler for the new sink */
1622 if (!(new_resampler = pa_resampler_new(
1624 &i->sample_spec, &i->channel_map,
1625 &dest->sample_spec, &dest->channel_map,
1626 i->requested_resample_method,
1627 ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
1628 ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
1629 (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
1630 pa_log_warn("Unsupported resampling operation.");
1631 return -PA_ERR_NOTSUPPORTED;
1634 new_resampler = NULL;
1640 i->save_sink = save;
1641 pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
1643 pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
1645 if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
1646 i->sink->n_corked++;
1648 /* Replace resampler and render queue */
1649 if (new_resampler != i->thread_info.resampler) {
1651 if (i->thread_info.resampler)
1652 pa_resampler_free(i->thread_info.resampler);
1653 i->thread_info.resampler = new_resampler;
1655 pa_memblockq_free(i->thread_info.render_memblockq);
1657 i->thread_info.render_memblockq = pa_memblockq_new(
1659 MEMBLOCKQ_MAXLENGTH,
1661 pa_frame_size(&i->sink->sample_spec),
1666 i->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID;
1669 pa_sink_update_status(dest);
1671 update_volume_due_to_moving(i, dest);
1673 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
1675 /* If we're entering passthrough mode, disable the monitor */
1676 if (pa_sink_input_is_passthrough(i) && i->sink->monitor_source)
1677 pa_source_suspend(i->sink->monitor_source, TRUE, PA_SUSPEND_PASSTHROUGH);
1679 pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
1681 /* Notify everyone */
1682 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
1683 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1688 /* Called from main context */
1689 void pa_sink_input_fail_move(pa_sink_input *i) {
1691 pa_sink_input_assert_ref(i);
1692 pa_assert_ctl_context();
1693 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1694 pa_assert(!i->sink);
1696 /* Check if someone wants this sink input? */
1697 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_STOP)
1703 pa_sink_input_kill(i);
1706 /* Called from main context */
1707 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
1710 pa_sink_input_assert_ref(i);
1711 pa_assert_ctl_context();
1712 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1714 pa_sink_assert_ref(dest);
1716 if (dest == i->sink)
1719 if (!pa_sink_input_may_move_to(i, dest))
1720 return -PA_ERR_NOTSUPPORTED;
1722 pa_sink_input_ref(i);
1724 if ((r = pa_sink_input_start_move(i)) < 0) {
1725 pa_sink_input_unref(i);
1729 if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
1730 pa_sink_input_fail_move(i);
1731 pa_sink_input_unref(i);
1735 pa_sink_input_unref(i);
1740 /* Called from IO thread context */
1741 void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
1742 pa_bool_t corking, uncorking;
1744 pa_sink_input_assert_ref(i);
1745 pa_sink_input_assert_io_context(i);
1747 if (state == i->thread_info.state)
1750 if ((state == PA_SINK_INPUT_DRAINED || state == PA_SINK_INPUT_RUNNING) &&
1751 !(i->thread_info.state == PA_SINK_INPUT_DRAINED || i->thread_info.state != PA_SINK_INPUT_RUNNING))
1752 pa_atomic_store(&i->thread_info.drained, 1);
1754 corking = state == PA_SINK_INPUT_CORKED && i->thread_info.state == PA_SINK_INPUT_RUNNING;
1755 uncorking = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
1757 if (i->state_change)
1758 i->state_change(i, state);
1760 i->thread_info.state = state;
1764 pa_log_debug("Requesting rewind due to corking");
1766 /* This will tell the implementing sink input driver to rewind
1767 * so that the unplayed already mixed data is not lost */
1768 pa_sink_input_request_rewind(i, 0, TRUE, TRUE, FALSE);
1770 } else if (uncorking) {
1772 i->thread_info.underrun_for = (uint64_t) -1;
1773 i->thread_info.playing_for = 0;
1775 pa_log_debug("Requesting rewind due to uncorking");
1777 /* OK, we're being uncorked. Make sure we're not rewound when
1778 * the hw buffer is remixed and request a remix. */
1779 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
1783 /* Called from thread context, except when it is not. */
1784 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1785 pa_sink_input *i = PA_SINK_INPUT(o);
1786 pa_sink_input_assert_ref(i);
1790 case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
1791 if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
1792 i->thread_info.soft_volume = i->soft_volume;
1793 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1797 case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
1798 if (i->thread_info.muted != i->muted) {
1799 i->thread_info.muted = i->muted;
1800 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1804 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1805 pa_usec_t *r = userdata;
1807 r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
1808 r[1] += pa_sink_get_latency_within_thread(i->sink);
1813 case PA_SINK_INPUT_MESSAGE_SET_RATE:
1815 i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
1816 pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
1820 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1821 pa_sink_input *ssync;
1823 pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
1825 for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
1826 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
1828 for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
1829 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
1834 case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
1835 pa_usec_t *usec = userdata;
1837 *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
1841 case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
1842 pa_usec_t *r = userdata;
1844 *r = i->thread_info.requested_sink_latency;
1849 return -PA_ERR_NOTIMPLEMENTED;
1852 /* Called from main thread */
1853 pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
1854 pa_sink_input_assert_ref(i);
1855 pa_assert_ctl_context();
1857 if (i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED)
1858 return pa_atomic_load(&i->thread_info.drained) ? PA_SINK_INPUT_DRAINED : PA_SINK_INPUT_RUNNING;
1863 /* Called from IO context */
1864 pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
1865 pa_sink_input_assert_ref(i);
1866 pa_sink_input_assert_io_context(i);
1868 if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
1869 return pa_memblockq_is_empty(i->thread_info.render_memblockq);
1874 /* Called from IO context */
1875 void pa_sink_input_request_rewind(
1877 size_t nbytes /* in our sample spec */,
1880 pa_bool_t dont_rewind_render) {
1884 /* If 'rewrite' is TRUE the sink is rewound as far as requested
1885 * and possible and the exact value of this is passed back the
1886 * implementor via process_rewind(). If 'flush' is also TRUE all
1887 * already rendered data is also dropped.
1889 * If 'rewrite' is FALSE the sink is rewound as far as requested
1890 * and possible and the already rendered data is dropped so that
1891 * in the next iteration we read new data from the
1892 * implementor. This implies 'flush' is TRUE. If
1893 * dont_rewind_render is TRUE then the render memblockq is not
1896 /* nbytes = 0 means maximum rewind request */
1898 pa_sink_input_assert_ref(i);
1899 pa_sink_input_assert_io_context(i);
1900 pa_assert(rewrite || flush);
1901 pa_assert(!dont_rewind_render || !rewrite);
1903 /* We don't take rewind requests while we are corked */
1904 if (i->thread_info.state == PA_SINK_INPUT_CORKED)
1907 nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
1909 /* pa_log_debug("request rewrite %zu", nbytes); */
1911 /* Calculate how much we can rewind locally without having to
1914 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
1918 /* Check if rewinding for the maximum is requested, and if so, fix up */
1921 /* Calculate maximum number of bytes that could be rewound in theory */
1922 nbytes = i->sink->thread_info.max_rewind + lbq;
1924 /* Transform from sink domain */
1925 if (i->thread_info.resampler)
1926 nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
1929 /* Remember how much we actually want to rewrite */
1930 if (i->thread_info.rewrite_nbytes != (size_t) -1) {
1932 /* Make sure to not overwrite over underruns */
1933 if (nbytes > i->thread_info.playing_for)
1934 nbytes = (size_t) i->thread_info.playing_for;
1936 i->thread_info.rewrite_nbytes = nbytes;
1938 i->thread_info.rewrite_nbytes = (size_t) -1;
1941 i->thread_info.rewrite_flush =
1942 i->thread_info.rewrite_flush ||
1943 (flush && i->thread_info.rewrite_nbytes != 0);
1945 i->thread_info.dont_rewind_render =
1946 i->thread_info.dont_rewind_render ||
1949 if (nbytes != (size_t) -1) {
1951 /* Transform to sink domain */
1952 if (i->thread_info.resampler)
1953 nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
1956 pa_sink_request_rewind(i->sink, nbytes - lbq);
1958 /* This call will make sure process_rewind() is called later */
1959 pa_sink_request_rewind(i->sink, 0);
1963 /* Called from main context */
1964 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
1965 pa_sink_input_assert_ref(i);
1966 pa_assert_ctl_context();
1969 /* FIXME: Shouldn't access resampler object from main context! */
1971 pa_silence_memchunk_get(
1972 &i->core->silence_cache,
1976 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
1981 /* Called from main context */
1982 void pa_sink_input_send_event(pa_sink_input *i, const char *event, pa_proplist *data) {
1983 pa_proplist *pl = NULL;
1984 pa_sink_input_send_event_hook_data hook_data;
1986 pa_sink_input_assert_ref(i);
1987 pa_assert_ctl_context();
1994 data = pl = pa_proplist_new();
1996 hook_data.sink_input = i;
1997 hook_data.data = data;
1998 hook_data.event = event;
2000 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
2003 i->send_event(i, event, data);
2007 pa_proplist_free(pl);