Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
126 commits
Select commit Hold shift + click to select a range
78998c1
refactor(media): move the media model out of JellyfinTypes
ethanndickson Sep 18, 2026
1d2a41b
refactor(player): put the Jellyfin facade behind PlaybackSource
ethanndickson Sep 18, 2026
371576c
refactor(platform): report video codec capabilities through an applier
ethanndickson Sep 18, 2026
11d5e29
refactor(ui): gate provider-specific controls on ProviderCapabilities
ethanndickson Sep 18, 2026
56fbaa8
refactor(settings): move the server half of settings into a Jellyfin …
ethanndickson Sep 18, 2026
bd545d3
feat(provider): add Provider, ProviderRegistry and ProviderCapabilities
ethanndickson Sep 18, 2026
0016e9b
refactor(ui): move Jellyfin-only QML under qml/providers/jellyfin
ethanndickson Sep 18, 2026
3d89e47
build: check the module seam and move source-agnostic files into core
ethanndickson Sep 18, 2026
eab71bc
refactor(app): compose the Jellyfin provider outside AppController
ethanndickson Sep 18, 2026
6ae2ffd
Merge branch 'refactor/provider-ui' into refactor/provider-seam
ethanndickson Sep 18, 2026
8f5fd05
refactor(settings): drop the account rows when the provider has no auth
ethanndickson Sep 18, 2026
e47cfbd
refactor(provider): put the catalog, search, item state and artwork b…
ethanndickson Sep 18, 2026
bd84d7c
refactor(platform): hand the platform layer hooks instead of AppContr…
ethanndickson Sep 18, 2026
0fd7c86
build: move the source-agnostic controllers and artwork into core
ethanndickson Sep 18, 2026
5c2e6df
docs: describe the provider registry and JellyfinProvider in the modu…
ethanndickson Sep 18, 2026
1ca5d88
Merge branch 'refactor/provider-catalog' into refactor/provider-seam
ethanndickson Sep 18, 2026
8532a1e
refactor(provider): finish the Provider surface and free AppControlle…
ethanndickson Sep 18, 2026
49fbe37
feat(provider): add a folder-of-files provider and choose the provide…
ethanndickson Sep 18, 2026
9fb3bc7
docs: describe the finished provider surface and the two providers
ethanndickson Sep 18, 2026
96e6911
docs: add the provider split plan
ethanndickson Sep 20, 2026
e15483b
feat(provider): add bounded script runtime and delayed QML warming
sachk Sep 20, 2026
e25719a
docs(provider): record channel gates and expose warming completion
sachk Sep 20, 2026
d1df290
feat(provider): add cancellable worker timers and deadline coverage
sachk Sep 20, 2026
85e464c
build(provider): bundle pinned Jellyfin sources and verify embedded c…
sachk Sep 20, 2026
4271892
feat(provider): persist source identity and isolate stale operations
sachk Sep 20, 2026
1b2b631
fix(provider): reject unavailable host extensions and UI imports
sachk Sep 20, 2026
6246063
fix(provider): load bundled modules through the worker registry
sachk Sep 21, 2026
256e867
fix(build): share generated provider resources across consumers
sachk Sep 21, 2026
348b4d0
feat(provider): host scoped QML actions with bounded native list models
sachk Sep 21, 2026
b4f54e2
fix(bench): include page construction and record measurement context
Sep 21, 2026
a05a0f6
feat(provider): decode listing pages into source-scoped native data o…
Sep 21, 2026
b27e705
docs(provider): prioritize real Jellyfin A/B integration and handoff
Sep 21, 2026
4d8daeb
feat(api): wire portable JavaScript Jellyfin adapter and backend sele…
sachk Sep 21, 2026
c49aea7
fix(providers): update bundled spool.jellyfin with resume endpoint fix
sachk Sep 21, 2026
33f6f75
fix(platform): version-scope qml disk cache and support SAM launch pa…
sachk Sep 21, 2026
f22d3e0
feat(benchmark): add head-to-head provider benchmark option
sachk Sep 21, 2026
adf93fb
test(benchmark): harden provider benchmark against single-step reject…
sachk Sep 21, 2026
f241566
feat(provider): add safe provider package unpacking and validation
sachk Sep 21, 2026
7c37094
feat(provider): add package installation and dynamic module scanning …
sachk Sep 21, 2026
2938289
feat(shell): add provider onboarding screen and update account picker…
sachk Sep 21, 2026
ae363fe
chore(release): bump version to 0.8.0
sachk Sep 21, 2026
fe3eabf
docs: add portable provider implementation brief
sachk Sep 21, 2026
e2e21b9
fix(provider): use self-contained puff decompressor and eliminate ext…
sachk Sep 22, 2026
558e750
fix(platform): compile DesktopPlaybackRuntime into core target for li…
sachk Sep 22, 2026
ddd287a
fix(tests): run provider-qml-cache with offscreen QPA platform in hea…
sachk Sep 22, 2026
3e5d30f
fix(android): retry Gradle packaging on transient network failures
sachk Sep 22, 2026
fbea554
feat(provider): switch jellyfin to js backend and add stream quality …
sachk Sep 22, 2026
35daf80
refactor(provider): remove legacy native jellyfin backend and streaml…
sachk Sep 22, 2026
c0e5285
refactor(provider): replace native Jellyfin with multi-account provid…
sachk Sep 22, 2026
42f560d
fix(provider): close races found while rewriting the provider tests
sachk Sep 22, 2026
8d73b66
test(provider): rewrite provider tests for the multi-account platform
sachk Sep 22, 2026
0e24095
chore(provider): pin spool.jellyfin 0.2.0 built from spool-jellyfin@6…
sachk Sep 22, 2026
31c9a9c
docs(sdk): describe provider API 0.2, packages, screens and publishing
sachk Sep 22, 2026
cbf54b2
fix(shell): issues found running the app against a real Jellyfin
sachk Sep 22, 2026
84a85da
fix(build): key the QML disk cache on the bundled providers
sachk Sep 22, 2026
dd219cf
test(provider): opt-in live Jellyfin test through registry and hub
sachk Sep 22, 2026
e17879d
chore(provider): pin spool.jellyfin 0.2.0 built from spool-jellyfin@e…
sachk Sep 22, 2026
47b06e6
chore(provider): pin the published spool.jellyfin v0.2.0 release asset
sachk Sep 22, 2026
7fc034e
test(provider): wait for accounts to finish starting before a hot ins…
sachk Sep 22, 2026
1f10989
fix(provider): list every installed provider; missing operations are …
sachk Sep 22, 2026
efb04b4
docs: one providers.md for the platform as built; AGENTS.md seam section
sachk Sep 22, 2026
29529ef
fix(bench): start the route walk after accounts restore; empty home i…
sachk Sep 22, 2026
e709ff7
fix(android): drive the system media controls through ApplicationHooks
sachk Sep 23, 2026
ebd6316
fix(app): fetch the autoplay item through the catalog
sachk Sep 23, 2026
d98c661
feat(provider): choose where providers may come from at build time
sachk Sep 23, 2026
7228015
fix(package-audit): resolve libraries by file name, and run the test
sachk Sep 23, 2026
5a18e55
fix(appimage): bundle glibc so Linux packages start on any distro
sachk Sep 23, 2026
5becbe5
test(package-audit): register the ELF audit test on Linux only
sachk Sep 23, 2026
8a29170
fix(ui): draw a text caret that can be seen on every screen
sachk Sep 23, 2026
1b81cb3
feat(search): search every server at once through the fewest accounts
sachk Sep 23, 2026
cb99f94
refactor: call the app Spool everywhere
sachk Sep 23, 2026
387ca15
fix(provider): pass every library filter to providers as one object
sachk Sep 23, 2026
00e0ba2
refactor(ui): sparser provider screens, no subtitles that repeat the …
sachk Sep 23, 2026
92a9280
feat(provider): bundle Emby and Plex, and Jellyfin 0.2.1
sachk Sep 23, 2026
16c6394
refactor: remove code nothing calls any more
sachk Sep 23, 2026
37631ec
docs(providers): search across users of a server, and the bundled pro…
sachk Sep 23, 2026
f2db2bb
docs(agents): Emby and Plex are bundled providers too
sachk Sep 23, 2026
f7d7027
fix(webos): rebuild Qt with current cursor patch
sachk Sep 26, 2026
3767b32
feat(providers): restore threaded connection speed testing
sachk Sep 26, 2026
a6d1c04
feat(details): position episode rails at viewing progress
sachk Sep 26, 2026
73e0253
feat(providers): probe media ranges and warm all packaged QML
sachk Sep 26, 2026
c49caf8
chore(providers): bundle published Plex Emby and Jellyfin releases
sachk Sep 26, 2026
044703a
fix(artwork): preserve inherited provider image ownership
sachk Sep 27, 2026
3306e33
fix(ui): scale and wrap provider update feedback
sachk Sep 27, 2026
95591f0
feat(dev): discover sibling providers for bundled-only local builds
sachk Sep 27, 2026
f8ce4e2
feat(providers): complete optional parity extensions and account flows
sachk Sep 28, 2026
4c0b01e
feat(release): ship 0.8.2 with guided provider installs
sachk Sep 28, 2026
16d16fb
test(providers): load bundled modules by resource filename
sachk Sep 28, 2026
423a37f
test(providers): compare canonical checkout paths on macOS
sachk Sep 28, 2026
5a1f48f
test(settings): await applied snapshot after account switch
sachk Sep 28, 2026
d699cd6
feat(providers): refine discovery, sign-in and contextual device cont…
sachk Sep 28, 2026
dbe277d
fix(ui): size the device dropdown to its controls
sachk Sep 28, 2026
8a07c34
chore(release): prepare Spool 0.8.3
sachk Sep 28, 2026
cf80180
test(settings): allow the first account to finish during fixture loading
sachk Sep 28, 2026
ea88b87
fix(discovery): allow declared LAN probes during provider login
sachk Sep 28, 2026
63a3499
test(providers): allow cold Windows fixtures time to start
sachk Sep 28, 2026
20481a6
perf(player): load trickplay sheets only when previewed
sachk Sep 30, 2026
503cb00
perf(ui): defer folder dialogs and avoid redundant settings work
sachk Sep 30, 2026
8b7f60f
feat(providers): compile shared forms and configure local media libra…
sachk Sep 30, 2026
8ffe1f4
fix(ui): distinguish login actions with blue button fills
sachk Sep 30, 2026
15c2307
fix(artwork): preserve image metadata across QML value boundaries
sachk Sep 30, 2026
97e3617
fix(render): respect desktop SDR mode and matching video targets
sachk Sep 30, 2026
154ee76
fix(artwork): isolate authenticated playback previews by account
sachk Sep 30, 2026
d4fec04
fix(browse): prioritize visible artwork and invalidate removed accoun…
sachk Sep 30, 2026
ac0cafe
fix(player): resume a stream cut off mid-item instead of advancing
sachk Sep 30, 2026
e06db71
test: drop restated schema declarations and revive the pinned-archive…
sachk Sep 30, 2026
ece9642
feat(providers): clearer sign-in codes and a roomier provider list
sachk Sep 30, 2026
d4dd0d3
feat(browse): offer HDR where a server can filter by it
sachk Sep 30, 2026
465a2c2
chore(providers): bundle Jellyfin 0.2.7, Emby 0.1.3 and Plex 0.1.4
sachk Sep 30, 2026
94726fd
fix(webos): forward mpv_render_context_get_info through the lazy libm…
sachk Sep 30, 2026
79d0daf
feat(player): show external subtitle files during direct play
sachk Sep 30, 2026
fe4ddf2
feat(ui): rearrange libraries and improve sign-in and search
sachk Sep 30, 2026
66f25ec
chore(release): bundle released providers for Spool 0.8.4
sachk Sep 30, 2026
2878b4e
fix(ui): keep server badges within media cards
sachk Sep 30, 2026
9e6ee87
test(providers): compare canonical local folder identity on macOS
sachk Sep 30, 2026
4cf4fb9
fix(artwork): gate buffered grid requests by model row
sachk Sep 30, 2026
07ef272
test(runtime): isolate disk caches for mutable provider fixtures
sachk Sep 30, 2026
12a77e6
fix(runtime): measure Windows script budget by worker CPU time
sachk Sep 30, 2026
84c469c
test(collections): keep concurrent removal fixture pending
sachk Sep 30, 2026
7e04b33
chore(release): prepare Spool 0.8.8
sachk Sep 30, 2026
958bb53
test(settings): control bootstrap and write response barriers
sachk Sep 30, 2026
e2d8049
chore(release): prepare Spool 0.8.9
sachk Sep 30, 2026
58a5ac1
test(artwork): report preview request failures without credentials
sachk Sep 30, 2026
3d87a2c
fix(artwork): preserve numeric account scopes in preview URLs
sachk Sep 30, 2026
4fbd3a1
fix(release): ship FFmpeg 9.0.2 with scoped upstream VEX evidence
sachk Oct 1, 2026
2bd7c72
perf(trickplay): retain sprite textures and prefetch directional prev…
sachk Oct 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Bug report
description: Report a reproducible Spool for Jellyfin defect
description: Report a reproducible Spool defect
title: "[Bug]: "
labels: [bug]
body:
Expand Down
58 changes: 29 additions & 29 deletions .github/workflows/build-artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,10 @@ jobs:


- name: Lint compiled QML
run: nix develop .#native -c cmake --build build/linux-release/app --target jellyfin-native_qmllint_strict
run: nix develop .#native -c cmake --build build/linux-release/app --target spool_qmllint_strict

- name: Launch-test host app UI
run: nix develop .#native -c bash tools/launch-native-app.sh build/linux-release/install/bin/jellyfin-native
run: nix develop .#native -c bash tools/launch-native-app.sh build/linux-release/install/bin/spool

# A page switch is meant to cost one frame. That is a number, so it is
# measured every commit rather than noticed once it has got bad.
Expand All @@ -327,15 +327,15 @@ jobs:
SPOOL_BENCH=routes \
SPOOL_BENCH_OUT="$PWD/dist/render-benchmark/warm.json" \
SPOOL_BENCH_ITERATIONS=4 \
bash tools/launch-native-app.sh build/linux-release/install/bin/jellyfin-native
bash tools/launch-native-app.sh build/linux-release/install/bin/spool
# The same walk with every page dropped between switches: what a
# memory-starved device pays, tracked but not gated.
nix develop .#native -c env \
SPOOL_BENCH=routes \
SPOOL_BENCH_COLD=1 \
SPOOL_BENCH_OUT="$PWD/dist/render-benchmark/cold.json" \
SPOOL_BENCH_ITERATIONS=4 \
bash tools/launch-native-app.sh build/linux-release/install/bin/jellyfin-native
bash tools/launch-native-app.sh build/linux-release/install/bin/spool

- name: Report render latency
run: |
Expand Down Expand Up @@ -394,17 +394,17 @@ jobs:
echo 'error: extracted AppImage contains qmltypes metadata' >&2
exit 1
fi
elf_args=(elf "$extracted" --root usr/bin/jellyfin-native)
test ! -f "$extracted/usr/bin/secret-tool" || elf_args+=(--root usr/bin/secret-tool)
elf_args=(elf "$extracted" --root usr/bin/spool)
test ! -f "$extracted/usr/libexec/secret-tool" || elf_args+=(--root usr/libexec/secret-tool)
while IFS= read -r elf; do elf_args+=(--root "${elf#"$extracted/"}"); done \
< <(find "$extracted/usr/lib" -type f -name 'libmpv.so.*' | sort)
for root in usr/plugins usr/qml; do
test ! -d "$extracted/$root" || while IFS= read -r elf; do
elf_args+=(--root "${elf#"$extracted/"}")
done < <(find "$extracted/$root" -type f -name '*.so*' | sort)
done
for soname in ld-linux-x86-64.so.2 libc.so.6 libdl.so.2 libm.so.6 libmvec.so.1 \
libpthread.so.0 libresolv.so.2 librt.so.1 libutil.so.1 libGLESv2.so.2 libgbm.so.1 libglapi.so.0
# glibc is bundled; only these come from the host.
for soname in libGLESv2.so.2 libgbm.so.1 libglapi.so.0
do
elf_args+=(--allow-system "$soname")
done
Expand All @@ -420,7 +420,7 @@ jobs:

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.0
with:
name: spool-for-jellyfin-linux
name: spool-linux
path: |
dist/*.AppImage
dist/*-linux-x86_64.tar.zst
Expand Down Expand Up @@ -577,7 +577,7 @@ jobs:
--parallel "$(sysctl -n hw.ncpu)" --output-on-failure

- name: Lint compiled QML
run: nix develop .#native --no-write-lock-file -c cmake --build build/macos/app --target jellyfin-native_qmllint_strict
run: nix develop .#native --no-write-lock-file -c cmake --build build/macos/app --target spool_qmllint_strict

- name: Load bundled Vulkan runtime
run: |
Expand Down Expand Up @@ -613,7 +613,7 @@ jobs:

- name: Launch-test macOS app UI
env:
JELLYFIN_LAUNCH_TEST_QPA_PLATFORM: cocoa
SPOOL_LAUNCH_TEST_QPA_PLATFORM: cocoa
run: nix develop .#native --no-write-lock-file -c bash tools/launch-native-app.sh build/macos/install/Spool.app

- name: Sign macOS application
Expand Down Expand Up @@ -650,7 +650,7 @@ jobs:
if [[ '${{ inputs.enable_macos_signing }}' == true ]]; then
codesign --verify --strict --deep --verbose=2 "$app"
fi
JELLYFIN_LAUNCH_TEST_QPA_PLATFORM=cocoa \
SPOOL_LAUNCH_TEST_QPA_PLATFORM=cocoa \
bash tools/launch-native-app.sh "$app"
bash tools/detach-dmg.sh "$mountpoint"
trap - EXIT
Expand All @@ -670,7 +670,7 @@ jobs:

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.0
with:
name: spool-for-jellyfin-macos-dmg-${{ matrix.arch }}
name: spool-macos-dmg-${{ matrix.arch }}
path: |
dist/*.dmg
dist/*.dmg.app.tar.gz
Expand Down Expand Up @@ -798,7 +798,7 @@ jobs:
test -n "$data_tar"
tar -tf "$data_tar" | tee "$work/data-files.txt" >/dev/null
grep -Eq '(^|/)appinfo\.json$' "$work/data-files.txt"
grep -Eq '(^|/)bin/jellyfin-native$' "$work/data-files.txt"
grep -Eq '(^|/)bin/spool$' "$work/data-files.txt"

mkdir "$work/data"
tar -xf "$data_tar" -C "$work/data"
Expand All @@ -824,12 +824,12 @@ jobs:
appinfo = json.load(handle)

assert appinfo["id"] == "com.sachk.spool", appinfo.get("id")
assert appinfo["main"] == "bin/jellyfin-native", appinfo.get("main")
assert appinfo["main"] == "bin/spool", appinfo.get("main")
assert re.fullmatch(r"\d+\.\d+\.\d+", appinfo["version"]), appinfo.get("version")
print(f"Validated {appinfo['id']} {appinfo['version']} IPK")
PY

launcher="$(find "$work/data" -path '*/bin/jellyfin-native' -type f -print -quit)"
launcher="$(find "$work/data" -path '*/bin/spool' -type f -print -quit)"
test -n "$launcher"
test -x "$launcher"
python3 - "$launcher" <<'PY'
Expand All @@ -843,9 +843,9 @@ jobs:
header = handle.read(20)

if header[:4] != b"\x7fELF":
binary = binary.with_name("jellyfin-native.real")
assert binary.is_file(), "launcher is not ELF and jellyfin-native.real is missing"
assert os.access(binary, os.X_OK), "jellyfin-native.real is not executable"
binary = binary.with_name("spool.real")
assert binary.is_file(), "launcher is not ELF and spool.real is missing"
assert os.access(binary, os.X_OK), "spool.real is not executable"
with binary.open("rb") as handle:
header = handle.read(20)

Expand All @@ -860,7 +860,7 @@ jobs:

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.0
with:
name: spool-for-jellyfin-webos-ipk
name: spool-webos-ipk
path: build/*.ipk
if-no-files-found: error
retention-days: ${{ inputs.release && 1 || 7 }}
Expand Down Expand Up @@ -1028,15 +1028,15 @@ jobs:
if: ${{ failure() && matrix.abi == 'x86_64' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.0
with:
name: spool-for-jellyfin-android-launch-test
name: spool-android-launch-test
path: |
build/android/launch-test
build/android/emulator.log
retention-days: 1

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.0
with:
name: spool-for-jellyfin-android-apks-${{ matrix.abi }}
name: spool-android-apks-${{ matrix.abi }}
path: dist/android/*.apk
if-no-files-found: error
retention-days: ${{ inputs.release && 1 || 7 }}
Expand Down Expand Up @@ -1083,12 +1083,12 @@ jobs:
# will wait for and one they will not.
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: spool-for-jellyfin-android-apks-arm64-v8a
name: spool-android-apks-arm64-v8a
path: dist/android

- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: spool-for-jellyfin-android-apks-armeabi-v7a
name: spool-android-apks-armeabi-v7a
path: dist/android

- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
Expand Down Expand Up @@ -1152,7 +1152,7 @@ jobs:

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.0
with:
name: spool-for-jellyfin-android-apk-universal
name: spool-android-apk-universal
path: dist/android/spool-universal.apk
if-no-files-found: error
retention-days: ${{ inputs.release && 1 || 7 }}
Expand All @@ -1166,8 +1166,8 @@ jobs:
env:
QT_VERSION: ${{ needs.toolchain.outputs.qt_version }}
QT_ARCH: win64_${{ needs.toolchain.outputs.qt_windows_kit }}
JELLYFIN_QT_ROOT: C:\Qt\${{ needs.toolchain.outputs.qt_version }}\${{ needs.toolchain.outputs.qt_windows_kit }}
JELLYFIN_QCORO_ROOT: C:\Qt\${{ needs.toolchain.outputs.qcoro_windows_prefix }}
SPOOL_QT_ROOT: C:\Qt\${{ needs.toolchain.outputs.qt_version }}\${{ needs.toolchain.outputs.qt_windows_kit }}
SPOOL_QCORO_ROOT: C:\Qt\${{ needs.toolchain.outputs.qcoro_windows_prefix }}

steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2
Expand Down Expand Up @@ -1265,7 +1265,7 @@ jobs:
- name: Upload portable executable
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.0
with:
name: spool-for-jellyfin-windows-x64-portable
name: spool-windows-x64-portable
path: |
dist/*-Portable.exe
if-no-files-found: error
Expand All @@ -1274,7 +1274,7 @@ jobs:
- name: Upload installer executable
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.0
with:
name: spool-for-jellyfin-windows-x64-installer
name: spool-windows-x64-installer
path: |
dist/*-Setup.exe
if-no-files-found: error
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- name: Upload corresponding source
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.0
with:
name: spool-for-jellyfin-corresponding-source
name: spool-corresponding-source
path: release-source/*
retention-days: 1

Expand Down Expand Up @@ -280,7 +280,7 @@ jobs:
fi
gh release download "$TAG" --repo "$GITHUB_REPOSITORY" \
--pattern SHA256SUMS.txt --dir "$RUNNER_TEMP"
bundle="Spool-for-Jellyfin-$version-linux-x86_64.tar.zst"
bundle="Spool-$version-linux-x86_64.tar.zst"
checksum="$(awk -v want="$bundle" \
'{ sub(/^\*/, "", $2); if ($2 == want) print $1 }' \
"$RUNNER_TEMP/SHA256SUMS.txt")"
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/rescan-release-sboms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ jobs:
mkdir sboms
tag="$(gh release list --exclude-drafts --limit 1 --json tagName --jq '.[0].tagName')"
test -n "$tag"
gh release download "$tag" --pattern '*.cdx.json' --dir sboms
test -n "$(find sboms -type f -name '*.cdx.json' -print -quit)"
gh release download "$tag" --pattern '*.syft.json' --pattern 'ffmpeg-vex.json' --dir sboms
test -n "$(find sboms -type f -name '*.syft.json' -print -quit)"
- name: Enforce vulnerability policy
run: |
set -euo pipefail
for sbom in sboms/*.cdx.json; do
"$RUNNER_TEMP/release-tools/grype" "sbom:$sbom" --fail-on high --only-fixed
for sbom in sboms/*.syft.json; do
"$RUNNER_TEMP/release-tools/grype" "sbom:$sbom" --vex sboms/ffmpeg-vex.json --fail-on high --only-fixed
done
4 changes: 2 additions & 2 deletions .qmlls.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[General]
; QML files live at qml/ and qml/*/, so include both relative depths.
buildDir=../build/linux-dev/app:../../build/linux-dev/app
; QML files live at qml/, qml/*/ and qml/providers/*/, so include every relative depth.
buildDir=../build/linux-dev/app:../../build/linux-dev/app:../../../build/linux-dev/app
no-cmake-calls=true
39 changes: 26 additions & 13 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Project

- Spool for Jellyfin client for webOS and desktop.
- Spool: a media player for webOS, desktop and Android.
- Prefer a smaller, faster, easier-to-extend codebase over compatibility scaffolding or speculative abstractions.
- The app is prerelease software: bump/reset caches on schema changes instead of adding migrations or fallback readers.
- `mpv/` is a submodule. Commit mpv changes inside `mpv/`, then commit its pointer here.
Expand All @@ -29,18 +29,31 @@

## Module Seam

The goal is one core that several backends can sit on (spool-jellyfin,
spool-plex, spool-stremio). `CMakeLists.txt` groups sources into
`SPOOL_PLATFORM_SOURCES`, `SPOOL_PLAYER_SOURCES`, `SPOOL_SHELL_SOURCES` and
`SPOOL_JELLYFIN_SOURCES` to mark where that cut goes. They still build as one
library; the grouping exists so the split stays mechanical.
The app knows no media backend. Every source is a provider package (JS logic
and QML screens) run by `src/provider/`; `docs/providers.md` describes the
pieces and `sdk/` is the provider contract (API 0.2). Jellyfin, Emby and Plex live in
spool-player/spool-jellyfin, spool-emby and spool-plex and are bundled from
the pins in `providers/lock.json`.

- Do not add a `src/api/` or `src/discovery/` include to the platform, player
or shell groups. Four such dependencies already exist and are the work a
split has to undo first: `PlayerController`, `PlaybackReporter`,
`PlayQueueController` and `SettingsController` each take a
`JellyfinApiFacade`, and `configurePlatformPlaybackCapabilities()` is
handed one.
- Core is everything under `src/` except `src/providers/` (native providers;
only `LocalProvider` today) and `src/main.cpp`, the composition root. Core
never includes `src/providers/`; `tools/check-module-seam.sh` is the
`module-seam` ctest.
- The app sees one `Provider`, `SourceHub`, which routes to every enabled
account. IDs leaving it are scoped (`<8 hex>:<id>`) and stay opaque to
routes, caches and QML. Pages reach media through `Catalog`,
`SearchSource`, `UserItemStateSink`, `ArtworkSource`, `PlaybackSource` and
`StreamQualityControl`, never a provider type.
- Shared QML gates optional controls on the `ProviderCapabilities` singleton
(search, userItemState, playbackReporting, segments, groupPlayback,
remoteControl, streamQuality, trickplay): what the enabled accounts can do
between them. Provider-specific UI is the provider's own QML, mounted by
`shell/ProviderSurface` with a `ProviderUiContext`; item-menu entries come
from the manifest's `actions`.
- Group playback and remote control are generic (`GroupPlaybackController`,
`AppControllerRemote.cpp`); providers translate their protocol into
`group` and `remote` events. Do not touch `src/player` or
`qml/pages/Player*` for provider work beyond renames.
- `qml/primitives` and `qml/theme` reach exactly two singletons, `Art.url` and
`Settings.uiScalePercent`. Keep it that way; page- and shell-level QML is
where backend-shaped data belongs.
Expand All @@ -63,7 +76,7 @@ library; the grouping exists so the split stays mechanical.
- Build without launching with `nix run .#build`.
- Run the test suite the way CI does with `nix run .#tests` (release build, then the same ctest invocation and exclusions as the workflow).
- Leave interactive UI testing to the user. Do not drive their desktop with xdotool/xdgtool or similar input automation, or launch visible smoke tests unless explicitly requested. Use builds and isolated/offscreen checks for verification.
- Use `nix develop .#native -c ...` for targeted development commands (e.g. `cmake --preset linux-dev`, then `cmake --build build/linux-dev/app --target jellyfin-native`).
- Use `nix develop .#native -c ...` for targeted development commands (e.g. `cmake --preset linux-dev`, then `cmake --build build/linux-dev/app --target spool`).
- The image-diagnostics equivalents remain `nix run .#image-debug-build` followed by `nix run .#image-debug`.
- Batch coherent edits, then run one build and one `qmlformat`/`clang-format` invocation over all touched files; don't build or format file-by-file.

Expand Down
Loading
Loading