Internet radio browser GUI for music/video streams from various directory services.

⌈⌋ ⎇ branch:  streamtuner2


Diff

Differences From Artifact [6ec5e242b7]:

To Artifact [c7435085e0]:


1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







# encoding: UTF-8
# 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.5
# version: 0.6
# category: radio
# config: 
#    { name: xiph_source, value: web, type: select, select: "cache=JSON cache srv|xml=Clunky XML blob|web=Forbidden fruits", description: "Source for station list extraction." }
# priority: standard
# png:
#   iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAg5JREFUOI2lk1tIE2AUx3+7CG1tlmlG1rSEHrKgEUF7yO40taQiRj10I4qKkOaT4hIUItuTkC8hpJAQtJCICrFpzEKw
#   h61eQorGNBOTzbEt16ZrnR5Wq3mZD/3heziX//983znngyyov+eSbHEA5WKBhs4BKVy9gsqajqwiCwo0dA5IQX5u2s4moliMPPV1nCeDzxgNBFDHE2wsKMPzsGVefobjcnO7RMfeMuL341ZBrNEGRmPqqjdvsbbf
191
192
193
194
195
196
197
198

199
200
201
202

203
204



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222















223
224
225
226
227
228
229
230





231
232
233
234



235
236
237











238
239
240
241
242
243
244
191
192
193
194
195
196
197

198
199
200
201
202
203


204
205
206
207
208
209















210
211
212
213
214
215
216
217
218
219
220
221
222
223
224


225





226
227
228
229
230
231



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255







-
+




+
-
-
+
+
+



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-

-
-
-
-
-
+
+
+
+
+

-
-
-
+
+
+



+
+
+
+
+
+
+
+
+
+
+







      elif by_format.get(cat):
          url = "http://dir.xiph.org/by_format/{}".format(by_format[cat])
      elif cat:
          url = "http://dir.xiph.org/by_genre/{}".format(cat.title())

      # Collect all result pages
      html = ahttp.get(url)
      for i in range(1,4):
      for i in range(1,5):
          if html.find('page={}">{}</a></li>'.format(i, i+1)) < 0:
              break
          self.status(i/5.1)
          html += ahttp.get(url, {"search": cat.title(), "page": i})
      try:
      try: html = html.encode("raw_unicode_escape").decode("utf-8")
      except: pass
          html = html.encode("raw_unicode_escape").decode("utf-8")
      except:
          pass

      # Find streams
      r = []
      #for row in re.findall("""<tr class="row[01]">(.+?)</tr>""", html, re.X|re.S):
      #    pass
      ls = re.findall("""
          <tr\s+class="row[01]">
          .*? class="name">
               <a\s+href="(.*?)"[^>]*>
                (.*?)</a>
          .*? "listeners">\[(\d+)
          .*? "stream-description">(.*?)<
          .*? Tags: (.*?) </div>
          .*? href="(/listen/\d+/listen.xspf)"
          .*? class="format"\s+title="([^"]+)"
          .*? /by_format/([^"]+)
      """, html, re.X|re.S)
            
      rows = re.findall("""<tr\s+class="row\d*">(.+?)</tr>""", html, re.S)
      for html in rows:
          ls = self.rx_all(
               dict(
                  homepage = """ class="name">  <a\s+href="(.*?)" """,
                  title = """ class="name">  <a[^>]*> (.*?)</a> """,
                  listeners = """ "listeners">\[(\d+) """,
                  playing = """ "stream-description">(.*?)< """,
                  tags = """ (?s) Tags: (.*?) </div> """,
                  url = """ href="(/listen/\d+/listen.xspf)" """,
                  bits = """ class="format"\s+title="([^"]+)" """,
                  fmt = """ /by_format/([^"]+) """,
              ),
              html
          )
      # Assemble
      for homepage, title, listeners, playing, tags, url, bits, fmt in ls:
          r.append(dict(
              genre = unhtml(tags),
              title = unhtml(title),
              homepage = ahttp.fix_url(homepage),
              playing = unhtml(playing),
              url = "http://dir.xiph.org{}".format(url),
              genre = unhtml(ls["tags"]),
              title = unhtml(ls["title"]),
              homepage = ahttp.fix_url(ls["homepage"]),
              playing = unhtml(ls["playing"]),
              url = "http://dir.xiph.org{}".format(ls["url"]),
              listformat = "xspf",
              listeners = int(listeners),
              bitrate = bitrate(bits),
              format = mime_fmt(guess_format(fmt)),
              listeners = int(ls["listeners"]),
              bitrate = bitrate(ls["bits"]),
              format = mime_fmt(guess_format(ls["fmt"])),
          ))
      return r

  # Regex dict
  def rx_all(self, fields, src, flags=re.X):
      row = {}
      for k, v in fields.items():
          m = re.search(v, src, flags)
          if m:
              row[k] = m.group(1)
          else:
              row[k] = ""
      return row
     


  # Static list of categories
  genres = [
        "pop",
        [
            "top40", "90s", "80s", "britpop", "disco", "urban", "party",