def get_pulsar_binary(): binary = "pulsar" + (PLATFORM["os"] == "windows" and ".exe" or "") platform = PLATFORM.copy() if platform["os"] == "darwin": # 64 bits anyway on Darwin platform["arch"] = "x64" elif platform["os"] == "windows": # 32 bits anyway on Windows platform["arch"] = "x86" binary_dir = os.path.join(ADDON.getAddonInfo("path"), "resources", "bin", "%(os)s_%(arch)s" % platform) if platform["os"] == "android": app_id = android_get_current_appid() xbmc_data_path = os.path.join("/data", "data", app_id) if os.path.exists(xbmc_data_path) and uid == os.stat(xbmc_data_path).st_uid: binary_dir = os.path.join(xbmc_data_path, "files", ADDON_ID) else: dest_binary_dir = os.path.join(xbmc.translatePath(ADDON.getAddonInfo("profile")), "bin", "%(os)s_%(arch)s" % platform) binary_path = os.path.join(binary_dir, binary) dest_binary_path = os.path.join(dest_binary_dir, binary) # Testing for size to see if update is needed. This is a poor test indeed, but it's sufficient. if not os.path.exists(dest_binary_path) or os.path.getsize(dest_binary_path) != os.path.getsize(binary_path): log.info("pulsar daemon is outdated, updating...") import shutil try: os.makedirs(dest_binary_dir) except OSError: pass shutil.rmtree(dest_binary_dir) shutil.copytree(binary_dir, dest_binary_dir) return dest_binary_dir, ensure_exec_perms(dest_binary_path)
def get_pulsar_binary(): binary = "pulsar" + (PLATFORM["os"] == "windows" and ".exe" or "") platform = PLATFORM.copy() if platform["os"] == "darwin": # 64 bits anyway on Darwin platform["arch"] = "x64" elif platform["os"] == "windows": # 32 bits anyway on Windows platform["arch"] = "x86" binary_dir = os.path.join(ADDON.getAddonInfo("path"), "resources", "bin", "%(os)s_%(arch)s" % platform) if platform["os"] == "android": app_id = android_get_current_appid() xbmc_data_path = os.path.join("/data", "data", app_id) dest_binary_dir = os.path.join(xbmc_data_path, "files", ADDON_ID, "bin", "%(os)s_%(arch)s" % platform) else: dest_binary_dir = os.path.join(xbmc.translatePath(ADDON.getAddonInfo("profile")), "bin", "%(os)s_%(arch)s" % platform) binary_path = os.path.join(binary_dir, binary) dest_binary_path = os.path.join(dest_binary_dir, binary) if not os.path.exists(dest_binary_path) or get_pulsard_checksum(dest_binary_path) != get_pulsard_checksum(binary_path): log.info("Updating pulsar daemon...") import shutil try: os.makedirs(dest_binary_dir) except OSError: pass try: shutil.rmtree(dest_binary_dir) except: pass shutil.copytree(binary_dir, dest_binary_dir) return dest_binary_dir, ensure_exec_perms(dest_binary_path)
def pulsard_thread(): while not xbmc.abortRequested: log.info("pulsard: starting pulsard") proc = start_pulsard(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) threading.Thread(target=wait_for_abortRequested, args=[proc]).start() while proc.poll() is None: log.info(proc.stdout.readline()) if proc.returncode == 0 or xbmc.abortRequested: break notify("Pulsar has crashed, restarting...", time=1000)
def server_thread(): try: s = bjsonrpc.createserver(port=JSONRPC_EXT_PORT, handler_factory=PulsarRPCServer) log.info("pulsar: starting jsonrpc service") s.serve() log.info("pulsar: exiting jsonrpc service") except Exception, e: import traceback map(log.info, traceback.format_exc().split("\n")) raise
def server_thread(): import xbmc import bjsonrpc try: s = bjsonrpc.createserver(port=JSONRPC_EXT_PORT, handler_factory=PulsarRPCServer) s._do_serve = lambda: (not xbmc.abortRequested) log.info("pulsar: starting jsonrpc service") s.serve() log.info("pulsar: exiting jsonrpc service") except Exception, e: import traceback map(log.info, traceback.format_exc().split("\n")) raise
def pulsard_thread(monitor): try: import xbmc while not xbmc.abortRequested: log.info("pulsard: starting pulsard") proc = start_pulsard(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) threading.Thread(target=wait_for_abortRequested, args=[proc, monitor]).start() while proc.poll() is None: log.info(proc.stdout.readline()) if proc.returncode == 0 or xbmc.abortRequested: break notify("Pulsar has crashed, restarting...", time=1000) except Exception, e: import xbmc import traceback map(xbmc.log, traceback.format_exc().split("\n")) raise
def main(): # Make sure the XBMC jsonrpc server is started. xbmc.startServer(xbmc.SERVER_JSONRPCSERVER, True) # Start the JSONRPC thread threading.Thread(target=server_thread).start() # Start the Pulsard thread threading.Thread(target=pulsard_thread).start() # Get the monitor monitor = PulsarMonitor() # XBMC loop while not xbmc.abortRequested: xbmc.sleep(4000) log.info("pulsar: exiting pulsard")
def run(): # Make sure the XBMC jsonrpc server is started. xbmc.startServer(xbmc.SERVER_JSONRPCSERVER, True) # Make the monitor monitor = PulsarMonitor() threads = [ threading.Thread(target=server_thread), # JSONRPC thread threading.Thread(target=pulsard_thread, args=[monitor]), # Pulsard thread ] for t in threads: t.daemon = True t.start() # XBMC loop while not xbmc.abortRequested: xbmc.sleep(1000) log.info("pulsar: exiting pulsard")
def pulsard_thread(monitor): try: import xbmc while not xbmc.abortRequested: log.info("pulsard: starting pulsard") proc = start_pulsard(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) threading.Thread(target=wait_for_abortRequested, args=[proc, monitor]).start() if PLATFORM["os"] == "windows": while proc.poll() is None: log.info(proc.stdout.readline()) else: # Kodi hangs on some Android (sigh...) systems when doing a blocking # read. We count on the fact that Pulsar daemon flushes its log # output on \n, creating a pretty clean output import fcntl fd = proc.stdout.fileno() fl = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) while proc.poll() is None: try: log.info(proc.stdout.readline()) continue except IOError: time.sleep(1) # nothing to read, sleep if proc.returncode == 0 or xbmc.abortRequested: break notify("Pulsar has crashed, restarting...", time=1000) except Exception, e: import xbmc import traceback map(xbmc.log, traceback.format_exc().split("\n")) raise
def get_pulsar_binary(): binary = "pulsar" + (PLATFORM["os"] == "windows" and ".exe" or "") platform = PLATFORM.copy() if platform["os"] == "darwin": # 64 bits anyway on Darwin platform["arch"] = "x64" elif platform["os"] == "windows": # 32 bits anyway on Windows platform["arch"] = "x86" binary_dir = os.path.join(ADDON.getAddonInfo("path"), "resources", "bin", "%(os)s_%(arch)s" % platform) if platform["os"] == "android": binary_dir = binary_dir.replace("/storage/emulated/0", "/storage/emulated/legacy") app_id = android_get_current_appid() xbmc_data_path = os.path.join("/data", "data", app_id) dest_binary_dir = os.path.join(xbmc_data_path, "files", ADDON_ID, "bin", "%(os)s_%(arch)s" % platform) else: dest_binary_dir = os.path.join( xbmc.translatePath(ADDON.getAddonInfo("profile")), "bin", "%(os)s_%(arch)s" % platform) try: binary_dir = binary_dir.decode("latin1") dest_binary_dir = dest_binary_dir.decode("latin1") except UnicodeEncodeError: log.info("Unable to decode: binary_dir=%s dest_binary_dir=%s" % (repr(binary_dir), repr(dest_binary_dir))) binary_path = os.path.join(binary_dir, binary) dest_binary_path = os.path.join(dest_binary_dir, binary) if not os.path.exists(dest_binary_path) or get_pulsard_checksum( dest_binary_path) != get_pulsard_checksum(binary_path): log.info("Updating pulsar daemon...") try: os.makedirs(dest_binary_dir) except OSError: pass try: shutil.rmtree(dest_binary_dir) except: pass shutil.copytree(binary_dir, dest_binary_dir) # Clean stale files in the directory, as this can cause headaches on # Android when they are unreachable dest_files = set(os.listdir(dest_binary_dir)) orig_files = set(os.listdir(binary_dir)) log.info("Deleting stale files %s" % (dest_files - orig_files)) for file_ in (dest_files - orig_files): path = os.path.join(dest_binary_dir, file_) if os.path.isdir(path): shutil.rmtree(path) else: os.remove(path) return dest_binary_dir, ensure_exec_perms(dest_binary_path)
def get_pulsar_binary(): binary = "pulsar" + (PLATFORM["os"] == "windows" and ".exe" or "") platform = PLATFORM.copy() if platform["os"] == "darwin": # 64 bits anyway on Darwin platform["arch"] = "x64" elif platform["os"] == "windows": # 32 bits anyway on Windows platform["arch"] = "x86" binary_dir = os.path.join(ADDON.getAddonInfo("path"), "resources", "bin", "%(os)s_%(arch)s" % platform) if platform["os"] == "android": app_id = android_get_current_appid() xbmc_data_path = os.path.join("/data", "data", app_id) if os.path.exists(xbmc_data_path) and uid == os.stat( xbmc_data_path).st_uid: binary_dir = os.path.join(xbmc_data_path, "files", ADDON_ID) else: dest_binary_dir = os.path.join( xbmc.translatePath(ADDON.getAddonInfo("profile")), "bin", "%(os)s_%(arch)s" % platform) binary_path = os.path.join(binary_dir, binary) dest_binary_path = os.path.join(dest_binary_dir, binary) # Testing for size to see if update is needed. This is a poor test indeed, but it's sufficient. if not os.path.exists(dest_binary_path) or os.path.getsize( dest_binary_path) != os.path.getsize(binary_path): log.info("pulsar daemon is outdated, updating...") import shutil try: os.makedirs(dest_binary_dir) except OSError: pass shutil.rmtree(dest_binary_dir) shutil.copytree(binary_dir, dest_binary_dir) return dest_binary_dir, ensure_exec_perms(dest_binary_path)
def get_pulsar_binary(): binary = "pulsar" + (PLATFORM["os"] == "windows" and ".exe" or "") platform = PLATFORM.copy() if platform["os"] == "darwin": # 64 bits anyway on Darwin platform["arch"] = "x64" elif platform["os"] == "windows": # 32 bits anyway on Windows platform["arch"] = "x86" binary_dir = os.path.join(ADDON.getAddonInfo("path"), "resources", "bin", "%(os)s_%(arch)s" % platform) if platform["os"] == "android": binary_dir = binary_dir.replace("/storage/emulated/0", "/storage/emulated/legacy") app_id = android_get_current_appid() xbmc_data_path = os.path.join("/data", "data", app_id) dest_binary_dir = os.path.join(xbmc_data_path, "files", ADDON_ID, "bin", "%(os)s_%(arch)s" % platform) else: dest_binary_dir = os.path.join(xbmc.translatePath(ADDON.getAddonInfo("profile")), "bin", "%(os)s_%(arch)s" % platform) try: binary_dir = binary_dir.decode("latin1") dest_binary_dir = dest_binary_dir.decode("latin1") except UnicodeEncodeError: log.info("Unable to decode: binary_dir=%s dest_binary_dir=%s" % (repr(binary_dir), repr(dest_binary_dir))) binary_path = os.path.join(binary_dir, binary) dest_binary_path = os.path.join(dest_binary_dir, binary) if not os.path.exists(dest_binary_path) or get_pulsard_checksum(dest_binary_path) != get_pulsard_checksum(binary_path): log.info("Updating pulsar daemon...") try: os.makedirs(dest_binary_dir) except OSError: pass try: shutil.rmtree(dest_binary_dir) except: pass shutil.copytree(binary_dir, dest_binary_dir) # Clean stale files in the directory, as this can cause headaches on # Android when they are unreachable dest_files = set(os.listdir(dest_binary_dir)) orig_files = set(os.listdir(binary_dir)) log.info("Deleting stale files %s" % (dest_files - orig_files)) for file_ in (dest_files - orig_files): path = os.path.join(dest_binary_dir, file_) if os.path.isdir(path): shutil.rmtree(path) else: os.remove(path) return dest_binary_dir, ensure_exec_perms(dest_binary_path)
def wait_for_abortRequested(proc, monitor): monitor.closing.wait() log.info("pulsard: exiting pulsard daemon") proc.terminate() log.info("pulsard: pulsard daemon exited")
def wait_for_abortRequested(proc): while not xbmc.abortRequested: time.sleep(1) log.info("pulsard: exiting pulsard daemon") proc.terminate() log.info("pulsard: pulsard daemon exited")