// yt - A fully featured command line YouTube client // // Copyright (C) 2024 Benedikt Peetz // SPDX-License-Identifier: GPL-3.0-or-later // // This file is part of Yt. // // You should have received a copy of the License along with this program. // If not, see . use std::{fmt::Write, path::PathBuf}; use url::Url; use crate::{ constants::{DEFAULT_MPV_PLAYBACK_SPEED, DEFAULT_SUBTITLE_LANGS}, storage::video_database::extractor_hash::ExtractorHash, }; pub mod downloader; pub mod extractor_hash; pub mod getters; pub mod setters; #[derive(Debug)] pub struct Video { pub cache_path: Option, pub description: Option, pub duration: Option, pub extractor_hash: ExtractorHash, pub last_status_change: i64, /// The associated subscription this video was fetched from (null, when the video was `add`ed) pub parent_subscription_name: Option, pub priority: i64, pub publish_date: Option, pub status: VideoStatus, /// The video is currently changing its state (for example from being `SELECT` to being `CACHE`) pub status_change: bool, pub thumbnail_url: Option, pub title: String, pub url: Url, } #[derive(Debug)] pub struct VideoOptions { pub yt_dlp: YtDlpOptions, pub mpv: MpvOptions, } impl VideoOptions { pub(crate) fn new(subtitle_langs: String, playback_speed: f64) -> Self { let yt_dlp = YtDlpOptions { subtitle_langs }; let mpv = MpvOptions { playback_speed }; Self { yt_dlp, mpv } } /// This will write out the options that are different from the defaults. /// Beware, that this does not set the priority. pub fn to_cli_flags(self) -> String { let mut f = String::new(); if self.mpv.playback_speed != DEFAULT_MPV_PLAYBACK_SPEED { write!(f, " --speed '{}'", self.mpv.playback_speed).expect("Works"); } if self.yt_dlp.subtitle_langs != DEFAULT_SUBTITLE_LANGS { write!(f, " --subtitle-langs '{}'", self.yt_dlp.subtitle_langs).expect("Works"); } f.trim().to_owned() } } #[derive(Debug)] /// Additionally settings passed to mpv on watch pub struct MpvOptions { /// The playback speed. (1 is 100%, 2.7 is 270%, and so on) pub playback_speed: f64, } #[derive(Debug)] /// Additionally configuration options, passed to yt-dlp on download pub struct YtDlpOptions { /// In the form of `lang1,lang2,lang3` (e.g. `en,de,sv`) pub subtitle_langs: String, } /// # Video Lifetime (words in are commands): /// /// / \ /// -> Dropped // yt select /// | /// Cache // yt cache /// | /// Watched // yt watch #[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum VideoStatus { #[default] Pick, /// The video has been select to be watched Watch, /// The video has been cached and is ready to be watched Cached, /// The video has been watched Watched, /// The video has been select to be dropped Drop, /// The video has been dropped Dropped, } impl VideoStatus { pub fn as_command(&self) -> &str { // NOTE: Keep the serialize able variants synced with the main `select` function <2024-06-14> match self { VideoStatus::Pick => "pick", VideoStatus::Watch => "watch", VideoStatus::Cached => "watch", VideoStatus::Watched => "watch", VideoStatus::Drop => "drop", VideoStatus::Dropped => "drop", } } pub fn as_db_integer(&self) -> i64 { // These numbers should not change their mapping! // Oh, and keep them in sync with the SQLite check constraint. match self { VideoStatus::Pick => 0, VideoStatus::Watch => 1, VideoStatus::Cached => 2, VideoStatus::Watched => 3, VideoStatus::Drop => 4, VideoStatus::Dropped => 5, } } pub fn from_db_integer(num: i64) -> Self { match num { 0 => Self::Pick, 1 => Self::Watch, 2 => Self::Cached, 3 => Self::Watched, 4 => Self::Drop, 5 => Self::Dropped, other => unreachable!( "The database returned a enum discriminator, unknown to us: '{}'", other ), } } pub fn as_str(&self) -> &'static str { match self { VideoStatus::Pick => "Pick", VideoStatus::Watch => "Watch", VideoStatus::Cached => "Cache", VideoStatus::Watched => "Watched", VideoStatus::Drop => "Drop", VideoStatus::Dropped => "Dropped", } } }