Skip to content

Tauri Commands: Streaming

All streaming Tauri commands are implemented in src-tauri/src/vozduxan_stream.rs. They are the bridge between the frontend audio player and the vozduxan C++ library.

Source: src-tauri/src/vozduxan_stream.rs


Command reference

torrent_prepare_stream

Starts or resumes playback of a specific file within a torrent.

// Frontend
const ready = await invoke<{ url: string }>("torrent_prepare_stream", {
  magnet: string,
  fileIdx: number,
  torrentFileB64: string | null,   // base64 .torrent file, or null
});
// ready.url = "http://127.0.0.1:<port>/stream/<token>"

Rust side: decodes torrentFileB64 from base64 if present, then calls state.prepare(app, magnet, fileIdx, torrent_bytes). See Rust Wrapper — prepare() for the full token-bucket logic and version-guard pattern.

If torrentFileB64 is provided, vozduxan starts the torrent from the binary content directly, skipping the DHT metadata exchange. This saves several seconds on first-time playback for RuTracker tracks.

Returns: { url: string } — the local HTTP stream URL.


torrent_release_stream

Releases a stream by token. Called when a track ends, is skipped, or the component unmounts.

await invoke("torrent_release_stream", { token: string });

Rust side: runs in spawn_blocking because vozduxan_stream_release joins the C++ priority thread (~100 ms). The blocking call must not happen on the async executor thread.

After the C++ call returns, the Rust side: 1. Clears whichever token bucket held this token (current_token, prefetch_token, or warm_prefetch_token). 2. Increments the eviction counter. Every 10 releases, calls vozduxan_session_evict to remove idle torrents whose TTL has expired from the libtorrent session.


torrent_dispose_preview

Releases all active tokens (current + prefetch + warm). Called by the cache purge action in Settings.

Rust side: runs in spawn_blocking. Collects all three token values (taking them from the mutexes) before entering C++, then releases them sequentially. This mutex-drop-before-C++ pattern avoids serializing unrelated Tauri commands during the ~300 ms total C++ join time (3 tokens × ~100 ms each).

After releasing, calls vozduxan_session_evict unconditionally.


torrent_prepare_cancel

Cancels an in-flight torrent_prepare_stream call.

await invoke("torrent_prepare_cancel");

Sets the prepare_cancelled AtomicBool to true. The prepare() loop in Rust polls this flag and returns an error when it's set. This is used by the player when the user switches tracks before the current track finishes buffering.


torrent_prefetch_next_track

Warms the next track's piece priority window without blocking the current track.

const result = await invoke("torrent_prefetch_next_track", {
  currentMagnet: string,
  currentFileIdx: number,
  nextMagnet: string,
  nextFileIdx: number,
  nextTorrentFileB64: string | null,
  warmOnly: boolean,   // false = track+1 bucket, true = track+2 bucket
});

currentMagnet and currentFileIdx are accepted for API compatibility but unused in the vozduxan path — vozduxan manages the active session internally and doesn't need the current track identity to schedule prefetch.

warmOnly = false → stores in prefetch_token (the real next track). warmOnly = true → stores in warm_prefetch_token (second-ahead warm-up).


vozduxan_notify_position

Forwards the current playback byte offset to the C++ priority scheduler.

await invoke("vozduxan_notify_position", {
  token: string,
  byteOffset: number,  // current playback position in bytes
});

Called on every timeupdate event from the <audio> element and on seek. The C++ priority worker uses this to slide the piece priority window forward.

This command is non-blocking on the Rust side — it calls notify_position which immediately writes to the token's state structure without any mutex contention on the C++ side.


vozduxan_stream_stats

Returns download rate and peer count for a stream token. Used by the stream status popup in the player UI.

const stats = await invoke<{ downloadRate: number; numPeers: number }>(
  "vozduxan_stream_stats",
  { token: string }
);

Calls vozduxan_stream_stats in C++ directly — no spawn_blocking needed because it only reads from lightweight statistics fields.


torrent_magnet_list_files

Lists the files inside a magnet/torrent without starting playback.

const files = await invoke<TorrentFile[]>("torrent_magnet_list_files", {
  magnet: string,
});

Used to enumerate files before the user selects a specific track to play. Calls state.list_files(magnet, None) — see Rust Wrapper.


spawn_blocking discipline

Commands that call C++ code that blocks for significant time (priority thread joins, eviction) use tokio::task::spawn_blocking. This moves the blocking call off the async executor thread pool, preventing it from starving other pending commands.

The pattern:

tokio::task::spawn_blocking(move || {
    // C++ call here (may block for ~100 ms)
    unsafe { ffi::vozduxan_stream_release(inner.ptr, token_c.as_ptr()) };
    // post-C++ cleanup
})
.await
.map_err(|e| format!("spawn_blocking error: {e}"))

Commands that only read lightweight statistics or write flags (vozduxan_notify_position, torrent_prepare_cancel) do not need spawn_blocking.