def __init__(self): try: from urllib.parse import urlparse except ImportError: from urlparse import urlparse # argv[0] can contain the entire path, so we limit ourselves to the base url pid = urlparse(argv[0]) self.pluginid = '{}://{}/'.format(pid.scheme, pid.netloc) self.pluginhandle = int( argv[1]) if (1 < len(argv)) and self.pluginid else -1 self._globals['monitor'] = xbmc.Monitor() self._globals['addon'] = xbmcaddon.Addon() self._globals['dialog'] = xbmcgui.Dialog() # self._globals['dialogprogress'] = xbmcgui.DialogProgress() self._globals['hasExtRC'] = xbmc.getCondVisibility( 'System.HasAddon(script.chromium_remotecontrol)') self._globals['DATA_PATH'] = py2_decode( xbmc.translatePath(self.addon.getAddonInfo('profile'))) self._globals['CONFIG_PATH'] = OSPJoin(self._globals['DATA_PATH'], 'config') self._globals['HOME_PATH'] = py2_decode( xbmc.translatePath('special://home')) self._globals['PLUGIN_PATH'] = py2_decode( self._globals['addon'].getAddonInfo('path')) # With main PATHs configured, we initialise the get/write path attributes # and generate/retrieve the device ID getConfig.configPath = self._globals['CONFIG_PATH'] writeConfig.configPath = self._globals['CONFIG_PATH'] self._globals['deviceID'] = self.genID() self._globals['__plugin__'] = self._globals['addon'].getAddonInfo( 'name') self._globals['__authors__'] = self._globals['addon'].getAddonInfo( 'author') self._globals['__credits__'] = "" self._globals['__version__'] = self._globals['addon'].getAddonInfo( 'version') # OS Detection if xbmc.getCondVisibility('system.platform.windows'): self._globals['platform'] |= self.OS_WINDOWS if xbmc.getCondVisibility('system.platform.linux'): self._globals['platform'] |= self.OS_LINUX if xbmc.getCondVisibility('system.platform.osx'): self._globals['platform'] |= self.OS_OSX if xbmc.getCondVisibility('system.platform.android'): self._globals['platform'] |= self.OS_ANDROID if (xbmcvfs.exists('/etc/os-release')) and ( 'libreelec' in xbmcvfs.File('/etc/os-release').read()): self._globals['platform'] |= self.OS_LE # Save the language code for HTTP requests and set the locale for l10n loc = getdefaultlocale()[0] userAcceptLanguages = 'en-gb{}, en;q=0.5' self._globals['userAcceptLanguages'] = userAcceptLanguages.format( '') if not loc else '{}, {}'.format( loc.lower().replace('_', '-'), userAcceptLanguages.format(';q=0.75')) self._globals['CONTEXTMENU_MULTIUSER'] = [ (getString(30130, self._globals['addon']).split('…')[0], 'RunPlugin({}?mode=LogIn)'.format(self.pluginid)), (getString(30131, self._globals['addon']).split('…')[0], 'RunPlugin({}?mode=removeUser)'.format(self.pluginid)), (getString(30132, self._globals['addon']), 'RunPlugin({}?mode=renameUser)'.format(self.pluginid)) ]
def getInputStream(): if xbmc.getCondVisibility('System.AddonIsEnabled(%s)' % (INPUTSTREAM_BETA)): return INPUTSTREAM_BETA else: return INPUTSTREAM
def get_video_url(plugin, item_id, next_url, download_mode=False, **kwargs): resp = urlquick.get(next_url, headers={'User-Agent': web_utils.get_random_ua()}, max_age=-1) json_parser = json.loads(resp.text) if json_parser["detail"]["informations"]['consumptionPlatform'] == 'HAPI': # Get DeviceId header_device_id = { 'referer': 'https://secure-player.canal-plus.com/one/prod/v2/', } resp_device_id = urlquick.get(URL_DEVICE_ID, headers=header_device_id, max_age=-1) device_id = re.compile(r'deviceId\"\:\"(.*?)\"').findall( resp_device_id.text)[0] if xbmc.getCondVisibility('system.platform.android'): if get_kodi_version() < 18: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False is_helper = inputstreamhelper.Helper('mpd') if not is_helper.check_inputstream(): return False if download_mode: xbmcgui.Dialog().ok('Info', plugin.localize(30603)) return False Script.notify("INFO", plugin.localize(LABELS['drm_notification']), Script.NOTIFY_INFO) return False # Get Portail Id session_requests = requests.session() resp_app_config = session_requests.get(URL_REPLAY % item_id) json_app_config = re.compile('window.app_config=(.*?)};').findall( resp_app_config.text)[0] json_app_config_parser = json.loads(json_app_config + ('}')) portail_id = json_app_config_parser["api"]["pass"][ "portailIdEncrypted"] # Get PassToken payload = { 'deviceId': 'unknown', 'vect': 'INTERNET', 'media': 'PC', 'portailId': portail_id } resp_token_mycanal = session_requests.post(URL_TOKEN, data=payload) json_token_parser = json.loads(resp_token_mycanal.text) pass_token = json_token_parser["response"]["passToken"] # Get stream Id for stream_datas in json_parser["detail"]["informations"][ "videoURLs"]: if stream_datas["drmType"] == "DRM PlayReady": payload = { 'comMode': stream_datas['comMode'], 'contentId': stream_datas['contentId'], 'distMode': stream_datas['distMode'], 'distTechnology': stream_datas['distTechnology'], 'drmType': stream_datas['drmType'], 'functionalType': stream_datas['functionalType'], 'hash': stream_datas['hash'], 'idKey': stream_datas['idKey'], 'quality': stream_datas['quality'] } payload = json.dumps(payload) headers = { 'Accept': 'application/json, text/plain, */*', 'Authorization': 'PASS Token="%s"' % pass_token, 'Content-Type': 'application/json; charset=UTF-8', 'XX-DEVICE': 'pc %s' % device_id, 'XX-DOMAIN': 'cpfra', 'XX-OPERATOR': 'pc', 'XX-Profile-Id': '0', 'XX-SERVICE': 'mycanal', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' } resp_stream_datas = session_requests.put(URL_STREAM_DATAS, data=payload, headers=headers) jsonparser_stream_datas = json.loads( resp_stream_datas.text) resp_real_stream_datas = session_requests.get( jsonparser_stream_datas['@medias'], headers=headers) jsonparser_real_stream_datas = json.loads( resp_real_stream_datas.text) item = Listitem() item.path = jsonparser_real_stream_datas["VF"][0]["media"][ 0]["distribURL"] + '/manifest' item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) item.property['inputstreamaddon'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'ism' item.property[ 'inputstream.adaptive.license_type'] = 'com.microsoft.playready' return item else: if get_kodi_version() < 18: xbmcgui.Dialog().ok('Info', plugin.localize(30602)) return False is_helper = inputstreamhelper.Helper('mpd', drm='widevine') if not is_helper.check_inputstream(): return False if download_mode: xbmcgui.Dialog().ok('Info', plugin.localize(30603)) return False Script.notify("INFO", plugin.localize(LABELS['drm_notification']), Script.NOTIFY_INFO) return False # Get Portail Id session_requests = requests.session() resp_app_config = session_requests.get(URL_REPLAY % item_id) json_app_config = re.compile('window.app_config=(.*?)};').findall( resp_app_config.text)[0] json_app_config_parser = json.loads(json_app_config + ('}')) portail_id = json_app_config_parser["api"]["pass"][ "portailIdEncrypted"] # Get PassToken payload = { 'deviceId': 'unknown', 'vect': 'INTERNET', 'media': 'PC', 'portailId': portail_id } resp_token_mycanal = session_requests.post(URL_TOKEN, data=payload) json_token_parser = json.loads(resp_token_mycanal.text) pass_token = json_token_parser["response"]["passToken"] # Get stream Id for stream_datas in json_parser["detail"]["informations"][ "videoURLs"]: if 'Widevine' in stream_datas["drmType"]: payload = { 'comMode': stream_datas['comMode'], 'contentId': stream_datas['contentId'], 'distMode': stream_datas['distMode'], 'distTechnology': stream_datas['distTechnology'], 'drmType': stream_datas['drmType'], 'functionalType': stream_datas['functionalType'], 'hash': stream_datas['hash'], 'idKey': stream_datas['idKey'], 'quality': stream_datas['quality'] } payload = json.dumps(payload) headers = { 'Accept': 'application/json, text/plain, */*', 'Authorization': 'PASS Token="%s"' % pass_token, 'Content-Type': 'application/json; charset=UTF-8', 'XX-DEVICE': 'pc %s' % device_id, 'XX-DOMAIN': 'cpfra', 'XX-OPERATOR': 'pc', 'XX-Profile-Id': '0', 'XX-SERVICE': 'mycanal', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' } resp_stream_datas = session_requests.put(URL_STREAM_DATAS, data=payload, headers=headers) jsonparser_stream_datas = json.loads( resp_stream_datas.text) resp_real_stream_datas = session_requests.get( jsonparser_stream_datas['@medias'], headers=headers) jsonparser_real_stream_datas = json.loads( resp_real_stream_datas.text) item = Listitem() item.path = jsonparser_real_stream_datas["VF"][0]["media"][ 0]["distribURL"] + '/manifest' item.label = get_selected_item_label() item.art.update(get_selected_item_art()) item.info.update(get_selected_item_info()) item.property['inputstreamaddon'] = 'inputstream.adaptive' item.property['inputstream.adaptive.manifest_type'] = 'ism' item.property[ 'inputstream.adaptive.license_type'] = 'com.widevine.alpha' value_pass_token = 'PASS Token="%s"' % pass_token headers2 = { 'Accept': 'application/json, text/plain, */*', 'Authorization': value_pass_token, 'Content-Type': 'text/plain', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36', 'Origin': 'https://www.mycanal.fr', 'XX-DEVICE': 'pc %s' % device_id, 'XX-DOMAIN': 'cpfra', 'XX-OPERATOR': 'pc', 'XX-Profile-Id': '0', 'XX-SERVICE': 'mycanal', } # Return HTTP 200 but the response is not correctly interpreted by inputstream (https://github.com/peak3d/inputstream.adaptive/issues/267) item.property[ 'inputstream.adaptive.license_key'] = jsonparser_stream_datas[ '@licence'] + '?drmType=DRM%20Widevine' + '|%s|b{SSM}|' % urlencode( headers2) return item stream_url = '' for stream_datas in json_parser["detail"]["informations"]["videoURLs"]: if stream_datas["encryption"] == 'clear': stream_url = stream_datas["videoURL"] if download_mode: return download.download_video(stream_url) return stream_url
def get_condition(cond): return xbmc.getCondVisibility(cond)
def Window_Is_Loading(self): return int( xbmc.getCondVisibility('Window.IsVisible(10138)') or xbmc.getCondVisibility('Window.IsActive(10138)') or xbmc.getCondVisibility('Window.IsVisible(10160)') or xbmc.getCondVisibility('Window.IsActive(10160)'))
def AddonSettingsOpened(self): return int( xbmc.getCondVisibility('Window.IsVisible(10140)') or xbmc.getCondVisibility('Window.IsActive(10140)') or xbmc.getCondVisibility('Window.IsVisible(12002)'))
def hasMovie(self): return (xbmc.getCondVisibility('Library.HasContent(Movies)'))
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": "", "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"): dump_version(ret) 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(): dump_version(ret) 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"]: dump_version(ret) ret["arch"] = "armv7" elif "arm" in ret["machine"]: dump_version(ret) 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": dump_version(ret) 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 onAction(self, action): controlID = self.getFocusId() try: if not controlID and not action == xbmcgui.ACTION_MOUSE_MOVE: if self.lastFocusID: self.setFocusId(self.lastFocusID) if controlID == self.SECTION_LIST_ID: self.checkSectionItem(action=action) if controlID == self.SERVER_BUTTON_ID: if action == xbmcgui.ACTION_SELECT_ITEM: self.showServers() return elif action == xbmcgui.ACTION_MOUSE_LEFT_CLICK: self.showServers(mouse=True) self.setBoolProperty('show.servers', True) return elif controlID == self.USER_BUTTON_ID: if action == xbmcgui.ACTION_SELECT_ITEM: self.showUserMenu() return elif action == xbmcgui.ACTION_MOUSE_LEFT_CLICK: self.showUserMenu(mouse=True) self.setBoolProperty('show.options', True) return if controlID == self.SERVER_BUTTON_ID and action == xbmcgui.ACTION_MOVE_RIGHT: self.setFocusId(self.USER_BUTTON_ID) elif controlID == self.USER_BUTTON_ID and action == xbmcgui.ACTION_MOVE_LEFT: self.setFocusId(self.SERVER_BUTTON_ID) elif controlID == self.SEARCH_BUTTON_ID and action == xbmcgui.ACTION_MOVE_RIGHT: if xbmc.getCondVisibility('Player.HasMedia + Control.IsVisible({0})'.format(self.PLAYER_STATUS_BUTTON_ID)): self.setFocusId(self.PLAYER_STATUS_BUTTON_ID) else: self.setFocusId(self.SERVER_BUTTON_ID) elif controlID == self.PLAYER_STATUS_BUTTON_ID and action == xbmcgui.ACTION_MOVE_RIGHT: self.setFocusId(self.SERVER_BUTTON_ID) elif 399 < controlID < 500: if action.getId() in MOVE_SET: self.checkHubItem(controlID) elif action.getId() == xbmcgui.ACTION_PLAYER_PLAY: self.hubItemClicked(controlID, auto_play=True) return if action in(xbmcgui.ACTION_NAV_BACK, xbmcgui.ACTION_PREVIOUS_MENU, xbmcgui.ACTION_CONTEXT_MENU): optionsFocused = xbmc.getCondVisibility('ControlGroup({0}).HasFocus(0)'.format(self.OPTIONS_GROUP_ID)) offSections = util.getGlobalProperty('off.sections') if action in (xbmcgui.ACTION_NAV_BACK, xbmcgui.ACTION_PREVIOUS_MENU): if self.getFocusId() == self.USER_LIST_ID: self.setFocusId(self.USER_BUTTON_ID) return elif self.getFocusId() == self.SERVER_LIST_ID: self.setFocusId(self.SERVER_BUTTON_ID) return if util.advancedSettings.fastBack and not optionsFocused and offSections \ and self.lastFocusID not in (self.USER_BUTTON_ID, self.SERVER_BUTTON_ID, self.SEARCH_BUTTON_ID, self.SECTION_LIST_ID): self.setProperty('hub.focus', '0') self.setFocusId(self.SECTION_LIST_ID) return if action in(xbmcgui.ACTION_NAV_BACK, xbmcgui.ACTION_CONTEXT_MENU): if not optionsFocused and offSections \ and (not util.advancedSettings.fastBack or action == xbmcgui.ACTION_CONTEXT_MENU): self.lastNonOptionsFocusID = self.lastFocusID self.setFocusId(self.OPTIONS_GROUP_ID) return elif action == xbmcgui.ACTION_CONTEXT_MENU and optionsFocused and offSections \ and self.lastNonOptionsFocusID: self.setFocusId(self.lastNonOptionsFocusID) self.lastNonOptionsFocusID = None return if action in(xbmcgui.ACTION_NAV_BACK, xbmcgui.ACTION_PREVIOUS_MENU) and not self.confirmExit(): return except: util.ERROR() kodigui.BaseWindow.onAction(self, action)
def isPlaying(): """ Returns True if the player is playing video. """ return xbmc.getCondVisibility('Player.Playing') and xbmc.getCondVisibility( 'Player.HasVideo')
def start(): http = HTTP() monitor = xbmc.Monitor() restart_queued = False boot_merge = settings.getBool('boot_merge', False) set_kodi_string('_iptv_merge_force_run') while not monitor.waitForAbort(1): http.start() if settings.getBool('http_api', False) else http.stop() forced = ADDON_DEV or get_kodi_string('_iptv_merge_force_run') or 0 if forced or boot_merge or ( settings.getBool('auto_merge', True) and time.time() - userdata.get('last_run', 0) > settings.getInt('reload_time_hours', 12) * 3600): set_kodi_string('_iptv_merge_force_run', '1') url = router.url_for('run_merge', forced=int(forced)) dirs, files = xbmcvfs.listdir(url) result, msg = int(files[0][0]), unquote_plus(files[0][1:]) if result: restart_queued = True userdata.set('last_run', int(time.time())) set_kodi_string('_iptv_merge_force_run') if restart_queued and settings.getBool('restart_pvr', False): if forced: progress = gui.progressbg( heading='Reloading IPTV Simple Client') if KODI_VERSION > 18: restart_queued = False try: xbmcaddon.Addon(IPTV_SIMPLE_ID).setSetting( 'm3uPathType', '0') except Exception as e: pass elif forced or (not xbmc.getCondVisibility('Pvr.IsPlayingTv') and not xbmc.getCondVisibility('Pvr.IsPlayingRadio')): restart_queued = False kodi_rpc('Addons.SetAddonEnabled', { 'addonid': IPTV_SIMPLE_ID, 'enabled': False }) wait_delay = 4 for i in range(wait_delay): if monitor.waitForAbort(1): break if forced: progress.update((i + 1) * int(100 / wait_delay)) kodi_rpc('Addons.SetAddonEnabled', { 'addonid': IPTV_SIMPLE_ID, 'enabled': True }) if forced: progress.update(100) progress.close() boot_merge = False if ADDON_DEV: break http.stop()
def wait_for_skinshortcuts_window(): '''wait untill skinshortcuts is active window (because of any animations that may have been applied)''' while not MONITOR.abortRequested() and not xbmc.getCondVisibility( "Window.IsActive(DialogSelect.xml) | !Window.IsActive(script-skin_helper_service-ColorPicker.xml) | Window.IsActive(DialogKeyboard.xml)" ): MONITOR.waitForAbort(0.1)
def render(self): fullRefresh = 0 while xbmc.abortRequested == False and self.exit == False: if not xbmc.Player().isPlayingVideo(): if self.state == videoState.started: if isinstance(self.t1, Thread): #print self.t1.is_alive(), self.renderstop, self.state, xbmc.Player().isPlayingVideo() if self.t1.isAlive() == False: self.state = videoState.error elif xbmc.Player().isPlayingAudio(): self.state = videoState.inactive if self.renderstop == False: fullRefresh += 1 if fullRefresh < 30 and self.state == videoState.inactive: if self.inControl == False and self.xnewa.sid != None: self.getActivity(True) if self.renderstop == True: self.renderstop = False self.getScreen() self.getActivity() else: fullRefresh = 0 import glob fileNames = glob.glob( xbmc.translatePath('special://temp') + 'knew5/emulate*.png') for file in fileNames: try: os.remove(file) except: xbmc.log('Error deleting ' + file) if self.state == videoState.playing or self.state == videoState.error or self.state == videoState.stopped: if self.sdlmode != SDL.disabled: if self.skipStop == False: try: url = self.base + '/control?media=stop' if self.state == videoState.error: url += '&message=Player%20error' url += self.xnewa.client screenFile1 = xbmc.translatePath( 'special://temp' ) + 'knew5/emulate-' + str( time.time()) + '.png' xbmc.log(url) pngfile = urlopen(url) pngfile.close() except Exception as err: print(err) else: self.skipStop = False else: #url = self.base + '/control?key=131155' + self.xnewa.client url = self.base + '/control?key=' + str( 83 | 0x20000) + self.xnewa.client xbmc.log(url) try: jpgfile = urlopen(url) screenFile = xbmc.translatePath( 'special://temp' ) + 'knew5/emulate-' + str( time.time()) + '.png' output = open(screenFile, 'wb') output.write(jpgfile.read()) output.close() self.image.setImage(screenFile, False) self.getActivity() except Exception as err: print(err) self.setOSDMode(True) self.sidUpdate() self.state = videoState.inactive self.xnewa.logMessage('Stopped playback') url = self.base + '/control?key=131188' + self.xnewa.client xbmc.log(url) try: jpgfile = urlopen(url) screenFile = xbmc.translatePath( 'special://temp') + 'knew5/emulate-' + str( time.time()) + '.png' output = open(screenFile, 'wb') output.write(jpgfile.read()) output.close() self.image.setImage(screenFile, False) self.getActivity() except Exception as err: print(err) xbmc.sleep(1000) else: self.state = videoState.playing if self.sdlmode == SDL.full: if self.wasFullScreen: if xbmc.getCondVisibility( 'videoplayer.isfullscreen') == 0: self.wasFullScreen = False url = self.base + '/control?move=49x57' + self.xnewa.client screenFile1 = xbmc.translatePath( 'special://temp') + 'knew5/emulate-a' + str( time.time()) + '.png' xbmc.log(url) try: pngfile = urlopen(url) if pngfile.code == 200: output = open(screenFile1, 'wb') output.write(pngfile.read()) output.close() pngfile.close() self.image.setImage(screenFile1, False) print(pngfile.code) self.setOSDMode(False) self.getActivity() except Exception as err: print(err) try: url = self.base + '/control?media=' + str( xbmc.Player().getTime()) + self.xnewa.client screenFile1 = xbmc.translatePath( 'special://temp') + 'knew5/emulate-' + str( time.time()) + '.png' xbmc.log(url) request = Request(url) pngfile = urlopen(request) if pngfile.code == 200 and xbmc.getCondVisibility( 'videoplayer.isfullscreen') == 0: output = open(screenFile1, 'wb') output.write(pngfile.read()) output.close() self.image.setImage(screenFile1, False) # needs rendering always true so just self.getActivity() elif pngfile.code == 204: self.setOSDMode(False) else: print(pngfile.code) pngfile.close() self.skipStop = False except Exception as err: print(err) pass self.getActivity() xbmc.sleep(1000) return
def optionsButtonClicked(self, from_item=False): options = [] mli = self.episodeListControl.getSelectedItem() if mli: if len(mli.dataSource.media) > 1: options.append({'key': 'play_version', 'display': T(32451, 'Play Version...')}) if mli.dataSource.isWatched and not mli.dataSource.viewOffset.asInt(): options.append({'key': 'mark_unwatched', 'display': T(32318, 'Mark Unplayed')}) else: options.append({'key': 'mark_watched', 'display': T(32319, 'Mark Played')}) # if True: # options.append({'key': 'add_to_playlist', 'display': '[COLOR FF808080]Add To Playlist[/COLOR]'}) if xbmc.getCondVisibility('Player.HasAudio + MusicPlayer.HasNext'): options.append({'key': 'play_next', 'display': T(32325, 'Play Next')}) if self.season: if self.season.isWatched: options.append({'key': 'mark_season_unwatched', 'display': T(32320, 'Mark Season Unplayed')}) else: options.append({'key': 'mark_season_watched', 'display': T(32321, 'Mark Season Played')}) if mli.dataSource.server.allowsMediaDeletion: options.append({'key': 'delete', 'display': T(32322, 'Delete')}) # if xbmc.getCondVisibility('Player.HasAudio') and self.section.TYPE == 'artist': # options.append({'key': 'add_to_queue', 'display': 'Add To Queue'}) if options: options.append(dropdown.SEPARATOR) options.append({'key': 'to_show', 'display': T(32323, 'Go To Show')}) options.append({'key': 'to_section', 'display': T(32324, u'Go to {0}').format(self.show_.getLibrarySectionTitle())}) pos = (500, 620) bottom = False setDropdownProp = False if from_item: viewPos = self.episodeListControl.getViewPosition() if viewPos > 6: pos = (1490, 312 + (viewPos * 100)) bottom = True else: pos = (1490, 167 + (viewPos * 100)) bottom = False setDropdownProp = True choice = dropdown.showDropdown(options, pos, pos_is_bottom=bottom, close_direction='top', set_dropdown_prop=setDropdownProp) if not choice: return if choice['key'] == 'play_version': self.episodeListClicked(play_version=True) elif choice['key'] == 'play_next': xbmc.executebuiltin('PlayerControl(Next)') elif choice['key'] == 'mark_watched': mli.dataSource.markWatched() self.updateItems(mli) util.MONITOR.watchStatusChanged() elif choice['key'] == 'mark_unwatched': mli.dataSource.markUnwatched() self.updateItems(mli) util.MONITOR.watchStatusChanged() elif choice['key'] == 'mark_season_watched': self.season.markWatched() self.updateItems() util.MONITOR.watchStatusChanged() elif choice['key'] == 'mark_season_unwatched': self.season.markUnwatched() self.updateItems() util.MONITOR.watchStatusChanged() elif choice['key'] == 'to_show': self.processCommand(opener.open(self.show_.ratingKey)) elif choice['key'] == 'to_section': self.goHome(self.show_.getLibrarySectionId()) elif choice['key'] == 'delete': self.delete()
def hasTV(self): return (xbmc.getCondVisibility('Library.HasContent(TVShows)'))
def onAction(self, action): if xbmc.getCondVisibility('Window.IsActive(selectdialog)'): if self.doKodiSelectDialogHack(action): return try: self.resetTimeout() controlID = self.getFocusId() if action.getId() in KEY_MOVE_SET: self.setProperty('mouse.mode', '') elif action == xbmcgui.ACTION_MOUSE_MOVE: self.setProperty('mouse.mode', '1') if controlID in (self.MAIN_BUTTON_ID, self.NO_OSD_BUTTON_ID): if action == xbmcgui.ACTION_MOUSE_LEFT_CLICK: if self.getProperty('mouse.mode') != '1': self.setProperty('mouse.mode', '1') self.seekMouse( action, without_osd=controlID == self.NO_OSD_BUTTON_ID) return elif action == xbmcgui.ACTION_MOUSE_MOVE: self.seekMouse( action, without_osd=controlID == self.NO_OSD_BUTTON_ID, preview=True) return passThroughMain = False if controlID == self.SKIP_INTRO_BUTTON_ID: if action == xbmcgui.ACTION_SELECT_ITEM: self.setProperty('show.introSkip_OSDOnly', '1') self.doSeek(int(self.intro.endTimeOffset)) return elif action == xbmcgui.ACTION_MOVE_DOWN: self.setProperty('show.introSkip_OSDOnly', '1') self.showOSD() elif action in (xbmcgui.ACTION_MOVE_RIGHT, xbmcgui.ACTION_STEP_FORWARD, xbmcgui.ACTION_MOVE_LEFT, xbmcgui.ACTION_STEP_BACK): # allow no-OSD-seeking with intro skip button shown passThroughMain = True if controlID == self.MAIN_BUTTON_ID: # we're seeking from the timeline with the OSD open - do an actual timeline seek if not self._seeking and action.getId() in KEY_STEP_SEEK_SET: self.selectedOffset = self.trueOffset() if action in (xbmcgui.ACTION_MOVE_RIGHT, xbmcgui.ACTION_STEP_FORWARD): if self.useDynamicStepsForTimeline: return self.skipForward() return self.seekByOffset(10000, auto_seek=self.useAutoSeek) elif action in (xbmcgui.ACTION_MOVE_LEFT, xbmcgui.ACTION_STEP_BACK): if self.useDynamicStepsForTimeline: return self.skipBack() return self.seekByOffset(-10000, auto_seek=self.useAutoSeek) elif action == xbmcgui.ACTION_MOVE_DOWN: self.updateBigSeek() # elif action == xbmcgui.ACTION_MOVE_UP: # self.seekForward(60000) # elif action == xbmcgui.ACTION_MOVE_DOWN: # self.seekBack(60000) # don't auto-apply the currently selected seek when pressing down elif controlID == self.PLAY_PAUSE_BUTTON_ID and self.previousFocusID == self.MAIN_BUTTON_ID \ and action == xbmcgui.ACTION_MOVE_DOWN: self.resetSeeking() elif controlID == self.NO_OSD_BUTTON_ID or passThroughMain: if action in (xbmcgui.ACTION_MOVE_RIGHT, xbmcgui.ACTION_MOVE_LEFT): # we're seeking from the timeline, with the OSD closed; act as we're skipping if not self._seeking: self.selectedOffset = self.trueOffset() if action == xbmcgui.ACTION_MOVE_RIGHT: self.skipForward(without_osd=True) else: self.skipBack(without_osd=True) if action in (xbmcgui.ACTION_MOVE_UP, xbmcgui.ACTION_MOVE_DOWN, xbmcgui.ACTION_BIG_STEP_FORWARD, xbmcgui.ACTION_BIG_STEP_BACK ) and not self._seekingWithoutOSD: self.selectedOffset = self.trueOffset() self.setBigSeekShift() self.updateProgress() self.showOSD() self.setFocusId(self.BIG_SEEK_LIST_ID) elif action.getButtonCode() == 61519: # xbmc.executebuiltin('Action(PlayerProcessInfo)') xbmc.executebuiltin('Action(CodecInfo)') elif controlID == self.BIG_SEEK_LIST_ID: if action in (xbmcgui.ACTION_MOVE_RIGHT, xbmcgui.ACTION_BIG_STEP_FORWARD): return self.updateBigSeek(changed=True) elif action in (xbmcgui.ACTION_MOVE_LEFT, xbmcgui.ACTION_BIG_STEP_BACK): return self.updateBigSeek(changed=True) elif action == xbmcgui.ACTION_MOVE_UP and self.getProperty( 'show.introSkip'): self.setFocusId(self.SKIP_INTRO_BUTTON_ID) return if action.getButtonCode() == 61516: builtin.Action('CycleSubtitle') elif action.getButtonCode() == 61524: builtin.Action('ShowSubtitles') elif action.getButtonCode() == 323714: # Alt-left builtin.PlayerControl('tempodown') elif action.getButtonCode() == 323715: # Alt-right builtin.PlayerControl('tempoup') elif action == xbmcgui.ACTION_NEXT_ITEM: next(self.handler) elif action == xbmcgui.ACTION_PREV_ITEM: self.handler.prev() elif action in (xbmcgui.ACTION_PREVIOUS_MENU, xbmcgui.ACTION_NAV_BACK, xbmcgui.ACTION_STOP): if self._seeking: self.resetSeeking() self.updateCurrent() self.updateProgress() if self.osdVisible(): self.hideOSD() return if action in (xbmcgui.ACTION_PREVIOUS_MENU, xbmcgui.ACTION_NAV_BACK): if self._osdHideAnimationTimeout: if self._osdHideAnimationTimeout >= time.time(): return else: self._osdHideAnimationTimeout = None if self.osdVisible(): self.hideOSD() else: self.doClose() # self.handler.onSeekAborted() self.handler.player.stop() return except: util.ERROR() kodigui.BaseDialog.onAction(self, action)
def has_addon(addon_id): return xbmc.getCondVisibility('System.HasAddon(%s)' % addon_id) == 1
def render(self): fullRefresh = 0 while xbmc.abortRequested == False and self.exit == False: if not xbmc.Player().isPlayingVideo(): if self.state == videoState.started: if isinstance(self.t1, Thread): #print self.t1.is_alive(), self.renderstop, self.state, xbmc.Player().isPlayingVideo() if self.t1.isAlive() == False: self.state = videoState.error elif xbmc.Player().isPlayingAudio(): self.state = videoState.inactive if self.renderstop == False: fullRefresh += 1 if fullRefresh < 30 and self.state == videoState.inactive: if self.inControl == False and self.xnewa.sid != None: self.getActivity(True) if self.renderstop == True: self.renderstop = False self.getScreen() self.getActivity() else: fullRefresh = 0 import glob fileNames = glob.glob(xbmc.translatePath('special://temp') + 'knew5/emulate*.png' ) for file in fileNames: try: os.remove(file) except: xbmc.log('Error deleting ' + file) if self.state == videoState.playing or self.state == videoState.error or self.state == videoState.stopped: if self.sdlmode != SDL.disabled: if self.skipStop == False: try: url = self.base + '/control?media=stop' if self.state == videoState.error: url += '&message=Player%20error' url += self.xnewa.client screenFile1 = xbmc.translatePath('special://temp') + 'knew5/emulate-'+ str(time.time()) + '.png' xbmc.log(url) pngfile = urlopen(url) pngfile.close() except Exception as err: print(err) else: self.skipStop = False self.setOSDMode(True) self.sidUpdate() self.state = videoState.inactive url = self.base + '/control?key=131188' + self.xnewa.client xbmc.log(url) try: jpgfile = urlopen(url) screenFile = xbmc.translatePath('special://temp') + 'knew5/emulate-'+ str(time.time()) + '.png' output = open(screenFile,'wb') output.write(jpgfile.read()) output.close() self.image.setImage(screenFile,False) self.getActivity() except err: print(err) xbmc.sleep(1000) else: self.state = videoState.playing if self.sdlmode == SDL.full: if self.wasFullScreen: if xbmc.getCondVisibility('videoplayer.isfullscreen') == 0: self.wasFullScreen = False url = self.base + '/control?move=49x57' + self.xnewa.client screenFile1 = xbmc.translatePath('special://temp') + 'knew5/emulate-a'+ str(time.time()) + '.png' xbmc.log(url) try: pngfile = urlopen(url) output = open(screenFile1,'wb') output.write(pngfile.read()) output.close() pngfile.close() self.image.setImage(screenFile1,False) self.getActivity() except Exception as err: print(err) try: url = self.base + '/control?media=' + str(xbmc.Player().getTime()) + self.xnewa.client screenFile1 = xbmc.translatePath('special://temp') + 'knew5/emulate-'+ str(time.time()) + '.png' xbmc.log(url) request = Request(url) pngfile = urlopen(request) if pngfile.code == 200 and xbmc.getCondVisibility('videoplayer.isfullscreen') == 0: output = open(screenFile1,'wb') output.write(pngfile.read()) output.close() self.image.setImage(screenFile1,False) # needs rendering always true so just self.getActivity() elif pngfile.code == 204: self.setOSDMode(False) else: print(pngfile.code) pngfile.close() self.skipStop = False except Exception as err: print(err) pass xbmc.sleep(1000) return
def listing(): ''' Display all jellyfin nodes and dynamic entries when appropriate. ''' total = int(window('Jellyfin.nodes.total') or 0) sync = get_sync() whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']] servers = get_credentials()['Servers'][1:] for i in range(total): window_prop = "Jellyfin.nodes.%s" % i path = window('%s.index' % window_prop) if not path: path = window('%s.content' % window_prop) or window( '%s.path' % window_prop) label = window('%s.title' % window_prop) node = window('%s.type' % window_prop) artwork = window('%s.artwork' % window_prop) view_id = window('%s.id' % window_prop) context = [] if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music', 'mixed') and view_id not in whitelist: label = "%s %s" % (label, translate(33166)) context.append(( translate(33123), "RunPlugin(plugin://plugin.video.jellyfin/?mode=synclib&id=%s)" % view_id)) if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music') and view_id in whitelist: context.append((translate( 33136 ), "RunPlugin(plugin://plugin.video.jellyfin/?mode=updatelib&id=%s)" % view_id)) context.append((translate( 33132 ), "RunPlugin(plugin://plugin.video.jellyfin/?mode=repairlib&id=%s)" % view_id)) context.append((translate( 33133 ), "RunPlugin(plugin://plugin.video.jellyfin/?mode=removelib&id=%s)" % view_id)) LOG.debug("--[ listing/%s/%s ] %s", node, label, path) if path: if xbmc.getCondVisibility('Window.IsActive(Pictures)' ) and node in ('photos', 'homevideos'): directory(label, path, artwork=artwork) elif xbmc.getCondVisibility('Window.IsActive(Videos)' ) and node not in ('photos', 'music', 'audiobooks'): directory(label, path, artwork=artwork, context=context) elif xbmc.getCondVisibility('Window.IsActive(Music)') and node in ( 'music'): directory(label, path, artwork=artwork, context=context) elif not xbmc.getCondVisibility( 'Window.IsActive(Videos) | Window.IsActive(Pictures) | Window.IsActive(Music)' ): directory(label, path, artwork=artwork) for server in servers: context = [] if server.get('ManualAddress'): context.append((translate( 33141 ), "RunPlugin(plugin://plugin.video.jellyfin/?mode=removeserver&server=%s)" % server['Id'])) if 'AccessToken' not in server: directory("%s (%s)" % (server['Name'], translate(30539)), "plugin://plugin.video.jellyfin/?mode=login&server=%s" % server['Id'], False, context=context) else: directory(server['Name'], "plugin://plugin.video.jellyfin/?mode=browse&server=%s" % server['Id'], context=context) directory(translate(33194), "plugin://plugin.video.jellyfin/?mode=managelibs", True) directory(translate(33134), "plugin://plugin.video.jellyfin/?mode=addserver", False) directory(translate(33054), "plugin://plugin.video.jellyfin/?mode=adduser", False) directory(translate(5), "plugin://plugin.video.jellyfin/?mode=settings", False) directory(translate(33058), "plugin://plugin.video.jellyfin/?mode=reset", False) directory(translate(33180), "plugin://plugin.video.jellyfin/?mode=restartservice", False) if settings('backupPath'): directory(translate(33092), "plugin://plugin.video.jellyfin/?mode=backup", False) xbmcplugin.setContent(PROCESS_HANDLE, 'files') xbmcplugin.endOfDirectory(PROCESS_HANDLE)
def Player_IsPaused(self): return int(xbmc.getCondVisibility("Player.Paused"))
def get_themes(): ''' Add theme media locally, via strm. This is only for tv tunes. If another script is used, adjust this code. ''' from helper.utils import normalize_string from helper.playutils import PlayUtils from helper.xmls import tvtunes_nfo library = xbmc.translatePath( "special://profile/addon_data/plugin.video.jellyfin/library") play = settings('useDirectPaths') == "1" if not xbmcvfs.exists(library + '/'): xbmcvfs.mkdir(library) if xbmc.getCondVisibility('System.HasAddon(script.tvtunes)'): tvtunes = xbmcaddon.Addon(id="script.tvtunes") tvtunes.setSetting('custom_path_enable', "true") tvtunes.setSetting('custom_path', library) LOG.info("TV Tunes custom path is enabled and set.") else: dialog("ok", heading="{jellyfin}", line1=translate(33152)) return with Database('jellyfin') as jellyfindb: all_views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views() views = [ x[0] for x in all_views if x[2] in ('movies', 'tvshows', 'mixed') ] items = {} server = TheVoid('GetServerAddress', {'ServerId': None}).get() token = TheVoid('GetToken', {'ServerId': None}).get() for view in views: result = TheVoid('GetThemes', {'Type': "Video", 'Id': view}).get() for item in result['Items']: folder = normalize_string(item['Name']) items[item['Id']] = folder result = TheVoid('GetThemes', {'Type': "Song", 'Id': view}).get() for item in result['Items']: folder = normalize_string(item['Name']) items[item['Id']] = folder for item in items: nfo_path = os.path.join(library, items[item]) nfo_file = os.path.join(nfo_path, "tvtunes.nfo") if not xbmcvfs.exists(nfo_path): xbmcvfs.mkdir(nfo_path) themes = TheVoid('GetTheme', {'Id': item}).get() paths = [] for theme in themes['ThemeVideosResult']['Items'] + themes[ 'ThemeSongsResult']['Items']: putils = PlayUtils(theme, False, None, server, token) if play: paths.append(putils.direct_play(theme['MediaSources'][0])) else: paths.append(putils.direct_url(theme['MediaSources'][0])) tvtunes_nfo(nfo_file, paths) dialog("notification", heading="{jellyfin}", message=translate(33153), icon="{jellyfin}", time=1000, sound=False)
def do_check(self): return require_version( self.minversion, required=True) and KODI_VERSION > 17 and xbmc.getCondVisibility( 'system.platform.android')
if __name__ == "__main__": ADDON_DATA_DIR = sys.argv[1] LINUX_x86_64_TVBUS = os.path.join(ADDON_DATA_DIR, "resources", "tvbus", "bin", "linux_x86_64", "tvbus") WIN_32_TVBUS = os.path.join(ADDON_DATA_DIR, "resources", "tvbus", "bin", "win32", "tvbus.exe") ENGINE = None tvbus_url = sys.argv[2] access_code = sys.argv[3] localport = sys.argv[4] playerport = sys.argv[5] if xbmc.getCondVisibility("system.platform.android"): pass elif xbmc.getCondVisibility("system.platform.linux"): if "x86_64" == platform.machine(): ENV = os.environ.copy() ENGINE = LINUX_x86_64_TVBUS test_exe(ENGINE, ENV) elif xbmc.getCondVisibility("system.platform.windows"): ENV = None ENGINE = WIN_32_TVBUS test_exe(ENGINE) if ENGINE: TvbusMonitor(ENGINE, ENV, tvbus_url, access_code, localport, playerport).run()
# # You should have received a copy of the GNU General Public License # along with PlutoTV. If not, see <http://www.gnu.org/licenses/>. # -*- coding: utf-8 -*- import os, sys, time, _strptime, datetime, re, traceback, uuid, routing import socket, json, inputstreamhelper, requests, collections from six.moves import urllib from simplecache import SimpleCache, use_cache from itertools import repeat, cycle, chain, zip_longest from kodi_six import xbmc, xbmcaddon, xbmcplugin, xbmcgui, xbmcvfs, py2_encode, py2_decode from favorites import * try: if xbmc.getCondVisibility('System.Platform.Android'): raise Exception('Using Android threading') from multiprocessing.pool import ThreadPool SUPPORTS_POOL = True except Exception: SUPPORTS_POOL = False try: basestring #py2 except NameError: #py3 basestring = str unicode = str # Plugin Info ADDON_ID = 'plugin.video.plutotv' REAL_SETTINGS = xbmcaddon.Addon(id=ADDON_ID)
def run(self): while not MONITOR.abortRequested(): WAIT_TIME = 300 if xbmc.getCondVisibility( 'System.HasAddon(plugin.video.pseudotv.live)'): try: asset = json.loads( xbmcgui.Window(10000).getProperty(PROP_KEY)) except: asset = {} if self.chkVOD(): # Build Recommend VOD asset['vod'] = [] #clear older list items = load( self.getDirs('plugin://%s/ondemand' % (ADDON_ID), ADDON_VERSION)).get('result', {}).get('files', []) for item in items: if item.get('filetype') == 'directory': label = '%s (%s)' % (item.get('label'), ADDON_NAME) plot = (item.get("plot", "") or item.get("plotoutline", "") or item.get("description", "")) icon = (item.get('art', {}).get('logo', '') or item.get('art', {}).get('thumb', '') or LOGO) asset.setdefault('vod', []).append({ 'type': 'vod', 'name': label, 'description': plot, 'icon': icon, 'path': item.get('file'), 'id': ADDON_ID }) xbmcgui.Window(10000).setProperty('Last_VOD', str(time.time())) if xbmc.getCondVisibility( 'System.HasAddon(service.iptv.manager)'): if REAL_SETTINGS.getSettingBool('iptv.enabled'): try: # Manager Info IPTV_MANAGER = xbmcaddon.Addon( id='service.iptv.manager') IPTV_PATH = IPTV_MANAGER.getAddonInfo('profile') IPTV_M3U = os.path.join(IPTV_PATH, 'playlist.m3u8') IPTV_XMLTV = os.path.join(IPTV_PATH, 'epg.xml') asset['iptv'] = { 'type': 'iptv', 'name': ADDON_NAME, 'icon': ICON.replace( ADDON_PATH, 'special://home/addons/%s/' % (ADDON_ID)).replace('\\', '/'), 'm3u': { 'path': IPTV_M3U, 'slug': '@%s' % (slugify(ADDON_NAME)) }, 'xmltv': { 'path': IPTV_XMLTV }, 'id': ADDON_ID } except Exception as e: asset['iptv'] = {} xbmc.log( '%s-%s-regPseudoTV failed! %s' % (ADDON_ID, ADDON_VERSION, e), xbmc.LOGERROR) else: asset['iptv'] = {} xbmcgui.Window(10000).setProperty(PROP_KEY, json.dumps(asset)) if MONITOR.waitForAbort(WAIT_TIME): break
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 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 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 osdVisible(self): return xbmc.getCondVisibility('Control.IsVisible(801)')
def onNotification(self, sender, method, data): if sender.lower() not in ('plugin.video.jellyfin', 'xbmc', 'upnextprovider.signal'): return if sender == 'plugin.video.jellyfin': method = method.split('.')[1] if method not in ('GetItem', 'ReportProgressRequested', 'LoadServer', 'RandomItems', 'Recommended', 'GetServerAddress', 'GetPlaybackInfo', 'Browse', 'GetImages', 'GetToken', 'PlayPlaylist', 'Play', 'GetIntros', 'GetAdditionalParts', 'RefreshItem', 'Genres', 'FavoriteItem', 'DeleteItem', 'AddUser', 'GetSession', 'GetUsers', 'GetThemes', 'GetTheme', 'Playstate', 'GeneralCommand', 'GetTranscodeOptions', 'RecentlyAdded', 'BrowseSeason', 'LiveTV', 'GetLiveStream'): return data = json.loads(data)[0] elif sender.startswith('upnextprovider'): LOG.info('Attempting to play the next episode via upnext') method = method.split('.', 1)[1] if method not in ('plugin.video.jellyfin_play_action', ): LOG.info('Received invalid upnext method: %s', method) return data = json.loads(data) method = "Play" if data: data = json.loads(binascii.unhexlify(data[0])) else: if method not in ('Player.OnPlay', 'VideoLibrary.OnUpdate', 'Player.OnAVChange'): ''' We have to clear the playlist if it was stopped before it has been played completely. Otherwise the next played item will be added the previous queue. ''' if method == "Player.OnStop": xbmc.sleep( 3000 ) # let's wait for the player so we don't clear the canceled playlist by mistake. if xbmc.getCondVisibility( "!Player.HasMedia + !Window.IsVisible(busydialog)" ): xbmc.executebuiltin("Playlist.Clear") LOG.info("[ playlist ] cleared") return data = json.loads(data) LOG.debug("[ %s: %s ] %s", sender, method, JsonDebugPrinter(data)) if self.sleep: LOG.info("System.OnSleep detected, ignore monitor request.") return try: if not data.get('ServerId'): server = Jellyfin() else: if method != 'LoadServer' and data[ 'ServerId'] not in self.servers: try: connect.Connect().register(data['ServerId']) self.server_instance(data['ServerId']) except Exception as error: LOG.exception(error) dialog("ok", "{jellyfin}", translate(33142)) return server = Jellyfin(data['ServerId']) except Exception as error: LOG.exception(error) server = Jellyfin() if method == 'GetItem': item = server.jellyfin.get_item(data['Id']) self.void_responder(data, item) elif method == 'GetAdditionalParts': item = server.jellyfin.get_additional_parts(data['Id']) self.void_responder(data, item) elif method == 'GetIntros': item = server.jellyfin.get_intros(data['Id']) self.void_responder(data, item) elif method == 'GetImages': item = server.jellyfin.get_images(data['Id']) self.void_responder(data, item) elif method == 'GetServerAddress': server_address = server.auth.get_server_info( server.auth.server_id)['address'] self.void_responder(data, server_address) elif method == 'GetPlaybackInfo': sources = server.jellyfin.get_play_info(data['Id'], data['Profile']) self.void_responder(data, sources) elif method == 'GetLiveStream': sources = server.jellyfin.get_live_stream(data['Id'], data['PlaySessionId'], data['Token'], data['Profile']) self.void_responder(data, sources) elif method == 'GetToken': token = server.auth.jellyfin_token() self.void_responder(data, token) elif method == 'GetSession': session = server.jellyfin.get_device(self.device_id) self.void_responder(data, session) elif method == 'GetUsers': users = server.jellyfin.get_users() self.void_responder(data, users) elif method == 'GetTranscodeOptions': result = server.jellyfin.get_transcode_settings() self.void_responder(data, result) elif method == 'GetThemes': if data['Type'] == 'Video': theme = server.jellyfin.get_items_theme_video(data['Id']) else: theme = server.jellyfin.get_items_theme_song(data['Id']) self.void_responder(data, theme) elif method == 'GetTheme': theme = server.jellyfin.get_themes(data['Id']) self.void_responder(data, theme) elif method == 'Browse': result = downloader.get_filtered_section(data.get('Id'), data.get('Media'), data.get('Limit'), data.get('Recursive'), data.get('Sort'), data.get('SortOrder'), data.get('Filters'), data.get('Params'), data.get('ServerId')) self.void_responder(data, result) elif method == 'BrowseSeason': result = server.jellyfin.get_seasons(data['Id']) self.void_responder(data, result) elif method == 'LiveTV': result = server.jellyfin.get_channels() self.void_responder(data, result) elif method == 'RecentlyAdded': result = server.jellyfin.get_recently_added( data.get('Media'), data.get('Id'), data.get('Limit')) self.void_responder(data, result) elif method == 'Genres': result = server.jellyfin.get_genres(data.get('Id')) self.void_responder(data, result) elif method == 'Recommended': result = server.jellyfin.get_recommendation( data.get('Id'), data.get('Limit')) self.void_responder(data, result) elif method == 'RefreshItem': server.jellyfin.refresh_item(data['Id']) elif method == 'FavoriteItem': server.jellyfin.favorite(data['Id'], data['Favorite']) elif method == 'DeleteItem': server.jellyfin.delete_item(data['Id']) elif method == 'PlayPlaylist': server.jellyfin.post_session( server.config.data['app.session'], "Playing", { 'PlayCommand': "PlayNow", 'ItemIds': data['Id'], 'StartPositionTicks': 0 }) elif method == 'Play': items = server.jellyfin.get_items(data['ItemIds']) PlaylistWorker(data.get('ServerId'), items, data['PlayCommand'] == 'PlayNow', data.get('StartPositionTicks', 0), data.get('AudioStreamIndex'), data.get('SubtitleStreamIndex')).start() elif method in ('ReportProgressRequested', 'Player.OnAVChange'): self.player.report_playback(data.get('Report', True)) elif method == 'Playstate': self.playstate(data) elif method == 'GeneralCommand': self.general_commands(data) elif method == 'LoadServer': self.server_instance(data['ServerId']) elif method == 'AddUser': server.jellyfin.session_add_user(server.config.data['app.session'], data['Id'], data['Add']) self.additional_users(server) elif method == 'Player.OnPlay': on_play(data, server) elif method == 'VideoLibrary.OnUpdate': on_update(data, server)
def showOSD(self): self.setProperty('show.OSD', '1') xbmc.executebuiltin('Dialog.Close(videoosd,true)') if xbmc.getCondVisibility('Player.showinfo'): xbmc.executebuiltin('Action(Info)') self.setFocusId(self.PLAY_PAUSE_BUTTON_ID)
def service(self): ''' If error is encountered, it will rerun this function. Start new "daemon threads" to process library updates. (actual daemon thread is not supported in Kodi) ''' self.download_threads = [ thread for thread in self.download_threads if not thread.is_done ] self.writer_threads['updated'] = [ thread for thread in self.writer_threads['updated'] if not thread.is_done ] self.writer_threads['userdata'] = [ thread for thread in self.writer_threads['userdata'] if not thread.is_done ] self.writer_threads['removed'] = [ thread for thread in self.writer_threads['removed'] if not thread.is_done ] if not self.player.isPlayingVideo() or settings( 'syncDuringPlay.bool') or xbmc.getCondVisibility( 'VideoPlayer.Content(livetv)'): self.worker_downloads() self.worker_sort() self.worker_updates() self.worker_userdata() self.worker_remove() self.worker_notify() if self.pending_refresh: window('jellyfin_sync.bool', True) if self.total_updates > self.progress_display: queue_size = self.worker_queue_size() if self.progress_updates is None: self.progress_updates = xbmcgui.DialogProgressBG() self.progress_updates.create(translate('addon_name'), translate(33178)) self.progress_updates.update( int((float(self.total_updates - queue_size) / float(self.total_updates)) * 100), message="%s: %s" % (translate(33178), queue_size)) elif queue_size: self.progress_updates.update( int((float(self.total_updates - queue_size) / float(self.total_updates)) * 100), message="%s: %s" % (translate(33178), queue_size)) else: self.progress_updates.update(int( (float(self.total_updates - queue_size) / float(self.total_updates)) * 100), message=translate(33178)) if not settings( 'dbSyncScreensaver.bool') and self.screensaver is None: xbmc.executebuiltin('InhibitIdleShutdown(true)') self.screensaver = get_screensaver() set_screensaver(value="") if (self.pending_refresh and not self.download_threads and not self.writer_threads['updated'] and not self.writer_threads['userdata'] and not self.writer_threads['removed']): self.pending_refresh = False self.save_last_sync() self.total_updates = 0 window('jellyfin_sync', clear=True) if self.progress_updates: self.progress_updates.close() self.progress_updates = None if not settings( 'dbSyncScreensaver.bool') and self.screensaver is not None: xbmc.executebuiltin('InhibitIdleShutdown(false)') set_screensaver(value=self.screensaver) self.screensaver = None if xbmc.getCondVisibility('Container.Content(musicvideos)' ): # Prevent cursor from moving xbmc.executebuiltin('Container.Refresh') else: # Update widgets xbmc.executebuiltin('UpdateLibrary(video)') if xbmc.getCondVisibility('Window.IsMedia'): xbmc.executebuiltin('Container.Refresh')
def trackIsPlaying(track): return xbmc.getCondVisibility('String.StartsWith(MusicPlayer.Comment,{0})'.format('PLEX-{0}:'.format(track.ratingKey)))