diff -Nru pulseaudio-13.99.1/debian/changelog pulseaudio-13.99.1/debian/changelog --- pulseaudio-13.99.1/debian/changelog 2020-07-15 15:29:05.000000000 +0800 +++ pulseaudio-13.99.1/debian/changelog 2020-08-08 13:32:49.000000000 +0800 @@ -1,3 +1,12 @@ +pulseaudio (1:13.99.1-1ubuntu9) groovy; urgency=medium + + * d/p/0034-alsa-adjust-ucm-sink-source-priority-according-to-po.patch + * d/p/0035-ucm-add-possibility-to-skip-the-UCM-card-completely-.patch + * d/p/0036-device-port-queue-CARD-CHANGE-event-before-update-de.patch + * (LP: #1889217) + + -- Hui Wang Sat, 08 Aug 2020 13:32:49 +0800 + pulseaudio (1:13.99.1-1ubuntu8) groovy; urgency=medium * d/p/0033-alsa-make-the-unsuspend-more-robust.patch: diff -Nru pulseaudio-13.99.1/debian/patches/0034-alsa-adjust-ucm-sink-source-priority-according-to-po.patch pulseaudio-13.99.1/debian/patches/0034-alsa-adjust-ucm-sink-source-priority-according-to-po.patch --- pulseaudio-13.99.1/debian/patches/0034-alsa-adjust-ucm-sink-source-priority-according-to-po.patch 1970-01-01 08:00:00.000000000 +0800 +++ pulseaudio-13.99.1/debian/patches/0034-alsa-adjust-ucm-sink-source-priority-according-to-po.patch 2020-08-08 13:31:41.000000000 +0800 @@ -0,0 +1,89 @@ +From c8653c13faed5d877db3870335b870c144f01513 Mon Sep 17 00:00:00 2001 +From: Hui Wang +Date: Thu, 11 Jun 2020 15:49:05 +0800 +Subject: [PATCH] alsa: adjust ucm sink/source priority according to ports + priority + +On the machines with the ucm used, the different input/output devices +often have different pcm stream, so they often belong to different +sources and sinks, this is greatly different from the design of all +devices connected to a codec (without ucm). + +For example, on a machine with ucm2 used: +the internal dmic is on source#0 +the external mic is on the source#1 +the internal spk is on sink#0 +the external headphone is on sink#1 + +Users expect that after plugging the external device, it will become +the active device automatically. The switch-on-port-available could +make it to be the active_port on its own source/sink, but can't make +source/sink to be default_source/sink since the sources/sinks belong +to the same profile (HiFi usually). + +If we adjust the source/sink priority according to ucm ports priority, +the device_port.c could handle the default_source/sink changing then. +Usually we set higher priority for external device than internal +device in the ucm. + +In order to bring the lowest side effect on the source/sink priority, +I change the ucm priority to units digit first, then add it to the +original priority. + +Signed-off-by: Hui Wang +--- + src/modules/alsa/alsa-sink.c | 13 +++++++++++++ + src/modules/alsa/alsa-source.c | 13 +++++++++++++ + 2 files changed, 26 insertions(+) + +diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c +index 457dc2785..3fe429c80 100644 +--- a/src/modules/alsa/alsa-sink.c ++++ b/src/modules/alsa/alsa-sink.c +@@ -2598,6 +2598,19 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca + goto fail; + } + ++ if (u->ucm_context) { ++ pa_device_port *port; ++ void *state; ++ unsigned h_prio = 0; ++ PA_HASHMAP_FOREACH(port, u->sink->ports, state) { ++ if (!h_prio || port->priority > h_prio) ++ h_prio = port->priority; ++ } ++ /* ucm ports prioriy is 100, 200, ..., 900, change it to units digit */ ++ h_prio = h_prio / 100; ++ u->sink->priority += h_prio; ++ } ++ + if (pa_modargs_get_value_u32(ma, "deferred_volume_safety_margin", + &u->sink->thread_info.volume_change_safety_margin) < 0) { + pa_log("Failed to parse deferred_volume_safety_margin parameter"); +diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c +index da99ac610..b1149c675 100644 +--- a/src/modules/alsa/alsa-source.c ++++ b/src/modules/alsa/alsa-source.c +@@ -2284,6 +2284,19 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p + goto fail; + } + ++ if (u->ucm_context) { ++ pa_device_port *port; ++ void *state; ++ unsigned h_prio = 0; ++ PA_HASHMAP_FOREACH(port, u->source->ports, state) { ++ if (!h_prio || port->priority > h_prio) ++ h_prio = port->priority; ++ } ++ /* ucm ports prioriy is 100, 200, ..., 900, change it to units digit */ ++ h_prio = h_prio / 100; ++ u->source->priority += h_prio; ++ } ++ + if (pa_modargs_get_value_u32(ma, "deferred_volume_safety_margin", + &u->source->thread_info.volume_change_safety_margin) < 0) { + pa_log("Failed to parse deferred_volume_safety_margin parameter"); +-- +2.17.1 + diff -Nru pulseaudio-13.99.1/debian/patches/0035-ucm-add-possibility-to-skip-the-UCM-card-completely-.patch pulseaudio-13.99.1/debian/patches/0035-ucm-add-possibility-to-skip-the-UCM-card-completely-.patch --- pulseaudio-13.99.1/debian/patches/0035-ucm-add-possibility-to-skip-the-UCM-card-completely-.patch 1970-01-01 08:00:00.000000000 +0800 +++ pulseaudio-13.99.1/debian/patches/0035-ucm-add-possibility-to-skip-the-UCM-card-completely-.patch 2020-08-08 13:31:41.000000000 +0800 @@ -0,0 +1,156 @@ +From 7a00c865f1e205c0c7891901cc4748ef43df31ee Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sun, 7 Jun 2020 18:25:41 +0200 +Subject: [PATCH 2/2] ucm: add possibility to skip the UCM card completely + (Linked) + +We have a requirement to "hide" some hardware drivers, because +other (main) UCM configuration will refer them. + +BugLink: https://github.com/alsa-project/alsa-ucm-conf/issues/30 +Signed-off-by: Jaroslav Kysela +--- + src/modules/alsa/alsa-ucm.c | 16 ++++++++++++++-- + src/modules/alsa/alsa-ucm.h | 2 ++ + src/modules/alsa/module-alsa-card.c | 10 ++++++++-- + src/pulsecore/module.c | 8 ++++++-- + src/pulsecore/module.h | 2 ++ + 5 files changed, 32 insertions(+), 6 deletions(-) + +diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c +index 9d6456162..c837ca921 100644 +--- a/src/modules/alsa/alsa-ucm.c ++++ b/src/modules/alsa/alsa-ucm.c +@@ -722,7 +722,7 @@ static void append_lost_relationship(pa_alsa_ucm_device *dev) { + + int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) { + char *card_name; +- const char **verb_list; ++ const char **verb_list, *value; + int num_verbs, i, err = 0; + + /* support multiple card instances, address card directly by index */ +@@ -746,12 +746,24 @@ int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) { + } + } + ++ err = snd_use_case_get(ucm->ucm_mgr, "=Linked", &value); ++ if (err >= 0) { ++ if (strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) { ++ free((void *)value); ++ pa_log_info("Empty (linked) UCM for card %s", card_name); ++ err = -PA_ALSA_ERR_UCM_LINKED; ++ goto ucm_verb_fail; ++ } ++ free((void *)value); ++ } ++ + pa_log_info("UCM available for card %s", card_name); + + /* get a list of all UCM verbs (profiles) for this card */ + num_verbs = snd_use_case_verb_list(ucm->ucm_mgr, &verb_list); + if (num_verbs < 0) { + pa_log("UCM verb list not found for %s", card_name); ++ err = num_verbs; + goto ucm_verb_fail; + } + +@@ -771,7 +783,7 @@ int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) { + + if (!ucm->verbs) { + pa_log("No UCM verb is valid for %s", card_name); +- err = -1; ++ err = -ENOENT; + } + + snd_use_case_free_list(verb_list, num_verbs); +diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h +index e7a795ced..3244dc2eb 100644 +--- a/src/modules/alsa/alsa-ucm.h ++++ b/src/modules/alsa/alsa-ucm.h +@@ -30,6 +30,8 @@ typedef void snd_use_case_mgr_t; + + #include "alsa-mixer.h" + ++#define PA_ALSA_ERR_UCM_LINKED (9999) ++ + /** For devices: List of verbs, devices or modifiers available */ + #define PA_ALSA_PROP_UCM_NAME "alsa.ucm.name" + +diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c +index c5852b43d..05490ef9a 100644 +--- a/src/modules/alsa/module-alsa-card.c ++++ b/src/modules/alsa/module-alsa-card.c +@@ -785,6 +785,7 @@ int pa__init(pa_module *m) { + const char *profile_str = NULL; + char *fn = NULL; + bool namereg_fail = false; ++ int err = -1, rval; + + pa_alsa_refcnt_inc(); + +@@ -841,7 +842,12 @@ int pa__init(pa_module *m) { + + snd_config_update_free_global(); + +- if (u->use_ucm && !pa_alsa_ucm_query_profiles(&u->ucm, u->alsa_card_index)) { ++ rval = u->use_ucm ? pa_alsa_ucm_query_profiles(&u->ucm, u->alsa_card_index) : -1; ++ if (rval == -PA_ALSA_ERR_UCM_LINKED) { ++ err = -PA_MODULE_ERR_SKIP; ++ goto fail; ++ } ++ if (rval == 0) { + pa_log_info("Found UCM profiles"); + + u->profile_set = pa_alsa_ucm_add_profile_set(&u->ucm, &u->core->default_channel_map); +@@ -1009,7 +1015,7 @@ fail: + + pa__done(m); + +- return -1; ++ return err; + } + + int pa__get_n_used(pa_module *m) { +diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c +index 70b816072..15a54b6ec 100644 +--- a/src/pulsecore/module.c ++++ b/src/pulsecore/module.c +@@ -116,7 +116,7 @@ int pa_module_load(pa_module** module, pa_core *c, const char *name, const char + bool (*load_once)(void); + const char* (*get_deprecated)(void); + pa_modinfo *mi; +- int errcode; ++ int errcode, rval; + + pa_assert(module); + pa_assert(c); +@@ -188,7 +188,11 @@ int pa_module_load(pa_module** module, pa_core *c, const char *name, const char + pa_assert_se(pa_idxset_put(c->modules, m, &m->index) >= 0); + pa_assert(m->index != PA_IDXSET_INVALID); + +- if (m->init(m) < 0) { ++ if ((rval = m->init(m)) < 0) { ++ if (rval == -PA_MODULE_ERR_SKIP) { ++ errcode = -PA_ERR_NOENTITY; ++ goto fail; ++ } + pa_log_error("Failed to load module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : ""); + errcode = -PA_ERR_IO; + goto fail; +diff --git a/src/pulsecore/module.h b/src/pulsecore/module.h +index b5a7fad77..0f4d91e0b 100644 +--- a/src/pulsecore/module.h ++++ b/src/pulsecore/module.h +@@ -30,6 +30,8 @@ typedef struct pa_module pa_module; + + #include + ++#define PA_MODULE_ERR_SKIP (9999) ++ + struct pa_module { + pa_core *core; + char *name, *argument; +-- +2.17.1 + diff -Nru pulseaudio-13.99.1/debian/patches/0036-device-port-queue-CARD-CHANGE-event-before-update-de.patch pulseaudio-13.99.1/debian/patches/0036-device-port-queue-CARD-CHANGE-event-before-update-de.patch --- pulseaudio-13.99.1/debian/patches/0036-device-port-queue-CARD-CHANGE-event-before-update-de.patch 1970-01-01 08:00:00.000000000 +0800 +++ pulseaudio-13.99.1/debian/patches/0036-device-port-queue-CARD-CHANGE-event-before-update-de.patch 2020-08-08 13:31:41.000000000 +0800 @@ -0,0 +1,62 @@ +From 2ae94c141ff4d76d60a66a71d80acefbba3966d1 Mon Sep 17 00:00:00 2001 +From: Libin Yang +Date: Sat, 13 Jun 2020 06:27:08 -0400 +Subject: [PATCH] device-port: queue CARD CHANGE event before update default + sink + +In single profile mode (headphone and speaker use different PCMs), +when headphone is plugged in, pa_device_port_set_available() will call +pa_core_update_default_sink/source() before posting +PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE to the gnome. +And pa_core_update_default_sink/source() will post +PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE to the gnome. +So the original event sequence is: +1. PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE +2. PA_SUBSCRIPTION_EVENT_CARD | PA_SUBSCRIPTION_EVENT_CHANGE + +In gnome-control-center: +When it receives PA_SUBSCRIPTION_EVENT_SERVER, it will call +req_update_server_info () to update the panel; +When it receives PA_SUBSCRIPTION_EVENT_CARD, it will update +the card information, for example, when the headphone is connected, +it will call gtk_list_store_append() to append the headphone. + +Let's use an example to clarify the correct sequence. +Assume we plug in headphone. PA will set the default sink to headphone +from speaker, and hope gnome sound setting "Output Deivce" to highlight to +"headphone". PA should send PA_SUBSCRIPTION_EVENT_CARD firstly to notify +gnome-control-center "headphone" is plugged in. And then it sends +PA_SUBSCRIPTION_EVENT_SERVER to trigger sound setting to highlight +to "headphone". + +Signed-off-by: Libin Yang +--- + src/pulsecore/device-port.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c +index d5677b16d..07761365e 100644 +--- a/src/pulsecore/device-port.c ++++ b/src/pulsecore/device-port.c +@@ -107,6 +107,8 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) { + * be created before port objects, and then p->card could be non-NULL for + * the whole lifecycle of pa_device_port. */ + if (p->card && p->card->linked) { ++ pa_subscription_post(p->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, p->card->index); ++ pa_hook_fire(&p->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], p); + /* A sink or source whose active port is unavailable can't be the + * default sink/source, so port availability changes may affect the + * default sink/source choice. */ +@@ -138,9 +140,6 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) { + pa_core_move_streams_to_newly_available_preferred_source(p->core, source); + } + } +- +- pa_subscription_post(p->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, p->card->index); +- pa_hook_fire(&p->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], p); + } + } + +-- +2.17.1 + diff -Nru pulseaudio-13.99.1/debian/patches/series pulseaudio-13.99.1/debian/patches/series --- pulseaudio-13.99.1/debian/patches/series 2020-07-15 15:29:05.000000000 +0800 +++ pulseaudio-13.99.1/debian/patches/series 2020-08-08 13:32:14.000000000 +0800 @@ -3,6 +3,9 @@ git_config_upgrade.patch 0032-alsa-mixer-store-the-ucm_device-with-the-order-of-th.patch 0033-alsa-make-the-unsuspend-more-robust.patch +0034-alsa-adjust-ucm-sink-source-priority-according-to-po.patch +0035-ucm-add-possibility-to-skip-the-UCM-card-completely-.patch +0036-device-port-queue-CARD-CHANGE-event-before-update-de.patch # Ubuntu specific config/fixes 0001-volume-config-changes.patch