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-256 hash.

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_URL override)
  • 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

  1. Local small / direct preview — window.smf.toFileUrl(path) for images, markdown, and many A/V cases.
  2. RetrieveMedia — fetch bytes (optionally chunked in main for large/peer files) into a blob URL for in-app <audio> / <video> / image preview.
  3. Peer video stream — try StreamMedia → ViewMediaStreamFunction so 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