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

⌈⌋ ⎇ branch:  streamtuner2


Check-in [5fe8de1fd7]

Overview
Comment:Support direct URLs in DND import (only used as literal url=, brings up streamedit window afterwards).
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5fe8de1fd7871c8ba16e256ea53cf2fa3483568d
User & Date: mario on 2015-05-05 10:43:26
Other Links: manifest | tags
Context
2015-05-05
10:44
Simplify core plugin dependency lookups. check-in: 120249ab54 user: mario tags: trunk
10:43
Support direct URLs in DND import (only used as literal url=, brings up streamedit window afterwards). check-in: 5fe8de1fd7 user: mario tags: trunk
10:42
Fix missing channel key error. Add icon. check-in: f4dfbc1e53 user: mario tags: trunk
Changes

Modified channels/dnd.py from [b0d6800112] to [129abbd2da].

1
2
3
4
5
6
7
8
9
10
11
12
13
# encoding: UTF-8
# api: streamtuner2
# title: Drag and Drop
# description: Copy streams/stations from and to other applications.
# depends: uikit >= 1.8, action >= 1.0
# version: 0.6
# type: feature
# config:
#   { name: dnd_format, type: select, value: xspf, select: "pls|m3u|xspf|jspf|asx|smil|desktop|srv", description: "Default temporary file format for copying a station." }
# category: io
# priority: default
# support: experimental
#





|







1
2
3
4
5
6
7
8
9
10
11
12
13
# encoding: UTF-8
# api: streamtuner2
# title: Drag and Drop
# description: Copy streams/stations from and to other applications.
# depends: uikit >= 1.8, action >= 1.0
# version: 0.7
# type: feature
# config:
#   { name: dnd_format, type: select, value: xspf, select: "pls|m3u|xspf|jspf|asx|smil|desktop|srv", description: "Default temporary file format for copying a station." }
# category: io
# priority: default
# support: experimental
#
189
190
191
192
193
194
195

196
197
198

199
200
201
202
203

204
205
206

207
208
209

210

211
212
213
214
215
216
217
        
        # Prepare new converter
        cnv = action.save_playlist(source=r["listformat"], multiply=False)

        # internal JSON row
        if info >= 51:
            buf = 'text', json.dumps(r)

        # Pass M3U/PLS/XSPF as literal payload
        elif info >= 20:
            buf = 'text', cnv.export(urls=[r["url"]], row=r, dest=self.cnv_types[info])

        # Direct server URL
        elif info >= 10:
            urls = action.convert_playlist(r["url"], r["listformat"], "srv", False, r)
            #buf = 'uris', urls
            buf = 'text', urls[0]

        # Text sources are assumed to understand the literal URL or expect a description block
        elif info >= 5:
            buf = 'text', "{url}\n# Title: {title}\n# Homepage: {homepage}\n\n".format(**r)

        # Direct URL as text/uri-list
        elif conf.dnd_format == "srv":
            buf = 'uris', [self.row.get("url")]

        # Create temporary PLS file, because "text/uri-list" is widely misunderstood and just implemented for file:// IRLs

        else:
            title = re.sub("[^\w-]+", "_", r["title"]).strip()
            tmpfn = "{}/{}.{}".format(conf.tmp, title, conf.dnd_format)
            log.DND("tmpfn", tmpfn)
            cnv.file(rows=[r], dest=conf.dnd_format, fn=tmpfn)
            if info == 4:
                buf = 'uris', ["file://{}".format(tmpfn)]







>



>





>



>



>
|
>







189
190
191
192
193
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
        
        # Prepare new converter
        cnv = action.save_playlist(source=r["listformat"], multiply=False)

        # internal JSON row
        if info >= 51:
            buf = 'text', json.dumps(r)

        # Pass M3U/PLS/XSPF as literal payload
        elif info >= 20:
            buf = 'text', cnv.export(urls=[r["url"]], row=r, dest=self.cnv_types[info])

        # Direct server URL
        elif info >= 10:
            urls = action.convert_playlist(r["url"], r["listformat"], "srv", False, r)
            #buf = 'uris', urls
            buf = 'text', urls[0]

        # Text sources are assumed to understand the literal URL or expect a description block
        elif info >= 5:
            buf = 'text', "{url}\n# Title: {title}\n# Homepage: {homepage}\n\n".format(**r)

        # Direct URL as text/uri-list
        elif conf.dnd_format == "srv":
            buf = 'uris', [self.row.get("url")]

        # Create temporary PLS file, because "text/uri-list" is widely misunderstood
        # and just used for file:// IRLs in drag and drops
        else:
            title = re.sub("[^\w-]+", "_", r["title"]).strip()
            tmpfn = "{}/{}.{}".format(conf.tmp, title, conf.dnd_format)
            log.DND("tmpfn", tmpfn)
            cnv.file(rows=[r], dest=conf.dnd_format, fn=tmpfn)
            if info == 4:
                buf = 'uris', ["file://{}".format(tmpfn)]
266
267
268
269
270
271
272


273
274


275
276
277

278
279
280
281
282
283
284


285
286

287
288
289
290








291
292
293
294
295
296
297
            log.DND("Received row in internal format, append+reload")
            rows += [ json.loads(data) ]

        # Convertible formats as direct payload
        elif data and info >= 5:
            log.DND("Converting direct payload playlist")
            cnv = action.extract_playlist(data)


            if info >= 20:
                fmt = self.cnv_types[info]


            else:
                fmt = cnv.probe_fmt()
                if fmt == "href": fmt = "raw"

            add = cnv.rows(fmt)
            rows += [ cnv.mkrow(row) for row in add ]

        # Extract from playlist files, either passed as text/uri-list or single FILE_NAME
        elif urls:
            log.DND("Importing from playlist file")
            for fn in urls or [data]:


                if not re.match("^(scp|file)://(localhost)?/|/", fn):
                    continue

                fn = compat2and3.urldecode(re.sub("^\w+://[^/]*", "", fn))
                cnv = action.extract_playlist(fn=fn)
                if cnv.src:
                    rows += [ cnv.mkrow(row) for row in cnv.rows() ]








        
        # Insert and update view
        if rows:
            cn.insert_rows(rows, y)
            cn.save()
            # Show streamedit window if title is empty
            if not len(rows[0].get("title", "")):







>
>


>
>



>







>
>
|
|
>
|
|
|
|
>
>
>
>
>
>
>
>







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
            log.DND("Received row in internal format, append+reload")
            rows += [ json.loads(data) ]

        # Convertible formats as direct payload
        elif data and info >= 5:
            log.DND("Converting direct payload playlist")
            cnv = action.extract_playlist(data)
            
            # known DND info format
            if info >= 20:
                fmt = self.cnv_types[info]

            # else probe content (which also works for URLs in plain text)
            else:
                fmt = cnv.probe_fmt()
                if fmt == "href": fmt = "raw"

            add = cnv.rows(fmt)
            rows += [ cnv.mkrow(row) for row in add ]

        # Extract from playlist files, either passed as text/uri-list or single FILE_NAME
        elif urls:
            log.DND("Importing from playlist file")
            for fn in urls or [data]:

                # Plain file urls
                if re.match("^(scp|file)://(localhost)?/|/", fn):

                    # read and convert playlist files
                    fn = compat2and3.urldecode(re.sub("^\w+://[^/]*", "", fn))
                    cnv = action.extract_playlist(fn=fn)
                    if cnv.src:
                        rows += [ cnv.mkrow(row) for row in cnv.rows() ]

                # Real resource links, http://server:8090/.mp3 etc
                else:
                    # Action module can't query streaming servers yet,
                    # so append a stub entry of just the target url,
                    # which will bring up the streamedit dialog
                    rows += [ dict(url=fn, title="", playing="", genre="url") ]
                    
        
        # Insert and update view
        if rows:
            cn.insert_rows(rows, y)
            cn.save()
            # Show streamedit window if title is empty
            if not len(rows[0].get("title", "")):