Internet radio browser GUI for music/video streams from various directory services.

⌈⌋ ⎇ branch:  streamtuner2


Check-in [c8dcfb540d]

Overview
Comment:no more TV listings on Shoutcast
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | py3
Files: files | file ages | folders
SHA1: c8dcfb540d884bc852d6b9dcd34380183f7d5dc3
User & Date: mario on 2014-04-11 02:27:30
Other Links: branch diff | manifest | tags
Context
2014-04-11
02:28
basic.ch is no more check-in: 00f1bd3fd7 user: mario tags: py3
02:27
no more TV listings on Shoutcast check-in: c8dcfb540d user: mario tags: py3
01:24
remove pson fallback check-in: eabee8e3c9 user: mario tags: py3
Changes

Deleted channels/tv.py version [2d1fa5a0ac].

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
#
# api: streamtuner2
# title: shoutcast TV
# description: TV listings from shoutcast
# version: 0.0
# stolen-from: Tunapie.sf.net
#
# As seen in Tunapie, there are still TV listings on Shoutcast. This module
# adds a separate tab for them. Streamtuner2 is centrally and foremost about
# radio listings, so this plugin will remain one of the few exceptions.
#
#   http://www.shoutcast.com/sbin/newtvlister.phtml?alltv=1
#
# Pasing with lxml is dead simple in this case, so we use etree directly
# instead of PyQuery. Like with the Xiph plugin, downloaded streams are simply
# stored in .streams["all"] pseudo-category.
#
# icon: http://cemagraphics.deviantart.com/art/Little-Tv-Icon-96461135

from channels import *
import ahttp as http
import lxml.etree




# TV listings from shoutcast.com
class tv(ChannelPlugin):

	# desc
	api = "streamtuner2"
	module = "tv"
	title = "TV"
	version = 0.1
	homepage = "http://www.shoutcast.com/" 
	base_url = "http://www.shoutcast.com/sbin/newtvlister.phtml?alltv=1"
	play_url = "http://yp.shoutcast.com/sbin/tunein-station.pls?id="
	listformat = "audio/x-scpls"  # video streams are NSV linked in PLS format

        # settings
        config = [
        ]
        
        # categories
        categories = ["all", "video"]
        current = ""
        default = "all"
        empty = ""

        # redefine
        streams = {}


        # get complete list
        def all(self):
            r = []

            # retrieve
            xml = http.get(self.base_url)
            
            # split up <station> entries
            for station in lxml.etree.fromstring(xml):

                r.append({
                    "title": station.get("name"),
                    "playing": station.get("ct"),
                    "id": station.get("id"),
                    "url": self.play_url + station.get("id"),
                    "format": "video/nsv",
                    "time": station.get("rt"),
                    "extra": station.get("load"),
                    "genre": station.get("genre"),
                    "bitrate": int(station.get("br")),
                    "listeners": int(station.get("lc")),
                })
                              
            return r
         
            
        # genre switch
        def load(self, cat, force=False):
            if force or not self.streams.get("all"):
                self.streams["all"] = self.all()
            ChannelPlugin.load(self, cat, force)
        
            
        # update from the list
        def update_categories(self):

            # update it always here:  #if not self.streams.get("all"):
            self.streams["all"] = self.all()

            # enumerate categories
            c = {"all":100000}
            for row in self.streams["all"]:
                for genre in row["genre"].split(" "):
                    if len(genre)>2 and row["bitrate"]>=200:
                        c[genre] = c.get(genre, 0) + 1
            # append
            self.categories = sorted(c, key=c.get, reverse=True)



        # extract from big list
        def update_streams(self, cat, search=""):

            # autoload only if "all" category is missing
            if not self.streams.get("all"):
                self.streams["all"] = self.all()
    
            # return complete list as-is            
            if cat == "all":
                return self.streams[cat]
                
            # search for category
            else:
                return [row for row in self.streams["all"] if row["genre"].find(cat)>=0]






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<