- windows_d3d11.rs / windows_player_surface.rs: detect whether the
active display supports HDR and, when the "HDR output" preference is
on, create the D3D11 swap chain with an HDR-capable format; expose
hdr_display_supported() for the frontend to query.
- mpv_render.rs: drop the now-redundant format/width/height fields
from the D3D11 render target — mpv_d3d11_fbo only needs the texture,
which already carries its own format/dimensions.
- linux_player_surface.rs: track whether the current Vulkan context is
HDR-capable on a shared flag for parity with the Windows path.
- storage.rs: add read_pref_bool() to read boolean prefs (used for the
hdrEnabled toggle).
- lib.rs: register the player_hdr_supported command; tauri.conf.json
sets a transparent window background so HDR/SDR compositing doesn't
show a black flash.
- Frontend: add an "HDR output" toggle in Playback settings, auto-detect
and store display support on first run via player_hdr_supported.
- mpv_render.rs: enable "info"-level mpv logging and route messages to
the matching Rust log level with prefix/level context; use mpv's
native int64/flag property getters (get_i64_property/
get_flag_property) instead of parsing track-list strings, and log
each queried track (id/title/lang/codec/selected/external) to make
subtitle-track issues diagnosable from the app log.
- player.rs: wire up the previously-unused torrent_sibling_subtitles
scan as a new player_torrent_sibling_subtitles command — finds
subtitle files (.srt/.ass/.ssa/.vtt/.sub) bundled in the same torrent
as the playing video, matching by exact filename, by a shared
S01E02-style episode tag, or (for single-video torrents) by being
the only video in the release.
- lib.rs: register the new command, elevate "subtitles:" debug_log
lines to warn so they're visible without FLUXA_DEBUG_LOGS, and make
torrent_engine_request pub(crate) so player.rs can call it.
- usePlayer.ts: load resolved subtitles into mpv one at a time (was
all at once), which was triggering 429s from subtitle CDNs; merge in
the torrent-bundled subtitles found above.
- mpvPlayer.ts: add the player_torrent_sibling_subtitles wrapper.
- subtitles.ts: trace addon subtitle resolution via debug_log, and cap
addon results to 2 per language (OpenSubtitles returns dozens of
near-duplicates).
Downstream of the fluxa-core rquickjs "bindgen" feature removal —
prunes bindgen/cexpr/clang-sys and their transitive deps from the lock
file (avoids requiring libclang to build).
Downloads and verifies (checksum) the libVLC 3.0.23 runtime for
Windows/macOS/Linux CI jobs and copies libvlc + its plugins next to
the app binary, alongside the existing libmpv bundling — needed now
that libVLC renders embedded instead of via a system install.
- ReactPlayerOverlay: also clear the loading overlay once mpv reports
firstFramePresented, not just once frame/vo heuristics line up, so
slow-to-report streams don't get stuck showing the loader.
- ShelfRow: key list items by id+index (and give the trailing skeleton
a stable key) to stop React key collisions when a shelf has
duplicate ids.
- usePlayerNativeEvents: surface a friendlier "Source error" message
when the native player error looks like a network/stream failure
(HTTP errors, timeouts, DNS, TLS) instead of the raw mpv error text.
- libvlc_render.rs: locate/load libvlc more robustly (Windows DLL
search path, plugin path discovery), route libvlc log messages into
the app logger, lazily create the media player, and add audio
mute/track and subtitle-track control bindings.
- macos_player_surface.rs: attach the libVLC output to the native
NSView so it renders inside the app window (macOS), switching
between the Vulkan and libVLC render paths based on the active
engine.
- Update the player-engine description strings to reflect that libVLC
now renders embedded rather than in its own window.
The external-stream check ran after showPlayerLoading had already
fired, so tapping a paywall/config-link stream card briefly opened the
player loading overlay before falling back to the browser. Moved the
check to the top of handlePlay, before any player UI state is touched.
The TS wrapper never sent it, so every addon manifest fetch failed at
the FFI boundary with "missing field unknownName" before the manifest
body was even read.
Replaces the local regex-based detection heuristic and search-result
matching with calls into fluxa-core, so the same logic Android can now
also use isn't duplicated (or drifting) between platforms.
Continues the shared-core migration: addon sort/priority ordering and
disabled-addon filtering now route through fluxa-core instead of being
computed locally, alongside the broader policy delegation already
in flight across screens and hooks.
The Vulkan render+present ran inside the 16ms glib timeout on the GTK
main thread — the same thread WebKit uses for overlay input — and FIFO
presents plus vkAcquireNextImageKHR (100ms timeout) blocked it for a
large slice of every frame, which made the React player overlay laggy
compared to the OpenGL path (which just draws into GTK's own FBO).
Windows and macOS already render on a dedicated thread; Linux now does
too. The GTK loop only publishes the surface size through atomics and
keeps the GDK/Wayland surface handles.
Also:
- prefer VK_PRESENT_MODE_MAILBOX_KHR when available so presents don't
block on vsync at all
- take the player_renderer lock only around the mpv render itself, not
across acquire/present, so overlay IPC (seek, status polls) no longer
queues behind vsync waits
- on X11, create the Vulkan surface on a private XOpenDisplay connection;
GTK never calls XInitThreads, so presenting over GTK's Display from
another thread would race
- a load issued before the render thread has wired mpv's Vulkan render
context is now deferred and retried instead of failing
- nuvioSync.ts drops its in-TS import/merge policy (watchlist mapping,
progress construction, watched reconciliation, savedAt bumps, profile
and collection mapping) and now orchestrates pulls around
nuvio* core methods, including the pending savedAt-bump behavior
- animeDetection.ts deleted: dead duplicate of core anime_detection,
playback already used coreDetectAnimePlayback
- air-date refresh due-check, SIMKL scrobble stop threshold, and the
torrent readiness budget now come from core instead of local constants
Bailing out between vkAcquireNextImageKHR and present left the acquire
semaphore with a pending signal and the image unpresented; the next frame
reused the semaphore in that state. On any render_and_present failure,
wait for the device to idle, recreate the binary semaphores, and rebuild
the swapchain.
ensure_public_host checked DNS and then let reqwest re-resolve, so a
rebinding DNS entry could swap in a private IP between the check and the
request. vetted_client resolves once, validates every address, and pins
the connection to that set via resolve_to_addrs. Redirects to IP-literal
private hosts are refused as well. The shared artwork client goes away
since pinning is per-host.
The 60s tokio timeout only fires at await points, so a plugin stuck in a
synchronous loop blocked its spawn_blocking thread forever. An interrupt
handler with the same deadline preempts synchronous execution too, and a
256MB memory limit stops unbounded allocation.
settings.render_backend(_desc) and settings.player_engine(_desc) were
referenced via t() but never added to either locale file, so the
hardcoded || fallback strings were silently used instead.
Previously sync failures were silently swallowed. Record errors into
NuvioSyncMeta on both the automatic and manual sync paths, and show
a "Sync error" status line in the sync service popover when present.
Adds a context menu on the player overlay and source rows to copy a
stream's direct/magnet link or trigger an offline download, backed
by a new stream_magnet_link command and a torrent-download resolver
that reuses (or starts) the torrent server on demand. Also refactors
start_torrent_stream's health-check into ensure_healthy_torrent_base_url
for reuse, and keeps the torrent server alive across stream stops so
downloads can still be resolved, tearing it down only on app exit.