mirror of
https://github.com/lutris/lutris
synced 2024-10-04 14:59:37 +00:00
Replace the single file pattern for service-media with a list
It's a list of one element except for Lutris banners and cover-art; these now support both .jpg and .png, where the user can assign either file type without transcoding. This, in turn, allow transparency to be used in banners and cover-art via PNG files. We still transcode any other file types into JPEG files here.
This commit is contained in:
parent
08466f2258
commit
236f0c9999
|
@ -17,7 +17,7 @@ from lutris.gui.dialogs.delegates import DialogInstallUIDelegate
|
|||
from lutris.gui.widgets.common import Label, NumberEntry, SlugEntry
|
||||
from lutris.gui.widgets.notifications import send_notification
|
||||
from lutris.gui.widgets.scaled_image import ScaledImage
|
||||
from lutris.gui.widgets.utils import MEDIA_CACHE_INVALIDATED, get_image_file_format
|
||||
from lutris.gui.widgets.utils import MEDIA_CACHE_INVALIDATED, get_image_file_extension
|
||||
from lutris.runners import import_runner
|
||||
from lutris.services.lutris import LutrisBanner, LutrisCoverart, LutrisIcon, download_lutris_media
|
||||
from lutris.util.jobs import AsyncCall
|
||||
|
@ -713,13 +713,23 @@ class GameDialogCommon(SavableModelessDialog, DialogInstallUIDelegate):
|
|||
slug = self.slug or self.game.slug
|
||||
service_media = self.service_medias[image_type]
|
||||
self.game.custom_images.add(image_type)
|
||||
dest_path = service_media.get_media_path(slug)
|
||||
file_format = service_media.file_format
|
||||
dest_paths = service_media.get_possible_media_paths(slug)
|
||||
|
||||
if image_path != dest_path:
|
||||
if file_format == get_image_file_format(image_path):
|
||||
if image_path not in dest_paths:
|
||||
ext = get_image_file_extension(image_path)
|
||||
dest_path = None
|
||||
for candidate in dest_paths:
|
||||
if os.path.isfile(candidate):
|
||||
os.remove(candidate)
|
||||
if candidate.casefold().endswith(ext):
|
||||
dest_path = candidate
|
||||
|
||||
if dest_path:
|
||||
shutil.copy(image_path, dest_path, follow_symlinks=True)
|
||||
else:
|
||||
dest_path = dest_paths[0]
|
||||
file_format = {".jpg": "jpeg", ".png": "png"}[get_image_file_extension(dest_paths[0])]
|
||||
|
||||
# If we must transcode the image, we'll scale the image up based on
|
||||
# the UI scale factor, to try to avoid blurriness. Of course this won't
|
||||
# work if the user changes the scaling later, but what can you do.
|
||||
|
|
|
@ -38,21 +38,21 @@ def open_uri(uri):
|
|||
system.spawn(["xdg-open", uri])
|
||||
|
||||
|
||||
def get_image_file_format(path):
|
||||
"""Returns the file format fo an image, either 'jpeg' or 'png';
|
||||
we deduce this from the file extension, or if that fails the
|
||||
def get_image_file_extension(path):
|
||||
"""Returns the canonical file extension for an image,
|
||||
either 'jpg' or 'png'; we deduce this from the file extension, or if that fails the
|
||||
file's 'magic' prefix bytes."""
|
||||
ext = os.path.splitext(path)[1].lower()
|
||||
ext = os.path.splitext(path)[1].casefold()
|
||||
if ext in [".jpg", ".jpeg"]:
|
||||
return "jpeg"
|
||||
return ".jpg"
|
||||
if path == ".png":
|
||||
return "png"
|
||||
return ".png"
|
||||
|
||||
file_type = magic.from_file(path).lower()
|
||||
file_type = magic.from_file(path).casefold()
|
||||
if "jpeg image data" in file_type:
|
||||
return "jpeg"
|
||||
return ".jpg"
|
||||
if "png image data" in file_type:
|
||||
return "png"
|
||||
return ".png"
|
||||
|
||||
return None
|
||||
|
||||
|
|
|
@ -34,8 +34,7 @@ class AmazonBanner(ServiceMedia):
|
|||
service = "amazon"
|
||||
size = (200, 112)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "amazon/banners")
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg"]
|
||||
api_field = "image"
|
||||
url_pattern = "%s"
|
||||
|
||||
|
|
|
@ -34,16 +34,14 @@ class LutrisBanner(ServiceMedia):
|
|||
service = 'lutris'
|
||||
size = BANNER_SIZE
|
||||
dest_path = settings.BANNER_PATH
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg", "%s.png"]
|
||||
api_field = 'banner'
|
||||
|
||||
|
||||
class LutrisIcon(LutrisBanner):
|
||||
size = ICON_SIZE
|
||||
dest_path = settings.ICON_PATH
|
||||
file_pattern = "lutris_%s.png"
|
||||
file_format = "png"
|
||||
file_patterns = ["lutris_%s.png"]
|
||||
api_field = 'icon'
|
||||
|
||||
@property
|
||||
|
@ -57,8 +55,7 @@ class LutrisIcon(LutrisBanner):
|
|||
class LutrisCoverart(ServiceMedia):
|
||||
service = 'lutris'
|
||||
size = (264, 352)
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg", "%s.png"]
|
||||
dest_path = settings.COVERART_PATH
|
||||
api_field = 'coverart'
|
||||
|
||||
|
|
|
@ -57,8 +57,7 @@ GAME_IDS = {
|
|||
class BattleNetCover(ServiceMedia):
|
||||
service = 'battlenet'
|
||||
size = (176, 234)
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg"]
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "battlenet/coverart")
|
||||
api_field = 'coverart'
|
||||
|
||||
|
|
|
@ -19,8 +19,7 @@ class DolphinBanner(ServiceMedia):
|
|||
service = "dolphin"
|
||||
source = "local"
|
||||
size = (96, 32)
|
||||
file_pattern = "%s.png"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.png"]
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "dolphin/banners/small")
|
||||
|
||||
|
||||
|
|
|
@ -56,8 +56,7 @@ class EAAppGames:
|
|||
|
||||
class EAAppArtSmall(ServiceMedia):
|
||||
service = "ea_app"
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg"]
|
||||
size = (63, 89)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "ea_app/pack-art-small")
|
||||
api_field = "packArtSmall"
|
||||
|
|
|
@ -33,8 +33,7 @@ BOX_ART_SIZE = (200, 267)
|
|||
class DieselGameMedia(ServiceMedia):
|
||||
service = "egs"
|
||||
remote_size = (200, 267)
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg"]
|
||||
min_logo_x = 300
|
||||
min_logo_y = 150
|
||||
|
||||
|
@ -111,8 +110,7 @@ class DieselGameBoxLogo(DieselGameMedia):
|
|||
"""EGS game box"""
|
||||
size = (200, 100)
|
||||
remote_size = size
|
||||
file_pattern = "%s.png"
|
||||
file_format = "png"
|
||||
file_patterns = ["%s.png"]
|
||||
visible = False
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "egs/game_logo")
|
||||
api_field = "DieselGameBoxLogo"
|
||||
|
|
|
@ -22,8 +22,7 @@ class FlathubBanner(ServiceMedia):
|
|||
service = "flathub"
|
||||
size = (128, 128)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "flathub/banners")
|
||||
file_pattern = "%s.png"
|
||||
file_format = "png"
|
||||
file_patterns = ["%s.png"]
|
||||
url_field = 'iconDesktopUrl'
|
||||
|
||||
def get_media_url(self, details):
|
||||
|
|
|
@ -28,8 +28,7 @@ class GogSmallBanner(ServiceMedia):
|
|||
service = "gog"
|
||||
size = (100, 60)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "gog/banners/small")
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg"]
|
||||
api_field = "image"
|
||||
url_pattern = "https:%s_prof_game_100x60.jpg"
|
||||
|
||||
|
|
|
@ -24,8 +24,7 @@ class HumbleBundleIcon(ServiceMedia):
|
|||
service = "humblebundle"
|
||||
size = (70, 70)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "humblebundle/icons")
|
||||
file_pattern = "%s.png"
|
||||
file_format = "png"
|
||||
file_patterns = ["%s.png"]
|
||||
api_field = "icon"
|
||||
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@ class ItchIoCover(ServiceMedia):
|
|||
service = "itchio"
|
||||
size = (315, 250)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "itchio/cover")
|
||||
file_pattern = "%s.png"
|
||||
file_format = "png"
|
||||
file_patterns = ["%s.png"]
|
||||
|
||||
def get_media_url(self, details):
|
||||
"""Extract cover from API"""
|
||||
|
|
|
@ -50,8 +50,7 @@ class OriginLauncher:
|
|||
|
||||
class OriginPackArtSmall(ServiceMedia):
|
||||
service = "origin"
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg"]
|
||||
size = (63, 89)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "origin/pack-art-small")
|
||||
api_field = "packArtSmall"
|
||||
|
|
|
@ -19,8 +19,7 @@ class ScummvmBanner(ServiceMedia):
|
|||
service = "scummvm"
|
||||
source = "local"
|
||||
size = (96, 32)
|
||||
file_pattern = "%s.png"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.png"]
|
||||
dest_path = settings.CACHE_DIR
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import json
|
|||
import os
|
||||
import random
|
||||
import time
|
||||
from typing import List
|
||||
|
||||
from lutris.database.services import ServiceGameCollection
|
||||
from lutris.util import system
|
||||
|
@ -18,8 +19,7 @@ class ServiceMedia:
|
|||
visible = True # This media should be displayed as an option in the UI
|
||||
small_size = None
|
||||
dest_path = None
|
||||
file_pattern = NotImplemented
|
||||
file_format = NotImplemented
|
||||
file_patterns = NotImplemented
|
||||
api_field = NotImplemented
|
||||
url_pattern = "%s"
|
||||
|
||||
|
@ -28,11 +28,21 @@ class ServiceMedia:
|
|||
os.makedirs(self.dest_path)
|
||||
|
||||
def get_filename(self, slug):
|
||||
return self.file_pattern % slug
|
||||
return self.file_patterns[0] % slug
|
||||
|
||||
def get_media_path(self, slug):
|
||||
"""Return the absolute path of a local media file"""
|
||||
return os.path.join(self.dest_path, self.get_filename(slug))
|
||||
candidates = self.get_possible_media_paths(slug)
|
||||
if len(candidates) > 1:
|
||||
for path in candidates:
|
||||
if os.path.isfile(path):
|
||||
return path
|
||||
return candidates[0]
|
||||
|
||||
def get_possible_media_paths(self, slug: str) -> List[str]:
|
||||
"""Return the absolute path of a local media file"""
|
||||
return [os.path.join(self.dest_path, pattern % slug)
|
||||
for pattern in self.file_patterns]
|
||||
|
||||
def exists(self, slug):
|
||||
"""Whether the icon for the specified slug exists locally"""
|
||||
|
|
|
@ -25,8 +25,7 @@ class SteamBanner(ServiceMedia):
|
|||
service = "steam"
|
||||
size = (184, 69)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "steam/banners")
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg"]
|
||||
api_field = "appid"
|
||||
url_pattern = "http://cdn.akamai.steamstatic.com/steam/apps/%s/capsule_184x69.jpg"
|
||||
|
||||
|
@ -35,8 +34,7 @@ class SteamCover(ServiceMedia):
|
|||
service = "steam"
|
||||
size = (200, 300)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "steam/covers")
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg"]
|
||||
api_field = "appid"
|
||||
url_pattern = "http://cdn.steamstatic.com/steam/apps/%s/library_600x900.jpg"
|
||||
|
||||
|
@ -45,8 +43,7 @@ class SteamBannerLarge(ServiceMedia):
|
|||
service = "steam"
|
||||
size = (460, 215)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "steam/header")
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg"]
|
||||
api_field = "appid"
|
||||
url_pattern = "https://cdn.cloudflare.steamstatic.com/steam/apps/%s/header.jpg"
|
||||
|
||||
|
|
|
@ -30,8 +30,7 @@ class UbisoftCover(ServiceMedia):
|
|||
service = "ubisoft"
|
||||
size = (160, 186)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "ubisoft/covers")
|
||||
file_pattern = "%s.jpg"
|
||||
file_format = "jpeg"
|
||||
file_patterns = ["%s.jpg"]
|
||||
api_field = "id"
|
||||
url_pattern = "https://ubiservices.cdn.ubi.com/%s/spaceCardAsset/boxArt_mobile.jpg?imwidth=320"
|
||||
|
||||
|
|
|
@ -35,8 +35,7 @@ class XDGMedia(ServiceMedia):
|
|||
source = "local"
|
||||
size = (64, 64)
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "xdg/icons")
|
||||
file_pattern = "%s.png"
|
||||
file_format = "png"
|
||||
file_patterns = ["%s.png"]
|
||||
|
||||
|
||||
class XDGService(BaseService):
|
||||
|
|
Loading…
Reference in a new issue