Check-in [ea924e3c27]
Overview
Comment: | Introduce FeaturePlugin as new base class for channels and all other plugins. Pre-defines the meta, module attributes and calls init2(). |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ea924e3c27911b844b8b6159392ce90b |
User & Date: | mario on 2017-01-05 21:23:23 |
Other Links: | manifest | tags |
Context
2017-01-05
| ||
21:33 | Fix `links` plugin format: attribute; make it understood by channel.play() that a homepage-only row triggers the web browser. check-in: f48ad79aa1 user: mario tags: trunk | |
21:23 | Introduce FeaturePlugin as new base class for channels and all other plugins. Pre-defines the meta, module attributes and calls init2(). check-in: ea924e3c27 user: mario tags: trunk | |
21:22 | Detect more absent variables/login, introduce UI delay on submission. check-in: 9eeccf1f29 user: mario tags: trunk | |
Changes
Modified channels/__init__.py from [c58402c723] to [4a4e01489e].
1 2 3 4 5 6 | # encoding: UTF-8 # api: streamtuner2 # type: class # category: ui # title: Channel plugins # description: Base implementation for channels and feature plugins | | | 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.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 | import re import copy import inspect # Only export plugin classes and a few utility functions __all__ = [ | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 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__ = [ "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(FeaturePlugin): # control attributes meta = { "config": [] } base_url = "" listformat = "pls" audioformat = "audio/mpeg" # fallback value has_search = False |
︙ | ︙ | |||
67 68 69 70 71 72 73 | 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 | < | 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 # 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 | # constructor def __init__(self, parent=None): #self.streams = {} self.gtk_list = None self.gtk_cat = None | < < < < | < < | < < | < < | 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 # base init (meta infos, parent reference, init2) FeaturePlugin.__init__(self, parent) # 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 | 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` | < < < < < < < < | 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` #--------------------- 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 | listformat = row.get("listformat", self.listformat) action.record(row, audioformat, listformat) return row | < < < < < < < < < | 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 | # 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): | > > | 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): |
︙ | ︙ |
Modified channels/jamendo.py from [0db1a39017] to [d440527930].
︙ | ︙ | |||
320 321 322 323 324 325 326 | #"url": "http://api.jamendo.com/get2/stream/track/xspf/?album_id=%s&streamencoding=ogg2&n=all&from=app-%s" % (e["id"], self.cid), #"format": "audio/ogg", #"listformat": "xspf", "url": "http://api.jamendo.com/v3.0/tracks?client_id={}&audioformat={}&album_id={}".format(self.cid, fmt, e["id"]), "listformat": "jamj", "format": fmt_mime, }) | | | 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | #"url": "http://api.jamendo.com/get2/stream/track/xspf/?album_id=%s&streamencoding=ogg2&n=all&from=app-%s" % (e["id"], self.cid), #"format": "audio/ogg", #"listformat": "xspf", "url": "http://api.jamendo.com/v3.0/tracks?client_id={}&audioformat={}&album_id={}".format(self.cid, fmt, e["id"]), "listformat": "jamj", "format": fmt_mime, }) # Feeds (News) elif cat == "feeds": for e in self.api(method="feeds", order="date_start_desc", target="notlogged"): if e.get("joinid") and e.get("subtitle"): entries.append({ "genre": e["type"], "title": e["title"]["en"], |
︙ | ︙ |