diff --git a/Cargo.lock b/Cargo.lock index fa5ca1407..45ae4e5b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1859,7 +1859,6 @@ dependencies = [ "craft-xml", "proptest", "serde", - "serde_json", ] [[package]] diff --git a/crates/timeline/Cargo.toml b/crates/timeline/Cargo.toml index 3eca9bc5c..59a79ed4b 100644 --- a/crates/timeline/Cargo.toml +++ b/crates/timeline/Cargo.toml @@ -15,18 +15,14 @@ workspace = true serde = ["dep:serde"] # Final Cut Pro 7 XML (`fcp7`), read with craft-xml's bounded parser. xml = ["dep:craft-xml"] -# OpenTimelineIO JSON (`otio`), with serde_json. -otio = ["dep:serde_json"] [dependencies] serde = { workspace = true, optional = true } craft-xml = { workspace = true, optional = true } -serde_json = { workspace = true, optional = true } [dev-dependencies] proptest = { workspace = true } -serde_json = { workspace = true } [[test]] name = "it" -required-features = ["xml", "otio"] +required-features = ["xml"] diff --git a/crates/timeline/README.md b/crates/timeline/README.md index 6397d9d2e..f53be17d6 100644 --- a/crates/timeline/README.md +++ b/crates/timeline/README.md @@ -16,7 +16,6 @@ text formats that are documents of their own. | `edl` | CMX 3600 edit decision lists: `parse` to the list as written (events, their lines and timecode fields, `M2`, `AUD`, clip-name, source-file, effect-name and locator comments), `write` for events the caller built, channel codes, reel names, the frame-rate guess. | | `fcp7` (feature `xml`) | Final Cut Pro 7 XML (`xmeml` 4 and 5, the dialect Premiere Pro reads and writes) to and from `model`. Read with craft-xml, strictly and bounded. | | `fcpxml` (feature `xml`) | FCPXML 1.9–1.11 to and from `model`: the primary storyline as V1, connected clips by lane, `ref-clip` compounds as nested sequences, rational times exact, transforms, opacity, volume and their keyframes, retiming through `timeMap`. | -| `otio` (feature `otio`) | OpenTimelineIO JSON to and from `model`: timelines, collections, stacks as nested sequences, gaps, transitions, markers, linear time warps and freeze frames. What OTIO has no schema for goes in `metadata.`, and the model's `ext` is merged into it, so an application's own data round-trips. | | crate root | `Format` (EDL, xmeml, FCPXML, OTIO, AAF, OMF), `detect_text`, `decode_text`. | No file I/O. EDL and ALE give the document as the format writes it. The formats that describe a @@ -24,7 +23,7 @@ whole edit read into and write from `model`; mapping `model` onto an application stays in the application. AAF and OMF are in `craft-aaf`. -Feature `xml`: the XML formats, on craft-xml. Feature `otio`: OpenTimelineIO, on serde_json. Feature `serde`: `Serialize` / `Deserialize` for the time, report and `Format` types. +Feature `xml`: the XML formats, on craft-xml. Feature `serde`: `Serialize` / `Deserialize` for the time, report and `Format` types. ## Specifications diff --git a/crates/timeline/src/fcpxml.rs b/crates/timeline/src/fcpxml.rs index 198574718..81342f70c 100644 --- a/crates/timeline/src/fcpxml.rs +++ b/crates/timeline/src/fcpxml.rs @@ -1325,7 +1325,7 @@ mod tests { "# ); let mut report = Report::default(); - let iopts = ImportOptions { base_dir: None, name: None, catalog: &crate::fx::Standard, namespace: "test" }; + let iopts = ImportOptions { base_dir: None, catalog: &crate::fx::Standard, namespace: "test" }; let imported = import(&xml, &iopts, &mut report).expect("import succeeds"); let xopts = ExportOptions { relative_to: None, diff --git a/crates/timeline/src/lib.rs b/crates/timeline/src/lib.rs index b638fd3ec..4de152282 100644 --- a/crates/timeline/src/lib.rs +++ b/crates/timeline/src/lib.rs @@ -15,7 +15,6 @@ //! - [`edl`]: CMX 3600 edit decision lists. //! - [`fcp7`] (feature `xml`): Final Cut Pro 7 XML (`xmeml`). //! - [`fcpxml`] (feature `xml`): FCPXML 1.9–1.11. -//! - [`otio`] (feature `otio`): OpenTimelineIO JSON. //! - [`Format`], [`detect_text`], [`decode_text`]: which interchange format a document is. //! //! No file I/O: documents are text or bytes, and media references are strings. Each format module @@ -31,8 +30,6 @@ pub mod fcp7; pub mod fcpxml; pub mod fx; pub mod model; -#[cfg(feature = "otio")] -pub mod otio; pub mod path; pub mod rate; pub mod report; @@ -119,7 +116,7 @@ pub enum Error { } impl Error { - #[cfg_attr(not(any(feature = "xml", feature = "otio")), allow(dead_code))] + #[cfg_attr(not(feature = "xml"), allow(dead_code))] pub(crate) fn parse(format: Format, message: impl Into) -> Error { Error::Parse { format: format.name(), message: message.into() } } @@ -145,8 +142,6 @@ pub type Result = std::result::Result; pub struct ImportOptions<'a> { /// Directory relative media paths are resolved against (normally the document's directory). pub base_dir: Option<&'a str>, - /// Name for a timeline the document leaves unnamed. - pub name: Option<&'a str>, /// The application's effects and generators (see [`model::Catalog`]; [`fx::Standard`] knows /// only what the formats name themselves). pub catalog: &'a dyn model::Catalog, diff --git a/crates/timeline/src/model.rs b/crates/timeline/src/model.rs index 3f8db8c1c..6adff43dd 100644 --- a/crates/timeline/src/model.rs +++ b/crates/timeline/src/model.rs @@ -14,7 +14,7 @@ //! supplies. //! - **Generators** other than the ones every editor has: [`Generator::Other`] carries a name and //! an opaque payload. -//! - **Extensions.** `ext` on items (a sequence's is its item's), tracks, clips, transitions and markers is JSON +//! - **Extensions.** `ext` on items, sequences, tracks, clips, transitions and markers is JSON //! text the application owns. A format that can carry application metadata (OpenTimelineIO) //! writes it under the application's namespace and gives it back on reading; the others ignore it. @@ -540,11 +540,12 @@ pub struct Sequence { pub markers: Vec, /// Timecode of the first frame, in frames. pub start_timecode: i64, + pub ext: Ext, } impl Sequence { pub fn new(settings: SequenceSettings) -> Self { - Self { settings, video_tracks: Vec::new(), audio_tracks: Vec::new(), markers: Vec::new(), start_timecode: 0 } + Self { settings, video_tracks: Vec::new(), audio_tracks: Vec::new(), markers: Vec::new(), start_timecode: 0, ext: None } } /// The end of the last clip. pub fn duration(&self) -> Tick { diff --git a/crates/timeline/tests/it/fcp7.rs b/crates/timeline/tests/it/fcp7.rs index 00d0704ec..dfa3cc186 100644 --- a/crates/timeline/tests/it/fcp7.rs +++ b/crates/timeline/tests/it/fcp7.rs @@ -723,7 +723,7 @@ fn absurd_timebase_is_bounded() { ); let (imported, _) = fcp7_import(&doc, None); for seq in &imported.sequences { - for format in [Format::Fcp7Xml, Format::Fcpxml, Format::Otio] { + for format in [Format::Fcp7Xml, Format::Fcpxml] { export(&imported.project, *seq, format, &xopts()).unwrap_or_else(|e| panic!("{format:?}: {e}")); } } @@ -742,7 +742,7 @@ fn absurd_start_timecode_is_bounded() { "#; let (imported, report) = fcp7_import(doc, None); for seq in &imported.sequences { - for format in [Format::Fcp7Xml, Format::Fcpxml, Format::Otio] { + for format in [Format::Fcp7Xml, Format::Fcpxml] { export(&imported.project, *seq, format, &xopts()).unwrap_or_else(|e| panic!("{format:?}: {e}")); } assert_eq!(imported.project.sequence(*seq).map(|s| s.start_timecode), Some(0)); diff --git a/crates/timeline/tests/it/main.rs b/crates/timeline/tests/it/main.rs index f8d222b28..12e73ea72 100644 --- a/crates/timeline/tests/it/main.rs +++ b/crates/timeline/tests/it/main.rs @@ -2,5 +2,4 @@ mod fcp7; mod fcpxml; -mod otio; mod support; diff --git a/crates/timeline/tests/it/support.rs b/crates/timeline/tests/it/support.rs index 1afb703a0..4a3247d78 100644 --- a/crates/timeline/tests/it/support.rs +++ b/crates/timeline/tests/it/support.rs @@ -11,7 +11,7 @@ use craft_timeline::model::{ TransitionId, VideoStreamInfo, }; use craft_timeline::time::{FrameRate, TICKS_PER_SECOND, Tick, TimeRange}; -use craft_timeline::{Error, ExportOptions, Format, ImportOptions, Imported, Report, fcp7, fcpxml, otio}; +use craft_timeline::{Error, ExportOptions, Format, ImportOptions, Imported, Report, fcp7, fcpxml}; /// [`Standard`] and a few effects an application adds: a blur, a grade, two transitions. pub struct TestCatalog; @@ -31,7 +31,6 @@ fn extra() -> Vec { def("lumetri", "Lumetri Color", EffectKind::Video, "Color Correction", vec![float("exposure", "Exposure", 0.0)]), def("dip_to_white", "Dip to White", EffectKind::VideoTransition, "Dissolve", vec![]), def("push", "Push", EffectKind::VideoTransition, "Slide", vec![]), - def("iris_round", "Iris Round", EffectKind::VideoTransition, "Iris", vec![]), ] } @@ -50,7 +49,7 @@ impl Catalog for TestCatalog { pub const NS: &str = "testapp"; pub fn iopts(base_dir: Option<&str>) -> ImportOptions<'_> { - ImportOptions { base_dir, name: None, catalog: &TestCatalog, namespace: NS } + ImportOptions { base_dir, catalog: &TestCatalog, namespace: NS } } pub fn xopts() -> ExportOptions<'static> { @@ -308,7 +307,6 @@ pub fn import(bytes: &[u8], format: Format, base_dir: Option<&str>) -> Result<(I let imported = match format { Format::Fcp7Xml => fcp7::import(&text, &opts, &mut report), Format::Fcpxml => fcpxml::import(&text, &opts, &mut report), - Format::Otio => otio::import(&text, &opts, &mut report), _ => Err(Error::Other(format!("{} is not read here", format.name()))), }?; Ok((imported, report)) @@ -320,7 +318,6 @@ pub fn export(p: &Project, seq: ItemId, format: Format, opts: &ExportOptions) -> let text = match format { Format::Fcp7Xml => fcp7::export(p, seq, opts, &mut report), Format::Fcpxml => fcpxml::export(p, seq, opts, &mut report), - Format::Otio => otio::export(p, seq, opts, &mut report), _ => Err(Error::Other(format!("{} is not written here", format.name()))), }?; Ok((text.into_bytes(), report))