diff options
Diffstat (limited to 'src/pulsecore/sink-input.c')
-rw-r--r-- | src/pulsecore/sink-input.c | 90 |
1 files changed, 68 insertions, 22 deletions
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 1fdb3fa6..b1b9fb56 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -117,6 +117,7 @@ static void reset_callbacks(pa_sink_input *i) { i->attach = NULL; i->detach = NULL; i->suspend = NULL; + i->suspend_within_thread = NULL; i->moving = NULL; i->kill = NULL; i->get_latency = NULL; @@ -287,6 +288,7 @@ int pa_sink_input_new( i->volume_factor = data->volume_factor; pa_cvolume_init(&i->soft_volume); + memset(i->relative_volume, 0, sizeof(i->relative_volume)); i->save_volume = data->save_volume; i->save_sink = data->save_sink; i->save_muted = data->save_muted; @@ -333,8 +335,8 @@ int pa_sink_input_new( 0, &i->sink->silence); - pa_assert_se(pa_idxset_put(core->sink_inputs, pa_sink_input_ref(i), &i->index) == 0); - pa_assert_se(pa_idxset_put(i->sink->inputs, i, NULL) == 0); + pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0); + pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0); if (i->client) pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0); @@ -529,7 +531,7 @@ void pa_sink_input_put(pa_sink_input *i) { pa_sink_update_flat_volume(i->sink, &new_volume); pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE); } else - pa_sw_cvolume_multiply(&i->soft_volume, &i->virtual_volume, &i->volume_factor); + pa_sink_input_set_relative_volume(i, &i->virtual_volume); i->thread_info.soft_volume = i->soft_volume; i->thread_info.muted = i->muted; @@ -822,6 +824,9 @@ void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) { pa_sink_input_assert_ref(i); + if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY)) + usec = i->sink->fixed_latency; + if (usec != (pa_usec_t) -1) usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency); @@ -833,8 +838,6 @@ pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa /* Called from main context */ pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) { - pa_usec_t min_latency, max_latency; - pa_sink_input_assert_ref(i); if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) { @@ -846,10 +849,14 @@ pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) * we have to touch the thread info data directly */ if (i->sink) { - pa_sink_get_latency_range(i->sink, &min_latency, &max_latency); + if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY)) + usec = i->sink->fixed_latency; - if (usec != (pa_usec_t) -1) + if (usec != (pa_usec_t) -1) { + pa_usec_t min_latency, max_latency; + pa_sink_get_latency_range(i->sink, &min_latency, &max_latency); usec = PA_CLAMP(usec, min_latency, max_latency); + } } i->thread_info.requested_sink_latency = usec; @@ -900,11 +907,12 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo /* OK, we are in normal volume mode. The volume only affects * ourselves */ - pa_sw_cvolume_multiply(&i->soft_volume, volume, &i->volume_factor); + pa_sink_input_set_relative_volume(i, volume); /* Hooks have the ability to play games with i->soft_volume */ pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], i); + /* Copy the new soft_volume to the thread_info struct */ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0); } @@ -922,24 +930,50 @@ const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) { /* Called from main context */ pa_cvolume *pa_sink_input_get_relative_volume(pa_sink_input *i, pa_cvolume *v) { + unsigned c; + pa_sink_input_assert_ref(i); pa_assert(v); pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); - *v = i->virtual_volume; - /* This always returns a relative volume, even in flat volume mode */ - if (i->sink->flags & PA_SINK_FLAT_VOLUME) { - pa_cvolume sv; + v->channels = i->sample_spec.channels; + + for (c = 0; c < v->channels; c++) + v->values[c] = pa_sw_volume_from_linear(i->relative_volume[c]); + + return v; +} + +/* Called from main context */ +void pa_sink_input_set_relative_volume(pa_sink_input *i, const pa_cvolume *v) { + unsigned c; + pa_cvolume _v; + + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); + pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec)); - sv = *pa_sink_get_volume(i->sink, FALSE); + if (!v) + v = pa_cvolume_reset(&_v, i->sample_spec.channels); - pa_sw_cvolume_divide(v, v, - pa_cvolume_remap(&sv, &i->sink->channel_map, &i->channel_map)); + /* This basically calculates: + * + * i->relative_volume := v + * i->soft_volume := i->relative_volume * i->volume_factor */ + + i->soft_volume.channels = i->sample_spec.channels; + + for (c = 0; c < i->sample_spec.channels; c++) { + i->relative_volume[c] = pa_sw_volume_to_linear(v->values[c]); + + i->soft_volume.values[c] = pa_sw_volume_from_linear( + i->relative_volume[c] * + pa_sw_volume_to_linear(i->volume_factor.values[c])); } - return v; + /* We don't copy the data to the thread_info data. That's left for someone else to do */ } /* Called from main context */ @@ -1109,9 +1143,11 @@ int pa_sink_input_start_move(pa_sink_input *i) { if (i->sink->flags & PA_SINK_FLAT_VOLUME) { pa_cvolume new_volume; - /* Make the absolute volume relative */ - i->virtual_volume = i->soft_volume; - i->soft_volume = i->volume_factor; + /* Make the virtual volume relative */ + pa_sink_input_get_relative_volume(i, &i->virtual_volume); + + /* And reset the the relative volume */ + pa_sink_input_set_relative_volume(i, NULL); /* We might need to update the sink's volume if we are in flat * volume mode. */ @@ -1124,6 +1160,8 @@ int pa_sink_input_start_move(pa_sink_input *i) { pa_sink_update_status(i->sink); i->sink = NULL; + pa_sink_input_unref(i); + return 0; } @@ -1171,7 +1209,7 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { i->sink = dest; i->save_sink = save; - pa_idxset_put(dest->inputs, i, NULL); + pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL); if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED) i->sink->n_corked++; @@ -1236,11 +1274,19 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { if (!pa_sink_input_may_move_to(i, dest)) return -PA_ERR_NOTSUPPORTED; - if ((r = pa_sink_input_start_move(i)) < 0) + pa_sink_input_ref(i); + + if ((r = pa_sink_input_start_move(i)) < 0) { + pa_sink_input_unref(i); return r; + } - if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) + if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) { + pa_sink_input_unref(i); return r; + } + + pa_sink_input_unref(i); return 0; } |