]> code.delx.au - pulseaudio/commitdiff
get additional device data from udev
authorLennart Poettering <lennart@poettering.net>
Sun, 1 Mar 2009 19:34:07 +0000 (20:34 +0100)
committerLennart Poettering <lennart@poettering.net>
Sun, 1 Mar 2009 20:38:22 +0000 (21:38 +0100)
configure.ac
src/Makefile.am
src/modules/alsa/alsa-sink.c
src/modules/alsa/alsa-source.c
src/modules/alsa/alsa-util.c
src/modules/alsa/alsa-util.h
src/modules/alsa/module-alsa-card.c
src/modules/hal-util.c
src/modules/udev-util.c [new file with mode: 0644]
src/modules/udev-util.h [new file with mode: 0644]

index a1ded9e3e47a7e93d8aa6b98151c1ea5861bcae7..b2131299987324789bdce7b7d496e2bd97d02750 100644 (file)
@@ -977,6 +977,41 @@ AC_SUBST(HAL_LIBS)
 AC_SUBST(HAVE_HAL)
 AM_CONDITIONAL([HAVE_HAL], [test "x$HAVE_HAL" = x1])
 
+#### UDEV support (optional) ####
+
+AC_ARG_ENABLE([udev],
+    AS_HELP_STRING([--disable-udev],[Disable optional UDEV support]),
+        [
+            case "${enableval}" in
+                yes) udev=yes ;;
+                no) udev=no ;;
+                *) AC_MSG_ERROR(bad value ${enableval} for --disable-udev) ;;
+            esac
+        ],
+        [udev=auto])
+if test "x${udev}" != xno -a \( "x$HAVE_OSS" = "x1" -o "x$HAVE_ALSA" = "x1" \) ; then
+    PKG_CHECK_MODULES(UDEV, [ libudev ],
+        [
+            HAVE_UDEV=1
+            AC_DEFINE([HAVE_UDEV], 1, [Have UDEV.])
+        ],
+        [
+            HAVE_UDEV=0
+            if test "x$udev" = xyes ; then
+                AC_MSG_ERROR([*** UDEV support not found])
+            fi
+        ])
+else
+    HAVE_UDEV=0
+fi
+
+AC_SUBST(UDEV_CFLAGS)
+AC_SUBST(UDEV_LIBS)
+AC_SUBST(HAVE_UDEV)
+AM_CONDITIONAL([HAVE_UDEV], [test "x$HAVE_UDEV" = x1])
+
+AC_DEFINE([LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE], 1, [I know the API is subject to change.])
+
 #### BlueZ support (optional) ####
 
 AC_ARG_ENABLE([bluez],
@@ -1340,6 +1375,11 @@ if test "x$HAVE_HAL" = "x1" ; then
    ENABLE_HAL=yes
 fi
 
+ENABLE_UDEV=no
+if test "x$HAVE_UDEV" = "x1" ; then
+   ENABLE_UDEV=yes
+fi
+
 ENABLE_TCPWRAP=no
 if test "x${LIBWRAP_LIBS}" != x ; then
    ENABLE_TCPWRAP=yes
@@ -1399,6 +1439,7 @@ echo "
     Enable Async DNS:              ${ENABLE_LIBASYNCNS}
     Enable LIRC:                   ${ENABLE_LIRC}
     Enable HAL:                    ${ENABLE_HAL}
+    Enable udev:                   ${ENABLE_UDEV}
     Enable BlueZ:                  ${ENABLE_BLUEZ}
     Enable TCP Wrappers:           ${ENABLE_TCPWRAP}
     Enable libsamplerate:          ${ENABLE_LIBSAMPLERATE}
index f5a1febe576a9b13cc7115bd1563fcbe9fe694f4..9f2fa02ae2d02ac843e248688cd059fe7d66b9b5 100644 (file)
@@ -1313,6 +1313,12 @@ libalsa_util_la_LIBADD += $(HAL_LIBS)
 libalsa_util_la_CFLAGS += $(HAL_CFLAGS)
 endif
 
+if HAVE_UDEV
+libalsa_util_la_SOURCES += modules/udev-util.h modules/udev-util.c
+libalsa_util_la_LIBADD += $(UDEV_LIBS)
+libalsa_util_la_CFLAGS += $(UDEV_CFLAGS)
+endif
+
 if HAVE_DBUS
 libalsa_util_la_SOURCES += modules/reserve.h modules/reserve.c modules/reserve-wrap.c modules/reserve-wrap.h
 libalsa_util_la_LIBADD += $(DBUS_LIBS) libdbus-util.la
index 0aef1bd53887736abf28fd3b9e4ab06a01b260b9..b6fcbb79aac83af8fa27151e388dc746d94323f6 100644 (file)
@@ -1667,6 +1667,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
         pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile->description);
     }
 
+    pa_alsa_set_description(data.proplist);
+
     u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
     pa_sink_new_data_done(&data);
 
index 671df3fedeb519f76a29d9c26464718e554d3610..f56b96f3b2ff9222d99ece891c367ba770acd774 100644 (file)
@@ -1509,6 +1509,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
         pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile->description);
     }
 
+    pa_alsa_set_description(data.proplist);
+
     u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
     pa_source_new_data_done(&data);
 
index 6740c06927f99ef34c85eb0c9de5fa3b882d24ec..2f06acd0c4b57d6570c05fc2e8152377a980dcb7 100644 (file)
 #include "hal-util.h"
 #endif
 
+#ifdef HAVE_UDEV
+#include "udev-util.h"
+#endif
+
 struct pa_alsa_fdlist {
     unsigned num_fds;
     struct pollfd *fds;
@@ -1362,6 +1366,35 @@ void pa_alsa_redirect_errors_dec(void) {
         snd_lib_error_set_handler(NULL);
 }
 
+void pa_alsa_set_description(pa_proplist *p) {
+    const char *s;
+    pa_assert(p);
+
+    if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
+        return;
+
+    if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
+        if (pa_streq(s, "internal")) {
+            pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, _("Internal Audio"));
+            return;
+        }
+
+    if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME))) {
+        pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
+        return;
+    }
+
+    if ((s = pa_proplist_gets(p, "alsa.card_name"))) {
+        pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
+        return;
+    }
+
+    if ((s = pa_proplist_gets(p, "alsa.name"))) {
+        pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
+        return;
+    }
+}
+
 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
     char *cn, *lcn, *dn;
 
@@ -1385,6 +1418,10 @@ void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
         pa_xfree(dn);
     }
 
+#ifdef HAVE_UDEV
+    pa_udev_get_info(c, p, card);
+#endif
+
 #ifdef HAVE_HAL
     pa_hal_get_info(c, p, card);
 #endif
@@ -1411,7 +1448,7 @@ void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *
 
     snd_pcm_class_t class;
     snd_pcm_subclass_t subclass;
-    const char *n, *id, *sdn, *cn = NULL;
+    const char *n, *id, *sdn;
     int card;
 
     pa_assert(p);
@@ -1426,6 +1463,7 @@ void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *
         if (alsa_class_table[class])
             pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
     }
+
     subclass = snd_pcm_info_get_subclass(pcm_info);
     if (subclass <= SND_PCM_SUBCLASS_LAST)
         if (alsa_subclass_table[subclass])
@@ -1443,17 +1481,8 @@ void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *
 
     pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
 
-    if ((card = snd_pcm_info_get_card(pcm_info)) >= 0) {
+    if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
         pa_alsa_init_proplist_card(c, p, card);
-        cn = pa_proplist_gets(p, "alsa.card_name");
-    }
-
-    if (cn && n && !strstr(cn, n) && !strstr(n, cn))
-        pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s, %s", cn, n);
-    else if (cn && (!n || strstr(cn, n)))
-        pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, cn);
-    else if (n)
-        pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, n);
 }
 
 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
index 899532e2498d0878f7f23c2468cc4bbe2f22378f..1fb5996ad85f02afad558eb5beffbb93acdcccf6 100644 (file)
@@ -123,6 +123,7 @@ void pa_alsa_redirect_errors_dec(void);
 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info);
 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card);
 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm);
+void pa_alsa_set_description(pa_proplist *p);
 
 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents);
 
index fc6b886b9d80143fbd224fc5b61b0ecd30e4aaf3..74f3099b2fc370bfb73d7786f5465ccd6f617619 100644 (file)
@@ -318,6 +318,7 @@ int pa__init(pa_module *m) {
     data.module = m;
     pa_alsa_init_proplist_card(m->core, data.proplist, alsa_card_index);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_id);
+    pa_alsa_set_description(data.proplist);
     set_card_name(&data, ma, u->device_id);
 
     if (reserve)
index 82bbc57ee29041cf53cad7e2fc667876689955fa..6959a7062bcfe4152a550b303d6c63c60f4b01d7 100644 (file)
@@ -89,6 +89,9 @@ int pa_hal_get_info(pa_core *core, pa_proplist *p, int card) {
 
     pa_proplist_sets(p, "hal.udi", udis[i]);
 
+    /* The data HAL stores in info.product is not actually a product
+     * string but simply the ALSA card name. We will hence not write
+     * it to PA_PROP_DEVICE_PRODUCT_NAME */
     t = libhal_device_get_property_string(hal, udis[i], "info.product", &error);
     if (dbus_error_is_set(&error))
         dbus_error_free(&error);
diff --git a/src/modules/udev-util.c b/src/modules/udev-util.c
new file mode 100644 (file)
index 0000000..a72bc8f
--- /dev/null
@@ -0,0 +1,142 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2009 Lennart Poettering
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <libudev.h>
+
+#include <pulse/xmalloc.h>
+#include <pulse/proplist.h>
+
+#include <pulsecore/log.h>
+#include <pulsecore/core-util.h>
+
+#include "udev-util.h"
+
+static int read_id(struct udev_device *d, const char *n) {
+    const char *v;
+    unsigned u;
+
+    pa_assert(d);
+    pa_assert(n);
+
+    if (!(v = udev_device_get_property_value(d, n)))
+        return -1;
+
+    if (pa_startswith(v, "0x"))
+        v += 2;
+
+    if (!*v)
+        return -1;
+
+    if (sscanf(v, "%04x", &u) != 1)
+        return -1;
+
+    if (u > 0xFFFFU)
+        return -1;
+
+    return u;
+}
+
+int pa_udev_get_info(pa_core *core, pa_proplist *p, int card_idx) {
+    int r = -1;
+    struct udev *udev;
+    struct udev_device *card;
+    char *t;
+    const char *v;
+    int id;
+
+    pa_assert(core);
+    pa_assert(p);
+    pa_assert(card_idx >= 0);
+
+    if (!(udev = udev_new())) {
+        pa_log_error("Failed to allocate udev context.");
+        goto finish;
+    }
+
+    t = pa_sprintf_malloc("%s/class/sound/card%i", udev_get_sys_path(udev), card_idx);
+    card = udev_device_new_from_syspath(udev, t);
+    pa_xfree(t);
+
+    if (!card) {
+        pa_log_error("Failed to get card object.");
+        goto finish;
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_DEVICE_BUS))
+        if ((v = udev_device_get_property_value(card, "ID_BUS")) && *v)
+            pa_proplist_sets(p, PA_PROP_DEVICE_BUS, v);
+
+    if (!pa_proplist_contains(p, PA_PROP_DEVICE_VENDOR_ID))
+        if ((id = read_id(card, "ID_VENDOR_ID")) > 0 && *v)
+            pa_proplist_setf(p, PA_PROP_DEVICE_VENDOR_ID, "%04x", id);
+
+    if (!pa_proplist_contains(p, PA_PROP_DEVICE_VENDOR_NAME)) {
+        if ((v = udev_device_get_property_value(card, "ID_VENDOR_FROM_DATABASE")) && *v)
+            pa_proplist_sets(p, PA_PROP_DEVICE_VENDOR_NAME, v);
+        else if ((v = udev_device_get_property_value(card, "ID_VENDOR")) && *v)
+            pa_proplist_sets(p, PA_PROP_DEVICE_VENDOR_NAME, v);
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_DEVICE_PRODUCT_ID))
+        if ((id = read_id(card, "ID_MODEL_ID")) >= 0)
+            pa_proplist_setf(p, PA_PROP_DEVICE_PRODUCT_ID, "%04x", id);
+
+    if (!pa_proplist_contains(p, PA_PROP_DEVICE_PRODUCT_NAME)) {
+        if ((v = udev_device_get_property_value(card, "ID_MODEL_FROM_DATABASE")) && *v)
+            pa_proplist_sets(p, PA_PROP_DEVICE_PRODUCT_NAME, v);
+        else if ((v = udev_device_get_property_value(card, "ID_MODEL")) && *v)
+            pa_proplist_sets(p, PA_PROP_DEVICE_PRODUCT_NAME, v);
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_DEVICE_SERIAL))
+        if ((v = udev_device_get_property_value(card, "ID_SERIAL")) && *v)
+            pa_proplist_sets(p, PA_PROP_DEVICE_SERIAL, v);
+
+    if (!pa_proplist_contains(p, PA_PROP_DEVICE_FORM_FACTOR))
+        if ((v = udev_device_get_property_value(card, "SOUND_FORM_FACTOR")) && *v)
+            pa_proplist_sets(p, PA_PROP_DEVICE_FORM_FACTOR, v);
+
+    if (!pa_proplist_contains(p, PA_PROP_DEVICE_BUS_PATH))
+        if ((v = udev_device_get_devpath(card)))
+            pa_proplist_sets(p, PA_PROP_DEVICE_BUS_PATH, v);
+
+    /* This is normaly not set by th udev rules but may be useful to
+     * allow administrators to overwrite the device description.*/
+    if (!pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
+        if ((v = udev_device_get_property_value(card, "SOUND_DESCRIPTION")) && *v)
+            pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, v);
+
+    r = 0;
+
+finish:
+
+    if (card)
+        udev_device_unref(card);
+
+    if (udev)
+        udev_unref(udev);
+
+    return r;
+}
diff --git a/src/modules/udev-util.h b/src/modules/udev-util.h
new file mode 100644 (file)
index 0000000..86fbba7
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef fooudevutilhfoo
+#define fooudevutilhfoo
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2009 Lennart Poettering
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+
+#include <pulsecore/core.h>
+
+int pa_udev_get_info(pa_core *core, pa_proplist *p, int card);
+
+#endif