]> code.delx.au - pulseaudio/blob - src/pulsecore/sink-input.c
Revert "Add volume ramping feature - sink-input modification"
[pulseaudio] / src / pulsecore / sink-input.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <pulse/utf8.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/util.h>
34
35 #include <pulsecore/sample-util.h>
36 #include <pulsecore/core-subscribe.h>
37 #include <pulsecore/log.h>
38 #include <pulsecore/play-memblockq.h>
39 #include <pulsecore/namereg.h>
40 #include <pulsecore/core-util.h>
41
42 #include "sink-input.h"
43
44 #define MEMBLOCKQ_MAXLENGTH (32*1024*1024)
45 #define CONVERT_BUFFER_LENGTH (PA_PAGE_SIZE)
46
47 PA_DEFINE_PUBLIC_CLASS(pa_sink_input, pa_msgobject);
48
49 static void sink_input_free(pa_object *o);
50 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v);
51
52 static int check_passthrough_connection(pa_sink_input_flags_t flags, pa_sink *dest) {
53
54 if (dest->flags & PA_SINK_PASSTHROUGH) {
55
56 if (pa_idxset_size(dest->inputs) > 0) {
57
58 pa_sink_input *alt_i;
59 uint32_t idx;
60
61 alt_i = pa_idxset_first(dest->inputs, &idx);
62
63 /* only need to check the first input is not PASSTHROUGH */
64 if (alt_i->flags & PA_SINK_INPUT_PASSTHROUGH) {
65 pa_log_warn("Sink is already connected to PASSTHROUGH input");
66 return -PA_ERR_BUSY;
67 }
68
69 /* Current inputs are PCM, check new input is not PASSTHROUGH */
70 if (flags & PA_SINK_INPUT_PASSTHROUGH) {
71 pa_log_warn("Sink is already connected, cannot accept new PASSTHROUGH INPUT");
72 return -PA_ERR_BUSY;
73 }
74 }
75
76 } else {
77 if (flags & PA_SINK_INPUT_PASSTHROUGH) {
78 pa_log_warn("Cannot connect PASSTHROUGH sink input to sink without PASSTHROUGH capabilities");
79 return -PA_ERR_INVALID;
80 }
81 }
82 return PA_OK;
83 }
84
85 pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) {
86 pa_assert(data);
87
88 pa_zero(*data);
89 data->resample_method = PA_RESAMPLER_INVALID;
90 data->proplist = pa_proplist_new();
91
92 return data;
93 }
94
95 void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec) {
96 pa_assert(data);
97
98 if ((data->sample_spec_is_set = !!spec))
99 data->sample_spec = *spec;
100 }
101
102 void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map) {
103 pa_assert(data);
104
105 if ((data->channel_map_is_set = !!map))
106 data->channel_map = *map;
107 }
108
109 pa_bool_t pa_sink_input_new_data_is_volume_writable(pa_sink_input_new_data *data) {
110 pa_assert(data);
111
112 if (data->flags & PA_SINK_INPUT_PASSTHROUGH)
113 return FALSE;
114
115 if (data->origin_sink && (data->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
116 return FALSE;
117
118 return TRUE;
119 }
120
121 void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) {
122 pa_assert(data);
123 pa_assert(pa_sink_input_new_data_is_volume_writable(data));
124
125 if ((data->volume_is_set = !!volume))
126 data->volume = *volume;
127 }
128
129 void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
130 pa_assert(data);
131 pa_assert(volume_factor);
132
133 if (data->volume_factor_is_set)
134 pa_sw_cvolume_multiply(&data->volume_factor, &data->volume_factor, volume_factor);
135 else {
136 data->volume_factor_is_set = TRUE;
137 data->volume_factor = *volume_factor;
138 }
139 }
140
141 void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
142 pa_assert(data);
143 pa_assert(volume_factor);
144
145 if (data->volume_factor_sink_is_set)
146 pa_sw_cvolume_multiply(&data->volume_factor_sink, &data->volume_factor_sink, volume_factor);
147 else {
148 data->volume_factor_sink_is_set = TRUE;
149 data->volume_factor_sink = *volume_factor;
150 }
151 }
152
153 void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
154 pa_assert(data);
155
156 data->muted_is_set = TRUE;
157 data->muted = !!mute;
158 }
159
160 void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
161 pa_assert(data);
162
163 pa_proplist_free(data->proplist);
164 }
165
166 /* Called from main context */
167 static void reset_callbacks(pa_sink_input *i) {
168 pa_assert(i);
169
170 i->pop = NULL;
171 i->process_rewind = NULL;
172 i->update_max_rewind = NULL;
173 i->update_max_request = NULL;
174 i->update_sink_requested_latency = NULL;
175 i->update_sink_latency_range = NULL;
176 i->update_sink_fixed_latency = NULL;
177 i->attach = NULL;
178 i->detach = NULL;
179 i->suspend = NULL;
180 i->suspend_within_thread = NULL;
181 i->moving = NULL;
182 i->kill = NULL;
183 i->get_latency = NULL;
184 i->state_change = NULL;
185 i->may_move_to = NULL;
186 i->send_event = NULL;
187 i->volume_changed = NULL;
188 i->mute_changed = NULL;
189 }
190
191 /* Called from main context */
192 int pa_sink_input_new(
193 pa_sink_input **_i,
194 pa_core *core,
195 pa_sink_input_new_data *data) {
196
197 pa_sink_input *i;
198 pa_resampler *resampler = NULL;
199 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
200 pa_channel_map original_cm;
201 int r;
202 char *pt;
203
204 pa_assert(_i);
205 pa_assert(core);
206 pa_assert(data);
207 pa_assert_ctl_context();
208
209 if (data->client)
210 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
211
212 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0)
213 return r;
214
215 pa_assert(!data->volume_is_set || pa_sink_input_new_data_is_volume_writable(data));
216 pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
217
218 if (!data->sink) {
219 data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK);
220 data->save_sink = FALSE;
221 }
222
223 pa_return_val_if_fail(data->sink, -PA_ERR_NOENTITY);
224 pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)), -PA_ERR_BADSTATE);
225 pa_return_val_if_fail(!data->sync_base || (data->sync_base->sink == data->sink && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED), -PA_ERR_INVALID);
226
227 r = check_passthrough_connection(data->flags, data->sink);
228 pa_return_val_if_fail(r == PA_OK, r);
229
230 if (!data->sample_spec_is_set)
231 data->sample_spec = data->sink->sample_spec;
232
233 pa_return_val_if_fail(pa_sample_spec_valid(&data->sample_spec), -PA_ERR_INVALID);
234
235 if (!data->channel_map_is_set) {
236 if (pa_channel_map_compatible(&data->sink->channel_map, &data->sample_spec))
237 data->channel_map = data->sink->channel_map;
238 else
239 pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
240 }
241
242 pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
243
244 if (!data->volume_is_set) {
245 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
246 data->volume_is_absolute = FALSE;
247 data->save_volume = FALSE;
248 }
249
250 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec), -PA_ERR_INVALID);
251
252 if (!data->volume_factor_is_set)
253 pa_cvolume_reset(&data->volume_factor, data->sample_spec.channels);
254
255 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor, &data->sample_spec), -PA_ERR_INVALID);
256
257 if (!data->volume_factor_sink_is_set)
258 pa_cvolume_reset(&data->volume_factor_sink, data->sink->sample_spec.channels);
259
260 pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor_sink, &data->sink->sample_spec), -PA_ERR_INVALID);
261
262 if (!data->muted_is_set)
263 data->muted = FALSE;
264
265 if (data->flags & PA_SINK_INPUT_FIX_FORMAT)
266 data->sample_spec.format = data->sink->sample_spec.format;
267
268 if (data->flags & PA_SINK_INPUT_FIX_RATE)
269 data->sample_spec.rate = data->sink->sample_spec.rate;
270
271 original_cm = data->channel_map;
272
273 if (data->flags & PA_SINK_INPUT_FIX_CHANNELS) {
274 data->sample_spec.channels = data->sink->sample_spec.channels;
275 data->channel_map = data->sink->channel_map;
276 }
277
278 pa_assert(pa_sample_spec_valid(&data->sample_spec));
279 pa_assert(pa_channel_map_valid(&data->channel_map));
280
281 /* Due to the fixing of the sample spec the volume might not match anymore */
282 pa_cvolume_remap(&data->volume, &original_cm, &data->channel_map);
283
284 if (data->resample_method == PA_RESAMPLER_INVALID)
285 data->resample_method = core->resample_method;
286
287 pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
288
289 if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
290 return r;
291
292 if ((data->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND) &&
293 pa_sink_get_state(data->sink) == PA_SINK_SUSPENDED) {
294 pa_log_warn("Failed to create sink input: sink is suspended.");
295 return -PA_ERR_BADSTATE;
296 }
297
298 if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) {
299 pa_log_warn("Failed to create sink input: too many inputs per sink.");
300 return -PA_ERR_TOOLARGE;
301 }
302
303 if ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
304 !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) ||
305 !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) {
306
307 if (!(resampler = pa_resampler_new(
308 core->mempool,
309 &data->sample_spec, &data->channel_map,
310 &data->sink->sample_spec, &data->sink->channel_map,
311 data->resample_method,
312 ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
313 ((data->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
314 (core->disable_remixing || (data->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
315 (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
316 pa_log_warn("Unsupported resampling operation.");
317 return -PA_ERR_NOTSUPPORTED;
318 }
319 }
320
321 i = pa_msgobject_new(pa_sink_input);
322 i->parent.parent.free = sink_input_free;
323 i->parent.process_msg = pa_sink_input_process_msg;
324
325 i->core = core;
326 i->state = PA_SINK_INPUT_INIT;
327 i->flags = data->flags;
328 i->proplist = pa_proplist_copy(data->proplist);
329 i->driver = pa_xstrdup(pa_path_get_filename(data->driver));
330 i->module = data->module;
331 i->sink = data->sink;
332 i->origin_sink = data->origin_sink;
333 i->client = data->client;
334
335 i->requested_resample_method = data->resample_method;
336 i->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID;
337 i->sample_spec = data->sample_spec;
338 i->channel_map = data->channel_map;
339
340 if (!data->volume_is_absolute && pa_sink_flat_volume_enabled(i->sink)) {
341 pa_cvolume remapped;
342
343 /* When the 'absolute' bool is not set then we'll treat the volume
344 * as relative to the sink volume even in flat volume mode */
345 remapped = data->sink->reference_volume;
346 pa_cvolume_remap(&remapped, &data->sink->channel_map, &data->channel_map);
347 pa_sw_cvolume_multiply(&i->volume, &data->volume, &remapped);
348 } else
349 i->volume = data->volume;
350
351 i->volume_factor = data->volume_factor;
352 i->volume_factor_sink = data->volume_factor_sink;
353 i->real_ratio = i->reference_ratio = data->volume;
354 pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
355 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
356 i->save_volume = data->save_volume;
357 i->save_sink = data->save_sink;
358 i->save_muted = data->save_muted;
359
360 i->muted = data->muted;
361
362 if (data->sync_base) {
363 i->sync_next = data->sync_base->sync_next;
364 i->sync_prev = data->sync_base;
365
366 if (data->sync_base->sync_next)
367 data->sync_base->sync_next->sync_prev = i;
368 data->sync_base->sync_next = i;
369 } else
370 i->sync_next = i->sync_prev = NULL;
371
372 i->direct_outputs = pa_idxset_new(NULL, NULL);
373
374 reset_callbacks(i);
375 i->userdata = NULL;
376
377 i->thread_info.state = i->state;
378 i->thread_info.attached = FALSE;
379 pa_atomic_store(&i->thread_info.drained, 1);
380 i->thread_info.sample_spec = i->sample_spec;
381 i->thread_info.resampler = resampler;
382 i->thread_info.soft_volume = i->soft_volume;
383 i->thread_info.muted = i->muted;
384 i->thread_info.requested_sink_latency = (pa_usec_t) -1;
385 i->thread_info.rewrite_nbytes = 0;
386 i->thread_info.rewrite_flush = FALSE;
387 i->thread_info.dont_rewind_render = FALSE;
388 i->thread_info.underrun_for = (uint64_t) -1;
389 i->thread_info.playing_for = 0;
390 i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
391
392 i->thread_info.render_memblockq = pa_memblockq_new(
393 0,
394 MEMBLOCKQ_MAXLENGTH,
395 0,
396 pa_frame_size(&i->sink->sample_spec),
397 0,
398 1,
399 0,
400 &i->sink->silence);
401
402 pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
403 pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0);
404
405 if (i->client)
406 pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
407
408 pt = pa_proplist_to_string_sep(i->proplist, "\n ");
409 pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
410 i->index,
411 pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
412 i->sink->name,
413 pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
414 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
415 pt);
416 pa_xfree(pt);
417
418 /* Don't forget to call pa_sink_input_put! */
419
420 *_i = i;
421 return 0;
422 }
423
424 /* Called from main context */
425 static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
426 pa_assert(i);
427 pa_assert_ctl_context();
428
429 if (!i->sink)
430 return;
431
432 if (i->state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED)
433 pa_assert_se(i->sink->n_corked -- >= 1);
434 else if (i->state != PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_CORKED)
435 i->sink->n_corked++;
436 }
437
438 /* Called from main context */
439 static void sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
440 pa_sink_input *ssync;
441 pa_assert(i);
442 pa_assert_ctl_context();
443
444 if (state == PA_SINK_INPUT_DRAINED)
445 state = PA_SINK_INPUT_RUNNING;
446
447 if (i->state == state)
448 return;
449
450 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);
451
452 update_n_corked(i, state);
453 i->state = state;
454
455 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev) {
456 update_n_corked(ssync, state);
457 ssync->state = state;
458 }
459 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) {
460 update_n_corked(ssync, state);
461 ssync->state = state;
462 }
463
464 if (state != PA_SINK_INPUT_UNLINKED) {
465 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
466
467 for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev)
468 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
469
470 for (ssync = i->sync_next; ssync; ssync = ssync->sync_next)
471 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
472
473 if (PA_SINK_INPUT_IS_LINKED(state))
474 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
475 }
476
477 pa_sink_update_status(i->sink);
478 }
479
480 /* Called from main context */
481 void pa_sink_input_unlink(pa_sink_input *i) {
482 pa_bool_t linked;
483 pa_source_output *o, *p = NULL;
484
485 pa_assert(i);
486 pa_assert_ctl_context();
487
488 /* See pa_sink_unlink() for a couple of comments how this function
489 * works */
490
491 pa_sink_input_ref(i);
492
493 linked = PA_SINK_INPUT_IS_LINKED(i->state);
494
495 if (linked)
496 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
497
498 if (i->sync_prev)
499 i->sync_prev->sync_next = i->sync_next;
500 if (i->sync_next)
501 i->sync_next->sync_prev = i->sync_prev;
502
503 i->sync_prev = i->sync_next = NULL;
504
505 pa_idxset_remove_by_data(i->core->sink_inputs, i, NULL);
506
507 if (i->sink)
508 if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
509 pa_sink_input_unref(i);
510
511 if (i->client)
512 pa_idxset_remove_by_data(i->client->sink_inputs, i, NULL);
513
514 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
515 pa_assert(o != p);
516 pa_source_output_kill(o);
517 p = o;
518 }
519
520 update_n_corked(i, PA_SINK_INPUT_UNLINKED);
521 i->state = PA_SINK_INPUT_UNLINKED;
522
523 if (linked && i->sink) {
524 /* We might need to update the sink's volume if we are in flat volume mode. */
525 if (pa_sink_flat_volume_enabled(i->sink))
526 pa_sink_set_volume(i->sink, NULL, FALSE, FALSE);
527
528 if (i->sink->asyncmsgq)
529 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL) == 0);
530 }
531
532 reset_callbacks(i);
533
534 if (linked) {
535 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
536 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
537 }
538
539 if (i->sink) {
540 pa_sink_update_status(i->sink);
541 i->sink = NULL;
542 }
543
544 pa_core_maybe_vacuum(i->core);
545
546 pa_sink_input_unref(i);
547 }
548
549 /* Called from main context */
550 static void sink_input_free(pa_object *o) {
551 pa_sink_input* i = PA_SINK_INPUT(o);
552
553 pa_assert(i);
554 pa_assert_ctl_context();
555 pa_assert(pa_sink_input_refcnt(i) == 0);
556
557 if (PA_SINK_INPUT_IS_LINKED(i->state))
558 pa_sink_input_unlink(i);
559
560 pa_log_info("Freeing input %u \"%s\"", i->index, pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)));
561
562 /* Side note: this function must be able to destruct properly any
563 * kind of sink input in any state, even those which are
564 * "half-moved" or are connected to sinks that have no asyncmsgq
565 * and are hence half-destructed themselves! */
566
567 if (i->thread_info.render_memblockq)
568 pa_memblockq_free(i->thread_info.render_memblockq);
569
570 if (i->thread_info.resampler)
571 pa_resampler_free(i->thread_info.resampler);
572
573 if (i->proplist)
574 pa_proplist_free(i->proplist);
575
576 if (i->direct_outputs)
577 pa_idxset_free(i->direct_outputs, NULL, NULL);
578
579 if (i->thread_info.direct_outputs)
580 pa_hashmap_free(i->thread_info.direct_outputs, NULL, NULL);
581
582 pa_xfree(i->driver);
583 pa_xfree(i);
584 }
585
586 /* Called from main context */
587 void pa_sink_input_put(pa_sink_input *i) {
588 pa_sink_input_state_t state;
589
590 pa_sink_input_assert_ref(i);
591 pa_assert_ctl_context();
592
593 pa_assert(i->state == PA_SINK_INPUT_INIT);
594
595 /* The following fields must be initialized properly */
596 pa_assert(i->pop);
597 pa_assert(i->process_rewind);
598 pa_assert(i->kill);
599
600 state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
601
602 update_n_corked(i, state);
603 i->state = state;
604
605 /* We might need to update the sink's volume if we are in flat volume mode. */
606 if (pa_sink_flat_volume_enabled(i->sink))
607 pa_sink_set_volume(i->sink, NULL, FALSE, i->save_volume);
608 else {
609 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
610 pa_assert(pa_cvolume_is_norm(&i->volume));
611 pa_assert(pa_cvolume_is_norm(&i->reference_ratio));
612 }
613
614 set_real_ratio(i, &i->volume);
615 }
616
617 i->thread_info.soft_volume = i->soft_volume;
618 i->thread_info.muted = i->muted;
619
620 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0);
621
622 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
623 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
624
625 pa_sink_update_status(i->sink);
626 }
627
628 /* Called from main context */
629 void pa_sink_input_kill(pa_sink_input*i) {
630 pa_sink_input_assert_ref(i);
631 pa_assert_ctl_context();
632 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
633
634 i->kill(i);
635 }
636
637 /* Called from main context */
638 pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
639 pa_usec_t r[2] = { 0, 0 };
640
641 pa_sink_input_assert_ref(i);
642 pa_assert_ctl_context();
643 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
644
645 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, r, 0, NULL) == 0);
646
647 if (i->get_latency)
648 r[0] += i->get_latency(i);
649
650 if (sink_latency)
651 *sink_latency = r[1];
652
653 return r[0];
654 }
655
656 /* Called from thread context */
657 void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
658 pa_bool_t do_volume_adj_here, need_volume_factor_sink;
659 pa_bool_t volume_is_norm;
660 size_t block_size_max_sink, block_size_max_sink_input;
661 size_t ilength;
662
663 pa_sink_input_assert_ref(i);
664 pa_sink_input_assert_io_context(i);
665 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
666 pa_assert(pa_frame_aligned(slength, &i->sink->sample_spec));
667 pa_assert(chunk);
668 pa_assert(volume);
669
670 /* pa_log_debug("peek"); */
671
672 pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING ||
673 i->thread_info.state == PA_SINK_INPUT_CORKED ||
674 i->thread_info.state == PA_SINK_INPUT_DRAINED);
675
676 block_size_max_sink_input = i->thread_info.resampler ?
677 pa_resampler_max_block_size(i->thread_info.resampler) :
678 pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sample_spec);
679
680 block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sink->sample_spec);
681
682 /* Default buffer size */
683 if (slength <= 0)
684 slength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec);
685
686 if (slength > block_size_max_sink)
687 slength = block_size_max_sink;
688
689 if (i->thread_info.resampler) {
690 ilength = pa_resampler_request(i->thread_info.resampler, slength);
691
692 if (ilength <= 0)
693 ilength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
694 } else
695 ilength = slength;
696
697 if (ilength > block_size_max_sink_input)
698 ilength = block_size_max_sink_input;
699
700 /* If the channel maps of the sink and this stream differ, we need
701 * to adjust the volume *before* we resample. Otherwise we can do
702 * it after and leave it for the sink code */
703
704 do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
705 volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
706 need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);
707
708 while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
709 pa_memchunk tchunk;
710
711 /* There's nothing in our render queue. We need to fill it up
712 * with data from the implementor. */
713
714 if (i->thread_info.state == PA_SINK_INPUT_CORKED ||
715 i->pop(i, ilength, &tchunk) < 0) {
716
717 /* OK, we're corked or the implementor didn't give us any
718 * data, so let's just hand out silence */
719 pa_atomic_store(&i->thread_info.drained, 1);
720
721 pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE, TRUE);
722 i->thread_info.playing_for = 0;
723 if (i->thread_info.underrun_for != (uint64_t) -1)
724 i->thread_info.underrun_for += ilength;
725 break;
726 }
727
728 pa_atomic_store(&i->thread_info.drained, 0);
729
730 pa_assert(tchunk.length > 0);
731 pa_assert(tchunk.memblock);
732
733 i->thread_info.underrun_for = 0;
734 i->thread_info.playing_for += tchunk.length;
735
736 while (tchunk.length > 0) {
737 pa_memchunk wchunk;
738 pa_bool_t nvfs = need_volume_factor_sink;
739
740 wchunk = tchunk;
741 pa_memblock_ref(wchunk.memblock);
742
743 if (wchunk.length > block_size_max_sink_input)
744 wchunk.length = block_size_max_sink_input;
745
746 /* It might be necessary to adjust the volume here */
747 if (do_volume_adj_here && !volume_is_norm) {
748 pa_memchunk_make_writable(&wchunk, 0);
749
750 if (i->thread_info.muted) {
751 pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
752 nvfs = FALSE;
753
754 } else if (!i->thread_info.resampler && nvfs) {
755 pa_cvolume v;
756
757 /* If we don't need a resampler we can merge the
758 * post and the pre volume adjustment into one */
759
760 pa_sw_cvolume_multiply(&v, &i->thread_info.soft_volume, &i->volume_factor_sink);
761 pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &v);
762 nvfs = FALSE;
763
764 } else
765 pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);
766 }
767
768 if (!i->thread_info.resampler) {
769
770 if (nvfs) {
771 pa_memchunk_make_writable(&wchunk, 0);
772 pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
773 }
774
775 pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
776 } else {
777 pa_memchunk rchunk;
778 pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
779
780 /* pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */
781
782 if (rchunk.memblock) {
783
784 if (nvfs) {
785 pa_memchunk_make_writable(&rchunk, 0);
786 pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
787 }
788
789 pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
790 pa_memblock_unref(rchunk.memblock);
791 }
792 }
793
794 pa_memblock_unref(wchunk.memblock);
795
796 tchunk.index += wchunk.length;
797 tchunk.length -= wchunk.length;
798 }
799
800 pa_memblock_unref(tchunk.memblock);
801 }
802
803 pa_assert_se(pa_memblockq_peek(i->thread_info.render_memblockq, chunk) >= 0);
804
805 pa_assert(chunk->length > 0);
806 pa_assert(chunk->memblock);
807
808 /* pa_log_debug("peeking %lu", (unsigned long) chunk->length); */
809
810 if (chunk->length > block_size_max_sink)
811 chunk->length = block_size_max_sink;
812
813 /* Let's see if we had to apply the volume adjustment ourselves,
814 * or if this can be done by the sink for us */
815
816 if (do_volume_adj_here)
817 /* We had different channel maps, so we already did the adjustment */
818 pa_cvolume_reset(volume, i->sink->sample_spec.channels);
819 else if (i->thread_info.muted)
820 /* We've both the same channel map, so let's have the sink do the adjustment for us*/
821 pa_cvolume_mute(volume, i->sink->sample_spec.channels);
822 else
823 *volume = i->thread_info.soft_volume;
824 }
825
826 /* Called from thread context */
827 void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
828
829 pa_sink_input_assert_ref(i);
830 pa_sink_input_assert_io_context(i);
831 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
832 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
833 pa_assert(nbytes > 0);
834
835 /* pa_log_debug("dropping %lu", (unsigned long) nbytes); */
836
837 pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
838 }
839
840 /* Called from thread context */
841 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
842 size_t lbq;
843 pa_bool_t called = FALSE;
844
845 pa_sink_input_assert_ref(i);
846 pa_sink_input_assert_io_context(i);
847 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
848 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
849
850 /* pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes); */
851
852 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
853
854 if (nbytes > 0 && !i->thread_info.dont_rewind_render) {
855 pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
856 pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
857 }
858
859 if (i->thread_info.rewrite_nbytes == (size_t) -1) {
860
861 /* We were asked to drop all buffered data, and rerequest new
862 * data from implementor the next time push() is called */
863
864 pa_memblockq_flush_write(i->thread_info.render_memblockq, TRUE);
865
866 } else if (i->thread_info.rewrite_nbytes > 0) {
867 size_t max_rewrite, amount;
868
869 /* Calculate how much make sense to rewrite at most */
870 max_rewrite = nbytes + lbq;
871
872 /* Transform into local domain */
873 if (i->thread_info.resampler)
874 max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
875
876 /* Calculate how much of the rewinded data should actually be rewritten */
877 amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
878
879 if (amount > 0) {
880 pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
881
882 /* Tell the implementor */
883 if (i->process_rewind)
884 i->process_rewind(i, amount);
885 called = TRUE;
886
887 /* Convert back to to sink domain */
888 if (i->thread_info.resampler)
889 amount = pa_resampler_result(i->thread_info.resampler, amount);
890
891 if (amount > 0)
892 /* Ok, now update the write pointer */
893 pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE, TRUE);
894
895 if (i->thread_info.rewrite_flush)
896 pa_memblockq_silence(i->thread_info.render_memblockq);
897
898 /* And reset the resampler */
899 if (i->thread_info.resampler)
900 pa_resampler_reset(i->thread_info.resampler);
901 }
902 }
903
904 if (!called)
905 if (i->process_rewind)
906 i->process_rewind(i, 0);
907
908 i->thread_info.rewrite_nbytes = 0;
909 i->thread_info.rewrite_flush = FALSE;
910 i->thread_info.dont_rewind_render = FALSE;
911 }
912
913 /* Called from thread context */
914 size_t pa_sink_input_get_max_rewind(pa_sink_input *i) {
915 pa_sink_input_assert_ref(i);
916 pa_sink_input_assert_io_context(i);
917
918 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_rewind) : i->sink->thread_info.max_rewind;
919 }
920
921 /* Called from thread context */
922 size_t pa_sink_input_get_max_request(pa_sink_input *i) {
923 pa_sink_input_assert_ref(i);
924 pa_sink_input_assert_io_context(i);
925
926 /* We're not verifying the status here, to allow this to be called
927 * in the state change handler between _INIT and _RUNNING */
928
929 return i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_request) : i->sink->thread_info.max_request;
930 }
931
932 /* Called from thread context */
933 void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
934 pa_sink_input_assert_ref(i);
935 pa_sink_input_assert_io_context(i);
936 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
937 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
938
939 pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
940
941 if (i->update_max_rewind)
942 i->update_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
943 }
944
945 /* Called from thread context */
946 void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
947 pa_sink_input_assert_ref(i);
948 pa_sink_input_assert_io_context(i);
949 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
950 pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
951
952 if (i->update_max_request)
953 i->update_max_request(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
954 }
955
956 /* Called from thread context */
957 pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
958 pa_sink_input_assert_ref(i);
959 pa_sink_input_assert_io_context(i);
960
961 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
962 usec = i->sink->thread_info.fixed_latency;
963
964 if (usec != (pa_usec_t) -1)
965 usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
966
967 i->thread_info.requested_sink_latency = usec;
968 pa_sink_invalidate_requested_latency(i->sink, TRUE);
969
970 return usec;
971 }
972
973 /* Called from main context */
974 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
975 pa_sink_input_assert_ref(i);
976 pa_assert_ctl_context();
977
978 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
979 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
980 return usec;
981 }
982
983 /* If this sink input is not realized yet or we are being moved,
984 * we have to touch the thread info data directly */
985
986 if (i->sink) {
987 if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
988 usec = pa_sink_get_fixed_latency(i->sink);
989
990 if (usec != (pa_usec_t) -1) {
991 pa_usec_t min_latency, max_latency;
992 pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
993 usec = PA_CLAMP(usec, min_latency, max_latency);
994 }
995 }
996
997 i->thread_info.requested_sink_latency = usec;
998
999 return usec;
1000 }
1001
1002 /* Called from main context */
1003 pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
1004 pa_sink_input_assert_ref(i);
1005 pa_assert_ctl_context();
1006
1007 if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
1008 pa_usec_t usec = 0;
1009 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1010 return usec;
1011 }
1012
1013 /* If this sink input is not realized yet or we are being moved,
1014 * we have to touch the thread info data directly */
1015
1016 return i->thread_info.requested_sink_latency;
1017 }
1018
1019 /* Called from main context */
1020 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute) {
1021 pa_cvolume v;
1022
1023 pa_sink_input_assert_ref(i);
1024 pa_assert_ctl_context();
1025 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1026 pa_assert(volume);
1027 pa_assert(pa_cvolume_valid(volume));
1028 pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
1029 pa_assert(pa_sink_input_is_volume_writable(i));
1030
1031 if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) {
1032 v = i->sink->reference_volume;
1033 pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
1034
1035 if (pa_cvolume_compatible(volume, &i->sample_spec))
1036 volume = pa_sw_cvolume_multiply(&v, &v, volume);
1037 else
1038 volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume));
1039 } else {
1040 if (!pa_cvolume_compatible(volume, &i->sample_spec)) {
1041 v = i->volume;
1042 volume = pa_cvolume_scale(&v, pa_cvolume_max(volume));
1043 }
1044 }
1045
1046 if (pa_cvolume_equal(volume, &i->volume)) {
1047 i->save_volume = i->save_volume || save;
1048 return;
1049 }
1050
1051 i->volume = *volume;
1052 i->save_volume = save;
1053
1054 if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
1055 /* We are in flat volume mode, so let's update all sink input
1056 * volumes and update the flat volume of the sink */
1057
1058 pa_sink_set_volume(i->sink, NULL, TRUE, save);
1059
1060 } else {
1061 /* OK, we are in normal volume mode. The volume only affects
1062 * ourselves */
1063 set_real_ratio(i, volume);
1064
1065 /* Copy the new soft_volume to the thread_info struct */
1066 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
1067 }
1068
1069 /* The volume changed, let's tell people so */
1070 if (i->volume_changed)
1071 i->volume_changed(i);
1072
1073 /* The virtual volume changed, let's tell people so */
1074 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1075 }
1076
1077 /* Called from main context */
1078 static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {
1079 pa_sink_input_assert_ref(i);
1080 pa_assert_ctl_context();
1081 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1082 pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
1083
1084 /* This basically calculates:
1085 *
1086 * i->real_ratio := v
1087 * i->soft_volume := i->real_ratio * i->volume_factor */
1088
1089 if (v)
1090 i->real_ratio = *v;
1091 else
1092 pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
1093
1094 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1095 /* We don't copy the data to the thread_info data. That's left for someone else to do */
1096 }
1097
1098 /* Called from main context */
1099 pa_bool_t pa_sink_input_is_volume_readable(pa_sink_input *i) {
1100 pa_sink_input_assert_ref(i);
1101 pa_assert_ctl_context();
1102
1103 return !(i->flags & PA_SINK_INPUT_PASSTHROUGH);
1104 }
1105
1106 /* Called from main context */
1107 pa_bool_t pa_sink_input_is_volume_writable(pa_sink_input *i) {
1108 pa_sink_input_assert_ref(i);
1109 pa_assert_ctl_context();
1110
1111 if (i->flags & PA_SINK_INPUT_PASSTHROUGH)
1112 return FALSE;
1113
1114 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
1115 return FALSE;
1116
1117 return TRUE;
1118 }
1119
1120 /* Called from main context */
1121 pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, pa_bool_t absolute) {
1122 pa_sink_input_assert_ref(i);
1123 pa_assert_ctl_context();
1124 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1125 pa_assert(pa_sink_input_is_volume_readable(i));
1126
1127 if (absolute || !pa_sink_flat_volume_enabled(i->sink))
1128 *volume = i->volume;
1129 else
1130 *volume = i->reference_ratio;
1131
1132 return volume;
1133 }
1134
1135 /* Called from main context */
1136 void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save) {
1137 pa_sink_input_assert_ref(i);
1138 pa_assert_ctl_context();
1139 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1140
1141 if (!i->muted == !mute) {
1142 i->save_muted = i->save_muted || mute;
1143 return;
1144 }
1145
1146 i->muted = mute;
1147 i->save_muted = save;
1148
1149 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
1150
1151 /* The mute status changed, let's tell people so */
1152 if (i->mute_changed)
1153 i->mute_changed(i);
1154
1155 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1156 }
1157
1158 /* Called from main context */
1159 pa_bool_t pa_sink_input_get_mute(pa_sink_input *i) {
1160 pa_sink_input_assert_ref(i);
1161 pa_assert_ctl_context();
1162 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1163
1164 return i->muted;
1165 }
1166
1167 /* Called from main thread */
1168 void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
1169 pa_sink_input_assert_ref(i);
1170 pa_assert_ctl_context();
1171
1172 if (p)
1173 pa_proplist_update(i->proplist, mode, p);
1174
1175 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1176 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1177 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1178 }
1179 }
1180
1181 /* Called from main context */
1182 void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) {
1183 pa_sink_input_assert_ref(i);
1184 pa_assert_ctl_context();
1185 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1186
1187 sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
1188 }
1189
1190 /* Called from main context */
1191 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
1192 pa_sink_input_assert_ref(i);
1193 pa_assert_ctl_context();
1194 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1195 pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE);
1196
1197 if (i->sample_spec.rate == rate)
1198 return 0;
1199
1200 i->sample_spec.rate = rate;
1201
1202 pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
1203
1204 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1205 return 0;
1206 }
1207
1208 /* Called from main context */
1209 void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
1210 const char *old;
1211 pa_sink_input_assert_ref(i);
1212 pa_assert_ctl_context();
1213
1214 if (!name && !pa_proplist_contains(i->proplist, PA_PROP_MEDIA_NAME))
1215 return;
1216
1217 old = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME);
1218
1219 if (old && name && pa_streq(old, name))
1220 return;
1221
1222 if (name)
1223 pa_proplist_sets(i->proplist, PA_PROP_MEDIA_NAME, name);
1224 else
1225 pa_proplist_unset(i->proplist, PA_PROP_MEDIA_NAME);
1226
1227 if (PA_SINK_INPUT_IS_LINKED(i->state)) {
1228 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
1229 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1230 }
1231 }
1232
1233 /* Called from main context */
1234 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
1235 pa_sink_input_assert_ref(i);
1236 pa_assert_ctl_context();
1237
1238 return i->actual_resample_method;
1239 }
1240
1241 /* Called from main context */
1242 pa_bool_t pa_sink_input_may_move(pa_sink_input *i) {
1243 pa_sink_input_assert_ref(i);
1244 pa_assert_ctl_context();
1245 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1246
1247 if (i->flags & PA_SINK_INPUT_DONT_MOVE)
1248 return FALSE;
1249
1250 if (i->sync_next || i->sync_prev) {
1251 pa_log_warn("Moving synchronized streams not supported.");
1252 return FALSE;
1253 }
1254
1255 return TRUE;
1256 }
1257
1258 /* Called from main context */
1259 pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
1260 pa_sink_input_assert_ref(i);
1261 pa_assert_ctl_context();
1262 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1263 pa_sink_assert_ref(dest);
1264
1265 if (dest == i->sink)
1266 return TRUE;
1267
1268 if (!pa_sink_input_may_move(i))
1269 return FALSE;
1270
1271 if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
1272 pa_log_warn("Failed to move sink input: too many inputs per sink.");
1273 return FALSE;
1274 }
1275
1276 if (check_passthrough_connection(i->flags, dest) < 0)
1277 return FALSE;
1278
1279 if (i->may_move_to)
1280 if (!i->may_move_to(i, dest))
1281 return FALSE;
1282
1283 return TRUE;
1284 }
1285
1286 /* Called from main context */
1287 int pa_sink_input_start_move(pa_sink_input *i) {
1288 pa_source_output *o, *p = NULL;
1289 int r;
1290
1291 pa_sink_input_assert_ref(i);
1292 pa_assert_ctl_context();
1293 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1294 pa_assert(i->sink);
1295
1296 if (!pa_sink_input_may_move(i))
1297 return -PA_ERR_NOTSUPPORTED;
1298
1299 if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
1300 return r;
1301
1302 /* Kill directly connected outputs */
1303 while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
1304 pa_assert(o != p);
1305 pa_source_output_kill(o);
1306 p = o;
1307 }
1308 pa_assert(pa_idxset_isempty(i->direct_outputs));
1309
1310 pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
1311
1312 if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
1313 pa_assert_se(i->sink->n_corked-- >= 1);
1314
1315 if (pa_sink_flat_volume_enabled(i->sink))
1316 /* We might need to update the sink's volume if we are in flat
1317 * volume mode. */
1318 pa_sink_set_volume(i->sink, NULL, FALSE, FALSE);
1319
1320 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
1321
1322 pa_sink_update_status(i->sink);
1323 pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
1324 i->sink = NULL;
1325
1326 pa_sink_input_unref(i);
1327
1328 return 0;
1329 }
1330
1331 /* Called from main context. If i has an origin sink that uses volume sharing,
1332 * then also the origin sink and all streams connected to it need to update
1333 * their volume - this function does all that by using recursion. */
1334 static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) {
1335 pa_cvolume old_volume;
1336
1337 pa_assert(i);
1338 pa_assert(dest);
1339 pa_assert(i->sink); /* The destination sink should already be set. */
1340
1341 if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
1342 pa_sink *root_sink = i->sink;
1343 pa_sink_input *origin_sink_input;
1344 uint32_t idx;
1345
1346 while (root_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
1347 root_sink = root_sink->input_to_master->sink;
1348
1349 if (pa_sink_flat_volume_enabled(i->sink)) {
1350 /* Ok, so the origin sink uses volume sharing, and flat volume is
1351 * enabled. The volume will have to be updated as follows:
1352 *
1353 * i->volume := i->sink->real_volume
1354 * (handled later by pa_sink_set_volume)
1355 * i->reference_ratio := i->volume / i->sink->reference_volume
1356 * (handled later by pa_sink_set_volume)
1357 * i->real_ratio stays unchanged
1358 * (streams whose origin sink uses volume sharing should
1359 * always have real_ratio of 0 dB)
1360 * i->soft_volume stays unchanged
1361 * (streams whose origin sink uses volume sharing should
1362 * always have volume_factor as soft_volume, so no change
1363 * should be needed) */
1364
1365 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
1366 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
1367
1368 /* Notifications will be sent by pa_sink_set_volume(). */
1369
1370 } else {
1371 /* Ok, so the origin sink uses volume sharing, and flat volume is
1372 * disabled. The volume will have to be updated as follows:
1373 *
1374 * i->volume := 0 dB
1375 * i->reference_ratio := 0 dB
1376 * i->real_ratio stays unchanged
1377 * (streams whose origin sink uses volume sharing should
1378 * always have real_ratio of 0 dB)
1379 * i->soft_volume stays unchanged
1380 * (streams whose origin sink uses volume sharing should
1381 * always have volume_factor as soft_volume, so no change
1382 * should be needed) */
1383
1384 old_volume = i->volume;
1385 pa_cvolume_reset(&i->volume, i->volume.channels);
1386 pa_cvolume_reset(&i->reference_ratio, i->reference_ratio.channels);
1387 pa_assert(pa_cvolume_is_norm(&i->real_ratio));
1388 pa_assert(pa_cvolume_equal(&i->soft_volume, &i->volume_factor));
1389
1390 /* Notify others about the changed sink input volume. */
1391 if (!pa_cvolume_equal(&i->volume, &old_volume)) {
1392 if (i->volume_changed)
1393 i->volume_changed(i);
1394
1395 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1396 }
1397 }
1398
1399 /* Additionally, the origin sink volume needs updating:
1400 *
1401 * i->origin_sink->reference_volume := root_sink->reference_volume
1402 * i->origin_sink->real_volume := root_sink->real_volume
1403 * i->origin_sink->soft_volume stays unchanged
1404 * (sinks that use volume sharing should always have
1405 * soft_volume of 0 dB) */
1406
1407 old_volume = i->origin_sink->reference_volume;
1408
1409 i->origin_sink->reference_volume = root_sink->reference_volume;
1410 pa_cvolume_remap(&i->origin_sink->reference_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
1411
1412 i->origin_sink->real_volume = root_sink->real_volume;
1413 pa_cvolume_remap(&i->origin_sink->real_volume, &root_sink->channel_map, &i->origin_sink->channel_map);
1414
1415 pa_assert(pa_cvolume_is_norm(&i->origin_sink->soft_volume));
1416
1417 /* Notify others about the changed sink volume. If you wonder whether
1418 * i->origin_sink->set_volume() should be called somewhere, that's not
1419 * the case, because sinks that use volume sharing shouldn't have any
1420 * internal volume that set_volume() would update. If you wonder
1421 * whether the thread_info variables should be synced, yes, they
1422 * should, and it's done by the PA_SINK_MESSAGE_FINISH_MOVE message
1423 * handler. */
1424 if (!pa_cvolume_equal(&i->origin_sink->reference_volume, &old_volume))
1425 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, i->origin_sink->index);
1426
1427 /* Recursively update origin sink inputs. */
1428 PA_IDXSET_FOREACH(origin_sink_input, i->origin_sink->inputs, idx)
1429 update_volume_due_to_moving(origin_sink_input, dest);
1430
1431 } else {
1432 old_volume = i->volume;
1433
1434 if (pa_sink_flat_volume_enabled(i->sink)) {
1435 /* Ok, so this is a regular stream, and flat volume is enabled. The
1436 * volume will have to be updated as follows:
1437 *
1438 * i->volume := i->reference_ratio * i->sink->reference_volume
1439 * i->reference_ratio stays unchanged
1440 * i->real_ratio := i->volume / i->sink->real_volume
1441 * (handled later by pa_sink_set_volume)
1442 * i->soft_volume := i->real_ratio * i->volume_factor
1443 * (handled later by pa_sink_set_volume) */
1444
1445 i->volume = i->sink->reference_volume;
1446 pa_cvolume_remap(&i->volume, &i->sink->channel_map, &i->channel_map);
1447 pa_sw_cvolume_multiply(&i->volume, &i->volume, &i->reference_ratio);
1448
1449 } else {
1450 /* Ok, so this is a regular stream, and flat volume is disabled.
1451 * The volume will have to be updated as follows:
1452 *
1453 * i->volume := i->reference_ratio
1454 * i->reference_ratio stays unchanged
1455 * i->real_ratio := i->reference_ratio
1456 * i->soft_volume := i->real_ratio * i->volume_factor */
1457
1458 i->volume = i->reference_ratio;
1459 i->real_ratio = i->reference_ratio;
1460 pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
1461 }
1462
1463 /* Notify others about the changed sink input volume. */
1464 if (!pa_cvolume_equal(&i->volume, &old_volume)) {
1465 /* XXX: In case i->sink has flat volume enabled, then real_ratio
1466 * and soft_volume are not updated yet. Let's hope that the
1467 * callback implementation doesn't care about those variables... */
1468 if (i->volume_changed)
1469 i->volume_changed(i);
1470
1471 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1472 }
1473 }
1474
1475 /* If i->sink == dest, then recursion has finished, and we can finally call
1476 * pa_sink_set_volume(), which will do the rest of the updates. */
1477 if ((i->sink == dest) && pa_sink_flat_volume_enabled(i->sink))
1478 pa_sink_set_volume(i->sink, NULL, FALSE, i->save_volume);
1479 }
1480
1481 /* Called from main context */
1482 int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
1483 pa_resampler *new_resampler;
1484
1485 pa_sink_input_assert_ref(i);
1486 pa_assert_ctl_context();
1487 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1488 pa_assert(!i->sink);
1489 pa_sink_assert_ref(dest);
1490
1491 if (!pa_sink_input_may_move_to(i, dest))
1492 return -PA_ERR_NOTSUPPORTED;
1493
1494 if (i->thread_info.resampler &&
1495 pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &dest->sample_spec) &&
1496 pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &dest->channel_map))
1497
1498 /* Try to reuse the old resampler if possible */
1499 new_resampler = i->thread_info.resampler;
1500
1501 else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
1502 !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) ||
1503 !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) {
1504
1505 /* Okey, we need a new resampler for the new sink */
1506
1507 if (!(new_resampler = pa_resampler_new(
1508 i->core->mempool,
1509 &i->sample_spec, &i->channel_map,
1510 &dest->sample_spec, &dest->channel_map,
1511 i->requested_resample_method,
1512 ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
1513 ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
1514 (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
1515 pa_log_warn("Unsupported resampling operation.");
1516 return -PA_ERR_NOTSUPPORTED;
1517 }
1518 } else
1519 new_resampler = NULL;
1520
1521 if (i->moving)
1522 i->moving(i, dest);
1523
1524 i->sink = dest;
1525 i->save_sink = save;
1526 pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
1527
1528 pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
1529
1530 if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
1531 i->sink->n_corked++;
1532
1533 /* Replace resampler and render queue */
1534 if (new_resampler != i->thread_info.resampler) {
1535
1536 if (i->thread_info.resampler)
1537 pa_resampler_free(i->thread_info.resampler);
1538 i->thread_info.resampler = new_resampler;
1539
1540 pa_memblockq_free(i->thread_info.render_memblockq);
1541
1542 i->thread_info.render_memblockq = pa_memblockq_new(
1543 0,
1544 MEMBLOCKQ_MAXLENGTH,
1545 0,
1546 pa_frame_size(&i->sink->sample_spec),
1547 0,
1548 1,
1549 0,
1550 &i->sink->silence);
1551 }
1552 pa_sink_update_status(dest);
1553
1554 update_volume_due_to_moving(i, dest);
1555
1556 pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
1557
1558 pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
1559
1560 /* Notify everyone */
1561 pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
1562
1563 pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
1564
1565 return 0;
1566 }
1567
1568 /* Called from main context */
1569 void pa_sink_input_fail_move(pa_sink_input *i) {
1570
1571 pa_sink_input_assert_ref(i);
1572 pa_assert_ctl_context();
1573 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1574 pa_assert(!i->sink);
1575
1576 /* Check if someone wants this sink input? */
1577 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_STOP)
1578 return;
1579
1580 if (i->moving)
1581 i->moving(i, NULL);
1582
1583 pa_sink_input_kill(i);
1584 }
1585
1586 /* Called from main context */
1587 int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
1588 int r;
1589
1590 pa_sink_input_assert_ref(i);
1591 pa_assert_ctl_context();
1592 pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
1593 pa_assert(i->sink);
1594 pa_sink_assert_ref(dest);
1595
1596 if (dest == i->sink)
1597 return 0;
1598
1599 if (!pa_sink_input_may_move_to(i, dest))
1600 return -PA_ERR_NOTSUPPORTED;
1601
1602 pa_sink_input_ref(i);
1603
1604 if ((r = pa_sink_input_start_move(i)) < 0) {
1605 pa_sink_input_unref(i);
1606 return r;
1607 }
1608
1609 if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
1610 pa_sink_input_fail_move(i);
1611 pa_sink_input_unref(i);
1612 return r;
1613 }
1614
1615 pa_sink_input_unref(i);
1616
1617 return 0;
1618 }
1619
1620 /* Called from IO thread context */
1621 void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
1622 pa_bool_t corking, uncorking;
1623
1624 pa_sink_input_assert_ref(i);
1625 pa_sink_input_assert_io_context(i);
1626
1627 if (state == i->thread_info.state)
1628 return;
1629
1630 if ((state == PA_SINK_INPUT_DRAINED || state == PA_SINK_INPUT_RUNNING) &&
1631 !(i->thread_info.state == PA_SINK_INPUT_DRAINED || i->thread_info.state != PA_SINK_INPUT_RUNNING))
1632 pa_atomic_store(&i->thread_info.drained, 1);
1633
1634 corking = state == PA_SINK_INPUT_CORKED && i->thread_info.state == PA_SINK_INPUT_RUNNING;
1635 uncorking = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
1636
1637 if (i->state_change)
1638 i->state_change(i, state);
1639
1640 i->thread_info.state = state;
1641
1642 if (corking) {
1643
1644 pa_log_debug("Requesting rewind due to corking");
1645
1646 /* This will tell the implementing sink input driver to rewind
1647 * so that the unplayed already mixed data is not lost */
1648 pa_sink_input_request_rewind(i, 0, TRUE, TRUE, FALSE);
1649
1650 } else if (uncorking) {
1651
1652 i->thread_info.underrun_for = (uint64_t) -1;
1653 i->thread_info.playing_for = 0;
1654
1655 pa_log_debug("Requesting rewind due to uncorking");
1656
1657 /* OK, we're being uncorked. Make sure we're not rewound when
1658 * the hw buffer is remixed and request a remix. */
1659 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
1660 }
1661 }
1662
1663 /* Called from thread context, except when it is not. */
1664 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1665 pa_sink_input *i = PA_SINK_INPUT(o);
1666 pa_sink_input_assert_ref(i);
1667
1668 switch (code) {
1669
1670 case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
1671 if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
1672 i->thread_info.soft_volume = i->soft_volume;
1673 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1674 }
1675 return 0;
1676
1677 case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
1678 if (i->thread_info.muted != i->muted) {
1679 i->thread_info.muted = i->muted;
1680 pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
1681 }
1682 return 0;
1683
1684 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1685 pa_usec_t *r = userdata;
1686
1687 r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
1688 r[1] += pa_sink_get_latency_within_thread(i->sink);
1689
1690 return 0;
1691 }
1692
1693 case PA_SINK_INPUT_MESSAGE_SET_RATE:
1694
1695 i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
1696 pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
1697
1698 return 0;
1699
1700 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1701 pa_sink_input *ssync;
1702
1703 pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
1704
1705 for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
1706 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
1707
1708 for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
1709 pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
1710
1711 return 0;
1712 }
1713
1714 case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
1715 pa_usec_t *usec = userdata;
1716
1717 *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
1718 return 0;
1719 }
1720
1721 case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
1722 pa_usec_t *r = userdata;
1723
1724 *r = i->thread_info.requested_sink_latency;
1725 return 0;
1726 }
1727 }
1728
1729 return -PA_ERR_NOTIMPLEMENTED;
1730 }
1731
1732 /* Called from main thread */
1733 pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
1734 pa_sink_input_assert_ref(i);
1735 pa_assert_ctl_context();
1736
1737 if (i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED)
1738 return pa_atomic_load(&i->thread_info.drained) ? PA_SINK_INPUT_DRAINED : PA_SINK_INPUT_RUNNING;
1739
1740 return i->state;
1741 }
1742
1743 /* Called from IO context */
1744 pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
1745 pa_sink_input_assert_ref(i);
1746 pa_sink_input_assert_io_context(i);
1747
1748 if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
1749 return pa_memblockq_is_empty(i->thread_info.render_memblockq);
1750
1751 return TRUE;
1752 }
1753
1754 /* Called from IO context */
1755 void pa_sink_input_request_rewind(
1756 pa_sink_input *i,
1757 size_t nbytes /* in our sample spec */,
1758 pa_bool_t rewrite,
1759 pa_bool_t flush,
1760 pa_bool_t dont_rewind_render) {
1761
1762 size_t lbq;
1763
1764 /* If 'rewrite' is TRUE the sink is rewound as far as requested
1765 * and possible and the exact value of this is passed back the
1766 * implementor via process_rewind(). If 'flush' is also TRUE all
1767 * already rendered data is also dropped.
1768 *
1769 * If 'rewrite' is FALSE the sink is rewound as far as requested
1770 * and possible and the already rendered data is dropped so that
1771 * in the next iteration we read new data from the
1772 * implementor. This implies 'flush' is TRUE. If
1773 * dont_rewind_render is TRUE then the render memblockq is not
1774 * rewound. */
1775
1776 /* nbytes = 0 means maximum rewind request */
1777
1778 pa_sink_input_assert_ref(i);
1779 pa_sink_input_assert_io_context(i);
1780 pa_assert(rewrite || flush);
1781 pa_assert(!dont_rewind_render || !rewrite);
1782
1783 /* We don't take rewind requests while we are corked */
1784 if (i->thread_info.state == PA_SINK_INPUT_CORKED)
1785 return;
1786
1787 nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
1788
1789 /* pa_log_debug("request rewrite %zu", nbytes); */
1790
1791 /* Calculate how much we can rewind locally without having to
1792 * touch the sink */
1793 if (rewrite)
1794 lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
1795 else
1796 lbq = 0;
1797
1798 /* Check if rewinding for the maximum is requested, and if so, fix up */
1799 if (nbytes <= 0) {
1800
1801 /* Calculate maximum number of bytes that could be rewound in theory */
1802 nbytes = i->sink->thread_info.max_rewind + lbq;
1803
1804 /* Transform from sink domain */
1805 if (i->thread_info.resampler)
1806 nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
1807 }
1808
1809 /* Remember how much we actually want to rewrite */
1810 if (i->thread_info.rewrite_nbytes != (size_t) -1) {
1811 if (rewrite) {
1812 /* Make sure to not overwrite over underruns */
1813 if (nbytes > i->thread_info.playing_for)
1814 nbytes = (size_t) i->thread_info.playing_for;
1815
1816 i->thread_info.rewrite_nbytes = nbytes;
1817 } else
1818 i->thread_info.rewrite_nbytes = (size_t) -1;
1819 }
1820
1821 i->thread_info.rewrite_flush =
1822 i->thread_info.rewrite_flush ||
1823 (flush && i->thread_info.rewrite_nbytes != 0);
1824
1825 i->thread_info.dont_rewind_render =
1826 i->thread_info.dont_rewind_render ||
1827 dont_rewind_render;
1828
1829 if (nbytes != (size_t) -1) {
1830
1831 /* Transform to sink domain */
1832 if (i->thread_info.resampler)
1833 nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
1834
1835 if (nbytes > lbq)
1836 pa_sink_request_rewind(i->sink, nbytes - lbq);
1837 else
1838 /* This call will make sure process_rewind() is called later */
1839 pa_sink_request_rewind(i->sink, 0);
1840 }
1841 }
1842
1843 /* Called from main context */
1844 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
1845 pa_sink_input_assert_ref(i);
1846 pa_assert_ctl_context();
1847 pa_assert(ret);
1848
1849 /* FIXME: Shouldn't access resampler object from main context! */
1850
1851 pa_silence_memchunk_get(
1852 &i->core->silence_cache,
1853 i->core->mempool,
1854 ret,
1855 &i->sample_spec,
1856 i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
1857
1858 return ret;
1859 }
1860
1861 /* Called from main context */
1862 void pa_sink_input_send_event(pa_sink_input *i, const char *event, pa_proplist *data) {
1863 pa_proplist *pl = NULL;
1864 pa_sink_input_send_event_hook_data hook_data;
1865
1866 pa_sink_input_assert_ref(i);
1867 pa_assert_ctl_context();
1868 pa_assert(event);
1869
1870 if (!i->send_event)
1871 return;
1872
1873 if (!data)
1874 data = pl = pa_proplist_new();
1875
1876 hook_data.sink_input = i;
1877 hook_data.data = data;
1878 hook_data.event = event;
1879
1880 if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
1881 goto finish;
1882
1883 i->send_event(i, event, data);
1884
1885 finish:
1886 if (pl)
1887 pa_proplist_free(pl);
1888 }