Después de pasar demasiadas horas tratando de encontrar la causa root de por qué esto estaba sucediendo, me di por vencido y escribí un shell script.
En primer lugar, necesitamos una forma de encontrar y cambiar los dispositivos de audio desde la línea de comandos. Por suerte, el desarrollador Deweller hizo una pequeña utilidad para hacer exactamente eso: https://github.com/deweller/switchaudio-osx . Se puede instalar a través de Homebrew o MacPorts si tiene alguno de los dos instalados; alternativamente, descargue el Intel o Silicio de Apple binario de MacPorts directamente, y copiar switchaudiosource
en /usr/local/bin
debería funcionar tal cual, sin dependencias.
Escribí el siguiente script, que quiero que se ejecute cada 1-2 segundos. Usted querrá editar los nombres de speakerA
y SpeakerB
.
#!/bin/bash
speakerA="SRS-XB12"
speakerB="Built-in Output"
if ! cat /tmp/audioSwitcherSavedState.txt
then
switchaudiosource -a | grep $speakerA && echo "connected" > /tmp/audioSwitcherSavedState.txt || echo "disconnected" > /tmp/audioSwitcherSavedState.txt
elif [ "$(cat /tmp/audioSwitcherSavedState.txt)" == "disconnected" ] && switchaudiosource -a | grep $speakerA
then
echo "connected" > /tmp/audioSwitcherSavedState.txt
for device in {output,system}
do
SwitchAudioSource -t "$device" -s "$speakerA"
done
osascript -e 'if application "QuickTime Player" is not running then return' -e 'tell application "QuickTime Player"' -e 'repeat with i from 1 to count of every document' -e 'if document i is playing and duration of document i > 0 then set current time of document i to (current time of document i) - 5' -e 'end repeat' -e 'end tell'
elif [ "$(cat /tmp/audioSwitcherSavedState.txt)" == "connected" ] && ! switchaudiosource -a | grep $speakerA
then
echo "disconnected" > /tmp/audioSwitcherSavedState.txt
for device in {output,system}
do
SwitchAudioSource -t "$device" -s "$speakerB"
done
osascript -e 'if application "QuickTime Player" is not running then return' -e 'tell application "QuickTime Player"' -e 'repeat with i from 1 to count of every document' -e 'if document i is playing and duration of document i > 0 then set current time of document i to (current time of document i) - 8' -e 'end repeat' -e 'end tell'
fi
Este script hace lo siguiente:
- Si aún no existe, cree un archivo de texto temporal que registre si
speakerA
está conectado al Mac.
- Si
speakerA
estaba previamente desconectada, y ahora está conectada, cambie a speakerA
.
- Si
speakerA
estaba conectada anteriormente, y ahora está desconectada, cambie a SpeakerB
(mis altavoces internos).
- En cualquiera de los dos casos anteriores, también actualizamos el archivo temporal, por lo que el código sólo se ejecutará una vez por conexión o desconexión. Y, si Quicktime está reproduciendo algún audio en ese momento, rebobinaremos el archivo unos segundos para que no se pierda nada mientras se cambian los dispositivos.
Para que este script fuera útil, necesitaba que se ejecutara una vez cada dos segundos, así que lo convertí en un LaunchAgent. Decidí que quería que esto viviera como un archivo único y autocontenido, así que puse todo el código en una sola línea (ilegible) y lo volqué directamente en mi plist de LaunchAgent. Tenga en cuenta que debido a que los LaunchAgents necesitan conocer la ruta completa de la mayoría de los binarios, este LaunchAgent asume que el switchaudiosource
binario vive en /usr/local/bin/
.
<!--
Changes audio output device to "SRS-XB12" when a device by that name
is connected; changes audio output device back to "Built-in Output"
when a device named "SRS-XB12" is disconnected. Edit these names to
whatever is appropriate for your sound setup.
Requires SwitchAudioSource to be present in /usr/local/bin/
-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>wowfunhappy.audio-switcher</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-c</string>
<string>speakerA="SRS-XB12" ; speakerB="Built-in Output" ; if ! cat /tmp/audioSwitcherSavedState.txt ; then /usr/local/bin/switchaudiosource -a | grep $speakerA && echo "connected" > /tmp/audioSwitcherSavedState.txt || echo "disconnected" > /tmp/audioSwitcherSavedState.txt ; elif [ "$(cat /tmp/audioSwitcherSavedState.txt)" == "disconnected" ] && /usr/local/bin/switchaudiosource -a | grep $speakerA ; then echo "connected" > /tmp/audioSwitcherSavedState.txt ; for device in {output,system} ; do /usr/local/bin/SwitchAudioSource -t "$device" -s "$speakerA" ; done ; /usr/bin/osascript -e 'if application "QuickTime Player" is not running then return' -e 'tell application "QuickTime Player"' -e 'repeat with i from 1 to count of every document' -e 'if document i is playing and duration of document i > 0 then set current time of document i to (current time of document i) - 5' -e 'end repeat' -e 'end tell' ; elif [ "$(cat /tmp/audioSwitcherSavedState.txt)" == "connected" ] && ! /usr/local/bin/switchaudiosource -a | grep $speakerA ; then echo "disconnected" > /tmp/audioSwitcherSavedState.txt ; for device in {output,system} ; do /usr/local/bin/SwitchAudioSource -t "$device" -s "$speakerB" ; done ; /usr/bin/osascript -e 'if application "QuickTime Player" is not running then return' -e 'tell application "QuickTime Player"' -e 'repeat with i from 1 to count of every document' -e 'if document i is playing and duration of document i > 0 then set current time of document i to (current time of document i) - 8' -e 'end repeat' -e 'end tell' ; fi</string>
</array>
<key>LimitLoadToSessionType</key>
<array>
<string>Aqua</string>
</array>
<key>ProcessType</key>
<string>Background</string>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>1</integer>
</dict>
</plist>
Guarde lo anterior como ~/Library/LaunchAgents/wowfunhappy.audio-switcher.plist
y cerrar la sesión y volver a entrar, y el audio debería cambiar automáticamente.