#! /usr/bin/python from socket import * import BaseHTTPServer import SocketServer import sys, urllib, urllib2, httplib, re, cgi, socket from urllib2 import urlparse class StreamServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): def __init__(self, port, host=socket.gethostname()): self.port = port SocketServer.TCPServer.__init__(self, (host, port), myHTTPRequestHandler) class mediaClip: def __init__ (self, site, path, content_length, duration, begin, end, fragSize): self.site = site self.path = path self.content_length = content_length self.dur = duration self.beg = begin self.end = end self.fragSize = fragSize def toSecs(self, timecode): l = timecode.split(':') return 60*60*int(l[0]) + 60*int(l[1]) + int(l[2]) def offset(self, bytes, pdur, begOrEnd): percent = float(begOrEnd) / float(dur) offset = int ( percent * int(bytes) ) return offset def bounds (self): dur = self.toSecs(self.dur) beg = self.toSecs(self.beg) end = self.toSecs(self.end) rangeBegin = self.offset(self.content_length,dur,beg) rangeEnd = self.offset(self.content_length,dur,end) return [ rangeBegin, rangeEnd ] def length (self): (rangeBegin, rangeEnd) = self.bounds() return rangeEnd - rangeBegin class myHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): def whichURL(self, site, path): conn = httplib.HTTPConnection(site) conn.request('HEAD', path) response = conn.getresponse() content_length = response.msg.getheader('content-length') location = response.msg.getheader('location') while ( location is not None ): print 'redirecting to %s' % location (scheme, site, path, args, query, frag) = urlparse.urlparse(location) path = path + args + query conn.close() conn = httplib.HTTPConnection(site) conn.request('HEAD', path) response = conn.getresponse() content_length = response.msg.getheader('content-length') location = response.msg.getheader('location') conn.close() print "%s, %s, %s" % ( site, path, content_length) return ( [site, path, content_length] ) def clipMP3( self, clip ): (rangeBegin, rangeEnd) = clip.bounds() params = urllib.urlencode({}) headers = {'Range': 'bytes=%s-%s' % (rangeBegin,rangeEnd)} conn = httplib.HTTPConnection(clip.site) conn.request('GET', clip.path, params, headers) response = conn.getresponse() print response.status, response.reason print response.msg.items() chunk = response.read(clip.fragSize) self.wfile.write(chunk) while ( chunk is not '' ): chunk = response.read(clip.fragSize) if ( chunk is not '' ): print "sending another chunk of %s%s (%s)" % (clip.site, clip.path, len(chunk)) self.wfile.write(chunk) print """done sending clip %s/%s ---------------------------------------""" % (clip.site, clip.path) conn.close() def do_GET(self): q = self.requestline.split()[1] q = re.sub('^[/\?]+','',q) q = re.sub('&','&',q) pq = cgi.parse_qs(q) (site, path, content_length) = self.whichURL( pq['site'][0], urllib.quote(pq['url'][0]) ) ( duration, begin, end ) = [ pq['dur'][0], pq['beg'][0], pq['end'][0] ] clip = mediaClip(site, path, content_length, duration, begin, end, fragSize=20000) self.send_head(clip.length()) self.clipMP3( clip ) def send_head(self,content_length): self.send_response(200) self.send_header("Content-Type", "audio/mpeg") self.send_header("Content-Length", content_length) self.end_headers() def run(port): S = StreamServer(port=port) try: print "serving on port %s" % port S.serve_forever() except: print "Stopped." sys.exit() if __name__ == '__main__': if sys.argv[2:]: port = int(sys.argv[2]) else: port = 8002 run(port)