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

โŒˆโŒ‹ โŽ‡ branch:  streamtuner2


Check-in [eadb28d92c]

Overview
Comment:filtermusic: XML blob is gone, just web extraction now.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: eadb28d92c2ba74973f2f8780fbd95c6e8368835
User & Date: mario on 2020-05-11 18:41:01
Other Links: manifest | tags
Context
2020-05-11
19:11
updated SomeFM extraction and default stream list check-in: c2360471af user: mario tags: trunk
18:41
filtermusic: XML blob is gone, just web extraction now. check-in: eadb28d92c user: mario tags: trunk
18:21
Listenlive.eu is gone as well. check-in: ce9cfc68b0 user: mario tags: trunk
Changes

Modified channels/filtermusic.py from [6f77373870] to [56ef72e89a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# encoding: UTF-8
# api: streamtuner2
# title: filtermusic
# description: Daily refreshed list of electronic+dance music streams.
# version: 0.1
# type: channel
# url: http://filtermusic.net/
# category: radio
# config:
#   { name: filtermusic_src, type: select, value: web, select: "web=Website|xml=XML Data|buf=Buffered", description: "Which data source to read from. (Both HTML and XML extraction are speedy.)" }
# png:
#   iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH3wQeBA4mIX2CmQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAGISURBVCjPnVI9SyNRFD333slMMhrNjBJU0FSLIlovy6IWbmelhRJ/gI2lkMXfIOwv2K38qizstFCs3B+wLFhoIfiR1cggkXzMvHnPIiG6
#   GkE8zYXLPfe8c94F2oAkk7CHHLIIb4AAEIlkcuJmARr8OTxW+pKe9l6PSqN0jOe9hd3014J09tdP96SHSLh8GKirsM1+TvnZ5RN/buO5ItvcUH4BCwC7vex0Vf5stroGMKFu+3omKymdfUTMrs9uDyczAHzfz+VyIpwgu1u8NGccSjbFUyOz/vyOUVVoDZbq3+1gd6lQWMnn85PTEzPR4mdnKjLhrS6uBasArNrZ3t36N29u6/7ge/1038QRECul
#   arWaNrqLvV/lHx2U/pQYbXowUTUuXwJGV0rxQ/H/sKkU/yuqC4dSfdZA0wMAELd+4wUhNFUABro52Spvg54l9y7Cq1g/RiBwAvTkQURs2waBwQARiGE93RKJzW5v/fxIl68bXdd1gyA4Pv6tlLqLbyJEoamX4iI+gEdAknsz9gP1pgAAAABJRU5ErkJggg==
# x-doc:
#   http://code.google.com/p/filtermusic-dot-net/source/browse/
# priority: extra
# extraction-method: regex, xml
#
#
# Filtermusic.net is a radio collection with primarily electronic
# and dance music stations.
#
#  ยท All entries come with direct server stream URLs.
#  ยท No homepage listings, or further genre details etc.


from config import *
from channels import *
import ahttp
import re
import xml.etree.ElementTree as ET




|












|






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# encoding: UTF-8
# api: streamtuner2
# title: filtermusic
# description: Daily refreshed list of electronic+dance music streams.
# version: 0.2
# type: channel
# url: http://filtermusic.net/
# category: radio
# config:
#   { name: filtermusic_src, type: select, value: web, select: "web=Website|xml=XML Data|buf=Buffered", description: "Which data source to read from. (Both HTML and XML extraction are speedy.)" }
# png:
#   iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH3wQeBA4mIX2CmQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAGISURBVCjPnVI9SyNRFD333slMMhrNjBJU0FSLIlovy6IWbmelhRJ/gI2lkMXfIOwv2K38qizstFCs3B+wLFhoIfiR1cggkXzMvHnPIiG6
#   GkE8zYXLPfe8c94F2oAkk7CHHLIIb4AAEIlkcuJmARr8OTxW+pKe9l6PSqN0jOe9hd3014J09tdP96SHSLh8GKirsM1+TvnZ5RN/buO5ItvcUH4BCwC7vex0Vf5stroGMKFu+3omKymdfUTMrs9uDyczAHzfz+VyIpwgu1u8NGccSjbFUyOz/vyOUVVoDZbq3+1gd6lQWMnn85PTEzPR4mdnKjLhrS6uBasArNrZ3t36N29u6/7ge/1038QRECul
#   arWaNrqLvV/lHx2U/pQYbXowUTUuXwJGV0rxQ/H/sKkU/yuqC4dSfdZA0wMAELd+4wUhNFUABro52Spvg54l9y7Cq1g/RiBwAvTkQURs2waBwQARiGE93RKJzW5v/fxIl68bXdd1gyA4Pv6tlLqLbyJEoamX4iI+gEdAknsz9gP1pgAAAABJRU5ErkJggg==
# x-doc:
#   http://code.google.com/p/filtermusic-dot-net/source/browse/
# priority: extra
# extraction-method: regex
#
#
# Filtermusic.net is a radio collection with primarily electronic
# and dance music stations.
#
#  ยท All entries come with direct server stream URLs.
#  ยท No homepage listings, and genre details spotty (so omitted).


from config import *
from channels import *
import ahttp
import re
import xml.etree.ElementTree as ET
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# filtermusic.net
class filtermusic (ChannelPlugin):

    # control attributes
    has_search = False
    listformat = "srv"
    audioformat = "audio/mpeg"
    titles = dict(listeners=False, bitrate=False, playing=False)
    categories = ["House / Dance", "Lounge Grooves", "Rock / Metal", "Breaks / Drum'n'Bass", "Various / Independent", "Downtempo / Ambient", "60's / 70's / 80's / 90's", "Hits / Mainstream", "Electronica / Industrial", "Techno / Trance", "HipHop / RnB", "Classical", "Eclectic", "Funk / Soul / Disco", "Reggae / Dub / Dancehall", "International / Ethnic", "Jazz", "Latin / Salsa / Tango"]


    # static
    def update_categories(self):
        pass


    # Refresh station list
    def update_streams(self, cat, search=None):
        if conf.filtermusic_src == "web":
            return self.from_web(cat)
        else:
            return self.from_xml(cat)


    # Extract directly from filtermusic.net html
    def from_web(self, cat):
        ucat = re.sub("\W+", "-", cat.lower().replace("'", ""))
        html = ahttp.get("http://filtermusic.net/{}".format(ucat))

        ls = re.findall("""<h4>(.*?)</h4><p>(.*?)</p>.*?href='(.*?)'""", html)







        r = [
            dict(genre=cat, title=title, playing=descr, url=url)
            for title,descr,url in ls
        ]
        return r


    # Parse and cache XML,
    # Stucture is: <z> <g> id="Genre"> <t id="Title"> <u>URL</u> </t> ... </g> ... </z>
    def from_xml(self, cat):
        buf = {}
        z = ET.fromstring(ahttp.get("http://www.filtermusic.net/xml/list.2.0.xml"))
        for g in z:
            try:
                genre = g.attrib["id"]
                buf[genre] = []
            except:
                # no group "id" for trailing <r>..</r> tag
                continue
            for t in g:
                buf[genre].append(dict(genre=genre, title=t.attrib.get("id"), url="http://"+t[0].text))
        if conf.filtermusic_src == "buf":
            self.streams = buf
        return buf[cat]









|
|









<
|
<
<






|
|
>
>
>
>
>
>
>

|



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

53


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73




















74
# filtermusic.net
class filtermusic (ChannelPlugin):

    # control attributes
    has_search = False
    listformat = "srv"
    audioformat = "audio/mpeg"
    titles = dict(listeners=False, bitrate=False, playing="Description")
    categories = ["Top Radio Stations", "House / Dance", "Lounge Grooves", "Rock / Metal", "Breaks / Drum'n'Bass", "Various / Independent", "Downtempo / Ambient", "60's / 70's / 80's / 90's", "Hits / Mainstream", "Electronica / Industrial", "Techno / Trance", "HipHop / RnB", "Classical", "Eclectic", "Funk / Soul / Disco", "Reggae / Dub / Dancehall", "International / Ethnic", "Jazz", "Latin / Salsa / Tango"]


    # static
    def update_categories(self):
        pass


    # Refresh station list
    def update_streams(self, cat, search=None):

        return self.from_web(cat)




    # Extract directly from filtermusic.net html
    def from_web(self, cat):
        ucat = re.sub("\W+", "-", cat.lower().replace("'", ""))
        html = ahttp.get("http://filtermusic.net/{}".format(ucat))
        
        rx_station = re.compile("""
               <h4>((?!Support\s+filtermusic).*?)</h4>\s*
               <p>(.*?)</p>.*?
               data-listen='(.*?)'
            """, re.X|re.S
        )
        ls = re.findall(rx_station, html)
        log.DATA(ls)
        r = [
            dict(genre=cat, title=unhtml(title), playing=unhtml(descr), url=url)
            for title,descr,url in ls
        ]
        return r