2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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
31 #include <pulse/utf8.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/util.h>
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>
42 #include "sink-input.h"
44 #define MEMBLOCKQ_MAXLENGTH (32*1024*1024)
45 #define CONVERT_BUFFER_LENGTH (PA_PAGE_SIZE)
47 PA_DEFINE_PUBLIC_CLASS(pa_sink_input
, pa_msgobject
);
49 static void sink_input_free(pa_object
*o
);
50 static void set_real_ratio(pa_sink_input
*i
, const pa_cvolume
*v
);
52 static int check_passthrough_connection(pa_sink_input_flags_t flags
, pa_sink
*dest
) {
54 if (dest
->flags
& PA_SINK_PASSTHROUGH
) {
56 if (pa_idxset_size(dest
->inputs
) > 0) {
61 alt_i
= pa_idxset_first(dest
->inputs
, &idx
);
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");
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");
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
;
85 pa_sink_input_new_data
* pa_sink_input_new_data_init(pa_sink_input_new_data
*data
) {
89 data
->resample_method
= PA_RESAMPLER_INVALID
;
90 data
->proplist
= pa_proplist_new();
91 data
->volume_writable
= TRUE
;
96 void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data
*data
, const pa_sample_spec
*spec
) {
99 if ((data
->sample_spec_is_set
= !!spec
))
100 data
->sample_spec
= *spec
;
103 void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data
*data
, const pa_channel_map
*map
) {
106 if ((data
->channel_map_is_set
= !!map
))
107 data
->channel_map
= *map
;
110 void pa_sink_input_new_data_set_volume(pa_sink_input_new_data
*data
, const pa_cvolume
*volume
) {
112 pa_assert(data
->volume_writable
);
114 if ((data
->volume_is_set
= !!volume
))
115 data
->volume
= *volume
;
118 void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data
*data
, const pa_cvolume
*volume_factor
) {
120 pa_assert(volume_factor
);
122 if (data
->volume_factor_is_set
)
123 pa_sw_cvolume_multiply(&data
->volume_factor
, &data
->volume_factor
, volume_factor
);
125 data
->volume_factor_is_set
= TRUE
;
126 data
->volume_factor
= *volume_factor
;
130 void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data
*data
, const pa_cvolume
*volume_factor
) {
132 pa_assert(volume_factor
);
134 if (data
->volume_factor_sink_is_set
)
135 pa_sw_cvolume_multiply(&data
->volume_factor_sink
, &data
->volume_factor_sink
, volume_factor
);
137 data
->volume_factor_sink_is_set
= TRUE
;
138 data
->volume_factor_sink
= *volume_factor
;
142 void pa_sink_input_new_data_set_muted(pa_sink_input_new_data
*data
, pa_bool_t mute
) {
145 data
->muted_is_set
= TRUE
;
146 data
->muted
= !!mute
;
149 void pa_sink_input_new_data_done(pa_sink_input_new_data
*data
) {
152 pa_proplist_free(data
->proplist
);
155 /* Called from main context */
156 static void reset_callbacks(pa_sink_input
*i
) {
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
;
169 i
->suspend_within_thread
= 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
;
180 /* Called from main context */
181 int pa_sink_input_new(
184 pa_sink_input_new_data
*data
) {
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
;
196 pa_assert_ctl_context();
199 pa_proplist_update(data
->proplist
, PA_UPDATE_MERGE
, data
->client
->proplist
);
201 if (data
->origin_sink
&& (data
->origin_sink
->flags
& PA_SINK_SHARE_VOLUME_WITH_MASTER
))
202 data
->volume_writable
= FALSE
;
204 if ((r
= pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SINK_INPUT_NEW
], data
)) < 0)
207 pa_return_val_if_fail(!data
->driver
|| pa_utf8_valid(data
->driver
), -PA_ERR_INVALID
);
210 data
->sink
= pa_namereg_get(core
, NULL
, PA_NAMEREG_SINK
);
211 data
->save_sink
= FALSE
;
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
);
218 r
= check_passthrough_connection(data
->flags
, data
->sink
);
219 pa_return_val_if_fail(r
== PA_OK
, r
);
221 if (!data
->sample_spec_is_set
)
222 data
->sample_spec
= data
->sink
->sample_spec
;
224 pa_return_val_if_fail(pa_sample_spec_valid(&data
->sample_spec
), -PA_ERR_INVALID
);
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
;
230 pa_channel_map_init_extend(&data
->channel_map
, data
->sample_spec
.channels
, PA_CHANNEL_MAP_DEFAULT
);
233 pa_return_val_if_fail(pa_channel_map_compatible(&data
->channel_map
, &data
->sample_spec
), -PA_ERR_INVALID
);
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
;
241 pa_return_val_if_fail(pa_cvolume_compatible(&data
->volume
, &data
->sample_spec
), -PA_ERR_INVALID
);
243 if (!data
->volume_factor_is_set
)
244 pa_cvolume_reset(&data
->volume_factor
, data
->sample_spec
.channels
);
246 pa_return_val_if_fail(pa_cvolume_compatible(&data
->volume_factor
, &data
->sample_spec
), -PA_ERR_INVALID
);
248 if (!data
->volume_factor_sink_is_set
)
249 pa_cvolume_reset(&data
->volume_factor_sink
, data
->sink
->sample_spec
.channels
);
251 pa_return_val_if_fail(pa_cvolume_compatible(&data
->volume_factor_sink
, &data
->sink
->sample_spec
), -PA_ERR_INVALID
);
253 if (!data
->muted_is_set
)
256 if (data
->flags
& PA_SINK_INPUT_FIX_FORMAT
)
257 data
->sample_spec
.format
= data
->sink
->sample_spec
.format
;
259 if (data
->flags
& PA_SINK_INPUT_FIX_RATE
)
260 data
->sample_spec
.rate
= data
->sink
->sample_spec
.rate
;
262 original_cm
= data
->channel_map
;
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
;
269 pa_assert(pa_sample_spec_valid(&data
->sample_spec
));
270 pa_assert(pa_channel_map_valid(&data
->channel_map
));
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
);
275 if (data
->resample_method
== PA_RESAMPLER_INVALID
)
276 data
->resample_method
= core
->resample_method
;
278 pa_return_val_if_fail(data
->resample_method
< PA_RESAMPLER_MAX
, -PA_ERR_INVALID
);
280 if ((r
= pa_hook_fire(&core
->hooks
[PA_CORE_HOOK_SINK_INPUT_FIXATE
], data
)) < 0)
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
;
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
;
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
)) {
298 if (!(resampler
= pa_resampler_new(
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
;
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
;
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
;
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
;
331 if (!data
->volume_is_absolute
&& pa_sink_flat_volume_enabled(i
->sink
)) {
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
);
340 i
->volume
= data
->volume
;
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
;
352 i
->muted
= data
->muted
;
354 if (data
->sync_base
) {
355 i
->sync_next
= data
->sync_base
->sync_next
;
356 i
->sync_prev
= data
->sync_base
;
358 if (data
->sync_base
->sync_next
)
359 data
->sync_base
->sync_next
->sync_prev
= i
;
360 data
->sync_base
->sync_next
= i
;
362 i
->sync_next
= i
->sync_prev
= NULL
;
364 i
->direct_outputs
= pa_idxset_new(NULL
, NULL
);
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
);
384 i
->thread_info
.render_memblockq
= pa_memblockq_new(
388 pa_frame_size(&i
->sink
->sample_spec
),
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);
398 pa_assert_se(pa_idxset_put(i
->client
->sink_inputs
, i
, NULL
) >= 0);
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",
403 pa_strnull(pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
)),
405 pa_sample_spec_snprint(st
, sizeof(st
), &i
->sample_spec
),
406 pa_channel_map_snprint(cm
, sizeof(cm
), &i
->channel_map
),
410 /* Don't forget to call pa_sink_input_put! */
416 /* Called from main context */
417 static void update_n_corked(pa_sink_input
*i
, pa_sink_input_state_t state
) {
419 pa_assert_ctl_context();
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
)
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
;
434 pa_assert_ctl_context();
436 if (state
== PA_SINK_INPUT_DRAINED
)
437 state
= PA_SINK_INPUT_RUNNING
;
439 if (i
->state
== state
)
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);
444 update_n_corked(i
, state
);
447 for (ssync
= i
->sync_prev
; ssync
; ssync
= ssync
->sync_prev
) {
448 update_n_corked(ssync
, state
);
449 ssync
->state
= state
;
451 for (ssync
= i
->sync_next
; ssync
; ssync
= ssync
->sync_next
) {
452 update_n_corked(ssync
, state
);
453 ssync
->state
= state
;
456 if (state
!= PA_SINK_INPUT_UNLINKED
) {
457 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED
], i
);
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
);
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
);
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
);
469 pa_sink_update_status(i
->sink
);
472 /* Called from main context */
473 void pa_sink_input_unlink(pa_sink_input
*i
) {
475 pa_source_output
*o
, *p
= NULL
;
478 pa_assert_ctl_context();
480 /* See pa_sink_unlink() for a couple of comments how this function
483 pa_sink_input_ref(i
);
485 linked
= PA_SINK_INPUT_IS_LINKED(i
->state
);
488 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_UNLINK
], i
);
491 i
->sync_prev
->sync_next
= i
->sync_next
;
493 i
->sync_next
->sync_prev
= i
->sync_prev
;
495 i
->sync_prev
= i
->sync_next
= NULL
;
497 pa_idxset_remove_by_data(i
->core
->sink_inputs
, i
, NULL
);
500 if (pa_idxset_remove_by_data(i
->sink
->inputs
, i
, NULL
))
501 pa_sink_input_unref(i
);
504 pa_idxset_remove_by_data(i
->client
->sink_inputs
, i
, NULL
);
506 while ((o
= pa_idxset_first(i
->direct_outputs
, NULL
))) {
508 pa_source_output_kill(o
);
512 update_n_corked(i
, PA_SINK_INPUT_UNLINKED
);
513 i
->state
= PA_SINK_INPUT_UNLINKED
;
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
);
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);
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
);
532 pa_sink_update_status(i
->sink
);
536 pa_core_maybe_vacuum(i
->core
);
538 pa_sink_input_unref(i
);
541 /* Called from main context */
542 static void sink_input_free(pa_object
*o
) {
543 pa_sink_input
* i
= PA_SINK_INPUT(o
);
546 pa_assert_ctl_context();
547 pa_assert(pa_sink_input_refcnt(i
) == 0);
549 if (PA_SINK_INPUT_IS_LINKED(i
->state
))
550 pa_sink_input_unlink(i
);
552 pa_log_info("Freeing input %u \"%s\"", i
->index
, pa_strnull(pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
)));
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! */
559 if (i
->thread_info
.render_memblockq
)
560 pa_memblockq_free(i
->thread_info
.render_memblockq
);
562 if (i
->thread_info
.resampler
)
563 pa_resampler_free(i
->thread_info
.resampler
);
566 pa_proplist_free(i
->proplist
);
568 if (i
->direct_outputs
)
569 pa_idxset_free(i
->direct_outputs
, NULL
, NULL
);
571 if (i
->thread_info
.direct_outputs
)
572 pa_hashmap_free(i
->thread_info
.direct_outputs
, NULL
, NULL
);
578 /* Called from main context */
579 void pa_sink_input_put(pa_sink_input
*i
) {
580 pa_sink_input_state_t state
;
582 pa_sink_input_assert_ref(i
);
583 pa_assert_ctl_context();
585 pa_assert(i
->state
== PA_SINK_INPUT_INIT
);
587 /* The following fields must be initialized properly */
589 pa_assert(i
->process_rewind
);
592 state
= i
->flags
& PA_SINK_INPUT_START_CORKED
? PA_SINK_INPUT_CORKED
: PA_SINK_INPUT_RUNNING
;
594 update_n_corked(i
, state
);
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
);
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
));
606 set_real_ratio(i
, &i
->volume
);
609 i
->thread_info
.soft_volume
= i
->soft_volume
;
610 i
->thread_info
.muted
= i
->muted
;
612 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
->sink
), PA_SINK_MESSAGE_ADD_INPUT
, i
, 0, NULL
) == 0);
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
);
617 pa_sink_update_status(i
->sink
);
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
));
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 };
633 pa_sink_input_assert_ref(i
);
634 pa_assert_ctl_context();
635 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
637 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_GET_LATENCY
, r
, 0, NULL
) == 0);
640 r
[0] += i
->get_latency(i
);
643 *sink_latency
= r
[1];
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
;
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
));
662 /* pa_log_debug("peek"); */
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
);
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
);
672 block_size_max_sink
= pa_frame_align(pa_mempool_block_size_max(i
->core
->mempool
), &i
->sink
->sample_spec
);
674 /* Default buffer size */
676 slength
= pa_frame_align(CONVERT_BUFFER_LENGTH
, &i
->sink
->sample_spec
);
678 if (slength
> block_size_max_sink
)
679 slength
= block_size_max_sink
;
681 if (i
->thread_info
.resampler
) {
682 ilength
= pa_resampler_request(i
->thread_info
.resampler
, slength
);
685 ilength
= pa_frame_align(CONVERT_BUFFER_LENGTH
, &i
->sample_spec
);
689 if (ilength
> block_size_max_sink_input
)
690 ilength
= block_size_max_sink_input
;
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 */
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
);
700 while (!pa_memblockq_is_readable(i
->thread_info
.render_memblockq
)) {
703 /* There's nothing in our render queue. We need to fill it up
704 * with data from the implementor. */
706 if (i
->thread_info
.state
== PA_SINK_INPUT_CORKED
||
707 i
->pop(i
, ilength
, &tchunk
) < 0) {
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);
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
;
720 pa_atomic_store(&i
->thread_info
.drained
, 0);
722 pa_assert(tchunk
.length
> 0);
723 pa_assert(tchunk
.memblock
);
725 i
->thread_info
.underrun_for
= 0;
726 i
->thread_info
.playing_for
+= tchunk
.length
;
728 while (tchunk
.length
> 0) {
730 pa_bool_t nvfs
= need_volume_factor_sink
;
733 pa_memblock_ref(wchunk
.memblock
);
735 if (wchunk
.length
> block_size_max_sink_input
)
736 wchunk
.length
= block_size_max_sink_input
;
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);
742 if (i
->thread_info
.muted
) {
743 pa_silence_memchunk(&wchunk
, &i
->thread_info
.sample_spec
);
746 } else if (!i
->thread_info
.resampler
&& nvfs
) {
749 /* If we don't need a resampler we can merge the
750 * post and the pre volume adjustment into one */
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
);
757 pa_volume_memchunk(&wchunk
, &i
->thread_info
.sample_spec
, &i
->thread_info
.soft_volume
);
760 if (!i
->thread_info
.resampler
) {
763 pa_memchunk_make_writable(&wchunk
, 0);
764 pa_volume_memchunk(&wchunk
, &i
->sink
->sample_spec
, &i
->volume_factor_sink
);
767 pa_memblockq_push_align(i
->thread_info
.render_memblockq
, &wchunk
);
770 pa_resampler_run(i
->thread_info
.resampler
, &wchunk
, &rchunk
);
772 /* pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */
774 if (rchunk
.memblock
) {
777 pa_memchunk_make_writable(&rchunk
, 0);
778 pa_volume_memchunk(&rchunk
, &i
->sink
->sample_spec
, &i
->volume_factor_sink
);
781 pa_memblockq_push_align(i
->thread_info
.render_memblockq
, &rchunk
);
782 pa_memblock_unref(rchunk
.memblock
);
786 pa_memblock_unref(wchunk
.memblock
);
788 tchunk
.index
+= wchunk
.length
;
789 tchunk
.length
-= wchunk
.length
;
792 pa_memblock_unref(tchunk
.memblock
);
795 pa_assert_se(pa_memblockq_peek(i
->thread_info
.render_memblockq
, chunk
) >= 0);
797 pa_assert(chunk
->length
> 0);
798 pa_assert(chunk
->memblock
);
800 /* pa_log_debug("peeking %lu", (unsigned long) chunk->length); */
802 if (chunk
->length
> block_size_max_sink
)
803 chunk
->length
= block_size_max_sink
;
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 */
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
);
815 *volume
= i
->thread_info
.soft_volume
;
818 /* Called from thread context */
819 void pa_sink_input_drop(pa_sink_input
*i
, size_t nbytes
/* in sink sample spec */) {
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);
827 /* pa_log_debug("dropping %lu", (unsigned long) nbytes); */
829 pa_memblockq_drop(i
->thread_info
.render_memblockq
, nbytes
);
832 /* Called from thread context */
833 void pa_sink_input_process_rewind(pa_sink_input
*i
, size_t nbytes
/* in sink sample spec */) {
835 pa_bool_t called
= FALSE
;
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
));
842 /* pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes); */
844 lbq
= pa_memblockq_get_length(i
->thread_info
.render_memblockq
);
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
);
851 if (i
->thread_info
.rewrite_nbytes
== (size_t) -1) {
853 /* We were asked to drop all buffered data, and rerequest new
854 * data from implementor the next time push() is called */
856 pa_memblockq_flush_write(i
->thread_info
.render_memblockq
, TRUE
);
858 } else if (i
->thread_info
.rewrite_nbytes
> 0) {
859 size_t max_rewrite
, amount
;
861 /* Calculate how much make sense to rewrite at most */
862 max_rewrite
= nbytes
+ lbq
;
864 /* Transform into local domain */
865 if (i
->thread_info
.resampler
)
866 max_rewrite
= pa_resampler_request(i
->thread_info
.resampler
, max_rewrite
);
868 /* Calculate how much of the rewinded data should actually be rewritten */
869 amount
= PA_MIN(i
->thread_info
.rewrite_nbytes
, max_rewrite
);
872 pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount
);
874 /* Tell the implementor */
875 if (i
->process_rewind
)
876 i
->process_rewind(i
, amount
);
879 /* Convert back to to sink domain */
880 if (i
->thread_info
.resampler
)
881 amount
= pa_resampler_result(i
->thread_info
.resampler
, amount
);
884 /* Ok, now update the write pointer */
885 pa_memblockq_seek(i
->thread_info
.render_memblockq
, - ((int64_t) amount
), PA_SEEK_RELATIVE
, TRUE
);
887 if (i
->thread_info
.rewrite_flush
)
888 pa_memblockq_silence(i
->thread_info
.render_memblockq
);
890 /* And reset the resampler */
891 if (i
->thread_info
.resampler
)
892 pa_resampler_reset(i
->thread_info
.resampler
);
897 if (i
->process_rewind
)
898 i
->process_rewind(i
, 0);
900 i
->thread_info
.rewrite_nbytes
= 0;
901 i
->thread_info
.rewrite_flush
= FALSE
;
902 i
->thread_info
.dont_rewind_render
= FALSE
;
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
);
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
;
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
);
918 /* We're not verifying the status here, to allow this to be called
919 * in the state change handler between _INIT and _RUNNING */
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
;
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
));
931 pa_memblockq_set_maxrewind(i
->thread_info
.render_memblockq
, nbytes
);
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
);
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
));
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
);
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
);
953 if (!(i
->sink
->flags
& PA_SINK_DYNAMIC_LATENCY
))
954 usec
= i
->sink
->thread_info
.fixed_latency
;
956 if (usec
!= (pa_usec_t
) -1)
957 usec
= PA_CLAMP(usec
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
959 i
->thread_info
.requested_sink_latency
= usec
;
960 pa_sink_invalidate_requested_latency(i
->sink
, TRUE
);
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();
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);
975 /* If this sink input is not realized yet or we are being moved,
976 * we have to touch the thread info data directly */
979 if (!(i
->sink
->flags
& PA_SINK_DYNAMIC_LATENCY
))
980 usec
= pa_sink_get_fixed_latency(i
->sink
);
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
);
989 i
->thread_info
.requested_sink_latency
= usec
;
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();
999 if (PA_SINK_INPUT_IS_LINKED(i
->state
) && i
->sink
) {
1001 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY
, &usec
, 0, NULL
) == 0);
1005 /* If this sink input is not realized yet or we are being moved,
1006 * we have to touch the thread info data directly */
1008 return i
->thread_info
.requested_sink_latency
;
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
) {
1015 pa_sink_input_assert_ref(i
);
1016 pa_assert_ctl_context();
1017 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
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
);
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
);
1027 if (pa_cvolume_compatible(volume
, &i
->sample_spec
))
1028 volume
= pa_sw_cvolume_multiply(&v
, &v
, volume
);
1030 volume
= pa_sw_cvolume_multiply_scalar(&v
, &v
, pa_cvolume_max(volume
));
1032 if (!pa_cvolume_compatible(volume
, &i
->sample_spec
)) {
1034 volume
= pa_cvolume_scale(&v
, pa_cvolume_max(volume
));
1038 if (pa_cvolume_equal(volume
, &i
->volume
)) {
1039 i
->save_volume
= i
->save_volume
|| save
;
1043 i
->volume
= *volume
;
1044 i
->save_volume
= save
;
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 */
1050 pa_sink_set_volume(i
->sink
, NULL
, TRUE
, save
);
1053 /* OK, we are in normal volume mode. The volume only affects
1055 set_real_ratio(i
, volume
);
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);
1061 /* The volume changed, let's tell people so */
1062 if (i
->volume_changed
)
1063 i
->volume_changed(i
);
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
);
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
));
1076 /* This basically calculates:
1078 * i->real_ratio := v
1079 * i->soft_volume := i->real_ratio * i->volume_factor */
1084 pa_cvolume_reset(&i
->real_ratio
, i
->sample_spec
.channels
);
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 */
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();
1095 return !(i
->flags
& PA_SINK_INPUT_PASSTHROUGH
);
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
));
1105 if (absolute
|| !pa_sink_flat_volume_enabled(i
->sink
))
1106 *volume
= i
->volume
;
1108 *volume
= i
->reference_ratio
;
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
));
1119 if (!i
->muted
== !mute
) {
1120 i
->save_muted
= i
->save_muted
|| mute
;
1125 i
->save_muted
= save
;
1127 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE
, NULL
, 0, NULL
) == 0);
1129 /* The mute status changed, let's tell people so */
1130 if (i
->mute_changed
)
1133 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
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
));
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();
1151 pa_proplist_update(i
->proplist
, mode
, p
);
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
);
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
));
1165 sink_input_set_state(i
, b
? PA_SINK_INPUT_CORKED
: PA_SINK_INPUT_RUNNING
);
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
);
1175 if (i
->sample_spec
.rate
== rate
)
1178 i
->sample_spec
.rate
= rate
;
1180 pa_asyncmsgq_post(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
), PA_SINK_INPUT_MESSAGE_SET_RATE
, PA_UINT_TO_PTR(rate
), 0, NULL
, NULL
);
1182 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1186 /* Called from main context */
1187 void pa_sink_input_set_name(pa_sink_input
*i
, const char *name
) {
1189 pa_sink_input_assert_ref(i
);
1190 pa_assert_ctl_context();
1192 if (!name
&& !pa_proplist_contains(i
->proplist
, PA_PROP_MEDIA_NAME
))
1195 old
= pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
);
1197 if (old
&& name
&& pa_streq(old
, name
))
1201 pa_proplist_sets(i
->proplist
, PA_PROP_MEDIA_NAME
, name
);
1203 pa_proplist_unset(i
->proplist
, PA_PROP_MEDIA_NAME
);
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
);
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();
1216 return i
->actual_resample_method
;
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
));
1225 if (i
->flags
& PA_SINK_INPUT_DONT_MOVE
)
1228 if (i
->sync_next
|| i
->sync_prev
) {
1229 pa_log_warn("Moving synchronized streams not supported.");
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
);
1243 if (dest
== i
->sink
)
1246 if (!pa_sink_input_may_move(i
))
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.");
1254 if (check_passthrough_connection(i
->flags
, dest
) < 0)
1258 if (!i
->may_move_to(i
, dest
))
1264 /* Called from main context */
1265 int pa_sink_input_start_move(pa_sink_input
*i
) {
1266 pa_source_output
*o
, *p
= NULL
;
1269 pa_sink_input_assert_ref(i
);
1270 pa_assert_ctl_context();
1271 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1274 if (!pa_sink_input_may_move(i
))
1275 return -PA_ERR_NOTSUPPORTED
;
1277 if ((r
= pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_MOVE_START
], i
)) < 0)
1280 /* Kill directly connected outputs */
1281 while ((o
= pa_idxset_first(i
->direct_outputs
, NULL
))) {
1283 pa_source_output_kill(o
);
1286 pa_assert(pa_idxset_isempty(i
->direct_outputs
));
1288 pa_idxset_remove_by_data(i
->sink
->inputs
, i
, NULL
);
1290 if (pa_sink_input_get_state(i
) == PA_SINK_INPUT_CORKED
)
1291 pa_assert_se(i
->sink
->n_corked
-- >= 1);
1293 if (pa_sink_flat_volume_enabled(i
->sink
))
1294 /* We might need to update the sink's volume if we are in flat
1296 pa_sink_set_volume(i
->sink
, NULL
, FALSE
, FALSE
);
1298 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
->sink
), PA_SINK_MESSAGE_START_MOVE
, i
, 0, NULL
) == 0);
1300 pa_sink_update_status(i
->sink
);
1301 pa_cvolume_remap(&i
->volume_factor_sink
, &i
->sink
->channel_map
, &i
->channel_map
);
1304 pa_sink_input_unref(i
);
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
;
1317 pa_assert(i
->sink
); /* The destination sink should already be set. */
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
;
1324 while (root_sink
->flags
& PA_SINK_SHARE_VOLUME_WITH_MASTER
)
1325 root_sink
= root_sink
->input_to_master
->sink
;
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:
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) */
1343 pa_assert(pa_cvolume_is_norm(&i
->real_ratio
));
1344 pa_assert(pa_cvolume_equal(&i
->soft_volume
, &i
->volume_factor
));
1346 /* Notifications will be sent by pa_sink_set_volume(). */
1349 /* Ok, so the origin sink uses volume sharing, and flat volume is
1350 * disabled. The volume will have to be updated as follows:
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) */
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
));
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
);
1373 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1377 /* Additionally, the origin sink volume needs updating:
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) */
1385 old_volume
= i
->origin_sink
->reference_volume
;
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
);
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
);
1393 pa_assert(pa_cvolume_is_norm(&i
->origin_sink
->soft_volume
));
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
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
);
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
);
1410 old_volume
= i
->volume
;
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:
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) */
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
);
1428 /* Ok, so this is a regular stream, and flat volume is disabled.
1429 * The volume will have to be updated as follows:
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 */
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
);
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
);
1449 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
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
);
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
;
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
);
1469 if (!pa_sink_input_may_move_to(i
, dest
))
1470 return -PA_ERR_NOTSUPPORTED
;
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
))
1476 /* Try to reuse the old resampler if possible */
1477 new_resampler
= i
->thread_info
.resampler
;
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
)) {
1483 /* Okey, we need a new resampler for the new sink */
1485 if (!(new_resampler
= pa_resampler_new(
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
;
1497 new_resampler
= NULL
;
1503 i
->save_sink
= save
;
1504 pa_idxset_put(dest
->inputs
, pa_sink_input_ref(i
), NULL
);
1506 pa_cvolume_remap(&i
->volume_factor_sink
, &i
->channel_map
, &i
->sink
->channel_map
);
1508 if (pa_sink_input_get_state(i
) == PA_SINK_INPUT_CORKED
)
1509 i
->sink
->n_corked
++;
1511 /* Replace resampler and render queue */
1512 if (new_resampler
!= i
->thread_info
.resampler
) {
1514 if (i
->thread_info
.resampler
)
1515 pa_resampler_free(i
->thread_info
.resampler
);
1516 i
->thread_info
.resampler
= new_resampler
;
1518 pa_memblockq_free(i
->thread_info
.render_memblockq
);
1520 i
->thread_info
.render_memblockq
= pa_memblockq_new(
1522 MEMBLOCKQ_MAXLENGTH
,
1524 pa_frame_size(&i
->sink
->sample_spec
),
1530 pa_sink_update_status(dest
);
1532 update_volume_due_to_moving(i
, dest
);
1534 pa_assert_se(pa_asyncmsgq_send(i
->sink
->asyncmsgq
, PA_MSGOBJECT(i
->sink
), PA_SINK_MESSAGE_FINISH_MOVE
, i
, 0, NULL
) == 0);
1536 pa_log_debug("Successfully moved sink input %i to %s.", i
->index
, dest
->name
);
1538 /* Notify everyone */
1539 pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH
], i
);
1541 pa_subscription_post(i
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, i
->index
);
1546 /* Called from main context */
1547 void pa_sink_input_fail_move(pa_sink_input
*i
) {
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
);
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
)
1561 pa_sink_input_kill(i
);
1564 /* Called from main context */
1565 int pa_sink_input_move_to(pa_sink_input
*i
, pa_sink
*dest
, pa_bool_t save
) {
1568 pa_sink_input_assert_ref(i
);
1569 pa_assert_ctl_context();
1570 pa_assert(PA_SINK_INPUT_IS_LINKED(i
->state
));
1572 pa_sink_assert_ref(dest
);
1574 if (dest
== i
->sink
)
1577 if (!pa_sink_input_may_move_to(i
, dest
))
1578 return -PA_ERR_NOTSUPPORTED
;
1580 pa_sink_input_ref(i
);
1582 if ((r
= pa_sink_input_start_move(i
)) < 0) {
1583 pa_sink_input_unref(i
);
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
);
1593 pa_sink_input_unref(i
);
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
;
1602 pa_sink_input_assert_ref(i
);
1603 pa_sink_input_assert_io_context(i
);
1605 if (state
== i
->thread_info
.state
)
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);
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
;
1615 if (i
->state_change
)
1616 i
->state_change(i
, state
);
1618 i
->thread_info
.state
= state
;
1622 pa_log_debug("Requesting rewind due to corking");
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
);
1628 } else if (uncorking
) {
1630 i
->thread_info
.underrun_for
= (uint64_t) -1;
1631 i
->thread_info
.playing_for
= 0;
1633 pa_log_debug("Requesting rewind due to uncorking");
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
);
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
);
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
);
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
);
1662 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1663 pa_usec_t
*r
= userdata
;
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
);
1671 case PA_SINK_INPUT_MESSAGE_SET_RATE
:
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
));
1678 case PA_SINK_INPUT_MESSAGE_SET_STATE
: {
1679 pa_sink_input
*ssync
;
1681 pa_sink_input_set_state_within_thread(i
, PA_PTR_TO_UINT(userdata
));
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
));
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
));
1692 case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY
: {
1693 pa_usec_t
*usec
= userdata
;
1695 *usec
= pa_sink_input_set_requested_latency_within_thread(i
, *usec
);
1699 case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY
: {
1700 pa_usec_t
*r
= userdata
;
1702 *r
= i
->thread_info
.requested_sink_latency
;
1707 return -PA_ERR_NOTIMPLEMENTED
;
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();
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
;
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
);
1726 if (PA_SINK_INPUT_IS_LINKED(i
->thread_info
.state
))
1727 return pa_memblockq_is_empty(i
->thread_info
.render_memblockq
);
1732 /* Called from IO context */
1733 void pa_sink_input_request_rewind(
1735 size_t nbytes
/* in our sample spec */,
1738 pa_bool_t dont_rewind_render
) {
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.
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
1754 /* nbytes = 0 means maximum rewind request */
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
);
1761 /* We don't take rewind requests while we are corked */
1762 if (i
->thread_info
.state
== PA_SINK_INPUT_CORKED
)
1765 nbytes
= PA_MAX(i
->thread_info
.rewrite_nbytes
, nbytes
);
1767 /* pa_log_debug("request rewrite %zu", nbytes); */
1769 /* Calculate how much we can rewind locally without having to
1772 lbq
= pa_memblockq_get_length(i
->thread_info
.render_memblockq
);
1776 /* Check if rewinding for the maximum is requested, and if so, fix up */
1779 /* Calculate maximum number of bytes that could be rewound in theory */
1780 nbytes
= i
->sink
->thread_info
.max_rewind
+ lbq
;
1782 /* Transform from sink domain */
1783 if (i
->thread_info
.resampler
)
1784 nbytes
= pa_resampler_request(i
->thread_info
.resampler
, nbytes
);
1787 /* Remember how much we actually want to rewrite */
1788 if (i
->thread_info
.rewrite_nbytes
!= (size_t) -1) {
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
;
1794 i
->thread_info
.rewrite_nbytes
= nbytes
;
1796 i
->thread_info
.rewrite_nbytes
= (size_t) -1;
1799 i
->thread_info
.rewrite_flush
=
1800 i
->thread_info
.rewrite_flush
||
1801 (flush
&& i
->thread_info
.rewrite_nbytes
!= 0);
1803 i
->thread_info
.dont_rewind_render
=
1804 i
->thread_info
.dont_rewind_render
||
1807 if (nbytes
!= (size_t) -1) {
1809 /* Transform to sink domain */
1810 if (i
->thread_info
.resampler
)
1811 nbytes
= pa_resampler_result(i
->thread_info
.resampler
, nbytes
);
1814 pa_sink_request_rewind(i
->sink
, nbytes
- lbq
);
1816 /* This call will make sure process_rewind() is called later */
1817 pa_sink_request_rewind(i
->sink
, 0);
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();
1827 /* FIXME: Shouldn't access resampler object from main context! */
1829 pa_silence_memchunk_get(
1830 &i
->core
->silence_cache
,
1834 i
->thread_info
.resampler
? pa_resampler_max_block_size(i
->thread_info
.resampler
) : 0);
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
;
1844 pa_sink_input_assert_ref(i
);
1845 pa_assert_ctl_context();
1852 data
= pl
= pa_proplist_new();
1854 hook_data
.sink_input
= i
;
1855 hook_data
.data
= data
;
1856 hook_data
.event
= event
;
1858 if (pa_hook_fire(&i
->core
->hooks
[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT
], &hook_data
) < 0)
1861 i
->send_event(i
, event
, data
);
1865 pa_proplist_free(pl
);