906 lines
28 KiB
Rust
906 lines
28 KiB
Rust
#![cfg(test)]
|
|
use super::*;
|
|
|
|
// We need the VSScript functions, and either VSScript API 3.2 or the VapourSynth functions.
|
|
#[cfg(all(
|
|
feature = "vsscript-functions",
|
|
any(
|
|
feature = "vapoursynth-functions",
|
|
feature = "gte-vsscript-api-32"
|
|
)
|
|
))]
|
|
mod need_api_and_vsscript {
|
|
use std::ffi::CStr;
|
|
use std::fmt::Debug;
|
|
use std::mem;
|
|
use std::slice;
|
|
use std::sync::mpsc::channel;
|
|
|
|
use super::*;
|
|
use function::Function;
|
|
use prelude::*;
|
|
use video_info::{Framerate, Resolution};
|
|
|
|
fn props_test(frame: &Frame, fps_num: i64) {
|
|
let props = frame.props();
|
|
assert_eq!(props.key_count(), 2);
|
|
assert_eq!(props.key(0), "_DurationDen");
|
|
assert_eq!(props.key(1), "_DurationNum");
|
|
|
|
assert_eq!(props.value_count(props.key(0)), Ok(1));
|
|
assert_eq!(props.get_int(props.key(0)), Ok(fps_num));
|
|
assert_eq!(props.value_count(props.key(1)), Ok(1));
|
|
assert_eq!(props.get_int(props.key(1)), Ok(1));
|
|
}
|
|
|
|
fn env_video_var_test(env: &vsscript::Environment) {
|
|
let mut map = OwnedMap::new(API::get().unwrap());
|
|
assert!(env.get_variable("video", &mut map).is_ok());
|
|
assert_eq!(map.key_count(), 1);
|
|
assert_eq!(map.key(0), "video");
|
|
let node = map.get_node("video");
|
|
assert!(node.is_ok());
|
|
}
|
|
|
|
fn green_frame_test(frame: &Frame) {
|
|
let format = frame.format();
|
|
assert_eq!(format.name(), "RGB24");
|
|
assert_eq!(format.plane_count(), 3);
|
|
|
|
for plane in 0..format.plane_count() {
|
|
let resolution = frame.resolution(plane);
|
|
assert_eq!(
|
|
resolution,
|
|
Resolution {
|
|
width: 1920,
|
|
height: 1080,
|
|
}
|
|
);
|
|
|
|
let color = if plane == 1 { [255; 1920] } else { [0; 1920] };
|
|
|
|
for row in 0..resolution.height {
|
|
let data_row = frame.data_row(plane, row);
|
|
assert_eq!(&data_row[..], &color[..]);
|
|
let data_row = frame.plane_row::<u8>(plane, row);
|
|
assert_eq!(&data_row[..], &color[..]);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn green_test(env: &vsscript::Environment) {
|
|
#[cfg(feature = "gte-vsscript-api-31")]
|
|
let (node, alpha_node) = {
|
|
let output = env.get_output(0);
|
|
assert!(output.is_ok());
|
|
output.unwrap()
|
|
};
|
|
#[cfg(not(feature = "gte-vsscript-api-31"))]
|
|
let (node, alpha_node) = (env.get_output(0).unwrap(), None::<Node>);
|
|
|
|
assert!(alpha_node.is_none());
|
|
|
|
let info = node.info();
|
|
|
|
if let Property::Constant(format) = info.format {
|
|
assert_eq!(format.name(), "RGB24");
|
|
} else {
|
|
assert!(false);
|
|
}
|
|
|
|
assert_eq!(
|
|
info.framerate,
|
|
Property::Constant(Framerate {
|
|
numerator: 60,
|
|
denominator: 1,
|
|
})
|
|
);
|
|
assert_eq!(
|
|
info.resolution,
|
|
Property::Constant(Resolution {
|
|
width: 1920,
|
|
height: 1080,
|
|
})
|
|
);
|
|
|
|
#[cfg(feature = "gte-vapoursynth-api-32")]
|
|
assert_eq!(info.num_frames, 100);
|
|
#[cfg(not(feature = "gte-vapoursynth-api-32"))]
|
|
assert_eq!(info.num_frames, Property::Constant(100));
|
|
|
|
let frame = node.get_frame(0).unwrap();
|
|
green_frame_test(&frame);
|
|
props_test(&frame, 60);
|
|
env_video_var_test(&env);
|
|
}
|
|
|
|
#[test]
|
|
fn green() {
|
|
let env =
|
|
vsscript::Environment::from_file("test-vpy/green.vpy", vsscript::EvalFlags::Nothing)
|
|
.unwrap();
|
|
green_test(&env);
|
|
}
|
|
|
|
#[test]
|
|
fn green_from_string() {
|
|
let env =
|
|
vsscript::Environment::from_script(include_str!("../test-vpy/green.vpy")).unwrap();
|
|
green_test(&env);
|
|
}
|
|
|
|
#[test]
|
|
fn variable() {
|
|
let env =
|
|
vsscript::Environment::from_file("test-vpy/variable.vpy", vsscript::EvalFlags::Nothing)
|
|
.unwrap();
|
|
|
|
#[cfg(feature = "gte-vsscript-api-31")]
|
|
let (node, alpha_node) = {
|
|
let output = env.get_output(0);
|
|
assert!(output.is_ok());
|
|
output.unwrap()
|
|
};
|
|
#[cfg(not(feature = "gte-vsscript-api-31"))]
|
|
let (node, alpha_node) = (env.get_output(0).unwrap(), None::<Node>);
|
|
|
|
assert!(alpha_node.is_none());
|
|
|
|
let info = node.info();
|
|
|
|
assert_eq!(info.format, Property::Variable);
|
|
assert_eq!(info.framerate, Property::Variable);
|
|
assert_eq!(info.resolution, Property::Variable);
|
|
|
|
#[cfg(feature = "gte-vapoursynth-api-32")]
|
|
assert_eq!(info.num_frames, 200);
|
|
#[cfg(not(feature = "gte-vapoursynth-api-32"))]
|
|
assert_eq!(info.num_frames, Property::Constant(200));
|
|
|
|
// Test the first frame.
|
|
let frame = node.get_frame(0).unwrap();
|
|
let format = frame.format();
|
|
assert_eq!(format.name(), "RGB24");
|
|
assert_eq!(format.plane_count(), 3);
|
|
|
|
for plane in 0..format.plane_count() {
|
|
let resolution = frame.resolution(plane);
|
|
assert_eq!(
|
|
resolution,
|
|
Resolution {
|
|
width: 1920,
|
|
height: 1080,
|
|
}
|
|
);
|
|
|
|
let color = if plane == 1 { [255; 1920] } else { [0; 1920] };
|
|
|
|
for row in 0..resolution.height {
|
|
let data_row = frame.data_row(plane, row);
|
|
assert_eq!(&data_row[..], &color[..]);
|
|
let data_row = frame.plane_row::<u8>(plane, row);
|
|
assert_eq!(&data_row[..], &color[..]);
|
|
}
|
|
}
|
|
|
|
props_test(&frame, 60);
|
|
|
|
// Test the first frame of the next format.
|
|
let frame = node.get_frame(100).unwrap();
|
|
let format = frame.format();
|
|
assert_eq!(format.name(), "Gray8");
|
|
assert_eq!(format.plane_count(), 1);
|
|
|
|
let plane = 0;
|
|
let resolution = frame.resolution(plane);
|
|
assert_eq!(
|
|
resolution,
|
|
Resolution {
|
|
width: 1280,
|
|
height: 720,
|
|
}
|
|
);
|
|
|
|
let color = [127; 1280];
|
|
|
|
for row in 0..resolution.height {
|
|
let data_row = frame.data_row(plane, row);
|
|
assert_eq!(&data_row[..], &color[..]);
|
|
let data_row = frame.plane_row::<u8>(plane, row);
|
|
assert_eq!(&data_row[..], &color[..]);
|
|
}
|
|
|
|
props_test(&frame, 30);
|
|
env_video_var_test(&env);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(feature = "gte-vsscript-api-31")]
|
|
fn alpha() {
|
|
let env =
|
|
vsscript::Environment::from_file("test-vpy/alpha.vpy", vsscript::EvalFlags::Nothing)
|
|
.unwrap();
|
|
|
|
let (_, alpha_node) = {
|
|
let output = env.get_output(0);
|
|
assert!(output.is_ok());
|
|
output.unwrap()
|
|
};
|
|
|
|
assert!(alpha_node.is_some());
|
|
let alpha_node = alpha_node.unwrap();
|
|
|
|
let info = alpha_node.info();
|
|
|
|
if let Property::Constant(format) = info.format {
|
|
assert_eq!(format.name(), "Gray8");
|
|
} else {
|
|
assert!(false);
|
|
}
|
|
|
|
assert_eq!(
|
|
info.framerate,
|
|
Property::Constant(Framerate {
|
|
numerator: 60,
|
|
denominator: 1,
|
|
})
|
|
);
|
|
assert_eq!(
|
|
info.resolution,
|
|
Property::Constant(Resolution {
|
|
width: 1920,
|
|
height: 1080,
|
|
})
|
|
);
|
|
|
|
#[cfg(feature = "gte-vapoursynth-api-32")]
|
|
assert_eq!(info.num_frames, 100);
|
|
#[cfg(not(feature = "gte-vapoursynth-api-32"))]
|
|
assert_eq!(info.num_frames, Property::Constant(100));
|
|
|
|
let frame = alpha_node.get_frame(0).unwrap();
|
|
let format = frame.format();
|
|
assert_eq!(format.name(), "Gray8");
|
|
assert_eq!(format.plane_count(), 1);
|
|
|
|
let resolution = frame.resolution(0);
|
|
assert_eq!(
|
|
resolution,
|
|
Resolution {
|
|
width: 1920,
|
|
height: 1080,
|
|
}
|
|
);
|
|
|
|
for row in 0..resolution.height {
|
|
let data_row = frame.data_row(0, row);
|
|
assert_eq!(&data_row[..], &[128; 1920][..]);
|
|
let data_row = frame.plane_row::<u8>(0, row);
|
|
assert_eq!(&data_row[..], &[128; 1920][..]);
|
|
}
|
|
}
|
|
|
|
fn verify_pixel_format<T: Component + Debug + Copy + PartialEq>(
|
|
env: &Environment,
|
|
index: i32,
|
|
bits_per_sample: u8,
|
|
color: [T; 3],
|
|
) {
|
|
#[cfg(feature = "gte-vsscript-api-31")]
|
|
let node = env.get_output(index).unwrap().0;
|
|
#[cfg(not(feature = "gte-vsscript-api-31"))]
|
|
let node = env.get_output(index).unwrap();
|
|
|
|
let frame = node.get_frame(0).unwrap();
|
|
let format = frame.format();
|
|
|
|
assert_eq!(format.bits_per_sample(), bits_per_sample);
|
|
let bytes_per_sample = ((bits_per_sample + 7) / 8).next_power_of_two();
|
|
assert_eq!(format.bytes_per_sample(), bytes_per_sample);
|
|
|
|
for plane_num in 0..3 {
|
|
// Compare the entire row at once for speed.
|
|
let row_gt = vec![color[plane_num]; frame.width(plane_num)];
|
|
|
|
for y in 0..frame.height(plane_num) {
|
|
let row = frame.plane_row(plane_num, y);
|
|
assert_eq!(row.len(), frame.width(plane_num));
|
|
assert_eq!(&row_gt[..], row);
|
|
}
|
|
|
|
if let Ok(data) = frame.plane(plane_num) {
|
|
assert_eq!(data.len(), frame.height(plane_num) * frame.width(plane_num));
|
|
|
|
for y in 0..frame.height(plane_num) {
|
|
assert_eq!(
|
|
&row_gt[..],
|
|
&data[y * frame.width(plane_num)..(y + 1) * frame.width(plane_num)]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn pixel_formats() {
|
|
let env = vsscript::Environment::from_file(
|
|
"test-vpy/pixel-formats.vpy",
|
|
vsscript::EvalFlags::Nothing,
|
|
).unwrap();
|
|
|
|
verify_pixel_format(&env, 0, 10, [789u16, 123u16, 456u16]);
|
|
verify_pixel_format(&env, 1, 32, [5f32, 42f32, 0.25f32]);
|
|
verify_pixel_format(&env, 2, 32, [0.125f32, 10f32, 0.5f32]);
|
|
verify_pixel_format(&env, 3, 17, [77777u32, 88888u32, 99999u32]);
|
|
verify_pixel_format(&env, 4, 32, [u32::max_value(), 12345u32, 65432u32]);
|
|
|
|
#[cfg(feature = "f16-pixel-type")]
|
|
verify_pixel_format(
|
|
&env,
|
|
5,
|
|
16,
|
|
[
|
|
half::f16::from_f32(0.0625f32),
|
|
half::f16::from_f32(5f32),
|
|
half::f16::from_f32(0.25f32),
|
|
],
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic]
|
|
fn invalid_component_type() {
|
|
let env = vsscript::Environment::from_file(
|
|
"test-vpy/pixel-formats.vpy",
|
|
vsscript::EvalFlags::Nothing,
|
|
).unwrap();
|
|
|
|
#[cfg(feature = "gte-vsscript-api-31")]
|
|
let node = env.get_output(0).unwrap().0;
|
|
#[cfg(not(feature = "gte-vsscript-api-31"))]
|
|
let node = env.get_output(0).unwrap();
|
|
|
|
let frame = node.get_frame(0).unwrap();
|
|
let _ = frame.plane_row::<u8>(0, 0); // Should be u16.
|
|
}
|
|
|
|
#[test]
|
|
fn gradient() {
|
|
let env =
|
|
vsscript::Environment::from_file("test-vpy/gradient.vpy", vsscript::EvalFlags::Nothing)
|
|
.unwrap();
|
|
|
|
#[cfg(feature = "gte-vsscript-api-31")]
|
|
let node = env.get_output(0).unwrap().0;
|
|
#[cfg(not(feature = "gte-vsscript-api-31"))]
|
|
let node = env.get_output(0).unwrap();
|
|
|
|
let frame = node.get_frame(0).unwrap();
|
|
for plane in 0..3 {
|
|
for row in 0..16 {
|
|
let mut gt = [0u8; 16];
|
|
for col in 0..16 {
|
|
gt[col] = match plane {
|
|
0 => row as u8 * 16,
|
|
1 => col as u8 * 16,
|
|
2 => 0,
|
|
_ => unreachable!(),
|
|
};
|
|
}
|
|
|
|
let data = frame.data_row(plane, row);
|
|
assert_eq!(data, >[..]);
|
|
let data = frame.plane_row::<u8>(plane, row);
|
|
assert_eq!(data, >[..]);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn clear_output() {
|
|
let env =
|
|
vsscript::Environment::from_script(include_str!("../test-vpy/green.vpy")).unwrap();
|
|
assert!(
|
|
env.clear_output(1)
|
|
.err()
|
|
.map(|e| if let vsscript::Error::NoOutput = e {
|
|
true
|
|
} else {
|
|
false
|
|
}).unwrap_or(false)
|
|
);
|
|
assert!(env.clear_output(0).is_ok());
|
|
assert!(
|
|
env.clear_output(0)
|
|
.err()
|
|
.map(|e| if let vsscript::Error::NoOutput = e {
|
|
true
|
|
} else {
|
|
false
|
|
}).unwrap_or(false)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn iterators() {
|
|
let env =
|
|
vsscript::Environment::from_script(include_str!("../test-vpy/green.vpy")).unwrap();
|
|
|
|
#[cfg(feature = "gte-vsscript-api-31")]
|
|
let (node, alpha_node) = env.get_output(0).unwrap();
|
|
#[cfg(not(feature = "gte-vsscript-api-31"))]
|
|
let (node, alpha_node) = (env.get_output(0).unwrap(), None::<Node>);
|
|
|
|
assert!(alpha_node.is_none());
|
|
|
|
let frame = node.get_frame(0).unwrap();
|
|
let props = frame.props();
|
|
|
|
assert_eq!(props.keys().size_hint(), (2, Some(2)));
|
|
// assert_eq!(props.iter().size_hint(), (2, Some(2)));
|
|
}
|
|
|
|
#[test]
|
|
fn vsscript_variables() {
|
|
let env =
|
|
vsscript::Environment::from_script(include_str!("../test-vpy/green.vpy")).unwrap();
|
|
|
|
let mut map = OwnedMap::new(API::get().unwrap());
|
|
assert!(env.get_variable("video", &mut map).is_ok());
|
|
assert!(env.clear_variable("video").is_ok());
|
|
assert!(env.clear_variable("video").is_err());
|
|
assert!(env.get_variable("video", &mut map).is_err());
|
|
|
|
assert!(env.set_variables(&map).is_ok());
|
|
assert!(env.get_variable("video", &mut map).is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn get_frame_async() {
|
|
let env =
|
|
vsscript::Environment::from_file("test-vpy/green.vpy", vsscript::EvalFlags::Nothing)
|
|
.unwrap();
|
|
|
|
#[cfg(feature = "gte-vsscript-api-31")]
|
|
let (node, alpha_node) = {
|
|
let output = env.get_output(0);
|
|
assert!(output.is_ok());
|
|
output.unwrap()
|
|
};
|
|
#[cfg(not(feature = "gte-vsscript-api-31"))]
|
|
let (node, alpha_node) = (env.get_output(0).unwrap(), None::<Node>);
|
|
|
|
assert!(alpha_node.is_none());
|
|
|
|
let mut rxs = Vec::new();
|
|
|
|
for i in 0..10 {
|
|
let (tx, rx) = channel();
|
|
rxs.push(rx);
|
|
|
|
node.get_frame_async(i, move |frame, n, node| {
|
|
assert!(frame.is_ok());
|
|
let frame = frame.unwrap();
|
|
|
|
assert_eq!(n, i);
|
|
assert_eq!(
|
|
node.info().framerate,
|
|
Property::Constant(Framerate {
|
|
numerator: 60,
|
|
denominator: 1,
|
|
})
|
|
);
|
|
|
|
green_frame_test(&frame);
|
|
props_test(&frame, 60);
|
|
|
|
assert_eq!(tx.send(()), Ok(()));
|
|
});
|
|
}
|
|
|
|
drop(node); // Test dropping prematurely.
|
|
|
|
for rx in rxs {
|
|
assert_eq!(rx.recv(), Ok(()));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn get_frame_async_error() {
|
|
let env =
|
|
vsscript::Environment::from_file("test-vpy/green.vpy", vsscript::EvalFlags::Nothing)
|
|
.unwrap();
|
|
|
|
#[cfg(feature = "gte-vsscript-api-31")]
|
|
let (node, alpha_node) = {
|
|
let output = env.get_output(0);
|
|
assert!(output.is_ok());
|
|
output.unwrap()
|
|
};
|
|
#[cfg(not(feature = "gte-vsscript-api-31"))]
|
|
let (node, alpha_node) = (env.get_output(0).unwrap(), None::<Node>);
|
|
|
|
assert!(alpha_node.is_none());
|
|
|
|
let (tx, rx) = channel();
|
|
|
|
// The clip only has 100 frames, so requesting the 101th one produces an error.
|
|
node.get_frame_async(100, move |frame, n, node| {
|
|
assert!(frame.is_err());
|
|
assert_eq!(n, 100);
|
|
assert_eq!(
|
|
node.info().framerate,
|
|
Property::Constant(Framerate {
|
|
numerator: 60,
|
|
denominator: 1,
|
|
})
|
|
);
|
|
|
|
assert_eq!(tx.send(()), Ok(()));
|
|
});
|
|
|
|
assert_eq!(rx.recv(), Ok(()));
|
|
}
|
|
|
|
#[test]
|
|
fn core() {
|
|
let env =
|
|
vsscript::Environment::from_file("test-vpy/green.vpy", vsscript::EvalFlags::Nothing)
|
|
.unwrap();
|
|
|
|
let core = env.get_core();
|
|
assert!(core.is_ok());
|
|
let core = core.unwrap();
|
|
|
|
let yuv420p8 = core.get_format(PresetFormat::YUV420P8.into());
|
|
assert!(yuv420p8.is_some());
|
|
let yuv420p8 = yuv420p8.unwrap();
|
|
|
|
assert_eq!(yuv420p8.id(), PresetFormat::YUV420P8.into());
|
|
assert_eq!(yuv420p8.name(), "YUV420P8");
|
|
assert_eq!(yuv420p8.plane_count(), 3);
|
|
assert_eq!(yuv420p8.color_family(), ColorFamily::YUV);
|
|
assert_eq!(yuv420p8.sample_type(), SampleType::Integer);
|
|
assert_eq!(yuv420p8.bits_per_sample(), 8);
|
|
assert_eq!(yuv420p8.bytes_per_sample(), 1);
|
|
assert_eq!(yuv420p8.sub_sampling_w(), 1);
|
|
assert_eq!(yuv420p8.sub_sampling_h(), 1);
|
|
|
|
let yuv422p8 = core.get_format(PresetFormat::YUV422P8.into()).unwrap();
|
|
assert_eq!(yuv422p8.sub_sampling_w(), 1);
|
|
assert_eq!(yuv422p8.sub_sampling_h(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn plugins() {
|
|
let env =
|
|
vsscript::Environment::from_file("test-vpy/green.vpy", vsscript::EvalFlags::Nothing)
|
|
.unwrap();
|
|
|
|
fn bind<'a, T: ?Sized, U: ?Sized>(_: &'a T, x: &'a U) -> &'a U {
|
|
x
|
|
}
|
|
|
|
let core = env.get_core().unwrap();
|
|
let plugins = core.plugins();
|
|
let ids: Vec<_> = plugins
|
|
.keys()
|
|
.filter_map(|key| unsafe {
|
|
bind(
|
|
key,
|
|
CStr::from_ptr(plugins.get_data(key).unwrap().as_ptr() as _),
|
|
).to_str()
|
|
.ok()
|
|
}).filter_map(|id| id.split(';').nth(1))
|
|
.collect();
|
|
assert!(ids.contains(&"com.vapoursynth.std"));
|
|
assert!(ids.contains(&"com.vapoursynth.resize"));
|
|
|
|
let std = core.get_plugin_by_id("com.vapoursynth.std");
|
|
assert!(std.is_ok());
|
|
let std = std.unwrap();
|
|
assert!(std.is_some());
|
|
let std = std.unwrap();
|
|
|
|
let functions = std.functions();
|
|
let names: Vec<_> = functions
|
|
.keys()
|
|
.filter_map(|key| unsafe {
|
|
bind(
|
|
key,
|
|
CStr::from_ptr(functions.get_data(key).unwrap().as_ptr() as _),
|
|
).to_str()
|
|
.ok()
|
|
.map(|value| (key, value))
|
|
}).filter_map(|(key, value)| value.split(';').nth(0).map(|name| (key, name)))
|
|
.collect();
|
|
assert!(names.contains(&("CropRel", "CropRel")));
|
|
|
|
#[cfg(feature = "gte-vsscript-api-31")]
|
|
let (node, _) = env.get_output(0).unwrap();
|
|
#[cfg(not(feature = "gte-vsscript-api-31"))]
|
|
let (node, _) = (env.get_output(0).unwrap(), None::<Node>);
|
|
|
|
let mut args = OwnedMap::new(API::get().unwrap());
|
|
args.set_node("clip", &node);
|
|
args.set_int("left", 100);
|
|
|
|
let rv = std.invoke("CropRel", &args).unwrap();
|
|
assert!(rv.error().is_none());
|
|
|
|
let node = rv.get_node("clip");
|
|
assert!(node.is_ok());
|
|
let node = node.unwrap();
|
|
|
|
let frame = node.get_frame(0).unwrap();
|
|
assert_eq!(
|
|
frame.resolution(0),
|
|
Resolution {
|
|
width: 1820,
|
|
height: 1080,
|
|
}
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn functions() {
|
|
let env =
|
|
vsscript::Environment::from_file("test-vpy/green.vpy", vsscript::EvalFlags::Nothing)
|
|
.unwrap();
|
|
|
|
let core = env.get_core().unwrap();
|
|
let api = API::get().unwrap();
|
|
|
|
let function = Function::new(api, core, |_api, _core, in_, out| {
|
|
assert_eq!(in_.get_int("hello").unwrap(), 1337);
|
|
out.set_int("there", 42).unwrap();
|
|
});
|
|
|
|
let mut in_ = OwnedMap::new(api);
|
|
let mut out = OwnedMap::new(api);
|
|
in_.set_int("hello", 1337).unwrap();
|
|
|
|
function.call(&in_, &mut out);
|
|
|
|
assert!(out.error().is_none());
|
|
assert_eq!(out.get_int("there").unwrap(), 42);
|
|
}
|
|
}
|
|
|
|
// We need either VSScript API 3.2 or the VapourSynth functions.
|
|
#[cfg(any(
|
|
feature = "vapoursynth-functions",
|
|
all(
|
|
feature = "vsscript-functions",
|
|
feature = "gte-vsscript-api-32"
|
|
)
|
|
))]
|
|
mod need_api {
|
|
use std::ffi::CString;
|
|
use std::sync::mpsc::{channel, Sender};
|
|
use std::sync::Mutex;
|
|
|
|
use super::*;
|
|
use prelude::*;
|
|
|
|
#[test]
|
|
fn maps() {
|
|
let mut map = OwnedMap::new(API::get().unwrap());
|
|
|
|
assert_eq!(map.key_count(), 0);
|
|
|
|
assert_eq!(map.touch("test_frame", ValueType::Frame), Ok(()));
|
|
assert_eq!(map.value_type("test_frame"), Ok(ValueType::Frame));
|
|
assert_eq!(map.value_count("test_frame"), Ok(0));
|
|
assert_eq!(
|
|
map.append_int("test_frame", 42),
|
|
Err(map::Error::WrongValueType)
|
|
);
|
|
assert_eq!(
|
|
map.append("test_frame", &42),
|
|
Err(map::Error::WrongValueType)
|
|
);
|
|
|
|
assert_eq!(map.set_int("i", 42), Ok(()));
|
|
assert_eq!(map.get_int("i"), Ok(42));
|
|
assert_eq!(map.append_int("i", 43), Ok(()));
|
|
assert_eq!(map.get_int("i"), Ok(42));
|
|
{
|
|
let iter = map.get_int_iter("i");
|
|
assert!(iter.is_ok());
|
|
let mut iter = iter.unwrap();
|
|
assert_eq!(iter.next(), Some(42));
|
|
assert_eq!(iter.next(), Some(43));
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
assert_eq!(map.set("i", &42), Ok(()));
|
|
assert_eq!(map.get("i"), Ok(42));
|
|
assert_eq!(map.append("i", &43), Ok(()));
|
|
assert_eq!(map.get("i"), Ok(42));
|
|
{
|
|
let iter = map.get_iter::<i64>("i");
|
|
assert!(iter.is_ok());
|
|
let mut iter = iter.unwrap();
|
|
assert_eq!(iter.next(), Some(42));
|
|
assert_eq!(iter.next(), Some(43));
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
#[cfg(feature = "gte-vapoursynth-api-31")]
|
|
{
|
|
assert_eq!(map.get_int_array("i"), Ok(&[42, 43][..]));
|
|
|
|
assert_eq!(map.set_int_array("ia", &[10, 20, 30]), Ok(()));
|
|
assert_eq!(map.get_int_array("ia"), Ok(&[10, 20, 30][..]));
|
|
}
|
|
|
|
assert_eq!(map.set_float("f", 42f64), Ok(()));
|
|
assert_eq!(map.get_float("f"), Ok(42f64));
|
|
assert_eq!(map.append_float("f", 43f64), Ok(()));
|
|
assert_eq!(map.get_float("f"), Ok(42f64));
|
|
{
|
|
let iter = map.get_float_iter("f");
|
|
assert!(iter.is_ok());
|
|
let mut iter = iter.unwrap();
|
|
assert_eq!(iter.next(), Some(42f64));
|
|
assert_eq!(iter.next(), Some(43f64));
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
assert_eq!(map.set("f", &42f64), Ok(()));
|
|
assert_eq!(map.get("f"), Ok(42f64));
|
|
assert_eq!(map.append("f", &43f64), Ok(()));
|
|
assert_eq!(map.get("f"), Ok(42f64));
|
|
{
|
|
let iter = map.get_iter::<f64>("f");
|
|
assert!(iter.is_ok());
|
|
let mut iter = iter.unwrap();
|
|
assert_eq!(iter.next(), Some(42f64));
|
|
assert_eq!(iter.next(), Some(43f64));
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
#[cfg(feature = "gte-vapoursynth-api-31")]
|
|
{
|
|
assert_eq!(map.get_float_array("f"), Ok(&[42f64, 43f64][..]));
|
|
|
|
assert_eq!(map.set_float_array("fa", &[10f64, 20f64, 30f64]), Ok(()));
|
|
assert_eq!(map.get_float_array("fa"), Ok(&[10f64, 20f64, 30f64][..]));
|
|
}
|
|
|
|
assert_eq!(map.set_data("d", &[1, 2, 3]), Ok(()));
|
|
assert_eq!(map.get_data("d"), Ok(&[1, 2, 3][..]));
|
|
assert_eq!(map.append_data("d", &[4, 5, 6]), Ok(()));
|
|
assert_eq!(map.get_data("d"), Ok(&[1, 2, 3][..]));
|
|
{
|
|
let iter = map.get_data_iter("d");
|
|
assert!(iter.is_ok());
|
|
let mut iter = iter.unwrap();
|
|
assert_eq!(iter.next(), Some(&[1, 2, 3][..]));
|
|
assert_eq!(iter.next(), Some(&[4, 5, 6][..]));
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
assert_eq!(map.set("d", &&[1, 2, 3][..]), Ok(()));
|
|
assert_eq!(map.get("d"), Ok(&[1, 2, 3][..]));
|
|
assert_eq!(map.append("d", &&[4, 5, 6][..]), Ok(()));
|
|
assert_eq!(map.get("d"), Ok(&[1, 2, 3][..]));
|
|
{
|
|
let iter = map.get_iter::<&[u8]>("d");
|
|
assert!(iter.is_ok());
|
|
let mut iter = iter.unwrap();
|
|
assert_eq!(iter.next(), Some(&[1, 2, 3][..]));
|
|
assert_eq!(iter.next(), Some(&[4, 5, 6][..]));
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
// TODO: node, frame and function method tests when we can make them.
|
|
|
|
assert_eq!(map.delete_key("test_frame"), Ok(()));
|
|
assert_eq!(map.delete_key("test_frame"), Err(map::Error::KeyNotFound));
|
|
|
|
assert_eq!(map.error(), None);
|
|
assert_eq!(map.set_error("hello there"), Ok(()));
|
|
assert_eq!(
|
|
map.error().as_ref().map(|x| x.as_ref()),
|
|
Some("hello there")
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "gte-vapoursynth-api-34")]
|
|
#[test]
|
|
fn message_handler() {
|
|
let api = API::get().unwrap();
|
|
let (tx, rx) = channel();
|
|
|
|
// Hopefully no one logs anything here and breaks the test.
|
|
api.set_message_handler(move |message_type, message| {
|
|
assert_eq!(tx.send((message_type, message.to_owned())), Ok(()));
|
|
});
|
|
|
|
assert_eq!(
|
|
api.log(MessageType::Warning, "test warning message"),
|
|
Ok(())
|
|
);
|
|
assert_eq!(
|
|
rx.recv(),
|
|
Ok((
|
|
MessageType::Warning,
|
|
CString::new("test warning message").unwrap()
|
|
))
|
|
);
|
|
|
|
assert_eq!(api.log(MessageType::Debug, "test debug message"), Ok(()));
|
|
assert_eq!(
|
|
rx.recv(),
|
|
Ok((
|
|
MessageType::Debug,
|
|
CString::new("test debug message").unwrap()
|
|
))
|
|
);
|
|
|
|
assert_eq!(
|
|
api.log(MessageType::Critical, "test critical message"),
|
|
Ok(())
|
|
);
|
|
assert_eq!(
|
|
rx.recv(),
|
|
Ok((
|
|
MessageType::Critical,
|
|
CString::new("test critical message").unwrap()
|
|
))
|
|
);
|
|
|
|
{
|
|
lazy_static! {
|
|
static ref SENDER: Mutex<Option<Sender<(MessageType, CString)>>> = Mutex::new(None);
|
|
}
|
|
|
|
let (tx, rx) = channel();
|
|
*SENDER.lock().unwrap() = Some(tx);
|
|
|
|
api.set_message_handler_trivial(|message_type, message| {
|
|
let guard = SENDER.lock().unwrap();
|
|
let tx = guard.as_ref().unwrap();
|
|
assert_eq!(tx.send((message_type, message.to_owned())), Ok(()));
|
|
});
|
|
|
|
assert_eq!(
|
|
api.log(MessageType::Warning, "test warning message"),
|
|
Ok(())
|
|
);
|
|
assert_eq!(
|
|
rx.recv(),
|
|
Ok((
|
|
MessageType::Warning,
|
|
CString::new("test warning message").unwrap()
|
|
))
|
|
);
|
|
|
|
assert_eq!(api.log(MessageType::Debug, "test debug message"), Ok(()));
|
|
assert_eq!(
|
|
rx.recv(),
|
|
Ok((
|
|
MessageType::Debug,
|
|
CString::new("test debug message").unwrap()
|
|
))
|
|
);
|
|
|
|
assert_eq!(
|
|
api.log(MessageType::Critical, "test critical message"),
|
|
Ok(())
|
|
);
|
|
assert_eq!(
|
|
rx.recv(),
|
|
Ok((
|
|
MessageType::Critical,
|
|
CString::new("test critical message").unwrap()
|
|
))
|
|
);
|
|
}
|
|
|
|
api.clear_message_handler();
|
|
}
|
|
}
|