[pulseaudio-commits] [Git][pulseaudio/pulseaudio][master] 2 commits: switch-on-port-available: Check if we need to change the active profile
Tanu Kaskinen
gitlab at gitlab.freedesktop.org
Fri Dec 14 08:37:25 UTC 2018
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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/pulseaudio-commits/attachments/20181214/ebff7ac2/attachment-0001.html>
More information about the pulseaudio-commits
mailing list