sink-input: Query sink inputs for max_rewind value when setting max_rewind

This patch is in preparation of allowing virtual sinks to specify their own
max_rewind limit.

Currently pa_sink_set_max_rewind_within_thread() simply sets the value of
max_rewind and informs the sink inputs about the new value. Virtual sinks
may however provide their own limit on max_rewind.

This patch allows to query the active sink inputs for the max_rewind value
they support and sets max_rewind to the minimum supported value. This way,
the max_rewind value from the virtual sinks can be communicated to the master
sink.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/120>
This commit is contained in:
Georg Chini 2021-01-01 00:32:52 +01:00 committed by PulseAudio Marge Bot
parent 5c6d91a97c
commit a37fd7eada
3 changed files with 44 additions and 0 deletions

View file

@ -347,6 +347,7 @@ static void reset_callbacks(pa_sink_input *i) {
i->send_event = NULL;
i->volume_changed = NULL;
i->mute_changed = NULL;
i->get_max_rewind_limit = NULL;
}
/* Called from main context */

View file

@ -156,6 +156,13 @@ struct pa_sink_input {
* changes. Called from IO context. */
void (*update_max_rewind) (pa_sink_input *i, size_t nbytes); /* may be NULL */
/* Called whenever the maximum rewindable size of the sink
* changes. Used by virtual sinks to communicate rewind limits
* of the virtual sink to the master sink. Must return size_t (-1)
* if there is no limit or if the virtual sink is not opened.
* Called from IO context. */
size_t (*get_max_rewind_limit) (pa_sink_input *i); /* may be NULL */
/* Called whenever the maximum request size of the sink
* changes. Called from IO context. */
void (*update_max_request) (pa_sink_input *i, size_t nbytes); /* may be NULL */

View file

@ -2594,6 +2594,40 @@ static void set_shared_volume_within_thread(pa_sink *s) {
}
}
/* Called from IO thread. Gets max_rewind limit from sink inputs.
* This function is used to communicate the max_rewind value of a
* virtual sink to the master sink. The get_max_rewind_limit()
* callback is implemented by sink inputs connecting a virtual
* sink to its master. */
static size_t get_max_rewind_limit(pa_sink *s, size_t requested_limit) {
pa_sink_input *i;
void *state = NULL;
size_t rewind_limit;
pa_assert(s);
/* Get rewind limit in sink sample spec from sink inputs */
rewind_limit = (size_t)(-1);
if (PA_SINK_IS_LINKED(s->thread_info.state)) {
PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
if (i->get_max_rewind_limit) {
size_t limit;
limit = i->get_max_rewind_limit(i);
if (rewind_limit == (size_t)(-1) || rewind_limit > limit)
rewind_limit = limit;
}
}
}
/* Set max_rewind */
if (rewind_limit != (size_t)(-1))
requested_limit = PA_MIN(rewind_limit, requested_limit);
return requested_limit;
}
/* Called from IO thread, except when it is not */
int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
pa_sink *s = PA_SINK(o);
@ -3143,6 +3177,8 @@ void pa_sink_set_max_rewind_within_thread(pa_sink *s, size_t max_rewind) {
pa_sink_assert_ref(s);
pa_sink_assert_io_context(s);
max_rewind = get_max_rewind_limit(s, max_rewind);
if (max_rewind == s->thread_info.max_rewind)
return;