pulseaudio/0013-alsa-ucm-add-support-for-master-volume.patch
Takashi Iwai 5dabf3bcba Accepting request 774841 from home:tiwai:branches:multimedia:libs
- Backport upstream fixes / enhancements about alsa modules:
  mainly for UCM support (boo#1160914):
  0001-alsa-mixer-path-test-Hide-unused-functions-when-buil.patch
  0002-alsa-mixer-recognize-the-Speaker-Jack-control.patch
  0003-alsa-mixer-add-support-for-SteelSeries-Arctis-Pro-20.patch
  0004-alsa-mixer-Add-support-for-SteelSeries-Arctis-5-2019.patch
  0005-alsa-mixer-add-support-for-LucidSound-LS31-and-creat.patch
  0006-alsa-ucm-use-ucm2-name-for-the-direct-card-index-ope.patch
  0007-alsa-ucm-add-mixer-IDs-to-ucm_items.patch
  0008-alsa-mixer-handle-the-index-for-ALSA-mixer-element-i.patch
  0009-alsa-mixer-improve-alsa_id_decode-function.patch
  0010-alsa-ucm-Support-Playback-CaptureVolume.patch
  0011-alsa-ucm-Fix-volume-control-based-on-review.patch
  0012-alsa-ucm-use-the-correct-mixer-identifiers-as-first.patch
  0013-alsa-ucm-add-support-for-master-volume.patch
  0014-alsa-ucm-split-correctly-JackHWMute-device-names.patch
  0015-alsa-ucm-fix-parsing-for-JackControl.patch
  0016-alsa-ucm-add-comments-to-ucm_get_mixer_id.patch
  0017-alsa-ucm-validate-access-to-PA_DEVICE_PORT_DATA.patch
  0018-alsa-Skip-resume-PCM-if-hardware-doesn-t-support-it.patch
  0019-alsa-ucm-parse-correctly-the-device-values.patch
  0020-alsa-ucm-do-not-try-to-use-UCM-device-name-as-jack-n.patch
  0021-alsa-util-do-not-try-to-guess-the-mixer-name-from-th.patch
  0022-alsa-ucm-add-control-and-mixer-device-items.patch
  0023-alsa-ucm-get-the-mixer-names-from-ucm-don-t-guess.patch
  0024-alsa-ucm-use-the-proper-mixer-name-for-ucm-pcm-sink-.patch
  0025-alsa-mixer-handle-interface-type-CARD-PCM-for-mixer-.patch
  0026-alsa-mixer-Add-the-ability-to-pass-the-intended-role.patch
  0027-alsa-mixer-Set-the-intended-role-of-Steelseries-Arct.patch
  0028-alsa-rewrite-mixer-open-close-cache-mixer-accesses-i.patch

OBS-URL: https://build.opensuse.org/request/show/774841
OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/pulseaudio?expand=0&rev=217
2020-02-17 11:47:50 +00:00

331 lines
14 KiB
Diff

From 6d830bf0f08c7f92418c2d8b0e73c0415dca03c8 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Wed, 27 Nov 2019 11:34:49 +0100
Subject: [PATCH] alsa-ucm: add support for master volume
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
src/modules/alsa/alsa-mixer.c | 20 +++++-----
src/modules/alsa/alsa-mixer.h | 1 +
src/modules/alsa/alsa-ucm.c | 86 +++++++++++++++++++++++++++++++++----------
src/modules/alsa/alsa-ucm.h | 19 ++++++++++
4 files changed, 96 insertions(+), 30 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index f57aabe5d885..ed06f42d86da 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -1923,7 +1923,7 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping *mapping, snd_mixer_t *m)
return 0;
}
-static pa_alsa_element* element_get(pa_alsa_path *p, const char *section, bool prefixed) {
+pa_alsa_element * pa_alsa_element_get(pa_alsa_path *p, const char *section, bool prefixed) {
pa_alsa_element *e;
char *name;
int index;
@@ -2025,7 +2025,7 @@ static pa_alsa_option* option_get(pa_alsa_path *p, const char *section) {
return p->last_option;
}
- pa_assert_se(e = element_get(p, en, false));
+ pa_assert_se(e = pa_alsa_element_get(p, en, false));
PA_LLIST_FOREACH(o, e->options)
if (pa_streq(o->alsa_name, on))
@@ -2054,7 +2054,7 @@ static int element_parse_switch(pa_config_parser_state *state) {
p = state->userdata;
- if (!(e = element_get(p, state->section, true))) {
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
pa_log("[%s:%u] Switch makes no sense in '%s'", state->filename, state->lineno, state->section);
return -1;
}
@@ -2085,7 +2085,7 @@ static int element_parse_volume(pa_config_parser_state *state) {
p = state->userdata;
- if (!(e = element_get(p, state->section, true))) {
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
pa_log("[%s:%u] Volume makes no sense in '%s'", state->filename, state->lineno, state->section);
return -1;
}
@@ -2121,7 +2121,7 @@ static int element_parse_enumeration(pa_config_parser_state *state) {
p = state->userdata;
- if (!(e = element_get(p, state->section, true))) {
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
pa_log("[%s:%u] Enumeration makes no sense in '%s'", state->filename, state->lineno, state->section);
return -1;
}
@@ -2213,7 +2213,7 @@ static int element_parse_required(pa_config_parser_state *state) {
p = state->userdata;
- e = element_get(p, state->section, true);
+ e = pa_alsa_element_get(p, state->section, true);
o = option_get(p, state->section);
j = jack_get(p, state->section);
if (!e && !o && !j) {
@@ -2279,7 +2279,7 @@ static int element_parse_direction(pa_config_parser_state *state) {
p = state->userdata;
- if (!(e = element_get(p, state->section, true))) {
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
pa_log("[%s:%u] Direction makes no sense in '%s'", state->filename, state->lineno, state->section);
return -1;
}
@@ -2305,7 +2305,7 @@ static int element_parse_direction_try_other(pa_config_parser_state *state) {
p = state->userdata;
- if (!(e = element_get(p, state->section, true))) {
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
pa_log("[%s:%u] Direction makes no sense in '%s'", state->filename, state->lineno, state->section);
return -1;
}
@@ -2328,7 +2328,7 @@ static int element_parse_volume_limit(pa_config_parser_state *state) {
p = state->userdata;
- if (!(e = element_get(p, state->section, true))) {
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
pa_log("[%s:%u] volume-limit makes no sense in '%s'", state->filename, state->lineno, state->section);
return -1;
}
@@ -2386,7 +2386,7 @@ static int element_parse_override_map(pa_config_parser_state *state) {
p = state->userdata;
- if (!(e = element_get(p, state->section, true))) {
+ if (!(e = pa_alsa_element_get(p, state->section, true))) {
pa_log("[%s:%u] Override map makes no sense in '%s'", state->filename, state->lineno, state->section);
return -1;
}
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 709f270fbfa5..0b634f2f2be1 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -244,6 +244,7 @@ void pa_alsa_element_dump(pa_alsa_element *e);
pa_alsa_path *pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction);
pa_alsa_path *pa_alsa_path_synthesize(const char *element, pa_alsa_direction_t direction);
+pa_alsa_element *pa_alsa_element_get(pa_alsa_path *p, const char *section, bool prefixed);
int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m, bool ignore_dB);
void pa_alsa_path_dump(pa_alsa_path *p);
int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v);
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
index 65ec6941e8de..46d016541ddf 100644
--- a/src/modules/alsa/alsa-ucm.c
+++ b/src/modules/alsa/alsa-ucm.c
@@ -200,6 +200,14 @@ static void ucm_add_devices_to_idxset(
}
}
+static void ucm_volume_free(pa_alsa_ucm_volume *vol) {
+ pa_assert(vol);
+ pa_xfree(vol->mixer_elem);
+ pa_xfree(vol->master_elem);
+ pa_xfree(vol->master_type);
+ pa_xfree(vol);
+}
+
/* Get the volume identifier */
static char *ucm_get_mixer_id(
pa_alsa_ucm_device *device,
@@ -244,6 +252,32 @@ static char *ucm_get_mixer_id(
return value2;
}
+/* Get the volume identifier */
+static pa_alsa_ucm_volume *ucm_get_mixer_volume(
+ pa_alsa_ucm_device *device,
+ const char *mprop,
+ const char *cprop,
+ const char *cid,
+ const char *masterid,
+ const char *mastertype)
+{
+ pa_alsa_ucm_volume *vol;
+ char *mixer_elem;
+
+ mixer_elem = ucm_get_mixer_id(device, mprop, cprop, cid);
+ if (mixer_elem == NULL)
+ return NULL;
+ vol = pa_xnew0(pa_alsa_ucm_volume, 1);
+ if (vol == NULL) {
+ pa_xfree(mixer_elem);
+ return NULL;
+ }
+ vol->mixer_elem = mixer_elem;
+ vol->master_elem = pa_xstrdup(pa_proplist_gets(device->proplist, masterid));
+ vol->master_type = pa_xstrdup(pa_proplist_gets(device->proplist, mastertype));
+ return vol;
+}
+
/* Create a property list for this ucm device */
static int ucm_get_device_property(
pa_alsa_ucm_device *device,
@@ -258,6 +292,7 @@ static int ucm_get_device_property(
int err;
uint32_t ui;
int n_confdev, n_suppdev;
+ pa_alsa_ucm_volume *vol;
for (i = 0; item[i].id; i++) {
id = pa_sprintf_malloc("=%s/%s", item[i].id, device_name);
@@ -340,12 +375,14 @@ static int ucm_get_device_property(
pa_log_debug("UCM playback priority %s for device %s error", value, device_name);
}
- value = ucm_get_mixer_id(device,
- PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM,
- PA_ALSA_PROP_UCM_PLAYBACK_VOLUME,
- "PlaybackVolume");
- if (value)
- pa_hashmap_put(device->playback_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), (void *)value);
+ vol = ucm_get_mixer_volume(device,
+ PA_ALSA_PROP_UCM_PLAYBACK_MIXER_ELEM,
+ PA_ALSA_PROP_UCM_PLAYBACK_VOLUME,
+ "PlaybackVolume",
+ PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ELEM,
+ PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE);
+ if (vol)
+ pa_hashmap_put(device->playback_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), vol);
}
if (device->capture_channels) { /* source device */
@@ -368,12 +405,14 @@ static int ucm_get_device_property(
pa_log_debug("UCM capture priority %s for device %s error", value, device_name);
}
- value = ucm_get_mixer_id(device,
- PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM,
- PA_ALSA_PROP_UCM_CAPTURE_VOLUME,
- "CaptureVolume");
- if (value)
- pa_hashmap_put(device->capture_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), (void *)value);
+ vol = ucm_get_mixer_volume(device,
+ PA_ALSA_PROP_UCM_CAPTURE_MIXER_ELEM,
+ PA_ALSA_PROP_UCM_CAPTURE_VOLUME,
+ "CaptureVolume",
+ PA_ALSA_PROP_UCM_CAPTURE_MASTER_ELEM,
+ PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE);
+ if (vol)
+ pa_hashmap_put(device->capture_volumes, pa_xstrdup(pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME)), vol);
}
if (PA_UCM_PLAYBACK_PRIORITY_UNSET(device) || PA_UCM_CAPTURE_PRIORITY_UNSET(device)) {
@@ -478,9 +517,9 @@ static int ucm_get_devices(pa_alsa_ucm_verb *verb, snd_use_case_mgr_t *uc_mgr) {
d->available = PA_AVAILABLE_UNKNOWN;
d->playback_volumes = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree,
- pa_xfree);
+ (pa_free_cb_t) ucm_volume_free);
d->capture_volumes = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree,
- pa_xfree);
+ (pa_free_cb_t) ucm_volume_free);
PA_LLIST_PREPEND(pa_alsa_ucm_device, verb->devices, d);
}
@@ -819,9 +858,10 @@ static void ucm_add_port_combination(
char *name, *desc;
const char *dev_name;
const char *direction;
- const char *profile, *volume_element;
+ const char *profile;
pa_alsa_ucm_device *sorted[num], *dev;
pa_alsa_ucm_port_data *data;
+ pa_alsa_ucm_volume *vol;
void *state;
for (i = 0; i < num; i++)
@@ -892,21 +932,27 @@ static void ucm_add_port_combination(
* ports. */
data = PA_DEVICE_PORT_DATA(port);
- PA_HASHMAP_FOREACH_KV(profile, volume_element, is_sink ? dev->playback_volumes : dev->capture_volumes, state) {
- pa_alsa_path *path = pa_alsa_path_synthesize(volume_element,
+ 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);
if (!path)
- pa_log_warn("Failed to set up volume control: %s", volume_element);
+ 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(volume_element), path);
+ 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(volume_element), path);
+ pa_hashmap_put(dev->capture_mapping->input_path_set->paths, pa_xstrdup(vol->mixer_elem), path);
}
}
}
diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h
index d8507a83615c..a6863abc05a6 100644
--- a/src/modules/alsa/alsa-ucm.h
+++ b/src/modules/alsa/alsa-ucm.h
@@ -60,6 +60,12 @@ typedef void snd_use_case_mgr_t;
/** For devices: Playback mixer master type */
#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE "alsa.ucm.playback.master.type"
+/** For devices: Playback mixer master identifier */
+#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_ID "alsa.ucm.playback.master.id"
+
+/** For devices: Playback mixer master type */
+#define PA_ALSA_PROP_UCM_PLAYBACK_MASTER_TYPE "alsa.ucm.playback.master.type"
+
/** For devices: Playback priority */
#define PA_ALSA_PROP_UCM_PLAYBACK_PRIORITY "alsa.ucm.playback.priority"
@@ -87,6 +93,12 @@ typedef void snd_use_case_mgr_t;
/** For devices: Capture mixer identifier */
#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE "alsa.ucm.capture.master.type"
+/** For devices: Capture mixer identifier */
+#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_ID "alsa.ucm.capture.master.id"
+
+/** For devices: Capture mixer identifier */
+#define PA_ALSA_PROP_UCM_CAPTURE_MASTER_TYPE "alsa.ucm.capture.master.type"
+
/** For devices: Capture priority */
#define PA_ALSA_PROP_UCM_CAPTURE_PRIORITY "alsa.ucm.capture.priority"
@@ -114,6 +126,7 @@ typedef struct pa_alsa_ucm_device pa_alsa_ucm_device;
typedef struct pa_alsa_ucm_config pa_alsa_ucm_config;
typedef struct pa_alsa_ucm_mapping_context pa_alsa_ucm_mapping_context;
typedef struct pa_alsa_ucm_port_data pa_alsa_ucm_port_data;
+typedef struct pa_alsa_ucm_volume pa_alsa_ucm_volume;
int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index);
pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_channel_map *default_channel_map);
@@ -246,4 +259,10 @@ struct pa_alsa_ucm_port_data {
pa_alsa_path *path;
};
+struct pa_alsa_ucm_volume {
+ char *mixer_elem; /* mixer element identifier */
+ char *master_elem; /* master mixer element identifier */
+ char *master_type;
+};
+
#endif
--
2.16.4