[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