From b706b8e55eb39bde6370e51feb6e22505a410efa Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Tue, 26 Dec 2023 15:32:31 +0100 Subject: [PATCH 01/13] [ci] Upstream updates to the flatpak manifest (from flathub) --- scripts/flatpak/README.md | 5 +- .../org.linuxshowplayer.LinuxShowPlayer.json | 66 +++------ scripts/flatpak/pyqt-build.sh | 50 ------- scripts/flatpak/pyqt-modules.json | 73 ---------- scripts/flatpak/python-modules.json | 136 +++++++++--------- 5 files changed, 88 insertions(+), 242 deletions(-) delete mode 100644 scripts/flatpak/pyqt-build.sh delete mode 100644 scripts/flatpak/pyqt-modules.json diff --git a/scripts/flatpak/README.md b/scripts/flatpak/README.md index 569d666a4..40c38ccc1 100644 --- a/scripts/flatpak/README.md +++ b/scripts/flatpak/README.md @@ -1,15 +1,12 @@ ### INTRO -(╯°□°)╯︵ ┻━┻ - The scripts in this folder allow to build a Flatpak package of Linux Show Player. * **build_flatpak.sh:** Combine the commands from "functions.sh" to run a complete build * **config.sh:** Some environment configuration * **functions.sh:** A collection of commands to build the flatpak * **patch-flatpak.py:** Patch the flatpak manifest to use the current CI branch/commit - * **poetry-flatpak.py:** Starting from the project poetry.lock generate the appropriate modules to install the python requirements - * **pyqt-build.sh:** Used to invoke "sip-install" to build pyqt + * **poetry-flatpak.py:** Generate the appropriate modules to install the python requirements ### REQUIREMENTS diff --git a/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json b/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json index 1017787d5..a2fa36c09 100644 --- a/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json +++ b/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json @@ -3,6 +3,8 @@ "runtime": "org.kde.Platform", "runtime-version": "5.15-23.08", "sdk": "org.kde.Sdk", + "base": "com.riverbankcomputing.PyQt.BaseApp", + "base-version": "5.15-23.08", "command": "linux-show-player", "rename-icon": "linuxshowplayer", "finish-args": [ @@ -11,38 +13,26 @@ "--socket=wayland", "--socket=fallback-x11", "--socket=pulseaudio", - "--system-talk-name=org.freedesktop.RealtimeKit1", "--filesystem=xdg-run/pipewire-0", "--filesystem=home", "--device=all" ], + "cleanup-commands": [ + "/app/cleanup-BaseApp.sh" + ], "cleanup": [ "*.la", "*.a", "/include", - "/lib/pkgconfig" + "/lib/pkgconfig", + "/share/man" ], + "build-options": { + "env": [ + "BASEAPP_REMOVE_WEBENGINE=1" + ] + }, "modules": [ - { - "name": "Jack", - "buildsystem": "simple", - "build-commands": [ - "./waf configure --prefix=$FLATPAK_DEST", - "./waf build -j $FLATPAK_BUILDER_N_JOBS", - "./waf install" - ], - "sources": [ - { - "type": "git", - "url": "https://github.com/jackaudio/jack2.git", - "tag": "v1.9.22", - "commit": "4f58969432339a250ce87fe855fb962c67d00ddb" - } - ], - "cleanup": [ - "*" - ] - }, { "name": "RtMidi", "config-opts": [ @@ -69,20 +59,7 @@ } ] }, - { - "name": "liblo", - "config-opts": [ - "--disable-examples", - "--disable-tools" - ], - "sources": [ - { - "type": "git", - "url": "https://github.com/radarsat1/liblo.git", - "commit": "02989c6c69f54157b8d9651fb8d9ad6de8128d59" - } - ] - }, + "shared-modules/linux-audio/liblo.json", { "name": "pyliblo3", "buildsystem": "simple", @@ -165,7 +142,7 @@ "sources": [ { "type": "archive", - "url": "ftp://ftp.alsa-project.org/pub/pyalsa/pyalsa-1.2.7.tar.bz2", + "url": "https://www.alsa-project.org/files/pub/pyalsa/pyalsa-1.2.7.tar.bz2", "sha256": "67d8f99f1ccf23e7ebdfa2c3be0b09f147949fd9511d1e6748b7f412ef046e1f" } ] @@ -201,7 +178,6 @@ } ] }, - "pyqt-modules.json", "pygobject-modules.json", "python-modules.json", { @@ -209,14 +185,10 @@ "buildsystem": "simple", "build-commands": [ "pip3 install --no-deps --no-build-isolation --prefix=\"${FLATPAK_DEST}\" .", - "mkdir -p /app/share/applications/", - "mkdir -p /app/share/mime/packages/", - "mkdir -p /app/share/metainfo/", - "mkdir -p /app/share/icons/hicolor/512x512/apps/", - "cp dist/linuxshowplayer.desktop /app/share/applications/org.linuxshowplayer.LinuxShowPlayer.desktop", - "cp dist/linuxshowplayer.xml /app/share/mime/packages/org.linuxshowplayer.LinuxShowPlayer.xml", - "cp dist/linuxshowplayer.metainfo.xml /app/share/metainfo/org.linuxshowplayer.LinuxShowPlayer.metainfo.xml", - "cp dist/linuxshowplayer.png /app/share/icons/hicolor/512x512/apps/linuxshowplayer.png" + "install -Dm644 dist/linuxshowplayer.desktop ${FLATPAK_DEST}/share/applications/${FLATPAK_ID}.desktop", + "install -Dm644 dist/linuxshowplayer.xml /app/share/mime/packages/${FLATPAK_ID}.xml", + "install -Dm644 dist/linuxshowplayer.metainfo.xml /app/share/metainfo/${FLATPAK_ID}.metainfo.xml", + "install -Dm644 dist/linuxshowplayer.png /app/share/icons/hicolor/512x512/apps/linuxshowplayer.png" ], "sources": [ { @@ -227,4 +199,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/scripts/flatpak/pyqt-build.sh b/scripts/flatpak/pyqt-build.sh deleted file mode 100644 index 65990bcfa..000000000 --- a/scripts/flatpak/pyqt-build.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env sh - -PYTHON_VERSION=$(python3 -c 'import sys; print("{}.{}".format(*sys.version_info))') - -sip-install \ - --qt-shared \ - --concatenate 1 \ - --confirm-license \ - --debug \ - --verbose \ - --disable QtBluetooth \ - --disable QtDBus \ - --disable QtDesigner \ - --disable QtHelp \ - --disable QtLocation \ - --disable QtMultimedia \ - --disable QtMultimediaWidgets \ - --disable QtNetwork \ - --disable QtNfc \ - --disable QtOpenGL \ - --disable QtPositioning \ - --disable QtPrintSupport \ - --disable QtQml \ - --disable QtQuick \ - --disable QtQuickWidgets \ - --disable QtRemoteObjects \ - --disable QtSensors \ - --disable QtSerialPort \ - --disable QtSql \ - --disable QtSvg \ - --disable QtTest \ - --disable QtTextToSpeech \ - --disable QtWebChannel \ - --disable QtWebSockets \ - --disable QtXml \ - --disable QtXmlPatterns \ - --disable _QOpenGLFunctions_2_0 \ - --disable _QOpenGLFunctions_2_1 \ - --disable _QOpenGLFunctions_4_1_Core \ - --no-dbus-python \ - --no-designer-plugin \ - --no-docstrings \ - --no-qml-plugin \ - --no-tools \ - --jobs="${FLATPAK_BUILDER_N_JOBS}" \ - --build-dir="${FLATPAK_BUILDER_BUILDDIR}/tmp" \ - --target-dir="${FLATPAK_DEST}/lib/python${PYTHON_VERSION}/site-packages" \ - --qmake-setting QMAKE_CFLAGS="$CFLAGS" \ - --qmake-setting QMAKE_CXXFLAGS="$CXXFLAGS" \ - --qmake-setting QMAKE_LFLAGS="$LDFLAGS" \ No newline at end of file diff --git a/scripts/flatpak/pyqt-modules.json b/scripts/flatpak/pyqt-modules.json deleted file mode 100644 index 7a35cf906..000000000 --- a/scripts/flatpak/pyqt-modules.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "name": "pyqt-modules", - "modules": [ - { - "name": "pyqt5-build-dependencies", - "buildsystem": "simple", - "build-commands": [ - "pip3 install --no-index --no-build-isolation --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} tomli ply sip pyqt-builder" - ], - "cleanup": [ - "*" - ], - "sources": [ - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", - "sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl", - "sha256": "096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/a6/4e/c34eee70109e9a8110672f074fc18b5022bf4b9b4c92641245c73ae0b21a/sip-6.7.12.tar.gz", - "sha256": "08e66f742592eb818ac8fda4173e2ed64c9f2d40b70bee11db1c499127d98450" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/21/e9/5ee4d76d3f4c566b090924e36da067748db948a5faeff4142d149a4d5a15/PyQt-builder-1.15.3.tar.gz", - "sha256": "5b33e99edcb77d4a63a38605f4457a04cff4e254c771ed529ebc9589906ccdb1" - } - ] - }, - { - "name": "pyqt5-sip", - "buildsystem": "simple", - "build-commands": [ - "pip3 install --no-index --no-build-isolation --prefix=\"${FLATPAK_DEST}\" ." - ], - "sources": [ - { - "type": "archive", - "url": "https://files.pythonhosted.org/packages/ee/81/fce2a475aa56c1f49707d9306b930695b6ff078c2242c9f2fd72a3214e1f/PyQt5_sip-12.13.0.tar.gz", - "sha256": "7f321daf84b9c9dbca61b80e1ef37bdaffc0e93312edae2cd7da25b953971d91" - } - ] - }, - { - "name": "pyqt5", - "buildsystem": "simple", - "build-commands": [ - ". ${FLATPAK_BUILDER_BUILDDIR}/build" - ], - "sources": [ - { - "type": "archive", - "url": "https://files.pythonhosted.org/packages/4d/5d/b8b6e26956ec113ad3f566e02abd12ac3a56b103fcc7e0735e27ee4a1df3/PyQt5-5.15.10.tar.gz", - "sha256": "d46b7804b1b10a4ff91753f8113e5b5580d2b4462f3226288e2d84497334898a" - }, - { - "type": "file", - "path": "pyqt-build.sh", - "dest-filename": "build" - } - ], - "cleanup": [ - "/bin" - ] - } - ] -} \ No newline at end of file diff --git a/scripts/flatpak/python-modules.json b/scripts/flatpak/python-modules.json index 15eed34da..75c17ddb8 100644 --- a/scripts/flatpak/python-modules.json +++ b/scripts/flatpak/python-modules.json @@ -10,6 +10,16 @@ "url": "https://files.pythonhosted.org/packages/26/87/f238c0670b94533ac0353a4e2a1a771a0cc73277b88bff23d3ae35a256c1/docutils-0.20.1-py3-none-any.whl", "sha256": "96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6" }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/57/f4/a69c20ee4f660081a7dedb1ac57f29be9378e04edfcb90c526b923d4bebc/beautifulsoup4-4.12.2-py3-none-any.whl", + "sha256": "bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/64/62/428ef076be88fa93716b576e4a01f919d25968913e817077a386fcbe4f42/certifi-2023.11.17-py3-none-any.whl", + "sha256": "e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474" + }, { "type": "file", "url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", @@ -20,11 +30,6 @@ "url": "https://files.pythonhosted.org/packages/3b/00/2344469e2084fb287c2e0b57b72910309874c3245463acd6cf5e3db69324/appdirs-1.4.4-py2.py3-none-any.whl", "sha256": "a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/64/88/c7083fc61120ab661c5d0b82cb77079fc1429d3f913a456c1c82cf4658f7/alabaster-0.7.13-py3-none-any.whl", - "sha256": "1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3" - }, { "type": "file", "url": "https://files.pythonhosted.org/packages/86/14/5dc2eb02b7cc87b2f95930310a2cc5229198414919a116b564832c747bc1/Babel-2.13.1-py3-none-any.whl", @@ -32,28 +37,28 @@ }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/57/f4/a69c20ee4f660081a7dedb1ac57f29be9378e04edfcb90c526b923d4bebc/beautifulsoup4-4.12.2-py3-none-any.whl", - "sha256": "bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a" + "url": "https://files.pythonhosted.org/packages/64/88/c7083fc61120ab661c5d0b82cb77079fc1429d3f913a456c1c82cf4658f7/alabaster-0.7.13-py3-none-any.whl", + "sha256": "1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/64/62/428ef076be88fa93716b576e4a01f919d25968913e817077a386fcbe4f42/certifi-2023.11.17-py3-none-any.whl", - "sha256": "e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474" + "url": "https://files.pythonhosted.org/packages/28/76/e6222113b83e3622caa4bb41032d0b1bf785250607392e1b778aca0b8a7d/charset_normalizer-3.3.2-py3-none-any.whl", + "sha256": "3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/17/b7/fd357a7961875637930d138aa2667e6fd08bd888a5c173d4b7b2667f7cb9/furo-2023.9.10-py3-none-any.whl", - "sha256": "513092538537dc5c596691da06e3c370714ec99bc438680edc1debffb73e5bfc" + "url": "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", + "sha256": "0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", - "sha256": "0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b" + "url": "https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl", + "sha256": "90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/aa/2b/2ae0c789fd08d5b44e745726d08a17e6d3d7d09071d05473105edc7615f2/humanize-4.9.0-py3-none-any.whl", - "sha256": "ce284a76d5b1377fd8836733b983bfb0b76f1aa1c090de2566fcf008d7f6ab16" + "url": "https://files.pythonhosted.org/packages/cc/37/db7ba97e676af155f5fcb1a35466f446eadc9104e25b83366e8088c9c926/importlib_metadata-6.8.0-py3-none-any.whl", + "sha256": "3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb" }, { "type": "file", @@ -62,33 +67,33 @@ }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/28/76/e6222113b83e3622caa4bb41032d0b1bf785250607392e1b778aca0b8a7d/charset_normalizer-3.3.2-py3-none-any.whl", - "sha256": "3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc" + "url": "https://files.pythonhosted.org/packages/aa/2b/2ae0c789fd08d5b44e745726d08a17e6d3d7d09071d05473105edc7615f2/humanize-4.9.0-py3-none-any.whl", + "sha256": "ce284a76d5b1377fd8836733b983bfb0b76f1aa1c090de2566fcf008d7f6ab16" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl", - "sha256": "90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" + "url": "https://files.pythonhosted.org/packages/17/b7/fd357a7961875637930d138aa2667e6fd08bd888a5c173d4b7b2667f7cb9/furo-2023.9.10-py3-none-any.whl", + "sha256": "513092538537dc5c596691da06e3c370714ec99bc438680edc1debffb73e5bfc" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/cc/37/db7ba97e676af155f5fcb1a35466f446eadc9104e25b83366e8088c9c926/importlib_metadata-6.8.0-py3-none-any.whl", - "sha256": "3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb" + "url": "https://files.pythonhosted.org/packages/68/ce/95b0bae7968c65473e1298efb042e10cafc7bafc14d9e4f154008241c91d/cffi-1.16.0.tar.gz", + "sha256": "bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/e3/05/ed67ccf462fff0b559e6ea7b3e3fcb20dec9d57bf90b5c5e72a6f316183e/livereload-2.6.3-py2.py3-none-any.whl", - "sha256": "ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4" + "url": "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", + "sha256": "84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/bc/c3/f068337a370801f372f2f8f6bad74a5c140f6fda3d9de154052708dd3c65/Jinja2-3.1.2-py3-none-any.whl", - "sha256": "6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" + "url": "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", + "sha256": "355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/e5/3c/fe85f19699a7b40c8f9ce8ecee7e269b9b3c94099306df6f9891bdefeedd/mdit_py_plugins-0.4.0-py3-none-any.whl", - "sha256": "b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9" + "url": "https://files.pythonhosted.org/packages/bc/c3/f068337a370801f372f2f8f6bad74a5c140f6fda3d9de154052708dd3c65/Jinja2-3.1.2-py3-none-any.whl", + "sha256": "6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" }, { "type": "file", @@ -97,24 +102,29 @@ }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", - "sha256": "355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1" + "url": "https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl", + "sha256": "8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", - "sha256": "84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8" + "url": "https://files.pythonhosted.org/packages/e3/05/ed67ccf462fff0b559e6ea7b3e3fcb20dec9d57bf90b5c5e72a6f316183e/livereload-2.6.3-py2.py3-none-any.whl", + "sha256": "ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/68/ce/95b0bae7968c65473e1298efb042e10cafc7bafc14d9e4f154008241c91d/cffi-1.16.0.tar.gz", - "sha256": "bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0" + "url": "https://files.pythonhosted.org/packages/e5/3c/fe85f19699a7b40c8f9ce8ecee7e269b9b3c94099306df6f9891bdefeedd/mdit_py_plugins-0.4.0-py3-none-any.whl", + "sha256": "b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9" }, { "type": "file", "url": "https://files.pythonhosted.org/packages/b0/0e/b551e09391220208764c00ed2b382e198414329d8b6037eeb54a8008d737/mido-1.3.0-py3-none-any.whl", "sha256": "a710a274c8a1a3fd481f526d174a16e117b5e58d719ad92937a67fb6167a9432" }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl", + "sha256": "58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f" + }, { "type": "file", "url": "https://files.pythonhosted.org/packages/1d/f6/6d61a023d758f488e36638076e8a4ec4447a2cdf86938cf6c60cf1c860e6/myst_parser-2.0.0-py3-none-any.whl", @@ -122,29 +132,19 @@ }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl", - "sha256": "8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9" + "url": "https://files.pythonhosted.org/packages/4c/f3/038b302fdfbe3be7da016777069f26ceefe11a681055ea1f7817546508e3/soupsieve-2.5-py3-none-any.whl", + "sha256": "eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7" }, { "type": "file", "url": "https://files.pythonhosted.org/packages/ed/dc/c02e01294f7265e63a7315fe086dd1df7dacb9f840a804da846b96d01b96/snowballstemmer-2.2.0-py2.py3-none-any.whl", "sha256": "c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a" }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/6d/7c/59a3248f411813f8ccba92a55feaac4bf360d29e2ff05ee7d8e1ef2d7dbf/MarkupSafe-2.1.3.tar.gz", - "sha256": "af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad" - }, { "type": "file", "url": "https://files.pythonhosted.org/packages/cd/e5/af35f7ea75cf72f2cd079c95ee16797de7cd71f29ea7c68ae5ce7be1eda0/PyYAML-6.0.1.tar.gz", "sha256": "bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43" }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/7e/7d/8fb7557b6c9298d2bcda57f4d070de443c6355dfb475582378e2aa16a02c/sphinx_autobuild-2021.3.14-py3-none-any.whl", - "sha256": "8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac" - }, { "type": "file", "url": "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", @@ -157,18 +157,18 @@ }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl", - "sha256": "58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f" + "url": "https://files.pythonhosted.org/packages/3c/dd/018ce05c532a22007ac58d4f45232514cd9d6dd0ee1dc374e309db830983/sphinx_basic_ng-1.0.0b2-py3-none-any.whl", + "sha256": "eb09aedbabfb650607e9b4b68c9d240b90b1e1be221d6ad71d61c52e29f7932b" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/4c/f3/038b302fdfbe3be7da016777069f26ceefe11a681055ea1f7817546508e3/soupsieve-2.5-py3-none-any.whl", - "sha256": "eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7" + "url": "https://files.pythonhosted.org/packages/7e/7d/8fb7557b6c9298d2bcda57f4d070de443c6355dfb475582378e2aa16a02c/sphinx_autobuild-2021.3.14-py3-none-any.whl", + "sha256": "8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/3c/dd/018ce05c532a22007ac58d4f45232514cd9d6dd0ee1dc374e309db830983/sphinx_basic_ng-1.0.0b2-py3-none-any.whl", - "sha256": "eb09aedbabfb650607e9b4b68c9d240b90b1e1be221d6ad71d61c52e29f7932b" + "url": "https://files.pythonhosted.org/packages/48/17/325cf6a257d84751a48ae90752b3d8fe0be8f9535b6253add61c49d0d9bc/sphinx-7.1.2-py3-none-any.whl", + "sha256": "d170a81825b2fcacb6dfd5a0d7f578a053e45d3f2b153fecc948c37344eb4cbe" }, { "type": "file", @@ -180,11 +180,6 @@ "url": "https://files.pythonhosted.org/packages/06/c1/5e2cafbd03105ce50d8500f9b4e8a6e8d02e22d0475b574c3b3e9451a15f/sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", "sha256": "29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228" }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", - "sha256": "2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178" - }, { "type": "file", "url": "https://files.pythonhosted.org/packages/c5/09/5de5ed43a521387f18bdf5f5af31d099605c992fd25372b2b9b825ce48ee/sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", @@ -197,18 +192,18 @@ }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/48/17/325cf6a257d84751a48ae90752b3d8fe0be8f9535b6253add61c49d0d9bc/sphinx-7.1.2-py3-none-any.whl", - "sha256": "d170a81825b2fcacb6dfd5a0d7f578a053e45d3f2b153fecc948c37344eb4cbe" + "url": "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", + "sha256": "2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", - "sha256": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + "url": "https://files.pythonhosted.org/packages/96/94/c31f58c7a7f470d5665935262ebd7455c7e4c7782eb525658d3dbf4b9403/urllib3-2.1.0-py3-none-any.whl", + "sha256": "55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/c6/77/5464ec50dd0f1c1037e3c93249b040c8fc8078fdda97530eeb02424b6eea/sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", - "sha256": "352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd" + "url": "https://files.pythonhosted.org/packages/d9/66/48866fc6b158c81cc2bfecc04c480f105c6040e8b077bc54c634b4a67926/zipp-3.17.0-py3-none-any.whl", + "sha256": "0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31" }, { "type": "file", @@ -217,18 +212,23 @@ }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/48/64/679260ca0c3742e2236c693dc6c34fb8b153c14c21d2aa2077c5a01924d6/tornado-6.3.3.tar.gz", - "sha256": "e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe" + "url": "https://files.pythonhosted.org/packages/c6/77/5464ec50dd0f1c1037e3c93249b040c8fc8078fdda97530eeb02424b6eea/sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", + "sha256": "352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/d9/66/48866fc6b158c81cc2bfecc04c480f105c6040e8b077bc54c634b4a67926/zipp-3.17.0-py3-none-any.whl", - "sha256": "0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31" + "url": "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", + "sha256": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" }, { "type": "file", - "url": "https://files.pythonhosted.org/packages/96/94/c31f58c7a7f470d5665935262ebd7455c7e4c7782eb525658d3dbf4b9403/urllib3-2.1.0-py3-none-any.whl", - "sha256": "55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3" + "url": "https://files.pythonhosted.org/packages/48/64/679260ca0c3742e2236c693dc6c34fb8b153c14c21d2aa2077c5a01924d6/tornado-6.3.3.tar.gz", + "sha256": "e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/6d/7c/59a3248f411813f8ccba92a55feaac4bf360d29e2ff05ee7d8e1ef2d7dbf/MarkupSafe-2.1.3.tar.gz", + "sha256": "af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad" } ] } \ No newline at end of file From d5433ef4b9ab2f3f350e8edc93c39f322bf363d5 Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Tue, 26 Dec 2023 15:41:25 +0100 Subject: [PATCH 02/13] [docs] Update installation instructions, fix typos --- docs/user/index.md | 4 ++-- docs/user/installation.md | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/user/index.md b/docs/user/index.md index 75c4fa4ff..1bbffefd1 100644 --- a/docs/user/index.md +++ b/docs/user/index.md @@ -40,7 +40,7 @@ Here some functionality offered by LiSP: Currently, only GNU/Linux systems are supported. -The application is quite stable, is already been used for multiple performances +The application is quite stable, it's already been used for multiple performances by different people, but, due to the heterogeneous nature of the GNU/Linux ecosystem, my suggestion is to test it in a "production" environment to detect possible problems -with some configuration. +with some configurations. diff --git a/docs/user/installation.md b/docs/user/installation.md index 72050c38a..18b292f81 100644 --- a/docs/user/installation.md +++ b/docs/user/installation.md @@ -19,10 +19,12 @@ follow their _simple_ instructions, Date: Tue, 26 Dec 2023 16:16:16 +0100 Subject: [PATCH 03/13] [ci] fix: add submodule --- .gitmodules | 3 +++ scripts/flatpak/shared-submodules | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 scripts/flatpak/shared-submodules diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..a60ac1665 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "scripts/flatpak/shared-submodules"] + path = scripts/flatpak/shared-submodules + url = https://github.com/flathub/shared-modules.git diff --git a/scripts/flatpak/shared-submodules b/scripts/flatpak/shared-submodules new file mode 160000 index 000000000..55a8e460c --- /dev/null +++ b/scripts/flatpak/shared-submodules @@ -0,0 +1 @@ +Subproject commit 55a8e460c6343229597a13e973ba4855c27a1c4c From 40bd03579343fe68f4669664291c3469f72c9c19 Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Tue, 26 Dec 2023 16:18:42 +0100 Subject: [PATCH 04/13] [ci] fix: use correct path --- .gitmodules | 2 +- scripts/flatpak/{shared-submodules => shared-modules} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename scripts/flatpak/{shared-submodules => shared-modules} (100%) diff --git a/.gitmodules b/.gitmodules index a60ac1665..19ad74a3b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "scripts/flatpak/shared-submodules"] - path = scripts/flatpak/shared-submodules + path = scripts/flatpak/shared-modules url = https://github.com/flathub/shared-modules.git diff --git a/scripts/flatpak/shared-submodules b/scripts/flatpak/shared-modules similarity index 100% rename from scripts/flatpak/shared-submodules rename to scripts/flatpak/shared-modules From 3004a24f7296da78af4fd06c2192d5f937ba6581 Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Tue, 26 Dec 2023 16:30:56 +0100 Subject: [PATCH 05/13] [ci] fix: checkout submodules in circleci --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index d227eeb18..507b01264 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,6 +12,8 @@ jobs: steps: - checkout + - run: git submodule sync + - run: git submodule update --init - run: name: SYSTEM ⟹ Install required packages From 922a576a5a0268d08551c7ee3ccefc77b7ad8021 Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Tue, 26 Dec 2023 16:45:31 +0100 Subject: [PATCH 06/13] [ci] fix: install runtime/base via flatpak-builder --- scripts/flatpak/functions.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/scripts/flatpak/functions.sh b/scripts/flatpak/functions.sh index 3e654e37f..8eae52c0c 100755 --- a/scripts/flatpak/functions.sh +++ b/scripts/flatpak/functions.sh @@ -18,13 +18,12 @@ function flatpak_build_manifest() { function flatpak_install_runtime() { echo "" - echo "###################################################" - echo "# Install flatpak (flathub) runtime and sdk #" - echo "###################################################" + echo "######################################" + echo "# Add flatpak remote (flathub) #" + echo "######################################" echo "" flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo - flatpak install --user --noninteractive --assumeyes flathub $FLATPAK_INSTALL } function flatpak_build() { @@ -37,7 +36,7 @@ function flatpak_build() { # Prepare the repository ostree init --mode=archive-z2 --repo=repo # Build the flatpak - flatpak-builder --verbose --force-clean --ccache --repo=repo build $FLATPAK_APP_ID.json + flatpak-builder --verbose --force-clean --ccache --repo=repo --user --install-deps-from=flathub build $FLATPAK_APP_ID.json } From 85aa9b1d917d99a03bf6add0f098b50f58b0b7c2 Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Sat, 20 Jan 2024 15:40:34 +0100 Subject: [PATCH 07/13] [flatpack] bundle soundtouch and corresponding gstreamer plugin (fix #303) --- scripts/flatpak/gstreamer-modules.json | 51 +++++++++++++++++++ .../org.linuxshowplayer.LinuxShowPlayer.json | 1 + 2 files changed, 52 insertions(+) create mode 100644 scripts/flatpak/gstreamer-modules.json diff --git a/scripts/flatpak/gstreamer-modules.json b/scripts/flatpak/gstreamer-modules.json new file mode 100644 index 000000000..cb0243fe3 --- /dev/null +++ b/scripts/flatpak/gstreamer-modules.json @@ -0,0 +1,51 @@ +{ + "name": "gst-modules", + "modules": [ + { + "name": "soundtouch", + "buildsystem": "cmake-ninja", + "config-opts": [ + "-DBUILD_SHARED_LIBS=ON" + ], + "sources": [ + { + "type": "git", + "url": "https://codeberg.org/soundtouch/soundtouch.git", + "tag": "2.3.1", + "commit": "e1f315f5358d9db5cee35a7a2886425489fcefe8" + } + ], + "cleanup": [ + "/bin", + "/lib/cmake", + "/share/doc" + ] + }, + { + "name": "gstreamer-plugins-bad", + "buildsystem": "meson", + "builddir": true, + "config-opts": [ + "-Dauto_features=disabled", + "-Dgood=disabled", + "-Dugly=disabled", + "-Dbad=enabled", + "-Dgst-plugins-bad:soundtouch=enabled", + "-Dgst-full-plugins=soundtouch" + ], + "no-make-install": true, + "build-commands": [ + "install -Dm644 subprojects/gst-plugins-bad/ext/soundtouch/libgstsoundtouch.so /app/lib/gstreamer-1.0/libgstsoundtouch.so" + ], + "sources": [ + { + "type": "git", + "url": "https://gitlab.freedesktop.org/gstreamer/gstreamer.git", + "tag": "1.22.8", + "commit": "4af14db10e8355f980bbf79733af004e59d255fc", + "disable-submodules": true + } + ] + } + ] +} \ No newline at end of file diff --git a/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json b/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json index a2fa36c09..980e636a2 100644 --- a/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json +++ b/scripts/flatpak/org.linuxshowplayer.LinuxShowPlayer.json @@ -178,6 +178,7 @@ } ] }, + "gstreamer-modules.json", "pygobject-modules.json", "python-modules.json", { From 715c965aa9404de697a49886b8d497fd2fbc6164 Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Sat, 27 Jan 2024 22:36:22 +0100 Subject: [PATCH 08/13] [ci] update image version --- .circleci/config.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 507b01264..37711cb55 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,9 @@ version: 2.1 jobs: build-flatpak: machine: - image: ubuntu-2204:2023.07.2 + image: ubuntu-2204:2023.10.1 + + resource_class: large working_directory: ~/repo From 16c41c4d7bb43fe3aa06b7a3f4342c2de1db86c4 Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Sun, 18 Feb 2024 20:06:38 +0100 Subject: [PATCH 09/13] Fix: stop cutting the last few milliseconds of audio --- lisp/plugins/gst_backend/gst_media.py | 105 +++++++++++++++----------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/lisp/plugins/gst_backend/gst_media.py b/lisp/plugins/gst_backend/gst_media.py index a33138f63..e4f8087e0 100644 --- a/lisp/plugins/gst_backend/gst_media.py +++ b/lisp/plugins/gst_backend/gst_media.py @@ -140,7 +140,6 @@ def seek(self, position): self.sought.emit(self, position) def loop_release(self): - # if self.state == MediaState.Playing or self.state == MediaState.Paused: self.__loop = 0 def element(self, class_name): @@ -163,41 +162,54 @@ def update_properties(self, properties): def __reset_media(self): self.__loop = self.loop - def __seek(self, position, flush=True): - if self.state == MediaState.Playing or self.state == MediaState.Paused: - max_position = self.duration - if 0 < self.stop_time < self.duration: - max_position = self.stop_time - - if position < max_position: - # Query segment info for the playback rate - query = Gst.Query.new_segment(Gst.Format.TIME) - self.__pipeline.query(query) - rate = Gst.Query.parse_segment(query)[0] - - # Check stop_position value - stop_type = Gst.SeekType.NONE - if self.stop_time > 0: - stop_type = Gst.SeekType.SET - - # Seek the pipeline - flags = Gst.SeekFlags.SEGMENT | Gst.SeekFlags.TRICKMODE - if flush: - flags |= Gst.SeekFlags.FLUSH - - result = self.__pipeline.seek( - rate if rate > 0 else 1, - Gst.Format.TIME, - flags, - Gst.SeekType.SET, - position * Gst.MSECOND, - stop_type, - self.stop_time * Gst.MSECOND, - ) + def __segment_stop_position(self): + if 0 < self.stop_time < self.duration: + return self.stop_time - return result + return self.duration - return False + def __seek(self, position, flush=True): + if ( + self.state not in (MediaState.Playing, MediaState.Paused) + or position > self.__segment_stop_position() + ): + return False + + # Query segment info for the playback rate + query = Gst.Query.new_segment(Gst.Format.TIME) + self.__pipeline.query(query) + rate = Gst.Query.parse_segment(query)[0] + + # Check if we need to set an early stop position + if self.stop_time > 0: + stop_type = Gst.SeekType.SET + else: + stop_type = Gst.SeekType.NONE + + # Decide which SeekFlags we want to use + flags = Gst.SeekFlags.TRICKMODE + + # We want to receive SEGMENT_DONE messages, allowing seamless loops, + # except for the "last" loop, were we want to receive a normal EOS + # to ensure that all pipeline buffers have been processed. + if self.__loop != 0: + flags |= Gst.SeekFlags.SEGMENT + + # While seeking, we typically want to flush any buffered data. However, + # there are exceptions, such as during seamless looping, where flushing is undesirable. + if flush: + flags |= Gst.SeekFlags.FLUSH + + # Seek the pipeline + return self.__pipeline.seek( + rate if rate > 0 else 1, + Gst.Format.TIME, + flags, + Gst.SeekType.SET, + position * Gst.MSECOND, + stop_type, + self.stop_time * Gst.MSECOND, + ) def __on_loops_changed(self, loops): self.__loop = loops @@ -266,24 +278,27 @@ def __init_pipeline(self): def __on_message(self, bus, message): if message.src == self.__pipeline: - if message.type in ( - Gst.MessageType.SEGMENT_DONE, - Gst.MessageType.EOS, - ): + if message.type == Gst.MessageType.SEGMENT_DONE: if self.__loop != 0: # If we still have loops to do then seek to start self.__loop -= 1 self.__seek(self.start_time, flush=False) else: - # Otherwise go in READY state - self.__pipeline.set_state(Gst.State.READY) - self.__pipeline.get_state(Gst.SECOND) + # We reached loop 0 earlier (e.g. due to a loop-release). + # We cannot stop the pipeline yet, likely there's still data in the buffers, + # to "force" an EOS event we seek to the end of the stream, without flushing. + self.__seek(self.__segment_stop_position(), flush=False) + + elif message.type == Gst.MessageType.EOS: + self.__pipeline.set_state(Gst.State.READY) + self.__pipeline.get_state(Gst.SECOND) + + for element in self.elements: + element.eos() - for element in self.elements: - element.eos() + self.__reset_media() + self.eos.emit(self) - self.__reset_media() - self.eos.emit(self) elif message.type == Gst.MessageType.CLOCK_LOST: self.__pipeline.set_state(Gst.State.PAUSED) self.__pipeline.set_state(Gst.State.PLAYING) From c82664e4efddb1ebe5127d2f8e02eaf084c37feb Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Sat, 24 Feb 2024 17:51:52 +0100 Subject: [PATCH 10/13] Fix #310: when running in flatpak, run "command-cue(s)" command on the host system --- docs/user/cues/misc_cues.md | 3 ++ lisp/__init__.py | 3 ++ lisp/plugins/action_cues/command_cue.py | 39 +++++++++++++++---- .../org.linuxshowplayer.LinuxShowPlayer.json | 3 +- 4 files changed, 39 insertions(+), 9 deletions(-) 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" From f4cc7b206fb7c15356ccf50095f2a864191df341 Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Sat, 24 Feb 2024 17:55:39 +0100 Subject: [PATCH 11/13] Update translation source files --- lisp/i18n/ts/en/action_cues.ts | 21 +++++++++++++-------- lisp/i18n/ts/en/gst_backend.ts | 4 ++-- lisp/i18n/ts/en/lisp.ts | 34 +++++++++++++++++----------------- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/lisp/i18n/ts/en/action_cues.ts b/lisp/i18n/ts/en/action_cues.ts index 512617ce9..285e0bcfd 100644 --- a/lisp/i18n/ts/en/action_cues.ts +++ b/lisp/i18n/ts/en/action_cues.ts @@ -27,32 +27,37 @@ CommandCue - + Command Command - + Command to execute, as in a shell Command to execute, as in a shell - + Discard command output Discard command output - + Ignore command errors Ignore command errors - + Kill instead of terminate Kill instead of terminate - + + Run the command on the host system + + + + Command cue ended with an error status. Exit code: {} @@ -83,7 +88,7 @@ Stop-All - + Command Cue Command Cue @@ -177,7 +182,7 @@ Stop Settings - + Command Command diff --git a/lisp/i18n/ts/en/gst_backend.ts b/lisp/i18n/ts/en/gst_backend.ts index ed551781f..322e0e7cc 100644 --- a/lisp/i18n/ts/en/gst_backend.ts +++ b/lisp/i18n/ts/en/gst_backend.ts @@ -140,7 +140,7 @@ GstMediaError - + Cannot create pipeline element: "{}" @@ -156,7 +156,7 @@ GstMediaWarning - + Invalid pipeline element: "{}" diff --git a/lisp/i18n/ts/en/lisp.ts b/lisp/i18n/ts/en/lisp.ts index df7e98fe4..53e353295 100644 --- a/lisp/i18n/ts/en/lisp.ts +++ b/lisp/i18n/ts/en/lisp.ts @@ -4,25 +4,25 @@ About - + + About Linux Show Player + About Linux Show Player + + + Authors Authors - + Contributors Contributors - + Translators Translators - - - About Linux Show Player - About Linux Show Player - AboutDialog @@ -32,32 +32,32 @@ - + Info Info - + License License - + Contributors Contributors - + Web site Web site - + Discussion - + Source code Source code @@ -124,17 +124,17 @@ ApplicationError - + Startup error - + Error while reading the session file "{}" - + Unable to create the cue "{}" From 45fd0b94a1542c4454f30e59025c8e240ce339c5 Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Sat, 24 Feb 2024 17:56:27 +0100 Subject: [PATCH 12/13] New Crowdin updates (#304) --- lisp/i18n/ts/de_DE/action_cues.ts | 8 ++-- lisp/i18n/ts/de_DE/controller.ts | 14 +++---- lisp/i18n/ts/de_DE/gst_backend.ts | 10 ++--- lisp/i18n/ts/de_DE/lisp.ts | 68 +++++++++++++++---------------- lisp/i18n/ts/de_DE/list_layout.ts | 6 +-- lisp/i18n/ts/de_DE/midi.ts | 12 +++--- lisp/i18n/ts/de_DE/network.ts | 2 +- lisp/i18n/ts/de_DE/osc.ts | 10 ++--- lisp/i18n/ts/de_DE/presets.ts | 16 ++++---- lisp/i18n/ts/de_DE/rename_cues.ts | 16 ++++---- lisp/i18n/ts/de_DE/replay_gain.ts | 4 +- lisp/i18n/ts/de_DE/timecode.ts | 18 ++++---- 12 files changed, 92 insertions(+), 92 deletions(-) diff --git a/lisp/i18n/ts/de_DE/action_cues.ts b/lisp/i18n/ts/de_DE/action_cues.ts index 8df70198f..dc45579e7 100644 --- a/lisp/i18n/ts/de_DE/action_cues.ts +++ b/lisp/i18n/ts/de_DE/action_cues.ts @@ -54,7 +54,7 @@ Command cue ended with an error status. Exit code: {} - Command cue ended with an error status. Exit code: {} + Befehls-Cue endete mit einem Fehlerstatus. Exit-Code: {} @@ -70,7 +70,7 @@ Seek Cue - Positions-Cue + Seek-Cue @@ -156,7 +156,7 @@ Time to reach - Zeit zum Erreichen + Zu erreichende Zeit @@ -164,7 +164,7 @@ Seek Settings - Sucheinstellungen + Seek Einstellungen diff --git a/lisp/i18n/ts/de_DE/controller.ts b/lisp/i18n/ts/de_DE/controller.ts index 753ee3c8e..9a3f51568 100644 --- a/lisp/i18n/ts/de_DE/controller.ts +++ b/lisp/i18n/ts/de_DE/controller.ts @@ -6,7 +6,7 @@ Cannot load controller protocol: "{}" - Cannot load controller protocol: "{}" + Kann das Controller-Protokoll nicht laden: "{}" @@ -85,7 +85,7 @@ Error while importing configuration entry, skipped. - Error while importing configuration entry, skipped. + Fehler beim Importieren des Konfigurationseintrags, übersprungen. @@ -98,12 +98,12 @@ OSC Path: - OSC Path: + OSC-Pfad: /path/to/method - /pfad/zu/methode + /pfad/zur/methode @@ -167,13 +167,13 @@ Osc path seems invalid, do not forget to edit the path later. - Osc path seems invalid, -do not forget to edit the path later. + OSC-Pfad scheint ungültig, +vergessen Sie nicht, den Pfad später zu überarbeiten. Error while importing configuration entry, skipped. - Error while importing configuration entry, skipped. + Fehler beim Importieren des Konfigurationseintrags, übersprungen. diff --git a/lisp/i18n/ts/de_DE/gst_backend.ts b/lisp/i18n/ts/de_DE/gst_backend.ts index 563b7c45c..35af7adca 100644 --- a/lisp/i18n/ts/de_DE/gst_backend.ts +++ b/lisp/i18n/ts/de_DE/gst_backend.ts @@ -11,7 +11,7 @@ To make your custom PCM objects appear correctly in this list requires adding a 'hint.description' line to them. - To make your custom PCM objects appear correctly in this list requires adding a 'hint.description' line to them. + Um Ihre eigenen PCM-Objekte korrekt in dieser Liste erscheinen zu lassen, muss eine 'hint.description' Zeile hinzugefügt werden. @@ -142,7 +142,7 @@ Cannot create pipeline element: "{}" - Cannot create pipeline element: "{}" + Pipeline-Element kann nicht erstellt werden: "{}" @@ -158,7 +158,7 @@ Invalid pipeline element: "{}" - Invalid pipeline element: "{}" + Ungültiges Pipeline-Element: "{}" @@ -187,7 +187,7 @@ An error occurred while disconnecting Jack ports - An error occurred while disconnecting Jack ports + Fehler beim Trennen der Jack-Ports @@ -337,7 +337,7 @@ ALSA Default Device - ALSA Default Device + ALSA Standardgerät diff --git a/lisp/i18n/ts/de_DE/lisp.ts b/lisp/i18n/ts/de_DE/lisp.ts index b7ce98c6a..b919db50b 100644 --- a/lisp/i18n/ts/de_DE/lisp.ts +++ b/lisp/i18n/ts/de_DE/lisp.ts @@ -29,7 +29,7 @@ Linux Show Player is a cue player designed for stage productions. - Linux Show Player is a cue player designed for stage productions. + Der Linux Show Player ist ein Cue-Player, entwickelt für Bühnenproduktionen. @@ -49,7 +49,7 @@ Web site - Website + Webseite @@ -75,7 +75,7 @@ Cannot load configuration page: "{}" ({}) - Cannot load configuration page: "{}" ({}) + Konfigurationsseite kann nicht geladen werden: "{}" ({}) @@ -113,7 +113,7 @@ Application language (require a restart) - Anwendungssprache (Neustart erforderlich) + Anwendungssprache (benötigt Neustart) @@ -131,12 +131,12 @@ Error while reading the session file "{}" - Error while reading the session file "{}" + Fehler beim Lesen der Sitzungsdatei "{}" Unable to create the cue "{}" - Unable to create the cue "{}" + Konnte das Cue "{}" nicht erstellen @@ -144,7 +144,7 @@ Cannot load python class: "{0}" - Cannot load python class: "{0}" + Kann Python-Klasse nicht laden: "{0}" @@ -165,7 +165,7 @@ Configuration read from {} - Configuration read from {} + Konfiguration eingelesen von {} @@ -183,7 +183,7 @@ Invalid path "{}", return default. - Invalid path "{}", return default. + Ungültiger Pfad "{}", Rückfall auf den Standard. @@ -246,7 +246,7 @@ Release from Loop - Release from Loop + Schleife beenden @@ -310,7 +310,7 @@ Cue settings changed: "{}" - Cue settings changed: "{}" + Cue-Einstellungen wurden verändert: "{}" @@ -354,22 +354,22 @@ Interrupt fade - Interrupt fade + Überblenden unterbrechen Used globally when interrupting cues - Used globally when interrupting cues + Global beim Unterbrechen von Cues verwendet Fallback fade settings - Fallback fade settings + Fallback-Fade-Einstellungen Used for fade-in and fade-out actions, for cues where fade duration is set to 0. - Used for fade-in and fade-out actions, for cues where fade duration is set to 0. + Wird für Fade-In- und Fade-Out-Aktionen verwendet, bei denen die Fade-Dauer auf 0 gesetzt ist. @@ -781,7 +781,7 @@ The current session contains changes that have not been saved. - The current session contains changes that have not been saved. + Die aktuelle Sitzung enthält Änderungen, die nicht gespeichert wurden. @@ -794,7 +794,7 @@ Registered cue menu: "{}" - Registered cue menu: "{}" + Cue-Menü registriert: "{}" @@ -835,7 +835,7 @@ Repetition after first play (-1 = infinite) - Repetition after first play (-1 = infinite) + Wiederholung nach der ersten Wiedergabe (-1 = unendlich) @@ -843,7 +843,7 @@ Cannot load python module: "{0}" - Cannot load python module: "{0}" + Python-Modul kann nicht geladen werden: "{0}" @@ -851,27 +851,27 @@ A plugin by the name of "{}" already exists. - A plugin by the name of "{}" already exists. + Ein Plugin mit dem Namen "{}" existiert bereits. The requested plugin is not loaded: "{}" - The requested plugin is not loaded: "{}" + Das angeforderte Plugin wurde nicht geladen: "{}" Failed to register plugin: "{}" - Failed to register plugin: "{}" + Plugin konnte nicht registriert werden: "{}" Failed to terminate plugin: "{}" - Failed to terminate plugin: "{}" + Plugin konnte nicht beendet werden: "{}" Cannot satisfy dependencies for plugin: "{}" - Cannot satisfy dependencies for plugin: "{}" + Kann Abhängigkeiten für das Plugin "{}" nicht erfüllen @@ -879,12 +879,12 @@ Plugin terminated: "{}" - Plugin terminated: "{}" + Plugin beendet: "{}" Plugin loaded: "{}" - Plugin loaded: "{}" + Plugin geladen: "{}" @@ -892,12 +892,12 @@ Plugin - Plugin + Plugin Enabled - Enabled + Aktiviert @@ -905,27 +905,27 @@ Plugin disabled. Enable to use. - Plugin disabled. Enable to use. + Plugin deaktiviert. Zum Nutzen aktivieren. An error has occurred with this plugin. Please see logs for further information. - An error has occurred with this plugin. Please see logs for further information. + Ein Fehler betrifft dieses Plugin. Die Logs enthalten weitere Informationen. There is a non-critical issue with this disabled plugin. Please see logs for further information. - There is a non-critical issue with this disabled plugin. Please see logs for further information. + Ein unkritisches Problem betrifft dieses deaktivierte Plugin. Die Logs enthalten weitere Informationen. Plugin loaded and ready for use. - Plugin loaded and ready for use. + Plugin geladen und einsatzbereit. A non-critical issue is affecting this plugin. Please see logs for further information. - A non-critical issue is affecting this plugin. Please see logs for further information. + Ein unkritisches Problem betrifft dieses Plugin. Die Logs enthalten weitere Informationen. @@ -961,7 +961,7 @@ Media Cue - Media Cue + Medien-Cue diff --git a/lisp/i18n/ts/de_DE/list_layout.ts b/lisp/i18n/ts/de_DE/list_layout.ts index aa478f60d..c3c12f361 100644 --- a/lisp/i18n/ts/de_DE/list_layout.ts +++ b/lisp/i18n/ts/de_DE/list_layout.ts @@ -24,7 +24,7 @@ To move cues drag them - Um Cues zu verschieben, ziehen Sie sie + Um Cues zu verschieben, ziehen Sie diese @@ -145,7 +145,7 @@ GO Key: - GO Taste: + GO-Taste: @@ -155,7 +155,7 @@ GO minimum interval (ms): - GO minimales Intervall (ms): + Minimales Intervall für GO (in ms): diff --git a/lisp/i18n/ts/de_DE/midi.ts b/lisp/i18n/ts/de_DE/midi.ts index b60f9cb91..c96f3d63c 100644 --- a/lisp/i18n/ts/de_DE/midi.ts +++ b/lisp/i18n/ts/de_DE/midi.ts @@ -35,17 +35,17 @@ Cannot connect to MIDI output port '{}'. - Cannot connect to MIDI output port '{}'. + Verbindung zum MIDI-Ausgangsport '{}' nicht möglich. Cannot connect to MIDI input port '{}'. - Cannot connect to MIDI input port '{}'. + Verbindung zum MIDI-Eingangsport '{}' nicht möglich. Cannot create ALSA-MIDI port monitor, MIDI connections/disconnections will not be detected. - Cannot create ALSA-MIDI port monitor, MIDI connections/disconnections will not be detected. + ALSA-MIDI-Port-Monitor kann nicht erstellt werden, MIDI-Verbindungen werden nicht erkannt. @@ -53,17 +53,17 @@ Connecting to MIDI port: '{}' - Connecting to MIDI port: '{}' + Verbinde mit MIDI-Port: '{}' MIDI port disconnected: '{}' - MIDI port disconnected: '{}' + MIDI-Port getrennt: '{}' Connecting to matching MIDI port: '{}' - Connecting to matching MIDI port: '{}' + Verbinde mit dem passenden MIDI-Port: '{}' diff --git a/lisp/i18n/ts/de_DE/network.ts b/lisp/i18n/ts/de_DE/network.ts index bcd8afd89..41ad60afa 100644 --- a/lisp/i18n/ts/de_DE/network.ts +++ b/lisp/i18n/ts/de_DE/network.ts @@ -22,7 +22,7 @@ Start serving network API at: http://{}:{}/ - Start serving network API at: http://{}:{}/ + Starten der Netzwerk-API unter: http://{}:{}/ diff --git a/lisp/i18n/ts/de_DE/osc.ts b/lisp/i18n/ts/de_DE/osc.ts index 38f664ad3..51cc226b6 100644 --- a/lisp/i18n/ts/de_DE/osc.ts +++ b/lisp/i18n/ts/de_DE/osc.ts @@ -22,7 +22,7 @@ OSC Cue - OSC Cue + OSC-Cue @@ -60,7 +60,7 @@ Time (sec) - Zeit (Sek) + Zeit (in Sek) @@ -88,7 +88,7 @@ Cannot send OSC message, see error for details - Cannot send OSC message, see error for details + OSC-Nachricht kann nicht gesendet werden, siehe Fehler für Details @@ -96,7 +96,7 @@ Message from {} -> path: "{}" args: {} - Message from {} -> path: "{}" args: {} + Nachricht von {} -> Pfad: "{}" Args: {} @@ -104,7 +104,7 @@ Cannot start OSC server - Cannot start OSC server + OSC-Server kann nicht gestartet werden diff --git a/lisp/i18n/ts/de_DE/presets.ts b/lisp/i18n/ts/de_DE/presets.ts index 1844d216f..4baab4fad 100644 --- a/lisp/i18n/ts/de_DE/presets.ts +++ b/lisp/i18n/ts/de_DE/presets.ts @@ -69,22 +69,22 @@ Error while deleting preset "{}" - Error while deleting preset "{}" + Fehler beim Löschen des Presets "{}" Cannot load preset "{}" - Cannot load preset "{}" + Kann Preset "{}" nicht laden Cannot save preset "{}" - Cannot save preset "{}" + Kann Preset "{}" nicht speichern Cannot rename preset "{}" - Cannot rename preset "{}" + Kann Preset "{}" nicht umbenennen @@ -94,7 +94,7 @@ Preset "{}" already exists, overwrite? - Preset "{}" already exists, overwrite? + Ein Preset mit dem Namen "{}" existiert bereits, überschreiben? @@ -114,7 +114,7 @@ Some presets already exists, overwrite? - Some presets already exists, overwrite? + Einige Presets existieren bereits, überschreiben? @@ -129,12 +129,12 @@ Apply to cue - Apply to cue + Auf Cue anwenden Apply to selected cues - Apply to selected cues + Auf ausgewählte Cues anwenden diff --git a/lisp/i18n/ts/de_DE/rename_cues.ts b/lisp/i18n/ts/de_DE/rename_cues.ts index e8ced2e00..b9797532d 100644 --- a/lisp/i18n/ts/de_DE/rename_cues.ts +++ b/lisp/i18n/ts/de_DE/rename_cues.ts @@ -70,16 +70,16 @@ Example: Only the numbers are between parenthesis and will be usable with $0 in the first line. For more information about Regexes, consult python documentation at: https://docs.python.org/3/howto/regex.html#regex-howto - You can use Regexes to rename your cues. + Sie können Regexes verwenden, um Ihre Cues umzubenennen. -Insert expressions captured with regexes in the line below with $0 for the first parenthesis, $1 forthe second, etc... -In the second line, you can use standard Python Regexes to match expressions in the original cues names. Use parenthesis to capture parts of the matched expression. +Fügen Sie mit Regexes in die Zeile unten erfasste Ausdrücke mit $0 für die erste Klammer ein, $1 für die zweite, etc... +In der zweiten Zeile können Sie standardmäßige Python-Regexes verwenden, um Ausdrücke in den ursprünglichen Namen zu finden. Verwenden Sie Klammern um Teile des passenden Ausdrucks zu erfassen. -Example: -^[a-z]([0-9]+) will find a lower case character([a-z]), followed by one or more number. -Only the numbers are between parenthesis and will be usable with $0 in the first line. +Beispiel: +^[a-z]([0-9]+) findet ein Kleinbuchstaben ([a-z]), gefolgt von einer oder mehreren Zahlen. +Nur die Zahlen liegen zwischen Klammern und können mit $0 in der ersten Zeile verwendet werden. -For more information about Regexes, consult python documentation at: https://docs.python.org/3/howto/regex.html#regex-howto +Weitere Informationen über Regexes sind in der Python-Dokumentation zu finden unter: https://docs.python.org/3/howto/regex.html#regex-howto @@ -110,7 +110,7 @@ For more information about Regexes, consult python documentation at: https://doc Regex error: catch with () before display with $n - Regex error: catch with () before display with $n + Regex-Fehler: Catch mit () vor Anzeige mit $n diff --git a/lisp/i18n/ts/de_DE/replay_gain.ts b/lisp/i18n/ts/de_DE/replay_gain.ts index 4fc11babd..231097f60 100644 --- a/lisp/i18n/ts/de_DE/replay_gain.ts +++ b/lisp/i18n/ts/de_DE/replay_gain.ts @@ -67,12 +67,12 @@ An error occurred during gain calculation. - An error occurred during gain calculation. + Bei der Gain-Berechnung ist ein Fehler aufgetreten. An error occurred while processing gain results. - An error occurred while processing gain results. + Ein Fehler trat bei der Verarbeitung der Gain-Ergebnisse auf. diff --git a/lisp/i18n/ts/de_DE/timecode.ts b/lisp/i18n/ts/de_DE/timecode.ts index bef0e5536..6f5a30b8c 100644 --- a/lisp/i18n/ts/de_DE/timecode.ts +++ b/lisp/i18n/ts/de_DE/timecode.ts @@ -6,12 +6,12 @@ Timecode - Timecode + Zeitcode Timecode Settings - Timecode Einstellungen + Zeitcode-Einstellungen @@ -19,7 +19,7 @@ Cannot load timecode protocol: "{}" - Cannot load timecode protocol: "{}" + Zeitcode-Protokoll kann nicht geladen werden: "{}" @@ -28,8 +28,8 @@ Cannot send timecode. OLA daemon has stopped. - Cannot send timecode. -OLA daemon has stopped. + Zeitcode kann nicht gesendet werden, weil der +OLA-Daemon gestoppt wurde. @@ -52,22 +52,22 @@ OLA daemon has stopped. Track number - Spurnummer + Tracknummer Timecode Settings - Timecode-Einstellungen + Zeitcode-Einstellungen Timecode Format: - Timecode-Format: + Zeitcode-Format: Timecode Protocol: - Timecode Protokoll: + Zeitcode-Protokoll: From 88f17c9c6781daaa39bffeed701c7dc83b73afd1 Mon Sep 17 00:00:00 2001 From: Francesco Ceruti Date: Wed, 28 Feb 2024 22:22:15 +0100 Subject: [PATCH 13/13] Update translation files --- lisp/i18n/qm/base_de_DE.qm | Bin 58099 -> 59209 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lisp/i18n/qm/base_de_DE.qm b/lisp/i18n/qm/base_de_DE.qm index 738fca74777c695f5b7a1c66305e814967bd3243..39b4d20060f6058a047d882b7c206d3653cbde6e 100644 GIT binary patch delta 11304 zcmcIo2UwI>);`nwj1d8`j)Ed8D%eGdh)4uQg4nP`nt)|A6p2P1yGF5oy4I)(_8!L; zB}T>GTVh#PO`<8r#3YtYT#WyFzRNJ^y8rI~Jp0FooSE<5@7#0V^PY0&(NWdObE>(u zoslbvqE{1D*(7A$Z9+EqTF8PhA(t-_@@zIy%r5M|D`c8Z$o=z$JWwjnZWZ4zB@rd& z5Cy(R>iue>RS!sgd<{{-B3U}=(iBpk$HM3Y(x}f9DK$b4IxFPV4ANBpfGFT7X&PK1 zvdtq+i-APWDAM$VqT%;RGw1-(`@Kn%xt^$A0cokzqoJV1+yoruRQFOMm z5m81cMNffe1I|$NUycyvPo|jE6c~1!Vm{qNl%7v9CyxTMVbmpNCsBAIbyaSIbcuQy7XyJRLQZl}FDE~kZ=l{Y zUclpu)cYh9MYR)h!yF;6BvS9^j{*G=N*V$KCdUYQY!W4{UjRd=3YnWveUGmry5ORI z+G3(0HT9dc3kUu# zu%cp|`cIE*uik+{y|N_tyty$58nbwZOT)9(_uiHbmgrG zc=~yN<(-f#M6Kp2A9hp`9oH#;O*u=nZ?E!?qeqdJk;*?i!K1{(DnI1`qIPFgRc|4$ zyY5m2M1aIA=Bfe`Gl(2&RlQ&NyIs|AcqGyKx~fJjH$2$Z zbJeVS@Nn)j)q<%8c>Gkg%>Pruf2tKVj_{Lin{xm4n$M7sM99ZK~}U<4}0%t zq9J3{c`^6Eet&h|D(4mylB?>GD?<@WyE^|lVjnYKJ(>{P?)TKAw+}$6%@?xPdqURU zA!OYgAv@m|GWCLxXT#KE)`Mi`3hECWe<0@f)HAQ#BC0=Iy*vrzwe?f4FAO2_pRQi- zEX2Y7$MFE<2+*oGFP}lwfz&&SeRN=0sO0{gFmBTbuhmS>!8)&M{tN}9mYnsFY+K3cQ zR1qM}T&_uct2ydLk*4RZQ>gvXLe7fT^!f=1Hp|x}­5dkJ~KsL4DD!^6MS49-J{ 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