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