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