def dump_version(): try: p = platform.platform() except: p = "Could not detect" log.info("""Python version: %s dist: %s linux_distribution: %s system: %s machine: %s platform: %s uname: %s version: %s mac_ver: %s """ % ( sys.version.split('\n'), str(platform.dist()), linux_distribution(), platform.system(), platform.machine(), p, platform.uname(), platform.version(), platform.mac_ver(), ))
def run(): # Make sure the XBMC jsonrpc server is started. xbmc.startServer(xbmc.SERVER_JSONRPCSERVER, True) # Make the monitor monitor = ElementumMonitor() threads = [ threading.Thread(target=server_thread), # JSONRPC thread ] if not ONLY_CLIENT and PLATFORM["fork"]: threads.append( threading.Thread(target=elementumd_thread, args=[monitor])) # Elementumd thread for t in threads: t.daemon = True t.start() # XBMC loop while not monitor.abortRequested(): xbmc.sleep(1000) if PLATFORM['kodi'] >= 19: monitor.onAbortRequested() log.info("elementum: exiting elementumd")
def run(): # Make sure the XBMC jsonrpc server is started. xbmc.startServer(xbmc.SERVER_JSONRPCSERVER, True) # Make the monitor monitor = ElementumMonitor() threads = [ threading.Thread(target=server_thread), # JSONRPC thread ] if not ONLY_CLIENT: sys.stderr.write("elementum: ONLY " + str(ONLY_CLIENT)) threads.append( threading.Thread(target=elementumd_thread, args=[monitor])) # Elementumd thread for t in threads: t.daemon = True t.start() # XBMC loop while not xbmc.abortRequested: xbmc.sleep(1000) log.info("elementum: exiting elementumd")
def dump_version(ret): try: p = platform.platform() except: p = "Could not detect" try: log.info("""Python version: %s dist: %s linux_distribution: %s system: %s machine: %s platform: %s uname: %s version: %s mac_ver: %s """ % ( sys.version.split('\n'), str(platform.dist()), linux_distribution(), platform.system(), platform.machine(), p, platform.uname(), platform.version(), platform.mac_ver() )) except: if ret is not None: log.info("Cannot write detection info. Ret: %s" % (repr(ret))) pass
def download_github_folder(repo, folder, destination): contents_url = "https://api.github.com/repos/%s/contents/%s" % (repo, folder) log.info("Downloading repo content for folder: %s, to folder: %s" % (contents_url, destination)) try: with requests.get(contents_url) as r: lists = json.loads(r.content, parse_int=str) downloaded = 0 for i in lists: if 'download_url' not in i: continue dest = os.path.join(destination, urllib_parse.unquote(i['download_url'].rsplit('/', 1)[1])) log.info("Downloading file '%s' to '%s'" % (i['download_url'], dest)) with requests.get(i['download_url'], stream=True) as rd: rd.raise_for_status() with open(dest, 'wb') as f: for chunk in rd.iter_content(chunk_size=8192): f.write(chunk) downloaded += 1 return downloaded > 0 except Exception as e: log.error("Could not get list of files from github: %s" % e) raise
def Reset(self): for i in self._objects: try: self._objects[i].hide() except: pass log.info("Resetting RPC objects...") self._objects = {}
def wait_for_abortRequested(proc, monitor): monitor.closing.wait() log.info("elementumd: exiting elementumd daemon") try: proc.terminate() except OSError: pass # Process already exited, nothing to terminate log.info("elementumd: elementumd daemon exited")
def server_thread(): try: s = bjsonrpc.createserver(host="0.0.0.0", port=JSONRPC_EXT_PORT, handler_factory=ElementumRPCServer) log.info("elementum: starting jsonrpc service") s.serve() log.info("elementum: exiting jsonrpc service") except Exception: import traceback map(log.error, traceback.format_exc().split("\n")) raise
def doPlay(): dbid = getDbId() mediatype = getMediaType() xbmcgui.Dialog().notification(ADDON.getLocalizedString(32009), sys.listitem.getLabel(), xbmcgui.NOTIFICATION_INFO, 3000) log.info("Playing for: DBID=%s, MediaType=%s" % (dbid, mediatype)) url = "plugin://plugin.video.elementum/context/%s/%s/play" % (mediatype, dbid) log.info("Starting Elementum with: %s" % url) xbmc.Player().play(url)
def system_information(): build = xbmc.getInfoLabel("System.BuildVersion") log.info("System information: %(os)s_%(arch)s %(version)s" % PLATFORM) log.info("Kodi build version: %s" % build) log.info("OS type: %s" % platform.system()) log.info("uname: %s" % repr(platform.uname())) return PLATFORM
def jsonrpc_enabled(notify=False): try: s = socket.socket() s.connect(('127.0.0.1', 9090)) s.close() log.info("Kodi's JSON-RPC service is available, starting up...") del s return True except Exception as e: log.error(repr(e)) if notify: xbmc.executebuiltin("ActivateWindow(ServiceSettings)") dialog = xbmcgui.Dialog() dialog.ok("Elementum", getLocalizedString(30199)) return False
def doLibraryAction(action): dbid = getDbId() mediatype = getMediaType() heading = ADDON.getLocalizedString( 32017) if action == "add" else "Unsupported action" xbmcgui.Dialog().notification(heading, sys.listitem.getLabel(), xbmcgui.NOTIFICATION_INFO, 3000) log.info("%s library item: DBID=%s, MediaType=%s" % (action, dbid, mediatype)) url = "plugin://plugin.video.elementum/context/library/%s/%s/%s" % ( mediatype, dbid, action) log.info("Starting Elementum with: %s" % url) xbmc.Player().play(url)
def run(): # Make sure the XBMC jsonrpc server is started. xbmc.startServer(xbmc.SERVER_JSONRPCSERVER, True) # Make the monitor monitor = ElementumMonitor() threads = [ threading.Thread(target=server_thread), # JSONRPC thread threading.Thread(target=elementumd_thread, args=[monitor]), # Elementumd thread ] for t in threads: t.daemon = True t.start() # XBMC loop while not xbmc.abortRequested: xbmc.sleep(1000) log.info("elementum: exiting elementumd")
def GetCurrentView(self): skinPath = xbmc.translatePath('special://skin/') xml = os.path.join(skinPath, 'addon.xml') f = xbmcvfs.File(xml) read = f.read() f.close() try: src = re.search('defaultresolution="([^"]+)', read, re.DOTALL).group(1) except: src = re.search('<res.+?folder="([^"]+)', read, re.DOTALL).group(1) src = os.path.join(skinPath, src, 'MyVideoNav.xml') f = xbmcvfs.File(src) read = f.read() f.close() match = re.search('<views>([^<]+)', read, re.DOTALL) if match: views = match.group(1) log.info("Skin's ViewModes: %s" % views) for view in views.split(','): if xbmc.getInfoLabel('Control.GetLabel(%s)' % view): return view
def doPlay(): dbid = getDbId() mediatype = getMediaType() use_elementum_path = False if not dbid.isdigit(): try: path = sys.listitem.getfilename() except AttributeError: path = sys.listitem.getPath() if path.startswith("plugin://plugin.video.elementum"): use_elementum_path = True xbmcgui.Dialog().notification(ADDON.getLocalizedString(32009), sys.listitem.getLabel(), xbmcgui.NOTIFICATION_INFO, 3000) if use_elementum_path: log.info("Playing elementum item: path=%s, MediaType=%s" % (path, mediatype)) if mediatype == 'season': url = re.sub(r'/(episodes)(/?[^/]*)$', r'/links\g<2>', path, count=1) else: url = path else: log.info("Playing library item: DBID=%s, MediaType=%s" % (dbid, mediatype)) url = "plugin://plugin.video.elementum/context/media/%s/%s/play" % ( mediatype, dbid) log.info("Starting Elementum with: %s" % url) xbmc.Player().play(url)
def elementumd_thread(monitor): crash_count = 0 try: while not xbmc.abortRequested: log.info("elementumd: starting elementumd") proc = start_elementumd(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if not proc: break 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 Elementum daemon flushes its log # output on \n, creating a pretty clean output import fcntl import select 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: to_read, _, _ = select.select([proc.stdout], [], []) for ro in to_read: line = ro.readline() if line == "": # write end is closed break log.info(line) except IOError: time.sleep(1) # nothing to read, sleep if proc.returncode == 0 or xbmc.abortRequested: break if proc.returncode == 5: notify(getLocalizedString(30332), time=3000) else: crash_count += 1 notify(getLocalizedString(30100), time=3000) xbmc.executebuiltin("Dialog.Close(all, true)") system_information() time.sleep(5) if crash_count >= 3: notify(getLocalizedString(30110), time=3000) break except Exception as e: import traceback map(log.error, traceback.format_exc().split("\n")) notify("%s: %s" % (getLocalizedString(30226), repr(e).encode('utf-8'))) raise
def doTraktAction(action): dbid = getDbId() mediatype = getMediaType() if action == "watched": heading = ADDON.getLocalizedString(32018) elif action == "unwatched": heading = ADDON.getLocalizedString(32019) else: heading = "Unsupported action" if not dbid.isdigit(): showtmdbid = xbmc.getInfoLabel('ListItem.Property(ShowTMDBId)') try: tmdbID = sys.listitem.getUniqueID('tmdb') except AttributeError: tmdbID = "" if tmdbID == "" or ((mediatype == 'season' or mediatype == 'episode') and showtmdbid == ""): log.error("Could not find TMDB id for %s" % dbid) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007), ADDON.getLocalizedString(32014), xbmcgui.NOTIFICATION_WARNING, 3000) return xbmcgui.Dialog().notification(heading, sys.listitem.getLabel(), xbmcgui.NOTIFICATION_INFO, 3000) if not dbid.isdigit(): log.info("Make %s non-library item: tmdbID=%s, MediaType=%s" % (action, tmdbID, mediatype)) else: log.info("Make %s library item: DBID=%s, MediaType=%s" % (action, dbid, mediatype)) if not dbid.isdigit(): if mediatype == 'movie': url = "plugin://plugin.video.elementum/movie/%s/%s" % (tmdbID, action) if mediatype == 'tvshow': url = "plugin://plugin.video.elementum/show/%s/%s" % (tmdbID, action) elif mediatype == 'season': season = xbmc.getInfoLabel('ListItem.Season') url = "plugin://plugin.video.elementum/show/%s/season/%s/%s" % ( showtmdbid, season, action) elif mediatype == 'episode': season = xbmc.getInfoLabel('ListItem.Season') episode = xbmc.getInfoLabel('ListItem.Episode') url = "plugin://plugin.video.elementum/show/%s/season/%s/episode/%s/%s" % ( showtmdbid, season, episode, action) else: url = "plugin://plugin.video.elementum/context/media/%s/%s/%s" % ( mediatype, dbid, action) log.info("Starting Elementum with: %s" % url) xbmc.Player().play(url)
def elementumd_thread(monitor): restart_count = 0 max_restart = 3 last_code = 0 try: monitor_abort = xbmc.Monitor() # For Kodi >= 14 while not monitor_abort.abortRequested(): # If we ran out of attempts of last exit code was '-9': we do not try to start it again. # So if you kill the binary with '-9': it will not be restarted by this monitor. if restart_count > max_restart or last_code == -9: if monitor.reboot(): log.debug("elementumd: resetting attempts") restart_count = 0 last_code = 0 monitor.reboot(False) else: time.sleep(5) continue log.info("elementumd: starting elementumd") proc = None if hasSubprocess: proc = start_elementumd(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if not proc: break else: log.info( "elementumd: current system is unable to run the binary") break threading.Thread(target=wait_for_abortRequested, args=[proc, monitor]).start() if not hasSubprocess: break if binary_platform["os"] == "windows": while proc.poll() is None: log.info(toUtf8(proc.stdout.readline())) else: # Kodi hangs on some Android (sigh...) systems when doing a blocking # read. We count on the fact that Elementum daemon flushes its log # output on \n, creating a pretty clean output import fcntl import select 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: to_read, _, _ = select.select([proc.stdout], [], []) for ro in to_read: line = ro.readline() if line == "": # write end is closed break try: log.info(toUtf8(line)) except TypeError: pass except IOError: time.sleep(1) # nothing to read, sleep last_code = proc.returncode if monitor_abort.abortRequested(): break if proc.returncode == 0 or proc.returncode == -9 or proc.returncode == -1: continue if proc.returncode == 5: restart_count = 0 notify(getLocalizedString(30332), time=3000) else: restart_count += 1 notify(getLocalizedString(30100), time=3000) xbmc.executebuiltin("Dialog.Close(all, true)") system_information() time.sleep(5) if restart_count >= max_restart: log.debug("elementumd: no attempts left") notify(getLocalizedString(30110), time=3000) continue except Exception as e: import traceback map(log.error, traceback.format_exc().split("\n")) notify("%s: %s" % (getLocalizedString(30226), repr(e).encode('utf-8'))) raise log.debug("elementumd: closing")
def DialogProgressBG_Cleanup(self): log.info("Cleaning up dialogs") for hwnd in self._objects: if isinstance(self._objects[hwnd], xbmcgui.DialogProgressBG): self._objects[hwnd].close()
def get_platform(): try: binary_platform = ADDON.getSetting("binary_platform") except: binary_platform = "auto" pass build = xbmc.getInfoLabel("System.BuildVersion") kodi_version = int(build.split()[0][:2]) if binary_platform and "auto" not in binary_platform.lower(): custom = binary_platform.split('_') if len(custom) > 1: return { "os": custom[0], "arch": custom[1], "fork": True, "version": "", "kodi": kodi_version, "build": build } ret = { "auto_arch": sys.maxsize > 2 ** 32 and "64-bit" or "32-bit", "arch": sys.maxsize > 2 ** 32 and "x64" or "x86", "os": "", "version": "", "kodi": kodi_version, "build": build, "fork": True, "machine": "", "system": "", "platform": "" } try: ret["os"] = platform.release() except: pass try: ret["machine"] = platform.machine() except: # Default 'machine' for Android can be 'arm' if xbmc.getCondVisibility("system.platform.android"): ret["machine"] = "arm" pass try: ret["system"] = platform.system() except: pass try: ret["platform"] = platform.platform() except: pass if xbmc.getCondVisibility("system.platform.android"): ret["os"] = "android" if "arm" in ret["machine"].lower() or "aarch" in ret["machine"].lower(): ret["arch"] = "arm" if "64" in ret["machine"] and ret["auto_arch"] == "64-bit": ret["arch"] = "arm64" elif xbmc.getCondVisibility("system.platform.linux"): ret["os"] = "linux" if "aarch" in ret["machine"].lower() or "arm64" in ret["machine"].lower(): if xbmc.getCondVisibility("system.platform.linux.raspberrypi"): ret["arch"] = "armv7" elif ret["auto_arch"] == "32-bit": ret["arch"] = "armv7" elif ret["auto_arch"] == "64-bit": ret["arch"] = "arm64" # elif platform.architecture()[0].startswith("32"): # ret["arch"] = "armv6" else: ret["arch"] = "armv7" elif "armv7" in ret["machine"]: ret["arch"] = "armv7" elif "arm" in ret["machine"]: cpuarch = "" if "aarch" in ret["machine"].lower() or "arm" in ret["machine"].lower(): info = cpuinfo() for proc in info.keys(): log.info("CPU: %s=%s" % (proc, info[proc])) model = "" if "model name" in info[proc]: model = info[proc]["model name"].lower() elif "Processor" in info[proc]: model = info[proc]["Processor"].lower() if model: log.info("Exploring model: %s" % model) if "aarch" in model or "arm64" in model or "v8l" in model: cpuarch = "arm64" elif "armv7" in model or "v7l" in model: cpuarch = "armv7" break if cpuarch: log.info("Using CPU info arch: %s" % cpuarch) ret["arch"] = cpuarch else: ret["arch"] = "armv6" elif xbmc.getCondVisibility("system.platform.xbox"): ret["os"] = "windows" ret["arch"] = "x64" ret["fork"] = False elif xbmc.getCondVisibility("system.platform.windows"): ret["os"] = "windows" if ret["machine"].endswith('64'): ret["arch"] = "x64" elif ret["system"] == "Darwin": ret["os"] = "darwin" ret["arch"] = "x64" if "AppleTV" in ret["platform"]: ret["os"] = "ios" ret["arch"] = "armv7" ret["fork"] = False if "64bit" in ret["platform"]: ret["arch"] = "arm64" elif xbmc.getCondVisibility("system.platform.ios"): ret["os"] = "ios" ret["arch"] = "armv7" ret["fork"] = False if "64bit" in ret["platform"]: ret["arch"] = "arm64" # elif xbmc.getCondVisibility("system.platform.osx"): # ret["os"] = "darwin" # ret["arch"] = "x64" # elif xbmc.getCondVisibility("system.platform.ios"): # ret["os"] = "ios" # ret["arch"] = "armv7" return ret
def doAssign(): mediatype = getMediaType() try: path = sys.listitem.getfilename() except AttributeError: path = sys.listitem.getPath() use_tmdb_id = False if path.startswith("plugin://plugin.video.elementum"): """plugin://plugin.video.elementum/show/1622/season/15/episode/1/links/Supernatural%20S15E01 plugin://plugin.video.elementum/show/1622/season/15/episodes plugin://plugin.video.elementum/movie/628/links/Interview%20with%20the%20Vampire%20%281994%29""" use_tmdb_id = True result = re.search(r'plugin://plugin.video.elementum/[^/]+/(\d+)/.*', path) if result: tmdbID = result.group(1) else: log.error("Could not find TMDB id for %s" % path) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007), ADDON.getLocalizedString(32014), xbmcgui.NOTIFICATION_WARNING, 3000) return if mediatype == 'season': result = re.search( r'plugin://plugin.video.elementum/[^/]+/\d+/season/(\d+)/.*', path) if result: season_number = result.group(1) else: log.error("Could not find season number for %s" % path) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007), ADDON.getLocalizedString(32014), xbmcgui.NOTIFICATION_WARNING, 3000) return if mediatype == 'episode': result = re.search( r'plugin://plugin.video.elementum/[^/]+/\d+/season/(\d+)/episode/(\d+)/.*', path) if result: season_number = result.group(1) episode_number = result.group(2) else: log.error("Could not find season/episode number for %s" % path) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007), ADDON.getLocalizedString(32014), xbmcgui.NOTIFICATION_WARNING, 3000) return else: dbid = getDbId() if not dbid.isdigit(): log.error("Kodi library ID is wrong %s" % dbid) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007), ADDON.getLocalizedString(32016), xbmcgui.NOTIFICATION_WARNING, 3000) return # we also can use plugin://plugin.video.elementum/torrents/ file = xbmcgui.Dialog().browseSingle( 1, ADDON.getLocalizedString(32010), 'files', '', False, False, 'plugin://plugin.video.elementum/history/') if file == '': return try: parsed_url = urlparse(file) params = parse_qs(parsed_url.query) if 'infohash' in params: torrentid = params['infohash'][0] else: torrentid = params['resume'][0] except Exception as e: log.error("Could not get torrent info for %s: %s" % (file, e)) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007), ADDON.getLocalizedString(32015), xbmcgui.NOTIFICATION_WARNING, 3000) return if not use_tmdb_id: url = "plugin://plugin.video.elementum/context/torrents/assign/%s/kodi/%s/%s" % ( torrentid, mediatype, dbid) log.info("Assigning torrent %s for: DBID=%s, MediaType=%s" % (torrentid, dbid, mediatype)) else: if mediatype == 'movie': url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/%s/%s" % ( torrentid, mediatype, tmdbID) elif mediatype == 'season': url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/show/%s/%s/%s" % ( torrentid, tmdbID, mediatype, season_number) elif mediatype == 'episode': url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/show/%s/season/%s/%s/%s" % ( torrentid, tmdbID, season_number, mediatype, episode_number) log.info("Assigning torrent %s for: TMDBID=%s, MediaType=%s" % (torrentid, tmdbID, mediatype)) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32010), sys.listitem.getLabel(), xbmcgui.NOTIFICATION_INFO, 3000) log.info("Starting Elementum with: %s" % url) xbmc.Player().play(url)
except AttributeError: path = item.getPath() truelabel = item.getLabel() infolabel = xbmc.getInfoLabel('ListItem.Label') dbid = xbmc.getInfoLabel('ListItem.DBID') mediatype = xbmc.getInfoLabel('ListItem.DBTYPE') try: tmdbID = item.getUniqueID('tmdb') except AttributeError: tmdbID = "not supported" properties = { 'resume_time': item.getProperty('ResumeTime'), 'start_offset': item.getProperty('StartOffset'), 'start_percent': item.getProperty('StartPercent') } log.info("Properties: %s;" % properties) all_labels = getJSONResponse( '{"jsonrpc": "2.0", "method": "XBMC.GetInfoLabels", "params": { "labels": %s }, "id": "0"}' % json.dumps(info_labels)) log.info("Labels: %s" % json.dumps(all_labels["result"], indent=4)) log.info( "truelabel: %s; infolabel: %s; dbid: %s; tmdbID: %s; mediatype: %s; path: %s;" % (truelabel, infolabel, dbid, tmdbID, mediatype, path)) xbmcgui.Dialog().notification( "truelabel: %s" % truelabel, "infolabel: %s; dbid: %s; tmdbID: %s; mediatype: %s; path: %s;" % (infolabel, dbid, tmdbID, mediatype, path))
def get_platform(): build = xbmc.getInfoLabel("System.BuildVersion") kodi_version = int(build.split()[0][:2]) ret = { "auto_arch": sys.maxsize > 2 ** 32 and "64-bit" or "32-bit", "arch": sys.maxsize > 2 ** 32 and "x64" or "x86", "os": "", "version": platform.release(), "kodi": kodi_version, "build": build, "fork": True, } if xbmc.getCondVisibility("system.platform.android"): dump_version() ret["os"] = "android" if "arm" in platform.machine().lower() or "aarch" in platform.machine().lower(): ret["arch"] = "arm" if "64" in platform.machine() and ret["auto_arch"] == "64-bit": ret["arch"] = "arm64" elif xbmc.getCondVisibility("system.platform.linux"): ret["os"] = "linux" if "aarch" in platform.machine().lower() or "arm64" in platform.machine().lower(): dump_version() if xbmc.getCondVisibility("system.platform.linux.raspberrypi"): ret["arch"] = "armv7" elif ret["auto_arch"] == "32-bit": ret["arch"] = "armv7" elif ret["auto_arch"] == "64-bit": ret["arch"] = "arm64" # elif platform.architecture()[0].startswith("32"): # ret["arch"] = "armv6" else: ret["arch"] = "armv7" elif "armv7" in platform.machine(): dump_version() ret["arch"] = "armv7" elif "arm" in platform.machine(): dump_version() cpuarch = "" if "aarch" in platform.machine().lower() or "arm" in platform.machine().lower(): info = cpuinfo() for proc in info.keys(): log.info("CPU: %s=%s" % (proc, info[proc])) model = "" if "model name" in info[proc]: model = info[proc]["model name"].lower() elif "Processor" in info[proc]: model = info[proc]["Processor"].lower() if model: log.info("Exploring model: %s" % model) if "aarch" in model or "arm64" in model or "v8l" in model: cpuarch = "arm64" elif "armv7" in model or "v7l" in model: cpuarch = "armv7" break if cpuarch: log.info("Using CPU info arch: %s" % cpuarch) ret["arch"] = cpuarch else: ret["arch"] = "armv6" elif xbmc.getCondVisibility("system.platform.xbox"): ret["os"] = "windows" ret["arch"] = "x64" ret["fork"] = False elif xbmc.getCondVisibility("system.platform.windows"): ret["os"] = "windows" if platform.machine().endswith('64'): ret["arch"] = "x64" elif platform.system() == "Darwin": dump_version() ret["os"] = "darwin" ret["arch"] = "x64" if "AppleTV" in platform.platform(): ret["os"] = "ios" ret["arch"] = "armv7" ret["fork"] = False if "64bit" in platform.platform(): ret["arch"] = "arm64" elif xbmc.getCondVisibility("system.platform.ios"): ret["os"] = "ios" ret["arch"] = "armv7" ret["fork"] = False if "64bit" in platform.platform(): ret["arch"] = "arm64" # elif xbmc.getCondVisibility("system.platform.osx"): # ret["os"] = "darwin" # ret["arch"] = "x64" # elif xbmc.getCondVisibility("system.platform.ios"): # ret["os"] = "ios" # ret["arch"] = "armv7" return ret
def start_elementumd(**kwargs): jsonrpc_failures = 0 while jsonrpc_enabled() is False: jsonrpc_failures += 1 log.warning( "Unable to connect to Kodi's JSON-RPC service, retrying...") if jsonrpc_failures > 1: time.sleep(5) if not jsonrpc_enabled(notify=True): log.error( "Unable to reach Kodi's JSON-RPC service, aborting...") return False else: break time.sleep(3) elementum_dir, elementum_binary = get_elementum_binary() log.info("Binary dir: %s, item: %s " % (elementum_dir, elementum_binary)) if elementum_dir is False or elementum_binary is False: return False lockfile = os.path.join(ADDON_PATH, ".lockfile") if os.path.exists(lockfile): log.warning("Existing process found from lockfile, killing...") try: with open(lockfile) as lf: pid = int(lf.read().rstrip(" \t\r\n\0")) os.kill(pid, 9) except OSError as e: if e.errno != 3: # Ignore: OSError: [Errno 3] No such process log.error(repr(e)) except Exception as e: log.error(repr(e)) if binary_platform["os"] == "windows": try: library_lockfile = os.path.join( xbmc.translatePath( ADDON.getAddonInfo("profile")).decode('utf-8'), "library.db.lock") log.warning("Removing library.db.lock file at %s ..." % library_lockfile) os.remove(library_lockfile) except Exception as e: log.error(repr(e)) SW_HIDE = 0 STARTF_USESHOWWINDOW = 1 args = [elementum_binary] kwargs["cwd"] = elementum_dir if binary_platform["os"] == "windows": args[0] = getWindowsShortPath(elementum_binary) kwargs["cwd"] = getWindowsShortPath(elementum_dir) si = subprocess.STARTUPINFO() si.dwFlags = STARTF_USESHOWWINDOW si.wShowWindow = SW_HIDE clear_fd_inherit_flags() kwargs["startupinfo"] = si else: env = os.environ.copy() env["LD_LIBRARY_PATH"] = "%s:%s" % (elementum_dir, env.get("LD_LIBRARY_PATH", "")) kwargs["env"] = env kwargs["close_fds"] = True wait_counter = 1 log.debug("Checking for visible") while xbmc.getCondVisibility( 'Window.IsVisible(10140)') or xbmc.getCondVisibility( 'Window.IsActive(10140)'): if wait_counter == 1: log.info( 'Add-on settings currently opened, waiting before starting...') if wait_counter > 300: break time.sleep(1) wait_counter += 1 log.info("elementumd: start args: %s, kw: %s" % (args, kwargs)) if hasSubprocess: return subprocess.Popen(args, **kwargs) return False
def get_elementum_binary(): global binary_platform binary_platform = get_platform() binary = "elementum" + (binary_platform["os"] == "windows" and ".exe" or "") binary_dir = os.path.join(ADDON_PATH, "resources", "bin", "%(os)s_%(arch)s" % binary_platform) if binary_platform["os"] == "android": log.info("Detected binary folder: %s" % binary_dir) binary_dir_legacy = binary_dir.replace("/storage/emulated/0", "/storage/emulated/legacy") if os.path.exists(binary_dir_legacy): binary_dir = binary_dir_legacy log.info("Using changed binary folder for Android: %s" % binary_dir) app_id = android_get_current_appid() xbmc_data_path = os.path.join("/data", "data", app_id) if not os.path.exists(xbmc_data_path): log.info( "%s path does not exist, so using %s as xbmc_data_path" % (xbmc_data_path, xbmc.translatePath("special://xbmcbin/"))) xbmc_data_path = xbmc.translatePath("special://xbmcbin/") if not os.path.exists(xbmc_data_path): log.info("%s path does not exist, so using %s as xbmc_data_path" % (xbmc_data_path, xbmc.translatePath("special://masterprofile/"))) xbmc_data_path = xbmc.translatePath("special://masterprofile/") dest_binary_dir = os.path.join(xbmc_data_path, "files", ADDON_ID, "bin", "%(os)s_%(arch)s" % binary_platform) else: dest_binary_dir = os.path.join( xbmc.translatePath(ADDON.getAddonInfo("profile")), "bin", "%(os)s_%(arch)s" % binary_platform) binary_path = os.path.join(binary_dir, binary) dest_binary_path = os.path.join(dest_binary_dir, binary) log.info("Binary detection. Source: %s, Destination: %s" % (binary_path, dest_binary_path)) if not os.path.exists(binary_path): # notify((getLocalizedString(30103) + " %(os)s_%(arch)s" % PLATFORM), time=7000) dialog_ok("LOCALIZE[30347];;" + "%(os)s_%(arch)s" % binary_platform) system_information() try: log.info("Source directory (%s):\n%s" % (binary_dir, os.listdir(os.path.join(binary_dir, "..")))) log.info("Destination directory (%s):\n%s" % (dest_binary_dir, os.listdir(os.path.join(dest_binary_dir, "..")))) except Exception: pass return False, False if os.path.isdir(dest_binary_path): log.warning( "Destination path is a directory, expected previous binary file, removing..." ) try: shutil.rmtree(dest_binary_path) except Exception as e: log.error("Unable to remove destination path for update: %s" % e) system_information() return False, False if not os.path.exists(dest_binary_path) or not os.path.exists( binary_path) or get_elementumd_checksum( dest_binary_path) != get_elementumd_checksum( binary_path) or not filecmp.cmp( dest_binary_path, binary_path, shallow=True): log.info("Updating elementum daemon...") try: os.makedirs(dest_binary_dir) except OSError: pass try: shutil.rmtree(dest_binary_dir) except Exception as e: log.error("Unable to remove destination path for update: %s" % e) system_information() pass try: shutil.copytree(binary_dir, dest_binary_dir) except Exception as e: log.error("Unable to copy to destination path for update: %s" % e) system_information() return False, False # 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) log.info("Binary detection: [ Source: %s, Destination: %s ]" % (binary_path, dest_binary_path)) return dest_binary_dir, ensure_exec_perms(dest_binary_path)
def doAssign(): mediatype = getMediaType() try: path = sys.listitem.getfilename() except AttributeError: path = sys.listitem.getPath() use_elementum_path = False try: tmdbID = sys.listitem.getUniqueID('tmdb') except AttributeError: tmdbID = "" if tmdbID == "": if path.startswith("plugin://plugin.video.elementum"): use_elementum_path = True tmdbID = getTMDBidFromElementumPath(path) if not tmdbID: return if mediatype == 'season': season_number = getSeasonNumberFromElementumPath(path) if not season_number: return if mediatype == 'episode': season_number = getSeasonNumberFromElementumPath(path) episode_number = getEpisodeNumberFromElementumPath(path) if not season_number or not episode_number: return else: dbid = getDbId() if not dbid.isdigit(): log.error("Kodi library ID is wrong %s" % dbid) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007), ADDON.getLocalizedString(32016), xbmcgui.NOTIFICATION_WARNING, 3000) return # we also can use plugin://plugin.video.elementum/torrents/ file = xbmcgui.Dialog().browseSingle( 1, ADDON.getLocalizedString(32010), 'files', '', False, False, 'plugin://plugin.video.elementum/history/') if file == '': return try: parsed_url = urlparse(file) params = parse_qs(parsed_url.query) if 'infohash' in params: torrentid = params['infohash'][0] else: torrentid = params['resume'][0] except Exception as e: log.error("Could not get torrent info for %s: %s" % (file, e)) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32007), ADDON.getLocalizedString(32015), xbmcgui.NOTIFICATION_WARNING, 3000) return if use_elementum_path: if mediatype == 'movie': url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/%s/%s" % ( torrentid, mediatype, tmdbID) elif mediatype == 'season': url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/show/%s/%s/%s" % ( torrentid, tmdbID, mediatype, season_number) elif mediatype == 'episode': url = "plugin://plugin.video.elementum/context/torrents/assign/%s/tmdb/show/%s/season/%s/%s/%s" % ( torrentid, tmdbID, season_number, mediatype, episode_number) log.info("Assigning torrent %s for: TMDBID=%s, MediaType=%s" % (torrentid, tmdbID, mediatype)) else: if tmdbID != "": url = "plugin://plugin.video.elementum/torrents/assign/%s/%s" % ( torrentid, tmdbID) log.info("Assigning torrent %s for: TMDBID=%s, MediaType=%s" % (torrentid, tmdbID, mediatype)) else: url = "plugin://plugin.video.elementum/context/torrents/assign/%s/kodi/%s/%s" % ( torrentid, mediatype, dbid) log.info("Assigning torrent %s for: DBID=%s, MediaType=%s" % (torrentid, dbid, mediatype)) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32010), sys.listitem.getLabel(), xbmcgui.NOTIFICATION_INFO, 3000) log.info("Starting Elementum with: %s" % url) xbmc.Player().play(url)