Software Pandora Audio Switch


KickAss

Very Active Member
Joined
Mar 9, 2011
Messages
604
Location
Germany
Pandora Audio Switch
v0.5
Versionhistory:
v0.1 - initial release
v0.2 - added the templatename pattern to make adding custom templates easier
v0.3 - adding templates to the script is no longer necessary. it will look for the template file according to -o templatename
v0.4 - added zaxxon compatibility
v0.5 - added working software volume control for the hardware device

  • Switch your system's default audio output with ease and almost zero config work
  • Have as many bluetooth or hardware based audio devices as you like
  • Have a simple menubar toggle to click-switch audio output
  • Entirely "onboard" ALSA based (no further dependencies)
The basic Idea

I've been using bluetooth audio on the pandora for a while now. But bluetooth audio isn't that simple with ALSA. For some reason there's no really helpful documentation. At least i didn't find any. So i kept struggeling. I finally managed to get where i wanted to go and i wanted to make things a little easier for others.

The pandora already has everything you need to get bluetooth audio going. Proper configuration just isn't simple, so ppl may try, but give up after some frustrating experience. PAS is here to help.
This is all done with ALSA only. PulseAudio may be great and all, but it's resource hungry and we don't even need it.

What PAS does is: it holds predefined ALSA config files with device definitions (one per device) and copies them to the correct spot on demand. This enables you to easily set up the devices you have as default ALSA devices and switch between them on the fly with just a click of a button or a simple bash script call (whatever you prefer). I may even write a gui at some point. But usage could not be simpler as it already is.

The basic Design


PAS provides the following:
  • pas.sh
    • This is the actual script. It copies the config file corresponding to the audio output mode of your choice.
  • .asoundrc_hw
    • This is the predefined config to enable audio through the built in speakers.
  • .asoundrc_bt
    • This is the predefined config template to enable bluetooth audio devices.
Let's say you want to use a couple of different bluetooth devices. What about that?
This is the strong side of this design: You would simply start with the provided .asoundrc_bt, add your device specific MAC address and save it as a new template, .asoundrc_carstereo for example. Got a shiny new headset? Go ahead and add .asoundrc_headset to your collection of templates.
All you need to do now is to make pas.sh aware of the templates you want to use. Ill show you how to do that a couple of lines later.
All it takes to switch from carstereo to headset is a simple call:
Code:
pas.sh -o headset
How cool is that?

Prerequisites


In order for this to work out properly we need to take care of a couple of things:
  • Edit /etc/bluetooth/audio.conf
    Make sure the [General] section holds the following:
    Code:
    [General]
    Enable=Source,Sink,Headset,Socket,Control

    If you like you can also enable autoconnection:
    Code:
    AutoConnect=true
  • Edit /usr/share/alsa/alsa.conf
    For the sake of compatibility with libpnd change
    Code:
    ~/.asoundrc
    to
    Code:
    /home/${USER}/.asoundrc
  • If you worked on ALSA's config files (~/.asoundrc and/or /etc/asound.conf) before, you may want to back them up now and keep them somewhere save. Because we will now delete those files:
    Code:
    rm -v ~/.asoundrc
    rm -v /etc/asound.conf
    This makes sure our setup is not compromised by any ill configured file.
  • Find your device's MAC address:
    Enable bluetooth on the pandora and activate your bluetooth device (e.g. your headset) so it can be found.
    On the pandora a window should pop up, the bluetooth device manager:
    pandora_bt1.png

    If it doesn't pop up, open it manually with:
    Code:
    blueman-manager
    You can also use:
    Code:
    hcitool scan
    Code:
    hcitool con
    Search for devices and write down their MAC addresses -> XX:XX:XX:XX:XX:XX
    Do not pair with them yet!
Get PAS started

Simply download and extract the provided pas.zip. It holds all the necessary files to start with. To keep things simple place the files in
Code:
~/pas/
You can, of course, place them anywhere you like. But then you will need to adjust pas.sh.

Luckily you will not need to edit .asoundrc_hw. So just forget about it.

Edit .asoundrc_bt and add a device specific MAC address you wrote down before:
Code:
# This is the bluetooth enabled ALSA config file.
# It is meant to set the main audio output to bluetooth.
# Please set device's MAC Address correctly or try autodetection.
#
# Try Alsa's BT autodetection
#@hooks [
#    {
#        func load
#        files [
#            "/usr/share/alsa/bluetooth.conf"
#        ]
#        errors false
#    }
#]

pcm.!default {
    type plug
    slave.pcm "btsoftvol"
}

pcm.btheadset {
    type bluetooth
    device "XX:XX:XX:XX:XX:XX"
    rate "44100"
    profile "auto"
}

pcm.bluetooth {
    type plug
    slave {
        pcm btheadset
    }
}

ctl.bluetooth {
    type plug
    slave {
        pcm btheadset
    }
}

pcm.btsoftvol {
    type softvol
    slave.pcm "bluetooth"
    control.name "Master"
    control.card 0
}

ctl.btsoftvol {
    type softvol
    slave.pcm "bluetooth"
    control.name "Master"
    control.card 0
}
Save this file as .asoundrc_bt_headset for example.
"bt_headset" will be this template's name. That's important, because we will use that name later in pas.sh.
If you want to use other bluetooth devices just edit .asoundrc_bt again, add another MAC address and save the file with a different name, .asoundrc_bt_carstereo for example.
Do this for as many device specific (because they hold the device specific MAC address) files as you like.

Editing pas.sh is no longer necessary. Here's the code anyway:
Code:
#!/bin/bash
##################
#  #
#  PAS v0.4  #
#  #
##################
#
# This is a quick and dirty but still quite awesome script to switch ALSA
# output on the fly. It copies valid config files to enable output
# devices on demand.
# As of version 0.4 two templates are provided:
#
# 1. BT output -> .asoundrc_bt
# 2. HW output -> .asoundrc_hw
#
# You only need to add a valid device MAC address to .asoundrc_bt
# and save it as .asoundrc_outputname
# Make then use of it with: pas.sh -o outputname
# For every outputname you need a .asoundrc_outputname file!
#
# Please save your own customized .asoundrc files in PAS_PATH.
# Because of libpnd it is best to avoid ~ and use absolute paths here:

PAS_PATH=/home/${USER}/pas/

# Before any sound is being played ALSA parses the config files, so
# there's NO need to restart your system after you used this script.
#
# Please set PAS_PATH correctly!

if [[ $# = 0 ]]; then
  echo "No options parsed. Try "$0" --help"
fi

while [[ $# > 0 ]]
do
key="$1"

case $key in
   -o|--output)
   OUTPUT="$2"
   shift
   if [ -f ${PAS_PATH}.asoundrc_${OUTPUT} ];then
     echo "Switching audio output to: "${OUTPUT}
     echo "using config files from: "${PAS_PATH}
     rm -v /home/${USER}/.asoundrc
  cp -v ${PAS_PATH}.asoundrc_${OUTPUT} /home/${USER}/.asoundrc
   else
     echo "Unsupported output mode parsed. Exiting."
     echo "For every -o outputname you need a .asoundrc_outputname file!"
   fi
   ;;
   -h|--help)
   echo "##################"
   echo "#  #"
   echo "#  PAS v0.4  #"
   echo "#  #"
   echo "##################"
   echo
   echo "Pandora Audio Switch v0.4"
   echo "------------------------"
   echo "Usage:"
   echo "-h|--help    Display this message."
   echo "-o|--output   Set audio output device."
   echo
   echo "Example: ./pas.sh -o bt_headset"
   echo "  ./pas.sh -o boombox"
   echo
   ;;
   *)
   echo "Unknown option parsed. Exiting."
   ;;
esac
shift
done
Now all you need to do is this:
Code:
pas.sh -o hw
pas.sh -o bt_carstereo
pas.sh -o bt_boombox
As long as there is a corresponding .asoundrc_OUTPUT file it will work. Yay :)

Pair your devices


Open the bluetooth device manager again.
Right-click on your device. Click on "Setup":
pandora_bt2.png

Connect using the A2DP protocol.
If you're asked to enter the PIN code, try: 0000
If that doesn't work go study your device's user manual.
Hopefully your device gets connected. Click the star button to "trust" that device.

Use pas.sh


Let's assume you just connected your headset. Set it as ALSA's default output device with:
Code:
pas.sh -o bt_headset
Start playing audio using mplayer, smplayer, audacious, deadbeef... you name it.
Enjoy bluetooth audio :)
All of a sudden your headset's battery is empty.
Code:
pas.sh -o hw
will get the built in speakers going :)

Hints

Add the following to ~/.bashrc to make pas.sh available from everywhere:
Code:
alias pas='~/pas/pas.sh'

mplayer defaults to the oss audio driver on superzaxxon. It will ignore our alsa settings and you will not get bluetooth audio output.
You can change that by editing /usr/etc/mplayer/mplayer.conf:
Code:
ao=alsa

PAS does set pcm.!default devices. Basically this means that every program that plays audio through ALSA will use that default device. We do it that way, because with bluetooth you don't want to tell every program separately to use the bluetooth device. You prolly just want all the audio through bluetooth. Well, i do :)

Unfortunately this setup does not work with all programs (for different reasons). But it does work with most.
 

Attachments

  • pas_0.5.zip
    2 KB · Views: 435
Last edited:
I've not tried this tool yet, but as far as finding MAC addresses, the bluetooth GUI in SuperZaxxon doesn't show them for long enough to copy them down, and I don't see a way to get them back. (Is your screenshot from Slackware?)

Anyway, the easiest thing is to enable Bluetooth and then type "hcitool scan" in a terminal. This lists all the MAC addresses and names of pairable bluetooth devices nearby.
 
Also, "hcitool scan" sometimes does not return devices you are in an active connection with. If you already connected to your headset and "hcitool scan" does not show you what you want, "hcitool con" will list your active connection types along with their MAC address.
[doublepost=1459121320,1459094877][/doublepost]Does anybody else run Openbox?

Since kickass was so great in providing the script/framework that everyone can use for switching asound config files, I decided to integrate the script into my openbox menu configuration. My configuration checks if you have the script installed to "~/pas/pas.sh" and if you do, it reads all the .asoundrc_* files you have saved there, and lists them as options in the Connectivity section of the menu.

Simply replace the togglemenu function in /usr/bin/openbox-functions script with the following:
Code:
function togglemenu
{
    if [ -f $XDG_CACHE_HOME/wifi ]
    then
        wifistate=$(cat $XDG_CACHE_HOME/wifi )
    else
        if [ "`lsmod | grep wl1251`" ]
        then
            wifistate="OFF"
        else
            wifistate="ON"
        fi
    fi

    if [ -f $XDG_CACHE_HOME/bluetooth ]
    then
        bluetoothstate=$(cat $XDG_CACHE_HOME/bluetooth )
    else
        INTERFACE="`hciconfig | grep "^hci" | cut -d ':' -f 1`"      

        if [ "$INTERFACE" != "" ]
        then      
            if hciconfig "$INTERFACE" | grep UP &>/dev/null
            then
                bluetoothstate="OFF"
            else
                bluetoothstate="ON"
            fi
        else
            bluetoothstate="ON"
        fi
    fi  

    if [ -f $XDG_CACHE_HOME/usb ]
    then
        usbstate=$(cat $XDG_CACHE_HOME/usb )
    else
        if [ "`lsmod | grep ehci_hcd`" ]
        then
            usbstate="OFF"
        else
            usbstate="ON"
        fi
    fi

    if [ $(pidof nm-applet) ]
    then
        nmappletstate="OFF"
    else
        nmappletstate="ON"
    fi

    if [ $(pidof bluetooth-applet) ]
    then
        bluetoothappletstate="OFF"
    else
        bluetoothappletstate="ON"
    fi  
  
    if [ -f ~/pas/pas.sh ]
    then
    paspath=~/pas/
    asoundlist=$(ls -a $paspath.asoundrc_*)
    asoundfilenames=${asoundlist//$paspath/}
    asoundoptions=${asoundfilenames//.asoundrc_/}
    asoundoptionarray=($asoundoptions)
    fi  
  
    echo "<openbox_pipe_menu>"
    echo "<item label=\"Switch WiFi Hardware $wifistate\" icon=\"/tmp/iconcache/op_wifi.png\">"
        echo "<action name=\"Execute\">"
            echo "<command>sudo openbox-functions wifi_$wifistate</command>"
        echo "</action>"
    echo "</item>"
    echo "<item label=\"Switch WiFi Applet $nmappletstate\" icon=\"/usr/share/icons/hicolor/22x22/apps/nm-device-wwan.png\">"
        echo "<action name=\"Execute\">"
            echo "<command>openbox-functions networkapp_$nmappletstate</command>"
        echo "</action>"
    echo "</item>"
    echo "<item label=\"Edit Network Connections\" icon=\"/usr/share/icons/gnome/32x32/status/network-idle.png\">"
    echo "<action name=\"Execute\">"
        echo "<command>nm-connection-editor</command>"
    echo "</action>"
    echo "</item>"
    echo "<separator />"
    echo "<item label=\"Switch Bluetooth Hardware $bluetoothstate\" icon=\"/usr/share/icons/hicolor/32x32/apps/bluetooth.png\">"
        echo "<action name=\"Execute\">"
            echo "<command>openbox-functions bluetooth_$bluetoothstate</command>"
        echo "</action>"
    echo "</item>"
    echo "<item label=\"Switch Bluetooth Applet $bluetoothappletstate\" icon=\"/usr/share/icons/openbox/bluetooth_app.png\">"
        echo "<action name=\"Execute\">"
            echo "<command>openbox-functions bluetoothapp_$bluetoothappletstate</command>"
        echo "</action>"
    echo "</item>"
    echo "<separator />"
    echo "<item label=\"Switch USB Host $usbstate\" icon=\"/tmp/iconcache/op_usbhost.png\">"
        echo "<action name=\"Execute\">"
            echo "<command>sudo openbox-functions usbhost_$usbstate</command>"
        echo "</action>"
    echo "</item>"
    if [ -f ~/pas/pas.sh ]
    then
    echo "<separator />"
    for asiter in ${asoundoptionarray[@]}
    do
    echo "<item label=\"Switch Sound To $asiter\" icon=\"/usr/share/icons/hicolor/32x32/apps/bluetooth.png\">"
        echo "<action name=\"Execute\">"
            echo "<command>~/pas/pas.sh -o $asiter</command>"
        echo "</action>"
    echo "</item>"
    done
    fi
    echo "</openbox_pipe_menu>"
}
[doublepost=1459124111][/doublepost]Also, now that I actually have everything set up, my system seems to ignore the ~/.asoundrc file.

I am testing with SuperZaxxon and the audacious PND, and it continues to output through the internal speakers.

Up until now I've always been using "/etc/asound.conf". I did make sure to delete this file.

For now, I will probably modify your script to go back to using "/etc/asound.conf" instead of "~/.asoundrc" at least on my own system.

Does anyone else running SuperZaxxon have trouble using the "~/.asoundrc" file?
 

Attachments

  • 160327-181209.png
    160327-181209.png
    190.8 KB · Views: 484
Also, now that I actually have everything set up, my system seems to ignore the ~/.asoundrc file.

I am testing with SuperZaxxon and the audacious PND, and it continues to output through the internal speakers.

Up until now I've always been using "/etc/asound.conf". I did make sure to delete this file.
ALSA should read both files. You can check if its configured to do so -> /usr/share/alsa/alsa.conf
In it's default state it should read both.

For a change, try setting your audio output to bt using pas.sh and then try to play a file using mplayer:
Code:
mplayer path/to/some/mp3file
without any other options. this will invoke mplayer, using pcm.!default.
My guess is that audacious uses it's own configuration.

As soon as i am home i will sort this out for zaxxon.
Did anyone try this on slackware?
 
Just tested:

Mplayer installed to NAND recognizes "~/.asoundrc".

Audacious PND does not.
 
the almighty ptitseb mentioned the other day, that in the scope of a pnd HOME gets diverted to the appdata folder.
try to put your .asoundrc into audacious' appdata folder. this is actually just a wild guess (and i don't think that's the problem here), but you might try.
 
The SMPlayer2 PND responds to /etc/asound.conf or appdata/smplayer2/.asoundrc , but not ~/.asoundrc . So the diverted home directory does seem to be a problem. We could make asound.conf writeable by the normal user account so not needing sudo every time.

For SMPlayer2, also need to edit smplayer2.ini changing "driver\audio_output=oss" to "alsa", or none of those files do anything.

Any other apps which ignore asound.conf also might not be using alsa.
 
Last edited:
what a bummer.

well, thanks for checking that out.
i still thinks it's weird, because ALSA should work outside the scope of any PND. but obviously it's an issue.
i will investigate further.

for some reason i like the per user setup with ~/.asoundrc files better than the /etc/asound.conf approach.
but seeing that most pandora owners prolly use it as a single user device anyway it doesn't really make that much of a difference.

again:
PAS v0.3 works great on slackware.
i got a little time on my hands now and will get things working with zaxxon.

EDIT:
in the meantime someone on zaxxon could edit /usr/share/alsa/alsa.conf to tell ALSA to look for
/home/[username]/.asoundrc
instead of
~/.asoundrc
and test again :)
[doublepost=1459162314,1459150881][/doublepost]i'm on the train but did a quick check:

setting /usr/share/alsa/alsa.conf to read /home/yourusernamehere/.asoundrc
(amongst the first couple of lines) works for me in zaxxon.

i tried it with the gmu pnd (dont have any other player as pnd file right now). i changed pas.sh to use the full path to the home dir (i. e. /home/username instead of ~) and it works.

if i do pas.sh -o headset
gmu tries to open the bt device.

if i do pas.sh -o hw
gmu doesn't try to open the bt device.

hopefully this is solving your issues.
 
okay:
with full paths and minor changes to the script PAS now works on zaxxon 1.73 (i didn't update to 1.74 yet).

expect PAS v0.4 to come soon.
[doublepost=1459256032,1459233290][/doublepost]updated.
edit /etc/share/alsa/alsa.conf as described and use pas_0.4 and it should work with slackware and zaxxon.
 
I installed your script, I don't have a bluetooth headset here right now, but I prepared everything.
However I don't have blueman-manager installed on my pandora and can't find it in the Angström repository. All I have is "bluetooth-applet", which shows way less options than the famous blueman-manager. Where did you get it?
 
i started working on this on slackware.
prolly superzaxxon doesnt offer blueman. cant say for sure, my pandora is in for repairs.

doesnt really matter tho, as long as you put your device MAC address in there it should work with bluetooth-applet or network-manager or whatever you got.
i tested PAS 0.4 successfully on a freshly flashed superzaxxon.
 
Awesome, thanks for the clarification. :) At least setting the option back to "hw" works after I tried to connect to my laptop as bluetooth speaker - which didn't work. XD
 
Uh great ;) didn't know this script exist....don't have something to test, but i think it could be integrated into firmware or made a PND.
 
I am testing it right now at the train with a cheap bluetooth headset I bought once, Works like a charme, thank you very much! I am writing this on my pandora with the new free wifi on German trains while listining to music over bluetooth. :D
The only problem is, that the sound stops if the pandora is under load like opening a webpage - even with netsurf. Maybe giving the audio process a higher priority helps. But that's not the fault of your script. ;D

Great work, thanks again! :)
[doublepost=1485754798,1485754542][/doublepost]Addition: Giving my audio player a lower nice value indeed helps. It stills stoters, but much better. :D
 
I've had lots of bluetooth devices suffer stuttering/cutting out, including headset, mice, and controllers. The culprit seemed to be the Wifi module from what I can tell, because I didn't notice the problem when using ethernet over USB.
 
And bt to itself. Internet auf bt had the same problem. ;)
 
im glad you guys like it :)

in order to get flawless BT performance: use a wifi dongle. they are tiny and make a huge difference!
 
Well, I could also use a bt-dongle, I have a tiny one at home :)
 
Back
Top