Tanu Kaskinen pushed to branch master at PulseAudio / pulseaudio
Commits: 30a551bb by João Paulo Rechi Vita at 2018-12-14T08:10:26Z 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 - - - - - 40e72e02 by João Paulo Rechi Vita at 2018-12-14T08:22:59Z module-alsa-card: Update the active profile's availability last The previous commit introduces logic in module-switch-on-port-available that may change a card's active profile when its availability changes to PA_AVAILABLE_NO. To choose the new active profile, it needs a consistent view of the new availability of all profiles, so this commit changes the order which the ALSA driver updates all profiles' availability to ensure the active profile is last. This is not generic enough to cover cases were we may want to take an action on availability changes of profiles other than the active one that also need a consistent view of all profiles' availability. But we don't have any callbacks implementing such action at the moment. - - - - - 2 changed files: - src/modules/alsa/module-alsa-card.c - src/modules/module-switch-on-port-available.c Changes: ===================================== src/modules/alsa/module-alsa-card.c ===================================== @@ -368,6 +368,7 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { pa_alsa_jack *jack; struct temp_port_avail *tp, *tports; pa_card_profile *profile; + pa_available_t active_available = PA_AVAILABLE_UNKNOWN; pa_assert(u); @@ -463,6 +464,8 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { * * If there are no output ports at all, but the profile contains at least * one sink, then the output is considered to be available. */ + if (u->card->active_profile) + active_available = u->card->active_profile->available; PA_HASHMAP_FOREACH(profile, u->card->profiles, state) { pa_device_port *port; void *state2; @@ -492,9 +495,18 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { if ((has_input_port && !found_available_input_port) || (has_output_port && !found_available_output_port)) available = PA_AVAILABLE_NO; - pa_card_profile_set_available(profile, available); + /* We want to update the active profile's status last, so logic that + * may change the active profile based on profile availability status + * has an updated view of all profiles' availabilities. */ + if (profile == u->card->active_profile) + active_available = available; + else + pa_card_profile_set_available(profile, available); } + if (u->card->active_profile) + pa_card_profile_set_available(u->card->active_profile, active_available); + pa_xfree(tports); return 0; } ===================================== src/modules/module-switch-on-port-available.c ===================================== @@ -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], View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/compare/3d9deb1e5679e15c3277e144a822be9b0a036514...40e72e02eb938b5c1150ce79e691efc5118770c1 -- View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/compare/3d9deb1e5679e15c3277e144a822be9b0a036514...40e72e02eb938b5c1150ce79e691efc5118770c1 You're receiving this email because of your account on gitlab.freedesktop.org.
_______________________________________________ pulseaudio-commits mailing list pulseaudio-commits@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/pulseaudio-commits