mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
switch-on-port-available: Check if we need to change the active profile
When a port becomes unavailble its profile may also become unavailable. If that profile is the card's active profile, we need to switch the card's active profile to a different one. If we don't do that a card may get stuck on a profile without available ports, but its sink and source will still exist, preventing module-rescue-streams to move the streams to a different card with available ports. The relation between port availability and profile availability is defined by the driver, and for the ALSA driver a profile is considered available if there is at least one (available || unknown) port for each direction implemented by the profile. Because of that we can only check the profile's availability and priority when looking for the best profile and don't need to look at port's priorities. https://phabricator.endlessm.com/T24904
This commit is contained in:
parent
3d9deb1e56
commit
30a551bbc4
1 changed files with 43 additions and 0 deletions
|
|
@ -277,6 +277,10 @@ static void switch_from_port(pa_device_port *port) {
|
|||
|
||||
pa_log_debug("Trying to switch away from port %s, found %s", port->name, best_port ? best_port->name : "no better option");
|
||||
|
||||
/* If there is no available port to switch to we need check if the active
|
||||
* profile is still available in the
|
||||
* PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED callback, as at this point
|
||||
* the profile availability hasn't been updated yet. */
|
||||
if (best_port)
|
||||
switch_to_port(best_port);
|
||||
}
|
||||
|
|
@ -312,6 +316,43 @@ static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port
|
|||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static pa_card_profile *find_best_profile(pa_card *card) {
|
||||
pa_card_profile *profile, *best_profile;
|
||||
void *state;
|
||||
|
||||
pa_assert(card);
|
||||
best_profile = pa_hashmap_get(card->profiles, "off");
|
||||
|
||||
PA_HASHMAP_FOREACH(profile, card->profiles, state) {
|
||||
if (profile->available == PA_AVAILABLE_NO)
|
||||
continue;
|
||||
|
||||
if (profile->priority > best_profile->priority)
|
||||
best_profile = profile;
|
||||
}
|
||||
|
||||
return best_profile;
|
||||
}
|
||||
|
||||
static pa_hook_result_t card_profile_available_hook_callback(pa_core *c, pa_card_profile *profile, struct userdata *u) {
|
||||
pa_card *card;
|
||||
|
||||
pa_assert(profile);
|
||||
pa_assert_se(card = profile->card);
|
||||
|
||||
if (profile->available != PA_AVAILABLE_NO)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (!pa_streq(profile->name, card->active_profile->name))
|
||||
return PA_HOOK_OK;
|
||||
|
||||
pa_log_debug("Active profile %s on card %s became unavailable, switching to another profile", profile->name, card->name);
|
||||
pa_card_set_profile(card, find_best_profile(card), false);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
|
||||
}
|
||||
|
||||
static void handle_all_unavailable(pa_core *core) {
|
||||
pa_card *card;
|
||||
uint32_t state;
|
||||
|
|
@ -514,6 +555,8 @@ int pa__init(pa_module*m) {
|
|||
PA_HOOK_NORMAL, (pa_hook_cb_t) source_new_hook_callback, NULL);
|
||||
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED],
|
||||
PA_HOOK_LATE, (pa_hook_cb_t) port_available_hook_callback, NULL);
|
||||
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED],
|
||||
PA_HOOK_LATE, (pa_hook_cb_t) card_profile_available_hook_callback, NULL);
|
||||
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PUT],
|
||||
PA_HOOK_NORMAL, (pa_hook_cb_t) card_put_hook_callback, u);
|
||||
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_UNLINK],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue