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

⌈⌋ ⎇ branch:  streamtuner2


Check-in [083338eb6c]

Overview
Comment:Update fetching to use new //directory.shoutcast.com/ base url. Remove obsolete catmap checking. Category extraction still functional. ToDo: support playlist format alternatives (pls/m3u/xspf)..
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 083338eb6cd04791868003944123d127f1e93b72
User & Date: mario on 2018-10-07 14:37:50
Other Links: manifest | tags
Context
2018-10-07
15:21
Add shoutcast_format=pls/m3u/xpsf option check-in: 5d84c96422 user: mario tags: trunk
14:37
Update fetching to use new //directory.shoutcast.com/ base url. Remove obsolete catmap checking. Category extraction still functional. ToDo: support playlist format alternatives (pls/m3u/xspf).. check-in: 083338eb6c user: mario tags: trunk
2018-08-20
16:04
Disable man page compression, as that left Yelp files inaccessible check-in: 32abb5dd8e user: mario tags: trunk
Changes

Modified channels/shoutcast.py from [68512fd7c7] to [e546a5a55d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# api: streamtuner2
# title: Shoutcast.com
# description: Primary list of shoutcast servers (now managed by radionomy).
# type: channel
# category: radio
# author: Mario
# original: Jean-Yves Lefort
# version: 1.5
# url: http://www.shoutcast.com/
# config: -
# priority: default
# png:
#   iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAelJREFUOI2NU0toE2EYnM12t2wLkhSXSIgEJMHFQ2naQ+kpoPYQoaXH3gRFsegloUhRQTyU2oOgggQUzzlEQomIBzU+EHooBIol0cOGLqFFFiJ5SB5skvFU6ebRduA7/DAz
#   /PM9BJLoh3Q6zVQqBZfLhXq9jlAohHA4LHTzhvqJ2+02c7kcgsEgfD4fRFFEPp+HZVmUJEk41kAURcHv99Pj8cAwDGiaBkVR0C0GAJDsW7VajYVCgYlEguVymZZlsVKpcG1tlYd5fX8AAIqiCF6vF6VSibIsI5lMYvvDE1xymwDu/ec5BhkcIJPJIHJzFqf372P1cgMf
#   f46cLIKu61yJXufr5VO0voyzEZ/k8sI4s9ns0RFarRZjL56inIshekWGenYS6IzhR9PCntRBIBCw8XsiFItFNLMxPJgfwVjDi4Y8g2b9DILaMKZGd2Ca5tEGiqJg2xjF200H6J+AvKtjeG8T3998xW5nAk6n08bviSBJEqhewLlpN4bMHfwxfuH5J8J98SGerS/B4XDY







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# api: streamtuner2
# title: Shoutcast.com
# description: Primary list of shoutcast servers (now managed by radionomy).
# type: channel
# category: radio
# author: Mario
# original: Jean-Yves Lefort
# version: 1.6
# url: http://www.shoutcast.com/
# config: -
# priority: default
# png:
#   iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAelJREFUOI2NU0toE2EYnM12t2wLkhSXSIgEJMHFQ2naQ+kpoPYQoaXH3gRFsegloUhRQTyU2oOgggQUzzlEQomIBzU+EHooBIol0cOGLqFFFiJ5SB5skvFU6ebRduA7/DAz
#   /PM9BJLoh3Q6zVQqBZfLhXq9jlAohHA4LHTzhvqJ2+02c7kcgsEgfD4fRFFEPp+HZVmUJEk41kAURcHv99Pj8cAwDGiaBkVR0C0GAJDsW7VajYVCgYlEguVymZZlsVKpcG1tlYd5fX8AAIqiCF6vF6VSibIsI5lMYvvDE1xymwDu/ec5BhkcIJPJIHJzFqf372P1cgMf
#   f46cLIKu61yJXufr5VO0voyzEZ/k8sI4s9ns0RFarRZjL56inIshekWGenYS6IzhR9PCntRBIBCw8XsiFItFNLMxPJgfwVjDi4Y8g2b9DILaMKZGd2Ca5tEGiqJg2xjF200H6J+AvKtjeG8T3998xW5nAk6n08bviSBJEqhewLlpN4bMHfwxfuH5J8J98SGerS/B4XDY
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
#
# We do need a catmap now too, but that's easy to aquire and will be kept
# within the cache dirs.
#
class shoutcast(channels.ChannelPlugin):

    # attrs
    base_url = "http://shoutcast.com/"
    listformat = "pls"
    has_search = False
    
    # categories
    categories = []
    catmap = {"Choral": 35, "Winter": 275, "JROCK": 306, "Motown": 237, "Political": 290, "Tango": 192, "Ska": 22, "Comedy": 283, "Decades": 212, "European": 143, "Reggaeton": 189, "Islamic": 307, "Freestyle": 114, "French": 145, "Western": 53, "Dancepunk": 6, "News": 287, "Xtreme": 23, "Bollywood": 138, "Celtic": 141, "Kids": 278, "Filipino": 144, "Hanukkah": 270, "Greek": 146, "Punk": 21, "Spiritual": 211, "Industrial": 14, "Baroque": 33, "Talk": 282, "JPOP": 227, "Scanner": 291, "Mediterranean": 154, "Swing": 174, "Themes": 89, "IDM": 75, "40s": 214, "Funk": 236, "Rap": 110, "House": 74, "Educational": 285, "Caribbean": 140, "Misc": 295, "30s": 213, "Anniversary": 266, "Sports": 293, "International": 134, "Tribute": 107, "Piano": 41, "Romantic": 42, "90s": 219, "Latin": 177, "Grunge": 10, "Dubstep": 312, "Government": 286, "Country": 44, "Salsa": 191, "Hardcore": 11, "Afrikaans": 309, "Downtempo": 69, "Merengue": 187, "Psychedelic": 260, "Female": 95, "Bop": 167, "Tribal": 80, "Metal": 195, "70s": 217, "Tejano": 193, "Exotica": 55, "Anime": 277, "BlogTalk": 296, "African": 135, "Patriotic": 101, "Blues": 24, "Turntablism": 119, "Chinese": 142, "Garage": 72, "Dance": 66, "Valentine": 273, "Barbershop": 222, "Alternative": 1, "Technology": 294, "Folk": 82, "Klezmer": 152, "Samba": 315, "Turkish": 305, "Trance": 79, "Dub": 245, "Rock": 250, "Polka": 59, "Modern": 39, "Lounge": 57, "Indian": 149, "Hindi": 148, "Brazilian": 139, "Eclectic": 93, "Korean": 153, "Creole": 316, "Dancehall": 244, "Surf": 264, "Reggae": 242, "Goth": 9, "Oldies": 226, "Zouk": 162, "Environmental": 207, "Techno": 78, "Adult": 90, "Rockabilly": 262, "Wedding": 274, "Russian": 157, "Sexy": 104, "Chill": 92, "Opera": 40, "Emo": 8, "Experimental": 94, "Showtunes": 280, "Breakbeat": 65, "Jungle": 76, "Soundtracks": 276, "LoFi": 15, "Metalcore": 202, "Bachata": 178, "Kwanzaa": 272, "Banda": 179, "Americana": 46, "Classical": 32, "German": 302, "Tamil": 160, "Bluegrass": 47, "Halloween": 269, "College": 300, "Ambient": 63, "Birthday": 267, "Meditation": 210, "Electronic": 61, "50s": 215, "Chamber": 34, "Heartache": 96, "Britpop": 3, "Soca": 158, "Grindcore": 199, "Reality": 103, "00s": 303, "Symphony": 43, "Pop": 220, "Ranchera": 188, "Electro": 71, "Christmas": 268, "Christian": 123, "Progressive": 77, "Jazz": 163, "Trippy": 108, "Instrumental": 97, "Tropicalia": 194, "Fusion": 170, "Healing": 209, "Glam": 255, "80s": 218, "KPOP": 308, "Worldbeat": 161, "Mixtapes": 117, "60s": 216, "Mariachi": 186, "Soul": 240, "Cumbia": 181, "Inspirational": 122, "Impressionist": 38, "Gospel": 129, "Disco": 68, "Arabic": 136, "Idols": 225, "Ragga": 247, "Demo": 67, "LGBT": 98, "Honeymoon": 271, "Japanese": 150, "Community": 284, "Weather": 317, "Asian": 137, "Hebrew": 151, "Flamenco": 314, "Shuffle": 105}
    
    # redefine
    streams = {}
    
        
    # Extracts the category list from www.shoutcast.com,
    # stores a catmap (title => id)
    def update_categories(self):
        html = ahttp.get(self.base_url)
        #log.DATA( html )
        self.categories = []
        
        # Genre list in sidebar


        """  <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)

        # group
        current = []
        for (title, id, main) in subs:
            self.catmap[title] = int(id)







|



















>
>
|
>
>







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
#
# We do need a catmap now too, but that's easy to aquire and will be kept
# within the cache dirs.
#
class shoutcast(channels.ChannelPlugin):

    # attrs
    base_url = "http://directory.shoutcast.com/"
    listformat = "pls"
    has_search = False
    
    # categories
    categories = []
    catmap = {"Choral": 35, "Winter": 275, "JROCK": 306, "Motown": 237, "Political": 290, "Tango": 192, "Ska": 22, "Comedy": 283, "Decades": 212, "European": 143, "Reggaeton": 189, "Islamic": 307, "Freestyle": 114, "French": 145, "Western": 53, "Dancepunk": 6, "News": 287, "Xtreme": 23, "Bollywood": 138, "Celtic": 141, "Kids": 278, "Filipino": 144, "Hanukkah": 270, "Greek": 146, "Punk": 21, "Spiritual": 211, "Industrial": 14, "Baroque": 33, "Talk": 282, "JPOP": 227, "Scanner": 291, "Mediterranean": 154, "Swing": 174, "Themes": 89, "IDM": 75, "40s": 214, "Funk": 236, "Rap": 110, "House": 74, "Educational": 285, "Caribbean": 140, "Misc": 295, "30s": 213, "Anniversary": 266, "Sports": 293, "International": 134, "Tribute": 107, "Piano": 41, "Romantic": 42, "90s": 219, "Latin": 177, "Grunge": 10, "Dubstep": 312, "Government": 286, "Country": 44, "Salsa": 191, "Hardcore": 11, "Afrikaans": 309, "Downtempo": 69, "Merengue": 187, "Psychedelic": 260, "Female": 95, "Bop": 167, "Tribal": 80, "Metal": 195, "70s": 217, "Tejano": 193, "Exotica": 55, "Anime": 277, "BlogTalk": 296, "African": 135, "Patriotic": 101, "Blues": 24, "Turntablism": 119, "Chinese": 142, "Garage": 72, "Dance": 66, "Valentine": 273, "Barbershop": 222, "Alternative": 1, "Technology": 294, "Folk": 82, "Klezmer": 152, "Samba": 315, "Turkish": 305, "Trance": 79, "Dub": 245, "Rock": 250, "Polka": 59, "Modern": 39, "Lounge": 57, "Indian": 149, "Hindi": 148, "Brazilian": 139, "Eclectic": 93, "Korean": 153, "Creole": 316, "Dancehall": 244, "Surf": 264, "Reggae": 242, "Goth": 9, "Oldies": 226, "Zouk": 162, "Environmental": 207, "Techno": 78, "Adult": 90, "Rockabilly": 262, "Wedding": 274, "Russian": 157, "Sexy": 104, "Chill": 92, "Opera": 40, "Emo": 8, "Experimental": 94, "Showtunes": 280, "Breakbeat": 65, "Jungle": 76, "Soundtracks": 276, "LoFi": 15, "Metalcore": 202, "Bachata": 178, "Kwanzaa": 272, "Banda": 179, "Americana": 46, "Classical": 32, "German": 302, "Tamil": 160, "Bluegrass": 47, "Halloween": 269, "College": 300, "Ambient": 63, "Birthday": 267, "Meditation": 210, "Electronic": 61, "50s": 215, "Chamber": 34, "Heartache": 96, "Britpop": 3, "Soca": 158, "Grindcore": 199, "Reality": 103, "00s": 303, "Symphony": 43, "Pop": 220, "Ranchera": 188, "Electro": 71, "Christmas": 268, "Christian": 123, "Progressive": 77, "Jazz": 163, "Trippy": 108, "Instrumental": 97, "Tropicalia": 194, "Fusion": 170, "Healing": 209, "Glam": 255, "80s": 218, "KPOP": 308, "Worldbeat": 161, "Mixtapes": 117, "60s": 216, "Mariachi": 186, "Soul": 240, "Cumbia": 181, "Inspirational": 122, "Impressionist": 38, "Gospel": 129, "Disco": 68, "Arabic": 136, "Idols": 225, "Ragga": 247, "Demo": 67, "LGBT": 98, "Honeymoon": 271, "Japanese": 150, "Community": 284, "Weather": 317, "Asian": 137, "Hebrew": 151, "Flamenco": 314, "Shuffle": 105}
    
    # redefine
    streams = {}
    
        
    # Extracts the category list from www.shoutcast.com,
    # stores a catmap (title => id)
    def update_categories(self):
        html = ahttp.get(self.base_url)
        #log.DATA( html )
        self.categories = []
        
        # Genre list in sidebar
        """
           <li id="genre-3" class="sub-genre " genreid="3" parentgenreid="1">
                <a href="/Genre?name=Britpop" onclick="return loadStationsByGenre('Britpop', 3, 1);">Britpop</a>
           </li>
        """
        rx = re.compile(r"loadStationsByGenre\(  '([^']+)' [,\s]* (\d+) [,\s]* (\d+)  \)", re.X)
        subs = rx.findall(html)

        # group
        current = []
        for (title, id, main) in subs:
            self.catmap[title] = int(id)
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
        # .categories/.catmap get saved by reload_categories()
        pass
        

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

        if (cat not in self.catmap):
            log.ERR( "Category not in known map.", cat )
            return []
        id = self.catmap[cat]

        # page
        url = "http://www.shoutcast.com/Home/BrowseByGenre"
        params = { "genrename": cat }
        referer = None
        try:
            json = ahttp.get(url, params=params, referer=referer, post=1, ajax=1)
            json = json_decode(json)
        except:
            log.ERR("HTTP request or JSON decoding failed. Outdated python/requests perhaps.")







<
<
<
<
<

|







94
95
96
97
98
99
100





101
102
103
104
105
106
107
108
109
        # .categories/.catmap get saved by reload_categories()
        pass
        

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






        # page
        url = "http://directory.shoutcast.com/Home/BrowseByGenre"
        params = { "genrename": cat }
        referer = None
        try:
            json = ahttp.get(url, params=params, referer=referer, post=1, ajax=1)
            json = json_decode(json)
        except:
            log.ERR("HTTP request or JSON decoding failed. Outdated python/requests perhaps.")