Bluetooth : Support AVC target feature
[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_PA_SINK_INPUT && !i->pcm_dump_fp && i->state == PA_SINK_INPUT_RUNNING) {
87         pa_gettimeofday(&now);
88         localtime_r(&now.tv_sec, &tm);
89         memset(&datetime[0], 0x00, sizeof(datetime));
90         strftime(&datetime[0], sizeof(datetime), "%H%M%S", &tm);
91         dump_time = pa_sprintf_malloc("%s.%03ld", &datetime[0], now.tv_usec / 1000);
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_PA_SINK_INPUT && i->pcm_dump_fp) {
118         fclose(i->pcm_dump_fp);
119         pa_log_info("%s closed", i->dump_path);
120         pa_xfree(i->dump_path);
121         i->pcm_dump_fp = NULL;
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) {
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         data->save_sink = save;
314     } else {
315         /* Extended API: let's see if this sink supports the formats the client can provide */
316         formats = pa_sink_check_formats(s, data->req_formats);
317
318         if (formats && !pa_idxset_isempty(formats)) {
319             /* Sink supports at least one of the requested formats */
320             data->sink = s;
321             data->save_sink = save;
322             if (data->nego_formats)
323                 pa_idxset_free(data->nego_formats, (pa_free_cb_t) pa_format_info_free);
324             data->nego_formats = formats;
325         } else {
326             /* Sink doesn't support any of the formats requested by the client */
327             if (formats)
328                 pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
329             ret = false;
330         }
331     }
332
333     return ret;
334 }
335
336 bool pa_sink_input_new_data_set_formats(pa_sink_input_new_data *data, pa_idxset *formats) {
337     pa_assert(data);
338     pa_assert(formats);
339
340     if (data->req_formats)
341         pa_idxset_free(data->req_formats, (pa_free_cb_t) pa_format_info_free);
342
343     data->req_formats = formats;
344
345     if (data->sink) {
346         /* Trigger format negotiation */
347         return pa_sink_input_new_data_set_sink(data, data->sink, data->save_sink);
348     }
349
350     return true;
351 }
352
353 void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
354     pa_assert(data);
355
356     if (data->req_formats)
357         pa_idxset_free(data->req_formats, (pa_free_cb_t) pa_format_info_free);
358
359     if (data->nego_formats)
360         pa_idxset_free(data->nego_formats, (pa_free_cb_t) pa_format_info_free);
361
362     if (data->format)
363         pa_format_info_free(data->format);
364
365     if (data->volume_factor_items)
366         pa_hashmap_free(data->volume_factor_items);
367
368     if (data->volume_factor_sink_items)
369         pa_hashmap_free(data->volume_factor_sink_items);
370
371     pa_proplist_free(data->proplist);
372 }
373
374 /* Called from main context */
375 static void reset_callbacks(pa_sink_input *i) {
376     pa_assert(i);
377
378     i->pop = NULL;
379     i->process_underrun = NULL;
380     i->process_rewind = NULL;
381     i->update_max_rewind = NULL;
382     i->update_max_request = NULL;
383     i->update_sink_requested_latency = NULL;
384     i->update_sink_latency_range = NULL;
385     i->update_sink_fixed_latency = NULL;
386     i->attach = NULL;
387     i->detach = NULL;
388     i->suspend = NULL;
389     i->suspend_within_thread = NULL;
390     i->moving = NULL;
391     i->kill = NULL;
392     i->get_latency = NULL;
393     i->state_change = NULL;
394     i->may_move_to = NULL;
395     i->send_event = NULL;
396     i->volume_changed = NULL;
397     i->mute_changed = NULL;
398 }
399
400 /* Called from main context */
401 int pa_sink_input_new(
402         pa_sink_input **_i,
403         pa_core *core,
404         pa_sink_input_new_data *data) {
405
406     pa_sink_input *i;
407     pa_resampler *resampler = NULL;
408     char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], fmt[PA_FORMAT_INFO_SNPRINT_MAX];
409     pa_channel_map volume_map;
410     int r;
411     char *pt;
412     char *memblockq_name;
413
414     pa_assert(_i);
415     pa_assert(core);
416     pa_assert(data);
417     pa_assert_ctl_context();
418
419     if (data->client)
420         pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
421
422     if (data->origin_sink && (data->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
423         data->volume_writable = false;
424
425     if (!data->req_formats) {
426         /* From this point on, we want to work only with formats, and get back
427          * to using the sample spec and channel map after all decisions w.r.t.
428          * routing are complete. */
429         pa_format_info *f;
430         pa_idxset *formats;
431
432         f = pa_format_info_from_sample_spec2(&data->sample_spec, data->channel_map_is_set ? &data->channel_map : NULL,
433                                              !(data->flags & PA_SINK_INPUT_FIX_FORMAT),
434                                              !(data->flags & PA_SINK_INPUT_FIX_RATE),
435                                              !(data->flags & PA_SINK_INPUT_FIX_CHANNELS));
436         if (!f)
437             return -PA_ERR_INVALID;
438
439         formats = pa_idxset_new(NULL, NULL);
440         pa_idxset_put(formats, f, NULL);
441         pa_sink_input_new_data_set_formats(data, formats);
442     }
443
444     if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0)
445         return r;
446
447     pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
448
449     if (!data->sink) {
450         pa_sink *sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK);
451         pa_return_val_if_fail(sink, -PA_ERR_NOENTITY);
452         pa_sink_input_new_data_set_sink(data, sink, false);
453 #ifdef __TIZEN__
454     } else {
455         pa_sink_input_new_data_set_sink(data, data->sink, false);
456 #endif
457     }
458
459     /* If something didn't pick a format for us, pick the top-most format since
460      * we assume this is sorted in priority order */
461     if (!data->format && data->nego_formats && !pa_idxset_isempty(data->nego_formats))
462         data->format = pa_format_info_copy(pa_idxset_first(data->nego_formats, NULL));
463
464     if (PA_LIKELY(data->format)) {
465         pa_log_debug("Negotiated format: %s", pa_format_info_snprint(fmt, sizeof(fmt), data->format));
466     } else {
467         pa_format_info *format;
468         uint32_t idx;
469
470         pa_log_info("Sink does not support any requested format:");
471         PA_IDXSET_FOREACH(format, data->req_formats, idx)
472             pa_log_info(" -- %s", pa_format_info_snprint(fmt, sizeof(fmt), format));
473
474         return -PA_ERR_NOTSUPPORTED;
475     }
476
477     pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)), -PA_ERR_BADSTATE);
478     pa_return_val_if_fail(!data->sync_base || (data->sync_base->sink == data->sink
479                                                && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED),
480                           -PA_ERR_INVALID);
481
482     /* Routing is done. We have a sink and a format. */
483
484     if (data->volume_is_set && pa_format_info_is_pcm(data->format)) {
485         /* If volume is set, we need to save the original data->channel_map,
486          * so that we can remap the volume from the original channel map to the
487          * final channel map of the stream in case data->channel_map gets
488          * modified in pa_format_info_to_sample_spec2(). */
489         r = pa_stream_get_volume_channel_map(&data->volume, data->channel_map_is_set ? &data->channel_map : NULL, data->format, &volume_map);
490         if (r < 0)
491             return r;
492     }
493
494     /* Now populate the sample spec and channel map according to the final
495      * format that we've negotiated */
496     r = pa_format_info_to_sample_spec2(data->format, &data->sample_spec, &data->channel_map, &data->sink->sample_spec,
497                                        &data->sink->channel_map);
498     if (r < 0)
499         return r;
500
501     r = check_passthrough_connection(pa_sink_input_new_data_is_passthrough(data), data->sink);
502     if (r != PA_OK)
503         return r;
504
505     /* Don't restore (or save) stream volume for passthrough streams and
506      * prevent attenuation/gain */
507     if (pa_sink_input_new_data_is_passthrough(data)) {
508         data->volume_is_set = true;
509         pa_cvolume_reset(&data->volume, data->sample_spec.channels);
510         data->volume_is_absolute = true;
511         data->save_volume = false;
512     }
513
514     if (!data->volume_is_set) {
515         pa_cvolume_reset(&data->volume, data->sample_spec.channels);
516         data->volume_is_absolute = false;
517         data->save_volume = false;
518     }
519
520     if (!data->volume_writable)
521         data->save_volume = false;
522
523     if (data->volume_is_set)
524         /* The original volume channel map may be different than the final
525          * stream channel map, so remapping may be needed. */
526         pa_cvolume_remap(&data->volume, &volume_map, &data->channel_map);
527
528     if (!data->muted_is_set)
529         data->muted = false;
530
531     if (!(data->flags & PA_SINK_INPUT_VARIABLE_RATE) &&
532         !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec)) {
533         /* try to change sink format and rate. This is done before the FIXATE hook since
534            module-suspend-on-idle can resume a sink */
535
536         pa_log_info("Trying to change sample spec");
537         pa_sink_reconfigure(data->sink, &data->sample_spec, pa_sink_input_new_data_is_passthrough(data));
538     }
539
540     if (pa_sink_input_new_data_is_passthrough(data) &&
541         !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec)) {
542         /* rate update failed, or other parts of sample spec didn't match */
543
544         pa_log_debug("Could not update sink sample spec to match passthrough stream");
545         return -PA_ERR_NOTSUPPORTED;
546     }
547
548     if (data->resample_method == PA_RESAMPLER_INVALID)
549         data->resample_method = core->resample_method;
550
551     pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
552
553     if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
554         return r;
555
556     if ((data->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND) &&
557         pa_sink_get_state(data->sink) == PA_SINK_SUSPENDED) {
558         pa_log_warn("Failed to create sink input: sink is suspended.");
559         return -PA_ERR_BADSTATE;
560     }
561
562     if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) {
563         pa_log_warn("Failed to create sink input: too many inputs per sink.");
564         return -PA_ERR_TOOLARGE;
565     }
566
567     if ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
568         !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) ||
569         !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) {
570
571         /* Note: for passthrough content we need to adjust the output rate to that of the current sink-input */
572         if (!pa_sink_input_new_data_is_passthrough(data)) /* no resampler for passthrough content */
573             if (!(resampler = pa_resampler_new(
574                           core->mempool,
575                           &data->sample_spec, &data->channel_map,
576                           &data->sink->sample_spec, &data->sink->channel_map,
577                           core->lfe_crossover_freq,
578                           data->resample_method,
579                           ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
580                           ((data->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
581                           (core->disable_remixing || (data->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
582                           (core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
583                           (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
584                 pa_log_warn("Unsupported resampling operation.");
585                 return -PA_ERR_NOTSUPPORTED;
586             }
587     }
588
589     i = pa_msgobject_new(pa_sink_input);
590     i->parent.parent.free = sink_input_free;
591     i->parent.process_msg = pa_sink_input_process_msg;
592
593     i->core = core;
594     i->state = PA_SINK_INPUT_INIT;
595     i->flags = data->flags;
596     i->proplist = pa_proplist_copy(data->proplist);
597     i->driver = pa_xstrdup(pa_path_get_filename(data->driver));
598     i->module = data->module;
599     i->sink = data->sink;
600     i->origin_sink = data->origin_sink;
601     i->client = data->client;
602
603     i->requested_resample_method = data->resample_method;
604     i->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID;
605     i->sample_spec = data->sample_spec;
606     i->channel_map = data->channel_map;
607     i->format = pa_format_info_copy(data->format);
608
609     if (!data->volume_is_absolute && pa_sink_flat_volume_enabled(i->sink)) {
610         pa_cvolume remapped;
611
612         /* When the 'absolute' bool is not set then we'll treat the volume
613          * as relative to the sink volume even in flat volume mode */
614         remapped = data->sink->reference_volume;
615         pa_cvolume_remap(&remapped, &data->sink->channel_map, &data->channel_map);
616         pa_sw_cvolume_multiply(&i->volume, &data->volume, &remapped);
617     } else
618         i->volume = data->volume;
619
620     i->volume_factor_items = data->volume_factor_items;
621     data->volume_factor_items = NULL;
622     volume_factor_from_hashmap(&i->volume_factor, i->volume_factor_items, i->sample_spec.channels);
623
624     i->volume_factor_sink_items = data->volume_factor_sink_items;
625     data->volume_factor_sink_items = NULL;
626     volume_factor_from_hashmap(&i->volume_factor_sink, i->volume_factor_sink_items, i->sink->sample_spec.channels);
627
628 #ifdef TIZEN_VOLUME_RAMP
629     i->ramp_factor_items = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL,
630                                                (pa_free_cb_t) volume_ramp_factor_entry_free);
631 #endif
632     i->real_ratio = i->reference_ratio = data->volume;
633     pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
634     pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
635 #ifdef TIZEN_INDIVIDUAL_VOLUME_RATIO
636     i->individual_volume_ratio = data->individual_volume_ratio;
637 #endif
638     i->volume_writable = data->volume_writable;
639     i->save_volume = data->save_volume;
640     i->save_sink = data->save_sink;
641     i->save_muted = data->save_muted;
642
643     i->muted = data->muted;
644
645     if (data->sync_base) {
646         i->sync_next = data->sync_base->sync_next;
647         i->sync_prev = data->sync_base;
648
649         if (data->sync_base->sync_next)
650             data->sync_base->sync_next->sync_prev = i;
651         data->sync_base->sync_next = i;
652     } else
653         i->sync_next = i->sync_prev = NULL;
654
655     i->direct_outputs = pa_idxset_new(NULL, NULL);
656
657     reset_callbacks(i);
658     i->userdata = NULL;
659 #ifdef TIZEN_EMPTY_POP
660     i->is_virtual = pa_safe_streq(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), "VIRTUAL_STREAM");
661 #endif
662 #ifdef TIZEN_PCM_DUMP
663     i->pcm_dump_fp = NULL;
664     i->dump_path = NULL;
665     i->dump_length = 0;
666 #endif
667 #ifdef TIZEN_VOLUME_RAMP
668     if (data->flags & PA_SINK_INPUT_START_RAMP_MUTED)
669         pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_MUTED, data->sink->sample_spec.channels);
670     else
671         pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_NORM, data->sink->sample_spec.channels);
672 #endif
673
674     i->thread_info.state = i->state;
675     i->thread_info.attached = false;
676     pa_atomic_store(&i->thread_info.drained, 1);
677     i->thread_info.sample_spec = i->sample_spec;
678     i->thread_info.resampler = resampler;
679     i->thread_info.soft_volume = i->soft_volume;
680     i->thread_info.muted = i->muted;
681     i->thread_info.requested_sink_latency = (pa_usec_t) -1;
682     i->thread_info.rewrite_nbytes = 0;
683     i->thread_info.rewrite_flush = false;
684     i->thread_info.dont_rewind_render = false;
685     i->thread_info.underrun_for = (uint64_t) -1;
686     i->thread_info.underrun_for_sink = 0;
687     i->thread_info.playing_for = 0;
688     i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
689 #ifdef TIZEN_VOLUME_RAMP
690     i->thread_info.ramp = i->ramp;
691 #endif
692
693     pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
694     pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0);
695
696     if (i->client)
697         pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
698
699     memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index);
700     i->thread_info.render_memblockq = pa_memblockq_new(
701             memblockq_name,
702             0,
703             MEMBLOCKQ_MAXLENGTH,
704             0,
705             &i->sink->sample_spec,
706             0,
707             1,
708             0,
709             &i->sink->silence);
710     pa_xfree(memblockq_name);
711
712     pt = pa_proplist_to_string_sep(i->proplist, "\n    ");
713     pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n    %s",
714                 i->index,
715                 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
716                 i->sink->name,
717                 pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
718                 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
719                 pt);
720     pa_xfree(pt);
721
722     /* Don't forget to call pa_sink_input_put! */
723
724     *_i = i;
725     return 0;
726 }
727
728 /* Called from main context */
729 static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
730     pa_assert(i);
731     pa_assert_ctl_context();
732
733     if (!i->sink)
734         return;
735
736     if (i->state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED)
737         pa_assert_se(i->sink->n_corked -- >= 1);
738     else if (i->state != PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_CORKED)
739         i->sink->n_corked++;
740 }
741
742 /* Called from main context */
743 static void sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
744     pa_sink_input *ssync;
745     pa_assert(i);
746     pa_assert_ctl_context();
747
748     if (state == PA_SINK_INPUT_DRAINED)
749         state = PA_SINK_INPUT_RUNNING;
750
751     if (i->state == state)
752         return;
753
754 #ifdef TIZEN_EMPTY_POP
755     if (state != PA_SINK_INPUT_RUNNING && _empty_pop_is_started(i))
756         _empty_pop_reset(i);
757 #endif
758
759     if (i->sink) {
760         if (i->state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING && pa_sink_used_by(i->sink) == 0 &&
761             !pa_sample_spec_equal(&i->sample_spec, &i->sink->sample_spec)) {
762             /* We were uncorked and the sink was not playing anything -- let's try
763              * to update the sample format and rate to avoid resampling */
764             pa_sink_reconfigure(i->sink, &i->sample_spec, pa_sink_input_is_passthrough(i));
765         }
766
767         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) == 0);
768     } else {
769         /* If the sink is not valid, pa_sink_input_set_state_within_thread() must be called directly */
770
771         pa_sink_input_set_state_within_thread(i, state);
772
773         for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
774             pa_sink_input_set_state_within_thread(ssync, state);
775
776         for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
777             pa_sink_input_set_state_within_thread(ssync, state);
778     }
779 #ifdef TIZEN_PCM_DUMP
780     if (i->state == PA_SINK_INPUT_RUNNING && i->pcm_dump_fp && (i->core->pcm_dump_option & PA_PCM_DUMP_OPTION_SEPARATED)) {
781         /* close file for dump pcm */
782         fclose(i->pcm_dump_fp);
783         pa_log_info("%s closed", i->dump_path);
784         pa_xfree(i->dump_path);
785         i->pcm_dump_fp = NULL;
786     }
787 #endif
788 #ifdef __TIZEN__
789     if (state == PA_SINK_INPUT_RUNNING)
790         i->time_of_start_to_run = pa_rtclock_now();
791 #endif
792
793     update_n_corked(i, state);
794     i->state = state;
795
796     for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev) {
797         update_n_corked(ssync, state);
798         ssync->state = state;
799     }
800     for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) {
801         update_n_corked(ssync, state);
802         ssync->state = state;
803     }
804
805     if (state != PA_SINK_INPUT_UNLINKED) {
806         pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
807
808         for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev)
809             pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
810
811         for (ssync = i->sync_next; ssync; ssync = ssync->sync_next)
812             pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
813
814         if (PA_SINK_INPUT_IS_LINKED(state))
815             pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
816     }
817
818     if (i->sink)
819         pa_sink_update_status(i->sink);
820 }
821
822 /* Called from main context */
823 void pa_sink_input_unlink(pa_sink_input *i) {
824     bool linked;
825     pa_source_output *o, PA_UNUSED *p = NULL;
826
827     pa_sink_input_assert_ref(i);
828     pa_assert_ctl_context();
829
830     /* See pa_sink_unlink() for a couple of comments how this function
831      * works */
832
833     pa_sink_input_ref(i);
834
835     linked = PA_SINK_INPUT_IS_LINKED(i->state);
836
837     if (linked)
838         pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
839
840     if (i->sync_prev)
841         i->sync_prev->sync_next = i->sync_next;
842     if (i->sync_next)
843         i->sync_next->sync_prev = i->sync_prev;
844
845     i->sync_prev = i->sync_next = NULL;
846
847     pa_idxset_remove_by_data(i->core->sink_inputs, i, NULL);
848
849     if (i->sink)
850         if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
851             pa_sink_input_unref(i);
852
853     if (i->client)
854         pa_idxset_remove_by_data(i->client->sink_inputs, i, NULL);
855
856     while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
857         pa_assert(o != p);
858         pa_source_output_kill(o);
859         p = o;
860     }
861
862     update_n_corked(i, PA_SINK_INPUT_UNLINKED);
863     i->state = PA_SINK_INPUT_UNLINKED;
864
865     if (linked && i->sink) {
866         if (pa_sink_input_is_passthrough(i))
867             pa_sink_leave_passthrough(i->sink);
868
869         /* We might need to update the sink's volume if we are in flat volume mode. */
870         if (pa_sink_flat_volume_enabled(i->sink))
871             pa_sink_set_volume(i->sink, NULL, false, false);
872
873         if (i->sink->asyncmsgq)
874             pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL) == 0);
875     }
876
877     reset_callbacks(i);
878
879     if (i->sink) {
880         if (PA_SINK_IS_LINKED(pa_sink_get_state(i->sink)))
881             pa_sink_update_status(i->sink);
882
883         i->sink = NULL;
884     }
885
886     if (linked) {
887         pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
888         pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
889     }
890
891     pa_core_maybe_vacuum(i->core);
892
893     pa_sink_input_unref(i);
894 }
895
896 /* Called from main context */
897 static void sink_input_free(pa_object *o) {
898     pa_sink_input* i = PA_SINK_INPUT(o);
899
900     pa_assert(i);
901     pa_assert_ctl_context();
902     pa_assert(pa_sink_input_refcnt(i) == 0);
903     pa_assert(!PA_SINK_INPUT_IS_LINKED(i->state));
904
905     pa_log_info("Freeing input %u \"%s\"", i->index,
906                 i->proplist ? pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)) : "");
907
908     /* Side note: this function must be able to destruct properly any
909      * kind of sink input in any state, even those which are
910      * "half-moved" or are connected to sinks that have no asyncmsgq
911      * and are hence half-destructed themselves! */
912
913     if (i->thread_info.render_memblockq)
914         pa_memblockq_free(i->thread_info.render_memblockq);
915
916     if (i->thread_info.resampler)
917         pa_resampler_free(i->thread_info.resampler);
918 #ifdef TIZEN_PCM_DUMP
919     /* close file for dump pcm */
920     if (i->pcm_dump_fp) {
921         fclose(i->pcm_dump_fp);
922         pa_log_info("%s closed", i->dump_path);
923         pa_xfree(i->dump_path);
924         i->pcm_dump_fp = NULL;
925     }
926 #endif
927
928     if (i->format)
929         pa_format_info_free(i->format);
930
931     if (i->proplist)
932         pa_proplist_free(i->proplist);
933
934     if (i->direct_outputs)
935         pa_idxset_free(i->direct_outputs, NULL);
936
937     if (i->thread_info.direct_outputs)
938         pa_hashmap_free(i->thread_info.direct_outputs);
939
940     if (i->volume_factor_items)
941         pa_hashmap_free(i->volume_factor_items);
942
943     if (i->volume_factor_sink_items)
944         pa_hashmap_free(i->volume_factor_sink_items);
945
946 #ifdef TIZEN_VOLUME_RAMP
947     if (i->ramp_factor_items)
948         pa_hashmap_free(i->ramp_factor_items);
949 #endif
950     pa_xfree(i->driver);
951     pa_xfree(i);
952 }
953
954 /* Called from main context */
955 void pa_sink_input_put(pa_sink_input *i) {
956     pa_sink_input_state_t state;
957
958     pa_sink_input_assert_ref(i);
959     pa_assert_ctl_context();
960
961     pa_assert(i->state == PA_SINK_INPUT_INIT);
962
963     /* The following fields must be initialized properly */
964     pa_assert(i->pop);
965     pa_assert(i->process_rewind);
966     pa_assert(i->kill);
967
968     state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
969
970     update_n_corked(i, state);
971     i->state = state;
972
973     /* We might need to update the sink's volume if we are in flat volume mode. */
974     if (pa_sink_flat_volume_enabled(i->sink))
975         pa_sink_set_volume(i->sink, NULL, false, i->save_volume);
976     else {
977         if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
978             pa_assert(pa_cvolume_is_norm(&i->volume));
979             pa_assert(pa_cvolume_is_norm(&i->reference_ratio));
980         }
981
982         set_real_ratio(i, &i->volume);
983     }
984
985     if (pa_sink_input_is_passthrough(i))
986         pa_sink_enter_passthrough(i->sink);
987
988     i->thread_info.soft_volume = i->soft_volume;
989     i->thread_info.muted = i->muted;
990
991     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0);
992
993     pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
994     pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
995
996     pa_sink_update_status(i->sink);
997 }
998
999 /* Called from main context */
1000 void pa_sink_input_kill(pa_sink_input*i) {
1001     pa_sink_input_assert_ref(i);
1002     pa_assert_ctl_context();
1003     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1004
1005     i->kill(i);
1006 }
1007
1008 /* Called from main context */
1009 pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
1010     pa_usec_t r[2] = { 0, 0 };
1011
1012     pa_sink_input_assert_ref(i);
1013     pa_assert_ctl_context();
1014     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1015
1016     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, r, 0, NULL) == 0);
1017
1018     if (i->get_latency)
1019         r[0] += i->get_latency(i);
1020
1021     if (sink_latency)
1022         *sink_latency = r[1];
1023
1024     return r[0];
1025 }
1026
1027 #ifdef TIZEN_VOLUME_RAMP
1028 /* Called from thread context */
1029 static void check_and_apply_silence(pa_sink_input *i) {
1030     pa_sink_input_assert_ref(i);
1031
1032     if (i->thread_info.silenced && i->thread_info.silence_duration > 0) {
1033         pa_memchunk schunk;
1034         size_t target_length = pa_usec_to_bytes(i->thread_info.silence_duration, &i->sink->sample_spec);
1035
1036         pa_silence_memchunk_get(&i->core->silence_cache,
1037                                 i->core->mempool,
1038                                 &schunk,
1039                                 &i->sink->sample_spec,
1040                                 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
1041
1042         while (target_length > 0) {
1043             if (target_length < schunk.length)
1044                 schunk.length = target_length;
1045             pa_memblockq_push_align(i->thread_info.render_memblockq, &schunk);
1046             target_length -= schunk.length;
1047 #ifdef SINK_INPUT_DEBUG
1048             pa_log_debug("add memchunk for slience, length(%u)", schunk.length);
1049 #endif
1050         }
1051         pa_memblock_unref(schunk.memblock);
1052
1053         i->thread_info.silenced = false;
1054         i->thread_info.silence_duration = 0;
1055     }
1056 }
1057
1058 /* Called from thread context */
1059 static void check_and_apply_ramp(pa_cvolume_ramp_int *ramp, const pa_sample_spec *spec, pa_memchunk *chunk) {
1060     pa_cvolume target;
1061
1062     pa_assert(ramp);
1063     pa_assert(spec);
1064     pa_assert(chunk);
1065
1066     /* check for possible volume ramp and apply it */
1067     if (pa_cvolume_ramp_active(ramp)) {
1068         pa_memchunk_make_writable(chunk, 0);
1069         pa_volume_ramp_memchunk(chunk, spec, ramp);
1070     } else if (pa_cvolume_ramp_target_active(ramp)) {
1071         pa_memchunk_make_writable(chunk, 0);
1072         pa_cvolume_ramp_get_targets(ramp, &target);
1073         pa_volume_memchunk(chunk, spec, &target);
1074     }
1075 }
1076 #endif
1077
1078 /* Called from thread context */
1079 void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa_memchunk *chunk, pa_cvolume *volume) {
1080     bool do_volume_adj_here, need_volume_factor_sink;
1081     bool volume_is_norm;
1082 #ifdef TIZEN_VOLUME_RAMP
1083     bool prev_ramp_finished = false;
1084 #endif
1085     size_t block_size_max_sink, block_size_max_sink_input;
1086     size_t ilength;
1087     size_t ilength_full;
1088
1089 #ifdef __TIZEN__
1090     pa_sink_avc_mode_t avc_mode = PA_SINK_AVC_OFF;
1091 #endif
1092
1093     pa_sink_input_assert_ref(i);
1094     pa_sink_input_assert_io_context(i);
1095     pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1096     pa_assert(pa_frame_aligned(slength, &i->sink->sample_spec));
1097     pa_assert(chunk);
1098     pa_assert(volume);
1099
1100 #ifdef SINK_INPUT_DEBUG
1101 #ifdef __TIZEN__
1102     pa_log_debug("peek, idx(%u)", i->index);
1103 #else
1104     pa_log_debug("peek");
1105 #endif
1106 #endif
1107
1108     block_size_max_sink_input = i->thread_info.resampler ?
1109         pa_resampler_max_block_size(i->thread_info.resampler) :
1110         pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sample_spec);
1111
1112     block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sink->sample_spec);
1113
1114     /* Default buffer size */
1115     if (slength <= 0)
1116         slength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec);
1117
1118     if (slength > block_size_max_sink)
1119         slength = block_size_max_sink;
1120
1121     if (i->thread_info.resampler) {
1122         ilength = pa_resampler_request(i->thread_info.resampler, slength);
1123
1124         if (ilength <= 0)
1125             ilength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
1126     } else
1127         ilength = slength;
1128
1129     /* Length corresponding to slength (without limiting to
1130      * block_size_max_sink_input). */
1131     ilength_full = ilength;
1132
1133     if (ilength > block_size_max_sink_input)
1134         ilength = block_size_max_sink_input;
1135
1136     /* If the channel maps of the sink and this stream differ, we need
1137      * to adjust the volume *before* we resample. Otherwise we can do
1138      * it after and leave it for the sink code */
1139
1140     do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
1141     volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
1142     need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);
1143
1144 #ifdef __TIZEN__
1145     avc_mode = pa_sink_get_avc_mode(i->sink);
1146 #ifdef SINK_INPUT_DEBUG
1147     pa_log("idx(%u), avc mode(%d), do(%d), norm(%d), nvfs(%d), muted(%d), resampler(%p)",
1148             i->index, avc_mode,
1149             do_volume_adj_here, volume_is_norm, need_volume_factor_sink,
1150             i->thread_info.muted, i->thread_info.resampler);
1151 #endif
1152 #endif
1153
1154     while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
1155         pa_memchunk tchunk;
1156
1157         /* There's nothing in our render queue. We need to fill it up
1158          * with data from the implementor. */
1159
1160         if (i->thread_info.state == PA_SINK_INPUT_CORKED ||
1161             i->pop(i, ilength, &tchunk) < 0) {
1162
1163             /* OK, we're corked or the implementor didn't give us any
1164              * data, so let's just hand out silence */
1165             pa_atomic_store(&i->thread_info.drained, 1);
1166
1167             pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE, true);
1168             i->thread_info.playing_for = 0;
1169             if (i->thread_info.underrun_for != (uint64_t) -1) {
1170                 i->thread_info.underrun_for += ilength_full;
1171                 i->thread_info.underrun_for_sink += slength;
1172             }
1173             break;
1174         }
1175
1176         pa_atomic_store(&i->thread_info.drained, 0);
1177
1178         pa_assert(tchunk.length > 0);
1179         pa_assert(tchunk.memblock);
1180
1181         i->thread_info.underrun_for = 0;
1182         i->thread_info.underrun_for_sink = 0;
1183         i->thread_info.playing_for += tchunk.length;
1184
1185         while (tchunk.length > 0) {
1186             pa_memchunk wchunk;
1187             bool nvfs = need_volume_factor_sink;
1188
1189             wchunk = tchunk;
1190             pa_memblock_ref(wchunk.memblock);
1191
1192             if (wchunk.length > block_size_max_sink_input)
1193                 wchunk.length = block_size_max_sink_input;
1194
1195             /* It might be necessary to adjust the volume here */
1196 #ifdef __TIZEN__
1197             if (do_volume_adj_here && !volume_is_norm && avc_mode != PA_SINK_AVC_NORM) {
1198 #else
1199             if (do_volume_adj_here && !volume_is_norm) {
1200 #endif
1201                 pa_memchunk_make_writable(&wchunk, 0);
1202
1203 #ifdef __TIZEN__
1204                 if (i->thread_info.muted || avc_mode == PA_SINK_AVC_SILENT) {
1205 #else
1206                 if (i->thread_info.muted) {
1207 #endif
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             prev_ramp_finished = i->thread_info.ramp.finished;
1228 #endif
1229             if (!i->thread_info.resampler) {
1230
1231                 if (nvfs) {
1232                     pa_memchunk_make_writable(&wchunk, 0);
1233                     pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
1234                 }
1235
1236 #ifdef TIZEN_VOLUME_RAMP
1237                 check_and_apply_ramp(&i->thread_info.ramp, &i->sink->sample_spec, &wchunk);
1238 #endif
1239                 pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
1240             } else {
1241                 pa_memchunk rchunk;
1242 #ifdef TIZEN_VOLUME_RAMP
1243                 check_and_apply_ramp(&i->thread_info.ramp, &i->thread_info.sample_spec, &wchunk);
1244 #endif
1245                 pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
1246
1247 #ifdef SINK_INPUT_DEBUG
1248                 pa_log_debug("pushing %lu", (unsigned long) rchunk.length);
1249 #endif
1250
1251                 if (rchunk.memblock) {
1252
1253                     if (nvfs) {
1254                         pa_memchunk_make_writable(&rchunk, 0);
1255                         pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
1256                     }
1257
1258                     pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
1259                     pa_memblock_unref(rchunk.memblock);
1260                 }
1261             }
1262
1263             pa_memblock_unref(wchunk.memblock);
1264
1265             tchunk.index += wchunk.length;
1266             tchunk.length -= wchunk.length;
1267         }
1268
1269         pa_memblock_unref(tchunk.memblock);
1270     }
1271
1272     pa_assert_se(pa_memblockq_peek(i->thread_info.render_memblockq, chunk) >= 0);
1273
1274     pa_assert(chunk->length > 0);
1275     pa_assert(chunk->memblock);
1276
1277 #ifdef SINK_INPUT_DEBUG
1278     pa_log_debug("peeking %lu", (unsigned long) chunk->length);
1279 #endif
1280
1281     if (chunk->length > block_size_max_sink)
1282         chunk->length = block_size_max_sink;
1283
1284     /* Let's see if we had to apply the volume adjustment ourselves,
1285      * or if this can be done by the sink for us */
1286
1287 #ifdef __TIZEN__
1288     if (do_volume_adj_here || avc_mode == PA_SINK_AVC_NORM)
1289 #else
1290     if (do_volume_adj_here)
1291 #endif
1292         /* We had different channel maps, so we already did the adjustment */
1293         pa_cvolume_reset(volume, i->sink->sample_spec.channels);
1294 #ifdef __TIZEN__
1295     else if (i->thread_info.muted || avc_mode == PA_SINK_AVC_SILENT)
1296 #else
1297     else if (i->thread_info.muted)
1298 #endif
1299         /* We've both the same channel map, so let's have the sink do the adjustment for us*/
1300         pa_cvolume_mute(volume, i->sink->sample_spec.channels);
1301     else
1302         *volume = i->thread_info.soft_volume;
1303 #ifdef TIZEN_PCM_DUMP
1304     pa_sink_input_write_pcm_dump(i, chunk);
1305 #endif
1306 #ifdef TIZEN_VOLUME_RAMP
1307     /* Hook fire only if ramp is finished. Note that it does not mean all the ramped data
1308      * is written to the device, hence it needs to be improved later on. */
1309     if (!prev_ramp_finished && i->thread_info.ramp.finished) {
1310         pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_RAMP_FINISH], i);
1311         i->thread_info.ramp.finished = false;
1312     }
1313 #endif
1314 }
1315
1316 /* Called from thread context */
1317 void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
1318
1319     pa_sink_input_assert_ref(i);
1320     pa_sink_input_assert_io_context(i);
1321     pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1322     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1323     pa_assert(nbytes > 0);
1324
1325 #ifdef SINK_INPUT_DEBUG
1326     pa_log_debug("dropping %lu", (unsigned long) nbytes);
1327 #endif
1328 #ifdef TIZEN_PCM_DUMP
1329     if (i->pcm_dump_fp && i->dump_length) {
1330         int64_t seek_length;
1331
1332         seek_length = (int64_t) (nbytes - i->dump_length);
1333
1334         if (seek_length < 0)
1335             fseeko(i->pcm_dump_fp, (off_t)seek_length, SEEK_CUR);
1336
1337         i->dump_length = 0;
1338     }
1339 #endif
1340
1341     pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
1342 }
1343
1344 /* Called from thread context */
1345 bool pa_sink_input_process_underrun(pa_sink_input *i) {
1346     pa_sink_input_assert_ref(i);
1347     pa_sink_input_assert_io_context(i);
1348
1349     if (pa_memblockq_is_readable(i->thread_info.render_memblockq))
1350         return false;
1351
1352     if (i->process_underrun && i->process_underrun(i)) {
1353         /* All valid data has been played back, so we can empty this queue. */
1354         pa_memblockq_silence(i->thread_info.render_memblockq);
1355         return true;
1356     }
1357     return false;
1358 }
1359
1360 /* Called from thread context */
1361 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
1362     size_t lbq;
1363     bool called = false;
1364
1365     pa_sink_input_assert_ref(i);
1366     pa_sink_input_assert_io_context(i);
1367     pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1368     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1369
1370 #ifdef SINK_INPUT_DEBUG
1371     pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes);
1372 #endif
1373
1374     lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
1375
1376     if (nbytes > 0 && !i->thread_info.dont_rewind_render) {
1377         pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
1378         pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
1379     }
1380
1381     if (i->thread_info.rewrite_nbytes == (size_t) -1) {
1382
1383 #ifdef TIZEN_PCM_DUMP
1384         /* rewind pcm */
1385         if (i->pcm_dump_fp)
1386             fseeko(i->pcm_dump_fp, (off_t)pa_memblockq_get_length(i->thread_info.render_memblockq) * (-1), SEEK_CUR);
1387 #endif
1388         /* We were asked to drop all buffered data, and rerequest new
1389          * data from implementor the next time peek() is called */
1390
1391         pa_memblockq_flush_write(i->thread_info.render_memblockq, true);
1392
1393     } else if (i->thread_info.rewrite_nbytes > 0) {
1394         size_t max_rewrite, amount;
1395
1396         /* Calculate how much make sense to rewrite at most */
1397         max_rewrite = nbytes + lbq;
1398
1399         /* Transform into local domain */
1400         if (i->thread_info.resampler)
1401             max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
1402
1403         /* Calculate how much of the rewinded data should actually be rewritten */
1404         amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
1405
1406         if (amount > 0) {
1407             pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
1408
1409 #ifdef TIZEN_PCM_DUMP
1410             /* rewind pcm */
1411             if (i->pcm_dump_fp)
1412                 fseeko(i->pcm_dump_fp, (off_t)amount * (-1), SEEK_CUR);
1413 #endif
1414             /* Tell the implementor */
1415             if (i->process_rewind)
1416                 i->process_rewind(i, amount);
1417             called = true;
1418
1419             /* Convert back to sink domain */
1420             if (i->thread_info.resampler)
1421                 amount = pa_resampler_result(i->thread_info.resampler, amount);
1422
1423             if (amount > 0)
1424                 /* Ok, now update the write pointer */
1425                 pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE, true);
1426
1427             if (i->thread_info.rewrite_flush)
1428                 pa_memblockq_silence(i->thread_info.render_memblockq);
1429
1430             /* And rewind the resampler */
1431             if (i->thread_info.resampler)
1432                 pa_resampler_rewind(i->thread_info.resampler, amount);
1433         }
1434     }
1435
1436     if (!called)
1437         if (i->process_rewind)
1438             i->process_rewind(i, 0);
1439
1440     i->thread_info.rewrite_nbytes = 0;
1441     i->thread_info.rewrite_flush = false;
1442     i->thread_info.dont_rewind_render = false;
1443 }
1444
1445 /* Called from thread context */
1446 size_t pa_sink_input_get_max_rewind(pa_sink_input *i) {
1447     pa_sink_input_assert_ref(i);
1448     pa_sink_input_assert_io_context(i);
1449
1450     return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_rewind) : i->sink->thread_info.max_rewind;
1451 }
1452
1453 /* Called from thread context */
1454 size_t pa_sink_input_get_max_request(pa_sink_input *i) {
1455     pa_sink_input_assert_ref(i);
1456     pa_sink_input_assert_io_context(i);
1457
1458     /* We're not verifying the status here, to allow this to be called
1459      * in the state change handler between _INIT and _RUNNING */
1460
1461     return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_request) : i->sink->thread_info.max_request;
1462 }
1463
1464 /* Called from thread context */
1465 void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */) {
1466     pa_sink_input_assert_ref(i);
1467     pa_sink_input_assert_io_context(i);
1468     pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1469     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1470
1471     pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
1472
1473     if (i->update_max_rewind)
1474         i->update_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
1475 }
1476
1477 /* Called from thread context */
1478 void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */) {
1479     pa_sink_input_assert_ref(i);
1480     pa_sink_input_assert_io_context(i);
1481     pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
1482     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
1483
1484     if (i->update_max_request)
1485         i->update_max_request(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
1486 }
1487
1488 /* Called from thread context */
1489 pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
1490     pa_sink_input_assert_ref(i);
1491     pa_sink_input_assert_io_context(i);
1492
1493     if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1494         usec = i->sink->thread_info.fixed_latency;
1495
1496     if (usec != (pa_usec_t) -1)
1497         usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
1498
1499     i->thread_info.requested_sink_latency = usec;
1500     pa_sink_invalidate_requested_latency(i->sink, true);
1501
1502     return usec;
1503 }
1504
1505 /* Called from main context */
1506 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
1507     pa_sink_input_assert_ref(i);
1508     pa_assert_ctl_context();
1509
1510     if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1511         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1512         return usec;
1513     }
1514
1515     /* If this sink input is not realized yet or we are being moved,
1516      * we have to touch the thread info data directly */
1517
1518     if (i->sink) {
1519         if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
1520             usec = pa_sink_get_fixed_latency(i->sink);
1521
1522         if (usec != (pa_usec_t) -1) {
1523             pa_usec_t min_latency, max_latency;
1524             pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
1525             usec = PA_CLAMP(usec, min_latency, max_latency);
1526         }
1527     }
1528
1529     i->thread_info.requested_sink_latency = usec;
1530
1531     return usec;
1532 }
1533
1534 /* Called from main context */
1535 pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
1536     pa_sink_input_assert_ref(i);
1537     pa_assert_ctl_context();
1538
1539     if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1540         pa_usec_t usec = 0;
1541         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1542         return usec;
1543     }
1544
1545     /* If this sink input is not realized yet or we are being moved,
1546      * we have to touch the thread info data directly */
1547
1548     return i->thread_info.requested_sink_latency;
1549 }
1550
1551 /* Called from main context */
1552 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool save, bool absolute) {
1553     pa_cvolume v;
1554
1555     pa_sink_input_assert_ref(i);
1556     pa_assert_ctl_context();
1557     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1558     pa_assert(volume);
1559     pa_assert(pa_cvolume_valid(volume));
1560     pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
1561     pa_assert(i->volume_writable);
1562
1563     if (!absolute && pa_sink_flat_volume_enabled(i->sink)) {
1564         v = i->sink->reference_volume;
1565         pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
1566
1567         if (pa_cvolume_compatible(volume, &i->sample_spec))
1568             volume = pa_sw_cvolume_multiply(&v, &v, volume);
1569         else
1570             volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume));
1571     } else {
1572         if (!pa_cvolume_compatible(volume, &i->sample_spec)) {
1573             v = i->volume;
1574             volume = pa_cvolume_scale(&v, pa_cvolume_max(volume));
1575         }
1576     }
1577
1578     if (pa_cvolume_equal(volume, &i->volume)) {
1579         i->save_volume = i->save_volume || save;
1580         return;
1581     }
1582
1583     pa_sink_input_set_volume_direct(i, volume);
1584     i->save_volume = save;
1585
1586     if (pa_sink_flat_volume_enabled(i->sink)) {
1587         /* We are in flat volume mode, so let's update all sink input
1588          * volumes and update the flat volume of the sink */
1589
1590         pa_sink_set_volume(i->sink, NULL, true, save);
1591
1592     } else {
1593         /* OK, we are in normal volume mode. The volume only affects
1594          * ourselves */
1595         set_real_ratio(i, volume);
1596         pa_sink_input_set_reference_ratio(i, &i->volume);
1597
1598         /* Copy the new soft_volume to the thread_info struct */
1599         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1600     }
1601 }
1602
1603 void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa_cvolume *volume_factor) {
1604     struct volume_factor_entry *v;
1605
1606     pa_sink_input_assert_ref(i);
1607     pa_assert_ctl_context();
1608     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1609     pa_assert(volume_factor);
1610     pa_assert(key);
1611     pa_assert(pa_cvolume_valid(volume_factor));
1612     pa_assert(volume_factor->channels == 1 || pa_cvolume_compatible(volume_factor, &i->sample_spec));
1613
1614     v = volume_factor_entry_new(key, volume_factor);
1615     if (!pa_cvolume_compatible(volume_factor, &i->sample_spec))
1616         pa_cvolume_set(&v->volume, i->sample_spec.channels, volume_factor->values[0]);
1617
1618     pa_assert_se(pa_hashmap_put(i->volume_factor_items, v->key, v) >= 0);
1619     if (pa_hashmap_size(i->volume_factor_items) == 1)
1620         i->volume_factor = v->volume;
1621     else
1622         pa_sw_cvolume_multiply(&i->volume_factor, &i->volume_factor, &v->volume);
1623
1624     pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1625
1626     /* Copy the new soft_volume to the thread_info struct */
1627     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1628 }
1629
1630 /* Returns 0 if an entry was removed and -1 if no entry for the given key was
1631  * found. */
1632 int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) {
1633     struct volume_factor_entry *v;
1634
1635     pa_sink_input_assert_ref(i);
1636     pa_assert(key);
1637     pa_assert_ctl_context();
1638     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1639
1640     if (pa_hashmap_remove_and_free(i->volume_factor_items, key) < 0)
1641         return -1;
1642
1643     switch (pa_hashmap_size(i->volume_factor_items)) {
1644         case 0:
1645             pa_cvolume_reset(&i->volume_factor, i->sample_spec.channels);
1646             break;
1647         case 1:
1648             v = pa_hashmap_first(i->volume_factor_items);
1649             i->volume_factor = v->volume;
1650             break;
1651         default:
1652             volume_factor_from_hashmap(&i->volume_factor, i->volume_factor_items, i->volume_factor.channels);
1653     }
1654
1655     pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1656
1657 #ifdef TIZEN_VOLUME_RAMP
1658     /* If a ramp was set, skip rewinding. It'll be rewinded with SET_VOLUME_RAMP later. */
1659     if (pa_cvolume_ramp_target_active(&i->ramp))  {
1660         bool skip_rewind = true;
1661         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, &skip_rewind, 0, NULL) == 0);
1662     } else {
1663 #endif
1664     /* Copy the new soft_volume to the thread_info struct */
1665     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1666 #ifdef TIZEN_VOLUME_RAMP
1667     }
1668 #endif
1669
1670     return 0;
1671 }
1672
1673 #ifdef TIZEN_VOLUME_RAMP
1674 void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg) {
1675     struct volume_ramp_factor_entry *r;
1676
1677     pa_sink_input_assert_ref(i);
1678     pa_assert_ctl_context();
1679     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1680     pa_assert(ramp_factor);
1681     pa_assert(key);
1682     pa_assert(pa_cvolume_ramp_valid(ramp_factor));
1683     pa_assert(ramp_factor->channels == 1 || pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec));
1684
1685     r = volume_ramp_factor_entry_new(key, ramp_factor);
1686     if (!pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec))
1687         pa_cvolume_ramp_set(&r->ramp, i->sample_spec.channels,
1688                                       ramp_factor->ramps[0].type,
1689                                       ramp_factor->ramps[0].length,
1690                                       ramp_factor->ramps[0].target);
1691
1692     pa_assert_se(pa_hashmap_put(i->ramp_factor_items, r->key, r) >= 0);
1693     if (pa_hashmap_size(i->ramp_factor_items) == 1)
1694         pa_cvolume_ramp_set(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length, r->ramp.ramps[0].target);
1695     else
1696         pa_sw_cvolume_ramp_multiply(&i->ramp_factor, &i->ramp_factor, &r->ramp);
1697
1698     pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp,  i->sample_spec.rate);
1699
1700     if (send_msg)
1701         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
1702 }
1703
1704 /* Returns 0 if an entry was removed and -1 if no entry for the given key was
1705  * found. */
1706 int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg) {
1707     struct volume_ramp_factor_entry *r;
1708
1709     pa_sink_input_assert_ref(i);
1710     pa_assert(key);
1711     pa_assert_ctl_context();
1712     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1713
1714     r = pa_hashmap_remove(i->ramp_factor_items, key);
1715     if (!r)
1716         return -1;
1717
1718     switch (pa_hashmap_size(i->ramp_factor_items)) {
1719         case 0:
1720             pa_cvolume_ramp_reset(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length);
1721             break;
1722         case 1: {
1723             struct volume_ramp_factor_entry *rf;
1724             if ((rf = pa_hashmap_first(i->ramp_factor_items)))
1725                 pa_cvolume_ramp_set(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length, rf->ramp.ramps[0].target);
1726             break;
1727         }
1728         default:
1729             volume_ramp_factor_from_hashmap(&i->ramp_factor, i->ramp_factor_items, i->ramp_factor.channels, i->ramp_factor.ramps[0].type, i->ramp_factor.ramps[0].length);
1730     }
1731
1732     volume_ramp_factor_entry_free(r);
1733
1734     pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate);
1735
1736     if (send_msg)
1737         pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
1738
1739     return 0;
1740 }
1741 #endif
1742 /* Called from main context */
1743 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {
1744     pa_sink_input_assert_ref(i);
1745     pa_assert_ctl_context();
1746     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1747     pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
1748
1749     /* This basically calculates:
1750      *
1751      * i->real_ratio := v
1752      * i->soft_volume := i->real_ratio * i->volume_factor */
1753
1754     if (v)
1755         i->real_ratio = *v;
1756     else
1757         pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
1758
1759     pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1760     /* We don't copy the data to the thread_info data. That's left for someone else to do */
1761 }
1762
1763 /* Called from main or I/O context */
1764 bool pa_sink_input_is_passthrough(pa_sink_input *i) {
1765     pa_sink_input_assert_ref(i);
1766
1767     if (PA_UNLIKELY(!pa_format_info_is_pcm(i->format)))
1768         return true;
1769
1770     if (PA_UNLIKELY(i->flags & PA_SINK_INPUT_PASSTHROUGH))
1771         return true;
1772
1773     return false;
1774 }
1775
1776 /* Called from main context */
1777 bool pa_sink_input_is_volume_readable(pa_sink_input *i) {
1778     pa_sink_input_assert_ref(i);
1779     pa_assert_ctl_context();
1780
1781     return !pa_sink_input_is_passthrough(i);
1782 }
1783
1784 /* Called from main context */
1785 pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute) {
1786     pa_sink_input_assert_ref(i);
1787     pa_assert_ctl_context();
1788     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1789     pa_assert(pa_sink_input_is_volume_readable(i));
1790
1791     if (absolute || !pa_sink_flat_volume_enabled(i->sink))
1792         *volume = i->volume;
1793     else
1794         *volume = i->reference_ratio;
1795
1796     return volume;
1797 }
1798
1799 /* Called from main context */
1800 void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save) {
1801     bool old_mute;
1802
1803     pa_sink_input_assert_ref(i);
1804     pa_assert_ctl_context();
1805     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1806
1807     old_mute = i->muted;
1808
1809     if (mute == old_mute) {
1810         i->save_muted |= save;
1811         return;
1812     }
1813
1814     i->muted = mute;
1815     pa_log_debug("The mute of sink input %u changed from %s to %s.", i->index, pa_yes_no(old_mute), pa_yes_no(mute));
1816
1817     i->save_muted = save;
1818
1819     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
1820
1821     /* The mute status changed, let's tell people so */
1822     if (i->mute_changed)
1823         i->mute_changed(i);
1824
1825     pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1826     pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MUTE_CHANGED], i);
1827 }
1828
1829 void pa_sink_input_set_property(pa_sink_input *i, const char *key, const char *value) {
1830     char *old_value = NULL;
1831     const char *new_value;
1832
1833     pa_assert(i);
1834     pa_assert(key);
1835
1836     if (pa_proplist_contains(i->proplist, key)) {
1837         old_value = pa_xstrdup(pa_proplist_gets(i->proplist, key));
1838         if (value && old_value && pa_streq(value, old_value))
1839             goto finish;
1840
1841         if (!old_value)
1842             old_value = pa_xstrdup("(data)");
1843     } else {
1844         if (!value)
1845             goto finish;
1846
1847         old_value = pa_xstrdup("(unset)");
1848     }
1849
1850     if (value) {
1851         pa_proplist_sets(i->proplist, key, value);
1852         new_value = value;
1853     } else {
1854         pa_proplist_unset(i->proplist, key);
1855         new_value = "(unset)";
1856     }
1857
1858     if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1859         pa_log_debug("Sink input %u: proplist[%s]: %s -> %s", i->index, key, old_value, new_value);
1860         pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1861         pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1862     }
1863
1864 finish:
1865     pa_xfree(old_value);
1866 }
1867
1868 void pa_sink_input_set_property_arbitrary(pa_sink_input *i, const char *key, const uint8_t *value, size_t nbytes) {
1869     const uint8_t *old_value;
1870     size_t old_nbytes;
1871     const char *old_value_str;
1872     const char *new_value_str;
1873
1874     pa_assert(i);
1875     pa_assert(key);
1876
1877     if (pa_proplist_get(i->proplist, key, (const void **) &old_value, &old_nbytes) >= 0) {
1878         if (value && nbytes == old_nbytes && !memcmp(value, old_value, nbytes))
1879             return;
1880
1881         old_value_str = "(data)";
1882
1883     } else {
1884         if (!value)
1885             return;
1886
1887         old_value_str = "(unset)";
1888     }
1889
1890     if (value) {
1891         pa_proplist_set(i->proplist, key, value, nbytes);
1892         new_value_str = "(data)";
1893     } else {
1894         pa_proplist_unset(i->proplist, key);
1895         new_value_str = "(unset)";
1896     }
1897
1898     if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1899         pa_log_debug("Sink input %u: proplist[%s]: %s -> %s", i->index, key, old_value_str, new_value_str);
1900         pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1901         pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1902     }
1903 }
1904
1905 /* Called from main thread */
1906 void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
1907     void *state;
1908     const char *key;
1909     const uint8_t *value;
1910     size_t nbytes;
1911
1912     pa_sink_input_assert_ref(i);
1913     pa_assert(p);
1914     pa_assert_ctl_context();
1915
1916     switch (mode) {
1917         case PA_UPDATE_SET: {
1918             /* Delete everything that is not in p. */
1919             for (state = NULL; (key = pa_proplist_iterate(i->proplist, &state));) {
1920                 if (!pa_proplist_contains(p, key))
1921                     pa_sink_input_set_property(i, key, NULL);
1922             }
1923
1924             /* Fall through. */
1925         }
1926
1927         case PA_UPDATE_REPLACE: {
1928             for (state = NULL; (key = pa_proplist_iterate(p, &state));) {
1929                 pa_proplist_get(p, key, (const void **) &value, &nbytes);
1930                 pa_sink_input_set_property_arbitrary(i, key, value, nbytes);
1931             }
1932
1933             break;
1934         }
1935
1936         case PA_UPDATE_MERGE: {
1937             for (state = NULL; (key = pa_proplist_iterate(p, &state));) {
1938                 if (pa_proplist_contains(i->proplist, key))
1939                     continue;
1940
1941                 pa_proplist_get(p, key, (const void **) &value, &nbytes);
1942                 pa_sink_input_set_property_arbitrary(i, key, value, nbytes);
1943             }
1944
1945             break;
1946         }
1947     }
1948 }
1949
1950 /* Called from main context */
1951 void pa_sink_input_cork(pa_sink_input *i, bool b) {
1952     pa_sink_input_assert_ref(i);
1953     pa_assert_ctl_context();
1954     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1955
1956     sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
1957 }
1958
1959 /* Called from main context */
1960 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
1961     pa_sink_input_assert_ref(i);
1962     pa_assert_ctl_context();
1963     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1964     pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE);
1965
1966     if (i->sample_spec.rate == rate)
1967         return 0;
1968
1969     i->sample_spec.rate = rate;
1970
1971     if (i->sink)
1972         pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
1973     else {
1974         i->thread_info.sample_spec.rate = rate;
1975         pa_resampler_set_input_rate(i->thread_info.resampler, rate);
1976     }
1977
1978     pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1979     return 0;
1980 }
1981
1982 /* Called from main context */
1983 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
1984     pa_sink_input_assert_ref(i);
1985     pa_assert_ctl_context();
1986
1987     return i->actual_resample_method;
1988 }
1989
1990 /* Called from main context */
1991 bool pa_sink_input_may_move(pa_sink_input *i) {
1992     pa_sink_input_assert_ref(i);
1993     pa_assert_ctl_context();
1994     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1995
1996     if (i->flags & PA_SINK_INPUT_DONT_MOVE)
1997         return false;
1998
1999     if (i->sync_next || i->sync_prev) {
2000         pa_log_warn("Moving synchronized streams not supported.");
2001         return false;
2002     }
2003
2004     return true;
2005 }
2006
2007 static bool find_filter_sink_input(pa_sink_input *target, pa_sink *s) {
2008     unsigned PA_UNUSED i = 0;
2009     while (s && s->input_to_master) {
2010         if (s->input_to_master == target)
2011             return true;
2012         s = s->input_to_master->sink;
2013         pa_assert(i++ < 100);
2014     }
2015     return false;
2016 }
2017
2018 static bool is_filter_sink_moving(pa_sink_input *i) {
2019     pa_sink *sink = i->sink;
2020
2021     if (!sink)
2022         return false;
2023
2024     while (sink->input_to_master) {
2025         sink = sink->input_to_master->sink;
2026
2027         if (!sink)
2028             return true;
2029     }
2030
2031     return false;
2032 }
2033
2034 /* Called from main context */
2035 bool pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
2036     pa_sink_input_assert_ref(i);
2037     pa_assert_ctl_context();
2038     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2039     pa_sink_assert_ref(dest);
2040
2041     if (dest == i->sink)
2042         return true;
2043
2044     if (dest->unlink_requested)
2045         return false;
2046
2047     if (!pa_sink_input_may_move(i))
2048         return false;
2049
2050     /* Make sure we're not creating a filter sink cycle */
2051     if (find_filter_sink_input(i, dest)) {
2052         pa_log_debug("Can't connect input to %s, as that would create a cycle.", dest->name);
2053         return false;
2054     }
2055
2056     /* If this sink input is connected to a filter sink that itself is moving,
2057      * then don't allow the move. Moving requires sending a message to the IO
2058      * thread of the old sink, and if the old sink is a filter sink that is
2059      * moving, there's no IO thread associated to the old sink. */
2060     if (is_filter_sink_moving(i)) {
2061         pa_log_debug("Can't move input from filter sink %s, because the filter sink itself is currently moving.",
2062                      i->sink->name);
2063         return false;
2064     }
2065
2066     if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
2067         pa_log_warn("Failed to move sink input: too many inputs per sink.");
2068         return false;
2069     }
2070
2071     if (check_passthrough_connection(pa_sink_input_is_passthrough(i), dest) < 0)
2072         return false;
2073
2074     if (i->may_move_to)
2075         if (!i->may_move_to(i, dest))
2076             return false;
2077
2078     return true;
2079 }
2080
2081 /* Called from main context */
2082 int pa_sink_input_start_move(pa_sink_input *i) {
2083     pa_source_output *o, PA_UNUSED *p = NULL;
2084     struct volume_factor_entry *v;
2085     void *state = NULL;
2086     int r;
2087
2088     pa_sink_input_assert_ref(i);
2089     pa_assert_ctl_context();
2090     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2091     pa_assert(i->sink);
2092
2093     if (!pa_sink_input_may_move(i))
2094         return -PA_ERR_NOTSUPPORTED;
2095
2096     if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
2097         return r;
2098
2099     pa_log_debug("Starting to move sink input %u from '%s'", (unsigned) i->index, i->sink->name);
2100
2101     /* Kill directly connected outputs */
2102     while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
2103         pa_assert(o != p);
2104         pa_source_output_kill(o);
2105         p = o;
2106     }
2107     pa_assert(pa_idxset_isempty(i->direct_outputs));
2108
2109     pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
2110
2111     if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
2112         pa_assert_se(i->sink->n_corked-- >= 1);
2113
2114     if (pa_sink_input_is_passthrough(i))
2115         pa_sink_leave_passthrough(i->sink);
2116
2117     if (pa_sink_flat_volume_enabled(i->sink))
2118         /* We might need to update the sink's volume if we are in flat
2119          * volume mode. */
2120         pa_sink_set_volume(i->sink, NULL, false, false);
2121
2122     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
2123
2124     pa_sink_update_status(i->sink);
2125
2126     PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
2127         pa_cvolume_remap(&v->volume, &i->sink->channel_map, &i->channel_map);
2128
2129     pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
2130
2131     i->sink = NULL;
2132
2133     pa_sink_input_unref(i);
2134
2135     return 0;
2136 }
2137
2138 /* Called from main context. If i has an origin sink that uses volume sharing,
2139  * then also the origin sink and all streams connected to it need to update
2140  * their volume - this function does all that by using recursion. */
2141 static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) {
2142     pa_cvolume new_volume;
2143
2144     pa_assert(i);
2145     pa_assert(dest);
2146     pa_assert(i->sink); /* The destination sink should already be set. */
2147
2148     if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
2149         pa_sink *root_sink = pa_sink_get_master(i->sink);
2150         pa_sink_input *origin_sink_input;
2151         uint32_t idx;
2152
2153         if (PA_UNLIKELY(!root_sink))
2154             return;
2155
2156         if (pa_sink_flat_volume_enabled(i->sink)) {
2157             /* Ok, so the origin sink uses volume sharing, and flat volume is
2158              * enabled. The volume will have to be updated as follows:
2159              *
2160              *     i->volume := i->sink->real_volume
2161              *         (handled later by pa_sink_set_volume)
2162              *     i->reference_ratio := i->volume / i->sink->reference_volume
2163              *         (handled later by pa_sink_set_volume)
2164              *     i->real_ratio stays unchanged
2165              *         (streams whose origin sink uses volume sharing should
2166              *          always have real_ratio of 0 dB)
2167              *     i->soft_volume stays unchanged
2168              *         (streams whose origin sink uses volume sharing should
2169              *          always have volume_factor as soft_volume, so no change
2170              *          should be needed) */
2171
2172             pa_assert(pa_cvolume_is_norm(&i->real_ratio));
2173             pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
2174
2175             /* Notifications will be sent by pa_sink_set_volume(). */
2176
2177         } else {
2178             /* Ok, so the origin sink uses volume sharing, and flat volume is
2179              * disabled. The volume will have to be updated as follows:
2180              *
2181              *     i->volume := 0 dB
2182              *     i->reference_ratio := 0 dB
2183              *     i->real_ratio stays unchanged
2184              *         (streams whose origin sink uses volume sharing should
2185              *          always have real_ratio of 0 dB)
2186              *     i->soft_volume stays unchanged
2187              *         (streams whose origin sink uses volume sharing should
2188              *          always have volume_factor as soft_volume, so no change
2189              *          should be needed) */
2190
2191             pa_cvolume_reset(&new_volume, i->volume.channels);
2192             pa_sink_input_set_volume_direct(i, &new_volume);
2193             pa_sink_input_set_reference_ratio(i, &new_volume);
2194             pa_assert(pa_cvolume_is_norm(&i->real_ratio));
2195             pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
2196         }
2197
2198         /* Additionally, the origin sink volume needs updating:
2199          *
2200          *     i->origin_sink->reference_volume := root_sink->reference_volume
2201          *     i->origin_sink->real_volume := root_sink->real_volume
2202          *     i->origin_sink->soft_volume stays unchanged
2203          *         (sinks that use volume sharing should always have
2204          *          soft_volume of 0 dB) */
2205
2206         new_volume = root_sink->reference_volume;
2207         pa_cvolume_remap(&new_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
2208         pa_sink_set_reference_volume_direct(i->origin_sink, &new_volume);
2209
2210         i->origin_sink->real_volume = root_sink->real_volume;
2211         pa_cvolume_remap(&i->origin_sink->real_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
2212
2213         pa_assert(pa_cvolume_is_norm(&i->origin_sink->soft_volume));
2214
2215         /* If you wonder whether i->origin_sink->set_volume() should be called
2216          * somewhere, that's not the case, because sinks that use volume
2217          * sharing shouldn't have any internal volume that set_volume() would
2218          * update. If you wonder whether the thread_info variables should be
2219          * synced, yes, they should, and it's done by the
2220          * PA_SINK_MESSAGE_FINISH_MOVE message handler. */
2221
2222         /* Recursively update origin sink inputs. */
2223         PA_IDXSET_FOREACH(origin_sink_input, i->origin_sink->inputs, idx)
2224             update_volume_due_to_moving(origin_sink_input, dest);
2225
2226     } else {
2227         if (pa_sink_flat_volume_enabled(i->sink)) {
2228             /* Ok, so this is a regular stream, and flat volume is enabled. The
2229              * volume will have to be updated as follows:
2230              *
2231              *     i->volume := i->reference_ratio * i->sink->reference_volume
2232              *     i->reference_ratio stays unchanged
2233              *     i->real_ratio := i->volume / i->sink->real_volume
2234              *         (handled later by pa_sink_set_volume)
2235              *     i->soft_volume := i->real_ratio * i->volume_factor
2236              *         (handled later by pa_sink_set_volume) */
2237
2238             new_volume = i->sink->reference_volume;
2239             pa_cvolume_remap(&new_volume, &i->sink->channel_map, &i->channel_map);
2240             pa_sw_cvolume_multiply(&new_volume, &new_volume, &i->reference_ratio);
2241             pa_sink_input_set_volume_direct(i, &new_volume);
2242
2243         } else {
2244             /* Ok, so this is a regular stream, and flat volume is disabled.
2245              * The volume will have to be updated as follows:
2246              *
2247              *     i->volume := i->reference_ratio
2248              *     i->reference_ratio stays unchanged
2249              *     i->real_ratio := i->reference_ratio
2250              *     i->soft_volume := i->real_ratio * i->volume_factor */
2251
2252             pa_sink_input_set_volume_direct(i, &i->reference_ratio);
2253             i->real_ratio = i->reference_ratio;
2254             pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
2255         }
2256     }
2257
2258     /* If i->sink == dest, then recursion has finished, and we can finally call
2259      * pa_sink_set_volume(), which will do the rest of the updates. */
2260     if ((i->sink == dest) && pa_sink_flat_volume_enabled(i->sink))
2261         pa_sink_set_volume(i->sink, NULL, false, i->save_volume);
2262 }
2263
2264 /* Called from main context */
2265 int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, bool save) {
2266     struct volume_factor_entry *v;
2267     void *state = NULL;
2268
2269     pa_sink_input_assert_ref(i);
2270     pa_assert_ctl_context();
2271     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2272     pa_assert(!i->sink);
2273     pa_sink_assert_ref(dest);
2274
2275     if (!pa_sink_input_may_move_to(i, dest))
2276         return -PA_ERR_NOTSUPPORTED;
2277
2278     if (pa_sink_input_is_passthrough(i) && !pa_sink_check_format(dest, i->format)) {
2279         pa_proplist *p = pa_proplist_new();
2280         pa_log_debug("New sink doesn't support stream format, sending format-changed and killing");
2281         /* Tell the client what device we want to be on if it is going to
2282          * reconnect */
2283         pa_proplist_sets(p, "device", dest->name);
2284         pa_sink_input_send_event(i, PA_STREAM_EVENT_FORMAT_LOST, p);
2285         pa_proplist_free(p);
2286         return -PA_ERR_NOTSUPPORTED;
2287     }
2288
2289     if (!(i->flags & PA_SINK_INPUT_VARIABLE_RATE) &&
2290         !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec)) {
2291         /* try to change dest sink format and rate if possible without glitches.
2292            module-suspend-on-idle resumes destination sink with
2293            SINK_INPUT_MOVE_FINISH hook */
2294
2295         pa_log_info("Trying to change sample spec");
2296         pa_sink_reconfigure(dest, &i->sample_spec, pa_sink_input_is_passthrough(i));
2297     }
2298
2299     if (i->moving)
2300         i->moving(i, dest);
2301
2302     i->sink = dest;
2303     i->save_sink = save;
2304     pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
2305
2306     PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
2307         pa_cvolume_remap(&v->volume, &i->channel_map, &i->sink->channel_map);
2308
2309     pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
2310
2311     if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
2312         i->sink->n_corked++;
2313
2314     pa_sink_input_update_resampler(i);
2315
2316     pa_sink_update_status(dest);
2317
2318     update_volume_due_to_moving(i, dest);
2319
2320     if (pa_sink_input_is_passthrough(i))
2321         pa_sink_enter_passthrough(i->sink);
2322
2323     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
2324
2325     pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
2326
2327     /* Notify everyone */
2328     pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
2329     pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2330
2331     return 0;
2332 }
2333
2334 /* Called from main context */
2335 void pa_sink_input_fail_move(pa_sink_input *i) {
2336
2337     pa_sink_input_assert_ref(i);
2338     pa_assert_ctl_context();
2339     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2340     pa_assert(!i->sink);
2341
2342     /* Check if someone wants this sink input? */
2343     if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_STOP)
2344         return;
2345
2346     if (i->moving)
2347         i->moving(i, NULL);
2348
2349     pa_sink_input_kill(i);
2350 }
2351
2352 /* Called from main context */
2353 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, bool save) {
2354     int r;
2355
2356     pa_sink_input_assert_ref(i);
2357     pa_assert_ctl_context();
2358     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2359     pa_assert(i->sink);
2360     pa_sink_assert_ref(dest);
2361
2362     if (dest == i->sink)
2363         return 0;
2364
2365     if (!pa_sink_input_may_move_to(i, dest))
2366         return -PA_ERR_NOTSUPPORTED;
2367
2368     pa_sink_input_ref(i);
2369
2370     if ((r = pa_sink_input_start_move(i)) < 0) {
2371         pa_sink_input_unref(i);
2372         return r;
2373     }
2374
2375     if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
2376         pa_sink_input_fail_move(i);
2377         pa_sink_input_unref(i);
2378         return r;
2379     }
2380
2381     pa_sink_input_unref(i);
2382
2383     return 0;
2384 }
2385
2386 /* Called from IO thread context except when cork() is called without a valid sink. */
2387 void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
2388     bool corking, uncorking;
2389
2390     pa_sink_input_assert_ref(i);
2391
2392     if (state == i->thread_info.state)
2393         return;
2394
2395 #ifdef TIZEN_EMPTY_POP
2396     if (state != PA_SINK_INPUT_RUNNING && _empty_pop_is_started(i))
2397         _empty_pop_reset(i);
2398 #endif
2399
2400     if ((state == PA_SINK_INPUT_DRAINED || state == PA_SINK_INPUT_RUNNING) &&
2401         !(i->thread_info.state == PA_SINK_INPUT_DRAINED || i->thread_info.state != PA_SINK_INPUT_RUNNING))
2402         pa_atomic_store(&i->thread_info.drained, 1);
2403
2404     corking = state == PA_SINK_INPUT_CORKED && i->thread_info.state == PA_SINK_INPUT_RUNNING;
2405     uncorking = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
2406
2407     if (i->state_change)
2408         i->state_change(i, state);
2409
2410     if (corking) {
2411
2412         pa_log_debug("Requesting rewind due to corking");
2413
2414         /* This will tell the implementing sink input driver to rewind
2415          * so that the unplayed already mixed data is not lost */
2416         if (i->sink)
2417             pa_sink_input_request_rewind(i, 0, true, true, false);
2418
2419         /* Set the corked state *after* requesting rewind */
2420         i->thread_info.state = state;
2421
2422     } else if (uncorking) {
2423
2424         pa_log_debug("Requesting rewind due to uncorking");
2425
2426         i->thread_info.underrun_for = (uint64_t) -1;
2427         i->thread_info.underrun_for_sink = 0;
2428         i->thread_info.playing_for = 0;
2429
2430         /* Set the uncorked state *before* requesting rewind */
2431         i->thread_info.state = state;
2432
2433         /* OK, we're being uncorked. Make sure we're not rewound when
2434          * the hw buffer is remixed and request a remix. */
2435         if (i->sink)
2436             pa_sink_input_request_rewind(i, 0, false, true, true);
2437     } else
2438         /* We may not be corking or uncorking, but we still need to set the state. */
2439         i->thread_info.state = state;
2440 }
2441
2442 /* Called from thread context, except when it is not. */
2443 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
2444     pa_sink_input *i = PA_SINK_INPUT(o);
2445     pa_sink_input_assert_ref(i);
2446
2447     switch (code) {
2448
2449         case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
2450             if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
2451                 i->thread_info.soft_volume = i->soft_volume;
2452 #ifdef TIZEN_VOLUME_RAMP
2453                 /* Skip rewinding */
2454                 if (userdata && (bool)(*(bool*)userdata) == true)
2455                     return 0;
2456 #endif
2457                 pa_sink_input_request_rewind(i, 0, true, false, false);
2458             }
2459             return 0;
2460
2461 #ifdef TIZEN_VOLUME_RAMP
2462         case PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP:
2463             /* we have ongoing ramp where we take current start values */
2464             pa_cvolume_ramp_start_from(&i->thread_info.ramp, &i->ramp);
2465             i->thread_info.ramp = i->ramp;
2466             pa_sink_input_request_rewind(i, 0, true, false, false);
2467             return 0;
2468 #endif
2469         case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
2470             if (i->thread_info.muted != i->muted) {
2471                 i->thread_info.muted = i->muted;
2472                 pa_sink_input_request_rewind(i, 0, true, false, false);
2473             }
2474             return 0;
2475
2476         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
2477             pa_usec_t *r = userdata;
2478
2479             r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
2480             r[1] += pa_sink_get_latency_within_thread(i->sink, false);
2481
2482             return 0;
2483         }
2484
2485         case PA_SINK_INPUT_MESSAGE_SET_RATE:
2486
2487             i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
2488             pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
2489
2490             return 0;
2491
2492         case PA_SINK_INPUT_MESSAGE_SET_STATE: {
2493             pa_sink_input *ssync;
2494
2495             pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
2496
2497             for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
2498                 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
2499
2500             for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
2501                 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
2502
2503             return 0;
2504         }
2505
2506         case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
2507             pa_usec_t *usec = userdata;
2508
2509             *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
2510             return 0;
2511         }
2512
2513         case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
2514             pa_usec_t *r = userdata;
2515
2516             *r = i->thread_info.requested_sink_latency;
2517             return 0;
2518         }
2519     }
2520
2521     return -PA_ERR_NOTIMPLEMENTED;
2522 }
2523
2524 /* Called from main thread */
2525 pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
2526     pa_sink_input_assert_ref(i);
2527     pa_assert_ctl_context();
2528
2529     if (i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED)
2530         return pa_atomic_load(&i->thread_info.drained) ? PA_SINK_INPUT_DRAINED : PA_SINK_INPUT_RUNNING;
2531
2532     return i->state;
2533 }
2534
2535 /* Called from IO context */
2536 bool pa_sink_input_safe_to_remove(pa_sink_input *i) {
2537     pa_sink_input_assert_ref(i);
2538     pa_sink_input_assert_io_context(i);
2539
2540     if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
2541         return pa_memblockq_is_empty(i->thread_info.render_memblockq);
2542
2543     return true;
2544 }
2545
2546 /* Called from IO context */
2547 void pa_sink_input_request_rewind(
2548         pa_sink_input *i,
2549         size_t nbytes  /* in our sample spec */,
2550         bool rewrite,  /* rewrite what we have, or get fresh data? */
2551         bool flush,    /* flush render memblockq? */
2552         bool dont_rewind_render) {
2553
2554     size_t lbq;
2555
2556     /* If 'rewrite' is true the sink is rewound as far as requested
2557      * and possible and the exact value of this is passed back the
2558      * implementor via process_rewind(). If 'flush' is also true all
2559      * already rendered data is also dropped.
2560      *
2561      * If 'rewrite' is false the sink is rewound as far as requested
2562      * and possible and the already rendered data is dropped so that
2563      * in the next iteration we read new data from the
2564      * implementor. This implies 'flush' is true.  If
2565      * dont_rewind_render is true then the render memblockq is not
2566      * rewound. */
2567
2568     /* nbytes = 0 means maximum rewind request */
2569
2570     pa_sink_input_assert_ref(i);
2571     pa_sink_input_assert_io_context(i);
2572     pa_assert(rewrite || flush);
2573     pa_assert(!dont_rewind_render || !rewrite);
2574
2575     /* We don't take rewind requests while we are corked */
2576     if (i->thread_info.state == PA_SINK_INPUT_CORKED)
2577         return;
2578
2579     nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
2580
2581 #ifdef SINK_INPUT_DEBUG
2582     pa_log_debug("request rewrite %zu", nbytes);
2583 #endif
2584
2585     /* Calculate how much we can rewind locally without having to
2586      * touch the sink */
2587     if (rewrite)
2588         lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
2589     else
2590         lbq = 0;
2591
2592     /* Check if rewinding for the maximum is requested, and if so, fix up */
2593     if (nbytes <= 0) {
2594
2595         /* Calculate maximum number of bytes that could be rewound in theory */
2596         nbytes = i->sink->thread_info.max_rewind + lbq;
2597
2598         /* Transform from sink domain */
2599         if (i->thread_info.resampler)
2600             nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
2601     }
2602
2603     /* Remember how much we actually want to rewrite */
2604     if (i->thread_info.rewrite_nbytes != (size_t) -1) {
2605         if (rewrite) {
2606             /* Make sure to not overwrite over underruns */
2607             if (nbytes > i->thread_info.playing_for)
2608                 nbytes = (size_t) i->thread_info.playing_for;
2609
2610             i->thread_info.rewrite_nbytes = nbytes;
2611         } else
2612             i->thread_info.rewrite_nbytes = (size_t) -1;
2613     }
2614
2615     i->thread_info.rewrite_flush =
2616         i->thread_info.rewrite_flush || flush;
2617
2618     i->thread_info.dont_rewind_render =
2619         i->thread_info.dont_rewind_render ||
2620         dont_rewind_render;
2621
2622     /* nbytes is -1 if some earlier rewind request had rewrite == false. */
2623     if (nbytes != (size_t) -1) {
2624
2625         /* Transform to sink domain */
2626         if (i->thread_info.resampler)
2627             nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
2628
2629         if (nbytes > lbq)
2630             pa_sink_request_rewind(i->sink, nbytes - lbq);
2631         else
2632             /* This call will make sure process_rewind() is called later */
2633             pa_sink_request_rewind(i->sink, 0);
2634     }
2635 }
2636
2637 /* Called from main context */
2638 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
2639     pa_sink_input_assert_ref(i);
2640     pa_assert_ctl_context();
2641     pa_assert(ret);
2642
2643     /* FIXME: Shouldn't access resampler object from main context! */
2644
2645     pa_silence_memchunk_get(
2646                 &i->core->silence_cache,
2647                 i->core->mempool,
2648                 ret,
2649                 &i->sample_spec,
2650                 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
2651
2652     return ret;
2653 }
2654
2655 #ifdef TIZEN_EMPTY_POP
2656 static void _empty_pop_start(pa_sink_input *i) {
2657     i->empty_pop_initial_timestamp = pa_rtclock_now();
2658     i->empty_pop_previous_duration = 0;
2659
2660     pa_log_debug("[%u] empty pop started!!!", i->index);
2661 }
2662
2663 static bool _empty_pop_is_started(pa_sink_input *i) {
2664     if (i->empty_pop_initial_timestamp > 0)
2665         return true;
2666     else
2667         return false;
2668 }
2669
2670 static uint32_t _empty_pop_calc_duration(pa_sink_input *i) {
2671     return (uint32_t)((pa_rtclock_now() - i->empty_pop_initial_timestamp) / PA_USEC_PER_SEC);
2672 }
2673
2674 static void _empty_pop_print_duration(pa_sink_input *i, uint32_t empty_pop_duration) {
2675     /* print only once per seconds */
2676     if (empty_pop_duration <= i->empty_pop_previous_duration)
2677         return;
2678
2679     i->empty_pop_previous_duration = empty_pop_duration;
2680
2681     pa_log_debug("[%u] empty pop (no sink-input data) for [%u] sec., timeout is [%u] sec.",
2682                   i->index, empty_pop_duration, i->core->empty_pop_threshold);
2683 }
2684
2685 static void _empty_pop_reset(pa_sink_input *i) {
2686     i->empty_pop_initial_timestamp = 0;
2687     i->empty_pop_previous_duration = 0;
2688
2689     pa_log_debug("[%u] empty pop reset...", i->index);
2690 }
2691
2692 void pa_sink_input_update_empty_pop(pa_sink_input *i, size_t length, bool *is_timeout) {
2693     pa_sink_input_assert_ref(i);
2694     pa_assert(is_timeout);
2695
2696     if (length == 0) {
2697         if (_empty_pop_is_started(i)) {
2698             /* calculate empty pop duration in seconds */
2699             uint32_t empty_pop_duration = _empty_pop_calc_duration(i);
2700             if (empty_pop_duration >= i->core->empty_pop_threshold) {
2701                 *is_timeout = true;
2702                 _empty_pop_reset(i);
2703                 return;
2704             }
2705             _empty_pop_print_duration(i, empty_pop_duration);
2706         } else {
2707             _empty_pop_start(i);
2708         }
2709     } else {
2710         if (_empty_pop_is_started(i))
2711             _empty_pop_reset(i);
2712     }
2713
2714     *is_timeout = false;
2715 }
2716 #endif /* TIZEN_EMPTY_POP */
2717 #ifdef __TIZEN__
2718 /* Called from the main thread. */
2719 void pa_sink_input_set_silence_to_first_peek(pa_sink_input *i, bool silence, pa_usec_t duration) {
2720
2721     pa_sink_input_assert_ref(i);
2722     pa_assert_ctl_context();
2723     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2724
2725     i->thread_info.silenced = silence;
2726     i->thread_info.silence_duration = duration;
2727
2728     return;
2729 }
2730 #endif
2731
2732 /* Called from main context */
2733 void pa_sink_input_send_event(pa_sink_input *i, const char *event, pa_proplist *data) {
2734     pa_proplist *pl = NULL;
2735     pa_sink_input_send_event_hook_data hook_data;
2736
2737     pa_sink_input_assert_ref(i);
2738     pa_assert_ctl_context();
2739     pa_assert(event);
2740
2741     if (!i->send_event)
2742         return;
2743
2744     if (!data)
2745         data = pl = pa_proplist_new();
2746
2747     hook_data.sink_input = i;
2748     hook_data.data = data;
2749     hook_data.event = event;
2750
2751     if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
2752         goto finish;
2753
2754     i->send_event(i, event, data);
2755
2756 finish:
2757     if (pl)
2758         pa_proplist_free(pl);
2759 }
2760
2761 /* Called from main context */
2762 /* Updates the sink input's resampler with whatever the current sink requires
2763  * -- useful when the underlying sink's sample spec might have changed */
2764 int pa_sink_input_update_resampler(pa_sink_input *i) {
2765     pa_resampler *new_resampler;
2766     char *memblockq_name;
2767
2768     pa_sink_input_assert_ref(i);
2769     pa_assert_ctl_context();
2770
2771     if (i->thread_info.resampler &&
2772         pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &i->sink->sample_spec) &&
2773         pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &i->sink->channel_map))
2774
2775         new_resampler = i->thread_info.resampler;
2776
2777     else if (!pa_sink_input_is_passthrough(i) &&
2778         ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
2779          !pa_sample_spec_equal(&i->sample_spec, &i->sink->sample_spec) ||
2780          !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map))) {
2781
2782         new_resampler = pa_resampler_new(i->core->mempool,
2783                                      &i->sample_spec, &i->channel_map,
2784                                      &i->sink->sample_spec, &i->sink->channel_map,
2785                                      i->core->lfe_crossover_freq,
2786                                      i->requested_resample_method,
2787                                      ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
2788                                      ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
2789                                      (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
2790                                      (i->core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
2791                                      (i->core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0));
2792
2793         if (!new_resampler) {
2794             pa_log_warn("Unsupported resampling operation.");
2795             return -PA_ERR_NOTSUPPORTED;
2796         }
2797     } else
2798         new_resampler = NULL;
2799
2800     if (new_resampler == i->thread_info.resampler)
2801         return 0;
2802
2803     if (i->thread_info.resampler)
2804         pa_resampler_free(i->thread_info.resampler);
2805
2806     i->thread_info.resampler = new_resampler;
2807
2808     pa_memblockq_free(i->thread_info.render_memblockq);
2809
2810     memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index);
2811     i->thread_info.render_memblockq = pa_memblockq_new(
2812             memblockq_name,
2813             0,
2814             MEMBLOCKQ_MAXLENGTH,
2815             0,
2816             &i->sink->sample_spec,
2817             0,
2818             1,
2819             0,
2820             &i->sink->silence);
2821     pa_xfree(memblockq_name);
2822
2823     i->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID;
2824
2825     pa_log_debug("Updated resampler for sink input %d", i->index);
2826
2827     return 0;
2828 }
2829
2830 /* Called from the IO thread. */
2831 void pa_sink_input_attach(pa_sink_input *i) {
2832     pa_assert(i);
2833     pa_assert(!i->thread_info.attached);
2834
2835     i->thread_info.attached = true;
2836
2837     if (i->attach)
2838         i->attach(i);
2839 }
2840
2841 /* Called from the IO thread. */
2842 void pa_sink_input_detach(pa_sink_input *i) {
2843     pa_assert(i);
2844
2845     if (!i->thread_info.attached)
2846         return;
2847
2848     i->thread_info.attached = false;
2849
2850     if (i->detach)
2851         i->detach(i);
2852 }
2853
2854 /* Called from the main thread. */
2855 void pa_sink_input_set_volume_direct(pa_sink_input *i, const pa_cvolume *volume) {
2856     pa_cvolume old_volume;
2857     char old_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2858     char new_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2859
2860     pa_assert(i);
2861     pa_assert(volume);
2862
2863     old_volume = i->volume;
2864
2865     if (pa_cvolume_equal(volume, &old_volume))
2866         return;
2867
2868     i->volume = *volume;
2869     pa_log_debug("The volume of sink input %u changed from %s to %s.", i->index,
2870                  pa_cvolume_snprint_verbose(old_volume_str, sizeof(old_volume_str), &old_volume, &i->channel_map, true),
2871                  pa_cvolume_snprint_verbose(new_volume_str, sizeof(new_volume_str), volume, &i->channel_map, true));
2872
2873     if (i->volume_changed)
2874         i->volume_changed(i);
2875
2876     pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2877     pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_VOLUME_CHANGED], i);
2878 }
2879
2880 /* Called from the main thread. */
2881 void pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume *ratio) {
2882     pa_cvolume old_ratio;
2883     char old_ratio_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2884     char new_ratio_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2885
2886     pa_assert(i);
2887     pa_assert(ratio);
2888
2889     old_ratio = i->reference_ratio;
2890
2891     if (pa_cvolume_equal(ratio, &old_ratio))
2892         return;
2893
2894     i->reference_ratio = *ratio;
2895
2896     if (!PA_SINK_INPUT_IS_LINKED(i->state))
2897         return;
2898
2899     pa_log_debug("Sink input %u reference ratio changed from %s to %s.", i->index,
2900                  pa_cvolume_snprint_verbose(old_ratio_str, sizeof(old_ratio_str), &old_ratio, &i->channel_map, true),
2901                  pa_cvolume_snprint_verbose(new_ratio_str, sizeof(new_ratio_str), ratio, &i->channel_map, true));
2902 }