mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2026-04-06 07:15:41 -04:00
alsa-ucm: allow binding same mic to multiple profiles
When UCM configure assigns the same mic to different profiles, such as
Speaker.conf:
...
SectionDevice."Mic" {
xxxx
}
...
HiFi.conf: (use the same Mic}
...
SectionDevice."Mic" {
xxxx
}
...
In this case, Speaker and HiFi profiles should both support "Mic" device.
However, in ucm_add_port_combination(), pulseaudio will check
if the port has been already created before (In speaker.conf in in case),
HiFi will never have chance to put the port to itself. This will
cause HiFi don't support "MiC".
This patch's logic is:
Create the port if necessary.
Add the port as per the UCM requirement.
Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
This commit is contained in:
parent
36a4923f9b
commit
43308015f5
1 changed files with 86 additions and 23 deletions
|
|
@ -84,6 +84,8 @@ static pa_alsa_ucm_device *verb_find_device(pa_alsa_ucm_verb *verb, const char *
|
|||
|
||||
static void ucm_port_data_init(pa_alsa_ucm_port_data *port, pa_alsa_ucm_config *ucm, pa_device_port *core_port,
|
||||
pa_alsa_ucm_device **devices, unsigned n_devices);
|
||||
static void ucm_port_add_devices(pa_device_port *port, pa_alsa_ucm_device **pdevices, int num);
|
||||
static void device_add_ucm_port(pa_alsa_ucm_device *device, pa_alsa_ucm_port_data *port);
|
||||
static void ucm_port_data_free(pa_device_port *port);
|
||||
static void ucm_port_update_available(pa_alsa_ucm_port_data *port);
|
||||
|
||||
|
|
@ -934,6 +936,61 @@ fail:
|
|||
}
|
||||
}
|
||||
|
||||
static int devs_have_same_property(pa_alsa_ucm_device *dev1,
|
||||
pa_alsa_ucm_device *dev2,
|
||||
const char *prop)
|
||||
{
|
||||
const char *val1, *val2;
|
||||
|
||||
/* check whether the 2 devices have the exactly same property */
|
||||
val1 = pa_proplist_gets(dev1->proplist, prop);
|
||||
val2 = pa_proplist_gets(dev2->proplist, prop);
|
||||
if (val1 && val2)
|
||||
return pa_streq(val1, val2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ucm_port_add_devices(pa_device_port *port,
|
||||
pa_alsa_ucm_device **pdevices,
|
||||
int num)
|
||||
{
|
||||
pa_alsa_ucm_device *device;
|
||||
pa_alsa_ucm_port_data *portdata;
|
||||
unsigned idx;
|
||||
int found, i;
|
||||
|
||||
pa_assert(port);
|
||||
|
||||
portdata = PA_DEVICE_PORT_DATA(port);
|
||||
for (i = 0; i < num; i++) {
|
||||
found = 0;
|
||||
PA_DYNARRAY_FOREACH(device, portdata->devices, idx) {
|
||||
if (pdevices[i] == device) {
|
||||
found = 1;
|
||||
break;
|
||||
} else {
|
||||
if (!devs_have_same_property(pdevices[i], device, PA_ALSA_PROP_UCM_PLAYBACK_CHANNELS))
|
||||
pa_log_warn("port %s has different playback channel devices\n", port->name);
|
||||
if (!devs_have_same_property(pdevices[i], device, PA_ALSA_PROP_UCM_PLAYBACK_RATE))
|
||||
pa_log_warn("port %s has different playback rate devices\n", port->name);
|
||||
if (!devs_have_same_property(pdevices[i], device, PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY))
|
||||
pa_log_warn("port %s has different playback priority devices\n", port->name);
|
||||
if (!devs_have_same_property(pdevices[i], device, PA_ALSA_PROP_UCM_CAPTURE_CHANNELS))
|
||||
pa_log_warn("port %s has different capture channel devices\n", port->name);
|
||||
if (!devs_have_same_property(pdevices[i], device, PA_ALSA_PROP_UCM_CAPTURE_RATE))
|
||||
pa_log_warn("port %s has different capture rate devices\n", port->name);
|
||||
if (!devs_have_same_property(pdevices[i], device, PA_ALSA_PROP_UCM_CAPTURE_PRIORITY))
|
||||
pa_log_warn("port %s has different capture priority devices\n", port->name);
|
||||
}
|
||||
}
|
||||
if (found == 0) {
|
||||
pa_dynarray_append(portdata->devices, pdevices[i]);
|
||||
device_add_ucm_port(pdevices[i], portdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ucm_add_port_combination(
|
||||
pa_hashmap *hash,
|
||||
pa_alsa_ucm_mapping_context *context,
|
||||
|
|
@ -1019,34 +1076,40 @@ static void ucm_add_port_combination(
|
|||
|
||||
pa_hashmap_put(ports, port->name, port);
|
||||
pa_log_debug("Add port %s: %s", port->name, port->description);
|
||||
}
|
||||
|
||||
if (num == 1) {
|
||||
/* To keep things simple and not worry about stacking controls, we only support hardware volumes on non-combination
|
||||
* ports. */
|
||||
data = PA_DEVICE_PORT_DATA(port);
|
||||
/* If the pdevices are not added to the portdata, let's add them */
|
||||
ucm_port_add_devices(port, pdevices, num);
|
||||
|
||||
PA_HASHMAP_FOREACH_KV(profile, vol, is_sink ? dev->playback_volumes : dev->capture_volumes, state) {
|
||||
pa_alsa_path *path = pa_alsa_path_synthesize(vol->mixer_elem,
|
||||
is_sink ? PA_ALSA_DIRECTION_OUTPUT : PA_ALSA_DIRECTION_INPUT);
|
||||
/* It needs to setup the paths when setup the profiles */
|
||||
if (num == 1 && cp) {
|
||||
/*
|
||||
* To keep things simple and not worry about stacking controls,
|
||||
* we only support hardware volumes on non-combination ports.
|
||||
*/
|
||||
data = PA_DEVICE_PORT_DATA(port);
|
||||
|
||||
if (!path)
|
||||
pa_log_warn("Failed to set up volume control: %s", vol->mixer_elem);
|
||||
else {
|
||||
if (vol->master_elem) {
|
||||
pa_alsa_element *e = pa_alsa_element_get(path, vol->master_elem, false);
|
||||
e->switch_use = PA_ALSA_SWITCH_MUTE;
|
||||
e->volume_use = PA_ALSA_VOLUME_MERGE;
|
||||
}
|
||||
PA_HASHMAP_FOREACH_KV(profile, vol, is_sink ? dev->playback_volumes : dev->capture_volumes, state) {
|
||||
pa_alsa_path *path = pa_alsa_path_synthesize(vol->mixer_elem,
|
||||
is_sink ? PA_ALSA_DIRECTION_OUTPUT : PA_ALSA_DIRECTION_INPUT);
|
||||
|
||||
pa_hashmap_put(data->paths, pa_xstrdup(profile), path);
|
||||
|
||||
/* Add path also to already created empty path set */
|
||||
dev = sorted[0];
|
||||
if (is_sink)
|
||||
pa_hashmap_put(dev->playback_mapping->output_path_set->paths, pa_xstrdup(vol->mixer_elem), path);
|
||||
else
|
||||
pa_hashmap_put(dev->capture_mapping->input_path_set->paths, pa_xstrdup(vol->mixer_elem), path);
|
||||
if (!path)
|
||||
pa_log_warn("Failed to set up volume control: %s", vol->mixer_elem);
|
||||
else {
|
||||
if (vol->master_elem) {
|
||||
pa_alsa_element *e = pa_alsa_element_get(path, vol->master_elem, false);
|
||||
e->switch_use = PA_ALSA_SWITCH_MUTE;
|
||||
e->volume_use = PA_ALSA_VOLUME_MERGE;
|
||||
}
|
||||
|
||||
pa_hashmap_put(data->paths, pa_xstrdup(profile), path);
|
||||
|
||||
/* Add path also to already created empty path set */
|
||||
dev = sorted[0];
|
||||
if (is_sink)
|
||||
pa_hashmap_put(dev->playback_mapping->output_path_set->paths, pa_xstrdup(vol->mixer_elem), path);
|
||||
else
|
||||
pa_hashmap_put(dev->capture_mapping->input_path_set->paths, pa_xstrdup(vol->mixer_elem), path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue