Index: channels/__init__.py ================================================================== --- channels/__init__.py +++ channels/__init__.py @@ -1,15 +1,16 @@ # # encoding: UTF-8 # api: streamtuner2 # type: base # category: ui -# title: Channel plugin handling +# title: Channel plugins # description: Base implementation for channels and feature plugins # version: 1.1 # license: public domain # author: mario +# url: http://fossil.include-once.org/streamtuner2/ # pack: # file.py global_key.py history.py icast.py internet_radio.py # itunes.py jamendo.py links.py live365.py modarchive.py # myoggradio.py punkcast.py shoutcast.py surfmusik.py tunein.py # timer.py xiph.py youtube.py radiotray.py *.png @@ -42,10 +43,11 @@ import os.path import xml.sax.saxutils import re import copy import inspect +import pkgutil # Only export plugin classes __all__ = [ "GenericChannel", "ChannelPlugin", "module_list" @@ -56,38 +58,27 @@ # Search through ./channels/ and get module basenames. # Also order them by conf.channel_order # def module_list(): - # find plugin files - ls = os.listdir(conf.share + "/channels/") - ls = [fn[:-3] for fn in ls if re.match("^[a-z][\w\d_]+\.py$", fn)] + # Should list plugins within zips as well as local paths + ls = pkgutil.iter_modules(["channels"]) + ls = [name for loader,name,ispkg in ls] # resort with tab order order = [module.strip() for module in conf.channel_order.lower().replace(".","_").replace("-","_").split(",")] ls = [module for module in (order) if (module in ls)] + [module for module in (ls) if (module not in order)] return ls - -# dict==object -#class struct(dict): -# def __init__(self, *xargs, **kwargs): -# self.__dict__ = self -# self.update(kwargs) -# [self.update(x) for x in xargs] -# pass - # generic channel module --------------------------------------- class GenericChannel(object): # desc - module = "generic" - meta = {} - title = "GenericChannel" + meta = { "config": [] } homepage = "http://fossil.include-once.org/streamtuner2/" base_url = "" listformat = "audio/x-scpls" audioformat = "audio/mpeg" # fallback value config = [] @@ -135,12 +126,13 @@ def __init__(self, parent=None): #self.streams = {} self.gtk_list = None self.gtk_cat = None - self.meta = plugin_meta(inspect.getsourcefile(inspect.getmodule(self))) - self.config = self.meta["config"] + self.meta = plugin_meta(None, inspect.getcomments(inspect.getmodule(self))) + self.config = self.meta.get("config", []) + self.title = self.meta.get("title", self.module) # only if streamtuner2 is run in graphical mode if (parent): self.cache() self.gui(parent) @@ -150,10 +142,20 @@ # called before application shutdown # some plugins might override this, to save their current streams[] data def shutdown(self): pass #__del__ = shutdown + + + # get class name + @property + def module(self): + return self.__class__.__name__ + # get title + @property + def title(self): + return self.meta.get("title", self.module) # returns station entries from streams[] for .current category def stations(self): return self.streams.get(self.current, []) @@ -208,11 +210,11 @@ self.load(self.current) else: mygtk.columns(self.gtk_list, self.datamap, []) # add to main menu - mygtk.add_menu(parent.channelmenuitems, self.title, lambda w: parent.channel_switch(w, self.module) or 1) + mygtk.add_menu(parent.channelmenuitems, self.meta["title"], lambda w: parent.channel_switch(w, self.module) or 1) # make private copy of .datamap and modify field (title= only ATM) def update_datamap(self, search="name", title=None): if self.datamap == GenericChannel.datamap: @@ -575,12 +577,12 @@ icon = gtk.Image() icon.set_property("pixbuf", gtk.gdk.pixbuf_new_from_file(fn)) icon.set_property("icon-size", 1) icon.set_property("visible", True) label.pack_start(icon, expand=False, fill=True) - if self.title: - text = gtk.Label(self.title) + if self.meta["title"]: + text = gtk.Label(self.meta["title"]) text.set_property("visible", True) label.pack_start(text, expand=True, fill=True) # pack it into an event container to catch double-clicks ev_label = gtk.EventBox()