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

⌈⌋ ⎇ branch:  streamtuner2


Check-in [4836962bd4]

Overview
Comment:Ah, Shoutcast, switching again. → HTML extraction is now JS lexing → {genreid:} is now {genrename:}
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4836962bd47132eb0b783450192476ef77b66ca0
User & Date: mario on 2014-08-05 02:39:46
Other Links: manifest | tags
Context
2014-08-05
02:42
Optional homepage querying, stripping musicgoal stream_urls. check-in: 2b60750fdf user: mario tags: trunk
02:39
Ah, Shoutcast, switching again. → HTML extraction is now JS lexing → {genreid:} is now {genrename:} check-in: 4836962bd4 user: mario tags: trunk
2014-08-01
01:35
Initial support for Dirble.com, provides grouped categories and search feature. check-in: 7965619312 user: mario tags: trunk
Changes

Modified channels/shoutcast.py from [f86f5c5147] to [ffcf202481].

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
33
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
33







-
+

















-
+







#
# api: streamtuner2
# title: Shoutcast.com
# description: Primary list of shoutcast servers (now managed by radionomy).
# type: channel
# category: radio
# priority: default
# version: 1.4
# version: 1.5
# depends: pq, re, http
# author: Mario
# original: Jean-Yves Lefort
#
# Shoutcast is a server software for audio streaming. It automatically spools
# station information on shoutcast.com
# It has been aquired by Radionomy in 2014, since then significant changes
# took place. The former YP got deprecated, now seemingly undeprecated.
#
#   http://wiki.winamp.com/wiki/SHOUTcast_Radio_Directory_API 
#
# But neither their Wiki nor Bulletin Board provide concrete information on
# the eligibility of open source desktop apps for an authhash.
#
# Therefore we'll be retrieving stuff from the homepage still. The new
# interface conveniently uses JSON already, so let's use that:
#
#   POST http://www.shoutcast.com/Home/BrowseByGenre {genreid: 9}
#   POST http://www.shoutcast.com/Home/BrowseByGenre {genrename: Pop}
#
# We do need a catmap now too, but that's easy to aquire and will be kept
# within the cache dirs.
#
#
#

70
71
72
73
74
75
76
77

78
79
80
81
82
83
84


85
86
87
88
89

90
91



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
70
71
72
73
74
75
76

77




78


79
80
81


82
83
84


85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113







-
+
-
-
-
-

-
-
+
+

-
-


+
-
-
+
+
+





-













-
+







        
    # Extracts the category list from www.shoutcast.com,
    # stores a catmap (title => id)
    def update_categories(self):
        html = http.get(self.base_url)
        #__print__( dbg.DATA, html )
        self.categories = []

        
        # Main genres from mobile dropdown
        """ <option value="1">Alternative</option> """
        rx = re.compile(r'<option value="(\d+)">(\w+\h*\w+)<')
        main = rx.findall(html)
        # Genre list in sidebar
        """ <li><a href="#c-genre-2" onclick="loadStationsByGenre(2, true)">Adult Alternative</a></li> """
        rx = re.compile(r'c-genre-(\d+).+?>(\w[\w\h]*\w)<')
        """  <li><a id="genre-90" href="/Genre?name=Adult" onclick="loadStationsByGenre('Adult', 90, 89); return false;">Adult</a></li> """
        rx = re.compile(r"loadStationsByGenre\(  '([^']+)' [,\s]* (\d+) [,\s]* (\d+)  \)", re.X)
        subs = rx.findall(html)
        print main
        print subs

        # group
        current = []
        for (id, title) in subs:
            if (id,title) in main:
        for (title, id, main) in subs:
            self.catmap[title] = int(id)
            if not int(main):
                self.categories.append(title)
                current = []
                self.categories.append(current)
            else:
                current.append(title)
            self.catmap[title] = int(id)
        self.save()


    # downloads stream list from shoutcast for given category
    def update_streams(self, cat):

        if (cat not in self.catmap):
            __print__( dbg.ERR, "nocat" )
            return []
        id = self.catmap[cat]

        # page
        url = "http://www.shoutcast.com/Home/BrowseByGenre"
        params = { "genreid": int(id) }
        params = { "genrename": cat }
        referer = None
        json = http.get(url, params=params, referer=referer, post=1, ajax=1)
        self.parent.status(0.75)

        # remap JSON
        entries = []
        for e in json_decode(json):