Instalando pulseaudio en Debian Jessie

Me había resistido hasta el momento, pero al final no me ha quedado más remedio que instalar pulseaudio si quería usar un headset bluetooth que me habían regalado. BlueZ 5 (que es la versión que viene empaquetada en Debian Jessie) no trae soporte para ALSA, así que la única opción que me quedaba era arremangarme e instalar el servidor de audio fruto de la calenturienta mente de Lennart Poettering.

Hay un segmento de la comunidad del software libre que ha convertido a Poettering en una especie de supervillano que conspira en la sombra con el objetivo de destruir <inserte aquí su distribución favorita>. A mí me parece simplemente un mediocre diseñador de software, o al menos es lo que me ha demostrado con ese pedazo de mierda que es Avahi1.

A pulseaudio le precede su fama de dejar infinidad de sistemas sin sonido, de tener un pésimo rendimiento e introducir lag y de ser críptico en sus opciones y escasamente documentado. Lo que no he visto son críticas sobre sus pésimas decisiones arquitectónicas: un demonio de usuario que hay que mantener constantemente bajo supervisión para que no se muera y nos deje sin sonido. No deja de ser irónico que esos mismos diseñadores ahora pretendan convertir otro demonio del sistema (D-Bus) en un API del kernel Linux (kdbus), cuando con el sonido han hecho precisamente lo opuesto: sustituir un API del kernel (ALSA) por un demonio (pulseaudio), encima en espacio de usuario.

Puedo entender que se haya tenido que introducir una capa adicional en la pila de sonido, ya que había elementos que formaban parte de ésta y sin embargo, al no están bajo el paraguas de ALSA sino de otros drivers (como unos altavoces USB o mi propio caso de unos headphones bluetooth), no estaban integrados con el resto. Previamente, para solucionarlo, cada uno utilizaba su propio "pegamento", que variaba desde simples scripts hasta los complejos demonios con capacidad de hacer streaming de sonido por la red que formaban parte de algunos escritorios.

Reunir todos esos pedazos en una única solución definitiva y estándar es un loable objetivo, pero donde parece fallar pulseaudio es en la implementación de dicho objetivo. La que debería ser una capa sencilla y sobre todo ligera se convierte en algo complejo y pesado por culpa de la sobreingeniería. Pretender hacerlo todo y cubrir todos los casos imaginables ha conducido a un software difícil de configurar y con enorme propensión a fallar. Por eso no es extraño que tanto el software en sí como su principal autor tengan tan mala prensa.

La experiencia más habitual es la de una persona cuyo sonido está funcionando bien con ALSA y que al tratar de migrar a pulseaudio se encuentra con una variada colección de problemas, algunas veces menores pero molestos, y otras veces en las que directamente no les funciona el sonido. Mi experiencia no ha sido muy diferente.

Pero empecemos por el principio, instalando los paquetes pulseaudio y pavucontrol:

# aptitude --without-recommends install pulseaudio pavucontrol
Se instalarán los siguiente paquetes NUEVOS:     
  libasound2-plugins{a} libfftw3-single3{a} libpulsedsp{a} libspeexdsp1{a} libwebrtc-audio-processing-0{a}
  pavucontrol pulseaudio pulseaudio-utils{a} 
Se RECOMIENDAN los siguientes paquetes, pero NO se instalarán:
  pulseaudio-module-x11 rtkit

Aun intentando instalar sin recomendaciones, podéis observar que pulseaudio tiene tendencia al bloatware2 e instala por dependencias bibliotecas adicionales3 que no sé muy bien qué pintan ahí.

Ahora deberíais comprobar que vuestras aplicaciones de sonido funcionan: reproductor de MP3, de video, etc. Además, para gestionar pulseaudio, la herramienta que recomiendan utilizar a día de hoy es pavucontrol. En documentación antigua encontraréis referencias a otras herramientas que están obsoletas, pero que por alguna razón se siguen incluyendo en Debian.

Pestaña de salidas de pavucontrol

Aquí me topé con mi primer problema: la pantalla de pavucontrol se quedaba congelada en un fondo gris tras un instante inicial donde aparecían brevísimamente los controles. Tras revisar los logs me encuentro esto:

pulseaudio[4263]: [pulseaudio] source.c: Assertion '(default_rate % 4000 == 0) || (default_rate % 11025 == 0)' failed at pulsecore/source.c:1016, function pa_source_update_rate(). Aborting.
pulseaudio[4996]: [pulseaudio] pid.c: Stale PID file, overwriting.
pulseaudio[4996]: [pulseaudio] source.c: Assertion '(default_rate % 4000 == 0) || (default_rate % 11025 == 0)' failed at pulsecore/source.c:1016, function pa_source_update_rate(). Aborting.
pulseaudio[5004]: [pulseaudio] pid.c: Stale PID file, overwriting.
pulseaudio[5004]: [pulseaudio] source.c: Assertion '(default_rate % 4000 == 0) || (default_rate % 11025 == 0)' failed at pulsecore/source.c:1016, function pa_source_update_rate(). Aborting.
pulseaudio[5012]: [pulseaudio] pid.c: Stale PID file, overwriting.
pulseaudio[5012]: [pulseaudio] source.c: Assertion '(default_rate % 4000 == 0) || (default_rate % 11025 == 0)' failed at pulsecore/source.c:1016, function pa_source_update_rate(). Aborting.
pulseaudio[5020]: [pulseaudio] pid.c: Stale PID file, overwriting.
pulseaudio[5020]: [pulseaudio] source.c: Assertion '(default_rate % 4000 == 0) || (default_rate % 11025 == 0)' failed at pulsecore/source.c:1016, function pa_source_update_rate(). Aborting.
pulseaudio[5028]: [pulseaudio] pid.c: Stale PID file, overwriting.
pulseaudio[5028]: [pulseaudio] source.c: Assertion '(default_rate % 4000 == 0) || (default_rate % 11025 == 0)' failed at pulsecore/source.c:1016, function pa_source_update_rate(). Aborting.
...

(Sólo he puesto unas pocas líneas, pero el log sigue con decenas de repeticiones de la misma secuencia)

Lo que estamos viendo aquí es que el proceso de pulseaudio se está muriendo continuamente, pero a la vez es vuelto a levantar por su supervisor (de ahí los diferentes PIDs entre corchetes y el mensaje de Stale PID file, overwriting. que es que el nuevo proceso ha encontrado un fichero con el PID del antiguo) en un ciclo sin fin. Y esto se produce únicamente cuando se lanza pavucontrol, que al intentar hablar con el demonio provoca su muerte, y se queda con la pantalla en gris mientras intenta reestablecer contacto, algo que sólo consigue cuando la nueva instancia del demonio se encuentra finalmente disponible.

La cuestión es ¿por qué está muriendo el proceso pulseaudio? ¿Y qué es ese extraño mensaje sobre una aserción fallida?:

Assertion '(default_rate % 4000 == 0) || (default_rate % 11025 == 0)' failed at pulsecore/source.c:1016, function pa_source_update_rate(). Aborting.

Conseguí encontrar un bug, el #777178 dónde parecía que alguien tenía un problema muy similar. Por desgracia, no aclaraba nada, excepto que el problema podía estar solucionado en pulseaudio 6.0 (que salió después del freeze de Jessie y por lo tanto no está disponible en la versión estable). Así que tocó tirar de código fuente, y buscar el origen del mensaje y su posible significado.

El texto del mensaje me llevó a esta línea en el código fuente de pulseaudio 5.0. Esa línea es una aserción que controla que la variable default_rate sólo tenga valores que sean divisibles por 4000 o 11025. Sea lo que sea lo que lo provocaba, ¡pulseaudio estaba muriéndose por una aserción! Para los que seais profanos, os explico que las aserciones se utilizan para indicar condiciones "imposibles" en un programa. Los programadores las utilizamos cuando estamos depurando un programa o probándolo, para encontrar errores que se nos pueden haber escapado. En producción, normalmente los programas no vienen con las aserciones activadas ya que una sóla aserción incumplida hace que todo el programa termine brusca e inmediatamente.

El mero hecho de usar aserciones, en vez de condiciones y controlar los errores, ya me indicaba una programación descuidada y perezosa. Pero es que además recordemos el contexto: estamos hablando de un proceso que es tan importante que esté funcionando de contínuo que incluso lleva un mecanismo de supervisión para garantizarlo. Emplear algo tan burdo como una aserción en un entorno de ese tipo es una auténtica chapuza.

Classic Facepalm

Otros programadores debían estar de acuerdo con mi valoración, porque este commit posterior —incluido a partir de pulseaudio 6.0— eliminaba las aserciones. En el mensaje del commit se indica:

This fixes assertion failures that manifest themselves with cards
that support only weird rates such as 37286Hz. Tested with snd-pcsp.

Fijaos la salvajada de usar una aserción con una variable cuyo valor proviene del exterior (no algo interno al programa), y que por lo tanto no se controla. Es un despropósito total.

El commit anterior además apuntaba al bug 48109 del bugzilla de pulseaudio, titulado "pulseaudio-1.99.2 doesn't like snd-pcsp". Eso me puso tras la pista del módulo del kernel snd-pcsp, que viene por defecto en los kernels empaquetados por Debian y que yo también tengo seleccionado en mi .config por el mismo motivo. Os voy a incluir el texto de la ayuda de la opción CONFIG_SND_PCSP, que es la que incluye este módulo en el kernel:

CONFIG_SND_PCSP:

  If you don't have a sound card in your computer, you can include a
  driver for the PC speaker which allows it to act like a primitive
  sound card. This driver also replaces the pcspkr driver for beeps.

  You can compile this as a module which will be called snd-pcsp.

  WARNING: if you already have a soundcard, enabling this
  driver may lead to a problem. Namely, it may get loaded
  before the other sound driver of yours, making the
  pc-speaker a default sound device. Which is likely not
  what you want. To make this driver play nicely with other
  sound driver, you can add this in a configuration file under
  /etc/modprobe.d/ directory: options snd-pcsp index=2

  You don't need this driver if you only want your pc-speaker to beep.
  You don't need this driver if you have a tablet piezo beeper
  in your PC instead of the real speaker.

  Say N if you have a sound card.
  Say M if you don't.
  Say Y only if you really know what you do.

Este módulo emula una "tarjeta de sonido" usando el beep de la placa base4. Pero, como dice el texto anterior, no hay que activar la opción si se tiene una tarjeta de sonido, porque de lo contrario lo único que se consigue son problemas. Como ha sido mi caso, al reportar un valor inesperado que ha provocado el mal funcionamiento de pulseaudio. La gente de Debian Kernel debería revisar su política de incluir este módulo5, porque es totalmente problemático con la gran mayoría de las configuraciones actuales que llevan tarjeta de sonido de serie, y tampoco aporta nada a los que no la tienen.

Resumiendo, el problema se puede solucionar actualizando a pulseaudio 6.0, que ya trae el código corregido. Sin embargo, esta opción no es recomendable con carácter general hasta que dicha versión esté disponible a través de backports, ya que implicaría instalar un paquete de testing en stable. La otra posibilidad es deshabilitar el módulo del kernel snd-pcsp, bien sea haciendo blacklist del módulo o quitándolo directamente de la configuración en un kernel compilado a medida.

Este ha sido el problema más serio con pulseaudio, pero no el único. Todavía me quedan algunos "flecos" que solucionar:

  • El botón multimedia de mute no funciona correctamente cuando tiene que realizar la función de "unmute". Por lo que he podido ver en el ALSA mixer, al pulsarlo se hace mute del maestro y de dos canales más, pero al volverlo a pulsar sólo se hace unmute del maestro, por lo que el sonido no vuelve. Es una molestia tener que abrir el ALSA mixer para reactivar estos canales.
  • Tampoco me funcionan los botones multimedia de subir/bajar volumen cuando está activo el sonido a través de los cascos bluetooth.

Pero, como en realidad no he llegado a investigarlos, tampoco quiero llegar a conclusiones y echarle la culpa a pulseaudio sin más: bien podría ser una deficiencia del soporte de pulseaudio de Xfce, o simplemente que me falte algún paquete por instalar (que no sería la primera vez).

:wq


  1. y que aun no he sido capaz de erradicar totalmente de mi sistema 

  2. no os enseño el grafo completo de dependencias porque fliparíais... 

  3. y que si desinstaláis, es probable que tengáis que borrar manualmente 

  4. si sois jóvenes es posible que no sepáis de lo que estoy hablando 

  5. por mi parte también debería revisar cuidadosamente las opciones de compilación del subsistema de sonido de mi configuración del kernel 

blogroll

social