pub mod types; pub mod online; pub mod offline; pub mod hybrid; pub use types::*; pub use online::{OnlineRepository, JRayActor}; pub use offline::OfflineRepository; pub use hybrid::HybridRepository; use async_trait::async_trait; /// Repository trait for media access (online, offline, or hybrid) /// /// @req: UR-002 - Access media when online or offline /// @req: UR-007 - Navigate media in library /// @req: UR-008 - Search media across libraries /// @req: IR-010 - Jellyfin API client for library browsing /// @req: DR-012 - Local database for media metadata cache /// @req: DR-013 - Repository pattern for online/offline data access #[async_trait] pub trait MediaRepository: Send + Sync { /// Get all libraries /// /// @req: UR-007 - Navigate media in library /// @req: JA-003 - Get user library views async fn get_libraries(&self) -> Result, RepoError>; /// Get items in a library or parent /// /// @req: UR-007 - Navigate media in library /// @req: JA-004 - Get library items (paginated) async fn get_items( &self, parent_id: &str, options: Option, ) -> Result; /// Get a single item by ID /// /// @req: UR-007 - Navigate media in library /// @req: JA-005 - Get item details and metadata async fn get_item(&self, item_id: &str) -> Result; /// Get latest items in a library /// /// @req: UR-024 - View recently added content on server /// @req: JA-016 - Get recently added items async fn get_latest_items( &self, parent_id: &str, limit: Option, ) -> Result, RepoError>; /// Get resume items (continue watching/listening) /// /// @req: UR-019 - Resume playback from where you left off /// @req: UR-023 - View "Next Up" / Continue Watching on home screen /// @req: JA-015 - Get "Continue Watching" items async fn get_resume_items( &self, parent_id: Option<&str>, limit: Option, ) -> Result, RepoError>; /// Get next up episodes /// /// @req: UR-023 - View "Next Up" / Continue Watching; auto-play next episode /// @req: JA-014 - Get "Next Up" items async fn get_next_up_episodes( &self, series_id: Option<&str>, limit: Option, ) -> Result, RepoError>; /// Get recently played audio async fn get_recently_played_audio( &self, limit: Option, ) -> Result, RepoError>; /// Get albums the user has played, but not recently ("rediscover" / haven't /// listened to in a while). Returns albums sorted by least-recently played /// first, optionally restricted to a parent library. async fn get_rediscover_albums( &self, parent_id: Option<&str>, limit: Option, ) -> Result, RepoError>; /// Get resume movies async fn get_resume_movies(&self, limit: Option) -> Result, RepoError>; /// Get genres async fn get_genres(&self, parent_id: Option<&str>) -> Result, RepoError>; /// Search for items /// /// @req: UR-008 - Search media across libraries /// @req: JA-006 - Search across libraries async fn search( &self, query: &str, options: Option, ) -> Result; /// Get playback info for streaming /// /// @req: UR-003 - Play videos /// @req: UR-004 - Play audio uninterrupted /// @req: JA-007 - Get playback info and stream URL async fn get_playback_info(&self, item_id: &str) -> Result; /// Get audio stream URL for a track /// /// @req: UR-004 - Play audio uninterrupted /// @req: JA-007 - Get playback info and stream URL async fn get_audio_stream_url(&self, item_id: &str) -> Result; /// Get Live TV channels (broadcast / IPTV) for browsing. async fn get_live_tv_channels(&self) -> Result, RepoError>; /// Get the root list of plugin "Channels" (Jellyfin Channels feature). /// Drill-down into a channel reuses `get_items(channel_id, ...)`. async fn get_channels(&self) -> Result; /// Open a live stream (Live TV channel or live channel item) for playback. /// /// Returns the server transcoding URL plus identifiers needed to manage the /// stream. Required before a live channel can be played over HLS. async fn open_live_stream(&self, item_id: &str) -> Result; /// Report playback start /// /// @req: UR-025 - Sync watch history and progress back to Jellyfin /// @req: JA-010 - Report playback start async fn report_playback_start( &self, item_id: &str, position_ticks: i64, ) -> Result<(), RepoError>; /// Report playback progress /// /// @req: UR-025 - Sync watch history and progress back to Jellyfin /// @req: JA-011 - Report playback progress (periodic) async fn report_playback_progress( &self, item_id: &str, position_ticks: i64, ) -> Result<(), RepoError>; /// Report playback stopped /// /// @req: UR-025 - Sync watch history and progress back to Jellyfin /// @req: JA-012 - Report playback stopped async fn report_playback_stopped( &self, item_id: &str, position_ticks: i64, ) -> Result<(), RepoError>; /// Get image URL (synchronous - just constructs URL) fn get_image_url( &self, item_id: &str, image_type: ImageType, options: Option, ) -> String; /// Get subtitle URL (synchronous - just constructs URL) /// Called by frontend via Tauri invoke (getSubtitleUrl in VideoPlayer.svelte) #[allow(dead_code)] fn get_subtitle_url( &self, item_id: &str, media_source_id: &str, stream_index: i32, format: &str, ) -> String; /// Get video download URL (synchronous - just constructs URL) /// Called by frontend via Tauri invoke (getVideoDownloadUrl in VideoDownloadButton.svelte) #[allow(dead_code)] fn get_video_download_url( &self, item_id: &str, quality: &str, media_source_id: Option<&str>, ) -> String; /// Mark item as favorite async fn mark_favorite(&self, item_id: &str) -> Result<(), RepoError>; /// Unmark item as favorite async fn unmark_favorite(&self, item_id: &str) -> Result<(), RepoError>; /// Get person details async fn get_person(&self, person_id: &str) -> Result; /// Get items by person (filmography) async fn get_items_by_person( &self, person_id: &str, options: Option, ) -> Result; /// Get similar/related items for a movie or show /// /// @req: UR-009 - Discover similar content based on current item async fn get_similar_items( &self, item_id: &str, limit: Option, ) -> Result; // ===== Playlist Methods ===== /// Create a new playlist on the server /// /// @req: UR-014 - Make and edit playlists of music that sync back to Jellyfin /// @req: JA-019 - Get/create/update playlists async fn create_playlist( &self, name: &str, item_ids: &[String], ) -> Result; /// Delete a playlist /// /// @req: UR-014 - Make and edit playlists of music that sync back to Jellyfin /// @req: JA-019 - Get/create/update playlists async fn delete_playlist(&self, playlist_id: &str) -> Result<(), RepoError>; /// Rename a playlist /// /// @req: UR-014 - Make and edit playlists of music that sync back to Jellyfin /// @req: JA-019 - Get/create/update playlists async fn rename_playlist(&self, playlist_id: &str, name: &str) -> Result<(), RepoError>; /// Get playlist items with PlaylistItemId (needed for remove/reorder) /// /// @req: UR-014 - Make and edit playlists of music that sync back to Jellyfin /// @req: JA-019 - Get/create/update playlists async fn get_playlist_items( &self, playlist_id: &str, ) -> Result, RepoError>; /// Add items to a playlist /// /// @req: UR-014 - Make and edit playlists of music that sync back to Jellyfin /// @req: JA-020 - Add/remove items from playlist async fn add_to_playlist( &self, playlist_id: &str, item_ids: &[String], ) -> Result<(), RepoError>; /// Remove items from a playlist using entry IDs (PlaylistItemId, NOT media item IDs) /// /// @req: UR-014 - Make and edit playlists of music that sync back to Jellyfin /// @req: JA-020 - Add/remove items from playlist async fn remove_from_playlist( &self, playlist_id: &str, entry_ids: &[String], ) -> Result<(), RepoError>; /// Move a playlist item to a new position /// /// @req: UR-014 - Make and edit playlists of music that sync back to Jellyfin /// @req: JA-020 - Add/remove items from playlist async fn move_playlist_item( &self, playlist_id: &str, item_id: &str, new_index: u32, ) -> Result<(), RepoError>; }