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