alsa: legacy card - implement device port type parser and assignment
authorJaroslav Kysela <perex@perex.cz>
Fri, 17 Apr 2020 13:34:24 +0000 (15:34 +0200)
committerTanu Kaskinen <tanuk@iki.fi>
Wed, 17 Jun 2020 06:06:12 +0000 (06:06 +0000)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
src/modules/alsa/alsa-mixer.c
src/modules/alsa/alsa-mixer.h

index 611e806..0ab9b81 100644 (file)
@@ -107,6 +107,12 @@ struct description_map {
     const char *description;
 };
 
+struct description2_map {
+    const char *key;
+    const char *description;
+    pa_device_port_type_t type;
+};
+
 static char *alsa_id_str(char *dst, size_t dst_len, pa_alsa_mixer_id *id) {
     if (id->index > 0) {
         snprintf(dst, dst_len, "'%s',%d", id->name, id->index);
@@ -288,6 +294,19 @@ static const char *lookup_description(const char *key, const struct description_
     return NULL;
 }
 
+static const struct description2_map *lookup_description2(const char *key, const struct description2_map dm[], unsigned n) {
+    unsigned i;
+
+    if (!key)
+        return NULL;
+
+    for (i = 0; i < n; i++)
+        if (pa_streq(dm[i].key, key))
+            return &dm[i];
+
+    return NULL;
+}
+
 struct pa_alsa_fdlist {
     unsigned num_fds;
     struct pollfd *fds;
@@ -2160,6 +2179,50 @@ static int element_parse_enumeration(pa_config_parser_state *state) {
     return 0;
 }
 
+static int parse_type(pa_config_parser_state *state) {
+    struct device_port_types {
+        const char *name;
+        pa_device_port_type_t type;
+    } device_port_types[] = {
+        { "unknown",      PA_DEVICE_PORT_TYPE_UNKNOWN },
+        { "aux",          PA_DEVICE_PORT_TYPE_AUX },
+        { "speaker",      PA_DEVICE_PORT_TYPE_SPEAKER },
+        { "headphones",   PA_DEVICE_PORT_TYPE_HEADPHONES },
+        { "line",         PA_DEVICE_PORT_TYPE_LINE },
+        { "mic",          PA_DEVICE_PORT_TYPE_MIC },
+        { "headset",      PA_DEVICE_PORT_TYPE_HEADSET },
+        { "handset",      PA_DEVICE_PORT_TYPE_HANDSET },
+        { "earpiece",     PA_DEVICE_PORT_TYPE_EARPIECE },
+        { "spdif",        PA_DEVICE_PORT_TYPE_SPDIF },
+        { "hdmi",         PA_DEVICE_PORT_TYPE_HDMI },
+        { "tv",           PA_DEVICE_PORT_TYPE_TV },
+        { "radio",        PA_DEVICE_PORT_TYPE_RADIO },
+        { "video",        PA_DEVICE_PORT_TYPE_VIDEO },
+        { "usb",          PA_DEVICE_PORT_TYPE_USB },
+        { "bluetooth",    PA_DEVICE_PORT_TYPE_BLUETOOTH },
+        { "portable",     PA_DEVICE_PORT_TYPE_PORTABLE },
+        { "handsfree",    PA_DEVICE_PORT_TYPE_HANDSFREE },
+        { "car",          PA_DEVICE_PORT_TYPE_CAR },
+        { "hifi",         PA_DEVICE_PORT_TYPE_HIFI },
+        { "phone",        PA_DEVICE_PORT_TYPE_PHONE },
+        { "network",      PA_DEVICE_PORT_TYPE_NETWORK },
+        { "analog",       PA_DEVICE_PORT_TYPE_ANALOG },
+    };
+    pa_alsa_path *path;
+    unsigned int idx;
+
+    path = state->userdata;
+
+    for (idx = 0; idx < PA_ELEMENTSOF(device_port_types); idx++)
+        if (pa_streq(state->rvalue, device_port_types[idx].name)) {
+            path->device_port_type = device_port_types[idx].type;
+            return 0;
+        }
+
+    pa_log("[%s:%u] Invalid value for option 'type': %s", state->filename, state->lineno, state->rvalue);
+    return -1;
+}
+
 static int parse_eld_device(pa_config_parser_state *state) {
     pa_alsa_path *path;
     uint32_t eld_device;
@@ -2642,35 +2705,38 @@ static int element_verify(pa_alsa_element *e) {
 }
 
 static int path_verify(pa_alsa_path *p) {
-    static const struct description_map well_known_descriptions[] = {
-        { "analog-input",               N_("Analog Input") },
-        { "analog-input-microphone",    N_("Microphone") },
-        { "analog-input-microphone-front",    N_("Front Microphone") },
-        { "analog-input-microphone-rear",     N_("Rear Microphone") },
-        { "analog-input-microphone-dock",     N_("Dock Microphone") },
-        { "analog-input-microphone-internal", N_("Internal Microphone") },
-        { "analog-input-microphone-headset",  N_("Headset Microphone") },
-        { "analog-input-linein",        N_("Line In") },
-        { "analog-input-radio",         N_("Radio") },
-        { "analog-input-video",         N_("Video") },
-        { "analog-output",              N_("Analog Output") },
-        { "analog-output-headphones",   N_("Headphones") },
-        { "analog-output-headphones-mono",    N_("Headphones Mono Output") },
-        { "analog-output-lfe-on-mono",  N_("LFE on Separate Mono Output") },
-        { "analog-output-lineout",      N_("Line Out") },
-        { "analog-output-mono",         N_("Analog Mono Output") },
-        { "analog-output-speaker",      N_("Speakers") },
-        { "hdmi-output",                N_("HDMI / DisplayPort") },
-        { "iec958-stereo-output",       N_("Digital Output (S/PDIF)") },
-        { "iec958-stereo-input",        N_("Digital Input (S/PDIF)") },
-        { "iec958-passthrough-output",  N_("Digital Passthrough (S/PDIF)") },
-        { "multichannel-input",         N_("Multichannel Input") },
-        { "multichannel-output",        N_("Multichannel Output") },
-        { "steelseries-arctis-5-output-game", N_("Game Output") },
-        { "steelseries-arctis-5-output-chat", N_("Chat Output") },
+    static const struct description2_map well_known_descriptions[] = {
+        { "analog-input",                     N_("Analog Input"),                 PA_DEVICE_PORT_TYPE_ANALOG },
+        { "analog-input-microphone",          N_("Microphone"),                   PA_DEVICE_PORT_TYPE_MIC },
+        { "analog-input-microphone-front",    N_("Front Microphone"),             PA_DEVICE_PORT_TYPE_MIC },
+        { "analog-input-microphone-rear",     N_("Rear Microphone"),              PA_DEVICE_PORT_TYPE_MIC },
+        { "analog-input-microphone-dock",     N_("Dock Microphone"),              PA_DEVICE_PORT_TYPE_MIC },
+        { "analog-input-microphone-internal", N_("Internal Microphone"),          PA_DEVICE_PORT_TYPE_MIC },
+        { "analog-input-microphone-headset",  N_("Headset Microphone"),           PA_DEVICE_PORT_TYPE_MIC },
+        { "analog-input-linein",              N_("Line In"),                      PA_DEVICE_PORT_TYPE_LINE },
+        { "analog-input-radio",               N_("Radio"),                        PA_DEVICE_PORT_TYPE_RADIO },
+        { "analog-input-video",               N_("Video"),                        PA_DEVICE_PORT_TYPE_VIDEO },
+        { "analog-output",                    N_("Analog Output"),                PA_DEVICE_PORT_TYPE_ANALOG },
+        { "analog-output-headphones",         N_("Headphones"),                   PA_DEVICE_PORT_TYPE_HEADPHONES },
+        { "analog-output-headphones-mono",    N_("Headphones Mono Output"),       PA_DEVICE_PORT_TYPE_HEADPHONES },
+        { "analog-output-lineout",            N_("Line Out"),                     PA_DEVICE_PORT_TYPE_LINE },
+        { "analog-output-mono",               N_("Analog Mono Output"),           PA_DEVICE_PORT_TYPE_ANALOG },
+        { "analog-output-speaker",            N_("Speakers"),                     PA_DEVICE_PORT_TYPE_SPEAKER },
+        { "hdmi-output",                      N_("HDMI / DisplayPort"),           PA_DEVICE_PORT_TYPE_HDMI },
+        { "iec958-stereo-output",             N_("Digital Output (S/PDIF)"),      PA_DEVICE_PORT_TYPE_SPDIF },
+        { "iec958-stereo-input",              N_("Digital Input (S/PDIF)"),       PA_DEVICE_PORT_TYPE_SPDIF },
+        { "iec958-passthrough-output",        N_("Digital Passthrough (S/PDIF)"), PA_DEVICE_PORT_TYPE_SPDIF },
+        { "multichannel-input",               N_("Multichannel Input"),           PA_DEVICE_PORT_TYPE_LINE },
+        { "multichannel-output",              N_("Multichannel Output"),          PA_DEVICE_PORT_TYPE_LINE },
+        { "steelseries-arctis-5-output-game", N_("Game Output"),                  PA_DEVICE_PORT_TYPE_HEADSET },
+        { "steelseries-arctis-5-output-chat", N_("Chat Output"),                  PA_DEVICE_PORT_TYPE_HEADSET },
     };
 
     pa_alsa_element *e;
+    const char *key = p->description_key ? p->description_key : p->name;
+    const struct description2_map *map = lookup_description2(key,
+                                                             well_known_descriptions,
+                                                             PA_ELEMENTSOF(well_known_descriptions));
 
     pa_assert(p);
 
@@ -2678,10 +2744,12 @@ static int path_verify(pa_alsa_path *p) {
         if (element_verify(e) < 0)
             return -1;
 
-    if (!p->description)
-        p->description = pa_xstrdup(lookup_description(p->description_key ? p->description_key : p->name,
-                                                       well_known_descriptions,
-                                                       PA_ELEMENTSOF(well_known_descriptions)));
+    if (map) {
+        if (p->device_port_type == PA_DEVICE_PORT_TYPE_UNKNOWN)
+            p->device_port_type = map->type;
+        if (!p->description)
+            p->description = pa_xstrdup(map->description);
+    }
 
     if (!p->description) {
         if (p->description_key)
@@ -2714,6 +2782,7 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
         { "priority",            pa_config_parse_unsigned,          NULL, "General" },
         { "description-key",     pa_config_parse_string,            NULL, "General" },
         { "description",         pa_config_parse_string,            NULL, "General" },
+        { "type",                parse_type,                        NULL, "General" },
         { "mute-during-activation", pa_config_parse_bool,           NULL, "General" },
         { "eld-device",          parse_eld_device,                  NULL, "General" },
 
@@ -5074,6 +5143,7 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports, /* card ports */
         pa_device_port_new_data_set_name(&port_data, name);
         pa_device_port_new_data_set_description(&port_data, description);
         pa_device_port_new_data_set_direction(&port_data, path->direction == PA_ALSA_DIRECTION_OUTPUT ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT);
+        pa_device_port_new_data_set_type(&port_data, path->device_port_type);
         pa_device_port_new_data_set_available_group(&port_data, path->available_group);
 
         p = pa_device_port_new(core, &port_data, sizeof(pa_alsa_port_data));
index b6010b7..88fc4d3 100644 (file)
@@ -212,6 +212,7 @@ struct pa_alsa_path {
     char *description_key;
     char *description;
     char *available_group;
+    pa_device_port_type_t device_port_type;
     unsigned priority;
     bool autodetect_eld_device;
     pa_alsa_mixer *eld_mixer_handle;