Skip to content

Instantly share code, notes, and snippets.

@simlei
Last active October 22, 2022 07:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simlei/226fdfec2063dd3bdae47b2c6ae6aca1 to your computer and use it in GitHub Desktop.
Save simlei/226fdfec2063dd3bdae47b2c6ae6aca1 to your computer and use it in GitHub Desktop.
Reconnect bluetooth on raspbian, using PulseAudio pactl and expect
#!/usr/bin/expect -f
# from: https://gist.github.com/RamonGilabert/046727b302b4d9fb0055
set prompt "#"
set address [lindex $argv 0]
set timeout 20
spawn sudo bluetoothctl
# expect -re $prompt
send "connect $address\r"
# send_user "\nTrying to connect; sleeping some time...\r"
expect {
-re ".*Connection successful.*" {
# expect -re $prompt
send_user "expected connect, got connect :)\r"
send "exit\r"
# expect eof
}
-re ".*Failed to connect.*InProgress" {
send_user "ok, we'll be waiting..."
}
-re ".*Failed to connect.*" {
send_user "error that is not InProgress..."
send "exit\r"
exit 1
}
timeout {
send_user "could not connect in due time, exiting...\r"
send "exit\r"
exit 1
}
}
send_user "finished interacting with bluetoothctl\r"
#!/usr/bin/env bash
cardaddr="${1:-40:ED:98:1A:9A:B1}"
if [[ "$1" == "--help" ]]; then
echo "first arg: the bluetooth address; by default: 40:ED:98:1A:9A:B1"
exit 0
fi
# resolve the current directory
thisdir="$(readlink -f "${BASH_SOURCE[0]}")"
thisdir="${thisdir%/*}"
# have a lockfile/singleton behavior or not
use_lockfile=1
lockfile=$HOME/.btreconnect.lock
if [[ $use_lockfile == 1 && -e $lockfile ]]; then
echo "==========$(date) already in process, exiting"
exit 1
fi
if [[ $use_lockfile == 1 ]]; then
touch $lockfile
fi
# finish and exit behavior: I don't like traps, add your own...
# uses zenity if it's installed to display a message box
finish_with_msg() {
if which zenity; then
zenity --info --text="$1" --width=250 --timeout="${3:-4}" &
else
echo "MSG: $1" >&2
fi
finish_with $2
}
finish_with() {
if [[ $use_lockfile == 1 ]]; then
rm $lockfile 2>/dev/null || :
fi
exit ${1:-0}
}
echo "=========== $(date): connecting $cardaddr" >&2
cardaddr_underscore="${cardaddr//:/_}"
# set -euo pipefail
stdbuf -o0 -i0 -e0 $thisdir/bt_conn_up.expect $cardaddr
echo looking for cards... >&2
cardcmd_out=( $( pactl list cards short | grep "$cardaddr_underscore" | tr -s ' ' | cut -d ' ' -f 1-2 ) ) || :
if [[ ${#cardcmd_out[@]} -lt 1 ]]; then
finish_with_msg "could not find bluetooth sound device (card); exiting"$'\n'"You may try again..." 2
fi
cardno="${cardcmd_out[0]}"
cardname="${cardcmd_out[1]}"
echo looking for sinks... >&2
sinkcmd_out=( $( pactl list sinks short | grep "$cardaddr_underscore" | tr -s ' ' | cut -d ' ' -f 1-2 ) ) || :
if [[ ${#sinkcmd_out[@]} -lt 1 ]]; then
finish_with_msg "could not find bluetooth sound device (card); exiting"$'\n'"You may try again..." 2
fi
sinkno="${sinkcmd_out[0]}"
sinkname="${sinkcmd_out[1]}"
echo setting defaults and rerouting sinkinputs... >&2
echo pactl set-default-sink $sinkname >&2
pactl set-default-sink $sinkname
echo pactl set-card-profile $cardno a2dp_sink >&2
pactl set-card-profile $cardno a2dp_sink
echo "rerouting any existing sound sources" >&2
while read -r sinkinput_line; do
inputnr="$(echo $sinkinput_line | tr -s ' ' | cut -f 1 )" || :
echo pactl move-sink-input $inputnr $sinkno >&2
pactl move-sink-input $inputnr $sinkno || {
finish_with_msg "mapping devices failed"$'\n'"You may try again..." 2
}
done < <(pactl list sink-inputs short | cut -f 1 || :)
finish_with_msg "SUCCESS: The program thinks it reconnected successfully :)" 0 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment