ferret/crates/player-core/src/lib.rs

46 lines
1.8 KiB
Rust
Executable File

//! Headless video player engine.
//!
//! `PlayerEngine` owns a libmpv instance, runs it on a dedicated thread, and
//! exposes a request/response API to the UI via two channels:
//!
//! - `Cmd` channel (UI → engine) : commands like LoadFile, Seek, SetVolume
//! - `Event` channel (engine → UI): state updates like TimePos, EndReached
//!
//! The engine thread does ONE thing: drain libmpv's event queue and translate
//! raw `mpv_event`s into typed `Event`s on the channel. Commands from the UI
//! are applied synchronously on the engine thread (libmpv is thread-safe but
//! we serialize to keep the model simple and the call stack debuggable).
//!
//! ## Accuracy-first error policy
//!
//! The engine configures libmpv for visual accuracy over continuity:
//! - `hr-seek=yes` : exact seeks, not keyframe-snapped
//! - `vd-lavc-fast=no` : full decode, no shortcuts
//! - `framedrop=vo` : only drop frames at the VO if behind, never on decode
//! - `video-sync=display-resample` : resample audio to match display
//!
//! This matches mpv's defaults; we set them explicitly to prevent user
//! config (~/.config/mpv/mpv.conf) from sneaking in different behavior.
#![allow(dead_code)]
pub mod cmd;
pub mod engine;
pub mod event;
pub mod state;
pub mod error;
pub mod options;
pub use cmd::{
Cmd, LoadOptions, LoopMode, MarkerExportFormat, RandomMode,
MAGIC_FILE_DIALOG, MAGIC_FOLDER_DIALOG, MAGIC_PLAYLIST_DIALOG,
MAGIC_SAVE_DIALOG_TXT, MAGIC_SAVE_DIALOG_JSON,
MAGIC_SUBTITLE_DIALOG, MAGIC_IMPORT_MARKERS_DIALOG,
MAGIC_EXPORT_VIDEO_DIALOG,
};
pub use engine::PlayerEngine;
pub use event::{EngineEvent, EngineEventSender};
pub use state::{AudioTrack, PlaybackState, PlayerStatus, Track};
pub use options::EngineOptions;
pub use error::{CoreError, CoreResult};