Skip to content

Instantly share code, notes, and snippets.

@ednisley
Last active June 15, 2016 15:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ednisley/6760b4ebab068c5c89acbacaf6db6045 to your computer and use it in GitHub Desktop.
Save ednisley/6760b4ebab068c5c89acbacaf6db6045 to your computer and use it in GitHub Desktop.
Python source code: Raspberry Pi Streaming Radio Player
from evdev import InputDevice,ecodes,KeyEvent
import subprocess32 as subprocess
import select
import re
import sys
import time
Media = {'KEY_KP7' : ['Classical',['mplayer','-playlist','http://stream2137.init7.net/listen.pls']],
'KEY_KP8' : ['Jazz',['mplayer','-playlist','http://stream2138.init7.net/listen.pls']],
'KEY_KP9' : ['WMHT',['mplayer','http://live.str3am.com:2070/wmht1']],
'KEY_KP4' : ['Classic 1000',['mplayer','-playlist','http://listen.radionomy.com/1000classicalhits.m3u']],
'KEY_KP5' : ['DCNY 911',['mplayer','-playlist','http://www.broadcastify.com/scripts/playlists/1/12305/-5857889408.m3u']],
'KEY_KP6' : ['WAMC',['mplayer','http://pubint.ic.llnwd.net/stream/pubint_wamc']],
'KEY_KP1' : ['60s',['mplayer','-playlist','http://listen.radionomy.com/all60sallthetime-keepfreemusiccom.m3u']],
'KEY_KP2' : ['50-70s',['mplayer','-playlist','http://listen.radionomy.com/golden-50-70s-hits.m3u']],
'KEY_KP3' : ['Soft Rock',['mplayer','-playlist','http://listen.radionomy.com/softrockradio.m3u']],
'KEY_KP0' : ['Zen',['mplayer','-playlist','http://listen.radionomy.com/zen-for-you.m3u']]
}
CurrentKC = 'KEY_KP7'
Controls = {'KEY_KPSLASH' : '//////',
'KEY_KPASTERISK' : '******',
'KEY_KPENTER' : ' ',
'KEY_KPMINUS' : '<',
'KEY_KPPLUS' : '>',
'KEY_VOLUMEUP' : '*',
'KEY_VOLUMEDOWN' : '/'
}
MuteDelay = 5.5 # delay before non-music track; varies with buffering
UnMuteDelay = 7.3 # delay after non-music track
MixerChannel = 'PCM' # which amixer thing to use
# set up event inputs and polling objects
# This requires some udev magic to create the symlinks
k = InputDevice('/dev/input/keypad')
k.grab()
kp = select.poll()
kp.register(k.fileno(),select.POLLIN + select.POLLPRI + select.POLLERR)
v = InputDevice('/dev/input/volume')
v.grab()
vp = select.poll()
vp.register(v.fileno(),select.POLLIN + select.POLLPRI + select.POLLERR)
# set up files for mplayer pipes
lw = open('/tmp/mp.log','w') # mplayer piped output
lr = open('/tmp/mp.log','r') # ... reading that output
# set the mixer output low enough that the initial stream won't wake the dead
subprocess.call(['amixer','sset',MixerChannel,'10'])
# Start the player with the default stream
print 'Starting mplayer on',Media[CurrentKC][0],' -> ',Media[CurrentKC][-1][-1]
p = subprocess.Popen(Media[CurrentKC][-1],
stdin=subprocess.PIPE,stdout=lw,stderr=subprocess.STDOUT)
print ' ... running'
#--------------------
#--- Play the streams
while True:
# pluck next line from mplayer and decode it
text = lr.readline()
if 'ICY Info: ' in text: # these lines may contain track names
trkinfo = text.split(';') # also splits at semicolon embedded in track name
for ln in trkinfo:
if 'StreamTitle' in ln: # this part contains a track name
if 2 == ln.count("'"): # exactly two single quotes = probably none embedded in track name
trkhit = re.search(r"StreamTitle='(.*)'",ln)
if trkhit: # true for valid search results
TrackName = trkhit.group(1) # the string between the two quotes
print 'Track name: ', TrackName
if ('' == TrackName or 'TargetSpot' in TrackName) and 'radionomy' in Media[CurrentKC][-1][-1]:
print ' ... muting empty Radionomy track'
time.sleep(MuteDelay)
subprocess.call(['amixer','-q','sset',MixerChannel,'mute'])
else:
print ' ... unmuting'
time.sleep(UnMuteDelay)
subprocess.call(['amixer','-q','sset',MixerChannel,'unmute'])
else:
print ' ... semicolon in track name: ', ln
else:
print ' ... quotes in track name: ', ln
elif 'Exiting...' in text:
print 'Got EOF / stream cutoff'
print ' ... killing dead mplayer'
p.kill()
print ' ... flushing pipes'
lw.truncate(0)
print ' ... discarding keys'
while [] != kp.poll(0):
kev = k.read
print ' ... restarting mplayer: ',Media[CurrentKC][0]
p = subprocess.Popen(Media[CurrentKC][-1],
stdin=subprocess.PIPE,stdout=lw,stderr=subprocess.STDOUT)
print ' ... running'
continue
# accept pending events from volume control knob
if [] != vp.poll(10):
vev = v.read()
for e in vev:
if e.type == ecodes.EV_KEY:
kc = KeyEvent(e).keycode
# print 'Volume kc: ',kc
if kc in Controls:
print 'Vol Control: ',kc
try:
p.stdin.write(Controls[kc])
except Exception as e:
print "Can't send control: ",e
print ' ... restarting player: ',Media[CurrentKC][0]
p = subprocess.Popen(Media[CurrentKC][-1],
stdin=subprocess.PIPE,stdout=lw,stderr=subprocess.STDOUT)
print ' ... running'
# accept pending events from keypad
if [] != kp.poll(10):
kev = k.read()
for e in kev:
if e.type == ecodes.EV_KEY:
kc = KeyEvent(e).keycode
if kc == 'KEY_NUMLOCK':
continue
# print 'Got: ',kc
if (kc == 'KEY_BACKSPACE') and (KeyEvent(e).keystate == KeyEvent.key_hold):
if True:
print 'Backspace = shutdown!'
p = subprocess.call(['sudo','shutdown','-HP','now'])
else:
print 'BS = bail from main, ssh to restart!'
sys.exit(0)
if KeyEvent(e).keystate != KeyEvent.key_down:
continue
if kc in Controls:
print 'Control:', kc
try:
p.stdin.write(Controls[kc])
except Exception as e:
print "Can't send control: ",e
print ' ... restarting player: ',Media[CurrentKC][0]
p = subprocess.Popen(Media[CurrentKC][-1],
stdin=subprocess.PIPE,stdout=lw,stderr=subprocess.STDOUT)
print ' ... running'
if kc in Media:
print 'Switching stream to ',Media[kc][0],' -> ',Media[kc][-1][-1]
CurrentKC = kc
print ' ... halting player'
try:
p.communicate(input='q')
except Exception as e:
print 'Perhaps mplayer died?',e
print ' ... killing it for sure'
p.kill()
print ' ... flushing pipes'
lw.truncate(0)
print ' ... restarting player: ',Media[CurrentKC][0]
p = subprocess.Popen(Media[CurrentKC][-1],
stdin=subprocess.PIPE,stdout=lw,stderr=subprocess.STDOUT)
print ' ... running'
print 'Out of loop!'
@ednisley
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment