###################################################### ###################################################### # XBMC Script for SageTV # # by Brian Pattison aka Coolwave # # coolwave6@yahoo.com # # edited by kricker vs 2.22 # # 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("&", "&") psubtitle = psubtitle.replace("%60", "'") psubtitle = psubtitle.replace("%27", "'") psubtitle2 = psubtitle + " - " else: psubtitle = "" psubtitle2 = "" #First Run/Rerun if WebHTML.find('First Run') > 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 = ' ' 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('Dont Like', re.I) > 0: pdontlike = True else: pdontlike = False #Archived if WebHTML.find('Archived File', 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('