def install_file_by_sha1(cls, sha1, name, path): print("[DOWNLOADER] install_file_by_sha1", sha1) # FIXME: Also find files from file database / plugins print(repr(path)) if not os.path.exists(os.path.dirname(path)): os.makedirs(os.path.dirname(path)) src = PluginManager.instance().find_file_by_sha1(sha1) if src: dst = path dst_partial = dst + ".partial" sha1_obj = hashlib.sha1() with open(src, "rb") as fin: with open(dst_partial, "wb") as fout: while True: data = fin.read(65536) if not data: break fout.write(data) sha1_obj.update(data) if sha1_obj.hexdigest() != sha1: raise Exception("File from plugin does not match SHA-1") os.rename(dst_partial, dst) return cache_path = cls.get_cache_path(sha1) if os.path.exists(cache_path): print("[CACHE]", cache_path) # FIXME: Atomic copy utility function? shutil.copy(cache_path, path) # so we later can delete least accessed files in cache... os.utime(cache_path, None) return url = cls.sha1_to_url(sha1, name) print("[DOWNLOADER]", url) raise_exception_in_offline_mode() r = requests.get(url, stream=True) try: r.raise_for_status() temp_path = path + ".partial." + str(uuid4()) h = hashlib.sha1() with open(temp_path, "wb") as output: for chunk in r.iter_content(chunk_size=65536): h.update(chunk) output.write(chunk) finally: r.close() if h.hexdigest() != sha1: print("error: downloaded sha1 is", h.hexdigest(), "- wanted", sha1) raise Exception("sha1 of downloaded file does not match") # Atomic "copy" to cache location temp_cache_path = cache_path + ".partial." + str(uuid4()) shutil.copy(temp_path, temp_cache_path) os.rename(temp_cache_path, cache_path) # Move downloaded file into file position (atomic) os.rename(temp_path, path)
def app_main(): executable = PluginManager.instance().find_executable("retroarch") args = sys.argv[1:] libretro_core = find_libretro_core("nestopia_libretro") args.extend(["-L", libretro_core]) process = executable.popen(args) process.wait()
def expansion_exec(exe_name, argv): executable = PluginManager.instance().find_executable(exe_name) p = executable.popen( argv[1:], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0, ) return p
def run(self): executable = PluginManager.instance().find_executable( self.emulator.name ) if executable is None and self.emulator.allow_system_emulator: executable_path = shutil.which(self.emulator.name) if executable_path is not None: executable = Executable(executable_path) if executable is None: raise LookupError( "Could not find emulator " + repr(self.emulator.name) ) self.emulator.process = self.start_emulator(executable)
def install_mame_hash_file(self, name): # FIXME: Better to find data file based on path/provides rather than # hardcoding plugin name, but... plugin = PluginManager.instance().plugin("MAME-FS") src = plugin.data_file_path("hash/" + name) hash_dir = os.path.join(self.cwd.path, "hash") if not os.path.exists(hash_dir): os.makedirs(hash_dir) dst = os.path.join(hash_dir, name) # FIXME: Check if file is the same (no need to copy) if os.path.exists(dst) and filecmp.cmp(src, dst): print("[A5200] Hash file", name, "already in place") return print("[A5200] Installing hash/" + name) shutil.copy2(src, dst)
def cheats_file(self, name): dev_path = os.path.join("..", "cheats", name) # FIXME: if development_mode ? if os.path.exists(dev_path): print("Found cheats file:", dev_path) return dev_path try: plugin = PluginManager.instance().plugin("Cheats") except LookupError: print("No cheats plugin found") return None path = plugin.data_file_path(name) if os.path.exists(path): print("Found cheats file:", path) return path print("No cheats file found:", name) return None
def __init__(self, parent): super().__init__(parent) icon = fsui.Icon("plugins", "pkg:workspace") self.add_header(icon, gettext("Plugins")) self.list_view = fsui.ListView(self) self.list_view.set_min_height(140) # self.list_view.item_activated.connect(self.on_plugin_activated) image = fsui.Image("workspace:res/16x16/settings.png") plugin_manager = PluginManager.instance() for plugin in plugin_manager.plugins(): text = "{0} ({1})".format(plugin.name, plugin.version) if plugin.outdated: text += " - " + gettext("This plugin is outdated").upper() print("[PLUGINS] {0}".format(text)) self.list_view.add_item(text, icon=image) self.layout.add(self.list_view, fill=True, expand=True)
def app_main(): plugin_manager = PluginManager.instance() plugins = plugin_manager.plugins() provides = plugin_manager.provides() for plugin in plugins: print("# {} ({})".format(plugin.name, type(plugin).__name__)) print(plugin.path) print("") print("# Provides:") for name in sorted(provides): plugin = provides[name] print("# {} ({})".format(name, plugin.name)) # print("", plugin.provides()[name]) print("")
def find_libretro_core(self, name): path = self.find_libretro_core_development(name) if path: return path # return "{}.so".format(name) if self.emulator.path == "/snap/bin/retroarch": # Hack, hardcoded for Debian/Ubuntu return os.path.expanduser( "~/snap/retroarch/current/.config/retroarch/" "cores/{}.so".format(name)) if self.emulator.path == "/usr/bin/retroarch": # Hack, hardcoded for Debian/Ubuntu return "/usr/lib/x86_64-linux-gnu/libretro/{}.so".format(name) if self.emulator.path == "/usr/local/bin/retroarch": base_path = os.path.expanduser("~/.config/retroarch/") core_path = os.path.join(base_path, "cores/{}.so".format(name)) return core_path return PluginManager.instance().find_library_path(name)
def find_retroarch_shader(self, name): relative_path = "shaders/shaders_glsl/" + name + ".glslp" path = self.find_libretro_shader_development(relative_path) if path: return path if self.emulator.path == "/snap/bin/retroarch": base_path = os.path.expanduser( "~/snap/retroarch/current/.config/retroarch/") return os.path.join(base_path, relative_path) if self.emulator.path == "/usr/local/bin/retroarch": base_path = os.path.expanduser("~/.config/retroarch/") return os.path.join(base_path, relative_path) if self.emulator.path: # FIXME: .. return "" # FIXME: Better to find data file based on path/provides rather than # hardcoding plugin name, but... try: plugin = PluginManager.instance().plugin("RetroArch-FS") except LookupError: return "" else: return plugin.data_file_path(relative_path)
def find_executable(name): return PluginManager.instance().find_executable(name)
def app_main(): executable = PluginManager.instance().find_executable("dosbox-fs") process = executable.popen(sys.argv[1:]) process.wait()
def find_retroarch_shader(name): # FIXME: Better to find data file based on path/provides rather than # hardcoding plugin name, but... plugin = PluginManager.instance().plugin("RetroArch-FS") return plugin.data_file_path("shaders/shaders_glsl/" + name + ".glslp")
def find_libretro_core(name): # return "/usr/lib/x86_64-linux-gnu/libretro/{}.so".format(name) return PluginManager.instance().find_library_path(name)
def find_resource(self, name): return PluginManager.instance().find_resource(name)
def __init__(self, parent): StatusElement.__init__(self, parent) self.error_icon = Image("launcher:res/16x16/error.png") self.warning_icon = Image("launcher:res/16x16/warning_3.png") self.notice_icon = Image("launcher:res/16x16/information.png") self.icons = [self.error_icon, self.warning_icon, self.notice_icon] self.coordinates = [] self.warnings = [] self.game_notice = "" self.variant_notice = "" self.variant_warning = "" self.variant_error = "" self.joy_emu_conflict = "" self.using_joy_emu = False self.kickstart_file = "" self.x_kickstart_file_sha1 = "" self.update_available = "" self.__error = "" self.x_missing_files = "" self.download_page = "" self.download_file = "" self.platform = "" self.amiga_model = "" self.amiga_model_calculated = "" self.chip_memory = "" self.chip_memory_calculated = 0 self.outdated_plugins = [] self.custom_config = set() self.custom_uae_config = set() self.settings_config_keys = set() plugin_manager = PluginManager.instance() for plugin in plugin_manager.plugins(): if plugin.outdated: self.outdated_plugins.append(plugin.name) ConfigBehavior( self, [ "x_game_notice", "x_variant_notice", "x_variant_warning", "x_variant_error", "x_joy_emu_conflict", "amiga_model", "x_kickstart_file_sha1", "kickstart_file", "download_page", "download_file", "x_missing_files", "__error", "chip_memory", "jit_compiler", "platform", ], ) SettingsBehavior(self, ["__update_available"]) LauncherConfig.add_listener(self) for key in JOYSTICK_KEYS: self.on_config(key, LauncherConfig.get(key)) for key in LauncherConfig.keys(): if LauncherConfig.is_custom_uae_option(key): self.on_config(key, LauncherConfig.get(key)) elif LauncherConfig.is_custom_option(key): self.on_config(key, LauncherConfig.get(key)) LauncherSettings.add_listener(self) for key in LauncherSettings.keys(): if LauncherConfig.is_config_only_option(key): self.on_setting(key, LauncherSettings.get(key))