• 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     if (i->sink) {
1886         AUDIO_INFO_LOG("[StartMove]: SinkInput[%{public}u] --xxxx--> sink[%{public}u, %{public}s]",
1887             i->index, i->sink->index, i->sink->name);
1888     }
1889 
1890     /* Kill directly connected outputs */
1891     while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
1892         pa_assert(o != p);
1893         pa_source_output_kill(o);
1894         p = o;
1895     }
1896     pa_assert(pa_idxset_isempty(i->direct_outputs));
1897 
1898     pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
1899 
1900     if (i->state == PA_SINK_INPUT_CORKED)
1901         pa_assert_se(i->sink->n_corked-- >= 1);
1902 
1903     if (pa_sink_input_is_passthrough(i))
1904         pa_sink_leave_passthrough(i->sink);
1905 
1906     if (pa_sink_flat_volume_enabled(i->sink))
1907         /* We might need to update the sink's volume if we are in flat
1908          * volume mode. */
1909         pa_sink_set_volume(i->sink, NULL, false, false);
1910 
1911     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
1912 
1913     pa_sink_update_status(i->sink);
1914 
1915     PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
1916         pa_cvolume_remap(&v->volume, &i->sink->channel_map, &i->channel_map);
1917 
1918     pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
1919 
1920     /* Calculate how much of the latency was rewound on the old sink */
1921     i->origin_rewind_bytes = pa_sink_get_last_rewind(i->sink) / pa_frame_size(&i->sink->sample_spec);
1922     i->origin_rewind_bytes = i->origin_rewind_bytes * i->sample_spec.rate / i->sink->sample_spec.rate;
1923     i->origin_rewind_bytes *= pa_frame_size(&i->sample_spec);
1924 
1925     i->sink = NULL;
1926     i->sink_requested_by_application = false;
1927 
1928     pa_sink_input_unref(i);
1929 
1930     return 0;
1931 }
1932 
1933 /* Called from main context. If i has an origin sink that uses volume sharing,
1934  * then also the origin sink and all streams connected to it need to update
1935  * their volume - this function does all that by using recursion. */
update_volume_due_to_moving(pa_sink_input * i,pa_sink * dest)1936 static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) {
1937     pa_cvolume new_volume;
1938 
1939     pa_assert(i);
1940     pa_assert(dest);
1941     pa_assert(i->sink); /* The destination sink should already be set. */
1942 
1943     if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1944         pa_sink *root_sink = pa_sink_get_master(i->sink);
1945         pa_sink_input *origin_sink_input;
1946         uint32_t idx;
1947 
1948         if (PA_UNLIKELY(!root_sink))
1949             return;
1950 
1951         if (pa_sink_flat_volume_enabled(i->sink)) {
1952             /* Ok, so the origin sink uses volume sharing, and flat volume is
1953              * enabled. The volume will have to be updated as follows:
1954              *
1955              *     i->volume := i->sink->real_volume
1956              *         (handled later by pa_sink_set_volume)
1957              *     i->reference_ratio := i->volume / i->sink->reference_volume
1958              *         (handled later by pa_sink_set_volume)
1959              *     i->real_ratio stays unchanged
1960              *         (streams whose origin sink uses volume sharing should
1961              *          always have real_ratio of 0 dB)
1962              *     i->soft_volume stays unchanged
1963              *         (streams whose origin sink uses volume sharing should
1964              *          always have volume_factor as soft_volume, so no change
1965              *          should be needed) */
1966 
1967             pa_assert(pa_cvolume_is_norm(&i->real_ratio));
1968             pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
1969 
1970             /* Notifications will be sent by pa_sink_set_volume(). */
1971 
1972         } else {
1973             /* Ok, so the origin sink uses volume sharing, and flat volume is
1974              * disabled. The volume will have to be updated as follows:
1975              *
1976              *     i->volume := 0 dB
1977              *     i->reference_ratio := 0 dB
1978              *     i->real_ratio stays unchanged
1979              *         (streams whose origin sink uses volume sharing should
1980              *          always have real_ratio of 0 dB)
1981              *     i->soft_volume stays unchanged
1982              *         (streams whose origin sink uses volume sharing should
1983              *          always have volume_factor as soft_volume, so no change
1984              *          should be needed) */
1985 
1986             pa_cvolume_reset(&new_volume, i->volume.channels);
1987             pa_sink_input_set_volume_direct(i, &new_volume);
1988             pa_sink_input_set_reference_ratio(i, &new_volume);
1989             pa_assert(pa_cvolume_is_norm(&i->real_ratio));
1990             pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
1991         }
1992 
1993         /* Additionally, the origin sink volume needs updating:
1994          *
1995          *     i->origin_sink->reference_volume := root_sink->reference_volume
1996          *     i->origin_sink->real_volume := root_sink->real_volume
1997          *     i->origin_sink->soft_volume stays unchanged
1998          *         (sinks that use volume sharing should always have
1999          *          soft_volume of 0 dB) */
2000 
2001         new_volume = root_sink->reference_volume;
2002         pa_cvolume_remap(&new_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
2003         pa_sink_set_reference_volume_direct(i->origin_sink, &new_volume);
2004 
2005         i->origin_sink->real_volume = root_sink->real_volume;
2006         pa_cvolume_remap(&i->origin_sink->real_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
2007 
2008         pa_assert(pa_cvolume_is_norm(&i->origin_sink->soft_volume));
2009 
2010         /* If you wonder whether i->origin_sink->set_volume() should be called
2011          * somewhere, that's not the case, because sinks that use volume
2012          * sharing shouldn't have any internal volume that set_volume() would
2013          * update. If you wonder whether the thread_info variables should be
2014          * synced, yes, they should, and it's done by the
2015          * PA_SINK_MESSAGE_FINISH_MOVE message handler. */
2016 
2017         /* Recursively update origin sink inputs. */
2018         PA_IDXSET_FOREACH(origin_sink_input, i->origin_sink->inputs, idx)
2019             update_volume_due_to_moving(origin_sink_input, dest);
2020 
2021     } else {
2022         if (pa_sink_flat_volume_enabled(i->sink)) {
2023             /* Ok, so this is a regular stream, and flat volume is enabled. The
2024              * volume will have to be updated as follows:
2025              *
2026              *     i->volume := i->reference_ratio * i->sink->reference_volume
2027              *     i->reference_ratio stays unchanged
2028              *     i->real_ratio := i->volume / i->sink->real_volume
2029              *         (handled later by pa_sink_set_volume)
2030              *     i->soft_volume := i->real_ratio * i->volume_factor
2031              *         (handled later by pa_sink_set_volume) */
2032 
2033             new_volume = i->sink->reference_volume;
2034             pa_cvolume_remap(&new_volume, &i->sink->channel_map, &i->channel_map);
2035             pa_sw_cvolume_multiply(&new_volume, &new_volume, &i->reference_ratio);
2036             pa_sink_input_set_volume_direct(i, &new_volume);
2037 
2038         } else {
2039             /* Ok, so this is a regular stream, and flat volume is disabled.
2040              * The volume will have to be updated as follows:
2041              *
2042              *     i->volume := i->reference_ratio
2043              *     i->reference_ratio stays unchanged
2044              *     i->real_ratio := i->reference_ratio
2045              *     i->soft_volume := i->real_ratio * i->volume_factor */
2046 
2047             pa_sink_input_set_volume_direct(i, &i->reference_ratio);
2048             i->real_ratio = i->reference_ratio;
2049             pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
2050         }
2051     }
2052 
2053     /* If i->sink == dest, then recursion has finished, and we can finally call
2054      * pa_sink_set_volume(), which will do the rest of the updates. */
2055     if ((i->sink == dest) && pa_sink_flat_volume_enabled(i->sink))
2056         pa_sink_set_volume(i->sink, NULL, false, i->save_volume);
2057 }
2058 
2059 /* Called from the main thread. */
set_preferred_sink(pa_sink_input * i,const char * sink_name)2060 static void set_preferred_sink(pa_sink_input *i, const char *sink_name) {
2061     pa_assert(i);
2062 
2063     if (pa_safe_streq(i->preferred_sink, sink_name))
2064         return;
2065 
2066     pa_log_debug("Sink input %u: preferred_sink: %s -> %s",
2067                  i->index, i->preferred_sink ? i->preferred_sink : "(unset)", sink_name ? sink_name : "(unset)");
2068     pa_xfree(i->preferred_sink);
2069     i->preferred_sink = pa_xstrdup(sink_name);
2070 
2071     pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2072     pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PREFERRED_SINK_CHANGED], i);
2073 }
2074 
2075 /* Restores the render memblockq from the history memblockq during a move.
2076  * Called from main context while the sink input is detached. */
restore_render_memblockq(pa_sink_input * i)2077 static void restore_render_memblockq(pa_sink_input *i) {
2078     size_t block_size, to_push;
2079     size_t latency_bytes = 0;
2080     size_t bytes_on_origin_sink = 0;
2081     size_t resampler_delay_bytes = 0;
2082 
2083     /* Calculate how much of the latency was left on the old sink */
2084     latency_bytes = pa_usec_to_bytes(i->thread_info.origin_sink_latency, &i->sample_spec);
2085     if (latency_bytes > i->origin_rewind_bytes)
2086             bytes_on_origin_sink = latency_bytes - i->origin_rewind_bytes;
2087 
2088     /* Get resampler latency of old resampler */
2089     resampler_delay_bytes = i->thread_info.resampler_delay_frames * pa_frame_size(&i->sample_spec);
2090 
2091     /* Flush the render memblockq  and reset the resampler */
2092     pa_memblockq_flush_write(i->thread_info.render_memblockq, true);
2093     if (i->thread_info.resampler)
2094         pa_resampler_reset(i->thread_info.resampler);
2095 
2096     /* Rewind the history queue */
2097     if (i->origin_rewind_bytes + resampler_delay_bytes > 0)
2098         pa_memblockq_rewind(i->thread_info.history_memblockq, i->origin_rewind_bytes + resampler_delay_bytes);
2099 
2100     /* If something is left playing on the origin sink, add silence to the render memblockq */
2101     if (bytes_on_origin_sink > 0) {
2102         pa_memchunk chunk;;
2103 
2104         chunk.length = pa_resampler_result(i->thread_info.resampler, bytes_on_origin_sink);
2105         if (chunk.length > 0) {
2106             chunk.memblock = pa_memblock_new(i->core->mempool, chunk.length);
2107             chunk.index = 0;
2108             pa_silence_memchunk(&chunk, &i->sink->sample_spec);
2109             pa_memblockq_push(i->thread_info.render_memblockq, &chunk);
2110             pa_memblock_unref(chunk.memblock);
2111         }
2112     }
2113 
2114     /* Determine maximum block size */
2115     if (i->thread_info.resampler)
2116         block_size = pa_resampler_max_block_size(i->thread_info.resampler);
2117     else
2118         block_size = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sample_spec);
2119 
2120     /* Now push all the data in the history queue into the render memblockq */
2121     to_push = pa_memblockq_get_length(i->thread_info.history_memblockq);
2122     while (to_push > 0) {
2123         pa_memchunk in_chunk, out_chunk;
2124         size_t push_bytes;
2125 
2126         push_bytes = block_size;
2127         if (to_push < block_size)
2128             push_bytes = to_push;
2129 
2130         if (pa_memblockq_peek_fixed_size(i->thread_info.history_memblockq, push_bytes, &in_chunk) < 0) {
2131             pa_log_warn("Could not restore memblockq during move");
2132             break;
2133         }
2134 
2135         if (i->thread_info.resampler) {
2136             pa_resampler_run(i->thread_info.resampler, &in_chunk, &out_chunk);
2137             pa_memblock_unref(in_chunk.memblock);
2138         } else
2139             out_chunk = in_chunk;
2140 
2141         if (out_chunk.length > 0) {
2142             pa_memblockq_push(i->thread_info.render_memblockq, &out_chunk);
2143             pa_memblock_unref(out_chunk.memblock);
2144         }
2145 
2146         pa_memblockq_drop(i->thread_info.history_memblockq, push_bytes);
2147         to_push -= push_bytes;
2148     }
2149 
2150     /* No need to rewind the history queue here, it will be re-synchronized
2151      * with the render queue during the next pa_sink_input_drop() call. */
2152 
2153     /* Tell the sink input not to ask the implementer to rewrite during the
2154      * the next rewind */
2155     i->thread_info.dont_rewrite = true;
2156 }
2157 
2158 /* Called from main context */
pa_sink_input_finish_move(pa_sink_input * i,pa_sink * dest,bool save)2159 int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, bool save) {
2160     struct volume_factor_entry *v;
2161     void *state = NULL;
2162 
2163     pa_sink_input_assert_ref(i);
2164     pa_assert_ctl_context();
2165     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2166     pa_assert(!i->sink);
2167     pa_sink_assert_ref(dest);
2168 
2169     if (!pa_sink_input_may_move_to(i, dest))
2170         return -PA_ERR_NOTSUPPORTED;
2171 
2172     if (pa_sink_input_is_passthrough(i) && !pa_sink_check_format(dest, i->format)) {
2173         pa_proplist *p = pa_proplist_new();
2174         pa_log_debug("New sink doesn't support stream format, sending format-changed and killing");
2175         /* Tell the client what device we want to be on if it is going to
2176          * reconnect */
2177         pa_proplist_sets(p, "device", dest->name);
2178         pa_sink_input_send_event(i, PA_STREAM_EVENT_FORMAT_LOST, p);
2179         pa_proplist_free(p);
2180         return -PA_ERR_NOTSUPPORTED;
2181     }
2182 
2183     if (!(i->flags & PA_SINK_INPUT_VARIABLE_RATE) &&
2184         !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec)) {
2185         /* try to change dest sink format and rate if possible without glitches.
2186            module-suspend-on-idle resumes destination sink with
2187            SINK_INPUT_MOVE_FINISH hook */
2188 
2189         pa_log_info("Trying to change sample spec");
2190         pa_sink_reconfigure(dest, &i->sample_spec, pa_sink_input_is_passthrough(i));
2191     }
2192 
2193     if (i->moving)
2194         i->moving(i, dest);
2195 
2196     i->sink = dest;
2197     if (dest) {
2198         AUDIO_INFO_LOG("[FinishMove]: SinkInput[%{public}u] ----------> sink[%{public}u, %{public}s]",
2199             i->index, dest->index, dest->name);
2200     }
2201 
2202     /* save == true, means user is calling the move_to() and want to
2203        save the preferred_sink */
2204     if (save) {
2205         if (dest == dest->core->default_sink)
2206             set_preferred_sink(i, NULL);
2207         else
2208             set_preferred_sink(i, dest->name);
2209     }
2210 
2211     pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
2212 
2213     PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
2214         pa_cvolume_remap(&v->volume, &i->channel_map, &i->sink->channel_map);
2215 
2216     pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
2217 
2218     if (i->state == PA_SINK_INPUT_CORKED)
2219         i->sink->n_corked++;
2220 
2221     pa_sink_input_update_resampler(i, false);
2222 
2223     // restore_render_memblockq(i); // restore is needless for moving between sinks
2224 
2225     pa_sink_update_status(dest);
2226 
2227     update_volume_due_to_moving(i, dest);
2228 
2229     if (pa_sink_input_is_passthrough(i))
2230         pa_sink_enter_passthrough(i->sink);
2231 
2232     pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
2233 
2234     /* Reset move variable */
2235     i->origin_rewind_bytes = 0;
2236 
2237     pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
2238 
2239     /* Notify everyone */
2240     pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
2241     pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2242 
2243     return 0;
2244 }
2245 
2246 /* Called from main context */
pa_sink_input_fail_move(pa_sink_input * i)2247 void pa_sink_input_fail_move(pa_sink_input *i) {
2248 
2249     pa_sink_input_assert_ref(i);
2250     pa_assert_ctl_context();
2251     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2252     pa_assert(!i->sink);
2253 
2254     /* Check if someone wants this sink input? */
2255     if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_STOP)
2256         return;
2257 
2258     /* Can we move the sink input to the default sink? */
2259     if (i->core->rescue_streams && pa_sink_input_may_move_to(i, i->core->default_sink)) {
2260         if (pa_sink_input_finish_move(i, i->core->default_sink, false) >= 0)
2261             return;
2262     }
2263 
2264     AUDIO_WARNING_LOG("[FailMove]: SinkInput[%{public}u] moving FAILED.", i->index);
2265     if (i->moving)
2266         i->moving(i, NULL);
2267 
2268     pa_sink_input_kill(i);
2269 }
2270 
2271 /* Called from main context */
pa_sink_input_move_to(pa_sink_input * i,pa_sink * dest,bool save)2272 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, bool save) {
2273     int r;
2274 
2275     pa_sink_input_assert_ref(i);
2276     pa_assert_ctl_context();
2277     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2278     pa_assert(i->sink);
2279     pa_sink_assert_ref(dest);
2280 
2281     if (dest == i->sink)
2282         return 0;
2283 
2284     if (!pa_sink_input_may_move_to(i, dest))
2285         return -PA_ERR_NOTSUPPORTED;
2286 
2287     pa_sink_input_ref(i);
2288 
2289     if ((r = pa_sink_input_start_move(i)) < 0) {
2290         pa_sink_input_unref(i);
2291         return r;
2292     }
2293 
2294     if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
2295         pa_sink_input_fail_move(i);
2296         pa_sink_input_unref(i);
2297         return r;
2298     }
2299 
2300     pa_sink_input_unref(i);
2301 
2302     return 0;
2303 }
2304 
2305 /* 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)2306 void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
2307     bool corking, uncorking;
2308 
2309     pa_sink_input_assert_ref(i);
2310 
2311     if (state == i->thread_info.state)
2312         return;
2313 
2314     corking = state == PA_SINK_INPUT_CORKED && i->thread_info.state == PA_SINK_INPUT_RUNNING;
2315     uncorking = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
2316 
2317     if (i->state_change)
2318         i->state_change(i, state);
2319 
2320     if (corking) {
2321 
2322         pa_log_debug("Requesting rewind due to corking");
2323 
2324         /* This will tell the implementing sink input driver to rewind
2325          * so that the unplayed already mixed data is not lost */
2326         if (i->sink)
2327             pa_sink_input_request_rewind(i, 0, true, true, false);
2328 
2329         /* Set the corked state *after* requesting rewind */
2330         i->thread_info.state = state;
2331 
2332     } else if (uncorking) {
2333 
2334         pa_log_debug("Requesting rewind due to uncorking");
2335 
2336         i->thread_info.underrun_for = (uint64_t) -1;
2337         i->thread_info.underrun_for_sink = 0;
2338         i->thread_info.playing_for = 0;
2339 
2340         /* Set the uncorked state *before* requesting rewind */
2341         i->thread_info.state = state;
2342 
2343         /* OK, we're being uncorked. Make sure we're not rewound when
2344          * the hw buffer is remixed and request a remix. */
2345         if (i->sink)
2346             pa_sink_input_request_rewind(i, 0, false, true, true);
2347     } else
2348         /* We may not be corking or uncorking, but we still need to set the state. */
2349         i->thread_info.state = state;
2350 }
2351 
2352 /* 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)2353 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
2354     pa_sink_input *i = PA_SINK_INPUT(o);
2355     pa_sink_input_assert_ref(i);
2356 
2357     switch (code) {
2358 
2359         case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
2360             if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
2361                 i->thread_info.soft_volume = i->soft_volume;
2362                 pa_sink_input_request_rewind(i, 0, true, false, false);
2363             }
2364             return 0;
2365 
2366         case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
2367             if (i->thread_info.muted != i->muted) {
2368                 i->thread_info.muted = i->muted;
2369                 pa_sink_input_request_rewind(i, 0, true, false, false);
2370             }
2371             return 0;
2372 
2373         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
2374             pa_usec_t *r = userdata;
2375 
2376             r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
2377             r[0] += pa_resampler_get_delay_usec(i->thread_info.resampler);
2378             r[1] += pa_sink_get_latency_within_thread(i->sink, false);
2379 
2380             return 0;
2381         }
2382 
2383         case PA_SINK_INPUT_MESSAGE_SET_RATE:
2384 
2385             i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
2386             pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
2387 
2388             return 0;
2389 
2390         case PA_SINK_INPUT_MESSAGE_SET_STATE: {
2391             pa_sink_input *ssync;
2392 
2393             pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
2394 
2395             for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
2396                 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
2397 
2398             for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
2399                 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
2400 
2401             return 0;
2402         }
2403 
2404         case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
2405             pa_usec_t *usec = userdata;
2406 
2407             *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
2408             return 0;
2409         }
2410 
2411         case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
2412             pa_usec_t *r = userdata;
2413 
2414             *r = i->thread_info.requested_sink_latency;
2415             return 0;
2416         }
2417     }
2418 
2419     return -PA_ERR_NOTIMPLEMENTED;
2420 }
2421 
2422 /* Called from IO context */
pa_sink_input_safe_to_remove(pa_sink_input * i)2423 bool pa_sink_input_safe_to_remove(pa_sink_input *i) {
2424     pa_sink_input_assert_ref(i);
2425     pa_sink_input_assert_io_context(i);
2426 
2427     if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
2428         return pa_memblockq_is_empty(i->thread_info.render_memblockq);
2429 
2430     return true;
2431 }
2432 
2433 /* Called from IO context */
pa_sink_input_request_rewind(pa_sink_input * i,size_t nbytes,bool rewrite,bool flush,bool dont_rewind_render)2434 void pa_sink_input_request_rewind(
2435         pa_sink_input *i,
2436         size_t nbytes  /* in our sample spec */,
2437         bool rewrite,  /* rewrite what we have, or get fresh data? */
2438         bool flush,    /* flush render memblockq? */
2439         bool dont_rewind_render) {
2440 
2441     size_t lbq;
2442 
2443     /* If 'rewrite' is true the sink is rewound as far as requested
2444      * and possible and the exact value of this is passed back the
2445      * implementor via process_rewind(). If 'flush' is also true all
2446      * already rendered data is also dropped.
2447      *
2448      * If 'rewrite' is false the sink is rewound as far as requested
2449      * and possible and the already rendered data is dropped so that
2450      * in the next iteration we read new data from the
2451      * implementor. This implies 'flush' is true.  If
2452      * dont_rewind_render is true then the render memblockq is not
2453      * rewound. */
2454 
2455     /* nbytes = 0 means maximum rewind request */
2456 
2457     pa_sink_input_assert_ref(i);
2458     pa_sink_input_assert_io_context(i);
2459     pa_assert(rewrite || flush);
2460     pa_assert(!dont_rewind_render || !rewrite);
2461 
2462     /* We don't take rewind requests while we are corked */
2463     if (i->thread_info.state == PA_SINK_INPUT_CORKED)
2464         return;
2465 
2466     nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
2467 
2468 #ifdef SINK_INPUT_DEBUG
2469     pa_log_debug("request rewrite %zu", nbytes);
2470 #endif
2471 
2472     /* Calculate how much we can rewind locally without having to
2473      * touch the sink */
2474     if (rewrite)
2475         lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
2476     else
2477         lbq = 0;
2478 
2479     /* Check if rewinding for the maximum is requested, and if so, fix up */
2480     if (nbytes <= 0) {
2481 
2482         /* Calculate maximum number of bytes that could be rewound in theory.
2483          * If the sink has a virtual sink attached, limit rewinding to max_rewind.
2484          *
2485          * The max_rewind value of a virtual sink depends on the rewinding capability
2486          * of its DSP code. The DSP code is rewound in the process_rewind() callback
2487          * of the sink input. Therefore rewinding must be limited to max_rewind here. */
2488         nbytes = i->sink->thread_info.max_rewind;
2489         if (!pa_sink_has_filter_attached(i->sink) && !pa_sink_is_filter(i->sink))
2490             nbytes += lbq;
2491 
2492         /* Transform from sink domain */
2493         nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
2494     }
2495 
2496     /* For virtual sinks there are two situations where nbytes may exceed max_rewind:
2497      * 1) If an underrun was detected.
2498      * 2) When the sink input is rewound during a move when it is attached to
2499      *    the destination sink.
2500      * Moving a sink input is handled without involving the implementer, so the
2501      * implementer will only be asked to rewind more than max_rewind if an
2502      * underrun occurs. In that case, the DSP code of virtual sinks should be
2503      * reset instead of rewound. Therefore the rewind function of filters should
2504      * check if the requested rewind exceeds the maximum possible rewind of the
2505      * filter. */
2506 
2507     /* Remember how much we actually want to rewrite */
2508     if (i->thread_info.rewrite_nbytes != (size_t) -1) {
2509         if (rewrite) {
2510             /* Make sure to not overwrite over underruns */
2511             if (nbytes > i->thread_info.playing_for)
2512                 nbytes = (size_t) i->thread_info.playing_for;
2513 
2514             i->thread_info.rewrite_nbytes = nbytes;
2515         } else
2516             i->thread_info.rewrite_nbytes = (size_t) -1;
2517     }
2518 
2519     i->thread_info.rewrite_flush =
2520         i->thread_info.rewrite_flush || flush;
2521 
2522     i->thread_info.dont_rewind_render =
2523         i->thread_info.dont_rewind_render ||
2524         dont_rewind_render;
2525 
2526     /* nbytes is -1 if some earlier rewind request had rewrite == false. */
2527     if (nbytes != (size_t) -1) {
2528 
2529         /* Transform to sink domain */
2530         nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
2531 
2532         if (nbytes > lbq)
2533             pa_sink_request_rewind(i->sink, nbytes - lbq);
2534         else
2535             /* This call will make sure process_rewind() is called later */
2536             pa_sink_request_rewind(i->sink, 0);
2537     }
2538 }
2539 
2540 /* Called from main context */
pa_sink_input_get_silence(pa_sink_input * i,pa_memchunk * ret)2541 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
2542     pa_sink_input_assert_ref(i);
2543     pa_assert_ctl_context();
2544     pa_assert(ret);
2545 
2546     /* FIXME: Shouldn't access resampler object from main context! */
2547 
2548     pa_silence_memchunk_get(
2549                 &i->core->silence_cache,
2550                 i->core->mempool,
2551                 ret,
2552                 &i->sample_spec,
2553                 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
2554 
2555     return ret;
2556 }
2557 
2558 /* Called from main context */
pa_sink_input_send_event(pa_sink_input * i,const char * event,pa_proplist * data)2559 void pa_sink_input_send_event(pa_sink_input *i, const char *event, pa_proplist *data) {
2560     pa_proplist *pl = NULL;
2561     pa_sink_input_send_event_hook_data hook_data;
2562 
2563     pa_sink_input_assert_ref(i);
2564     // pa_assert_ctl_context();
2565     pa_assert(event);
2566 
2567     if (!i->send_event)
2568         return;
2569 
2570     if (!data)
2571         data = pl = pa_proplist_new();
2572 
2573     hook_data.sink_input = i;
2574     hook_data.data = data;
2575     hook_data.event = event;
2576 
2577     if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
2578         goto finish;
2579 
2580     i->send_event(i, event, data);
2581 
2582 finish:
2583     if (pl)
2584         pa_proplist_free(pl);
2585 }
2586 
2587 /* Called from main context */
2588 /* Updates the sink input's resampler with whatever the current sink requires
2589  * -- useful when the underlying sink's sample spec might have changed */
pa_sink_input_update_resampler(pa_sink_input * i,bool flush_history)2590 int pa_sink_input_update_resampler(pa_sink_input *i, bool flush_history) {
2591     pa_resampler *new_resampler;
2592     char *memblockq_name;
2593 
2594     pa_sink_input_assert_ref(i);
2595     pa_assert_ctl_context();
2596 
2597     if (i->thread_info.resampler &&
2598         pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &i->sink->sample_spec) &&
2599         pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &i->sink->channel_map))
2600 
2601         new_resampler = i->thread_info.resampler;
2602 
2603     else if (!pa_sink_input_is_passthrough(i) &&
2604         ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
2605          !pa_sample_spec_equal(&i->sample_spec, &i->sink->sample_spec) ||
2606          !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map))) {
2607 
2608         new_resampler = pa_resampler_new(i->core->mempool,
2609                                      &i->sample_spec, &i->channel_map,
2610                                      &i->sink->sample_spec, &i->sink->channel_map,
2611                                      i->core->lfe_crossover_freq,
2612                                      i->requested_resample_method,
2613                                      ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
2614                                      ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
2615                                      (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
2616                                      (i->core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
2617                                      (i->core->remixing_produce_lfe ? PA_RESAMPLER_PRODUCE_LFE : 0) |
2618                                      (i->core->remixing_consume_lfe ? PA_RESAMPLER_CONSUME_LFE : 0));
2619 
2620         if (!new_resampler) {
2621             pa_log_warn("Unsupported resampling operation.");
2622             return -PA_ERR_NOTSUPPORTED;
2623         }
2624     } else
2625         new_resampler = NULL;
2626 
2627     if (flush_history)
2628         pa_memblockq_flush_write(i->thread_info.history_memblockq, true);
2629 
2630     if (new_resampler == i->thread_info.resampler)
2631         return 0;
2632 
2633     if (i->thread_info.resampler)
2634         pa_resampler_free(i->thread_info.resampler);
2635 
2636     i->thread_info.resampler = new_resampler;
2637 
2638     pa_memblockq_free(i->thread_info.render_memblockq);
2639 
2640     memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index);
2641     i->thread_info.render_memblockq = pa_memblockq_new(
2642             memblockq_name,
2643             0,
2644             MEMBLOCKQ_MAXLENGTH,
2645             0,
2646             &i->sink->sample_spec,
2647             0,
2648             1,
2649             0,
2650             &i->sink->silence);
2651     pa_xfree(memblockq_name);
2652 
2653     i->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID;
2654 
2655     pa_log_debug("Updated resampler for sink input %d", i->index);
2656 
2657     return 0;
2658 }
2659 
2660 /* Called from the IO thread. */
pa_sink_input_attach(pa_sink_input * i)2661 void pa_sink_input_attach(pa_sink_input *i) {
2662     pa_assert(i);
2663     pa_assert(!i->thread_info.attached);
2664 
2665     i->thread_info.attached = true;
2666 
2667     if (i->attach)
2668         i->attach(i);
2669 }
2670 
2671 /* Called from the IO thread. */
pa_sink_input_detach(pa_sink_input * i)2672 void pa_sink_input_detach(pa_sink_input *i) {
2673     pa_assert(i);
2674 
2675     if (!i->thread_info.attached)
2676         return;
2677 
2678     i->thread_info.attached = false;
2679 
2680     if (i->detach)
2681         i->detach(i);
2682 }
2683 
2684 /* Called from the main thread. */
pa_sink_input_set_volume_direct(pa_sink_input * i,const pa_cvolume * volume)2685 void pa_sink_input_set_volume_direct(pa_sink_input *i, const pa_cvolume *volume) {
2686     pa_cvolume old_volume;
2687     char old_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2688     char new_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2689 
2690     pa_assert(i);
2691     pa_assert(volume);
2692 
2693     old_volume = i->volume;
2694 
2695     if (pa_cvolume_equal(volume, &old_volume))
2696         return;
2697 
2698     i->volume = *volume;
2699     pa_log_debug("The volume of sink input %u changed from %s to %s.", i->index,
2700                  pa_cvolume_snprint_verbose(old_volume_str, sizeof(old_volume_str), &old_volume, &i->channel_map, true),
2701                  pa_cvolume_snprint_verbose(new_volume_str, sizeof(new_volume_str), volume, &i->channel_map, true));
2702 
2703     if (i->volume_changed)
2704         i->volume_changed(i);
2705 
2706     pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2707     pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_VOLUME_CHANGED], i);
2708 }
2709 
2710 /* Called from the main thread. */
pa_sink_input_set_reference_ratio(pa_sink_input * i,const pa_cvolume * ratio)2711 void pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume *ratio) {
2712     pa_cvolume old_ratio;
2713     char old_ratio_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2714     char new_ratio_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2715 
2716     pa_assert(i);
2717     pa_assert(ratio);
2718 
2719     old_ratio = i->reference_ratio;
2720 
2721     if (pa_cvolume_equal(ratio, &old_ratio))
2722         return;
2723 
2724     i->reference_ratio = *ratio;
2725 
2726     if (!PA_SINK_INPUT_IS_LINKED(i->state))
2727         return;
2728 
2729     pa_log_debug("Sink input %u reference ratio changed from %s to %s.", i->index,
2730                  pa_cvolume_snprint_verbose(old_ratio_str, sizeof(old_ratio_str), &old_ratio, &i->channel_map, true),
2731                  pa_cvolume_snprint_verbose(new_ratio_str, sizeof(new_ratio_str), ratio, &i->channel_map, true));
2732 }
2733 
2734 /* Called from the main thread.
2735  *
2736  * This is called when e.g. module-stream-restore wants to change the preferred
2737  * sink. As a side effect the stream is moved to the new preferred sink. Note
2738  * that things can work also in the other direction: if the user moves
2739  * a stream, as a side effect the preferred sink is changed. This could cause
2740  * an infinite loop, but it's avoided by these two measures:
2741  *   - When pa_sink_input_set_preferred_sink() is called, it calls
2742  *     pa_sink_input_move_to() with save=false, which avoids the recursive
2743  *     pa_sink_input_set_preferred_sink() call.
2744  *   - When the primary operation is to move a stream,
2745  *     pa_sink_input_finish_move() calls set_preferred_sink() instead of
2746  *     pa_sink_input_set_preferred_sink(). set_preferred_sink() doesn't move
2747  *     the stream as a side effect.
2748  */
pa_sink_input_set_preferred_sink(pa_sink_input * i,pa_sink * s)2749 void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s) {
2750     pa_assert(i);
2751 
2752     if (s) {
2753         set_preferred_sink(i, s->name);
2754         pa_sink_input_move_to(i, s, false);
2755     } else {
2756         set_preferred_sink(i, NULL);
2757         pa_sink_input_move_to(i, i->core->default_sink, false);
2758     }
2759 }
2760 
pa_sink_input_handle_ohos_underrun(pa_sink_input * i)2761 void pa_sink_input_handle_ohos_underrun(pa_sink_input *i) {
2762     if (i->process_underrun_ohos && (pa_atomic_load(&i->isFirstReaded) == 1)) {
2763         i->process_underrun_ohos(i);
2764     }
2765 }
2766