Wine: Set environment through flatpak-spawn
arguments
Partially fixes #305
This commit is contained in:
parent
909c3cbdc1
commit
45ad3e2632
|
@ -68,7 +68,7 @@ class PreLaunchThread(QRunnable):
|
|||
|
||||
if launch_args.pre_launch_command:
|
||||
proc = get_configured_process()
|
||||
proc.setProcessEnvironment(launch_args.env)
|
||||
proc.setProcessEnvironment(launch_args.environment)
|
||||
self.signals.started_pre_launch_command.emit()
|
||||
proc.start(launch_args.pre_launch_command[0], launch_args.pre_launch_command[1:])
|
||||
if launch_args.pre_launch_wait:
|
||||
|
@ -119,6 +119,7 @@ class RareLauncher(RareApp):
|
|||
|
||||
def __init__(self, args: InitArgs):
|
||||
super(RareLauncher, self).__init__(args, f"{type(self).__name__}_{args.app_name}_{{0}}.log")
|
||||
self.socket: Optional[QLocalSocket] = None
|
||||
self._hook.deleteLater()
|
||||
self._hook = RareLauncherException(self, args, self)
|
||||
|
||||
|
@ -126,7 +127,11 @@ class RareLauncher(RareApp):
|
|||
self.no_sync_on_exit = False
|
||||
self.args = args
|
||||
self.core = LegendaryCore()
|
||||
self.rgame = RareGameSlim(self.core, self.core.get_game(args.app_name))
|
||||
game = self.core.get_game(args.app_name)
|
||||
if not game:
|
||||
self.logger.error(f"Game {args.app_name} not found. Exiting")
|
||||
QApplication.exit(1)
|
||||
self.rgame = RareGameSlim(self.core, game)
|
||||
|
||||
lang = self.settings.value("language", self.core.language_code, type=str)
|
||||
self.load_translator(lang)
|
||||
|
@ -242,13 +247,14 @@ class RareLauncher(RareApp):
|
|||
)
|
||||
self.stop()
|
||||
|
||||
@pyqtSlot(object)
|
||||
def launch_game(self, args: LaunchArgs):
|
||||
# should never happen
|
||||
if not args:
|
||||
self.stop()
|
||||
return
|
||||
if self.console:
|
||||
self.console.set_env(args.env)
|
||||
self.console.set_env(args.environment)
|
||||
self.start_time = time.time()
|
||||
|
||||
if args.is_origin_game:
|
||||
|
@ -256,9 +262,9 @@ class RareLauncher(RareApp):
|
|||
self.stop() # stop because it is no subprocess
|
||||
return
|
||||
|
||||
if args.cwd:
|
||||
self.game_process.setWorkingDirectory(args.cwd)
|
||||
self.game_process.setProcessEnvironment(args.env)
|
||||
if args.working_directory:
|
||||
self.game_process.setWorkingDirectory(args.working_directory)
|
||||
self.game_process.setProcessEnvironment(args.environment)
|
||||
# send start message after process started
|
||||
self.game_process.started.connect(lambda: self.send_message(
|
||||
StateChangedModel(
|
||||
|
@ -268,8 +274,8 @@ class RareLauncher(RareApp):
|
|||
))
|
||||
if self.rgame.app_name in DETACHED_APP_NAMES and platform.system() == "Windows":
|
||||
self.game_process.deleteLater()
|
||||
subprocess.Popen([args.executable] + args.args, cwd=args.cwd,
|
||||
env={i: args.env.value(i) for i in args.env.keys()})
|
||||
subprocess.Popen([args.executable] + args.arguments, cwd=args.working_directory,
|
||||
env={i: args.environment.value(i) for i in args.environment.keys()})
|
||||
if self.console:
|
||||
self.console.log("Launching game detached")
|
||||
self.stop()
|
||||
|
@ -277,13 +283,13 @@ class RareLauncher(RareApp):
|
|||
if self.args.dry_run:
|
||||
self.logger.info("Dry run activated")
|
||||
if self.console:
|
||||
self.console.log(f"{args.executable} {' '.join(args.args)}")
|
||||
self.console.log(f"{args.executable} {' '.join(args.arguments)}")
|
||||
self.console.log(f"Do not start {self.rgame.app_name}")
|
||||
self.console.accept_close = True
|
||||
print(args.executable, " ".join(args.args))
|
||||
print(args.executable, " ".join(args.arguments))
|
||||
self.stop()
|
||||
return
|
||||
self.game_process.start(args.executable, args.args)
|
||||
self.game_process.start(args.executable, args.arguments)
|
||||
|
||||
def error_occurred(self, error_str: str):
|
||||
self.logger.warning(error_str)
|
||||
|
|
|
@ -44,9 +44,9 @@ class InitArgs(Namespace):
|
|||
@dataclass
|
||||
class LaunchArgs:
|
||||
executable: str = ""
|
||||
args: List[str] = None
|
||||
cwd: str = None
|
||||
env: QProcessEnvironment = None
|
||||
arguments: List[str] = None
|
||||
working_directory: str = None
|
||||
environment: QProcessEnvironment = None
|
||||
pre_launch_command: str = ""
|
||||
pre_launch_wait: bool = False
|
||||
is_origin_game: bool = False # only for windows to launch as url
|
||||
|
@ -60,7 +60,7 @@ def get_origin_params(core: LegendaryCore, app_name, offline: bool,
|
|||
origin_uri = core.get_origin_uri(app_name, offline)
|
||||
if platform.system() == "Windows":
|
||||
launch_args.executable = origin_uri
|
||||
launch_args.args = []
|
||||
launch_args.arguments = []
|
||||
# only set it here true, because on linux it is a launch command like every other game
|
||||
launch_args.is_origin_game = True
|
||||
return launch_args
|
||||
|
@ -71,12 +71,19 @@ def get_origin_params(core: LegendaryCore, app_name, offline: bool,
|
|||
command.append(origin_uri)
|
||||
|
||||
env = core.get_app_environment(app_name)
|
||||
launch_args.env = QProcessEnvironment.systemEnvironment()
|
||||
|
||||
if os.environ.get("container") == "flatpak":
|
||||
flatpak_command = ["flatpak-spawn", "--host"]
|
||||
for name, value in env.items():
|
||||
flatpak_command.append(f"--env={name}={value}")
|
||||
command = flatpak_command.extend(command)
|
||||
|
||||
launch_args.environment = QProcessEnvironment.systemEnvironment()
|
||||
for name, value in env.items():
|
||||
launch_args.env.insert(name, value)
|
||||
launch_args.environment.insert(name, value)
|
||||
|
||||
launch_args.executable = command[0]
|
||||
launch_args.args = command[1:]
|
||||
launch_args.arguments = command[1:]
|
||||
return launch_args
|
||||
|
||||
|
||||
|
@ -100,10 +107,12 @@ def get_game_params(core: LegendaryCore, igame: InstalledGame, args: InitArgs,
|
|||
app_name=igame.app_name, offline=args.offline
|
||||
)
|
||||
|
||||
full_params = list()
|
||||
full_params = []
|
||||
|
||||
if os.environ.get("container") == "flatpak":
|
||||
full_params.extend(["flatpak-spawn", "--host"])
|
||||
for name, value in params.environment.items():
|
||||
full_params.append(f"--env={name}={value}")
|
||||
|
||||
full_params.extend(params.launch_command)
|
||||
full_params.append(
|
||||
|
@ -114,12 +123,12 @@ def get_game_params(core: LegendaryCore, igame: InstalledGame, args: InitArgs,
|
|||
full_params.extend(params.user_parameters)
|
||||
|
||||
launch_args.executable = full_params[0]
|
||||
launch_args.args = full_params[1:]
|
||||
launch_args.arguments = full_params[1:]
|
||||
|
||||
launch_args.env = QProcessEnvironment.systemEnvironment()
|
||||
launch_args.environment = QProcessEnvironment.systemEnvironment()
|
||||
for name, value in params.environment.items():
|
||||
launch_args.env.insert(name, value)
|
||||
launch_args.cwd = params.working_directory
|
||||
launch_args.environment.insert(name, value)
|
||||
launch_args.working_directory = params.working_directory
|
||||
return launch_args
|
||||
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class WineResolver(Worker):
|
|||
# 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)):
|
||||
if not os.path.exists(self.wine_exec):
|
||||
# pylint: disable=E1136
|
||||
self.signals.result_ready[str].emit("")
|
||||
return
|
||||
|
@ -82,28 +82,33 @@ class OriginWineWorker(QRunnable):
|
|||
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
|
||||
use_wine = False
|
||||
if not use_wine:
|
||||
# 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)])
|
||||
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)
|
||||
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 = wine.query_reg_key(wine_exec, wine_env, f"HKLM\\{reg_path}", reg_key)
|
||||
|
||||
# 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)
|
||||
logger.debug("Found Wine install directory %s", install_dir)
|
||||
|
||||
if install_dir:
|
||||
install_dir = wine.convert_to_unix_path(wine_exec, wine_env, install_dir)
|
||||
logger.debug("Found Unix install directory %s", install_dir)
|
||||
|
||||
if install_dir:
|
||||
if os.path.isdir(install_dir):
|
||||
install_size = path_size(install_dir)
|
||||
rgame.set_origin_attributes(install_dir, install_size)
|
||||
logger.debug(f"Found Origin game {rgame.title} ({install_dir}, {format_size(install_size)})")
|
||||
logger.debug(f"Origin game {rgame.title} ({install_dir}, {format_size(install_size)})")
|
||||
else:
|
||||
logger.warning(f"Found Origin game {rgame.title} ({install_dir} does not exist)")
|
||||
logger.info(f"Origin registry worker finished in {time.time() - t}s")
|
||||
logger.warning(f"Origin game {rgame.title} ({install_dir} does not exist)")
|
||||
logger.info(f"Origin worker finished in {time.time() - t}s")
|
||||
|
|
|
@ -2,10 +2,13 @@ import os
|
|||
import shutil
|
||||
import subprocess
|
||||
from configparser import ConfigParser
|
||||
from logging import getLogger
|
||||
from typing import Mapping, Dict, List, Tuple
|
||||
|
||||
from rare.lgndr.core import LegendaryCore
|
||||
|
||||
logger = getLogger("Wine")
|
||||
|
||||
|
||||
# this is a copied function from legendary.utils.wine_helpers, but registry file can be specified
|
||||
def read_registry(registry: str, wine_pfx: str) -> ConfigParser:
|
||||
|
@ -21,16 +24,22 @@ def read_registry(registry: str, wine_pfx: str) -> ConfigParser:
|
|||
|
||||
def execute(cmd: List, wine_env: Mapping) -> Tuple[str, str]:
|
||||
if os.environ.get("container") == "flatpak":
|
||||
cmd = ["flatpak-spawn", "--host"] + cmd
|
||||
flatpak_cmd = ["flatpak-spawn", "--host"]
|
||||
for name, value in wine_env.items():
|
||||
flatpak_cmd.append(f"--env={name}={value}")
|
||||
cmd = flatpak_cmd + cmd
|
||||
proc = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
env=wine_env,
|
||||
# Use the current environment if we are in flatpak or our own if we are on host
|
||||
# In flatpak our environment is passed through `flatpak-spawn` arguments
|
||||
env=os.environ.copy() if os.environ.get("container") == "flatpak" else wine_env,
|
||||
shell=False,
|
||||
text=True,
|
||||
)
|
||||
return proc.communicate()
|
||||
res = proc.communicate()
|
||||
return res
|
||||
|
||||
|
||||
def resolve_path(wine_exec: str, wine_env: Mapping, path: str) -> str:
|
||||
|
@ -65,18 +74,11 @@ def convert_to_windows_path(wine_exec: str, wine_env: Mapping, path: str) -> str
|
|||
|
||||
def convert_to_unix_path(wine_exec: str, wine_env: Mapping, path: str) -> str:
|
||||
path = path.strip().strip('"')
|
||||
cmd = [winepath(wine_exec), "-u", path]
|
||||
cmd = [wine_exec, "winepath.exe", "-u", path]
|
||||
out, err = execute(cmd, wine_env)
|
||||
return os.path.realpath(out.strip())
|
||||
|
||||
|
||||
def winepath(wine_exec: str) -> str:
|
||||
_winepath = os.path.join(os.path.dirname(wine_exec), "winepath")
|
||||
if not os.path.isfile(_winepath):
|
||||
return ""
|
||||
return _winepath
|
||||
|
||||
|
||||
def wine(core: LegendaryCore, app_name: str = "default") -> str:
|
||||
_wine = core.lgd.config.get(
|
||||
app_name, "wine_executable", fallback=core.lgd.config.get(
|
||||
|
@ -87,8 +89,11 @@ def wine(core: LegendaryCore, app_name: str = "default") -> str:
|
|||
|
||||
|
||||
def environ(core: LegendaryCore, app_name: str = "default") -> Dict:
|
||||
_environ = os.environ.copy()
|
||||
# Get a clean environment if we are in flatpak, this environment will be pass
|
||||
# to `flatpak-spawn`, otherwise use the system's.
|
||||
_environ = {} if os.environ.get("container") == "flatpak" else os.environ.copy()
|
||||
_environ.update(core.get_app_environment(app_name))
|
||||
_environ["WINEDEBUG"] = "-all"
|
||||
_environ["WINEDLLOVERRIDES"] = "winemenubuilder=d;mscoree=d;mshtml=d;"
|
||||
_environ["DISPLAY"] = ""
|
||||
return _environ
|
||||
|
|
Loading…
Reference in a new issue