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(PA_SINK_INPUT_IS_LINKED(i->state));
1574 pa_assert(pa_sink_input_is_volume_readable(i));
1575
1576 if (absolute || !pa_sink_flat_volume_enabled(i->sink))
1577 *volume = i->volume;
1578 else
1579 *volume = i->reference_ratio;
1580
1581 return volume;
1582 }
1583
1584 /* Called from main context */
pa_sink_input_set_mute(pa_sink_input * i,bool mute,bool save)1585 void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save) {
1586 bool old_mute;
1587
1588 pa_sink_input_assert_ref(i);
1589 pa_assert_ctl_context();
1590 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1591
1592 old_mute = i->muted;
1593
1594 if (mute == old_mute) {
1595 i->save_muted |= save;
1596 return;
1597 }
1598
1599 i->muted = mute;
1600 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));
1601
1602 i->save_muted = save;
1603
1604 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
1605
1606 /* The mute status changed, let's tell people so */
1607 if (i->mute_changed)
1608 i->mute_changed(i);
1609
1610 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1611 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MUTE_CHANGED], i);
1612 }
1613
pa_sink_input_set_property(pa_sink_input * i,const char * key,const char * value)1614 void pa_sink_input_set_property(pa_sink_input *i, const char *key, const char *value) {
1615 char *old_value = NULL;
1616 const char *new_value;
1617
1618 pa_assert(i);
1619 pa_assert(key);
1620
1621 if (pa_proplist_contains(i->proplist, key)) {
1622 old_value = pa_xstrdup(pa_proplist_gets(i->proplist, key));
1623 if (value && old_value && pa_streq(value, old_value))
1624 goto finish;
1625
1626 if (!old_value)
1627 old_value = pa_xstrdup("(data)");
1628 } else {
1629 if (!value)
1630 goto finish;
1631
1632 old_value = pa_xstrdup("(unset)");
1633 }
1634
1635 if (value) {
1636 pa_proplist_sets(i->proplist, key, value);
1637 new_value = value;
1638 } else {
1639 pa_proplist_unset(i->proplist, key);
1640 new_value = "(unset)";
1641 }
1642
1643 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1644 pa_log_debug("Sink input %u: proplist[%s]: %s -> %s", i->index, key, old_value, new_value);
1645 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1646 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1647 }
1648
1649 finish:
1650 pa_xfree(old_value);
1651 }
1652
pa_sink_input_set_property_arbitrary(pa_sink_input * i,const char * key,const uint8_t * value,size_t nbytes)1653 void pa_sink_input_set_property_arbitrary(pa_sink_input *i, const char *key, const uint8_t *value, size_t nbytes) {
1654 const uint8_t *old_value;
1655 size_t old_nbytes;
1656 const char *old_value_str;
1657 const char *new_value_str;
1658
1659 pa_assert(i);
1660 pa_assert(key);
1661
1662 if (pa_proplist_get(i->proplist, key, (const void **) &old_value, &old_nbytes) >= 0) {
1663 if (value && nbytes == old_nbytes && !memcmp(value, old_value, nbytes))
1664 return;
1665
1666 old_value_str = "(data)";
1667
1668 } else {
1669 if (!value)
1670 return;
1671
1672 old_value_str = "(unset)";
1673 }
1674
1675 if (value) {
1676 pa_proplist_set(i->proplist, key, value, nbytes);
1677 new_value_str = "(data)";
1678 } else {
1679 pa_proplist_unset(i->proplist, key);
1680 new_value_str = "(unset)";
1681 }
1682
1683 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1684 pa_log_debug("Sink input %u: proplist[%s]: %s -> %s", i->index, key, old_value_str, new_value_str);
1685 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1686 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1687 }
1688 }
1689
1690 /* Called from main thread */
pa_sink_input_update_proplist(pa_sink_input * i,pa_update_mode_t mode,pa_proplist * p)1691 void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
1692 void *state;
1693 const char *key;
1694 const uint8_t *value;
1695 size_t nbytes;
1696
1697 pa_sink_input_assert_ref(i);
1698 pa_assert(p);
1699 pa_assert_ctl_context();
1700
1701 switch (mode) {
1702 case PA_UPDATE_SET:
1703 /* Delete everything that is not in p. */
1704 for (state = NULL; (key = pa_proplist_iterate(i->proplist, &state));) {
1705 if (!pa_proplist_contains(p, key))
1706 pa_sink_input_set_property(i, key, NULL);
1707 }
1708
1709 /* Fall through. */
1710 case PA_UPDATE_REPLACE:
1711 for (state = NULL; (key = pa_proplist_iterate(p, &state));) {
1712 pa_proplist_get(p, key, (const void **) &value, &nbytes);
1713 pa_sink_input_set_property_arbitrary(i, key, value, nbytes);
1714 }
1715
1716 break;
1717 case PA_UPDATE_MERGE:
1718 for (state = NULL; (key = pa_proplist_iterate(p, &state));) {
1719 if (pa_proplist_contains(i->proplist, key))
1720 continue;
1721
1722 pa_proplist_get(p, key, (const void **) &value, &nbytes);
1723 pa_sink_input_set_property_arbitrary(i, key, value, nbytes);
1724 }
1725
1726 break;
1727 }
1728 }
1729
1730 /* Called from main context */
pa_sink_input_cork(pa_sink_input * i,bool b)1731 void pa_sink_input_cork(pa_sink_input *i, bool b) {
1732 pa_sink_input_assert_ref(i);
1733 pa_assert_ctl_context();
1734 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1735
1736 sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
1737
1738 if (b && i->thread_info.resampler) {
1739 pa_resampler_reset(i->thread_info.resampler);
1740 }
1741 }
1742
1743 /* Called from main context */
pa_sink_input_set_rate(pa_sink_input * i,uint32_t rate)1744 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
1745 pa_sink_input_assert_ref(i);
1746 pa_assert_ctl_context();
1747 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1748 pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE);
1749
1750 if (i->sample_spec.rate == rate)
1751 return 0;
1752
1753 i->sample_spec.rate = rate;
1754
1755 if (i->sink)
1756 pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
1757 else {
1758 i->thread_info.sample_spec.rate = rate;
1759 pa_resampler_set_input_rate(i->thread_info.resampler, rate);
1760 }
1761
1762 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1763 return 0;
1764 }
1765
1766 /* Called from main context */
pa_sink_input_get_resample_method(pa_sink_input * i)1767 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
1768 pa_sink_input_assert_ref(i);
1769 pa_assert_ctl_context();
1770
1771 return i->actual_resample_method;
1772 }
1773
1774 /* Called from main context */
pa_sink_input_may_move(pa_sink_input * i)1775 bool pa_sink_input_may_move(pa_sink_input *i) {
1776 pa_sink_input_assert_ref(i);
1777 pa_assert_ctl_context();
1778 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1779
1780 if (i->flags & PA_SINK_INPUT_DONT_MOVE)
1781 return false;
1782
1783 if (i->sync_next || i->sync_prev) {
1784 pa_log_warn("Moving synchronized streams not supported.");
1785 return false;
1786 }
1787
1788 return true;
1789 }
1790
find_filter_sink_input(pa_sink_input * target,pa_sink * s)1791 static bool find_filter_sink_input(pa_sink_input *target, pa_sink *s) {
1792 unsigned PA_UNUSED i = 0;
1793 while (s && s->input_to_master) {
1794 if (s->input_to_master == target)
1795 return true;
1796 s = s->input_to_master->sink;
1797 pa_assert(i++ < 100);
1798 }
1799 return false;
1800 }
1801
is_filter_sink_moving(pa_sink_input * i)1802 static bool is_filter_sink_moving(pa_sink_input *i) {
1803 pa_sink *sink = i->sink;
1804
1805 if (!sink)
1806 return false;
1807
1808 while (sink->input_to_master) {
1809 sink = sink->input_to_master->sink;
1810
1811 if (!sink)
1812 return true;
1813 }
1814
1815 return false;
1816 }
1817
1818 /* Called from main context */
pa_sink_input_may_move_to(pa_sink_input * i,pa_sink * dest)1819 bool pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
1820 pa_sink_input_assert_ref(i);
1821 pa_assert_ctl_context();
1822 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1823 pa_sink_assert_ref(dest);
1824
1825 if (dest == i->sink)
1826 return true;
1827
1828 if (dest->unlink_requested)
1829 return false;
1830
1831 if (!pa_sink_input_may_move(i))
1832 return false;
1833
1834 /* Make sure we're not creating a filter sink cycle */
1835 if (find_filter_sink_input(i, dest)) {
1836 pa_log_debug("Can't connect input to %s, as that would create a cycle.", dest->name);
1837 return false;
1838 }
1839
1840 /* If this sink input is connected to a filter sink that itself is moving,
1841 * then don't allow the move. Moving requires sending a message to the IO
1842 * thread of the old sink, and if the old sink is a filter sink that is
1843 * moving, there's no IO thread associated to the old sink. */
1844 if (is_filter_sink_moving(i)) {
1845 pa_log_debug("Can't move input from filter sink %s, because the filter sink itself is currently moving.",
1846 i->sink->name);
1847 return false;
1848 }
1849
1850 if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
1851 pa_log_warn("Failed to move sink input: too many inputs per sink.");
1852 return false;
1853 }
1854
1855 if (check_passthrough_connection(pa_sink_input_is_passthrough(i), dest) < 0)
1856 return false;
1857
1858 if (i->may_move_to)
1859 if (!i->may_move_to(i, dest))
1860 return false;
1861
1862 return true;
1863 }
1864
1865 /* Called from main context */
pa_sink_input_start_move(pa_sink_input * i)1866 int pa_sink_input_start_move(pa_sink_input *i) {
1867 pa_source_output *o, PA_UNUSED *p = NULL;
1868 struct volume_factor_entry *v;
1869 void *state = NULL;
1870 int r;
1871
1872 pa_sink_input_assert_ref(i);
1873 pa_assert_ctl_context();
1874 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1875 pa_assert(i->sink);
1876
1877 if (!pa_sink_input_may_move(i))
1878 return -PA_ERR_NOTSUPPORTED;
1879
1880 if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
1881 return r;
1882
1883 pa_log_debug("Starting to move sink input %u from '%s'", (unsigned) i->index, i->sink->name);
1884 if (i->sink) {
1885 AUDIO_INFO_LOG("[StartMove]: SinkInput[%{public}u] --xxxx--> sink[%{public}u, %{public}s]",
1886 i->index, i->sink->index, i->sink->name);
1887 }
1888
1889 /* Kill directly connected outputs */
1890 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
1891 pa_assert(o != p);
1892 pa_source_output_kill(o);
1893 p = o;
1894 }
1895 pa_assert(pa_idxset_isempty(i->direct_outputs));
1896
1897 pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
1898
1899 if (i->state == PA_SINK_INPUT_CORKED)
1900 pa_assert_se(i->sink->n_corked-- >= 1);
1901
1902 if (pa_sink_input_is_passthrough(i))
1903 pa_sink_leave_passthrough(i->sink);
1904
1905 if (pa_sink_flat_volume_enabled(i->sink))
1906 /* We might need to update the sink's volume if we are in flat
1907 * volume mode. */
1908 pa_sink_set_volume(i->sink, NULL, false, false);
1909
1910 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
1911
1912 pa_sink_update_status(i->sink);
1913
1914 PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
1915 pa_cvolume_remap(&v->volume, &i->sink->channel_map, &i->channel_map);
1916
1917 pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
1918
1919 /* Calculate how much of the latency was rewound on the old sink */
1920 i->origin_rewind_bytes = pa_sink_get_last_rewind(i->sink) / pa_frame_size(&i->sink->sample_spec);
1921 i->origin_rewind_bytes = i->origin_rewind_bytes * i->sample_spec.rate / i->sink->sample_spec.rate;
1922 i->origin_rewind_bytes *= pa_frame_size(&i->sample_spec);
1923
1924 i->sink = NULL;
1925 i->sink_requested_by_application = false;
1926
1927 pa_sink_input_unref(i);
1928
1929 return 0;
1930 }
1931
1932 /* Called from main context. If i has an origin sink that uses volume sharing,
1933 * then also the origin sink and all streams connected to it need to update
1934 * their volume - this function does all that by using recursion. */
update_volume_due_to_moving(pa_sink_input * i,pa_sink * dest)1935 static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) {
1936 pa_cvolume new_volume;
1937
1938 pa_assert(i);
1939 pa_assert(dest);
1940 pa_assert(i->sink); /* The destination sink should already be set. */
1941
1942 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1943 pa_sink *root_sink = pa_sink_get_master(i->sink);
1944 pa_sink_input *origin_sink_input;
1945 uint32_t idx;
1946
1947 if (PA_UNLIKELY(!root_sink))
1948 return;
1949
1950 if (pa_sink_flat_volume_enabled(i->sink)) {
1951 /* Ok, so the origin sink uses volume sharing, and flat volume is
1952 * enabled. The volume will have to be updated as follows:
1953 *
1954 * i->volume := i->sink->real_volume
1955 * (handled later by pa_sink_set_volume)
1956 * i->reference_ratio := i->volume / i->sink->reference_volume
1957 * (handled later by pa_sink_set_volume)
1958 * i->real_ratio stays unchanged
1959 * (streams whose origin sink uses volume sharing should
1960 * always have real_ratio of 0 dB)
1961 * i->soft_volume stays unchanged
1962 * (streams whose origin sink uses volume sharing should
1963 * always have volume_factor as soft_volume, so no change
1964 * should be needed) */
1965
1966 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
1967 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
1968
1969 /* Notifications will be sent by pa_sink_set_volume(). */
1970
1971 } else {
1972 /* Ok, so the origin sink uses volume sharing, and flat volume is
1973 * disabled. The volume will have to be updated as follows:
1974 *
1975 * i->volume := 0 dB
1976 * i->reference_ratio := 0 dB
1977 * i->real_ratio stays unchanged
1978 * (streams whose origin sink uses volume sharing should
1979 * always have real_ratio of 0 dB)
1980 * i->soft_volume stays unchanged
1981 * (streams whose origin sink uses volume sharing should
1982 * always have volume_factor as soft_volume, so no change
1983 * should be needed) */
1984
1985 pa_cvolume_reset(&new_volume, i->volume.channels);
1986 pa_sink_input_set_volume_direct(i, &new_volume);
1987 pa_sink_input_set_reference_ratio(i, &new_volume);
1988 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
1989 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
1990 }
1991
1992 /* Additionally, the origin sink volume needs updating:
1993 *
1994 * i->origin_sink->reference_volume := root_sink->reference_volume
1995 * i->origin_sink->real_volume := root_sink->real_volume
1996 * i->origin_sink->soft_volume stays unchanged
1997 * (sinks that use volume sharing should always have
1998 * soft_volume of 0 dB) */
1999
2000 new_volume = root_sink->reference_volume;
2001 pa_cvolume_remap(&new_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
2002 pa_sink_set_reference_volume_direct(i->origin_sink, &new_volume);
2003
2004 i->origin_sink->real_volume = root_sink->real_volume;
2005 pa_cvolume_remap(&i->origin_sink->real_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
2006
2007 pa_assert(pa_cvolume_is_norm(&i->origin_sink->soft_volume));
2008
2009 /* If you wonder whether i->origin_sink->set_volume() should be called
2010 * somewhere, that's not the case, because sinks that use volume
2011 * sharing shouldn't have any internal volume that set_volume() would
2012 * update. If you wonder whether the thread_info variables should be
2013 * synced, yes, they should, and it's done by the
2014 * PA_SINK_MESSAGE_FINISH_MOVE message handler. */
2015
2016 /* Recursively update origin sink inputs. */
2017 PA_IDXSET_FOREACH(origin_sink_input, i->origin_sink->inputs, idx)
2018 update_volume_due_to_moving(origin_sink_input, dest);
2019
2020 } else {
2021 if (pa_sink_flat_volume_enabled(i->sink)) {
2022 /* Ok, so this is a regular stream, and flat volume is enabled. The
2023 * volume will have to be updated as follows:
2024 *
2025 * i->volume := i->reference_ratio * i->sink->reference_volume
2026 * i->reference_ratio stays unchanged
2027 * i->real_ratio := i->volume / i->sink->real_volume
2028 * (handled later by pa_sink_set_volume)
2029 * i->soft_volume := i->real_ratio * i->volume_factor
2030 * (handled later by pa_sink_set_volume) */
2031
2032 new_volume = i->sink->reference_volume;
2033 pa_cvolume_remap(&new_volume, &i->sink->channel_map, &i->channel_map);
2034 pa_sw_cvolume_multiply(&new_volume, &new_volume, &i->reference_ratio);
2035 pa_sink_input_set_volume_direct(i, &new_volume);
2036
2037 } else {
2038 /* Ok, so this is a regular stream, and flat volume is disabled.
2039 * The volume will have to be updated as follows:
2040 *
2041 * i->volume := i->reference_ratio
2042 * i->reference_ratio stays unchanged
2043 * i->real_ratio := i->reference_ratio
2044 * i->soft_volume := i->real_ratio * i->volume_factor */
2045
2046 pa_sink_input_set_volume_direct(i, &i->reference_ratio);
2047 i->real_ratio = i->reference_ratio;
2048 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
2049 }
2050 }
2051
2052 /* If i->sink == dest, then recursion has finished, and we can finally call
2053 * pa_sink_set_volume(), which will do the rest of the updates. */
2054 if ((i->sink == dest) && pa_sink_flat_volume_enabled(i->sink))
2055 pa_sink_set_volume(i->sink, NULL, false, i->save_volume);
2056 }
2057
2058 /* Called from the main thread. */
set_preferred_sink(pa_sink_input * i,const char * sink_name)2059 static void set_preferred_sink(pa_sink_input *i, const char *sink_name) {
2060 pa_assert(i);
2061
2062 if (pa_safe_streq(i->preferred_sink, sink_name))
2063 return;
2064
2065 pa_log_debug("Sink input %u: preferred_sink: %s -> %s",
2066 i->index, i->preferred_sink ? i->preferred_sink : "(unset)", sink_name ? sink_name : "(unset)");
2067 pa_xfree(i->preferred_sink);
2068 i->preferred_sink = pa_xstrdup(sink_name);
2069
2070 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2071 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PREFERRED_SINK_CHANGED], i);
2072 }
2073
2074 /* Restores the render memblockq from the history memblockq during a move.
2075 * Called from main context while the sink input is detached. */
restore_render_memblockq(pa_sink_input * i)2076 static void restore_render_memblockq(pa_sink_input *i) {
2077 size_t block_size, to_push;
2078 size_t latency_bytes = 0;
2079 size_t bytes_on_origin_sink = 0;
2080 size_t resampler_delay_bytes = 0;
2081
2082 /* Calculate how much of the latency was left on the old sink */
2083 latency_bytes = pa_usec_to_bytes(i->thread_info.origin_sink_latency, &i->sample_spec);
2084 if (latency_bytes > i->origin_rewind_bytes)
2085 bytes_on_origin_sink = latency_bytes - i->origin_rewind_bytes;
2086
2087 /* Get resampler latency of old resampler */
2088 resampler_delay_bytes = i->thread_info.resampler_delay_frames * pa_frame_size(&i->sample_spec);
2089
2090 /* Flush the render memblockq and reset the resampler */
2091 pa_memblockq_flush_write(i->thread_info.render_memblockq, true);
2092 if (i->thread_info.resampler)
2093 pa_resampler_reset(i->thread_info.resampler);
2094
2095 /* Rewind the history queue */
2096 if (i->origin_rewind_bytes + resampler_delay_bytes > 0)
2097 pa_memblockq_rewind(i->thread_info.history_memblockq, i->origin_rewind_bytes + resampler_delay_bytes);
2098
2099 /* If something is left playing on the origin sink, add silence to the render memblockq */
2100 if (bytes_on_origin_sink > 0) {
2101 pa_memchunk chunk;;
2102
2103 chunk.length = pa_resampler_result(i->thread_info.resampler, bytes_on_origin_sink);
2104 if (chunk.length > 0) {
2105 chunk.memblock = pa_memblock_new(i->core->mempool, chunk.length);
2106 chunk.index = 0;
2107 pa_silence_memchunk(&chunk, &i->sink->sample_spec);
2108 pa_memblockq_push(i->thread_info.render_memblockq, &chunk);
2109 pa_memblock_unref(chunk.memblock);
2110 }
2111 }
2112
2113 /* Determine maximum block size */
2114 if (i->thread_info.resampler)
2115 block_size = pa_resampler_max_block_size(i->thread_info.resampler);
2116 else
2117 block_size = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sample_spec);
2118
2119 /* Now push all the data in the history queue into the render memblockq */
2120 to_push = pa_memblockq_get_length(i->thread_info.history_memblockq);
2121 while (to_push > 0) {
2122 pa_memchunk in_chunk, out_chunk;
2123 size_t push_bytes;
2124
2125 push_bytes = block_size;
2126 if (to_push < block_size)
2127 push_bytes = to_push;
2128
2129 if (pa_memblockq_peek_fixed_size(i->thread_info.history_memblockq, push_bytes, &in_chunk) < 0) {
2130 pa_log_warn("Could not restore memblockq during move");
2131 break;
2132 }
2133
2134 if (i->thread_info.resampler) {
2135 pa_resampler_run(i->thread_info.resampler, &in_chunk, &out_chunk);
2136 pa_memblock_unref(in_chunk.memblock);
2137 } else
2138 out_chunk = in_chunk;
2139
2140 if (out_chunk.length > 0) {
2141 pa_memblockq_push(i->thread_info.render_memblockq, &out_chunk);
2142 pa_memblock_unref(out_chunk.memblock);
2143 }
2144
2145 pa_memblockq_drop(i->thread_info.history_memblockq, push_bytes);
2146 to_push -= push_bytes;
2147 }
2148
2149 /* No need to rewind the history queue here, it will be re-synchronized
2150 * with the render queue during the next pa_sink_input_drop() call. */
2151
2152 /* Tell the sink input not to ask the implementer to rewrite during the
2153 * the next rewind */
2154 i->thread_info.dont_rewrite = true;
2155 }
2156
2157 /* Called from main context */
pa_sink_input_finish_move(pa_sink_input * i,pa_sink * dest,bool save)2158 int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, bool save) {
2159 struct volume_factor_entry *v;
2160 void *state = NULL;
2161
2162 pa_sink_input_assert_ref(i);
2163 pa_assert_ctl_context();
2164 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2165 pa_assert(!i->sink);
2166 pa_sink_assert_ref(dest);
2167
2168 if (!pa_sink_input_may_move_to(i, dest))
2169 return -PA_ERR_NOTSUPPORTED;
2170
2171 if (pa_sink_input_is_passthrough(i) && !pa_sink_check_format(dest, i->format)) {
2172 pa_proplist *p = pa_proplist_new();
2173 pa_log_debug("New sink doesn't support stream format, sending format-changed and killing");
2174 /* Tell the client what device we want to be on if it is going to
2175 * reconnect */
2176 pa_proplist_sets(p, "device", dest->name);
2177 pa_sink_input_send_event(i, PA_STREAM_EVENT_FORMAT_LOST, p);
2178 pa_proplist_free(p);
2179 return -PA_ERR_NOTSUPPORTED;
2180 }
2181
2182 if (!(i->flags & PA_SINK_INPUT_VARIABLE_RATE) &&
2183 !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec)) {
2184 /* try to change dest sink format and rate if possible without glitches.
2185 module-suspend-on-idle resumes destination sink with
2186 SINK_INPUT_MOVE_FINISH hook */
2187
2188 pa_log_info("Trying to change sample spec");
2189 pa_sink_reconfigure(dest, &i->sample_spec, pa_sink_input_is_passthrough(i));
2190 }
2191
2192 if (i->moving)
2193 i->moving(i, dest);
2194
2195 i->sink = dest;
2196 if (dest) {
2197 AUDIO_INFO_LOG("[FinishMove]: SinkInput[%{public}u] ----------> sink[%{public}u, %{public}s]",
2198 i->index, dest->index, dest->name);
2199 }
2200
2201 /* save == true, means user is calling the move_to() and want to
2202 save the preferred_sink */
2203 if (save) {
2204 if (dest == dest->core->default_sink)
2205 set_preferred_sink(i, NULL);
2206 else
2207 set_preferred_sink(i, dest->name);
2208 }
2209
2210 pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
2211
2212 PA_HASHMAP_FOREACH(v, i->volume_factor_sink_items, state)
2213 pa_cvolume_remap(&v->volume, &i->channel_map, &i->sink->channel_map);
2214
2215 pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
2216
2217 if (i->state == PA_SINK_INPUT_CORKED)
2218 i->sink->n_corked++;
2219
2220 pa_sink_input_update_resampler(i, false);
2221
2222 pa_sink_update_status(dest);
2223
2224 update_volume_due_to_moving(i, dest);
2225
2226 if (pa_sink_input_is_passthrough(i))
2227 pa_sink_enter_passthrough(i->sink);
2228
2229 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
2230
2231 /* Reset move variable */
2232 i->origin_rewind_bytes = 0;
2233
2234 pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
2235
2236 /* Notify everyone */
2237 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
2238 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2239
2240 return 0;
2241 }
2242
2243 /* Called from main context */
pa_sink_input_fail_move(pa_sink_input * i)2244 void pa_sink_input_fail_move(pa_sink_input *i) {
2245
2246 pa_sink_input_assert_ref(i);
2247 pa_assert_ctl_context();
2248 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2249 pa_assert(!i->sink);
2250
2251 /* Check if someone wants this sink input? */
2252 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_STOP)
2253 return;
2254
2255 /* Can we move the sink input to the default sink? */
2256 if (i->core->rescue_streams && pa_sink_input_may_move_to(i, i->core->default_sink)) {
2257 if (pa_sink_input_finish_move(i, i->core->default_sink, false) >= 0)
2258 return;
2259 }
2260
2261 AUDIO_WARNING_LOG("[FailMove]: SinkInput[%{public}u] moving FAILED.", i->index);
2262 if (i->moving)
2263 i->moving(i, NULL);
2264
2265 pa_sink_input_kill(i);
2266 }
2267
2268 /* Called from main context */
pa_sink_input_move_to(pa_sink_input * i,pa_sink * dest,bool save)2269 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, bool save) {
2270 int r;
2271
2272 pa_sink_input_assert_ref(i);
2273 pa_assert_ctl_context();
2274 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
2275 pa_assert(i->sink);
2276 pa_sink_assert_ref(dest);
2277
2278 if (dest == i->sink)
2279 return 0;
2280
2281 if (!pa_sink_input_may_move_to(i, dest))
2282 return -PA_ERR_NOTSUPPORTED;
2283
2284 pa_sink_input_ref(i);
2285
2286 if ((r = pa_sink_input_start_move(i)) < 0) {
2287 pa_sink_input_unref(i);
2288 return r;
2289 }
2290
2291 if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
2292 pa_sink_input_fail_move(i);
2293 pa_sink_input_unref(i);
2294 return r;
2295 }
2296
2297 pa_sink_input_unref(i);
2298
2299 return 0;
2300 }
2301
2302 /* 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)2303 void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
2304 bool corking, uncorking;
2305
2306 pa_sink_input_assert_ref(i);
2307
2308 if (state == i->thread_info.state)
2309 return;
2310
2311 corking = state == PA_SINK_INPUT_CORKED && i->thread_info.state == PA_SINK_INPUT_RUNNING;
2312 uncorking = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
2313
2314 if (i->state_change)
2315 i->state_change(i, state);
2316
2317 if (corking) {
2318
2319 pa_log_debug("Requesting rewind due to corking");
2320
2321 /* This will tell the implementing sink input driver to rewind
2322 * so that the unplayed already mixed data is not lost */
2323 if (i->sink)
2324 pa_sink_input_request_rewind(i, 0, true, true, false);
2325
2326 /* Set the corked state *after* requesting rewind */
2327 i->thread_info.state = state;
2328
2329 } else if (uncorking) {
2330
2331 pa_log_debug("Requesting rewind due to uncorking");
2332
2333 i->thread_info.underrun_for = (uint64_t) -1;
2334 i->thread_info.underrun_for_sink = 0;
2335 i->thread_info.playing_for = 0;
2336
2337 /* Set the uncorked state *before* requesting rewind */
2338 i->thread_info.state = state;
2339
2340 /* OK, we're being uncorked. Make sure we're not rewound when
2341 * the hw buffer is remixed and request a remix. */
2342 if (i->sink)
2343 pa_sink_input_request_rewind(i, 0, false, true, true);
2344 } else
2345 /* We may not be corking or uncorking, but we still need to set the state. */
2346 i->thread_info.state = state;
2347 }
2348
2349 /* 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)2350 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
2351 pa_sink_input *i = PA_SINK_INPUT(o);
2352 pa_sink_input_assert_ref(i);
2353
2354 switch (code) {
2355
2356 case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
2357 if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
2358 i->thread_info.soft_volume = i->soft_volume;
2359 pa_sink_input_request_rewind(i, 0, true, false, false);
2360 }
2361 return 0;
2362
2363 case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
2364 if (i->thread_info.muted != i->muted) {
2365 i->thread_info.muted = i->muted;
2366 pa_sink_input_request_rewind(i, 0, true, false, false);
2367 }
2368 return 0;
2369
2370 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
2371 pa_usec_t *r = userdata;
2372
2373 r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
2374 r[0] += pa_resampler_get_delay_usec(i->thread_info.resampler);
2375 r[1] += pa_sink_get_latency_within_thread(i->sink, false);
2376
2377 return 0;
2378 }
2379
2380 case PA_SINK_INPUT_MESSAGE_SET_RATE:
2381
2382 i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
2383 pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
2384
2385 return 0;
2386
2387 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
2388 pa_sink_input *ssync;
2389
2390 pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
2391
2392 for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
2393 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
2394
2395 for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
2396 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
2397
2398 return 0;
2399 }
2400
2401 case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
2402 pa_usec_t *usec = userdata;
2403
2404 *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
2405 return 0;
2406 }
2407
2408 case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
2409 pa_usec_t *r = userdata;
2410
2411 *r = i->thread_info.requested_sink_latency;
2412 return 0;
2413 }
2414 }
2415
2416 return -PA_ERR_NOTIMPLEMENTED;
2417 }
2418
2419 /* Called from IO context */
pa_sink_input_safe_to_remove(pa_sink_input * i)2420 bool pa_sink_input_safe_to_remove(pa_sink_input *i) {
2421 pa_sink_input_assert_ref(i);
2422 pa_sink_input_assert_io_context(i);
2423
2424 if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
2425 return pa_memblockq_is_empty(i->thread_info.render_memblockq);
2426
2427 return true;
2428 }
2429
2430 /* Called from IO context */
pa_sink_input_request_rewind(pa_sink_input * i,size_t nbytes,bool rewrite,bool flush,bool dont_rewind_render)2431 void pa_sink_input_request_rewind(
2432 pa_sink_input *i,
2433 size_t nbytes /* in our sample spec */,
2434 bool rewrite, /* rewrite what we have, or get fresh data? */
2435 bool flush, /* flush render memblockq? */
2436 bool dont_rewind_render) {
2437
2438 size_t lbq;
2439
2440 /* If 'rewrite' is true the sink is rewound as far as requested
2441 * and possible and the exact value of this is passed back the
2442 * implementor via process_rewind(). If 'flush' is also true all
2443 * already rendered data is also dropped.
2444 *
2445 * If 'rewrite' is false the sink is rewound as far as requested
2446 * and possible and the already rendered data is dropped so that
2447 * in the next iteration we read new data from the
2448 * implementor. This implies 'flush' is true. If
2449 * dont_rewind_render is true then the render memblockq is not
2450 * rewound. */
2451
2452 /* nbytes = 0 means maximum rewind request */
2453
2454 pa_sink_input_assert_ref(i);
2455 pa_sink_input_assert_io_context(i);
2456 pa_assert(rewrite || flush);
2457 pa_assert(!dont_rewind_render || !rewrite);
2458
2459 /* We don't take rewind requests while we are corked */
2460 if (i->thread_info.state == PA_SINK_INPUT_CORKED)
2461 return;
2462
2463 nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
2464
2465 #ifdef SINK_INPUT_DEBUG
2466 pa_log_debug("request rewrite %zu", nbytes);
2467 #endif
2468
2469 /* Calculate how much we can rewind locally without having to
2470 * touch the sink */
2471 if (rewrite)
2472 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
2473 else
2474 lbq = 0;
2475
2476 /* Check if rewinding for the maximum is requested, and if so, fix up */
2477 if (nbytes <= 0) {
2478
2479 /* Calculate maximum number of bytes that could be rewound in theory.
2480 * If the sink has a virtual sink attached, limit rewinding to max_rewind.
2481 *
2482 * The max_rewind value of a virtual sink depends on the rewinding capability
2483 * of its DSP code. The DSP code is rewound in the process_rewind() callback
2484 * of the sink input. Therefore rewinding must be limited to max_rewind here. */
2485 nbytes = i->sink->thread_info.max_rewind;
2486 if (!pa_sink_has_filter_attached(i->sink) && !pa_sink_is_filter(i->sink))
2487 nbytes += lbq;
2488
2489 /* Transform from sink domain */
2490 nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
2491 }
2492
2493 /* For virtual sinks there are two situations where nbytes may exceed max_rewind:
2494 * 1) If an underrun was detected.
2495 * 2) When the sink input is rewound during a move when it is attached to
2496 * the destination sink.
2497 * Moving a sink input is handled without involving the implementer, so the
2498 * implementer will only be asked to rewind more than max_rewind if an
2499 * underrun occurs. In that case, the DSP code of virtual sinks should be
2500 * reset instead of rewound. Therefore the rewind function of filters should
2501 * check if the requested rewind exceeds the maximum possible rewind of the
2502 * filter. */
2503
2504 /* Remember how much we actually want to rewrite */
2505 if (i->thread_info.rewrite_nbytes != (size_t) -1) {
2506 if (rewrite) {
2507 /* Make sure to not overwrite over underruns */
2508 if (nbytes > i->thread_info.playing_for)
2509 nbytes = (size_t) i->thread_info.playing_for;
2510
2511 i->thread_info.rewrite_nbytes = nbytes;
2512 } else
2513 i->thread_info.rewrite_nbytes = (size_t) -1;
2514 }
2515
2516 i->thread_info.rewrite_flush =
2517 i->thread_info.rewrite_flush || flush;
2518
2519 i->thread_info.dont_rewind_render =
2520 i->thread_info.dont_rewind_render ||
2521 dont_rewind_render;
2522
2523 /* nbytes is -1 if some earlier rewind request had rewrite == false. */
2524 if (nbytes != (size_t) -1) {
2525
2526 /* Transform to sink domain */
2527 nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
2528
2529 if (nbytes > lbq)
2530 pa_sink_request_rewind(i->sink, nbytes - lbq);
2531 else
2532 /* This call will make sure process_rewind() is called later */
2533 pa_sink_request_rewind(i->sink, 0);
2534 }
2535 }
2536
2537 /* Called from main context */
pa_sink_input_get_silence(pa_sink_input * i,pa_memchunk * ret)2538 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
2539 pa_sink_input_assert_ref(i);
2540 pa_assert_ctl_context();
2541 pa_assert(ret);
2542
2543 /* FIXME: Shouldn't access resampler object from main context! */
2544
2545 pa_silence_memchunk_get(
2546 &i->core->silence_cache,
2547 i->core->mempool,
2548 ret,
2549 &i->sample_spec,
2550 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
2551
2552 return ret;
2553 }
2554
2555 /* Called from main context */
pa_sink_input_send_event(pa_sink_input * i,const char * event,pa_proplist * data)2556 void pa_sink_input_send_event(pa_sink_input *i, const char *event, pa_proplist *data) {
2557 pa_proplist *pl = NULL;
2558 pa_sink_input_send_event_hook_data hook_data;
2559
2560 pa_sink_input_assert_ref(i);
2561 pa_assert_ctl_context();
2562 pa_assert(event);
2563
2564 if (!i->send_event)
2565 return;
2566
2567 if (!data)
2568 data = pl = pa_proplist_new();
2569
2570 hook_data.sink_input = i;
2571 hook_data.data = data;
2572 hook_data.event = event;
2573
2574 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
2575 goto finish;
2576
2577 i->send_event(i, event, data);
2578
2579 finish:
2580 if (pl)
2581 pa_proplist_free(pl);
2582 }
2583
2584 /* Called from main context */
2585 /* Updates the sink input's resampler with whatever the current sink requires
2586 * -- useful when the underlying sink's sample spec might have changed */
pa_sink_input_update_resampler(pa_sink_input * i,bool flush_history)2587 int pa_sink_input_update_resampler(pa_sink_input *i, bool flush_history) {
2588 pa_resampler *new_resampler;
2589 char *memblockq_name;
2590
2591 pa_sink_input_assert_ref(i);
2592 pa_assert_ctl_context();
2593
2594 if (i->thread_info.resampler &&
2595 pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &i->sink->sample_spec) &&
2596 pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &i->sink->channel_map))
2597
2598 new_resampler = i->thread_info.resampler;
2599
2600 else if (!pa_sink_input_is_passthrough(i) &&
2601 ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
2602 !pa_sample_spec_equal(&i->sample_spec, &i->sink->sample_spec) ||
2603 !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map))) {
2604
2605 new_resampler = pa_resampler_new(i->core->mempool,
2606 &i->sample_spec, &i->channel_map,
2607 &i->sink->sample_spec, &i->sink->channel_map,
2608 i->core->lfe_crossover_freq,
2609 i->requested_resample_method,
2610 ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
2611 ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
2612 (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
2613 (i->core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
2614 (i->core->remixing_produce_lfe ? PA_RESAMPLER_PRODUCE_LFE : 0) |
2615 (i->core->remixing_consume_lfe ? PA_RESAMPLER_CONSUME_LFE : 0));
2616
2617 if (!new_resampler) {
2618 pa_log_warn("Unsupported resampling operation.");
2619 return -PA_ERR_NOTSUPPORTED;
2620 }
2621 } else
2622 new_resampler = NULL;
2623
2624 if (flush_history)
2625 pa_memblockq_flush_write(i->thread_info.history_memblockq, true);
2626
2627 if (new_resampler == i->thread_info.resampler)
2628 return 0;
2629
2630 if (i->thread_info.resampler)
2631 pa_resampler_free(i->thread_info.resampler);
2632
2633 i->thread_info.resampler = new_resampler;
2634
2635 pa_memblockq_free(i->thread_info.render_memblockq);
2636
2637 memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index);
2638 i->thread_info.render_memblockq = pa_memblockq_new(
2639 memblockq_name,
2640 0,
2641 MEMBLOCKQ_MAXLENGTH,
2642 0,
2643 &i->sink->sample_spec,
2644 0,
2645 1,
2646 0,
2647 &i->sink->silence);
2648 pa_xfree(memblockq_name);
2649
2650 i->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID;
2651
2652 pa_log_debug("Updated resampler for sink input %d", i->index);
2653
2654 return 0;
2655 }
2656
2657 /* Called from the IO thread. */
pa_sink_input_attach(pa_sink_input * i)2658 void pa_sink_input_attach(pa_sink_input *i) {
2659 pa_assert(i);
2660 pa_assert(!i->thread_info.attached);
2661
2662 i->thread_info.attached = true;
2663
2664 if (i->attach)
2665 i->attach(i);
2666 }
2667
2668 /* Called from the IO thread. */
pa_sink_input_detach(pa_sink_input * i)2669 void pa_sink_input_detach(pa_sink_input *i) {
2670 pa_assert(i);
2671
2672 if (!i->thread_info.attached)
2673 return;
2674
2675 i->thread_info.attached = false;
2676
2677 if (i->detach)
2678 i->detach(i);
2679 }
2680
2681 /* Called from the main thread. */
pa_sink_input_set_volume_direct(pa_sink_input * i,const pa_cvolume * volume)2682 void pa_sink_input_set_volume_direct(pa_sink_input *i, const pa_cvolume *volume) {
2683 pa_cvolume old_volume;
2684 char old_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2685 char new_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2686
2687 pa_assert(i);
2688 pa_assert(volume);
2689
2690 old_volume = i->volume;
2691
2692 if (pa_cvolume_equal(volume, &old_volume))
2693 return;
2694
2695 i->volume = *volume;
2696 pa_log_debug("The volume of sink input %u changed from %s to %s.", i->index,
2697 pa_cvolume_snprint_verbose(old_volume_str, sizeof(old_volume_str), &old_volume, &i->channel_map, true),
2698 pa_cvolume_snprint_verbose(new_volume_str, sizeof(new_volume_str), volume, &i->channel_map, true));
2699
2700 if (i->volume_changed)
2701 i->volume_changed(i);
2702
2703 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
2704 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_VOLUME_CHANGED], i);
2705 }
2706
2707 /* Called from the main thread. */
pa_sink_input_set_reference_ratio(pa_sink_input * i,const pa_cvolume * ratio)2708 void pa_sink_input_set_reference_ratio(pa_sink_input *i, const pa_cvolume *ratio) {
2709 pa_cvolume old_ratio;
2710 char old_ratio_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2711 char new_ratio_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
2712
2713 pa_assert(i);
2714 pa_assert(ratio);
2715
2716 old_ratio = i->reference_ratio;
2717
2718 if (pa_cvolume_equal(ratio, &old_ratio))
2719 return;
2720
2721 i->reference_ratio = *ratio;
2722
2723 if (!PA_SINK_INPUT_IS_LINKED(i->state))
2724 return;
2725
2726 pa_log_debug("Sink input %u reference ratio changed from %s to %s.", i->index,
2727 pa_cvolume_snprint_verbose(old_ratio_str, sizeof(old_ratio_str), &old_ratio, &i->channel_map, true),
2728 pa_cvolume_snprint_verbose(new_ratio_str, sizeof(new_ratio_str), ratio, &i->channel_map, true));
2729 }
2730
2731 /* Called from the main thread.
2732 *
2733 * This is called when e.g. module-stream-restore wants to change the preferred
2734 * sink. As a side effect the stream is moved to the new preferred sink. Note
2735 * that things can work also in the other direction: if the user moves
2736 * a stream, as a side effect the preferred sink is changed. This could cause
2737 * an infinite loop, but it's avoided by these two measures:
2738 * - When pa_sink_input_set_preferred_sink() is called, it calls
2739 * pa_sink_input_move_to() with save=false, which avoids the recursive
2740 * pa_sink_input_set_preferred_sink() call.
2741 * - When the primary operation is to move a stream,
2742 * pa_sink_input_finish_move() calls set_preferred_sink() instead of
2743 * pa_sink_input_set_preferred_sink(). set_preferred_sink() doesn't move
2744 * the stream as a side effect.
2745 */
pa_sink_input_set_preferred_sink(pa_sink_input * i,pa_sink * s)2746 void pa_sink_input_set_preferred_sink(pa_sink_input *i, pa_sink *s) {
2747 pa_assert(i);
2748
2749 if (s) {
2750 set_preferred_sink(i, s->name);
2751 pa_sink_input_move_to(i, s, false);
2752 } else {
2753 set_preferred_sink(i, NULL);
2754 pa_sink_input_move_to(i, i->core->default_sink, false);
2755 }
2756 }
2757
pa_sink_input_handle_ohos_underrun(pa_sink_input * i)2758 void pa_sink_input_handle_ohos_underrun(pa_sink_input *i) {
2759 if (i->process_underrun_ohos && (pa_atomic_load(&i->isFirstReaded) == 1)) {
2760 i->process_underrun_ohos(i);
2761 }
2762 }
2763