Check-in [a4cb6da4ac]
Overview
| Comment: | Add old Compound★ example plugin, slightly updated for current meta data scheme. | 
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive | 
| Timelines: | family | ancestors | descendants | both | trunk | 
| Files: | files | file ages | folders | 
| SHA1: | a4cb6da4ac10fa22844cf96488041120 | 
| User & Date: | mario on 2015-04-14 16:57:36 | 
| Other Links: | manifest | tags | 
Context
| 2015-04-14 | ||
| 17:03 | Not implemented: `8tracks` (plugin name suffers from identifier mismatch, and it's not quite doable in ST2, because 8tracks requires feedback shortly after playback has begun; yet streamtuner can't inspect any configured audio player for actually doing so.) check-in: 327d2ed94c user: mario tags: trunk | |
| 16:57 | Add old Compound★ example plugin, slightly updated for current meta data scheme. check-in: a4cb6da4ac user: mario tags: trunk | |
| 16:43 | Old helper script to make streamripper add genre. Though there are `-D` pattern options that often work better. And KStreamripper or fIcy/fPls might be more modern. check-in: 39e61e9915 user: mario tags: trunk | |
Changes
Added contrib/bieber.py version [42bda022a3].
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 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 | 
# api: streamtuner2
# title: Bieber
# description: Bieber music
# url: http://www.justinbiebermusic.com/
# version: 5.2
# type: channel
# category: example
# config: 
#     { "name": "bieber_filter", "type": "text", "value": "BIEBERBLAST", "description": "So and so." }
# priority: joke
#
# This was an entertaining test plugin for development. (Compound function
# went into the search feature, and the compound channel plugin obviously.)
#
# It's however a very simple plugin, and hence a good basis for writing
# your own extensions.
from channels import *
# Bieber music filter plugin
class bieber(ChannelPlugin):
    # config data
    config = [
    ]
    
    # category map
    categories = ['the Biebs']
    default = 'the Biebs'
    current = 'the Biebs'
    # static category list
    def update_categories(self):
        # nothing to do here
        pass
    # just runs over all channel plugins, and scans their streams{} for matching entries
    def update_streams(self, cat, force=0):
        # result list
        entries = []
        
        # kill our current list, so we won't find our own entries
        self.streams = {}
        
        # swamp through all plugins
        for name,p in self.parent.channels.iteritems():
            #print "bieberquest: channel", name
            # subcategories in plugins        
            for cat,stations in p.streams.iteritems():
                #print "   bq cat", cat
            
                # station entries
                for row in stations:
                    # collect text fields, do some typecasting, lowercasing
                    text = "|".join([str(e) for e in row.values()])
                    text = text.lower()
                    # compare
                    if text.find("bieb") >= 0:
                    
                        # add to result list
                        row["genre"] = name + ": " + row.get("genre", "")
                        entries.append(row)
        # return final rows list
        return entries
        
 | 
Added contrib/compound.py version [cde5ef1bb0].
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | 
# encoding: UTF-8
# api: streamtuner2
# title: Compound★
# description: combines station lists from multiple channels
# version: 0.1
# type: channel
# category: virtual
# url: http://fossil.include-once.org/streamtuner2/
# config: -
#    { name: compound_channels, type: text, value: "shoutcast, internet_radio, xiph, surfmusic", description: "Merge channels, or use all (*)" }
#    { name: compound_genres, type: text, value: "Top 40, x", description: "Extract categories, or just use intersection (x)" }
# priority: unsupported
# 
# Use this plugin to mix categories and their station entries from two
# or more different directory channels. It merges the lists, albeit in
# a rather crude way. (If anyone is interested, I could add a proper
# regex or something now.)
#
# Per default it lists only selected categories. But can be configured to
# merge just intersectioning categories/genres. Entry order is determined
# from station occourence count in channels AND their individual listener
# count (where available) using some guesswork to eliminate duplicates.
from channels import *
import action
import http
from config import conf
# merging channel
class compound (ChannelPlugin):
    # runtime options
    has_search = False
    listformat = "href"  # row entries will contain exact `listformat` classification
    audioformat = "audio/*"   # same as for correct encoding mime type
    
    # references
    parent = None
    
    # data
    streams = {}
    categories = []
    
    
    
    # which categories
    def update_categories(self):
        # as-is category list
        cats = self.split(conf.compound_genres)
        self.categories = [c for c in cats if c != "x"]
        
        # if intersection
        if "x" in cats:
            once = []
            for chan in self.channels():
                for add in self.flatten(self.parent.channels[chan].categories):
                    # second occourence in two channels
                    if add.lower() in once:
                        if add not in self.categories:
                            self.categories.append(add)
                    else: #if add not in self.categories:
                        once.append(add.lower())
        pass
                        
        
    # flatten our two-level categories list
    def flatten(self, a):
        return [i for sub in a for i in (sub if type(sub)==list else [sub])]
    # break up name lists        
    def split(self, s):
        return [s.strip() for s in s.split(",")]
    # get list of channels
    def channels(self):
        # get list
        ls = self.split(conf.compound_channels)
      
        # resolve "*"
        if "*" in ls:
            ls = self.parent.channel_names  # includes bookmarks
            if self.module in ls:
                ls.remove(self.module)	    # but not compound
        return ls
          
          
    # combine stream lists
    def update_streams(self, cat):
        r = []
        have = []
    
        # look through channels
        if cat in self.categories:
            for cn in self.channels():
            
                # get channel, refresh list
                c = self.parent.channels[cn]
                
                # 
                for row in self.get_streams(c, cat):
                    # copy
                    row = dict(row)
                    
                    #row["listeners"] = 1000 + row.get("listeners", 0) / 10
                    row["extra"] = cn  # or genre?
                    row["listformat"] = c.listformat
                    # duplicates                    
                    if row["title"].lower() in have or row["url"] in have:
                        for i,cmp in enumerate(r):
                            if cmp["title"].lower()==row["title"].lower() or cmp["url"].find(row["url"])>=0:
                                r[i]["listeners"] = row.get("listeners",0) + 5000
                        pass
                    else:
                        r.append(row)
                        have.append(row["title"].lower())  # we're comparing lowercase titles
                        have.append(row["url"][:row["url"].find("http://")])  # save last http:// part (internet-radio redirects to shoutcast urls)
                        
        # sort by listeners
        r = sorted(r, key=lambda x: -x.get("listeners", 0))
        return r
    # extract station list from other channel plugin    
    def get_streams(self, c, cat):
        # if empty?
        #c.load(cat)
        return c.streams.get(cat) \
            or c.update_streams(cat.replace(" ","")) \
            or []
    
 |