use byteorder::{ReadBytesExt, LittleEndian};
use force_plate::ForcePlate;
use marker::{Marker, LabeledMarker};
use rigid_body::RigidBody;
use semver::Version;
use skeleton::Skeleton;
use std::collections::BTreeMap;
use std::io::BufRead;
use super::{Result, Unpack, ParseError, read_cstring};
#[derive(Clone, Debug, PartialEq)]
pub struct FrameOfData {
pub frame_number: i32,
pub marker_sets: BTreeMap<String, Vec<Marker>>,
pub other_markers: Vec<Marker>,
pub rigid_bodies: Vec<RigidBody>,
pub skeletons: Vec<Skeleton>,
pub labeled_markers: Vec<LabeledMarker>,
pub force_plates: Option<Vec<ForcePlate>>,
pub latency: f32,
pub timecode: (u32, u32),
pub timestamp: Option<f64>,
pub is_recording: Option<bool>,
pub tracked_models_changed: Option<bool>,
}
fn unpack_vec<R, T: Unpack<R>, B: BufRead>(ver: &Version, bytes: &mut B) -> Result<Vec<R>> {
let num = try!(bytes.read_i32::<LittleEndian>());
trace!("Unpacking vector of length {}", num);
let mut result = Vec::with_capacity(num as usize);
for _ in 0..num {
result.push(try!(T::unpack(ver, bytes)));
}
Ok(result)
}
impl Unpack<FrameOfData> for FrameOfData {
fn unpack<B: BufRead>(ver: &Version, bytes: &mut B) -> Result<FrameOfData> {
debug!("Unpacking frame of data");
let frame_num = try!(bytes.read_i32::<LittleEndian>());
trace!("Frame number: {}", frame_num);
let num_marker_sets = try!(bytes.read_i32::<LittleEndian>());
trace!("Number of marker sets: {}", num_marker_sets);
let mut sets = BTreeMap::new();
for _ in 0..num_marker_sets {
let name = try!(read_cstring(bytes));
let num_markers = try!(bytes.read_i32::<LittleEndian>());
let mut markers = Vec::with_capacity(num_markers as usize);
for _ in 0..num_markers {
markers.push(try!(Marker::unpack(ver, bytes)));
}
sets.insert(name, markers);
}
let others = try!(unpack_vec::<Marker, Marker, _>(ver, bytes));
let bodies = try!(unpack_vec::<RigidBody, RigidBody, _>(ver, bytes));
let skels = try!(unpack_vec::<Skeleton, Skeleton, _>(ver, bytes));
let labeled = try!(unpack_vec::<LabeledMarker, LabeledMarker, _>(ver, bytes));
let plates = if *ver >= Version::parse("2.9.0").unwrap() {
Some(try!(unpack_vec::<ForcePlate, ForcePlate, _>(ver, bytes)))
} else {
None
};
let latency = try!(bytes.read_f32::<LittleEndian>());
trace!("Latency: {}", latency);
let tc = try!(bytes.read_u32::<LittleEndian>());
let tcs = try!(bytes.read_u32::<LittleEndian>());
trace!("Time code: ({}, {})", tc, tcs);
let ts = if *ver >= Version::parse("2.7.0").unwrap() {
Some(try!(bytes.read_f64::<LittleEndian>()))
} else if *ver >= Version::parse("2.6.0").unwrap() {
Some(try!(bytes.read_f32::<LittleEndian>()) as f64)
} else {
None
};
let (is_rec, tmc) = if *ver >= Version::parse("2.6.0").unwrap() {
let params = try!(bytes.read_i16::<LittleEndian>());
(Some(params & 0x01 > 0), Some(params & 0x02 > 0))
} else {
(None, None)
};
let eod = try!(bytes.read_i32::<LittleEndian>());
if eod == 0 {
trace!("Parsed complete frame of data");
Ok(FrameOfData {
frame_number: frame_num,
marker_sets: sets,
other_markers: others,
rigid_bodies: bodies,
skeletons: skels,
labeled_markers: labeled,
force_plates: plates,
latency: latency,
timecode: (tc, tcs),
timestamp: ts,
is_recording: is_rec,
tracked_models_changed: tmc,
})
} else {
debug!("End of data tag, 0 != {}", eod);
Err(ParseError::UnknownError)
}
}
}