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

⌈⌋ ⎇ branch:  streamtuner2


Check-in [08803f2b56]

Overview
Comment:Add duplicate filter for Xiph.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 08803f2b563222c60b6ca66be9015d9ec0fa6c82
User & Date: mario on 2020-05-11 16:24:20
Other Links: manifest | tags
Context
2020-05-11
16:34
Fix for radionet station/player page change `"streamUrl":` to `"streams":[{"url":` check-in: 059815af7b user: mario tags: trunk
16:24
Add duplicate filter for Xiph. check-in: 08803f2b56 user: mario tags: trunk
16:23
Fix for new url prefix in station list. check-in: 80b73f490d user: mario tags: trunk
Changes

Modified channels/xiph.py from [cff583b758] to [5e8e93fcb4].

1
2
3
4
5
6
7

8
9
10

11
12
13
14
15
16
17
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18






-
+



+







# 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.7
# version: 0.8
# category: radio
# config: 
#    { 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." }
#    { name: xiph_filter, value: 1, type: bool, description: "Filter duplicate stations from list." }
# priority: standard
# png:
#   iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAg5JREFUOI2lk1tIE2AUx3+7CG1tlmlG1rSEHrKgEUF7yO40taQiRj10I4qKkOaT4hIUItuTkC8hpJAQtJCICrFpzEKw
#   h61eQorGNBOTzbEt16ZrnR5Wq3mZD/3heziX//983znngyyov+eSbHEA5WKBhs4BKVy9gsqajqwiCwo0dA5IQX5u2s4moliMPPV1nCeDzxgNBFDHE2wsKMPzsGVefobjcnO7RMfeMuL341ZBrNEGRmPqqjdvsbbf
#   w7irO4Oj+rdywNNNucmERsLUVndR8uYRU13PCew6hpgP8W02xMpIsik++qk5oweW6y3yob8WnXacZDKJWh1Cp4OtRUHsh19TUlUGViv09RGqKAenU5QnLKm+rK88LjgcUnxmr/h8iNO5XYJBRAQZ/qiVeptGWjty
#   5cClDWLwugQRIRiU5UdPCoD6S89jhV6pks9WG6fuwtBtF5v72vC1v+B86SsM+jD56hjnyiM0lRrAbofeXjQJLdE/78jbXSU5166I6f5VeeDdKdq6GtlSd0QkVU+8XsQhlt9W6izbZ5aMKWgtp2WT/yUHd0xSYU7i
#   dsPQ+1WMKIsJD08wEV2HGLeRyNMjawqRxhuKBfdgz1m7fI/4mVX+ZGxmgniOoJv+QZHGAMC7p60ZnHkC8HfzZmLTBCd9af9ccnqMc9HTdmFe4kLkJbH/4h0xVtcu+SP/C78AL6btab6woPcAAAAASUVORK5CYII=
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209







-
+








-
+







  # uncover station homepages.
  #@use_rx
  def from_raw_html(self, cat, search=None, use_rx=False):

      # Build request URL
      by_format = {t.lower(): t for t in self.categories[-1]}
      if search:
          url = "http://dir.xiph.org/search?search={}".format(search)
          url = "http://dir.xiph.org/search?q={}".format(search)
          cat = "search"
      elif by_format.get(cat):
          url = "http://dir.xiph.org/codecs/{}".format(by_format[cat].title())
      elif cat:
          url = "http://dir.xiph.org/genres/{}".format(cat.title())

      # Collect all result pages
      html = ahttp.get(url)
      for i in range(1,5):
      for i in range(1,9):
          m = re.search('href="[?]cursor=(\w+)">Next</a>', html)
          if not m:
              break
          self.status(i/5.1)
          html += ahttp.get(url, {"cursor": m.group(1)})
      try:
          html = html.encode("raw_unicode_escape").decode("utf-8")
240
241
242
243
244
245
246





247










248
249
250
251
252
253
254
241
242
243
244
245
246
247
248
249
250
251
252

253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269







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







              listformat = "srv",
              listeners = to_int(ls["listeners"]),
              bitrate = 0,  #bitrate(ls["bits"]),
              format = mime_fmt(guess_format(ls["fmt"])),
              tags = unhtml(ls["tags"])
          ))
          #log.DATA(r)
      return self.filter_duplicates(r)

  # strip entries by title+playing from Xiph BETA result list
  def filter_duplicates(self, entries):
      if "xiph_filter" not in conf or not int(conf.xiph_filter):
      return r
          return entries
      seen = []
      filt_r = filter(lambda row: row["title"] not in seen and not seen.append(row["title"]), entries)
      return filt_r
      for row in entries:
          curr = (row["title"], row["playing"])
          if not curr in seen:
             filt_r.append(row)
             seen.append(curr)
      return filt_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: