diff options
| -rw-r--r-- | Makefile.am | 6 | ||||
| -rw-r--r-- | configure.ac | 41 | ||||
| -rw-r--r-- | m4/shave.m4 | 50 | ||||
| -rw-r--r-- | shave-libtool.in | 2 | ||||
| -rw-r--r-- | shave.in | 8 | ||||
| -rw-r--r-- | src/Makefile.am | 6 | ||||
| -rw-r--r-- | src/modules/alsa/alsa-sink.c | 2 | ||||
| -rw-r--r-- | src/modules/alsa/alsa-source.c | 2 | ||||
| -rw-r--r-- | src/modules/alsa/alsa-util.c | 42 | ||||
| -rw-r--r-- | src/modules/alsa/alsa-util.h | 1 | ||||
| -rw-r--r-- | src/modules/alsa/module-alsa-card.c | 1 | ||||
| -rw-r--r-- | src/modules/bluetooth/bluetooth-util.c | 4 | ||||
| -rw-r--r-- | src/modules/bluetooth/ipc.h | 3 | ||||
| -rw-r--r-- | src/modules/bluetooth/module-bluetooth-device.c | 2 | ||||
| -rw-r--r-- | src/modules/hal-util.c | 3 | ||||
| -rw-r--r-- | src/modules/reserve.h | 21 | ||||
| -rw-r--r-- | src/modules/udev-util.c | 142 | ||||
| -rw-r--r-- | src/modules/udev-util.h | 30 | ||||
| -rw-r--r-- | src/pulse/proplist.h | 33 | ||||
| -rw-r--r-- | src/pulse/thread-mainloop.h | 10 | ||||
| -rw-r--r-- | src/pulsecore/card.c | 3 | ||||
| -rw-r--r-- | src/pulsecore/ffmpeg/resample2.c | 27 | ||||
| -rw-r--r-- | src/pulsecore/sink.c | 69 | ||||
| -rw-r--r-- | src/pulsecore/sink.h | 3 | ||||
| -rw-r--r-- | src/pulsecore/source.c | 3 | 
25 files changed, 428 insertions, 86 deletions
diff --git a/Makefile.am b/Makefile.am index 8735d312..9a3ca7b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,6 +61,12 @@ dist-hook:  		( git-changelog.perl || echo "git-changelog.perl failed." ) > ${distdir}/ChangeLog 2>&1 ; \  	fi +update-shave: +	for i in shave.in shave.m4 shave-libtool.in; do \ +		wget -O $$i http://git.lespiau.name/cgit/shave/blob/\?path=shave/$$i ; \ +	done +	mv shave.m4 m4/ +  .PHONY: homepage distcleancheck doxygen  DISTCLEANFILES = \ diff --git a/configure.ac b/configure.ac index a1ded9e3..77d777d7 100644 --- a/configure.ac +++ b/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 >= 137 ], +        [ +            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} diff --git a/m4/shave.m4 b/m4/shave.m4 index 44d3908b..0c2c9f5a 100644 --- a/m4/shave.m4 +++ b/m4/shave.m4 @@ -1,9 +1,12 @@  dnl Make automake/libtool output more friendly to humans  dnl -dnl SHAVE_INIT([shavedir]) +dnl SHAVE_INIT([shavedir],[default_mode])  dnl  dnl shavedir: the directory where the shave scripts are, it defaults to  dnl           $(top_builddir) +dnl default_mode: (enable|disable) default shave mode.  This parameter +dnl               controls shave's behaviour when no option has been +dnl               given to configure.  It defaults to disable.  dnl  dnl * SHAVE_INIT should be called late in your configure.(ac|in) file (just  dnl   before AC_CONFIG_FILE/AC_OUTPUT is perfect.  This macro rewrites CC and @@ -11,19 +14,26 @@ dnl   LIBTOOL, you don't want the configure tests to have these variables  dnl   re-defined.  dnl * This macro requires GNU make's -s option. -AC_DEFUN([SHAVE_INIT], +AC_DEFUN([_SHAVE_ARG_ENABLE],  [ -  dnl enable/disable shave    AC_ARG_ENABLE([shave], -    AS_HELP_STRING([--enable-shave], -                   [use shave to make the build pretty [[default=no]]]),, -    [enable_shave=no]) +    AS_HELP_STRING( +      [--enable-shave], +      [use shave to make the build pretty [[default=$1]]]),, +      [enable_shave=$1] +    ) +]) + +AC_DEFUN([SHAVE_INIT], +[ +  dnl you can tweak the default value of enable_shave +  m4_if([$2], [enable], [_SHAVE_ARG_ENABLE(yes)], [_SHAVE_ARG_ENABLE(no)])    if test x"$enable_shave" = xyes; then      dnl where can we find the shave scripts?      m4_if([$1],, -      [shavedir='$(top_builddir)'], -      [shavedir='$(top_builddir)'/$1]) +      [shavedir="$ac_pwd"], +      [shavedir="$ac_pwd/$1"])      AC_SUBST(shavedir)      dnl make is now quiet @@ -35,19 +45,22 @@ AC_DEFUN([SHAVE_INIT],      dnl substitute libtool      SHAVE_SAVED_LIBTOOL=$LIBTOOL -    AC_SUBST(SHAVE_SAVED_LIBTOOL) -    LIBTOOL="\$(SHELL) \$(shavedir)/shave-libtool '\$(SHAVE_SAVED_LIBTOOL)'" +    LIBTOOL="${SHELL} ${shavedir}/shave-libtool '${SHAVE_SAVED_LIBTOOL}'"      AC_SUBST(LIBTOOL)      dnl substitute cc/cxx      SHAVE_SAVED_CC=$CC      SHAVE_SAVED_CXX=$CXX -    AC_SUBST(SHAVE_SAVED_CC) -    AC_SUBST(SHAVE_SAVED_CXX) -    CC="\$(SHELL) \$(shavedir)/shave cc '\$(SHAVE_SAVED_CC)'" -    CXX="\$(SHELL) \$(shavedir)/shave cxx '\$(SHAVE_SAVED_CXX)'" +    SHAVE_SAVED_FC=$FC +    SHAVE_SAVED_F77=$F77 +    CC="${SHELL} ${shavedir}/shave cc ${SHAVE_SAVED_CC}" +    CXX="${SHELL} ${shavedir}/shave cxx ${SHAVE_SAVED_CXX}" +    FC="${SHELL} ${shavedir}/shave fc ${SHAVE_SAVED_FC}" +    F77="${SHELL} ${shavedir}/shave f77 ${SHAVE_SAVED_F77}"      AC_SUBST(CC)      AC_SUBST(CXX) +    AC_SUBST(FC) +    AC_SUBST(F77)      V=@    else @@ -58,12 +71,3 @@ AC_DEFUN([SHAVE_INIT],    AC_SUBST(Q)  ]) -AC_DEFUN([SHAVE_OUTPUT], -[ -  if test x"$enable_shave" = xyes; then -    dnl small workaround to fix libtool itself -    dnl it's shokingly hard to find a better way, really! wtf... -    test -f $srcdir/libtool && (tmpfile=`mktemp` && cat $srcdir/libtool | sed "s,^LTCC=.*$,LTCC=\"$SHELL $ac_pwd/shave cc $SHAVE_SAVED_CC\"," > $tmpfile && mv $tmpfile $srcdir/libtool) -  fi - -]) diff --git a/shave-libtool.in b/shave-libtool.in index 30e6f138..1f3a720c 100644 --- a/shave-libtool.in +++ b/shave-libtool.in @@ -8,7 +8,7 @@ fi  lt_unmangle ()  { -   last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_]\*_la-##'` +   last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_\-\.]*_la-##'`  }  # the real libtool to use @@ -8,7 +8,7 @@ fi  lt_unmangle ()  { -   last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_]\*_la-##'` +   last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_\-\.]*_la-##'`  }  # the tool to wrap (cc, cxx, ar, ranlib, ..) @@ -50,6 +50,12 @@ link,*)  *,cc)      Q="  CC    "      ;; +*,fc) +    Q="  FC    " +    ;; +*,f77) +    Q="  F77   " +    ;;  *,*)      # should not happen      Q="  CC    " diff --git a/src/Makefile.am b/src/Makefile.am index f5a1febe..9f2fa02a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 708e020c..d4325881 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -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_init_description(data.proplist); +      u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);      pa_sink_new_data_done(&data); diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index 4321c7ff..7a1b0f8d 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -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_init_description(data.proplist); +      u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);      pa_source_new_data_done(&data); diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c index 6740c069..7d833ff7 100644 --- a/src/modules/alsa/alsa-util.c +++ b/src/modules/alsa/alsa-util.c @@ -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,26 @@ void pa_alsa_redirect_errors_dec(void) {          snd_lib_error_set_handler(NULL);  } +pa_bool_t pa_alsa_init_description(pa_proplist *p) { +    const char *s; +    pa_assert(p); + +    if (pa_device_init_description(p)) +        return TRUE; + +    if ((s = pa_proplist_gets(p, "alsa.card_name"))) { +        pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s); +        return TRUE; +    } + +    if ((s = pa_proplist_gets(p, "alsa.name"))) { +        pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s); +        return TRUE; +    } + +    return FALSE; +} +  void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {      char *cn, *lcn, *dn; @@ -1385,6 +1409,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 +1439,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 +1454,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 +1472,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) { diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h index 899532e2..a8397ae9 100644 --- a/src/modules/alsa/alsa-util.h +++ b/src/modules/alsa/alsa-util.h @@ -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); +pa_bool_t pa_alsa_init_description(pa_proplist *p);  int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents); diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index fc6b886b..9e149a48 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -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_init_description(data.proplist);      set_card_name(&data, ma, u->device_id);      if (reserve) diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index 7855c2ef..6b522200 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -811,8 +811,8 @@ const char*pa_bluetooth_get_form_factor(uint32_t class) {          [1] = "headset",          [2] = "hands-free",          [4] = "microphone", -        [5] = "external-speakers", -        [6] = "headphones", +        [5] = "speaker", +        [6] = "headphone",          [7] = "portable",          [8] = "car",          [10] = "hifi" diff --git a/src/modules/bluetooth/ipc.h b/src/modules/bluetooth/ipc.h index 4203150b..f030acfa 100644 --- a/src/modules/bluetooth/ipc.h +++ b/src/modules/bluetooth/ipc.h @@ -160,7 +160,8 @@ struct bt_get_capabilities_req {  #define BT_HFP_CODEC_PCM			0x00 -#define BT_PCM_FLAG_NREC			1 +#define BT_PCM_FLAG_NREC			0x01 +#define BT_PCM_FLAG_PCM_ROUTING			0x02  typedef struct {  	uint8_t transport; diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index b2fb1db1..3332df2c 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -1728,7 +1728,7 @@ static int add_card(struct userdata *u, const char * default_profile) {      pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device->address);      pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "bluez");      pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "sound"); -    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CONNECTOR, "bluetooth"); +    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_BUS, "bluetooth");      if ((ff = pa_bluetooth_get_form_factor(u->device->class)))          pa_proplist_sets(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, ff);      pa_proplist_sets(data.proplist, "bluez.path", u->device->path); diff --git a/src/modules/hal-util.c b/src/modules/hal-util.c index 82bbc57e..6959a706 100644 --- a/src/modules/hal-util.c +++ b/src/modules/hal-util.c @@ -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/reserve.h b/src/modules/reserve.h index ceb1ad11..b315a08c 100644 --- a/src/modules/reserve.h +++ b/src/modules/reserve.h @@ -31,10 +31,11 @@  typedef struct rd_device rd_device;  /* Prototype for a function that is called whenever someone else wants - * your app to release the device you having locked. A return value <= - * 0 denies the request, a positive return value agrees to it. Before - * returning your application should close the device in question - * completely to make sure the new application may acceess it. */ + * your application to release the device it has locked. A return + * value <= 0 denies the request, a positive return value agrees to + * it. Before returning your application should close the device in + * question completely to make sure the new application may access + * it. */  typedef int (*rd_request_cb_t)(  	rd_device *d,  	int forced);                  /* Non-zero if an application forcibly took the lock away without asking. If this is the case then the return value of this call is ignored. */ @@ -48,20 +49,20 @@ int rd_acquire(  	const char *device_name,      /* The device to lock, e.g. "Audio0" */  	const char *application_name, /* A human readable name of the application, e.g. "PulseAudio Sound Server" */  	int32_t priority,             /* The priority for this application. If unsure use 0 */ -	rd_request_cb_t request_cb,   /* Will be called whenever someone asks that this device shall be released. May be NULL if priority is INT32_MAX */ +	rd_request_cb_t request_cb,   /* Will be called whenever someone requests that this device shall be released. May be NULL if priority is INT32_MAX */  	DBusError *error);            /* If we fail due to a D-Bus related issue the error will be filled in here. May be NULL. */ -/* Unlock (if needed) and destroy a rd_device object again */ +/* Unlock (if needed) and destroy an rd_device object again */  void rd_release(rd_device *d); -/* Set the application device name for a rd_device object Returns 0 on - * success, a negative errno style return value on error. */ +/* Set the application device name for an rd_device object. Returns 0 + * on success, a negative errno style return value on error. */  int rd_set_application_device_name(rd_device *d, const char *name); -/* Attach a userdata pointer to a rd_device */ +/* Attach a userdata pointer to an rd_device */  void rd_set_userdata(rd_device *d, void *userdata); -/* Query the userdata pointer from a rd_device. Returns NULL if no +/* Query the userdata pointer from an rd_device. Returns NULL if no   * userdata was set. */  void* rd_get_userdata(rd_device *d); diff --git a/src/modules/udev-util.c b/src/modules/udev-util.c new file mode 100644 index 00000000..a72bc8f8 --- /dev/null +++ b/src/modules/udev-util.c @@ -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 index 00000000..86fbba7f --- /dev/null +++ b/src/modules/udev-util.h @@ -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 diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h index fa44c426..d5f5bc04 100644 --- a/src/pulse/proplist.h +++ b/src/pulse/proplist.h @@ -45,8 +45,10 @@ PA_C_DECL_BEGIN  /** For streams: source filename if applicable, in URI format or local path. e.g. "/home/lennart/music/foobar.ogg" */  #define PA_PROP_MEDIA_FILENAME                 "media.filename" +/** \cond fulldocs */  /** For streams: icon for the media. A binary blob containing PNG image data */  #define PA_PROP_MEDIA_ICON                     "media.icon" +/** \endcond */  /** For streams: an XDG icon name for the media. e.g. "audio-x-mp3" */  #define PA_PROP_MEDIA_ICON_NAME                "media.icon_name" @@ -81,8 +83,10 @@ PA_C_DECL_BEGIN  /** For streams that belong to a window on the screen: a textual id for identifying a window logically. e.g. "org.gnome.Totem.MainWindow" */  #define PA_PROP_WINDOW_ID                      "window.id" +/** \cond fulldocs */  /** For streams that belong to a window on the screen: window icon. A binary blob containing PNG image data */  #define PA_PROP_WINDOW_ICON                    "window.icon" +/** \endcond */  /** For streams that belong to a window on the screen: an XDG icon name for the window. e.g. "totem" */  #define PA_PROP_WINDOW_ICON_NAME               "window.icon_name" @@ -108,8 +112,10 @@ PA_C_DECL_BEGIN  /** For clients/streams: a version string e.g. "0.6.88" */  #define PA_PROP_APPLICATION_VERSION            "application.version" +/** \cond fulldocs */  /** For clients/streams: application icon. A binary blob containing PNG image data */  #define PA_PROP_APPLICATION_ICON               "application.icon" +/** \endcond */  /** For clients/streams: an XDG icon name for the application. e.g. "totem" */  #define PA_PROP_APPLICATION_ICON_NAME          "application.icon_name" @@ -150,17 +156,34 @@ PA_C_DECL_BEGIN  /** For devices: serial number if applicable. e.g. "4711-0815-1234" */  #define PA_PROP_DEVICE_SERIAL                  "device.serial" -/** For devices: vendor/product ID if applicable. e.g. 1274:1371 */ -#define PA_PROP_DEVICE_VENDOR_PRODUCT_ID       "device.vendor_product_id" +/** For devices: vendor ID if applicable. e.g. 1274 */ +#define PA_PROP_DEVICE_VENDOR_ID               "device.vendor.id" + +/** For devices: vendor name if applicable. e.g. "Foocorp Heavy Industries" */ +#define PA_PROP_DEVICE_VENDOR_NAME             "device.vendor.name" + +/** For devices: product ID if applicable. e.g. 4565 */ +#define PA_PROP_DEVICE_PRODUCT_ID              "device.product.id" + +/** For devices: product name if applicable. e.g. "SuperSpeakers 2000 Pro" */ +#define PA_PROP_DEVICE_PRODUCT_NAME            "device.product.name"  /** For devices: device class. One of "sound", "modem", "monitor", "filter" */  #define PA_PROP_DEVICE_CLASS                   "device.class" -/** For devices: form factor if applicable. One of "internal-speakers", "external-speakers", "handset", "tv-capture", "webcam", "microphone", "headset", "headphones", "hands-free", "car", "hifi", "computer", "portable" */ +/** For devices: form factor if applicable. One of "internal", "speaker", "handset", "tv", "webcam", "microphone", "headset", "headphone", "hands-free", "car", "hifi", "computer", "portable" */  #define PA_PROP_DEVICE_FORM_FACTOR             "device.form_factor" -/** For devices: connector of the device if applicable. One of "isa", "pci", "usb", "firewire", "bluetooth" */ -#define PA_PROP_DEVICE_CONNECTOR               "device.connector" +/** For devices: bus of the device if applicable. One of "isa", "pci", "usb", "firewire", "bluetooth" */ +#define PA_PROP_DEVICE_BUS                     "device.bus" + +/** \cond fulldocs */ +/** For devices: icon for the device. A binary blob containing PNG image data */ +#define PA_PROP_DEVICE_ICON                    "device.icon" +/** \endcond */ + +/** For devices: an XDG icon name for the device. e.g. "sound-card-speakers-usb" */ +#define PA_PROP_DEVICE_ICON_NAME               "device.icon_name"  /** For devices: access mode of the device if applicable. One of "mmap", "mmap_rewrite", "serial" */  #define PA_PROP_DEVICE_ACCESS_MODE             "device.access_mode" diff --git a/src/pulse/thread-mainloop.h b/src/pulse/thread-mainloop.h index 4de338a1..f0b1a84b 100644 --- a/src/pulse/thread-mainloop.h +++ b/src/pulse/thread-mainloop.h @@ -108,10 +108,10 @@ PA_C_DECL_BEGIN   * Example:   *   * \code - * static void my_drain_callback(pa_stream*s, int success, void *userdata) { + * static void my_drain_callback(pa_stream *s, int success, void *userdata) {   *     pa_threaded_mainloop *m;   * - *     m = (pa_threaded_mainloop*)userdata; + *     m = userdata;   *     assert(m);   *   *     pa_threaded_mainloop_signal(m, 0); @@ -125,7 +125,7 @@ PA_C_DECL_BEGIN   *     o = pa_stream_drain(s, my_drain_callback, m);   *     assert(o);   * - *     while (pa_operation_get_state(o) != OPERATION_DONE) + *     while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)   *         pa_threaded_mainloop_wait(m);   *   *     pa_operation_unref(o); @@ -167,7 +167,7 @@ PA_C_DECL_BEGIN   * static void my_drain_callback(pa_stream*s, int success, void *userdata) {   *     pa_threaded_mainloop *m;   * - *     m = (pa_threaded_mainloop*)userdata; + *     m = userdata;   *     assert(m);   *   *     drain_result = &success; @@ -183,7 +183,7 @@ PA_C_DECL_BEGIN   *     o = pa_stream_drain(s, my_drain_callback, m);   *     assert(o);   * - *     while (pa_operation_get_state(o) != OPERATION_DONE) + *     while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)   *         pa_threaded_mainloop_wait(m);   *   *     pa_operation_unref(o); diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index 515d1f90..94064c72 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -160,6 +160,9 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {      c->userdata = NULL;      c->set_profile = NULL; +    pa_device_init_description(c->proplist); +    pa_device_init_icon(c->proplist, TRUE); +      pa_assert_se(pa_idxset_put(core->cards, c, &c->index) >= 0);      pa_log_info("Created %u \"%s\"", c->index, c->name); diff --git a/src/pulsecore/ffmpeg/resample2.c b/src/pulsecore/ffmpeg/resample2.c index ed59448a..ac9db73c 100644 --- a/src/pulsecore/ffmpeg/resample2.c +++ b/src/pulsecore/ffmpeg/resample2.c @@ -20,7 +20,7 @@   */  /** - * @file resample2.c + * @file libavcodec/resample2.c   * audio resampling   * @author Michael Niedermayer <michaelni@gmx.at>   */ @@ -175,10 +175,6 @@ void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_coun  #endif  } -/** - * Initializes an audio resampler. - * Note, if either rate is not an integer then simply scale both rates up so they are. - */  AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff){      AVResampleContext *c= av_mallocz(sizeof(AVResampleContext));      double factor= FFMIN(out_rate * cutoff / in_rate, 1.0); @@ -206,33 +202,12 @@ void av_resample_close(AVResampleContext *c){      av_freep(&c);  } -/** - * Compensates samplerate/timestamp drift. The compensation is done by changing - * the resampler parameters, so no audible clicks or similar distortions occur - * @param compensation_distance distance in output samples over which the compensation should be performed - * @param sample_delta number of output samples which should be output less - * - * example: av_resample_compensate(c, 10, 500) - * here instead of 510 samples only 500 samples would be output - * - * note, due to rounding the actual compensation might be slightly different, - * especially if the compensation_distance is large and the in_rate used during init is small - */  void av_resample_compensate(AVResampleContext *c, int sample_delta, int compensation_distance){  //    sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensation_distance / c->ideal_dst_incr;      c->compensation_distance= compensation_distance;      c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance;  } -/** - * resamples. - * @param src an array of unconsumed samples - * @param consumed the number of samples of src which have been consumed are returned here - * @param src_size the number of unconsumed samples available - * @param dst_size the amount of space in samples available in dst - * @param update_ctx if this is 0 then the context wont be modified, that way several channels can be resampled with the same context - * @return the number of samples written in dst or -1 if an error occurred - */  int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx){      int dst_index, i;      int index= c->index; diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 7441e971..fadbb857 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -33,6 +33,7 @@  #include <pulse/xmalloc.h>  #include <pulse/timeval.h>  #include <pulse/util.h> +#include <pulse/i18n.h>  #include <pulsecore/sink-input.h>  #include <pulsecore/namereg.h> @@ -172,6 +173,9 @@ pa_sink* pa_sink_new(      if (data->card)          pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist); +    pa_device_init_description(data->proplist); +    pa_device_init_icon(data->proplist, TRUE); +      if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {          pa_xfree(s);          pa_namereg_unregister(core, name); @@ -1886,3 +1890,68 @@ size_t pa_sink_get_max_request(pa_sink *s) {      return r;  } + +/* Called from main context */ +pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink) { +    const char *ff, *t = NULL, *s = "", *profile, *bus; + +    pa_assert(p); + +    if (pa_proplist_contains(p, PA_PROP_DEVICE_ICON_NAME)) +        return TRUE; + +    if ((ff = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) { + +        if (pa_streq(ff, "microphone")) +            t = "audio-input-microphone"; +        else if (pa_streq(ff, "webcam")) +            t = "camera-web"; +        else if (pa_streq(ff, "computer")) +            t = "computer"; +        else if (pa_streq(ff, "handset")) +            t = "phone"; +    } + +    if (!t) { +        if (is_sink) +            t = "audio-card"; +        else +            t = "audio-input-microphone"; +    } + +    if ((profile = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) { +        if (strstr(profile, "analog")) +            s = "-analog"; +        else if (strstr(profile, "iec958")) +            s = "-iec958"; +        else if (strstr(profile, "hdmi")) +            s = "-hdmi"; +    } + +    bus = pa_proplist_gets(p, PA_PROP_DEVICE_BUS); + +    pa_proplist_setf(p, PA_PROP_DEVICE_ICON_NAME, "%s%s%s%s", t, pa_strempty(s), bus ? "-" : "", pa_strempty(bus)); + +    return TRUE; +} + +pa_bool_t pa_device_init_description(pa_proplist *p) { +    const char *s; +    pa_assert(p); + +    if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION)) +        return TRUE; + +    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 TRUE; +        } + +    if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_NAME))) { +        pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s); +        return TRUE; +    } + +    return FALSE; +} diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 124b4e11..2eaae697 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -225,6 +225,9 @@ void pa_sink_attach(pa_sink *s);  void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume); +pa_bool_t pa_device_init_description(pa_proplist *p); +pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink); +  /**** May be called by everyone, from main context */  /* The returned value is supposed to be in the time domain of the sound card! */ diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index c0d6d9ea..4ce5cbfe 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -163,6 +163,9 @@ pa_source* pa_source_new(      if (data->card)          pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist); +    pa_device_init_description(data->proplist); +    pa_device_init_icon(data->proplist, FALSE); +      if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) {          pa_xfree(s);          pa_namereg_unregister(core, name);  | 
