FreeBSD nos permite cambiar de dispositivo de audio fácilmente mediante el comando “sysctl hw.snd.default_unit” tan solo debemos consultar los dispositivos disponibles:
pcm0: <Intel Haswell (HDMI/DP 8ch)> (play)
pcm1: <Realtek ALC292 (Analog 2.0+HP/2.0)> (play/rec) default
pcm2: <Realtek ALC292 (Internal Analog Mic)> (rec)
pcm3:
Installed devices from userspace:
Y realizar la asignación pertinente:
El problema de este método es que cada vez que cambiemos de dispositivo tendremos que reiniciar las aplicaciones abiertas para que relean el dispositivo de audio nuevo.
Para evitar dicho inconveniente podemos utilizar virtual_oss, un servicio que multiplexa y demultiplexa dispositivos de audio, la idea es que las aplicaciones siempre abran el dispositivo creado por virtual_oss pero que este realice el enrutado al dispositivo final.
Instalamos virtual_oss:
Habilitamos el servicio:
Configuramos los parámetros de virtual_oss, en mi caso se trata de un portátil donde los altavoces son el dispositivo pcm1 que equivale a dsp1:
-T devname Install entry in /dev/sndstat
-C num Set the maximum number of mix channels to num.
-c num Set mix channels for the subsequent commands.
-S Enable automatic DSP rate resampling.
-i priority Set real-time priority to priority. Refer to rtprio(1) for more information.
Priority is an integer between 0 and RTP_PRIO_MAX (usually 31). 0 is the highest priority 31 the lowest.
-r rate Set default sample-rate for the subsequent commands.
-b bits Set sample depth to bits for the subsequent commands. Valid values are 8, 16, 24 and 32.
-s value Set default buffer size to value. If the argument is suffixed by "ms" it is interpreted as milliseconds.
Else the argument gives number of samples. The buffer size specified is per channel. If there are multiple
channels, the total buffer size will be larger.
-f devname Set both playback and recording DSP device
-d name Create an OSS device by given name.
-t devname Set control device name.
Los dispositivos de audio tanto de entrada como de salida se pueden definir con un solo parámetro:
-f devname Set both playback and recording DSP device
O de forma independiente:
-P devname Set playback DSP device only. Specifying /dev/null is magic and
means no playback device. Specifying a sndio(7) device
descriptor prefixed by "/dev/sndio/" is also magic, and will use
a sndio backend rather than an OSS device.
-R devname Set recording DSP device only. Specifying /dev/null is magic and
means no recording device.
Arrancamos el servicio:
Consultamos los dispositivos disponibles y vemos que hay uno mas en la sección userspace:
Installed devices:
pcm0: <Intel Haswell (HDMI/DP 8ch)> (play)
pcm1: <Realtek ALC292 (Analog 2.0+HP/2.0)> (play/rec) default
pcm2: <Realtek ALC292 (Internal Analog Mic)> (rec)
pcm3: <USB audio> (play/rec)
Installed devices from userspace:
dsp: <Virtual OSS> (play/rec)
Lo ideal llegados a este punto serÃa cerrar las X para asegurarnos de que todas las aplicaciones utilicen el dispositivo creado por virtual_oss.
Ahora si queremos hacer un cambio en caliente a los auriculares USB por ejemplo tan solo debemos indicar el dsp correcto:
Para revertir a los altavoces:
Un script que puede resultarnos útil es el siguiente:
#!/usr/bin/env bash
grep 'Virtual OSS' /dev/sndstat 1>/dev/null
if [ $? -eq 0 ]; then
VIRTUAL_OSS_DETECTED=1
else
VIRTUAL_OSS_DETECTED=0
fi
LAST_DEVICE=$(grep pcm /dev/sndstat | awk -F ":" '{print$1}' | awk -F "pcm" '{print$2}' | tail -n1)
#echo "LAST_DEVICE: $LAST_DEVICE"
for NEXT_DEVICE in $(grep pcm /dev/sndstat | awk -F ":" '{print$1}' | awk -F "pcm" '{print$2}'); do
#echo "NEXT_DEVICE: $NEXT_DEVICE"
if [ $VIRTUAL_OSS_DETECTED -eq 1 ]; then
CURRENT_DEVICE=$(virtual_oss_cmd /dev/dsp.ctl|grep 'Output device name' | awk -F "/dev/dsp" '{print$2}')
else
CURRENT_DEVICE=$(grep default /dev/sndstat | awk -F ":" '{print$1}' | awk -F "pcm" '{print$2}')
fi
#echo "CURRENT_DEVICE: $CURRENT_DEVICE"
if [ $NEXT_DEVICE -le $CURRENT_DEVICE ] && [ $NEXT_DEVICE -ne $LAST_DEVICE ]; then
#echo "Continue"
continue
else
if [ $CURRENT_DEVICE -eq $LAST_DEVICE ] && [ $NEXT_DEVICE -eq $LAST_DEVICE ]; then
NEXT_DEVICE=0
#echo "NEXT_DEVICE: $NEXT_DEVICE"
fi
DEVICE_NAME=$(grep pcm$NEXT_DEVICE /dev/sndstat | awk -F "<" '{print$2}' | awk -F ">" '{print$1}')
if [ $VIRTUAL_OSS_DETECTED -eq 1 ]; then
virtual_oss_cmd /dev/dsp.ctl -f /dev/dsp$NEXT_DEVICE
else
sysctl hw.snd.default_unit=$NEXT_DEVICE
fi
if [ $? -eq 0 ]; then
notify-send "Audio device changed: PCM$NEXT_DEVICE: $DEVICE_NAME"
break
else
notify-send "Error changing audio device, reverting"
if [ $VIRTUAL_OSS_DETECTED -eq 1 ]; then
virtual_oss_cmd /dev/dsp.ctl -f /dev/dsp$CURRENT_DEVICE
else
sysctl hw.snd.default_unit=$CURRENT_DEVICE
fi
fi
fi
done