mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-04 13:29:59 -05:00
virtual-source-common: Integrate uplink sink into virtual source library
This patch integrates the uplink sink feature of module-virtual-source into the virtual source library, so that every virtual source can use it. The patch also introduces latency handling and rewinding for the uplink sink. Similar to the monitor source, the only useful definition of the latency appears to be the negative of the master source latency. Rewinding will not be possible in most situations, because the underlying memblockq is nearly always empty. module-combine-sink and module-suspend-on-idle required some changes to deal correctly with this type of sink.
This commit is contained in:
parent
0b26ed9b0c
commit
9f70ad3c95
10 changed files with 512 additions and 249 deletions
|
|
@ -71,7 +71,7 @@ static void timeout_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval
|
|||
pa_core_maybe_vacuum(d->userdata->core);
|
||||
}
|
||||
|
||||
if (d->source && pa_source_check_suspend(d->source, NULL) <= 0 && !(d->source->suspend_cause & PA_SUSPEND_IDLE)) {
|
||||
if (d->source && pa_source_check_suspend(d->source, NULL, NULL) <= 0 && !(d->source->suspend_cause & PA_SUSPEND_IDLE)) {
|
||||
pa_log_info("Source %s idle for too long, suspending ...", d->source->name);
|
||||
pa_source_suspend(d->source, true, PA_SUSPEND_IDLE);
|
||||
pa_core_maybe_vacuum(d->userdata->core);
|
||||
|
|
@ -109,6 +109,29 @@ static void resume(struct device_info *d) {
|
|||
}
|
||||
}
|
||||
|
||||
/* If the monitor source of a sink becomes idle and the sink is
|
||||
* idle as well, we have to check if it is an uplink sink because
|
||||
* the underlying virtual source might also have become idle. */
|
||||
static void restart_check_uplink(struct device_info *d, pa_source_output *ignore, struct userdata *u) {
|
||||
struct device_info *d_master;
|
||||
|
||||
pa_assert(d);
|
||||
pa_assert(u);
|
||||
|
||||
restart(d);
|
||||
|
||||
if (!d->sink || (d->sink && !d->sink->uplink_of))
|
||||
return;
|
||||
|
||||
if (!d->sink->uplink_of->source)
|
||||
return;
|
||||
|
||||
if ((d_master = pa_hashmap_get(u->device_infos, d->sink->uplink_of->source))) {
|
||||
if (pa_source_check_suspend(d_master->source, NULL, ignore) <= 0)
|
||||
restart(d_master);
|
||||
}
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_input_fixate_hook_cb(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) {
|
||||
struct device_info *d;
|
||||
|
||||
|
|
@ -145,7 +168,7 @@ static pa_hook_result_t source_output_fixate_hook_cb(pa_core *c, pa_source_outpu
|
|||
if (d) {
|
||||
resume(d);
|
||||
if (d->source) {
|
||||
if (pa_source_check_suspend(d->source, NULL) <= 0)
|
||||
if (pa_source_check_suspend(d->source, NULL, NULL) <= 0)
|
||||
restart(d);
|
||||
} else {
|
||||
/* The source output is connected to a monitor source. */
|
||||
|
|
@ -170,6 +193,13 @@ static pa_hook_result_t sink_input_unlink_hook_cb(pa_core *c, pa_sink_input *s,
|
|||
struct device_info *d;
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink)))
|
||||
restart(d);
|
||||
|
||||
if (s->sink->uplink_of && s->sink->uplink_of->source) {
|
||||
if (pa_source_check_suspend(s->sink->uplink_of->source, s, NULL) <= 0) {
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink->uplink_of->source)))
|
||||
restart(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PA_HOOK_OK;
|
||||
|
|
@ -189,12 +219,12 @@ static pa_hook_result_t source_output_unlink_hook_cb(pa_core *c, pa_source_outpu
|
|||
if (pa_sink_check_suspend(s->source->monitor_of, NULL, s) <= 0)
|
||||
d = pa_hashmap_get(u->device_infos, s->source->monitor_of);
|
||||
} else {
|
||||
if (pa_source_check_suspend(s->source, s) <= 0)
|
||||
if (pa_source_check_suspend(s->source, NULL, s) <= 0)
|
||||
d = pa_hashmap_get(u->device_infos, s->source);
|
||||
}
|
||||
|
||||
if (d)
|
||||
restart(d);
|
||||
restart_check_uplink(d, s, u);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
|
@ -206,10 +236,18 @@ static pa_hook_result_t sink_input_move_start_hook_cb(pa_core *c, pa_sink_input
|
|||
pa_sink_input_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
if (pa_sink_check_suspend(s->sink, s, NULL) <= 0)
|
||||
if (pa_sink_check_suspend(s->sink, s, NULL) <= 0) {
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink)))
|
||||
restart(d);
|
||||
|
||||
if (s->sink->uplink_of && s->sink->uplink_of->source) {
|
||||
if (pa_source_check_suspend(s->sink->uplink_of->source, s, NULL) <= 0) {
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink->uplink_of->source)))
|
||||
restart(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
|
|
@ -240,12 +278,12 @@ static pa_hook_result_t source_output_move_start_hook_cb(pa_core *c, pa_source_o
|
|||
if (pa_sink_check_suspend(s->source->monitor_of, NULL, s) <= 0)
|
||||
d = pa_hashmap_get(u->device_infos, s->source->monitor_of);
|
||||
} else {
|
||||
if (pa_source_check_suspend(s->source, s) <= 0)
|
||||
if (pa_source_check_suspend(s->source, NULL, s) <= 0)
|
||||
d = pa_hashmap_get(u->device_infos, s->source);
|
||||
}
|
||||
|
||||
if (d)
|
||||
restart(d);
|
||||
restart_check_uplink(d, s, u);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
|
@ -278,9 +316,14 @@ static pa_hook_result_t sink_input_state_changed_hook_cb(pa_core *c, pa_sink_inp
|
|||
pa_sink_input_assert_ref(s);
|
||||
pa_assert(u);
|
||||
|
||||
if (s->state == PA_SINK_INPUT_RUNNING && s->sink)
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink)))
|
||||
resume(d);
|
||||
if (s->sink) {
|
||||
if ((d = pa_hashmap_get(u->device_infos, s->sink))) {
|
||||
if (s->state == PA_SINK_INPUT_RUNNING)
|
||||
resume(d);
|
||||
else if (s->state == PA_SINK_INPUT_CORKED && pa_sink_check_suspend(s->sink, NULL, NULL) <= 0)
|
||||
restart(d);
|
||||
}
|
||||
}
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
|
@ -289,9 +332,9 @@ static pa_hook_result_t source_output_state_changed_hook_cb(pa_core *c, pa_sourc
|
|||
pa_assert(c);
|
||||
pa_source_output_assert_ref(s);
|
||||
pa_assert(u);
|
||||
struct device_info *d = NULL;
|
||||
|
||||
if (s->state == PA_SOURCE_OUTPUT_RUNNING && s->source) {
|
||||
struct device_info *d;
|
||||
|
||||
if (s->source->monitor_of)
|
||||
d = pa_hashmap_get(u->device_infos, s->source->monitor_of);
|
||||
|
|
@ -300,6 +343,15 @@ static pa_hook_result_t source_output_state_changed_hook_cb(pa_core *c, pa_sourc
|
|||
|
||||
if (d)
|
||||
resume(d);
|
||||
} else if (s->state == PA_SOURCE_OUTPUT_CORKED && s->source) {
|
||||
|
||||
if (s->source->monitor_of && pa_sink_check_suspend(s->source->monitor_of, NULL, NULL) <= 0)
|
||||
d = pa_hashmap_get(u->device_infos, s->source->monitor_of);
|
||||
else if (pa_source_check_suspend(s->source, NULL, NULL) <= 0)
|
||||
d = pa_hashmap_get(u->device_infos, s->source);
|
||||
|
||||
if (d)
|
||||
restart_check_uplink(d, NULL, u);
|
||||
}
|
||||
|
||||
return PA_HOOK_OK;
|
||||
|
|
@ -349,7 +401,7 @@ static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct user
|
|||
pa_hashmap_put(u->device_infos, o, d);
|
||||
|
||||
if ((d->sink && pa_sink_check_suspend(d->sink, NULL, NULL) <= 0) ||
|
||||
(d->source && pa_source_check_suspend(d->source, NULL) <= 0))
|
||||
(d->source && pa_source_check_suspend(d->source, NULL, NULL) <= 0))
|
||||
restart(d);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
|
|
@ -407,7 +459,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
|
|||
} else if (pa_source_isinstance(o)) {
|
||||
pa_source *s = PA_SOURCE(o);
|
||||
|
||||
if (pa_source_check_suspend(s, NULL) <= 0)
|
||||
if (pa_source_check_suspend(s, NULL, NULL) <= 0)
|
||||
if (PA_SOURCE_IS_OPENED(s->state))
|
||||
restart(d);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue