Implement Retroarch Importer

I'm quite rusty with Python, so please let me know if there are any (or many) grave mistakes!
This commit is contained in:
Rilic
2023-07-15 14:28:04 +01:00
parent c9a1104b44
commit c96b64f72e
6 changed files with 151 additions and 1 deletions

View File

@@ -226,6 +226,20 @@ template $PreferencesWindow : Adw.PreferencesWindow {
}
}
Adw.ExpanderRow retroarch_expander_row {
title: _("Retroarch");
show-enable-switch: true;
Adw.ActionRow retroarch_config_action_row {
title: _("Install Location");
Button retroarch_config_file_chooser_button {
icon-name: "folder-symbolic";
valign: center;
}
}
}
Adw.ExpanderRow flatpak_expander_row {
title: _("Flatpak");
show-enable-switch: true;

View File

@@ -64,6 +64,12 @@
<key name="legendary-location" type="s">
<default>"~/.config/legendary/"</default>
</key>
<key name="retroarch" type="b">
<default>true</default>
</key>
<key name="retroarch-location" type="s">
<default>"~/.var/app/org.libretro.RetroArch/config/retroarch/"</default>
</key>
<key name="flatpak" type="b">
<default>true</default>
</key>
@@ -110,4 +116,4 @@
<default>"[]"</default>
</key>
</schema>
</schemalist>
</schemalist>

View File

@@ -17,6 +17,7 @@
"--filesystem=~/.var/app/com.heroicgameslauncher.hgl/config/heroic/:ro",
"--filesystem=~/.var/app/com.usebottles.bottles/data/bottles/:ro",
"--filesystem=~/.var/app/io.itch.itch/config/itch/:ro",
"--filesystem=~/.var/app/org.libretro.RetroArch/config/retroarch/:ro",
"--filesystem=/var/lib/flatpak:ro"
],
"cleanup" : [

View File

@@ -0,0 +1,119 @@
# retroarch_source.py
#
# Copyright 2023 Rilic
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later
from pathlib import Path
from time import time
import json
import os
import logging
from json import JSONDecodeError
from src import shared
from src.game import Game
from src.importer.sources.location import Location
from src.importer.sources.source import (
SourceIterationResult,
SourceIterator,
Source
)
class RetroarchSourceIterator(SourceIterator):
source: "RetroarchSource"
def generator_builder(self) -> SourceIterationResult:
playlist_files = []
for file in os.listdir(self.source.config_location["playlists"]):
if file.endswith('.lpl'):
playlist_files.append(file)
playlist_items = []
for playlist_file in playlist_files:
open_file = open(str(self.source.config_location["playlists"]) + "/" + playlist_file)
try:
playlist_json = json.load(open_file)
except (JSONDecodeError, OSError, KeyError):
logging.warning("Cannot read playlist file: %s", str(playlist_file))
continue
for item in playlist_json["items"]:
# Select the core. Try the content's core first, then the playlist's
# default core.
core_path = item["core_path"]
if core_path == "DETECT":
default_core = playlist_json["default_core_path"]
if default_core:
core_path = default_core
else:
logging.warning("Cannot find core for: %s", str(item["path"]))
continue
# Build game
game_title = item["label"].split("(", 1)[0]
values = {
"source": self.source.id,
"added": int(time()),
"name": game_title,
"game_id": self.source.game_id_format.format(game_id=item["crc32"][:8]),
"executable": self.source.executable_format.format(
rom_path = item["path"],
core_path = core_path,
)
}
game = Game(values)
additional_data = {}
# Get boxart
boxart_image_name = item["label"].split(".", 1)[0] + ".png"
boxart_folder_name = playlist_file.split(".", 1)[0]
image_path = self.source.config_location["thumbnails"] / boxart_folder_name / "Named_Boxarts" / boxart_image_name
additional_data = {"local_image_path": image_path}
yield(game, additional_data)
class RetroarchSource(Source):
args = ' -L "{core_path}" "{rom_path}"'
name = "Retroarch"
available_on = {"linux"}
iterator_class = RetroarchSourceIterator
executable_format = 'retroarch' + args
config_location = Location(
schema_key="retroarch-location",
candidates=(
shared.flatpak_dir / "org.libretro.RetroArch" / "config" / "retroarch",
shared.config_dir / "retroarch",
shared.home / ".config" / "retroarch",
),
paths={
"playlists": (True, "playlists"),
"thumbnails": (True, "thumbnails"),
},
)
# Check if installation is flatpak'd.
# TODO: There's probably a MUCH better way of doing this.
# There's *is* a URI format, but it doesn't seem to work on the flatpak
# version of Retroarch. https://github.com/libretro/RetroArch/pull/13563
if str(shared.flatpak_dir) in str(config_location["playlists"]):
executable_format = 'flatpak run org.libretro.RetroArch' + args

View File

@@ -33,6 +33,7 @@ from src import shared
from src.details_window import DetailsWindow
from src.game import Game
from src.importer.importer import Importer
from src.importer.sources.retroarch_source import RetroarchSource
from src.importer.sources.bottles_source import BottlesSource
from src.importer.sources.flatpak_source import FlatpakSource
from src.importer.sources.heroic_source import HeroicSource
@@ -230,6 +231,9 @@ class CartridgesApplication(Adw.Application):
if shared.schema.get_boolean("legendary"):
importer.add_source(LegendarySource())
if shared.schema.get_boolean("retroarch"):
importer.add_source(RetroarchSource())
importer.run()
def on_remove_game_action(self, *_args):

View File

@@ -30,6 +30,7 @@ from src.importer.sources.flatpak_source import FlatpakSource
from src.importer.sources.heroic_source import HeroicSource
from src.importer.sources.itch_source import ItchSource
from src.importer.sources.legendary_source import LegendarySource
from src.importer.sources.retroarch_source import RetroarchSource
from src.importer.sources.location import UnresolvableLocationError
from src.importer.sources.lutris_source import LutrisSource
from src.importer.sources.source import Source
@@ -82,6 +83,9 @@ class PreferencesWindow(Adw.PreferencesWindow):
legendary_config_action_row = Gtk.Template.Child()
legendary_config_file_chooser_button = Gtk.Template.Child()
retroarch_expander_row = Gtk.Template.Child()
retroarch_config_file_chooser_button = Gtk.Template.Child()
flatpak_expander_row = Gtk.Template.Child()
flatpak_data_action_row = Gtk.Template.Child()
flatpak_data_file_chooser_button = Gtk.Template.Child()
@@ -138,6 +142,7 @@ class PreferencesWindow(Adw.PreferencesWindow):
ItchSource,
LegendarySource,
LutrisSource,
RetroarchSource,
SteamSource,
):
source = source_class()
@@ -385,3 +390,4 @@ class PreferencesWindow(Adw.PreferencesWindow):
# Set the source row subtitles
self.resolve_locations(source)
self.update_source_action_row_paths(source)