mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-04 13:29:59 -05:00
device-manager: Keep a cache of the highest priority devices for each role.
Rather than querying our database on every new stream, we keep a cache and only update it when a sink/source is added/removed.
This commit is contained in:
parent
009d087f86
commit
df893f6d72
1 changed files with 52 additions and 47 deletions
|
|
@ -72,6 +72,21 @@ static const char* const valid_modargs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
#define NUM_ROLES 9
|
||||
enum {
|
||||
ROLE_NONE,
|
||||
ROLE_VIDEO,
|
||||
ROLE_MUSIC,
|
||||
ROLE_GAME,
|
||||
ROLE_EVENT,
|
||||
ROLE_PHONE,
|
||||
ROLE_ANIMATION,
|
||||
ROLE_PRODUCTION,
|
||||
ROLE_A11Y,
|
||||
};
|
||||
|
||||
typedef uint32_t role_indexes_t[NUM_ROLES];
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_module *module;
|
||||
|
|
@ -95,25 +110,13 @@ struct userdata {
|
|||
pa_bool_t on_hotplug;
|
||||
pa_bool_t on_rescue;
|
||||
pa_bool_t do_routing;
|
||||
|
||||
role_indexes_t preferred_sinks;
|
||||
role_indexes_t preferred_sources;
|
||||
};
|
||||
|
||||
#define ENTRY_VERSION 1
|
||||
|
||||
#define NUM_ROLES 9
|
||||
enum {
|
||||
ROLE_NONE,
|
||||
ROLE_VIDEO,
|
||||
ROLE_MUSIC,
|
||||
ROLE_GAME,
|
||||
ROLE_EVENT,
|
||||
ROLE_PHONE,
|
||||
ROLE_ANIMATION,
|
||||
ROLE_PRODUCTION,
|
||||
ROLE_A11Y,
|
||||
};
|
||||
|
||||
typedef uint32_t role_indexes_t[NUM_ROLES];
|
||||
|
||||
struct entry {
|
||||
uint8_t version;
|
||||
char description[PA_NAME_MAX];
|
||||
|
|
@ -211,6 +214,7 @@ static void trigger_save(struct userdata *u) {
|
|||
}
|
||||
|
||||
static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) {
|
||||
/** @todo: Compare the priority lists too */
|
||||
if (strncmp(a->description, b->description, sizeof(a->description)))
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -428,7 +432,7 @@ static uint32_t get_role_index(const char* role) {
|
|||
return PA_INVALID_INDEX;
|
||||
}
|
||||
|
||||
static role_indexes_t *get_highest_priority_device_indexes(struct userdata *u, const char *prefix) {
|
||||
static void update_highest_priority_device_indexes(struct userdata *u, const char *prefix, void *ignore_device) {
|
||||
role_indexes_t *indexes, highest_priority_available;
|
||||
pa_datum key;
|
||||
pa_bool_t done, sink_mode;
|
||||
|
|
@ -436,14 +440,18 @@ static role_indexes_t *get_highest_priority_device_indexes(struct userdata *u, c
|
|||
pa_assert(u);
|
||||
pa_assert(prefix);
|
||||
|
||||
indexes = pa_xnew(role_indexes_t, 1);
|
||||
sink_mode = (strcmp(prefix, "sink:") == 0);
|
||||
|
||||
if (sink_mode)
|
||||
indexes = &u->preferred_sinks;
|
||||
else
|
||||
indexes = &u->preferred_sources;
|
||||
|
||||
for (uint32_t i = 0; i < NUM_ROLES; ++i) {
|
||||
*indexes[i] = PA_INVALID_INDEX;
|
||||
}
|
||||
pa_zero(highest_priority_available);
|
||||
|
||||
sink_mode = (strcmp(prefix, "sink:") == 0);
|
||||
|
||||
done = !pa_database_first(u->database, &key, NULL);
|
||||
|
||||
/* Find all existing devices with the same prefix so we find the highest priority device for each role */
|
||||
|
|
@ -471,6 +479,8 @@ static role_indexes_t *get_highest_priority_device_indexes(struct userdata *u, c
|
|||
pa_sink *sink;
|
||||
|
||||
PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
|
||||
if ((pa_sink*) ignore_device == sink)
|
||||
continue;
|
||||
if (strcmp(sink->name, device_name) == 0) {
|
||||
found = TRUE;
|
||||
idx = sink->index; /* Is this needed? */
|
||||
|
|
@ -481,6 +491,8 @@ static role_indexes_t *get_highest_priority_device_indexes(struct userdata *u, c
|
|||
pa_source *source;
|
||||
|
||||
PA_IDXSET_FOREACH(source, u->core->sources, idx) {
|
||||
if ((pa_source*) ignore_device == source)
|
||||
continue;
|
||||
if (strcmp(source->name, device_name) == 0) {
|
||||
found = TRUE;
|
||||
idx = source->index; /* Is this needed? */
|
||||
|
|
@ -506,8 +518,6 @@ static role_indexes_t *get_highest_priority_device_indexes(struct userdata *u, c
|
|||
pa_datum_free(&key);
|
||||
key = next_key;
|
||||
}
|
||||
|
||||
return indexes;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -531,12 +541,9 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n
|
|||
role_index = get_role_index(role);
|
||||
|
||||
if (PA_INVALID_INDEX != role_index) {
|
||||
role_indexes_t *indexes;
|
||||
uint32_t device_index;
|
||||
|
||||
pa_assert_se(indexes = get_highest_priority_device_indexes(u, "sink:"));
|
||||
|
||||
device_index = *indexes[role_index];
|
||||
device_index = u->preferred_sinks[role_index];
|
||||
if (PA_INVALID_INDEX != device_index) {
|
||||
pa_sink *sink;
|
||||
|
||||
|
|
@ -574,12 +581,9 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
|
|||
role_index = get_role_index(role);
|
||||
|
||||
if (PA_INVALID_INDEX != role_index) {
|
||||
role_indexes_t *indexes;
|
||||
uint32_t device_index;
|
||||
|
||||
pa_assert_se(indexes = get_highest_priority_device_indexes(u, "source:"));
|
||||
|
||||
device_index = *indexes[role_index];
|
||||
device_index = u->preferred_sources[role_index];
|
||||
if (PA_INVALID_INDEX != device_index) {
|
||||
pa_source *source;
|
||||
|
||||
|
|
@ -594,9 +598,8 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
|
|||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t reroute_sinks(struct userdata *u) {
|
||||
static pa_hook_result_t reroute_sinks(struct userdata *u, pa_sink *ignore_sink) {
|
||||
pa_sink_input *si;
|
||||
role_indexes_t *indexes;
|
||||
uint32_t idx;
|
||||
|
||||
pa_assert(u);
|
||||
|
|
@ -604,7 +607,7 @@ static pa_hook_result_t reroute_sinks(struct userdata *u) {
|
|||
if (!u->do_routing)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
pa_assert_se(indexes = get_highest_priority_device_indexes(u, "sink:"));
|
||||
update_highest_priority_device_indexes(u, "sink:", ignore_sink);
|
||||
|
||||
PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
|
||||
const char *role;
|
||||
|
|
@ -632,7 +635,7 @@ static pa_hook_result_t reroute_sinks(struct userdata *u) {
|
|||
if (PA_INVALID_INDEX == role_index)
|
||||
continue;
|
||||
|
||||
device_index = *indexes[role_index];
|
||||
device_index = u->preferred_sinks[role_index];
|
||||
if (PA_INVALID_INDEX == device_index)
|
||||
continue;
|
||||
|
||||
|
|
@ -643,14 +646,11 @@ static pa_hook_result_t reroute_sinks(struct userdata *u) {
|
|||
pa_sink_input_move_to(si, sink, TRUE);
|
||||
}
|
||||
|
||||
pa_xfree(indexes);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_hook_result_t reroute_sources(struct userdata *u) {
|
||||
static pa_hook_result_t reroute_sources(struct userdata *u, pa_source* ignore_source) {
|
||||
pa_source_output *so;
|
||||
role_indexes_t *indexes;
|
||||
uint32_t idx;
|
||||
|
||||
pa_assert(u);
|
||||
|
|
@ -658,7 +658,7 @@ static pa_hook_result_t reroute_sources(struct userdata *u) {
|
|||
if (!u->do_routing)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
pa_assert_se(indexes = get_highest_priority_device_indexes(u, "source:"));
|
||||
update_highest_priority_device_indexes(u, "source:", ignore_source);
|
||||
|
||||
PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
|
||||
const char *role;
|
||||
|
|
@ -689,7 +689,7 @@ static pa_hook_result_t reroute_sources(struct userdata *u) {
|
|||
if (PA_INVALID_INDEX == role_index)
|
||||
continue;
|
||||
|
||||
device_index = *indexes[role_index];
|
||||
device_index = u->preferred_sources[role_index];
|
||||
if (PA_INVALID_INDEX == device_index)
|
||||
continue;
|
||||
|
||||
|
|
@ -700,8 +700,6 @@ static pa_hook_result_t reroute_sources(struct userdata *u) {
|
|||
pa_source_output_move_to(so, source, TRUE);
|
||||
}
|
||||
|
||||
pa_xfree(indexes);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
|
|
@ -711,7 +709,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, PA_GCC_UNUSED pa_sink
|
|||
pa_assert(u->core == c);
|
||||
pa_assert(u->on_hotplug);
|
||||
|
||||
return reroute_sinks(u);
|
||||
return reroute_sinks(u, NULL);
|
||||
}
|
||||
|
||||
static pa_hook_result_t source_put_hook_callback(pa_core *c, PA_GCC_UNUSED pa_source *source, struct userdata *u) {
|
||||
|
|
@ -720,11 +718,12 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, PA_GCC_UNUSED pa_so
|
|||
pa_assert(u->core == c);
|
||||
pa_assert(u->on_hotplug);
|
||||
|
||||
return reroute_sources(u);
|
||||
return reroute_sources(u, NULL);
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, PA_GCC_UNUSED pa_sink *sink, struct userdata *u) {
|
||||
static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
|
||||
pa_assert(c);
|
||||
pa_assert(sink);
|
||||
pa_assert(u);
|
||||
pa_assert(u->core == c);
|
||||
pa_assert(u->on_rescue);
|
||||
|
|
@ -733,11 +732,12 @@ static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, PA_GCC_UNUSED pa_s
|
|||
if (c->state == PA_CORE_SHUTDOWN)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
return reroute_sinks(u);
|
||||
return reroute_sinks(u, sink);
|
||||
}
|
||||
|
||||
static pa_hook_result_t source_unlink_hook_callback(pa_core *c, PA_GCC_UNUSED pa_source *source, struct userdata *u) {
|
||||
static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
|
||||
pa_assert(c);
|
||||
pa_assert(source);
|
||||
pa_assert(u);
|
||||
pa_assert(u->core == c);
|
||||
pa_assert(u->on_rescue);
|
||||
|
|
@ -746,7 +746,7 @@ static pa_hook_result_t source_unlink_hook_callback(pa_core *c, PA_GCC_UNUSED pa
|
|||
if (c->state == PA_CORE_SHUTDOWN)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
return reroute_sinks(u);
|
||||
return reroute_sources(u, source);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1151,12 +1151,17 @@ int pa__init(pa_module*m) {
|
|||
pa_log_info("Sucessfully opened database file '%s'.", fname);
|
||||
pa_xfree(fname);
|
||||
|
||||
/* We cycle over all the available sinks so that they are added to our database if they are not in it yet */
|
||||
PA_IDXSET_FOREACH(sink, m->core->sinks, idx)
|
||||
subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, sink->index, u);
|
||||
|
||||
PA_IDXSET_FOREACH(source, m->core->sources, idx)
|
||||
subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW, source->index, u);
|
||||
|
||||
/* Update our caches (all available devices will be present in our database now */
|
||||
update_highest_priority_device_indexes(u, "sink:", NULL);
|
||||
update_highest_priority_device_indexes(u, "source:", NULL);
|
||||
|
||||
PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx)
|
||||
subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue