1
2
3
4
5
6
7
8
9
10
11
12
13
14 | 1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
-
+
| # encoding: UTF-8
# api: streamtuner2
# type: class
# category: ui
# title: Channel plugins
# description: Base implementation for channels and feature plugins
# version: 1.6
# version: 1.7
# license: public domain
# author: mario
# url: http://fossil.include-once.org/streamtuner2/
# pack:
# *.py
# config: -
# priority: core |
|
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 | 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 |
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
| import re
import copy
import inspect
# Only export plugin classes and a few utility functions
__all__ = [
"GenericChannel", "ChannelPlugin", "use_rx", "mime_fmt",
"entity_decode", "strip_tags", "nl", "unhtml", "to_int"
"FeaturePlugin", "GenericChannel", "ChannelPlugin", "use_rx", "mime_fmt",
"stub_parent", "entity_decode", "strip_tags", "nl", "unhtml", "to_int"
]
__path__.insert(0, conf.dir + "/plugins")
# Base class for plugins (features or channels)
class FeaturePlugin(object):
# plugin meta and object references
module = ""
meta = { "config": [] }
parent = None # main window
# minimum setup for ChannelPlugins and feature hooks
def __init__(self, parent, *k, **kw):
# set up meta infos
self.parent = parent
self.module = self.__class__.__name__
self.meta = plugin_meta(src = inspect.getcomments(inspect.getmodule(self)))
self.config = self.meta.get("config", [])
self.title = self.meta.get("title", self.module)
# add default options values to config.conf.* dict
conf.add_plugin_defaults(self.meta, self.module)
# implicit action handler registration
if hasattr(self, "resolve_urn"):
action.handler["urn:%s" % self.module] = self.resolve_urn
# secondary init function
self.init2(parent)
# optionally to be overriden by plugins (run after base __init__)
def init2(self, parent, *k, **kw):
pass
# Statusbar stub (defers to parent/main window, if in GUI mode)
def status(self, *args, **kw):
if self.parent:
self.parent.status(*args, **kw)
else:
log.INFO("status():", *v)
# Statusbar with highlighting and default icon
def warn(self, text, *args, **kw):
if isinstance(text, (str, unicode)) and "status_color" in conf:
text = "<span background='%s'>%s</span>" % (conf.status_color, text)
kw["markup"] = 1
if not "icon" in kw:
kw["icon"] = "gtk-dialog-warning"
self.status(text, *args, **kw)
# Generic channel module
class GenericChannel(object):
class GenericChannel(FeaturePlugin):
# control attributes
meta = { "config": [] }
base_url = ""
listformat = "pls"
audioformat = "audio/mpeg" # fallback value
has_search = False |
|
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 | 117
118
119
120
121
122
123
124
125
126
127
128
129
130 |
-
| gtk_list = None # Gtk widget for station treeview
gtk_cat = None # Gtk widget for category columns
ls = None # ListStore for station treeview
rowmap = None # Preserve streams-datamap
pix_entry = None # ListStore entry that contains favicon
img_resize = None # Rescale `img` references to icon size
fixed_size = [24,24] # Default height+width for favicons
parent = None # reference to main window
# mapping of stream{} data into gtk treeview/treestore representation
datamap = [
# coltitle width [ datasrc key, type, renderer, attrs ] [cellrenderer2], ...
["", 20, ["state", str, "pixbuf", {}], ],
["Genre", 65, ['genre', str, "t", {}], ],
["Station Title",275, ["title", str, "text", {"strikethrough":11, "cell-background":12, "cell-background-set":13}], ["favicon", gtk.gdk.Pixbuf, "pixbuf", {}], ], |
|
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150 | 173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189 |
-
-
-
-
-
+
-
-
-
+
-
-
-
+
-
-
|
# constructor
def __init__(self, parent=None):
#self.streams = {}
self.gtk_list = None
self.gtk_cat = None
self.module = self.__class__.__name__
self.meta = plugin_meta(src = inspect.getcomments(inspect.getmodule(self)))
self.config = self.meta.get("config", [])
self.title = self.meta.get("title", self.module)
# add default options values to config.conf.* dict
conf.add_plugin_defaults(self.meta, self.module)
# base init (meta infos, parent reference, init2)
# extra init function
if hasattr(self, "init2"):
self.init2(parent)
FeaturePlugin.__init__(self, parent)
if hasattr(self, "resolve_urn"):
action.handler["urn:%s" % self.module] = self.resolve_urn
# Only if streamtuner2 is run in graphical mode
if (parent):
# Update/display stream processors
if not self.prepare_filters:
self.prepare_filters += [
self.prepare_filter_icons, |
|
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 | 229
230
231
232
233
234
235
236
237
238
239
240
241
242 |
-
-
-
-
-
-
-
-
| def columns(self, entries=None):
self.ls, self.rowmap, self.pix_entry = uikit.columns(
self.gtk_list, self.datamap, entries,
show_favicons=True, fixed_size=self.fixed_size
)
# no longer using `conf.show_favicons`
# Statusbar stub (defers to parent/main window, if in GUI mode)
def status(self, *args, **kw):
if self.parent: self.parent.status(*args, **kw)
else: log.INFO("status():", *v)
def warn(self, *args, **kw):
self.status(*args, icon="gtk-dialog-warning", **kw)
#--------------------- streams/model data accesss ---------------------------
# Traverse category TreeModel to set current, expand parent nodes
def select_current(self, name): |
|
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607 | 616
617
618
619
620
621
622
623
624
625
626
627
628
629 |
-
-
-
-
-
-
-
-
-
| listformat = row.get("listformat", self.listformat)
action.record(row, audioformat, listformat)
return row
# channel plugin without glade-pre-defined notebook tab
#
class ChannelPlugin(GenericChannel):
module = "abstract" |
|
678
679
680
681
682
683
684
685
686
687
688
689
690
691 | 700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715 |
+
+
|
# try to initialize superclass now, before adding to channel tabs
GenericChannel.gui(self, parent)
# add notebook tab
tab = parent.notebook_channels.insert_page_menu(vbox, ev_label, plain_label, -1)
parent.notebook_channels.set_tab_reorderable(vbox, True)
# WORKAROUND for direct channel module imports,
# eases instantiations without GUI a little,
# reducing module dependencies (conf. / ahttp. / channels. / parent.) would be better
def stub_parent(object): |
|