def get_env(self, os_env=False): env = {} if os_env: env.update(os.environ.copy()) system_env = self.system_config.get('env') or {} env.update(system_env) dri_prime = self.system_config.get('dri_prime') if dri_prime: env["DRI_PRIME"] = "1" else: env["DRI_PRIME"] = "0" runtime_ld_library_path = None if self.use_runtime(): runtime_env = runtime.get_env() if 'STEAM_RUNTIME' in runtime_env and 'STEAM_RUNTIME' not in env: env['STEAM_RUNTIME'] = runtime_env['STEAM_RUNTIME'] if 'LD_LIBRARY_PATH' in runtime_env: runtime_ld_library_path = runtime_env['LD_LIBRARY_PATH'] if runtime_ld_library_path: ld_library_path = env.get("LD_LIBRARY_PATH") if not ld_library_path: ld_library_path = '$LD_LIBRARY_PATH' ld_library_path = ":".join([runtime_ld_library_path, ld_library_path]) env["LD_LIBRARY_PATH"] = ld_library_path return env
def execute(self, data): """Run an executable file.""" args = [] if isinstance(data, dict): self._check_required_params("file", data, "execute") file_ref = data["file"] args_string = data.get("args", "") for arg in shlex.split(args_string): args.append(self._substitute(arg)) else: file_ref = data # Determine whether 'file' value is a file id or a path exec_path = self._get_file(file_ref) or self._substitute(file_ref) if not exec_path: raise ScriptingError("Unable to find file %s" % file_ref, file_ref) if not os.path.exists(exec_path): raise ScriptingError("Unable to find required executable", exec_path) self.chmodx(exec_path) terminal = data.get("terminal") if terminal: terminal = system.get_default_terminal() command = [exec_path] + args logger.debug("Executing %s" % command) thread = LutrisThread(command, env=runtime.get_env(), term=terminal, cwd=self.target_path) self.abort_current_task = thread.killall thread.run() self.abort_current_task = None
def get_runtime_env(self): """Return runtime environment variables. This method may be overridden in runner classes. (Notably for Lutris wine builds) Returns: dict """ return runtime.get_env( prefer_system_libs=self.system_config.get("prefer_system_libs", True) )
def run(self, *args): """Run the runner alone.""" if not self.runnable_alone: return if not self.is_installed(): installed = self.install_dialog() if not installed: return command_data = self.get_run_data() command = command_data.get('command') env = (command_data.get('env') or {}).copy() if self.use_runtime(): env.update(runtime.get_env()) thread = LutrisThread(command, runner=self, env=env, watch=False) thread.start()
def get_runtime_env(self): """Return runtime environment variables with path to wine for Lutris builds""" wine_path = self.get_executable() wine_root = None if WINE_DIR: wine_root = os.path.dirname(os.path.dirname(wine_path)) for proton_path in get_proton_paths(): if proton_path in wine_path: wine_root = os.path.dirname(os.path.dirname(wine_path)) if "-4." in wine_path or "/4." in wine_path: version = "Ubuntu-18.04" else: version = "legacy" return runtime.get_env( version=version, prefer_system_libs=self.system_config.get("prefer_system_libs", True), wine_path=wine_root )
def get_runtime_env(self): """Return runtime environment variables with path to wine for Lutris builds""" wine_path = self.get_executable() wine_root = None if WINE_DIR: wine_root = os.path.dirname(os.path.dirname(wine_path)) for proton_path in get_proton_paths(): if proton_path in wine_path: wine_root = os.path.dirname(os.path.dirname(wine_path)) if "-4." in wine_path or "/4." in wine_path: version = "Ubuntu-18.04" else: version = "legacy" return runtime.get_env( version=version, prefer_system_libs=self.system_config.get("prefer_system_libs", True), wine_path=wine_root, )
def execute(self, data): """Run an executable file.""" args = [] terminal = None working_dir = None if isinstance(data, dict): self._check_required_params('file', data, 'execute') file_ref = data['file'] args_string = data.get('args', '') for arg in shlex.split(args_string): args.append(self._substitute(arg)) terminal = data.get('terminal') working_dir = data.get('working_dir') else: file_ref = data # Determine whether 'file' value is a file id or a path exec_path = self._get_file(file_ref) or self._substitute(file_ref) if not exec_path: raise ScriptingError("Unable to find file %s" % file_ref, file_ref) if not os.path.exists(exec_path): raise ScriptingError("Unable to find required executable", exec_path) if not os.access(exec_path, os.X_OK): self.chmodx(exec_path) if terminal: terminal = system.get_default_terminal() if not working_dir or not os.path.exists(working_dir): working_dir = self.target_path command = [exec_path] + args logger.debug("Executing %s" % command) thread = LutrisThread(command, env=runtime.get_env(), term=terminal, cwd=self.target_path, watch=False) self.abort_current_task = thread.killall thread.run() self.abort_current_task = None
def run(self, *args): """Run the runner alone.""" if not self.runnable_alone: return if not self.is_installed(): installed = self.install_dialog() if not installed: return if self.use_runtime(): if runtime.is_outdated() or runtime.is_updating(): result = dialogs.RuntimeUpdateDialog().run() if not result == Gtk.ResponseType.OK: return command_data = self.get_run_data() command = command_data.get('command') env = (command_data.get('env') or {}).copy() if self.use_runtime(): env.update(runtime.get_env()) thread = LutrisThread(command, runner=self, env=env, watch=False) thread.start()
def do_play(self, prelaunched, _error=None): if not prelaunched: self.state = self.STATE_STOPPED return system_config = self.runner.system_config self.original_outputs = display.get_outputs() gameplay_info = self.runner.play() env = {} logger.debug("Launching %s: %s" % (self.name, gameplay_info)) if 'error' in gameplay_info: self.show_error_message(gameplay_info) self.state = self.STATE_STOPPED return sdl_video_fullscreen = system_config.get('sdl_video_fullscreen') or '' env['SDL_VIDEO_FULLSCREEN_DISPLAY'] = sdl_video_fullscreen restrict_to_display = system_config.get('display') if restrict_to_display != 'off': display.turn_off_except(restrict_to_display) time.sleep(3) self.resolution_changed = True resolution = system_config.get('resolution') if resolution != 'off': display.change_resolution(resolution) time.sleep(3) self.resolution_changed = True if system_config.get('reset_pulse'): audio.reset_pulse() self.killswitch = system_config.get('killswitch') if self.killswitch and not os.path.exists(self.killswitch): # Prevent setting a killswitch to a file that doesn't exists self.killswitch = None # Command launch_arguments = gameplay_info['command'] primusrun = system_config.get('primusrun') if primusrun and system.find_executable('primusrun'): launch_arguments.insert(0, 'primusrun') xephyr = system_config.get('xephyr') or 'off' if xephyr != 'off': if xephyr == '8bpp': xephyr_depth = '8' else: xephyr_depth = '16' xephyr_resolution = system_config.get('xephyr_resolution') or '640x480' xephyr_command = ['Xephyr', ':2', '-ac', '-screen', xephyr_resolution + 'x' + xephyr_depth, '-glamor', '-reset', '-terminate', '-fullscreen'] xephyr_thread = LutrisThread(xephyr_command) xephyr_thread.start() time.sleep(3) env['DISPLAY'] = ':2' if system_config.get('use_us_layout'): setxkbmap_command = ['setxkbmap', '-model', 'pc101', 'us', '-print'] xkbcomp_command = ['xkbcomp', '-', os.environ.get('DISPLAY', ':0')] xkbcomp = subprocess.Popen(xkbcomp_command, stdin=subprocess.PIPE) subprocess.Popen(setxkbmap_command, env=os.environ, stdout=xkbcomp.stdin).communicate() xkbcomp.communicate() pulse_latency = system_config.get('pulse_latency') if pulse_latency: env['PULSE_LATENCY_MSEC'] = '60' prefix_command = system_config.get("prefix_command") or '' if prefix_command.strip(): launch_arguments.insert(0, prefix_command) single_cpu = system_config.get('single_cpu') or False if single_cpu: logger.info('The game will run on a single CPU core') launch_arguments.insert(0, '0') launch_arguments.insert(0, '-c') launch_arguments.insert(0, 'taskset') terminal = system_config.get('terminal') if terminal: terminal = system_config.get("terminal_app", system.get_default_terminal()) if terminal and not system.find_executable(terminal): dialogs.ErrorDialog("The selected terminal application " "could not be launched:\n" "%s" % terminal) self.state = self.STATE_STOPPED return # Env vars game_env = gameplay_info.get('env') or {} env.update(game_env) system_env = system_config.get('env') or {} env.update(system_env) ld_preload = gameplay_info.get('ld_preload') or '' env["LD_PRELOAD"] = ld_preload # Runtime management ld_library_path = "" if self.runner.use_runtime(): runtime_env = runtime.get_env() if 'STEAM_RUNTIME' in runtime_env and 'STEAM_RUNTIME' not in env: env['STEAM_RUNTIME'] = runtime_env['STEAM_RUNTIME'] if 'LD_LIBRARY_PATH' in runtime_env: ld_library_path = runtime_env['LD_LIBRARY_PATH'] game_ld_libary_path = gameplay_info.get('ld_library_path') if game_ld_libary_path: if not ld_library_path: ld_library_path = '$LD_LIBRARY_PATH' ld_library_path = ":".join([game_ld_libary_path, ld_library_path]) env["LD_LIBRARY_PATH"] = ld_library_path # /Env vars self.game_thread = LutrisThread(launch_arguments, runner=self.runner, env=env, rootpid=gameplay_info.get('rootpid'), term=terminal) if hasattr(self.runner, 'stop'): self.game_thread.set_stop_command(self.runner.stop) self.game_thread.start() self.state = self.STATE_RUNNING if 'joy2key' in gameplay_info: self.joy2key(gameplay_info['joy2key']) xboxdrv_config = system_config.get('xboxdrv') if xboxdrv_config: self.xboxdrv_start(xboxdrv_config) self.heartbeat = GLib.timeout_add(HEARTBEAT_DELAY, self.beat)
def execute(self, data): """Run an executable file.""" args = [] terminal = None working_dir = None env = {} if isinstance(data, dict): self._check_required_params([("file", "command")], data, "execute") if "command" in data and "file" in data: raise ScriptingError( "Parameters file and command can't be used " "at the same time for the execute command", data, ) file_ref = data.get("file", "") command = data.get("command", "") args_string = data.get("args", "") for arg in shlex.split(args_string): args.append(self._substitute(arg)) terminal = data.get("terminal") working_dir = data.get("working_dir") if not data.get("disable_runtime"): # Possibly need to handle prefer_system_libs here env.update(runtime.get_env()) # Loading environment variables set in the script env.update(self.script_env) # Environment variables can also be passed to the execute command local_env = data.get("env") or {} env.update({key: self._substitute(value) for key, value in local_env.items()}) include_processes = shlex.split(data.get("include_processes", "")) exclude_processes = shlex.split(data.get("exclude_processes", "")) elif isinstance(data, str): command = data include_processes = [] exclude_processes = [] else: raise ScriptingError("No parameters supplied to execute command.", data) if command: file_ref = "bash" args = ["-c", self._get_file(command.strip())] include_processes.append("bash") else: # Determine whether 'file' value is a file id or a path file_ref = self._get_file(file_ref) if system.path_exists(file_ref) and not system.is_executable(file_ref): logger.warning("Making %s executable", file_ref) system.make_executable(file_ref) exec_path = system.find_executable(file_ref) if not exec_path: raise ScriptingError("Unable to find executable %s" % file_ref) if terminal: terminal = system.get_default_terminal() if not working_dir or not os.path.exists(working_dir): working_dir = self.target_path command = MonitoredCommand( [exec_path] + args, env=env, term=terminal, cwd=working_dir, include_processes=include_processes, exclude_processes=exclude_processes, ) command.start() GLib.idle_add(self.parent.attach_logger, command) self.heartbeat = GLib.timeout_add(1000, self._monitor_task, command) return "STOP"
def execute(self, data): """Run an executable file.""" args = [] terminal = None working_dir = None env = {} if isinstance(data, dict): self._check_required_params([('file', 'command')], data, 'execute') if 'command' in data and 'file' in data: raise ScriptingError( 'Parameters file and command can\'t be used ' 'at the same time for the execute command', data) file_ref = data.get('file', '') command = data.get('command', '') args_string = data.get('args', '') for arg in shlex.split(args_string): args.append(self._substitute(arg)) terminal = data.get('terminal') working_dir = data.get('working_dir') if not data.get('disable_runtime', False): # Possibly need to handle prefer_system_libs here env.update(runtime.get_env()) userenv = data.get('env') or {} for key in userenv: env_value = userenv[key] userenv[key] = self._get_file(env_value) env.update(userenv) include_processes = shlex.split(data.get('include_processes', '')) exclude_processes = shlex.split(data.get('exclude_processes', '')) elif isinstance(data, str): command = data include_processes = [] exclude_processes = [] else: raise ScriptingError('No parameters supplied to execute command.', data) if command: file_ref = 'bash' args = ['-c', self._get_file(command.strip())] include_processes.append('bash') else: # Determine whether 'file' value is a file id or a path file_ref = self._get_file(file_ref) exec_path = system.find_executable(file_ref) if not exec_path: raise ScriptingError("Unable to find executable %s" % file_ref) if not os.access(exec_path, os.X_OK): logger.warning("Making %s executable", exec_path) self.chmodx(exec_path) if terminal: terminal = system.get_default_terminal() if not working_dir or not os.path.exists(working_dir): working_dir = self.target_path command = [exec_path] + args logger.debug("Executing %s", command) thread = LutrisThread(command, env=env, term=terminal, cwd=working_dir, include_processes=include_processes, exclude_processes=exclude_processes) thread.start() GLib.idle_add(self.parent.attach_logger, thread) self.heartbeat = GLib.timeout_add(1000, self._monitor_task, thread) return 'STOP'
def exec_in_thread(command): arguments = shlex.split(command) env = runtime.get_env() thread = LutrisThread(arguments, env=env) thread.start() return thread
def do_play(self, prelaunched, _error=None): if not prelaunched: self.state = self.STATE_STOPPED return system_config = self.runner.system_config self.original_outputs = display.get_outputs() gameplay_info = self.runner.play() env = {} logger.debug("Launching %s: %s" % (self.name, gameplay_info)) if 'error' in gameplay_info: show_error_message(gameplay_info) self.state = self.STATE_STOPPED return sdl_video_fullscreen = system_config.get('sdl_video_fullscreen') or '' env['SDL_VIDEO_FULLSCREEN_DISPLAY'] = sdl_video_fullscreen restrict_to_display = system_config.get('display') if restrict_to_display != 'off': display.turn_off_except(restrict_to_display) time.sleep(3) self.resolution_changed = True resolution = system_config.get('resolution') if resolution != 'off': display.change_resolution(resolution) time.sleep(3) self.resolution_changed = True if system_config.get('reset_pulse'): audio.reset_pulse() self.killswitch = system_config.get('killswitch') if self.killswitch and not os.path.exists(self.killswitch): # Prevent setting a killswitch to a file that doesn't exists self.killswitch = None # Command launch_arguments = gameplay_info['command'] primusrun = system_config.get('primusrun') if primusrun and system.find_executable('primusrun'): launch_arguments.insert(0, 'primusrun') xephyr = system_config.get('xephyr') or 'off' if xephyr != 'off': if xephyr == '8bpp': xephyr_depth = '8' else: xephyr_depth = '16' xephyr_resolution = system_config.get('xephyr_resolution') or '640x480' xephyr_command = ['Xephyr', ':2', '-ac', '-screen', xephyr_resolution + 'x' + xephyr_depth, '-glamor', '-reset', '-terminate', '-fullscreen'] xephyr_thread = LutrisThread(xephyr_command) xephyr_thread.start() time.sleep(3) env['DISPLAY'] = ':2' if system_config.get('use_us_layout'): setxkbmap_command = ['setxkbmap', '-model', 'pc101', 'us', '-print'] xkbcomp_command = ['xkbcomp', '-', os.environ.get('DISPLAY', ':0')] xkbcomp = subprocess.Popen(xkbcomp_command, stdin=subprocess.PIPE) subprocess.Popen(setxkbmap_command, env=os.environ, stdout=xkbcomp.stdin).communicate() xkbcomp.communicate() pulse_latency = system_config.get('pulse_latency') if pulse_latency: env['PULSE_LATENCY_MSEC'] = '60' prefix_command = system_config.get("prefix_command") or '' if prefix_command.strip(): launch_arguments.insert(0, prefix_command) single_cpu = system_config.get('single_cpu') or False if single_cpu: logger.info('The game will run on a single CPU core') launch_arguments.insert(0, '0') launch_arguments.insert(0, '-c') launch_arguments.insert(0, 'taskset') terminal = system_config.get('terminal') if terminal: terminal = system_config.get("terminal_app", system.get_default_terminal()) if terminal and not system.find_executable(terminal): dialogs.ErrorDialog("The selected terminal application " "could not be launched:\n" "%s" % terminal) self.state = self.STATE_STOPPED return # Env vars game_env = gameplay_info.get('env') or {} env.update(game_env) system_env = system_config.get('env') or {} env.update(system_env) ld_preload = gameplay_info.get('ld_preload') or '' env["LD_PRELOAD"] = ld_preload # Runtime management ld_library_path = "" if self.runner.use_runtime(): runtime_env = runtime.get_env() if 'STEAM_RUNTIME' in runtime_env and 'STEAM_RUNTIME' not in env: env['STEAM_RUNTIME'] = runtime_env['STEAM_RUNTIME'] if 'LD_LIBRARY_PATH' in runtime_env: ld_library_path = runtime_env['LD_LIBRARY_PATH'] game_ld_libary_path = gameplay_info.get('ld_library_path') if game_ld_libary_path: if not ld_library_path: ld_library_path = '$LD_LIBRARY_PATH' ld_library_path = ":".join(game_ld_libary_path, ld_library_path) env["LD_LIBRARY_PATH"] = ld_library_path # /Env vars self.game_thread = LutrisThread(launch_arguments, runner=self.runner, env=env, rootpid=gameplay_info.get('rootpid'), term=terminal) if hasattr(self.runner, 'stop'): self.game_thread.set_stop_command(self.runner.stop) self.game_thread.start() self.state = self.STATE_RUNNING if 'joy2key' in gameplay_info: self.joy2key(gameplay_info['joy2key']) xboxdrv_config = system_config.get('xboxdrv') if xboxdrv_config: self.xboxdrv_start(xboxdrv_config) self.heartbeat = GLib.timeout_add(HEARTBEAT_DELAY, self.beat)
def execute(self, data): """Run an executable file.""" args = [] terminal = None working_dir = None env = {} if isinstance(data, dict): if 'command' not in data and 'file' not in data: raise ScriptingError('Parameter file or command is mandatory ' 'for the execute command', data) elif 'command' in data and 'file' in data: raise ScriptingError('Parameters file and command can\'t be ' 'used at the same time for the execute ' 'command', data) file_ref = data.get('file', '') command = data.get('command', '') args_string = data.get('args', '') for arg in shlex.split(args_string): args.append(self._substitute(arg)) terminal = data.get('terminal') working_dir = data.get('working_dir') if not data.get('disable_runtime', False): env.update(runtime.get_env()) userenv = data.get('env', {}) for key in userenv: v = userenv[key] userenv[key] = self._get_file(v) or self._substitute(v) env.update(userenv) include_processes = shlex.split(data.get('include_processes', '')) exclude_processes = shlex.split(data.get('exclude_processes', '')) elif isinstance(data, str): command = data include_processes = [] exclude_processes = [] else: raise ScriptingError('No parameters supplied to execute command.', data) if command: command = command.strip() command = self._get_file(command) or self._substitute(command) file_ref = 'bash' args = ['-c', command] include_processes.append('bash') else: # Determine whether 'file' value is a file id or a path file_ref = self._get_file(file_ref) or self._substitute(file_ref) exec_path = system.find_executable(file_ref) if not exec_path: raise ScriptingError("Unable to find executable %s" % file_ref) if not os.access(exec_path, os.X_OK): self.chmodx(exec_path) if terminal: terminal = system.get_default_terminal() if not working_dir or not os.path.exists(working_dir): working_dir = self.target_path command = [exec_path] + args logger.debug("Executing %s" % command) thread = LutrisThread(command, env=env, term=terminal, cwd=working_dir, include_processes=include_processes, exclude_processes=exclude_processes) thread.start() GLib.idle_add(self.parent.attach_logger, thread) self.heartbeat = GLib.timeout_add(1000, self._monitor_task, thread) return 'STOP'
def execute(self, data): """Run an executable file.""" args = [] terminal = None working_dir = None env = {} if isinstance(data, dict): self._check_required_params([("file", "command")], data, "execute") if "command" in data and "file" in data: raise ScriptingError( "Parameters file and command can't be used " "at the same time for the execute command", data, ) file_ref = data.get("file", "") command = data.get("command", "") args_string = data.get("args", "") for arg in shlex.split(args_string): args.append(self._substitute(arg)) terminal = data.get("terminal") working_dir = data.get("working_dir") if not data.get("disable_runtime", False): # Possibly need to handle prefer_system_libs here env.update(runtime.get_env()) # Loading environment variables set in the script env.update(self.script_env) # Environment variables can also be passed to the execute command local_env = data.get("env") or {} env.update({ key: self._substitute(value) for key, value in local_env.items() }) include_processes = shlex.split(data.get("include_processes", "")) exclude_processes = shlex.split(data.get("exclude_processes", "")) elif isinstance(data, str): command = data include_processes = [] exclude_processes = [] else: raise ScriptingError("No parameters supplied to execute command.", data) if command: file_ref = "bash" args = ["-c", self._get_file(command.strip())] include_processes.append("bash") else: # Determine whether 'file' value is a file id or a path file_ref = self._get_file(file_ref) exec_path = system.find_executable(file_ref) if not exec_path: raise ScriptingError("Unable to find executable %s" % file_ref) if not os.access(exec_path, os.X_OK): logger.warning("Making %s executable", exec_path) self.chmodx(exec_path) if terminal: terminal = system.get_default_terminal() if not working_dir or not os.path.exists(working_dir): working_dir = self.target_path command = MonitoredCommand( [exec_path] + args, env=env, term=terminal, cwd=working_dir, include_processes=include_processes, exclude_processes=exclude_processes, ) command.start() GLib.idle_add(self.parent.attach_logger, command) self.heartbeat = GLib.timeout_add(1000, self._monitor_task, command) return "STOP"