1
0
Fork 0
mirror of synced 2024-06-26 18:20:50 +12:00

OriginWineWorker: Execute during launch and properly resolve paths for Wine

This commit is contained in:
loathingKernel 2023-03-07 22:53:18 +02:00
parent d399382afd
commit 92346e11d0
No known key found for this signature in database
GPG key ID: CE0C72D0B53821FD
6 changed files with 60 additions and 24 deletions

View file

@ -1,6 +1,6 @@
from logging import getLogger
from PyQt5.QtCore import QSettings, Qt, pyqtSlot, QThreadPool
from PyQt5.QtCore import QSettings, Qt, pyqtSlot
from PyQt5.QtWidgets import QStackedWidget, QVBoxLayout, QWidget, QScrollArea, QFrame
from rare.models.game import RareGame
@ -11,7 +11,6 @@ from rare.shared import (
ImageManagerSingleton,
)
from rare.shared import RareCore
from rare.shared.workers.wine_resolver import OriginWineWorker
from rare.widgets.library_layout import LibraryLayout
from rare.widgets.sliding_stack import SlidingStackedWidget
from .game_info import GameInfoTabs
@ -155,9 +154,6 @@ class GamesTab(QStackedWidget):
self.filter_games(self.active_filter)
self.update_count_games_label()
worker = OriginWineWorker(self.core, self.rcore.origin_games)
QThreadPool.globalInstance().start(worker)
def add_library_widget(self, rgame: RareGame):
try:
icon_widget, list_widget = self.library_controller.add_game(rgame)

View file

@ -248,7 +248,7 @@ class GameInfo(QWidget, SideTabContents):
self.ui.lbl_install_size.setEnabled(bool(self.rgame.install_size))
self.ui.install_size.setEnabled(bool(self.rgame.install_size))
self.ui.install_size.setText(
format_size(self.rgame.igame.install_size) if self.rgame.install_size else "N/A"
format_size(self.rgame.install_size) if self.rgame.install_size else "N/A"
)
self.ui.lbl_install_path.setEnabled(bool(self.rgame.install_path))

View file

@ -21,6 +21,7 @@ from .workers import (
FetchWorker,
GamesWorker,
NonAssetWorker,
OriginWineWorker,
SavesWorker,
EntitlementsWorker,
)
@ -48,6 +49,7 @@ class RareCore(QObject):
self.__games_fetched: bool = False
self.__non_asset_fetched: bool = False
self.__origin_resolved: bool = False
self.__saves_fetched: bool = False
self.__entitlements_fetched: bool = False
@ -276,6 +278,9 @@ class RareCore(QObject):
self.__add_games_and_dlcs(games, dlc_dict)
self.__non_asset_fetched = True
status = "Loaded games without assets"
if res_type == FetchWorker.Result.ORIGIN:
self.__origin_resolved = True
status = "Resolved Origin installation status"
if res_type == FetchWorker.Result.SAVES:
saves, _ = result
for save in saves:
@ -291,6 +296,7 @@ class RareCore(QObject):
fetched = [
self.__games_fetched,
self.__non_asset_fetched,
self.__origin_resolved,
self.__saves_fetched,
self.__entitlements_fetched,
]
@ -307,6 +313,7 @@ class RareCore(QObject):
def fetch(self):
self.__games_fetched: bool = False
self.__non_asset_fetched: bool = False
self.__origin_resolved: bool = False
self.__saves_fetched: bool = False
self.__entitlements_fetched: bool = False
@ -325,9 +332,16 @@ class RareCore(QObject):
else:
self.__saves_fetched = True
def resolve_origin(self):
origin_worker = OriginWineWorker(self.__core, self.__args, self.origin_games)
origin_worker.signals.result.connect(self.handle_result)
QThreadPool.globalInstance().start(origin_worker)
def fetch_extra(self):
non_asset_worker = NonAssetWorker(self.__core, self.__args)
non_asset_worker.signals.result.connect(self.handle_result)
non_asset_worker.signals.finished.connect(self.resolve_origin)
QThreadPool.globalInstance().start(non_asset_worker)
entitlements_worker = EntitlementsWorker(self.__core, self.__args)

View file

@ -3,4 +3,5 @@ from .install_info import InstallInfoWorker
from .move import MoveWorker
from .uninstall import UninstallWorker
from .verify import VerifyWorker
from .wine_resolver import OriginWineWorker
from .worker import Worker, QueueWorker

View file

@ -16,6 +16,7 @@ class FetchWorker(Worker):
class Result(IntEnum):
GAMES = 1
NON_ASSET = 2
ORIGIN = 3
SAVES = 5
ENTITLEMENTS = 6

View file

@ -2,16 +2,18 @@ import os
import platform
import subprocess
import time
from argparse import Namespace
from configparser import ConfigParser
from logging import getLogger
from typing import Union, Iterator
from PyQt5.QtCore import pyqtSignal, QObject, QRunnable
from PyQt5.QtCore import pyqtSignal, QObject
from rare.lgndr.core import LegendaryCore
from rare.models.game import RareGame
from rare.models.pathspec import PathSpec
from rare.utils.misc import read_registry, path_size, format_size
from .fetch import FetchWorker
from .worker import Worker
if platform.system() == "Windows":
@ -35,9 +37,9 @@ class WineResolver(Worker):
self.wine_env["DISPLAY"] = ""
self.wine_binary = core.lgd.config.get(
app_name,
"wine_executable",
fallback=core.lgd.config.get("default", "wine_executable", fallback="wine"),
app_name, "wine_executable", fallback=core.lgd.config.get(
"default", "wine_executable", fallback="wine"
)
)
self.winepath_binary = os.path.join(os.path.dirname(self.wine_binary), "winepath")
self.path = PathSpec(core, app_name).cook(path)
@ -82,19 +84,15 @@ class WineResolver(Worker):
return
class OriginWineWorker(QRunnable):
def __init__(self, core: LegendaryCore, games: Union[Iterator[RareGame], RareGame]):
super().__init__()
self.setAutoDelete(True)
class OriginWineWorker(FetchWorker):
def __init__(self, core: LegendaryCore, args: Namespace, games: Union[Iterator[RareGame], RareGame]):
super(OriginWineWorker, self).__init__(core, args)
self.__cache: dict[str, ConfigParser] = {}
if isinstance(games, RareGame):
games = [games]
self.games = games
self.core = core
def run(self) -> None:
def run_real(self) -> None:
t = time.time()
for rgame in self.games:
if not rgame.is_origin:
@ -109,16 +107,41 @@ class OriginWineWorker(QRunnable):
if platform.system() == "Windows":
install_dir = windows_helpers.query_registry_value(winreg.HKEY_LOCAL_MACHINE, reg_path, "Install Dir")
else:
wine_prefix = self.core.lgd.config.get(rgame.app_name, "wine_prefix",
fallback=os.path.expanduser("~/.wine"))
reg = self.__cache.get(wine_prefix) or read_registry("system.reg", wine_prefix)
wine_prefix = self.core.lgd.config.get(
rgame.app_name, "wine_prefix", fallback=self.core.lgd.config.get(
"default", "wine_prefix", fallback=os.path.expanduser("~/.wine")
)
)
reg = self.__cache.get(wine_prefix, None) or read_registry("system.reg", wine_prefix)
self.__cache[wine_prefix] = reg
# TODO: find a better solution
reg_path = reg_path.replace("\\", "\\\\") \
.replace("SOFTWARE", "Software").replace("WOW6432Node", "Wow6432Node")
reg_path = reg_path.replace("SOFTWARE", "Software").replace("WOW6432Node", "Wow6432Node")
# lk: split and rejoin the registry path to avoid slash expansion
reg_path = "\\\\".join([x for x in reg_path.split("\\") if bool(x)])
install_dir = reg.get(reg_path, '"Install Dir"', fallback=None)
if install_dir:
wine = self.core.lgd.config.get(
rgame.app_name, "wine_executable", fallback=self.core.lgd.config.get(
"default", "wine_executable", fallback="wine"
)
)
winepath = os.path.join(os.path.dirname(wine), "winepath")
wine_env = os.environ.copy()
wine_env.update(self.core.get_app_environment(rgame.app_name))
wine_env["WINEDLLOVERRIDES"] = "winemenubuilder=d;mscoree=d;mshtml=d;"
wine_env["DISPLAY"] = ""
install_dir = install_dir.strip().strip('"')
proc = subprocess.Popen(
[winepath, "-u", install_dir],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=wine_env,
shell=False,
text=True,
)
out, err = proc.communicate()
install_dir = os.path.realpath(out.strip())
if install_dir:
if os.path.exists(install_dir):
size = path_size(install_dir)
@ -126,4 +149,5 @@ class OriginWineWorker(QRunnable):
logger.debug(f"Found Origin game {rgame.title} ({install_dir}, {format_size(size)})")
else:
logger.warning(f"Found Origin game {rgame.title} ({install_dir} does not exist)")
self.signals.result.emit((), FetchWorker.Result.ORIGIN)
logger.info(f"Origin registry worker finished in {time.time() - t}s")