# Platform-Specific Player Backends ## Player Events System **Location**: `src-tauri/src/player/events.rs` The player uses a push-based event system to notify the frontend of state changes: ```rust pub enum PlayerStatusEvent { /// Playback position updated (emitted periodically during playback) PositionUpdate { position: f64, duration: f64 }, /// Player state changed StateChanged { state: String, media_id: Option }, /// Media has finished loading and is ready to play MediaLoaded { duration: f64 }, /// Playback has ended naturally PlaybackEnded, /// Buffering state changed Buffering { percent: u8 }, /// An error occurred during playback Error { message: String, recoverable: bool }, /// Volume changed VolumeChanged { volume: f32, muted: bool }, /// Sleep timer state changed SleepTimerChanged { mode: SleepTimerMode, remaining_seconds: u32, }, /// Show next episode popup with countdown ShowNextEpisodePopup { current_episode: MediaItem, next_episode: MediaItem, countdown_seconds: u32, auto_advance: bool, }, /// Countdown tick (emitted every second during autoplay countdown) CountdownTick { remaining_seconds: u32 }, /// Queue changed (items added, removed, reordered, or playback mode changed) QueueChanged { items: Vec, current_index: Option, shuffle: bool, repeat: RepeatMode, has_next: bool, has_previous: bool, }, /// Media session changed (activity context changed: Audio/Movie/TvShow/Idle) SessionChanged { session: MediaSessionType }, } ``` Events are emitted via Tauri's event system: ```mermaid flowchart LR subgraph Backend["Player Backend"] MPV["MPV/ExoPlayer"] end subgraph EventSystem["Event System"] Emitter["TauriEventEmitter
emit()"] Bus["Tauri Event Bus
'player-event'"] end subgraph Frontend["Frontend"] Listener["playerEvents.ts
Frontend Listener"] Store["Player Store Update
(position, state, etc)"] end MPV --> Emitter --> Bus --> Listener --> Store ``` **Frontend Listener** (`src/lib/services/playerEvents.ts`): - Listens for `player-event` Tauri events - Updates player/queue stores based on event type - Auto-advances to next track on `PlaybackEnded` - On `StateChanged` events, calls `invoke("player_get_queue")` to update `appState.hasNext`/`hasPrevious` -- this enables MiniPlayer skip button state **Important**: The command is `player_get_queue` (returns `QueueStatus` with `hasNext`/`hasPrevious`). There is no `player_get_queue_status` command. ## HTML5 Video Adapter (webview-rendered video) **Location**: `src/lib/player/html5Adapter.ts`, `src/lib/player/index.ts`, report commands in `src-tauri/src/commands/player/timers.rs` Video on desktop (Linux WebKitGTK) — and, per current interim behavior, Android — is rendered by an HTML5 `