Add default-monitor-time-sec
[platform/upstream/pulseaudio.git] / src / pulsecore / sink-input.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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/>.
19 ***/
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #ifdef TIZEN_PCM_DUMP
28 #include <time.h>
29 #endif
30
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>
38 #endif
39 #ifdef __TIZEN__
40 #include <pulse/rtclock.h>
41 #endif
42
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>
51
52 #include "sink-input.h"
53
54 /* #define SINK_INPUT_DEBUG */
55
56 #define MEMBLOCKQ_MAXLENGTH (32*1024*1024)
57 #define CONVERT_BUFFER_LENGTH (pa_page_size())
58
59 PA_DEFINE_PUBLIC_CLASS(pa_sink_input, pa_msgobject);
60
61 struct volume_factor_entry {
62     char *key;
63     pa_cvolume volume;
64 };
65
66 #ifdef TIZEN_VOLUME_RAMP
67 struct volume_ramp_factor_entry {
68     char *key;
69     pa_cvolume_ramp ramp;
70 };
71 #endif
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);
75 #endif
76 #ifdef TIZEN_PCM_DUMP
77 static void pa_sink_input_write_pcm_dump(pa_sink_input *i, pa_memchunk *chunk)
78 {
79     char *dump_time = NULL, *dump_path_surfix = NULL;
80     const char *s_device_api_str, *card_name_str, *device_idx_str;
81     struct timeval now;
82     struct tm tm;
83     char datetime[7];
84
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);
92
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));
98             } else {
99                 dump_path_surfix = pa_sprintf_malloc("%s", s_device_api_str);
100             }
101         } else {
102             dump_path_surfix = pa_sprintf_malloc("%s", i->sink->name);
103         }
104
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);
107         if (i->dump_path) {
108             i->pcm_dump_fp = fopen(i->dump_path, "w");
109             if (!i->pcm_dump_fp)
110                 pa_log_warn("%s open failed", i->dump_path);
111             else
112                 pa_log_info("%s opened", i->dump_path);
113         }
114         pa_xfree(dump_time);
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;
122     }
123
124     /* dump pcm */
125     if (i->pcm_dump_fp) {
126         void *ptr = NULL;
127
128         ptr = pa_memblock_acquire(chunk->memblock);
129         if (ptr) {
130             i->dump_length = chunk->length;
131             fwrite((uint8_t *)ptr + chunk->index, 1, chunk->length, i->pcm_dump_fp);
132         } else {
133             i->dump_length = 0;
134             pa_log_warn("pa_memblock_acquire is failed. ptr is NULL");
135         }
136         pa_memblock_release(chunk->memblock);
137     }
138 }
139 #endif
140
141 static struct volume_factor_entry *volume_factor_entry_new(const char *key, const pa_cvolume *volume) {
142     struct volume_factor_entry *entry;
143
144     pa_assert(key);
145     pa_assert(volume);
146
147     entry = pa_xnew(struct volume_factor_entry, 1);
148     entry->key = pa_xstrdup(key);
149
150     entry->volume = *volume;
151
152     return entry;
153 }
154
155 static void volume_factor_entry_free(struct volume_factor_entry *volume_entry) {
156     pa_assert(volume_entry);
157
158     pa_xfree(volume_entry->key);
159     pa_xfree(volume_entry);
160 }
161
162 static void volume_factor_from_hashmap(pa_cvolume *v, pa_hashmap *items, uint8_t channels) {
163     struct volume_factor_entry *entry;
164     void *state = NULL;
165
166     pa_cvolume_reset(v, channels);
167     PA_HASHMAP_FOREACH(entry, items, state)
168         pa_sw_cvolume_multiply(v, v, &entry->volume);
169 }
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;
173
174     pa_assert(key);
175     pa_assert(ramp);
176
177     entry = pa_xnew(struct volume_ramp_factor_entry, 1);
178     entry->key = pa_xstrdup(key);
179
180     entry->ramp = *ramp;
181
182     return entry;
183 }
184
185 static void volume_ramp_factor_entry_free(struct volume_ramp_factor_entry *ramp_entry) {
186     pa_assert(ramp_entry);
187
188     pa_xfree(ramp_entry->key);
189     pa_xfree(ramp_entry);
190 }
191
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;
194     void *state = NULL;
195
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);
199
200 }
201 #endif
202
203 static void sink_input_free(pa_object *o);
204 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v);
205
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");
209         return -PA_ERR_BUSY;
210     }
211
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");
215         return -PA_ERR_BUSY;
216     }
217
218     return PA_OK;
219 }
220
221 pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) {
222     pa_assert(data);
223
224     pa_zero(*data);
225     data->resample_method = PA_RESAMPLER_INVALID;
226     data->proplist = pa_proplist_new();
227     data->volume_writable = true;
228
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;
235 #endif
236
237     return data;
238 }
239
240 void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec) {
241     pa_assert(data);
242
243     if ((data->sample_spec_is_set = !!spec))
244         data->sample_spec = *spec;
245 }
246
247 void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map) {
248     pa_assert(data);
249
250     if ((data->channel_map_is_set = !!map))
251         data->channel_map = *map;
252 }
253
254 bool pa_sink_input_new_data_is_passthrough(pa_sink_input_new_data *data) {
255     pa_assert(data);
256
257     if (PA_LIKELY(data->format) && PA_UNLIKELY(!pa_format_info_is_pcm(data->format)))
258         return true;
259
260     if (PA_UNLIKELY(data->flags & PA_SINK_INPUT_PASSTHROUGH))
261         return true;
262
263     return false;
264 }
265
266 void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) {
267     pa_assert(data);
268     pa_assert(data->volume_writable);
269
270     if ((data->volume_is_set = !!volume))
271         data->volume = *volume;
272 }
273
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;
276
277     pa_assert(data);
278     pa_assert(key);
279     pa_assert(volume_factor);
280
281     v = volume_factor_entry_new(key, volume_factor);
282     pa_assert_se(pa_hashmap_put(data->volume_factor_items, v->key, v) >= 0);
283 }
284
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;
287
288     pa_assert(data);
289     pa_assert(key);
290     pa_assert(volume_factor);
291
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);
294 }
295
296 void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, bool mute) {
297     pa_assert(data);
298
299     data->muted_is_set = true;
300     data->muted = mute;
301 }
302
303 bool pa_sink_input_new_data_set_sink(pa_sink_input_new_data *data, pa_sink *s, bool save, bool requested_by_application) {
304     bool ret = true;
305     pa_idxset *formats = NULL;
306
307     pa_assert(data);
308     pa_assert(s);
309
310     if (!data->req_formats) {
311         /* We're not working with the extended API */
312         data->sink = s;
313         if (save) {
314             pa_xfree(data->preferred_sink);
315             data->preferred_sink = pa_xstrdup(s->name);
316         }
317         data->sink_requested_by_application = requested_by_application;
318     } else {
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);
321
322         if (formats && !pa_idxset_isempty(formats)) {
323             /* Sink supports at least one of the requested formats */
324             data->sink = s;
325             if (save) {
326                 pa_xfree(data->preferred_sink);
327                 data->preferred_sink = pa_xstrdup(s->name);
328             }
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;
333         } else {
334             /* Sink doesn't support any of the formats requested by the client */
335             if (formats)
336                 pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
337             ret = false;
338         }
339     }
340
341     return ret;
342 }
343
344 bool pa_sink_input_new_data_set_formats(pa_sink_input_new_data *data, pa_idxset *formats) {
345     pa_assert(data);
346     pa_assert(formats);
347
348     if (data->req_formats)
349         pa_idxset_free(data->req_formats, (pa_free_cb_t) pa_format_info_free);
350
351     data->req_formats = formats;
352
353     if (data->sink) {
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);
356     }
357
358     return true;
359 }
360
361 void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
362     pa_assert(data);
363
364     if (data->req_formats)
365         pa_idxset_free(data->req_formats, (pa_free_cb_t) pa_format_info_free);
366
367     if (data->nego_formats)
368         pa_idxset_free(data->nego_formats, (pa_free_cb_t) pa_format_info_free);
369
370     if (data->format)
371         pa_format_info_free(data->format);
372
373     if (data->volume_factor_items)
374         pa_hashmap_free(data->volume_factor_items);
375
376     if (data->volume_factor_sink_items)
377         pa_hashmap_free(data->volume_factor_sink_items);
378
379     if (data->preferred_sink)
380         pa_xfree(data->preferred_sink);
381
382     pa_proplist_free(data->proplist);
383 }
384
385 /* Called from main context */
386 static void reset_callbacks(pa_sink_input *i) {
387     pa_assert(i);
388
389     i->pop = NULL;
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;
397     i->attach = NULL;
398     i->detach = NULL;
399     i->suspend = NULL;
400     i->suspend_within_thread = NULL;
401     i->moving = NULL;
402     i->kill = 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;
409 }
410
411 /* Called from main context */
412 int pa_sink_input_new(
413         pa_sink_input **_i,
414         pa_core *core,
415         pa_sink_input_new_data *data) {
416
417     pa_sink_input *i;
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;
421     int r;
422     char *pt;
423     char *memblockq_name;
424
425     pa_assert(_i);
426     pa_assert(core);
427     pa_assert(data);
428     pa_assert_ctl_context();
429
430     if (data->client)
431         pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
432
433     if (data->origin_sink && (data->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
434         data->volume_writable = false;
435
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. */
440         pa_format_info *f;
441         pa_idxset *formats;
442
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));
447         if (!f)
448             return -PA_ERR_INVALID;
449
450         formats = pa_idxset_new(NULL, NULL);
451         pa_idxset_put(formats, f, NULL);
452         pa_sink_input_new_data_set_formats(data, formats);
453     }
454
455     if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0)
456         return r;
457
458     pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
459
460     if (!data->sink) {
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);
464 #ifdef __TIZEN__
465     } else {
466         pa_sink_input_new_data_set_sink(data, data->sink, false, false);
467 #endif
468     }
469
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));
474
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);
480
481         pa_log_debug("Negotiated format: %s", pa_format_info_snprint(fmt, sizeof(fmt), data->format));
482     } else {
483         pa_format_info *format;
484         uint32_t idx;
485
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));
489
490         return -PA_ERR_NOTSUPPORTED;
491     }
492
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),
496                           -PA_ERR_INVALID);
497
498     /* Routing is done. We have a sink and a format. */
499
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);
506         if (r < 0)
507             return r;
508     } else {
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);
512     }
513
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);
518     if (r < 0)
519         return r;
520
521     r = check_passthrough_connection(pa_sink_input_new_data_is_passthrough(data), data->sink);
522     if (r != PA_OK)
523         return r;
524
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;
532     }
533
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;
538     }
539
540     if (!data->volume_writable)
541         data->save_volume = false;
542
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);
547
548     if (!data->muted_is_set)
549         data->muted = false;
550
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 */
555
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));
558     }
559
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 */
563
564         pa_log_debug("Could not update sink sample spec to match passthrough stream");
565         return -PA_ERR_NOTSUPPORTED;
566     }
567
568     if (data->resample_method == PA_RESAMPLER_INVALID)
569         data->resample_method = core->resample_method;
570
571     pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
572
573     if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
574         return r;
575
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;
580     }
581
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.");
584 #ifdef __TIZEN__
585         pa_core_dump_sink_inputs(core);
586 #endif
587         return -PA_ERR_TOOLARGE;
588     }
589
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)) {
593
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(
597                           core->mempool,
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;
610             }
611     }
612
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;
616
617     i->core = core;
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;
627
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);
633
634     if (!data->volume_is_absolute && pa_sink_flat_volume_enabled(i->sink)) {
635         pa_cvolume remapped;
636
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);
642     } else
643         i->volume = data->volume;
644
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);
648
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);
652
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);
656 #endif
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;
662 #endif
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;
667
668     i->muted = data->muted;
669
670     if (data->sync_base) {
671         i->sync_next = data->sync_base->sync_next;
672         i->sync_prev = data->sync_base;
673
674         if (data->sync_base->sync_next)
675             data->sync_base->sync_next->sync_prev = i;
676         data->sync_base->sync_next = i;
677     } else
678         i->sync_next = i->sync_prev = NULL;
679
680     i->direct_outputs = pa_idxset_new(NULL, NULL);
681
682     reset_callbacks(i);
683     i->userdata = NULL;
684 #ifdef TIZEN_EMPTY_POP
685     i->is_virtual = pa_safe_streq(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), "VIRTUAL_STREAM");
686 #endif
687 #ifdef TIZEN_PCM_DUMP
688     i->pcm_dump_fp = NULL;
689     i->dump_path = NULL;
690     i->dump_length = 0;
691 #endif
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);
695     else
696         pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_NORM, data->sink->sample_spec.channels);
697 #endif
698
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;
715 #endif
716
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);
719
720     if (i->client)
721         pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
722
723     memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index);
724     i->thread_info.render_memblockq = pa_memblockq_new(
725             memblockq_name,
726             0,
727             MEMBLOCKQ_MAXLENGTH,
728             0,
729             &i->sink->sample_spec,
730             0,
731             1,
732             0,
733             &i->sink->silence);
734     pa_xfree(memblockq_name);
735
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",
738                 i->index,
739                 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
740                 i->sink->name,
741                 pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
742                 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
743                 pt);
744     pa_xfree(pt);
745
746     /* Don't forget to call pa_sink_input_put! */
747
748     *_i = i;
749     return 0;
750 }
751
752 /* Called from main context */
753 static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
754     pa_assert(i);
755     pa_assert_ctl_context();
756
757     if (!i->sink)
758         return;
759
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)
763         i->sink->n_corked++;
764 }
765
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;
769     pa_assert(i);
770     pa_assert_ctl_context();
771
772     if (i->state == state)
773         return;
774
775 #ifdef TIZEN_EMPTY_POP
776     if (state != PA_SINK_INPUT_RUNNING && _empty_pop_is_started(i))
777         _empty_pop_reset(i);
778 #endif
779
780     if (i->sink) {
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));
786         }
787
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);
789     } else {
790         /* If the sink is not valid, pa_sink_input_set_state_within_thread() must be called directly */
791
792         pa_sink_input_set_state_within_thread(i, state);
793
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);
796
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);
799     }
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;
807     }
808 #endif
809 #ifdef __TIZEN__
810     if (state == PA_SINK_INPUT_RUNNING)
811         i->time_of_start_to_run = pa_rtclock_now();
812 #endif
813
814     update_n_corked(i, state);
815     i->state = state;
816
817     for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev) {
818         update_n_corked(ssync, state);
819         ssync->state = state;
820     }
821     for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) {
822         update_n_corked(ssync, state);
823         ssync->state = state;
824     }
825
826     if (state != PA_SINK_INPUT_UNLINKED) {
827         pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
828
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);
831
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);
834
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);
837     }
838
839     if (i->sink)
840         pa_sink_update_status(i->sink);
841 }
842
843 /* Called from main context */
844 void pa_sink_input_unlink(pa_sink_input *i) {
845     bool linked;
846     pa_source_output *o, PA_UNUSED *p = NULL;
847
848     pa_sink_input_assert_ref(i);
849     pa_assert_ctl_context();
850
851     /* See pa_sink_unlink() for a couple of comments how this function
852      * works */
853
854     pa_sink_input_ref(i);
855
856     linked = PA_SINK_INPUT_IS_LINKED(i->state);
857
858     if (linked)
859         pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
860
861     if (i->sync_prev)
862         i->sync_prev->sync_next = i->sync_next;
863     if (i->sync_next)
864         i->sync_next->sync_prev = i->sync_prev;
865
866     i->sync_prev = i->sync_next = NULL;
867
868     pa_idxset_remove_by_data(i->core->sink_inputs, i, NULL);
869
870     if (i->sink)
871         if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
872             pa_sink_input_unref(i);
873
874     if (i->client)
875         pa_idxset_remove_by_data(i->client->sink_inputs, i, NULL);
876
877     while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
878         pa_assert(o != p);
879         pa_source_output_kill(o);
880         p = o;
881     }
882
883     update_n_corked(i, PA_SINK_INPUT_UNLINKED);
884     i->state = PA_SINK_INPUT_UNLINKED;
885
886     if (linked && i->sink) {
887         if (pa_sink_input_is_passthrough(i))
888             pa_sink_leave_passthrough(i->sink);
889
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);
893
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);
896     }
897
898     reset_callbacks(i);
899
900     if (i->sink) {
901         if (PA_SINK_IS_LINKED(i->sink->state))
902             pa_sink_update_status(i->sink);
903
904         i->sink = NULL;
905     }
906
907     if (linked) {
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);
910     }
911
912     pa_core_maybe_vacuum(i->core);
913
914     pa_sink_input_unref(i);
915 }
916
917 /* Called from main context */
918 static void sink_input_free(pa_object *o) {
919     pa_sink_input* i = PA_SINK_INPUT(o);
920
921     pa_assert(i);
922     pa_assert_ctl_context();
923     pa_assert(pa_sink_input_refcnt(i) == 0);
924     pa_assert(!PA_SINK_INPUT_IS_LINKED(i->state));
925
926     pa_log_info("Freeing input %u \"%s\"", i->index,
927                 i->proplist ? pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)) : "");
928
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! */
933
934     if (i->thread_info.render_memblockq)
935         pa_memblockq_free(i->thread_info.render_memblockq);
936
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;
946     }
947 #endif
948
949     if (i->format)
950         pa_format_info_free(i->format);
951
952     if (i->proplist)
953         pa_proplist_free(i->proplist);
954
955     if (i->direct_outputs)
956         pa_idxset_free(i->direct_outputs, NULL);
957
958     if (i->thread_info.direct_outputs)
959         pa_hashmap_free(i->thread_info.direct_outputs);
960
961     if (i->volume_factor_items)
962         pa_hashmap_free(i->volume_factor_items);
963
964     if (i->volume_factor_sink_items)
965         pa_hashmap_free(i->volume_factor_sink_items);
966
967     if (i->preferred_sink)
968         pa_xfree(i->preferred_sink);
969
970 #ifdef TIZEN_VOLUME_RAMP
971     if (i->ramp_factor_items)
972         pa_hashmap_free(i->ramp_factor_items);
973 #endif
974
975     pa_xfree(i->driver);
976     pa_xfree(i);
977 }
978
979 /* Called from main context */
980 void pa_sink_input_put(pa_sink_input *i) {
981     pa_sink_input_state_t state;
982
983     pa_sink_input_assert_ref(i);
984     pa_assert_ctl_context();
985
986     pa_assert(i->state == PA_SINK_INPUT_INIT);
987
988     /* The following fields must be initialized properly */
989     pa_assert(i->pop);
990     pa_assert(i->process_rewind);
991     pa_assert(i->kill);
992
993     state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
994
995     update_n_corked(i, state);
996     i->state = state;
997
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);
1001     else {
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));
1005         }
1006
1007         set_real_ratio(i, &i->volume);
1008     }
1009
1010     if (pa_sink_input_is_passthrough(i))
1011         pa_sink_enter_passthrough(i->sink);
1012
1013     i->thread_info.soft_volume = i->soft_volume;
1014     i->thread_info.muted = i->muted;
1015
1016     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0);
1017
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);
1020
1021     pa_sink_update_status(i->sink);
1022 }
1023
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));
1029
1030     i->kill(i);
1031 }
1032
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 };
1036
1037     pa_sink_input_assert_ref(i);
1038     pa_assert_ctl_context();
1039     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1040
1041     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, r, 0, NULL) == 0);
1042
1043     if (i->get_latency)
1044         r[0] += i->get_latency(i);
1045
1046     if (sink_latency)
1047         *sink_latency = r[1];
1048
1049     return r[0];
1050 }
1051
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);
1056
1057     if (i->thread_info.silenced && i->thread_info.silence_duration > 0) {
1058         pa_memchunk schunk;
1059         size_t target_length = pa_usec_to_bytes(i->thread_info.silence_duration, &i->sink->sample_spec);
1060
1061         pa_silence_memchunk_get(&i->core->silence_cache,
1062                                 i->core->mempool,
1063                                 &schunk,
1064                                 &i->sink->sample_spec,
1065                                 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
1066
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);
1074 #endif
1075         }
1076         pa_memblock_unref(schunk.memblock);
1077
1078         i->thread_info.silenced = false;
1079         i->thread_info.silence_duration = 0;
1080     }
1081 }
1082
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) {
1085     pa_cvolume target;
1086
1087     pa_assert(ramp);
1088     pa_assert(spec);
1089     pa_assert(chunk);
1090
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);
1099     }
1100 }
1101 #endif
1102
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;
1109 #endif
1110     size_t block_size_max_sink, block_size_max_sink_input;
1111     size_t ilength;
1112     size_t ilength_full;
1113
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));
1118     pa_assert(chunk);
1119     pa_assert(volume);
1120
1121 #ifdef SINK_INPUT_DEBUG
1122 #ifdef __TIZEN__
1123     pa_log_debug("peek, idx(%u)", i->index);
1124 #else
1125     pa_log_debug("peek");
1126 #endif
1127 #endif
1128
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);
1132
1133     block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sink->sample_spec);
1134
1135     /* Default buffer size */
1136     if (slength <= 0)
1137         slength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec);
1138
1139     if (slength > block_size_max_sink)
1140         slength = block_size_max_sink;
1141
1142     if (i->thread_info.resampler) {
1143         ilength = pa_resampler_request(i->thread_info.resampler, slength);
1144
1145         if (ilength <= 0)
1146             ilength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
1147     } else
1148         ilength = slength;
1149
1150     /* Length corresponding to slength (without limiting to
1151      * block_size_max_sink_input). */
1152     ilength_full = ilength;
1153
1154     if (ilength > block_size_max_sink_input)
1155         ilength = block_size_max_sink_input;
1156
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 */
1160
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);
1164
1165     while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
1166         pa_memchunk tchunk;
1167
1168         /* There's nothing in our render queue. We need to fill it up
1169          * with data from the implementor. */
1170
1171         if (i->thread_info.state == PA_SINK_INPUT_CORKED ||
1172             i->pop(i, ilength, &tchunk) < 0) {
1173
1174             /* OK, we're corked or the implementor didn't give us any
1175              * data, so let's just hand out silence */
1176
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;
1182             }
1183             break;
1184         }
1185
1186         pa_assert(tchunk.length > 0);
1187         pa_assert(tchunk.memblock);
1188
1189         i->thread_info.underrun_for = 0;
1190         i->thread_info.underrun_for_sink = 0;
1191         i->thread_info.playing_for += tchunk.length;
1192
1193         while (tchunk.length > 0) {
1194             pa_memchunk wchunk;
1195             bool nvfs = need_volume_factor_sink;
1196
1197             wchunk = tchunk;
1198             pa_memblock_ref(wchunk.memblock);
1199
1200             if (wchunk.length > block_size_max_sink_input)
1201                 wchunk.length = block_size_max_sink_input;
1202
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);
1206
1207                 if (i->thread_info.muted) {
1208                     pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
1209                     nvfs = false;
1210
1211                 } else if (!i->thread_info.resampler && nvfs) {
1212                     pa_cvolume v;
1213
1214                     /* If we don't need a resampler we can merge the
1215                      * post and the pre volume adjustment into one */
1216
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);
1219                     nvfs = false;
1220
1221                 } else
1222                     pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);
1223             }
1224
1225 #ifdef TIZEN_VOLUME_RAMP
1226             check_and_apply_silence(i);
1227
1228             prev_ramp_finished = i->thread_info.ramp.finished;
1229 #endif
1230             if (!i->thread_info.resampler) {
1231
1232                 if (nvfs) {
1233                     pa_memchunk_make_writable(&wchunk, 0);
1234                     pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
1235                 }
1236
1237 #ifdef TIZEN_VOLUME_RAMP
1238                 check_and_apply_ramp(&i->thread_info.ramp, &i->sink->sample_spec, &wchunk);
1239 #endif
1240                 pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
1241             } else {
1242                 pa_memchunk rchunk;
1243 #ifdef TIZEN_VOLUME_RAMP
1244                 check_and_apply_ramp(&i->thread_info.ramp, &i->thread_info.sample_spec, &wchunk);
1245 #endif
1246                 pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
1247
1248 #ifdef SINK_INPUT_DEBUG
1249                 pa_log_debug("pushing %lu", (unsigned long) rchunk.length);
1250 #endif
1251
1252                 if (rchunk.memblock) {
1253
1254                     if (nvfs) {
1255                         pa_memchunk_make_writable(&rchunk, 0);
1256                         pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
1257                     }
1258
1259                     pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
1260                     pa_memblock_unref(rchunk.memblock);
1261                 }
1262             }
1263
1264             pa_memblock_unref(wchunk.memblock);
1265
1266             tchunk.index += wchunk.length;
1267             tchunk.length -= wchunk.length;
1268         }
1269
1270         pa_memblock_unref(tchunk.memblock);
1271     }
1272
1273     pa_assert_se(pa_memblockq_peek(i->thread_info.render_memblockq, chunk) >= 0);
1274
1275     pa_assert(chunk->length > 0);
1276     pa_assert(chunk->memblock);
1277
1278 #ifdef SINK_INPUT_DEBUG
1279     pa_log_debug("peeking %lu", (unsigned long) chunk->length);
1280 #endif
1281
1282     if (chunk->length > block_size_max_sink)
1283         chunk->length = block_size_max_sink;
1284
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 */
1287
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);
1294     else
1295         *volume = i->thread_info.soft_volume;
1296 #ifdef TIZEN_PCM_DUMP
1297     pa_sink_input_write_pcm_dump(i, chunk);
1298 #endif
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;
1305     }
1306 #endif
1307 }
1308
1309 /* Called from thread context */
1310 void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
1311
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);
1317
1318 #ifdef SINK_INPUT_DEBUG
1319     pa_log_debug("dropping %lu", (unsigned long) nbytes);
1320 #endif
1321 #ifdef TIZEN_PCM_DUMP
1322     if (i->pcm_dump_fp && i->dump_length) {
1323         int64_t seek_length;
1324
1325         seek_length = (int64_t) (nbytes - i->dump_length);
1326
1327         if (seek_length < 0)
1328             fseeko(i->pcm_dump_fp, (off_t)seek_length, SEEK_CUR);
1329
1330         i->dump_length = 0;
1331     }
1332 #endif
1333
1334     pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
1335 }
1336
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);
1341
1342     if (pa_memblockq_is_readable(i->thread_info.render_memblockq))
1343         return false;
1344
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);
1348         return true;
1349     }
1350     return false;
1351 }
1352
1353 /* Called from thread context */
1354 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
1355     size_t lbq;
1356     bool called = false;
1357
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));
1362
1363 #ifdef SINK_INPUT_DEBUG
1364     pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes);
1365 #endif
1366
1367     lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
1368
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);
1372     }
1373
1374     if (i->thread_info.rewrite_nbytes == (size_t) -1) {
1375
1376 #ifdef TIZEN_PCM_DUMP
1377         /* rewind pcm */
1378         if (i->pcm_dump_fp)
1379             fseeko(i->pcm_dump_fp, (off_t)pa_memblockq_get_length(i->thread_info.render_memblockq) * (-1), SEEK_CUR);
1380 #endif
1381         /* We were asked to drop all buffered data, and rerequest new
1382          * data from implementor the next time peek() is called */
1383
1384         pa_memblockq_flush_write(i->thread_info.render_memblockq, true);
1385
1386     } else if (i->thread_info.rewrite_nbytes > 0) {
1387         size_t max_rewrite, amount;
1388
1389         /* Calculate how much make sense to rewrite at most */
1390         max_rewrite = nbytes;
1391         if (nbytes > 0)
1392             max_rewrite += lbq;
1393
1394         /* Transform into local domain */
1395         if (i->thread_info.resampler)
1396             max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
1397
1398         /* Calculate how much of the rewinded data should actually be rewritten */
1399         amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
1400
1401         if (amount > 0) {
1402             pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
1403
1404 #ifdef TIZEN_PCM_DUMP
1405             /* rewind pcm */
1406             if (i->pcm_dump_fp)
1407                 fseeko(i->pcm_dump_fp, (off_t)amount * (-1), SEEK_CUR);
1408 #endif
1409             /* Tell the implementor */
1410             if (i->process_rewind)
1411                 i->process_rewind(i, amount);
1412             called = true;
1413
1414             /* Convert back to sink domain */
1415             if (i->thread_info.resampler)
1416                 amount = pa_resampler_result(i->thread_info.resampler, amount);
1417
1418             if (amount > 0)
1419                 /* Ok, now update the write pointer */
1420                 pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE, true);
1421
1422             if (i->thread_info.rewrite_flush)
1423                 pa_memblockq_silence(i->thread_info.render_memblockq);
1424
1425             /* And rewind the resampler */
1426             if (i->thread_info.resampler)
1427                 pa_resampler_rewind(i->thread_info.resampler, amount);
1428         }
1429     }
1430
1431     if (!called)
1432         if (i->process_rewind)
1433             i->process_rewind(i, 0);
1434
1435     i->thread_info.rewrite_nbytes = 0;
1436     i->thread_info.rewrite_flush = false;
1437     i->thread_info.dont_rewind_render = false;
1438 }
1439
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);
1444
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;
1446 }
1447
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);
1452
1453     /* We're not verifying the status here, to allow this to be called
1454      * in the state change handler between _INIT and _RUNNING */
1455
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;
1457 }
1458
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));
1465
1466     pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
1467
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);
1470 }
1471
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));
1478
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);
1481 }
1482
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);
1487
1488     if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1489         usec = i->sink->thread_info.fixed_latency;
1490
1491     if (usec != (pa_usec_t) -1)
1492         usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
1493
1494     i->thread_info.requested_sink_latency = usec;
1495     pa_sink_invalidate_requested_latency(i->sink, true);
1496
1497     return usec;
1498 }
1499
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();
1504
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);
1507         return usec;
1508     }
1509
1510     /* If this sink input is not realized yet or we are being moved,
1511      * we have to touch the thread info data directly */
1512
1513     if (i->sink) {
1514         if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1515             usec = pa_sink_get_fixed_latency(i->sink);
1516
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);
1521         }
1522     }
1523
1524     i->thread_info.requested_sink_latency = usec;
1525
1526     return usec;
1527 }
1528
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();
1533
1534     if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1535         pa_usec_t usec = 0;
1536         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1537         return usec;
1538     }
1539
1540     /* If this sink input is not realized yet or we are being moved,
1541      * we have to touch the thread info data directly */
1542
1543     return i->thread_info.requested_sink_latency;
1544 }
1545
1546 /* Called from main context */
1547 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool save, bool absolute) {
1548     pa_cvolume v;
1549
1550     pa_sink_input_assert_ref(i);
1551     pa_assert_ctl_context();
1552     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1553     pa_assert(volume);
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);
1557
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);
1561
1562         if (pa_cvolume_compatible(volume, &i->sample_spec))
1563             volume = pa_sw_cvolume_multiply(&v, &v, volume);
1564         else
1565             volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume));
1566     } else {
1567         if (!pa_cvolume_compatible(volume, &i->sample_spec)) {
1568             v = i->volume;
1569             volume = pa_cvolume_scale(&v, pa_cvolume_max(volume));
1570         }
1571     }
1572
1573     if (pa_cvolume_equal(volume, &i->volume)) {
1574         i->save_volume = i->save_volume || save;
1575         return;
1576     }
1577
1578     pa_sink_input_set_volume_direct(i, volume);
1579     i->save_volume = save;
1580
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 */
1584
1585         pa_sink_set_volume(i->sink, NULL, true, save);
1586
1587     } else {
1588         /* OK, we are in normal volume mode. The volume only affects
1589          * ourselves */
1590         set_real_ratio(i, volume);
1591         pa_sink_input_set_reference_ratio(i, &i->volume);
1592
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);
1595     }
1596 }
1597
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;
1600
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);
1605     pa_assert(key);
1606     pa_assert(pa_cvolume_valid(volume_factor));
1607     pa_assert(volume_factor->channels == 1 || pa_cvolume_compatible(volume_factor, &i->sample_spec));
1608
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]);
1612
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;
1616     else
1617         pa_sw_cvolume_multiply(&i->volume_factor, &i->volume_factor, &v->volume);
1618
1619     pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1620
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);
1623 }
1624
1625 /* Returns 0 if an entry was removed and -1 if no entry for the given key was
1626  * found. */
1627 int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) {
1628     struct volume_factor_entry *v;
1629
1630     pa_sink_input_assert_ref(i);
1631     pa_assert(key);
1632     pa_assert_ctl_context();
1633     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1634
1635     if (pa_hashmap_remove_and_free(i->volume_factor_items, key) < 0)
1636         return -1;
1637
1638     switch (pa_hashmap_size(i->volume_factor_items)) {
1639         case 0:
1640             pa_cvolume_reset(&i->volume_factor, i->sample_spec.channels);
1641             break;
1642         case 1:
1643             v = pa_hashmap_first(i->volume_factor_items);
1644             i->volume_factor = v->volume;
1645             break;
1646         default:
1647             volume_factor_from_hashmap(&i->volume_factor, i->volume_factor_items, i->volume_factor.channels);
1648     }
1649
1650     pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1651
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);
1657     } else {
1658 #endif
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
1662     }
1663 #endif
1664
1665     return 0;
1666 }
1667
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;
1671
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);
1676     pa_assert(key);
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));
1679
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);
1686
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);
1690     else
1691         pa_sw_cvolume_ramp_multiply(&i->ramp_factor, &i->ramp_factor, &r->ramp);
1692
1693     pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp,  i->sample_spec.rate);
1694
1695     if (send_msg)
1696         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
1697 }
1698
1699 /* Returns 0 if an entry was removed and -1 if no entry for the given key was
1700  * found. */
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;
1703
1704     pa_sink_input_assert_ref(i);
1705     pa_assert(key);
1706     pa_assert_ctl_context();
1707     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1708
1709     r = pa_hashmap_remove(i->ramp_factor_items, key);
1710     if (!r)
1711         return -1;
1712
1713     switch (pa_hashmap_size(i->ramp_factor_items)) {
1714         case 0:
1715             pa_cvolume_ramp_reset(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length);
1716             break;
1717         case 1: {
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);
1721             break;
1722         }
1723         default:
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);
1725     }
1726
1727     volume_ramp_factor_entry_free(r);
1728
1729     pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate);
1730
1731     if (send_msg)
1732         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
1733
1734     return 0;
1735 }
1736 #endif
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));
1743
1744     /* This basically calculates:
1745      *
1746      * i->real_ratio := v
1747      * i->soft_volume := i->real_ratio * i->volume_factor */
1748
1749     if (v)
1750         i->real_ratio = *v;
1751     else
1752         pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
1753
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 */
1756 }
1757
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);
1761
1762     if (PA_UNLIKELY(!pa_format_info_is_pcm(i->format)))
1763         return true;
1764
1765     if (PA_UNLIKELY(i->flags & PA_SINK_INPUT_PASSTHROUGH))
1766         return true;
1767
1768     return false;
1769 }
1770
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();
1775
1776     return !pa_sink_input_is_passthrough(i);
1777 }
1778
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));
1785
1786     if (absolute || !pa_sink_flat_volume_enabled(i->sink))
1787         *volume = i->volume;
1788     else
1789         *volume = i->reference_ratio;
1790
1791     return volume;
1792 }
1793
1794 /* Called from main context */
1795 void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save) {
1796     bool old_mute;
1797
1798     pa_sink_input_assert_ref(i);
1799     pa_assert_ctl_context();
1800     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1801
1802     old_mute = i->muted;
1803
1804     if (mute == old_mute) {
1805         i->save_muted |= save;
1806         return;
1807     }
1808
1809     i->muted = mute;
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));
1811
1812     i->save_muted = save;
1813
1814     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
1815
1816     /* The mute status changed, let's tell people so */
1817     if (i->mute_changed)
1818         i->mute_changed(i);
1819
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);
1822 }
1823
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;
1827
1828     pa_assert(i);
1829     pa_assert(key);
1830
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))
1834             goto finish;
1835
1836         if (!old_value)
1837             old_value = pa_xstrdup("(data)");
1838     } else {
1839         if (!value)
1840             goto finish;
1841
1842         old_value = pa_xstrdup("(unset)");
1843     }
1844
1845     if (value) {
1846         pa_proplist_sets(i->proplist, key, value);
1847         new_value = value;
1848     } else {
1849         pa_proplist_unset(i->proplist, key);
1850         new_value = "(unset)";
1851     }
1852
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);
1857     }
1858
1859 finish:
1860     pa_xfree(old_value);
1861 }
1862
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;
1865     size_t old_nbytes;
1866     const char *old_value_str;
1867     const char *new_value_str;
1868
1869     pa_assert(i);
1870     pa_assert(key);
1871
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))
1874             return;
1875
1876         old_value_str = "(data)";
1877
1878     } else {
1879         if (!value)
1880             return;
1881
1882         old_value_str = "(unset)";
1883     }
1884
1885     if (value) {
1886         pa_proplist_set(i->proplist, key, value, nbytes);
1887         new_value_str = "(data)";
1888     } else {
1889         pa_proplist_unset(i->proplist, key);
1890         new_value_str = "(unset)";
1891     }
1892
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);
1897     }
1898 }
1899
1900 /* Called from main thread */
1901 void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
1902     void *state;
1903     const char *key;
1904     const uint8_t *value;
1905     size_t nbytes;
1906
1907     pa_sink_input_assert_ref(i);
1908     pa_assert(p);
1909     pa_assert_ctl_context();
1910
1911     switch (mode) {
1912         case PA_UPDATE_SET:
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);
1917             }
1918
1919             /* Fall through. */
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);
1924             }
1925
1926             break;
1927         case PA_UPDATE_MERGE:
1928             for (state = NULL; (key = pa_proplist_iterate(p, &state));) {
1929                 if (pa_proplist_contains(i->proplist, key))
1930                     continue;
1931
1932                 pa_proplist_get(p, key, (const void **) &value, &nbytes);
1933                 pa_sink_input_set_property_arbitrary(i, key, value, nbytes);
1934             }
1935
1936             break;
1937     }
1938 }
1939
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));
1945
1946     sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
1947 }
1948
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);
1955
1956     if (i->sample_spec.rate == rate)
1957         return 0;
1958
1959     i->sample_spec.rate = rate;
1960
1961     if (i->sink)
1962         pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
1963     else {
1964         i->thread_info.sample_spec.rate = rate;
1965         pa_resampler_set_input_rate(i->thread_info.resampler, rate);
1966     }
1967
1968     pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1969     return 0;
1970 }
1971
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();
1976
1977     return i->actual_resample_method;
1978 }
1979
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));
1985
1986     if (i->flags & PA_SINK_INPUT_DONT_MOVE)
1987         return false;
1988
1989     if (i->sync_next || i->sync_prev) {
1990         pa_log_warn("Moving synchronized streams not supported.");
1991         return false;
1992     }
1993
1994     return true;
1995 }
1996
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)
2001             return true;
2002         s = s->input_to_master->sink;
2003         pa_assert(i++ < 100);
2004     }
2005     return false;
2006 }
2007
2008 static bool is_filter_sink_moving(pa_sink_input *i) {
2009     pa_sink *sink = i->sink;
2010
2011     if (!sink)
2012         return false;
2013
2014     while (sink->input_to_master) {
2015         sink = sink->input_to_master->sink;
2016
2017         if (!sink)
2018             return true;
2019     }
2020
2021     return false;
2022 }
2023
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);
2030
2031     if (dest == i->sink)
2032         return true;
2033
2034     if (dest->unlink_requested)
2035         return false;
2036
2037     if (!pa_sink_input_may_move(i))
2038         return false;
2039
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);
2043         return false;
2044     }
2045
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.",
2052                      i->sink->name);
2053         return false;
2054     }
2055
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.");
2058         return false;
2059     }
2060
2061     if (check_passthrough_connection(pa_sink_input_is_passthrough(i), dest) < 0)
2062         return false;
2063
2064     if (i->may_move_to)
2065         if (!i->may_move_to(i, dest))
2066             return false;
2067
2068     return true;
2069 }
2070
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;
2075     void *state = NULL;
2076     int r;
2077
2078     pa_sink_input_assert_ref(i);
2079     pa_assert_ctl_context();
2080     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2081     pa_assert(i->sink);
2082
2083     if (!pa_sink_input_may_move(i))
2084         return -PA_ERR_NOTSUPPORTED;
2085
2086     if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
2087         return r;
2088
2089     pa_log_debug("Starting to move sink input %u from '%s'", (unsigned) i->index, i->sink->name);
2090
2091     /* Kill directly connected outputs */
2092     while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
2093         pa_assert(o != p);
2094         pa_source_output_kill(o);
2095         p = o;
2096     }
2097     pa_assert(pa_idxset_isempty(i->direct_outputs));
2098
2099     pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
2100
2101     if (i->state == PA_SINK_INPUT_CORKED)
2102         pa_assert_se(i->sink->n_corked-- >= 1);
2103
2104     if (pa_sink_input_is_passthrough(i))
2105         pa_sink_leave_passthrough(i->sink);
2106
2107     if (pa_sink_flat_volume_enabled(i->sink))
2108         /* We might need to update the sink's volume if we are in flat
2109          * volume mode. */
2110         pa_sink_set_volume(i->sink, NULL, false, false);
2111
2112     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
2113
2114     pa_sink_update_status(i->sink);
2115
2116     PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
2117         pa_cvolume_remap(&v->volume, &i->sink->channel_map, &i->channel_map);
2118
2119     pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
2120
2121     i->sink = NULL;
2122     i->sink_requested_by_application = false;
2123
2124     pa_sink_input_unref(i);
2125
2126     return 0;
2127 }
2128
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;
2134
2135     pa_assert(i);
2136     pa_assert(dest);
2137     pa_assert(i->sink); /* The destination sink should already be set. */
2138
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;
2142         uint32_t idx;
2143
2144         if (PA_UNLIKELY(!root_sink))
2145             return;
2146
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:
2150              *
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) */
2162
2163             pa_assert(pa_cvolume_is_norm(&i->real_ratio));
2164             pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
2165
2166             /* Notifications will be sent by pa_sink_set_volume(). */
2167
2168         } else {
2169             /* Ok, so the origin sink uses volume sharing, and flat volume is
2170              * disabled. The volume will have to be updated as follows:
2171              *
2172              *     i->volume := 0 dB
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) */
2181
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));
2187         }
2188
2189         /* Additionally, the origin sink volume needs updating:
2190          *
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) */
2196
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);
2200
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);
2203
2204         pa_assert(pa_cvolume_is_norm(&i->origin_sink->soft_volume));
2205
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. */
2212
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);
2216
2217     } else {
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:
2221              *
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) */
2228
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);
2233
2234         } else {
2235             /* Ok, so this is a regular stream, and flat volume is disabled.
2236              * The volume will have to be updated as follows:
2237              *
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 */
2242
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);
2246         }
2247     }
2248
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);
2253 }
2254
2255 /* Called from the main thread. */
2256 static void set_preferred_sink(pa_sink_input *i, const char *sink_name) {
2257     pa_assert(i);
2258
2259     if (pa_safe_streq(i->preferred_sink, sink_name))
2260         return;
2261
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);
2266
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);
2269 }
2270
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;
2274     void *state = NULL;
2275
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);
2281
2282     if (!pa_sink_input_may_move_to(i, dest))
2283         return -PA_ERR_NOTSUPPORTED;
2284
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
2289          * reconnect */
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;
2294     }
2295
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 */
2301
2302         pa_log_info("Trying to change sample spec");
2303         pa_sink_reconfigure(dest, &i->sample_spec, pa_sink_input_is_passthrough(i));
2304     }
2305
2306     if (i->moving)
2307         i->moving(i, dest);
2308
2309     i->sink = dest;
2310     /* save == true, means user is calling the move_to() and want to
2311        save the preferred_sink */
2312     if (save) {
2313         if (dest == dest->core->default_sink)
2314             set_preferred_sink(i, NULL);
2315         else
2316             set_preferred_sink(i, dest->name);
2317     }
2318
2319     pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
2320
2321     PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
2322         pa_cvolume_remap(&v->volume, &i->channel_map, &i->sink->channel_map);
2323
2324     pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
2325
2326     if (i->state == PA_SINK_INPUT_CORKED)
2327         i->sink->n_corked++;
2328
2329     pa_sink_input_update_resampler(i);
2330
2331     pa_sink_update_status(dest);
2332
2333     update_volume_due_to_moving(i, dest);
2334
2335     if (pa_sink_input_is_passthrough(i))
2336         pa_sink_enter_passthrough(i->sink);
2337
2338     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
2339
2340     pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
2341
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);
2345
2346     return 0;
2347 }
2348
2349 /* Called from main context */
2350 void pa_sink_input_fail_move(pa_sink_input *i) {
2351
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);
2356
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)
2359         return;
2360
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)
2364             return;
2365     }
2366
2367     if (i->moving)
2368         i->moving(i, NULL);
2369
2370     pa_sink_input_kill(i);
2371 }
2372
2373 /* Called from main context */
2374 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, bool save) {
2375     int r;
2376
2377     pa_sink_input_assert_ref(i);
2378     pa_assert_ctl_context();
2379     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2380     pa_assert(i->sink);
2381     pa_sink_assert_ref(dest);
2382
2383     if (dest == i->sink)
2384         return 0;
2385
2386     if (!pa_sink_input_may_move_to(i, dest))
2387         return -PA_ERR_NOTSUPPORTED;
2388
2389     pa_sink_input_ref(i);
2390
2391     if ((r = pa_sink_input_start_move(i)) < 0) {
2392         pa_sink_input_unref(i);
2393         return r;
2394     }
2395
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);
2399         return r;
2400     }
2401
2402     pa_sink_input_unref(i);
2403
2404     return 0;
2405 }
2406
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;
2410
2411     pa_sink_input_assert_ref(i);
2412
2413     if (state == i->thread_info.state)
2414         return;
2415
2416 #ifdef TIZEN_EMPTY_POP
2417     if (state != PA_SINK_INPUT_RUNNING && _empty_pop_is_started(i))
2418         _empty_pop_reset(i);
2419 #endif
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;
2422
2423     if (i->state_change)
2424         i->state_change(i, state);
2425
2426     if (corking) {
2427
2428         pa_log_debug("Requesting rewind due to corking");
2429
2430         /* This will tell the implementing sink input driver to rewind
2431          * so that the unplayed already mixed data is not lost */
2432         if (i->sink)
2433             pa_sink_input_request_rewind(i, 0, true, true, false);
2434
2435         /* Set the corked state *after* requesting rewind */
2436         i->thread_info.state = state;
2437
2438     } else if (uncorking) {
2439
2440         pa_log_debug("Requesting rewind due to uncorking");
2441
2442         i->thread_info.underrun_for = (uint64_t) -1;
2443         i->thread_info.underrun_for_sink = 0;
2444         i->thread_info.playing_for = 0;
2445
2446         /* Set the uncorked state *before* requesting rewind */
2447         i->thread_info.state = state;
2448
2449         /* OK, we're being uncorked. Make sure we're not rewound when
2450          * the hw buffer is remixed and request a remix. */
2451         if (i->sink)
2452             pa_sink_input_request_rewind(i, 0, false, true, true);
2453     } else
2454         /* We may not be corking or uncorking, but we still need to set the state. */
2455         i->thread_info.state = state;
2456 }
2457
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);
2462
2463     switch (code) {
2464
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)
2471                     return 0;
2472 #endif
2473                 pa_sink_input_request_rewind(i, 0, true, false, false);
2474             }
2475             return 0;
2476
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);
2483             return 0;
2484 #endif
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);
2489             }
2490             return 0;
2491
2492         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
2493             pa_usec_t *r = userdata;
2494
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);
2497
2498             return 0;
2499         }
2500
2501         case PA_SINK_INPUT_MESSAGE_SET_RATE:
2502
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));
2505
2506             return 0;
2507
2508         case PA_SINK_INPUT_MESSAGE_SET_STATE: {
2509             pa_sink_input *ssync;
2510
2511             pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
2512
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));
2515
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));
2518
2519             return 0;
2520         }
2521
2522         case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
2523             pa_usec_t *usec = userdata;
2524
2525             *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
2526             return 0;
2527         }
2528
2529         case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
2530             pa_usec_t *r = userdata;
2531
2532             *r = i->thread_info.requested_sink_latency;
2533             return 0;
2534         }
2535     }
2536
2537     return -PA_ERR_NOTIMPLEMENTED;
2538 }
2539
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);
2544
2545     if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
2546         return pa_memblockq_is_empty(i->thread_info.render_memblockq);
2547
2548     return true;
2549 }
2550
2551 /* Called from IO context */
2552 void pa_sink_input_request_rewind(
2553         pa_sink_input *i,
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) {
2558
2559     size_t lbq;
2560
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.
2565      *
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
2571      * rewound. */
2572
2573     /* nbytes = 0 means maximum rewind request */
2574
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);
2579
2580     /* We don't take rewind requests while we are corked */
2581     if (i->thread_info.state == PA_SINK_INPUT_CORKED)
2582         return;
2583
2584     nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
2585
2586 #ifdef SINK_INPUT_DEBUG
2587     pa_log_debug("request rewrite %zu", nbytes);
2588 #endif
2589
2590     /* Calculate how much we can rewind locally without having to
2591      * touch the sink */
2592     if (rewrite)
2593         lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
2594     else
2595         lbq = 0;
2596
2597     /* Check if rewinding for the maximum is requested, and if so, fix up */
2598     if (nbytes <= 0) {
2599
2600         /* Calculate maximum number of bytes that could be rewound in theory */
2601         nbytes = i->sink->thread_info.max_rewind + lbq;
2602
2603         /* Transform from sink domain */
2604         if (i->thread_info.resampler)
2605             nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
2606     }
2607
2608     /* Remember how much we actually want to rewrite */
2609     if (i->thread_info.rewrite_nbytes != (size_t) -1) {
2610         if (rewrite) {
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;
2614
2615             i->thread_info.rewrite_nbytes = nbytes;
2616         } else
2617             i->thread_info.rewrite_nbytes = (size_t) -1;
2618     }
2619
2620     i->thread_info.rewrite_flush =
2621         i->thread_info.rewrite_flush || flush;
2622
2623     i->thread_info.dont_rewind_render =
2624         i->thread_info.dont_rewind_render ||
2625         dont_rewind_render;
2626
2627     /* nbytes is -1 if some earlier rewind request had rewrite == false. */
2628     if (nbytes != (size_t) -1) {
2629
2630         /* Transform to sink domain */
2631         if (i->thread_info.resampler)
2632             nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
2633
2634         if (nbytes > lbq)
2635             pa_sink_request_rewind(i->sink, nbytes - lbq);
2636         else
2637             /* This call will make sure process_rewind() is called later */
2638             pa_sink_request_rewind(i->sink, 0);
2639     }
2640 }
2641
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();
2646     pa_assert(ret);
2647
2648     /* FIXME: Shouldn't access resampler object from main context! */
2649
2650     pa_silence_memchunk_get(
2651                 &i->core->silence_cache,
2652                 i->core->mempool,
2653                 ret,
2654                 &i->sample_spec,
2655                 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
2656
2657     return ret;
2658 }
2659
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;
2664
2665     pa_log_debug("[%u] empty pop started!!!", i->index);
2666 }
2667
2668 static bool _empty_pop_is_started(pa_sink_input *i) {
2669     if (i->empty_pop_initial_timestamp > 0)
2670         return true;
2671     else
2672         return false;
2673 }
2674
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);
2677 }
2678
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)
2682         return;
2683
2684     i->empty_pop_previous_duration = empty_pop_duration;
2685
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);
2688 }
2689
2690 static void _empty_pop_reset(pa_sink_input *i) {
2691     i->empty_pop_initial_timestamp = 0;
2692     i->empty_pop_previous_duration = 0;
2693
2694     pa_log_warn("[%u] empty pop reset...", i->index);
2695 }
2696
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);
2700
2701     if (length == 0) {
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) {
2706                 *is_timeout = true;
2707                 _empty_pop_reset(i);
2708                 return;
2709             }
2710             _empty_pop_print_duration(i, empty_pop_duration);
2711         } else {
2712             _empty_pop_start(i);
2713         }
2714     } else {
2715         if (_empty_pop_is_started(i))
2716             _empty_pop_reset(i);
2717     }
2718
2719     *is_timeout = false;
2720 }
2721 #endif /* TIZEN_EMPTY_POP */
2722 #ifdef __TIZEN__
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) {
2725
2726     pa_sink_input_assert_ref(i);
2727     pa_assert_ctl_context();
2728     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2729
2730     i->thread_info.silenced = silence;
2731     i->thread_info.silence_duration = duration;
2732
2733     return;
2734 }
2735 #endif
2736
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;
2741
2742     pa_sink_input_assert_ref(i);
2743     pa_assert_ctl_context();
2744     pa_assert(event);
2745
2746     if (!i->send_event)
2747         return;
2748
2749     if (!data)
2750         data = pl = pa_proplist_new();
2751
2752     hook_data.sink_input = i;
2753     hook_data.data = data;
2754     hook_data.event = event;
2755
2756     if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
2757         goto finish;
2758
2759     i->send_event(i, event, data);
2760
2761 finish:
2762     if (pl)
2763         pa_proplist_free(pl);
2764 }
2765
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;
2772
2773     pa_sink_input_assert_ref(i);
2774     pa_assert_ctl_context();
2775
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))
2779
2780         new_resampler = i->thread_info.resampler;
2781
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))) {
2786
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));
2798
2799         if (!new_resampler) {
2800             pa_log_warn("Unsupported resampling operation.");
2801             return -PA_ERR_NOTSUPPORTED;
2802         }
2803     } else
2804         new_resampler = NULL;
2805
2806     if (new_resampler == i->thread_info.resampler)
2807         return 0;
2808
2809     if (i->thread_info.resampler)
2810         pa_resampler_free(i->thread_info.resampler);
2811
2812     i->thread_info.resampler = new_resampler;
2813
2814     pa_memblockq_free(i->thread_info.render_memblockq);
2815
2816     memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index);
2817     i->thread_info.render_memblockq = pa_memblockq_new(
2818             memblockq_name,
2819             0,
2820             MEMBLOCKQ_MAXLENGTH,
2821             0,
2822             &i->sink->sample_spec,
2823             0,
2824             1,
2825             0,
2826             &i->sink->silence);
2827     pa_xfree(memblockq_name);
2828
2829     i->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID;
2830
2831     pa_log_debug("Updated resampler for sink input %d", i->index);
2832
2833     return 0;
2834 }
2835
2836 /* Called from the IO thread. */
2837 void pa_sink_input_attach(pa_sink_input *i) {
2838     pa_assert(i);
2839     pa_assert(!i->thread_info.attached);
2840
2841     i->thread_info.attached = true;
2842
2843     if (i->attach)
2844         i->attach(i);
2845 }
2846
2847 /* Called from the IO thread. */
2848 void pa_sink_input_detach(pa_sink_input *i) {
2849     pa_assert(i);
2850
2851     if (!i->thread_info.attached)
2852         return;
2853
2854     i->thread_info.attached = false;
2855
2856     if (i->detach)
2857         i->detach(i);
2858 }
2859
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];
2865
2866     pa_assert(i);
2867     pa_assert(volume);
2868
2869     old_volume = i->volume;
2870
2871     if (pa_cvolume_equal(volume, &old_volume))
2872         return;
2873
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));
2878
2879     if (i->volume_changed)
2880         i->volume_changed(i);
2881
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);
2884 }
2885
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];
2891
2892     pa_assert(i);
2893     pa_assert(ratio);
2894
2895     old_ratio = i->reference_ratio;
2896
2897     if (pa_cvolume_equal(ratio, &old_ratio))
2898         return;
2899
2900     i->reference_ratio = *ratio;
2901
2902     if (!PA_SINK_INPUT_IS_LINKED(i->state))
2903         return;
2904
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));
2908 }
2909
2910 /* Called from the main thread.
2911  *
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.
2924  */
2925 void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s) {
2926     pa_assert(i);
2927
2928     if (s) {
2929         set_preferred_sink(i, s->name);
2930         pa_sink_input_move_to(i, s, false);
2931     } else {
2932         set_preferred_sink(i, NULL);
2933         pa_sink_input_move_to(i, i->core->default_sink, false);
2934     }
2935 }
2936
2937 #ifdef __TIZEN__
2938 void pa_sink_input_dump_info(pa_sink_input *i, unsigned int iteration, unsigned int total) {
2939     pa_assert(i);
2940
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)));
2950 }
2951 #endif