This is a ridiculously involved workaround for a little bug in https://github.com/fredemmott/StreamDeck-AudioSwitcher that creates duplicate usb device entries after reboot.
Issue: https://github.com/fredemmott/StreamDeck-AudioSwitcher/issues/56
WARNING: Please back up your configurations before running any of this. Also note that when I was debugging the launch agent code, it would often freeze the OS and I would have to force restart often. However, now that it's running, it's quite stable.
Create script that will replace the device ID. Place it in /usr/local/bin.
/usr/local/bin/fix-audio-mapping.sh
#!/bin/bash
# For reference: https://dev.to/anesabml/autostart-scrcpy-on-device-connection-39a
# Prerequisites:
# brew install jq
# brew install switchaudio-osx
# Usage:
# Update vars
# STREAMDECK_PROFILE - path to your streamdeck profile manifest
# DEVICE_JSON_PATH - json path to the
# DEVICE_GREP_STR - a grep search for your usb device
# Will be searched like this:
# $ SwitchAudioSource -f json -a | grep -i SEARCHTERM
STREAMDECK_PROFILE="Users/justin/Library/Application Support/com.elgato.StreamDeck/ProfilesV2/A380B6A4-A474-4433-8AA5-C1AF5BFB5054.sdProfile/manifest.json"
DEVICE_JSON_PATH='.Actions."1,2".Settings.secondary'
DEVICE_GREP_STR='vanatoo'
jq() {
/opt/homebrew/bin/jq "$@"
}
export -f jq
SwitchAudioSource() {
/opt/homebrew/bin/SwitchAudioSource "$@"
}
export -f SwitchAudioSource
# Redirect std out to a log file
exec 1> ~/output.log 2>&1
date # To timestamp the run in the log
CURRENT_DEVICE=$(
cat "$STREAMDECK_PROFILE" | jq $DEVICE_JSON_PATH
)
DETECTED_DEVICE=$(
sleep 1
SwitchAudioSource -f json -a | grep -i $DEVICE_GREP_STR | jq '.uid="output/\(.uid)" | .uid'
)
echo "Detected"
echo $DETECTED_DEVICE
if [ -z "$DETECTED_DEVICE" ];
then
echo "Search device not found. Skipping..."
else
echo "Search device found!"
if [ "$DETECTED_DEVICE" == "$CURRENT_DEVICE" ];
then
echo "No change needed"
else
echo "Change needed!"
echo "Updating from"
echo $CURRENT_DEVICE
echo "to"
echo $DETECTED_DEVICE
killall Stream\ Deck
# Update the value
jq '. | .Actions."1,2".Settings.secondar = "testing"'
tmpfile=$(mktemp)
cat "$STREAMDECK_PROFILE" | jq ". | $DEVICE_JSON_PATH = $DETECTED_DEVICE" > ${tmpfile}
cp "$STREAMDECK_PROFILE" "$STREAMDECK_PROFILE.bak"
cat ${tmpfile} > "$STREAMDECK_PROFILE"
# The -g to not bring to foreground isn't respected for some reason
open -g /Applications/Stream\ Deck.app
fi
fi
Create a Launch Agent: This is run a command everytime a specific USB device is connected. I set this to run every time my speaker connection is detected.
~Library/LaunchAgents/com.streamdeck.audiofix.plist
<?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>com.streamdeck.audiofix</string>
<key>ProgramArguments</key>
<array>
<!--
For this first argument, see
https://dev.to/anesabml/autostart-scrcpy-on-device-connection-39a
https://github.com/himbeles/mac-device-connect-daemon
Summary:
git clone https://github.com/himbeles/mac-device-connect-daemon
gcc -framework Foundation -o xpc_set_event_stream_handler xpc_set_event_stream_handler.m
cp xpc_set_event_stream_handler /usr/local/bin/
-->
<string>/usr/local/bin/xpc_set_event_stream_handler</string>
<string>/usr/local/bin/fix-audio-mapping.sh</string>
</array>
<key>LaunchEvents</key>
<dict>
<key>com.apple.iokit.matching</key>
<dict>
<key>com.apple.device-attach</key>
<dict>
<key>idProduct</key>
<integer>18</integer> <!-- Determine with `ioreg -p IOUSB -l` -->
<key>idVendor</key>
<integer>3468</integer> <!-- Determine with `ioreg -p IOUSB -l` -->
<key>IOProviderClass</key>
<string>IOUSBDevice</string>
<key>IOMatchLaunchStream</key>
<true/>
</dict>
</dict>
</dict>
</dict>
</plist>
Load the launch agent:
launchctl load ~/Library/LaunchAgents/com.streamdeck.audiofix.plist
The script will now run and replace the usb id with the updated id.