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]
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|