You are not logged in.
I'm using mpd + Sonata for my music collection (and loving it...). I also have 2 soundcards. One is the internal laptop soundcard and the other is an external USB soundcard. I want to automate mpd so that if the USB soundcard is plugged in, it only uses that output. If it's not plugged in, I want mpd to only use the internal soundcard. With the command-line client mpc you can enable/disable outputs, so is there some kind of script or something I can use to do this? These are my outputs:
[hb@hb-laptop .config]$ mpc outputs
Output 1 (Conectiv) is enabled
Output 2 (Intel) is enabled
Offline
Funny you should ask... I just got a setup like this working. Here is what I did.
1) First of all you need to create a udev rule that will execute appropriate scripts when your USB soundcard is connect it. You have to figure out what your USB soundcard shows up as under /dev when it is plugged in -- for me it is /dev/dsp2 ("dsp" is internal card and "dsp1" is the modem for some reason)... It's probably the highest "dsp*" entry in the /dev directory.
Once you know that you can create a udev rule. My /etc/udev/rules.d/85-bithead.rules looks like this (the file name doesn't really matter as long as the path is correct):
KERNEL=="dsp2", ACTION=="add", SUBSYSTEM=="sound",\
RUN+="/home/filip/scripts/bithead-add.sh"
KERNEL=="dsp2", ACTION=="remove", SUBSYSTEM=="sound",\
RUN+="/home/filip/scripts/bithead-remove.sh"
2) You need scripts that will do the actual output switching. The general philosophy of my scripts is to edit mpd configuration file and then restart mpd -- you could rewrite the scripts to switch outputs using mpc (I didn't realize that was a possibility when I wrote these). The config file that gets edited is ~/.mpdconf -- the file is also linked to /etc/mpd.conf (this is important). You could probably just skip the home dir file completely and edit the /etc/mpd.conf directly -- there must be an /etc/mpd.conf file with the correct information in either case, just having a ".mpdconf" file in your home dir is not enough. You will need to edit those scripts intelligently to make sure that mpd config file is edited correctly for your setup. In my case the usb soundcard works as "hw:2,0" alsa output while the internal card is "hw:0,0" -- if this is different on your system you will need to adjust the scripts appropriately. Anyways, these are the scripts for the udev rule.
bithead-add.sh:
#!/bin/sh
cat /home/filip/.mpdconf | grep -q "hw:0,0"
if [ "$?" -eq "0" ]
then
sed -i 's/hw:0,0/hw:2,0/g' /home/filip/.mpdconf
fi
mpd --kill
/usr/bin/mpd /etc/mpd.conf &> /dev/null
and bithead-remove.sh:
#!/bin/sh
cat /home/filip/.mpdconf | grep -q "hw:2,0"
if [ "$?" -eq "0" ]
then
sed -i 's/hw:2,0/hw:0,0/g' /home/filip/.mpdconf
fi
mpd --kill
/usr/bin/mpd /etc/mpd.conf &> /dev/null
3) You also probably want mpd to detect the usb soundcard correctly in case it is connected at boot. What I did is I created a new daemon startup script called "mpd-multicard" that doesn't run mpd directly when started, but calls a script which first checks if my usb soundcard is connected and then edits mpd config file correctly before starting mpd. I use "mpd-multicard" instead of regular "mpd" in my rc.conf file. This is the /etc/rc.d/mpd-multicard file (it's basically a slightly modified version of the default mpd daemon startup script):
#!/bin/bash
. /etc/rc.conf
. /etc/rc.d/functions
case "$1" in
start)
stat_busy "Starting Music Player Daemon"
/home/filip/scripts/mpd-multicard.sh
if [ $? -gt 0 ]; then
stat_fail
else
add_daemon mpd
stat_done
fi
;;
stop)
stat_busy "Stopping Music Player Daemon"
/usr/bin/mpd --kill /etc/mpd.conf &> /dev/null
if [ $? -gt 0 ]; then
stat_fail
else
rm_daemon mpd
stat_done
fi
;;
create-db)
stat_busy "Creating mpd's database ..."
logpath="/var/log/mpd/mpd.db-creation"
/usr/bin/mpd --create-db /etc/mpd.conf > $logpath \
&& stat_busy "Output written to $logpath"
stat_done
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo "usage: $0 {start|stop|restart|create-db}"
esac
exit 0
As you can see what this script does is call a script called mpd-multicard.sh instead of starting mpd directly. Here is mpd-multicard.sh:
#!/bin/sh
lsusb | grep -q 08bb:2902
if [ "$?" -eq "0" ]
then
cat /home/filip/.mpdconf | grep -q "hw:0,0"
if [ "$?" -eq "0" ]
then
sed -i 's/hw:0,0/hw:2,0/g' /home/filip/.mpdconf
fi
/usr/bin/mpd /etc/mpd.conf &> /dev/null
else
cat /home/filip/.mpdconf | grep -q "hw:2,0"
if [ "$?" -eq "0" ]
then
sed -i 's/hw:2,0/hw:0,0/g' /home/filip/.mpdconf
fi
/usr/bin/mpd /etc/mpd.conf &> /dev/null
fi
You will need modify this script to use the correct xxxx:xxxx ID number for you USB soundcard -- my card is identified as "08bb:2902" -- you can get this number by using "lsusb" command when your usb soundcard is connected. The previous qualifications about the alsa output names (hw:0,0 and hw:2,0) and mpd config file locations naturally apply as well.
4) Lastly, here is the script I use to switch outputs manually when both cards are connected . Hopefully the logic here should be self-explanatory at this stage:
#!/bin/sh
# The scripts switches the soundcard currently used and restarts mpd
# It must be run as root.
# Check if user is root
if [ `whoami` != "root" ]
then
echo "You need to be root!";
exit 1
fi
lsusb | grep -q 08bb:2902
if [ "$?" -eq "0" ]
then
cat /home/filip/.mpdconf | grep -q "hw:2,0"
if [ "$?" -eq "0" ]
then
echo ":: Switching to the internal sound card..."
sed -i 's/hw:2,0/hw:0,0/g' /home/filip/.mpdconf
mpd --kill
/usr/bin/mpd /etc/mpd.conf &> /dev/null
else
echo ":: Switching to Bithead..."
sed -i 's/hw:0,0/hw:2,0/g' /home/filip/.mpdconf
mpd --kill
/usr/bin/mpd /etc/mpd.conf &> /dev/null
fi
else
echo "Bithead is not connected."
cat /home/filip/.mpdconf | grep -q "hw:2,0"
if [ "$?" -eq "0" ]
then
sed -i 's/hw:2,0/hw:0,0/g' /home/filip/.mpdconf
mpd --kill
/usr/bin/mpd /etc/mpd.conf &> /dev/null
fi
fi
I have this in my .bashrc:
alias sound="sudo /home/filip/scripts/soundcard.sh"
And I have /home/filip/scripts/soundcard.sh specified in my sudoers file so it doesn't need a password.
Offline
Awesome tutorial, thank you very much! You've explained it very clearly and a non-programmer like me can actually see the logic in your scripts. I haven't got time to try this out tonight, but I'll get working on it tomorrow.
mpd --kill
/usr/bin/mpd /etc/mpd.conf &> /dev/null
Would this be replaceable by "/etc/rc.d/mpd-multicard restart"? And why is the "&> /dev/null" needed?
Offline
Awesome tutorial, thank you very much! You've explained it very clearly and a non-programmer like me can actually see the logic in your scripts. I haven't got time to try this out tonight, but I'll get working on it tomorrow.
mpd --kill /usr/bin/mpd /etc/mpd.conf &> /dev/null
Would this be replaceable by "/etc/rc.d/mpd-multicard restart"? And why is the "&> /dev/null" needed?
There were some problems when "/etc/rc.d/mpd-multicard restart" was called by HAL events -- for some reason using this command would result in the internal card being selected all the time. The "&> /dev/null" makes sure that no output is printed when the command is executed -- I used it in my scripts, frankly, because I coped the entire command from the daemon startup script; I wanted to make sure that mpd was started in exactly the same way as it would be started if I used the daemon startup script. You could probably get rid of it if you want, it shouldn't really make any difference one or the other way.
Offline
Really awesome tutorial.
Could be a great page on the wiki
Thanks -- the wiki idea had occurred to me; I think I'll write something up eventually, but I think I'd like to rewrite the scripts a bit (to clean them up and make then easier to adapt for different setups) before I actually make a wiki article out of that. Sometime in the next couple of weeks...
Offline
Well I got it working! I haven't implemented it all due to time constraints, but I will soon. I'm using the mpc enable/disable commands at the moment in the scripts, which is working great for me.
Offline