mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
get additional device data from udev
This commit is contained in:
parent
cc8d51ad62
commit
784ac5b0da
10 changed files with 268 additions and 11 deletions
41
configure.ac
41
configure.ac
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@
|
|||
#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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
142
src/modules/udev-util.c
Normal file
142
src/modules/udev-util.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
30
src/modules/udev-util.h
Normal file
30
src/modules/udev-util.h
Normal file
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue