Skip to content

Instantly share code, notes, and snippets.

@OndraZizka
Last active May 29, 2024 13:43
Show Gist options
  • Save OndraZizka/2724d353f695dacd73a50883dfdf0fc6 to your computer and use it in GitHub Desktop.
Save OndraZizka/2724d353f695dacd73a50883dfdf0fc6 to your computer and use it in GitHub Desktop.
Bluetooth headset - switch between quality sound + no mic (A2DP) and crappy sound and mic (HSP/HFP)
#!/bin/bash
#### Restart Bluetooth
if [ "$1" == "resetBT" ] ; then
sudo rfkill block bluetooth && sleep 0.1 && sudo rfkill unblock bluetooth;
exit;
fi;
#### Toggle listen/speak
if [ "$1" == "" -o "$1" == "toggle" ] ; then
LINE=`pacmd list-sinks | grep '\(name:\|alias\)' | grep -B1 F5A | head -1`
if [ "$LINE" == "" ] ; then echo "F5A headset not found."; $0 reset; sleep 2; exit; fi
SINK_NAME="bluez_sink.00_19_5D_25_6F_6C.a2dp_sink"
if $(echo "$LINE" | grep $SINK_NAME &> /dev/null) ; then
echo "Detected quality sound output, that means we can't speak; switch that."
$0 speak;
else
echo "Quality sound not found, switch to the good sound."
$0 listen;
fi
fi
#### Change the output to F5A
if [ "$1" == "listen" ] ; then
LINE=`pacmd list-sinks | grep '\(name:\|alias\)' | grep -B1 F5A | head -1`
if [ "$LINE" == "" ] ; then echo "F5A phones not found."; $0 reset; sleep 2; exit; fi
# name: <bluez_sink.00_19_5D_25_6F_6C.headset_head_unit>
## Get what's between <...>
SINK_NAME=`echo "$LINE" | tr '>' '<' | cut -d'<' -f2`;
## The above gives an ID according to the active profile.
## To set manually:
#SINK_NAME="bluez_sink.00_19_5D_25_6F_6C.headset_head_unit"
#SINK_NAME="bluez_sink.00_19_5D_25_6F_6C.a2dp_sink"
## Switch the output to that.
echo "Switching audio output to $SINK_NAME";
pacmd set-default-sink "$SINK_NAME"
#### Change profile to quality output + no mic. From `pacmd list-cards`:
CARD="bluez_card.00_19_5D_25_6F_6C"
PROFILE="a2dp_sink"
echo "Switching audio profile to $PROFILE";
pacmd set-card-profile $CARD $PROFILE
exit;
fi;
#### Input
if [ "$1" == "speak" ] ; then
## Change profile to crappy output + mic. From `pacmd list-cards`:
CARD="bluez_card.00_19_5D_25_6F_6C"
pacmd set-card-profile $CARD headset_head_unit
LINE=`pacmd list-sources | grep '\(name:\|alias\)' | grep -B1 F5A | head -1`
if [ "$LINE" == "" ] ; then echo "F5A mic not found."; $0 reset; sleep 2; exit; fi
SOURCE_NAME=`echo "$LINE" | tr '>' '<' | cut -d'<' -f2`;
#SOURCE_NAME="bluez_source.00_19_5D_25_6F_6C.headset_head_unit"
#SOURCE_NAME="bluez_sink.00_19_5D_25_6F_6C.a2dp_sink.monitor"
echo "Switching audio input to $SOURCE_NAME";
pacmd set-default-source "$SOURCE_NAME" || echo 'Try `pacmd list-sources`.';
fi;
#### Resources:
## Why this is needed
# https://jimshaver.net/2015/03/31/going-a2dp-only-on-linux/
## My original question
# https://askubuntu.com/questions/1004712/audio-profile-changes-automatically-to-hsp-bad-quality-when-i-change-input-to/1009156#1009156
## Script to monitor plugged earphones and switch when unplugged (Ubuntu does that, but nice script):
# https://github.com/freundTech/linux-helper-scripts/blob/master/padevswitch/padevswitch
@OndraZizka
Copy link
Author

Hi all, I am glad that there has been quite a lot of activity around my humble script :)

I personally moved to a device with BlueTooth 5, so I can't work on this anymore.

@tvaillantdeguelis wrote a good summary - BlueTooth 4 was not capable of supporting a microphone at a decent quality, unless there were workarounds supported by both the drivers and the device, like setting up 2 BT connections. I could not make that work on Linux.

@JustinFrost47
Copy link

@Fuzzphorescent I ran into the same problem today.

You might have found a solution for your problem by now, but I hope someone else with similar problem finds this useful

Original script searches ( greps) for F5A keyword from list of connected devices (sinks to be accurate) , well your device might have different name like mine. So, that's why you got that error.

The script given by artem328 worked like a charm for me along with toggle button. So try it out

@Fuzzphorescent
Copy link

@JustinFrost47 I never did figure it out but now having read your answer, it seems so obvious what the problem was. Looks like I hadn't skimmed the code back then to find out what prompted the error message.

I've since moved to a newer machine running Windows 10 (which is posing its own set of BT-related challenges). I'm now inspired to dust off the old laptop and give it another go for an undeserved sense of accomplishment. Thanks for the help, cheers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment