#! /usr/bin/env python # Copyright (c) 2004 Brian Dam Pedersen # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import re import os import popen2 import sys import threading import select import time mpgcmd="mpg123 -y -s $URL" playcmd="aplay -f cd" class Player(object): def __init__(self): self.playing=0 self.url_list=[] self.url_list_lock=threading.Lock() def play(self,url,retries=5): def play_worker(): irun=1 mpg=popen2.Popen3(mpgcmd.replace("$URL",url), 0,1024) alsa=popen2.Popen3(playcmd,0,1024) retry=retries while self.playing and irun: w=os.waitpid(mpg.pid,os.WNOHANG) if w[0]==mpg.pid: if retry==0: irun=0 print "ERROR: max retries reached" else: mpg=popen2.Popen3(mpgcmd.replace("$URL",url), 0,1024) retry-=1 print "Retry %d" % (retries-retry) continue res=select.select([mpg.fromchild],[],[],3.) if not res: print "ERROR: No response from mpeg player" try: os.kill(mpg.pid,9) except: pass if retry==0: irun=0 else: mpg=popen2.Popen3(mpgcmd.replace("$URL",url), 0,1024) retry-=1 continue data=mpg.fromchild.read(1024) alsa.tochild.write(data) if irun: os.kill(mpg.pid,9) os.kill(alsa.pid,9) print "Done" self.playing=1 self.play_thread=threading.Thread(target=play_worker) self.play_thread.start() def play_list(self,url_list,notifier=None): def play_list_worker(): while self.url_list: self.url_list_lock.acquire() if not self.url_list: self.url_list_lock.release() break t=self.url_list[0] self.url_list=self.url_list[1:] self.url_list_lock.release() if type(t)==type([]): title=t[1] if notifier: notifier(title) t=t[0] self.play(t) self.play_thread.join() self.url_list_lock.acquire() self.url_list=url_list[:] self.url_list_lock.release() self.play_list_thread=threading.Thread(target=play_list_worker) self.play_list_thread.start() def stop(self): self.url_list_lock.acquire() self.url_list=[] self.url_list_lock.release() self.skip() def skip(self): self.playing=0 if __name__=="__main__": # Parse the playlist file try: pls=open(sys.argv[1]).readlines() except: pls=[] global queue queue=None entries=[] idxs=[] def addfile(x): entries.append([x.group(2),'']) idxs.append(int(x.group(1))) def addtitle(x): idx=int(x.group(1)) val=x.group(2) if not idx in idxs: return entries[idxs.index(int(idx))][1]=val map(addfile,filter(lambda x: x,map(lambda x: re.match(".*File([0-9]+) *= *(.*) *",x),pls))) map(addtitle,filter(lambda x: x,map(lambda x: re.match(".*Title([0-9]+) *= *(.*) *",x),pls))) # Sort the entries if idxs: sidx=idxs[:] sidx.sort() uentries=entries[:] entries=[] for s in sidx: entries.append(uentries[idxs.index(s)]) print entries from Tkinter import * actentry="" player=Player() def quitme(): player.stop() frame.quit() root=Tk() frame=Frame(root) frame.pack() titletxt=StringVar() title=Label(frame,textvariable=titletxt) titletxt.set("Connecting...") title.pack(side=TOP) close=Button(frame,text="Stop",command=quitme) close.pack(side=RIGHT) def notify_func(name): global queue queue=name def read_queue(): global queue if queue: titletxt.set(queue) queue=None root.after(1000,read_queue) root.title("Pathetic Little Stream Player 0.1") root.after(100,lambda : player.play_list(entries,notify_func)) root.after(1000,read_queue) root.mainloop()