Since this thing was put in, I've had numerous complaints regarding freezing in the EPG, constant buffering, and general crappiness. Why, oh why do these issues suddenly exist? XMBC hates me, that's why.
Starting a new thread in Python (the scripting language used by XBMC) is easy:
class myThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
# Do stuff here
aThread = myThread()
myThread.start()
Excellent, now we have a thread. That's the easy part. It runs in the background, the main thread still gets called as normal, the world is a wonderful place. Under normal conditions, this thread can be preempted and so it won't block normal operation. Ah, but we run into an issue when we issue a JSON call from inside that thread:
myThread.start()
Excellent, now we have a thread. That's the easy part. It runs in the background, the main thread still gets called as normal, the world is a wonderful place. Under normal conditions, this thread can be preempted and so it won't block normal operation. Ah, but we run into an issue when we issue a JSON call from inside that thread:
xbmc.executeJSONRPC(command)
This makes a call to an XBMC library function. This function may take up to 15 or 20 seconds to complete. The kicker? This function blocks any Python code from running, even from a different thread. That means no user keypress callbacks, no actions if the user stops the video...no nothing. That doesn't make for a pleasant experience. So, what to do. Thankfully, XBMC provides a webserver that can process JSON calls, and guess what? Since Python isn't directly calling the library function, it won't block the code in other threads. So that's the answer! Kind of. Users don't HAVE to have the webserver turned on. It's off by default...meaning they have to specifically turn it on for it to work. Here's the pleasant function that's required:
def determineWebServer(self):
if self.discoveredWebServer:
return
def determineWebServer(self):
if self.discoveredWebServer:
return
self.discoveredWebServer = True
self.webPort = 8080
self.webUsername = ''
self.webPassword = ''
fle = xbmc.translatePath("special://profile/guisettings.xml")
self.webPort = 8080
self.webUsername = ''
self.webPassword = ''
fle = xbmc.translatePath("special://profile/guisettings.xml")
try:
xml = open(fle, "r")
except:
self.log("determineWebServer Unable to open the settings file", xbmc.LOGERROR)
self.httpJSON = False
return
xml = open(fle, "r")
except:
self.log("determineWebServer Unable to open the settings file", xbmc.LOGERROR)
self.httpJSON = False
return
try:
dom = parse(xml)
except:
self.log('determineWebServer Unable to parse settings file', xbmc.LOGERROR)
self.httpJSON = False
return
dom = parse(xml)
except:
self.log('determineWebServer Unable to parse settings file', xbmc.LOGERROR)
self.httpJSON = False
return
xml.close()
try:
plname = dom.getElementsByTagName('webserver')
self.httpJSON = (plname[0].childNodes[0].nodeValue.lower() == 'true')
self.log('determineWebServer is ' + str(self.httpJSON))
if self.httpJSON == True:
plname = dom.getElementsByTagName('webserverport')
self.webPort = int(plname[0].childNodes[0].nodeValue)
self.log('determineWebServer port ' + str(self.webPort))
plname = dom.getElementsByTagName('webserverusername')
self.webUsername = plname[0].childNodes[0].nodeValue
self.log('determineWebServer username ' + self.webUsername)
plname = dom.getElementsByTagName('webserverpassword')
self.webPassword = plname[0].childNodes[0].nodeValue
self.log('determineWebServer password is ' + self.webPassword)
except:
return
try:
plname = dom.getElementsByTagName('webserver')
self.httpJSON = (plname[0].childNodes[0].nodeValue.lower() == 'true')
self.log('determineWebServer is ' + str(self.httpJSON))
if self.httpJSON == True:
plname = dom.getElementsByTagName('webserverport')
self.webPort = int(plname[0].childNodes[0].nodeValue)
self.log('determineWebServer port ' + str(self.webPort))
plname = dom.getElementsByTagName('webserverusername')
self.webUsername = plname[0].childNodes[0].nodeValue
self.log('determineWebServer username ' + self.webUsername)
plname = dom.getElementsByTagName('webserverpassword')
self.webPassword = plname[0].childNodes[0].nodeValue
self.log('determineWebServer password is ' + self.webPassword)
except:
return
This ridiculous function directly opens up the settings file that XBMC creates, checks to see if the user has enabled the webserver, and grabs the username, password, and port for it. So if this data is detected then that's the method that will be used for JSON calls. If it isn't (self.httpJSON is False) then the normal library call is made.
It's actually pretty amazing how much of the code is just a mix of ways to bypass certain limitations.
Also, please enable your webserver if you use PseudoTV! I don't care what port or what mess of username and password you have...just turn that sucker on.
So there ya go, the mess of the background thread and the insanity required to get it to work at all. I may find some better way to do this in the future, but for the moment this is what we have.
* If you liked this post please click on one of the ads, or donate through paypal to help support the PseudoTV developer
It's actually pretty amazing how much of the code is just a mix of ways to bypass certain limitations.
Also, please enable your webserver if you use PseudoTV! I don't care what port or what mess of username and password you have...just turn that sucker on.
So there ya go, the mess of the background thread and the insanity required to get it to work at all. I may find some better way to do this in the future, but for the moment this is what we have.
* If you liked this post please click on one of the ads, or donate through paypal to help support the PseudoTV developer
No comments:
Post a Comment