use crate::*;
use crate::aegp::*;
use ae_sys::AEGP_ItemH;
define_suite!(
ItemSuite,
AEGP_ItemSuite9,
kAEGPItemSuite,
kAEGPItemSuiteVersion9
);
impl ItemSuite {
pub fn new() -> Result<Self, Error> {
crate::Suite::new()
}
pub fn first_proj_item(&self, project_handle: &ProjectHandle) -> Result<ItemHandle, Error> {
Ok(ItemHandle::from_raw(
call_suite_fn_single!(self, AEGP_GetFirstProjItem -> ae_sys::AEGP_ItemH, project_handle.as_ptr())?
))
}
pub fn next_proj_item(&self, project_handle: &ProjectHandle, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<Option<ItemHandle>, Error> {
let next_item = call_suite_fn_single!(self, AEGP_GetNextProjItem -> ae_sys::AEGP_ItemH, project_handle.as_ptr(), item_handle.as_ptr())?;
if next_item.is_null() {
Ok(None)
} else {
Ok(Some(ItemHandle::from_raw(next_item)))
}
}
pub fn active_item(&self) -> Result<Option<ItemHandle>, Error> {
let item_handle = call_suite_fn_single!(self, AEGP_GetActiveItem -> ae_sys::AEGP_ItemH)?;
if item_handle.is_null() {
Ok(None)
} else {
Ok(Some(ItemHandle::from_raw(item_handle)))
}
}
pub fn is_item_selected(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<bool, Error> {
Ok(call_suite_fn_single!(self, AEGP_IsItemSelected -> ae_sys::A_Boolean, item_handle.as_ptr())? != 0)
}
pub fn select_item(&self, item_handle: impl AsPtr<AEGP_ItemH>, select: bool, deselect_others: bool) -> Result<(), Error> {
call_suite_fn!(self, AEGP_SelectItem, item_handle.as_ptr(), select.into(), deselect_others.into())
}
pub fn item_type(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<ItemType, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetItemType -> ae_sys::AEGP_ItemType, item_handle.as_ptr())?.into())
}
pub fn type_name(&self, item_type: ItemType) -> Result<String, Error> {
let mut buffer = [0i8; ae_sys::AEGP_MAX_TYPE_NAME_SIZE as _];
call_suite_fn!(self, AEGP_GetTypeName, item_type.into(), buffer.as_mut_ptr() as *mut _)?;
Ok(unsafe { std::ffi::CStr::from_ptr(buffer.as_ptr()) }.to_string_lossy().into_owned())
}
pub fn item_name(&self, item_handle: impl AsPtr<AEGP_ItemH>, plugin_id: PluginId) -> Result<String, Error> {
let mem_handle = call_suite_fn_single!(self, AEGP_GetItemName -> ae_sys::AEGP_MemHandle, plugin_id, item_handle.as_ptr())?;
Ok(unsafe {
U16CString::from_ptr_str(
MemHandle::<u16>::from_raw(mem_handle)?.lock()?.as_ptr(),
).to_string_lossy()
})
}
pub fn set_item_name(&self, item_handle: impl AsPtr<AEGP_ItemH>, name: &str) -> Result<(), Error> {
let name = U16CString::from_str(name).map_err(|_| Error::InvalidParms)?;
call_suite_fn!(self, AEGP_SetItemName, item_handle.as_ptr(), name.as_ptr())
}
pub fn item_id(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<ItemId, Error> {
call_suite_fn_single!(self, AEGP_GetItemID -> ItemId, item_handle.as_ptr())
}
pub fn item_flags(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<ItemFlags, Error> {
Ok(ItemFlags::from_bits_truncate(
call_suite_fn_single!(self, AEGP_GetItemFlags -> ae_sys::A_long, item_handle.as_ptr())? as _
))
}
pub fn set_item_use_proxy(&self, item_handle: impl AsPtr<AEGP_ItemH>, use_proxy: bool) -> Result<(), Error> {
call_suite_fn!(self, AEGP_SetItemUseProxy, item_handle.as_ptr(), use_proxy.into())
}
pub fn item_parent_folder(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<Option<ItemHandle>, Error> {
let parent_folder = call_suite_fn_single!(self, AEGP_GetItemParentFolder -> ae_sys::AEGP_ItemH, item_handle.as_ptr())?;
if parent_folder.is_null() {
Ok(None)
} else {
Ok(Some(ItemHandle::from_raw(parent_folder)))
}
}
pub fn set_item_parent_folder(&self, item_handle: impl AsPtr<AEGP_ItemH>, parent_folder: &ItemHandle) -> Result<(), Error> {
call_suite_fn!(self, AEGP_SetItemParentFolder, item_handle.as_ptr(), parent_folder.as_ptr())
}
pub fn item_duration(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<Time, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetItemDuration -> ae_sys::A_Time, item_handle.as_ptr())?.into())
}
pub fn item_current_time(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<Time, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetItemCurrentTime -> ae_sys::A_Time, item_handle.as_ptr())?.into())
}
pub fn item_dimensions(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<(u32, u32), Error> {
let (width, height) = call_suite_fn_double!(self, AEGP_GetItemDimensions -> ae_sys::A_long, ae_sys:: A_long, item_handle.as_ptr())?;
Ok((
width as _,
height as _
))
}
pub fn item_pixel_aspect_ratio(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<Ratio, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetItemPixelAspectRatio -> ae_sys::A_Ratio, item_handle.as_ptr())?.into())
}
pub fn delete_item(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<(), Error> {
call_suite_fn!(self, AEGP_DeleteItem, item_handle.as_ptr())
}
pub fn create_new_folder(&self, name: &str, parent_folder: Option<ItemHandle>) -> Result<ItemHandle, Error> {
let name = U16CString::from_str(name).map_err(|_| Error::InvalidParms)?;
Ok(ItemHandle::from_raw(
call_suite_fn_single!(self,
AEGP_CreateNewFolder -> ae_sys::AEGP_ItemH,
name.as_ptr(),
parent_folder.as_ref().map_or(std::ptr::null_mut(), |f| f.as_ptr())
)?
))
}
pub fn set_item_current_time(&self, item_handle: impl AsPtr<AEGP_ItemH>, new_time: Time) -> Result<(), Error> {
call_suite_fn!(self, AEGP_SetItemCurrentTime, item_handle.as_ptr(), &new_time.into())
}
pub fn item_comment(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<String, Error> {
let mem_handle = call_suite_fn_single!(self, AEGP_GetItemComment -> ae_sys::AEGP_MemHandle, item_handle.as_ptr())?;
Ok(unsafe {
U16CString::from_ptr_str(
MemHandle::<u16>::from_raw(mem_handle)?.lock()?.as_ptr(),
).to_string_lossy()
})
}
pub fn set_item_comment(&self, item_handle: impl AsPtr<AEGP_ItemH>, comment: &str) -> Result<(), Error> {
let comment = U16CString::from_str(comment).map_err(|_| Error::InvalidParms)?;
call_suite_fn!(self, AEGP_SetItemComment, item_handle.as_ptr(), comment.as_ptr())
}
pub fn item_label(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<LabelId, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetItemLabel -> ae_sys::AEGP_LabelID, item_handle.as_ptr())?.into())
}
pub fn set_item_label(&self, item_handle: impl AsPtr<AEGP_ItemH>, label: LabelId) -> Result<(), Error> {
call_suite_fn!(self, AEGP_SetItemLabel, item_handle.as_ptr(), label.into())
}
pub fn item_mru_view(&self, item_handle: impl AsPtr<AEGP_ItemH>) -> Result<ae_sys::AEGP_ItemViewP, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetItemMRUView -> ae_sys::AEGP_ItemViewP, item_handle.as_ptr())?.into())
}
}
register_handle!(AEGP_ItemH);
define_handle_wrapper!(ItemHandle, AEGP_ItemH);
define_enum! {
ae_sys::AEGP_ItemType,
ItemType {
None = ae_sys::AEGP_ItemType_NONE,
Folder = ae_sys::AEGP_ItemType_FOLDER,
Comp = ae_sys::AEGP_ItemType_COMP,
Solid = ae_sys::AEGP_ItemType_SOLID_defunct,
Footage = ae_sys::AEGP_ItemType_FOOTAGE,
}
}
define_enum! {
ae_sys::AEGP_LabelID,
LabelId {
None = ae_sys::AEGP_Label_NONE,
NoLabel = ae_sys::AEGP_Label_NO_LABEL,
Label1 = ae_sys::AEGP_Label_1,
Label2 = ae_sys::AEGP_Label_2,
Label3 = ae_sys::AEGP_Label_3,
Label4 = ae_sys::AEGP_Label_4,
Label5 = ae_sys::AEGP_Label_5,
Label6 = ae_sys::AEGP_Label_6,
Label7 = ae_sys::AEGP_Label_7,
Label8 = ae_sys::AEGP_Label_8,
Label9 = ae_sys::AEGP_Label_9,
Label10 = ae_sys::AEGP_Label_10,
Label11 = ae_sys::AEGP_Label_11,
Label12 = ae_sys::AEGP_Label_12,
Label13 = ae_sys::AEGP_Label_13,
Label14 = ae_sys::AEGP_Label_14,
Label15 = ae_sys::AEGP_Label_15,
Label16 = ae_sys::AEGP_Label_16,
}
}
bitflags::bitflags! {
pub struct ItemFlags: ae_sys::A_long {
const MISSING = ae_sys::AEGP_ItemFlag_MISSING as ae_sys::A_long;
const HAS_PROXY = ae_sys::AEGP_ItemFlag_HAS_PROXY as ae_sys::A_long;
const USING_PROXY = ae_sys::AEGP_ItemFlag_USING_PROXY as ae_sys::A_long;
const MISSING_PROXY = ae_sys::AEGP_ItemFlag_MISSING_PROXY as ae_sys::A_long;
const HAS_VIDEO = ae_sys::AEGP_ItemFlag_HAS_VIDEO as ae_sys::A_long;
const HAS_AUDIO = ae_sys::AEGP_ItemFlag_HAS_AUDIO as ae_sys::A_long;
const STILL = ae_sys::AEGP_ItemFlag_STILL as ae_sys::A_long;
const HAS_ACTIVE_AUDIO = ae_sys::AEGP_ItemFlag_HAS_ACTIVE_AUDIO as ae_sys::A_long;
}
}
define_suite_item_wrapper!(
ae_sys::AEGP_ItemH, ItemHandle,
suite: ItemSuite,
footage: aegp::suites::Footage,
comp: aegp::suites::Comp,
Item {
dispose: ;
is_selected() -> bool => suite.is_item_selected,
select(select: bool, deselect_others: bool) -> () => suite.select_item,
item_type() -> ItemType => suite.item_type,
name(plugin_id: PluginId) -> String => suite.item_name,
set_name(name: &str) -> () => suite.set_item_name,
id() -> ItemId => suite.item_id,
flags() -> ItemFlags => suite.item_flags,
set_use_proxy(use_proxy: bool) -> () => suite.set_item_use_proxy,
parent_folder() -> Option<ItemHandle> => suite.item_parent_folder,
set_parent_folder(parent_folder: &ItemHandle) -> () => suite.set_item_parent_folder,
duration() -> Time => suite.item_duration,
current_time() -> Time => suite.item_current_time,
dimensions() -> (u32, u32) => suite.item_dimensions,
pixel_aspect_ratio() -> Ratio => suite.item_pixel_aspect_ratio,
delete() -> () => suite.delete_item,
set_current_time(new_time: Time) -> () => suite.set_item_current_time,
comment() -> String => suite.item_comment,
set_comment(comment: &str) -> () => suite.set_item_comment,
label() -> LabelId => suite.item_label,
set_label(label: LabelId) -> () => suite.set_item_label,
mru_view() -> ae_sys::AEGP_ItemViewP => suite.item_mru_view,
main_footage() -> Footage => footage.main_footage_from_item,
proxy_footage() -> Footage => footage.proxy_footage_from_item,
set_proxy_footage(footage: impl AsPtr<ae_sys::AEGP_FootageH>) -> () => footage.set_item_proxy_footage,
replace_main_footage(footage: impl AsPtr<ae_sys::AEGP_FootageH>) -> () => footage.replace_item_main_footage,
footage_interpretation(proxy: bool) -> ae_sys::AEGP_FootageInterp => footage.footage_interpretation,
set_footage_interpretation(proxy: bool, interp: &ae_sys::AEGP_FootageInterp) -> () => footage.set_footage_interpretation,
solid_footage_color(proxy: bool) -> ae_sys::AEGP_ColorVal => footage.solid_footage_color,
set_solid_footage_color(proxy: bool, color: &ae_sys::AEGP_ColorVal) -> () => footage.set_solid_footage_color,
set_solid_footage_dimensions(proxy: bool, width: i32, height: i32) -> () => footage.set_solid_footage_dimensions,
}
);
impl Item {
pub fn type_name(&self) -> Result<String, Error> {
let Ok(ref suite) = *self.suite else { return Err(Error::MissingSuite); };
suite.type_name(self.item_type()?)
}
pub fn create_folder_inside(&self, name: &str) -> Result<Item, Error> {
let Ok(ref suite) = *self.suite else { return Err(Error::MissingSuite); };
Ok(Item::from_handle(
suite.create_new_folder(name, Some(self.handle))?,
false
))
}
pub fn composition(&self) -> Result<Composition, Error> {
if self.item_type()? == ItemType::Comp {
let Ok(ref comp) = *self.comp else { return Err(Error::MissingSuite); };
Ok(comp.comp_from_item(self.as_ptr())?.unwrap().into())
} else {
Err(Error::Parameter)
}
}
pub fn render_options(&self, plugin_id: PluginId) -> Result<aegp::RenderOptions, Error> {
aegp::RenderOptions::from_item(self.handle.as_ptr(), plugin_id)
}
}