Electron + React desktop player for SecureMediaFramework — spawns smf.jar locally, browses hash-grouped collections across your library and peers, and plays or streams media over an encrypted JSDF Realm.
SMF Player is the desktop front end for SecureMediaFramework. An Electron shell starts java -jar smf.jar, talks to its loopback JSON API on 127.0.0.1:2424, and gives you a React UI for realms, libraries, peer discovery, downloads, and playback.
Under the hood, peer traffic still rides JSDF (encrypted Realm / Distributor). The player never reimplements that crypto — it orchestrates SMF.
Repo: github.com/danschirripa/SMF_Player
What you get
| Feature | How it shows up |
|---|---|
| Local + peer library browser | Merges GetLibrary + GetPeerMediaLibraries into one list |
| Collections | Groups items that share the same SHA-256 hash (local and/or multiple peers) |
| Realm join UX | Create Realm / Join Realm + invite config save/open |
| Playback | Local file:// preview when safe; otherwise RetrieveMedia into a blob URL |
| Peer video streaming | Prefers StreamMedia + ViewMediaStreamFunction (backend preview window); falls back to retrieve |
| Downloads | Main-process chunked RetrieveMedia to disk with progress + cancel |
| Packaging | Electron Builder; java/smf.jar pulled via Git LFS |
Architecture
flowchart LR
ui[React UI App.tsx] -->|preload IPC| main[Electron main.ts]
main -->|spawn| jar[java -jar smf.jar]
main -->|HTTP JSON| api["SMF /api :2424"]
jar --> api
api --> jsdf[JSDF Realm :14789]
jsdf --> peers[Peer SMF nodes]
| Layer | Path | Role |
|---|---|---|
| Renderer | smf-player-app/src/App.tsx |
Almost all product UI + API call shaping |
| Preload | smf-player-app/electron/preload.ts |
Whitelisted window.smf.* bridge |
| Main | smf-player-app/electron/main.ts |
Spawns jar, proxies smf:request, file pickers, downloads, invite files, popout preview |
| Backend jar | java/smf.jar |
Packaged SecureMediaFramework (see library page) |
Stack (from package.json): Electron 30, React 18, Vite 5, TypeScript 5.2, Tailwind 4, Radix dialog primitives.
Collections (player-side concept)
SMF’s API is still path/record oriented. The player adds a Collection layer:
A collection is every
MediaItem(local or peer) that shares an identical SHA-256hash.
UI helpers pick a “primary” member (prefer local, prefer thumbnails), show source labels like Local + Peer / Peers (N), and let you choose which member to play or download when several peers host the same content.
Talking to SMF
Renderer calls go through IPC → main → HTTP, not straight from the page:
- Default base URL:
http://localhost:2424(VITE_SMF_API_URLoverride) - Main hard-codes health/proxy expectations around
http://127.0.0.1:2424 - Bodies always include
{ function: "..." }(SMF reads JSON even on GET)
Typical functions the UI drives: CreateRealm, JoinRealm, UpdateLibrary, GetLibrary, GetPeerMediaLibraries, GetKnownPeerList, RetrieveMedia, StreamMedia, ViewMediaStreamFunction, plus remove/save paths as needed.
Playback paths
- Local small / direct preview —
window.smf.toFileUrl(path)for images, markdown, and many A/V cases. - RetrieveMedia — fetch bytes (optionally chunked in main for large/peer files) into a blob URL for in-app
<audio>/<video>/ image preview. - Peer video stream — try
StreamMedia→ViewMediaStreamFunctionso the Java preview window handles MPEG-TS from the peer’s ffmpeg pipeline. If those functions are missing, fall back to RetrieveMedia with a notice.
Main-process helpers
IPC surface includes (non-exhaustive): smf:request, smf:pick-media, smf:download-media-to-file (+ progress events), smf:cancel-download, smf:save-invite-config / smf:open-invite-config, smf:get-local-ips, smf:open-popout-preview, smf:open-parent-folder, smf:delete-file.
On startup, main validates smf.jar (rejects Git LFS pointer files and non-ZIP headers) before spawn('java', ['-jar', jarPath]). Packaged builds load the jar from Electron resources/java/smf.jar; dev mode uses ../java/smf.jar next to the app root.
Run it
Prereqs: Node 16+, Java 11+ (SMF itself builds at 21), Git LFS for the jar.
git clone https://github.com/danschirripa/SMF_Player.git
cd SMF_Player
git lfs install
git lfs pull --include="java/smf.jar"
cd smf-player-app
npm install
npm run dev
Production package:
cd smf-player-app
npm run build # verify:smf-jar → tsc → vite build → electron-builder
Rebuild the backend from the SecureMediaFramework tree and copy into java/smf.jar when you need a fresher library (see the SMF packaging notes).
Honest caveats
- Without a real
java/smf.jar(LFS pulled / rebuilt), the app cannot start the backend — main will error-box on pointer/invalid jars. - Peer video “preview” for streams is currently the SMF Swing window, not the Electron
<video>element. - HTTP API trust model is loopback-only; anyone on the machine can hit
:2424. - Collection grouping is a player UX feature; the jar still keys the local library by path.
- Early version branding (
0.0.0) — expect sharp edges and API drift between jar and UI.
Where to look
| Area | Start here |
|---|---|
| UI + collections + playback | smf-player-app/src/App.tsx |
| Jar spawn, HTTP proxy, downloads | smf-player-app/electron/main.ts |
| Preload bridge | smf-player-app/electron/preload.ts |
| Bundled API docs | java/README.md, java/openapi.yaml |
| Backend source of truth | SecureMediaFramework |
| Wire protocol / crypto | JSDF |