13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | 13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 |
-
-
-
+
+
| # config:
# { type: env, name: http_proxy, description: proxy for HTTP access }
# { type: env, name: XDG_CONFIG_HOME, description: relocates user .config subdirectory }
# category: sound
# depends: pygtk | gi, threading, requests, pyquery, lxml
# id: streamtuner2
# pack: *.py, gtk3.xml.zlib, bin, channels/__init__.py, bundle/*.py, CREDITS, help/index.page,
# streamtuner2.desktop=/usr/share/applications/, README=/usr/share/doc/streamtuner2/,
# help/streamtuner2.1=/usr/share/man/man1/, NEWS.gz=/usr/share/doc/streamtuner2/changelog.gz,
# logo.png=/usr/share/pixmaps/streamtuner2.png
# streamtuner2.desktop, README, help/streamtuner2.1=/usr/share/man/man1/,
# NEWS.gz=/usr/share/doc/streamtuner2/changelog.gz, logo.png=/usr/share/pixmaps/streamtuner2.png
# architecture: all
#
# Streamtuner2 is a GUI for browsing internet radio directories, music
# collections, and video services - grouped by genres or categories.
# It runs your preferred audio player, and streamripper for recording.
#
# It's an independent rewrite of streamtuner1. Being written in Python, |
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441 | 400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444 |
-
-
+
+
+
+
+
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
|
# load plugins from /usr/share/streamtuner2/channels/
def load_plugin_channels(self):
# initialize plugin modules (pre-ordered)
ls = module_list()
for module in ls:
gui_startup(4/20.0 + 13.5/20.0 * float(ls.index(module))/len(ls), "loading module "+module)
for name in ls:
gui_startup(4/20.0 + 13.5/20.0 * float(ls.index(name))/len(ls), "loading module "+name)
# load defaults on first startup
if not name in conf.plugins:
conf.add_plugin_defaults(plugin_meta(module=name), name)
# skip module if disabled
if conf.plugins.get(module, 1) == False:
__print__(dbg.STAT, "disabled plugin:", module)
if conf.plugins.get(name, 1) == False:
__print__(dbg.STAT, "disabled plugin:", name)
continue
# or if it's a built-in (already imported)
elif module in self.features or module in self.channels:
elif name in self.features or name in self.channels:
continue
# load plugin
try:
plugin = __import__("channels."+module, globals(), None, [""])
plugin = __import__("channels."+name, globals(), None, [""])
#print [name for name,c in inspect.getmembers(plugin) if inspect.isclass(c)]
plugin_class = plugin.__dict__[module]
plugin_class = plugin.__dict__[name]
plugin_obj = plugin_class(parent=self)
# add to .channels{}
if issubclass(plugin_class, channels.GenericChannel):
self.channels[module] = plugin_obj
self.channels[name] = plugin_obj
# or .features{} for other plugin types
else:
self.features[module] = plugin_obj
self.features[name] = plugin_obj
except Exception as e:
__print__(dbg.INIT, "load_plugin_channels: error initializing:", module, ", exception:")
__print__(dbg.INIT, "load_plugin_channels: error initializing:", name, ", exception:")
traceback.print_exc()
# store window/widget states (sizes, selections, etc.)
def app_state(self, widget):
# gtk widget states
widgetnames = ["win_streamtuner2", "toolbar", "notebook_channels", ] \ |