67 lines
3.8 KiB
Rust
67 lines
3.8 KiB
Rust
//! File ▸ Import / Export ▸ Adobe Premiere Pro Project… (timeline interchange) through the command
|
|
//! registry, without media decoding (pixels: `crates/host/tests/timeline_interop.rs`).
|
|
|
|
use serde_json::json;
|
|
|
|
use crate::Session;
|
|
use crate::project::{ItemId, ItemKind, LayerSource};
|
|
|
|
fn tmp(name: &str) -> String {
|
|
let d = std::env::temp_dir().join(format!("effectcraft-timeline-tests-{}", std::process::id()));
|
|
std::fs::create_dir_all(&d).unwrap();
|
|
d.join(name).to_string_lossy().to_string()
|
|
}
|
|
|
|
#[test]
|
|
fn export_and_reimport_timeline_commands() {
|
|
let mut s = Session::default();
|
|
s.execute("comp.new", json!({"name": "Main", "width": 320, "height": 180, "frameRate": 25, "duration": 2})).unwrap();
|
|
let full = s.execute("layer.newSolid", json!({"color": "#ff8000"})).unwrap()["layer"].as_u64().unwrap();
|
|
s.execute("prop.set", json!({"layer": full, "path": "transform/opacity", "value": 40})).unwrap();
|
|
s.execute("layer.newSolid", json!({"color": "#0080ff", "width": 50, "height": 50})).unwrap();
|
|
s.execute("layer.newNull", json!({})).unwrap();
|
|
let main = s.active_comp_id().unwrap().0;
|
|
for (ext, format) in [("xml", "xml"), ("fcpxml", "fcpxml"), ("otio", "otio")] {
|
|
let path = tmp(&format!("Main.{ext}"));
|
|
// No exporter in a bare session: the small solid can't be pre-rendered and is left out.
|
|
let r = s.execute_checked("file.exportTimeline", json!({"comp": main, "path": path})).unwrap();
|
|
assert_eq!(r["format"], format);
|
|
// Only Final Cut Pro XML carries colour mattes; the other formats would pre-render solids.
|
|
assert_eq!(r["videoTracks"], if format == "xml" { 1 } else { 0 }, "{r}");
|
|
assert!(r["warnings"].as_array().unwrap().iter().any(|w| w.as_str().unwrap().contains("pre-render")), "{r}");
|
|
let r = s.execute_checked("file.importTimeline", json!({"path": path})).unwrap();
|
|
assert_eq!(r["format"], format);
|
|
let cid = ItemId(r["comps"][0].as_u64().unwrap());
|
|
assert_eq!(s.active_comp_id(), Some(cid));
|
|
let c = s.project.comp(cid).unwrap();
|
|
assert_eq!((c.width, c.height), (320, 180));
|
|
if format != "xml" {
|
|
assert!(c.layers.is_empty());
|
|
continue;
|
|
}
|
|
assert_eq!(c.layers.len(), 1);
|
|
let l = &c.layers[0];
|
|
let LayerSource::Solid { item } = l.source else { panic!("{:?}", l.source) };
|
|
let ItemKind::Solid(sol) = &s.project.item(item).unwrap().kind else { panic!() };
|
|
assert!((sol.color[0] - 1.0).abs() < 0.01 && (sol.color[2]).abs() < 0.01, "{:?}", sol.color);
|
|
assert!((l.transform().unwrap().get("opacity").unwrap().value.as_f64() - 40.0).abs() < 1e-6);
|
|
let folder = ItemId(r["folder"].as_u64().unwrap());
|
|
assert_eq!(s.project.item(folder).unwrap().name, format!("Main.{ext}"));
|
|
}
|
|
// A path without an extension gets the format's.
|
|
let r = s.execute_checked("file.exportTimeline", json!({"comp": main, "path": tmp("NoExt"), "format": "otio", "prerender": "none"})).unwrap();
|
|
assert!(r["path"].as_str().unwrap().ends_with("NoExt.otio"));
|
|
assert!(s.execute_checked("file.exportTimeline", json!({"path": tmp("x.xml"), "prerender": "sometimes"})).is_err());
|
|
assert!(s.execute_checked("file.importTimeline", json!({"path": "/nope/a.prproj"})).is_err());
|
|
let formats = s.execute("file.timelineFormats", json!({})).unwrap();
|
|
assert_eq!(formats.as_array().unwrap().len(), 6);
|
|
}
|
|
|
|
#[test]
|
|
fn premiere_menu_entries_keep_after_effects_labels() {
|
|
let entries = crate::menus::entries();
|
|
let find = |cmd: &str| entries.iter().find(|(_, e)| e.command == cmd).map(|(p, e)| (p.join(" > "), e.label.clone()));
|
|
assert_eq!(find("file.exportTimeline"), Some(("File > Export".into(), "Adobe Premiere Pro Project...".into())));
|
|
assert_eq!(find("file.importTimeline"), Some(("File > Import".into(), "Adobe Premiere Pro Project...".into())));
|
|
}
|