summaryrefslogtreecommitdiffstats
path: root/meta/recipes-multimedia/pulseaudio/pulseaudio
diff options
context:
space:
mode:
authorTanu Kaskinen <tanuk@iki.fi>2016-07-20 03:20:22 +0300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-07-26 08:56:27 +0100
commit7c9acf0ea47701e7ae17c7bee11929d1926e00ad (patch)
tree7b7d742107d639a4b0cd724942a5e203411f72c8 /meta/recipes-multimedia/pulseaudio/pulseaudio
parent328e249399b030990774fb3cebef49b5e8b615d5 (diff)
downloadpoky-7c9acf0ea47701e7ae17c7bee11929d1926e00ad.tar.gz
pulseaudio: 8.0 -> 9.0
Release notes: https://www.freedesktop.org/wiki/Software/PulseAudio/Notes/9.0/ Rebased 0001-client-conf-Add-allow-autospawn-for-root.patch. Removed 0001-Revert-module-switch-on-port-available-Route-to-pref.patch, because the issues that were caused by the reverted commit have been fixed. The patch set that fixes the initial selection of HDMI profiles (YOCTO#8448) is replaced with updated patches cherry-picked from upstream. (From OE-Core rev: 319595e8264af32c54ba6324e220eb4ec43b7565) Signed-off-by: Tanu Kaskinen <tanuk@iki.fi> Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-multimedia/pulseaudio/pulseaudio')
-rw-r--r--meta/recipes-multimedia/pulseaudio/pulseaudio/0001-Revert-module-switch-on-port-available-Route-to-pref.patch268
-rw-r--r--meta/recipes-multimedia/pulseaudio/pulseaudio/0001-alsa-bluetooth-fail-if-user-requested-profile-doesn-.patch (renamed from meta/recipes-multimedia/pulseaudio/pulseaudio/0002-alsa-bluetooth-fail-if-user-requested-profile-doesn-.patch)30
-rw-r--r--meta/recipes-multimedia/pulseaudio/pulseaudio/0001-card-add-pa_card_profile.ports.patch218
-rw-r--r--meta/recipes-multimedia/pulseaudio/pulseaudio/0001-client-conf-Add-allow-autospawn-for-root.patch18
-rw-r--r--meta/recipes-multimedia/pulseaudio/pulseaudio/0002-card-don-t-allow-the-CARD_NEW-hook-to-fail.patch37
-rw-r--r--meta/recipes-multimedia/pulseaudio/pulseaudio/0003-card-move-profile-selection-after-pa_card_new.patch373
-rw-r--r--meta/recipes-multimedia/pulseaudio/pulseaudio/0004-card-remove-pa_card_new_data.active_profile.patch72
-rw-r--r--meta/recipes-multimedia/pulseaudio/pulseaudio/0005-alsa-set-availability-for-some-unavailable-profiles.patch (renamed from meta/recipes-multimedia/pulseaudio/pulseaudio/0004-alsa-set-availability-for-some-unavailable-profiles.patch)38
8 files changed, 366 insertions, 688 deletions
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-Revert-module-switch-on-port-available-Route-to-pref.patch b/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-Revert-module-switch-on-port-available-Route-to-pref.patch
deleted file mode 100644
index 1c1e2fbdbc..0000000000
--- a/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-Revert-module-switch-on-port-available-Route-to-pref.patch
+++ /dev/null
@@ -1,268 +0,0 @@
1From b8b9b3da94a0c27090ceba243fdf54fb518c5489 Mon Sep 17 00:00:00 2001
2From: Tanu Kaskinen <tanuk@iki.fi>
3Date: Mon, 1 Feb 2016 15:34:59 +0200
4Subject: [PATCH] Revert "module-switch-on-port-available: Route to preferred
5 profile"
6
7This reverts commit e87100d41ef6d14f8dc7f803582191d9f8d8f183.
8
9The reverted commit had some unwanted consequences:
10https://bugs.freedesktop.org/show_bug.cgi?id=93903
11https://bugs.freedesktop.org/show_bug.cgi?id=93946
12
13The first regression has a fix here:
14https://patchwork.freedesktop.org/patch/72053/
15
16The second regression, however, doesn't have a fix yet. Therefore,
17it's best to revert the offending patch for now.
18
19Upstream-Status: Inappropriate [Upstream plans to fix the issues
20properly.]
21
22Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
23---
24 src/modules/module-switch-on-port-available.c | 172 ++++++++++----------------
25 1 file changed, 67 insertions(+), 105 deletions(-)
26
27diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
28index 5dd9786..8de68a3 100644
29--- a/src/modules/module-switch-on-port-available.c
30+++ b/src/modules/module-switch-on-port-available.c
31@@ -74,25 +74,22 @@ static bool profile_good_for_input(pa_card_profile *profile) {
32 static int try_to_switch_profile(pa_device_port *port) {
33 pa_card_profile *best_profile = NULL, *profile;
34 void *state;
35- unsigned best_prio = 0;
36
37- pa_log_debug("Finding best profile for port %s, preferred = %s",
38- port->name, pa_strnull(port->preferred_profile));
39+ pa_log_debug("Finding best profile");
40
41 PA_HASHMAP_FOREACH(profile, port->profiles, state) {
42 bool good = false;
43- const char *name;
44- unsigned prio = profile->priority;
45+
46+ if (best_profile && best_profile->priority >= profile->priority)
47+ continue;
48
49 /* We make a best effort to keep other direction unchanged */
50 switch (port->direction) {
51 case PA_DIRECTION_OUTPUT:
52- name = profile->output_name;
53 good = profile_good_for_output(profile);
54 break;
55
56 case PA_DIRECTION_INPUT:
57- name = profile->input_name;
58 good = profile_good_for_input(profile);
59 break;
60 }
61@@ -100,15 +97,7 @@ static int try_to_switch_profile(pa_device_port *port) {
62 if (!good)
63 continue;
64
65- /* Give a high bonus in case this is the preferred profile */
66- if (port->preferred_profile && pa_streq(name ? name : profile->name, port->preferred_profile))
67- prio += 1000000;
68-
69- if (best_profile && best_prio >= prio)
70- continue;
71-
72 best_profile = profile;
73- best_prio = prio;
74 }
75
76 if (!best_profile) {
77@@ -124,125 +113,98 @@ static int try_to_switch_profile(pa_device_port *port) {
78 return 0;
79 }
80
81-struct port_pointers {
82- pa_device_port *port;
83- pa_sink *sink;
84- pa_source *source;
85- bool is_possible_profile_active;
86- bool is_preferred_profile_active;
87- bool is_port_active;
88-};
89-
90-static const char* profile_name_for_dir(pa_card_profile *cp, pa_direction_t dir) {
91- if (dir == PA_DIRECTION_OUTPUT && cp->output_name)
92- return cp->output_name;
93- if (dir == PA_DIRECTION_INPUT && cp->input_name)
94- return cp->input_name;
95- return cp->name;
96-}
97-
98-static struct port_pointers find_port_pointers(pa_device_port *port) {
99- struct port_pointers pp = { .port = port };
100+static void find_sink_and_source(pa_card *card, pa_device_port *port, pa_sink **si, pa_source **so) {
101+ pa_sink *sink = NULL;
102+ pa_source *source = NULL;
103 uint32_t state;
104- pa_card *card;
105-
106- pa_assert(port);
107- pa_assert_se(card = port->card);
108
109 switch (port->direction) {
110 case PA_DIRECTION_OUTPUT:
111- PA_IDXSET_FOREACH(pp.sink, card->sinks, state)
112- if (port == pa_hashmap_get(pp.sink->ports, port->name))
113+ PA_IDXSET_FOREACH(sink, card->sinks, state)
114+ if (port == pa_hashmap_get(sink->ports, port->name))
115 break;
116 break;
117
118 case PA_DIRECTION_INPUT:
119- PA_IDXSET_FOREACH(pp.source, card->sources, state)
120- if (port == pa_hashmap_get(pp.source->ports, port->name))
121+ PA_IDXSET_FOREACH(source, card->sources, state)
122+ if (port == pa_hashmap_get(source->ports, port->name))
123 break;
124 break;
125 }
126
127- pp.is_possible_profile_active =
128- card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name);
129- pp.is_preferred_profile_active = pp.is_possible_profile_active && (!port->preferred_profile ||
130- pa_safe_streq(port->preferred_profile, profile_name_for_dir(card->active_profile, port->direction)));
131- pp.is_port_active = (pp.sink && pp.sink->active_port == port) || (pp.source && pp.source->active_port == port);
132-
133- return pp;
134+ *si = sink;
135+ *so = source;
136 }
137
138-/* Switches to a port, switching profiles if necessary or preferred */
139-static bool switch_to_port(pa_device_port *port) {
140- struct port_pointers pp = find_port_pointers(port);
141+static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
142+ pa_card* card;
143+ pa_sink *sink;
144+ pa_source *source;
145+ bool is_active_profile, is_active_port;
146
147- if (pp.is_port_active)
148- return true; /* Already selected */
149+ if (port->available == PA_AVAILABLE_UNKNOWN)
150+ return PA_HOOK_OK;
151
152- pa_log_debug("Trying to switch to port %s", port->name);
153- if (!pp.is_preferred_profile_active) {
154- if (try_to_switch_profile(port) < 0) {
155- if (pp.is_possible_profile_active)
156- return false;
157- }
158- else
159- /* Now that profile has changed, our sink and source pointers must be updated */
160- pp = find_port_pointers(port);
161- }
162+ card = port->card;
163
164- if (pp.source)
165- pa_source_set_port(pp.source, port->name, false);
166- if (pp.sink)
167- pa_sink_set_port(pp.sink, port->name, false);
168- return true;
169-}
170+ if (!card) {
171+ pa_log_warn("Port %s does not have a card", port->name);
172+ return PA_HOOK_OK;
173+ }
174
175-/* Switches away from a port, switching profiles if necessary or preferred */
176-static bool switch_from_port(pa_device_port *port) {
177- struct port_pointers pp = find_port_pointers(port);
178- pa_device_port *p, *best_port = NULL;
179- void *state;
180+ if (pa_idxset_size(card->sinks) == 0 && pa_idxset_size(card->sources) == 0)
181+ /* This card is not initialized yet. We'll handle it in
182+ sink_new / source_new callbacks later. */
183+ return PA_HOOK_OK;
184
185- if (!pp.is_port_active)
186- return true; /* Already deselected */
187+ find_sink_and_source(card, port, &sink, &source);
188
189- /* Try to find a good enough port to switch to */
190- PA_HASHMAP_FOREACH(p, port->card->ports, state)
191- if (p->direction == port->direction && p != port && p->available != PA_AVAILABLE_NO &&
192- (!best_port || best_port->priority < p->priority))
193- best_port = p;
194+ is_active_profile = card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name);
195+ is_active_port = (sink && sink->active_port == port) || (source && source->active_port == port);
196
197- pa_log_debug("Trying to switch away from port %s, found %s", port->name, best_port ? best_port->name : "no better option");
198+ if (port->available == PA_AVAILABLE_NO && !is_active_port)
199+ return PA_HOOK_OK;
200
201- if (best_port)
202- return switch_to_port(best_port);
203+ if (port->available == PA_AVAILABLE_YES) {
204+ if (is_active_port)
205+ return PA_HOOK_OK;
206
207- return false;
208-}
209+ if (!is_active_profile) {
210+ if (try_to_switch_profile(port) < 0)
211+ return PA_HOOK_OK;
212
213+ pa_assert(card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name));
214
215-static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
216- pa_assert(port);
217+ /* Now that profile has changed, our sink and source pointers must be updated */
218+ find_sink_and_source(card, port, &sink, &source);
219+ }
220
221- if (!port->card) {
222- pa_log_warn("Port %s does not have a card", port->name);
223- return PA_HOOK_OK;
224+ if (source)
225+ pa_source_set_port(source, port->name, false);
226+ if (sink)
227+ pa_sink_set_port(sink, port->name, false);
228 }
229
230- if (pa_idxset_size(port->card->sinks) == 0 && pa_idxset_size(port->card->sources) == 0)
231- /* This card is not initialized yet. We'll handle it in
232- sink_new / source_new callbacks later. */
233- return PA_HOOK_OK;
234+ if (port->available == PA_AVAILABLE_NO) {
235+ if (sink) {
236+ pa_device_port *p2 = pa_device_port_find_best(sink->ports);
237+
238+ if (p2 && p2->available != PA_AVAILABLE_NO)
239+ pa_sink_set_port(sink, p2->name, false);
240+ else {
241+ /* Maybe try to switch to another profile? */
242+ }
243+ }
244
245- switch (port->available) {
246- case PA_AVAILABLE_YES:
247- switch_to_port(port);
248- break;
249- case PA_AVAILABLE_NO:
250- switch_from_port(port);
251- break;
252- default:
253- break;
254+ if (source) {
255+ pa_device_port *p2 = pa_device_port_find_best(source->ports);
256+
257+ if (p2 && p2->available != PA_AVAILABLE_NO)
258+ pa_source_set_port(source, p2->name, false);
259+ else {
260+ /* Maybe try to switch to another profile? */
261+ }
262+ }
263 }
264
265 return PA_HOOK_OK;
266--
2672.7.0
268
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio/0002-alsa-bluetooth-fail-if-user-requested-profile-doesn-.patch b/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-alsa-bluetooth-fail-if-user-requested-profile-doesn-.patch
index be3655b23c..2f72ceb33b 100644
--- a/meta/recipes-multimedia/pulseaudio/pulseaudio/0002-alsa-bluetooth-fail-if-user-requested-profile-doesn-.patch
+++ b/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-alsa-bluetooth-fail-if-user-requested-profile-doesn-.patch
@@ -1,32 +1,26 @@
1From 339eb179baa7810113f6456accc05b3a32c1cdba Mon Sep 17 00:00:00 2001 1From 9c3cdfcd198ef9727ea542f284ac6d8c1bcd7a3a Mon Sep 17 00:00:00 2001
2From: Tanu Kaskinen <tanuk@iki.fi> 2From: Tanu Kaskinen <tanuk@iki.fi>
3Date: Fri, 23 Oct 2015 12:36:34 +0300 3Date: Fri, 23 Oct 2015 12:36:34 +0300
4Subject: [PATCH 2/4] alsa, bluetooth: fail if user-requested profile doesn't 4Subject: [PATCH 1/5] alsa, bluetooth: fail if user-requested profile doesn't
5 exist 5 exist
6 6
7If we can't fulfill the user request fully, I think we shouldn't 7If we can't fulfill the user request fully, I think we shouldn't
8fulfill it at all, to make it clear that the requested operation 8fulfill it at all, to make it clear that the requested operation
9didn't succeed. 9didn't succeed.
10 10
11http://bugzilla.yoctoproject.org/show_bug.cgi?id=8448 11Upstream-Status: Accepted [expected in 10.0]
12
13Signed-off-by: Jussi Kukkonen <jussi.kukkonen@intel.com>
14
15Upstream-Status: Denied [The patch set needs some work to be accepted.
16The review thread:
17http://thread.gmane.org/gmane.comp.audio.pulseaudio.general/24301]
18 12
19Signed-off-by: Tanu Kaskinen <tanuk@iki.fi> 13Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
20--- 14---
21 src/modules/alsa/module-alsa-card.c | 10 ++++++++-- 15 src/modules/alsa/module-alsa-card.c | 11 +++++++++--
22 src/modules/bluetooth/module-bluez4-device.c | 6 ++++-- 16 src/modules/bluetooth/module-bluez4-device.c | 7 +++++--
23 2 files changed, 12 insertions(+), 4 deletions(-) 17 2 files changed, 14 insertions(+), 4 deletions(-)
24 18
25diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c 19diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
26index a7fec04..32f517e 100644 20index e5cc4ae..d761683 100644
27--- a/src/modules/alsa/module-alsa-card.c 21--- a/src/modules/alsa/module-alsa-card.c
28+++ b/src/modules/alsa/module-alsa-card.c 22+++ b/src/modules/alsa/module-alsa-card.c
29@@ -754,8 +754,14 @@ int pa__init(pa_module *m) { 23@@ -799,8 +799,15 @@ int pa__init(pa_module *m) {
30 goto fail; 24 goto fail;
31 } 25 }
32 26
@@ -37,6 +31,7 @@ index a7fec04..32f517e 100644
37+ pa_card_new_data_set_profile(&data, profile); 31+ pa_card_new_data_set_profile(&data, profile);
38+ else { 32+ else {
39+ pa_log("No such profile: %s", profile); 33+ pa_log("No such profile: %s", profile);
34+ pa_card_new_data_done(&data);
40+ goto fail; 35+ goto fail;
41+ } 36+ }
42+ } 37+ }
@@ -44,10 +39,10 @@ index a7fec04..32f517e 100644
44 u->card = pa_card_new(m->core, &data); 39 u->card = pa_card_new(m->core, &data);
45 pa_card_new_data_done(&data); 40 pa_card_new_data_done(&data);
46diff --git a/src/modules/bluetooth/module-bluez4-device.c b/src/modules/bluetooth/module-bluez4-device.c 41diff --git a/src/modules/bluetooth/module-bluez4-device.c b/src/modules/bluetooth/module-bluez4-device.c
47index b40c6a0..94e6988 100644 42index 9a921a5..a2de525 100644
48--- a/src/modules/bluetooth/module-bluez4-device.c 43--- a/src/modules/bluetooth/module-bluez4-device.c
49+++ b/src/modules/bluetooth/module-bluez4-device.c 44+++ b/src/modules/bluetooth/module-bluez4-device.c
50@@ -2310,8 +2310,10 @@ static int add_card(struct userdata *u) { 45@@ -2301,8 +2301,11 @@ static int add_card(struct userdata *u) {
51 if ((default_profile = pa_modargs_get_value(u->modargs, "profile", NULL))) { 46 if ((default_profile = pa_modargs_get_value(u->modargs, "profile", NULL))) {
52 if (pa_hashmap_get(data.profiles, default_profile)) 47 if (pa_hashmap_get(data.profiles, default_profile))
53 pa_card_new_data_set_profile(&data, default_profile); 48 pa_card_new_data_set_profile(&data, default_profile);
@@ -55,11 +50,12 @@ index b40c6a0..94e6988 100644
55- pa_log_warn("Profile '%s' not valid or not supported by device.", default_profile); 50- pa_log_warn("Profile '%s' not valid or not supported by device.", default_profile);
56+ else { 51+ else {
57+ pa_log("Profile '%s' not valid or not supported by device.", default_profile); 52+ pa_log("Profile '%s' not valid or not supported by device.", default_profile);
53+ pa_card_new_data_done(&data);
58+ return -1; 54+ return -1;
59+ } 55+ }
60 } 56 }
61 57
62 u->card = pa_card_new(u->core, &data); 58 u->card = pa_card_new(u->core, &data);
63-- 59--
642.1.4 602.8.1
65 61
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-card-add-pa_card_profile.ports.patch b/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-card-add-pa_card_profile.ports.patch
deleted file mode 100644
index 84c951940b..0000000000
--- a/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-card-add-pa_card_profile.ports.patch
+++ /dev/null
@@ -1,218 +0,0 @@
1From d1c02971867bea10afcafc82c965414012c4d6bd Mon Sep 17 00:00:00 2001
2From: Tanu Kaskinen <tanuk@iki.fi>
3Date: Fri, 23 Oct 2015 12:23:13 +0300
4Subject: [PATCH 1/4] card: add pa_card_profile.ports
5
6Having ports accessible from pa_card_profile allows checking whether all ports
7of a profile are unavailable, and therefore helps with managing the profile
8availability (implemented in a later patch).
9
10http://bugzilla.yoctoproject.org/show_bug.cgi?id=8448
11
12Signed-off-by: Jussi Kukkonen <jussi.kukkonen@intel.com>
13
14Rebased on 8.0.
15
16Upstream-Status: Denied [The patch set needs some work to be accepted.
17The review thread:
18http://thread.gmane.org/gmane.comp.audio.pulseaudio.general/24301]
19
20Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
21---
22 src/modules/alsa/alsa-mixer.c | 4 +++-
23 src/modules/alsa/alsa-ucm.c | 1 +
24 src/modules/bluetooth/module-bluez4-device.c | 6 ++++++
25 src/modules/bluetooth/module-bluez5-device.c | 6 ++++++
26 src/pulsecore/card.c | 15 +++++++++++++++
27 src/pulsecore/card.h | 4 ++++
28 src/pulsecore/device-port.c | 7 ++++++-
29 7 files changed, 41 insertions(+), 2 deletions(-)
30
31diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
32index 1fe2a02..5b76b06 100644
33--- a/src/modules/alsa/alsa-mixer.c
34+++ b/src/modules/alsa/alsa-mixer.c
35@@ -4783,8 +4783,10 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports, /* card ports */
36 path->port = p;
37 }
38
39- if (cp)
40+ if (cp) {
41 pa_hashmap_put(p->profiles, cp->name, cp);
42+ pa_card_profile_add_port(cp, p);
43+ }
44
45 if (extra) {
46 pa_hashmap_put(extra, p->name, p);
47diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
48index 42f3242..68fcc26 100644
49--- a/src/modules/alsa/alsa-ucm.c
50+++ b/src/modules/alsa/alsa-ucm.c
51@@ -791,6 +791,7 @@ static void ucm_add_port_combination(
52 if (cp) {
53 pa_log_debug("Adding profile %s to port %s.", cp->name, port->name);
54 pa_hashmap_put(port->profiles, cp->name, cp);
55+ pa_card_profile_add_port(cp, port);
56 }
57
58 if (hash) {
59diff --git a/src/modules/bluetooth/module-bluez4-device.c b/src/modules/bluetooth/module-bluez4-device.c
60index 9a921a5..adecb32 100644
61--- a/src/modules/bluetooth/module-bluez4-device.c
62+++ b/src/modules/bluetooth/module-bluez4-device.c
63@@ -2180,6 +2180,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
64 p->max_sink_channels = 2;
65 p->max_source_channels = 0;
66 pa_hashmap_put(output_port->profiles, p->name, p);
67+ pa_card_profile_add_port(p, output_port);
68
69 d = PA_CARD_PROFILE_DATA(p);
70 *d = PA_BLUEZ4_PROFILE_A2DP;
71@@ -2191,6 +2192,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
72 p->max_sink_channels = 0;
73 p->max_source_channels = 2;
74 pa_hashmap_put(input_port->profiles, p->name, p);
75+ pa_card_profile_add_port(p, input_port);
76
77 d = PA_CARD_PROFILE_DATA(p);
78 *d = PA_BLUEZ4_PROFILE_A2DP_SOURCE;
79@@ -2203,6 +2205,8 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
80 p->max_source_channels = 1;
81 pa_hashmap_put(input_port->profiles, p->name, p);
82 pa_hashmap_put(output_port->profiles, p->name, p);
83+ pa_card_profile_add_port(p, input_port);
84+ pa_card_profile_add_port(p, output_port);
85
86 d = PA_CARD_PROFILE_DATA(p);
87 *d = PA_BLUEZ4_PROFILE_HSP;
88@@ -2215,6 +2219,8 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
89 p->max_source_channels = 1;
90 pa_hashmap_put(input_port->profiles, p->name, p);
91 pa_hashmap_put(output_port->profiles, p->name, p);
92+ pa_card_profile_add_port(p, input_port);
93+ pa_card_profile_add_port(p, output_port);
94
95 d = PA_CARD_PROFILE_DATA(p);
96 *d = PA_BLUEZ4_PROFILE_HFGW;
97diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
98index 84e6d55..b015c67 100644
99--- a/src/modules/bluetooth/module-bluez5-device.c
100+++ b/src/modules/bluetooth/module-bluez5-device.c
101@@ -1790,6 +1790,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
102 cp->max_sink_channels = 2;
103 cp->max_source_channels = 0;
104 pa_hashmap_put(output_port->profiles, cp->name, cp);
105+ pa_card_profile_add_port(cp, output_port);
106
107 p = PA_CARD_PROFILE_DATA(cp);
108 *p = PA_BLUETOOTH_PROFILE_A2DP_SINK;
109@@ -1801,6 +1802,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
110 cp->max_sink_channels = 0;
111 cp->max_source_channels = 2;
112 pa_hashmap_put(input_port->profiles, cp->name, cp);
113+ pa_card_profile_add_port(cp, input_port);
114
115 p = PA_CARD_PROFILE_DATA(cp);
116 *p = PA_BLUETOOTH_PROFILE_A2DP_SOURCE;
117@@ -1813,6 +1815,8 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
118 cp->max_source_channels = 1;
119 pa_hashmap_put(input_port->profiles, cp->name, cp);
120 pa_hashmap_put(output_port->profiles, cp->name, cp);
121+ pa_card_profile_add_port(cp, input_port);
122+ pa_card_profile_add_port(cp, output_port);
123
124 p = PA_CARD_PROFILE_DATA(cp);
125 *p = PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT;
126@@ -1825,6 +1829,8 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
127 cp->max_source_channels = 1;
128 pa_hashmap_put(input_port->profiles, cp->name, cp);
129 pa_hashmap_put(output_port->profiles, cp->name, cp);
130+ pa_card_profile_add_port(cp, input_port);
131+ pa_card_profile_add_port(cp, output_port);
132
133 p = PA_CARD_PROFILE_DATA(cp);
134 *p = PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY;
135diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
136index b6cbbf7..f92ac87 100644
137--- a/src/pulsecore/card.c
138+++ b/src/pulsecore/card.c
139@@ -45,6 +45,7 @@ pa_card_profile *pa_card_profile_new(const char *name, const char *description,
140 c->name = pa_xstrdup(name);
141 c->description = pa_xstrdup(description);
142 c->available = PA_AVAILABLE_UNKNOWN;
143+ c->ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
144
145 return c;
146 }
147@@ -52,6 +53,14 @@ pa_card_profile *pa_card_profile_new(const char *name, const char *description,
148 void pa_card_profile_free(pa_card_profile *c) {
149 pa_assert(c);
150
151+ if (c->ports) {
152+ pa_device_port *port;
153+ void *state;
154+ PA_HASHMAP_FOREACH(port, c->ports, state)
155+ pa_hashmap_remove (port->profiles, c->name);
156+ pa_hashmap_free(c->ports);
157+ }
158+
159 pa_xfree(c->input_name);
160 pa_xfree(c->output_name);
161 pa_xfree(c->name);
162@@ -59,6 +68,12 @@ void pa_card_profile_free(pa_card_profile *c) {
163 pa_xfree(c);
164 }
165
166+void pa_card_profile_add_port(pa_card_profile *profile, pa_device_port *port) {
167+ pa_assert(profile);
168+
169+ pa_hashmap_put(profile->ports, port->name, port);
170+}
171+
172 void pa_card_profile_set_available(pa_card_profile *c, pa_available_t available) {
173 pa_core *core;
174
175diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
176index 30bfc0e..fff9057 100644
177--- a/src/pulsecore/card.h
178+++ b/src/pulsecore/card.h
179@@ -50,6 +50,8 @@ struct pa_card_profile {
180 unsigned priority;
181 pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
182
183+ pa_hashmap *ports; /* port name -> pa_device_port */
184+
185 /* We probably want to have different properties later on here */
186 unsigned n_sinks;
187 unsigned n_sources;
188@@ -107,6 +109,8 @@ typedef struct pa_card_new_data {
189 pa_card_profile *pa_card_profile_new(const char *name, const char *description, size_t extra);
190 void pa_card_profile_free(pa_card_profile *c);
191
192+void pa_card_profile_add_port(pa_card_profile *profile, pa_device_port *port);
193+
194 /* The profile's available status has changed */
195 void pa_card_profile_set_available(pa_card_profile *c, pa_available_t available);
196
197diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
198index 5807d3e..d12dfbc 100644
199--- a/src/pulsecore/device-port.c
200+++ b/src/pulsecore/device-port.c
201@@ -107,8 +107,13 @@ static void device_port_free(pa_object *o) {
202 if (p->proplist)
203 pa_proplist_free(p->proplist);
204
205- if (p->profiles)
206+ if (p->profiles) {
207+ pa_card_profile *profile;
208+ void *state;
209+ PA_HASHMAP_FOREACH(profile, p->profiles, state)
210+ pa_hashmap_remove (profile->ports, p->name);
211 pa_hashmap_free(p->profiles);
212+ }
213
214 pa_xfree(p->preferred_profile);
215 pa_xfree(p->name);
216--
2172.7.0
218
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-client-conf-Add-allow-autospawn-for-root.patch b/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-client-conf-Add-allow-autospawn-for-root.patch
index bc32775836..33f7709ae4 100644
--- a/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-client-conf-Add-allow-autospawn-for-root.patch
+++ b/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-client-conf-Add-allow-autospawn-for-root.patch
@@ -1,4 +1,4 @@
1From 1cb5647f76dc8cd7bacbce2a64fac9e6c2dc3b16 Mon Sep 17 00:00:00 2001 1From babec3a50dd710d26b72f6c6d43bd79b04e954a6 Mon Sep 17 00:00:00 2001
2From: Tanu Kaskinen <tanu.kaskinen@linux.intel.com> 2From: Tanu Kaskinen <tanu.kaskinen@linux.intel.com>
3Date: Tue, 28 Apr 2015 14:32:43 +0300 3Date: Tue, 28 Apr 2015 14:32:43 +0300
4Subject: [PATCH] client-conf: Add allow-autospawn-for-root 4Subject: [PATCH] client-conf: Add allow-autospawn-for-root
@@ -24,10 +24,10 @@ Signed-off-by: Tanu Kaskinen <tanu.kaskinen@linux.intel.com>
24 5 files changed, 13 insertions(+), 1 deletion(-) 24 5 files changed, 13 insertions(+), 1 deletion(-)
25 25
26diff --git a/man/pulse-client.conf.5.xml.in b/man/pulse-client.conf.5.xml.in 26diff --git a/man/pulse-client.conf.5.xml.in b/man/pulse-client.conf.5.xml.in
27index 1002dbe..0058490 100644 27index b88898c..e737c96 100644
28--- a/man/pulse-client.conf.5.xml.in 28--- a/man/pulse-client.conf.5.xml.in
29+++ b/man/pulse-client.conf.5.xml.in 29+++ b/man/pulse-client.conf.5.xml.in
30@@ -71,6 +71,15 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 30@@ -82,6 +82,15 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
31 </option> 31 </option>
32 32
33 <option> 33 <option>
@@ -44,7 +44,7 @@ index 1002dbe..0058490 100644
44 run when autospawning. Defaults to a path configured at compile 44 run when autospawning. Defaults to a path configured at compile
45 time.</p> 45 time.</p>
46diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c 46diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c
47index 83331f8..0474583 100644 47index a3c9486..9f68ee5 100644
48--- a/src/pulse/client-conf.c 48--- a/src/pulse/client-conf.c
49+++ b/src/pulse/client-conf.c 49+++ b/src/pulse/client-conf.c
50@@ -138,6 +138,7 @@ void pa_client_conf_load(pa_client_conf *c, bool load_from_x11, bool load_from_e 50@@ -138,6 +138,7 @@ void pa_client_conf_load(pa_client_conf *c, bool load_from_x11, bool load_from_e
@@ -56,13 +56,13 @@ index 83331f8..0474583 100644
56 { "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL }, 56 { "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL },
57 { "enable-shm", pa_config_parse_not_bool, &c->disable_shm, NULL }, 57 { "enable-shm", pa_config_parse_not_bool, &c->disable_shm, NULL },
58diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h 58diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h
59index eac705a..131393a 100644 59index 7691ec7..19db7ed 100644
60--- a/src/pulse/client-conf.h 60--- a/src/pulse/client-conf.h
61+++ b/src/pulse/client-conf.h 61+++ b/src/pulse/client-conf.h
62@@ -38,6 +38,7 @@ typedef struct pa_client_conf { 62@@ -38,6 +38,7 @@ typedef struct pa_client_conf {
63 char *cookie_file_from_application; 63 char *cookie_file_from_application;
64 char *cookie_file_from_client_conf; 64 char *cookie_file_from_client_conf;
65 bool autospawn, disable_shm, auto_connect_localhost, auto_connect_display; 65 bool autospawn, disable_shm, disable_memfd, auto_connect_localhost, auto_connect_display;
66+ bool allow_autospawn_for_root; 66+ bool allow_autospawn_for_root;
67 size_t shm_size; 67 size_t shm_size;
68 } pa_client_conf; 68 } pa_client_conf;
@@ -80,10 +80,10 @@ index 26b7790..69830ef 100644
80 ; extra-arguments = --log-target=syslog 80 ; extra-arguments = --log-target=syslog
81 81
82diff --git a/src/pulse/context.c b/src/pulse/context.c 82diff --git a/src/pulse/context.c b/src/pulse/context.c
83index 4bc445f..d6c3f6d 100644 83index 69be5f4..d6e13e8 100644
84--- a/src/pulse/context.c 84--- a/src/pulse/context.c
85+++ b/src/pulse/context.c 85+++ b/src/pulse/context.c
86@@ -976,7 +976,7 @@ int pa_context_connect( 86@@ -1027,7 +1027,7 @@ int pa_context_connect(
87 if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) { 87 if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) {
88 88
89 #ifdef HAVE_GETUID 89 #ifdef HAVE_GETUID
@@ -93,5 +93,5 @@ index 4bc445f..d6c3f6d 100644
93 else { 93 else {
94 c->do_autospawn = true; 94 c->do_autospawn = true;
95-- 95--
961.9.3 962.8.1
97 97
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio/0002-card-don-t-allow-the-CARD_NEW-hook-to-fail.patch b/meta/recipes-multimedia/pulseaudio/pulseaudio/0002-card-don-t-allow-the-CARD_NEW-hook-to-fail.patch
new file mode 100644
index 0000000000..80c291f821
--- /dev/null
+++ b/meta/recipes-multimedia/pulseaudio/pulseaudio/0002-card-don-t-allow-the-CARD_NEW-hook-to-fail.patch
@@ -0,0 +1,37 @@
1From d4e6d07fef28d1bd8bfbceab4cc196ef54c23dd8 Mon Sep 17 00:00:00 2001
2From: Tanu Kaskinen <tanuk@iki.fi>
3Date: Tue, 7 Jun 2016 16:51:00 +0300
4Subject: [PATCH 2/5] card: don't allow the CARD_NEW hook to fail
5
6There is currently no use for allowing modules to cancel card creation,
7and I don't see need for that in the future either. Let's simplify
8things by removing the failure handling code.
9
10Upstream-Status: Accepted [expected in 10.0]
11
12Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
13---
14 src/pulsecore/card.c | 7 +------
15 1 file changed, 1 insertion(+), 6 deletions(-)
16
17diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
18index 410746b..0ac70b9 100644
19--- a/src/pulsecore/card.c
20+++ b/src/pulsecore/card.c
21@@ -149,12 +149,7 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
22 }
23
24 pa_card_new_data_set_name(data, name);
25-
26- if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_NEW], data) < 0) {
27- pa_xfree(c);
28- pa_namereg_unregister(core, name);
29- return NULL;
30- }
31+ pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_NEW], data);
32
33 c->core = core;
34 c->name = pa_xstrdup(data->name);
35--
362.8.1
37
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio/0003-card-move-profile-selection-after-pa_card_new.patch b/meta/recipes-multimedia/pulseaudio/pulseaudio/0003-card-move-profile-selection-after-pa_card_new.patch
index 0e7780154d..e0f424bbcc 100644
--- a/meta/recipes-multimedia/pulseaudio/pulseaudio/0003-card-move-profile-selection-after-pa_card_new.patch
+++ b/meta/recipes-multimedia/pulseaudio/pulseaudio/0003-card-move-profile-selection-after-pa_card_new.patch
@@ -1,61 +1,62 @@
1From 13e85dd1763e99d21a60323671b9a5df08bdae75 Mon Sep 17 00:00:00 2001 1From 0b98309fdbcd36fa92ab53e33c51b485b905e294 Mon Sep 17 00:00:00 2001
2From: Tanu Kaskinen <tanuk@iki.fi> 2From: Tanu Kaskinen <tanuk@iki.fi>
3Date: Fri, 23 Oct 2015 12:59:53 +0300 3Date: Fri, 23 Oct 2015 12:59:53 +0300
4Subject: [PATCH 3/4] card: move profile selection after pa_card_new() 4Subject: [PATCH 3/5] card: move profile selection after pa_card_new()
5 5
6I want module-alsa-card to set the availability of unavailable 6I want module-alsa-card to set the availability of unavailable
7profiles before the initial card profile gets selected, so that the 7profiles before the initial card profile gets selected, so that the
8selection logic can use correct availability information. 8selection logic can use correct availability information.
9module-alsa-card initializes the jack state after calling 9module-alsa-card initializes the jack state after calling
10pa_card_new(), however, and the profile selection happens in 10pa_card_new(), however, and the profile selection happens in
11pa_card_new(). This patch solves that by introducing pa_card_put() and 11pa_card_new(). This patch solves that by moving parts of pa_card_new()
12moving the profile selection code there. 12to pa_card_choose_initial_profile() and pa_card_put().
13
14pa_card_choose_initial_profile() applies the profile selection policy,
15so module-alsa-card can first call pa_card_new(), then initialize the
16jack state, and then call pa_card_choose_initial_profile(). After that
17module-alsa-card can still override the profile selection policy, in
18case module-alsa-card was loaded with the "profile" argument. Finally,
19pa_card_put() finalizes the card creation.
13 20
14An alternative solution would have been to move the jack 21An alternative solution would have been to move the jack
15initialization to happen before pa_card_new() and use pa_card_new_data 22initialization to happen before pa_card_new() and use pa_card_new_data
16instead of pa_card in the jack initialization code, but I disliked 23instead of pa_card in the jack initialization code, but I disliked
17that idea (I want to get rid of the "new data" pattern eventually). 24that idea (I want to get rid of the "new data" pattern eventually).
18 25
19The CARD_NEW hook is used when applying the initial profile policy, so
20that was moved to pa_card_put(). That required changing the hook data
21from pa_card_new_data to pa_card. module-card-restore now uses
22pa_card_set_profile() instead of pa_card_new_data_set_profile(). That
23required adding a state variable to pa_card, because
24pa_card_set_profile() needs to distinguish between setting the initial
25profile and setting the profile in other situations.
26
27The order in which the initial profile policy is applied is reversed 26The order in which the initial profile policy is applied is reversed
28in this patch. Previously the first one to set it won, now the last 27in this patch. Previously the first one to set it won, now the last
29one to set it wins. I think this is better, because if you have N 28one to set it wins. I think this is better, because if you have N
30parties that want to set the profile, we avoid checking N times 29parties that want to set the profile, we avoid checking N times
31whether someone else has already set the profile. 30whether someone else has already set the profile.
32 31
33http://bugzilla.yoctoproject.org/show_bug.cgi?id=8448 32Upstream-Status: Accepted [expected in 10.0]
34
35Signed-off-by: Jussi Kukkonen <jussi.kukkonen@intel.com>
36
37Rebased on 8.0.
38
39Upstream-Status: Denied [The patch set needs some work to be accepted.
40The review thread:
41http://thread.gmane.org/gmane.comp.audio.pulseaudio.general/24301]
42 33
43Signed-off-by: Tanu Kaskinen <tanuk@iki.fi> 34Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
44--- 35---
45 src/modules/alsa/module-alsa-card.c | 19 +++---- 36 src/modules/alsa/module-alsa-card.c | 32 +++++----
46 src/modules/bluetooth/module-bluez4-device.c | 18 +++---- 37 src/modules/bluetooth/module-bluez4-device.c | 31 +++++----
47 src/modules/bluetooth/module-bluez5-device.c | 1 + 38 src/modules/bluetooth/module-bluez5-device.c | 2 +
48 src/modules/macosx/module-coreaudio-device.c | 1 + 39 src/modules/macosx/module-coreaudio-device.c | 2 +
49 src/modules/module-card-restore.c | 24 +++++---- 40 src/modules/module-card-restore.c | 36 +++++++---
50 src/pulsecore/card.c | 81 +++++++++++++++------------- 41 src/pulsecore/card.c | 99 +++++++++++++++++-----------
51 src/pulsecore/card.h | 7 +++ 42 src/pulsecore/card.h | 9 +++
52 7 files changed, 86 insertions(+), 65 deletions(-) 43 src/pulsecore/core.h | 1 +
44 8 files changed, 143 insertions(+), 69 deletions(-)
53 45
54diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c 46diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
55index 9e8cde2..fe240f0 100644 47index d761683..1976230 100644
56--- a/src/modules/alsa/module-alsa-card.c 48--- a/src/modules/alsa/module-alsa-card.c
57+++ b/src/modules/alsa/module-alsa-card.c 49+++ b/src/modules/alsa/module-alsa-card.c
58@@ -770,15 +770,6 @@ int pa__init(pa_module *m) { 50@@ -671,7 +671,7 @@ int pa__init(pa_module *m) {
51 struct userdata *u;
52 pa_reserve_wrapper *reserve = NULL;
53 const char *description;
54- const char *profile = NULL;
55+ const char *profile_str = NULL;
56 char *fn = NULL;
57 bool namereg_fail = false;
58
59@@ -799,16 +799,6 @@ int pa__init(pa_module *m) {
59 goto fail; 60 goto fail;
60 } 61 }
61 62
@@ -64,6 +65,7 @@ index 9e8cde2..fe240f0 100644
64- pa_card_new_data_set_profile(&data, profile); 65- pa_card_new_data_set_profile(&data, profile);
65- else { 66- else {
66- pa_log("No such profile: %s", profile); 67- pa_log("No such profile: %s", profile);
68- pa_card_new_data_done(&data);
67- goto fail; 69- goto fail;
68- } 70- }
69- } 71- }
@@ -71,28 +73,47 @@ index 9e8cde2..fe240f0 100644
71 u->card = pa_card_new(m->core, &data); 73 u->card = pa_card_new(m->core, &data);
72 pa_card_new_data_done(&data); 74 pa_card_new_data_done(&data);
73 75
74@@ -789,6 +780,16 @@ int pa__init(pa_module *m) { 76@@ -822,6 +812,26 @@ int pa__init(pa_module *m) {
75 u->card->set_profile = card_set_profile; 77 (pa_hook_cb_t) card_suspend_changed, u);
76 78
77 init_jacks(u); 79 init_jacks(u);
78+ pa_card_put(u->card);
79+ 80+
80+ if ((profile = pa_modargs_get_value(u->modargs, "profile", NULL))) { 81+ pa_card_choose_initial_profile(u->card);
81+ u->card->active_profile = pa_hashmap_get(u->card->profiles, profile); 82+
82+ if (!u->card->active_profile) { 83+ /* If the "profile" modarg is given, we have to override whatever the usual
83+ pa_log("No such profile: %s", profile); 84+ * policy chose in pa_card_choose_initial_profile(). */
85+ profile_str = pa_modargs_get_value(u->modargs, "profile", NULL);
86+ if (profile_str) {
87+ pa_card_profile *profile;
88+
89+ profile = pa_hashmap_get(u->card->profiles, profile_str);
90+ if (!profile) {
91+ pa_log("No such profile: %s", profile_str);
84+ goto fail; 92+ goto fail;
85+ } 93+ }
94+
95+ pa_card_set_profile(u->card, profile, false);
86+ } 96+ }
87+ 97+
98+ pa_card_put(u->card);
99+
88 init_profile(u); 100 init_profile(u);
89 init_eld_ctls(u); 101 init_eld_ctls(u);
90 102
91diff --git a/src/modules/bluetooth/module-bluez4-device.c b/src/modules/bluetooth/module-bluez4-device.c 103diff --git a/src/modules/bluetooth/module-bluez4-device.c b/src/modules/bluetooth/module-bluez4-device.c
92index dd18217..5d0d3db 100644 104index a2de525..13fb7ab 100644
93--- a/src/modules/bluetooth/module-bluez4-device.c 105--- a/src/modules/bluetooth/module-bluez4-device.c
94+++ b/src/modules/bluetooth/module-bluez4-device.c 106+++ b/src/modules/bluetooth/module-bluez4-device.c
95@@ -2304,15 +2304,6 @@ static int add_card(struct userdata *u) { 107@@ -2238,7 +2238,7 @@ static int add_card(struct userdata *u) {
108 pa_bluez4_profile_t *d;
109 pa_bluez4_form_factor_t ff;
110 char *n;
111- const char *default_profile;
112+ const char *profile_str;
113 const pa_bluez4_device *device;
114 const pa_bluez4_uuid *uuid;
115
116@@ -2298,16 +2298,6 @@ static int add_card(struct userdata *u) {
96 *d = PA_BLUEZ4_PROFILE_OFF; 117 *d = PA_BLUEZ4_PROFILE_OFF;
97 pa_hashmap_put(data.profiles, p->name, p); 118 pa_hashmap_put(data.profiles, p->name, p);
98 119
@@ -101,6 +122,7 @@ index dd18217..5d0d3db 100644
101- pa_card_new_data_set_profile(&data, default_profile); 122- pa_card_new_data_set_profile(&data, default_profile);
102- else { 123- else {
103- pa_log("Profile '%s' not valid or not supported by device.", default_profile); 124- pa_log("Profile '%s' not valid or not supported by device.", default_profile);
125- pa_card_new_data_done(&data);
104- return -1; 126- return -1;
105- } 127- }
106- } 128- }
@@ -108,127 +130,126 @@ index dd18217..5d0d3db 100644
108 u->card = pa_card_new(u->core, &data); 130 u->card = pa_card_new(u->core, &data);
109 pa_card_new_data_done(&data); 131 pa_card_new_data_done(&data);
110 132
111@@ -2323,6 +2314,15 @@ static int add_card(struct userdata *u) { 133@@ -2319,6 +2309,25 @@ static int add_card(struct userdata *u) {
112
113 u->card->userdata = u; 134 u->card->userdata = u;
114 u->card->set_profile = card_set_profile; 135 u->card->set_profile = card_set_profile;
115+ pa_card_put(u->card); 136
137+ pa_card_choose_initial_profile(u->card);
138+
139+ /* If the "profile" modarg is given, we have to override whatever the usual
140+ * policy chose in pa_card_choose_initial_profile(). */
141+ profile_str = pa_modargs_get_value(u->modargs, "profile", NULL);
142+ if (profile_str) {
143+ pa_card_profile *profile;
116+ 144+
117+ if ((default_profile = pa_modargs_get_value(u->modargs, "profile", NULL))) { 145+ profile = pa_hashmap_get(u->card->profiles, profile_str);
118+ u->card->active_profile = pa_hashmap_get(u->card->profiles, default_profile); 146+ if (!profile) {
119+ if (!u->card->active_profile) { 147+ pa_log("No such profile: %s", profile_str);
120+ pa_log("Profile '%s' not valid or not supported by device.", default_profile);
121+ return -1; 148+ return -1;
122+ } 149+ }
150+
151+ pa_card_set_profile(u->card, profile, false);
123+ } 152+ }
124 153+
154+ pa_card_put(u->card);
155+
125 d = PA_CARD_PROFILE_DATA(u->card->active_profile); 156 d = PA_CARD_PROFILE_DATA(u->card->active_profile);
126 157
158 if (*d != PA_BLUEZ4_PROFILE_OFF && (!device->transports[*d] ||
127diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c 159diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
128index b015c67..7b90a31 100644 160index 84e6d55..498d0e1 100644
129--- a/src/modules/bluetooth/module-bluez5-device.c 161--- a/src/modules/bluetooth/module-bluez5-device.c
130+++ b/src/modules/bluetooth/module-bluez5-device.c 162+++ b/src/modules/bluetooth/module-bluez5-device.c
131@@ -1959,6 +1959,7 @@ static int add_card(struct userdata *u) { 163@@ -1953,6 +1953,8 @@ static int add_card(struct userdata *u) {
132 164
133 u->card->userdata = u; 165 u->card->userdata = u;
134 u->card->set_profile = set_profile_cb; 166 u->card->set_profile = set_profile_cb;
167+ pa_card_choose_initial_profile(u->card);
135+ pa_card_put(u->card); 168+ pa_card_put(u->card);
136 169
137 p = PA_CARD_PROFILE_DATA(u->card->active_profile); 170 p = PA_CARD_PROFILE_DATA(u->card->active_profile);
138 u->profile = *p; 171 u->profile = *p;
139diff --git a/src/modules/macosx/module-coreaudio-device.c b/src/modules/macosx/module-coreaudio-device.c 172diff --git a/src/modules/macosx/module-coreaudio-device.c b/src/modules/macosx/module-coreaudio-device.c
140index 0c92d42..7190ee9 100644 173index 6c9e55d..d91c656 100644
141--- a/src/modules/macosx/module-coreaudio-device.c 174--- a/src/modules/macosx/module-coreaudio-device.c
142+++ b/src/modules/macosx/module-coreaudio-device.c 175+++ b/src/modules/macosx/module-coreaudio-device.c
143@@ -807,6 +807,7 @@ int pa__init(pa_module *m) { 176@@ -821,6 +821,8 @@ int pa__init(pa_module *m) {
144 pa_card_new_data_done(&card_new_data); 177 pa_card_new_data_done(&card_new_data);
145 u->card->userdata = u; 178 u->card->userdata = u;
146 u->card->set_profile = card_set_profile; 179 u->card->set_profile = card_set_profile;
180+ pa_card_choose_initial_profile(u->card);
147+ pa_card_put(u->card); 181+ pa_card_put(u->card);
148 182
149 u->rtpoll = pa_rtpoll_new(); 183 u->rtpoll = pa_rtpoll_new();
150 pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); 184 pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
151diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c 185diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
152index f906843..dce6674 100644 186index 7545aa5..718a0dd 100644
153--- a/src/modules/module-card-restore.c 187--- a/src/modules/module-card-restore.c
154+++ b/src/modules/module-card-restore.c 188+++ b/src/modules/module-card-restore.c
155@@ -515,34 +515,38 @@ static pa_hook_result_t port_offset_change_callback(pa_core *c, pa_device_port * 189@@ -551,16 +551,6 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new
156 return PA_HOOK_OK; 190 if (!(e = entry_read(u, new_data->name)))
157 }
158
159-static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new_data, struct userdata *u) {
160+static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card *card, struct userdata *u) {
161 struct entry *e;
162 void *state;
163 pa_device_port *p;
164 struct port_info *p_info;
165
166- pa_assert(new_data);
167+ pa_assert(c);
168+ pa_assert(card);
169+ pa_assert(u);
170
171- if (!(e = entry_read(u, new_data->name)))
172+ if (!(e = entry_read(u, card->name)))
173 return PA_HOOK_OK; 191 return PA_HOOK_OK;
174 192
175 if (e->profile[0]) { 193- if (e->profile[0]) {
176- if (!new_data->active_profile) { 194- if (!new_data->active_profile) {
177- pa_card_new_data_set_profile(new_data, e->profile); 195- pa_card_new_data_set_profile(new_data, e->profile);
178- pa_log_info("Restored profile '%s' for card %s.", new_data->active_profile, new_data->name); 196- pa_log_info("Restored profile '%s' for card %s.", new_data->active_profile, new_data->name);
179- new_data->save_profile = true; 197- new_data->save_profile = true;
180+ pa_card_profile *profile; 198-
199- } else
200- pa_log_debug("Not restoring profile for card %s, because already set.", new_data->name);
201- }
202-
203 /* Always restore the latency offsets because their
204 * initial value is always 0 */
205
206@@ -590,6 +580,30 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new
207 return PA_HOOK_OK;
208 }
181 209
210+static pa_hook_result_t card_choose_initial_profile_callback(pa_core *core, pa_card *card, struct userdata *u) {
211+ struct entry *e;
212+
213+ if (!(e = entry_read(u, card->name)))
214+ return PA_HOOK_OK;
215+
216+ if (e->profile[0]) {
217+ pa_card_profile *profile;
218+
182+ profile = pa_hashmap_get(card->profiles, e->profile); 219+ profile = pa_hashmap_get(card->profiles, e->profile);
183+ if (profile) { 220+ if (profile) {
221+ pa_log_info("Restoring profile '%s' for card %s.", card->active_profile->name, card->name);
184+ pa_card_set_profile(card, profile, true); 222+ pa_card_set_profile(card, profile, true);
185+ pa_log_info("Restored profile '%s' for card %s.", card->active_profile->name, card->name); 223+ } else {
186 } else
187- pa_log_debug("Not restoring profile for card %s, because already set.", new_data->name);
188+ pa_log_debug("Tried to restore profile %s for card %s, but the card doesn't have such profile.", 224+ pa_log_debug("Tried to restore profile %s for card %s, but the card doesn't have such profile.",
189+ e->profile, card->name); 225+ e->profile, card->name);
190 } 226+ }
191 227+ }
192 /* Always restore the latency offsets because their 228+
193 * initial value is always 0 */ 229+ entry_free(e);
194 230+
195- pa_log_info("Restoring port latency offsets for card %s.", new_data->name); 231+ return PA_HOOK_OK;
196+ pa_log_info("Restoring port latency offsets for card %s.", card->name); 232+}
197 233+
198 PA_HASHMAP_FOREACH(p_info, e->ports, state) 234 static pa_hook_result_t card_preferred_port_changed_callback(pa_core *core, pa_card_preferred_port_changed_hook_data *data,
199- if ((p = pa_hashmap_get(new_data->ports, p_info->name))) { 235 struct userdata *u) {
200+ if ((p = pa_hashmap_get(card->ports, p_info->name))) { 236 struct entry *e;
201 p->latency_offset = p_info->offset; 237@@ -634,6 +648,8 @@ int pa__init(pa_module*m) {
202 if (!p->preferred_profile && p_info->profile) 238 u->module = m;
203 pa_device_port_set_preferred_profile(p, p_info->profile); 239
240 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) card_new_hook_callback, u);
241+ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_CHOOSE_INITIAL_PROFILE], PA_HOOK_NORMAL,
242+ (pa_hook_cb_t) card_choose_initial_profile_callback, u);
243 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);
244 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PREFERRED_PORT_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_preferred_port_changed_callback, u);
245 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_profile_changed_callback, u);
204diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c 246diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
205index f92ac87..1a6e705 100644 247index 0ac70b9..a0c3d93 100644
206--- a/src/pulsecore/card.c 248--- a/src/pulsecore/card.c
207+++ b/src/pulsecore/card.c 249+++ b/src/pulsecore/card.c
208@@ -148,6 +148,7 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) { 250@@ -176,38 +176,56 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
209 pa_assert(!pa_hashmap_isempty(data->profiles)); 251 c->preferred_input_port = data->preferred_input_port;
210 252 c->preferred_output_port = data->preferred_output_port;
211 c = pa_xnew0(pa_card, 1);
212+ c->state = PA_CARD_STATE_INIT;
213
214 if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_CARD, c, data->namereg_fail))) {
215 pa_xfree(c);
216@@ -156,12 +157,6 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
217
218 pa_card_new_data_set_name(data, name);
219
220- if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_NEW], data) < 0) {
221- pa_xfree(c);
222- pa_namereg_unregister(core, name);
223- return NULL;
224- }
225-
226 c->core = core;
227 c->name = pa_xstrdup(data->name);
228 c->proplist = pa_proplist_copy(data->proplist);
229@@ -184,38 +179,43 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
230 PA_HASHMAP_FOREACH(port, c->ports, state)
231 port->card = c;
232 253
233- if (data->active_profile) 254- if (data->active_profile)
234- if ((c->active_profile = pa_hashmap_get(c->profiles, data->active_profile))) 255- if ((c->active_profile = pa_hashmap_get(c->profiles, data->active_profile)))
@@ -252,50 +273,85 @@ index f92ac87..1a6e705 100644
252- PA_HASHMAP_FOREACH(profile, c->profiles, state) 273- PA_HASHMAP_FOREACH(profile, c->profiles, state)
253- if (!c->active_profile || profile->priority > c->active_profile->priority) 274- if (!c->active_profile || profile->priority > c->active_profile->priority)
254- c->active_profile = profile; 275- c->active_profile = profile;
255- } 276+void pa_card_choose_initial_profile(pa_card *card) {
256- pa_assert(c->active_profile);
257+void pa_card_put(pa_card *card) {
258+ pa_card_profile *profile; 277+ pa_card_profile *profile;
259+ void *state; 278+ void *state;
279+ pa_card_profile *best = NULL;
260+ 280+
261+ pa_assert(card); 281+ pa_assert(card);
262+ 282+
283+ /* By default, pick the highest priority profile that is not unavailable,
284+ * or if all profiles are unavailable, pick the profile with the highest
285+ * priority regardless of its availability. */
286+
263+ PA_HASHMAP_FOREACH(profile, card->profiles, state) { 287+ PA_HASHMAP_FOREACH(profile, card->profiles, state) {
264+ if (profile->available == PA_AVAILABLE_NO) 288+ if (profile->available == PA_AVAILABLE_NO)
265+ continue; 289+ continue;
266+ 290+
267+ if (!card->active_profile || profile->priority > card->active_profile->priority) 291+ if (!best || profile->priority > best->priority)
268+ card->active_profile = profile; 292+ best = profile;
293+ }
294+
295+ if (!best) {
296+ PA_HASHMAP_FOREACH(profile, card->profiles, state) {
297+ if (!best || profile->priority > best->priority)
298+ best = profile;
299 }
300- pa_assert(c->active_profile);
269 } 301 }
302+ pa_assert(best);
270 303
271- pa_device_init_description(c->proplist, c); 304- pa_device_init_description(c->proplist, c);
272- pa_device_init_icon(c->proplist, true); 305- pa_device_init_icon(c->proplist, true);
273- pa_device_init_intended_roles(c->proplist); 306- pa_device_init_intended_roles(c->proplist);
274+ /* If all profiles are unavailable, then we still need to pick one */ 307+ card->active_profile = best;
275+ if (!card->active_profile) { 308+ card->save_profile = false;
276+ PA_HASHMAP_FOREACH(profile, card->profiles, state)
277+ if (!card->active_profile || profile->priority > card->active_profile->priority)
278+ card->active_profile = profile;
279+ }
280+ pa_assert(card->active_profile);
281 309
282- pa_assert_se(pa_idxset_put(core->cards, c, &c->index) >= 0); 310- pa_assert_se(pa_idxset_put(core->cards, c, &c->index) >= 0);
283+ pa_hook_fire(&card->core->hooks[PA_CORE_HOOK_CARD_NEW], card); 311+ /* Let policy modules override the default. */
312+ pa_hook_fire(&card->core->hooks[PA_CORE_HOOK_CARD_CHOOSE_INITIAL_PROFILE], card);
313+}
284 314
285- pa_log_info("Created %u \"%s\"", c->index, c->name); 315- pa_log_info("Created %u \"%s\"", c->index, c->name);
286- pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_NEW, c->index); 316- pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_NEW, c->index);
287+ pa_assert_se(pa_idxset_put(card->core->cards, card, &card->index) >= 0); 317+void pa_card_put(pa_card *card) {
288+ card->state = PA_CARD_STATE_LINKED; 318+ pa_assert(card);
289 319
290- pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_PUT], c); 320- pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_PUT], c);
291- return c; 321- return c;
322+ pa_assert_se(pa_idxset_put(card->core->cards, card, &card->index) >= 0);
323+ card->linked = true;
324+
292+ pa_log_info("Created %u \"%s\"", card->index, card->name); 325+ pa_log_info("Created %u \"%s\"", card->index, card->name);
293+ pa_hook_fire(&card->core->hooks[PA_CORE_HOOK_CARD_PUT], card); 326+ pa_hook_fire(&card->core->hooks[PA_CORE_HOOK_CARD_PUT], card);
294+ pa_subscription_post(card->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_NEW, card->index); 327+ pa_subscription_post(card->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_NEW, card->index);
295 } 328 }
296 329
297 void pa_card_free(pa_card *c) { 330 void pa_card_free(pa_card *c) {
298@@ -306,20 +306,27 @@ int pa_card_set_profile(pa_card *c, pa_card_profile *profile, bool save) { 331@@ -218,15 +236,15 @@ void pa_card_free(pa_card *c) {
332
333 core = c->core;
334
335- pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_UNLINK], c);
336-
337- pa_namereg_unregister(core, c->name);
338-
339- pa_idxset_remove_by_data(c->core->cards, c, NULL);
340+ if (c->linked) {
341+ pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_UNLINK], c);
342
343- pa_log_info("Freed %u \"%s\"", c->index, c->name);
344+ pa_idxset_remove_by_data(c->core->cards, c, NULL);
345+ pa_log_info("Freed %u \"%s\"", c->index, c->name);
346+ pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_REMOVE, c->index);
347+ }
348
349- pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_REMOVE, c->index);
350+ pa_namereg_unregister(core, c->name);
351
352 pa_assert(pa_idxset_isempty(c->sinks));
353 pa_idxset_free(c->sinks, NULL);
354@@ -298,20 +316,27 @@ int pa_card_set_profile(pa_card *c, pa_card_profile *profile, bool save) {
299 return 0; 355 return 0;
300 } 356 }
301 357
@@ -307,7 +363,7 @@ index f92ac87..1a6e705 100644
307+ * be probably good to change this so that also the initial profile can be 363+ * be probably good to change this so that also the initial profile can be
308+ * set up in set_profile(), but if set_profile() fails, that would need 364+ * set up in set_profile(), but if set_profile() fails, that would need
309+ * some better handling than what we do here currently. */ 365+ * some better handling than what we do here currently. */
310+ if (c->state != PA_CARD_STATE_INIT && (r = c->set_profile(c, profile)) < 0) 366+ if (c->linked && (r = c->set_profile(c, profile)) < 0)
311 return r; 367 return r;
312 368
313- pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index); 369- pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index);
@@ -321,7 +377,7 @@ index f92ac87..1a6e705 100644
321 update_port_preferred_profile(c); 377 update_port_preferred_profile(c);
322 378
323- pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], c); 379- pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], c);
324+ if (c->state != PA_CARD_STATE_INIT) { 380+ if (c->linked) {
325+ pa_log_info("Changed profile of card %u \"%s\" to %s", c->index, c->name, profile->name); 381+ pa_log_info("Changed profile of card %u \"%s\" to %s", c->index, c->name, profile->name);
326+ pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], c); 382+ pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], c);
327+ pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index); 383+ pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index);
@@ -330,37 +386,44 @@ index f92ac87..1a6e705 100644
330 return 0; 386 return 0;
331 } 387 }
332diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h 388diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
333index fff9057..a944301 100644 389index d4970e3..fd1fe0a 100644
334--- a/src/pulsecore/card.h 390--- a/src/pulsecore/card.h
335+++ b/src/pulsecore/card.h 391+++ b/src/pulsecore/card.h
336@@ -34,6 +34,11 @@ typedef enum pa_available { 392@@ -86,6 +86,8 @@ struct pa_card {
337 PA_AVAILABLE_YES = 2, 393
338 } pa_available_t; 394 pa_suspend_cause_t suspend_cause;
339 395
340+typedef enum pa_card_state { 396+ bool linked;
341+ PA_CARD_STATE_INIT,
342+ PA_CARD_STATE_LINKED,
343+} pa_card_state_t;
344+ 397+
345 struct pa_card_profile { 398 void *userdata;
346 pa_card *card; 399
347 char *name; 400 int (*set_profile)(pa_card *c, pa_card_profile *profile);
348@@ -66,6 +71,7 @@ struct pa_card_profile { 401@@ -128,6 +130,13 @@ void pa_card_new_data_set_preferred_port(pa_card_new_data *data, pa_direction_t
349
350 struct pa_card {
351 uint32_t index;
352+ pa_card_state_t state;
353 pa_core *core;
354
355 char *name;
356@@ -120,6 +126,7 @@ void pa_card_new_data_set_profile(pa_card_new_data *data, const char *profile);
357 void pa_card_new_data_done(pa_card_new_data *data); 402 void pa_card_new_data_done(pa_card_new_data *data);
358 403
359 pa_card *pa_card_new(pa_core *c, pa_card_new_data *data); 404 pa_card *pa_card_new(pa_core *c, pa_card_new_data *data);
405+
406+/* Select the initial card profile according to the configured policies. This
407+ * must be called between pa_card_new() and pa_card_put(), after the port and
408+ * profile availablities have been initialized. */
409+void pa_card_choose_initial_profile(pa_card *card);
410+
360+void pa_card_put(pa_card *c); 411+void pa_card_put(pa_card *c);
361 void pa_card_free(pa_card *c); 412 void pa_card_free(pa_card *c);
362 413
363 void pa_card_add_profile(pa_card *c, pa_card_profile *profile); 414 void pa_card_add_profile(pa_card *c, pa_card_profile *profile);
415diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
416index 00d7f2f..802111b 100644
417--- a/src/pulsecore/core.h
418+++ b/src/pulsecore/core.h
419@@ -118,6 +118,7 @@ typedef enum pa_core_hook {
420 PA_CORE_HOOK_CLIENT_PROPLIST_CHANGED,
421 PA_CORE_HOOK_CLIENT_SEND_EVENT,
422 PA_CORE_HOOK_CARD_NEW,
423+ PA_CORE_HOOK_CARD_CHOOSE_INITIAL_PROFILE,
424 PA_CORE_HOOK_CARD_PUT,
425 PA_CORE_HOOK_CARD_UNLINK,
426 PA_CORE_HOOK_CARD_PREFERRED_PORT_CHANGED,
364-- 427--
3652.7.0 4282.8.1
366 429
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio/0004-card-remove-pa_card_new_data.active_profile.patch b/meta/recipes-multimedia/pulseaudio/pulseaudio/0004-card-remove-pa_card_new_data.active_profile.patch
new file mode 100644
index 0000000000..480f2cea41
--- /dev/null
+++ b/meta/recipes-multimedia/pulseaudio/pulseaudio/0004-card-remove-pa_card_new_data.active_profile.patch
@@ -0,0 +1,72 @@
1From 375bc56fd3d66f40a9650224e5bfea4002494ade Mon Sep 17 00:00:00 2001
2From: Tanu Kaskinen <tanuk@iki.fi>
3Date: Fri, 23 Oct 2015 13:50:35 +0300
4Subject: [PATCH 4/5] card: remove pa_card_new_data.active_profile
5
6It's not being used any more.
7
8Upstream-Status: Accepted [expected in 10.0]
9
10Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
11---
12 src/pulsecore/card.c | 8 --------
13 src/pulsecore/card.h | 5 -----
14 2 files changed, 13 deletions(-)
15
16diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
17index a0c3d93..bc5b75b 100644
18--- a/src/pulsecore/card.c
19+++ b/src/pulsecore/card.c
20@@ -96,13 +96,6 @@ void pa_card_new_data_set_name(pa_card_new_data *data, const char *name) {
21 data->name = pa_xstrdup(name);
22 }
23
24-void pa_card_new_data_set_profile(pa_card_new_data *data, const char *profile) {
25- pa_assert(data);
26-
27- pa_xfree(data->active_profile);
28- data->active_profile = pa_xstrdup(profile);
29-}
30-
31 void pa_card_new_data_set_preferred_port(pa_card_new_data *data, pa_direction_t direction, pa_device_port *port) {
32 pa_assert(data);
33
34@@ -125,7 +118,6 @@ void pa_card_new_data_done(pa_card_new_data *data) {
35 pa_hashmap_free(data->ports);
36
37 pa_xfree(data->name);
38- pa_xfree(data->active_profile);
39 }
40
41 pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
42diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
43index fd1fe0a..5699475 100644
44--- a/src/pulsecore/card.h
45+++ b/src/pulsecore/card.h
46@@ -101,15 +101,11 @@ typedef struct pa_card_new_data {
47 pa_module *module;
48
49 pa_hashmap *profiles;
50- char *active_profile;
51-
52 pa_hashmap *ports;
53 pa_device_port *preferred_input_port;
54 pa_device_port *preferred_output_port;
55
56 bool namereg_fail:1;
57-
58- bool save_profile:1;
59 } pa_card_new_data;
60
61 typedef struct {
62@@ -125,7 +121,6 @@ void pa_card_profile_set_available(pa_card_profile *c, pa_available_t available)
63
64 pa_card_new_data *pa_card_new_data_init(pa_card_new_data *data);
65 void pa_card_new_data_set_name(pa_card_new_data *data, const char *name);
66-void pa_card_new_data_set_profile(pa_card_new_data *data, const char *profile);
67 void pa_card_new_data_set_preferred_port(pa_card_new_data *data, pa_direction_t direction, pa_device_port *port);
68 void pa_card_new_data_done(pa_card_new_data *data);
69
70--
712.8.1
72
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio/0004-alsa-set-availability-for-some-unavailable-profiles.patch b/meta/recipes-multimedia/pulseaudio/pulseaudio/0005-alsa-set-availability-for-some-unavailable-profiles.patch
index e0efa70f32..5563d2c352 100644
--- a/meta/recipes-multimedia/pulseaudio/pulseaudio/0004-alsa-set-availability-for-some-unavailable-profiles.patch
+++ b/meta/recipes-multimedia/pulseaudio/pulseaudio/0005-alsa-set-availability-for-some-unavailable-profiles.patch
@@ -1,7 +1,7 @@
1From 690d567e298f6687b61c82660b051df5b25482ee Mon Sep 17 00:00:00 2001 1From ae6a01ba204b480bda6a5b4431be3d22e53a7006 Mon Sep 17 00:00:00 2001
2From: Tanu Kaskinen <tanuk@iki.fi> 2From: Tanu Kaskinen <tanuk@iki.fi>
3Date: Fri, 23 Oct 2015 13:37:11 +0300 3Date: Fri, 23 Oct 2015 13:37:11 +0300
4Subject: [PATCH 4/4] alsa: set availability for (some) unavailable profiles 4Subject: [PATCH 5/5] alsa: set availability for (some) unavailable profiles
5 5
6The alsa card hasn't so far set any availability for profiles. That 6The alsa card hasn't so far set any availability for profiles. That
7caused an issue with some HDMI hardware: the sound card has two HDMI 7caused an issue with some HDMI hardware: the sound card has two HDMI
@@ -22,50 +22,46 @@ pa_card_profile, however.
22 22
23BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=8448 23BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=8448
24 24
25Signed-off-by: Jussi Kukkonen <jussi.kukkonen@intel.com> 25Upstream-Status: Accepted [expected in 10.0]
26
27Rebased on 8.0.
28
29Upstream-Status: Denied [The patch set needs some work to be accepted.
30The review thread:
31http://thread.gmane.org/gmane.comp.audio.pulseaudio.general/24301]
32 26
33Signed-off-by: Tanu Kaskinen <tanuk@iki.fi> 27Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
34--- 28---
35 src/modules/alsa/module-alsa-card.c | 25 +++++++++++++++++++++++++ 29 src/modules/alsa/module-alsa-card.c | 27 +++++++++++++++++++++++++++
36 1 file changed, 25 insertions(+) 30 1 file changed, 27 insertions(+)
37 31
38diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c 32diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
39index fe240f0..bdbdc12 100644 33index 1976230..323e08a 100644
40--- a/src/modules/alsa/module-alsa-card.c 34--- a/src/modules/alsa/module-alsa-card.c
41+++ b/src/modules/alsa/module-alsa-card.c 35+++ b/src/modules/alsa/module-alsa-card.c
42@@ -366,6 +366,8 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { 36@@ -366,6 +366,7 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
43 void *state; 37 void *state;
44 pa_alsa_jack *jack; 38 pa_alsa_jack *jack;
45 struct temp_port_avail *tp, *tports; 39 struct temp_port_avail *tp, *tports;
46+ pa_device_port *port;
47+ pa_card_profile *profile; 40+ pa_card_profile *profile;
48 41
49 pa_assert(u); 42 pa_assert(u);
50 43
51@@ -412,6 +414,29 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { 44@@ -426,6 +427,32 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
45 if (tp->avail == PA_AVAILABLE_NO)
52 pa_device_port_set_available(tp->port, tp->avail); 46 pa_device_port_set_available(tp->port, tp->avail);
53 47
54 pa_xfree(tports);
55+
56+ /* Update profile availabilities. The logic could be improved; for now we 48+ /* Update profile availabilities. The logic could be improved; for now we
57+ * only set obviously unavailable profiles (those that contain only 49+ * only set obviously unavailable profiles (those that contain only
58+ * unavailable ports) to PA_AVAILABLE_NO and all others to 50+ * unavailable ports) to PA_AVAILABLE_NO and all others to
59+ * PA_AVAILABLE_UNKNOWN. */ 51+ * PA_AVAILABLE_UNKNOWN. */
60+ PA_HASHMAP_FOREACH(profile, u->card->profiles, state) { 52+ PA_HASHMAP_FOREACH(profile, u->card->profiles, state) {
53+ pa_device_port *port;
61+ void *state2; 54+ void *state2;
62+ pa_available_t available = PA_AVAILABLE_NO; 55+ pa_available_t available = PA_AVAILABLE_NO;
63+ 56+
64+ /* Don't touch the "off" profile. */ 57+ /* Don't touch the "off" profile. */
65+ if (pa_hashmap_size(profile->ports) == 0) 58+ if (profile->n_sources == 0 && profile->n_sinks == 0)
66+ continue; 59+ continue;
67+ 60+
68+ PA_HASHMAP_FOREACH(port, profile->ports, state2) { 61+ PA_HASHMAP_FOREACH(port, u->card->ports, state2) {
62+ if (!pa_hashmap_get(port->profiles, profile->name))
63+ continue;
64+
69+ if (port->available != PA_AVAILABLE_NO) { 65+ if (port->available != PA_AVAILABLE_NO) {
70+ available = PA_AVAILABLE_UNKNOWN; 66+ available = PA_AVAILABLE_UNKNOWN;
71+ break; 67+ break;
@@ -75,9 +71,9 @@ index fe240f0..bdbdc12 100644
75+ pa_card_profile_set_available(profile, available); 71+ pa_card_profile_set_available(profile, available);
76+ } 72+ }
77+ 73+
74 pa_xfree(tports);
78 return 0; 75 return 0;
79 } 76 }
80
81-- 77--
822.7.0 782.8.1
83 79