Index: channels/__init__.py ================================================================== --- channels/__init__.py +++ channels/__init__.py @@ -817,11 +817,11 @@ # rename map = { "audio/mp3":"audio/mpeg", # Note the real mime type is /mpeg, but /mp3 is more understandable in the GUI "ogg":"ogg", "ogm":"ogg", "xiph":"ogg", "vorbis":"ogg", "vnd.xiph.vorbis":"ogg", "mp3":"mpeg", "mp":"mpeg", "mp2":"mpeg", "mpc":"mpeg", "mps":"mpeg", - "aac+":"aac", "aacp":"aac", + "aac+":"aac", "aacp":"aac", "aac+":"aac", "realaudio":"x-pn-realaudio", "real":"x-pn-realaudio", "ra":"x-pn-realaudio", "ram":"x-pn-realaudio", "rm":"x-pn-realaudio", # yes, we do video "flv":"video/flv", "mp4":"video/mp4", } #map.update(action.listfmt_t) # list type formats (.m3u .pls and .xspf) Index: channels/xiph.py ================================================================== --- channels/xiph.py +++ channels/xiph.py @@ -2,14 +2,14 @@ # api: streamtuner2 # title: Xiph.org # description: ICEcast radios. Scans per JSON API, slow XML, or raw directory. # type: channel # url: http://dir.xiph.org/ -# version: 0.6 +# version: 0.7 # category: radio # config: -# { name: xiph_source, value: web, type: select, select: "cache=JSON cache srv|xml=Clunky XML blob|buffy=Buffy YP.XML|web=Forbidden fruits", description: "Source for station list extraction." } +# { name: xiph_source, value: buffy, type: select, select: "cache=JSON cache srv|xml=Clunky XML blob|buffy=Buffy YP.XML|web=Forbidden fruits", description: "Source for station list extraction." } # priority: standard # png: # iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAg5JREFUOI2lk1tIE2AUx3+7CG1tlmlG1rSEHrKgEUF7yO40taQiRj10I4qKkOaT4hIUItuTkC8hpJAQtJCICrFpzEKw # h61eQorGNBOTzbEt16ZrnR5Wq3mZD/3heziX//983znngyyov+eSbHEA5WKBhs4BKVy9gsqajqwiCwo0dA5IQX5u2s4moliMPPV1nCeDzxgNBFDHE2wsKMPzsGVefobjcnO7RMfeMuL341ZBrNEGRmPqqjdvsbbf # w7irO4Oj+rdywNNNucmERsLUVndR8uYRU13PCew6hpgP8W02xMpIsik++qk5oweW6y3yob8WnXacZDKJWh1Cp4OtRUHsh19TUlUGViv09RGqKAenU5QnLKm+rK88LjgcUnxmr/h8iNO5XYJBRAQZ/qiVeptGWjty @@ -24,21 +24,22 @@ # It also provides a directory listing of known internet # radio stations; only a handful of them using Ogg though. # The category list is hardwired in this plugin. And there # are three station fetching modes now: # -# → "JSON cache" retrieves a refurbished JSON station list, -# both sliceable genres and searchable. -# # → "Clunky XML" fetches the olden YP.XML, which is really # slow, then slices out genres. No search. # # → While the secret "buffy" mode keeps the XML blob in memory. # -# → "Forbidden Fruits" extracts from dir.xiph.org HTML pages, -# with homepages and listener/max infos available. Also -# enables live server searching. +# → "Forbidden Fruits" extracts from dir.xiph.org HTML pages. +# Albeit that doesn't contain homepages or bitrates anymore, +# +# → "JSON cache" retrieves a refurbished JSON station list, +# both sliceable genres and searchable. This will probably +# break now that the BETA interface also killed the JSON +# experimental API. # # The previous bitrate filter is now a separate plugin, but # available for all channels. @@ -189,54 +190,62 @@ by_format = {t.lower(): t for t in self.categories[-1]} if search: url = "http://dir.xiph.org/search?search={}".format(search) cat = "search" elif by_format.get(cat): - url = "http://dir.xiph.org/by_format/{}".format(by_format[cat]) + url = "http://dir.xiph.org/codecs/{}".format(by_format[cat].title()) elif cat: - url = "http://dir.xiph.org/by_genre/{}".format(cat.title()) + url = "http://dir.xiph.org/genres/{}".format(cat.title()) # Collect all result pages html = ahttp.get(url) for i in range(1,5): - if html.find('page={}">{}'.format(i, i+1)) < 0: + m = re.search('href="[?]cursor=(\w+)">Next', html) + if not m: break self.status(i/5.1) - html += ahttp.get(url, {"search": cat.title(), "page": i}) + html += ahttp.get(url, {"cursor": m.group(1)}) try: html = html.encode("raw_unicode_escape").decode("utf-8") except: pass # Find streams r = [] - rows = re.findall("""(.+?)""", html, re.S) + rows = re.findall("""(.+?)(?=\s+ ]*> (.*?) """, - listeners = """ "listeners">\[(\d+) """, - playing = """ "stream-description">(.*?)< """, - tags = """ (?s) Tags: (.*?) """, - url = """ href="(/listen/\d+/listen.xspf)" """, - bits = """ class="format"\s+title="([^"]+)" """, - fmt = """ /by_format/([^"]+) """, + #homepage = """ class="name"> ([^>]*) """, + listeners = """ (\d+) \s+ Listeners \s+ — """, + playing = """ class="card-subtitle[^>]*"> On\s+Air:\s+ ([^<]*) """, + description = """ class="card-text"> ([^>]*)

""", + tags = """ ((?:]+> [^<]+ \s+)+) — """, + url = """ ]+)"\s+class="btn[^>]+">Play """, + #bits = """ class="format"\s+title="([^"]+)" """, + fmt = """