use std::collections::HashMap;
pub type Time = f64;
pub struct Clip<'a, A> where A: 'a {
gen_node: Box<Fn(Time) -> A + 'a>
}
impl<'a, A> Clip<'a, A> {
pub fn new<F>(f: F) -> Self where F: 'a + Fn(Time) -> A {
Clip {
gen_node: Box::new(f)
}
}
}
#[derive(Clone)]
pub struct Cut<'a, 'b, A> where A: 'a, 'a: 'b {
pub in_time: Time,
pub out_time: Time,
pub inst_time: Time,
pub clip: &'b Clip<'a, A>
}
impl<'a, 'b, A> Cut<'a, 'b, A> where A :'a, 'a: 'b {
pub fn new(in_time: Time, out_time: Time, inst_time: Time, clip: &'b Clip<'a, A>) -> Self {
assert!(in_time <= out_time);
Cut {
in_time: in_time,
out_time: out_time,
inst_time: inst_time,
clip: clip
}
}
pub fn dur(&self) -> Time {
self.out_time - self.in_time
}
}
#[derive(Clone)]
pub struct Track<'a, 'b, A> where A: 'a, 'a: 'b {
cuts: Vec<Cut<'a, 'b, A>>
}
impl<'a, 'b, A> Track<'a, 'b, A> where A: 'a, 'a: 'b {
pub fn new() -> Self {
Track {
cuts: Vec::new()
}
}
pub fn add_cut(&mut self, cut: Cut<'a, 'b, A>) {
self.cuts.push(cut);
}
}
impl<'a, 'b, 'c, A> From<&'c [Cut<'a, 'b, A>]> for Track<'a, 'b, A> where A: Clone {
fn from(cuts: &'c [Cut<'a, 'b, A>]) -> Self {
Track {
cuts: cuts.to_vec()
}
}
}
pub struct Timeline<'a, 'b, A> where A: 'a, 'a: 'b {
tracks: Vec<Track<'a, 'b, A>>,
overlaps: Vec<Overlap<'a, A>>
}
impl<'a, 'b, A> Timeline<'a, 'b, A> where A: 'a, 'a: 'b {
pub fn new() -> Self {
Timeline {
tracks: Vec::new(),
overlaps: Vec::new()
}
}
pub fn from_manifest(manifest: &TimelineManifest, mapping: &HashMap<String, &'b Clip<'a, A>>) -> Self {
let mut timeline = Self::new();
for track_manifest in &manifest.tracks {
let mut track = Track::new();
for cut_manifest in &track_manifest.cuts {
let in_time = cut_manifest.in_time;
let out_time = cut_manifest.out_time;
let inst_time = cut_manifest.inst_time;
if let Some(clip) = mapping.get(&cut_manifest.clip).cloned() {
track.add_cut(Cut::new(in_time, out_time, inst_time, clip));
} else {
warn!("the clip {:?} doesn’t exist", cut_manifest.clip);
}
}
timeline.add_track(track);
}
timeline
}
pub fn add_track(&mut self, track: Track<'a, 'b, A>) {
self.tracks.push(track);
}
pub fn add_overlap(&mut self, overlap: Overlap<'a, A>) {
self.overlaps.push(overlap)
}
pub fn play(&self, t: Time) -> Played<A> {
let mut active_nodes = Vec::new();
for track in &self.tracks {
for cut in &track.cuts {
if cut.inst_time <= t && t <= cut.inst_time + cut.dur() {
active_nodes.push((cut.clip.gen_node)(t));
}
}
}
match active_nodes.len() {
0 => Played::Inactive,
1 => active_nodes.pop().map(Played::Resolved).unwrap_or(Played::Inactive),
_ => {
self.find_overlap(t).map(|overlap| {
Played::Resolved((overlap.fold)(active_nodes))
}).unwrap_or(Played::NoOverlap)
}
}
}
fn find_overlap(&self, t: Time) -> Option<&Overlap<A>> {
self.overlaps.iter().find(|x| x.inst_time <= t && t <= x.inst_time + x.dur)
}
}
pub enum Played<A> {
Resolved(A),
NoOverlap,
Inactive
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct TimelineManifest {
pub tracks: Vec<TrackManifest>
}
impl_load_json!(TimelineManifest, "timeline manifest");
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct TrackManifest {
pub cuts: Vec<CutManifest>
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CutManifest {
pub in_time: Time,
pub out_time: Time,
pub inst_time: Time,
pub clip: String
}
pub struct Overlap<'a, A> {
pub inst_time: Time,
pub dur: Time,
pub fold: Box<Fn(Vec<A>) -> A + 'a>,
}
impl<'a, A> Overlap<'a, A> {
pub fn new<F>(inst_time: Time, dur: Time, f: F) -> Self where F: 'a + Fn(Vec<A>) -> A {
Overlap {
inst_time: inst_time,
dur: dur,
fold: Box::new(f)
}
}
}