[pulseaudio-commits] 3 commits - src/modules
Tanu Kaskinen
tanuk at kemper.freedesktop.org
Tue Feb 19 10:51:39 PST 2013
src/modules/alsa/alsa-mixer.c | 3
src/modules/alsa/alsa-mixer.h | 1
src/modules/alsa/alsa-util.c | 68 ++++++++++++++++
src/modules/alsa/alsa-util.h | 8 +
src/modules/alsa/mixer/paths/analog-output.conf.common | 2
src/modules/alsa/mixer/paths/hdmi-output-0.conf | 1
src/modules/alsa/mixer/paths/hdmi-output-1.conf | 1
src/modules/alsa/mixer/paths/hdmi-output-2.conf | 1
src/modules/alsa/mixer/paths/hdmi-output-3.conf | 1
src/modules/alsa/module-alsa-card.c | 72 +++++++++++++++++
10 files changed, 158 insertions(+)
New commits:
commit fd3a4e588c558432cd213f6337204096fe709320
Author: David Henningsson <david.henningsson at canonical.com>
Date: Tue Feb 19 13:25:49 2013 +0100
alsa-card: Make ELD monitor name a port property
If there is a proper monitor name, we expose this as a device.product.name
property on the port. This can be useful for UIs who might want to show
this name.
Signed-off-by: David Henningsson <david.henningsson at canonical.com>
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index f5e1c9e..3b96cea 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -388,6 +388,77 @@ static int report_jack_state(snd_hctl_elem_t *elem, unsigned int mask)
return 0;
}
+static pa_device_port* find_port_with_eld_device(pa_hashmap *ports, int device) {
+ void *state;
+ pa_device_port *p;
+
+ PA_HASHMAP_FOREACH(p, ports, state) {
+ pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(p);
+ pa_assert(data->path);
+ if (device == data->path->eld_device)
+ return p;
+ }
+ return NULL;
+}
+
+static int hdmi_eld_changed(snd_hctl_elem_t *elem, unsigned int mask) {
+ struct userdata *u = snd_hctl_elem_get_callback_private(elem);
+ int device = snd_hctl_elem_get_device(elem);
+ const char *old_monitor_name;
+ pa_device_port *p;
+ pa_hdmi_eld eld;
+ bool changed = false;
+
+ p = find_port_with_eld_device(u->card->ports, device);
+ if (p == NULL) {
+ pa_log_error("Invalid device changed in ALSA: %d", device);
+ return 0;
+ }
+
+ if (pa_alsa_get_hdmi_eld(u->hctl_handle, device, &eld) < 0)
+ memset(&eld, 0, sizeof(eld));
+
+ old_monitor_name = pa_proplist_gets(p->proplist, PA_PROP_DEVICE_PRODUCT_NAME);
+ if (eld.monitor_name[0] == '\0') {
+ changed |= old_monitor_name != NULL;
+ pa_proplist_unset(p->proplist, PA_PROP_DEVICE_PRODUCT_NAME);
+ } else {
+ changed |= (old_monitor_name == NULL) || (strcmp(old_monitor_name, eld.monitor_name) != 0);
+ pa_proplist_sets(p->proplist, PA_PROP_DEVICE_PRODUCT_NAME, eld.monitor_name);
+ }
+
+ if (changed && mask != 0)
+ pa_subscription_post(u->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, u->card->index);
+
+ return 0;
+}
+
+static void init_eld_ctls(struct userdata *u) {
+ void *state;
+ pa_device_port *port;
+
+ PA_HASHMAP_FOREACH(port, u->card->ports, state) {
+ pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(port);
+ snd_hctl_elem_t* hctl_elem;
+ int device;
+
+ pa_assert(data->path);
+ device = data->path->eld_device;
+ if (device < 0)
+ continue;
+
+ hctl_elem = pa_alsa_find_eld_ctl(u->hctl_handle, device);
+ if (!hctl_elem) {
+ pa_log_debug("No ELD device found for port %s.", port->name);
+ continue;
+ }
+
+ snd_hctl_elem_set_callback_private(hctl_elem, u);
+ snd_hctl_elem_set_callback(hctl_elem, hdmi_eld_changed);
+ hdmi_eld_changed(hctl_elem, 0);
+ }
+}
+
static void init_jacks(struct userdata *u) {
void *state;
pa_alsa_path* path;
@@ -676,6 +747,7 @@ int pa__init(pa_module *m) {
init_profile(u);
init_jacks(u);
+ init_eld_ctls(u);
if (reserve)
pa_reserve_wrapper_unref(reserve);
commit bf487f0ffaeca7474232e5d62a3609344f8835b6
Author: David Henningsson <david.henningsson at canonical.com>
Date: Tue Feb 19 13:25:48 2013 +0100
alsa-mixer: Add possibility to configure ELD device
The alsa mixer kcontrol has "device index" 3, 7, 8, and 9.
We need to configure this properly.
Signed-off-by: David Henningsson <david.henningsson at canonical.com>
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index f2e68d3..137c9eb 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -2390,6 +2390,7 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
{ "description", pa_config_parse_string, NULL, "General" },
{ "name", pa_config_parse_string, NULL, "General" },
{ "mute-during-activation", pa_config_parse_bool, NULL, "General" },
+ { "eld-device", pa_config_parse_int, NULL, "General" },
/* [Option ...] */
{ "priority", option_parse_priority, NULL, NULL },
@@ -2422,11 +2423,13 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
p->name = pa_xstrndup(n, strcspn(n, "."));
p->proplist = pa_proplist_new();
p->direction = direction;
+ p->eld_device = -1;
items[0].data = &p->priority;
items[1].data = &p->description;
items[2].data = &p->name;
items[3].data = &mute_during_activation;
+ items[4].data = &p->eld_device;
if (!paths_dir)
paths_dir = get_default_paths_dir();
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 5b710a3..b3f7455 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -182,6 +182,7 @@ struct pa_alsa_path {
char *name;
char *description;
unsigned priority;
+ int eld_device;
pa_proplist *proplist;
pa_bool_t probed:1;
diff --git a/src/modules/alsa/mixer/paths/analog-output.conf.common b/src/modules/alsa/mixer/paths/analog-output.conf.common
index 01835fb..73d09f8 100644
--- a/src/modules/alsa/mixer/paths/analog-output.conf.common
+++ b/src/modules/alsa/mixer/paths/analog-output.conf.common
@@ -59,6 +59,8 @@
; mute-during-activation = yes | no # If this path supports hardware mute, should the hw mute be used while activating this
; # path? In some cases this can reduce extra noises during port switching, while in other
; # cases this can increase such noises. Default: no.
+; eld-device = ... # If this is an HDMI port, here's where to specify the device number for the ELD mixer
+; # control. The default is to not make use of ELD information.
;
; [Properties] # Property list for this path. The list is merged into the port property list.
; <key> = <value> # Each property is defined on its own line.
diff --git a/src/modules/alsa/mixer/paths/hdmi-output-0.conf b/src/modules/alsa/mixer/paths/hdmi-output-0.conf
index 69b39ec..3310147 100644
--- a/src/modules/alsa/mixer/paths/hdmi-output-0.conf
+++ b/src/modules/alsa/mixer/paths/hdmi-output-0.conf
@@ -1,6 +1,7 @@
[General]
description = HDMI / DisplayPort
priority = 59
+eld-device = 3
[Properties]
device.icon_name = video-display
diff --git a/src/modules/alsa/mixer/paths/hdmi-output-1.conf b/src/modules/alsa/mixer/paths/hdmi-output-1.conf
index 01eeeed..d81ee78 100644
--- a/src/modules/alsa/mixer/paths/hdmi-output-1.conf
+++ b/src/modules/alsa/mixer/paths/hdmi-output-1.conf
@@ -1,6 +1,7 @@
[General]
description = HDMI / DisplayPort 2
priority = 58
+eld-device = 7
[Properties]
device.icon_name = video-display
diff --git a/src/modules/alsa/mixer/paths/hdmi-output-2.conf b/src/modules/alsa/mixer/paths/hdmi-output-2.conf
index 5974511..349812f 100644
--- a/src/modules/alsa/mixer/paths/hdmi-output-2.conf
+++ b/src/modules/alsa/mixer/paths/hdmi-output-2.conf
@@ -1,6 +1,7 @@
[General]
description = HDMI / DisplayPort 3
priority = 57
+eld-device = 8
[Properties]
device.icon_name = video-display
diff --git a/src/modules/alsa/mixer/paths/hdmi-output-3.conf b/src/modules/alsa/mixer/paths/hdmi-output-3.conf
index 92a7acf..81463c9 100644
--- a/src/modules/alsa/mixer/paths/hdmi-output-3.conf
+++ b/src/modules/alsa/mixer/paths/hdmi-output-3.conf
@@ -1,6 +1,7 @@
[General]
description = HDMI / DisplayPort 4
priority = 56
+eld-device = 9
[Properties]
device.icon_name = video-display
commit eaa893d7d130a4074643eb7d4dc5cb22136a6e4a
Author: David Henningsson <david.henningsson at canonical.com>
Date: Tue Feb 19 13:25:47 2013 +0100
alsa-util: Add a function to read ELD info
Currently, this function only reads the monitor name, but could
be extended to read e g supported formats as well.
Signed-off-by: David Henningsson <david.henningsson at canonical.com>
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 114ab27..b556349 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1462,6 +1462,20 @@ snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name)
return snd_hctl_find_elem(hctl, id);
}
+snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device) {
+ snd_ctl_elem_id_t *id;
+
+ /* See if we can find the ELD control */
+ snd_ctl_elem_id_alloca(&id);
+ snd_ctl_elem_id_clear(id);
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
+ snd_ctl_elem_id_set_name(id, "ELD");
+ snd_ctl_elem_id_set_device(id, device);
+
+ return snd_hctl_find_elem(hctl, id);
+}
+
+
static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl) {
int err;
@@ -1574,3 +1588,57 @@ snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_h
snd_mixer_close(m);
return NULL;
}
+
+int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld) {
+
+ /* The ELD format is specific to HDA Intel sound cards and defined in the
+ HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
+ int err;
+ snd_hctl_elem_t *elem;
+ snd_ctl_elem_info_t *info;
+ snd_ctl_elem_value_t *value;
+ uint8_t *elddata;
+ unsigned int eldsize, mnl;
+
+ pa_assert(eld != NULL);
+
+ /* See if we can find the ELD control */
+ elem = pa_alsa_find_eld_ctl(hctl, device);
+ if (elem == NULL) {
+ pa_log_debug("No ELD info control found (for device=%d)", device);
+ return -1;
+ }
+
+ /* Does it have any contents? */
+ snd_ctl_elem_info_alloca(&info);
+ snd_ctl_elem_value_alloca(&value);
+ if ((err = snd_hctl_elem_info(elem, info)) < 0 ||
+ (err = snd_hctl_elem_read(elem, value)) < 0) {
+ pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err));
+ return -1;
+ }
+
+ eldsize = snd_ctl_elem_info_get_count(info);
+ elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
+ if (elddata == NULL || eldsize == 0) {
+ pa_log_debug("ELD info empty (for device=%d)", device);
+ return -1;
+ }
+ if (eldsize < 20 || eldsize > 256) {
+ pa_log_debug("ELD info has wrong size (for device=%d)", device);
+ return -1;
+ }
+
+ /* Try to fetch monitor name */
+ mnl = elddata[4] & 0x1f;
+ if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) {
+ pa_log_debug("No monitor name in ELD info (for device=%d)", device);
+ mnl = 0;
+ }
+ memcpy(eld->monitor_name, &elddata[20], mnl);
+ eld->monitor_name[mnl] = '\0';
+ if (mnl)
+ pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device);
+
+ return 0;
+}
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 1326e64..5b0a0bd 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -143,7 +143,15 @@ const char* pa_alsa_strerror(int errnum);
pa_bool_t pa_alsa_may_tsched(pa_bool_t want);
snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name);
+snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device);
snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl_t **hctl);
+typedef struct pa_hdmi_eld pa_hdmi_eld;
+struct pa_hdmi_eld {
+ char monitor_name[17];
+};
+
+int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld);
+
#endif
More information about the pulseaudio-commits
mailing list