Index: channels/__init__.py ================================================================== --- channels/__init__.py +++ channels/__init__.py @@ -132,10 +132,19 @@ # add default options values to config.conf.* dict conf.add_plugin_defaults(self.meta, self.module) # Only if streamtuner2 is run in graphical mode if (parent): + # Update/display stream processors + self.prepare_filters += [ + self.prepare_filter_icons, + ] + self.postprocess_filters += [ + self.postprocess_filter_required_fields, + self.postprocess_filter_homepage, + ] + # Load cache, instantiate Gtk widgets self.cache() self.gui(parent) # Stub for ST2 main window / dispatcher else: @@ -164,11 +173,11 @@ # add to main menu uikit.add_menu([parent.channelmenuitems], self.meta["title"], lambda w: parent.channel_switch_by_name(self.module) or 1) # Just wraps uikit.columns() to retain liststore, rowmap and pix_entry def columns(self, entries=None): - self.ls, self.rowmap, self.pix_entry = uikit.columns(self.gtk_list, self.datamap, entries) + self.ls, self.rowmap, self.pix_entry = uikit.columns(self.gtk_list, self.datamap, entries, show_favicons=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) @@ -290,22 +299,16 @@ if category == "empty": new_streams = self.empty_stub else: new_streams = self.update_streams(category) + # Postprocess new list of streams (e.g. assert existing title and url) if new_streams: - # check and modify entry; - # assert that title and url are present - modified = [] - for row in new_streams: - if len(set(["", None]) & set([row.get("title"), row.get("url")])): - continue - try: - modified.append( self.postprocess(row) ) - except Exception as e: - log.DATA(e, "Missing title or url. Postprocessing failed:", row) - new_streams = modified + try: + new_streams = self.postprocess(new_streams) + except Exception as e: + log.ERR(e, "Updating new streams, postprocessing failed:", row) # don't lose forgotten streams if conf.retain_deleted: self.streams[category] = new_streams + self.deleted_streams(new_streams, self.streams.get(category,[])) else: @@ -354,54 +357,48 @@ row["deleted"] = 1 diff.append(row) return diff - # prepare data for display - # - # - favourite icon - # - or deleted icon - # + # Prepare stream list for display + prepare_filters = [] def prepare(self, streams): - for i,row in enumerate(streams): - # state icon: bookmark star - if (conf.show_bookmarks and "bookmarks" in self.parent.channels and self.parent.bookmarks.is_in(streams[i].get("url", "file:///tmp/none"))): - streams[i]["favourite"] = 1 - - # state icon: INFO or DELETE - if (not row.get("state")): - if row.get("favourite"): - streams[i]["state"] = gtk.STOCK_ABOUT - if conf.retain_deleted and row.get("deleted"): - streams[i]["state"] = gtk.STOCK_DELETE - - # Favicons? construct local cache filename, basically reimplements favicon.row_to_fn() - if conf.show_favicons and "favicon" in self.parent.features: - url = row.get("img") or row.get("homepage") - if url: - # Normalize by stripping proto:// and non-alphanumeric chars - url = re.sub("[^\w._-]", "_", re.sub("^\w+://|/$", "", url.lower())) - streams[i]["favicon"] = "{}/icons/{}.png".format(conf.dir, url) - + for f in self.prepare_filters: + map(f, streams) + return streams + # state icon: bookmark star, or deleted mark + def prepare_filter_icons(self, row): + if conf.show_bookmarks:# and "bookmarks" in self.parent.channels: + row["favourite"] = self.parent.bookmarks.is_in(row.get("url", "file:///tmp/none")) + if not row.get("state"): + if row.get("favourite"): + row["state"] = gtk.STOCK_ABOUT + if row.get("deleted"): + row["state"] = gtk.STOCK_DELETE + + + # Stream list prepareations directly after reload, + # can remove entries, or just update fields. + postprocess_filters = [] + def postprocess(self, streams): + for f in self.postprocess_filters: + streams = filter(f, streams) return streams - - - # data preparations directly after reload - # - # - drop shoutcast homepage links - # - or find homepage name in title - # - def postprocess(self, row): - # deduce homepage URLs from title - # by looking for www.xyz.com domain names + # Filter entries without title or url + def postprocess_filter_required_fields(self, row): + return not len(set(["", None]) & set([row.get("title"), row.get("url")])) + # Deduce homepage URLs from title + # by looking for www.xyz.com domain names + def postprocess_filter_homepage(self, row): if not row.get("homepage"): url = self.rx_www_url.search(row.get("title", "")) if url: url = url.group(0).lower().replace(" ", "") url = (url if url.find("www.") == 0 else "www."+url) row["homepage"] = ahttp.fix_url(url) - return row + print row + return True # reload current stream from web directory def reload(self): Index: uikit.py ================================================================== --- uikit.py +++ uikit.py @@ -84,11 +84,11 @@ # entries = [ {"titlerow":"first", "interndat":123}, {"titlerow":"..."}, ] # Keys not mentioned in the datamap get ignored, and defaults are applied # for missing cols. All values must already be in the correct type however. # @staticmethod - def columns(widget, datamap=[], entries=None, pix_entry=False): + def columns(widget, datamap=[], entries=None, show_favicons=True, pix_entry=False): # create treeviewcolumns? if (not widget.get_column(0)): # loop through titles datapos = 0 @@ -184,11 +184,11 @@ # autotransform string -> gtk image object if (pix_entry and type(row[pix_entry]) == str): pix = None try: - if os.path.exists(row[pix_entry]): + if show_favicons and os.path.exists(row[pix_entry]): pix = gtk.gdk.pixbuf_new_from_file(row[pix_entry]) except Exception as e: log.ERR("uikik.columns: Pixbuf fail,", e) row[pix_entry] = pix or defaults[gtk.gdk.Pixbuf]