More Plex Companion cleanup
No dedicated logging anymore
This commit is contained in:
parent
43dc83ae57
commit
43b0af936f
8 changed files with 222 additions and 218 deletions
|
@ -5,10 +5,9 @@ import socket
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
|
|
||||||
import clientinfo
|
|
||||||
import utils
|
import utils
|
||||||
from plexbmchelper import listener, plexgdm, subscribers, functions, \
|
from plexbmchelper import listener, plexgdm, subscribers, functions, \
|
||||||
httppersist
|
httppersist, settings
|
||||||
|
|
||||||
|
|
||||||
@utils.logging
|
@utils.logging
|
||||||
|
@ -16,21 +15,12 @@ from plexbmchelper import listener, plexgdm, subscribers, functions, \
|
||||||
@utils.ThreadMethods
|
@utils.ThreadMethods
|
||||||
class PlexCompanion(threading.Thread):
|
class PlexCompanion(threading.Thread):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ci = clientinfo.ClientInfo()
|
|
||||||
self.clientId = ci.getDeviceId()
|
|
||||||
self.deviceName = ci.getDeviceName()
|
|
||||||
|
|
||||||
self.port = int(utils.settings('companionPort'))
|
|
||||||
self.logMsg("----===## Starting PlexCompanion ##===----", 1)
|
self.logMsg("----===## Starting PlexCompanion ##===----", 1)
|
||||||
|
self.settings = settings.getSettings()
|
||||||
|
|
||||||
# Start GDM for server/client discovery
|
# Start GDM for server/client discovery
|
||||||
self.client = plexgdm.plexgdm(
|
self.client = plexgdm.plexgdm()
|
||||||
debug=utils.settings('companionGDMDebugging'))
|
self.client.clientDetails(self.settings)
|
||||||
self.client.clientDetails(self.clientId, # UUID
|
|
||||||
self.deviceName, # clientName
|
|
||||||
self.port,
|
|
||||||
self.addonName,
|
|
||||||
'1.0') # Version
|
|
||||||
self.logMsg("Registration string is: %s "
|
self.logMsg("Registration string is: %s "
|
||||||
% self.client.getClientDetails(), 1)
|
% self.client.getClientDetails(), 1)
|
||||||
|
|
||||||
|
@ -46,7 +36,7 @@ class PlexCompanion(threading.Thread):
|
||||||
|
|
||||||
# Start up instances
|
# Start up instances
|
||||||
requestMgr = httppersist.RequestMgr()
|
requestMgr = httppersist.RequestMgr()
|
||||||
jsonClass = functions.jsonClass(requestMgr)
|
jsonClass = functions.jsonClass(requestMgr, self.settings)
|
||||||
subscriptionManager = subscribers.SubscriptionManager(
|
subscriptionManager = subscribers.SubscriptionManager(
|
||||||
jsonClass, requestMgr)
|
jsonClass, requestMgr)
|
||||||
|
|
||||||
|
@ -57,7 +47,8 @@ class PlexCompanion(threading.Thread):
|
||||||
client,
|
client,
|
||||||
subscriptionManager,
|
subscriptionManager,
|
||||||
jsonClass,
|
jsonClass,
|
||||||
('', self.port),
|
self.settings,
|
||||||
|
('', self.settings['myport']),
|
||||||
listener.MyHandler)
|
listener.MyHandler)
|
||||||
httpd.timeout = 0.95
|
httpd.timeout = 0.95
|
||||||
break
|
break
|
||||||
|
@ -99,7 +90,7 @@ class PlexCompanion(threading.Thread):
|
||||||
else:
|
else:
|
||||||
log("Client is no longer registered", 1)
|
log("Client is no longer registered", 1)
|
||||||
log("Plex Companion still running on port %s"
|
log("Plex Companion still running on port %s"
|
||||||
% self.port, 1)
|
% self.settings['myport'], 1)
|
||||||
message_count = 0
|
message_count = 0
|
||||||
|
|
||||||
# Get and set servers
|
# Get and set servers
|
||||||
|
@ -108,7 +99,7 @@ class PlexCompanion(threading.Thread):
|
||||||
subscriptionManager.notify()
|
subscriptionManager.notify()
|
||||||
xbmc.sleep(50)
|
xbmc.sleep(50)
|
||||||
except:
|
except:
|
||||||
log("Error in loop, continuing anyway", 1)
|
log("Error in loop, continuing anyway", 0)
|
||||||
log(traceback.format_exc(), 1)
|
log(traceback.format_exc(), 1)
|
||||||
xbmc.sleep(50)
|
xbmc.sleep(50)
|
||||||
|
|
||||||
|
|
|
@ -44,19 +44,20 @@ class ClientInfo():
|
||||||
return deviceName
|
return deviceName
|
||||||
|
|
||||||
def getPlatform(self):
|
def getPlatform(self):
|
||||||
|
|
||||||
if xbmc.getCondVisibility('system.platform.osx'):
|
if xbmc.getCondVisibility('system.platform.osx'):
|
||||||
return "OSX"
|
return "MacOSX"
|
||||||
elif xbmc.getCondVisibility('system.platform.atv2'):
|
elif xbmc.getCondVisibility('system.platform.atv2'):
|
||||||
return "ATV2"
|
return "AppleTV2"
|
||||||
elif xbmc.getCondVisibility('system.platform.ios'):
|
elif xbmc.getCondVisibility('system.platform.ios'):
|
||||||
return "iOS"
|
return "iOS"
|
||||||
elif xbmc.getCondVisibility('system.platform.windows'):
|
elif xbmc.getCondVisibility('system.platform.windows'):
|
||||||
return "Windows"
|
return "Windows"
|
||||||
|
elif xbmc.getCondVisibility('system.platform.raspberrypi'):
|
||||||
|
return "RaspberryPi"
|
||||||
elif xbmc.getCondVisibility('system.platform.linux'):
|
elif xbmc.getCondVisibility('system.platform.linux'):
|
||||||
return "Linux/RPi"
|
return "Linux"
|
||||||
elif xbmc.getCondVisibility('system.platform.android'):
|
elif xbmc.getCondVisibility('system.platform.android'):
|
||||||
return "Linux/Android"
|
return "Android"
|
||||||
else:
|
else:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,7 @@ import base64
|
||||||
import json
|
import json
|
||||||
import string
|
import string
|
||||||
import xbmc
|
import xbmc
|
||||||
import settings
|
from utils import logging
|
||||||
from utils import logMsg
|
|
||||||
|
|
||||||
|
|
||||||
def xbmc_photo():
|
def xbmc_photo():
|
||||||
|
@ -48,24 +47,6 @@ def plex_type(xbmc_type):
|
||||||
return plex_audio()
|
return plex_audio()
|
||||||
|
|
||||||
|
|
||||||
def getPlatform():
|
|
||||||
if xbmc.getCondVisibility('system.platform.osx'):
|
|
||||||
return "MacOSX"
|
|
||||||
elif xbmc.getCondVisibility('system.platform.atv2'):
|
|
||||||
return "AppleTV2"
|
|
||||||
elif xbmc.getCondVisibility('system.platform.ios'):
|
|
||||||
return "iOS"
|
|
||||||
elif xbmc.getCondVisibility('system.platform.windows'):
|
|
||||||
return "Windows"
|
|
||||||
elif xbmc.getCondVisibility('system.platform.raspberrypi'):
|
|
||||||
return "RaspberryPi"
|
|
||||||
elif xbmc.getCondVisibility('system.platform.linux'):
|
|
||||||
return "Linux"
|
|
||||||
elif xbmc.getCondVisibility('system.platform.android'):
|
|
||||||
return "Android"
|
|
||||||
return "Unknown"
|
|
||||||
|
|
||||||
|
|
||||||
def getXMLHeader():
|
def getXMLHeader():
|
||||||
return '<?xml version="1.0" encoding="utf-8" ?>'+"\r\n"
|
return '<?xml version="1.0" encoding="utf-8" ?>'+"\r\n"
|
||||||
|
|
||||||
|
@ -93,10 +74,11 @@ def textFromXml(element):
|
||||||
return element.firstChild.data
|
return element.firstChild.data
|
||||||
|
|
||||||
|
|
||||||
|
@logging
|
||||||
class jsonClass():
|
class jsonClass():
|
||||||
|
|
||||||
def __init__(self, requestMgr):
|
def __init__(self, requestMgr, settings):
|
||||||
self.settings = settings.getSettings()
|
self.settings = settings
|
||||||
self.requestMgr = requestMgr
|
self.requestMgr = requestMgr
|
||||||
|
|
||||||
def jsonrpc(self, action, arguments={}):
|
def jsonrpc(self, action, arguments={}):
|
||||||
|
@ -122,9 +104,8 @@ class jsonClass():
|
||||||
"jsonrpc" : "2.0",
|
"jsonrpc" : "2.0",
|
||||||
"method" : action})
|
"method" : action})
|
||||||
|
|
||||||
logMsg("PlexCompanion",
|
self.logMsg("Sending request to XBMC without network stack: %s"
|
||||||
"Sending request to XBMC without network stack: %s"
|
% request, 2)
|
||||||
% request, 2)
|
|
||||||
result = self.parseJSONRPC(xbmc.executeJSONRPC(request))
|
result = self.parseJSONRPC(xbmc.executeJSONRPC(request))
|
||||||
|
|
||||||
if not result and self.settings['webserver_enabled']:
|
if not result and self.settings['webserver_enabled']:
|
||||||
|
@ -159,14 +140,13 @@ class jsonClass():
|
||||||
|
|
||||||
def parseJSONRPC(self, jsonraw):
|
def parseJSONRPC(self, jsonraw):
|
||||||
if not jsonraw:
|
if not jsonraw:
|
||||||
logMsg("PlexCompanion", "Empty response from XBMC", 1)
|
self.logMsg("Empty response from XBMC", 1)
|
||||||
return {}
|
return {}
|
||||||
else:
|
else:
|
||||||
logMsg("PlexCompanion", "Response from XBMC: %s" % jsonraw, 2)
|
self.logMsg("Response from XBMC: %s" % jsonraw, 2)
|
||||||
parsed=json.loads(jsonraw)
|
parsed=json.loads(jsonraw)
|
||||||
if parsed.get('error', False):
|
if parsed.get('error', False):
|
||||||
logMsg("PlexCompanion", "XBMC returned an error: %s"
|
self.logMsg("XBMC returned an error: %s" % parsed.get('error'), -1)
|
||||||
% parsed.get('error'), -1)
|
|
||||||
return parsed.get('result', {})
|
return parsed.get('result', {})
|
||||||
|
|
||||||
def getPlayers(self):
|
def getPlayers(self):
|
||||||
|
|
|
@ -78,9 +78,13 @@ class RequestMgr:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return data.read() or True
|
return data.read() or True
|
||||||
except:
|
except socket_error as serr:
|
||||||
self.logMsg("Unable to connect to %s\nReason:" % host, -1)
|
# Ignore remote close and connection refused (e.g. shutdown PKC)
|
||||||
self.logMsg(traceback.print_exc(), -1)
|
if serr.errno in (errno.WSAECONNABORTED, errno.WSAECONNREFUSED):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.logMsg("Unable to connect to %s\nReason:" % host, -1)
|
||||||
|
self.logMsg(traceback.print_exc(), -1)
|
||||||
self.conns.pop(protocol+host+str(port), None)
|
self.conns.pop(protocol+host+str(port), None)
|
||||||
conn.close()
|
conn.close()
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import re
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
import xbmc
|
|
||||||
from SocketServer import ThreadingMixIn
|
from SocketServer import ThreadingMixIn
|
||||||
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
||||||
from urlparse import urlparse, parse_qs
|
from urlparse import urlparse, parse_qs
|
||||||
import settings
|
|
||||||
|
from xbmc import sleep
|
||||||
|
|
||||||
from functions import *
|
from functions import *
|
||||||
from utils import logging
|
from utils import logging
|
||||||
|
|
||||||
|
@ -14,9 +15,9 @@ class MyHandler(BaseHTTPRequestHandler):
|
||||||
protocol_version = 'HTTP/1.1'
|
protocol_version = 'HTTP/1.1'
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.serverlist = []
|
|
||||||
self.settings = settings.getSettings()
|
|
||||||
BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
|
BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
|
||||||
|
self.serverlist = []
|
||||||
|
self.settings = self.server.settings
|
||||||
|
|
||||||
def getServerByHost(self, host):
|
def getServerByHost(self, host):
|
||||||
if len(self.serverlist) == 1:
|
if len(self.serverlist) == 1:
|
||||||
|
@ -113,7 +114,7 @@ class MyHandler(BaseHTTPRequestHandler):
|
||||||
s.subMgr.addSubscriber(protocol, host, port, uuid, commandID)
|
s.subMgr.addSubscriber(protocol, host, port, uuid, commandID)
|
||||||
elif "/poll" in request_path:
|
elif "/poll" in request_path:
|
||||||
if params.get('wait', False) == '1':
|
if params.get('wait', False) == '1':
|
||||||
xbmc.sleep(950)
|
sleep(950)
|
||||||
commandID = params.get('commandID', 0)
|
commandID = params.get('commandID', 0)
|
||||||
s.response(re.sub(r"INSERTCOMMANDID", str(commandID), s.subMgr.msg(s.js.getPlayers())), {
|
s.response(re.sub(r"INSERTCOMMANDID", str(commandID), s.subMgr.msg(s.js.getPlayers())), {
|
||||||
'X-Plex-Client-Identifier': s.settings['uuid'],
|
'X-Plex-Client-Identifier': s.settings['uuid'],
|
||||||
|
@ -221,7 +222,7 @@ class MyHandler(BaseHTTPRequestHandler):
|
||||||
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
|
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
|
||||||
daemon_threads = True
|
daemon_threads = True
|
||||||
|
|
||||||
def __init__(self, client, subscriptionManager, jsonClass,
|
def __init__(self, client, subscriptionManager, jsonClass, settings,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
"""
|
"""
|
||||||
client: Class handle to plexgdm.plexgdm. We can thus ask for an up-to-
|
client: Class handle to plexgdm.plexgdm. We can thus ask for an up-to-
|
||||||
|
@ -232,4 +233,5 @@ class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
|
||||||
self.client = client
|
self.client = client
|
||||||
self.subscriptionManager = subscriptionManager
|
self.subscriptionManager = subscriptionManager
|
||||||
self.jsonClass = jsonClass
|
self.jsonClass = jsonClass
|
||||||
|
self.settings = settings
|
||||||
HTTPServer.__init__(self, *args, **kwargs)
|
HTTPServer.__init__(self, *args, **kwargs)
|
||||||
|
|
|
@ -26,23 +26,20 @@ __author__ = 'DHJ (hippojay) <plex@h-jay.com>'
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
import sys
|
|
||||||
import re
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import urllib2
|
|
||||||
|
|
||||||
import xbmc
|
from xbmc import sleep
|
||||||
|
|
||||||
import downloadutils
|
import downloadutils
|
||||||
from PlexFunctions import PMSHttpsEnabled
|
from PlexFunctions import PMSHttpsEnabled
|
||||||
from utils import window
|
from utils import window, logging
|
||||||
|
|
||||||
|
|
||||||
|
@logging
|
||||||
class plexgdm:
|
class plexgdm:
|
||||||
|
|
||||||
def __init__(self, debug=False):
|
def __init__(self):
|
||||||
|
|
||||||
self.discover_message = 'M-SEARCH * HTTP/1.0'
|
self.discover_message = 'M-SEARCH * HTTP/1.0'
|
||||||
self.client_header = '* HTTP/1.0'
|
self.client_header = '* HTTP/1.0'
|
||||||
self.client_data = None
|
self.client_data = None
|
||||||
|
@ -61,77 +58,115 @@ class plexgdm:
|
||||||
|
|
||||||
self.discovery_complete = False
|
self.discovery_complete = False
|
||||||
self.client_registered = False
|
self.client_registered = False
|
||||||
self.debug = debug
|
|
||||||
self.download = downloadutils.DownloadUtils().downloadUrl
|
self.download = downloadutils.DownloadUtils().downloadUrl
|
||||||
|
|
||||||
def __printDebug(self, message, level=1):
|
def clientDetails(self, settings):
|
||||||
if self.debug:
|
self.client_data = (
|
||||||
print "PlexGDM: %s" % message
|
"Content-Type: plex/media-player\r\n"
|
||||||
|
"Resource-Identifier: %s\r\n"
|
||||||
def clientDetails(self, c_id, c_name, c_post, c_product, c_version):
|
"Name: %s\r\n"
|
||||||
self.client_data = "Content-Type: plex/media-player\r\nResource-Identifier: %s\r\nName: %s\r\nPort: %s\r\nProduct: %s\r\nVersion: %s\r\nProtocol: plex\r\nProtocol-Version: 1\r\nProtocol-Capabilities: timeline,playback,navigation,mirror,playqueues\r\nDevice-Class: HTPC" % ( c_id, c_name, c_post, c_product, c_version )
|
"Port: %s\r\n"
|
||||||
self.client_id = c_id
|
"Product: %s\r\n"
|
||||||
|
"Version: %s\r\n"
|
||||||
|
"Protocol: plex\r\n"
|
||||||
|
"Protocol-Version: 1\r\n"
|
||||||
|
"Protocol-Capabilities: timeline,playback,navigation,"
|
||||||
|
"mirror,playqueues\r\n"
|
||||||
|
"Device-Class: HTPC"
|
||||||
|
) % (
|
||||||
|
settings['uuid'],
|
||||||
|
settings['client_name'],
|
||||||
|
settings['myport'],
|
||||||
|
settings['addonName'],
|
||||||
|
settings['version']
|
||||||
|
)
|
||||||
|
self.client_id = settings['uuid']
|
||||||
|
|
||||||
def getClientDetails(self):
|
def getClientDetails(self):
|
||||||
if not self.client_data:
|
if not self.client_data:
|
||||||
self.__printDebug("Client data has not been initialised. Please use PlexGDM.clientDetails()")
|
self.logMsg("Client data has not been initialised. Please use "
|
||||||
|
"PlexGDM.clientDetails()", -1)
|
||||||
|
|
||||||
return self.client_data
|
return self.client_data
|
||||||
|
|
||||||
def client_update (self):
|
def client_update(self):
|
||||||
update_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
update_sock = socket.socket(socket.AF_INET,
|
||||||
|
socket.SOCK_DGRAM,
|
||||||
|
socket.IPPROTO_UDP)
|
||||||
|
|
||||||
#Set socket reuse, may not work on all OSs.
|
# Set socket reuse, may not work on all OSs.
|
||||||
try:
|
try:
|
||||||
update_sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
|
update_sock.setsockopt(socket.SOL_SOCKET,
|
||||||
|
socket.SO_REUSEADDR,
|
||||||
|
1)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
#Attempt to bind to the socket to recieve and send data. If we can;t do this, then we cannot send registration
|
# Attempt to bind to the socket to recieve and send data. If we cant
|
||||||
|
# do this, then we cannot send registration
|
||||||
try:
|
try:
|
||||||
update_sock.bind(('0.0.0.0',self.client_update_port))
|
update_sock.bind(('0.0.0.0', self.client_update_port))
|
||||||
except:
|
except:
|
||||||
self.__printDebug( "Error: Unable to bind to port [%s] - client will not be registered" % self.client_update_port, 0)
|
self.logMsg("Unable to bind to port [%s] - client will not be "
|
||||||
|
"registered" % self.client_update_port, -1)
|
||||||
return
|
return
|
||||||
|
|
||||||
update_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
|
update_sock.setsockopt(socket.IPPROTO_IP,
|
||||||
status = update_sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(self._multicast_address) + socket.inet_aton('0.0.0.0'))
|
socket.IP_MULTICAST_TTL,
|
||||||
|
255)
|
||||||
|
update_sock.setsockopt(socket.IPPROTO_IP,
|
||||||
|
socket.IP_ADD_MEMBERSHIP,
|
||||||
|
socket.inet_aton(
|
||||||
|
self._multicast_address) +
|
||||||
|
socket.inet_aton('0.0.0.0'))
|
||||||
update_sock.setblocking(0)
|
update_sock.setblocking(0)
|
||||||
self.__printDebug("Sending registration data: HELLO %s\r\n%s" % (self.client_header, self.client_data), 3)
|
self.logMsg("Sending registration data: HELLO %s\r\n%s"
|
||||||
|
% (self.client_header, self.client_data), 2)
|
||||||
|
|
||||||
#Send initial client registration
|
# Send initial client registration
|
||||||
try:
|
try:
|
||||||
update_sock.sendto("HELLO %s\r\n%s" % (self.client_header, self.client_data), self.client_register_group)
|
update_sock.sendto("HELLO %s\r\n%s"
|
||||||
|
% (self.client_header, self.client_data),
|
||||||
|
self.client_register_group)
|
||||||
except:
|
except:
|
||||||
self.__printDebug( "Error: Unable to send registeration message" , 0)
|
self.logMsg("Unable to send registration message", -1)
|
||||||
|
|
||||||
#Now, listen for client discovery reguests and respond.
|
# Now, listen for client discovery reguests and respond.
|
||||||
while self._registration_is_running:
|
while self._registration_is_running:
|
||||||
try:
|
try:
|
||||||
data, addr = update_sock.recvfrom(1024)
|
data, addr = update_sock.recvfrom(1024)
|
||||||
self.__printDebug("Recieved UDP packet from [%s] containing [%s]" % (addr, data.strip()), 3)
|
self.logMsg("Recieved UDP packet from [%s] containing [%s]"
|
||||||
except socket.error, e:
|
% (addr, data.strip()), 2)
|
||||||
|
except socket.error:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if "M-SEARCH * HTTP/1." in data:
|
if "M-SEARCH * HTTP/1." in data:
|
||||||
self.__printDebug("Detected client discovery request from %s. Replying" % ( addr ,) , 2)
|
self.logMsg("Detected client discovery request from %s. "
|
||||||
|
" Replying" % addr, 2)
|
||||||
try:
|
try:
|
||||||
update_sock.sendto("HTTP/1.0 200 OK\r\n%s" % self.client_data, addr)
|
update_sock.sendto("HTTP/1.0 200 OK\r\n%s"
|
||||||
|
% self.client_data,
|
||||||
|
addr)
|
||||||
except:
|
except:
|
||||||
self.__printDebug( "Error: Unable to send client update message",0)
|
self.logMsg("Unable to send client update message", -1)
|
||||||
|
|
||||||
self.__printDebug("Sending registration data: HTTP/1.0 200 OK\r\n%s" % (self.client_data), 3)
|
self.logMsg("Sending registration data: HTTP/1.0 200 OK"
|
||||||
|
"\r\n%s" % self.client_data, 2)
|
||||||
self.client_registered = True
|
self.client_registered = True
|
||||||
xbmc.sleep(500)
|
sleep(500)
|
||||||
|
|
||||||
self.__printDebug("Client Update loop stopped",1)
|
self.logMsg("Client Update loop stopped", 1)
|
||||||
|
|
||||||
#When we are finished, then send a final goodbye message to deregister cleanly.
|
# When we are finished, then send a final goodbye message to
|
||||||
self.__printDebug("Sending registration data: BYE %s\r\n%s" % (self.client_header, self.client_data), 3)
|
# deregister cleanly.
|
||||||
|
self.logMsg("Sending registration data: BYE %s\r\n%s"
|
||||||
|
% (self.client_header, self.client_data), 2)
|
||||||
try:
|
try:
|
||||||
update_sock.sendto("BYE %s\r\n%s" % (self.client_header, self.client_data), self.client_register_group)
|
update_sock.sendto("BYE %s\r\n%s"
|
||||||
|
% (self.client_header, self.client_data),
|
||||||
|
self.client_register_group)
|
||||||
except:
|
except:
|
||||||
self.__printDebug( "Error: Unable to send client update message" ,0)
|
self.logMsg("Unable to send client update message", -1)
|
||||||
|
|
||||||
self.client_registered = False
|
self.client_registered = False
|
||||||
|
|
||||||
|
@ -140,7 +175,7 @@ class plexgdm:
|
||||||
if self.client_registered and self.discovery_complete:
|
if self.client_registered and self.discovery_complete:
|
||||||
|
|
||||||
if not self.server_list:
|
if not self.server_list:
|
||||||
self.__printDebug("Server list is empty. Unable to check",2)
|
self.logMsg("Server list is empty. Unable to check", 1)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -151,34 +186,33 @@ class plexgdm:
|
||||||
scheme = server['protocol']
|
scheme = server['protocol']
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.__printDebug("Did not find our server!", 2)
|
self.logMsg("Did not find our server!", 0)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.__printDebug("Checking server [%s] on port [%s]" % (media_server, media_port) ,2)
|
self.logMsg("Checking server [%s] on port [%s]"
|
||||||
|
% (media_server, media_port), 2)
|
||||||
client_result = self.download(
|
client_result = self.download(
|
||||||
'%s://%s:%s/clients' % (scheme, media_server, media_port))
|
'%s://%s:%s/clients' % (scheme, media_server, media_port))
|
||||||
# f = urllib2.urlopen('http://%s:%s/clients' % (media_server, media_port))
|
|
||||||
# client_result = f.read()
|
|
||||||
registered = False
|
registered = False
|
||||||
for client in client_result:
|
for client in client_result:
|
||||||
if (client.attrib.get('machineIdentifier') ==
|
if (client.attrib.get('machineIdentifier') ==
|
||||||
self.client_id):
|
self.client_id):
|
||||||
registered = True
|
registered = True
|
||||||
if registered:
|
if registered:
|
||||||
self.__printDebug("Client registration successful",1)
|
self.logMsg("Client registration successful", 1)
|
||||||
self.__printDebug("Client data is: %s" % client_result, 3)
|
self.logMsg("Client data is: %s" % client_result, 2)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
self.__printDebug("Client registration not found",1)
|
self.logMsg("Client registration not found", 1)
|
||||||
self.__printDebug("Client data is: %s" % client_result, 3)
|
self.logMsg("Client data is: %s" % client_result, 1)
|
||||||
|
|
||||||
except:
|
except:
|
||||||
self.__printDebug("Unable to check status")
|
self.logMsg("Unable to check status", 0)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def getServerList (self):
|
def getServerList(self):
|
||||||
return self.server_list
|
return self.server_list
|
||||||
|
|
||||||
def discover(self):
|
def discover(self):
|
||||||
|
@ -194,17 +228,18 @@ class plexgdm:
|
||||||
returnData = []
|
returnData = []
|
||||||
try:
|
try:
|
||||||
# Send data to the multicast group
|
# Send data to the multicast group
|
||||||
self.__printDebug("Sending discovery messages: %s" % self.discover_message, 2)
|
self.logMsg("Sending discovery messages: %s"
|
||||||
sent = sock.sendto(self.discover_message, self.discover_group)
|
% self.discover_message, 2)
|
||||||
|
sock.sendto(self.discover_message, self.discover_group)
|
||||||
|
|
||||||
# Look for responses from all recipients
|
# Look for responses from all recipients
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
data, server = sock.recvfrom(1024)
|
data, server = sock.recvfrom(1024)
|
||||||
self.__printDebug("Received data from %s, %s" % server, 3)
|
self.logMsg("Received data from %s, %s" % server, 2)
|
||||||
self.__printDebug("Data received is:\r\n %s" % data, 3)
|
self.logMsg("Data received is:\r\n %s" % data, 2)
|
||||||
returnData.append( { 'from' : server,
|
returnData.append({'from': server,
|
||||||
'data' : data } )
|
'data': data})
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
|
@ -221,18 +256,16 @@ class plexgdm:
|
||||||
if returnData:
|
if returnData:
|
||||||
|
|
||||||
for response in returnData:
|
for response in returnData:
|
||||||
update = { 'server' : response.get('from')[0] }
|
update = {'server': response.get('from')[0]}
|
||||||
|
|
||||||
#Check if we had a positive HTTP response
|
# Check if we had a positive HTTP reponse
|
||||||
if "200 OK" in response.get('data'):
|
if "200 OK" in response.get('data'):
|
||||||
|
|
||||||
for each in response.get('data').split('\r\n'):
|
for each in response.get('data').split('\r\n'):
|
||||||
update['discovery'] = "auto"
|
update['discovery'] = "auto"
|
||||||
update['owned']='1'
|
update['owned'] = '1'
|
||||||
update['master']= 1
|
update['master'] = 1
|
||||||
update['role']='master'
|
update['role'] = 'master'
|
||||||
update['class']=None
|
update['class'] = None
|
||||||
|
|
||||||
if "Content-Type:" in each:
|
if "Content-Type:" in each:
|
||||||
update['content-type'] = each.split(':')[1].strip()
|
update['content-type'] = each.split(':')[1].strip()
|
||||||
elif "Resource-Identifier:" in each:
|
elif "Resource-Identifier:" in each:
|
||||||
|
@ -291,12 +324,12 @@ class plexgdm:
|
||||||
self.server_list = discovered_servers
|
self.server_list = discovered_servers
|
||||||
|
|
||||||
if not self.server_list:
|
if not self.server_list:
|
||||||
self.__printDebug("No servers have been discovered",1)
|
self.logMsg("No servers have been discovered", 0)
|
||||||
else:
|
else:
|
||||||
self.__printDebug("Number of servers Discovered: %s" % len(self.server_list),1)
|
self.logMsg("Number of servers Discovered: %s"
|
||||||
|
% len(self.server_list), 2)
|
||||||
for items in self.server_list:
|
for items in self.server_list:
|
||||||
self.__printDebug("Server Discovered: %s" % items, 2)
|
self.logMsg("Server Discovered: %s" % items, 2)
|
||||||
|
|
||||||
|
|
||||||
def setInterval(self, interval):
|
def setInterval(self, interval):
|
||||||
self.discovery_interval = interval
|
self.discovery_interval = interval
|
||||||
|
@ -307,71 +340,54 @@ class plexgdm:
|
||||||
|
|
||||||
def stop_discovery(self):
|
def stop_discovery(self):
|
||||||
if self._discovery_is_running:
|
if self._discovery_is_running:
|
||||||
self.__printDebug("Discovery shutting down", 1)
|
self.logMsg("Discovery shutting down", 0)
|
||||||
self._discovery_is_running = False
|
self._discovery_is_running = False
|
||||||
self.discover_t.join()
|
self.discover_t.join()
|
||||||
del self.discover_t
|
del self.discover_t
|
||||||
else:
|
else:
|
||||||
self.__printDebug("Discovery not running", 1)
|
self.logMsg("Discovery not running", 0)
|
||||||
|
|
||||||
def stop_registration(self):
|
def stop_registration(self):
|
||||||
if self._registration_is_running:
|
if self._registration_is_running:
|
||||||
self.__printDebug("Registration shutting down", 1)
|
self.logMsg("Registration shutting down", 0)
|
||||||
self._registration_is_running = False
|
self._registration_is_running = False
|
||||||
self.register_t.join()
|
self.register_t.join()
|
||||||
del self.register_t
|
del self.register_t
|
||||||
else:
|
else:
|
||||||
self.__printDebug("Registration not running", 1)
|
self.logMsg("Registration not running", 0)
|
||||||
|
|
||||||
def run_discovery_loop(self):
|
def run_discovery_loop(self):
|
||||||
#Run initial discovery
|
# Run initial discovery
|
||||||
self.discover()
|
self.discover()
|
||||||
|
|
||||||
discovery_count=0
|
discovery_count = 0
|
||||||
while self._discovery_is_running:
|
while self._discovery_is_running:
|
||||||
discovery_count+=1
|
discovery_count += 1
|
||||||
if discovery_count > self.discovery_interval:
|
if discovery_count > self.discovery_interval:
|
||||||
self.discover()
|
self.discover()
|
||||||
discovery_count=0
|
discovery_count = 0
|
||||||
xbmc.sleep(500)
|
sleep(500)
|
||||||
|
|
||||||
def start_discovery(self, daemon = False):
|
def start_discovery(self, daemon=False):
|
||||||
if not self._discovery_is_running:
|
if not self._discovery_is_running:
|
||||||
self.__printDebug("Discovery starting up", 1)
|
self.logMsg("Discovery starting up", 0)
|
||||||
self._discovery_is_running = True
|
self._discovery_is_running = True
|
||||||
self.discover_t = threading.Thread(target=self.run_discovery_loop)
|
self.discover_t = threading.Thread(target=self.run_discovery_loop)
|
||||||
self.discover_t.setDaemon(daemon)
|
self.discover_t.setDaemon(daemon)
|
||||||
self.discover_t.start()
|
self.discover_t.start()
|
||||||
else:
|
else:
|
||||||
self.__printDebug("Discovery already running", 1)
|
self.logMsg("Discovery already running", 0)
|
||||||
|
|
||||||
def start_registration(self, daemon = False):
|
def start_registration(self, daemon=False):
|
||||||
if not self._registration_is_running:
|
if not self._registration_is_running:
|
||||||
self.__printDebug("Registration starting up", 1)
|
self.logMsg("Registration starting up", 0)
|
||||||
self._registration_is_running = True
|
self._registration_is_running = True
|
||||||
self.register_t = threading.Thread(target=self.client_update)
|
self.register_t = threading.Thread(target=self.client_update)
|
||||||
self.register_t.setDaemon(daemon)
|
self.register_t.setDaemon(daemon)
|
||||||
self.register_t.start()
|
self.register_t.start()
|
||||||
else:
|
else:
|
||||||
self.__printDebug("Registration already running", 1)
|
self.logMsg("Registration already running", 0)
|
||||||
|
|
||||||
def start_all(self, daemon = False):
|
def start_all(self, daemon=False):
|
||||||
self.start_discovery(daemon)
|
self.start_discovery(daemon)
|
||||||
self.start_registration(daemon)
|
self.start_registration(daemon)
|
||||||
|
|
||||||
|
|
||||||
#Example usage
|
|
||||||
if __name__ == '__main__':
|
|
||||||
client = plexgdm(debug=3)
|
|
||||||
client.clientDetails("Test-Name", "Test Client", "3003", "Test-App", "1.2.3")
|
|
||||||
client.start_all()
|
|
||||||
while not client.discovery_complete:
|
|
||||||
print "Waiting for results"
|
|
||||||
xbmc.sleep(1000)
|
|
||||||
xbmc.sleep(20000)
|
|
||||||
print client.getServerList()
|
|
||||||
if client.check_client_registration():
|
|
||||||
print "Successfully registered"
|
|
||||||
else:
|
|
||||||
print "Unsuccessfully registered"
|
|
||||||
client.stop_all()
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import xbmcaddon
|
from utils import guisettingsXML, settings, logMsg
|
||||||
import utils
|
import clientinfo
|
||||||
|
|
||||||
|
|
||||||
def getGUI(name):
|
def getGUI(name):
|
||||||
guisettingsXML = utils.guisettingsXML()
|
xml = guisettingsXML()
|
||||||
try:
|
try:
|
||||||
ans = list(guisettingsXML.iter(name))[0].text
|
ans = list(xml.iter(name))[0].text
|
||||||
if ans is None:
|
if ans is None:
|
||||||
ans = ''
|
ans = ''
|
||||||
except:
|
except:
|
||||||
|
@ -14,33 +14,45 @@ def getGUI(name):
|
||||||
|
|
||||||
|
|
||||||
def getSettings():
|
def getSettings():
|
||||||
settings = {}
|
client = clientinfo.ClientInfo()
|
||||||
addon = xbmcaddon.Addon()
|
options = {}
|
||||||
plexbmc = xbmcaddon.Addon('plugin.video.plexkodiconnect')
|
title = 'PlexCompanion Settings'
|
||||||
|
|
||||||
settings['debug'] = utils.settings('companionDebugging')
|
options['gdm_debug'] = settings('companionGDMDebugging')
|
||||||
settings['gdm_debug'] = utils.settings('companionGDMDebugging')
|
options['gdm_debug'] = True if options['gdm_debug'] == 'true' else False
|
||||||
|
|
||||||
# Transform 'true' into True because of the way Kodi's file settings work
|
options['client_name'] = settings('deviceName')
|
||||||
kodiSettingsList = ['debug', 'gdm_debug']
|
|
||||||
for entry in kodiSettingsList:
|
|
||||||
if settings[entry] == 'true':
|
|
||||||
settings[entry] = True
|
|
||||||
else:
|
|
||||||
settings[entry] = False
|
|
||||||
|
|
||||||
settings['client_name'] = plexbmc.getSetting('deviceName')
|
# XBMC web server options
|
||||||
|
options['webserver_enabled'] = (getGUI('webserver') == "true")
|
||||||
|
logMsg(title, 'Webserver is set to %s' % options['webserver_enabled'], 0)
|
||||||
|
webserverport = getGUI('webserverport')
|
||||||
|
try:
|
||||||
|
webserverport = int(webserverport)
|
||||||
|
logMsg(title, 'Using webserver port %s' % str(webserverport), 0)
|
||||||
|
except:
|
||||||
|
logMsg(title, 'No setting for webserver port found in guisettings.xml.'
|
||||||
|
'Using default fallback port 8080', 0)
|
||||||
|
webserverport = 8080
|
||||||
|
options['port'] = webserverport
|
||||||
|
|
||||||
# XBMC web server settings
|
options['user'] = getGUI('webserverusername')
|
||||||
settings['webserver_enabled'] = (getGUI('webserver') == "true")
|
options['passwd'] = getGUI('webserverpassword')
|
||||||
settings['port'] = int(getGUI('webserverport'))
|
logMsg(title, 'Webserver username: %s, password: %s'
|
||||||
settings['user'] = getGUI('webserverusername')
|
% (options['user'], options['passwd']), 1)
|
||||||
settings['passwd'] = getGUI('webserverpassword')
|
|
||||||
|
|
||||||
settings['uuid'] = plexbmc.getSetting('plex_client_Id')
|
options['addonName'] = client.getAddonName()
|
||||||
|
options['uuid'] = settings('plex_client_Id')
|
||||||
settings['version'] = plexbmc.getAddonInfo('version')
|
options['platform'] = client.getPlatform()
|
||||||
settings['plexbmc_version'] = plexbmc.getAddonInfo('version')
|
options['version'] = client.getVersion()
|
||||||
settings['myplex_user'] = plexbmc.getSetting('username')
|
options['plexbmc_version'] = options['version']
|
||||||
settings['myport'] = addon.getSetting('companionPort')
|
options['myplex_user'] = settings('username')
|
||||||
return settings
|
try:
|
||||||
|
options['myport'] = int(settings('companionPort'))
|
||||||
|
logMsg(title, 'Using Plex Companion Port %s'
|
||||||
|
% str(options['myport']), 0)
|
||||||
|
except:
|
||||||
|
logMsg(title, 'Error getting Plex Companion Port from file settings. '
|
||||||
|
'Using fallback port 39005', -1)
|
||||||
|
options['myport'] = 39005
|
||||||
|
return options
|
||||||
|
|
|
@ -43,8 +43,6 @@
|
||||||
<setting id="deviceNameOpt" label="30504" type="bool" default="false" />
|
<setting id="deviceNameOpt" label="30504" type="bool" default="false" />
|
||||||
<setting id="deviceName" label="30016" type="text" visible="eq(-1,true)" default="Kodi" />
|
<setting id="deviceName" label="30016" type="text" visible="eq(-1,true)" default="Kodi" />
|
||||||
<setting id="companionPort" label="39005" type="number" default="3005" option="int" visible="eq(-3,true)"/>
|
<setting id="companionPort" label="39005" type="number" default="3005" option="int" visible="eq(-3,true)"/>
|
||||||
<setting id="companionDebugging" label="39006" type="bool" default="false" visible="eq(-4,true)"/>
|
|
||||||
<setting id="companionGDMDebugging" label="39007" type="bool" default="false" visible="eq(-5,true)"/>
|
|
||||||
</category>
|
</category>
|
||||||
<category label="30506"><!-- Sync Options -->
|
<category label="30506"><!-- Sync Options -->
|
||||||
<setting type="lsep" label="30537" /><!-- Restart if you make changes -->
|
<setting type="lsep" label="30537" /><!-- Restart if you make changes -->
|
||||||
|
|
Loading…
Reference in a new issue