def _mnt_path(cls): ''' Return mount path, usually ~/.kodi/userdata/addon_data/tmp/mnt ''' mnt_path = os.path.join(cls._temp_path(), 'mnt') if not xbmcvfs.exists(mnt_path): xbmcvfs.mkdir(mnt_path) return mnt_path
def get_device_id(reset=False): ''' Return the device_id if already loaded. It will load from jellyfin_guid file. If it's a fresh setup, it will generate a new GUID to uniquely identify the setup for all users. window prop: jellyfin_deviceId ''' client_id = window('jellyfin_deviceId') if client_id: return client_id directory = xbmc.translatePath( 'special://profile/addon_data/plugin.video.jellyfin/') if not xbmcvfs.exists(directory): xbmcvfs.mkdir(directory) jellyfin_guid = os.path.join(directory, "jellyfin_guid") file_guid = xbmcvfs.File(jellyfin_guid) client_id = file_guid.read() if not client_id or reset: LOG.debug("Generating a new GUID.") client_id = str(create_id()) file_guid = xbmcvfs.File(jellyfin_guid, 'w') file_guid.write(client_id) file_guid.close() LOG.debug("DeviceId loaded: %s", client_id) window('jellyfin_deviceId', value=client_id) return client_id
def _temp_path(cls): ''' Return temporary path, usually ~/.kodi/userdata/addon_data/tmp ''' temp_path = os.path.join(ADDON_PROFILE, 'tmp') if not xbmcvfs.exists(temp_path): xbmcvfs.mkdir(temp_path) return temp_path
def selectPath(self, url, bypass=False): log('selectPath, url = ' + str(url)) newURL = url while not self.myMonitor.abortRequested(): items = list(self.buildItems(url)) if len(items) == 0: break elif len(items) == 2 and not bypass and items[0].getLabel().lower( ) == 'parent directory' and not items[1].getLabel().startswith( '.apk'): select = 1 #If one folder bypass selection. else: select = selectDialog( url.replace(BASE_URL, './').replace('//', '/'), items) if select is None: return #return on cancel. label = items[select].getLabel() newURL = items[select].getPath() preURL = url.rsplit('/', 2)[0] + '/' if newURL.endswith('.apk'): if not xbmcvfs.exists(SETTINGS_LOC): xbmcvfs.mkdir(SETTINGS_LOC) dest = xbmc.translatePath(os.path.join(SETTINGS_LOC, label)) self.setLastPath(url, dest) return self.downloadAPK(newURL, dest) elif label.lower( ) == 'parent directory' and "android" in preURL.lower(): return self.selectPath(preURL, True) elif label.lower( ) == 'parent directory' and "android" not in preURL.lower(): return self.selectPath(self.buildMain(), False) url = newURL + '/'
def verify_kodi_defaults(): ''' Make sure we have the kodi default folder in place. ''' node_path = xbmc.translatePath("special://profile/library/video") if not os.path.exists(node_path): try: shutil.copytree( src=xbmc.translatePath("special://xbmc/system/library/video"), dst=xbmc.translatePath("special://profile/library/video")) except Exception as error: LOG.warning(error) xbmcvfs.mkdir(node_path) for index, node in enumerate(['movies', 'tvshows', 'musicvideos']): file = os.path.join(node_path, node, "index.xml") if xbmcvfs.exists(file): xml = etree.parse(file).getroot() xml.set('order', str(17 + index)) tree = etree.ElementTree(xml) tree.write(file) playlist_path = xbmc.translatePath("special://profile/playlists/video") if not xbmcvfs.exists(playlist_path): xbmcvfs.mkdirs(playlist_path)
def download_external_subs(cls, src, filename): ''' Download external subtitles to temp folder to be able to have proper names to streams. ''' temp = xbmc.translatePath( "special://profile/addon_data/plugin.video.jellyfin/temp/") if not xbmcvfs.exists(temp): xbmcvfs.mkdir(temp) path = os.path.join(temp, filename) try: response = requests.get(src, stream=True, verify=False) response.raise_for_status() except Exception as error: LOG.exception(error) raise else: response.encoding = 'utf-8' with open(path, 'wb') as f: f.write(response.content) del response return path
def toggle(self, mode): # create profile file if not xbmcvfs.exists(ADDON_PATH_DATA): xbmcvfs.mkdir(ADDON_PATH_DATA) # try read last active profile f = xbmcvfs.File(os.path.join(ADDON_PATH_DATA, 'profile')) try: profile = f.read() except IOError: profile = '' f.close() if profile: if (len(self.aProfile) == 1) or (profile not in self.aProfile): profile = self.aProfile[0] else: ip = int(self.aProfile.index(profile)) if len(self.aProfile) == ip: try: profile = self.aProfile[0] except IndexError: profile = self.aProfile[0] else: try: profile = self.aProfile[ip + 1] except IndexError: profile = self.aProfile[0] else: profile = self.aProfile[0] self.profile(profile)
def _ia_cdm_path(cls): """Return the specified CDM path for inputstream.adaptive.""" addon = xbmcaddon.Addon('inputstream.adaptive') cdm_path = xbmc.translatePath(addon.getSetting('DECRYPTERPATH')) if not xbmcvfs.exists(cdm_path): xbmcvfs.mkdir(cdm_path) return cdm_path
def __init__(self): self.path = xbmc.translatePath(__addon__.getAddonInfo("profile")) if not xbmcvfs.exists(self.path): logger.debug("Making path structure: %s" % repr(self.path)) xbmcvfs.mkdir(self.path) self.path = os.path.join(self.path, 'queue.db') self._connection_cache = {} with self._get_conn() as conn: conn.execute(self._create)
def add_nodes(self, path, view, mixed=False): ''' Create or update the video node file. ''' folder = os.path.join(path, "jellyfin%s%s" % (view['Media'], view['Id'])) if not xbmcvfs.exists(folder): xbmcvfs.mkdir(folder) self.node_index(folder, view, mixed) if view['Media'] == 'tvshows': self.node_tvshow(folder, view) else: self.node(folder, view)
def _makedirs(path): if len(path) == 0: return False if(xbmcvfs.exists(path)): return True success = xbmcvfs.mkdir(path) if success == False: if path == os.path.dirname(xbmcvfs.translatePath(path)): return False if FileAccess._makedirs(os.path.dirname(xbmcvfs.translatePath(path))): return xbmcvfs.mkdir(path) return xbmcvfs.exists(path)
def _get_connection(): try: xbmcvfs.mkdir(xbmc.translatePath(addonInfo('profile')).decode('utf-8')) except AttributeError: xbmcvfs.mkdir(xbmc.translatePath(addonInfo('profile'))) try: conn = db.connect( os.path.join( xbmc.translatePath(addonInfo('profile')).decode('utf-8'), 'cache.db')) except AttributeError: conn = db.connect( os.path.join(xbmc.translatePath(addonInfo('profile')), 'cache.db')) conn.row_factory = _dict_factory return conn
def copy_recursive(path, dirs, dest): for directory in dirs: dirs_dir = os.path.join(path, directory) dest_dir = os.path.join(dest, directory) xbmcvfs.mkdir(dest_dir) dirs2, files = xbmcvfs.listdir(dirs_dir) if dirs2: copy_recursive(dirs_dir, dirs2, dest_dir) for file in files: copy_file(os.path.join(dirs_dir, file), os.path.join(dest_dir, file))
def copy_directory_contents_xbmcvfs(directory_from, directory_to): overall_success = True files_out = list() dirs_in_dir, files_in_dir = xbmcvfs.listdir( os.path.join(directory_from, '')) for ff in files_in_dir: if not xbmcvfs.copy( os.path.join(directory_from, ff), os.path.join( directory_to, ff)): #If move does not work, then copy overall_success = False else: xbmc.log( msg= 'Retro BIOS Tool: The file was copied from: %(file_from)s, to: %(file_to)s' % { 'file_from': os.path.join(directory_from, ff), 'file_to': os.path.join(directory_to, ff) }, level=xbmc.LOGDEBUG) files_out.append(os.path.join(directory_to, ff)) for dd in dirs_in_dir: if xbmcvfs.exists(os.path.join(directory_to, dd, '')) or xbmcvfs.mkdir( os.path.join(directory_to, dd)): files_out2, success = copy_directory_contents_xbmcvfs( os.path.join(directory_from, dd), os.path.join(directory_to, dd)) files_out = files_out + files_out2 else: overall_success = False return files_out, overall_success
def unzip(path, dest, folder=None): ''' Unzip file. zipfile module seems to fail on android with badziperror. ''' path = quote_plus(path) root = "zip://" + path + '/' if folder: xbmcvfs.mkdir(os.path.join(dest, folder)) dest = os.path.join(dest, folder) root = get_zip_directory(root, folder) dirs, files = xbmcvfs.listdir(root) if dirs: unzip_recursive(root, dirs, dest) for file in files: unzip_file(os.path.join(root, file), os.path.join(dest, file)) LOG.info("Unzipped %s", path)
def _mnt_path(cls): mnt_path = os.path.join(cls._temp_path(), 'mnt') if not xbmcvfs.exists(mnt_path): xbmcvfs.mkdir(mnt_path) return mnt_path
def _temp_path(cls): temp_path = os.path.join(ADDON_PROFILE, 'tmp') if not xbmcvfs.exists(temp_path): xbmcvfs.mkdir(temp_path) return temp_path
def get_themes(api_client): ''' 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 = translate_path( "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", "{jellyfin}", translate(33152)) return with Database('jellyfin') as jellyfindb: all_views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views() views = [ x.view_id for x in all_views if x.media_type in ('movies', 'tvshows', 'mixed') ] items = {} server = api_client.config.data['auth.server'] for view in views: result = api_client.get_items_theme_video(view) for item in result['Items']: folder = normalize_string(item['Name']) items[item['Id']] = folder result = api_client.get_items_theme_song(view) 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 = api_client.get_themes(item) paths = [] for theme in themes['ThemeVideosResult']['Items'] + themes[ 'ThemeSongsResult']['Items']: putils = PlayUtils(theme, False, None, server, api_client) 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 downloadVideo(url, name): def _pbhook(downloaded, filesize, url=None, dp=None, name=''): try: percent = min(int((downloaded * 100) / filesize), 100) currently_downloaded = float(downloaded) / (1024 * 1024) kbps_speed = int(downloaded / (time.perf_counter() if PY3 else time.clock() - start)) if kbps_speed > 0: eta = (filesize - downloaded) / kbps_speed else: eta = 0 kbps_speed = kbps_speed / 1024 total = float(filesize) / (1024 * 1024) mbs = '%.02f MB of %.02f MB' % (currently_downloaded, total) e = 'Speed: %.02f Kb/s ' % kbps_speed e += 'ETA: %02d:%02d' % divmod(eta, 60) dp.update(percent, '{0}[CR]{1}[CR]{2}'.format(name[:50], mbs, e)) except: percent = 100 dp.update(percent) if dp.iscanceled(): dp.close() raise StopDownloading('Stopped Downloading') def getResponse(url, headers2, size): try: if size > 0: size = int(size) headers2['Range'] = 'bytes=%d-' % size req = Request(url, headers=headers2) resp = urlopen(req, timeout=30) return resp except: return None def doDownload(url, dest, dp, name): headers = {} if '|' in url: url, uheaders = url.split('|') headers = dict(urllib_parse.parse_qsl(uheaders)) if 'User-Agent' not in list(headers.keys()): headers.update({'User-Agent': USER_AGENT}) resp = getResponse(url, headers, 0) if not resp: dialog.ok("Cumination", '{0}[CR]{1}'.format(i18n('dnld_fail'), i18n('no_resp'))) return False try: content = int(resp.headers['Content-Length']) except: content = 0 try: resumable = 'bytes' in resp.headers['Accept-Ranges'].lower() except: resumable = False if resumable: six.print_("Download is resumable") if content < 1: dialog.ok("Cumination", '{0}[CR]{1}'.format(i18n('unkn_size'), i18n('no_dnld'))) return False size = 8192 mb = content / (1024 * 1024) if content < size: size = content total = 0 errors = 0 count = 0 resume = 0 sleep = 0 six.print_('{0} : {1}MB {2} '.format(i18n('file_size'), mb, dest)) f = xbmcvfs.File(dest, 'w') chunk = None chunks = [] while True: downloaded = total for c in chunks: downloaded += len(c) percent = min(100 * downloaded / content, 100) _pbhook(downloaded, content, url, dp, name) chunk = None error = False try: chunk = resp.read(size) if not chunk: if percent < 99: error = True else: while len(chunks) > 0: c = chunks.pop(0) f.write(c) del c f.close() return True except Exception as e: six.print_(str(e)) error = True sleep = 10 errno = 0 if hasattr(e, 'errno'): errno = e.errno if errno == 10035: # 'A non-blocking socket operation could not be completed immediately' pass if errno == 10054: # 'An existing connection was forcibly closed by the remote host' errors = 10 # force resume sleep = 30 if errno == 11001: # 'getaddrinfo failed' errors = 10 # force resume sleep = 30 if chunk: errors = 0 chunks.append(chunk) if len(chunks) > 5: c = chunks.pop(0) f.write(c) total += len(c) del c if error: errors += 1 count += 1 xbmc.sleep(sleep * 1000) if (resumable and errors > 0) or errors >= 10: if (not resumable and resume >= 50) or resume >= 500: # Give up! return False resume += 1 errors = 0 if resumable: chunks = [] # create new response resp = getResponse(url, headers, total) else: # use existing response pass def clean_filename(s): if not s: return '' badchars = '\\/:*?\"<>|\'' for c in badchars: s = s.replace(c, '') return s.strip() download_path = addon.getSetting('download_path') if download_path == '': try: download_path = dialog.browse(0, i18n('dnld_path'), "", "", False, False) addon.setSetting(id='download_path', value=download_path) if not xbmcvfs.exists(download_path): xbmcvfs.mkdir(download_path) except: pass if download_path != '': dp = xbmcgui.DialogProgress() name = re.sub(r'\[COLOR.+?\/COLOR\]', '', name).strip() dp.create(i18n('cum_dnld'), name[:50]) tmp_file = tempfile.mktemp(dir=download_path, suffix=".mp4") tmp_file = xbmc.makeLegalFilename(tmp_file) if PY2 else xbmcvfs.makeLegalFilename(tmp_file) start = time.perf_counter() if PY3 else time.clock() try: downloaded = doDownload(url, tmp_file, dp, name) if downloaded: if PY2: vidfile = xbmc.makeLegalFilename(download_path + clean_filename(name) + ".mp4") else: vidfile = xbmcvfs.makeLegalFilename(download_path + clean_filename(name) + ".mp4") try: xbmcvfs.rename(tmp_file, vidfile) return vidfile except: return tmp_file else: raise StopDownloading(i18n('stop_dnld')) except: while xbmcvfs.exists(tmp_file): try: xbmcvfs.delete(tmp_file) break except: pass
def rbt_main(): # WIN = xbmcgui.Window(10000) # WIN.clearProperty('rbt.script_started') # if not WIN.getProperty('rbt.script_started'): xbmc.log(msg='Retro BIOS Tool: Tool Started', level=xbmc.LOGINFO) # WIN.setProperty('rbt.script_started','True') addon_name = 'plugin.program.retrobiostool' addon_handle = xbmcaddon.Addon(id='%(addon_name)s' % {'addon_name': addon_name}) bios_folder = addon_handle.getSetting(id='rbt_folder') if addon_handle.getSetting(id='rbt_generate_report') == 'true': generate_report = True else: generate_report = False addon_timeout = 5 bios_keyword = [ 'firmware%(number)s_path' % { 'number': x } for x in range(0, 21) ] libretro_git = r'https://raw.githubusercontent.com/libretro/libretro-super/master/dist/info/xxx_core_xxx.info' #These games are already known to not require any system/bios files, so skip them to make the tool faster ignore_these_addons = [ 'game.libretro', 'game.libretro.2048', 'game.libretro.2048_libretro_buildbot', 'game.libretro.81', 'game.libretro.81_libretro_buildbot', 'game.libretro.beetle-bsnes', 'game.libretro.beetle-bsnes_libretro_buildbot', 'game.libretro.beetle-bsnes_cplusplus98', 'game.libretro.beetle-bsnes_cplusplus98_libretro_buildbot', 'game.libretro.beetle-ngp', 'game.libretro.beetle-ngp_libretro_buildbot', 'game.libretro.beetle-vb', 'game.libretro.beetle-vb_libretro_buildbot', 'game.libretro.beetle-wswan', 'game.libretro.beetle-wswan_libretro_buildbot', 'game.libretro.bnes', 'game.libretro.bnes_libretro_buildbot', 'game.libretro.cannonball', 'game.libretro.cannonball_libretro_buildbot', 'game.libretro.cap32', 'game.libretro.cap32_libretro_buildbot', 'game.libretro.chailove', 'game.libretro.chailove_libretro_buildbot', 'game.libretro.craft', 'game.libretro.craft_libretro_buildbot', 'game.libretro.crocods', 'game.libretro.crocods_libretro_buildbot', 'game.libretro.daphne', 'game.libretro.daphne_libretro_buildbot', 'game.libretro.dinothawr', 'game.libretro.dinothawr_libretro_buildbot', 'game.libretro.dosbox', 'game.libretro.dosbox_libretro_buildbot', 'game.libretro.dosbox_svn', 'game.libretro.dosbox_svn_libretro_buildbot', 'game.libretro.easyrpg', 'game.libretro.easyrpg_libretro_buildbot', 'game.libretro.emux_nes', 'game.libretro.emux_nes_libretro_buildbot', 'game.libretro.fbalpha', 'game.libretro.fbalpha2012', 'game.libretro.fbalpha2012_libretro_buildbot', 'game.libretro.fbalpha2012_cps1', 'game.libretro.fbalpha2012_cps1_libretro_buildbot', 'game.libretro.fbalpha2012_cps2', 'game.libretro.fbalpha2012_cps2_libretro_buildbot', 'game.libretro.fbalpha2012_neogeo', 'game.libretro.fbalpha2012_neogeo_libretro_buildbot', 'game.libretro.fbalpha_libretro_buildbot', 'game.libretro.fuse', 'game.libretro.fuse_libretro_buildbot', 'game.libretro.gearboy', 'game.libretro.gearboy_libretro_buildbot', 'game.libretro.gearsystem', 'game.libretro.gearsystem_libretro_buildbot', 'game.libretro.gme', 'game.libretro.gme_libretro_buildbot', 'game.libretro.gw', 'game.libretro.gw_libretro_buildbot', 'game.libretro.lutro', 'game.libretro.lutro_libretro_buildbot', 'game.libretro.mednafen_ngp', 'game.libretro.mednafen_ngp_libretro_buildbot', 'game.libretro.mednafen_snes', 'game.libretro.mednafen_snes_libretro_buildbot', 'game.libretro.mednafen_vb', 'game.libretro.mednafen_vb_libretro_buildbot', 'game.libretro.mednafen_wswan', 'game.libretro.mednafen_wswan_libretro_buildbot', 'game.libretro.meteor', 'game.libretro.meteor_libretro_buildbot', 'game.libretro.mrboom', 'game.libretro.mrboom_libretro_buildbot', 'game.libretro.nekop2', 'game.libretro.nekop2_libretro_buildbot', 'game.libretro.nx', 'game.libretro.nx_libretro_buildbot', 'game.libretro.nxengine', 'game.libretro.nxengine_libretro_buildbot', 'game.libretro.openlara', 'game.libretro.openlara_libretro_buildbot', 'game.libretro.pocketcdg', 'game.libretro.pocketcdg_libretro_buildbot', 'game.libretro.prboom', 'game.libretro.prboom_libretro_buildbot', 'game.libretro.quicknes', 'game.libretro.quicknes_libretro_buildbot', 'game.libretro.reminiscence', 'game.libretro.reminiscence_libretro_buildbot', 'game.libretro.scummvm', 'game.libretro.scummvm_libretro_buildbot', 'game.libretro.snes9x2002', 'game.libretro.snes9x2002_libretro_buildbot', 'game.libretro.snes9x2005', 'game.libretro.snes9x2005_libretro_buildbot', 'game.libretro.snes9x2005_plus', 'game.libretro.snes9x2005_plus_libretro_buildbot', 'game.libretro.snes9x2010', 'game.libretro.snes9x2010_libretro_buildbot', 'game.libretro.stella', 'game.libretro.stella2014', 'game.libretro.stella2014_libretro_buildbot', 'game.libretro.stella_libretro_buildbot', 'game.libretro.tgbdual', 'game.libretro.tgbdual_libretro_buildbot', 'game.libretro.theodore', 'game.libretro.theodore_libretro_buildbot', 'game.libretro.thepowdertoy', 'game.libretro.thepowdertoy_libretro_buildbot', 'game.libretro.tyrquake', 'game.libretro.tyrquake_libretro_buildbot', 'game.libretro.vecx', 'game.libretro.vecx_libretro_buildbot', 'game.libretro.vice_x128', 'game.libretro.vice_x128_libretro_buildbot', 'game.libretro.vice_x64', 'game.libretro.vice_x64_libretro_buildbot', 'game.libretro.vice_x64sc', 'game.libretro.vice_x64sc_libretro_buildbot', 'game.libretro.vice_xplus4', 'game.libretro.vice_xplus4_libretro_buildbot', 'game.libretro.vice_xvic', 'game.libretro.vice_xvic_libretro_buildbot', 'game.libretro.virtualjaguar', 'game.libretro.virtualjaguar_libretro_buildbot', 'game.libretro.xrick', 'game.libretro.xrick_libretro_buildbot' ] #Rename the following addons to match libretro naming retroplayer_to_libretro_map = { 'bsnes-mercury-accuracy': 'bsnes_mercury_accuracy', 'bsnes-mercury-balanced': 'bsnes_mercury_balanced', 'bsnes-mercury-performance': 'bsnes_mercury_performance', 'genplus': 'genesis_plus_gx', 'beetle-gba': 'mednafen_gba', 'beetle-lynx': 'mednafen_lynx', 'beetle-ngp': 'mednafen_ngp', 'beetle-pce-fast': 'mednafen_pce_fast', 'beetle-pcfx': 'mednafen_pcfx', 'beetle-psx': 'mednafen_psx', 'beetle-saturn': 'mednafen_saturn', 'beetle-bsnes': 'mednafen_snes', 'beetle-supergrafx': 'mednafen_supergrafx', 'beetle-vb': 'mednafen_vb', 'beetle-wswan': 'mednafen_wswan', 'pcsx-rearmed': 'pcsx_rearmed', 'uae': 'puae', 'vba-next': 'vba_next', 'vice': 'vice_x64' } #These special cases have folders listed in their info files rather than all the individual files, need to copy the entire folder special_folder_cases_map = { 'game.libretro.bluemsx': ['Databases', 'Machines'], 'game.libretro.bluemsx_libretro_buildbot': ['Databases', 'Machines'], 'game.libretro.reicast': ['dc'], 'game.libretro.dolphin_libretro_buildbot': ['dolphin-emu'], 'game.libretro.dolphin': ['dolphin-emu'], 'game.libretro.mame': ['mame'], 'game.libretro.mame_libretro_buildbot': ['mame'], 'game.libretro.mame2000': ['mame2000'], 'game.libretro.mame2000_libretro_buildbot': ['mame2000'], 'game.libretro.mame2003': ['mame2003'], 'game.libretro.mame2003_libretro_buildbot': ['mame2003'], 'game.libretro.mame2003_plus': ['mame2003-plus'], 'game.libretro.mame2003_plus_libretro_buildbot': ['mame2003-plus'], 'game.libretro.mame2010': ['mame2010'], 'game.libretro.mame2010_libretro_buildbot': ['mame2010'], 'game.libretro.mame2014': ['mame2014'], 'game.libretro.mame2014_libretro_buildbot': ['mame2014'], 'game.libretro.mame2015': ['mame2015'], 'game.libretro.mame2015_libretro_buildbot': ['mame2015'], 'game.libretro.mess2015': ['mess2015'], 'game.libretro.mess2015_libretro_buildbot': ['mess2015'], 'game.libretro.ppsspp': ['PPSSPP'], 'game.libretro.ppsspp_libretro_buildbot': ['PPSSPP'], 'game.libretro.puae': ['uae_data'], 'game.libretro.puae_libretro_buildbot': ['uae_data'], 'game.libretro.ume2014': ['ume2014'], 'game.libretro.ume2014_libretro_buildbot': ['ume2014'], } #Initialize report dict report_data = dict() report_data['addon_id'] = list() report_data['firmware_listed'] = list() report_data['firmware_files'] = list() report_data['firmware_found'] = list() report_data['info_file'] = list() if bios_folder is None or len(bios_folder) < 1: current_dialog = xbmcgui.Dialog() ret = current_dialog.ok( 'Retro BIOS Tool', 'The tool did not run.[CR]Enter a BIOS file location in settings first!' ) else: try: addons_available = xbmc.executeJSONRPC( '{ "jsonrpc": "2.0", "method": "Addons.GetAddons","params":{"type":"kodi.gameclient", "enabled": true}, "id": "1"}' ) addon_ids = [ x.get('addonid') for x in json.loads(addons_available).get( 'result').get('addons') if x.get('type') == 'kodi.gameclient' and x.get('addonid') not in ignore_these_addons ] xbmc.log( msg= 'Retro BIOS Tool: The following addons will be checked %(current_aids)s' % {'current_aids': ', '.join(addon_ids)}, level=xbmc.LOGDEBUG) except: addon_ids = None if addon_ids is not None: total_files_copied = 0 dp = xbmcgui.DialogProgress() dp.create('Retro BIOS Tools', 'Checking for BIOS Files') dp.update(0) s = requests.Session() for iiaid, aid in enumerate(addon_ids): dp.update(int(100 * (iiaid + 1) / len(addon_ids))) xbmc.log( msg='Retro BIOS Tool: Checking addon %(current_aid)s' % {'current_aid': aid}, level=xbmc.LOGINFO) report_data['addon_id'].append(aid) report_data['firmware_listed'].append(False) report_data['firmware_files'].append(None) report_data['firmware_found'].append(None) report_data['info_file'].append('') if dp.iscanceled(): run_was_cancelled = True dp.close() raise if aid.replace('game.libretro.', '').replace( '_libretro_buildbot', '') in retroplayer_to_libretro_map.keys(): current_git_url = libretro_git.replace( 'xxx_core_xxx', retroplayer_to_libretro_map[aid.replace( 'game.libretro.', '').replace( '_libretro_buildbot', '')] + '_libretro') else: current_git_url = libretro_git.replace( 'xxx_core_xxx', aid.replace('game.libretro.', '').replace( '_libretro_buildbot', '') + '_libretro') xbmc.log( msg= 'Retro BIOS Tool: Checking libretro for core info at %(current_git_url)s' % {'current_git_url': current_git_url}, level=xbmc.LOGDEBUG) try: r = s.get(current_git_url, verify=False, stream=True, timeout=addon_timeout) except Exception as current_exc: xbmc.log( msg= 'Retro BIOS Tool: Error getting libretro for core info at %(current_exc)s' % {'current_exc': current_exc}, level=xbmc.LOGDEBUG) current_info = r.text if len(current_info) > 0: report_data['info_file'][-1] = current_info current_bios_files = list() for bk in bios_keyword: current_check = re.findall( r'%(current_bk)s\s+=\s+\"(.*?)\"' % {'current_bk': bk}, current_info) if current_check is not None and len(current_check) > 0: current_bios_files.append(current_check[0].strip()) if len(current_bios_files) > 0: report_data['firmware_listed'][-1] = True if type(current_bios_files) is list: report_data['firmware_files'][-1] = current_bios_files report_data['firmware_found'][-1] = [ False for x in current_bios_files ] else: report_data['firmware_files'][-1] = [ current_bios_files ] report_data['firmware_found'][-1] = [False] xbmc.log( msg= 'Retro BIOS Tool: Looking for the following bios files %(current_files)s' % {'current_files': ', '.join(current_bios_files)}, level=xbmc.LOGDEBUG) current_addon = xbmcaddon.Addon(id='%(addon_name)s' % {'addon_name': aid}) current_addon_data_folder = py2_decode( xbmc.translatePath( current_addon.getAddonInfo('profile'))) current_addon_resources_folder = os.path.join( current_addon_data_folder, 'resources') current_addon_systems_folder = os.path.join( current_addon_resources_folder, 'system') for cbf in current_bios_files: current_bios_fullpath = os.path.join( bios_folder, *os.path.split(cbf)) if xbmcvfs.exists(current_bios_fullpath): xbmc.log( msg= 'Retro BIOS Tool: Found file %(current_cbf)s' % {'current_cbf': cbf}, level=xbmc.LOGDEBUG) if not xbmcvfs.exists( os.path.join(current_addon_data_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: The folder %(current_folder)s does not yet exist, so it will be created' % { 'current_folder': current_addon_data_folder }, level=xbmc.LOGDEBUG) if not xbmcvfs.mkdir( os.path.join(current_addon_data_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: Unable to create addon_data folder', level=xbmc.LOGERROR) if not xbmcvfs.exists( os.path.join( current_addon_resources_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: The folder %(current_folder)s does not yet exist, so it will be created' % { 'current_folder': current_addon_resources_folder }, level=xbmc.LOGDEBUG) if not xbmcvfs.mkdir( os.path.join( current_addon_resources_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: Unable to create addon_data resources folder', level=xbmc.LOGERROR) if not xbmcvfs.exists( os.path.join(current_addon_systems_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: The folder %(current_folder)s does not yet exist, so it will be created' % { 'current_folder': current_addon_systems_folder }, level=xbmc.LOGDEBUG) if not xbmcvfs.mkdir( os.path.join( current_addon_systems_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: Unable to create addon_data resources/system folder', level=xbmc.LOGERROR) if not xbmcvfs.exists( os.path.join(current_addon_systems_folder, cbf)): if xbmcvfs.copy( os.path.join(bios_folder, cbf), os.path.join( current_addon_systems_folder, cbf) ): #Copy the file to the correct system folder xbmc.log( msg= 'Retro BIOS Tool: Copying file %(current_cbf)s to %(current_folder)s' % { 'current_cbf': os.path.join(bios_folder, cbf), 'current_folder': os.path.join( current_addon_systems_folder, cbf) }, level=xbmc.LOGINFO) total_files_copied = total_files_copied + 1 report_data['firmware_found'][-1][ report_data['firmware_files'] [-1].index(cbf)] = True else: xbmc.log( msg= 'Retro BIOS Tool: Error copying file %(current_cbf)s to %(current_folder)s' % { 'current_cbf': os.path.join(bios_folder, cbf), 'current_folder': os.path.join( current_addon_systems_folder, cbf) }, level=xbmc.LOGERROR) else: xbmc.log( msg= 'Retro BIOS Tool: BIOS file %(current_cbf)s already present in %(current_folder)s' % { 'current_cbf': cbf, 'current_folder': os.path.join( current_addon_systems_folder, cbf) }, level=xbmc.LOGDEBUG) report_data['firmware_found'][-1][report_data[ 'firmware_files'][-1].index(cbf)] = True else: if xbmcvfs.exists( os.path.join(current_addon_systems_folder, cbf)): report_data['firmware_found'][-1][report_data[ 'firmware_files'][-1].index(cbf)] = True else: report_data['firmware_found'][-1][report_data[ 'firmware_files'][-1].index(cbf)] = False xbmc.log( msg= 'Retro BIOS Tool: Unable to find the file in your BIOS folder %(current_cbf)s ' % { 'current_cbf': os.path.join( bios_folder, cbf) }, level=xbmc.LOGERROR) else: xbmc.log( msg= 'Retro BIOS Tool: No bios files found for %(current_aid)s' % {'current_aid': aid}, level=xbmc.LOGDEBUG) report_data['firmware_listed'][-1] = False #Check folder specific cases if aid in special_folder_cases_map.keys(): current_addon = xbmcaddon.Addon(id='%(addon_name)s' % {'addon_name': aid}) current_addon_data_folder = py2_decode( xbmc.translatePath( current_addon.getAddonInfo('profile'))) current_addon_resources_folder = os.path.join( current_addon_data_folder, 'resources') current_addon_systems_folder = os.path.join( current_addon_resources_folder, 'system') current_bios_folder_fullpaths = [ os.path.join(bios_folder, x) for x in special_folder_cases_map[aid] ] current_ind_folders = [ x for x in special_folder_cases_map[aid] ] for cbfi, current_bios_folder_fullpath in enumerate( current_bios_folder_fullpaths): report_data['firmware_listed'][-1] = True report_data['firmware_files'][-1] = [ ', '.join([ x + ' (Folder)' for x in special_folder_cases_map[aid] ]) ] report_data['firmware_found'][-1] = [False] xbmc.log( msg= 'Retro BIOS Tool: Looking for the following bios folder %(current_folder)s' % {'current_folder': current_ind_folders[cbfi]}, level=xbmc.LOGDEBUG) if xbmcvfs.exists( os.path.join(current_bios_folder_fullpath, '')): if not xbmcvfs.exists( os.path.join(current_addon_data_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: The folder %(current_folder)s does not yet exist, so it will be created' % { 'current_folder': current_addon_data_folder }, level=xbmc.LOGDEBUG) if not xbmcvfs.mkdir( os.path.join(current_addon_data_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: Unable to create addon_data folder', level=xbmc.LOGERROR) if not xbmcvfs.exists( os.path.join( current_addon_resources_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: The folder %(current_folder)s does not yet exist, so it will be created' % { 'current_folder': current_addon_resources_folder }, level=xbmc.LOGDEBUG) if not xbmcvfs.mkdir( os.path.join( current_addon_resources_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: Unable to create addon_data resources folder', level=xbmc.LOGERROR) if not xbmcvfs.exists( os.path.join(current_addon_systems_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: The folder %(current_folder)s does not yet exist, so it will be created' % { 'current_folder': current_addon_systems_folder }, level=xbmc.LOGDEBUG) if not xbmcvfs.mkdir( os.path.join( current_addon_systems_folder, '')): xbmc.log( msg= 'Retro BIOS Tool: Unable to create addon_data resources/system folder', level=xbmc.LOGERROR) if not xbmcvfs.exists( os.path.join(current_addon_systems_folder, current_ind_folders[cbfi], '')): copied_folder_files, folder_copy_success = copy_directory_contents_xbmcvfs( current_bios_folder_fullpath, os.path.join(current_addon_systems_folder, current_ind_folders[cbfi])) if folder_copy_success: xbmc.log( msg= 'Retro BIOS Tool: Successfully copied the BIOS folder %(current_folder)s ' % { 'current_folder': os.path.join( bios_folder, current_ind_folders[cbfi]) }, level=xbmc.LOGDEBUG) report_data['firmware_found'][-1] = [True] total_files_copied = total_files_copied + 1 else: xbmc.log( msg= 'Retro BIOS Tool: The BIOS folder %(current_folder)s was found but could not be copied' % { 'current_folder': os.path.join( bios_folder, current_ind_folders[cbfi]) }, level=xbmc.LOGERROR) report_data['firmware_found'][-1] = [False] else: xbmc.log( msg= 'Retro BIOS Tool: The BIOS folder %(current_folder)s is already present' % { 'current_folder': os.path.join( current_addon_systems_folder, current_ind_folders[cbfi]) }, level=xbmc.LOGDEBUG) report_data['firmware_found'][-1] = [True] else: if xbmcvfs.exists( os.path.join(current_addon_systems_folder, current_ind_folders[cbfi], '')): report_data['firmware_found'][-1] = [True] xbmc.log( msg= 'Retro BIOS Tool: The BIOS folder is already present in your addon folder %(current_folder)s ' % { 'current_folder': os.path.join( current_addon_systems_folder, current_ind_folders[cbfi]) }, level=xbmc.LOGDEBUG) else: report_data['firmware_found'][-1] = [False] xbmc.log( msg= 'Retro BIOS Tool: Unable to find the folder in your BIOS folder %(current_folder)s ' % { 'current_folder': os.path.join( current_addon_systems_folder, current_ind_folders[cbfi]) }, level=xbmc.LOGDEBUG) dp.close() current_dialog = xbmcgui.Dialog() if total_files_copied > 0: ok_ret = current_dialog.ok( 'Completed', 'Tool copied %(total_files_copied)s total files.' % {'total_files_copied': total_files_copied}) else: ok_ret = current_dialog.ok( 'Completed', 'Tool did not copy any files' % {'total_files_copied': total_files_copied}) if generate_report: xbmc.log(msg='Retro BIOS Tool: Report Generated', level=xbmc.LOGDEBUG) xbmcplugin.addDirectoryItem( plugin_handle.handle, '', xbmcgui.ListItem( 'Retro BIOS Tool Report ([COLOR green]green=present[/COLOR], [COLOR red]red=missing[/COLOR]): ', offscreen=True)) for iiaid, aid in enumerate(report_data['addon_id']): report_item = 'Addon: %(current_addon_id)s, BIOS Listed: %(current_firmware_listed)s, ' % { 'current_addon_id': aid, 'current_firmware_listed': report_data['firmware_listed'][iiaid] } if report_data['firmware_listed'][iiaid]: report_subitem = 'Files: ' for icff, cff in enumerate( report_data['firmware_files'][iiaid]): if report_data['firmware_found'][iiaid][icff]: report_subitem = report_subitem + '[COLOR green]%(current_ff)s[/COLOR], ' % { 'current_ff': cff } else: report_subitem = report_subitem + '[COLOR red]%(current_ff)s[/COLOR], ' % { 'current_ff': cff } report_item = report_item + report_subitem if report_item.endswith(', '): report_item = report_item[:-2] li = xbmcgui.ListItem(report_item, offscreen=True) li.setInfo('video', { 'plot': report_subitem + '[CR]' + report_data['info_file'][iiaid] }) if xbmcvfs.exists( xbmc.translatePath( os.path.join('special://home', 'addons', str(aid), 'icon.png'))): li.setArt({ 'icon': xbmc.translatePath( os.path.join('special://home', 'addons', str(aid), 'icon.png')) }) elif xbmcvfs.exists( xbmc.translatePath( os.path.join('special://home', 'addons', str(aid), 'resources', 'icon.png'))): li.setArt({ 'icon': xbmc.translatePath( os.path.join('special://home', 'addons', str(aid), 'resources', 'icon.png')) }) elif xbmcvfs.exists( xbmc.translatePath( os.path.join('special://home', 'addons', str(aid), 'icon.jpg'))): li.setArt({ 'icon': xbmc.translatePath( os.path.join('special://home', 'addons', str(aid), 'icon.jpg')) }) elif xbmcvfs.exists( xbmc.translatePath( os.path.join('special://home', 'addons', str(aid), 'resources', 'icon.jpg'))): li.setArt({ 'icon': xbmc.translatePath( os.path.join('special://home', 'addons', str(aid), 'resources', 'icon.jpg')) }) else: xbmc.log( msg='Retro BIOS Tool: No icon found for %(current_aid)s' % {'current_aid': aid}, level=xbmc.LOGDEBUG) xbmcplugin.addDirectoryItem(plugin_handle.handle, '', li) xbmcplugin.endOfDirectory(plugin_handle.handle) else: xbmc.log(msg='Retro BIOS Tool: Report Skipped', level=xbmc.LOGDEBUG) # WIN.clearProperty('rbt.script_started') xbmc.log(msg='Retro BIOS Tool: Tool completed', level=xbmc.LOGINFO)
def check_data_dir(): if(not xbmcvfs.exists(xbmc.translatePath(data_dir()))): xbmcvfs.mkdir(xbmc.translatePath(data_dir()))
def _addon_cdm_path(cls): cdm_path = os.path.join(ADDON_PROFILE, 'cdm') if not xbmcvfs.exists(cdm_path): xbmcvfs.mkdir(cdm_path) return cdm_path
def save(self): # get audio config and save to file enabledProfiles = self.getEnabledProfiles() ret = dialog.DIALOG().start(self.xmlFile, labels={10071: ADDON_LANG(32100)}, buttons=enabledProfiles[1], thelist=10070, save_profile=True) notify.logDebug('the returned value is %s' % str(ret)) if ret is None: return False else: button = enabledProfiles[0][ret] settingsToSave = {} json_s = [ # get all settings from System / Audio section '{"jsonrpc":"2.0","method":"Settings.GetSettings", "params":{"level": "expert", "filter":{"section":"system","category":"audio"}},"id":1}', # get volume level '{"jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["volume"]}, "id": 1}', # get all settings from Player / Videos section '{"jsonrpc":"2.0","method":"Settings.GetSettings", "params":{"level": "expert", "filter":{"section":"player","category":"videoplayer"}}, "id":1}', # get all settings from System / Video section '{"jsonrpc":"2.0","method":"Settings.GetSettings", "params":{"level": "expert", "filter":{"section":"system","category":"display"}}, "id":1}' ] # send json requests for j in json_s: jsonGet = xbmc.executeJSONRPC(j) jsonGet = json.loads(jsonGet) notify.logDebug('[JSON]: %s' % str(jsonGet)) if 'result' in jsonGet: if 'settings' in jsonGet['result']: for theset in jsonGet['result']['settings']: if 'value' in theset.keys(): if theset['value'] == True or theset[ 'value'] == False: # lowercase bolean values settingsToSave[theset['id']] = str( theset['value']).lower() else: if isinstance(theset['value'], int): settingsToSave[theset['id']] = str( theset['value']) else: settingsToSave[theset['id']] = str( theset['value']).encode('utf-8') if 'volume' in jsonGet['result']: settingsToSave['volume'] = str(jsonGet['result']['volume']) # prepare JSON string to save to file if xbmc_version > 18: settingsToSave = convert(settingsToSave) jsonToWrite = json.dumps(settingsToSave) # create dir in addon data if not exist if not xbmcvfs.exists(ADDON_PATH_DATA): xbmcvfs.mkdir(ADDON_PATH_DATA) # save profile file notify.logInfo('[SAVING SETTING]: %s' % sName[button]) f = xbmcvfs.File( os.path.join(ADDON_PATH_DATA, 'profile%s.json' % str(button)), 'w') f.write(jsonToWrite) f.close() notify.popup('%s %s (%s)' % (ADDON_LANG(32102), str(button), sName[button]), force=True)
def extract(self, current_archive_file=None, current_directory_out=None, files_to_extract=None, extract_all=True): files_out = list() overall_success = True if current_archive_file is None: current_archive_file = self.archive_file if current_directory_out is None: current_directory_out = self.directory_out if files_to_extract is None: if not extract_all and (self.files_to_extract is None or len(self.files_to_extract) == 0): xbmc.log( msg= 'archive_tool error: extract_all set to False and no files were identified for extraction', level=xbmc.LOGERROR) overall_success = False return files_out, overall_success else: files_to_extract = self.files_to_extract else: if type(files_to_extract) is list and len(files_to_extract) > 0: extract_all = False #Override default extract_all if files_to_extract is populated if current_archive_file is not None: if current_directory_out is None: #Default to the same directory as the current_archive_file directory_to = os.path.join( os.path.split(xbmc.translatePath(current_archive_file))[0], '') else: directory_to = os.path.join( xbmc.translatePath(current_directory_out), '') if 'archive://' in current_archive_file or 'rar://' in current_archive_file: archive_path = current_archive_file else: if self.use_vfs_rar: archive_path = 'rar://%(archive_file)s' % { 'archive_file': url_quote(xbmc.translatePath(current_archive_file)) } else: archive_path = 'archive://%(archive_file)s' % { 'archive_file': url_quote(xbmc.translatePath(current_archive_file)) } dirs_in_archive, files_in_archive = xbmcvfs.listdir(archive_path) for ff in files_in_archive: file_from = os.path.join(archive_path, ff).replace( '\\', '/' ) #Windows unexpectedly requires a forward slash in the path if extract_all or file_from in files_to_extract: success = xbmcvfs.copy( file_from, os.path.join( xbmc.translatePath(directory_to), ff)) #Extract the file to the correct directory if not success: xbmc.log( msg= 'archive_tool error: Error extracting file %(ff)s from archive %(archive_file)s' % { 'ff': ff, 'archive_file': current_archive_file }, level=xbmc.LOGERROR) overall_success = False else: xbmc.log( msg= 'archive_tool: Extracted file %(ff)s from archive %(archive_file)s' % { 'ff': ff, 'archive_file': current_archive_file }, level=xbmc.LOGDEBUG) files_out.append( os.path.join(xbmc.translatePath(directory_to), ff) ) #Append the file to the list of extracted files else: xbmc.log( msg= 'archive_tool: The file %(ff)s from archive %(archive_file)s was not listed for extraction, so it will be skipped' % { 'ff': file_from, 'archive_file': current_archive_file }, level=xbmc.LOGDEBUG) for dd in dirs_in_archive: if xbmcvfs.mkdir( os.path.join(xbmc.translatePath(directory_to), dd) ): #Make the archive directory in the directory_to xbmc.log( msg= 'archive_tool: Created folder %(dd)s for archive %(archive_file)s' % { 'dd': os.path.join(xbmc.translatePath(directory_to), dd, ''), 'archive_file': current_archive_file }, level=xbmc.LOGDEBUG) files_out2, success2 = self.extract( current_archive_file=os.path.join( archive_path, dd, '').replace('\\', '/'), current_directory_out=os.path.join(directory_to, dd)) if success2: files_out = files_out + files_out2 #Append the files in the subdir to the list of extracted files else: xbmc.log( msg= 'archive_tool error: Error extracting files from the subdirectory %(dd)s in the archive %(archive_file)s' % { 'dd': dd, 'archive_file': current_archive_file }, level=xbmc.LOGERROR) overall_success = False else: overall_success = False xbmc.log( msg= 'archive_tool error: Unable to create the archive subdirectory %(dir_from)s in the archive %(archive_file)s' % { 'dir_from': os.path.join(xbmc.translatePath(directory_to), dd), 'archive_file': current_archive_file }, level=xbmc.LOGERROR) else: xbmc.log( msg= 'archive_tool error: The current archive file is not valid', level=xbmc.LOGERROR) overall_success = False return files_out, overall_success