diff --git a/docs/user/cues/misc_cues.md b/docs/user/cues/misc_cues.md index 50769fabf..7341234fe 100644 --- a/docs/user/cues/misc_cues.md +++ b/docs/user/cues/misc_cues.md @@ -26,6 +26,9 @@ Be sure to understand what you're doing, and avoid dangerous and untrested comma * **Discard command output:** when enabled the command output is discarded * **Ignore command errors:** when enabled errors are not reported * **Kill instead of terminate:** when enabled, on stop, the command is killed (abruptly interrupted by the OS) +* **Run the command on the host system (_Available only for flatpak installations._):** + When disabled the command will be run inside the sandbox, this will prevent access to any application + installed on your "host" system ### Examples diff --git a/lisp/__init__.py b/lisp/__init__.py index fd8697675..a0fa74a2b 100644 --- a/lisp/__init__.py +++ b/lisp/__init__.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with Linux Show Player. If not, see . +import os from os import path from appdirs import AppDirs @@ -46,3 +47,5 @@ ICON_THEMES_DIR = path.join(APP_DIR, "ui", "icons") ICON_THEME_COMMON = "lisp" + +RUNNING_IN_FLATPAK = "FLATPAK_ID" in os.environ diff --git a/lisp/plugins/action_cues/command_cue.py b/lisp/plugins/action_cues/command_cue.py index 6cdb95523..ee6c5eda9 100644 --- a/lisp/plugins/action_cues/command_cue.py +++ b/lisp/plugins/action_cues/command_cue.py @@ -21,6 +21,7 @@ from PyQt5.QtCore import Qt, QT_TRANSLATE_NOOP from PyQt5.QtWidgets import QVBoxLayout, QGroupBox, QLineEdit, QCheckBox +from lisp import RUNNING_IN_FLATPAK from lisp.core.decorators import async_function from lisp.core.properties import Property from lisp.cues.cue import Cue, CueAction @@ -45,6 +46,7 @@ class CommandCue(Cue): no_output = Property(default=True) no_error = Property(default=True) kill = Property(default=False) + run_on_host = Property(default=True) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -59,14 +61,15 @@ def __start__(self, fade=False): @async_function def __exec_command(self): - if not self.command.strip(): + command = self.__command() + if not command: return # If no_output is True, discard all the outputs std = subprocess.DEVNULL if self.no_output else None # Execute the command self.__process = subprocess.Popen( - self.command, shell=True, stdout=std, stderr=std + command, shell=True, stdout=std, stderr=std ) rcode = self.__process.wait() @@ -87,6 +90,17 @@ def __exec_command(self): self.__process = None self.__stopped = False + def __command(self): + if ( + self.command + and RUNNING_IN_FLATPAK + and self.run_on_host + and not self.command.startswith("flatpak-spawn") + ): + return f"flatpak-spawn --host {self.command}" + + return self.command + def __stop__(self, fade=False): if self.__process is not None: self.__stopped = True @@ -124,6 +138,10 @@ def __init__(self, *args, **kwargs): self.killCheckBox = QCheckBox(self) self.layout().addWidget(self.killCheckBox) + self.runOnHost = QCheckBox(self) + self.runOnHost.setVisible(RUNNING_IN_FLATPAK) + self.layout().addWidget(self.runOnHost) + self.retranslateUi() def retranslateUi(self): @@ -140,27 +158,30 @@ def retranslateUi(self): self.killCheckBox.setText( translate("CommandCue", "Kill instead of terminate") ) + self.runOnHost.setText( + translate("CommandCue", "Run the command on the host system") + ) def enableCheck(self, enabled): self.setGroupEnabled(self.group, enabled) self.noOutputCheckBox.setTristate(enabled) - if enabled: - self.noOutputCheckBox.setCheckState(Qt.PartiallyChecked) - self.noErrorCheckBox.setTristate(enabled) - if enabled: - self.killCheckBox.setCheckState(Qt.PartiallyChecked) - self.killCheckBox.setTristate(enabled) + self.runOnHost.setTristate(enabled) + if enabled: + self.noOutputCheckBox.setCheckState(Qt.PartiallyChecked) + self.killCheckBox.setCheckState(Qt.PartiallyChecked) self.killCheckBox.setCheckState(Qt.PartiallyChecked) + self.runOnHost.setChecked(Qt.PartiallyChecked) def loadSettings(self, settings): self.commandLineEdit.setText(settings.get("command", "")) self.noOutputCheckBox.setChecked(settings.get("no_output", True)) self.noErrorCheckBox.setChecked(settings.get("no_error", True)) self.killCheckBox.setChecked(settings.get("kill", False)) + self.runOnHost.setChecked(settings.get("run_on_host", True)) def getSettings(self): settings = {} @@ -176,6 +197,8 @@ def getSettings(self): settings["no_error"] = self.noErrorCheckBox.isChecked() if self.killCheckBox.checkState() != Qt.PartiallyChecked: settings["kill"] = self.killCheckBox.isChecked() + if self.runOnHost.checkState() != Qt.PartiallyChecked: + settings["run_on_host"] = self.runOnHost.isChecked() return settings diff --git a/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json b/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json index 980e636a2..e6ef610e4 100644 --- a/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json +++ b/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json @@ -15,7 +15,8 @@ "--socket=pulseaudio", "--filesystem=xdg-run/pipewire-0", "--filesystem=home", - "--device=all" + "--device=all", + "--talk-name=org.freedesktop.Flatpak" ], "cleanup-commands": [ "/app/cleanup-BaseApp.sh"