* Imagenes de instalación de las versiones estables para Mageia y OpenMandriva.

OpenMandriva: Mageia (Mageia 9) 20/Agosto/2023 - Anuncio, Descargas.

Blogdrake recomienda descargar las imágenes de instalación (iso) vía torrent para evitar corrupción de datos, aprovechar mejor su ancho de banda y mejorar la difusión de las distribuciones.

Reenvío del sonido entre ordenadores

Sí, Pulseaudio es malísimo. Hay quien afirma que incluso mató a su gato y violó a su perro. Pero aquí estoy yo, afirmando que Pulseaudio no sólo no es tan malo (al menos, ahora), sino que tiene virtudes muy interesantes.

Espera, ¿que no sabes qué es PulseAudio? Bueno, pues PulseAudio es un servidor de sonido. Digamos que las aplicaciones le pasan los datos de sonido que generan a PulseAudio, y éste decide qué hacer con esos datos: enviarlo a una u otra tarjeta de sonido, mezclarlo con otros sonidos, cambiar el volumen, enviarlo a otro servidor de PulseAudio en otro ordenador...

La que nos interesa aquí es que permite que el sonido se reproduzca en otro ordenador distinto al ordenador en el que se genera. Vamos, que tú estás delante de un ordenador, ejecutas un reproductor de música en otro ordenador por SSH y la música suena en el ordenador que tienes delante.

Así que veamos cómo usar Pulseaudio para conseguir tan interesante característica.

Configuración de PulseAudio

Para empezar, aunque ya debería estar hecho si se está siguiendo el manual, para el correcto funcionamiento del reenvío de sonido mediante Pulseaudio es imprescindible que cada ordenador tenga un nombre propio diferenciado. Cuando PulseAudio envía los datos desde un ordenador a otro utiliza el nombre del ordenador destino para hacer llegar el sonido. Si ambos se llaman "localhost", se envía los datos a sí mismo en lugar de al otro ordenador (porque "está más cerca", por decirlo de algún modo). Al ponerles un nombre diferenciado ya envía el sonido donde debe.

También es necesario que el nombre del equipo asociado a 127.0.0.1 sea el correcto (lo explicado anteriormente del orden de los nombres en el fichero /etc/hosts), ya que es lo que utiliza PulseAudio.

Como es lógico, para que todo esto funcione, necesitamos tener activado PulseAudio tanto en el ordenador que envía el sonido como en el que lo recibe. Si no estuviese activado no tenemos más que ejecutar, como root, draksound y habilitarlo.

Lo siguiente sólo es necesario hacerlo en el ordenador que vaya a recibir el sonido. Es decir, si desde el ordenador A nos conectamos por SSH al ordenador B y en este ejecutamos una aplicación, lo siguiente debe hacerse en el ordenador A. En el ordenador que envía el sonido no hay que modificar nada. Aunque lógicamente, si desde B también nos conectamos por SSH a A, también deberemos hacerlo en B.

Para que PulseAudio reciba el audio por SSH desde el ordenador remoto, simplemente hay que abrir las propiedades de PulseAudio (como usuario, ejecutar la aplicación paprefs) y marcar (a partir de Mandriva 2010.0, en la pestaña Servidor de Red) Habilitar el acceso desde la red a dispositivos de sonido locales. Esto debe habilitarse en cada usuario que vaya a utilizar aplicaciones remotas.

Es posible que modificando los módulos cargados al arrancar el demonio de Pulseaudio se consiga sin activar la recepción de datos remota para cada usuario que lo necesite. Además, parece que de ese modo puedes restringir las ips que tendrán acceso a los dispositivos de sonido locales (es decir, de las que se recibirán los datos).

Sin embargo, en el wiki de PulseAudio lo pone como "Obsoleto", aunque no sé si se refiere a que esos módulos están obsoletos, o que la aplicación PulseAudio Device Chooser está obsoleta y que en su lugar lo correcto es cargar los módulos :S No lo tengo nada claro, y dado que habilitándolo desde paprefs funciona correctamente, pues...

Cuando el sonido no se escucha

Todo esto está genial, ¿pero qué pasa si no escucho el sonido enviado por el ordenador remoto?

Asumiendo que PulseAudio está instalado en ambos ordenadores (lo cierto es que el ordenador remoto que envía el audio no necesita ni que haya un servidor de PulseAudio en ejecución), una forma de diagnosticar el problema es ejecutar en el ordenador que vaya a recibir el audio (el que tiene los altavoces donde lo queremos oír, vaya):

xprop -root | grep PULSE_SERVER

Si la configuración es correcta, nos devolverá algo como

PULSE_SERVER(STRING) = "{df7ee041b7c6698767f7afe64a21dfbd}unix:/home/dani/.pulse/df7ee041b7c6698767f7afe64a21dfbd:runtime/native tcp:HAL9004:4713 tcp6:HAL9004:4713"

Ojo al tcp:HAL9004:4713. En este ejemplo HAL9004 es el nombre que tiene mi ordenador cliente, cada cuál que espere el nombre que le puso a su ordenador cliente.

Si sale tcp:HAL9004:4713 pero no se oye nada (y ya se verificaron cosas como el volumen y demás), el problema seguramente sea debido a un cortafuegos. Para poder recibir el audio remoto, el puerto 4713 debe estar abierto en la interfaz de red por la que se transmiten los datos. Por ejemplo, en el entorno utilizado en este manual, el ordenador nuevo debería bien tener abierto el puerto 4713 en el cortafuegos de la interfaz de red eth1 (la que está conectada al ordenador viejo), bien no tener cortafuegos en la interfaz eth1.

Si en lugar del nombre de la máquina saliese localhost significaría que se puede recibir audio remoto, pero éste nunca llegaría ya que se reproduciría en la misma máquina que lo envía: el ordenador remoto mandaría el sonido a localhost, y el localhost más cercano a cualquier ordenador es él mismo (si tenemos un alias para 127.0.0.1 llamado localhost, claro). ¿Por qué puede ocurrir esto? Pues porque el nombre del equipo no se cambió correctamente (bien no se cambió en absoluto, bien se añadió el nombre deseado en /etc/hosts después de localhost en lugar de antes como se indicó anteriormente).

Si no sale nada relacionado con tcp, entonces no está activada la recepción de audio remoto. ¿Por qué puede ocurrir esto? Porque no habilitamos el acceso desde la red a dispositivos de sonido locales en el usuario con el que se está ejecutando PulseAudio (que, como ya se indicó, no tiene por qué ser el mismo con el que ejecutamos la orden anterior). O también porque tenemos más de un servidor de PulseAudio ejecutándose.

¿Cómo va a haber más de un servidor de PulseAudio ejecutándose? Pues si tenemos más de una sesión gráfica abierta. Cada vez que se abre una sesión gráfica de usuario, se lanza un servidor de PulseAudio que está activo hasta que se cierra dicha sesión. El problema está en que cuando un servidor de PulseAudio tiene activada la recepción remota se "apodera" del puerto de conexión a través del que se reciben los datos remotos. Si se ejecuta un segundo servidor en esa situación, éste no podrá utilizar el puerto de conexión, por lo que PULSE_SERVER(STRING) no contendrá la información de dicho puerto (es decir, no tendrá el tcp:HAL9004:4713). Cuando el servidor de PulseAudio remoto va a enviar los datos, se encuentra que no tiene información de a dónde debe enviarlo, por lo que el sonido acaba reproduciéndose en el ordenador remoto mismo.

Deafortunadamente, no sé cómo solucionar este problema, más allá de no abriendo varias sesiones gráficas de usuario cuando se va a acceder remotamente y se necesita el audio. En principio el problema se solucionaría si sólo se ejecutase un servidor de PulseAudio. Teóricamente esto es posible, ya que creo que el servidor de PulseAudio tiene una opción de ejecución global, y desde luego el sonido generado por las aplicaciones de un usuario puede ser manejado por el servidor de PulseAudio lanzado por otro usuario (ya que es lo que ocurre cuando en una sesión gráfica abrimos una sesión de consola con otro usuario). Peeero tampoco investigué mucho más cómo llevarlo a cabo. Así que si alguien quiere colaborar indicando cómo solucionarlo... ;)

Y si no es ninguna de las situaciones aquí expuestas, entonces ni idea, porque no me encontré con ese caso ;)

PulseAudio y SDL

En ocasiones, el sonido sonar suena, pero con chisporroteos o entrecortado. Si ocurre con todas las aplicaciones es posible que se pueda solucionar mediante draksound indicándole que NO utilice el modo Glitch-free. Al parecer el modo Glitch-free no se lleva nada bien con ciertos drivers de ALSA y causa que el sonido tenga los mencionados problemas.

Ahora, que si en la mayor parte de las aplicaciones el sonido está bien pero en algunas concretas es en las que se producen los cortes y el chisporroteo, entonces el problema puede ser que dichas aplicaciones utilizan la biblioteca SDL para el sonido (que a su vez puede usar ALSA, Esound, PulseAudio... Es una capa de abstracción para facilitar la vida a los desarrolladores de aplicaciones multimedia).

Aunque a priori uno podría pensar que sólo ocurriría con los juegos (que es para lo que se utiliza principalmente SDL), también puede suceder con otras aplicaciones como Kdenlive, el editor de vídeo de KDE. Y con Kdenlive fue con lo que me pasó a mí.

El problema viene de que Kdenlive utiliza el framework MLT para reproducir los vídeos, que a su vez utiliza SDL. SDL en la versión incluida en Mandriva 2009.1 no tiene driver para Pulseaudio, y por algún motivo que SDL saque el sonido por ALSA no le sienta nada bien a Pulseaudio (en un ordenador en que PulseAudio con ALSA funciona perfectamente, me refiero). Si, en cambio, se hace que SDL utilice el driver de Esound suena sin problemas... salvo en modo remoto, que no suena (pero veremos cómo hacer que suene ;) ).

Para cambiar el driver utilizado por SDL para el sonido, debe establecerse la variable SDL_AUDIODRIVER:

export SDL_AUDIODRIVER=esd

Si incluyésemos esa línea en el archivo .bashrc del usuario que vaya a ejecutar la aplicación que usa SDL para el sonido sería suficiente para que suene bien en local. Pero no lo hagas todavía, sigue leyendo.

Nosotros no nos conformamos con que suene bien en local. Queremos que suene bien en local, y en remoto. Como debe ser.

Y para que utilizando el driver esd (Esound) de SDL funcione bien en remoto tenemos que establecer la variable ESPEAKER al nombre del ordenador en que queremos que se reproduzca el sonido:

export ESPEAKER=HAL9004

donde HAL9004 es el nombre de la máquina deseada.

En la versión 1.2.12 de SDL incluyeron un driver para PulseAudio, por lo que en Mandriva 2010.0 no debería haber problema (debería funcionar de serie, incluido el sonido remoto, porque incluye SDL 1.2.13). A lo sumo, establecer el driver a pulse en lugar de a esd y estaría. Pero no... desafortunadamente el driver para PulseAudio de SDL en Mandriva 2010.0 sigue sonando bastante mal. El driver esd parece la única solución, al menos por ahora.

Enfrentándonos a Esound

Dado que tenemos que conformarnos con Esound para reenviar entre ordenadores el sonido de las aplicaciones que usan SDL para el sonido conviene extenderse un poco más en ello.

Lo primero que hay que tener en cuenta es que no es necesario arrancar ningún otro servidor de sonido. PulseAudio tiene un módulo de compatibilidad (que se carga por defecto) que actúa como servidor de Esound. Es decir, que aunque las aplicaciones digan "voy a enviar mi sonido a Esound", quien realmente se encarga de recibirlo es el propio PulseAudio.

Como dicho módulo de compatibilidad mimetiza tan bien el comportamiento de Esound, es necesario mencionar el archivo .esd_auth/home/nombreUsuario/.esd_auth leído por el servidor de PulseAudio al arrancar (donde nombreUsuario es el nombre del usuario que ejecuta el demonio de PulseAudio) es el mismo que el contenido del archivo /home/nombreUsuario/.esd_auth de la carpeta personal del usuario que ejecuta la aplicación que intenta reenviar el sonido.

Ahora veremos con más detalle este galimatías para intentar ayudar a su comprensión. Pero si después de leer los detalles sigues sin entender qué hay que hacer, quédate con esto: copia el archivo .esd_auth de un usuario concreto a todos los demás usuarios, tanto del ordenador local como del remoto (al final se indica un método sencillo para hacerlo). Y ahora, entremos en los farragosos detalles.

Cuando el servidor de PulseAudio arranca (por ejemplo, porque se entra en la sesión gráfica de un usuario) mira si en la carpeta personal del usuario que lanzó el servidor existe un archivo llamado .esd_auth. Si existe, lee su contenido y lo recuerda durante lo que dure su ejecución. Sino, lo crea con cierto valor y lo recuerda durante lo que dure su ejecución.

Ahora, establecemos la variable SDL_AUDIODRIVER a esd y ejecutamos una aplicación que use SDL para el sonido. El servidor de PulseAudio comprobará el contenido del archivo .esd_auth de la carpeta personal del usuario y lo comparará con el que tiene almacenado en su memoria. Si es el mismo, el sonido empezará a escucharse. Sino, silencio absoluto.

Esto quiere decir que si borramos el archivo .esd_auth mientras el servidor de PulseAudio está en ejecución, cuando una aplicación que use Esound intenet emitir sonido sólo habrá silencio.

No obstante, si no nos dedicamos a borrar dicho archivo el usuario que haya arrancado una sesión gráfica podrá escuchar el sonido sin problemas. Incluso si varios usuarios abren una sesión gráfica simultáneamente, el sonido enviado a Esound se escuchará sin problemas ya que cada sesión gráfica lanza su propio servidor de PulseAudio, que leerá o creará su propio archivo .esd_auth para cada usuario.

Peeero puede haber problemas igualmente. Supongamos que abrimos una única sesión gráfica de usuario con el usuario A. Desde dicha sesión gráfica, se abre una consola y se entra mediante "su - B" a una sesión de consola del usuario B. Como ya se comentó, las sesiones de consola sólo lanzan su propio servidor de PulseAudio si no hay ninguno disponible. Pero el servidor de PulseAudio de la sesion gráfica del usuario A está funcionando. En la sesión de consola del usuario B se establece SDL_AUDIODRIVER a esd y se ejecuta una aplicación que use SDL para el sonido. El resultado es silencio.

Como quien ejecuta la aplicación es el usuario B, el archivo .esd_auth de la carpeta personal del usuario B es /home/B/.esd_auth. Dicho archivo habrá sido creado por el servidor de PulseAudio lanzado por el usuario B cuando éste entró por primera vez en su sesión gráfica de usuario (y si dicho usuario nunca abrió una sesión gráfica, el archivo ni siquiera existirá). Sin embargo, ese archivo es distinto del que leyó el servidor de PulseAudio que va a reproducir ahora el sonido cuando arrancó, que será /home/A/.esd_auth, ya que recordemos que el servidor de PulseAudio se lanzó cuando el usuario A entró en su sesión gráfica.

Parece un caso muy específico y extraño, lo sé. Pero a mí me pasó :P

A pesar de todo, sirve para sentar las bases del problema que nos encontraremos al reenviar sonido entre ordenadores.

Supongamos que tenemos todo montado como se explicó en las partes anteriores de este manual, es decir, dos ordenadores interconectados cuyos usuarios se llaman igual en cada ordenador y pueden entrar por SSH en el ordenador remoto. Antes de llegar a tener todo correctamente funcionando, entramos en las sesiones gráficas de cada usuario en cada ordenador de manera local (vamos, sentados delante del ordenador). Al hacer eso, todos los directorios personales de los usuarios de cada ordenador tienen su propio archivo .esd_auth.

Da igual que los usuarios se llamen igual, el archivo /home/dani/.esd_auth del ordenador viejo es distinto del archivo /home/dani/.esd_auth del ordenador nuevo, ya que fueron creados por servidores de PulseAudio distintos. Y da igual que estén en el mismo ordenador, el archivo /home/dani/.esd_auth y el archivo /home/pruebassh/.esd_auth del ordenador viejo son distintos, ya que fueron creados por servidores de PulseAudio distintos. El servidor de PulseAudio que se ejecuta en una sesión de usuario de un ordenador es distinto de todos los demás (a efectos del archivo .esd_auth).

Creo que es fácil imaginarse cuál va a ser el problema. El usuario dani tiene abierta una sesión gráfica en el ordenador nuevo y entra por SSH al usuario dani del ordenador viejo. Establece SDL_AUDIODRIVER a esd y ESPEAKER al nombre del ordenador nuevo y ejecuta una aplicación que use SDL para el sonido. Exacto, silencio. No es que el sonido se reproduzca en el ordenador viejo en lugar del nuevo, es que no se reproduce en ningún sitio.

Y el motivo es el que te estás imaginando. El demonio de PulseAudio tiene en su memoria el archivo /home/dani/.esd_auth del ordenador nuevo que leyó al arrancar, y éste es distinto del archivo /home/dani/.esd_auth del ordenador viejo que es con el que se compara (ya que es el usuario dani del ordenador viejo el que ejecuta el programa).

¿Cómo saber si que no suenen las aplicaciones que usan SDL es un problema con el archivo .esd_auth? Buscando en los logs del sistema. Como root, podemos buscar en los logs mensajes que tengan que ver con esound de la siguiente manera:

find /var/log/ -exec grep -Hin "esound" {} \;

Esa orden buscará todos los archivos de /var/log y en cada uno de ellos buscará la cadena esound (sin distinguir mayúsculas y minúsculas), indicando el archivo y la línea en que lo encontró.

Si el problema está en el archivo .esd_auth seguramente encontraremos en /var/log/syslog, /var/log/messages y /var/log/user.log mensajes del tipo Kicked client with invalid authorization key. (expulsado cliente con clave de autorización inválida).

Además de que haya esos mensajes hay que fijarse que fuesen escritos más o menos cuando intentamos reproducir el sonido. Si el mensaje lo intentamos reproducir a las 15:16 del día 8 y resulta que el mensaje es /var/log/user.log:9115:Dec 4 23:42:15 HAL9004 pulseaudio[576]: protocol-esound.c: Kicked client with invalid authorization key., el mensaje no se corresponde con nuestro problema (ya que se escribió a las 23:42 del día 4).

Y si no hay mensajes de cliente expulsado puede que igualmente encontremos un mensaje que nos indique dónde está el problema. No obstante el único con el que yo me encontré fue el del archivo .esd_auth (pero me trajo de cabeza bastante tiempo hasta que encontré no sound from pulseaudio).

La configuración definitiva de Esound

Vale, genial, maravilloso, .esd_auth es el mal hecho archivo y debería ser erradicado. Pero hasta que eso ocurra, ¿qué hago para que PulseAudio reproduzca el sonido remoto con aplicaciones que usan SDL para el sonido?

Pues como ya indiqué, hacer que todos los usuarios de todos los ordenadores tengan el mismo archivo .esd_auth. ¿Y cómo hacer eso de manera fácil? Bien, seleccionemos un usuario que tenga un archivo .esd_auth, da lo mismo qué usuario sea, y distribuyamos su archivo. Para ello, ejecutamos las siguientes órdenes (como root) por cada usuario al que distribuir la clave:

cp -f /home/nombreUsuarioOrigen/.esd_auth /home/nombreUsuarioDestino/
chown nombreUsuarioDestino:nombreUsuarioDestino /home/nombreUsuarioDestino/.esd_auth
su - nombreUsuarioDestino -c "rsync .esd_auth nombreUsuarioDestino@nombreOrdenadorRemoto:~/"

La primera copia el archivo .esd_auth de la carpeta personal del usuario origen a la carpeta personal del usuario destino. La segunda cambia el propietario del archivo copiado para que sea el usuario destino. Y la tercera se convierte en el usuario destino y copia su clave en el mismo usuario del ordenador remoto indicado.

Para terminar, copiamos la clave del usuario origen del ordenador local al usuario remoto ejecutando como dicho usuario:

rsync .esd_auth nombreUsuarioOrigen@nombreOrdenadorRemoto:~/

Y listo, con esto el maldito archivo no debería volver a darnos problemas.

Para acabar, hasta ahora siempre hemos estado estableciendo las variables SDL_SOUNDDRIVER y ESPEAKER cuando eran necesarias. Eso, admitámoslo, es un engorro. Sería mucho mejor que se estableciesen automáticamente, ¿verdad?

Establecer SDL_AUDIODRIVER es trivial. Como ya se indicó, su valor siempre debe ser esd. Con establecerlo tal cuál al arrancar la sesión del usuario, sea gráfica o de consola, arreglado.

Pero ESPEAKER es el nombre de la máquina en la que queremos que suene el sonido... ¿Cómo saber cuál es? Pues utilizando la información del propio PulseAudio. Como se indicó anteriormente, PULSE_SERVER contiene, entre otras cosas, el nombre de la máquina en la que debe reproducirse el sonido. Utilizando la orden sed podemos extraer de todo el valor de PULSE_SERVER el que nos interesa:

export ESPEAKER=`xprop -root | grep PULSE_SERVER | sed "s/.*tcp:\([^:]*\).*/\1/"`

La expresión regular de sed dice lo siguiente: "de toda la cadena de texto que te pasen, quédate únicamente con el fragmento que está entre tcp: y el siguiente :.

Vale, ya sabemos el valor que tienen que tener ambas variables, ¿pero cómo hacemos que se establezcan automáticamente al arranca la sesión del usuario, sea gráfica o de consola?

Si quisiésemos establecerlo para un único usuario, podríamos hacerlo en el archivo .bashrc de la carpeta personal de dicho usuario. Pero lo que nos interesa es que todos los usuarios tengan correctamente establecidas esas variables, e ir modificando los .bashrc de cada usuario es un poco engorroso. Para eso está el directorio /etc/profile.d/.

El directorio /etc/profile.d/ contiene una serie de scripts, tanto para Bash (archivos .sh) como para C shell (archivos .csh), que se ejecutan para todos los usuarios cuando inician su sesión, sea gráfica o de consola. Bingo.

Simplemente tenemos que añadir un script que establezca dichas variables en el lenguaje del shell que utilicemos. Por ejemplo, todos mis usuarios usan Bash, así que yo tengo el archivo /etc/profile.d/esoundVariables.sh:

if [ $USER != "root" ]; then
    export SDL_AUDIODRIVER=esd
    if [ ! -z "$DISPLAY" ]; then
        export ESPEAKER=`xprop -root | grep PULSE_SERVER | sed "s/.*tcp:\([^:]*\).*/\1/"`
    fi
fi

Los permisos del archivo son lectura y escritura para root y lectura para el grupo y los demás (rw-r--r--, o 644 en octal). El archivo no necesita tener permisos de ejecución, ya que es leído/ejecutado desde otro script.

Pero un momento... ¡mentiroso! ¡Tramposo! ¡Rufián! ¡Ese script hace más cosas que establecer las variables! ¿Por qué?

Bien, por un lado, no tengo interés en que esas variables estén establecidas en el usuario root. No se me ocurre ningún buen motivo para que una aplicación que usa SDL para el sonido tenga que ejecutarse como root. Y como quiero un entorno de root lo más limpio y aseado posible, no lo contamino con variables innecesarias.

Y por otra parte, la variable ESPEAKER sólo se establece cuando la variable DISPLAY existe. ¿Y eso cuando es? Cuando estamos ejecutando algo en una sesión gráfica de usuario local, o bien estamos ejecutando algo en remoto por SSH desde una sesión gráfica local. O dicho de otra manera, si en el ordenador que estamos tenemos sesión gráfica, independientemente de dónde ejecutamos la aplicación.

El motivo de establecer la variable sólo en esa circunstancia se debe a que xprop -root, que devuelve las propiedades de la ventana raíz (por así decirlo, de la sesión gráfica) falla si no existe dicha sesión gráfica. No es que sea el fin del mundo si falla, pero si entramos en una sesión de consola (con Ctrl+Alt+F1 o similares) el mensaje de error queda feo ;) Además, si ESPEAKER no está establecido, el sonido se reproducirá en el ordenador local, como sería deseable en este caso.

Y dicho todo esto, qué ganas tengo de que SDL suene bien con PulseAudio por defecto y todo esto pase a ser historia de la informática ;)