Index: channels/__init__.py ================================================================== --- channels/__init__.py +++ channels/__init__.py @@ -133,17 +133,19 @@ 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, - ] + if not self.prepare_filters: + self.prepare_filters += [ + self.prepare_filter_icons, + ] + if not self.postprocess_filters: + 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 @@ -304,11 +306,11 @@ # Postprocess new list of streams (e.g. assert existing title and url) if new_streams: try: new_streams = self.postprocess(new_streams) except Exception as e: - log.ERR(e, "Updating new streams, postprocessing failed:", row) + log.ERR("Updating new streams, postprocessing failed:", e) # don't lose forgotten streams if conf.retain_deleted: self.streams[category] = new_streams + self.deleted_streams(new_streams, self.streams.get(category,[])) else: @@ -363,10 +365,11 @@ prepare_filters = [] def prepare(self, streams): 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"): @@ -374,23 +377,25 @@ 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. + # Stream list preparations - invoked directly after reload(), + # callbacks can remove entries, or just update fields. postprocess_filters = [] def postprocess(self, streams): for f in self.postprocess_filters: - streams = filter(f, streams) + streams = [row for row in streams if f(row, self)] return streams + # Filter entries without title or url - def postprocess_filter_required_fields(self, row): + def postprocess_filter_required_fields(self, row, channel): 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): + def postprocess_filter_homepage(self, row, channel): 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) Index: channels/filter_bitrate.py ================================================================== --- channels/filter_bitrate.py +++ channels/filter_bitrate.py @@ -1,17 +1,17 @@ # encoding: UTF-8 # api: streamtuner2 # title: Filter Bitrate -# description: Cleans up low-quality entries from all station lists. -# version: 0.1 +# description: Cleans out low-quality entries from all station lists. +# version: 0.2 # type: filter # category: audio -# priority: optional # config: -# { name: min_bitrate_mp3, value: 32, type: select, select: "32|48|64|80|96|112|128|144|160", description: Filter MP3 streams with lesser audio quality. } -# [ name: min_bitrate_ogg, value: 32, type: select, select: "32|48|64|80|96|112|128|144|160", description: OggVorbis/AAC sound ok with slightly lower bitrates still. ] -# hooks: - +# { name: min_bitrate_mp3, value: 32, type: select, select: "32=32kbit/s|48=48kbit/s|64=64kbit/s|80=80kbit/s|96=96kbit/s|112=112kbit/s|128=128kbit/s|144=144kbit/s|160=160kbit/s", description: Filter MP3 streams with lesser audio quality. } +# { name: min_bitrate_ogg, value: 48, type: select, select: "32=32kbit/s|48=48kbit/s|64=64kbit/s|80=80kbit/s|96=96kbit/s|112=112kbit/s|128=128kbit/s|144=144kbit/s|160=160kbit/s", description: Minimum bitrate for Ogg Vorbis and AAC. } +# priority: optional +# hooks: postprocess_filters # # Plugin that filters radio stations on bitrate (audio quality). # Anything below 64 kbit/s often sounds awful for MP3 streams. # While AAC or Ogg Vorbis might still be acceptable sometimes. # @@ -20,28 +20,29 @@ # Beware that some channels provide more entries with low bitrates, # thus might appear completely empty. from config import * -import channels +from channels import GenericChannel # Filter streams by bitrate -class filter_bitrate(): +class filter_bitrate(object): meta = plugin_meta() module = "filter_bitrate" - # Hijack GenericChannel.prepare - def __init__(self, parent): - channels.GenericChannel.postprocess_filters.append(self.filter_rows) - - # filter bitrate - def filter_rows(self, row): - b = int(row.get("bitrate", 0)) - if b <= 10: - return True - elif b < int(conf.min_bitrate_mp3): - return False - else: - return True + # Hijack postprocessing filters in stream_update handler + def __init__(self, parent): + GenericChannel.postprocess_filters.append(self.filter_rows) + print GenericChannel.postprocess_filters + + # Filter row on bitrate + def filter_rows(self, row, channel): + bits = int(row.get("bitrate", 0)) + if bits <= 10: + return True + elif row.get("format", channel.audioformat) in ("audio/ogg", "audio/aac", "audio/aacp"): + return bits >= int(conf.min_bitrate_ogg) + else: + return bits >= int(conf.min_bitrate_mp3)