Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/package-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ jobs:
run: |
set -euo pipefail
dnf install -y \
"https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-${{ matrix.fedora }}.noarch.rpm"
dnf install -y --allowerasing \
appstream \
cpio \
dbus-daemon \
desktop-file-utils \
ffmpeg-free \
ffmpeg \
findutils \
gcc-c++ \
git \
Expand Down
121 changes: 90 additions & 31 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.1.1
2.2.0
10 changes: 10 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
tryx-panorama-manager (2.2.0-1) noble; urgency=medium

* Add community-tested Panorama 391a:1011 printer-class support.
* Add Turris 620 391a:2011 media upload with 1280x720 MXHD preparation.
* Select media geometry and capabilities from the exact USB product.
* Bind retry, recovery, and firmware gates to the identified device model.
* Ship udev and AppStream metadata for all supported printer-class IDs.

-- DXVSI <dxvsi123@gmail.com> Sun, 09 Aug 2026 13:26:08 +0700

tryx-panorama-manager (2.1.1-1) noble; urgency=medium

* Start the sibling API 8 runtime for direct build-tree GUI launches.
Expand Down
8 changes: 4 additions & 4 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Suggests:
mesa-utils,
pciutils,
unzip
Description: control TRYX Panorama cooler displays on Linux
TRYX Panorama Manager controls compatible TRYX Panorama and Panorama SE
cooler displays. It supports custom media, display settings, system metrics,
and the PASE printer-class USB protocol.
Description: control compatible TRYX cooler displays on Linux
TRYX Panorama Manager controls compatible TRYX Panorama, Panorama SE, and
Turris 620 cooler displays. It uses model-specific media profiles and enables
only the printer-class USB capabilities supported by each device.
9 changes: 7 additions & 2 deletions packaging/70-tryx-pase-access.rules
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# TRYX PANORAMA SE exposes a vendor protocol over a USB Printer Class
# interface. Mark it for logind ACL assignment before 73-seat-late.rules.
# Supported TRYX displays expose a vendor protocol over a USB Printer Class
# interface. Mark them for logind ACL assignment before 73-seat-late.rules.

ACTION=="add|change", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="391a", ATTR{idProduct}=="1021", OWNER="root", GROUP="lp", MODE="0660", TAG+="uaccess"

ACTION=="add|change", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="391a", ATTR{idProduct}=="1011", OWNER="root", GROUP="lp", MODE="0660", TAG+="uaccess"

ACTION=="add|change", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="391a", ATTR{idProduct}=="2011", OWNER="root", GROUP="lp", MODE="0660", TAG+="uaccess"
5 changes: 4 additions & 1 deletion packaging/99-tryx-pase-printer.rules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# TRYX PANORAMA SE is not a CUPS printer. Clear printer units selected by
# Supported TRYX displays are not CUPS printers. Clear printer units selected by
# generic distro rules. Access is assigned earlier by 70-tryx-pase-access.rules.

ACTION=="add|change", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="391a", ATTR{idProduct}=="1021", ENV{SYSTEMD_WANTS}="", ENV{SYSTEMD_USER_WANTS}=""
ACTION=="add|change", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="391a", ATTR{idProduct}=="1011", ENV{SYSTEMD_WANTS}="", ENV{SYSTEMD_USER_WANTS}=""
ACTION=="add|change", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="391a", ATTR{idProduct}=="2011", ENV{SYSTEMD_WANTS}="", ENV{SYSTEMD_USER_WANTS}=""
4 changes: 2 additions & 2 deletions packaging/arch/PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
# PKGBUILD metadata and directory variables are consumed or provided by makepkg.
# shellcheck disable=SC2034,SC2154
pkgname=tryx-panorama-manager
pkgver=2.1.1
pkgver=2.2.0
pkgrel=1
pkgdesc='Control TRYX Panorama cooler displays on Linux'
pkgdesc='Control compatible TRYX cooler displays on Linux'
arch=('x86_64')
url='https://github.com/DXVSI/Tryx-Linux-GUI'
license=('MIT' 'BSD-2-Clause')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
<metadata_license>CC0-1.0</metadata_license>
<project_license>MIT AND BSD-2-Clause</project_license>
<name>TRYX Panorama Manager</name>
<summary>Control TRYX Panorama cooler displays on Linux</summary>
<summary>Control compatible TRYX cooler displays on Linux</summary>
<description>
<p>
TRYX Panorama Manager controls compatible TRYX Panorama and Panorama SE
cooler displays from Linux. It supports custom media, display settings,
system metrics, and the PASE printer-class USB protocol.
TRYX Panorama Manager controls compatible TRYX Panorama, Panorama SE, and
Turris 620 cooler displays from Linux. It uses model-specific media
profiles and enables only the capabilities supported by each device.
</p>
</description>
<developer id="io.github.dxvsi">
Expand All @@ -18,12 +18,25 @@
<launchable type="desktop-id">tryx-panorama-manager.desktop</launchable>
<provides>
<binary>tryx-panorama-manager</binary>
<modalias>usb:v391Ap1011d*</modalias>
<modalias>usb:v391Ap1021d*</modalias>
<modalias>usb:v391Ap2011d*</modalias>
</provides>
<url type="homepage">https://github.com/DXVSI/Tryx-Linux-GUI</url>
<url type="bugtracker">https://github.com/DXVSI/Tryx-Linux-GUI/issues</url>
<content_rating type="oars-1.1"/>
<releases>
<release version="2.2.0" type="stable" date="2026-08-09">
<description>
<ul>
<li>Add community-tested Panorama 391a:1011 printer-class support.</li>
<li>Add Turris 620 media preparation and acknowledged upload at 1280 by 720.</li>
<li>Adapt media editing and preview geometry to the connected model.</li>
<li>Reject unsupported operations before USB dispatch using exact product capabilities.</li>
<li>Bind session recovery and prepared-media retries to the exact USB product.</li>
</ul>
</description>
</release>
<release version="2.1.1" type="stable" date="2026-08-03">
<description>
<ul>
Expand Down
21 changes: 14 additions & 7 deletions packaging/rpm/tryx-panorama-manager.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Name: tryx-panorama-manager
Version: 2.1.1
Version: 2.2.0
Release: 1%{?dist}
Summary: Linux manager for supported TRYX Panorama cooler displays
Summary: Linux manager for supported TRYX cooler displays

License: MIT AND BSD-2-Clause
URL: https://github.com/DXVSI/Tryx-Linux-GUI
Expand All @@ -14,7 +14,7 @@ ExclusiveArch: x86_64
BuildRequires: gcc-c++
BuildRequires: make
BuildRequires: dbus-daemon
BuildRequires: ffmpeg-free
BuildRequires: ffmpeg
BuildRequires: qt6-rpm-macros
BuildRequires: qt6-linguist
BuildRequires: qt6-qtdeclarative-devel
Expand Down Expand Up @@ -46,7 +46,7 @@ Requires: qt6-qtdeclarative%{?_isa}
Requires: ffmpeg

# Native Wayland support and the legacy/firmware discovery helpers are useful
# but are not required for the PASE printer-class control path.
# but are not required for the printer-class control path.
Recommends: qt6-qtwayland%{?_isa}
Suggests: /usr/bin/adb
Suggests: /usr/bin/unzip
Expand All @@ -58,9 +58,9 @@ Suggests: /usr/bin/lspci

%description
TRYX Panorama Manager is a Qt 6 application for controlling supported TRYX
Panorama and Panorama SE cooler displays on Linux. It manages custom media,
display settings, live system metrics, and devices using the PASE
printer-class USB protocol.
Panorama, Panorama SE, and Turris 620 cooler displays on Linux. It uses
model-specific media profiles and enables only the printer-class USB
capabilities supported by each device.

The package contains open-source project components and host integration. It
does not contain vendor media, firmware archives, or the proprietary Rockchip
Expand Down Expand Up @@ -118,6 +118,13 @@ udevadm verify --resolve-names=never \
%{_mandir}/man1/tryx-panorama-manager.1*

%changelog
* Sun Aug 09 2026 DXVSI <DXVSI@users.noreply.github.com> - 2.2.0-1
- Add community-tested Panorama 391a:1011 printer-class support
- Add Turris 620 391a:2011 media upload with 1280x720 MXHD preparation
- Select media geometry and capabilities from the exact USB product
- Bind retry, recovery, and firmware gates to the identified device model
- Ship udev and AppStream metadata for all supported printer-class IDs

* Mon Aug 03 2026 DXVSI <DXVSI@users.noreply.github.com> - 2.1.1-1
- Start the sibling API 8 runtime for direct build-tree GUI launches
- Fail closed around systemd startup jobs and D-Bus owner replacement
Expand Down
38 changes: 38 additions & 0 deletions packaging/scripts/verify-package-contents.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,44 @@ require_file /usr/share/metainfo/io.github.dxvsi.tryx_panorama_manager.metainfo.
require_file /usr/share/licenses/tryx-panorama-manager/LICENSE
require_file /usr/share/licenses/tryx-panorama-manager/picojson-BSD-2-Clause.txt

expected_usb_product_ids=$(printf '%s\n' 1011 1021 2011)

udev_product_ids() {
sed -n \
's/.*ATTR{idVendor}=="391a".*ATTR{idProduct}=="\([[:xdigit:]]\{4\}\)".*/\1/p' \
"$1" |
tr '[:upper:]' '[:lower:]' |
LC_ALL=C sort
}

appstream_product_ids() {
sed -n \
's|.*<modalias>usb:v391Ap\([[:xdigit:]]\{4\}\)d\*</modalias>.*|\1|p' \
"$1" |
tr '[:upper:]' '[:lower:]' |
LC_ALL=C sort
}

for usb_product_source in \
"$staged_root/usr/lib/udev/rules.d/70-tryx-pase-access.rules" \
"$staged_root/usr/lib/udev/rules.d/99-tryx-pase-printer.rules"
do
packaged_usb_product_ids=$(udev_product_ids "$usb_product_source")
if [ "$packaged_usb_product_ids" != "$expected_usb_product_ids" ]; then
echo "unexpected supported USB product IDs in ${usb_product_source#"$staged_root"}:" >&2
printf '%s\n' "$packaged_usb_product_ids" >&2
exit 1
fi
done

metainfo_path=$staged_root/usr/share/metainfo/io.github.dxvsi.tryx_panorama_manager.metainfo.xml
packaged_usb_product_ids=$(appstream_product_ids "$metainfo_path")
if [ "$packaged_usb_product_ids" != "$expected_usb_product_ids" ]; then
echo "unexpected supported USB product IDs in ${metainfo_path#"$staged_root"}:" >&2
printf '%s\n' "$packaged_usb_product_ids" >&2
exit 1
fi

if [ -e "$staged_root/usr/bin/tryx-panorama-quick" ]; then
echo "package contains the retired secondary Quick launcher" >&2
exit 1
Expand Down
17 changes: 9 additions & 8 deletions packaging/tryx-panorama-manager.1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.TH TRYX-PANORAMA-MANAGER 1 "2026-08-03" "TRYX Panorama Manager 2.1.1" "User Commands"
.TH TRYX-PANORAMA-MANAGER 1 "2026-08-09" "TRYX Panorama Manager 2.2.0" "User Commands"
.SH NAME
tryx-panorama-manager \- control compatible TRYX Panorama cooler displays
tryx-panorama-manager \- control compatible TRYX cooler displays
.SH SYNOPSIS
.B tryx-panorama-manager
.br
Expand All @@ -9,13 +9,14 @@ tryx-panorama-manager \- control compatible TRYX Panorama cooler displays
.br
.SH DESCRIPTION
.B TRYX Panorama Manager
is a Qt 6 Quick application for controlling compatible TRYX Panorama and
Panorama SE cooler displays on Linux.
is a Qt 6 Quick application for controlling compatible TRYX Panorama,
Panorama SE, and Turris 620 cooler displays on Linux.
The desktop GUI communicates over the user D-Bus session with a separately
packaged private runtime that owns USB, legacy serial/ADB, media, live-metrics,
and firmware operations.
The application manages custom media, display settings, and devices using the
PASE printer-class USB protocol without bundling vendor media.
The application uses model-specific media profiles and enables only the
printer-class USB capabilities supported by each device, without bundling
vendor media.
.PP
Starting the graphical application starts the packaged systemd user service on
demand.
Expand All @@ -41,10 +42,10 @@ Systemd user unit for the background runtime.
Preset that keeps the user unit disabled after package installation.
.TP
.I /usr/lib/udev/rules.d/70-tryx-pase-access.rules
Early PASE device-access rule.
Early supported-device access rule.
.TP
.I /usr/lib/udev/rules.d/99-tryx-pase-printer.rules
Late rule that prevents printer-service activation for the PASE interface.
Late rule that prevents printer-service activation for supported interfaces.
.SH BUGS
Report issues at
.UR https://github.com/DXVSI/Tryx-Linux-GUI/issues
Expand Down
4 changes: 2 additions & 2 deletions packaging/tryx-panorama-manager.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
Type=Application
Name=TRYX Panorama Manager
Name[ru]=Менеджер TRYX Panorama
Comment=Manage TRYX Panorama cooler displays
Comment[ru]=Управление дисплеями систем охлаждения TRYX Panorama
Comment=Manage compatible TRYX cooler displays
Comment[ru]=Управление совместимыми дисплеями систем охлаждения TRYX
Exec=tryx-panorama-manager
Icon=tryx-panorama
Terminal=false
Expand Down
29 changes: 24 additions & 5 deletions qml/components/MediaEditor.qml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ Popup {
controller.rotation === 0 &&
(controller.mode !== "Crop" ||
controller.zoomPercent === 100)
readonly property real targetAspectRatio:
controller.targetWidth > 0 && controller.targetHeight > 0
? controller.targetWidth / controller.targetHeight
: 1
readonly property string targetResolution:
qsTr("%1 × %2").arg(controller.targetWidth)
.arg(controller.targetHeight)
readonly property string recoveredSourceResolution:
controller.originalMediaName.toLowerCase()
.endsWith(".h264_1280x720")
? qsTr("%1 × %2").arg(1280).arg(720)
: (controller.originalMediaName.toLowerCase()
.endsWith(".h264_2240x1080")
? qsTr("%1 × %2").arg(2240).arg(1080)
: targetResolution)

function synchronizeVisibility() {
if (controller.open && !root.opened)
Expand Down Expand Up @@ -134,7 +149,7 @@ Popup {
anchors.rightMargin: 12
text:
root.recoveredTransformIsGeometryNeutral
? qsTr("This device copy is already encoded at 2240 × 1080, so the current settings will not visibly change it. Existing padding is baked into the video. Choose Crop and raise Zoom above 100%, or rotate the video. Save as new does not change the active display; select the new copy in the library and apply it. Previously lost areas cannot be restored.")
? qsTr("This device copy is already encoded at %1, so the current settings will not visibly change it. Existing padding is baked into the video. Choose Crop and raise Zoom above 100%, or rotate the video. Save as new does not change the active display; select the new copy in the library and apply it. Previously lost areas cannot be restored.").arg(root.recoveredSourceResolution)
: qsTr("This is a private working copy recovered from the device. Save as new stores another media item but does not change the active display; select the new copy in the library and apply it. Replace original updates the original item. Saving re-encodes the video; areas lost before the original upload cannot be restored.")
color:
root.recoveredTransformIsGeometryNeutral
Expand All @@ -147,7 +162,9 @@ Popup {
id: previewViewport
Layout.fillWidth: true
Layout.preferredHeight:
Math.min(420, width * 1080 / 2240)
Math.min(
420,
width / root.targetAspectRatio)
Layout.minimumHeight: 220

Rectangle {
Expand All @@ -157,8 +174,9 @@ Popup {
anchors.centerIn: parent
width: Math.min(
parent.width,
parent.height * 2240 / 1080)
height: width * 1080 / 2240
parent.height *
root.targetAspectRatio)
height: width / root.targetAspectRatio
color: "#000000"
border.color: "#6b6f80"
radius: 6
Expand Down Expand Up @@ -253,10 +271,11 @@ Popup {
}

Label {
objectName: "mediaTargetResolution"
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: 8
text: "2240 × 1080"
text: root.targetResolution
color: "#b7bac7"
font.pixelSize: 11
}
Expand Down
4 changes: 2 additions & 2 deletions qml/pages/SettingsPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ ScrollView {

Label {
Layout.fillWidth: true
text: qsTr("Used by legacy serial/ADB devices. PASE printer-class devices are detected automatically.")
text: qsTr("Used by legacy serial/ADB devices. TRYX printer-class devices are detected automatically.")
color: "#7f8991"
wrapMode: Text.WordWrap
}
Expand Down Expand Up @@ -328,7 +328,7 @@ ScrollView {
Label {
Layout.fillWidth: true
text: root.runtime.printerClassDevicePresent
? qsTr("PASE printer class")
? qsTr("TRYX printer class")
: (root.runtime.legacyConnected
? qsTr("Legacy serial / ADB")
: qsTr("Waiting for device"))
Expand Down
Loading