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_PA_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_PA_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) {
305 pa_idxset *formats = NULL;
310 if (!data->req_formats) {
311 /* We're not working with the extended API */
313 data->save_sink = save;
315 /* Extended API: let's see if this sink supports the formats the client can provide */
316 formats = pa_sink_check_formats(s, data->req_formats);
318 if (formats && !pa_idxset_isempty(formats)) {
319 /* Sink supports at least one of the requested formats */
321 data->save_sink = save;
322 if (data->nego_formats)
323 pa_idxset_free(data->nego_formats, (pa_free_cb_t) pa_format_info_free);
324 data->nego_formats = formats;
326 /* Sink doesn't support any of the formats requested by the client */
328 pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
336 bool pa_sink_input_new_data_set_formats(pa_sink_input_new_data *data, pa_idxset *formats) {
340 if (data->req_formats)
341 pa_idxset_free(data->req_formats, (pa_free_cb_t) pa_format_info_free);
343 data->req_formats = formats;
346 /* Trigger format negotiation */
347 return pa_sink_input_new_data_set_sink(data, data->sink, data->save_sink);
353 void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
356 if (data->req_formats)
357 pa_idxset_free(data->req_formats, (pa_free_cb_t) pa_format_info_free);
359 if (data->nego_formats)
360 pa_idxset_free(data->nego_formats, (pa_free_cb_t) pa_format_info_free);
363 pa_format_info_free(data->format);
365 if (data->volume_factor_items)
366 pa_hashmap_free(data->volume_factor_items);
368 if (data->volume_factor_sink_items)
369 pa_hashmap_free(data->volume_factor_sink_items);
371 pa_proplist_free(data->proplist);
374 /* Called from main context */
375 static void reset_callbacks(pa_sink_input *i) {
379 i->process_underrun = NULL;
380 i->process_rewind = NULL;
381 i->update_max_rewind = NULL;
382 i->update_max_request = NULL;
383 i->update_sink_requested_latency = NULL;
384 i->update_sink_latency_range = NULL;
385 i->update_sink_fixed_latency = NULL;
389 i->suspend_within_thread = NULL;
392 i->get_latency = NULL;
393 i->state_change = NULL;
394 i->may_move_to = NULL;
395 i->send_event = NULL;
396 i->volume_changed = NULL;
397 i->mute_changed = NULL;
400 /* Called from main context */
401 int pa_sink_input_new(
404 pa_sink_input_new_data *data) {
407 pa_resampler *resampler = NULL;
408 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], fmt[PA_FORMAT_INFO_SNPRINT_MAX];
409 pa_channel_map volume_map;
412 char *memblockq_name;
417 pa_assert_ctl_context();
420 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
422 if (data->origin_sink && (data->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
423 data->volume_writable = false;
425 if (!data->req_formats) {
426 /* From this point on, we want to work only with formats, and get back
427 * to using the sample spec and channel map after all decisions w.r.t.
428 * routing are complete. */
432 f = pa_format_info_from_sample_spec2(&data->sample_spec, data->channel_map_is_set ? &data->channel_map : NULL,
433 !(data->flags & PA_SINK_INPUT_FIX_FORMAT),
434 !(data->flags & PA_SINK_INPUT_FIX_RATE),
435 !(data->flags & PA_SINK_INPUT_FIX_CHANNELS));
437 return -PA_ERR_INVALID;
439 formats = pa_idxset_new(NULL, NULL);
440 pa_idxset_put(formats, f, NULL);
441 pa_sink_input_new_data_set_formats(data, formats);
444 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0)
447 pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
450 pa_sink *sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK);
451 pa_return_val_if_fail(sink, -PA_ERR_NOENTITY);
452 pa_sink_input_new_data_set_sink(data, sink, false);
455 pa_sink_input_new_data_set_sink(data, data->sink, false);
459 /* If something didn't pick a format for us, pick the top-most format since
460 * we assume this is sorted in priority order */
461 if (!data->format && data->nego_formats && !pa_idxset_isempty(data->nego_formats))
462 data->format = pa_format_info_copy(pa_idxset_first(data->nego_formats, NULL));
464 if (PA_LIKELY(data->format)) {
465 pa_log_debug("Negotiated format: %s", pa_format_info_snprint(fmt, sizeof(fmt), data->format));
467 pa_format_info *format;
470 pa_log_info("Sink does not support any requested format:");
471 PA_IDXSET_FOREACH(format, data->req_formats, idx)
472 pa_log_info(" -- %s", pa_format_info_snprint(fmt, sizeof(fmt), format));
474 return -PA_ERR_NOTSUPPORTED;
477 pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)), -PA_ERR_BADSTATE);
478 pa_return_val_if_fail(!data->sync_base || (data->sync_base->sink == data->sink
479 && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED),
482 /* Routing is done. We have a sink and a format. */
484 if (data->volume_is_set && pa_format_info_is_pcm(data->format)) {
485 /* If volume is set, we need to save the original data->channel_map,
486 * so that we can remap the volume from the original channel map to the
487 * final channel map of the stream in case data->channel_map gets
488 * modified in pa_format_info_to_sample_spec2(). */
489 r = pa_stream_get_volume_channel_map(&data->volume, data->channel_map_is_set ? &data->channel_map : NULL, data->format, &volume_map);
494 /* Now populate the sample spec and channel map according to the final
495 * format that we've negotiated */
496 r = pa_format_info_to_sample_spec2(data->format, &data->sample_spec, &data->channel_map, &data->sink->sample_spec,
497 &data->sink->channel_map);
501 r = check_passthrough_connection(pa_sink_input_new_data_is_passthrough(data), data->sink);
505 /* Don't restore (or save) stream volume for passthrough streams and
506 * prevent attenuation/gain */
507 if (pa_sink_input_new_data_is_passthrough(data)) {
508 data->volume_is_set = true;
509 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
510 data->volume_is_absolute = true;
511 data->save_volume = false;
514 if (!data->volume_is_set) {
515 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
516 data->volume_is_absolute = false;
517 data->save_volume = false;
520 if (!data->volume_writable)
521 data->save_volume = false;
523 if (data->volume_is_set)
524 /* The original volume channel map may be different than the final
525 * stream channel map, so remapping may be needed. */
526 pa_cvolume_remap(&data->volume, &volume_map, &data->channel_map);
528 if (!data->muted_is_set)
531 if (!(data->flags & PA_SINK_INPUT_VARIABLE_RATE) &&
532 !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec)) {
533 /* try to change sink format and rate. This is done before the FIXATE hook since
534 module-suspend-on-idle can resume a sink */
536 pa_log_info("Trying to change sample spec");
537 pa_sink_reconfigure(data->sink, &data->sample_spec, pa_sink_input_new_data_is_passthrough(data));
540 if (pa_sink_input_new_data_is_passthrough(data) &&
541 !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec)) {
542 /* rate update failed, or other parts of sample spec didn't match */
544 pa_log_debug("Could not update sink sample spec to match passthrough stream");
545 return -PA_ERR_NOTSUPPORTED;
548 if (data->resample_method == PA_RESAMPLER_INVALID)
549 data->resample_method = core->resample_method;
551 pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
553 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
556 if ((data->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND) &&
557 pa_sink_get_state(data->sink) == PA_SINK_SUSPENDED) {
558 pa_log_warn("Failed to create sink input: sink is suspended.");
559 return -PA_ERR_BADSTATE;
562 if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) {
563 pa_log_warn("Failed to create sink input: too many inputs per sink.");
564 return -PA_ERR_TOOLARGE;
567 if ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
568 !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) ||
569 !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) {
571 /* Note: for passthrough content we need to adjust the output rate to that of the current sink-input */
572 if (!pa_sink_input_new_data_is_passthrough(data)) /* no resampler for passthrough content */
573 if (!(resampler = pa_resampler_new(
575 &data->sample_spec, &data->channel_map,
576 &data->sink->sample_spec, &data->sink->channel_map,
577 core->lfe_crossover_freq,
578 data->resample_method,
579 ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
580 ((data->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
581 (core->disable_remixing || (data->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
582 (core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
583 (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
584 pa_log_warn("Unsupported resampling operation.");
585 return -PA_ERR_NOTSUPPORTED;
589 i = pa_msgobject_new(pa_sink_input);
590 i->parent.parent.free = sink_input_free;
591 i->parent.process_msg = pa_sink_input_process_msg;
594 i->state = PA_SINK_INPUT_INIT;
595 i->flags = data->flags;
596 i->proplist = pa_proplist_copy(data->proplist);
597 i->driver = pa_xstrdup(pa_path_get_filename(data->driver));
598 i->module = data->module;
599 i->sink = data->sink;
600 i->origin_sink = data->origin_sink;
601 i->client = data->client;
603 i->requested_resample_method = data->resample_method;
604 i->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID;
605 i->sample_spec = data->sample_spec;
606 i->channel_map = data->channel_map;
607 i->format = pa_format_info_copy(data->format);
609 if (!data->volume_is_absolute && pa_sink_flat_volume_enabled(i->sink)) {
612 /* When the 'absolute' bool is not set then we'll treat the volume
613 * as relative to the sink volume even in flat volume mode */
614 remapped = data->sink->reference_volume;
615 pa_cvolume_remap(&remapped, &data->sink->channel_map, &data->channel_map);
616 pa_sw_cvolume_multiply(&i->volume, &data->volume, &remapped);
618 i->volume = data->volume;
620 i->volume_factor_items = data->volume_factor_items;
621 data->volume_factor_items = NULL;
622 volume_factor_from_hashmap(&i->volume_factor, i->volume_factor_items, i->sample_spec.channels);
624 i->volume_factor_sink_items = data->volume_factor_sink_items;
625 data->volume_factor_sink_items = NULL;
626 volume_factor_from_hashmap(&i->volume_factor_sink, i->volume_factor_sink_items, i->sink->sample_spec.channels);
628 #ifdef TIZEN_VOLUME_RAMP
629 i->ramp_factor_items = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL,
630 (pa_free_cb_t) volume_ramp_factor_entry_free);
632 i->real_ratio = i->reference_ratio = data->volume;
633 pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
634 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
635 #ifdef TIZEN_INDIVIDUAL_VOLUME_RATIO
636 i->individual_volume_ratio = data->individual_volume_ratio;
638 i->volume_writable = data->volume_writable;
639 i->save_volume = data->save_volume;
640 i->save_sink = data->save_sink;
641 i->save_muted = data->save_muted;
643 i->muted = data->muted;
645 if (data->sync_base) {
646 i->sync_next = data->sync_base->sync_next;
647 i->sync_prev = data->sync_base;
649 if (data->sync_base->sync_next)
650 data->sync_base->sync_next->sync_prev = i;
651 data->sync_base->sync_next = i;
653 i->sync_next = i->sync_prev = NULL;
655 i->direct_outputs = pa_idxset_new(NULL, NULL);
659 #ifdef TIZEN_EMPTY_POP
660 i->is_virtual = pa_safe_streq(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), "VIRTUAL_STREAM");
662 #ifdef TIZEN_PCM_DUMP
663 i->pcm_dump_fp = NULL;
667 #ifdef TIZEN_VOLUME_RAMP
668 if (data->flags & PA_SINK_INPUT_START_RAMP_MUTED)
669 pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_MUTED, data->sink->sample_spec.channels);
671 pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_NORM, data->sink->sample_spec.channels);
674 i->thread_info.state = i->state;
675 i->thread_info.attached = false;
676 pa_atomic_store(&i->thread_info.drained, 1);
677 i->thread_info.sample_spec = i->sample_spec;
678 i->thread_info.resampler = resampler;
679 i->thread_info.soft_volume = i->soft_volume;
680 i->thread_info.muted = i->muted;
681 i->thread_info.requested_sink_latency = (pa_usec_t) -1;
682 i->thread_info.rewrite_nbytes = 0;
683 i->thread_info.rewrite_flush = false;
684 i->thread_info.dont_rewind_render = false;
685 i->thread_info.underrun_for = (uint64_t) -1;
686 i->thread_info.underrun_for_sink = 0;
687 i->thread_info.playing_for = 0;
688 i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
689 #ifdef TIZEN_VOLUME_RAMP
690 i->thread_info.ramp = i->ramp;
693 pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
694 pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0);
697 pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
699 memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index);
700 i->thread_info.render_memblockq = pa_memblockq_new(
705 &i->sink->sample_spec,
710 pa_xfree(memblockq_name);
712 pt = pa_proplist_to_string_sep(i->proplist, "\n ");
713 pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
715 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
717 pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
718 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
722 /* Don't forget to call pa_sink_input_put! */
728 /* Called from main context */
729 static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
731 pa_assert_ctl_context();
736 if (i->state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED)
737 pa_assert_se(i->sink->n_corked -- >= 1);
738 else if (i->state != PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_CORKED)
742 /* Called from main context */
743 static void sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
744 pa_sink_input *ssync;
746 pa_assert_ctl_context();
748 if (state == PA_SINK_INPUT_DRAINED)
749 state = PA_SINK_INPUT_RUNNING;
751 if (i->state == state)
754 #ifdef TIZEN_EMPTY_POP
755 if (state != PA_SINK_INPUT_RUNNING && _empty_pop_is_started(i))
760 if (i->state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING && pa_sink_used_by(i->sink) == 0 &&
761 !pa_sample_spec_equal(&i->sample_spec, &i->sink->sample_spec)) {
762 /* We were uncorked and the sink was not playing anything -- let's try
763 * to update the sample format and rate to avoid resampling */
764 pa_sink_reconfigure(i->sink, &i->sample_spec, pa_sink_input_is_passthrough(i));
767 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);
769 /* If the sink is not valid, pa_sink_input_set_state_within_thread() must be called directly */
771 pa_sink_input_set_state_within_thread(i, state);
773 for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
774 pa_sink_input_set_state_within_thread(ssync, state);
776 for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
777 pa_sink_input_set_state_within_thread(ssync, state);
779 #ifdef TIZEN_PCM_DUMP
780 if (i->state == PA_SINK_INPUT_RUNNING && i->pcm_dump_fp && (i->core->pcm_dump_option & PA_PCM_DUMP_OPTION_SEPARATED)) {
781 /* close file for dump pcm */
782 fclose(i->pcm_dump_fp);
783 pa_log_info("%s closed", i->dump_path);
784 pa_xfree(i->dump_path);
785 i->pcm_dump_fp = NULL;
789 if (state == PA_SINK_INPUT_RUNNING)
790 i->time_of_start_to_run = pa_rtclock_now();
793 update_n_corked(i, state);
796 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev) {
797 update_n_corked(ssync, state);
798 ssync->state = state;
800 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) {
801 update_n_corked(ssync, state);
802 ssync->state = state;
805 if (state != PA_SINK_INPUT_UNLINKED) {
806 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
808 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev)
809 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
811 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next)
812 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
814 if (PA_SINK_INPUT_IS_LINKED(state))
815 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
819 pa_sink_update_status(i->sink);
822 /* Called from main context */
823 void pa_sink_input_unlink(pa_sink_input *i) {
825 pa_source_output *o, PA_UNUSED *p = NULL;
827 pa_sink_input_assert_ref(i);
828 pa_assert_ctl_context();
830 /* See pa_sink_unlink() for a couple of comments how this function
833 pa_sink_input_ref(i);
835 linked = PA_SINK_INPUT_IS_LINKED(i->state);
838 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
841 i->sync_prev->sync_next = i->sync_next;
843 i->sync_next->sync_prev = i->sync_prev;
845 i->sync_prev = i->sync_next = NULL;
847 pa_idxset_remove_by_data(i->core->sink_inputs, i, NULL);
850 if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
851 pa_sink_input_unref(i);
854 pa_idxset_remove_by_data(i->client->sink_inputs, i, NULL);
856 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
858 pa_source_output_kill(o);
862 update_n_corked(i, PA_SINK_INPUT_UNLINKED);
863 i->state = PA_SINK_INPUT_UNLINKED;
865 if (linked && i->sink) {
866 if (pa_sink_input_is_passthrough(i))
867 pa_sink_leave_passthrough(i->sink);
869 /* We might need to update the sink's volume if we are in flat volume mode. */
870 if (pa_sink_flat_volume_enabled(i->sink))
871 pa_sink_set_volume(i->sink, NULL, false, false);
873 if (i->sink->asyncmsgq)
874 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL) == 0);
880 if (PA_SINK_IS_LINKED(pa_sink_get_state(i->sink)))
881 pa_sink_update_status(i->sink);
887 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
888 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
891 pa_core_maybe_vacuum(i->core);
893 pa_sink_input_unref(i);
896 /* Called from main context */
897 static void sink_input_free(pa_object *o) {
898 pa_sink_input* i = PA_SINK_INPUT(o);
901 pa_assert_ctl_context();
902 pa_assert(pa_sink_input_refcnt(i) == 0);
903 pa_assert(!PA_SINK_INPUT_IS_LINKED(i->state));
905 pa_log_info("Freeing input %u \"%s\"", i->index,
906 i->proplist ? pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)) : "");
908 /* Side note: this function must be able to destruct properly any
909 * kind of sink input in any state, even those which are
910 * "half-moved" or are connected to sinks that have no asyncmsgq
911 * and are hence half-destructed themselves! */
913 if (i->thread_info.render_memblockq)
914 pa_memblockq_free(i->thread_info.render_memblockq);
916 if (i->thread_info.resampler)
917 pa_resampler_free(i->thread_info.resampler);
918 #ifdef TIZEN_PCM_DUMP
919 /* close file for dump pcm */
920 if (i->pcm_dump_fp) {
921 fclose(i->pcm_dump_fp);
922 pa_log_info("%s closed", i->dump_path);
923 pa_xfree(i->dump_path);
924 i->pcm_dump_fp = NULL;
929 pa_format_info_free(i->format);
932 pa_proplist_free(i->proplist);
934 if (i->direct_outputs)
935 pa_idxset_free(i->direct_outputs, NULL);
937 if (i->thread_info.direct_outputs)
938 pa_hashmap_free(i->thread_info.direct_outputs);
940 if (i->volume_factor_items)
941 pa_hashmap_free(i->volume_factor_items);
943 if (i->volume_factor_sink_items)
944 pa_hashmap_free(i->volume_factor_sink_items);
946 #ifdef TIZEN_VOLUME_RAMP
947 if (i->ramp_factor_items)
948 pa_hashmap_free(i->ramp_factor_items);
954 /* Called from main context */
955 void pa_sink_input_put(pa_sink_input *i) {
956 pa_sink_input_state_t state;
958 pa_sink_input_assert_ref(i);
959 pa_assert_ctl_context();
961 pa_assert(i->state == PA_SINK_INPUT_INIT);
963 /* The following fields must be initialized properly */
965 pa_assert(i->process_rewind);
968 state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
970 update_n_corked(i, state);
973 /* We might need to update the sink's volume if we are in flat volume mode. */
974 if (pa_sink_flat_volume_enabled(i->sink))
975 pa_sink_set_volume(i->sink, NULL, false, i->save_volume);
977 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
978 pa_assert(pa_cvolume_is_norm(&i->volume));
979 pa_assert(pa_cvolume_is_norm(&i->reference_ratio));
982 set_real_ratio(i, &i->volume);
985 if (pa_sink_input_is_passthrough(i))
986 pa_sink_enter_passthrough(i->sink);
988 i->thread_info.soft_volume = i->soft_volume;
989 i->thread_info.muted = i->muted;
991 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0);
993 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
994 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
996 pa_sink_update_status(i->sink);
999 /* Called from main context */
1000 void pa_sink_input_kill(pa_sink_input*i) {
1001 pa_sink_input_assert_ref(i);
1002 pa_assert_ctl_context();
1003 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1008 /* Called from main context */
1009 pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
1010 pa_usec_t r[2] = { 0, 0 };
1012 pa_sink_input_assert_ref(i);
1013 pa_assert_ctl_context();
1014 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1016 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, r, 0, NULL) == 0);
1019 r[0] += i->get_latency(i);
1022 *sink_latency = r[1];
1027 #ifdef TIZEN_VOLUME_RAMP
1028 /* Called from thread context */
1029 static void check_and_apply_silence(pa_sink_input *i) {
1030 pa_sink_input_assert_ref(i);
1032 if (i->thread_info.silenced && i->thread_info.silence_duration > 0) {
1034 size_t target_length = pa_usec_to_bytes(i->thread_info.silence_duration, &i->sink->sample_spec);
1036 pa_silence_memchunk_get(&i->core->silence_cache,
1039 &i->sink->sample_spec,
1040 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
1042 while (target_length > 0) {
1043 if (target_length < schunk.length)
1044 schunk.length = target_length;
1045 pa_memblockq_push_align(i->thread_info.render_memblockq, &schunk);
1046 target_length -= schunk.length;
1047 #ifdef SINK_INPUT_DEBUG
1048 pa_log_debug("add memchunk for slience, length(%u)", schunk.length);
1051 pa_memblock_unref(schunk.memblock);
1053 i->thread_info.silenced = false;
1054 i->thread_info.silence_duration = 0;
1058 /* Called from thread context */
1059 static void check_and_apply_ramp(pa_cvolume_ramp_int *ramp, const pa_sample_spec *spec, pa_memchunk *chunk) {
1066 /* check for possible volume ramp and apply it */
1067 if (pa_cvolume_ramp_active(ramp)) {
1068 pa_memchunk_make_writable(chunk, 0);
1069 pa_volume_ramp_memchunk(chunk, spec, ramp);
1070 } else if (pa_cvolume_ramp_target_active(ramp)) {
1071 pa_memchunk_make_writable(chunk, 0);
1072 pa_cvolume_ramp_get_targets(ramp, &target);
1073 pa_volume_memchunk(chunk, spec, &target);
1078 /* Called from thread context */
1079 void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa_memchunk *chunk, pa_cvolume *volume) {
1080 bool do_volume_adj_here, need_volume_factor_sink;
1081 bool volume_is_norm;
1082 #ifdef TIZEN_VOLUME_RAMP
1083 bool prev_ramp_finished = false;
1085 size_t block_size_max_sink, block_size_max_sink_input;
1087 size_t ilength_full;
1090 pa_sink_avc_mode_t avc_mode = PA_SINK_AVC_OFF;
1093 pa_sink_input_assert_ref(i);
1094 pa_sink_input_assert_io_context(i);
1095 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1096 pa_assert(pa_frame_aligned(slength, &i->sink->sample_spec));
1100 #ifdef SINK_INPUT_DEBUG
1102 pa_log_debug("peek, idx(%u)", i->index);
1104 pa_log_debug("peek");
1108 block_size_max_sink_input = i->thread_info.resampler ?
1109 pa_resampler_max_block_size(i->thread_info.resampler) :
1110 pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sample_spec);
1112 block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sink->sample_spec);
1114 /* Default buffer size */
1116 slength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec);
1118 if (slength > block_size_max_sink)
1119 slength = block_size_max_sink;
1121 if (i->thread_info.resampler) {
1122 ilength = pa_resampler_request(i->thread_info.resampler, slength);
1125 ilength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
1129 /* Length corresponding to slength (without limiting to
1130 * block_size_max_sink_input). */
1131 ilength_full = ilength;
1133 if (ilength > block_size_max_sink_input)
1134 ilength = block_size_max_sink_input;
1136 /* If the channel maps of the sink and this stream differ, we need
1137 * to adjust the volume *before* we resample. Otherwise we can do
1138 * it after and leave it for the sink code */
1140 do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
1141 volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
1142 need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);
1145 avc_mode = pa_sink_get_avc_mode(i->sink);
1146 #ifdef SINK_INPUT_DEBUG
1147 pa_log("idx(%u), avc mode(%d), do(%d), norm(%d), nvfs(%d), muted(%d), resampler(%p)",
1149 do_volume_adj_here, volume_is_norm, need_volume_factor_sink,
1150 i->thread_info.muted, i->thread_info.resampler);
1154 while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
1157 /* There's nothing in our render queue. We need to fill it up
1158 * with data from the implementor. */
1160 if (i->thread_info.state == PA_SINK_INPUT_CORKED ||
1161 i->pop(i, ilength, &tchunk) < 0) {
1163 /* OK, we're corked or the implementor didn't give us any
1164 * data, so let's just hand out silence */
1165 pa_atomic_store(&i->thread_info.drained, 1);
1167 pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE, true);
1168 i->thread_info.playing_for = 0;
1169 if (i->thread_info.underrun_for != (uint64_t) -1) {
1170 i->thread_info.underrun_for += ilength_full;
1171 i->thread_info.underrun_for_sink += slength;
1176 pa_atomic_store(&i->thread_info.drained, 0);
1178 pa_assert(tchunk.length > 0);
1179 pa_assert(tchunk.memblock);
1181 i->thread_info.underrun_for = 0;
1182 i->thread_info.underrun_for_sink = 0;
1183 i->thread_info.playing_for += tchunk.length;
1185 while (tchunk.length > 0) {
1187 bool nvfs = need_volume_factor_sink;
1190 pa_memblock_ref(wchunk.memblock);
1192 if (wchunk.length > block_size_max_sink_input)
1193 wchunk.length = block_size_max_sink_input;
1195 /* It might be necessary to adjust the volume here */
1197 if (do_volume_adj_here && !volume_is_norm && avc_mode != PA_SINK_AVC_NORM) {
1199 if (do_volume_adj_here && !volume_is_norm) {
1201 pa_memchunk_make_writable(&wchunk, 0);
1204 if (i->thread_info.muted || avc_mode == PA_SINK_AVC_SILENT) {
1206 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);
1227 prev_ramp_finished = i->thread_info.ramp.finished;
1229 if (!i->thread_info.resampler) {
1232 pa_memchunk_make_writable(&wchunk, 0);
1233 pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
1236 #ifdef TIZEN_VOLUME_RAMP
1237 check_and_apply_ramp(&i->thread_info.ramp, &i->sink->sample_spec, &wchunk);
1239 pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
1242 #ifdef TIZEN_VOLUME_RAMP
1243 check_and_apply_ramp(&i->thread_info.ramp, &i->thread_info.sample_spec, &wchunk);
1245 pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
1247 #ifdef SINK_INPUT_DEBUG
1248 pa_log_debug("pushing %lu", (unsigned long) rchunk.length);
1251 if (rchunk.memblock) {
1254 pa_memchunk_make_writable(&rchunk, 0);
1255 pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
1258 pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
1259 pa_memblock_unref(rchunk.memblock);
1263 pa_memblock_unref(wchunk.memblock);
1265 tchunk.index += wchunk.length;
1266 tchunk.length -= wchunk.length;
1269 pa_memblock_unref(tchunk.memblock);
1272 pa_assert_se(pa_memblockq_peek(i->thread_info.render_memblockq, chunk) >= 0);
1274 pa_assert(chunk->length > 0);
1275 pa_assert(chunk->memblock);
1277 #ifdef SINK_INPUT_DEBUG
1278 pa_log_debug("peeking %lu", (unsigned long) chunk->length);
1281 if (chunk->length > block_size_max_sink)
1282 chunk->length = block_size_max_sink;
1284 /* Let's see if we had to apply the volume adjustment ourselves,
1285 * or if this can be done by the sink for us */
1288 if (do_volume_adj_here || avc_mode == PA_SINK_AVC_NORM)
1290 if (do_volume_adj_here)
1292 /* We had different channel maps, so we already did the adjustment */
1293 pa_cvolume_reset(volume, i->sink->sample_spec.channels);
1295 else if (i->thread_info.muted || avc_mode == PA_SINK_AVC_SILENT)
1297 else if (i->thread_info.muted)
1299 /* We've both the same channel map, so let's have the sink do the adjustment for us*/
1300 pa_cvolume_mute(volume, i->sink->sample_spec.channels);
1302 *volume = i->thread_info.soft_volume;
1303 #ifdef TIZEN_PCM_DUMP
1304 pa_sink_input_write_pcm_dump(i, chunk);
1306 #ifdef TIZEN_VOLUME_RAMP
1307 /* Hook fire only if ramp is finished. Note that it does not mean all the ramped data
1308 * is written to the device, hence it needs to be improved later on. */
1309 if (!prev_ramp_finished && i->thread_info.ramp.finished) {
1310 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_RAMP_FINISH], i);
1311 i->thread_info.ramp.finished = false;
1316 /* Called from thread context */
1317 void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
1319 pa_sink_input_assert_ref(i);
1320 pa_sink_input_assert_io_context(i);
1321 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1322 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1323 pa_assert(nbytes > 0);
1325 #ifdef SINK_INPUT_DEBUG
1326 pa_log_debug("dropping %lu", (unsigned long) nbytes);
1328 #ifdef TIZEN_PCM_DUMP
1329 if (i->pcm_dump_fp && i->dump_length) {
1330 int64_t seek_length;
1332 seek_length = (int64_t) (nbytes - i->dump_length);
1334 if (seek_length < 0)
1335 fseeko(i->pcm_dump_fp, (off_t)seek_length, SEEK_CUR);
1341 pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
1344 /* Called from thread context */
1345 bool pa_sink_input_process_underrun(pa_sink_input *i) {
1346 pa_sink_input_assert_ref(i);
1347 pa_sink_input_assert_io_context(i);
1349 if (pa_memblockq_is_readable(i->thread_info.render_memblockq))
1352 if (i->process_underrun && i->process_underrun(i)) {
1353 /* All valid data has been played back, so we can empty this queue. */
1354 pa_memblockq_silence(i->thread_info.render_memblockq);
1360 /* Called from thread context */
1361 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
1363 bool called = false;
1365 pa_sink_input_assert_ref(i);
1366 pa_sink_input_assert_io_context(i);
1367 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1368 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1370 #ifdef SINK_INPUT_DEBUG
1371 pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes);
1374 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
1376 if (nbytes > 0 && !i->thread_info.dont_rewind_render) {
1377 pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
1378 pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
1381 if (i->thread_info.rewrite_nbytes == (size_t) -1) {
1383 #ifdef TIZEN_PCM_DUMP
1386 fseeko(i->pcm_dump_fp, (off_t)pa_memblockq_get_length(i->thread_info.render_memblockq) * (-1), SEEK_CUR);
1388 /* We were asked to drop all buffered data, and rerequest new
1389 * data from implementor the next time peek() is called */
1391 pa_memblockq_flush_write(i->thread_info.render_memblockq, true);
1393 } else if (i->thread_info.rewrite_nbytes > 0) {
1394 size_t max_rewrite, amount;
1396 /* Calculate how much make sense to rewrite at most */
1397 max_rewrite = nbytes + lbq;
1399 /* Transform into local domain */
1400 if (i->thread_info.resampler)
1401 max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
1403 /* Calculate how much of the rewinded data should actually be rewritten */
1404 amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
1407 pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
1409 #ifdef TIZEN_PCM_DUMP
1412 fseeko(i->pcm_dump_fp, (off_t)amount * (-1), SEEK_CUR);
1414 /* Tell the implementor */
1415 if (i->process_rewind)
1416 i->process_rewind(i, amount);
1419 /* Convert back to sink domain */
1420 if (i->thread_info.resampler)
1421 amount = pa_resampler_result(i->thread_info.resampler, amount);
1424 /* Ok, now update the write pointer */
1425 pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE, true);
1427 if (i->thread_info.rewrite_flush)
1428 pa_memblockq_silence(i->thread_info.render_memblockq);
1430 /* And rewind the resampler */
1431 if (i->thread_info.resampler)
1432 pa_resampler_rewind(i->thread_info.resampler, amount);
1437 if (i->process_rewind)
1438 i->process_rewind(i, 0);
1440 i->thread_info.rewrite_nbytes = 0;
1441 i->thread_info.rewrite_flush = false;
1442 i->thread_info.dont_rewind_render = false;
1445 /* Called from thread context */
1446 size_t pa_sink_input_get_max_rewind(pa_sink_input *i) {
1447 pa_sink_input_assert_ref(i);
1448 pa_sink_input_assert_io_context(i);
1450 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_rewind) : i->sink->thread_info.max_rewind;
1453 /* Called from thread context */
1454 size_t pa_sink_input_get_max_request(pa_sink_input *i) {
1455 pa_sink_input_assert_ref(i);
1456 pa_sink_input_assert_io_context(i);
1458 /* We're not verifying the status here, to allow this to be called
1459 * in the state change handler between _INIT and _RUNNING */
1461 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_request) : i->sink->thread_info.max_request;
1464 /* Called from thread context */
1465 void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
1466 pa_sink_input_assert_ref(i);
1467 pa_sink_input_assert_io_context(i);
1468 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1469 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1471 pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
1473 if (i->update_max_rewind)
1474 i->update_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
1477 /* Called from thread context */
1478 void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
1479 pa_sink_input_assert_ref(i);
1480 pa_sink_input_assert_io_context(i);
1481 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1482 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1484 if (i->update_max_request)
1485 i->update_max_request(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
1488 /* Called from thread context */
1489 pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
1490 pa_sink_input_assert_ref(i);
1491 pa_sink_input_assert_io_context(i);
1493 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1494 usec = i->sink->thread_info.fixed_latency;
1496 if (usec != (pa_usec_t) -1)
1497 usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
1499 i->thread_info.requested_sink_latency = usec;
1500 pa_sink_invalidate_requested_latency(i->sink, true);
1505 /* Called from main context */
1506 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
1507 pa_sink_input_assert_ref(i);
1508 pa_assert_ctl_context();
1510 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1511 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1515 /* If this sink input is not realized yet or we are being moved,
1516 * we have to touch the thread info data directly */
1519 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1520 usec = pa_sink_get_fixed_latency(i->sink);
1522 if (usec != (pa_usec_t) -1) {
1523 pa_usec_t min_latency, max_latency;
1524 pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
1525 usec = PA_CLAMP(usec, min_latency, max_latency);
1529 i->thread_info.requested_sink_latency = usec;
1534 /* Called from main context */
1535 pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
1536 pa_sink_input_assert_ref(i);
1537 pa_assert_ctl_context();
1539 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1541 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1545 /* If this sink input is not realized yet or we are being moved,
1546 * we have to touch the thread info data directly */
1548 return i->thread_info.requested_sink_latency;
1551 /* Called from main context */
1552 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool save, bool absolute) {
1555 pa_sink_input_assert_ref(i);
1556 pa_assert_ctl_context();
1557 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1559 pa_assert(pa_cvolume_valid(volume));
1560 pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
1561 pa_assert(i->volume_writable);
1563 if (!absolute && pa_sink_flat_volume_enabled(i->sink)) {
1564 v = i->sink->reference_volume;
1565 pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
1567 if (pa_cvolume_compatible(volume, &i->sample_spec))
1568 volume = pa_sw_cvolume_multiply(&v, &v, volume);
1570 volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume));
1572 if (!pa_cvolume_compatible(volume, &i->sample_spec)) {
1574 volume = pa_cvolume_scale(&v, pa_cvolume_max(volume));
1578 if (pa_cvolume_equal(volume, &i->volume)) {
1579 i->save_volume = i->save_volume || save;
1583 pa_sink_input_set_volume_direct(i, volume);
1584 i->save_volume = save;
1586 if (pa_sink_flat_volume_enabled(i->sink)) {
1587 /* We are in flat volume mode, so let's update all sink input
1588 * volumes and update the flat volume of the sink */
1590 pa_sink_set_volume(i->sink, NULL, true, save);
1593 /* OK, we are in normal volume mode. The volume only affects
1595 set_real_ratio(i, volume);
1596 pa_sink_input_set_reference_ratio(i, &i->volume);
1598 /* Copy the new soft_volume to the thread_info struct */
1599 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1603 void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa_cvolume *volume_factor) {
1604 struct volume_factor_entry *v;
1606 pa_sink_input_assert_ref(i);
1607 pa_assert_ctl_context();
1608 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1609 pa_assert(volume_factor);
1611 pa_assert(pa_cvolume_valid(volume_factor));
1612 pa_assert(volume_factor->channels == 1 || pa_cvolume_compatible(volume_factor, &i->sample_spec));
1614 v = volume_factor_entry_new(key, volume_factor);
1615 if (!pa_cvolume_compatible(volume_factor, &i->sample_spec))
1616 pa_cvolume_set(&v->volume, i->sample_spec.channels, volume_factor->values[0]);
1618 pa_assert_se(pa_hashmap_put(i->volume_factor_items, v->key, v) >= 0);
1619 if (pa_hashmap_size(i->volume_factor_items) == 1)
1620 i->volume_factor = v->volume;
1622 pa_sw_cvolume_multiply(&i->volume_factor, &i->volume_factor, &v->volume);
1624 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1626 /* Copy the new soft_volume to the thread_info struct */
1627 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1630 /* Returns 0 if an entry was removed and -1 if no entry for the given key was
1632 int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) {
1633 struct volume_factor_entry *v;
1635 pa_sink_input_assert_ref(i);
1637 pa_assert_ctl_context();
1638 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1640 if (pa_hashmap_remove_and_free(i->volume_factor_items, key) < 0)
1643 switch (pa_hashmap_size(i->volume_factor_items)) {
1645 pa_cvolume_reset(&i->volume_factor, i->sample_spec.channels);
1648 v = pa_hashmap_first(i->volume_factor_items);
1649 i->volume_factor = v->volume;
1652 volume_factor_from_hashmap(&i->volume_factor, i->volume_factor_items, i->volume_factor.channels);
1655 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1657 #ifdef TIZEN_VOLUME_RAMP
1658 /* If a ramp was set, skip rewinding. It'll be rewinded with SET_VOLUME_RAMP later. */
1659 if (pa_cvolume_ramp_target_active(&i->ramp)) {
1660 bool skip_rewind = true;
1661 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, &skip_rewind, 0, NULL) == 0);
1664 /* Copy the new soft_volume to the thread_info struct */
1665 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1666 #ifdef TIZEN_VOLUME_RAMP
1673 #ifdef TIZEN_VOLUME_RAMP
1674 void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg) {
1675 struct volume_ramp_factor_entry *r;
1677 pa_sink_input_assert_ref(i);
1678 pa_assert_ctl_context();
1679 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1680 pa_assert(ramp_factor);
1682 pa_assert(pa_cvolume_ramp_valid(ramp_factor));
1683 pa_assert(ramp_factor->channels == 1 || pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec));
1685 r = volume_ramp_factor_entry_new(key, ramp_factor);
1686 if (!pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec))
1687 pa_cvolume_ramp_set(&r->ramp, i->sample_spec.channels,
1688 ramp_factor->ramps[0].type,
1689 ramp_factor->ramps[0].length,
1690 ramp_factor->ramps[0].target);
1692 pa_assert_se(pa_hashmap_put(i->ramp_factor_items, r->key, r) >= 0);
1693 if (pa_hashmap_size(i->ramp_factor_items) == 1)
1694 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);
1696 pa_sw_cvolume_ramp_multiply(&i->ramp_factor, &i->ramp_factor, &r->ramp);
1698 pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate);
1701 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
1704 /* Returns 0 if an entry was removed and -1 if no entry for the given key was
1706 int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg) {
1707 struct volume_ramp_factor_entry *r;
1709 pa_sink_input_assert_ref(i);
1711 pa_assert_ctl_context();
1712 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1714 r = pa_hashmap_remove(i->ramp_factor_items, key);
1718 switch (pa_hashmap_size(i->ramp_factor_items)) {
1720 pa_cvolume_ramp_reset(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length);
1723 struct volume_ramp_factor_entry *rf;
1724 if ((rf = pa_hashmap_first(i->ramp_factor_items)))
1725 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);
1729 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);
1732 volume_ramp_factor_entry_free(r);
1734 pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate);
1737 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
1742 /* Called from main context */
1743 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {
1744 pa_sink_input_assert_ref(i);
1745 pa_assert_ctl_context();
1746 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1747 pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
1749 /* This basically calculates:
1751 * i->real_ratio := v
1752 * i->soft_volume := i->real_ratio * i->volume_factor */
1757 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
1759 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1760 /* We don't copy the data to the thread_info data. That's left for someone else to do */
1763 /* Called from main or I/O context */
1764 bool pa_sink_input_is_passthrough(pa_sink_input *i) {
1765 pa_sink_input_assert_ref(i);
1767 if (PA_UNLIKELY(!pa_format_info_is_pcm(i->format)))
1770 if (PA_UNLIKELY(i->flags & PA_SINK_INPUT_PASSTHROUGH))
1776 /* Called from main context */
1777 bool pa_sink_input_is_volume_readable(pa_sink_input *i) {
1778 pa_sink_input_assert_ref(i);
1779 pa_assert_ctl_context();
1781 return !pa_sink_input_is_passthrough(i);
1784 /* Called from main context */
1785 pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute) {
1786 pa_sink_input_assert_ref(i);
1787 pa_assert_ctl_context();
1788 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1789 pa_assert(pa_sink_input_is_volume_readable(i));
1791 if (absolute || !pa_sink_flat_volume_enabled(i->sink))
1792 *volume = i->volume;
1794 *volume = i->reference_ratio;
1799 /* Called from main context */
1800 void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save) {
1803 pa_sink_input_assert_ref(i);
1804 pa_assert_ctl_context();
1805 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1807 old_mute = i->muted;
1809 if (mute == old_mute) {
1810 i->save_muted |= save;
1815 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));
1817 i->save_muted = save;
1819 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
1821 /* The mute status changed, let's tell people so */
1822 if (i->mute_changed)
1825 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1826 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MUTE_CHANGED], i);
1829 void pa_sink_input_set_property(pa_sink_input *i, const char *key, const char *value) {
1830 char *old_value = NULL;
1831 const char *new_value;
1836 if (pa_proplist_contains(i->proplist, key)) {
1837 old_value = pa_xstrdup(pa_proplist_gets(i->proplist, key));
1838 if (value && old_value && pa_streq(value, old_value))
1842 old_value = pa_xstrdup("(data)");
1847 old_value = pa_xstrdup("(unset)");
1851 pa_proplist_sets(i->proplist, key, value);
1854 pa_proplist_unset(i->proplist, key);
1855 new_value = "(unset)";
1858 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1859 pa_log_debug("Sink input %u: proplist[%s]: %s -> %s", i->index, key, old_value, new_value);
1860 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1861 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1865 pa_xfree(old_value);
1868 void pa_sink_input_set_property_arbitrary(pa_sink_input *i, const char *key, const uint8_t *value, size_t nbytes) {
1869 const uint8_t *old_value;
1871 const char *old_value_str;
1872 const char *new_value_str;
1877 if (pa_proplist_get(i->proplist, key, (const void **) &old_value, &old_nbytes) >= 0) {
1878 if (value && nbytes == old_nbytes && !memcmp(value, old_value, nbytes))
1881 old_value_str = "(data)";
1887 old_value_str = "(unset)";
1891 pa_proplist_set(i->proplist, key, value, nbytes);
1892 new_value_str = "(data)";
1894 pa_proplist_unset(i->proplist, key);
1895 new_value_str = "(unset)";
1898 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1899 pa_log_debug("Sink input %u: proplist[%s]: %s -> %s", i->index, key, old_value_str, new_value_str);
1900 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1901 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1905 /* Called from main thread */
1906 void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
1909 const uint8_t *value;
1912 pa_sink_input_assert_ref(i);
1914 pa_assert_ctl_context();
1917 case PA_UPDATE_SET: {
1918 /* Delete everything that is not in p. */
1919 for (state = NULL; (key = pa_proplist_iterate(i->proplist, &state));) {
1920 if (!pa_proplist_contains(p, key))
1921 pa_sink_input_set_property(i, key, NULL);
1927 case PA_UPDATE_REPLACE: {
1928 for (state = NULL; (key = pa_proplist_iterate(p, &state));) {
1929 pa_proplist_get(p, key, (const void **) &value, &nbytes);
1930 pa_sink_input_set_property_arbitrary(i, key, value, nbytes);
1936 case PA_UPDATE_MERGE: {
1937 for (state = NULL; (key = pa_proplist_iterate(p, &state));) {
1938 if (pa_proplist_contains(i->proplist, key))
1941 pa_proplist_get(p, key, (const void **) &value, &nbytes);
1942 pa_sink_input_set_property_arbitrary(i, key, value, nbytes);
1950 /* Called from main context */
1951 void pa_sink_input_cork(pa_sink_input *i, bool b) {
1952 pa_sink_input_assert_ref(i);
1953 pa_assert_ctl_context();
1954 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1956 sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
1959 /* Called from main context */
1960 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
1961 pa_sink_input_assert_ref(i);
1962 pa_assert_ctl_context();
1963 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1964 pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE);
1966 if (i->sample_spec.rate == rate)
1969 i->sample_spec.rate = rate;
1972 pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
1974 i->thread_info.sample_spec.rate = rate;
1975 pa_resampler_set_input_rate(i->thread_info.resampler, rate);
1978 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1982 /* Called from main context */
1983 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
1984 pa_sink_input_assert_ref(i);
1985 pa_assert_ctl_context();
1987 return i->actual_resample_method;
1990 /* Called from main context */
1991 bool pa_sink_input_may_move(pa_sink_input *i) {
1992 pa_sink_input_assert_ref(i);
1993 pa_assert_ctl_context();
1994 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1996 if (i->flags & PA_SINK_INPUT_DONT_MOVE)
1999 if (i->sync_next || i->sync_prev) {
2000 pa_log_warn("Moving synchronized streams not supported.");
2007 static bool find_filter_sink_input(pa_sink_input *target, pa_sink *s) {
2008 unsigned PA_UNUSED i = 0;
2009 while (s && s->input_to_master) {
2010 if (s->input_to_master == target)
2012 s = s->input_to_master->sink;
2013 pa_assert(i++ < 100);
2018 static bool is_filter_sink_moving(pa_sink_input *i) {
2019 pa_sink *sink = i->sink;
2024 while (sink->input_to_master) {
2025 sink = sink->input_to_master->sink;
2034 /* Called from main context */
2035 bool pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
2036 pa_sink_input_assert_ref(i);
2037 pa_assert_ctl_context();
2038 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2039 pa_sink_assert_ref(dest);
2041 if (dest == i->sink)
2044 if (dest->unlink_requested)
2047 if (!pa_sink_input_may_move(i))
2050 /* Make sure we're not creating a filter sink cycle */
2051 if (find_filter_sink_input(i, dest)) {
2052 pa_log_debug("Can't connect input to %s, as that would create a cycle.", dest->name);
2056 /* If this sink input is connected to a filter sink that itself is moving,
2057 * then don't allow the move. Moving requires sending a message to the IO
2058 * thread of the old sink, and if the old sink is a filter sink that is
2059 * moving, there's no IO thread associated to the old sink. */
2060 if (is_filter_sink_moving(i)) {
2061 pa_log_debug("Can't move input from filter sink %s, because the filter sink itself is currently moving.",
2066 if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
2067 pa_log_warn("Failed to move sink input: too many inputs per sink.");
2071 if (check_passthrough_connection(pa_sink_input_is_passthrough(i), dest) < 0)
2075 if (!i->may_move_to(i, dest))
2081 /* Called from main context */
2082 int pa_sink_input_start_move(pa_sink_input *i) {
2083 pa_source_output *o, PA_UNUSED *p = NULL;
2084 struct volume_factor_entry *v;
2088 pa_sink_input_assert_ref(i);
2089 pa_assert_ctl_context();
2090 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2093 if (!pa_sink_input_may_move(i))
2094 return -PA_ERR_NOTSUPPORTED;
2096 if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
2099 pa_log_debug("Starting to move sink input %u from '%s'", (unsigned) i->index, i->sink->name);
2101 /* Kill directly connected outputs */
2102 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
2104 pa_source_output_kill(o);
2107 pa_assert(pa_idxset_isempty(i->direct_outputs));
2109 pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
2111 if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
2112 pa_assert_se(i->sink->n_corked-- >= 1);
2114 if (pa_sink_input_is_passthrough(i))
2115 pa_sink_leave_passthrough(i->sink);
2117 if (pa_sink_flat_volume_enabled(i->sink))
2118 /* We might need to update the sink's volume if we are in flat
2120 pa_sink_set_volume(i->sink, NULL, false, false);
2122 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
2124 pa_sink_update_status(i->sink);
2126 PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
2127 pa_cvolume_remap(&v->volume, &i->sink->channel_map, &i->channel_map);
2129 pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
2133 pa_sink_input_unref(i);
2138 /* Called from main context. If i has an origin sink that uses volume sharing,
2139 * then also the origin sink and all streams connected to it need to update
2140 * their volume - this function does all that by using recursion. */
2141 static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) {
2142 pa_cvolume new_volume;
2146 pa_assert(i->sink); /* The destination sink should already be set. */
2148 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
2149 pa_sink *root_sink = pa_sink_get_master(i->sink);
2150 pa_sink_input *origin_sink_input;
2153 if (PA_UNLIKELY(!root_sink))
2156 if (pa_sink_flat_volume_enabled(i->sink)) {
2157 /* Ok, so the origin sink uses volume sharing, and flat volume is
2158 * enabled. The volume will have to be updated as follows:
2160 * i->volume := i->sink->real_volume
2161 * (handled later by pa_sink_set_volume)
2162 * i->reference_ratio := i->volume / i->sink->reference_volume
2163 * (handled later by pa_sink_set_volume)
2164 * i->real_ratio stays unchanged
2165 * (streams whose origin sink uses volume sharing should
2166 * always have real_ratio of 0 dB)
2167 * i->soft_volume stays unchanged
2168 * (streams whose origin sink uses volume sharing should
2169 * always have volume_factor as soft_volume, so no change
2170 * should be needed) */
2172 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
2173 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
2175 /* Notifications will be sent by pa_sink_set_volume(). */
2178 /* Ok, so the origin sink uses volume sharing, and flat volume is
2179 * disabled. The volume will have to be updated as follows:
2182 * i->reference_ratio := 0 dB
2183 * i->real_ratio stays unchanged
2184 * (streams whose origin sink uses volume sharing should
2185 * always have real_ratio of 0 dB)
2186 * i->soft_volume stays unchanged
2187 * (streams whose origin sink uses volume sharing should
2188 * always have volume_factor as soft_volume, so no change
2189 * should be needed) */
2191 pa_cvolume_reset(&new_volume, i->volume.channels);
2192 pa_sink_input_set_volume_direct(i, &new_volume);
2193 pa_sink_input_set_reference_ratio(i, &new_volume);
2194 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
2195 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
2198 /* Additionally, the origin sink volume needs updating:
2200 * i->origin_sink->reference_volume := root_sink->reference_volume
2201 * i->origin_sink->real_volume := root_sink->real_volume
2202 * i->origin_sink->soft_volume stays unchanged
2203 * (sinks that use volume sharing should always have
2204 * soft_volume of 0 dB) */
2206 new_volume = root_sink->reference_volume;
2207 pa_cvolume_remap(&new_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
2208 pa_sink_set_reference_volume_direct(i->origin_sink, &new_volume);
2210 i->origin_sink->real_volume = root_sink->real_volume;
2211 pa_cvolume_remap(&i->origin_sink->real_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
2213 pa_assert(pa_cvolume_is_norm(&i->origin_sink->soft_volume));
2215 /* If you wonder whether i->origin_sink->set_volume() should be called
2216 * somewhere, that's not the case, because sinks that use volume
2217 * sharing shouldn't have any internal volume that set_volume() would
2218 * update. If you wonder whether the thread_info variables should be
2219 * synced, yes, they should, and it's done by the
2220 * PA_SINK_MESSAGE_FINISH_MOVE message handler. */
2222 /* Recursively update origin sink inputs. */
2223 PA_IDXSET_FOREACH(origin_sink_input, i->origin_sink->inputs, idx)
2224 update_volume_due_to_moving(origin_sink_input, dest);
2227 if (pa_sink_flat_volume_enabled(i->sink)) {
2228 /* Ok, so this is a regular stream, and flat volume is enabled. The
2229 * volume will have to be updated as follows:
2231 * i->volume := i->reference_ratio * i->sink->reference_volume
2232 * i->reference_ratio stays unchanged
2233 * i->real_ratio := i->volume / i->sink->real_volume
2234 * (handled later by pa_sink_set_volume)
2235 * i->soft_volume := i->real_ratio * i->volume_factor
2236 * (handled later by pa_sink_set_volume) */
2238 new_volume = i->sink->reference_volume;
2239 pa_cvolume_remap(&new_volume, &i->sink->channel_map, &i->channel_map);
2240 pa_sw_cvolume_multiply(&new_volume, &new_volume, &i->reference_ratio);
2241 pa_sink_input_set_volume_direct(i, &new_volume);
2244 /* Ok, so this is a regular stream, and flat volume is disabled.
2245 * The volume will have to be updated as follows:
2247 * i->volume := i->reference_ratio
2248 * i->reference_ratio stays unchanged
2249 * i->real_ratio := i->reference_ratio
2250 * i->soft_volume := i->real_ratio * i->volume_factor */
2252 pa_sink_input_set_volume_direct(i, &i->reference_ratio);
2253 i->real_ratio = i->reference_ratio;
2254 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
2258 /* If i->sink == dest, then recursion has finished, and we can finally call
2259 * pa_sink_set_volume(), which will do the rest of the updates. */
2260 if ((i->sink == dest) && pa_sink_flat_volume_enabled(i->sink))
2261 pa_sink_set_volume(i->sink, NULL, false, i->save_volume);
2264 /* Called from main context */
2265 int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, bool save) {
2266 struct volume_factor_entry *v;
2269 pa_sink_input_assert_ref(i);
2270 pa_assert_ctl_context();
2271 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2272 pa_assert(!i->sink);
2273 pa_sink_assert_ref(dest);
2275 if (!pa_sink_input_may_move_to(i, dest))
2276 return -PA_ERR_NOTSUPPORTED;
2278 if (pa_sink_input_is_passthrough(i) && !pa_sink_check_format(dest, i->format)) {
2279 pa_proplist *p = pa_proplist_new();
2280 pa_log_debug("New sink doesn't support stream format, sending format-changed and killing");
2281 /* Tell the client what device we want to be on if it is going to
2283 pa_proplist_sets(p, "device", dest->name);
2284 pa_sink_input_send_event(i, PA_STREAM_EVENT_FORMAT_LOST, p);
2285 pa_proplist_free(p);
2286 return -PA_ERR_NOTSUPPORTED;
2289 if (!(i->flags & PA_SINK_INPUT_VARIABLE_RATE) &&
2290 !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec)) {
2291 /* try to change dest sink format and rate if possible without glitches.
2292 module-suspend-on-idle resumes destination sink with
2293 SINK_INPUT_MOVE_FINISH hook */
2295 pa_log_info("Trying to change sample spec");
2296 pa_sink_reconfigure(dest, &i->sample_spec, pa_sink_input_is_passthrough(i));
2303 i->save_sink = save;
2304 pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
2306 PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
2307 pa_cvolume_remap(&v->volume, &i->channel_map, &i->sink->channel_map);
2309 pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
2311 if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
2312 i->sink->n_corked++;
2314 pa_sink_input_update_resampler(i);
2316 pa_sink_update_status(dest);
2318 update_volume_due_to_moving(i, dest);
2320 if (pa_sink_input_is_passthrough(i))
2321 pa_sink_enter_passthrough(i->sink);
2323 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
2325 pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
2327 /* Notify everyone */
2328 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
2329 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2334 /* Called from main context */
2335 void pa_sink_input_fail_move(pa_sink_input *i) {
2337 pa_sink_input_assert_ref(i);
2338 pa_assert_ctl_context();
2339 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2340 pa_assert(!i->sink);
2342 /* Check if someone wants this sink input? */
2343 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_STOP)
2349 pa_sink_input_kill(i);
2352 /* Called from main context */
2353 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, bool save) {
2356 pa_sink_input_assert_ref(i);
2357 pa_assert_ctl_context();
2358 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2360 pa_sink_assert_ref(dest);
2362 if (dest == i->sink)
2365 if (!pa_sink_input_may_move_to(i, dest))
2366 return -PA_ERR_NOTSUPPORTED;
2368 pa_sink_input_ref(i);
2370 if ((r = pa_sink_input_start_move(i)) < 0) {
2371 pa_sink_input_unref(i);
2375 if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
2376 pa_sink_input_fail_move(i);
2377 pa_sink_input_unref(i);
2381 pa_sink_input_unref(i);
2386 /* Called from IO thread context except when cork() is called without a valid sink. */
2387 void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
2388 bool corking, uncorking;
2390 pa_sink_input_assert_ref(i);
2392 if (state == i->thread_info.state)
2395 #ifdef TIZEN_EMPTY_POP
2396 if (state != PA_SINK_INPUT_RUNNING && _empty_pop_is_started(i))
2397 _empty_pop_reset(i);
2400 if ((state == PA_SINK_INPUT_DRAINED || state == PA_SINK_INPUT_RUNNING) &&
2401 !(i->thread_info.state == PA_SINK_INPUT_DRAINED || i->thread_info.state != PA_SINK_INPUT_RUNNING))
2402 pa_atomic_store(&i->thread_info.drained, 1);
2404 corking = state == PA_SINK_INPUT_CORKED && i->thread_info.state == PA_SINK_INPUT_RUNNING;
2405 uncorking = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
2407 if (i->state_change)
2408 i->state_change(i, state);
2412 pa_log_debug("Requesting rewind due to corking");
2414 /* This will tell the implementing sink input driver to rewind
2415 * so that the unplayed already mixed data is not lost */
2417 pa_sink_input_request_rewind(i, 0, true, true, false);
2419 /* Set the corked state *after* requesting rewind */
2420 i->thread_info.state = state;
2422 } else if (uncorking) {
2424 pa_log_debug("Requesting rewind due to uncorking");
2426 i->thread_info.underrun_for = (uint64_t) -1;
2427 i->thread_info.underrun_for_sink = 0;
2428 i->thread_info.playing_for = 0;
2430 /* Set the uncorked state *before* requesting rewind */
2431 i->thread_info.state = state;
2433 /* OK, we're being uncorked. Make sure we're not rewound when
2434 * the hw buffer is remixed and request a remix. */
2436 pa_sink_input_request_rewind(i, 0, false, true, true);
2438 /* We may not be corking or uncorking, but we still need to set the state. */
2439 i->thread_info.state = state;
2442 /* Called from thread context, except when it is not. */
2443 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
2444 pa_sink_input *i = PA_SINK_INPUT(o);
2445 pa_sink_input_assert_ref(i);
2449 case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
2450 if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
2451 i->thread_info.soft_volume = i->soft_volume;
2452 #ifdef TIZEN_VOLUME_RAMP
2453 /* Skip rewinding */
2454 if (userdata && (bool)(*(bool*)userdata) == true)
2457 pa_sink_input_request_rewind(i, 0, true, false, false);
2461 #ifdef TIZEN_VOLUME_RAMP
2462 case PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP:
2463 /* we have ongoing ramp where we take current start values */
2464 pa_cvolume_ramp_start_from(&i->thread_info.ramp, &i->ramp);
2465 i->thread_info.ramp = i->ramp;
2466 pa_sink_input_request_rewind(i, 0, true, false, false);
2469 case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
2470 if (i->thread_info.muted != i->muted) {
2471 i->thread_info.muted = i->muted;
2472 pa_sink_input_request_rewind(i, 0, true, false, false);
2476 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
2477 pa_usec_t *r = userdata;
2479 r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
2480 r[1] += pa_sink_get_latency_within_thread(i->sink, false);
2485 case PA_SINK_INPUT_MESSAGE_SET_RATE:
2487 i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
2488 pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
2492 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
2493 pa_sink_input *ssync;
2495 pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
2497 for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
2498 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
2500 for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
2501 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
2506 case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
2507 pa_usec_t *usec = userdata;
2509 *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
2513 case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
2514 pa_usec_t *r = userdata;
2516 *r = i->thread_info.requested_sink_latency;
2521 return -PA_ERR_NOTIMPLEMENTED;
2524 /* Called from main thread */
2525 pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
2526 pa_sink_input_assert_ref(i);
2527 pa_assert_ctl_context();
2529 if (i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED)
2530 return pa_atomic_load(&i->thread_info.drained) ? PA_SINK_INPUT_DRAINED : PA_SINK_INPUT_RUNNING;
2535 /* Called from IO context */
2536 bool pa_sink_input_safe_to_remove(pa_sink_input *i) {
2537 pa_sink_input_assert_ref(i);
2538 pa_sink_input_assert_io_context(i);
2540 if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
2541 return pa_memblockq_is_empty(i->thread_info.render_memblockq);
2546 /* Called from IO context */
2547 void pa_sink_input_request_rewind(
2549 size_t nbytes /* in our sample spec */,
2550 bool rewrite, /* rewrite what we have, or get fresh data? */
2551 bool flush, /* flush render memblockq? */
2552 bool dont_rewind_render) {
2556 /* If 'rewrite' is true the sink is rewound as far as requested
2557 * and possible and the exact value of this is passed back the
2558 * implementor via process_rewind(). If 'flush' is also true all
2559 * already rendered data is also dropped.
2561 * If 'rewrite' is false the sink is rewound as far as requested
2562 * and possible and the already rendered data is dropped so that
2563 * in the next iteration we read new data from the
2564 * implementor. This implies 'flush' is true. If
2565 * dont_rewind_render is true then the render memblockq is not
2568 /* nbytes = 0 means maximum rewind request */
2570 pa_sink_input_assert_ref(i);
2571 pa_sink_input_assert_io_context(i);
2572 pa_assert(rewrite || flush);
2573 pa_assert(!dont_rewind_render || !rewrite);
2575 /* We don't take rewind requests while we are corked */
2576 if (i->thread_info.state == PA_SINK_INPUT_CORKED)
2579 nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
2581 #ifdef SINK_INPUT_DEBUG
2582 pa_log_debug("request rewrite %zu", nbytes);
2585 /* Calculate how much we can rewind locally without having to
2588 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
2592 /* Check if rewinding for the maximum is requested, and if so, fix up */
2595 /* Calculate maximum number of bytes that could be rewound in theory */
2596 nbytes = i->sink->thread_info.max_rewind + lbq;
2598 /* Transform from sink domain */
2599 if (i->thread_info.resampler)
2600 nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
2603 /* Remember how much we actually want to rewrite */
2604 if (i->thread_info.rewrite_nbytes != (size_t) -1) {
2606 /* Make sure to not overwrite over underruns */
2607 if (nbytes > i->thread_info.playing_for)
2608 nbytes = (size_t) i->thread_info.playing_for;
2610 i->thread_info.rewrite_nbytes = nbytes;
2612 i->thread_info.rewrite_nbytes = (size_t) -1;
2615 i->thread_info.rewrite_flush =
2616 i->thread_info.rewrite_flush || flush;
2618 i->thread_info.dont_rewind_render =
2619 i->thread_info.dont_rewind_render ||
2622 /* nbytes is -1 if some earlier rewind request had rewrite == false. */
2623 if (nbytes != (size_t) -1) {
2625 /* Transform to sink domain */
2626 if (i->thread_info.resampler)
2627 nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
2630 pa_sink_request_rewind(i->sink, nbytes - lbq);
2632 /* This call will make sure process_rewind() is called later */
2633 pa_sink_request_rewind(i->sink, 0);
2637 /* Called from main context */
2638 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
2639 pa_sink_input_assert_ref(i);
2640 pa_assert_ctl_context();
2643 /* FIXME: Shouldn't access resampler object from main context! */
2645 pa_silence_memchunk_get(
2646 &i->core->silence_cache,
2650 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
2655 #ifdef TIZEN_EMPTY_POP
2656 static void _empty_pop_start(pa_sink_input *i) {
2657 i->empty_pop_initial_timestamp = pa_rtclock_now();
2658 i->empty_pop_previous_duration = 0;
2660 pa_log_debug("[%u] empty pop started!!!", i->index);
2663 static bool _empty_pop_is_started(pa_sink_input *i) {
2664 if (i->empty_pop_initial_timestamp > 0)
2670 static uint32_t _empty_pop_calc_duration(pa_sink_input *i) {
2671 return (uint32_t)((pa_rtclock_now() - i->empty_pop_initial_timestamp) / PA_USEC_PER_SEC);
2674 static void _empty_pop_print_duration(pa_sink_input *i, uint32_t empty_pop_duration) {
2675 /* print only once per seconds */
2676 if (empty_pop_duration <= i->empty_pop_previous_duration)
2679 i->empty_pop_previous_duration = empty_pop_duration;
2681 pa_log_debug("[%u] empty pop (no sink-input data) for [%u] sec., timeout is [%u] sec.",
2682 i->index, empty_pop_duration, i->core->empty_pop_threshold);
2685 static void _empty_pop_reset(pa_sink_input *i) {
2686 i->empty_pop_initial_timestamp = 0;
2687 i->empty_pop_previous_duration = 0;
2689 pa_log_debug("[%u] empty pop reset...", i->index);
2692 void pa_sink_input_update_empty_pop(pa_sink_input *i, size_t length, bool *is_timeout) {
2693 pa_sink_input_assert_ref(i);
2694 pa_assert(is_timeout);
2697 if (_empty_pop_is_started(i)) {
2698 /* calculate empty pop duration in seconds */
2699 uint32_t empty_pop_duration = _empty_pop_calc_duration(i);
2700 if (empty_pop_duration >= i->core->empty_pop_threshold) {
2702 _empty_pop_reset(i);
2705 _empty_pop_print_duration(i, empty_pop_duration);
2707 _empty_pop_start(i);
2710 if (_empty_pop_is_started(i))
2711 _empty_pop_reset(i);
2714 *is_timeout = false;
2716 #endif /* TIZEN_EMPTY_POP */
2718 /* Called from the main thread. */
2719 void pa_sink_input_set_silence_to_first_peek(pa_sink_input *i, bool silence, pa_usec_t duration) {
2721 pa_sink_input_assert_ref(i);
2722 pa_assert_ctl_context();
2723 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2725 i->thread_info.silenced = silence;
2726 i->thread_info.silence_duration = duration;
2732 /* Called from main context */
2733 void pa_sink_input_send_event(pa_sink_input *i, const char *event, pa_proplist *data) {
2734 pa_proplist *pl = NULL;
2735 pa_sink_input_send_event_hook_data hook_data;
2737 pa_sink_input_assert_ref(i);
2738 pa_assert_ctl_context();
2745 data = pl = pa_proplist_new();
2747 hook_data.sink_input = i;
2748 hook_data.data = data;
2749 hook_data.event = event;
2751 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
2754 i->send_event(i, event, data);
2758 pa_proplist_free(pl);
2761 /* Called from main context */
2762 /* Updates the sink input's resampler with whatever the current sink requires
2763 * -- useful when the underlying sink's sample spec might have changed */
2764 int pa_sink_input_update_resampler(pa_sink_input *i) {
2765 pa_resampler *new_resampler;
2766 char *memblockq_name;
2768 pa_sink_input_assert_ref(i);
2769 pa_assert_ctl_context();
2771 if (i->thread_info.resampler &&
2772 pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &i->sink->sample_spec) &&
2773 pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &i->sink->channel_map))
2775 new_resampler = i->thread_info.resampler;
2777 else if (!pa_sink_input_is_passthrough(i) &&
2778 ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
2779 !pa_sample_spec_equal(&i->sample_spec, &i->sink->sample_spec) ||
2780 !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map))) {
2782 new_resampler = pa_resampler_new(i->core->mempool,
2783 &i->sample_spec, &i->channel_map,
2784 &i->sink->sample_spec, &i->sink->channel_map,
2785 i->core->lfe_crossover_freq,
2786 i->requested_resample_method,
2787 ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
2788 ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
2789 (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
2790 (i->core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
2791 (i->core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0));
2793 if (!new_resampler) {
2794 pa_log_warn("Unsupported resampling operation.");
2795 return -PA_ERR_NOTSUPPORTED;
2798 new_resampler = NULL;
2800 if (new_resampler == i->thread_info.resampler)
2803 if (i->thread_info.resampler)
2804 pa_resampler_free(i->thread_info.resampler);
2806 i->thread_info.resampler = new_resampler;
2808 pa_memblockq_free(i->thread_info.render_memblockq);
2810 memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index);
2811 i->thread_info.render_memblockq = pa_memblockq_new(
2814 MEMBLOCKQ_MAXLENGTH,
2816 &i->sink->sample_spec,
2821 pa_xfree(memblockq_name);
2823 i->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID;
2825 pa_log_debug("Updated resampler for sink input %d", i->index);
2830 /* Called from the IO thread. */
2831 void pa_sink_input_attach(pa_sink_input *i) {
2833 pa_assert(!i->thread_info.attached);
2835 i->thread_info.attached = true;
2841 /* Called from the IO thread. */
2842 void pa_sink_input_detach(pa_sink_input *i) {
2845 if (!i->thread_info.attached)
2848 i->thread_info.attached = false;
2854 /* Called from the main thread. */
2855 void pa_sink_input_set_volume_direct(pa_sink_input *i, const pa_cvolume *volume) {
2856 pa_cvolume old_volume;
2857 char old_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2858 char new_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2863 old_volume = i->volume;
2865 if (pa_cvolume_equal(volume, &old_volume))
2868 i->volume = *volume;
2869 pa_log_debug("The volume of sink input %u changed from %s to %s.", i->index,
2870 pa_cvolume_snprint_verbose(old_volume_str, sizeof(old_volume_str), &old_volume, &i->channel_map, true),
2871 pa_cvolume_snprint_verbose(new_volume_str, sizeof(new_volume_str), volume, &i->channel_map, true));
2873 if (i->volume_changed)
2874 i->volume_changed(i);
2876 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2877 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_VOLUME_CHANGED], i);
2880 /* Called from the main thread. */
2881 void pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume *ratio) {
2882 pa_cvolume old_ratio;
2883 char old_ratio_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2884 char new_ratio_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2889 old_ratio = i->reference_ratio;
2891 if (pa_cvolume_equal(ratio, &old_ratio))
2894 i->reference_ratio = *ratio;
2896 if (!PA_SINK_INPUT_IS_LINKED(i->state))
2899 pa_log_debug("Sink input %u reference ratio changed from %s to %s.", i->index,
2900 pa_cvolume_snprint_verbose(old_ratio_str, sizeof(old_ratio_str), &old_ratio, &i->channel_map, true),
2901 pa_cvolume_snprint_verbose(new_ratio_str, sizeof(new_ratio_str), ratio, &i->channel_map, true));