Fm radio

From MythTV Official Wiki
Revision as of 02:15, 19 March 2012 by Nekksys (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This article is to provide information on how to integrate FM radio into MythTV. This is based on Integrate Sirius but I wanted to post details on how to make it work for FM radio too.

I only have a Hauppage PVR-150 card. I cannot speak to other setups, but please feel free to edit this page to include information for others.


Important.png Note: The method used here will only work on a mythbox that has an FM Radio card (such as a PVR-150) installed locally. It does not matter if it is only a frontend box or a backend+frontend box, but the hardware must be in the box you are setting this up on.


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


Article from 10,000 feet

What this article is...

This article IS about:

  • Setting up MythTV to play FM Radio from a Hauppage Wintv PVR-150
  • How-To use programs 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 perfectly integrate with your particular MythTV GUI (we only cover the default menu theme)
  • An FM Radio Plug-in for MythTV
  • An audio stream capture how-to

What is required

Only a working installation of MythTV is required with a working PVR-150. Also you must be able to receive and play an FM signal on your PVR-150. To verify this do the following:

# ivtv-radio -s

This will scan the FM band for channels. Next do the following:

# ivtv-radio -f <frequency of channel>

for example:

# ivtv-radio -f 103.3

if this does not work, please see the [web page] for detail on how to make this work and return here when you have this working.

Hacking it together

OK, now we are going to write a couple of über-simple shell scripts that we will use to make MythTV work with your FM tuner. You will notice that these are simple, novice scripts that are pretty crude. This hasn't been called it a "hack" for nothing.

Create files

We need to create a couple of files so find a nice place you can create and execute them from. Personally, I put them in /usr/bin

# vi mythfm
#!/bin/bash
# Control PVR-150 FM in Myth

if [ "$1" = "wbfo" ]; then
        # First, we'll kill off any other stream that may be playing
        /usr/bin/mythfm_kill
        echo "I'm about to play:" $1
        /usr/local/bin/ivtv-radio -f 88.7 &

elif [ "$1" = "wbuf" ]; then
        # First, we'll kill off any other stream that may be playing
        /usr/bin/mythfm_kill
        echo "I'm about to play:" $1
        /usr/local/bin/ivtv-radio -f 92.9 &

else
        exit 1
fi
exit 0

You are going to want to change this for the stations you want. Add more "elif" statements to add more stations. Change the first line of each statement to include the callsign of the station and change the last line of each to add the station's FM frequency.


# vi mythfm_kill
#!/bin/bash
# Kill mythfm

pkill -f aplay

Now you will want to make them both executable:

# chmod a+x mythfm*

Test scripts

Now, pull up a command window and run one of the commands we just "made"

$ mythfm wbfo

Do you hear the stataion without having to enter a single thing in the command window? That's good, now use this to kill the stream

$ mythfm_kill

V4L-Based Radios

The following combined tune/kill script uses a more general approach that works for v4l-based radio devices. The basic idea here is that we first configure the tuner for the station we want, then capture from the radio device and forward to the output device. This method requires that you have fmtools and sox installed. For this to work you must also have alsa-oss support working. This can also be done with pure alsa (look at the sox manpage) but using oss was easier for me to get working. Save the following script to /usr/local/bin/mythfm then replace calls to "mythfm_kill" in the menus created below with "mythfm kill". It should be fairly obvious how to add stations to this script and add them to the menus.

-- work(dot)eric(at)gmail(dot)com

#!/bin/bash

# tune radio
function fmtune {
  fm -q -T- $1 on > /dev/null &
  sleep 1
  sox -q -r 32000 -w -c 2 -t ossdsp /dev/audio1 \
         -r 44100 -w -c 2 -t ossdsp /dev/audio &
}

# kill radio
function fmkill {
  killall -q /usr/bin/sox
  sleep 1
  killall -q /usr/bin/fm
}

# Station: Jack FM (93.1 MHz)
if [ "$1" = "jack" ] ; then
  echo "Tuning to Jack FM"
  fmkill ; sleep 1 ; fmtune 93.1

# Station: Star (98.7 MHz)
elif [ "$1" = "star" ] ; then
  echo "Tuning to Star"
  fmkill ; sleep 1 ; fmtune 98.7

# Station: Kill Radio
elif [ "$1" = "kill" ] ; then
  echo "Turning Off Radio"
  fmkill ; sleep 1 ; fm -q off &

else

  # print usage statement
  echo "Usage:" `basename $0` "[station]"
  echo "  stations: jack star kill"
  exit 1

fi

exit 0

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.


Important.png Note: If you are currently running MythTV version 0.20 or higher 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 Radio</text>
      <action>MENU fmmenu.xml</action>
   </button>

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

# vi fmmenu.xml


Warning.png Warning: The following code is wrong. Instead of using EXEC, the <action> should use EXECTV, which will pass as an argument to the script the video device that should be used. Then, the script mythfm should be modified to use the argument to detect which card should be used and tune the radio on that card. By using EXECTV, the <action> tells MythTV that the tuner it provides is not available for any recordings.

<mythmenu name="FMMENU">

   <button>
      <type>MUSIC</type>
      <text>88.7 - WBFO - NPR</text>
      <action>EXEC /usr/bin/mythfm wbfo</action>
   </button>

   <button>
      <type>MUSIC</type>
      <text>92.9 - WBUF - Jack FM</text>
      <action>EXEC /usr/bin/mythfm wbuf</action>
   </button>

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

</mythmenu>

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

You have to wrap mythfm around the stream because when MythTV runs the EXEC it waits for a response before it releases the button. mythfm simply kicks off ivtv-radio and tells MythTV that it's finished executing. You are going to have to modify this file if you want to add another language tag or if you want to add additional channels, it should be simple to see what needs done to make it work just be sure that you create the soft links before you try to add a button or it won't play the stream.


Additional Setup and Usage Notes

  1. The stream will play until you choose the "Stop Listening" button on the GUI (or the mythtv_kill script is executed)
  2. When you're listening to a station, it locks up the Video Card device for MythTV which. This means that you are using up one of your 'inputs' for video recording or watching TV. You must have more tuner cards in order to listen to FM on a PVR-150 and watch video at the same time.
  3. With MythDora 4.0 ivtv-radio is in /usr/bin. Modify scripts accordingly.
  4. If you have 2 PVR-150s then the radio may be on /dev/radio1. If so, add -d /dev/radio1 to the ivtv-radio lines. If the radio is at /dev/radio1 then the PCM device to use is /dev/video25. Add -i /dev/video25 to use this PCM device.

Screen shots

The new default main menu: Main Menu

The FM station selection menu: FM Menu


Alternative (Only for IVTV)

There are several issues with the method described above, like

  • MythTV does not know that the tuner is busy and might try to use it
  • Not being able to schedule radio recordings

The solution is to add the radio as a video device to MythTV. This allows you to control the radio as a normal channel in MythTV.

In mythtv-setup, add a new Video Source called radio.

Under Input Connections, set the Composite source (of the tuner card with the radio) to radio. Set all External Channel Commands for that tuner to "/usr/local/sbin/mythtv-fm.sh".

For each radio station/frequency that you want to be able to tune in to, you need to add a channel in the Channel Editor. Set the frequency to the 10 times the frequency. For example, if the FM frequency is 102.1, set it to 1021 in the Channel Editor.

And here is the script:

# vi /usr/local/sbin/mythtv-fm.sh
#!/bin/sh -x

channel=${1:0}
radio=/dev/radio0
video=/dev/video0
log=/var/log/mythtv/mythtv-fm.log
#log=/dev/null

echo Closing any ivtv-radio applications >> $log

if [ "$channel" -lt 800 ]; then
        pkill -f ivtv-radio
        echo Not changing to channel $channel >> $log
elif [ "$channel" -gt 1100 ]; then
        int=$(($channel / 1000))
        echo Changing video freq to $int >> $log
        pkill -f ivtv-radio && sleep 1 && /usr/bin/ivtv-tune -d $video -f $int >> $log && sleep 1 || /usr/bin/ivtv-tune -d $video -f $int >> $log
else
        int=$(($channel / 10))
        frac=$(($channel - 10 * $int))
        freq=`printf "%d.%d" $int $frac`
        echo Changing FM freq to $freq >> $log
        pkill -f ivtv-radio && sleep 1
        ivtv-radio -d $radio -f $freq -j >> $log &
fi

exit 0

You will need to change /dev/radio0 and /dev/video0 to your radio and video devices. To disable logging, uncomment the #log line.

Basically what is happening now is that all your channel change requests for that tuner is handled by this script. It first kills any ivtv-radio processes. It then checks the frequency and if the frequency is too high for FM, it is assumed to be TV and the ivtv-tune is called to change the TV channel. If the frequency is too low, it is just ignored.

This is based on http://readlist.com/lists/mythtv.org/mythtv-users/3/15176.html.