diff --git a/src/main.rs b/src/main.rs index 0c08408..1a5355a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,17 +3,18 @@ #![forbid(elided_lifetimes_in_paths, unsafe_code)] mod iotro; +mod preset; mod project; mod question; mod render; mod time; use self::{ - iotro::Language, project::{Project, ProjectLecture, ProjectSource, Resolution}, render::Renderer, time::{parse_date, parse_time, Time} }; +use crate::preset::Preset; use camino::Utf8PathBuf as PathBuf; use clap::Parser; use console::style; @@ -34,34 +35,24 @@ struct Args { #[clap(short = 'C', long, default_value = ".")] directory: PathBuf, - /// The slug of the course, e.g. "23ws-malo2". - #[clap(short = 'c', long, default_value = "23ws-malo2")] - course: String, - - /// The label of the course, e.g. "Mathematische Logik II". - #[clap(short, long, default_value = "Mathematische Logik II")] - label: String, - - /// The docent of the course, e.g. "Prof. E. Grädel". - #[clap(short, long, default_value = "Prof. E. Grädel")] - docent: String, - - /// The language of the lecture. Used for the intro and outro frame. - #[clap(short = 'L', long, default_value = "de")] - lang: Language<'static>, + /// The preset of the lecture. Can be a toml file or a known course slug. + #[clap(short, long)] + preset: String, #[cfg(feature = "mem_limit")] /// The memory limit for external tools like ffmpeg. #[clap(short, long, default_value = "12G")] mem_limit: String, - /// Transcode the final video clip down to the minimum resolution specified. + /// Transcode the final video clip down to the minimum resolution specified. If not + /// specified, the default value from the preset is used. #[clap(short, long)] transcode: Option, /// Transcode starts at this resolution, or the source resolution, whichever is lower. - #[clap(short = 'T', long, default_value = "1440p")] - transcode_start: Resolution, + /// If not specified, the default value from the preset is used. + #[clap(short = 'T', long)] + transcode_start: Option, /// Treat the audio as stereo. By default, only one channel from the input stereo will /// be used, assuming either the other channel is backup or the same as the used. @@ -125,7 +116,8 @@ fn main() { // process arguments let directory = args.directory.canonicalize_utf8().unwrap(); - let course = args.course; + let preset = Preset::find(&args.preset).unwrap(); + let course = preset.course; // let's see if we need to initialise the project let project_path = directory.join("project.toml"); @@ -170,10 +162,10 @@ fn main() { let project = Project { lecture: ProjectLecture { course, - label: args.label, - docent: args.docent, + label: preset.label, + docent: preset.docent, date, - lang: args.lang + lang: preset.lang }, source: ProjectSource { files, @@ -282,10 +274,10 @@ fn main() { }); // rescale the video - if let Some(lowest_res) = args.transcode { + if let Some(lowest_res) = args.transcode.or(preset.transcode) { for res in Resolution::values().into_iter().rev() { if res > project.source.metadata.as_ref().unwrap().source_res - || res > args.transcode_start + || res > args.transcode_start.unwrap_or(preset.transcode_start) || res < lowest_res { continue; diff --git a/src/preset.rs b/src/preset.rs new file mode 100644 index 0000000..85f37c6 --- /dev/null +++ b/src/preset.rs @@ -0,0 +1,77 @@ +//! This struct defines presets. + +use crate::{ + iotro::{Language, BRITISH, GERMAN}, + project::Resolution +}; +use anyhow::bail; +use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DisplayFromStr}; +use std::{fs, io}; + +#[serde_as] +#[derive(Deserialize, Serialize)] +pub(crate) struct Preset { + // options for the intro slide + pub(crate) course: String, + pub(crate) label: String, + pub(crate) docent: String, + + /// Course language + #[serde(default = "Default::default")] + #[serde_as(as = "DisplayFromStr")] + pub(crate) lang: Language<'static>, + + // coding options + pub(crate) transcode_start: Resolution, + pub(crate) transcode: Option +} + +fn preset_23ws_malo2() -> Preset { + Preset { + course: "23ws-malo2".into(), + label: "Mathematische Logik II".into(), + docent: "Prof. E. Grädel".into(), + lang: GERMAN, + transcode_start: Resolution::WQHD, + transcode: Some(Resolution::nHD) + } +} + +fn preset_24ss_algomod() -> Preset { + Preset { + course: "24ss-algomod".into(), + label: "Algorithmische Modelltheorie".into(), + docent: "Prof. E. Grädel".into(), + lang: GERMAN, + transcode_start: Resolution::WQHD, + transcode: Some(Resolution::HD) + } +} + +fn preset_24ss_qc() -> Preset { + Preset { + course: "24ss-qc".into(), + label: "Introduction to Quantum Computing".into(), + docent: "Prof. D. Unruh".into(), + lang: BRITISH, + transcode_start: Resolution::WQHD, + transcode: Some(Resolution::HD) + } +} + +impl Preset { + pub(crate) fn find(name: &str) -> anyhow::Result { + match fs::read(name) { + Ok(buf) => return Ok(toml::from_slice(&buf)?), + Err(err) if err.kind() == io::ErrorKind::NotFound => {}, + Err(err) => return Err(err.into()) + } + Ok(match name { + "23ws-malo2" => preset_23ws_malo2(), + "24ss-algomod" => preset_24ss_algomod(), + "24ss-qc" => preset_24ss_qc(), + _ => bail!("Unknown preset {name:?}") + }) + } +} diff --git a/src/project.rs b/src/project.rs index 46ed082..7dbda1f 100644 --- a/src/project.rs +++ b/src/project.rs @@ -1,3 +1,5 @@ +//! Defines the structure of the `project.toml` file. + use crate::{ iotro::Language, render::ffmpeg::FfmpegOutputFormat,