Check-in [8b3cd06ff7]
Overview
| Comment: | Adapted Live365 channel plugin for /cgi-bin/play.pls?stationid=123457&direct=1 stream URLs instead of extraction, works again |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
8b3cd06ff708ba014f3e677c8f2973da |
| User & Date: | mario on 2014-07-31 17:22:46 |
| Other Links: | manifest | tags |
Context
|
2014-08-01
| ||
| 01:34 | catmap{} cache handling now by _generic module check-in: cda3504633 user: mario tags: trunk | |
|
2014-07-31
| ||
| 17:22 | Adapted Live365 channel plugin for /cgi-bin/play.pls?stationid=123457&direct=1 stream URLs instead of extraction, works again check-in: 8b3cd06ff7 user: mario tags: trunk | |
| 03:23 | Fixed invalid encoding in (manually edited) releases.json check-in: e5effdd595 user: mario tags: trunk | |
Changes
Modified _package.epm from [81c1d8ed48] to [84031fd279].
1 | %product streamtuner2 - internet radio browser | | | 1 2 3 4 5 6 7 8 9 | %product streamtuner2 - internet radio browser %version 2.1.2 %vendor Mario Salzer %license %copyright Placed into the Public Domain, 2009-2014 %readme README %description Browser for Internet Radio Stations %description . |
| ︙ | ︙ | |||
29 30 31 32 33 34 35 | f 755 root root /usr/bin/streamtuner2 ./st2.py f 644 root root /usr/share/applications/streamtuner2.desktop ./streamtuner2.desktop d 755 root root /usr/share/streamtuner2 - f 644 root root /usr/share/streamtuner2/streamtuner2.png ./streamtuner2.png f 644 root root /usr/share/pixmaps/streamtuner2.png ./logo.png f 644 root root /usr/share/streamtuner2/gtk2.xml ./gtk2.xml f 644 root root /usr/share/streamtuner2/gtk3.xml ./gtk3.xml | | > > > > | 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 | f 755 root root /usr/bin/streamtuner2 ./st2.py f 644 root root /usr/share/applications/streamtuner2.desktop ./streamtuner2.desktop d 755 root root /usr/share/streamtuner2 - f 644 root root /usr/share/streamtuner2/streamtuner2.png ./streamtuner2.png f 644 root root /usr/share/pixmaps/streamtuner2.png ./logo.png f 644 root root /usr/share/streamtuner2/gtk2.xml ./gtk2.xml f 644 root root /usr/share/streamtuner2/gtk3.xml ./gtk3.xml #f 644 root root /usr/share/streamtuner2/pson.py ./pson.py #f 644 root root /usr/share/streamtuner2/processing.py ./processing.py f 644 root root /usr/share/streamtuner2/compat2and3.py ./compat2and3.py f 644 root root /usr/share/streamtuner2/action.py ./action.py f 644 root root /usr/share/streamtuner2/config.py ./config.py f 644 root root /usr/share/streamtuner2/ahttp.py ./ahttp.py f 644 root root /usr/share/streamtuner2/cli.py ./cli.py f 644 root root /usr/share/streamtuner2/mygtk.py ./mygtk.py f 644 root root /usr/share/streamtuner2/favicon.py ./favicon.py f 644 root root /usr/share/streamtuner2/pq.py ./pq.py #-- channels d 755 root root /usr/share/streamtuner2/channels - f 644 root root /usr/share/streamtuner2/channels/__init__.py ./channels/__init__.py f 644 root root /usr/share/streamtuner2/channels/_generic.py ./channels/_generic.py f 644 root root /usr/share/streamtuner2/channels/icast.py ./channels/icast.py f 644 root root /usr/share/streamtuner2/channels/icast.png ./channels/icast.png f 644 root root /usr/share/streamtuner2/channels/internet_radio.py ./channels/internet_radio.py f 644 root root /usr/share/streamtuner2/channels/internet_radio.png ./channels/internet_radio.png f 644 root root /usr/share/streamtuner2/channels/itunes.py ./channels/itunes.py f 644 root root /usr/share/streamtuner2/channels/itunes.png ./channels/itunes.png f 644 root root /usr/share/streamtuner2/channels/jamendo.py ./channels/jamendo.py f 644 root root /usr/share/streamtuner2/channels/jamendo.png ./channels/jamendo.png f 644 root root /usr/share/streamtuner2/channels/live365.py ./channels/live365.py f 644 root root /usr/share/streamtuner2/channels/live365.png ./channels/live365.png f 644 root root /usr/share/streamtuner2/channels/modarchive.py ./channels/modarchive.py f 644 root root /usr/share/streamtuner2/channels/modarchive.png ./channels/modarchive.png f 644 root root /usr/share/streamtuner2/channels/musicgoal.py ./channels/musicgoal.py |
| ︙ | ︙ | |||
71 72 73 74 75 76 77 | f 644 root root /usr/share/streamtuner2/channels/youtube.png ./channels/youtube.png f 644 root root /usr/share/streamtuner2/channels/global_key.py ./channels/global_key.py f 644 root root /usr/share/streamtuner2/channels/links.py ./channels/links.py f 644 root root /usr/share/streamtuner2/channels/timer.py ./channels/timer.py #-- scripts #d 755 root root /usr/share/streamtuner2/scripts - #f 644 root root /usr/share/streamtuner2/scripts/radiotop40_de.py ./scripts/radiotop40_de.py | < < | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | f 644 root root /usr/share/streamtuner2/channels/youtube.png ./channels/youtube.png f 644 root root /usr/share/streamtuner2/channels/global_key.py ./channels/global_key.py f 644 root root /usr/share/streamtuner2/channels/links.py ./channels/links.py f 644 root root /usr/share/streamtuner2/channels/timer.py ./channels/timer.py #-- scripts #d 755 root root /usr/share/streamtuner2/scripts - #f 644 root root /usr/share/streamtuner2/scripts/radiotop40_de.py ./scripts/radiotop40_de.py #-- help files f 644 root root /usr/share/man/man1/streamtuner2.1 ./help/streamtuner2.1 d 755 root root /usr/share/doc/streamtuner2/help - f 644 root root /usr/share/doc/streamtuner2/help/action_homepage.page ./help/action_homepage.page f 644 root root /usr/share/doc/streamtuner2/help/action_playing.page ./help/action_playing.page f 644 root root /usr/share/doc/streamtuner2/help/action_recording.page ./help/action_recording.page f 644 root root /usr/share/doc/streamtuner2/help/action_saving.page ./help/action_saving.page |
| ︙ | ︙ |
Modified ahttp.py from [31cf3bd93f] to [0fe1c60aea].
| ︙ | ︙ | |||
52 53 54 55 56 57 58 | #-- Retrieve data via HTTP # # Well, it says "get", but it actually does POST and AJAXish GET requests too. # | | | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
#-- Retrieve data via HTTP
#
# Well, it says "get", but it actually does POST and AJAXish GET requests too.
#
def get(url, params={}, referer="", post=0, ajax=0, binary=0, feedback=None, content=True):
__print__( dbg.HTTP, "GET", url, params )
# statusbar info
progress_feedback(url)
# combine headers
headers = {}
|
| ︙ | ︙ | |||
74 75 76 77 78 79 80 |
r = session.post(url, params=params, headers=headers)
else:
r = session.get(url, params=params, headers=headers)
__print__( dbg.HTTP, r.request.headers );
__print__( dbg.HTTP, r.headers );
| | | | < | | > | > > > > | 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 |
r = session.post(url, params=params, headers=headers)
else:
r = session.get(url, params=params, headers=headers)
__print__( dbg.HTTP, r.request.headers );
__print__( dbg.HTTP, r.headers );
# finish, clean statusbar
#progress_feedback(0.9)
progress_feedback("")
# result
__print__( dbg.INFO, "Content-Length", len(r.content) )
if not content:
return r
elif binary:
return r.content
else:
return r.text
#-- Append missing trailing slash to URLs
def fix_url(url):
if url is None:
|
| ︙ | ︙ |
Modified channels/file.py from [a8e2e93dda] to [f92686b376].
1 2 3 4 5 6 7 8 | # # api: streamtuner2 # title: File browser # description: Displays mp3/oggs or m3u/pls files from local media file directories. # type: channel # category: media # version: 0.0 # priority: optional | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # # api: streamtuner2 # title: File browser # description: Displays mp3/oggs or m3u/pls files from local media file directories. # type: channel # category: media # version: 0.0 # priority: optional # depends: mutagen # # # Local file browser. # # |
| ︙ | ︙ | |||
176 177 178 179 180 181 182 183 184 185 |
def update_categories(self):
self.scan_dirs()
# same as init
def update_streams(self, cat, x=0):
self.scan_dirs()
return self.streams.get(os.path.basename(cat))
| > > | 176 177 178 179 180 181 182 183 184 185 186 187 |
def update_categories(self):
self.scan_dirs()
# same as init
def update_streams(self, cat, x=0):
self.scan_dirs()
print(self.streams)
print(self.categories)
return self.streams.get(os.path.basename(cat))
|
Modified channels/live365.py from [861e1f12f9] to [be1047f842].
1 2 3 4 5 6 7 8 9 | # api: streamtunter2 # title: Live365 # description: Around 5000 categorized internet radio streams, some paid ad-free ones. # type: channel # category: radio # version: 0.3 # priority: optional # | < < | < > > > | | < < > | < | > | 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 |
# api: streamtunter2
# title: Live365
# description: Around 5000 categorized internet radio streams, some paid ad-free ones.
# type: channel
# category: radio
# version: 0.3
# priority: optional
#
#
#
# We're currently extracting from the JavaScript;
#
# stn.set("param", "value");
#
# And using a HTML5 player direct URL now:
#
# /cgi-bin/play.pls?stationid=%s&direct=1&file=%s.pls
#
#
#
# streamtuner2 modules
from config import conf
from mygtk import mygtk
import ahttp as http
from channels import *
from config import __print__, dbg
import action
# python modules
import re
import xml.dom.minidom
from xml.sax.saxutils import unescape as entity_decode, escape as xmlentities
import gtk
import copy
import urllib
from itertools import groupby
from time import time
from xml.dom.minidom import parseString
# channel live365
class live365(ChannelPlugin):
# desc
module = "live365"
title = "Live365"
|
| ︙ | ︙ | |||
79 80 81 82 83 84 85 |
# fixed for now
def update_categories(self):
pass
# extract stream infos
def update_streams(self, cat):
| | > > > | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > > > | | > > | > > > > > > | > > > > > > > > | > > > > | 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 149 150 151 152 153 154 155 |
# fixed for now
def update_categories(self):
pass
# extract stream infos
def update_streams(self, cat):
# Retrieve genere index pages
html = ""
for i in [1, 17, 33, 49]:
url = "http://www.live365.com/cgi-bin/directory.cgi?first=%i&site=web&mode=3&genre=%s&charset=UTF-8&target=content" % (i, cat.lower())
html += http.get(url, feedback=self.parent.status)
# Extract from JavaScript
rx = re.compile(r"""
stn.set\( " (\w+) ", \s+ " ((?:[^"\\]+|\\.)*) "\); \s+
""", re.X|re.I|re.S|re.M)
# Group entries before adding them
ls = []
for i,row in groupby(rx.findall(html), self.group_by_station):
row = dict(row)
ls.append({
"name": row["stationName"],
"title": row["title"],
"playing": "n/a",
"id": row["id"],
"access": row["listenerAccess"],
"status": row["status"],
"mode": row["serverMode"],
"rating": int(row["rating"]),
#"rating": row["ratingCount"],
"listeners": int(row["tlh"]),
"location": row["location"],
"favicon": row["imgUrl"],
"format": self.mediatype,
"url": "%scgi-bin/play.pls?stationid=%s&direct=1&file=%s.pls" % (self.base_url, row["id"], row["stationName"])
})
return ls
# itertools.groupby filter
gi = 0
def group_by_station(self, kv):
if kv[0] == "stationName":
self.gi += 1
return self.gi
# inject session id etc. into direct audio url
def UNUSED_play(self, row):
if row.get("url"):
# params
id = row["id"]
name = row["name"]
# get mini.cgi station resource
mini_url = "http://www.live365.com/cgi-bin/mini.cgi?version=3&templateid=xml&from=web&site=web" \
+ "&caller=&tag=web&station_name=%s&_=%i111" % (name, time())
mini_r = http.get(mini_url, content=False)
mini_xml = parseString(mini_r.text).getElementsByTagName("LIVE365_PLAYER_WINDOW")[0]
mini = lambda name: mini_xml.getElementsByTagName(name)[0].childNodes[0].data
# authorize with play.cgi
play_url = ""
# mk audio url
play = "http://%s/play" % mini("STREAM_URL") \
+ "?now=0&" \
+ mini("NANOCASTER_PARAMS") \
+ "&token=" + mini("TOKEN") \
+ "&AuthType=NORMAL&lid=276006-deu&SaneID=178.24.130.71-1406763621701"
# let's see what happens
action.action.play(play, self.mediatype, self.listformat)
|
Modified st2.py from [a922a58f51] to [3d89c6ea6f].
1 2 3 4 5 6 7 | #!/usr/bin/env python # encoding: UTF-8 # api: python # type: application # title: streamtuner2 # description: Directory browser for internet radio / audio streams # depends: pygtk | pygi, threading, pyquery, kronos, requests | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/env python # encoding: UTF-8 # api: python # type: application # title: streamtuner2 # description: Directory browser for internet radio / audio streams # depends: pygtk | pygi, threading, pyquery, kronos, requests # version: 2.1.2 # author: mario salzer # license: public domain # url: http://freshmeat.net/projects/streamtuner2 # config: <env name="http_proxy" value="" description="proxy for HTTP access" /> <env name="XDG_CONFIG_HOME" description="relocates user .config subdirectory" /> # category: multimedia # # |
| ︙ | ︙ | |||
92 93 94 95 96 97 98 | import ahttp import action # needs workaround... (action.main=main) import channels from channels import * import favicon | | | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | import ahttp import action # needs workaround... (action.main=main) import channels from channels import * import favicon __version__ = "2.1.2" # this represents the main window # and also contains most application behaviour main = None class StreamTunerTwo(gtk.Builder): |
| ︙ | ︙ |