Check-in [8a77525fb0]
Overview
Comment: | new plugin: script stations, for single-station extractiong/user scripts |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
8a77525fb0a2517104b5d10333a80cc7 |
User & Date: | mario on 2016-12-17 11:14:01 |
Other Links: | manifest | tags |
Context
2016-12-17
| ||
11:22 | Set Frequence3 as new default bookmark (curb the finder song) check-in: 0e8c56d915 user: mario tags: trunk | |
11:14 | new plugin: script stations, for single-station extractiong/user scripts check-in: 8a77525fb0 user: mario tags: trunk | |
11:01 | Adapt urn_resolve() invocation. Most handlers update the dict in place. A few will return a new row however. (This can be utilized to return a copy, instead of changing station entries → menat for user "script stations" plugin.) check-in: 0a425cfb5d user: mario tags: trunk | |
Changes
Modified channels/bookmarks.py from [767c735b6c] to [e1104d7956].
︙ | ︙ | |||
38 39 40 41 42 43 44 45 46 47 48 49 50 51 | # content listformat = "any" categories = ["favourite", ] # timer, links, search, and links show up as needed finder_song = { "genre": "Youtube ", "format": "video/youtube", "playing": "current_", "title": "The Finder song", "url": "http://youtube.com/v/omyZy4H8y9M", "homepage": "http://youtu.be/omyZy4H8y9M" } streams = {"favourite":[finder_song], "search":[], "scripts":[], "timer":[], "history":[], } default = "favourite" # cache list, to determine if a PLS url is bookmarked urls = [] def gui(self, parent): parent.notebook_channels.set_menu_label_text(parent.v_bookmarks, "bookmarks") | > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | # content listformat = "any" categories = ["favourite", ] # timer, links, search, and links show up as needed finder_song = { "genre": "Youtube ", "format": "video/youtube", "playing": "current_", "title": "The Finder song", "url": "http://youtube.com/v/omyZy4H8y9M", "homepage": "http://youtu.be/omyZy4H8y9M" } streams = {"favourite":[finder_song], "search":[], "scripts":[], "timer":[], "history":[], } default = "favourite" fixed_size = [32,24] # cache list, to determine if a PLS url is bookmarked urls = [] def gui(self, parent): parent.notebook_channels.set_menu_label_text(parent.v_bookmarks, "bookmarks") |
︙ | ︙ |
Added contrib/scripts.py version [d8221b6773].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 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 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 119 120 121 122 123 124 125 126 127 128 | # encoding: UTF-8 # api: streamtuner2 # title: Script stations # description: User scripts for individual stations # type: feature # category: bookmark # version: 0.1 # priority: theoretical # # This plugin provides for a simpler alternative to channel plugins. # It reads the ~./config/streamtuner2/script/ directory for script # files, and shows them in the bookmarks channel. Each script may # scan/uncover a station url at runtime. # Which obviously isn't meant for easily parseable stations, but for # the more difficult cases. # # There's support for python scripts obviously, but any executable # file (scripting language) can be run and queried for urls. # # Each is supposed to contain a meta comment block (much like this # plugin), except it's using more stream-oriented descriptors: # # #!/bin/sh # # title: Station title # # description: Fetching a live stream # # genre: jazz # # homepage: http://example.org/ # # # # Now normally, it would not just print something static. # # echo "http://example.org/.mp3" # # Obviously the purpose is more complicated extractions. Which is # why a .py script had acces to all ST2s parsing tools already. # # This is implemented using the action.handler hooks for urn: # modules. But ensures the resolver script is run each time - by # not caching the final stream url. # Conversly this plugin prevents editing of script station entries. # import os, shutil, copy, subprocess, sys, StringIO import csv, zipfile import re, json, pq import ahttp import config from config import * import uikit from compat2and3 import * import action from channels import * # dynamic station extractors from ~/.config/streamtuner2/scripts/ class scripts (object): # plugin info module = "scripts" meta = plugin_meta() parent = None dir = conf.dir + "/scripts" # register hooks def __init__(self, parent): if not os.path.exists(self.dir): os.mkdir(self.dir) self.parent = parent self.bm = parent.bookmarks action.handler["urn:script"] = self.urn_resolve self.bm.add_category("scripts") self.bm.category_plugins["scripts"] = self # find script files and compile station dicts def update_streams(self, cat): r = [] for fn in os.listdir(self.dir): meta = config.plugin_meta(fn=self.dir+"/"+fn) r.append(dict( genre = meta.get("genre", meta.get("type", "script")), title = meta.get("title", fn), playing = meta.get("description", meta.get("playing", "")), homepage = meta.get("homepage", ""), listeners = to_int(meta.get("listeners", "1")), bitrate = to_int(meta.get("bitrate", "64")), format = meta.get("format", "audio/mp3"), listformat = "href", file = fn, url = "urn:script:" + fn )) return r # run'em def urn_resolve(self, row, *x): if not row.get("file"): return # prepare fn = "%s/%s" % (self.dir, row["file"]) row = copy.copy(row) row["url"] = "" output = None # executable if os.path.isfile(fn) and os.access(fn, os.X_OK): f = subprocess.Popen([fn], stdout=subprocess.PIPE) output, err = f.communicate() # plain python script elif re.match("^[\w+-]\.py$"): real_stdout, sys.stdout = sys.stdout, StringIO.StringIO() execfile(fn) output, sys.stdout = sys.stdout.getvalue(), real_stdout # none else: return # extract urls if output: urls = re.findall("(\w+://\S+)", output) if urls: row["url"] = urls[0] # action module does not currently support multi-urls return row # Unlike other .resolve_urn() handlers this one returns a copy, # does not modify the passed dict. And this is only handled in # action.run_fmt_url(), but not by GenericChannel.play(). Why # OTOH this incudes a *double script invocation*. |