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