"""
A plugin to get radio links from listenlive.eu
"""
import sys, os, os.path, xbmcaddon
import xbmc, xbmcgui, xbmcplugin
import urllib, re, time
from HTMLParser import HTMLParser
from shutil import rmtree, copy
import traceback
from pprint import pprint
__plugin__ = "ListenLiveEU"
__version__ = '0.4.6'
__author__ = 'bootsy, xycl'
__date__ = '2013-01-16'
BASE_URL = 'http://www.listenlive.eu'
URL_INDEX = '/'.join( [BASE_URL, 'index.html'] )
URL_NEW = '/'.join( [BASE_URL, 'new.html'] )
addon = xbmcaddon.Addon(id='plugin.audio.listenliveeu')
DIR_HOME = addon.getAddonInfo('path').decode('utf-8')
DIR_HOME = xbmc.translatePath(DIR_HOME).decode('utf-8')
FILE_INDEX_PAGE = os.path.join(DIR_HOME, 'index.html')
DIR_SETTINGS = addon.getAddonInfo('profile').decode('utf-8')
DIR_SETTINGS = xbmc.translatePath(DIR_SETTINGS).decode('utf-8')
FILE_FAVS = os.path.join(DIR_SETTINGS, 'favorites.xml')
dialogProgress = xbmcgui.DialogProgress()
dialog = xbmcgui.Dialog()
def log(msg):
if type(msg) not in (str, unicode):
xbmc.log("[%s]: %s" % (__plugin__, type(msg)))
pprint (msg)
else:
if type(msg) in (unicode,):
msg = msg.encode('utf-8')
xbmc.log("[%s]: %s" % (__plugin__, msg))
def errorOK(title="", msg=""):
e = str( sys.exc_info()[ 1 ] )
log(e)
if not title:
title = __plugin__ + ' v' + __version__
if not msg:
msg = "ERROR!"
dialog.ok( title, msg, e )
#######################################################################################################################
# write favs file
#######################################################################################################################
def writeFavs():
f = open(xbmc.translatePath(FILE_FAVS),"w")
f.write('This is your favorites file.' + '\n')
f.close()
#######################################################################################################################
# add favorite
#######################################################################################################################
def addFav(url):
log("> addFav()")
if url:
try:
favoritesRE=re.compile('(?i)name=(.+?)&url=(.+?)\n')
favorites = favoritesRE.findall(url)
for favorite in favorites:
name = favorite[0]
url = favorite[1]
nameurl = 'name=%s&url=%s%s' % (name, url, '\n')
doc = open(FILE_FAVS, "r+")
text = doc.read().decode('utf-8')
doc.close()
if nameurl in text:
dialog.ok( __plugin__ + ' v' + __version__, __language__(30015), '', urllib.unquote_plus(name).decode('utf-8') )
else:
doc = open(FILE_FAVS, "a+")
doc.write(nameurl)
doc.close()
dialog.ok( __plugin__ + ' v' + __version__, __language__(30007), '', urllib.unquote_plus(name).decode('utf-8') )
except:
dialog.ok( __plugin__ + ' v' + __version__, __language__(30008), '', urllib.unquote_plus(name).decode('utf-8') )
return True
#######################################################################################################################
# remove favorite
#######################################################################################################################
def remFav(url):
log("> remFav()")
if url:
try:
favoritesRE=re.compile('(?i)name=(.+?)&url=(.+?)\n')
favorites = favoritesRE.findall(url)
for favorite in favorites:
name = favorite[0]
url = favorite[1]
nameurl = 'name=%s&url=%s%s' % (name, url, '\n')
if dialog.yesno( __plugin__ + ' v' + __version__, __language__(30009), '', urllib.unquote_plus(name).decode('utf-8') ):
doc = open(FILE_FAVS, "rU")
text = doc.read().decode('utf-8')
doc.close()
doc = open(FILE_FAVS, "w")
doc.write(text.replace(nameurl, ''))
doc.close()
xbmc.executebuiltin('Container.Refresh')
dialog.ok( __plugin__ + ' v' + __version__, __language__(30010), '', urllib.unquote_plus(name).decode('utf-8') )
doc = open(FILE_FAVS).read().decode('utf-8')
if doc == 'This is your favorites file.\n':
dialog.ok( __plugin__ + ' v' + __version__, __language__(30016) )
except:
dialog.ok( __plugin__ + ' v' + __version__, __language__(30011), '', urllib.unquote_plus(name).decode('utf-8') )
return True
#######################################################################################################################
# remove all favs
######################################################################################################
def remallFavs(url):
log("> remallFavs()")
if dialog.yesno(__plugin__ + ' v' + __version__, __language__(30012) ):
try:
doc = open(FILE_FAVS).read().decode('utf-8')
if doc == 'This is your favorites file.\n':
dialog.ok( __plugin__ + ' v' + __version__, __language__(30017) )
else:
deleteFile(FILE_FAVS)
dialog.ok( __plugin__ + ' v' + __version__, __language__(30013) )
xbmc.executebuiltin('Container.Refresh')
writeFavs()
except:
dialog.ok( __plugin__ + ' v' + __version__, __language__(30014) )
return True
#######################################################################################################################
# get favorite
######################################################################################################
def getFavorites(url):
log("> getFavorites()")
doc = open(url).read()
if doc:
try:
favoritesRE=re.compile('(?i)name=(.+?)&url=(.+?)\n')
favorites = favoritesRE.findall(doc)
for favorite in favorites:
name = favorite[0]
url = favorite[1]
infolabels = {}
addDirectoryItem(urllib.unquote_plus(name).decode('utf-8'), urllib.unquote_plus(url), 3, infoLabels=infolabels, isFolder=False)
xbmcplugin.addSortMethod( handle=int( sys.argv[ 1 ] ), sortMethod=xbmcplugin.SORT_METHOD_LABEL )
except:
errorOK("getFavorites()")
log("< getFavorites()")
return True
#######################################################################################################################
# get initial root category
#######################################################################################################################
def getRootCats():
log("> getRootCats()")
doc = open(FILE_FAVS).read().decode('utf-8')
if doc == 'This is your favorites file.\n':
items = ( (__language__(30000), "new"), (__language__(30001),"country"), (__language__(30002),"genre"), )
else:
items = ( (__language__(30000), "new"), (__language__(30003),"favorites"), (__language__(30001),"country"), (__language__(30002),"genre"), )
for title, url in items:
addDirectoryItem(title, url, 0)
xbmcplugin.addSortMethod( handle=int( sys.argv[ 1 ] ), sortMethod=xbmcplugin.SORT_METHOD_LABEL )
log("< getRootCats()")
return True
#######################################################################################################################
# Get category of by country or by genre
#######################################################################################################################
def getCats(byCountry):
log("> getCats() byCountry=%s" % byCountry)
ok = False
doc = getURL(URL_INDEX, FILE_INDEX_PAGE)
if doc:
log("getCats() parsing ...")
try:
# get section
baseRE = '
Browse by $SECTION.*?(.+?)
'
if byCountry:
sectionRE = baseRE.replace('$SECTION','country')
else:
sectionRE = baseRE.replace('$SECTION','genre')
#section = re.search(sectionRE, doc, re.IGNORECASE + re.MULTILINE + re.DOTALL).group(1)
section = re.search('(?ims)' + sectionRE, doc).group(1)
# parse info from section
p=re.compile('(.+?) getStreams()")
ok = False
#doc = open('/'.join( [DIR_HOME, 'top40.html'] ) ).read()
doc = getURL(url)
if doc:
try:
log("parsing doc ...")
doc=doc.replace('
','')
# get all table rows, one staion per row - with possible multiple streams
stationsRE=re.compile('(?ims)(
.*?
)')
# url, name, loc, stream(s), genre
#stationRE=re.compile('(?ims)(.*?).*? | (.*?) | .*?alt=".*?".*?().*?(?: | (.*?) | |)')
stationRE=re.compile('(?ims)(.*?).*?(.*?) | .*?alt=".*?".*?().*?(?: | (.*?) | |)')
#streamsRE=re.compile('(?i)href="(.*?)">(.*?)<')
streamsRE=re.compile('(?i)href="([^"]+)">(\d+ +[^"]+|\d+[.]\d+ +[^"]+)')
# get all stations
stations = stationsRE.findall(doc)
#pprint (stations)
genreExists = False
for station in stations:
#print station
# get station details
stationInfo = re.search(stationRE, station)
if not stationInfo:
log("stationInfo re not matched - ignore station")
continue
#print stationInfo.groups()
# ensure we only use allowed stream type
#type = stationInfo.group(3)
#if type not in ('MP3','Windows Media'): # add allowed type here
# log("ignored stream type: " + type)
# continue
name = stationInfo.group(1)
loc = stationInfo.group(2)
streamsData = stationInfo.group(3)
genre = stationInfo.group(4)
# parse station streams
streams = streamsRE.findall(streamsData)
for stream in streams:
streamURL = stream[0]
streamRate = stream[1]
if not streamRate.endswith('Kbps') or streamRate.endswith('kbps'):
log("ignored stream rate: " + streamRate)
continue
# further filter stream playlist types
#if streamURL.endswith('.m3u') or streamURL.endswith('.pls'):
#if not streamURL.endswith('ogg.m3u') and not streamURL.endswith('aac.m3u'):
# stream allowed, display it
infolabels = {}
label1 = "%s" % (name)
if list_loc=='true':
label1 += " | %s" % (loc)
if genre:
if list_genre=='true':
label1 += " | %s" % (genre)
infolabels["Genre"] = genre
genreExists = True # if any have genre then allow SORT_METHOD
if list_rate=='true':
label1 += " | %s" % (streamRate)
infolabels["Title"] = HTMLParser().unescape(label1)
streamRate2= streamRate.replace('Kbps', '')
streamRate2= streamRate2.replace('kbps', '')
#print 'rate2: ' + streamRate2 + ' - ' + 'min_rate: ' + min_rate
if float(streamRate2) >= float(min_rate):
#print 'show it!'
addDirectoryItem(HTMLParser().unescape(label1), streamURL, 2, infoLabels=infolabels, isFolder=False)
xbmcplugin.addSortMethod( handle=int( sys.argv[ 1 ] ), sortMethod=xbmcplugin.SORT_METHOD_LABEL )
if genreExists:
xbmcplugin.addSortMethod( handle=int( sys.argv[ 1 ] ), sortMethod=xbmcplugin.SORT_METHOD_GENRE )
ok = True
except:
errorOK("getStreams()")
log("< getStreams() ok=%s" % ok)
return ok
######################################################################################################
# fetch webpage or open filename if exists
######################################################################################################
def getURL(url, fn=''):
""" read a doc from an url and save to file (if required) """
try:
doc = ''
# load local file if exists
if fn and os.path.isfile(fn):
doc = open(fn).read()
if not doc:
deleteFile(fn) # empty file, remove it
log("Empty file removed: " + fn)
doc = ''
else:
log("Loaded existing file: " + fn)
if not doc:
safe_url = url.replace( " ", "%20" )
log('Downloading from url=%s' % safe_url)
sock = urllib.urlopen( safe_url )
doc = sock.read()
if fn:
fp = open(fn, "w")
fp.write(doc)
fp.close()
log("File saved to " + fn)
sock.close()
if doc:
return unicode(doc, 'utf-8', errors='ignore')
else:
return ''
except:
errorOK("getURL()")
return None
######################################################################################################
def get_params():
""" extract params from argv[2] to make a dict (key=value) """
paramDict = {}
try:
if sys.argv[2]:
paramPairs=sys.argv[2][1:].split( "&" )
for paramsPair in paramPairs:
paramSplits = paramsPair.split('=')
if (len(paramSplits))==2:
paramDict[paramSplits[0]] = paramSplits[1]
except:
errorOK()
return paramDict
######################################################################################################
def addDirectoryItem(name, url, mode, label2='', infoType="Music", infoLabels = {}, isFolder=True):
liz=xbmcgui.ListItem(name, label2)
if not infoLabels:
infoLabels = {"Title": name }
liz.setInfo( infoType, infoLabels )
v = "?name=%s&url=%s" % (urllib.quote_plus(name.encode('utf-8')), urllib.quote_plus(url.encode('utf-8')), )
action1 = 'XBMC.RunPlugin(plugin://plugin.audio.listenliveeu/?add%s%s)' % (v, '\n')
action2 = 'XBMC.RunPlugin(plugin://plugin.audio.listenliveeu/?remfav%s%s)' % (v, '\n')
action3 = 'XBMC.RunPlugin(plugin://plugin.audio.listenliveeu/?removeall)'
if mode==2:
try:
liz.addContextMenuItems([(__language__(30004), action1), (__language__(30006), action3)])
except:
errorOK("addDirectoryItem()")
elif mode==3:
try:
liz.addContextMenuItems([(__language__(30005), action2), (__language__(30006), action3)])
except:
errorOK("addDirectoryItem()")
u = "%s?url=%s&mode=%s&name=%s" % (sys.argv[0], urllib.quote_plus(url), mode, urllib.quote_plus(name.encode('utf-8')), )
log("%s" % u)
return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=isFolder)
######################################################################################################
def playStream(url, title=" "):
try:
log("> playStream() " + url)
log("> playStream() " + title)
plyr = xbmc.Player(xbmc.PLAYER_CORE_DVDPLAYER)
plyr.play( url )
isPlaying = plyr.isPlaying()
log("< playStream() isPlaying=%s" % isPlaying)
return isPlaying
except:
errorOK("playStream()")
return False
######################################################################################################
def deleteFile(fn):
try:
os.remove(fn)
log("File deleted: " + fn)
except: pass
#######################################################################################################################
# BEGIN !
#######################################################################################################################
try:
__settings__ = xbmcaddon.Addon(id='plugin.audio.listenliveeu')
__language__ = __settings__.getLocalizedString
except:
errorOK()
if not os.path.exists(DIR_SETTINGS):
os.mkdir(DIR_SETTINGS)
if not os.path.exists(FILE_FAVS):
writeFavs()
#######################################################################################################################
# get settings
#######################################################################################################################
list_loc = __settings__.getSetting( "list_loc" )
list_genre = __settings__.getSetting( "list_genre" )
list_rate = __settings__.getSetting( "list_rate" )
min_rate = __settings__.getSetting( "min_rate" )
#######################################################################################################################
params=get_params()
url=urllib.unquote_plus(params.get("url", ""))
name=urllib.unquote_plus(params.get("name",""))
mode=int(params.get("mode","0"))
log("Mode: %s" % mode)
log("URL: %s" % url)
log("Name: %s" % name)
if "?add" in sys.argv[ 2 ] :
ok = addFav(sys.argv[ 2 ])
xbmcplugin.endOfDirectory(int(sys.argv[1]), ok)
elif "?remfav" in sys.argv[ 2 ] :
ok = remFav(sys.argv[ 2 ])
xbmcplugin.endOfDirectory(int(sys.argv[1]), ok)
elif "?removeall" in sys.argv[ 2 ] :
ok = remallFavs(url)
xbmcplugin.endOfDirectory(int(sys.argv[1]), ok)
if not "?add" in sys.argv[ 2 ] and not "?remfav" in sys.argv[ 2 ] and not "?removeall" in sys.argv[ 2 ]:
if not sys.argv[ 2 ] or not url:
# new start - cleanup old files
deleteFile(FILE_INDEX_PAGE)
ok = getRootCats()
xbmcplugin.endOfDirectory(int(sys.argv[1]), ok)
elif url == "new":
ok = getStreams(URL_NEW)
xbmcplugin.endOfDirectory(int(sys.argv[1]), ok)
elif url == "favorites":
ok = getFavorites(FILE_FAVS)
xbmcplugin.endOfDirectory(int(sys.argv[1]), ok)
elif url == "country":
ok = getCats(True)
xbmcplugin.endOfDirectory(int(sys.argv[1]), ok)
elif url == "genre":
ok = getCats(False)
xbmcplugin.endOfDirectory(int(sys.argv[1]), ok)
elif mode==1:
ok = getStreams(url)
xbmcplugin.endOfDirectory(int(sys.argv[1]), ok)
elif mode==2:
ok = playStream(url, name)
elif mode==3:
ok = playStream(url, name)