Integrate XM

From MythTV

Jump to: navigation, search

This article is going to give you all of the info you need in order to pipe your online XM Satellite Radio account directly through your MythTV system. The first draft of this article is based around a Fedora Core 6 setup but it can be EASILY adapted to any distro. Please, READ THE ENTIRE ARTICLE CAREFULLY all the way to the end before you start anything.


Note: this is NOT a plug-in and is basically a hack but when completed it looks just like a plug-in.


Contents

Article from 10,000 feet

What this article is...

This article IS about:

  • Setting up MythTV to play streams from XM Radio Online
  • How-To use scripts that other people wrote (and are not affiliated with MythTV)
  • How-To integrate everything with the default MythTV menu theme

What this article is not...

This article IS NOT:

  • How-To get free access to the streams (although a XM guest account has been tested and works fine)
  • How-To perfectly integrate with your particular MythTV GUI (we only cover the default menu theme)
  • An XM Radio Plug-in for MythTV
  • An audio stream capture how-to

What you need to have

Setup

  • You only need to have an account setup at xmradio.com.

Installed

Required:

Optional:

Quick Install

I created an installer to quickly do everything below this block, to automate integrating this XM streaming into MythTV. I also created a script to automatically download the available XM channels online and create a XML MythTV menu for them. It creates them in the user's home '.mythtv' directory and alters the 'library.xml' file to include a 'Stream XM' menu option. The installer asks if you want to have this script run every night (by adding it to your crontab) so that you will always have the updated channels (such as XM Holly for Christmas or whatever).

Really, all you should need now is this installer, but I left everything below here in the wiki for historical reasons, if people wanted to read more in depth.

Download the installer:

wget http://creasonfamily.com/files/mythtv/mythtv_xm_stream_0.1.0.tar.gz

Then unzip and start the install:

tar -zxf mythtv_xm_stream_0.1.0.tar.gz
cd mythtv_xm_stream
perl install.pl

Just follow the prompts, but read everything! There is a README file in the mythtv_xm_stream directory too.

Older Install Method

OK, there was a shell script that I found that seemed to work pretty close to what I needed to get this working so I took that as a base and I hacked the living crap out of it to make it "better" and much more user friendly. (You're welcome.)

What I ended up with was 2 shell scripts; one of them manages the stream and the other manages the song titles (if you want to see them) So we are looking at a quick setup with almost no overhead (pending your a typical MythTV user and have mplayer installed).

Create the scripts

I recommend that you dump these scripts in your $PATH, (mine are in /usr/bin).

OK, now we will create the 2 files needed for this integration.

# cd /usr/bin
# vi xamp
wget http://www.flyingsawdust.com/media/mythtv/xmradio/xamp
wget http://www.flyingsawdust.com/media/mythtv/xmradio/xamp_song


Note: (Moved script text to the bottom of this page)

Now we need to make them executable

# chmod a+x xamp*

Initial script configuration

The original version of the script required you to get in and manually tweak a couple of settings. I didn't like that approach as it was a little TOO much of a "hack", even for this project. So I went in and created a wizard to build the settings and store them in a config file instead of directly in the script. You're welcome.

Let's walk through the config wizard.. make sure you do this as the mythtv user (or whatever your front end uses)

$ xamp setup

You will be asked to remove your old config file in case you have one. IF THIS IS YOUR FIRST SETUP CHOOSE YES.

Do you want to remove your existing config file? [y or n]

If you choose "y", you'll be faced with this big scary prompt.

****************************************************
***WARNING: Password will be stored in plaintext!***
****************************************************
Enter your XM Online Username [example@example.com]:

This is just telling you that your XM online password will be stored in the config file unencrypted. The original script didn't hash and password and I didn't implement it either, so that's just how it's going to be for the time being. Maybe I'll revise it one day to do encryption but I doubt it since I'm not an XM user.

Next, you are asked for your password which will not be echoed back to the command line so get it right. :-)

Enter your XM Online password:

Now your asked for stream quality. I don't use this service much but I was defaulted to high and I seem to see that it doesn't really matter unless your on dial-up or something. So just enter high, which is the default.

What stream quality? [high or low]

Now this next step is the part of the setup that could potentially cause problems for some users. The song notify window(s) I use are raw and brute, unlike python where if you have it installed you call the object and BAM it's there... this system makes you choose between 3 programs that are not tied to "shell scripting".

  • xmessage (raw)
  • gxmessage (GTK2 implementation of xmessage)
  • kdialog (KDE based implementation of xmessage)

I suggest using kdialog, but read on. If you can run 'xmessage' from a command line you can use it... it's ugly and rude but it works. If your Debian based (or you have GTK2 installed on your distro) you may have access to gxmessage, try running 'gxmessage' from a command window and if it works in that case use it as it's probably the best option. Then, there is the kdialog option which is the one I tested and used most often. If you run KDE then you probably have it installed but be warned that on ONE of my 2 front ends if I tried to use my remote control while the kdialog was "popped up" on the screen it would hard-lock the front end the other front end with the same setup it works great. Now, choose if you even want to see a song name pop up screen. If you choose "N" skip down a few lines.

Do you want to see song info popup? [y or n]

Now we are asked what program we want to use to show the song info on our screen (see above rant about option you have here)

---------
You have 3 default options to manage your song popup window:
gxmessage, xmessage, kdialog
kdialog: KDE only.
xmessage: Any. looks cheezy, but it gets the job done.
gxmessage: GTK2 Only. Best option if you're on a Debian based distro.
---------
Which window program do you want to use? [ [1]gxmessage, [2]xmessage, [3]kdialog ]

Select 1, 2, or 3.

The wizard is done and the script is setup and ready for action.

*****
Your config is stored at: /home/mythtv/.xmonline/config
Initial setup is complete...
Run this command to test: xamp 48
Run this command to stop: xamp kill
Run setup again to rebuild your config.
Enjoy!

Test the scripts

Now, lets test a station.

$ xamp 48

You will see something like this returned

Logged in as: Jim Beam
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   568  100   568    0     0   3507      0 --:--:-- --:--:-- --:--:--     0
Stream URL: mms://a1029.l1265760918.c12657.g.lm.akamaistream.net/blah-blah-blah
[mythtv@masterbed01 bin]$ MPlayer dev-SVN-rUNKNOWN-4.1.1 (C) 2000-2006 MPlayer Team
CPU: Intel(R) Pentium(R) 4 CPU 2.40GHz (Family: 15, Model: 2, Stepping: 7)
CPUflags:  MMX: 1 MMX2: 1 3DNow: 0 3DNow2: 0 SSE: 1 SSE2: 1
Compiled with runtime CPU detection.

It doesn't matter what you see in this window as it won't matter when we run it in MythTV. The important thing is that you DON'T see a password failure. If you see a password failure first make sure you can access the XM site and then re-run the setup. If you don't hear a stream after 30 - 45 seconds try the command again (sometimes it doesn't grab the stream by the horns) if it doesn't work after 2 or 3 tries there may be a problem try running the setup again.

If all goes well, you should hear station 48 happily streaming out of your speakers. Congrats! Now I'll show you how to "properly" kill the stream.

$ xamp kill

Your stream and song name (if enabled) both should stop and go away. If so, perfect! If not, try the setup again or watch the command line for obvious errors. If your running these commands from an SSH window and you see something about "unable to connect to X server" that's normal as you don't have an x session started.


Setting up the MythTV GUI

At this point, you should be able to listen to (and kill) streams from the command line with no user intervention... that's 1/2 the battle. Now, we are going to hack a couple of buttons onto the default menu theme.


Note: If you are currently running .20+ chances are that you're using the default menu theme. No, not the actual MythTV theme, just the menu theme. To check out which one you're using do this in Myth: Utilities / Setup (or Setup) -> Setup -> Appearance -> and at the bottom of the first options page you will see the menu themes selection box, we will be hacking into "Default" so make sure it's set to that one. If you use classic or DVR you can change some of the commands below so that your work is being done on that particular theme (just add /themes/classic or /themes/DVR respectively to the "cd" commands below).

Backup the default theme

# cd /usr/share/mythtv
# tar cfvz default_backup.tar.gz *.xml

I use the v option because it's an easy way to verify (VIA verbose) what files were put into the tar ball.

Hack the default theme

I'm only going to show you the 2 required changes to get this hack to work.

I added the following to my mainmenu.xml file.

# cd /usr/share/mythtv
# vi mainmenu.xml
   <button>
      <type>MUSIC</type>
      <text>Play XM Radio</text>
      <action>MENU xmmenu.xml</action>
   </button>

Then, I created the xmmenu.xml file (be sure to add all of the streams you want access to):

# vi xmmenu.xml
<mythmenu name="XM">

   <button>
      <type>MUSIC</type>
      <text>Squizz-XL</text>
      <action>EXEC /usr/bin/xamp kill 48</action>
   </button>

   <button>
      <type>MUSIC</type>
      <text>Ethel</text>
      <action>EXEC /usr/bin/xamp kill 47</action>
   </button>

   <button>
      <type>MUSIC</type>
      <text>Top Tracks</text>
      <action>EXEC /usr/bin/xamp kill 46</action>
   </button>

   <button>
      <type>MUSIC</type>
      <text>The 80s</text>
      <action>EXEC /usr/bin/xamp kill 8</action>
   </button>

   <button>
      <type>MUSIC</type>
      <text>Top 20 on 20</text>
      <action>EXEC /usr/bin/xamp kill 20</action>
   </button>

   <button>
      <type>TV_DELETE</type>
      <text>Stop Listening</text>
      <action>EXEC /usr/bin/xamp kill</action>
   </button>

</mythmenu>

Here is a full list of all XM online channels as of April 25, 2007:

wget http://www.flyingsawdust.com/media/mythtv/xmradio/xmmenu.xml

Since you are a XM user you will either know the number of the stations you like best or know how to look them up. Here are my selections but you can add as many or as few as you want to the above xml file. Be sure to leave the "Stop Listening" button or else you won't be able to kill your streams from the MythTV GUI.

  • Squizz-XL (48)
  • Ethel (47)
  • Top Tracks (46)
  • The 80s (8)
  • Top 20 on 20 (20)

Tag definitions

OK, now the tag definitions for the above xml file

  • "button" tells the theme to paint a button on the screen
  • "type" tells the theme what image to use for the button
  • "text" tells MythTV what button text to put on the screen
  • "action" tells MythTV what to do when you select the button

Why it works

MythTV runs the EXEC command and it waits for a response before it releases the button. The script kicks off the stream and, if you want song names, it kicks off the script to read them in a background process and then tells MythTV that it's finished executing, thus releasing MythTV to do other things. You are going to have to modify these xml files if you want to add another language tag or if you want to add additional channels, it should be simple to see what needs to be done in order to make it work.

Additional Setup and Usage Notes

  1. Be patient after you choose a stream as sometimes it will take 30 - 45 seconds to start playing
  2. The stream will play until you choose the "Stop Listening" button on the GUI (or the 'xamp kill' script is executed)
  3. When you're listening to a stream, it locks up the audio output device for MythTV which can be good and it can be bad, see below.
GOOD
  • If you want to watch a Baseball game on TV and listen to the commentators from XM instead of the TV commentators
  • If for some strange reason you want to actually listen to music and watch MTV instead of listening to the crappy reality shows they play 21x7
BAD
  • If you wanted to play 2 audio streams at once to make your own mix tapes. ;-)

Troubleshooting

Digital Audio Tweaks

Note for those users using digital audio & s/pdif, I needed to change the PLAYER line to read

PLAYER="mplayer -really-quiet -nojoystick -nolirc -nomouseinput -ao alsa -srate 48000"

the default rate produced no audio.


Screen shots

The new default main menu: XM added main menu

The XM stream selection menu: XM Menu

xamp Scripts

#!/bin/bash
# Thanks to B. Galliart
# Modified by Elisamuel Resto <user00265@gmail.com>
# Added config file, broke off song lookup, 
# did a few other things, and tweaked for 
# MythTV usage by Josh <TwoOneSix@thatclothingco.com>

# The script will only work with a valid XM Online USER and PASS
# <Josh> 
# This has been tested with both a guest and a real XM account

################################################################
##### You no longer need to modify anything in this script #####
################################################################

# I like to use functions and config files in my code
# so I have added a dynamic variable function
# and moved most of the settings into a config file
XM_HOME="$HOME/.xmonline"
CONFIG="$XM_HOME/config"

USER=""
PASS=""
CHAN=$1
RATE="" 
# If your using MythTV: LEAVE THE BELOW COMMAND ALONE
# unless you know exactly what you're doing
PLAYER="mplayer -really-quiet -nojoystick -nolirc -nomouseinput -ao esd,alsa,oss"
NOSONGINFO=""
UPDATEDELAY=5
SONGEXE="xamp_song"

# A simple function to handle the config file
eatLine(){
	line="$@"
	export $line
}

windowWarn(){
	echo "---------"
	echo "You have 3 default options to manage your song popup window:"
	echo "gxmessage, xmessage, kdialog"
	echo "kdialog: KDE only."
	echo "xmessage: Any. looks cheezy, but it gets the job done."
	echo "gxmessage: GTK2 Only. Best option if you're on a Debian based distro."
	echo "---------"
	echo "Which window program do you want to use? [ [1]gxmessage, [2]xmessage, [3]kdialog ]"; read cfg_window
	case $cfg_window in
		1) echo "MESSENGER=gxmessage" >> $CONFIG ;;
		2) echo "MESSENGER=xmessage" >> $CONFIG ;;
		3) echo "MESSENGER=kdialog" >> $CONFIG ;;
		*) echo "I didn't understand, defaulting to 'xmessage'" ;;
	esac
}

if [ $1 = "setup" ]; then
	if [ ! -d $XM_HOME ] ; then
		mkdir $XM_HOME
	fi

	if [ ! -f $CONFIG ] ; then
		echo "No profile has been created yet... let's create one."
	else
		echo "Do you want to remove your existing config file? [y or n]"; read rm_config
		case $rm_config in
			y) rm -f $CONFIG ;;
			n) echo "${CONFIG} was not harmed in the execution of this command."; exit 0 ;;
			*) echo "Not sure what that was, but I'm out!"; exit 0;;
		esac
	fi
fi

# check for a config
if [ ! -f $CONFIG ] ; then
        # No config found... let's start one.
        touch $XM_HOME/config
	echo "****************************************************"
	echo "***WARNING: Password will be stored in plaintext!***"
	echo "****************************************************"
        echo "Enter your XM Online Username [example@example.com]:"; read xm_user
        echo "USER=$xm_user" >> $CONFIG; echo ""
        echo -n "Enter your XM Online password:"; stty -echo; read xm_pass; stty echo
        echo "PASS=$xm_pass" >> $CONFIG; echo ""
        echo "What stream quality? [high or low]"; read bit_rate
        case $bit_rate in
		high) echo "RATE=$bit_rate" >> $CONFIG; echo "" ;;
                low) echo "RATE=$bit_rate" >> $CONFIG; echo "" ;;
                *) echo "Not sure what that was, but I'm defaulting to high."; echo "RATE=high" >> $CONFIG; echo "" ;;
        esac
        echo "Do you want to see song info popup? [y or n]"; read song_info
	case $song_info in
		y) echo "NOSONGINFO=0" >> $CONFIG; windowWarn ;;
		n) echo "NOSONGINFO=1" >> $CONFIG ;;
		*) echo "Not sure what that was, but I'm disabling song info."; echo "NOSONGINFO=1" >> $CONFIG ;;
	esac
	echo "*****"
	echo "Your config is stored at: $CONFIG"
	echo "Initial setup is complete..."
	echo "Run this command to test: xamp 48"
	echo "Run this command to stop: xamp kill"
	echo "Run setup again to rebuild your config."
	echo "Enjoy!"
	exit 0
fi

# let's set our variables.
exec 3<&0
exec 0<$CONFIG
while read line
do
	eatLine $line
done
exec 0<&3
# </Josh>

if [ "x$USER" == "xUSER" ] ; then
	echo "You must modify the USER variable in the script" >&2
	exit 1
fi

if [ "x$PASS" == "xPASS" ] ; then
	echo "You must modify the PASS variable in the script" >&2
	exit 1
fi

if [ "x$CHAN" == "x" ] ; then
	echo "Must provide a channel number on the command line" >&2
	echo "Such as \"$0 22\" to play channel 22" >&2
	exit 1
fi

# <Josh>
# Here we add a flag that says we can take the "kill" command
# so that we can kill off a currently playing stream
if [ "$1" = "kill" ]; then
	# this is harsh!
	pkill -f 'mms://'
	pkill -f 'xamp_song'

	# this says we can pass a new channel after the kill command
	# but if we don't then it just exits the script
	if [ "$2" != "" ]; then
		CHAN=$2
	else
		exit 0
	fi
fi
# </Josh>

cd $XM_HOME
rm -f xmonline.cookies xmonlinelogin.out xmonlinestream.out xmonlinesong.out xmonlinesong.old
curl -s -c xmonline.cookies -d "user_id=$USER" -d "pword=$PASS" http://xmro.xmradio.com/xstream/login_servlet.jsp > xmonlinelogin.out
EXITCODE=$?

if [ $EXITCODE -ne 0 ] ; then
	echo "curl error exit value ${EXITCODE}" >&2
	exit $EXITCODE
fi

egrep "Invalid email and/or password" xmonlinelogin.out > /dev/null
if [ $? -eq 0 ] ; then
	echo "Invalid email and/or password" >&2
	exit 1
fi

egrep "[(]Not .*? " xmonlinelogin.out > /dev/null
if [ $? -eq 0 ] ; then
	echo -n "Logged in as: " >&2
	egrep "[(]Not .*? " xmonlinelogin.out | sed 's/.*[(]Not //;s/? .*//' >&2
fi
rm -f xmonlinelogin.out

curl -s -b xmonline.cookies -d "" "http://player.xmradio.com/player/2ft/playMedia.jsp?ch=$CHAN&speed=$RATE" > xmonlinestream.out
egrep "xmmediaplayer[.]URL = '" xmonlinestream.out > /dev/null
if [ $? -eq 0 ] ; then
	STREAM=`egrep "xmmediaplayer[.]URL = '" xmonlinestream.out | sed "s/.*xmmediaplayer[.]URL = '//;s/';.*//"`
else
	egrep "<PARAM NAME=\"FileName\" VALUE=\"" xmonlinestream.out > /dev/null
	if [ $? -eq 0 ] ; then
		STREAM=`egrep "<PARAM NAME=\"FileName\" VALUE=\"" xmonlinestream.out | sed "s/.*<PARAM NAME=\"FileName\" VALUE=\"//;s/\">.*//"`
	else
		echo "Error parsing HTML to find stream URL" >&2
		exit 1
	fi
fi

rm -f xmonlinestream.out
STREAM=`curl -A "Windows-Media-Player/10.00.00.3646" "${STREAM}" | grep 'mms://' | sed -e 's/.*\<Ref href=\"//' | sed -e 's/\"\/>//'`
echo "Stream URL: ${STREAM}" >&2

$PLAYER $STREAM &
PLAYERPID=$!

if [ $NOSONGINFO -eq 1 ] ; then
	exit 0
else
	$SONGEXE $CHAN $UPDATEDELAY $PLAYERPID $MESSENGER $XM_HOME &
fi
# cd /usr/bin
# vi xamp_song
#!/bin/bash
# By: Josh <TwoOneSix@thatclothingco.com>
# I had to break this portion of the 
# script out on it's own for multiple reasons

CHAN=$1
UPDATEDELAY=$2
PLAYERPID=$3
MESSENGER=$4

cd $5
# create my functions to handle the different popup managers
fnc_gxmessage(){
gxmessage "`egrep '<artist>|<album>|<songtitle>|<channelnumber>|<channelname>' xmonlinesong.out | sed 's/<\/[a-z]*>//' | sed 's/^..<artist>/ Artist: /' | sed 's/^..<album>/ Album: /' | sed 's/^..<songtitle>/ Song Title: /' | sed 's/^..<channelnumber>/ Channel #: /' | sed 's/^..<channelname>/ Channel Name: /'`" -nofocus -title "Song Notification" -borderless -timeout 15 -center
}

fnc_xmessage(){
xmessage "`egrep '<artist>|<album>|<songtitle>|<channelnumber>|<channelname>' xmonlinesong.out | sed 's/<\/[a-z]*>//' | sed 's/^..<artist>/ Artist: /' | sed 's/^..<album>/ Album: /' | sed 's/^..<songtitle>/ Song Title: /' | sed 's/^..<channelnumber>/ Channel #: /' | sed 's/^..<channelname>/ Channel Name: /'`" -title "Song Notification" -timeout 15 -center
}

fnc_kdialog(){
kdialog --title "Song Notification" --passivepopup "`egrep '<artist>|<album>|<songtitle>|<channelnumber>|<channelname>' xmonlinesong.out | sed 's/<\/[a-z]*>//' | sed 's/^..<artist>/ Artist: /' | sed 's/^..<album>/ Album: /' | sed 's/^..<songtitle>/ Song Title: /' | sed 's/^..<channelnumber>/ Channel #: /' | sed 's/^..<channelname>/ Channel Name: /'`" 15
}

while [ true ] ; do
        curl -s -b xmonline.cookies -d "" -H "Pragma: no-cache" "http://player.xmradio.com/padData/pad_data_servlet.jsp?channel=$CHAN&rnd=$RANDOM" > xmonlinesong.out
        egrep "<artist>|<album>|<songtitle>|<channelnumber>|<channelname>" xmonlinesong.out > /dev/null
        if [ $? -ne 0 ] ; then
                echo "Error parsing html to find song info" >&2
                exit 1
        fi

        if [ -f xmonlinesong.old ] ; then
                DIFF=`comm -3 xmonlinesong.out xmonlinesong.old | wc -l`
        else
                DIFF=1
        fi

        if [ $DIFF -gt 0 ] ; then
		# dump the variable to kdialog
        	case $MESSENGER in
                	gxmessage) fnc_gxmessage ;;
	                xmessage) fnc_xmessage ;;
        	        kdialog) fnc_kdialog ;;
                	*) echo "I didn't understand, defaulting to 'xmessage'"; fnc_xmessage ;;
	        esac
        fi

        sleep $UPDATEDELAY
        mv xmonlinesong.out xmonlinesong.old
        ( kill -0 $PLAYERPID 2>&1 ) > /dev/null
        if [ $? -eq 1 ] ; then
                echo "Player ended" >&2
                rm -f xmonlinesong.old
                exit 0
        fi
done
Personal tools