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

111 lines
4.5 KiB
Python
Raw Normal View History

import os
import platform
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
import rare.utils.wine as wine
from rare.lgndr.core import LegendaryCore
from rare.models.game import RareGame
from rare.models.pathspec import PathSpec
from rare.utils.misc import path_size, format_size
from .fetch import FetchWorker
from .worker import Worker
if platform.system() == "Windows":
# noinspection PyUnresolvedReferences
import winreg # pylint: disable=E0401
from legendary.lfs import windows_helpers
logger = getLogger("WineResolver")
class WineResolver(Worker):
class Signals(QObject):
result_ready = pyqtSignal(str)
def __init__(self, core: LegendaryCore, path: str, app_name: str):
super(WineResolver, self).__init__()
self.signals = WineResolver.Signals()
self.wine_env = wine.environ(core, app_name)
self.wine_exec = wine.wine(core, app_name)
self.path = PathSpec(core, app_name).cook(path)
def run_real(self):
if "WINEPREFIX" not in self.wine_env or not os.path.exists(self.wine_env["WINEPREFIX"]):
# pylint: disable=E1136
self.signals.result_ready[str].emit("")
return
if not os.path.exists(self.wine_exec) or not os.path.exists(wine.winepath(self.wine_exec)):
# pylint: disable=E1136
self.signals.result_ready[str].emit("")
return
path = wine.resolve_path(self.wine_exec, self.wine_env, self.path)
# Clean wine output
real_path = wine.convert_to_unix_path(self.wine_exec, self.wine_env, path)
# pylint: disable=E1136
self.signals.result_ready[str].emit(real_path)
return
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
def run_real(self) -> None:
t = time.time()
for rgame in self.games:
if not rgame.is_origin:
continue
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 platform.system() == "Windows":
install_dir = windows_helpers.query_registry_value(winreg.HKEY_LOCAL_MACHINE, reg_path, reg_key)
else:
wine_env = wine.environ(self.core, rgame.app_name)
wine_exec = wine.wine(self.core, rgame.app_name)
# lk: this is the original way of gettijng the path by parsing "system.reg"
wine_prefix = wine.prefix(self.core, rgame.app_name)
reg = self.__cache.get(wine_prefix, None) or wine.read_registry("system.reg", wine_prefix)
self.__cache[wine_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)
# lk: this is the alternative way of getting the path by using wine itself
# install_dir = wine.query_reg_key(wine_exec, wine_env, f"HKLM\\{reg_path}", reg_key)
if install_dir:
install_dir = wine.convert_to_unix_path(wine_exec, wine_env, install_dir)
if install_dir:
if os.path.isdir(install_dir):
size = path_size(install_dir)
rgame.set_origin_attributes(install_dir, size)
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")