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, see <http://www.gnu.org/licenses/>.
31 #include <pulse/utf8.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/util.h>
34 #include <pulse/internal.h>
35 #ifdef TIZEN_EMPTY_POP
36 #include <pulse/rtclock.h>
37 #include <pulse/timeval.h>
40 #include <pulse/rtclock.h>
43 #include <pulsecore/core-format.h>
44 #include <pulsecore/mix.h>
45 #include <pulsecore/stream-util.h>
46 #include <pulsecore/core-subscribe.h>
47 #include <pulsecore/log.h>
48 #include <pulsecore/play-memblockq.h>
49 #include <pulsecore/namereg.h>
50 #include <pulsecore/core-util.h>
52 #include "sink-input.h"
54 /* #define SINK_INPUT_DEBUG */
56 #define MEMBLOCKQ_MAXLENGTH (32*1024*1024)
57 #define CONVERT_BUFFER_LENGTH (pa_page_size())
59 PA_DEFINE_PUBLIC_CLASS(pa_sink_input, pa_msgobject);
61 struct volume_factor_entry {
66 #ifdef TIZEN_VOLUME_RAMP
67 struct volume_ramp_factor_entry {
72 #ifdef TIZEN_EMPTY_POP
73 static void _empty_pop_reset(pa_sink_input *i);
74 static bool _empty_pop_is_started(pa_sink_input *i);
77 static void pa_sink_input_write_pcm_dump(pa_sink_input *i, pa_memchunk *chunk)
79 char *dump_time = NULL, *dump_path_surfix = NULL;
80 const char *s_device_api_str, *card_name_str, *device_idx_str;
85 /* open file for dump pcm */
86 if (i->core->pcm_dump & PA_PCM_DUMP_SINK_INPUT && !i->pcm_dump_fp && i->state == PA_SINK_INPUT_RUNNING) {
87 pa_gettimeofday(&now);
88 localtime_r(&now.tv_sec, &tm);
89 memset(&datetime[0], 0x00, sizeof(datetime));
90 strftime(&datetime[0], sizeof(datetime), "%H%M%S", &tm);
91 dump_time = pa_sprintf_malloc("%s.%03ld", &datetime[0], now.tv_usec / 1000);
93 if ((s_device_api_str = pa_proplist_gets(i->sink->proplist, PA_PROP_DEVICE_API))) {
94 if (pa_streq(s_device_api_str, "alsa")) {
95 card_name_str = pa_proplist_gets(i->sink->proplist, "alsa.card_name");
96 device_idx_str = pa_proplist_gets(i->sink->proplist, "alsa.device");
97 dump_path_surfix = pa_sprintf_malloc("%s.%s", pa_strnull(card_name_str), pa_strnull(device_idx_str));
99 dump_path_surfix = pa_sprintf_malloc("%s", s_device_api_str);
102 dump_path_surfix = pa_sprintf_malloc("%s", i->sink->name);
105 i->dump_path = pa_sprintf_malloc("%s_%s_pa-input%d-sink%d-%s_%dch_%d.raw", PA_PCM_DUMP_PATH_PREFIX, pa_strempty(dump_time),
106 i->index, i->sink->index, pa_strempty(dump_path_surfix), i->sample_spec.channels, i->sample_spec.rate);
108 i->pcm_dump_fp = fopen(i->dump_path, "w");
110 pa_log_warn("%s open failed", i->dump_path);
112 pa_log_info("%s opened", i->dump_path);
115 pa_xfree(dump_path_surfix);
116 /* close file for dump pcm when config is changed */
117 } else if (~i->core->pcm_dump & PA_PCM_DUMP_SINK_INPUT && i->pcm_dump_fp) {
118 fclose(i->pcm_dump_fp);
119 pa_log_info("%s closed", i->dump_path);
120 pa_xfree(i->dump_path);
121 i->pcm_dump_fp = NULL;
125 if (i->pcm_dump_fp) {
128 ptr = pa_memblock_acquire(chunk->memblock);
130 i->dump_length = chunk->length;
131 fwrite((uint8_t *)ptr + chunk->index, 1, chunk->length, i->pcm_dump_fp);
134 pa_log_warn("pa_memblock_acquire is failed. ptr is NULL");
136 pa_memblock_release(chunk->memblock);
141 static struct volume_factor_entry *volume_factor_entry_new(const char *key, const pa_cvolume *volume) {
142 struct volume_factor_entry *entry;
147 entry = pa_xnew(struct volume_factor_entry, 1);
148 entry->key = pa_xstrdup(key);
150 entry->volume = *volume;
155 static void volume_factor_entry_free(struct volume_factor_entry *volume_entry) {
156 pa_assert(volume_entry);
158 pa_xfree(volume_entry->key);
159 pa_xfree(volume_entry);
162 static void volume_factor_from_hashmap(pa_cvolume *v, pa_hashmap *items, uint8_t channels) {
163 struct volume_factor_entry *entry;
166 pa_cvolume_reset(v, channels);
167 PA_HASHMAP_FOREACH(entry, items, state)
168 pa_sw_cvolume_multiply(v, v, &entry->volume);
170 #ifdef TIZEN_VOLUME_RAMP
171 static struct volume_ramp_factor_entry *volume_ramp_factor_entry_new(const char *key, const pa_cvolume_ramp *ramp) {
172 struct volume_ramp_factor_entry *entry;
177 entry = pa_xnew(struct volume_ramp_factor_entry, 1);
178 entry->key = pa_xstrdup(key);
185 static void volume_ramp_factor_entry_free(struct volume_ramp_factor_entry *ramp_entry) {
186 pa_assert(ramp_entry);
188 pa_xfree(ramp_entry->key);
189 pa_xfree(ramp_entry);
192 static void volume_ramp_factor_from_hashmap(pa_cvolume_ramp *r, pa_hashmap *items, uint8_t channels, pa_volume_ramp_type_t type, long time) {
193 struct volume_ramp_factor_entry *entry;
196 pa_cvolume_ramp_reset(r, channels, type, time);
197 PA_HASHMAP_FOREACH(entry, items, state)
198 pa_sw_cvolume_ramp_multiply(r, r, &entry->ramp);
203 static void sink_input_free(pa_object *o);
204 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v);
206 static int check_passthrough_connection(bool passthrough, pa_sink *dest) {
207 if (pa_sink_is_passthrough(dest)) {
208 pa_log_warn("Sink is already connected to PASSTHROUGH input");
212 /* If current input(s) exist, check new input is not PASSTHROUGH */
213 if (pa_idxset_size(dest->inputs) > 0 && passthrough) {
214 pa_log_warn("Sink is already connected, cannot accept new PASSTHROUGH INPUT");
221 pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) {
225 data->resample_method = PA_RESAMPLER_INVALID;
226 data->proplist = pa_proplist_new();
227 data->volume_writable = true;
229 data->volume_factor_items = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL,
230 (pa_free_cb_t) volume_factor_entry_free);
231 data->volume_factor_sink_items = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL,
232 (pa_free_cb_t) volume_factor_entry_free);
233 #ifdef TIZEN_INDIVIDUAL_VOLUME_RATIO
234 data->individual_volume_ratio = 1.0;
240 void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec) {
243 if ((data->sample_spec_is_set = !!spec))
244 data->sample_spec = *spec;
247 void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map) {
250 if ((data->channel_map_is_set = !!map))
251 data->channel_map = *map;
254 bool pa_sink_input_new_data_is_passthrough(pa_sink_input_new_data *data) {
257 if (PA_LIKELY(data->format) && PA_UNLIKELY(!pa_format_info_is_pcm(data->format)))
260 if (PA_UNLIKELY(data->flags & PA_SINK_INPUT_PASSTHROUGH))
266 void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) {
268 pa_assert(data->volume_writable);
270 if ((data->volume_is_set = !!volume))
271 data->volume = *volume;
274 void pa_sink_input_new_data_add_volume_factor(pa_sink_input_new_data *data, const char *key, const pa_cvolume *volume_factor) {
275 struct volume_factor_entry *v;
279 pa_assert(volume_factor);
281 v = volume_factor_entry_new(key, volume_factor);
282 pa_assert_se(pa_hashmap_put(data->volume_factor_items, v->key, v) >= 0);
285 void pa_sink_input_new_data_add_volume_factor_sink(pa_sink_input_new_data *data, const char *key, const pa_cvolume *volume_factor) {
286 struct volume_factor_entry *v;
290 pa_assert(volume_factor);
292 v = volume_factor_entry_new(key, volume_factor);
293 pa_assert_se(pa_hashmap_put(data->volume_factor_sink_items, v->key, v) >= 0);
296 void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, bool mute) {
299 data->muted_is_set = true;
303 bool pa_sink_input_new_data_set_sink(pa_sink_input_new_data *data, pa_sink *s, bool save, bool requested_by_application) {
305 pa_idxset *formats = NULL;
310 if (!data->req_formats) {
311 /* We're not working with the extended API */
314 pa_xfree(data->preferred_sink);
315 data->preferred_sink = pa_xstrdup(s->name);
317 data->sink_requested_by_application = requested_by_application;
319 /* Extended API: let's see if this sink supports the formats the client can provide */
320 formats = pa_sink_check_formats(s, data->req_formats);
322 if (formats && !pa_idxset_isempty(formats)) {
323 /* Sink supports at least one of the requested formats */
326 pa_xfree(data->preferred_sink);
327 data->preferred_sink = pa_xstrdup(s->name);
329 data->sink_requested_by_application = requested_by_application;
330 if (data->nego_formats)
331 pa_idxset_free(data->nego_formats, (pa_free_cb_t) pa_format_info_free);
332 data->nego_formats = formats;
334 /* Sink doesn't support any of the formats requested by the client */
336 pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
344 bool pa_sink_input_new_data_set_formats(pa_sink_input_new_data *data, pa_idxset *formats) {
348 if (data->req_formats)
349 pa_idxset_free(data->req_formats, (pa_free_cb_t) pa_format_info_free);
351 data->req_formats = formats;
354 /* Trigger format negotiation */
355 return pa_sink_input_new_data_set_sink(data, data->sink, (data->preferred_sink != NULL), data->sink_requested_by_application);
361 void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
364 if (data->req_formats)
365 pa_idxset_free(data->req_formats, (pa_free_cb_t) pa_format_info_free);
367 if (data->nego_formats)
368 pa_idxset_free(data->nego_formats, (pa_free_cb_t) pa_format_info_free);
371 pa_format_info_free(data->format);
373 if (data->volume_factor_items)
374 pa_hashmap_free(data->volume_factor_items);
376 if (data->volume_factor_sink_items)
377 pa_hashmap_free(data->volume_factor_sink_items);
379 if (data->preferred_sink)
380 pa_xfree(data->preferred_sink);
382 pa_proplist_free(data->proplist);
385 /* Called from main context */
386 static void reset_callbacks(pa_sink_input *i) {
390 i->process_underrun = NULL;
391 i->process_rewind = NULL;
392 i->update_max_rewind = NULL;
393 i->update_max_request = NULL;
394 i->update_sink_requested_latency = NULL;
395 i->update_sink_latency_range = NULL;
396 i->update_sink_fixed_latency = NULL;
400 i->suspend_within_thread = NULL;
403 i->get_latency = NULL;
404 i->state_change = NULL;
405 i->may_move_to = NULL;
406 i->send_event = NULL;
407 i->volume_changed = NULL;
408 i->mute_changed = NULL;
411 /* Called from main context */
412 int pa_sink_input_new(
415 pa_sink_input_new_data *data) {
418 pa_resampler *resampler = NULL;
419 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], fmt[PA_FORMAT_INFO_SNPRINT_MAX];
420 pa_channel_map volume_map;
423 char *memblockq_name;
428 pa_assert_ctl_context();
431 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
433 if (data->origin_sink && (data->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
434 data->volume_writable = false;
436 if (!data->req_formats) {
437 /* From this point on, we want to work only with formats, and get back
438 * to using the sample spec and channel map after all decisions w.r.t.
439 * routing are complete. */
443 f = pa_format_info_from_sample_spec2(&data->sample_spec, data->channel_map_is_set ? &data->channel_map : NULL,
444 !(data->flags & PA_SINK_INPUT_FIX_FORMAT),
445 !(data->flags & PA_SINK_INPUT_FIX_RATE),
446 !(data->flags & PA_SINK_INPUT_FIX_CHANNELS));
448 return -PA_ERR_INVALID;
450 formats = pa_idxset_new(NULL, NULL);
451 pa_idxset_put(formats, f, NULL);
452 pa_sink_input_new_data_set_formats(data, formats);
455 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0)
458 pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
461 pa_sink *sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK);
462 pa_return_val_if_fail(sink, -PA_ERR_NOENTITY);
463 pa_sink_input_new_data_set_sink(data, sink, false, false);
466 pa_sink_input_new_data_set_sink(data, data->sink, false, false);
470 /* If something didn't pick a format for us, pick the top-most format since
471 * we assume this is sorted in priority order */
472 if (!data->format && data->nego_formats && !pa_idxset_isempty(data->nego_formats))
473 data->format = pa_format_info_copy(pa_idxset_first(data->nego_formats, NULL));
475 if (PA_LIKELY(data->format)) {
476 /* We know that data->sink is set, because data->format has been set.
477 * data->format is set after a successful format negotiation, and that
478 * can't happen before data->sink has been set. */
479 pa_assert(data->sink);
481 pa_log_debug("Negotiated format: %s", pa_format_info_snprint(fmt, sizeof(fmt), data->format));
483 pa_format_info *format;
486 pa_log_info("Sink does not support any requested format:");
487 PA_IDXSET_FOREACH(format, data->req_formats, idx)
488 pa_log_info(" -- %s", pa_format_info_snprint(fmt, sizeof(fmt), format));
490 return -PA_ERR_NOTSUPPORTED;
493 pa_return_val_if_fail(PA_SINK_IS_LINKED(data->sink->state), -PA_ERR_BADSTATE);
494 pa_return_val_if_fail(!data->sync_base || (data->sync_base->sink == data->sink
495 && data->sync_base->state == PA_SINK_INPUT_CORKED),
498 /* Routing is done. We have a sink and a format. */
500 if (data->volume_is_set && !pa_sink_input_new_data_is_passthrough(data)) {
501 /* If volume is set, we need to save the original data->channel_map,
502 * so that we can remap the volume from the original channel map to the
503 * final channel map of the stream in case data->channel_map gets
504 * modified in pa_format_info_to_sample_spec2(). */
505 r = pa_stream_get_volume_channel_map(&data->volume, data->channel_map_is_set ? &data->channel_map : NULL, data->format, &volume_map);
509 /* Initialize volume_map to invalid state. We check the state later to
510 * determine if volume remapping is needed. */
511 pa_channel_map_init(&volume_map);
514 /* Now populate the sample spec and channel map according to the final
515 * format that we've negotiated */
516 r = pa_format_info_to_sample_spec2(data->format, &data->sample_spec, &data->channel_map, &data->sink->sample_spec,
517 &data->sink->channel_map);
521 r = check_passthrough_connection(pa_sink_input_new_data_is_passthrough(data), data->sink);
525 /* Don't restore (or save) stream volume for passthrough streams and
526 * prevent attenuation/gain */
527 if (pa_sink_input_new_data_is_passthrough(data)) {
528 data->volume_is_set = true;
529 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
530 data->volume_is_absolute = true;
531 data->save_volume = false;
534 if (!data->volume_is_set) {
535 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
536 data->volume_is_absolute = false;
537 data->save_volume = false;
540 if (!data->volume_writable)
541 data->save_volume = false;
543 if (pa_channel_map_valid(&volume_map))
544 /* The original volume channel map may be different than the final
545 * stream channel map, so remapping may be needed. */
546 pa_cvolume_remap(&data->volume, &volume_map, &data->channel_map);
548 if (!data->muted_is_set)
551 if (!(data->flags & PA_SINK_INPUT_VARIABLE_RATE) &&
552 !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec)) {
553 /* try to change sink format and rate. This is done before the FIXATE hook since
554 module-suspend-on-idle can resume a sink */
556 pa_log_info("Trying to change sample spec");
557 pa_sink_reconfigure(data->sink, &data->sample_spec, pa_sink_input_new_data_is_passthrough(data));
560 if (pa_sink_input_new_data_is_passthrough(data) &&
561 !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec)) {
562 /* rate update failed, or other parts of sample spec didn't match */
564 pa_log_debug("Could not update sink sample spec to match passthrough stream");
565 return -PA_ERR_NOTSUPPORTED;
568 if (data->resample_method == PA_RESAMPLER_INVALID)
569 data->resample_method = core->resample_method;
571 pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
573 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
576 if ((data->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND) &&
577 data->sink->state == PA_SINK_SUSPENDED) {
578 pa_log_warn("Failed to create sink input: sink is suspended.");
579 return -PA_ERR_BADSTATE;
582 if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) {
583 pa_log_warn("Failed to create sink input: too many inputs per sink.");
585 pa_core_dump_sink_inputs(core);
587 return -PA_ERR_TOOLARGE;
590 if ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
591 !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) ||
592 !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) {
594 /* Note: for passthrough content we need to adjust the output rate to that of the current sink-input */
595 if (!pa_sink_input_new_data_is_passthrough(data)) /* no resampler for passthrough content */
596 if (!(resampler = pa_resampler_new(
598 &data->sample_spec, &data->channel_map,
599 &data->sink->sample_spec, &data->sink->channel_map,
600 core->lfe_crossover_freq,
601 data->resample_method,
602 ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
603 ((data->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
604 (core->disable_remixing || (data->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
605 (core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
606 (core->remixing_produce_lfe ? PA_RESAMPLER_PRODUCE_LFE : 0) |
607 (core->remixing_consume_lfe ? PA_RESAMPLER_CONSUME_LFE : 0)))) {
608 pa_log_warn("Unsupported resampling operation.");
609 return -PA_ERR_NOTSUPPORTED;
613 i = pa_msgobject_new(pa_sink_input);
614 i->parent.parent.free = sink_input_free;
615 i->parent.process_msg = pa_sink_input_process_msg;
618 i->state = PA_SINK_INPUT_INIT;
619 i->flags = data->flags;
620 i->proplist = pa_proplist_copy(data->proplist);
621 i->driver = pa_xstrdup(pa_path_get_filename(data->driver));
622 i->module = data->module;
623 i->sink = data->sink;
624 i->sink_requested_by_application = data->sink_requested_by_application;
625 i->origin_sink = data->origin_sink;
626 i->client = data->client;
628 i->requested_resample_method = data->resample_method;
629 i->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID;
630 i->sample_spec = data->sample_spec;
631 i->channel_map = data->channel_map;
632 i->format = pa_format_info_copy(data->format);
634 if (!data->volume_is_absolute && pa_sink_flat_volume_enabled(i->sink)) {
637 /* When the 'absolute' bool is not set then we'll treat the volume
638 * as relative to the sink volume even in flat volume mode */
639 remapped = data->sink->reference_volume;
640 pa_cvolume_remap(&remapped, &data->sink->channel_map, &data->channel_map);
641 pa_sw_cvolume_multiply(&i->volume, &data->volume, &remapped);
643 i->volume = data->volume;
645 i->volume_factor_items = data->volume_factor_items;
646 data->volume_factor_items = NULL;
647 volume_factor_from_hashmap(&i->volume_factor, i->volume_factor_items, i->sample_spec.channels);
649 i->volume_factor_sink_items = data->volume_factor_sink_items;
650 data->volume_factor_sink_items = NULL;
651 volume_factor_from_hashmap(&i->volume_factor_sink, i->volume_factor_sink_items, i->sink->sample_spec.channels);
653 #ifdef TIZEN_VOLUME_RAMP
654 i->ramp_factor_items = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL,
655 (pa_free_cb_t) volume_ramp_factor_entry_free);
657 i->real_ratio = i->reference_ratio = data->volume;
658 pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
659 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
660 #ifdef TIZEN_INDIVIDUAL_VOLUME_RATIO
661 i->individual_volume_ratio = data->individual_volume_ratio;
663 i->volume_writable = data->volume_writable;
664 i->save_volume = data->save_volume;
665 i->preferred_sink = pa_xstrdup(data->preferred_sink);
666 i->save_muted = data->save_muted;
668 i->muted = data->muted;
670 if (data->sync_base) {
671 i->sync_next = data->sync_base->sync_next;
672 i->sync_prev = data->sync_base;
674 if (data->sync_base->sync_next)
675 data->sync_base->sync_next->sync_prev = i;
676 data->sync_base->sync_next = i;
678 i->sync_next = i->sync_prev = NULL;
680 i->direct_outputs = pa_idxset_new(NULL, NULL);
684 #ifdef TIZEN_EMPTY_POP
685 i->is_virtual = pa_safe_streq(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), "VIRTUAL_STREAM");
687 #ifdef TIZEN_PCM_DUMP
688 i->pcm_dump_fp = NULL;
692 #ifdef TIZEN_VOLUME_RAMP
693 if (data->flags & PA_SINK_INPUT_START_RAMP_MUTED)
694 pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_MUTED, data->sink->sample_spec.channels);
696 pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_NORM, data->sink->sample_spec.channels);
699 i->thread_info.state = i->state;
700 i->thread_info.attached = false;
701 i->thread_info.sample_spec = i->sample_spec;
702 i->thread_info.resampler = resampler;
703 i->thread_info.soft_volume = i->soft_volume;
704 i->thread_info.muted = i->muted;
705 i->thread_info.requested_sink_latency = (pa_usec_t) -1;
706 i->thread_info.rewrite_nbytes = 0;
707 i->thread_info.rewrite_flush = false;
708 i->thread_info.dont_rewind_render = false;
709 i->thread_info.underrun_for = (uint64_t) -1;
710 i->thread_info.underrun_for_sink = 0;
711 i->thread_info.playing_for = 0;
712 i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
713 #ifdef TIZEN_VOLUME_RAMP
714 i->thread_info.ramp = i->ramp;
717 pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
718 pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0);
721 pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
723 memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index);
724 i->thread_info.render_memblockq = pa_memblockq_new(
729 &i->sink->sample_spec,
734 pa_xfree(memblockq_name);
736 pt = pa_proplist_to_string_sep(i->proplist, "\n ");
737 pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
739 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
741 pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
742 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
746 /* Don't forget to call pa_sink_input_put! */
752 /* Called from main context */
753 static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
755 pa_assert_ctl_context();
760 if (i->state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED)
761 pa_assert_se(i->sink->n_corked -- >= 1);
762 else if (i->state != PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_CORKED)
766 /* Called from main context */
767 static void sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
768 pa_sink_input *ssync;
770 pa_assert_ctl_context();
772 if (i->state == state)
775 #ifdef TIZEN_EMPTY_POP
776 if (state != PA_SINK_INPUT_RUNNING && _empty_pop_is_started(i))
781 if (i->state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING && pa_sink_used_by(i->sink) == 0 &&
782 !pa_sample_spec_equal(&i->sample_spec, &i->sink->sample_spec)) {
783 /* We were uncorked and the sink was not playing anything -- let's try
784 * to update the sample format and rate to avoid resampling */
785 pa_sink_reconfigure(i->sink, &i->sample_spec, pa_sink_input_is_passthrough(i));
788 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);
790 /* If the sink is not valid, pa_sink_input_set_state_within_thread() must be called directly */
792 pa_sink_input_set_state_within_thread(i, state);
794 for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
795 pa_sink_input_set_state_within_thread(ssync, state);
797 for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
798 pa_sink_input_set_state_within_thread(ssync, state);
800 #ifdef TIZEN_PCM_DUMP
801 if (i->state == PA_SINK_INPUT_RUNNING && i->pcm_dump_fp && (i->core->pcm_dump & PA_PCM_DUMP_SEPARATED)) {
802 /* close file for dump pcm */
803 fclose(i->pcm_dump_fp);
804 pa_log_info("%s closed", i->dump_path);
805 pa_xfree(i->dump_path);
806 i->pcm_dump_fp = NULL;
810 if (state == PA_SINK_INPUT_RUNNING)
811 i->time_of_start_to_run = pa_rtclock_now();
814 update_n_corked(i, state);
817 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev) {
818 update_n_corked(ssync, state);
819 ssync->state = state;
821 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) {
822 update_n_corked(ssync, state);
823 ssync->state = state;
826 if (state != PA_SINK_INPUT_UNLINKED) {
827 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
829 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev)
830 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
832 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next)
833 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
835 if (PA_SINK_INPUT_IS_LINKED(state))
836 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
840 pa_sink_update_status(i->sink);
843 /* Called from main context */
844 void pa_sink_input_unlink(pa_sink_input *i) {
846 pa_source_output *o, PA_UNUSED *p = NULL;
848 pa_sink_input_assert_ref(i);
849 pa_assert_ctl_context();
851 /* See pa_sink_unlink() for a couple of comments how this function
854 pa_sink_input_ref(i);
856 linked = PA_SINK_INPUT_IS_LINKED(i->state);
859 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
862 i->sync_prev->sync_next = i->sync_next;
864 i->sync_next->sync_prev = i->sync_prev;
866 i->sync_prev = i->sync_next = NULL;
868 pa_idxset_remove_by_data(i->core->sink_inputs, i, NULL);
871 if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
872 pa_sink_input_unref(i);
875 pa_idxset_remove_by_data(i->client->sink_inputs, i, NULL);
877 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
879 pa_source_output_kill(o);
883 update_n_corked(i, PA_SINK_INPUT_UNLINKED);
884 i->state = PA_SINK_INPUT_UNLINKED;
886 if (linked && i->sink) {
887 if (pa_sink_input_is_passthrough(i))
888 pa_sink_leave_passthrough(i->sink);
890 /* We might need to update the sink's volume if we are in flat volume mode. */
891 if (pa_sink_flat_volume_enabled(i->sink))
892 pa_sink_set_volume(i->sink, NULL, false, false);
894 if (i->sink->asyncmsgq)
895 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL) == 0);
901 if (PA_SINK_IS_LINKED(i->sink->state))
902 pa_sink_update_status(i->sink);
908 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
909 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
912 pa_core_maybe_vacuum(i->core);
914 pa_sink_input_unref(i);
917 /* Called from main context */
918 static void sink_input_free(pa_object *o) {
919 pa_sink_input* i = PA_SINK_INPUT(o);
922 pa_assert_ctl_context();
923 pa_assert(pa_sink_input_refcnt(i) == 0);
924 pa_assert(!PA_SINK_INPUT_IS_LINKED(i->state));
926 pa_log_info("Freeing input %u \"%s\"", i->index,
927 i->proplist ? pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)) : "");
929 /* Side note: this function must be able to destruct properly any
930 * kind of sink input in any state, even those which are
931 * "half-moved" or are connected to sinks that have no asyncmsgq
932 * and are hence half-destructed themselves! */
934 if (i->thread_info.render_memblockq)
935 pa_memblockq_free(i->thread_info.render_memblockq);
937 if (i->thread_info.resampler)
938 pa_resampler_free(i->thread_info.resampler);
939 #ifdef TIZEN_PCM_DUMP
940 /* close file for dump pcm */
941 if (i->pcm_dump_fp) {
942 fclose(i->pcm_dump_fp);
943 pa_log_info("%s closed", i->dump_path);
944 pa_xfree(i->dump_path);
945 i->pcm_dump_fp = NULL;
950 pa_format_info_free(i->format);
953 pa_proplist_free(i->proplist);
955 if (i->direct_outputs)
956 pa_idxset_free(i->direct_outputs, NULL);
958 if (i->thread_info.direct_outputs)
959 pa_hashmap_free(i->thread_info.direct_outputs);
961 if (i->volume_factor_items)
962 pa_hashmap_free(i->volume_factor_items);
964 if (i->volume_factor_sink_items)
965 pa_hashmap_free(i->volume_factor_sink_items);
967 if (i->preferred_sink)
968 pa_xfree(i->preferred_sink);
970 #ifdef TIZEN_VOLUME_RAMP
971 if (i->ramp_factor_items)
972 pa_hashmap_free(i->ramp_factor_items);
979 /* Called from main context */
980 void pa_sink_input_put(pa_sink_input *i) {
981 pa_sink_input_state_t state;
983 pa_sink_input_assert_ref(i);
984 pa_assert_ctl_context();
986 pa_assert(i->state == PA_SINK_INPUT_INIT);
988 /* The following fields must be initialized properly */
990 pa_assert(i->process_rewind);
993 state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
995 update_n_corked(i, state);
998 /* We might need to update the sink's volume if we are in flat volume mode. */
999 if (pa_sink_flat_volume_enabled(i->sink))
1000 pa_sink_set_volume(i->sink, NULL, false, i->save_volume);
1002 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1003 pa_assert(pa_cvolume_is_norm(&i->volume));
1004 pa_assert(pa_cvolume_is_norm(&i->reference_ratio));
1007 set_real_ratio(i, &i->volume);
1010 if (pa_sink_input_is_passthrough(i))
1011 pa_sink_enter_passthrough(i->sink);
1013 i->thread_info.soft_volume = i->soft_volume;
1014 i->thread_info.muted = i->muted;
1016 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0);
1018 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
1019 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
1021 pa_sink_update_status(i->sink);
1024 /* Called from main context */
1025 void pa_sink_input_kill(pa_sink_input*i) {
1026 pa_sink_input_assert_ref(i);
1027 pa_assert_ctl_context();
1028 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1033 /* Called from main context */
1034 pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
1035 pa_usec_t r[2] = { 0, 0 };
1037 pa_sink_input_assert_ref(i);
1038 pa_assert_ctl_context();
1039 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1041 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, r, 0, NULL) == 0);
1044 r[0] += i->get_latency(i);
1047 *sink_latency = r[1];
1052 #ifdef TIZEN_VOLUME_RAMP
1053 /* Called from thread context */
1054 static void check_and_apply_silence(pa_sink_input *i) {
1055 pa_sink_input_assert_ref(i);
1057 if (i->thread_info.silenced && i->thread_info.silence_duration > 0) {
1059 size_t target_length = pa_usec_to_bytes(i->thread_info.silence_duration, &i->sink->sample_spec);
1061 pa_silence_memchunk_get(&i->core->silence_cache,
1064 &i->sink->sample_spec,
1065 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
1067 while (target_length > 0) {
1068 if (target_length < schunk.length)
1069 schunk.length = target_length;
1070 pa_memblockq_push_align(i->thread_info.render_memblockq, &schunk);
1071 target_length -= schunk.length;
1072 #ifdef SINK_INPUT_DEBUG
1073 pa_log_debug("add memchunk for slience, length(%u)", schunk.length);
1076 pa_memblock_unref(schunk.memblock);
1078 i->thread_info.silenced = false;
1079 i->thread_info.silence_duration = 0;
1083 /* Called from thread context */
1084 static void check_and_apply_ramp(pa_cvolume_ramp_int *ramp, const pa_sample_spec *spec, pa_memchunk *chunk) {
1091 /* check for possible volume ramp and apply it */
1092 if (pa_cvolume_ramp_active(ramp)) {
1093 pa_memchunk_make_writable(chunk, 0);
1094 pa_volume_ramp_memchunk(chunk, spec, ramp);
1095 } else if (pa_cvolume_ramp_target_active(ramp)) {
1096 pa_memchunk_make_writable(chunk, 0);
1097 pa_cvolume_ramp_get_targets(ramp, &target);
1098 pa_volume_memchunk(chunk, spec, &target);
1103 /* Called from thread context */
1104 void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa_memchunk *chunk, pa_cvolume *volume) {
1105 bool do_volume_adj_here, need_volume_factor_sink;
1106 bool volume_is_norm;
1107 #ifdef TIZEN_VOLUME_RAMP
1108 bool prev_ramp_finished = false;
1110 size_t block_size_max_sink, block_size_max_sink_input;
1112 size_t ilength_full;
1114 pa_sink_input_assert_ref(i);
1115 pa_sink_input_assert_io_context(i);
1116 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1117 pa_assert(pa_frame_aligned(slength, &i->sink->sample_spec));
1121 #ifdef SINK_INPUT_DEBUG
1123 pa_log_debug("peek, idx(%u)", i->index);
1125 pa_log_debug("peek");
1129 block_size_max_sink_input = i->thread_info.resampler ?
1130 pa_resampler_max_block_size(i->thread_info.resampler) :
1131 pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sample_spec);
1133 block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sink->sample_spec);
1135 /* Default buffer size */
1137 slength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec);
1139 if (slength > block_size_max_sink)
1140 slength = block_size_max_sink;
1142 if (i->thread_info.resampler) {
1143 ilength = pa_resampler_request(i->thread_info.resampler, slength);
1146 ilength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
1150 /* Length corresponding to slength (without limiting to
1151 * block_size_max_sink_input). */
1152 ilength_full = ilength;
1154 if (ilength > block_size_max_sink_input)
1155 ilength = block_size_max_sink_input;
1157 /* If the channel maps of the sink and this stream differ, we need
1158 * to adjust the volume *before* we resample. Otherwise we can do
1159 * it after and leave it for the sink code */
1161 do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
1162 volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
1163 need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);
1165 while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
1168 /* There's nothing in our render queue. We need to fill it up
1169 * with data from the implementor. */
1171 if (i->thread_info.state == PA_SINK_INPUT_CORKED ||
1172 i->pop(i, ilength, &tchunk) < 0) {
1174 /* OK, we're corked or the implementor didn't give us any
1175 * data, so let's just hand out silence */
1177 pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE, true);
1178 i->thread_info.playing_for = 0;
1179 if (i->thread_info.underrun_for != (uint64_t) -1) {
1180 i->thread_info.underrun_for += ilength_full;
1181 i->thread_info.underrun_for_sink += slength;
1186 pa_assert(tchunk.length > 0);
1187 pa_assert(tchunk.memblock);
1189 i->thread_info.underrun_for = 0;
1190 i->thread_info.underrun_for_sink = 0;
1191 i->thread_info.playing_for += tchunk.length;
1193 while (tchunk.length > 0) {
1195 bool nvfs = need_volume_factor_sink;
1198 pa_memblock_ref(wchunk.memblock);
1200 if (wchunk.length > block_size_max_sink_input)
1201 wchunk.length = block_size_max_sink_input;
1203 /* It might be necessary to adjust the volume here */
1204 if (do_volume_adj_here && !volume_is_norm) {
1205 pa_memchunk_make_writable(&wchunk, 0);
1207 if (i->thread_info.muted) {
1208 pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
1211 } else if (!i->thread_info.resampler && nvfs) {
1214 /* If we don't need a resampler we can merge the
1215 * post and the pre volume adjustment into one */
1217 pa_sw_cvolume_multiply(&v, &i->thread_info.soft_volume, &i->volume_factor_sink);
1218 pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &v);
1222 pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);
1225 #ifdef TIZEN_VOLUME_RAMP
1226 check_and_apply_silence(i);
1228 prev_ramp_finished = i->thread_info.ramp.finished;
1230 if (!i->thread_info.resampler) {
1233 pa_memchunk_make_writable(&wchunk, 0);
1234 pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
1237 #ifdef TIZEN_VOLUME_RAMP
1238 check_and_apply_ramp(&i->thread_info.ramp, &i->sink->sample_spec, &wchunk);
1240 pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
1243 #ifdef TIZEN_VOLUME_RAMP
1244 check_and_apply_ramp(&i->thread_info.ramp, &i->thread_info.sample_spec, &wchunk);
1246 pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
1248 #ifdef SINK_INPUT_DEBUG
1249 pa_log_debug("pushing %lu", (unsigned long) rchunk.length);
1252 if (rchunk.memblock) {
1255 pa_memchunk_make_writable(&rchunk, 0);
1256 pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
1259 pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
1260 pa_memblock_unref(rchunk.memblock);
1264 pa_memblock_unref(wchunk.memblock);
1266 tchunk.index += wchunk.length;
1267 tchunk.length -= wchunk.length;
1270 pa_memblock_unref(tchunk.memblock);
1273 pa_assert_se(pa_memblockq_peek(i->thread_info.render_memblockq, chunk) >= 0);
1275 pa_assert(chunk->length > 0);
1276 pa_assert(chunk->memblock);
1278 #ifdef SINK_INPUT_DEBUG
1279 pa_log_debug("peeking %lu", (unsigned long) chunk->length);
1282 if (chunk->length > block_size_max_sink)
1283 chunk->length = block_size_max_sink;
1285 /* Let's see if we had to apply the volume adjustment ourselves,
1286 * or if this can be done by the sink for us */
1288 if (do_volume_adj_here)
1289 /* We had different channel maps, so we already did the adjustment */
1290 pa_cvolume_reset(volume, i->sink->sample_spec.channels);
1291 else if (i->thread_info.muted)
1292 /* We've both the same channel map, so let's have the sink do the adjustment for us*/
1293 pa_cvolume_mute(volume, i->sink->sample_spec.channels);
1295 *volume = i->thread_info.soft_volume;
1296 #ifdef TIZEN_PCM_DUMP
1297 pa_sink_input_write_pcm_dump(i, chunk);
1299 #ifdef TIZEN_VOLUME_RAMP
1300 /* Hook fire only if ramp is finished. Note that it does not mean all the ramped data
1301 * is written to the device, hence it needs to be improved later on. */
1302 if (!prev_ramp_finished && i->thread_info.ramp.finished) {
1303 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_RAMP_FINISH], i);
1304 i->thread_info.ramp.finished = false;
1309 /* Called from thread context */
1310 void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
1312 pa_sink_input_assert_ref(i);
1313 pa_sink_input_assert_io_context(i);
1314 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1315 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1316 pa_assert(nbytes > 0);
1318 #ifdef SINK_INPUT_DEBUG
1319 pa_log_debug("dropping %lu", (unsigned long) nbytes);
1321 #ifdef TIZEN_PCM_DUMP
1322 if (i->pcm_dump_fp && i->dump_length) {
1323 int64_t seek_length;
1325 seek_length = (int64_t) (nbytes - i->dump_length);
1327 if (seek_length < 0)
1328 fseeko(i->pcm_dump_fp, (off_t)seek_length, SEEK_CUR);
1334 pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
1337 /* Called from thread context */
1338 bool pa_sink_input_process_underrun(pa_sink_input *i) {
1339 pa_sink_input_assert_ref(i);
1340 pa_sink_input_assert_io_context(i);
1342 if (pa_memblockq_is_readable(i->thread_info.render_memblockq))
1345 if (i->process_underrun && i->process_underrun(i)) {
1346 /* All valid data has been played back, so we can empty this queue. */
1347 pa_memblockq_silence(i->thread_info.render_memblockq);
1353 /* Called from thread context */
1354 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
1356 bool called = false;
1358 pa_sink_input_assert_ref(i);
1359 pa_sink_input_assert_io_context(i);
1360 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1361 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1363 #ifdef SINK_INPUT_DEBUG
1364 pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes);
1367 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
1369 if (nbytes > 0 && !i->thread_info.dont_rewind_render) {
1370 pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
1371 pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
1374 if (i->thread_info.rewrite_nbytes == (size_t) -1) {
1376 #ifdef TIZEN_PCM_DUMP
1379 fseeko(i->pcm_dump_fp, (off_t)pa_memblockq_get_length(i->thread_info.render_memblockq) * (-1), SEEK_CUR);
1381 /* We were asked to drop all buffered data, and rerequest new
1382 * data from implementor the next time peek() is called */
1384 pa_memblockq_flush_write(i->thread_info.render_memblockq, true);
1386 } else if (i->thread_info.rewrite_nbytes > 0) {
1387 size_t max_rewrite, amount;
1389 /* Calculate how much make sense to rewrite at most */
1390 max_rewrite = nbytes;
1394 /* Transform into local domain */
1395 if (i->thread_info.resampler)
1396 max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
1398 /* Calculate how much of the rewinded data should actually be rewritten */
1399 amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
1402 pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
1404 #ifdef TIZEN_PCM_DUMP
1407 fseeko(i->pcm_dump_fp, (off_t)amount * (-1), SEEK_CUR);
1409 /* Tell the implementor */
1410 if (i->process_rewind)
1411 i->process_rewind(i, amount);
1414 /* Convert back to sink domain */
1415 if (i->thread_info.resampler)
1416 amount = pa_resampler_result(i->thread_info.resampler, amount);
1419 /* Ok, now update the write pointer */
1420 pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE, true);
1422 if (i->thread_info.rewrite_flush)
1423 pa_memblockq_silence(i->thread_info.render_memblockq);
1425 /* And rewind the resampler */
1426 if (i->thread_info.resampler)
1427 pa_resampler_rewind(i->thread_info.resampler, amount);
1432 if (i->process_rewind)
1433 i->process_rewind(i, 0);
1435 i->thread_info.rewrite_nbytes = 0;
1436 i->thread_info.rewrite_flush = false;
1437 i->thread_info.dont_rewind_render = false;
1440 /* Called from thread context */
1441 size_t pa_sink_input_get_max_rewind(pa_sink_input *i) {
1442 pa_sink_input_assert_ref(i);
1443 pa_sink_input_assert_io_context(i);
1445 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_rewind) : i->sink->thread_info.max_rewind;
1448 /* Called from thread context */
1449 size_t pa_sink_input_get_max_request(pa_sink_input *i) {
1450 pa_sink_input_assert_ref(i);
1451 pa_sink_input_assert_io_context(i);
1453 /* We're not verifying the status here, to allow this to be called
1454 * in the state change handler between _INIT and _RUNNING */
1456 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_request) : i->sink->thread_info.max_request;
1459 /* Called from thread context */
1460 void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
1461 pa_sink_input_assert_ref(i);
1462 pa_sink_input_assert_io_context(i);
1463 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1464 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1466 pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
1468 if (i->update_max_rewind)
1469 i->update_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
1472 /* Called from thread context */
1473 void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
1474 pa_sink_input_assert_ref(i);
1475 pa_sink_input_assert_io_context(i);
1476 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1477 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1479 if (i->update_max_request)
1480 i->update_max_request(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
1483 /* Called from thread context */
1484 pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
1485 pa_sink_input_assert_ref(i);
1486 pa_sink_input_assert_io_context(i);
1488 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1489 usec = i->sink->thread_info.fixed_latency;
1491 if (usec != (pa_usec_t) -1)
1492 usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
1494 i->thread_info.requested_sink_latency = usec;
1495 pa_sink_invalidate_requested_latency(i->sink, true);
1500 /* Called from main context */
1501 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
1502 pa_sink_input_assert_ref(i);
1503 pa_assert_ctl_context();
1505 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1506 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1510 /* If this sink input is not realized yet or we are being moved,
1511 * we have to touch the thread info data directly */
1514 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1515 usec = pa_sink_get_fixed_latency(i->sink);
1517 if (usec != (pa_usec_t) -1) {
1518 pa_usec_t min_latency, max_latency;
1519 pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
1520 usec = PA_CLAMP(usec, min_latency, max_latency);
1524 i->thread_info.requested_sink_latency = usec;
1529 /* Called from main context */
1530 pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
1531 pa_sink_input_assert_ref(i);
1532 pa_assert_ctl_context();
1534 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1536 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1540 /* If this sink input is not realized yet or we are being moved,
1541 * we have to touch the thread info data directly */
1543 return i->thread_info.requested_sink_latency;
1546 /* Called from main context */
1547 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool save, bool absolute) {
1550 pa_sink_input_assert_ref(i);
1551 pa_assert_ctl_context();
1552 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1554 pa_assert(pa_cvolume_valid(volume));
1555 pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
1556 pa_assert(i->volume_writable);
1558 if (!absolute && pa_sink_flat_volume_enabled(i->sink)) {
1559 v = i->sink->reference_volume;
1560 pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
1562 if (pa_cvolume_compatible(volume, &i->sample_spec))
1563 volume = pa_sw_cvolume_multiply(&v, &v, volume);
1565 volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume));
1567 if (!pa_cvolume_compatible(volume, &i->sample_spec)) {
1569 volume = pa_cvolume_scale(&v, pa_cvolume_max(volume));
1573 if (pa_cvolume_equal(volume, &i->volume)) {
1574 i->save_volume = i->save_volume || save;
1578 pa_sink_input_set_volume_direct(i, volume);
1579 i->save_volume = save;
1581 if (pa_sink_flat_volume_enabled(i->sink)) {
1582 /* We are in flat volume mode, so let's update all sink input
1583 * volumes and update the flat volume of the sink */
1585 pa_sink_set_volume(i->sink, NULL, true, save);
1588 /* OK, we are in normal volume mode. The volume only affects
1590 set_real_ratio(i, volume);
1591 pa_sink_input_set_reference_ratio(i, &i->volume);
1593 /* Copy the new soft_volume to the thread_info struct */
1594 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1598 void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa_cvolume *volume_factor) {
1599 struct volume_factor_entry *v;
1601 pa_sink_input_assert_ref(i);
1602 pa_assert_ctl_context();
1603 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1604 pa_assert(volume_factor);
1606 pa_assert(pa_cvolume_valid(volume_factor));
1607 pa_assert(volume_factor->channels == 1 || pa_cvolume_compatible(volume_factor, &i->sample_spec));
1609 v = volume_factor_entry_new(key, volume_factor);
1610 if (!pa_cvolume_compatible(volume_factor, &i->sample_spec))
1611 pa_cvolume_set(&v->volume, i->sample_spec.channels, volume_factor->values[0]);
1613 pa_assert_se(pa_hashmap_put(i->volume_factor_items, v->key, v) >= 0);
1614 if (pa_hashmap_size(i->volume_factor_items) == 1)
1615 i->volume_factor = v->volume;
1617 pa_sw_cvolume_multiply(&i->volume_factor, &i->volume_factor, &v->volume);
1619 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1621 /* Copy the new soft_volume to the thread_info struct */
1622 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1625 /* Returns 0 if an entry was removed and -1 if no entry for the given key was
1627 int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) {
1628 struct volume_factor_entry *v;
1630 pa_sink_input_assert_ref(i);
1632 pa_assert_ctl_context();
1633 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1635 if (pa_hashmap_remove_and_free(i->volume_factor_items, key) < 0)
1638 switch (pa_hashmap_size(i->volume_factor_items)) {
1640 pa_cvolume_reset(&i->volume_factor, i->sample_spec.channels);
1643 v = pa_hashmap_first(i->volume_factor_items);
1644 i->volume_factor = v->volume;
1647 volume_factor_from_hashmap(&i->volume_factor, i->volume_factor_items, i->volume_factor.channels);
1650 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1652 #ifdef TIZEN_VOLUME_RAMP
1653 /* If a ramp was set, skip rewinding. It'll be rewinded with SET_VOLUME_RAMP later. */
1654 if (pa_cvolume_ramp_target_active(&i->ramp)) {
1655 bool skip_rewind = true;
1656 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, &skip_rewind, 0, NULL) == 0);
1659 /* Copy the new soft_volume to the thread_info struct */
1660 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1661 #ifdef TIZEN_VOLUME_RAMP
1668 #ifdef TIZEN_VOLUME_RAMP
1669 void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg) {
1670 struct volume_ramp_factor_entry *r;
1672 pa_sink_input_assert_ref(i);
1673 pa_assert_ctl_context();
1674 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1675 pa_assert(ramp_factor);
1677 pa_assert(pa_cvolume_ramp_valid(ramp_factor));
1678 pa_assert(ramp_factor->channels == 1 || pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec));
1680 r = volume_ramp_factor_entry_new(key, ramp_factor);
1681 if (!pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec))
1682 pa_cvolume_ramp_set(&r->ramp, i->sample_spec.channels,
1683 ramp_factor->ramps[0].type,
1684 ramp_factor->ramps[0].length,
1685 ramp_factor->ramps[0].target);
1687 pa_assert_se(pa_hashmap_put(i->ramp_factor_items, r->key, r) >= 0);
1688 if (pa_hashmap_size(i->ramp_factor_items) == 1)
1689 pa_cvolume_ramp_set(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length, r->ramp.ramps[0].target);
1691 pa_sw_cvolume_ramp_multiply(&i->ramp_factor, &i->ramp_factor, &r->ramp);
1693 pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate);
1696 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
1699 /* Returns 0 if an entry was removed and -1 if no entry for the given key was
1701 int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg) {
1702 struct volume_ramp_factor_entry *r;
1704 pa_sink_input_assert_ref(i);
1706 pa_assert_ctl_context();
1707 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1709 r = pa_hashmap_remove(i->ramp_factor_items, key);
1713 switch (pa_hashmap_size(i->ramp_factor_items)) {
1715 pa_cvolume_ramp_reset(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length);
1718 struct volume_ramp_factor_entry *rf;
1719 if ((rf = pa_hashmap_first(i->ramp_factor_items)))
1720 pa_cvolume_ramp_set(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length, rf->ramp.ramps[0].target);
1724 volume_ramp_factor_from_hashmap(&i->ramp_factor, i->ramp_factor_items, i->ramp_factor.channels, i->ramp_factor.ramps[0].type, i->ramp_factor.ramps[0].length);
1727 volume_ramp_factor_entry_free(r);
1729 pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate);
1732 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
1737 /* Called from main context */
1738 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {
1739 pa_sink_input_assert_ref(i);
1740 pa_assert_ctl_context();
1741 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1742 pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
1744 /* This basically calculates:
1746 * i->real_ratio := v
1747 * i->soft_volume := i->real_ratio * i->volume_factor */
1752 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
1754 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1755 /* We don't copy the data to the thread_info data. That's left for someone else to do */
1758 /* Called from main or I/O context */
1759 bool pa_sink_input_is_passthrough(pa_sink_input *i) {
1760 pa_sink_input_assert_ref(i);
1762 if (PA_UNLIKELY(!pa_format_info_is_pcm(i->format)))
1765 if (PA_UNLIKELY(i->flags & PA_SINK_INPUT_PASSTHROUGH))
1771 /* Called from main context */
1772 bool pa_sink_input_is_volume_readable(pa_sink_input *i) {
1773 pa_sink_input_assert_ref(i);
1774 pa_assert_ctl_context();
1776 return !pa_sink_input_is_passthrough(i);
1779 /* Called from main context */
1780 pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute) {
1781 pa_sink_input_assert_ref(i);
1782 pa_assert_ctl_context();
1783 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1784 pa_assert(pa_sink_input_is_volume_readable(i));
1786 if (absolute || !pa_sink_flat_volume_enabled(i->sink))
1787 *volume = i->volume;
1789 *volume = i->reference_ratio;
1794 /* Called from main context */
1795 void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save) {
1798 pa_sink_input_assert_ref(i);
1799 pa_assert_ctl_context();
1800 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1802 old_mute = i->muted;
1804 if (mute == old_mute) {
1805 i->save_muted |= save;
1810 pa_log_debug("The mute of sink input %u changed from %s to %s.", i->index, pa_yes_no(old_mute), pa_yes_no(mute));
1812 i->save_muted = save;
1814 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
1816 /* The mute status changed, let's tell people so */
1817 if (i->mute_changed)
1820 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1821 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MUTE_CHANGED], i);
1824 void pa_sink_input_set_property(pa_sink_input *i, const char *key, const char *value) {
1825 char *old_value = NULL;
1826 const char *new_value;
1831 if (pa_proplist_contains(i->proplist, key)) {
1832 old_value = pa_xstrdup(pa_proplist_gets(i->proplist, key));
1833 if (value && old_value && pa_streq(value, old_value))
1837 old_value = pa_xstrdup("(data)");
1842 old_value = pa_xstrdup("(unset)");
1846 pa_proplist_sets(i->proplist, key, value);
1849 pa_proplist_unset(i->proplist, key);
1850 new_value = "(unset)";
1853 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1854 pa_log_debug("Sink input %u: proplist[%s]: %s -> %s", i->index, key, old_value, new_value);
1855 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1856 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1860 pa_xfree(old_value);
1863 void pa_sink_input_set_property_arbitrary(pa_sink_input *i, const char *key, const uint8_t *value, size_t nbytes) {
1864 const uint8_t *old_value;
1866 const char *old_value_str;
1867 const char *new_value_str;
1872 if (pa_proplist_get(i->proplist, key, (const void **) &old_value, &old_nbytes) >= 0) {
1873 if (value && nbytes == old_nbytes && !memcmp(value, old_value, nbytes))
1876 old_value_str = "(data)";
1882 old_value_str = "(unset)";
1886 pa_proplist_set(i->proplist, key, value, nbytes);
1887 new_value_str = "(data)";
1889 pa_proplist_unset(i->proplist, key);
1890 new_value_str = "(unset)";
1893 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1894 pa_log_debug("Sink input %u: proplist[%s]: %s -> %s", i->index, key, old_value_str, new_value_str);
1895 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1896 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1900 /* Called from main thread */
1901 void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
1904 const uint8_t *value;
1907 pa_sink_input_assert_ref(i);
1909 pa_assert_ctl_context();
1913 /* Delete everything that is not in p. */
1914 for (state = NULL; (key = pa_proplist_iterate(i->proplist, &state));) {
1915 if (!pa_proplist_contains(p, key))
1916 pa_sink_input_set_property(i, key, NULL);
1920 case PA_UPDATE_REPLACE:
1921 for (state = NULL; (key = pa_proplist_iterate(p, &state));) {
1922 pa_proplist_get(p, key, (const void **) &value, &nbytes);
1923 pa_sink_input_set_property_arbitrary(i, key, value, nbytes);
1927 case PA_UPDATE_MERGE:
1928 for (state = NULL; (key = pa_proplist_iterate(p, &state));) {
1929 if (pa_proplist_contains(i->proplist, key))
1932 pa_proplist_get(p, key, (const void **) &value, &nbytes);
1933 pa_sink_input_set_property_arbitrary(i, key, value, nbytes);
1940 /* Called from main context */
1941 void pa_sink_input_cork(pa_sink_input *i, bool b) {
1942 pa_sink_input_assert_ref(i);
1943 pa_assert_ctl_context();
1944 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1946 sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
1949 /* Called from main context */
1950 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
1951 pa_sink_input_assert_ref(i);
1952 pa_assert_ctl_context();
1953 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1954 pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE);
1956 if (i->sample_spec.rate == rate)
1959 i->sample_spec.rate = rate;
1962 pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
1964 i->thread_info.sample_spec.rate = rate;
1965 pa_resampler_set_input_rate(i->thread_info.resampler, rate);
1968 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1972 /* Called from main context */
1973 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
1974 pa_sink_input_assert_ref(i);
1975 pa_assert_ctl_context();
1977 return i->actual_resample_method;
1980 /* Called from main context */
1981 bool pa_sink_input_may_move(pa_sink_input *i) {
1982 pa_sink_input_assert_ref(i);
1983 pa_assert_ctl_context();
1984 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1986 if (i->flags & PA_SINK_INPUT_DONT_MOVE)
1989 if (i->sync_next || i->sync_prev) {
1990 pa_log_warn("Moving synchronized streams not supported.");
1997 static bool find_filter_sink_input(pa_sink_input *target, pa_sink *s) {
1998 unsigned PA_UNUSED i = 0;
1999 while (s && s->input_to_master) {
2000 if (s->input_to_master == target)
2002 s = s->input_to_master->sink;
2003 pa_assert(i++ < 100);
2008 static bool is_filter_sink_moving(pa_sink_input *i) {
2009 pa_sink *sink = i->sink;
2014 while (sink->input_to_master) {
2015 sink = sink->input_to_master->sink;
2024 /* Called from main context */
2025 bool pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
2026 pa_sink_input_assert_ref(i);
2027 pa_assert_ctl_context();
2028 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2029 pa_sink_assert_ref(dest);
2031 if (dest == i->sink)
2034 if (dest->unlink_requested)
2037 if (!pa_sink_input_may_move(i))
2040 /* Make sure we're not creating a filter sink cycle */
2041 if (find_filter_sink_input(i, dest)) {
2042 pa_log_debug("Can't connect input to %s, as that would create a cycle.", dest->name);
2046 /* If this sink input is connected to a filter sink that itself is moving,
2047 * then don't allow the move. Moving requires sending a message to the IO
2048 * thread of the old sink, and if the old sink is a filter sink that is
2049 * moving, there's no IO thread associated to the old sink. */
2050 if (is_filter_sink_moving(i)) {
2051 pa_log_debug("Can't move input from filter sink %s, because the filter sink itself is currently moving.",
2056 if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
2057 pa_log_warn("Failed to move sink input: too many inputs per sink.");
2061 if (check_passthrough_connection(pa_sink_input_is_passthrough(i), dest) < 0)
2065 if (!i->may_move_to(i, dest))
2071 /* Called from main context */
2072 int pa_sink_input_start_move(pa_sink_input *i) {
2073 pa_source_output *o, PA_UNUSED *p = NULL;
2074 struct volume_factor_entry *v;
2078 pa_sink_input_assert_ref(i);
2079 pa_assert_ctl_context();
2080 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2083 if (!pa_sink_input_may_move(i))
2084 return -PA_ERR_NOTSUPPORTED;
2086 if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
2089 pa_log_debug("Starting to move sink input %u from '%s'", (unsigned) i->index, i->sink->name);
2091 /* Kill directly connected outputs */
2092 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
2094 pa_source_output_kill(o);
2097 pa_assert(pa_idxset_isempty(i->direct_outputs));
2099 pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
2101 if (i->state == PA_SINK_INPUT_CORKED)
2102 pa_assert_se(i->sink->n_corked-- >= 1);
2104 if (pa_sink_input_is_passthrough(i))
2105 pa_sink_leave_passthrough(i->sink);
2107 if (pa_sink_flat_volume_enabled(i->sink))
2108 /* We might need to update the sink's volume if we are in flat
2110 pa_sink_set_volume(i->sink, NULL, false, false);
2112 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
2114 pa_sink_update_status(i->sink);
2116 PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
2117 pa_cvolume_remap(&v->volume, &i->sink->channel_map, &i->channel_map);
2119 pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
2122 i->sink_requested_by_application = false;
2124 pa_sink_input_unref(i);
2129 /* Called from main context. If i has an origin sink that uses volume sharing,
2130 * then also the origin sink and all streams connected to it need to update
2131 * their volume - this function does all that by using recursion. */
2132 static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) {
2133 pa_cvolume new_volume;
2137 pa_assert(i->sink); /* The destination sink should already be set. */
2139 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
2140 pa_sink *root_sink = pa_sink_get_master(i->sink);
2141 pa_sink_input *origin_sink_input;
2144 if (PA_UNLIKELY(!root_sink))
2147 if (pa_sink_flat_volume_enabled(i->sink)) {
2148 /* Ok, so the origin sink uses volume sharing, and flat volume is
2149 * enabled. The volume will have to be updated as follows:
2151 * i->volume := i->sink->real_volume
2152 * (handled later by pa_sink_set_volume)
2153 * i->reference_ratio := i->volume / i->sink->reference_volume
2154 * (handled later by pa_sink_set_volume)
2155 * i->real_ratio stays unchanged
2156 * (streams whose origin sink uses volume sharing should
2157 * always have real_ratio of 0 dB)
2158 * i->soft_volume stays unchanged
2159 * (streams whose origin sink uses volume sharing should
2160 * always have volume_factor as soft_volume, so no change
2161 * should be needed) */
2163 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
2164 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
2166 /* Notifications will be sent by pa_sink_set_volume(). */
2169 /* Ok, so the origin sink uses volume sharing, and flat volume is
2170 * disabled. The volume will have to be updated as follows:
2173 * i->reference_ratio := 0 dB
2174 * i->real_ratio stays unchanged
2175 * (streams whose origin sink uses volume sharing should
2176 * always have real_ratio of 0 dB)
2177 * i->soft_volume stays unchanged
2178 * (streams whose origin sink uses volume sharing should
2179 * always have volume_factor as soft_volume, so no change
2180 * should be needed) */
2182 pa_cvolume_reset(&new_volume, i->volume.channels);
2183 pa_sink_input_set_volume_direct(i, &new_volume);
2184 pa_sink_input_set_reference_ratio(i, &new_volume);
2185 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
2186 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
2189 /* Additionally, the origin sink volume needs updating:
2191 * i->origin_sink->reference_volume := root_sink->reference_volume
2192 * i->origin_sink->real_volume := root_sink->real_volume
2193 * i->origin_sink->soft_volume stays unchanged
2194 * (sinks that use volume sharing should always have
2195 * soft_volume of 0 dB) */
2197 new_volume = root_sink->reference_volume;
2198 pa_cvolume_remap(&new_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
2199 pa_sink_set_reference_volume_direct(i->origin_sink, &new_volume);
2201 i->origin_sink->real_volume = root_sink->real_volume;
2202 pa_cvolume_remap(&i->origin_sink->real_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
2204 pa_assert(pa_cvolume_is_norm(&i->origin_sink->soft_volume));
2206 /* If you wonder whether i->origin_sink->set_volume() should be called
2207 * somewhere, that's not the case, because sinks that use volume
2208 * sharing shouldn't have any internal volume that set_volume() would
2209 * update. If you wonder whether the thread_info variables should be
2210 * synced, yes, they should, and it's done by the
2211 * PA_SINK_MESSAGE_FINISH_MOVE message handler. */
2213 /* Recursively update origin sink inputs. */
2214 PA_IDXSET_FOREACH(origin_sink_input, i->origin_sink->inputs, idx)
2215 update_volume_due_to_moving(origin_sink_input, dest);
2218 if (pa_sink_flat_volume_enabled(i->sink)) {
2219 /* Ok, so this is a regular stream, and flat volume is enabled. The
2220 * volume will have to be updated as follows:
2222 * i->volume := i->reference_ratio * i->sink->reference_volume
2223 * i->reference_ratio stays unchanged
2224 * i->real_ratio := i->volume / i->sink->real_volume
2225 * (handled later by pa_sink_set_volume)
2226 * i->soft_volume := i->real_ratio * i->volume_factor
2227 * (handled later by pa_sink_set_volume) */
2229 new_volume = i->sink->reference_volume;
2230 pa_cvolume_remap(&new_volume, &i->sink->channel_map, &i->channel_map);
2231 pa_sw_cvolume_multiply(&new_volume, &new_volume, &i->reference_ratio);
2232 pa_sink_input_set_volume_direct(i, &new_volume);
2235 /* Ok, so this is a regular stream, and flat volume is disabled.
2236 * The volume will have to be updated as follows:
2238 * i->volume := i->reference_ratio
2239 * i->reference_ratio stays unchanged
2240 * i->real_ratio := i->reference_ratio
2241 * i->soft_volume := i->real_ratio * i->volume_factor */
2243 pa_sink_input_set_volume_direct(i, &i->reference_ratio);
2244 i->real_ratio = i->reference_ratio;
2245 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
2249 /* If i->sink == dest, then recursion has finished, and we can finally call
2250 * pa_sink_set_volume(), which will do the rest of the updates. */
2251 if ((i->sink == dest) && pa_sink_flat_volume_enabled(i->sink))
2252 pa_sink_set_volume(i->sink, NULL, false, i->save_volume);
2255 /* Called from the main thread. */
2256 static void set_preferred_sink(pa_sink_input *i, const char *sink_name) {
2259 if (pa_safe_streq(i->preferred_sink, sink_name))
2262 pa_log_debug("Sink input %u: preferred_sink: %s -> %s",
2263 i->index, i->preferred_sink ? i->preferred_sink : "(unset)", sink_name ? sink_name : "(unset)");
2264 pa_xfree(i->preferred_sink);
2265 i->preferred_sink = pa_xstrdup(sink_name);
2267 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2268 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PREFERRED_SINK_CHANGED], i);
2271 /* Called from main context */
2272 int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, bool save) {
2273 struct volume_factor_entry *v;
2276 pa_sink_input_assert_ref(i);
2277 pa_assert_ctl_context();
2278 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2279 pa_assert(!i->sink);
2280 pa_sink_assert_ref(dest);
2282 if (!pa_sink_input_may_move_to(i, dest))
2283 return -PA_ERR_NOTSUPPORTED;
2285 if (pa_sink_input_is_passthrough(i) && !pa_sink_check_format(dest, i->format)) {
2286 pa_proplist *p = pa_proplist_new();
2287 pa_log_debug("New sink doesn't support stream format, sending format-changed and killing");
2288 /* Tell the client what device we want to be on if it is going to
2290 pa_proplist_sets(p, "device", dest->name);
2291 pa_sink_input_send_event(i, PA_STREAM_EVENT_FORMAT_LOST, p);
2292 pa_proplist_free(p);
2293 return -PA_ERR_NOTSUPPORTED;
2296 if (!(i->flags & PA_SINK_INPUT_VARIABLE_RATE) &&
2297 !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec)) {
2298 /* try to change dest sink format and rate if possible without glitches.
2299 module-suspend-on-idle resumes destination sink with
2300 SINK_INPUT_MOVE_FINISH hook */
2302 pa_log_info("Trying to change sample spec");
2303 pa_sink_reconfigure(dest, &i->sample_spec, pa_sink_input_is_passthrough(i));
2310 /* save == true, means user is calling the move_to() and want to
2311 save the preferred_sink */
2313 if (dest == dest->core->default_sink)
2314 set_preferred_sink(i, NULL);
2316 set_preferred_sink(i, dest->name);
2319 pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
2321 PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
2322 pa_cvolume_remap(&v->volume, &i->channel_map, &i->sink->channel_map);
2324 pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
2326 if (i->state == PA_SINK_INPUT_CORKED)
2327 i->sink->n_corked++;
2329 pa_sink_input_update_resampler(i);
2331 pa_sink_update_status(dest);
2333 update_volume_due_to_moving(i, dest);
2335 if (pa_sink_input_is_passthrough(i))
2336 pa_sink_enter_passthrough(i->sink);
2338 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
2340 pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
2342 /* Notify everyone */
2343 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
2344 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2349 /* Called from main context */
2350 void pa_sink_input_fail_move(pa_sink_input *i) {
2352 pa_sink_input_assert_ref(i);
2353 pa_assert_ctl_context();
2354 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2355 pa_assert(!i->sink);
2357 /* Check if someone wants this sink input? */
2358 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_STOP)
2361 /* Can we move the sink input to the default sink? */
2362 if (i->core->rescue_streams && pa_sink_input_may_move_to(i, i->core->default_sink)) {
2363 if (pa_sink_input_finish_move(i, i->core->default_sink, false) >= 0)
2370 pa_sink_input_kill(i);
2373 /* Called from main context */
2374 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, bool save) {
2377 pa_sink_input_assert_ref(i);
2378 pa_assert_ctl_context();
2379 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2381 pa_sink_assert_ref(dest);
2383 if (dest == i->sink)
2386 if (!pa_sink_input_may_move_to(i, dest))
2387 return -PA_ERR_NOTSUPPORTED;
2389 pa_sink_input_ref(i);
2391 if ((r = pa_sink_input_start_move(i)) < 0) {
2392 pa_sink_input_unref(i);
2396 if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
2397 pa_sink_input_fail_move(i);
2398 pa_sink_input_unref(i);
2402 pa_sink_input_unref(i);
2407 /* Called from IO thread context except when cork() is called without a valid sink. */
2408 void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
2409 bool corking, uncorking;
2411 pa_sink_input_assert_ref(i);
2413 if (state == i->thread_info.state)
2416 #ifdef TIZEN_EMPTY_POP
2417 if (state != PA_SINK_INPUT_RUNNING && _empty_pop_is_started(i))
2418 _empty_pop_reset(i);
2420 corking = state == PA_SINK_INPUT_CORKED && i->thread_info.state == PA_SINK_INPUT_RUNNING;
2421 uncorking = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
2423 if (i->state_change)
2424 i->state_change(i, state);
2428 pa_log_debug("Requesting rewind due to corking");
2430 /* This will tell the implementing sink input driver to rewind
2431 * so that the unplayed already mixed data is not lost */
2433 pa_sink_input_request_rewind(i, 0, true, true, false);
2435 /* Set the corked state *after* requesting rewind */
2436 i->thread_info.state = state;
2438 } else if (uncorking) {
2440 pa_log_debug("Requesting rewind due to uncorking");
2442 i->thread_info.underrun_for = (uint64_t) -1;
2443 i->thread_info.underrun_for_sink = 0;
2444 i->thread_info.playing_for = 0;
2446 /* Set the uncorked state *before* requesting rewind */
2447 i->thread_info.state = state;
2449 /* OK, we're being uncorked. Make sure we're not rewound when
2450 * the hw buffer is remixed and request a remix. */
2452 pa_sink_input_request_rewind(i, 0, false, true, true);
2454 /* We may not be corking or uncorking, but we still need to set the state. */
2455 i->thread_info.state = state;
2458 /* Called from thread context, except when it is not. */
2459 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
2460 pa_sink_input *i = PA_SINK_INPUT(o);
2461 pa_sink_input_assert_ref(i);
2465 case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
2466 if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
2467 i->thread_info.soft_volume = i->soft_volume;
2468 #ifdef TIZEN_VOLUME_RAMP
2469 /* Skip rewinding */
2470 if (userdata && (bool)(*(bool*)userdata) == true)
2473 pa_sink_input_request_rewind(i, 0, true, false, false);
2477 #ifdef TIZEN_VOLUME_RAMP
2478 case PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP:
2479 /* we have ongoing ramp where we take current start values */
2480 pa_cvolume_ramp_start_from(&i->thread_info.ramp, &i->ramp);
2481 i->thread_info.ramp = i->ramp;
2482 pa_sink_input_request_rewind(i, 0, true, false, false);
2485 case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
2486 if (i->thread_info.muted != i->muted) {
2487 i->thread_info.muted = i->muted;
2488 pa_sink_input_request_rewind(i, 0, true, false, false);
2492 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
2493 pa_usec_t *r = userdata;
2495 r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
2496 r[1] += pa_sink_get_latency_within_thread(i->sink, false);
2501 case PA_SINK_INPUT_MESSAGE_SET_RATE:
2503 i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
2504 pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
2508 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
2509 pa_sink_input *ssync;
2511 pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
2513 for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
2514 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
2516 for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
2517 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
2522 case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
2523 pa_usec_t *usec = userdata;
2525 *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
2529 case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
2530 pa_usec_t *r = userdata;
2532 *r = i->thread_info.requested_sink_latency;
2537 return -PA_ERR_NOTIMPLEMENTED;
2540 /* Called from IO context */
2541 bool pa_sink_input_safe_to_remove(pa_sink_input *i) {
2542 pa_sink_input_assert_ref(i);
2543 pa_sink_input_assert_io_context(i);
2545 if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
2546 return pa_memblockq_is_empty(i->thread_info.render_memblockq);
2551 /* Called from IO context */
2552 void pa_sink_input_request_rewind(
2554 size_t nbytes /* in our sample spec */,
2555 bool rewrite, /* rewrite what we have, or get fresh data? */
2556 bool flush, /* flush render memblockq? */
2557 bool dont_rewind_render) {
2561 /* If 'rewrite' is true the sink is rewound as far as requested
2562 * and possible and the exact value of this is passed back the
2563 * implementor via process_rewind(). If 'flush' is also true all
2564 * already rendered data is also dropped.
2566 * If 'rewrite' is false the sink is rewound as far as requested
2567 * and possible and the already rendered data is dropped so that
2568 * in the next iteration we read new data from the
2569 * implementor. This implies 'flush' is true. If
2570 * dont_rewind_render is true then the render memblockq is not
2573 /* nbytes = 0 means maximum rewind request */
2575 pa_sink_input_assert_ref(i);
2576 pa_sink_input_assert_io_context(i);
2577 pa_assert(rewrite || flush);
2578 pa_assert(!dont_rewind_render || !rewrite);
2580 /* We don't take rewind requests while we are corked */
2581 if (i->thread_info.state == PA_SINK_INPUT_CORKED)
2584 nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
2586 #ifdef SINK_INPUT_DEBUG
2587 pa_log_debug("request rewrite %zu", nbytes);
2590 /* Calculate how much we can rewind locally without having to
2593 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
2597 /* Check if rewinding for the maximum is requested, and if so, fix up */
2600 /* Calculate maximum number of bytes that could be rewound in theory */
2601 nbytes = i->sink->thread_info.max_rewind + lbq;
2603 /* Transform from sink domain */
2604 if (i->thread_info.resampler)
2605 nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
2608 /* Remember how much we actually want to rewrite */
2609 if (i->thread_info.rewrite_nbytes != (size_t) -1) {
2611 /* Make sure to not overwrite over underruns */
2612 if (nbytes > i->thread_info.playing_for)
2613 nbytes = (size_t) i->thread_info.playing_for;
2615 i->thread_info.rewrite_nbytes = nbytes;
2617 i->thread_info.rewrite_nbytes = (size_t) -1;
2620 i->thread_info.rewrite_flush =
2621 i->thread_info.rewrite_flush || flush;
2623 i->thread_info.dont_rewind_render =
2624 i->thread_info.dont_rewind_render ||
2627 /* nbytes is -1 if some earlier rewind request had rewrite == false. */
2628 if (nbytes != (size_t) -1) {
2630 /* Transform to sink domain */
2631 if (i->thread_info.resampler)
2632 nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
2635 pa_sink_request_rewind(i->sink, nbytes - lbq);
2637 /* This call will make sure process_rewind() is called later */
2638 pa_sink_request_rewind(i->sink, 0);
2642 /* Called from main context */
2643 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
2644 pa_sink_input_assert_ref(i);
2645 pa_assert_ctl_context();
2648 /* FIXME: Shouldn't access resampler object from main context! */
2650 pa_silence_memchunk_get(
2651 &i->core->silence_cache,
2655 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
2660 #ifdef TIZEN_EMPTY_POP
2661 static void _empty_pop_start(pa_sink_input *i) {
2662 i->empty_pop_initial_timestamp = pa_rtclock_now();
2663 i->empty_pop_previous_duration = 0;
2665 pa_log_debug("[%u] empty pop started!!!", i->index);
2668 static bool _empty_pop_is_started(pa_sink_input *i) {
2669 if (i->empty_pop_initial_timestamp > 0)
2675 static uint32_t _empty_pop_calc_duration(pa_sink_input *i) {
2676 return (uint32_t)((pa_rtclock_now() - i->empty_pop_initial_timestamp) / PA_USEC_PER_SEC);
2679 static void _empty_pop_print_duration(pa_sink_input *i, uint32_t empty_pop_duration) {
2680 /* print only once per seconds */
2681 if (empty_pop_duration <= i->empty_pop_previous_duration)
2684 i->empty_pop_previous_duration = empty_pop_duration;
2686 pa_log_warn("[%u] empty pop (no sink-input data) for [%u] sec., timeout is [%u] sec.",
2687 i->index, empty_pop_duration, i->core->empty_pop_threshold);
2690 static void _empty_pop_reset(pa_sink_input *i) {
2691 i->empty_pop_initial_timestamp = 0;
2692 i->empty_pop_previous_duration = 0;
2694 pa_log_warn("[%u] empty pop reset...", i->index);
2697 void pa_sink_input_update_empty_pop(pa_sink_input *i, size_t length, bool *is_timeout) {
2698 pa_sink_input_assert_ref(i);
2699 pa_assert(is_timeout);
2702 if (_empty_pop_is_started(i)) {
2703 /* calculate empty pop duration in seconds */
2704 uint32_t empty_pop_duration = _empty_pop_calc_duration(i);
2705 if (empty_pop_duration >= i->core->empty_pop_threshold) {
2707 _empty_pop_reset(i);
2710 _empty_pop_print_duration(i, empty_pop_duration);
2712 _empty_pop_start(i);
2715 if (_empty_pop_is_started(i))
2716 _empty_pop_reset(i);
2719 *is_timeout = false;
2721 #endif /* TIZEN_EMPTY_POP */
2723 /* Called from the main thread. */
2724 void pa_sink_input_set_silence_to_first_peek(pa_sink_input *i, bool silence, pa_usec_t duration) {
2726 pa_sink_input_assert_ref(i);
2727 pa_assert_ctl_context();
2728 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2730 i->thread_info.silenced = silence;
2731 i->thread_info.silence_duration = duration;
2737 /* Called from main context */
2738 void pa_sink_input_send_event(pa_sink_input *i, const char *event, pa_proplist *data) {
2739 pa_proplist *pl = NULL;
2740 pa_sink_input_send_event_hook_data hook_data;
2742 pa_sink_input_assert_ref(i);
2743 pa_assert_ctl_context();
2750 data = pl = pa_proplist_new();
2752 hook_data.sink_input = i;
2753 hook_data.data = data;
2754 hook_data.event = event;
2756 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
2759 i->send_event(i, event, data);
2763 pa_proplist_free(pl);
2766 /* Called from main context */
2767 /* Updates the sink input's resampler with whatever the current sink requires
2768 * -- useful when the underlying sink's sample spec might have changed */
2769 int pa_sink_input_update_resampler(pa_sink_input *i) {
2770 pa_resampler *new_resampler;
2771 char *memblockq_name;
2773 pa_sink_input_assert_ref(i);
2774 pa_assert_ctl_context();
2776 if (i->thread_info.resampler &&
2777 pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &i->sink->sample_spec) &&
2778 pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &i->sink->channel_map))
2780 new_resampler = i->thread_info.resampler;
2782 else if (!pa_sink_input_is_passthrough(i) &&
2783 ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
2784 !pa_sample_spec_equal(&i->sample_spec, &i->sink->sample_spec) ||
2785 !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map))) {
2787 new_resampler = pa_resampler_new(i->core->mempool,
2788 &i->sample_spec, &i->channel_map,
2789 &i->sink->sample_spec, &i->sink->channel_map,
2790 i->core->lfe_crossover_freq,
2791 i->requested_resample_method,
2792 ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
2793 ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
2794 (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
2795 (i->core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
2796 (i->core->remixing_produce_lfe ? PA_RESAMPLER_PRODUCE_LFE : 0) |
2797 (i->core->remixing_consume_lfe ? PA_RESAMPLER_CONSUME_LFE : 0));
2799 if (!new_resampler) {
2800 pa_log_warn("Unsupported resampling operation.");
2801 return -PA_ERR_NOTSUPPORTED;
2804 new_resampler = NULL;
2806 if (new_resampler == i->thread_info.resampler)
2809 if (i->thread_info.resampler)
2810 pa_resampler_free(i->thread_info.resampler);
2812 i->thread_info.resampler = new_resampler;
2814 pa_memblockq_free(i->thread_info.render_memblockq);
2816 memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index);
2817 i->thread_info.render_memblockq = pa_memblockq_new(
2820 MEMBLOCKQ_MAXLENGTH,
2822 &i->sink->sample_spec,
2827 pa_xfree(memblockq_name);
2829 i->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID;
2831 pa_log_debug("Updated resampler for sink input %d", i->index);
2836 /* Called from the IO thread. */
2837 void pa_sink_input_attach(pa_sink_input *i) {
2839 pa_assert(!i->thread_info.attached);
2841 i->thread_info.attached = true;
2847 /* Called from the IO thread. */
2848 void pa_sink_input_detach(pa_sink_input *i) {
2851 if (!i->thread_info.attached)
2854 i->thread_info.attached = false;
2860 /* Called from the main thread. */
2861 void pa_sink_input_set_volume_direct(pa_sink_input *i, const pa_cvolume *volume) {
2862 pa_cvolume old_volume;
2863 char old_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2864 char new_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2869 old_volume = i->volume;
2871 if (pa_cvolume_equal(volume, &old_volume))
2874 i->volume = *volume;
2875 pa_log_debug("The volume of sink input %u changed from %s to %s.", i->index,
2876 pa_cvolume_snprint_verbose(old_volume_str, sizeof(old_volume_str), &old_volume, &i->channel_map, true),
2877 pa_cvolume_snprint_verbose(new_volume_str, sizeof(new_volume_str), volume, &i->channel_map, true));
2879 if (i->volume_changed)
2880 i->volume_changed(i);
2882 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2883 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_VOLUME_CHANGED], i);
2886 /* Called from the main thread. */
2887 void pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume *ratio) {
2888 pa_cvolume old_ratio;
2889 char old_ratio_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2890 char new_ratio_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2895 old_ratio = i->reference_ratio;
2897 if (pa_cvolume_equal(ratio, &old_ratio))
2900 i->reference_ratio = *ratio;
2902 if (!PA_SINK_INPUT_IS_LINKED(i->state))
2905 pa_log_debug("Sink input %u reference ratio changed from %s to %s.", i->index,
2906 pa_cvolume_snprint_verbose(old_ratio_str, sizeof(old_ratio_str), &old_ratio, &i->channel_map, true),
2907 pa_cvolume_snprint_verbose(new_ratio_str, sizeof(new_ratio_str), ratio, &i->channel_map, true));
2910 /* Called from the main thread.
2912 * This is called when e.g. module-stream-restore wants to change the preferred
2913 * sink. As a side effect the stream is moved to the new preferred sink. Note
2914 * that things can work also in the other direction: if the user moves
2915 * a stream, as a side effect the preferred sink is changed. This could cause
2916 * an infinite loop, but it's avoided by these two measures:
2917 * - When pa_sink_input_set_preferred_sink() is called, it calls
2918 * pa_sink_input_move_to() with save=false, which avoids the recursive
2919 * pa_sink_input_set_preferred_sink() call.
2920 * - When the primary operation is to move a stream,
2921 * pa_sink_input_finish_move() calls set_preferred_sink() instead of
2922 * pa_sink_input_set_preferred_sink(). set_preferred_sink() doesn't move
2923 * the stream as a side effect.
2925 void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s) {
2929 set_preferred_sink(i, s->name);
2930 pa_sink_input_move_to(i, s, false);
2932 set_preferred_sink(i, NULL);
2933 pa_sink_input_move_to(i, i->core->default_sink, false);
2938 void pa_sink_input_dump_info(pa_sink_input *i, unsigned int iteration, unsigned int total) {
2941 pa_log_warn(" #(%2u/%2u), index(%4u), client(%5d), sink(%2u), state(%d), muted(%s)"
2942 ", app(%s, %s), media(name:%s, role:%s)",
2943 iteration, total, i->index,
2944 i->client ? (int)i->client->index : -1,
2945 i->sink->index, i->state, pa_yes_no(i->muted),
2946 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_PROCESS_ID)),
2947 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)),
2948 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
2949 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_ROLE)));