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:
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" : [
|
||||
|
||||
119
src/importer/sources/retroarch_source.py
Normal file
119
src/importer/sources/retroarch_source.py
Normal 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
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user