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

⌈⌋ ⎇ branch:  streamtuner2


Check-in [f8c1bd8ce6]

Overview
Comment:Fetch channels per API search first, add playlists afterwards.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f8c1bd8ce6dcc9afa0cbb95fa14310467ee3e6f3
User & Date: mario on 2016-07-11 18:37:05
Other Links: manifest | tags
Context
2016-08-24
01:21
Minor text fixes check-in: ac7e0587e9 user: mario tags: trunk
2016-07-11
18:37
Fetch channels per API search first, add playlists afterwards. check-in: f8c1bd8ce6 user: mario tags: trunk
2016-06-28
16:17
Remove di.fm help page check-in: cf0c3d95f9 user: mario tags: trunk
Changes

Modified channels/youtube.py from [296b5551ad] to [5f9e55387f].

1
2
3
4
5
6
7
8
9
10
11
12
13
# encoding: UTF-8
# api: streamtuner2
# title: Youtube
# description: Channel, playlist and video browsing for youtube.
# type: channel
# version: 0.2
# url: http://www.youtube.com/
# category: video
# config:
#    { name: youtube_channels,  type: text,  value: "Key Of Awesome, Pentatonix",  description: "Preferred channels to list videos from.",  category: select }
#    { name: youtube_region,  type: select,  select: "=No Region|AR=Argentina|AU=Australia|AT=Austria|BE=Belgium|BR=Brazil|CA=Canada|CL=Chile|CO=Colombia|CZ=Czech Republic|EG=Egypt|FR=France|DE=Germany|GB=Great Britain|HK=Hong Kong|HU=Hungary|IN=India|IE=Ireland|IL=Israel|IT=Italy|JP=Japan|JO=Jordan|MY=Malaysia|MX=Mexico|MA=Morocco|NL=Netherlands|NZ=New Zealand|PE=Peru|PH=Philippines|PL=Poland|RU=Russia|SA=Saudi Arabia|SG=Singapore|ZA=South Africa|KR=South Korea|ES=Spain|SE=Sweden|CH=Switzerland|TW=Taiwan|AE=United Arab Emirates|US=United States",  value: GB,  description: "Filter by region id.",  category: auth }
#    { name: youtube_wadsworth,  type: boolean,  value: 0,  description: "Apply Wadsworth constant.",  category: filter }
# priority: default





|







1
2
3
4
5
6
7
8
9
10
11
12
13
# encoding: UTF-8
# api: streamtuner2
# title: Youtube
# description: Channel, playlist and video browsing for youtube.
# type: channel
# version: 0.3
# url: http://www.youtube.com/
# category: video
# config:
#    { name: youtube_channels,  type: text,  value: "Key Of Awesome, Pentatonix",  description: "Preferred channels to list videos from.",  category: select }
#    { name: youtube_region,  type: select,  select: "=No Region|AR=Argentina|AU=Australia|AT=Austria|BE=Belgium|BR=Brazil|CA=Canada|CL=Chile|CO=Colombia|CZ=Czech Republic|EG=Egypt|FR=France|DE=Germany|GB=Great Britain|HK=Hong Kong|HU=Hungary|IN=India|IE=Ireland|IL=Israel|IT=Italy|JP=Japan|JO=Jordan|MY=Malaysia|MX=Mexico|MA=Morocco|NL=Netherlands|NZ=New Zealand|PE=Peru|PH=Philippines|PL=Poland|RU=Russia|SA=Saudi Arabia|SG=Singapore|ZA=South Africa|KR=South Korea|ES=Spain|SE=Sweden|CH=Switzerland|TW=Taiwan|AE=United Arab Emirates|US=United States",  value: GB,  description: "Filter by region id.",  category: auth }
#    { name: youtube_wadsworth,  type: boolean,  value: 0,  description: "Apply Wadsworth constant.",  category: filter }
# priority: default
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
        # My Channels
        # - searches channel id for given title
        # - iterates over playlist
        # - then over playlistitems to get videos
        elif cat in channels:
            # channel id, e.g. UCEmCXnbNYz-MOtXi3lZ7W1Q
            UC = self.channel_id(cat)
            




            # playlist
            for i,playlist in enumerate(self.api("playlists", fields="items(id,snippet/title)", channelId=UC, maxResults=15)):

                # items (videos)
                for row in self.api("playlistItems", playlistId=playlist["id"], fields="items(snippet(title,resourceId/videoId,description))"):
                    entries.append(self.wrap3(row, {"genre": cat, "playing": playlist["snippet"]["title"]}))

                self.update_streams_partially_done(entries)
                self.parent.status(i / 15.0)
            




        
        # empty entries
        else:
            return self.placeholder
 
        # done    
        return entries







|
>
>
>
>
|









>
>
>
>







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
        # My Channels
        # - searches channel id for given title
        # - iterates over playlist
        # - then over playlistitems to get videos
        elif cat in channels:
            # channel id, e.g. UCEmCXnbNYz-MOtXi3lZ7W1Q
            UC = self.channel_id(cat)

            # fetches videos ordered by date
            for row in self.api("search", order="date", fields="pageInfo,nextPageToken,items(id,snippet(title,channelTitle,description))", channelId=UC, type="video"):
                entries.append( self.wrap3(row, {"genre": cat, "playing": cat}) )
            
            # augments with playlist entries
            for i,playlist in enumerate(self.api("playlists", fields="items(id,snippet/title)", channelId=UC, maxResults=15)):

                # items (videos)
                for row in self.api("playlistItems", playlistId=playlist["id"], fields="items(snippet(title,resourceId/videoId,description))"):
                    entries.append(self.wrap3(row, {"genre": cat, "playing": playlist["snippet"]["title"]}))

                self.update_streams_partially_done(entries)
                self.parent.status(i / 15.0)
            
            # unique entries
            e = []
            [e.append(v) for v in entries if v not in e]
            entries = e
        
        # empty entries
        else:
            return self.placeholder
 
        # done    
        return entries
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
        return id
    channel2id = {}



    #-- Retrieve Youtube API query results
    #
    def api(self, method, ver=3, pages=5, **params):
        items = []

        # URL and default parameters
        (base_url, defaults) = self.service[ver]
        params = dict( list(defaults.items()) + list(params.items())  )

        # Retrieve data set
        while pages > 0:
            j = ahttp.get(base_url + method, params=params)

            #log.DATA(j)
            if j:
                # json decode
                data = json.loads(j)
                
                # extract items
                if "items" in data:







|









>







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
        return id
    channel2id = {}



    #-- Retrieve Youtube API query results
    #
    def api(self, method, ver=3, pages=5, debug=False, **params):
        items = []

        # URL and default parameters
        (base_url, defaults) = self.service[ver]
        params = dict( list(defaults.items()) + list(params.items())  )

        # Retrieve data set
        while pages > 0:
            j = ahttp.get(base_url + method, params=params)
            #if debug:
            #log.DATA(j)
            if j:
                # json decode
                data = json.loads(j)
                
                # extract items
                if "items" in data:
289
290
291
292
293
294
295

296
297

298
299
300
301

302
303
304
305
306
307
308

        data.update(dict(
            url = "http://youtube.com/v/" + id,
            homepage = "http://youtu.be/" + id + ("?wadsworth=1" if conf.youtube_wadsworth else ""),
            format = self.audioformat,
            title = row["snippet"]["title"],
        ))

        
        # optional values

        if "playing" not in data:
            data["playing"] = row["snippet"]["channelTitle"]
        if "description" in row["snippet"]:
            data["description"] = row["snippet"]["description"],


        return data


    # API version 2.0s jsonified XML needs different unpacking:
    def wrap2(self, row):
        #log.DATA(row)







>


>
|
|
|
|
>







298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320

        data.update(dict(
            url = "http://youtube.com/v/" + id,
            homepage = "http://youtu.be/" + id + ("?wadsworth=1" if conf.youtube_wadsworth else ""),
            format = self.audioformat,
            title = row["snippet"]["title"],
        ))
        #log.DATA(row)
        
        # optional values
        if "snippet" in row:
            if "playing" not in data and "channelTitle" in row["snippet"]:
                 data["playing"] = row["snippet"]["channelTitle"]
            if "description" in row["snippet"] and "description" in row["snippet"]:
                data["description"] = row["snippet"]["description"],
        #log.UI(data)

        return data


    # API version 2.0s jsonified XML needs different unpacking:
    def wrap2(self, row):
        #log.DATA(row)