This commit is contained in:
nvrl committed 2026-08-02 19:37:03 +02:00
commit a1b345a029
80 files changed
+28033

No files matched your search

+95
View File
@@ -0,0 +1,95 @@
# Maintainer: Nils Pukropp <contact@narl.io>
#
# Local-build PKGBUILD, mirroring ../proton-drive-linux/packaging/PKGBUILD: this
# is NOT a source-fetch package, it compiles the working tree this file lives in.
#
# cd packaging && makepkg -fi
#
# Two things it needs that an ordinary AUR package would not:
#
# * Network, so cargo can fetch crates.io (`--locked`, not `--frozen`).
# * A sibling `../../proton-sdk-rs` checkout, for as long as the workspace
# carries `[patch.crates-io]`. Once proton-sdk 0.3.3 is published and that
# block is removed, the check in build() stops firing and the package
# builds from the registry alone.
pkgname=proton-stream
pkgver=0.1.0
pkgrel=1
pkgdesc="Netflix-style desktop client for Proton Drive public links: browse and stream a share"
arch=('x86_64')
url="https://github.com/narrrl/proton-stream"
license=('MIT')
# mpv carries libmpv.so plus its headers on Arch, so it is both the runtime and
# the build dependency. libsecret is the Secret Service side of the keyring —
# the share fragment and custom password never touch shares.json.
depends=('mpv' 'libsecret' 'hicolor-icon-theme')
makedepends=('cargo')
optdepends=('gnome-keyring: credential storage via Secret Service'
'kwallet: credential storage via Secret Service on KDE')
provides=('pstr')
# !lto for the same reason the sibling repo sets it; !debug keeps a 0.1.0 local
# package from also emitting a multi-hundred-MB -debug split.
options=('!lto' '!debug')
# Built in place from the checkout; nothing to fetch or checksum.
source=()
sha256sums=()
# Absolute path to the workspace root (packaging/ lives directly under it).
_workspace="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
pkgver() {
cd "$_workspace"
local v
v=$(grep -m1 '^version' Cargo.toml | cut -d'"' -f2)
printf '%s' "${v:-0.1.0}"
}
build() {
cd "$_workspace"
# The dev-only path patch. Fail early and legibly rather than a hundred lines
# into a cargo resolve error.
if grep -q '^\[patch\.crates-io\]' Cargo.toml && [[ ! -d "$_workspace/../proton-sdk-rs" ]]; then
echo "error: Cargo.toml still carries [patch.crates-io] pointing at ../proton-sdk-rs," >&2
echo " but that checkout is missing. Clone it beside this repo, or drop the" >&2
echo " patch block once proton-sdk 0.3.3 is on crates.io." >&2
return 1
fi
export RUSTUP_TOOLCHAIN=stable
export CARGO_TARGET_DIR="$_workspace/target"
cargo build --release --locked \
--bin proton-stream \
--bin pstr
}
check() {
cd "$_workspace"
export RUSTUP_TOOLCHAIN=stable
export CARGO_TARGET_DIR="$_workspace/target"
# Offline suites only; nothing here needs a share or an account.
cargo test --workspace --locked
}
package() {
cd "$_workspace"
local rel="target/release"
install -Dm755 "$rel/proton-stream" "$pkgdir/usr/bin/proton-stream"
install -Dm755 "$rel/pstr" "$pkgdir/usr/bin/pstr"
install -Dm644 "packaging/io.narl.proton-stream.desktop" \
"$pkgdir/usr/share/applications/io.narl.proton-stream.desktop"
install -Dm644 "packaging/io.narl.proton-stream.svg" \
"$pkgdir/usr/share/icons/hicolor/scalable/apps/io.narl.proton-stream.svg"
install -Dm644 "README.md" "$pkgdir/usr/share/doc/$pkgname/README.md"
if [[ -f LICENSE ]]; then
install -Dm644 "LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
else
warning "no LICENSE file in the repo root; the package ships without one"
fi
}
+139
View File
@@ -0,0 +1,139 @@
# Packaging
Everything here is driven by two scripts. `scripts/build.sh` covers Linux and
macOS; `scripts/build.ps1` covers Windows, because the `.exe` and the `.msi`
need MSVC and WiX and neither is reachable from a Unix host.
| Artifact | Command | Host it must run on |
|---|---|---|
| `dist/proton-stream-<ver>-<triple>.tar.gz` | `scripts/build.sh tarball` | Linux or macOS |
| `dist/proton-stream_<ver>-1_amd64.deb` | `scripts/build.sh deb` | any Linux |
| `dist/proton-stream-<ver>-1.x86_64.rpm` | `scripts/build.sh rpm` | any Linux with `rpmbuild` |
| `packaging/*.pkg.tar.zst` | `cd packaging && makepkg -fi` | Arch |
| `dist/Proton Stream.app` + `.dmg` | `scripts/build.sh dmg` | macOS |
| `dist/windows/proton-stream.exe` + `.zip` | `scripts\build.ps1 -Artifacts zip` | Windows |
| `dist/proton-stream-<ver>-x64.msi` | `scripts\build.ps1 -Artifacts msi` | Windows |
`scripts/build.sh` with no arguments produces everything the host can.
## How it fits together
One cargo build feeds every Linux and macOS artifact. The binaries are compiled
once, staged into a filesystem image at `dist/stage` — rooted so that
`dist/stage/usr/bin/pstr` is exactly where the file lands on the target system —
and each packager copies out of that image. A `.deb` and an `.rpm` from the same
run are therefore the same bytes, and neither `dpkg-deb` nor `rpmbuild` needs a
Rust toolchain or libmpv headers.
`--skip-build` reuses `dist/stage`, which is what you want when iterating on a
control file or a spec.
The Arch package is the exception: `makepkg` compiles in place from the
checkout, by Arch convention and to match `../proton-drive-linux`. It ignores
`dist/stage` entirely. `scripts/build.sh arch` runs it for you and copies the
result into `dist/`, but it is not part of `all` — it recompiles, and most hosts
are not Arch.
## Runtime dependencies, and why they are what they are
| | Why |
|---|---|
| **libmpv ≥ 0.34** | The player. `pstr-player` links it directly and drives it through `stream_cb`; nothing here shells out to `mpv(1)`, so packages depend on the library, not the player binary. |
| **libsecret / Secret Service** | The share URL fragment and the custom password are secrets and live in the OS credential store, never in `shares.json`. |
| **libGL, libxkbcommon, libX11, libwayland-client** | eframe on glow, with both display backends compiled in. |
Not dependencies, deliberately: **SQLite** (rusqlite is `bundled`) and
**OpenSSL** (TLS is rustls with webpki-roots). Both are inside the binary.
Per packager that is:
- Debian — `libmpv2 | libmpv1` (trixie | bookworm), `libsecret-1-0`, `libgl1`,
`libxkbcommon0`, `libx11-6`, `libwayland-client0`.
- RPM — `mpv-libs`, `libsecret`, `mesa-libGL`, `libxkbcommon`, `libX11`,
`libwayland-client`.
- Arch — `mpv` (which carries both `libmpv.so` and its headers), `libsecret`.
The `.deb` and `.rpm` are built from binaries compiled on the packaging host, so
they inherit its glibc. A package built on Arch installs on Fedora rawhide but
not on an older distribution — build on the oldest one you intend to support, or
in that distribution's container.
`AutoReqProv: no` in the spec is for the same reason: the ELF scan would generate
soname requirements against whatever the packaging host happens to have, so the
explicit `Requires` list stands instead.
## Windows
libmpv is the whole difficulty. `libmpv2-sys` emits `cargo:rustc-link-lib=mpv`,
so the linker wants an import library named `mpv.lib` and the process wants
`libmpv-2.dll` at run time. Neither ships with mpv's Windows *player* build —
both come from the separate **mpv-dev** archive:
<https://sourceforge.net/projects/mpv-player-windows/files/libmpv/>
Unpack it and point the script at it:
```powershell
scripts\build.ps1 -MpvDev C:\mpv-dev
```
If that directory has `mpv.def` but no `mpv.lib`, the script generates the import
library with `lib.exe` (`/name:libmpv-2.dll`, so it references the DLL that
actually ships). It finds `lib.exe` on `PATH` or imports the MSVC environment via
`vswhere`, so a plain PowerShell session works.
There is no static libmpv worth shipping, so **"standalone exe" means the exe
plus `libmpv-2.dll` beside it** — that pair, plus `pstr.exe` and the README, is
what the portable `.zip` contains and what the `.msi` installs.
The MSI needs the WiX toolset; the script installs it (`dotnet tool install
--global wix`) and adds the UI extension if they are missing. It installs to
`Program Files\Proton Stream`, puts a Start Menu shortcut on the GUI, and adds
the install directory to the system `PATH` so `pstr` works from a shell — that
`PATH` entry is tied to `pstr.exe`'s component, so uninstalling removes it.
`UpgradeCode` in `proton-stream.wxs` is fixed forever: it is what makes 0.2.0
replace 0.1.0 rather than install beside it. Never regenerate it.
Signing is opt-in: `-SignCertThumbprint <thumbprint>` signs both executables and
the MSI.
## macOS
`scripts/build.sh dmg` produces `Proton Stream.app` inside a drag-to-Applications
disk image.
By default it copies libmpv and its non-system dependency closure into
`Contents/Frameworks` and rewrites every install name, because a `.dmg` that
requires the recipient to have run `brew install mpv` is not a `.dmg` anyone can
use. The bundle is then ad-hoc signed — every `install_name_tool` edit
invalidates the signature, and an unsigned-but-modified binary is killed outright
on arm64. Pass `--no-bundle-libs` to link against the host's libmpv instead.
The `.icns` is rasterized from `io.narl.proton-stream.svg` when `rsvg-convert` or
`magick` is available; without either, the bundle ships without an icon.
## Files
| | |
|---|---|
| `PKGBUILD` | Arch, in-tree `makepkg` build |
| `proton-stream.spec` | RPM, installs from `dist/stage` |
| `io.narl.proton-stream.desktop` / `.svg` | Freedesktop entry and icon |
| `macos/Info.plist.in` | `.app` bundle plist; `@VERSION@`/`@BIN@`/`@APP_ID@` substituted at build time |
| `windows/proton-stream.wxs` | WiX v4+ installer definition |
| `windows/proton-stream.ico` | MSI and shortcut icon, rasterized from the SVG |
| `windows/license.rtf` | Fallback for the installer's license dialog; the repo's own `LICENSE` is preferred when it exists |
The Debian `control` file has no template — `scripts/build.sh` writes it, because
almost every field in it is computed.
## Two things to know before releasing
- **The `[patch.crates-io]` block in `Cargo.toml` is development only.** It points
at `../proton-sdk-rs`, so both build scripts refuse to start when it is present
and that checkout is missing. A release must build against the published
crates — drop the block once proton-sdk 0.3.3 is on crates.io.
- **There is no `LICENSE` file in the repository root** even though `Cargo.toml`
declares MIT. Every packager warns and ships without the license text; the MSI
falls back to `windows/license.rtf`. Adding the file fixes all of them at once.
+12
View File
@@ -0,0 +1,12 @@
[Desktop Entry]
Type=Application
Name=Proton Stream
GenericName=Media Library
Comment=Browse and stream a Proton Drive public link
Exec=proton-stream
Icon=io.narl.proton-stream
Terminal=false
Categories=AudioVideo;Video;Player;
Keywords=proton;drive;stream;video;media;library;
StartupNotify=true
SingleMainWindow=true
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="128" height="128" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="g" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#8b6dff"/>
<stop offset="1" stop-color="#6d4aff"/>
</linearGradient>
</defs>
<rect x="8" y="8" width="112" height="112" rx="26" fill="url(#g)"/>
<!-- The blocks a revision is fetched in: each one decrypts on its own, which
is the whole reason this app can seek. -->
<rect x="26" y="30" width="14" height="14" rx="3" fill="#ffffff" opacity="0.45"/>
<rect x="26" y="50" width="14" height="14" rx="3" fill="#ffffff" opacity="0.7"/>
<rect x="26" y="70" width="14" height="14" rx="3" fill="#ffffff" opacity="0.45"/>
<rect x="26" y="90" width="14" height="14" rx="3" fill="#ffffff" opacity="0.25"/>
<!-- play -->
<path fill="#ffffff" d="M56 34l46 30-46 30z"/>
</svg>

After

Width:  |  Height:  |  Size: 923 B

+38
View File
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Templated by scripts/build.sh: @VERSION@, @BIN@, @APP_ID@. -->
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>Proton Stream</string>
<key>CFBundleDisplayName</key>
<string>Proton Stream</string>
<key>CFBundleIdentifier</key>
<string>@APP_ID@</string>
<key>CFBundleExecutable</key>
<string>@BIN@</string>
<key>CFBundleIconFile</key>
<string>proton-stream</string>
<key>CFBundleShortVersionString</key>
<string>@VERSION@</string>
<key>CFBundleVersion</key>
<string>@VERSION@</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>LSMinimumSystemVersion</key>
<string>11.0</string>
<!-- The player is a window, not an agent; it belongs in the Dock. -->
<key>LSUIElement</key>
<false/>
<!-- Windowed video, so let the display stay awake is mpv's business, but the
bundle must at least declare it is not a background-only app. -->
<key>NSHighResolutionCapable</key>
<true/>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>MIT licensed. Nils Pukropp.</string>
</dict>
</plist>
+73
View File
@@ -0,0 +1,73 @@
# RPM built from an already-staged tree, not from source.
#
# `scripts/build.sh rpm` runs cargo once, stages a filesystem image under
# dist/stage, and then calls:
#
# rpmbuild -bb packaging/proton-stream.spec \
# --define "version 0.1.0" --define "stagedir /abs/path/to/dist/stage"
#
# Staging rather than compiling inside rpmbuild is deliberate: one cargo build
# feeds the tarball, the .deb and the .rpm, and rpmbuild does not then need
# libmpv headers or a Rust toolchain on the packaging host.
%global debug_package %{nil}
# The binaries are prebuilt, quite possibly on a different distribution, so let
# the explicit Requires below stand rather than having rpm scan the ELF and
# generate soname deps against whatever this host happens to have.
AutoReqProv: no
%{!?version: %global version 0.1.0}
Name: proton-stream
Version: %{version}
Release: 1%{?dist}
Summary: Netflix-style desktop client for Proton Drive public links
License: MIT
URL: https://github.com/narrrl/proton-stream
ExclusiveArch: x86_64
# libmpv does the demuxing and decoding; libsecret is where the share fragment
# and custom password live. SQLite is bundled into the binary (rusqlite
# `bundled`) and TLS is rustls, so neither shows up here.
Requires: mpv-libs >= 0.34
Requires: libsecret
Requires: mesa-libGL
Requires: libxkbcommon
Requires: libX11
Requires: libwayland-client
Requires: hicolor-icon-theme
Recommends: gnome-keyring
Provides: pstr = %{version}-%{release}
%description
Paste a Proton Drive share URL and its password, and get a browsable,
streamable library: a poster wall, a page per title with seasons and episodes,
resume-where-you-left-off, and an embedded libmpv player. No Proton account,
no server, no download step — a file's content blocks each decrypt on their
own, so seeking costs the blocks the seek lands on.
%prep
test -n "%{?stagedir}" || (echo 'Pass --define "stagedir /abs/path" (see scripts/build.sh)' >&2; exit 1)
test -d "%{stagedir}/usr/bin"
%build
# Nothing to do: %{stagedir} already holds release binaries.
%install
cp -a "%{stagedir}"/. %{buildroot}/
%files
%{_bindir}/proton-stream
%{_bindir}/pstr
%{_datadir}/applications/io.narl.proton-stream.desktop
%{_datadir}/icons/hicolor/scalable/apps/io.narl.proton-stream.svg
# Directory entries, so these stay correct whether or not the checkout has a
# LICENSE yet (a listed directory takes its contents with it).
%{_datadir}/doc/proton-stream/
%{_datadir}/licenses/proton-stream/
%changelog
* Sun Aug 02 2026 Nils Pukropp <contact@narl.io> - 0.1.0-1
- Initial package.
+14
View File
@@ -0,0 +1,14 @@
{\rtf1\ansi\ansicpg1252\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Segoe UI;}}
\viewkind4\uc1\pard\f0\fs20
MIT License\par
\par
Copyright (c) 2026 Nils Pukropp\par
\par
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\par
\par
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\par
\par
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\par
\par
This text mirrors the license Cargo.toml declares. It is regenerated from the repository's LICENSE file by scripts/build.ps1 when one exists.\par
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

+137
View File
@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The Linux-hosted .msi definition, built by scripts/build-windows.sh with
msitools' wixl:
wixl -a x64 -o dist/proton-stream-0.1.0-x64.msi packaging/windows/proton-stream.wixl.wxs \
-D Version=0.1.0 -D BinDir=... -D MpvDll=... -D IconFile=...
Why a second file at all, next to proton-stream.wxs
---------------------------------------------------
The WiX toolset cannot build an .msi on Linux. Not "is unsupported" — it
fails outright, in WixToolset.Core's BundleValidator.GetCanonicalRelativePath,
which validates every Directory/@Name by prepending a drive letter and asking
.NET to canonicalise it:
Path.GetFullPath("C:\\" + name) // on Linux: "/cwd/C:\name"
if (fullPath.StartsWith("C:\\")) // never true off Windows
so every <Directory Name="..."> in any .wxs is rejected with WIX0389. That is
true of WiX v5 and v6; v7 additionally requires accepting the Open Source
Maintenance Fee EULA. There is no workaround in the XML, because the check
runs before anything the document can influence.
wixl (from GNOME's msitools) writes the MSI tables directly and needs no
Windows anything, but it speaks the WiX **v3** schema and implements a subset
of it — hence this file rather than a preprocessor branch inside the v4 one.
What this loses against the WiX build
-------------------------------------
The dialog UI. WixUI_InstallDir, and with it the license page and the
"choose a folder" page, is a WiX extension with no wixl equivalent, so this
.msi installs with the plain Windows Installer progress UI and always lands in
Program Files. Everything that matters after that — per-machine install,
major-upgrade replacement, Add/Remove Programs entry with the icon, the PATH
entry, clean uninstall — is authored here and identical.
Keep in sync with proton-stream.wxs
-----------------------------------
UpgradeCode and every Component Guid are shared with that file, deliberately.
They are what lets an .msi built here upgrade one built on Windows (and the
reverse) instead of the two stacking up or corrupting each other's component
reference counts. Never regenerate them; a new *payload file* gets a new
Component with a new Guid, in both files.
-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*"
Name="Proton Stream"
Language="1033"
Version="$(var.Version)"
Manufacturer="Nils Pukropp"
UpgradeCode="0a5c3818-3401-469c-a2ac-a3172cef1938">
<Package InstallerVersion="500"
Compressed="yes"
InstallScope="perMachine"
Manufacturer="Nils Pukropp"
Description="Netflix-style desktop client for Proton Drive public links" />
<!-- Replace an older install rather than sitting beside it. Scheduled after
InstallInitialize so the old product is torn down before the new files
land: the reverse order leaves the uninstall of 0.1.0 deleting files
0.2.0 just wrote. -->
<Upgrade Id="0a5c3818-3401-469c-a2ac-a3172cef1938">
<UpgradeVersion Minimum="0.0.0" IncludeMinimum="yes"
Maximum="$(var.Version)" IncludeMaximum="yes"
Property="OLDERVERSIONBEINGUPGRADED" />
<UpgradeVersion Minimum="$(var.Version)" IncludeMinimum="no"
OnlyDetect="yes"
Property="NEWERVERSIONDETECTED" />
</Upgrade>
<Condition Message="A newer version of Proton Stream is already installed.">
NOT NEWERVERSIONDETECTED
</Condition>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
<Media Id="1" Cabinet="proton_stream.cab" EmbedCab="yes" />
<Icon Id="proton-stream.ico" SourceFile="$(var.IconFile)" />
<Property Id="ARPPRODUCTICON" Value="proton-stream.ico" />
<Property Id="ARPURLINFOABOUT" Value="https://github.com/narrrl/proton-stream" />
<Property Id="ARPNOREPAIR" Value="1" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="INSTALLDIR" Name="Proton Stream">
<Component Id="AppExe" Guid="623c8cb8-b826-4d57-a054-e5be56f24c19" Win64="yes">
<File Id="AppExe" Source="$(var.BinDir)/proton-stream.exe"
Name="proton-stream.exe" KeyPath="yes">
<!-- Not advertised: an advertised shortcut needs the feature
state machine that the dialog-less install does not drive. -->
<Shortcut Id="StartMenuShortcut"
Directory="ProgramMenuFolder"
Name="Proton Stream"
Description="Browse and stream a Proton Drive public link"
WorkingDirectory="INSTALLDIR"
Icon="proton-stream.ico"
Advertise="no" />
</File>
</Component>
<!-- The CLI, and the PATH entry that makes it worth installing. Tied
to the same component so uninstalling takes the PATH edit with
it. -->
<Component Id="CliExe" Guid="6440650e-281f-4842-a75a-4cbea8be0d71" Win64="yes">
<File Id="CliExe" Source="$(var.BinDir)/pstr.exe" Name="pstr.exe" KeyPath="yes" />
<Environment Id="PstrPath" Name="PATH" Value="[INSTALLDIR]"
Part="last" Action="set" System="yes" Permanent="no" />
</Component>
<!-- libmpv does the demuxing and decoding. There is no static build
of it worth shipping, so the DLL sits beside the exe. -->
<Component Id="MpvDll" Guid="ff74fc79-78e3-4ed8-881d-f322ed6ff6b4" Win64="yes">
<File Id="MpvDll" Source="$(var.MpvDll)" Name="libmpv-2.dll" KeyPath="yes" />
</Component>
<Component Id="ReadMe" Guid="5bb65b44-f5df-423b-8dcc-a753d7aef565" Win64="yes">
<File Id="ReadMe" Source="$(var.ReadMe)" Name="README.md" KeyPath="yes" />
</Component>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder" />
</Directory>
<Feature Id="Main" Title="Proton Stream" Level="1">
<ComponentRef Id="AppExe" />
<ComponentRef Id="CliExe" />
<ComponentRef Id="MpvDll" />
<ComponentRef Id="ReadMe" />
</Feature>
</Product>
</Wix>
+82
View File
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
WiX v4/v5/v6 installer definition. Built by scripts/build.ps1:
wix build -arch x64 -ext WixToolset.UI.wixext packaging/windows/proton-stream.wxs `
-d Version=0.1.0 -d BinDir=... -d MpvDll=... -d IconFile=... -d LicenseRtf=... -d ReadMe=... `
-o dist/proton-stream-0.1.0-x64.msi
UpgradeCode is fixed forever: it is what makes 0.2.0 replace 0.1.0 instead of
installing beside it. Never regenerate it.
-->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
<Package Name="Proton Stream"
Manufacturer="Nils Pukropp"
Version="$(var.Version)"
UpgradeCode="0a5c3818-3401-469c-a2ac-a3172cef1938"
Scope="perMachine"
Compressed="yes"
Language="1033">
<SummaryInformation Description="Netflix-style desktop client for Proton Drive public links" />
<MajorUpgrade AllowSameVersionUpgrades="yes"
DowngradeErrorMessage="A newer version of Proton Stream is already installed." />
<MediaTemplate EmbedCab="yes" />
<Icon Id="AppIcon" SourceFile="$(var.IconFile)" />
<Property Id="ARPPRODUCTICON" Value="AppIcon" />
<Property Id="ARPURLINFOABOUT" Value="https://github.com/narrrl/proton-stream" />
<Property Id="ARPNOREPAIR" Value="1" />
<!-- 6432 resolves to Program Files (x64) because the build passes -arch x64. -->
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="INSTALLFOLDER" Name="Proton Stream" />
</StandardDirectory>
<StandardDirectory Id="ProgramMenuFolder" />
<!-- The Guids are written out rather than left to WiX's deterministic
generation, and they match packaging/windows/proton-stream.wixl.wxs
one for one. That is what lets the Linux-built .msi and this one
upgrade each other instead of double-counting components. A new
payload file gets a new Component and a new Guid, in both files. -->
<ComponentGroup Id="AppComponents" Directory="INSTALLFOLDER">
<Component Guid="623c8cb8-b826-4d57-a054-e5be56f24c19">
<File Id="AppExe" Source="$(var.BinDir)\proton-stream.exe" KeyPath="yes" />
<Shortcut Id="StartMenuShortcut"
Directory="ProgramMenuFolder"
Name="Proton Stream"
Description="Browse and stream a Proton Drive public link"
Icon="AppIcon"
Advertise="yes" />
</Component>
<!-- The CLI, and the PATH entry that makes it worth installing. Tied to
the same component so uninstalling takes the PATH edit with it. -->
<Component Guid="6440650e-281f-4842-a75a-4cbea8be0d71">
<File Id="CliExe" Source="$(var.BinDir)\pstr.exe" KeyPath="yes" />
<Environment Id="PstrPath" Name="PATH" Value="[INSTALLFOLDER]"
Part="last" Action="set" System="yes" Permanent="no" />
</Component>
<!-- libmpv does the demuxing and decoding. There is no static build of it
worth shipping, so the DLL sits beside the exe. -->
<Component Guid="ff74fc79-78e3-4ed8-881d-f322ed6ff6b4">
<File Id="MpvDll" Source="$(var.MpvDll)" KeyPath="yes" />
</Component>
<Component Guid="5bb65b44-f5df-423b-8dcc-a753d7aef565">
<File Id="ReadMe" Source="$(var.ReadMe)" Name="README.md" KeyPath="yes" />
</Component>
</ComponentGroup>
<Feature Id="Main" Title="Proton Stream" Level="1">
<ComponentGroupRef Id="AppComponents" />
</Feature>
<WixVariable Id="WixUILicenseRtf" Value="$(var.LicenseRtf)" />
<ui:WixUI Id="WixUI_InstallDir" InstallDirectory="INSTALLFOLDER" />
</Package>
</Wix>