From 38c4e6f212e5980a318253c9b3b1e3d1eff67b99 Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Sat, 15 Aug 2009 16:10:20 -0800 Subject: [PATCH] add support for wax/asx files... [git-p4: depot-paths = "//depot/": change = 1373] --- README | 1 + shoutcast.py | 48 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/README b/README index 8310acf..255f3e1 100644 --- a/README +++ b/README @@ -99,6 +99,7 @@ v0.x: creating the files. If we get an error parsing the genres of ShoutCAST, try again. Print out the modules that failed to load. + Add support for WAX/ASX files in shoutcast. v0.5: Support multiple SSDP servers on the same box. diff --git a/shoutcast.py b/shoutcast.py index 57d839a..004f132 100644 --- a/shoutcast.py +++ b/shoutcast.py @@ -17,6 +17,7 @@ import os.path import random import time import traceback +import xml.dom.minidom from py_shoutcast import * @@ -203,25 +204,50 @@ class ShoutProxy(resource.Resource): map(fun, self.afterurls) self.afterurls = None - def gotPLS(self, page): + def gotURL(self, page): self.fetchingurls = False + try: + urls = self.parsePLS(page) + except ConfigParser.MissingSectionHeaderError: + urls = self.parseWAX(page) + + #log.msg('pls urls:', self.urls) + self.urls = urls + self.urlpos = random.randrange(len(self.urls)) + + self.triggerdefered(lambda x: x.callback(True)) + + def parseWAX(self, page): + print 'trying WAX' + dom = xml.dom.minidom.parseString(page) + rootel = dom.documentElement + if rootel.nodeName != 'asx': + raise ValueError('Only asx allowed, got %s' % + `rootel.nodeName`) + + urls = [] + for i in rootel.getElementsByTagName('entry'): + urls.extend(str(x.getAttribute('href')) for x in + i.getElementsByTagName('ref')) + + print 'returning:', `urls` + return urls + + def parsePLS(self, page): pls = ConfigParser.SafeConfigParser() pls.readfp(StringIO.StringIO(page)) # KCSM 91.1 doesn't provide a version #assert pls.getint(PLSsection, 'Version') == 2 assert pls.has_option(PLSsection, 'numberofentries') cnt = pls.getint(PLSsection, 'numberofentries') - self.urls = [] + urls = [] for i in range(cnt): i += 1 # stupid one based arrays - self.urls.append(pls.get(PLSsection, + urls.append(pls.get(PLSsection, 'File%d' % i)) - #log.msg('pls urls:', self.urls) - self.urlpos = random.randrange(len(self.urls)) - - self.triggerdefered(lambda x: x.callback(True)) + return urls - def errPLS(self, failure): + def errURL(self, failure): self.fetchingurls = False # XXX - retry? self.triggerdefered(lambda x: x.errback(failure)) @@ -255,8 +281,8 @@ class ShoutProxy(resource.Resource): # shouldn't getPage do proper escaping for me? self.afterurls = [ defer.Deferred() ] d = getPage(self.shoutpls.encode('ascii')) - d.addCallback(self.gotPLS) - d.addErrback(self.errPLS) + d.addCallback(self.gotURL) + d.addErrback(self.errURL) else: self.afterurls.append(defer.Deferred()) # Always add the callback if we don't have urls @@ -269,7 +295,7 @@ class ShoutProxy(resource.Resource): # and make sure the connection doesn't get closed return server.NOT_DONE_YET - synchronized = [ 'gotPLS', 'render', 'startNextConnection', + synchronized = [ 'gotURL', 'render', 'startNextConnection', 'triggerdefered', ] threadable.synchronize(ShoutProxy)