All pastes #1504715 Raw Edit

Mine

public text v1 · immutable
#1504715 ·published 2009-07-23 18:55 UTC
rendered paste body
#!/usr/bin/env python

# PyRadio: Curses based Internet Radio Player
# http://www.coderholic.com/pyradio
# Ben Dowling - 2008

import os
import sys
import curses
import thread
import subprocess

stations = [
	("S K Y . F M - Roots Reggae", "http://scfire-ntc-aa01.stream.aol.com:80/stream/1017"),
	("Radio Caraibes", "http://91.121.142.31:8000"),
	("Tim's Radio - flamencoradio.net", "http://flamencoradio.net:8100"),
	("Afterhours.FM (Trance/Progressive)", "http://at2.ah.fm:80"),	
	("BBC Radio 1", "mms://wmlive-acl.bbc.co.uk/wms/radio1/radio1_nb_e1s1"),
	("Digitally Imported: Chillout", "http://di.fm/mp3/chillout.pls"),
	("Digitally Imported: Trance", "http://di.fm/mp3/trance.pls"),
	("Digitally Imported: Classic Techno", "http://di.fm/mp3/classictechno.pls"),
	("Electronic Culture", "http://www.shouted.fm/tunein/electro-dsl.m3u"),
	("Frequence 3 (Pop)", "http://streams.frequence3.net/hd-mp3.m3u"),
	("Mostly Classical", "http://www.sky.fm/mp3/classical.pls"),
	("Proton Radio (House/Dance)", "http://www.protonradio.com:8000"),
	("Ragga Kings", "http://www.raggakings.net/listen.m3u"),
	("Secret Agent (Downtempo)", "http://somafm.com/secretagent.pls"),
	("Slay Radio (C64 Remix)", "http://sc.slayradio.org:8000/listen.pls"),
	("Smooth FM (Jazz)", "http://66.55.143.195:9028"),
	("SomaFM: Groove Salad", "http://somafm.com/startstream=groovesalad.pls"),
	("SomaFM: Beat Blender", "http://somafm.com/startstream=beatblender.pls"),
	("SomaFM: Cliq Hop", "http://somafm.com/startstream=cliqhop.pls"),
	("SomaFM: Sonic Universe", "http://somafm.com/startstream=sonicuniverse.pls"),
	("SomaFM: Tags Trance Trip", "http://somafm.com/tagstrance.pls"),
	("Virgin Radio (Pop)", "http://www.smgradio.com/core/audio/mp3/live.pls?service=vrbb"),
]

class Log(object):
	""" Log class that outputs text to a curses screen """	

	def __init__(self, cursesScreen):	
		self.cursesScreen = cursesScreen
		self.width = cursesScreen.getmaxyx()[1] - 5
	def write(self, str):
		self.cursesScreen.erase()		
		self.cursesScreen.addstr(0, 1, str[0: self.width].replace("\r", "").replace("\n", ""))
		self.cursesScreen.refresh()

	def readline(self):
		pass

class Player(object):
	""" Media player class. Playing is handled by mplayer """
	process = None

	def __init__(self, outputStream):
		self.outputStream = outputStream

	def __del__(self):
		self.close()

	def updateStatus(self):
		try:
			input = self.process.stdout.readline()
			while(input != ''):
				self.outputStream.write(input)
				input = self.process.stdout.readline()
		except: pass

	def play(self, url):
		self.close()
		self.process = subprocess.Popen(["mplayer", "-quiet", url], shell=False, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
		thread.start_new_thread(self.updateStatus, ())

	def sendCommand(self, command):
		if(self.process != None):
			try:
				self.process.stdin.write(command)
			except: pass
			
	def mute(self):
		self.sendCommand("m")

	def pause(self):
		self.sendCommand("p")
	
	def close(self):
		self.sendCommand("q")
		if self.process != None:
			os.kill(self.process.pid, 15)
			self.process.wait()
		self.process = None

class PyRadio(object):
	startPos = 0
	selection = 0

	def setup(self, stdscr):
		self.stdscr = stdscr

		try:
			curses.curs_set(0)
		except:
			pass

		curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK)
		curses.init_pair(2, curses.COLOR_BLUE, curses.COLOR_BLACK)
		curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK)
		curses.init_pair(4, curses.COLOR_GREEN, curses.COLOR_BLACK)
		curses.init_pair(5, curses.COLOR_WHITE, curses.COLOR_BLACK)
		curses.init_pair(6, curses.COLOR_BLACK, curses.COLOR_MAGENTA)
		curses.init_pair(7, curses.COLOR_BLACK, curses.COLOR_GREEN)

		self.maxY, self.maxX = stdscr.getmaxyx()

		self.headWin = curses.newwin(1, self.maxX, 0, 0)
		self.bodyWin = curses.newwin(self.maxY-2, self.maxX, 1, 0)
		self.footerWin = curses.newwin(1, self.maxX, self.maxY-1, 0)
		self.initHead()
		self.initBody()
		self.initFooter()

		self.log = Log(self.footerWin)
		self.player = Player(self.log)

		curses.doupdate()

		self.run()

	def initHead(self):
		info = " PyRadio 0.1 "
		self.headWin.addstr(0, 0, info, curses.color_pair(4))
		rightStr = "www.coderholic.com/pyradio"
		self.headWin.addstr(0, self.maxX - len(rightStr) - 1, rightStr, curses.color_pair(2))
		self.headWin.bkgd(' ', curses.color_pair(7))
		self.headWin.noutrefresh()

	def initBody(self):
		""" Initializes the body/story window """
		self.bodyWin.timeout(100)
		self.bodyWin.keypad(1)
		self.bodyMaxY, self.bodyMaxX = self.bodyWin.getmaxyx()
		self.bodyWin.noutrefresh()
		self.refreshBody()

	def initFooter(self):
		""" Initializes the body/story window """
		self.footerWin.bkgd(' ', curses.color_pair(7))
		self.footerWin.noutrefresh()

	def refreshBody(self):
		self.bodyWin.erase()
		self.bodyWin.box()		
	
		self.bodyWin.move(1, 1)
		maxDisplay = self.bodyMaxY - 1
		for idx in range(maxDisplay - 1):
			if(idx > maxDisplay): break			
			try:
				station = stations[idx + self.startPos]
				col = curses.color_pair(5)
				if idx + self.startPos == self.selection: 
					col = curses.color_pair(6)
					self.bodyWin.hline(idx + 1, 1, ' ', self.bodyMaxX - 2, col)
				self.bodyWin.addstr(idx + 1, 1, station[0], col)

			except IndexError:
				break

	def run(self):
		while True:
			try:
				c = self.bodyWin.getch()
				ret = self.keypress(c)
				if (ret == -1): return
			except KeyboardInterrupt:
				break

	def keypress(self, char):
		if char == curses.KEY_EXIT or char == ord('q'):
			self.player.close()
			return -1

		elif char in (curses.KEY_ENTER, ord('\n'), ord('\r')):
			url = stations[self.selection][1]
			self.player.play(url)
			return
		elif char == curses.KEY_DOWN or char== ord('j'):
			if self.selection < len(stations) - 1:
				if self.selection - self.startPos > (self.bodyMaxY - 4):
					self.startPos += 1				
				self.selection += 1
				self.refreshBody()
			return
		elif char == curses.KEY_UP or char == ord('k'):
			# Scroll stories up by one
			if self.selection > 0:
				self.selection -= 1
				if self.selection < self.startPos:
					self.startPos -= 1
				self.refreshBody()
			return
		elif char == ord('m'):
			self.player.mute()
			return

if __name__ == "__main__":
	pyRadio = PyRadio()
	curses.wrapper(pyRadio.setup)