use crate::ae_sys::AEGP_ItemH;
use crate::aegp::*;
use crate::*;
use after_effects_sys::{AEGP_ProjectH, AEGP_TimeDisplay3};
define_suite!(
ProjectSuite,
AEGP_ProjSuite6,
kAEGPProjSuite,
kAEGPProjSuiteVersion6
);
impl ProjectSuite {
pub fn new() -> Result<Self, Error> { crate::Suite::new() }
pub fn num_projects(&self) -> Result<i32, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetNumProjects -> ae_sys::A_long)?.into())
}
pub fn project_by_index(&self, proj_index: i32) -> Result<ProjectHandle, Error> {
Ok(ProjectHandle::from_raw(
call_suite_fn_single!( self, AEGP_GetProjectByIndex -> AEGP_ProjectH, proj_index)?,
))
}
pub fn project_time_display_config(&self, proj_handle: ProjectHandle) -> Result<TimeDisplayConfig, Error> {
Ok(call_suite_fn_single!( self, AEGP_GetProjectTimeDisplay -> AEGP_TimeDisplay3, proj_handle.into())?.into())
}
pub fn set_project_time_display_config(&self, proj_handle: ProjectHandle, config: TimeDisplayConfig) -> Result<(), Error> {
let config: AEGP_TimeDisplay3 = config.into();
call_suite_fn!( self, AEGP_SetProjectTimeDisplay, proj_handle.into(), &config)?;
Ok(())
}
pub fn project_name(&self, proj_handle: ProjectHandle) -> Result<String, Error> {
let mut buffer = [0i8; (ae_sys::AEGP_MAX_PROJ_NAME_SIZE + 1) as _];
call_suite_fn!(self, AEGP_GetProjectName, proj_handle.into(), buffer.as_mut_ptr() as *mut _)?;
Ok(unsafe { std::ffi::CStr::from_ptr(buffer.as_ptr()) }.to_string_lossy().into_owned())
}
pub fn project_path(&self, proj_handle: ProjectHandle) -> Result<String, Error> {
let mem_handle = call_suite_fn_single!(self, AEGP_GetProjectPath -> ae_sys::AEGP_MemHandle, proj_handle.into())?;
Ok(unsafe {
U16CString::from_ptr_str(MemHandle::<u16>::from_raw(mem_handle)?.lock()?.as_ptr()).to_string_lossy()
})
}
pub fn project_is_dirty(&self, proj_handle: ProjectHandle) -> Result<bool, Error> {
Ok(call_suite_fn_single!(self, AEGP_ProjectIsDirty -> ae_sys::A_Boolean, proj_handle.into())? != 0)
}
pub fn save_project_to_path(&self, proj_handle: ProjectHandle, path: &str) -> Result<(), Error> {
let path = widestring::U16CString::from_str(path).map_err(|_| Error::InvalidParms)?;
call_suite_fn!(self, AEGP_SaveProjectToPath, proj_handle.into(), path.as_ptr())?;
Ok(())
}
pub fn save_project_as(&self, proj_handle: ProjectHandle, path: &str) -> Result<(), Error> {
let path = widestring::U16CString::from_str(path).map_err(|_| Error::InvalidParms)?;
call_suite_fn!(self, AEGP_SaveProjectAs, proj_handle.into(), path.as_ptr())?;
Ok(())
}
pub fn project_root_folder(&self, proj_handle: ProjectHandle) -> Result<ItemHandle, Error> {
Ok(ItemHandle::from_raw(
call_suite_fn_single!(self, AEGP_GetProjectRootFolder -> AEGP_ItemH, proj_handle.into())?,
))
}
pub fn open_project_from_path(&self, path: &str) -> Result<ProjectHandle, Error> {
let path = widestring::U16CString::from_str(path).map_err(|_| Error::InvalidParms)?;
Ok(ProjectHandle::from_raw(call_suite_fn_single!(self, AEGP_OpenProjectFromPath -> AEGP_ProjectH, path.as_ptr())?))
}
pub fn new_project(&self) -> Result<ProjectHandle, Error> {
Ok(ProjectHandle::from_raw(call_suite_fn_single!(self, AEGP_NewProject -> AEGP_ProjectH)?))
}
pub fn project_bit_depth(
&self,
proj_handle: ProjectHandle,
) -> Result<ProjectBitDepth, Error> {
Ok(call_suite_fn_single!( self, AEGP_GetProjectBitDepth -> ae_sys::A_char, proj_handle.into())?.into())
}
pub fn set_project_bit_depth(
&self,
proj_handle: ProjectHandle,
bit_depth: ProjectBitDepth,
) -> Result<(), Error> {
Ok(call_suite_fn!(self, AEGP_SetProjectBitDepth, proj_handle.into(), bit_depth.into())?.into())
}
}
register_handle!(AEGP_ProjectH);
define_handle_wrapper!(ProjectHandle, AEGP_ProjectH);
define_enum! {
ae_sys::AEGP_ProjBitDepth,
ProjectBitDepth {
BitDepthU8 = ae_sys::AEGP_ProjBitDepth_8,
BitDepthU16 = ae_sys::AEGP_ProjBitDepth_16,
BitDepthF32 = ae_sys::AEGP_ProjBitDepth_32,
}
}
define_enum! {
ae_sys::AEGP_SourceTimecodeDisplayMode,
SourceTimecodeDisplayMode {
SourceTimeCode = ae_sys::AEGP_SourceTimecode_SOURCE_TIMECODE,
Zero = ae_sys::AEGP_SourceTimecode_ZERO,
}
}
define_enum! {
ae_sys::AEGP_TimeDisplayMode,
TimeDisplayMode {
TimeCode = ae_sys::AEGP_TimeDisplay_TIMECODE,
Frames = ae_sys::AEGP_TimeDisplay_FRAMES,
}
}
define_enum! {
ae_sys::AEGP_FramesDisplayMode,
FrameDisplayMode {
ZeroBased = ae_sys::AEGP_Frames_ZERO_BASED,
OneBased = ae_sys::AEGP_Frames_ONE_BASED,
TimeCodeConversion = ae_sys::AEGP_Frames_TIMECODE_CONVERSION,
}
}
#[derive(Debug, Copy, Clone)]
pub struct TimeDisplayConfig {
pub source_timecode_display_mode: SourceTimecodeDisplayMode,
pub footage_display_mode: TimeDisplayMode,
pub display_drop_frames: bool,
pub use_feet_frames: bool,
pub time_base: u8,
pub frames_per_foot: u8,
pub frame_display_mode: FrameDisplayMode,
}
impl Into<ae_sys::AEGP_TimeDisplay3> for TimeDisplayConfig {
fn into(self) -> ae_sys::AEGP_TimeDisplay3 {
ae_sys::AEGP_TimeDisplay3 {
display_mode: self.source_timecode_display_mode.into(),
footage_display_mode: self.footage_display_mode.into(),
display_dropframeB: self.display_drop_frames.into(),
use_feet_framesB: self.use_feet_frames.into(),
timebaseC: self.time_base as ae_sys::A_char,
frames_per_footC: self.frames_per_foot as ae_sys::A_char,
frames_display_mode: self.frame_display_mode.into(),
}
}
}
impl From<ae_sys::AEGP_TimeDisplay3> for TimeDisplayConfig {
fn from(time_display: ae_sys::AEGP_TimeDisplay3) -> Self {
Self {
source_timecode_display_mode: time_display.display_mode.into(),
footage_display_mode: time_display.footage_display_mode.into(),
display_drop_frames: time_display.display_dropframeB != 0,
use_feet_frames: time_display.use_feet_framesB != 0,
time_base: time_display.timebaseC as u8,
frames_per_foot: time_display.frames_per_footC as u8,
frame_display_mode: time_display.frames_display_mode.into(),
}
}
}