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*.
|