[pulseaudio-commits] [Git][pulseaudio/pulseaudio][master] 8 commits: device-port: introduce available_group member
Tanu Kaskinen
gitlab at gitlab.freedesktop.org
Wed Jun 17 06:10:46 UTC 2020
Tanu Kaskinen pushed to branch master at PulseAudio / pulseaudio
Commits:
861836c5 by Jaroslav Kysela at 2020-06-17T06:06:12+00:00
device-port: introduce available_group member
In some cases, the I/O connector functionality can be shared
and we cannot determine the proper purpose automatically.
We just know that something was inserted to the jack.
Introduce a group identifier (a simple string - unique
per group) which helps to determine the proper ports
for the application. The user interface may be used
to set the wanted behaviour.
Signed-off-by: Jaroslav Kysela <perex at perex.cz>
- - - - -
feee531c by Jaroslav Kysela at 2020-06-17T06:06:12+00:00
device-port: add type member
The clients might wanna to know for which purpose is the port.
Signed-off-by: Jaroslav Kysela <perex at perex.cz>
- - - - -
64eae8d8 by Jaroslav Kysela at 2020-06-17T06:06:12+00:00
protocol: describe v34 (available_group, port type)
Signed-off-by: Jaroslav Kysela <perex at perex.cz>
- - - - -
1fb44921 by Jaroslav Kysela at 2020-06-17T06:06:12+00:00
alsa-ucm: set available_group (use jack name)
Signed-off-by: Jaroslav Kysela <perex at perex.cz>
- - - - -
66185274 by Jaroslav Kysela at 2020-06-17T06:06:12+00:00
alsa: legacy card - set available_group
Create automatically the groups per paths where
the similar jacks are used.
Signed-off-by: Jaroslav Kysela <perex at perex.cz>
- - - - -
0333c2ba by Jaroslav Kysela at 2020-06-17T06:06:12+00:00
alsa: legacy card - implement device port type parser and assignment
Signed-off-by: Jaroslav Kysela <perex at perex.cz>
- - - - -
80b993cf by Jaroslav Kysela at 2020-06-17T06:06:12+00:00
alsa ucm: set device port type
Signed-off-by: Jaroslav Kysela <perex at perex.cz>
- - - - -
b2d33997 by Jaroslav Kysela at 2020-06-17T06:06:12+00:00
pactl: print device port type and available group
Signed-off-by: Jaroslav Kysela <perex at perex.cz>
- - - - -
16 changed files:
- PROTOCOL
- configure.ac
- src/modules/alsa/alsa-mixer.c
- src/modules/alsa/alsa-mixer.h
- src/modules/alsa/alsa-ucm.c
- src/modules/alsa/alsa-ucm.h
- src/modules/bluetooth/module-bluez5-device.c
- src/modules/module-tunnel.c
- src/modules/raop/raop-sink.c
- src/pulse/def.h
- src/pulse/introspect.c
- src/pulse/introspect.h
- src/pulsecore/device-port.c
- src/pulsecore/device-port.h
- src/pulsecore/protocol-native.c
- src/utils/pactl.c
Changes:
=====================================
PROTOCOL
=====================================
@@ -427,6 +427,10 @@ Added two values to the pa_encoding_t enum:
PA_ENCODING_TRUEHD_IEC61937 := 7
PA_ENCODING_DTSHD_IEC61937 := 8
+## v34, implemented by >= 14.0
+
+Added available_group and type fields to the device port info.
+
#### If you just changed the protocol, read this
## module-tunnel depends on the sink/source/sink-input/source-input protocol
## internals, so if you changed these, you might have broken module-tunnel.
=====================================
configure.ac
=====================================
@@ -42,7 +42,7 @@ AC_SUBST(PA_MINOR, pa_minor)
AC_SUBST(PA_MAJORMINOR, pa_major.pa_minor)
AC_SUBST(PA_API_VERSION, 12)
-AC_SUBST(PA_PROTOCOL_VERSION, 33)
+AC_SUBST(PA_PROTOCOL_VERSION, 34)
# The stable ABI for client applications, for the version info x:y:z
# always will hold x=z
=====================================
src/modules/alsa/alsa-mixer.c
=====================================
@@ -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;
@@ -739,6 +758,7 @@ void pa_alsa_path_free(pa_alsa_path *p) {
}
pa_proplist_free(p->proplist);
+ pa_xfree(p->available_group);
pa_xfree(p->name);
pa_xfree(p->description);
pa_xfree(p->description_key);
@@ -2159,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;
@@ -2641,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);
@@ -2677,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)
@@ -2713,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" },
@@ -4180,6 +4250,51 @@ fail:
return -1;
}
+/* the logic is simple: if we see the jack in multiple paths */
+/* assign all those jacks to one available_group */
+static void mapping_group_available(pa_hashmap *paths)
+{
+ void *state, *state2;
+ pa_alsa_path *p, *p2;
+ pa_alsa_jack *j, *j2;
+ uint32_t num = 1;
+
+ PA_HASHMAP_FOREACH(p, paths, state) {
+ const char *found = NULL;
+ bool has_control = false;
+ PA_LLIST_FOREACH(j, p->jacks) {
+ if (!j->has_control || j->state_plugged == PA_AVAILABLE_NO)
+ continue;
+ has_control = true;
+ j->state_plugged = PA_AVAILABLE_UNKNOWN;
+ PA_HASHMAP_FOREACH(p2, paths, state2) {
+ if (p2 == p)
+ break;
+ PA_LLIST_FOREACH(j2, p->jacks) {
+ if (!j2->has_control || j->state_plugged == PA_AVAILABLE_NO)
+ continue;
+ if (pa_streq(j->name, j2->name)) {
+ j2->state_plugged = PA_AVAILABLE_UNKNOWN;
+ found = p2->available_group;
+ break;
+ }
+ }
+ }
+ if (found)
+ break;
+ }
+ if (!has_control)
+ continue;
+ if (!found) {
+ p->available_group = pa_sprintf_malloc("Legacy %d", num);
+ } else {
+ p->available_group = pa_xstrdup(found);
+ }
+ if (!found)
+ num++;
+ }
+}
+
static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
pa_alsa_direction_t direction, pa_hashmap *used_paths,
pa_hashmap *mixers) {
@@ -4228,6 +4343,8 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile,
PA_HASHMAP_FOREACH(p, ps->paths, state)
pa_hashmap_put(used_paths, p, p);
+ mapping_group_available(ps->paths);
+
pa_log_debug("Available mixer paths (after tidying):");
pa_alsa_path_set_dump(ps);
}
@@ -5026,6 +5143,8 @@ 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));
pa_device_port_new_data_done(&port_data);
=====================================
src/modules/alsa/alsa-mixer.h
=====================================
@@ -211,6 +211,8 @@ struct pa_alsa_path {
char *name;
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;
=====================================
src/modules/alsa/alsa-ucm.c
=====================================
@@ -66,6 +66,11 @@
#ifdef HAVE_ALSA_UCM
+struct ucm_type {
+ const char *prefix;
+ pa_device_port_type_t type;
+};
+
struct ucm_items {
const char *id;
const char *property;
@@ -76,6 +81,7 @@ struct ucm_info {
unsigned priority;
};
+static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *device);
static void device_set_jack(pa_alsa_ucm_device *device, pa_alsa_jack *jack);
static void device_add_hw_mute_jack(pa_alsa_ucm_device *device, pa_alsa_jack *jack);
@@ -87,6 +93,21 @@ static void ucm_port_data_init(pa_alsa_ucm_port_data *port, pa_alsa_ucm_config *
static void ucm_port_data_free(pa_device_port *port);
static void ucm_port_update_available(pa_alsa_ucm_port_data *port);
+static struct ucm_type types[] = {
+ {"None", PA_DEVICE_PORT_TYPE_UNKNOWN},
+ {"Speaker", PA_DEVICE_PORT_TYPE_SPEAKER},
+ {"Line", PA_DEVICE_PORT_TYPE_LINE},
+ {"Mic", PA_DEVICE_PORT_TYPE_MIC},
+ {"Headphones", PA_DEVICE_PORT_TYPE_HEADPHONES},
+ {"Headset", PA_DEVICE_PORT_TYPE_HEADSET},
+ {"Handset", PA_DEVICE_PORT_TYPE_HANDSET},
+ {"Bluetooth", PA_DEVICE_PORT_TYPE_BLUETOOTH},
+ {"Earpiece", PA_DEVICE_PORT_TYPE_EARPIECE},
+ {"SPDIF", PA_DEVICE_PORT_TYPE_SPDIF},
+ {"HDMI", PA_DEVICE_PORT_TYPE_HDMI},
+ {NULL, 0}
+};
+
static struct ucm_items item[] = {
{"PlaybackPCM", PA_ALSA_PROP_UCM_SINK},
{"CapturePCM", PA_ALSA_PROP_UCM_SOURCE},
@@ -343,13 +364,27 @@ static int ucm_get_device_property(
const char *value;
const char **devices;
- char *id;
+ char *id, *s;
int i;
int err;
uint32_t ui;
int n_confdev, n_suppdev;
pa_alsa_ucm_volume *vol;
+ /* determine the device type */
+ device->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
+ id = s = pa_xstrdup(device_name);
+ while (s && *s && isalpha(*s)) s++;
+ if (s)
+ *s = '\0';
+ for (i = 0; types[i].prefix; i++)
+ if (pa_streq(id, types[i].prefix)) {
+ device->type = types[i].type;
+ break;
+ }
+ pa_xfree(id);
+
+ /* set properties */
for (i = 0; item[i].id; i++) {
id = pa_sprintf_malloc("%s/%s", item[i].id, device_name);
err = snd_use_case_get(uc_mgr, id, &value);
@@ -955,6 +990,8 @@ static void ucm_add_port_combination(
pa_alsa_ucm_device *sorted[num], *dev;
pa_alsa_ucm_port_data *data;
pa_alsa_ucm_volume *vol;
+ pa_alsa_jack *jack, *jack2;
+ pa_device_port_type_t type, type2;
void *state;
for (i = 0; i < num; i++)
@@ -973,6 +1010,8 @@ static void ucm_add_port_combination(
priority = is_sink ? dev->playback_priority : dev->capture_priority;
prio2 = (priority == 0 ? 0 : 1.0/priority);
+ jack = ucm_get_jack(context->ucm, dev);
+ type = dev->type;
for (i = 1; i < num; i++) {
char *tmp;
@@ -991,6 +1030,20 @@ static void ucm_add_port_combination(
priority = is_sink ? dev->playback_priority : dev->capture_priority;
if (priority != 0 && prio2 > 0)
prio2 += 1.0/priority;
+
+ jack2 = ucm_get_jack(context->ucm, dev);
+ if (jack2) {
+ if (jack && jack != jack2)
+ pa_log_warn("Multiple jacks per combined device '%s': '%s' '%s'", name, jack->name, jack2->name);
+ jack = jack2;
+ }
+
+ type2 = dev->type;
+ if (type2 != PA_DEVICE_PORT_TYPE_UNKNOWN) {
+ if (type != PA_DEVICE_PORT_TYPE_UNKNOWN && type != type2)
+ pa_log_warn("Multiple device types per combined device '%s': %d %d", name, type, type2);
+ type = type2;
+ }
}
/* Make combination ports always have lower priority, and use the formula
@@ -1008,7 +1061,10 @@ static void ucm_add_port_combination(
pa_device_port_new_data_init(&port_data);
pa_device_port_new_data_set_name(&port_data, name);
pa_device_port_new_data_set_description(&port_data, desc);
+ pa_device_port_new_data_set_type(&port_data, type);
pa_device_port_new_data_set_direction(&port_data, is_sink ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT);
+ if (jack)
+ pa_device_port_new_data_set_available_group(&port_data, jack->name);
port = pa_device_port_new(core, &port_data, sizeof(pa_alsa_ucm_port_data));
pa_device_port_new_data_done(&port_data);
=====================================
src/modules/alsa/alsa-ucm.h
=====================================
@@ -179,6 +179,8 @@ struct pa_alsa_ucm_device {
pa_proplist *proplist;
+ pa_device_port_type_t type;
+
unsigned playback_priority;
unsigned capture_priority;
=====================================
src/modules/bluetooth/module-bluez5-device.c
=====================================
@@ -1762,6 +1762,7 @@ static pa_available_t transport_state_to_availability(pa_bluetooth_transport_sta
static void create_card_ports(struct userdata *u, pa_hashmap *ports) {
pa_device_port *port;
pa_device_port_new_data port_data;
+ pa_device_port_type_t input_type, output_type;
const char *name_prefix, *input_description, *output_description;
pa_assert(u);
@@ -1771,60 +1772,67 @@ static void create_card_ports(struct userdata *u, pa_hashmap *ports) {
name_prefix = "unknown";
input_description = _("Bluetooth Input");
output_description = _("Bluetooth Output");
+ input_type = output_type = PA_DEVICE_PORT_TYPE_BLUETOOTH;
switch (form_factor_from_class(u->device->class_of_device)) {
case PA_BLUETOOTH_FORM_FACTOR_HEADSET:
name_prefix = "headset";
input_description = output_description = _("Headset");
+ input_type = output_type = PA_DEVICE_PORT_TYPE_HEADSET;
break;
case PA_BLUETOOTH_FORM_FACTOR_HANDSFREE:
name_prefix = "handsfree";
input_description = output_description = _("Handsfree");
+ input_type = output_type = PA_DEVICE_PORT_TYPE_HANDSFREE;
break;
case PA_BLUETOOTH_FORM_FACTOR_MICROPHONE:
name_prefix = "microphone";
input_description = _("Microphone");
output_description = _("Bluetooth Output");
+ input_type = PA_DEVICE_PORT_TYPE_MIC;
break;
case PA_BLUETOOTH_FORM_FACTOR_SPEAKER:
name_prefix = "speaker";
input_description = _("Bluetooth Input");
output_description = _("Speaker");
+ output_type = PA_DEVICE_PORT_TYPE_SPEAKER;
break;
case PA_BLUETOOTH_FORM_FACTOR_HEADPHONE:
name_prefix = "headphone";
input_description = _("Bluetooth Input");
output_description = _("Headphone");
+ output_type = PA_DEVICE_PORT_TYPE_HEADPHONES;
break;
case PA_BLUETOOTH_FORM_FACTOR_PORTABLE:
name_prefix = "portable";
input_description = output_description = _("Portable");
+ input_type = output_type = PA_DEVICE_PORT_TYPE_PORTABLE;
break;
case PA_BLUETOOTH_FORM_FACTOR_CAR:
name_prefix = "car";
input_description = output_description = _("Car");
+ input_type = output_type = PA_DEVICE_PORT_TYPE_CAR;
break;
case PA_BLUETOOTH_FORM_FACTOR_HIFI:
name_prefix = "hifi";
input_description = output_description = _("HiFi");
+ input_type = output_type = PA_DEVICE_PORT_TYPE_HIFI;
break;
case PA_BLUETOOTH_FORM_FACTOR_PHONE:
name_prefix = "phone";
input_description = output_description = _("Phone");
+ input_type = output_type = PA_DEVICE_PORT_TYPE_PHONE;
break;
case PA_BLUETOOTH_FORM_FACTOR_UNKNOWN:
- name_prefix = "unknown";
- input_description = _("Bluetooth Input");
- output_description = _("Bluetooth Output");
break;
}
@@ -1833,6 +1841,7 @@ static void create_card_ports(struct userdata *u, pa_hashmap *ports) {
pa_device_port_new_data_set_name(&port_data, u->output_port_name);
pa_device_port_new_data_set_description(&port_data, output_description);
pa_device_port_new_data_set_direction(&port_data, PA_DIRECTION_OUTPUT);
+ pa_device_port_new_data_set_type(&port_data, output_type);
pa_device_port_new_data_set_available(&port_data, get_port_availability(u, PA_DIRECTION_OUTPUT));
pa_assert_se(port = pa_device_port_new(u->core, &port_data, 0));
pa_assert_se(pa_hashmap_put(ports, port->name, port) >= 0);
@@ -1843,6 +1852,7 @@ static void create_card_ports(struct userdata *u, pa_hashmap *ports) {
pa_device_port_new_data_set_name(&port_data, u->input_port_name);
pa_device_port_new_data_set_description(&port_data, input_description);
pa_device_port_new_data_set_direction(&port_data, PA_DIRECTION_INPUT);
+ pa_device_port_new_data_set_type(&port_data, input_type);
pa_device_port_new_data_set_available(&port_data, get_port_availability(u, PA_DIRECTION_INPUT));
pa_assert_se(port = pa_device_port_new(u->core, &port_data, 0));
pa_assert_se(pa_hashmap_put(ports, port->name, port) >= 0);
=====================================
src/modules/module-tunnel.c
=====================================
@@ -1034,9 +1034,17 @@ static int read_ports(struct userdata *u, pa_tagstruct *t) {
pa_log("Parse failure");
return -PA_ERR_PROTOCOL;
}
- if (u->version >= 24 && pa_tagstruct_getu32(t, &priority) < 0) { /* available */
- pa_log("Parse failure");
- return -PA_ERR_PROTOCOL;
+ if (u->version >= 24) {
+ if (pa_tagstruct_getu32(t, &priority) < 0) { /* available */
+ pa_log("Parse failure");
+ return -PA_ERR_PROTOCOL;
+ }
+ if (u->version >= 34 &&
+ (pa_tagstruct_gets(t, &s) < 0 || /* available_group */
+ pa_tagstruct_getu32(t, &priority) < 0)) { /* device port type */
+ pa_log("Parse failure");
+ return -PA_ERR_PROTOCOL;
+ }
}
}
=====================================
src/modules/raop/raop-sink.c
=====================================
@@ -635,6 +635,7 @@ static pa_device_port *raop_create_port(struct userdata *u, const char *server)
pa_device_port_new_data_set_name(&data, "network-output");
pa_device_port_new_data_set_description(&data, server);
pa_device_port_new_data_set_direction(&data, PA_DIRECTION_OUTPUT);
+ pa_device_port_new_data_set_type(&data, PA_DEVICE_PORT_TYPE_NETWORK);
port = pa_device_port_new(u->core, &data, 0);
=====================================
src/pulse/def.h
=====================================
@@ -1070,6 +1070,33 @@ typedef enum pa_port_available {
/** \endcond */
#endif
+/** Port type. \since 14.0 */
+typedef enum pa_device_port_type {
+ PA_DEVICE_PORT_TYPE_UNKNOWN = 0,
+ PA_DEVICE_PORT_TYPE_AUX = 1,
+ PA_DEVICE_PORT_TYPE_SPEAKER = 2,
+ PA_DEVICE_PORT_TYPE_HEADPHONES = 3,
+ PA_DEVICE_PORT_TYPE_LINE = 4,
+ PA_DEVICE_PORT_TYPE_MIC = 5,
+ PA_DEVICE_PORT_TYPE_HEADSET = 6,
+ PA_DEVICE_PORT_TYPE_HANDSET = 7,
+ PA_DEVICE_PORT_TYPE_EARPIECE = 8,
+ PA_DEVICE_PORT_TYPE_SPDIF = 9,
+ PA_DEVICE_PORT_TYPE_HDMI = 10,
+ PA_DEVICE_PORT_TYPE_TV = 11,
+ PA_DEVICE_PORT_TYPE_RADIO = 12,
+ PA_DEVICE_PORT_TYPE_VIDEO = 13,
+ PA_DEVICE_PORT_TYPE_USB = 14,
+ PA_DEVICE_PORT_TYPE_BLUETOOTH = 15,
+ PA_DEVICE_PORT_TYPE_PORTABLE = 16,
+ PA_DEVICE_PORT_TYPE_HANDSFREE = 17,
+ PA_DEVICE_PORT_TYPE_CAR = 18,
+ PA_DEVICE_PORT_TYPE_HIFI = 19,
+ PA_DEVICE_PORT_TYPE_PHONE = 20,
+ PA_DEVICE_PORT_TYPE_NETWORK = 21,
+ PA_DEVICE_PORT_TYPE_ANALOG = 22,
+} pa_device_port_type_t;
+
PA_C_DECL_END
#endif
=====================================
src/pulse/introspect.c
=====================================
@@ -219,6 +219,13 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, u
goto fail;
i.ports[j]->available = av;
}
+ i.ports[j]->available_group = NULL;
+ i.ports[j]->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
+ if (o->context->version >= 34) {
+ if (pa_tagstruct_gets(t, &i.ports[j]->available_group) < 0 ||
+ pa_tagstruct_getu32(t, &i.ports[j]->type) < 0)
+ goto fail;
+ }
}
i.ports[j] = NULL;
@@ -492,11 +499,17 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
goto fail;
i.ports[j]->available = av;
}
+ i.ports[j]->available_group = NULL;
+ i.ports[j]->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
+ if (o->context->version >= 34) {
+ if (pa_tagstruct_gets(t, &i.ports[j]->available_group) < 0 ||
+ pa_tagstruct_getu32(t, &i.ports[j]->type))
+ goto fail;
+ }
}
i.ports[j] = NULL;
}
-
if (pa_tagstruct_gets(t, &ap) < 0)
goto fail;
@@ -863,6 +876,14 @@ static int fill_card_port_info(pa_context *context, pa_tagstruct* t, pa_card_inf
return -PA_ERR_PROTOCOL;
} else
port->latency_offset = 0;
+
+ port->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
+ if (context->version >= 34) {
+ if (pa_tagstruct_gets(t, &port->available_group) < 0 ||
+ pa_tagstruct_getu32(t, &port->type) < 0)
+ return -PA_ERR_PROTOCOL;
+ } else
+ port->available_group = NULL;
}
return 0;
=====================================
src/pulse/introspect.h
=====================================
@@ -229,6 +229,8 @@ typedef struct pa_sink_port_info {
const char *description; /**< Description of this port */
uint32_t priority; /**< The higher this value is, the more useful this port is as a default. */
int available; /**< A flags (see #pa_port_available), indicating availability status of this port. \since 2.0 */
+ const char *available_group; /**< A string indentifier which determine the group of devices handling the available state simultaneously. \since 14.0 */
+ uint32_t type; /**< Port device type (PA_PORT_DEVICE_TYPE). \since 14.0 */
} pa_sink_port_info;
/** Stores information about sinks. Please note that this structure
@@ -309,6 +311,8 @@ typedef struct pa_source_port_info {
const char *description; /**< Description of this port */
uint32_t priority; /**< The higher this value is, the more useful this port is as a default. */
int available; /**< A flags (see #pa_port_available), indicating availability status of this port. \since 2.0 */
+ const char *available_group; /**< A string indentifier which determine the group of devices handling the available state simultaneously. \since 14.0 */
+ uint32_t type; /**< Port device type (PA_PORT_DEVICE_TYPE). \since 14.0 */
} pa_source_port_info;
/** Stores information about sources. Please note that this structure
@@ -509,6 +513,8 @@ typedef struct pa_card_port_info {
pa_proplist *proplist; /**< Property list */
int64_t latency_offset; /**< Latency offset of the port that gets added to the sink/source latency when the port is active. \since 3.0 */
pa_card_profile_info2** profiles2; /**< Array of pointers to available profiles, or NULL. Array is terminated by an entry set to NULL. \since 5.0 */
+ const char *available_group; /**< A string indentifier which determine the group of devices handling the available state simultaneously. \since 14.0 */
+ uint32_t type; /**< Port device type (PA_PORT_DEVICE_TYPE). \since 14.0 */
} pa_card_port_info;
/** Stores information about cards. Please note that this structure
=====================================
src/pulsecore/device-port.c
=====================================
@@ -29,6 +29,7 @@ pa_device_port_new_data *pa_device_port_new_data_init(pa_device_port_new_data *d
pa_assert(data);
pa_zero(*data);
+ data->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
data->available = PA_AVAILABLE_UNKNOWN;
return data;
}
@@ -53,17 +54,31 @@ void pa_device_port_new_data_set_available(pa_device_port_new_data *data, pa_ava
data->available = available;
}
+void pa_device_port_new_data_set_available_group(pa_device_port_new_data *data, const char *group) {
+ pa_assert(data);
+
+ pa_xfree(data->available_group);
+ data->available_group = pa_xstrdup(group);
+}
+
void pa_device_port_new_data_set_direction(pa_device_port_new_data *data, pa_direction_t direction) {
pa_assert(data);
data->direction = direction;
}
+void pa_device_port_new_data_set_type(pa_device_port_new_data *data, pa_device_port_type_t type) {
+ pa_assert(data);
+
+ data->type = type;
+}
+
void pa_device_port_new_data_done(pa_device_port_new_data *data) {
pa_assert(data);
pa_xfree(data->name);
pa_xfree(data->description);
+ pa_xfree(data->available_group);
}
void pa_device_port_set_preferred_profile(pa_device_port *p, const char *new_pp) {
@@ -144,6 +159,7 @@ static void device_port_free(pa_object *o) {
if (p->profiles)
pa_hashmap_free(p->profiles);
+ pa_xfree(p->available_group);
pa_xfree(p->preferred_profile);
pa_xfree(p->name);
pa_xfree(p->description);
@@ -169,8 +185,11 @@ pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, si
p->card = NULL;
p->priority = 0;
p->available = data->available;
+ p->available_group = data->available_group;
+ data->available_group = NULL;
p->profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
p->direction = data->direction;
+ p->type = data->type;
p->latency_offset = 0;
p->proplist = pa_proplist_new();
=====================================
src/pulsecore/device-port.h
=====================================
@@ -43,9 +43,11 @@ struct pa_device_port {
char *name;
char *description;
char *preferred_profile;
+ pa_device_port_type_t type;
unsigned priority;
pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
+ char *available_group; /* a string indentifier which determine the group of devices handling the available state simulteneously */
pa_proplist *proplist;
pa_hashmap *profiles; /* Does not own the profiles */
@@ -67,14 +69,18 @@ typedef struct pa_device_port_new_data {
char *name;
char *description;
pa_available_t available;
+ char *available_group;
pa_direction_t direction;
+ pa_device_port_type_t type;
} pa_device_port_new_data;
pa_device_port_new_data *pa_device_port_new_data_init(pa_device_port_new_data *data);
void pa_device_port_new_data_set_name(pa_device_port_new_data *data, const char *name);
void pa_device_port_new_data_set_description(pa_device_port_new_data *data, const char *description);
void pa_device_port_new_data_set_available(pa_device_port_new_data *data, pa_available_t available);
+void pa_device_port_new_data_set_available_group(pa_device_port_new_data *data, const char *group);
void pa_device_port_new_data_set_direction(pa_device_port_new_data *data, pa_direction_t direction);
+void pa_device_port_new_data_set_type(pa_device_port_new_data *data, pa_device_port_type_t type);
void pa_device_port_new_data_done(pa_device_port_new_data *data);
pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, size_t extra);
=====================================
src/pulsecore/protocol-native.c
=====================================
@@ -3205,8 +3205,13 @@ static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sin
pa_tagstruct_puts(t, p->name);
pa_tagstruct_puts(t, p->description);
pa_tagstruct_putu32(t, p->priority);
- if (c->version >= 24)
+ if (c->version >= 24) {
pa_tagstruct_putu32(t, p->available);
+ if (c->version >= 34) {
+ pa_tagstruct_puts(t, p->available_group);
+ pa_tagstruct_putu32(t, p->type);
+ }
+ }
}
pa_tagstruct_puts(t, sink->active_port ? sink->active_port->name : NULL);
@@ -3275,8 +3280,13 @@ static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_s
pa_tagstruct_puts(t, p->name);
pa_tagstruct_puts(t, p->description);
pa_tagstruct_putu32(t, p->priority);
- if (c->version >= 24)
+ if (c->version >= 24) {
pa_tagstruct_putu32(t, p->available);
+ if (c->version >= 34) {
+ pa_tagstruct_puts(t, p->available_group);
+ pa_tagstruct_putu32(t, p->type);
+ }
+ }
}
pa_tagstruct_puts(t, source->active_port ? source->active_port->name : NULL);
@@ -3358,8 +3368,13 @@ static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_car
PA_HASHMAP_FOREACH(p, port->profiles, state2)
pa_tagstruct_puts(t, p->name);
- if (c->version >= 27)
+ if (c->version >= 27) {
pa_tagstruct_puts64(t, port->latency_offset);
+ if (c->version >= 34) {
+ pa_tagstruct_puts(t, port->available_group);
+ pa_tagstruct_putu32(t, port->type);
+ }
+ }
}
}
=====================================
src/utils/pactl.c
=====================================
@@ -234,12 +234,43 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
static const char* get_available_str_ynonly(int available) {
switch (available) {
- case PA_PORT_AVAILABLE_YES: return ", available";
- case PA_PORT_AVAILABLE_NO: return ", not available";
+ case PA_PORT_AVAILABLE_YES: return _(", available");
+ case PA_PORT_AVAILABLE_NO: return _(", not available");
}
return "";
}
+static const char* get_device_port_type(unsigned int type) {
+ static char buf[32];
+ switch (type) {
+ case PA_DEVICE_PORT_TYPE_UNKNOWN: return _("Unknown");
+ case PA_DEVICE_PORT_TYPE_AUX: return _("Aux");
+ case PA_DEVICE_PORT_TYPE_SPEAKER: return _("Speaker");
+ case PA_DEVICE_PORT_TYPE_HEADPHONES: return _("Headphones");
+ case PA_DEVICE_PORT_TYPE_LINE: return _("Line");
+ case PA_DEVICE_PORT_TYPE_MIC: return _("Mic");
+ case PA_DEVICE_PORT_TYPE_HEADSET: return _("Headset");
+ case PA_DEVICE_PORT_TYPE_HANDSET: return _("Handset");
+ case PA_DEVICE_PORT_TYPE_EARPIECE: return _("Earpiece");
+ case PA_DEVICE_PORT_TYPE_SPDIF: return _("SPDIF");
+ case PA_DEVICE_PORT_TYPE_HDMI: return _("HDMI");
+ case PA_DEVICE_PORT_TYPE_TV: return _("TV");
+ case PA_DEVICE_PORT_TYPE_RADIO: return _("Radio");
+ case PA_DEVICE_PORT_TYPE_VIDEO: return _("Video");
+ case PA_DEVICE_PORT_TYPE_USB: return _("USB");
+ case PA_DEVICE_PORT_TYPE_BLUETOOTH: return _("Bluetooth");
+ case PA_DEVICE_PORT_TYPE_PORTABLE: return _("Portable");
+ case PA_DEVICE_PORT_TYPE_HANDSFREE: return _("Handsfree");
+ case PA_DEVICE_PORT_TYPE_CAR: return _("Car");
+ case PA_DEVICE_PORT_TYPE_HIFI: return _("HiFi");
+ case PA_DEVICE_PORT_TYPE_PHONE: return _("Phone");
+ case PA_DEVICE_PORT_TYPE_NETWORK: return _("Network");
+ case PA_DEVICE_PORT_TYPE_ANALOG: return _("Analog");
+ }
+ snprintf(buf, sizeof(buf), "%s-%u", _("Unknown"), type);
+ return buf;
+}
+
static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) {
static const char *state_table[] = {
@@ -330,8 +361,10 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_
printf(_("\tPorts:\n"));
for (p = i->ports; *p; p++)
- printf("\t\t%s: %s (priority: %u%s)\n", (*p)->name, (*p)->description,
- (*p)->priority, get_available_str_ynonly((*p)->available));
+ printf(_("\t\t%s: %s (type: %s, priority: %u%s%s%s)\n"),
+ (*p)->name, (*p)->description, get_device_port_type((*p)->type),
+ (*p)->priority, (*p)->available_group ? _(", available group: ") : "",
+ (*p)->available_group ?: "", get_available_str_ynonly((*p)->available));
}
if (i->active_port)
@@ -436,8 +469,10 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int
printf(_("\tPorts:\n"));
for (p = i->ports; *p; p++)
- printf("\t\t%s: %s (priority: %u%s)\n", (*p)->name, (*p)->description,
- (*p)->priority, get_available_str_ynonly((*p)->available));
+ printf(_("\t\t%s: %s (type: %s, priority: %u%s%s%s)\n"),
+ (*p)->name, (*p)->description, get_device_port_type((*p)->type),
+ (*p)->priority, (*p)->available_group ? _(", available group: ") : "",
+ (*p)->available_group ?: "", get_available_str_ynonly((*p)->available));
}
if (i->active_port)
@@ -598,8 +633,9 @@ static void get_card_info_callback(pa_context *c, const pa_card_info *i, int is_
printf(_("\tPorts:\n"));
for (p = i->ports; *p; p++) {
pa_card_profile_info **pr = (*p)->profiles;
- printf("\t\t%s: %s (priority: %u, latency offset: %" PRId64 " usec%s)\n", (*p)->name,
- (*p)->description, (*p)->priority, (*p)->latency_offset,
+ printf(_("\t\t%s: %s (type: %s, priority: %u, latency offset: %" PRId64 " usec%s%s%s)\n"), (*p)->name,
+ (*p)->description, get_device_port_type((*p)->type), (*p)->priority, (*p)->latency_offset,
+ (*p)->available_group ? _(", available group: ") : "", (*p)->available_group ?: "",
get_available_str_ynonly((*p)->available));
if (!pa_proplist_isempty((*p)->proplist)) {
View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/compare/9315bbdfe5c2987bc1501653f9672f79a6f9ee6d...b2d33997930da473aa7ebd70076ac5e9d2ae01e8
--
View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/compare/9315bbdfe5c2987bc1501653f9672f79a6f9ee6d...b2d33997930da473aa7ebd70076ac5e9d2ae01e8
You're receiving this email because of your account on gitlab.freedesktop.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/pulseaudio-commits/attachments/20200617/a2d84fbf/attachment-0001.htm>
More information about the pulseaudio-commits
mailing list