Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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
@artem328

This comment has been minimized.

Copy link

@artem328 artem328 commented Jan 28, 2019

Thanks for script, i've modified it a little bit to have more universal usage.

#!/bin/bash

# run `pacmd list-sinks  | grep '\(name:\|alias\)'` and fill with value from alias of your bluetooth device
BLUETOOTH_DEVICE="YOUR DEVICE NAME"
PROFILE_A2DP="a2dp_sink"
PROFILE_HEADSET_UNIT="headset_head_unit"

####  Restart Bluetooth
if [ "${1}" == "reset" ] ; then
  sudo rfkill block bluetooth && sleep 0.1 && sudo rfkill unblock bluetooth;
  exit;
fi;

sink_name() {
    pacmd list-sinks  | grep '\(name:\|alias\)' | grep -B1 "${1}"  | head -1 | sed -rn 's/\s*name: <(.*?)>/\1/p'
}

card_name() {
    pacmd list-cards | grep 'name:' | grep "bluez" | sed -rn 's/\s*name: <(.*?)>/\1/p'
}

#### Toggle listen/speak
if [ "${1}" == "" -o "${1}" == "toggle" ] ; then
  SINK_NAME=$(sink_name "${BLUETOOTH_DEVICE}")
 
  if [ "${SINK_NAME}" == "" ] ; then echo "${BLUETOOTH_DEVICE} headset not found."; ${0} reset; sleep 2; exit; fi

  if $(echo "${SINK_NAME}" | grep "${PROFILE_A2DP}" &> /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
  SINK_NAME=$(sink_name "${BLUETOOTH_DEVICE}")
  if [ "${SINK_NAME}" == "" ] ; then echo "${BLUETOOTH_DEVICE} headset not found."; ${0} reset; sleep 2; exit; fi
  
  ## 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.:
  CARD=$(card_name)
  echo "Switching audio profile to ${PROFILE_A2DP}";
  pacmd set-card-profile "${CARD}" "${PROFILE_A2DP}"
  exit;
fi;

#### Input
if [ "${1}" == "speak" ] ; then
  ## Change profile to crappy output + mic.:
  CARD=$(card_name)
  pacmd set-card-profile "${CARD}" "${PROFILE_HEADSET_UNIT}"

  SOURCE_NAME=$(sink_name "${BLUETOOTH_DEVICE}")
  if [ "${SOURCE_NAME}" == "" ] ; then echo "${BLUETOOTH_DEVICE} mic not found."; ${0} reset; sleep 2; exit; fi
  echo "Switching audio input to ${SOURCE_NAME}";
  pacmd set-default-source "${SOURCE_NAME}.monitor" || 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
@emmanuelmathot

This comment has been minimized.

Copy link

@emmanuelmathot emmanuelmathot commented May 21, 2019

Thats great! It Works perfectly with My PLT Focus! Thx!

@hesparza

This comment has been minimized.

Copy link

@hesparza hesparza commented Feb 9, 2020

Thank you very much for this effort. I wonder how can it work on Windows? when I use my bluetooth headphones there I can talk and listen with good quality.

@david-alejandro-reyes-milian

This comment has been minimized.

Copy link

@david-alejandro-reyes-milian david-alejandro-reyes-milian commented Mar 19, 2020

really great, thanks. Bose headsets were giving headache with this. Regards!

@Vafa-Andalibi

This comment has been minimized.

Copy link

@Vafa-Andalibi Vafa-Andalibi commented May 1, 2020

worked like a charm

@jim9835

This comment has been minimized.

Copy link

@jim9835 jim9835 commented May 14, 2020

this looks like exactly what I need for my Mpow M5 headset. It works a treat in Ubuntu, but am now trying to get it to work in Manjaro KDE.

However, I'm getting "line 30: command not found"

Am a 'cut and paster' with code, so very limited understanding. My guess is that I've misunderstood the blanks I need to fill for my device.

My only initial change to the code was BLUETOOTH_DEVICE="Mpow M5"

Do I need to make other changes?

@Dentxinho

This comment has been minimized.

Copy link

@Dentxinho Dentxinho commented May 18, 2020

Thanks for script, i've modified it a little bit to have more universal usage.

Awesome, thank you.

@Dentxinho

This comment has been minimized.

Copy link

@Dentxinho Dentxinho commented May 18, 2020

My only initial change to the code was BLUETOOTH_DEVICE="Mpow M5"

Do I need to make other changes?

I don't think so, that's it.

@Nuke777

This comment has been minimized.

Copy link

@Nuke777 Nuke777 commented Jul 15, 2020

Hey I am new here. Can anyone please tell me what to do with the script? How to use it?

@weslleyspereira

This comment has been minimized.

Copy link

@weslleyspereira weslleyspereira commented Aug 4, 2020

Thank you for this script. It works nicely as expected! I suggest to use it together with a toggle button, e.g.,

#! /usr/bin/python

''' switchHeadphones.py
Tkinter toggle button to switch microphone On/Off using a script 

Modification of the solution proposed in
    https://www.daniweb.com/posts/jump/1909448
for the Mic On/Off script from
    https://gist.github.com/OndraZizka/2724d353f695dacd73a50883dfdf0fc6
'''

# Define the path for the script below, e.g.,
script = "./switchHeadphones.sh"

try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk
import os

__author__ = "Weslley S Pereira"
__email__ = "weslley.spereira@gmail.com"

def toggle(tog=[0]):
    '''
    a list default argument has a fixed address
    '''
    tog[0] = not tog[0]
    if tog[0]:
        os.system(script+' speak')
        t_btn.config(text='Switch Mic Off')
    else:
        os.system(script+' listen')
        t_btn.config(text='Switch Mic On')

root = tk.Tk()
root.title('Headphone  ')

t_btn = tk.Button(text='Switch Mic On', width=15, command=toggle)
t_btn.pack(pady=5)

root.mainloop()
@vvillschneider

This comment has been minimized.

Copy link

@vvillschneider vvillschneider commented Aug 10, 2020

Thanks!

@Paiusco

This comment has been minimized.

Copy link

@Paiusco Paiusco commented Aug 20, 2020

I think this should become a repo by it's own. There're nice improvements to be done to be more generic and w/ toggle functionality @OndraZizka what do you think?

@thedopepirate

This comment has been minimized.

Copy link

@thedopepirate thedopepirate commented Sep 28, 2020

Thank you for this script. It works nicely as expected! I suggest to use it together with a toggle button, e.g.,

#! /usr/bin/python

''' switchHeadphones.py
Tkinter toggle button to switch microphone On/Off using a script 

Modification of the solution proposed in
    https://www.daniweb.com/posts/jump/1909448
for the Mic On/Off script from
    https://gist.github.com/OndraZizka/2724d353f695dacd73a50883dfdf0fc6
'''

# Define the path for the script below, e.g.,
script = "./switchHeadphones.sh"

try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk
import os

__author__ = "Weslley S Pereira"
__email__ = "weslley.spereira@gmail.com"

def toggle(tog=[0]):
    '''
    a list default argument has a fixed address
    '''
    tog[0] = not tog[0]
    if tog[0]:
        os.system(script+' speak')
        t_btn.config(text='Switch Mic Off')
    else:
        os.system(script+' listen')
        t_btn.config(text='Switch Mic On')

root = tk.Tk()
root.title('Headphone  ')

t_btn = tk.Button(text='Switch Mic On', width=15, command=toggle)
t_btn.pack(pady=5)

root.mainloop()

I don't know how to run this, I'm new to linux. Can someone please help me out ?
@weslleyspereira @vvillschneider

@weslleyspereira

This comment has been minimized.

Copy link

@weslleyspereira weslleyspereira commented Sep 28, 2020

Usage:

  1. First, you may need to change the permissions of the original Shell script switchHeadphones.sh:
    chmod +x switchHeadphones.sh
  2. Then, after connecting your headphones, execute the script Python I suggested as follows:
    python <my_script.py> &
  3. Make sure the variable script holds the correct path for the original Shell script switchHeadphones.sh.
@thedopepirate

This comment has been minimized.

Copy link

@thedopepirate thedopepirate commented Sep 28, 2020

Usage:

1. First, you may need to change the permissions of the original Shell script `switchHeadphones.sh`:
   `chmod +x switchHeadphones.sh`

2. Then, after connecting your headphones, execute the script Python I suggested as follows:
   `python <my_script.py> &`

3. Make sure the variable `script` holds the correct path for the original Shell script `switchHeadphones.sh`.

@weslleyspereira, i tried running the above command of your's on ubuntu terminal , the chmod +x switchHeadphones.sh ran perfectly, but later the command python switchHeadphones.py gives me the following error:
File "switchHeadphones.py", line 9 if [ "${1}" == "reset" ] ; then ^ SyntaxError: invalid syntax
i renamed the file from .sh to .py as i could'nt run it
i have saved the file in my /home path. can you please help me out ? it would really mean a lot, thanks ^.^

@weslleyspereira

This comment has been minimized.

Copy link

@weslleyspereira weslleyspereira commented Sep 28, 2020

Hi!

  1. Did you configure the Shell script switchHeadphones.sh? In case not, you should. You can do as suggested in the Shell script:
    -- Run pacmd list-sinks | grep '\(name:\|alias\)' and fill with value from alias of your Bluetooth device
  2. The error you showed relates to the @artem328's script. Try running ./switchHeadphones.sh speak then ./switchHeadphones.sh listen in your terminal and see if everything works. My Python script is only an interface for this nice Shell script.
@Dentxinho

This comment has been minimized.

Copy link

@Dentxinho Dentxinho commented Sep 28, 2020

@thedopepirate you shouldn't rename the .sh to .py
The sh is the script that toggles bt audio. You can use it alone. The py is a GUI that shows a toggle button and it calls the sh under the hood

@appsessive

This comment has been minimized.

Copy link

@appsessive appsessive commented Jan 6, 2021

Thanks !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.