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

⌈⌋ ⎇ branch:  streamtuner2


Check-in [59075dcc1b]

Overview
Comment:Apply proper file extension to temp files (they're never cleaned up, are they?) Fix MIME type probing, strip attributes. Support Apple M3U minor type, detect GVP playlists.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | action-mapfmts
Files: files | file ages | folders
SHA1: 59075dcc1b794f69604ed60cb7b9452c55b8ea7b
User & Date: mario on 2015-04-10 11:56:40
Other Links: branch diff | manifest | tags
Context
2015-04-10
13:50
Implement filename update in SaveAs dialog on changing FileFilter (.m3u, .pls, .xspf) extension. check-in: 0a9cb60b3a user: mario tags: action-mapfmts
11:56
Apply proper file extension to temp files (they're never cleaned up, are they?) Fix MIME type probing, strip attributes. Support Apple M3U minor type, detect GVP playlists. check-in: 59075dcc1b user: mario tags: action-mapfmts
11:55
SurfMusik actually holds .m3u playlists. check-in: 46062ce00f user: mario tags: action-mapfmts
Changes

Modified action.py from [666f98e53e] to [a1f8b1c311].

44
45
46
47
48
49
50

51
52
53
54
55
56
57
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58







+









# Streamlink/listformat mapping
listfmt_t = {
    "audio/x-scpls":        "pls",
    "audio/x-mpegurl":      "m3u",
    "audio/mpegurl":        "m3u",
    "application/vnd.apple.mpegurl": "m3u",
    "video/x-ms-asf":       "asx",
    "application/xspf+xml": "xspf",
    "*/*":                  "href",  # "href" for unknown responses
    "url/direct":           "srv",
    "url/youtube":          "href",
    "url/http":             "href",
    "audio/x-pn-realaudio": "ram",
96
97
98
99
100
101
102

103
104
105
106
107
108
109
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111







+







   ("smil", r""" <smil[^>]*> .* <seq> """),
   ("html", r""" <(audio|video)\b[^>]+\bsrc\s*=\s*["']?https?:// """),
   ("wpl",  r""" <\?wpl \s+ version="1\.0" \s* \?> """),
   ("b4s",  r""" <WinampXML> """),   # http://gonze.com/playlists/playlist-format-survey.html
   ("jspf", r""" ^ \s* \{ \s* "playlist": \s* \{ """),
   ("asf",  r""" ^ \[Reference\] .*? ^Ref\d+= """),
   ("json", r""" "url": \s* "\w+:// """),
   ("gvp",  r""" ^gvp_version:1\.\d+$ """),
   ("href", r""" .* """),
]



# Exec wrapper
#
245
246
247
248
249
250
251
252

253
254
255
256
257
258
259
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261







-
+







        return [url]
    elif dest in ("srv", "href"):
        return urls
    debug( urls )

    # Otherwise convert to local file
    if local_file:
        fn, is_unique = tmp_fn(cnt)
        fn, is_unique = tmp_fn(cnt, dest)
        with open(fn, "wb") as f:
            debug(dbg.DATA, "exporting with format:", dest, " into filename:", fn)
            f.write( save_playlist(source="srv", multiply=True).export(urls=urls, dest=dest, title=title) )
        return [fn]
    else:
        return urls

269
270
271
272
273
274
275

276
277
278
279
280
281
282
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285







+







        if not len(r.headers):
            return ("srv", r)
    except:
        return ("srv", None)

    # Extract payload
    mime = r.headers.get("content-type", "href")
    mime = mime.split(";")[0].strip()
    # Map MIME to abbr type (pls, m3u, xspf)
    if listfmt_t.get(mime):
        mime = listfmt_t.get(mime)
    # Raw content (mp3, flv)
    elif mediafmt_t.get(mime):
        debug(dbg.ERR, "Got media MIME type for expected playlist", mime, " on url=", url)
        mime = mediafmt_t.get(mime)
444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459

460
461
462
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461

462
463
464
465







-
+







-
+



    global xmlentities
    from xml.sax.saxutils import escape as xmlentities
    return xmlentities(s)



# generate filename for temporary .m3u, if possible with unique id
def tmp_fn(pls):
def tmp_fn(pls, ext="m3u"):
    # use shoutcast unique stream id if available
    stream_id = re.search("http://.+?/.*?(\d+)", pls, re.M)
    stream_id = stream_id and stream_id.group(1) or "XXXXXX"
    try:
        channelname = main.current_channel
    except:
        channelname = "unknown"
    return (str(conf.tmp) + os.sep + "streamtuner2."+channelname+"."+stream_id+".m3u", len(stream_id) > 3 and stream_id != "XXXXXX")
    return (str(conf.tmp) + os.sep + "streamtuner2."+channelname+"."+stream_id+"."+ext, len(stream_id) > 3 and stream_id != "XXXXXX")