######################################################
######################################################
# XBMC Script for SageTV #
# by Brian Pattison aka Coolwave #
# coolwave6@yahoo.com #
# edited by kricker vs 21.5 #
# This is my first experience with Python. #
# Thanks to all the great scripts out there #
# for me to get code from. This script wouldn't #
# exist without nielm's webserver for SageTV. #
# The guys at Frey of course rock for creating #
# such an extensible piece of software in SageTV. #
# Same goes to the XMBC developers! Rock on! #
# Thanks also to the crazy graphic designers #
# creating all the skins for MediaPortal. Your #
# Graphics are used in every PVR program out there #
# and we love them. Please switch to SageTV so we #
# can have you all creating new STVs. :) #
# #
######################################################
######################################################
import os, threading, xbmc, xbmcgui, time
import urllib, urllib2, re, copy, xml.dom.minidom
from string import split, replace, find
try: Emulating = xbmcgui.Emulating
except: Emulating = False
######################################################
######################################################
#User Adjustable Variables#
# x and y can help to move the entire interface
# on the screen if it is not displayed properly
x = 30
y = -15
######################################################
######################################################
# PLEASE EDIT settings.xml TO CHANGE ANY OTHER SETTINGS #
if Emulating:
dirHome = 'Q:\\scripts\\SageTV\\'
dirSkin = 'skins\\BlueTwo\\'
else:
dirHome = os.getcwd()
dirHome = dirHome[:-1]+'\\'
#Settings Class
class Setting:
def __init__(self, tagname, attribname):
XMLFile = open(dirHome + 'settings.xml', "r")
XMLData = XMLFile.read()
dom = xml.dom.minidom.parseString(XMLData)
XMLFile.close()
Item = dom.getElementsByTagName(tagname)[0]
self.tagname = tagname
self.attribname = attribname
self.value = Item.getAttribute(attribname)
def update(self, newvalue):
try:
XMLFile = open(dirHome + 'settings.xml', "r")
XMLData = XMLFile.read()
dom = xml.dom.minidom.parseString(XMLData)
XMLFile.close()
Item = dom.getElementsByTagName(self.tagname)[0]
Item.setAttribute(self.attribname, newvalue)
xmlstring = dom.toxml()
f = file(dirHome + 'settings.xml', 'wb')
try:
f.write(xmlstring)
finally:
f.close()
except:
dialog = xbmcgui.Dialog()
dialog.ok("SageTV", "Cannot write to " + dirHome + "settings.xml")
#End Settings Class
s = Setting("Connection", "Ipaddress")
ipaddress = s.value
s = Setting("Connection", "Port")
port = s.value
s = Setting("Connection", "UserId")
userid = s.value
s = Setting("Connection", "Password")
password = s.value
s = Setting("Appearance", "ShowEpisodeNames")
if s.value.lower() == "true":
ShowEpisodeNames = True
else:
ShowEpisodeNames = False
s = Setting("Appearance", "ShowDontLike")
if s.value.lower() == "true":
ShowDontLike = True
else:
ShowDontLike = False
s = Setting("Appearance", "ShowArchive")
if s.value.lower() == "true":
ShowArchive = True
else:
ShowArchive = False
s = Setting("Appearance", "Skin")
dirSkin = "skins\\" + s.value + "\\"
s = Setting("System", "RecordingPath")
RecordingPath = s.value.split(',')
s = Setting("System", "XBMCPath")
XBMCPath = s.value.split(',')
if ipaddress == "0.0.0.0":
firstlaunch = True
dialog = xbmcgui.Dialog()
dialog.ok("SageTV", "Please enter the IP Adress of the SageTV webserver.")
keyboard = xbmc.Keyboard(ipaddress)
keyboard.doModal()
if (keyboard.isConfirmed()):
ipaddress = keyboard.getText()
s = Setting("Connection", "Ipaddress")
s.update(ipaddress)
dialog.ok("SageTV", "Please enter the port used on the SageTV webserver.")
keyboard = xbmc.Keyboard(port)
keyboard.doModal()
if (keyboard.isConfirmed()):
port = keyboard.getText()
s = Setting("Connection", "Port")
s.update(port)
dialog.ok("SageTV", "Please enter the username for the SageTV webserver.")
keyboard = xbmc.Keyboard(userid)
keyboard.doModal()
if (keyboard.isConfirmed()):
userid = keyboard.getText()
s = Setting("Connection", "UserId")
s.update(userid)
dialog.ok("SageTV", "Please enter the password for the SageTV webserver.")
keyboard = xbmc.Keyboard(password)
keyboard.doModal()
if (keyboard.isConfirmed()):
password = keyboard.getText()
s = Setting("Connection", "Password")
s.update(password)
else:
firstlaunch = False
webaddress = userid + ":" + password + "@" + ipaddress + ":" + port
#Get Current Date/Connect to webserver
try:
Base_URL = "http://" + webaddress + "/sage/Home"
WebSock = urllib.urlopen(Base_URL) # Opens a 'Socket' to URL
WebHTML = WebSock.read() # Reads Contents of URL and saves to Variable
WebSock.close() # Closes connection to url
CURRENT_DATE = re.compile('generated at: (....[0-9]*),', re.I).findall(WebHTML)[0]
Connect = True
except:
try:
Base_URL = "http://" + webaddress + "/sage/Home"
WebSock = urllib.urlopen(Base_URL) # Opens a 'Socket' to URL
WebHTML = WebSock.read() # Reads Contents of URL and saves to Variable
WebSock.close() # Closes connection to url
CURRENT_DATE = re.compile('generated at: (....[0-9]*),', re.I).findall(WebHTML)[0]
Connect = True
except:
dialog = xbmcgui.Dialog()
dialog.ok("SageTV", "Unable to connect to http://" + webaddress + ".")
Connect = False
if firstlaunch:
s = Setting("Connection", "Ipaddress")
s.update("0.0.0.0")
#Declare global static variables
ACTION_MOVE_LEFT = 1
ACTION_MOVE_RIGHT = 2
ACTION_MOVE_UP = 3
ACTION_MOVE_DOWN = 4
ACTION_PAGE_UP = 5
ACTION_PAGE_DOWN = 6
ACTION_SELECT_ITEM = 7
ACTION_HIGHLIGHT_ITEM = 8
ACTION_PARENT_DIR = 9
ACTION_PREVIOUS_MENU = 10
ACTION_SHOW_INFO = 11
ACTION_PAUSE = 12
ACTION_STOP = 13
ACTION_NEXT_ITEM = 14
ACTION_PREV_ITEM = 15
ACTION_SCROLL_UP = 111
ACTION_SCROLL_DOWN = 112
ACTION_REMOTE_PLAY = 79
ACTION_REMOTE_BACK = 9
class Program:
def __init__(self, mediafileid, airingid):
#Get info from webpage
if mediafileid != 0:
Base_URL = "http://" + webaddress + "/sage/DetailedInfo?MediaFileId=" + str(mediafileid)
pmfid = mediafileid
WebSock = urllib.urlopen(Base_URL) # Opens a 'Socket' to URL
WebHTML = WebSock.read() # Reads Contents of URL and saves to Variable
WebSock.close() # Closes connection to url
precorded = True
elif airingid != 0:
Base_URL = "http://" + webaddress + "/sage/DetailedInfo?AiringId=" + str(airingid)
pmfid = airingid
WebSock = urllib.urlopen(Base_URL) # Opens a 'Socket' to URL
WebHTML = WebSock.read() # Reads Contents of URL and saves to Variable
WebSock.close() # Closes connection to url
precorded = False
if WebHTML.find('Internal details: MediaFileID=') > 0:
pmfid = re.compile('Internal details: MediaFileID=([0-9]*)', re.I).findall(WebHTML)[0]
precorded = True
else:
WebHTML = ""
if WebHTML != "":
#Title
ptitle = re.compile('\n(.*)', re.I).findall(WebHTML)[0]
ptitle = ptitle.replace("&", "&")
ptitle = ptitle.replace("%60", "'")
ptitle = ptitle.replace("%27", "'")
#SubTitle
if WebHTML.find('
Episode:') > 0:
psubtitle = re.compile('
Episode: (.*)
', re.I).findall(WebHTML)[0]
psubtitle = psubtitle.replace("amp;", "")
psubtitle = psubtitle.replace("%60", "'")
psubtitle = psubtitle.replace("%27", "'")
psubtitle2 = psubtitle + " - "
else:
psubtitle = ""
psubtitle2 = ""
#First Run/Rerun
if WebHTML.find('
') > 0:
pfirstrun = True
else:
pfirstrun = False
#Currently Recording
if WebHTML.find('Record Options', re.I) > 0:
if WebHTML.find('Archive', re.I) > 0:
pcur_rec = False
else:
pcur_rec = True
else:
pcur_rec = False
#Date and Time
if WebHTML.find('Aired: \r\n', re.I) > 0:
pdatetime = re.compile('
Aired: \r\n(.*)\r\n', re.I).findall(WebHTML)[0]
pdate = re.compile('
Aired: \r\n(.*),.*\r\n', re.I).findall(WebHTML)[0]
if pdate == CURRENT_DATE:
pdate = 'Today'
ptime = re.compile('.*,.[0-9][0-9][0-9][0-9].([0-9]*:[0-9][0-9]...).-', re.I).findall(pdatetime)[0]
elif WebHTML.find('
Airing: \r\n', re.I) > 0:
pdatetime = re.compile('
Airing: \r\n(.*)\r\n', re.I).findall(WebHTML)[0]
pdate = re.compile('
Airing: \r\n(.*),.*\r\n', re.I).findall(WebHTML)[0]
ptime = re.compile('.*,.[0-9][0-9][0-9][0-9].([0-9]*:[0-9][0-9]...).-', re.I).findall(pdatetime)[0]
if pdate == CURRENT_DATE:
pdate = ptime
if pcur_rec: pdate = 'Now'
else:
pdatetime = ''
pdate = ''
ptime = ''
#Channel
if WebHTML.find('
Rating:', re.I) > 0:
pchannel = re.compile('
Channel: (.*)
Rating: .*
', re.I).findall(WebHTML)[0]
else:
try: pchannel = re.compile('Channel: (.*)
', re.I).findall(WebHTML)[0]
except: pchannel = "Err"
#Description
try: pshortdesc = re.compile('
Description: (.*)
', re.I).findall(WebHTML)[0]
except: pshortdesc = "N/A"
pdesc = pshortdesc + '\n\n'
starring = re.compile('q=(.*);nm=on', re.I).findall(WebHTML)
for i in range(len(starring)):
starring[i] = starring[i].replace("+", " ")
starring[i] = starring[i].replace("%3A", ":")
starring[i] = starring[i].replace("%60", "'")
starring[i] = starring[i].replace("%27", "'")
if i > 0: pdesc = pdesc + ", " + starring[i]
else: pdesc = pdesc + starring[i]
#category = re.compile('Category: (.*)
', re.I).findall(WebHTML)[0]
category = ' '
pdesc = pdesc + '\n\n' + category
showid = re.compile('Show ID: (.*)
', re.I).findall(WebHTML)[0]
pdesc = pdesc + '\n\n' + 'ShowID: ' + showid
#Record/Cancel Record
if WebHTML.find('command=Record', re.I) > 0:
pman_rec = False
else:
pman_rec = True
#Record Series/Cancel Record Series
if WebHTML.find('FavoriteId', re.I) > 0:
pfav = re.compile('FavoriteId=([0-9]*)">', re.I).findall(WebHTML)[0]
else:
pfav = "No"
#Watched/Unwatched
if WebHTML.find('command=ClearWatched', re.I) > 0:
pwatched = True
else:
pwatched = False
#Set/Clear Don't Like
if WebHTML.find('
', re.I) > 0:
pdontlike = True
else:
pdontlike = False
#Archived
if WebHTML.find('
', re.I) > 0:
parch = True
else:
parch = False
#Start/End Padding
pstartpadding = 0
pendpadding = 0
if pman_rec:
if WebHTML.find('name="startpad"', re.I) > 0:
pstartpadding = int(re.compile('name="startpad" value="([0-9]*)"', re.I).findall(WebHTML)[0])
pendpadding = int(re.compile('name="endpad" value="([0-9]*)"', re.I).findall(WebHTML)[0])
earlypadding = (re.compile('