UPDATE: http://pyther.net/blog/index.php/2010/08/iheartradio-command-line-mplayer/
If you have ever listened to any Clear Channel FM radio station then I am sure you have heard the ads to listen to the station online through iheartradio. The only problem is that iheartradio is a bulky and slow flash application. On a powerful desktop that isn’t a huge issue, but with my N900 (600mhz cpu, 256MB Ram) it takes over 5 minutes to start streaming the radio station. Of course, iheartradio has an application for the iPod and Blackberry, but no app for the N900.
I went on a quest to figure out how to listen to iheartradio without the bulky flash application and this is what I found.
Step 1:
The url of the a stations stream is can be found in a XML file, at URL “http://p2.STATION_NAME.ccomrcdn.com/player/player_dispatcher.html?section=radio&action=listen_live”
If I want to listen to The Fox (call letters: WTFX-FM), the URL of the XML would be “http://p2.wtfx-fm.ccomrcdn.com/player/player_dispatcher.html?section=radio&action=listen_live”
Open up the url in a web browser and grab the rtmp url which is between the <stream> tags. rtmp://cp21366.live.edgefcs.net/live/Lou_KY_WTFX-FM_OR@s7696?auth=daEcEbgdNb4a3bdcKdYcrcgcGara0c1c3cZ-bmC7wi-4q-LM3Y9_7nqEDps4CCulBtyp&aifp=1234&CHANNELID=981&CPROG=_&MARKET=LOUISVILLE-KY&REQUESTOR=WTFX-FM&SERVER_NAME=p2.wtfx-fm.ccomrcdn.com&SITE_ID=2038&STATION_ID=WTFX-FM&MNM=2&TYPEOFPLAY=0
Step 2:
Download and Install rtmpdump and mplayer
- Use your distro’s repositories
- rtmpdump is in AUR (archlinux)
Step 3:
Lastly open up the terminal and enter the following command: rtmpdump -r $RTMPURL -v | mplayer -
-r tells rtmpdump the url of the stream
-v tells rtmpdump that the stream is a live stream
The | (pipe) directs stdin to mplayer and the – after mplayer tells mplayer to read data from stdin
Example: rtmpdump -r "rtmp://cp21366.live.edgefcs.net/live/Lou_KY_WTFX-FM_OR@s7696?auth=daEcEbgdNb4a3bdcKdYcrcgcGara0c1c3cZ-bmC7wi-4q-LM3Y9_7nqEDps4CCulBtyp&aifp=1234&CHANNELID=981&CPROG=_&MARKET=LOUISVILLE-KY&REQUESTOR=WTFX-FM&SERVER_NAME=p2.wtfx-fm.ccomrcdn.com&SITE_ID=2038&STATION_ID=WTFX-FM&MNM=2&TYPEOFPLAY=0" -v | mplayer -
Things to watch out for:
- The RTMP url may change/expire. I have not been able to confirm this yet, but if the RTMP url changes you will simply need to open the url of the xml file (step 1) and copy the new rtmp url
Sources:
Maybe when I get some more time and become more ambitious I will write a small python wrapper that will extract the url from the xml file and start the stream.
A few months ago, I was talking to a friend and he wanted to share some files with me. However, we had no easy of doing this. Pondering about the problem, I though it would be great if there was a uploader with some basic user authentication. This brought about the birth of uploader. My biggest problem that I faced was the fact that I had no idea how to work with sessions and sqlite databases. That didn’t stop me though! During winter break and I went to tackle the challenge.
After digging through a lot of examples on the webpy.org website, I was eventually able to throw together something that worked. Winter break ended, the program was usable, and was left, without love, on my server.
Just last week, I started to play with uploader again and I noticed that the code was a disaster and confusing. So I started to rewrite the parts of the code that were bad and added comments. Since I already stumbled with sessions and database objects I had a much better understanding on how they worked and how to implement them into the code. During the last three days I have released uploader.
Github Page: http://github.com/pyther/uploader
Project Page: http://pyther.net/projects/uploader/
Screenshots:
With Kernel 2.6.26.32-rc6 suspend-2-ram (aka sleep/standby) finally works on my machine! However OSSv4 does not support suspend/hibernate which means that OSS must be unloaded.
This scripts does the following:
- Stop/Start specific Daemons
- Stop/Starts specific Programs
- Informs you of any programs that are preventing OSS from unloading
In my case I have the script stop mpd. Then it kills ossxmix and attempts to unload oss. On spawn it starts mpd again and loads ossxmix.
Here it is:
oss_s.py
#!/usr/bin/env python
import subprocess
import sys
import os
#Daemons that need to be stopped
daemons=('mpd',)
#Programs that are safe to kill
kill_apps=('ossxmix','vlc','mplayer','xine','xmms','audacious',)
#Programs to load on spawn/resume
load_apps=('ossxmix -xb',)
#User to start apps as
user='pyther'
def start():
p=subprocess.Popen(['soundon'])
p.wait()
for d in daemons:
p=subprocess.Popen(['/etc/rc.d/' + d, 'start'])
p.wait()
for a in load_apps:
#Load the program as a user, not root
os.system('sudo su -c \'' + a + ' &\' ' + user)
return
def stop():
for d in daemons:
p=subprocess.Popen(['/etc/rc.d/' + d, 'stop'])
p.wait()
for a in kill_apps:
p=subprocess.Popen(['killall',a])
p.wait()
o=subprocess.Popen(['soundoff'],stdout=subprocess.PIPE)
output=o.stdout.readlines()
list=[]
for line in output:
#If the line is empty skip it
line = line.rstrip("\n")
if line == '':
pass
#Otherwise lets split the line by spaces
else:
line=line.rsplit(' ')
#Going to see if the first word is an int
try:
pid=int(line[0])
except ValueError:
#Must not be an int
pass
#Good it is an int... lets continue
else:
app=line[1] #The second word is the name of the app
#If the list has no values, we will add the first running program
if len(list) == 0:
list.append([pid,app])
#Now lets check and see if the pid is already in the list
else:
inList=0 #Set to False by default
#Scanning items already in the list
#If we find a match we set inList to True and break out of the loop
for x in list:
if int(x[0]) == int(pid):
inList=1
break
if not inList:
list.append([pid,app])
if list:
print("Apps that need to be killed:")
for x in list:
pid=x[0]
app=x[1]
subprocess.Popen(['notify-send', '-u', 'normal', '-i', 'audio-card', '-t', '120000', 'PID: ' + str(pid) + ' is using OSS', str(pid) + ' - ' + app + '\nPlease kill this application.' ])
print("PID: " + str(pid) + " - " + app)
#Exit abnormally
sys.exit(1)
return
if __name__ == "__main__":
if len(sys.argv) <= 1:
print("Usage: start or stop")
sys.exit(1)
if os.geteuid() != 0:
print "You must be root to run this script."
sys.exit(1)
if sys.argv[1] == "start":
start()
elif sys.argv[1] == "stop":
stop()
else:
print "Usage: start or stop"
Usage is simple enough:
./oss_s.py start
./oss_s.py stop
Then to get the script to run on suspend/wake:
Save this as /etc/pm/sleep.d/48oss
#!/bin/bash
case $1 in
hibernate)
/home/pyther/bin/oss_s.py stop
;;
suspend)
/home/pyther/bin/oss_s.py stop
;;
thaw)
/home/pyther/bin/oss_s.py start
;;
resume)
/home/pyther/bin/oss_s.py start
;;
esac
Then make it executable
chmod +x /etc/pm/sleep.d/48oss
Of course you will have to modify the code as necessary.