1
0
Fork 0
mirror of synced 2024-09-18 18:38:52 +12:00
Rare/rare/shared/workers/wine_resolver.py

144 lines
5.9 KiB
Python
Raw Normal View History

import os
import platform
import time
from configparser import ConfigParser
from logging import getLogger
2023-09-24 06:21:58 +13:00
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
2023-09-24 06:21:58 +13:00
from rare.utils import runners, config_helper as config
from rare.utils.misc import path_size, format_size
from .worker import Worker
if platform.system() == "Windows":
# noinspection PyUnresolvedReferences
2023-09-24 06:21:58 +13:00
import winreg # pylint: disable=E0401
from legendary.lfs import windows_helpers
logger = getLogger("WineResolver")
2023-09-24 06:21:58 +13:00
class WinePathResolver(Worker):
class Signals(QObject):
2023-09-24 06:21:58 +13:00
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:
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
2023-09-24 06:21:58 +13:00
class WineSavePathResolver(WinePathResolver):
def __init__(self, core: LegendaryCore, rgame: RareGame):
cmd = core.get_app_launch_command(rgame.app_name)
env = core.get_app_environment(rgame.app_name)
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):
2023-09-24 06:21:58 +13:00
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
2023-09-24 06:21:58 +13:00
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
2023-09-24 06:21:58 +13:00
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:
2023-09-24 06:21:58 +13:00
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-09-24 06:21:58 +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
2023-09-24 06:21:58 +13:00
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)
2023-09-24 06:21:58 +13:00
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.title)
else:
logger.info("Could not find Wine install directory for %s", rgame.title)
if install_dir:
if os.path.isdir(install_dir):
install_size = path_size(install_dir)
rgame.set_origin_attributes(install_dir, install_size)
2023-09-03 23:47:44 +12:00
logger.info("Origin game %s (%s, %s)", rgame.title, install_dir, format_size(install_size))
else:
2023-09-03 23:47:44 +12:00
logger.warning("Origin game %s (%s does not exist)", rgame.title, install_dir)
else:
logger.info("Origin game %s is not installed", rgame.title)
logger.info("Origin worker finished in %ss", time.time() - t)