class RemoteHandler(BaseHTTPRequestHandler): """ Serves a HEAD request """ session = None playerCallback = None progress = None currentCommandId = 0 protocol_version = 'HTTP/1.1' #=========================================================================== # #=========================================================================== def do_HEAD(self): printl("", self, "S") printl("Serving HEAD request...", self, "D") self.answer_request() printl("", self, "C") #=========================================================================== # #=========================================================================== def do_GET(self): printl("", self, "S") printl("Serving GET request...", self, "D") self.answer_request() printl("", self, "C") #=========================================================================== # #=========================================================================== def do_OPTIONS(self): printl("", self, "S") printl("Serving OPTIONS request...", self, "D") self.send_response(200) self.send_header('Content-Length', '0') self.send_header('Content-Type', 'text/plain') self.send_header('Connection', 'close') self.setAccessControlHeaders() self.end_headers() self.wfile.close() printl("", self, "C") #=========================================================================== # #=========================================================================== def response(self, body, headers = {}, code = 200): printl("", self, "S") try: self.send_response(code) for key in headers: self.send_header(key, headers[key]) self.send_header('Content-Length', len(body)) self.send_header('Connection', "close") self.setAccessControlHeaders() self.end_headers() self.wfile.write(body) self.wfile.close() except: pass printl("", self, "C") #=========================================================================== # #=========================================================================== def answer_request(self): printl("", self, "S") try: request_path=self.path[1:] request_path=re.sub(r"\?.*","",request_path) printl("request path is: [%s]" % request_path, self, "D") # first we get all params form url params = self.getParams() data = {"command": "updateCommandId", "uuid": self.headers.get('X-Plex-Client-Identifier', self.client_address[0]), "commandID": params.get('commandID', False)} self.playerCallback(data) self.resetCallback() if request_path == "player/timeline/subscribe": self.response(getOKMsg(), getPlexHeaders()) protocol = params.get('protocol', False) host = self.client_address[0] port = params.get('port', False) uuid = self.headers.get('X-Plex-Client-Identifier', "") commandID = params.get('commandID', 0) printl("host: " + str(host), self, "D") printl("protocol: " + str(protocol), self, "D") printl("port: " + str(port), self, "D") printl("uuid: " + str(uuid), self, "D") printl("commandID: " + str(commandID), self, "D") data = {"command": "addSubscriber", "protocol": protocol, "host": host, "port": port, "uuid": uuid, "commandID": commandID} #subMgr.addSubscriber(protocol, host, port, uuid, commandID) self.playerCallback(data) self.resetCallback() elif "player/timeline/unsubscribe" in request_path: self.response(getOKMsg(), getPlexHeaders()) uuid = self.headers.get('X-Plex-Client-Identifier', False) or self.client_address[0] data = {"command": "removeSubscriber", "uuid": uuid} #subMgr.removeSubscriber(uuid) self.playerCallback(data) self.resetCallback() elif request_path == "resources": responseContent = getXMLHeader() responseContent += str(self.getResourceXml()) self.response(responseContent, getPlexHeaders()) elif request_path == "player/timeline/poll": commandID = params.get('commandID', 0) self.subMgr = SubscriptionManager() try: e2params = self.session.current_dialog.getPlayerState() if e2params: self.subMgr.progressFromEnigma2 = e2params['progress'] self.subMgr.playerStateFromEnigma2 = e2params["state"] self.subMgr.durationFromEnigma2 = e2params["duration"] self.subMgr.lastkey = e2params["lastKey"] self.answerPoll(commandID) sleep(1) except: print "no params" self.answerPoll(commandID) sleep(1) elif request_path == "player/playback/setParameters": volume = params["volume"] data = {"command": "setVolume", "volume": volume} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/pause": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "pause"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/play": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "play"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/stop": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "stop"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/skipNext": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "skipNext"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/skipPrevious": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "skipPrevious"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/stepForward": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "stepForward"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/stepBack": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "stepBack"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/seekTo": self.response(getOKMsg(), getPlexHeaders()) offset = params["offset"] data = {"command": "seekTo", "offset": offset} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/playMedia": self.response(getOKMsg(), getPlexHeaders()) self.currentAddress = params.get('address', self.client_address[0]) self.currentKey = params['key'] self.currentPort = params['port'] self.currentProtocol = params.get('protocol', "http") self.currentCompleteAddress = self.currentAddress + ":" + self.currentPort if "offset" in params: offset = int(params["offset"]) else: offset = 0 machineIdentifier = params["machineIdentifier"] printl("target machineIdentifier: " + str(machineIdentifier), self, "D") for serverConfig in config.plugins.dreamplex.Entries: printl("current machineIdentifier: " + str(serverConfig.machineIdentifier.value), self, "D") if machineIdentifier in serverConfig.machineIdentifier.value: printl("we have a match ...", self, "D") self.g_serverConfig = serverConfig self.plexInstance = Singleton().getPlexInstance(PlexLibrary(self.session, self.g_serverConfig, self.currentCompleteAddress, machineIdentifier)) listViewList, mediaContainer = self.plexInstance.getMixedContentFromSection(self.currentProtocol + "://" + self.currentAddress + ":" + self.currentPort + self.currentKey, fromRemotePlayer=True) autoPlayMode = False if offset > 0: forceResume = True else: forceResume = False resumeMode = False # this is always false because the ios and android app ask itself if we want to resume :-) no need to ask second time playbackMode = self.g_serverConfig.playbackType.value currentIndex = 0 libraryName = "Mixed" splittedData = self.currentKey.split("/") subtitleData = self.plexInstance.getSelectedSubtitleDataById(self.currentCompleteAddress, splittedData[-1]) data = {"command": "playMedia", "currentKey": self.currentKey, "listViewList": listViewList, "mediaContainer": mediaContainer, "autoPlayMode": autoPlayMode, "forceResume": forceResume, "resumeMode": resumeMode, "playbackMode": playbackMode, "currentIndex": currentIndex, "libraryName": libraryName, "subtitleData": subtitleData } self.playerCallback(data) self.resetCallback() else: printl("no match ...", self, "D") else: self.response(getOKMsg(), getPlexHeaders()) except: traceback.print_exc() self.wfile.close() printl("", self, "C") return try: self.wfile.close() except: pass printl("", self, "C") #=========================================================================== # #=========================================================================== def resetCallback(self): # we do this due to the fact that the messagepump is triggered mor often than we want to via playercallback for this reason we set to idle so that for example playMedia command is not called more than once data = {"command": "idle"} self.playerCallback(data) #=========================================================================== # #=========================================================================== def answerPoll(self, commandID): self.response(re.sub(r"INSERTCOMMANDID", str(commandID), self.subMgr.msg(self.getPlayers())), { 'Access-Control-Expose-Headers': 'X-Plex-Client-Identifier', 'Content-Type': 'text/xml' }) #=========================================================================== # #=========================================================================== def address_string(self): printl("", self, "S") host, port = self.client_address[:2] #return socket.getfqdn(host) printl("", self, "C") return host #=========================================================================== # #=========================================================================== def getResourceXml(self): printl("", self, "S") xml = "<MediaContainer><Player protocolCapabilities='playback, navigation' product='"+ getMyIp() +"' platformVersion='"+ getVersion() +"' platform='Enigma2' machineIdentifier='"+ getUUID() +"' title='"+ config.plugins.dreamplex.boxName.value +"' protocolVersion='1' deviceClass='stb'/></MediaContainer>" printl("", self, "C") return xml #=========================================================================== # #=========================================================================== def setXmlHeader(self, xml): printl("", self, "S") self.send_header('Content-type', 'text/xml; charset="utf-8"') self.send_header('Content-Length', str(len(xml))) printl("", self, "S") #=========================================================================== # #=========================================================================== def setAccessControlHeaders(self): printl("", self, "S") self.send_header('X-Plex-Client-Identifier', getUUID()) self.send_header('Access-Control-Max-Age', '1209600') self.send_header('Access-Control-Allow-Credentials', 'true') self.send_header('Access-Control-Allow-Origin', '*') self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') self.send_header("Access-Control-Allow-Headers", "x-plex-client-identifier,x-plex-device,x-plex-device-name,x-plex-platform,x-plex-platform-version,x-plex-product,x-plex-target-client-identifier,x-plex-username,x-plex-version") printl("", self, "S") #=========================================================================== # #=========================================================================== def getParams(self): printl("", self, "S") params = {} paramarrays = parse_qs(urlparse(self.path).query) for key in paramarrays: params[key] = paramarrays[key][0] printl("", self, "C") return params #=========================================================================== # #=========================================================================== def getPlayers(self): ret = {} try: ret = self.session.current_dialog.getPlayer() except: pass return ret
class RemoteHandler(BaseHTTPRequestHandler): """ Serves a HEAD request """ session = None playerCallback = None progress = None currentCommandId = 0 protocol_version = 'HTTP/1.1' #=========================================================================== # #=========================================================================== def do_HEAD(self): printl("", self, "S") printl("Serving HEAD request...", self, "D") self.answer_request() printl("", self, "C") #=========================================================================== # #=========================================================================== def do_GET(self): printl("", self, "S") printl("Serving GET request...", self, "D") self.answer_request() printl("", self, "C") #=========================================================================== # #=========================================================================== def do_OPTIONS(self): printl("", self, "S") printl("Serving OPTIONS request...", self, "D") self.send_response(200) self.send_header('Content-Length', '0') self.send_header('Content-Type', 'text/plain') self.send_header('Connection', 'close') self.setAccessControlHeaders() self.end_headers() self.wfile.close() printl("", self, "C") #=========================================================================== # #=========================================================================== def response(self, body, headers={}, code=200): printl("", self, "S") try: self.send_response(code) for key in headers: self.send_header(key, headers[key]) self.send_header('Content-Length', len(body)) self.send_header('Connection', "close") self.setAccessControlHeaders() self.end_headers() self.wfile.write(body) self.wfile.close() except: pass printl("", self, "C") #=========================================================================== # #=========================================================================== def answer_request(self): printl("", self, "S") try: request_path = self.path[1:] request_path = re.sub(r"\?.*", "", request_path) printl("request path is: [%s]" % request_path, self, "D") # first we get all params form url params = self.getParams() data = { "command": "updateCommandId", "uuid": self.headers.get('X-Plex-Client-Identifier', self.client_address[0]), "commandID": params.get('commandID', False) } self.playerCallback(data) self.resetCallback() if request_path == "player/timeline/subscribe": self.response(getOKMsg(), getPlexHeaders()) protocol = params.get('protocol', False) host = self.client_address[0] port = params.get('port', False) uuid = self.headers.get('X-Plex-Client-Identifier', "") commandID = params.get('commandID', 0) printl("host: " + str(host), self, "D") printl("protocol: " + str(protocol), self, "D") printl("port: " + str(port), self, "D") printl("uuid: " + str(uuid), self, "D") printl("commandID: " + str(commandID), self, "D") data = { "command": "addSubscriber", "protocol": protocol, "host": host, "port": port, "uuid": uuid, "commandID": commandID } #subMgr.addSubscriber(protocol, host, port, uuid, commandID) self.playerCallback(data) self.resetCallback() elif "player/timeline/unsubscribe" in request_path: self.response(getOKMsg(), getPlexHeaders()) uuid = self.headers.get('X-Plex-Client-Identifier', False) or self.client_address[0] data = {"command": "removeSubscriber", "uuid": uuid} #subMgr.removeSubscriber(uuid) self.playerCallback(data) self.resetCallback() elif request_path == "resources": responseContent = getXMLHeader() responseContent += str(self.getResourceXml()) self.response(responseContent, getPlexHeaders()) elif request_path == "player/timeline/poll": commandID = params.get('commandID', 0) self.subMgr = SubscriptionManager() try: e2params = self.session.current_dialog.getPlayerState() if e2params: self.subMgr.progressFromEnigma2 = e2params['progress'] self.subMgr.playerStateFromEnigma2 = e2params["state"] self.subMgr.durationFromEnigma2 = e2params["duration"] self.subMgr.lastkey = e2params["lastKey"] self.answerPoll(commandID) sleep(1) except: print "no params" self.answerPoll(commandID) sleep(1) elif request_path == "player/playback/setParameters": volume = params["volume"] data = {"command": "setVolume", "volume": volume} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/pause": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "pause"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/play": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "play"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/stop": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "stop"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/skipNext": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "skipNext"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/skipPrevious": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "skipPrevious"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/stepForward": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "stepForward"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/stepBack": self.response(getOKMsg(), getPlexHeaders()) data = {"command": "stepBack"} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/seekTo": self.response(getOKMsg(), getPlexHeaders()) offset = params["offset"] data = {"command": "seekTo", "offset": offset} self.playerCallback(data) self.resetCallback() elif request_path == "player/playback/playMedia": self.response(getOKMsg(), getPlexHeaders()) self.currentAddress = params.get('address', self.client_address[0]) self.currentKey = params['key'] self.currentPort = params['port'] self.currentProtocol = params.get('protocol', "http") self.currentCompleteAddress = self.currentAddress + ":" + self.currentPort if "offset" in params: offset = int(params["offset"]) else: offset = 0 machineIdentifier = params["machineIdentifier"] printl("target machineIdentifier: " + str(machineIdentifier), self, "D") for serverConfig in config.plugins.dreamplex.Entries: printl( "current machineIdentifier: " + str(serverConfig.machineIdentifier.value), self, "D") if machineIdentifier in serverConfig.machineIdentifier.value: printl("we have a match ...", self, "D") self.g_serverConfig = serverConfig self.plexInstance = Singleton().getPlexInstance( PlexLibrary(self.session, self.g_serverConfig, self.currentCompleteAddress, machineIdentifier)) listViewList, mediaContainer = self.plexInstance.getMixedContentFromSection( self.currentProtocol + "://" + self.currentAddress + ":" + self.currentPort + self.currentKey, fromRemotePlayer=True) autoPlayMode = False if offset > 0: forceResume = True else: forceResume = False resumeMode = False # this is always false because the ios and android app ask itself if we want to resume :-) no need to ask second time playbackMode = self.g_serverConfig.playbackType.value currentIndex = 0 libraryName = "Mixed" splittedData = self.currentKey.split("/") subtitleData = self.plexInstance.getSelectedSubtitleDataById( self.currentCompleteAddress, splittedData[-1]) data = { "command": "playMedia", "currentKey": self.currentKey, "listViewList": listViewList, "mediaContainer": mediaContainer, "autoPlayMode": autoPlayMode, "forceResume": forceResume, "resumeMode": resumeMode, "playbackMode": playbackMode, "currentIndex": currentIndex, "libraryName": libraryName, "subtitleData": subtitleData } self.playerCallback(data) self.resetCallback() else: printl("no match ...", self, "D") else: self.response(getOKMsg(), getPlexHeaders()) except: traceback.print_exc() self.wfile.close() printl("", self, "C") return try: self.wfile.close() except: pass printl("", self, "C") #=========================================================================== # #=========================================================================== def resetCallback(self): # we do this due to the fact that the messagepump is triggered mor often than we want to via playercallback for this reason we set to idle so that for example playMedia command is not called more than once data = {"command": "idle"} self.playerCallback(data) #=========================================================================== # #=========================================================================== def answerPoll(self, commandID): self.response( re.sub(r"INSERTCOMMANDID", str(commandID), self.subMgr.msg(self.getPlayers())), { 'Access-Control-Expose-Headers': 'X-Plex-Client-Identifier', 'Content-Type': 'text/xml' }) #=========================================================================== # #=========================================================================== def address_string(self): printl("", self, "S") host, port = self.client_address[:2] #return socket.getfqdn(host) printl("", self, "C") return host #=========================================================================== # #=========================================================================== def getResourceXml(self): printl("", self, "S") xml = "<MediaContainer><Player protocolCapabilities='playback, navigation' product='" + getMyIp( ) + "' platformVersion='" + getVersion( ) + "' platform='Enigma2' machineIdentifier='" + getUUID( ) + "' title='" + config.plugins.dreamplex.boxName.value + "' protocolVersion='1' deviceClass='stb'/></MediaContainer>" printl("", self, "C") return xml #=========================================================================== # #=========================================================================== def setXmlHeader(self, xml): printl("", self, "S") self.send_header('Content-type', 'text/xml; charset="utf-8"') self.send_header('Content-Length', str(len(xml))) printl("", self, "S") #=========================================================================== # #=========================================================================== def setAccessControlHeaders(self): printl("", self, "S") self.send_header('X-Plex-Client-Identifier', getUUID()) self.send_header('Access-Control-Max-Age', '1209600') self.send_header('Access-Control-Allow-Credentials', 'true') self.send_header('Access-Control-Allow-Origin', '*') self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') self.send_header( "Access-Control-Allow-Headers", "x-plex-client-identifier,x-plex-device,x-plex-device-name,x-plex-platform,x-plex-platform-version,x-plex-product,x-plex-target-client-identifier,x-plex-username,x-plex-version" ) printl("", self, "S") #=========================================================================== # #=========================================================================== def getParams(self): printl("", self, "S") params = {} paramarrays = parse_qs(urlparse(self.path).query) for key in paramarrays: params[key] = paramarrays[key][0] printl("", self, "C") return params #=========================================================================== # #=========================================================================== def getPlayers(self): ret = {} try: ret = self.session.current_dialog.getPlayer() except: pass return ret