1
0
Fork 0
mirror of synced 2024-06-29 11:40:37 +12:00
Rare/rare/shared/workers/wine_resolver.py

148 lines
6.2 KiB
Python
Raw Normal View History

import os
import platform
import time
from configparser import ConfigParser
from logging import getLogger
from typing import Union, Iterable, Mapping, List
from PyQt5.QtCore import pyqtSignal, QObject, QRunnable
from rare.lgndr.core import LegendaryCore
from rare.models.game import RareGame
from rare.models.pathspec import PathSpec
from rare.utils import config_helper as config
from rare.utils.misc import path_size, format_size
from .worker import Worker
if platform.system() == "Windows":
# noinspection PyUnresolvedReferences
import winreg # pylint: disable=E0401
from legendary.lfs import windows_helpers
else:
from rare.utils import runners
logger = getLogger("WineResolver")
class WinePathResolver(Worker):
class Signals(QObject):
result_ready = pyqtSignal(str, str)
def __init__(self, command: List[str], environ: Mapping, path: str):
super(WinePathResolver, self). __init__()
self.signals = WinePathResolver.Signals()
self.command = command
self.environ = environ
self.path = path
@staticmethod
def _resolve_unix_path(cmd, env, path: str) -> str:
if "waitforexitandrun" in cmd:
cmd[cmd.index("waitforexitandrun")] = "runinprefix"
logger.info("Resolving path '%s'", path)
wine_path = runners.resolve_path(cmd, env, path)
logger.debug("Resolved Wine path '%s'", path)
unix_path = runners.convert_to_unix_path(cmd, env, wine_path)
logger.debug("Resolved Unix path '%s'", unix_path)
return unix_path
def run_real(self):
path = self._resolve_unix_path(self.command, self.environ, self.path)
self.signals.result_ready.emit(path, "default")
return
class WineSavePathResolver(WinePathResolver):
def __init__(self, core: LegendaryCore, rgame: RareGame):
cmd = core.get_app_launch_command(rgame.app_name, disable_wine=config.get_boolean(rgame.app_name, "no_wine"))
env = core.get_app_environment(rgame.app_name, disable_wine=config.get_boolean(rgame.app_name, "no_wine"))
env = runners.get_environment(env, silent=True)
path = PathSpec(core, rgame.igame).resolve_egl_path_vars(rgame.raw_save_path)
if not (cmd and env and path):
raise RuntimeError(f"Cannot setup {type(self).__name__}, missing infomation")
super(WineSavePathResolver, self).__init__(cmd, env, path)
self.rgame = rgame
def run_real(self):
logger.info("Resolving save path for %s (%s)", self.rgame.app_title, self.rgame.app_name)
path = self._resolve_unix_path(self.command, self.environ, self.path)
# Clean wine output
# pylint: disable=E1136
if os.path.exists(path):
self.rgame.save_path = path
self.signals.result_ready.emit(path, self.rgame.app_name)
return
class OriginWineWorker(QRunnable):
def __init__(self, core: LegendaryCore, games: Union[Iterable[RareGame], RareGame]):
super(OriginWineWorker, self).__init__()
self.__cache: dict[str, ConfigParser] = {}
self.core = core
self.games = [games] if isinstance(games, RareGame) else games
def run(self) -> None:
t = time.time()
for rgame in self.games:
reg_path: str = rgame.game.metadata \
.get("customAttributes", {}) \
.get("RegistryPath", {}).get("value", None)
if not reg_path:
continue
reg_key: str = rgame.game.metadata \
.get("customAttributes", {}) \
.get("RegistryKey", {}).get("value", None)
if not reg_key:
continue
if platform.system() == "Windows":
install_dir = windows_helpers.query_registry_value(winreg.HKEY_LOCAL_MACHINE, reg_path, reg_key)
else:
command = self.core.get_app_launch_command(rgame.app_name)
environ = self.core.get_app_environment(rgame.app_name)
environ = runners.get_environment(environ, silent=True)
prefix = config.get_prefix(rgame.app_name)
if not prefix:
return
use_wine = False
if not use_wine:
2023-12-08 21:46:07 +13:00
# lk: this is the original way of getting the path by parsing "system.reg"
reg = self.__cache.get(prefix, None) or runners.read_registry("system.reg", prefix)
self.__cache[prefix] = reg
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, f'"{reg_key}"', fallback=None)
else:
# lk: this is the alternative way of getting the path by using wine itself
install_dir = runners.query_reg_key(command, environ, f"HKLM\\{reg_path}", reg_key)
if install_dir:
2023-09-03 23:47:44 +12:00
logger.debug("Found Wine install directory %s", install_dir)
install_dir = runners.convert_to_unix_path(command, environ, install_dir)
2023-09-03 23:47:44 +12:00
if install_dir:
logger.debug("Found Unix install directory %s", install_dir)
else:
logger.info("Could not find Unix install directory for %s", rgame.app_title)
2023-09-03 23:47:44 +12:00
else:
logger.info("Could not find Wine install directory for %s", rgame.app_title)
if install_dir:
if os.path.isdir(install_dir):
install_size = path_size(install_dir)
rgame.set_origin_attributes(install_dir, install_size)
logger.info("Origin game %s (%s, %s)", rgame.app_title, install_dir, format_size(install_size))
else:
logger.warning("Origin game %s (%s does not exist)", rgame.app_title, install_dir)
2023-09-03 23:47:44 +12:00
else:
logger.info("Origin game %s is not installed", rgame.app_title)
2023-09-03 23:47:44 +12:00
logger.info("Origin worker finished in %ss", time.time() - t)