diff options
Diffstat (limited to 'src/pulsecore/sink-input.c')
-rw-r--r-- | src/pulsecore/sink-input.c | 179 |
1 files changed, 90 insertions, 89 deletions
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index d4d11194..df42cae8 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -72,18 +72,11 @@ void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const data->channel_map = *map; } -void pa_sink_input_new_data_set_soft_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) { +void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) { pa_assert(data); - if ((data->soft_volume_is_set = !!volume)) - data->soft_volume = *volume; -} - -void pa_sink_input_new_data_set_virtual_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) { - pa_assert(data); - - if ((data->virtual_volume_is_set = !!volume)) - data->virtual_volume = *volume; + if ((data->volume_is_set = !!volume)) + data->volume = *volume; } void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) { @@ -120,7 +113,8 @@ static void reset_callbacks(pa_sink_input *i) { } /* Called from main context */ -pa_sink_input* pa_sink_input_new( +int pa_sink_input_new( + pa_sink_input **_i, pa_core *core, pa_sink_input_new_data *data, pa_sink_input_flags_t flags) { @@ -129,28 +123,34 @@ pa_sink_input* pa_sink_input_new( pa_resampler *resampler = NULL; char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_channel_map original_cm; + int r; + pa_assert(_i); pa_assert(core); pa_assert(data); - if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data) < 0) - return NULL; + if (data->client) + pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist); - pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver)); + if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0) + return r; + + pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID); if (!data->sink) { data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK); data->save_sink = FALSE; } - pa_return_null_if_fail(data->sink); - pa_return_null_if_fail(pa_sink_get_state(data->sink) != PA_SINK_UNLINKED); - pa_return_null_if_fail(!data->sync_base || (data->sync_base->sink == data->sink && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED)); + pa_return_val_if_fail(data->sink, -PA_ERR_NOENTITY); + pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)), -PA_ERR_BADSTATE); + 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); + pa_return_val_if_fail(!(flags & PA_SINK_INPUT_FAIL_ON_SUSPEND) || pa_sink_get_state(data->sink) != PA_SINK_SUSPENDED, -PA_ERR_BADSTATE); if (!data->sample_spec_is_set) data->sample_spec = data->sink->sample_spec; - pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec)); + pa_return_val_if_fail(pa_sample_spec_valid(&data->sample_spec), -PA_ERR_INVALID); if (!data->channel_map_is_set) { if (pa_channel_map_compatible(&data->sink->channel_map, &data->sample_spec)) @@ -159,38 +159,23 @@ pa_sink_input* pa_sink_input_new( pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); } - pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map)); - pa_return_null_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec)); + pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID); + pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID); - if (!data->virtual_volume_is_set) { + if (!data->volume_is_set) { if (data->sink->flags & PA_SINK_FLAT_VOLUME) { - data->virtual_volume = data->sink->virtual_volume; - pa_cvolume_remap(&data->virtual_volume, &data->sink->channel_map, &data->channel_map); + data->volume = *pa_sink_get_volume(data->sink, FALSE); + pa_cvolume_remap(&data->volume, &data->sink->channel_map, &data->channel_map); } else - pa_cvolume_reset(&data->virtual_volume, data->sample_spec.channels); + pa_cvolume_reset(&data->volume, data->sample_spec.channels); data->save_volume = FALSE; - } else if (!data->virtual_volume_is_absolute) { - - /* When the 'absolute' bool is set then we'll treat the volume - * as relative to the sink volume even in flat volume mode */ - if (data->sink->flags & PA_SINK_FLAT_VOLUME) { - pa_cvolume t = data->sink->virtual_volume; - pa_cvolume_remap(&t, &data->sink->channel_map, &data->channel_map); - pa_sw_cvolume_multiply(&data->virtual_volume, &data->virtual_volume, &t); - } } - pa_return_null_if_fail(pa_cvolume_valid(&data->virtual_volume)); - pa_return_null_if_fail(pa_cvolume_compatible(&data->virtual_volume, &data->sample_spec)); - - if (!data->soft_volume_is_set) - data->soft_volume = data->virtual_volume; - - pa_return_null_if_fail(pa_cvolume_valid(&data->soft_volume)); - pa_return_null_if_fail(pa_cvolume_compatible(&data->soft_volume, &data->sample_spec)); + pa_return_val_if_fail(pa_cvolume_valid(&data->volume), -PA_ERR_INVALID); + pa_return_val_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec), -PA_ERR_INVALID); if (!data->muted_is_set) data->muted = FALSE; @@ -212,23 +197,19 @@ pa_sink_input* pa_sink_input_new( pa_assert(pa_channel_map_valid(&data->channel_map)); /* Due to the fixing of the sample spec the volume might not match anymore */ - pa_cvolume_remap(&data->soft_volume, &original_cm, &data->channel_map); - pa_cvolume_remap(&data->virtual_volume, &original_cm, &data->channel_map); + pa_cvolume_remap(&data->volume, &original_cm, &data->channel_map); if (data->resample_method == PA_RESAMPLER_INVALID) data->resample_method = core->resample_method; - pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX); - - if (data->client) - pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist); + pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID); - if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data) < 0) - return NULL; + if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0) + return r; if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) { pa_log_warn("Failed to create sink input: too many inputs per sink."); - return NULL; + return -PA_ERR_TOOLARGE; } if ((flags & PA_SINK_INPUT_VARIABLE_RATE) || @@ -245,7 +226,7 @@ pa_sink_input* pa_sink_input_new( (core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) | (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) { pa_log_warn("Unsupported resampling operation."); - return NULL; + return -PA_ERR_NOTSUPPORTED; } } @@ -267,8 +248,18 @@ pa_sink_input* pa_sink_input_new( i->sample_spec = data->sample_spec; i->channel_map = data->channel_map; - i->virtual_volume = data->virtual_volume; - i->soft_volume = data->soft_volume; + if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !data->volume_is_absolute) { + /* When the 'absolute' bool is not set then we'll treat the volume + * as relative to the sink volume even in flat volume mode */ + + pa_cvolume t = *pa_sink_get_volume(data->sink, FALSE); + pa_cvolume_remap(&t, &data->sink->channel_map, &data->channel_map); + + pa_sw_cvolume_multiply(&i->virtual_volume, &data->volume, &t); + } else + i->virtual_volume = data->volume; + + pa_cvolume_init(&i->soft_volume); i->save_volume = data->save_volume; i->save_sink = data->save_sink; i->save_muted = data->save_muted; @@ -330,7 +321,8 @@ pa_sink_input* pa_sink_input_new( /* Don't forget to call pa_sink_input_put! */ - return i; + *_i = i; + return 0; } /* Called from main context */ @@ -347,7 +339,7 @@ static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) { } /* Called from main context */ -static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) { +static void sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) { pa_sink_input *ssync; pa_assert(i); @@ -355,7 +347,7 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) { state = PA_SINK_INPUT_RUNNING; if (i->state == state) - return 0; + return; 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); @@ -382,8 +374,6 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) { } pa_sink_update_status(i->sink); - - return 0; } /* Called from main context */ @@ -499,9 +489,6 @@ void pa_sink_input_put(pa_sink_input *i) { pa_assert(i->process_rewind); pa_assert(i->kill); - i->thread_info.soft_volume = i->soft_volume; - i->thread_info.muted = i->muted; - state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING; update_n_corked(i, state); @@ -512,7 +499,11 @@ void pa_sink_input_put(pa_sink_input *i) { pa_cvolume new_volume; pa_sink_update_flat_volume(i->sink, &new_volume); pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE); - } + } else + i->soft_volume = i->virtual_volume; + + i->thread_info.soft_volume = i->soft_volume; + i->thread_info.muted = i->muted; pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0); @@ -549,7 +540,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) { } /* Called from thread context */ -int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) { +void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) { pa_bool_t do_volume_adj_here; pa_bool_t volume_is_norm; size_t block_size_max_sink, block_size_max_sink_input; @@ -563,9 +554,6 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa /* pa_log_debug("peek"); */ - if (!i->pop) - return -1; - pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING || i->thread_info.state == PA_SINK_INPUT_CORKED || i->thread_info.state == PA_SINK_INPUT_DRAINED); @@ -692,8 +680,6 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa pa_cvolume_mute(volume, i->sink->sample_spec.channels); else *volume = i->thread_info.soft_volume; - - return 0; } /* Called from thread context */ @@ -960,7 +946,7 @@ void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) { int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) { pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); - pa_return_val_if_fail(i->thread_info.resampler, -1); + pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE); if (i->sample_spec.rate == rate) return 0; @@ -1048,16 +1034,17 @@ pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) { int pa_sink_input_start_move(pa_sink_input *i) { pa_source_output *o, *p = NULL; pa_sink *origin; + int r; pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); pa_assert(i->sink); if (!pa_sink_input_may_move(i)) - return -1; + return -PA_ERR_NOTSUPPORTED; - if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i) < 0) - return -1; + if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0) + return r; origin = i->sink; @@ -1074,9 +1061,15 @@ int pa_sink_input_start_move(pa_sink_input *i) { if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED) pa_assert_se(i->sink->n_corked-- >= 1); - /* We might need to update the sink's volume if we are in flat volume mode. */ if (i->sink->flags & PA_SINK_FLAT_VOLUME) { pa_cvolume new_volume; + + /* Make the absolute volume relative */ + i->virtual_volume = i->soft_volume; + pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels); + + /* We might need to update the sink's volume if we are in flat + * volume mode. */ pa_sink_update_flat_volume(i->sink, &new_volume); pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE); } @@ -1099,14 +1092,7 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { pa_sink_assert_ref(dest); if (!pa_sink_input_may_move_to(i, dest)) - return -1; - - i->sink = dest; - i->save_sink = save; - pa_idxset_put(dest->inputs, i, NULL); - - if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED) - i->sink->n_corked++; + return -PA_ERR_NOTSUPPORTED; if (i->thread_info.resampler && pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &dest->sample_spec) && @@ -1130,11 +1116,18 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { pa_log_warn("Unsupported resampling operation."); - return -1; + return -PA_ERR_NOTSUPPORTED; } } else new_resampler = NULL; + i->sink = dest; + i->save_sink = save; + pa_idxset_put(dest->inputs, i, NULL); + + if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED) + i->sink->n_corked++; + /* Replace resampler and render queue */ if (new_resampler != i->thread_info.resampler) { @@ -1157,9 +1150,15 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { pa_sink_update_status(dest); - /* We might need to update the sink's volume if we are in flat volume mode. */ if (i->sink->flags & PA_SINK_FLAT_VOLUME) { pa_cvolume new_volume; + + /* Make relative volume absolute again */ + pa_cvolume t = dest->virtual_volume; + pa_cvolume_remap(&t, &dest->channel_map, &i->channel_map); + pa_sw_cvolume_multiply(&i->virtual_volume, &i->virtual_volume, &t); + + /* We might need to update the sink's volume if we are in flat volume mode. */ pa_sink_update_flat_volume(i->sink, &new_volume); pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE); } @@ -1180,6 +1179,8 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { /* Called from main context */ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { + int r; + pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); pa_assert(i->sink); @@ -1189,13 +1190,13 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { return 0; if (!pa_sink_input_may_move_to(i, dest)) - return -1; + return -PA_ERR_NOTSUPPORTED; - if (pa_sink_input_start_move(i) < 0) - return -1; + if ((r = pa_sink_input_start_move(i)) < 0) + return r; - if (pa_sink_input_finish_move(i, dest, save) < 0) - return -1; + if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) + return r; return 0; } @@ -1310,7 +1311,7 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t } } - return -1; + return -PA_ERR_NOTIMPLEMENTED; } /* Called from main thread */ |