torttube/MILESTONES.md
Kayos 4aa6cc658d M6 — cross-compile aarch64-musl + addon.zip + install docs
scripts/build-addon-zip.sh runs the whole pipeline from a host with ssh
lucy:
- one-shot messense/rust-musl-cross:aarch64-musl container builds the
  sidecar static (6.2MB stripped). Doesn't mutate crafting-table.
- fetches yt-dlp_linux_aarch64 from the upstream release page so Tier 2
  + Tier 3 work on the Pi (LibreELEC ships no Python YouTube tools)
- packages everything into plugin.video.torttube.zip with the Kodi
  install-from-zip layout
- drops the zip at /mnt/user/downloads/torttube/ on Lucy SMB

Cargo.toml swaps rustypipe to default-features=false +
rustls-tls-webpki-roots so the cross-compile is openssl-free.

addon.xml drops the unused script.module.requests requirement — main.py
only uses Python stdlib + Kodi's own modules.

docs/install.md walks the Kodi UI flow + a smoke curl that fires
Player.Open via JSON-RPC. Pi-side smoke is pending Cobb's install on
192.168.0.158.
2026-05-23 08:54:46 -07:00

77 lines
3.7 KiB
Markdown

# torttube milestones
## M0 — Scaffold [current]
- [x] `Sulkta-Coop/torttube` on LAN Gitea
- [x] Layout: `addon/` (Python) + `sidecar/` (Rust workspace)
- [x] GPL-3.0 license headers
- [ ] crafting-table build target produces a static aarch64 sidecar binary
## M1 — sidecar resolve (three-tier)
- [ ] reads `{"op":"resolve","id":"<yt-id>"}` from stdin
- [ ] **Tier 1:** rustypipe → `{"streams":[…],"title":"…","duration_s":N,"source":"rustypipe"}`
- [ ] **Tier 2:** on Tier-1 failure, shell out to `yt-dlp -j <url>` → same JSON shape with `"source":"yt-dlp"`
- [ ] **Tier 3:** new op `{"op":"rip","id":"<yt-id>","dest":"/storage/.kodi/temp/torttube/<id>.<ext>"}` invoked by addon on Tier-1+2 stream failures or 403-mid-play; yt-dlp downloads file, sidecar returns local path
- [ ] typed errors for age-restricted / region-restricted / private (not panics)
- [ ] sig decoding verified against a known-good video
- [ ] DASH manifest URL or per-itag direct stream URL — whichever inputstream.adaptive prefers
## M2 — SponsorBlock
- [ ] `{"op":"sponsorblock","id":"<yt-id>"}` → segments array
- [ ] SHA-256 prefix lookup (privacy-preserving — only send first 4 hex chars)
- [ ] category filter honoured from addon settings (skip / mute / show only)
- [ ] cache per-session
## M3 — Kodi addon plays one video
- [ ] `addon.xml` + `main.py` register as video plugin
- [x] `main.py` handles `plugin://plugin.video.torttube/?action=play&id=<id>` and
`?url=<full-url>` — wired so JSON-RPC `Player.Open` from any LAN client
(phone, HA, curl) triggers resolve + play. See docs/remote-control.md.
- [ ] cross-compile sidecar for aarch64, drop into `bin/` of addon dir
- [ ] install + smoke on LibreELEC RPi at `192.168.0.158`
- [ ] (later) hardcoded list of 3 test videos for in-Kodi navigation
## M4 — search + channel browse
- [ ] search box → sidecar `{"op":"search","q":"…"}` → results
- [ ] channel browse → `{"op":"channel","id":"…"}`
- [ ] playlist browse → `{"op":"playlist","id":"…"}`
- [ ] result thumbnails + duration + uploader
## M5 — SponsorBlock skipping
- [ ] background thread on `Player()` polls position
- [ ] when position enters a skip segment → `xbmc.Player().seekTime(end)`
- [ ] toast on skip + skip-counter in settings
- [ ] category toggles in `settings.xml`
## M6 — install + cross-compile [PARTIAL]
- [x] cross-compile sidecar for aarch64-musl static via throwaway
`messense/rust-musl-cross:aarch64-musl` container. 6.2MB stripped
static binary. Builds clean from `scripts/build-addon-zip.sh`.
- [x] bundle yt-dlp's `yt-dlp_linux_aarch64` release binary for Tier 2/3
- [x] zip layout matches Kodi "install from zip" expectations
- [x] addon.zip dropped at `smb://lucy/downloads/torttube/` for Pi-side install
- [x] install + smoke recipe documented at `docs/install.md`
- [ ] **install on the actual Pi** + verify the JSON-RPC `Player.Open`
smoke against `192.168.0.158` — needs Cobb to either install via
Kodi UI or grant SSH to drop the zip directly
- [ ] armv7 build for older Pis (deferred — Cobb's TVs are all aarch64-capable)
## Upstream PR work (parallel lane — every bug evaluated for "fix it upstream?")
This isn't a separate milestone, it's a posture. Every sidecar bug we
diagnose: ask "is this rustypipe / NPE / yt-dlp's bug?" — if yes, fix lands
upstream too. Log every filed PR in [docs/upstream.md](docs/upstream.md).
Opening shortlist:
- rustypipe PR #77 — review + help land
- NPE #1357 (JDoc) — smallest credible PR, opens the relationship
- NPE #1444 (typed errors) — clean signal/contract change
- NPE #1360 (refactor link handlers, "help wanted")
- rustypipe ↔ NPE port — anything one project has that the other lacks