def sync_game_details(remote_library): """Update local game details, :return: A set of ids of the updated games. """ if not remote_library: return set() updated = set() for remote_game in remote_library: slug = remote_game["slug"] sync_required = False local_game = pga.get_game_by_field(slug, "slug") if not local_game: continue if local_game[ "updated"] and remote_game["updated"] > local_game["updated"]: # The remote game's info is more recent than the local game sync_required = True else: for key in remote_game.keys(): if (key in local_game.keys() and remote_game[key] and not local_game[key]): # Remote game has data that is missing from the local game. logger.info("Key %s is not present, forcing update", key) sync_required = True break if not sync_required: continue logger.debug("Syncing details for %s", slug) game_id = pga.add_or_update( id=local_game["id"], name=local_game["name"], runner=local_game["runner"], slug=slug, year=remote_game["year"], updated=remote_game["updated"], steamid=remote_game["steamid"], ) updated.add(game_id) if not local_game.get( "has_custom_banner") and remote_game["banner_url"]: path = resources.get_icon_path(slug, resources.BANNER) resources.download_media(remote_game["banner_url"], path, overwrite=True) if not local_game.get("has_custom_icon") and remote_game["icon_url"]: path = resources.get_icon_path(slug, resources.ICON) resources.download_media(remote_game["icon_url"], path, overwrite=True) if updated: logger.debug("%d games updated", len(updated)) return updated
def sync_game_details(remote_library): """Update local game details, :return: A set of ids of the updated games. """ if not remote_library: return set() updated = set() for remote_game in remote_library: slug = remote_game['slug'] sync_required = False local_game = pga.get_game_by_field(slug, 'slug') if not local_game: continue if local_game[ 'updated'] and remote_game['updated'] > local_game['updated']: # The remote game's info is more recent than the local game sync_required = True else: for key in remote_game.keys(): if key in local_game.keys( ) and remote_game[key] and not local_game[key]: # Remote game has data that is missing from the local game. sync_required = True break if not sync_required: continue logger.debug("Syncing details for %s" % slug) game_id = pga.add_or_update(name=local_game['name'], runner=local_game['runner'], slug=slug, year=remote_game['year'], updated=remote_game['updated'], steamid=remote_game['steamid']) updated.add(game_id) if not local_game.get( 'has_custom_banner') and remote_game['banner_url']: path = resources.get_icon_path(slug, resources.BANNER) resources.download_media(remote_game['banner_url'], path, overwrite=True) if not local_game.get('has_custom_icon') and remote_game['icon_url']: path = resources.get_icon_path(slug, resources.ICON) resources.download_media(remote_game['icon_url'], path, overwrite=True) if updated: logger.debug("%d games updated", len(updated)) return updated
def on_custom_image_reset_clicked(self, _widget, image_type): if image_type == "banner": self.game.has_custom_banner = False dest_path = resources.get_icon_path(self.game.slug, icon_type="banner") elif image_type == "icon": self.game.has_custom_icon = False dest_path = resources.get_icon_path(self.game.slug, icon_type="icon") else: raise ValueError("Unsupported image type %s" % image_type) os.remove(dest_path) self._set_image(image_type)
def sync_game_details(remote_library): """Update local game details, :return: A set of ids of the updated games. """ if not remote_library: return set() updated = set() for remote_game in remote_library: slug = remote_game['slug'] sync_required = False local_game = pga.get_game_by_field(slug, 'slug') if not local_game: continue if local_game['updated'] and remote_game['updated'] > local_game['updated']: # The remote game's info is more recent than the local game sync_required = True else: for key in remote_game.keys(): if key in local_game.keys() and remote_game[key] and not local_game[key]: # Remote game has data that is missing from the local game. sync_required = True break if not sync_required: continue logger.debug("Syncing details for %s" % slug) game_id = pga.add_or_update( name=local_game['name'], runner=local_game['runner'], slug=slug, year=remote_game['year'], updated=remote_game['updated'], steamid=remote_game['steamid'] ) updated.add(game_id) if not local_game.get('has_custom_banner') and remote_game['banner_url']: path = resources.get_icon_path(slug, resources.BANNER) resources.download_media(remote_game['banner_url'], path, overwrite=True) if not local_game.get('has_custom_icon') and remote_game['icon_url']: path = resources.get_icon_path(slug, resources.ICON) resources.download_media(remote_game['icon_url'], path, overwrite=True) if updated: logger.debug("%d games updated", len(updated)) return updated
def on_custom_image_select(self, _widget, image_type): dialog = Gtk.FileChooserNative.new( _("Please choose a custom image"), self, Gtk.FileChooserAction.OPEN, None, None, ) image_filter = Gtk.FileFilter() image_filter.set_name(_("Images")) image_filter.add_pixbuf_formats() dialog.add_filter(image_filter) response = dialog.run() if response == Gtk.ResponseType.ACCEPT: image_path = dialog.get_filename() if image_type == "banner": self.game.has_custom_banner = True dest_path = os.path.join(settings.BANNER_PATH, "%s.jpg" % self.game.slug) size = BANNER_SIZE file_format = "jpeg" else: self.game.has_custom_icon = True dest_path = resources.get_icon_path(self.game.slug) size = ICON_SIZE file_format = "png" pixbuf = get_pixbuf(image_path, size) pixbuf.savev(dest_path, file_format, [], []) self._set_image(image_type) if image_type == "icon": system.update_desktop_icons() dialog.destroy()
def get_pixbuf_for_game(game_slug, icon_type, is_installed=True): if icon_type.startswith("banner"): default_icon_path = os.path.join(datapath.get(), "media/default_banner.png") icon_path = resources.get_banner_path(game_slug) elif icon_type.startswith("icon"): default_icon_path = os.path.join(datapath.get(), "media/default_icon.png") icon_path = resources.get_icon_path(game_slug) else: logger.error("Invalid icon type '%s'", icon_type) return None size = IMAGE_SIZES[icon_type] pixbuf = get_pixbuf(icon_path, size, fallback=default_icon_path) if not is_installed: unavailable_game_overlay = os.path.join(datapath.get(), "media/unavailable.png") transparent_pixbuf = get_overlay(unavailable_game_overlay, size).copy() pixbuf.composite( transparent_pixbuf, 0, 0, size[0], size[1], 0, 0, 1, 1, GdkPixbuf.InterpType.NEAREST, 100, ) return transparent_pixbuf return pixbuf
def on_media_loaded(self, _response): """Callback to handle a response from the API with the new media""" if not self.medias: return for media_type in ("banner", "icon"): self.download_icons([(slug, self.medias[media_type][slug], get_icon_path(slug, media_type)) for slug in self.medias[media_type]], media_type)
def fetch_icon(self, slug): if not self.media_loaded: self.games_to_refresh.add(slug) return for media_type in ('banner', 'icon'): url = self.medias[media_type].get(slug) if url: download_media(url, get_icon_path(slug, media_type)) self.emit('icon-loaded', slug, media_type)
def fetch_icon(self, slug): if not self.media_loaded: self.games_to_refresh.add(slug) return for media_type in ("banner", "icon"): url = self.medias[media_type].get(slug) if url: logger.debug("Getting %s for %s: %s", media_type, slug, url) download_media(url, get_icon_path(slug, media_type)) self.emit("icon-loaded", slug, media_type)
def on_custom_image_reset_clicked(self, _widget, image_type): dest_path = "" if ImageType.banner & image_type: self.game.has_custom_banner = False dest_path = resources.get_banner_path(self.game.slug) if ImageType.icon & image_type: self.game.has_custom_icon = False dest_path = resources.get_icon_path(self.game.slug) os.remove(dest_path) self._set_image(image_type)
def on_custom_image_select(self, _widget, image_type): dialog = Gtk.FileChooserDialog( _("Please choose a custom image"), self, Gtk.FileChooserAction.OPEN, ( Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK, ), ) image_filter = Gtk.FileFilter() image_filter.set_name(_("Images")) image_filter.add_pixbuf_formats() dialog.add_filter(image_filter) response = dialog.run() if response == Gtk.ResponseType.OK: image_path = dialog.get_filename() if image_type == "banner": self.game.has_custom_banner = True dest_path = resources.get_icon_path(self.game.slug, icon_type=image_type) size = BANNER_SIZE file_format = "jpeg" else: self.game.has_custom_icon = True dest_path = resources.get_icon_path(self.game.slug, icon_type="icon") size = ICON_SIZE file_format = "png" pixbuf = get_pixbuf(image_path, size) pixbuf.savev(dest_path, file_format, [], []) self._set_image(image_type) if image_type == "icon": system.update_desktop_icons() dialog.destroy()
def on_custom_image_reset_clicked(self, _widget, image_type): if image_type == "banner": self.game.has_custom_banner = False dest_path = os.path.join(settings.BANNER_PATH, "%s.jpg" % self.game.slug) elif image_type == "icon": self.game.has_custom_icon = False dest_path = resources.get_icon_path(self.game.slug) else: raise ValueError("Unsupported image type %s" % image_type) if os.path.isfile(dest_path): os.remove(dest_path) self._set_image(image_type)
def sync_game_details(remote_library): """Update local game details, :return: A set of ids of the updated games. """ if not remote_library: return set() updated = set() for remote_game in remote_library: slug = remote_game["slug"] sync_required = False local_game = pga.get_game_by_field(slug, "slug") if not local_game: continue if local_game["updated"] and remote_game["updated"] > local_game["updated"]: # The remote game's info is more recent than the local game sync_required = True if not sync_required: continue logger.debug("Syncing details for %s", slug) game_id = pga.add_or_update( id=local_game["id"], name=local_game["name"], runner=local_game["runner"], slug=slug, year=remote_game["year"], updated=remote_game["updated"], steamid=remote_game["steamid"], ) updated.add(game_id) if not local_game.get("has_custom_banner") and remote_game["banner_url"]: path = resources.get_banner_path(slug) resources.download_media(remote_game["banner_url"], path, overwrite=True) if not local_game.get("has_custom_icon") and remote_game["icon_url"]: path = resources.get_icon_path(slug) resources.download_media(remote_game["icon_url"], path, overwrite=True) if updated: logger.debug("%d games updated", len(updated)) return updated
def get_pixbuf_for_game(game_slug, image_type, is_installed=True): icon_path = "" default_icon_path = "" if ImageType.banner & image_type: default_icon_path = os.path.join(datapath.get(), "media/default_banner.png") icon_path = resources.get_banner_path(game_slug) if ImageType.icon == image_type: default_icon_path = os.path.join(datapath.get(), "media/default_icon.png") icon_path = resources.get_icon_path(game_slug) size = IMAGE_SIZES[image_type] pixbuf = get_pixbuf(icon_path, size, fallback=default_icon_path) if not is_installed: unavailable_game_overlay = os.path.join(datapath.get(), "media/unavailable.png") transparent_pixbuf = get_overlay(unavailable_game_overlay, size).copy() pixbuf.composite( transparent_pixbuf, 0, 0, size[0], size[1], 0, 0, 1, 1, GdkPixbuf.InterpType.NEAREST, 100, ) return transparent_pixbuf return pixbuf
def has_icon(self, game_slug, media_type=None): """Return True if the game_slug has the icon of `icon_type`""" media_type = media_type or self.icon_type return system.path_exists(get_icon_path(game_slug, media_type))
def on_custom_image_select(self, _widget, image_type): dialog = Gtk.FileChooserDialog( _("Please choose a custom image"), self, Gtk.FileChooserAction.OPEN, ( Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK, ), ) image_filter = Gtk.FileFilter() image_filter.set_name(_("Images")) image_filter.add_pixbuf_formats() dialog.add_filter(image_filter) try: main_file_path = self.game.runner.get_main_file() except AttributeError: main_file_path = None path_type = PATH_TYPE.UNKNOWN if ImageType.banner & image_type: path_type = PATH_TYPE.BANNER if ImageType.icon & image_type: path_type = PATH_TYPE.ICON def_path = default_path_handler.get( # unfortuantely the original path is not stored entry=None, # No default for images default=None, main_file_path=main_file_path, install_path=self.lutris_config.game_config.get("game_path"), path_type=path_type) if os.path.isfile(def_path): if self.action != Gtk.FileChooserAction.SELECT_FOLDER: dialog.set_filename(os.path.basename(def_path)) def_path = os.path.dirname(def_path) dialog.set_current_folder(def_path) response = dialog.run() if response == Gtk.ResponseType.OK: image_path = dialog.get_filename() default_path_handler.set_selected(image_path, image_type) file_format = "" dest_path = "" size = None if ImageType.banner & image_type: self.game.has_custom_banner = True dest_path = resources.get_banner_path(self.game.slug) size = BANNER_SIZE file_format = "jpeg" if ImageType.icon & image_type: self.game.has_custom_icon = True dest_path = resources.get_icon_path(self.game.slug) size = ICON_SIZE file_format = "png" pixbuf = get_pixbuf(image_path, size) pixbuf.savev(dest_path, file_format, [], []) self._set_image(image_type) if ImageType.icon & image_type: resources.update_desktop_icons() dialog.destroy()
def play(self): url = self.game_config.get("main_file") if not url: return { "error": "CUSTOM", "text": ("The web address is empty, \n" "verify the game's configuration."), } # check if it's an url or a file is_url = urlparse(url).scheme != "" if not is_url: if not system.path_exists(url): return { "error": "CUSTOM", "text": ("The file " + url + " does not exist, \n" "verify the game's configuration."), } url = "file://" + url game_data = pga.get_game_by_field(self.config.game_config_id, "configpath") # keep the old behavior from browser runner, but with support for extra arguments! if self.runner_config.get("external_browser"): # is it possible to disable lutris runtime here? browser = self.runner_config.get( "custom_browser_executable") or "xdg-open" args = self.runner_config.get("custom_browser_args") if args == "": args = '"$GAME"' arguments = string.Template(args).safe_substitute({ "GAME": url, "URL": url }) command = [browser] for arg in shlex.split(arguments): command.append(arg) return {"command": command} icon = resources.get_icon_path(game_data.get("slug")) if not system.path_exists(icon): icon = DEFAULT_ICON command = [ self.get_executable(), os.path.join(settings.RUNNER_DIR, "web/electron/resources/app.asar"), url, "--name", game_data.get("name"), "--icon", icon, ] if self.runner_config.get("fullscreen"): command.append("--fullscreen") if self.runner_config.get("frameless"): command.append("--frameless") if self.runner_config.get("disable_resizing"): command.append("--disable-resizing") if self.runner_config.get("disable_menu_bar"): command.append("--disable-menu-bar") if self.runner_config.get("window_size"): command.append("--window-size") command.append(self.runner_config.get("window_size")) if self.runner_config.get("maximize_window"): command.append("--maximize-window") if self.runner_config.get("disable_scrolling"): command.append("--disable-scrolling") if self.runner_config.get("hide_cursor"): command.append("--hide-cursor") if self.runner_config.get("open_links"): command.append("--open-links") if self.runner_config.get("remove_margin"): command.append("--remove-margin") if self.runner_config.get("devtools"): command.append("--devtools") return {"command": command, "env": self.get_env(False)}
def play(self): url = self.game_config.get("main_file") if not url: return { "error": "CUSTOM", "text": _("The web address is empty, \n" "verify the game's configuration."), } # check if it's an url or a file is_url = urlparse(url).scheme != "" if not is_url: if not system.path_exists(url): return { "error": "CUSTOM", "text": _("The file %s does not exist, \n" "verify the game's configuration.") % url, } url = "file://" + url game_data = get_game_by_field(self.config.game_config_id, "configpath") # keep the old behavior from browser runner, but with support for extra arguments! if self.runner_config.get("external_browser"): # is it possible to disable lutris runtime here? browser = self.runner_config.get( "custom_browser_executable") or "xdg-open" args = self.runner_config.get("custom_browser_args") args = args or '"$GAME"' arguments = string.Template(args).safe_substitute({ "GAME": url, "URL": url }) command = [browser] for arg in split_arguments(arguments): command.append(arg) return {"command": command} icon = resources.get_icon_path(game_data.get("slug")) if not system.path_exists(icon): icon = DEFAULT_ICON command = [ self.get_executable(), os.path.join(settings.RUNNER_DIR, "web/electron/resources/app.asar"), url, "--name", game_data.get("name"), "--icon", icon, ] for key in [ "fullscreen", "frameless", "devtools", "disable_resizing", "disable_menu_bar", "maximize_window", "disable_scrolling", "hide_cursor", "open_links", "remove_margin", ]: if self.runner_config.get(key): converted_opt_name = key.replace("_", "-") command.append("--{option}".format(option=converted_opt_name)) if self.runner_config.get("window_size"): command.append("--window-size") command.append(self.runner_config.get("window_size")) if self.runner_config.get("user_agent"): command.append("--user-agent") command.append(self.runner_config.get("user_agent")) if linux.LINUX_SYSTEM.is_flatpak: command.append("--no-sandbox") return {"command": command, "env": self.get_env(False)}
def play(self): url = self.game_config.get("main_file") if not url: return { "error": "CUSTOM", "text": ( "The web address is empty, \n" "verify the game's configuration." ), } # check if it's an url or a file is_url = urlparse(url).scheme != "" if not is_url: if not system.path_exists(url): return { "error": "CUSTOM", "text": ( "The file " + url + " does not exist, \n" "verify the game's configuration." ), } url = "file://" + url game_data = pga.get_game_by_field(self.config.game_config_id, "configpath") # keep the old behavior from browser runner, but with support for extra arguments! if self.runner_config.get("external_browser"): # is it possible to disable lutris runtime here? browser = self.runner_config.get("custom_browser_executable") or "xdg-open" args = self.runner_config.get("custom_browser_args") args = args or '"$GAME"' arguments = string.Template(args).safe_substitute({"GAME": url, "URL": url}) command = [browser] for arg in shlex.split(arguments): command.append(arg) return {"command": command} icon = resources.get_icon_path(game_data.get("slug")) if not system.path_exists(icon): icon = DEFAULT_ICON command = [ self.get_executable(), os.path.join(settings.RUNNER_DIR, "web/electron/resources/app.asar"), url, "--name", game_data.get("name"), "--icon", icon, ] for key in [ "fullscreen", "frameless", "devtools", "disable_resizing", "disable_menu_bar", "maximize_window", "disable_scrolling", "hide_cursor", "open_links", "remove_margin", ]: if self.runner_config.get(key): converted_opt_name = key.replace("_", "-") command.append("--{option}".format(option=converted_opt_name)) if self.runner_config.get("window_size"): command.append("--window-size") command.append(self.runner_config.get("window_size")) return {"command": command, "env": self.get_env(False)}