,
351 | {
352 | self.get_at::(0)
353 | }
354 |
355 | fn get_at
(&self, index: usize) -> Result
356 | where
357 | P: Named + Get,
358 | P::ReturnType: ValueType + Sized + Getter,
359 | {
360 | >::get_at(self, index)
361 | }
362 | }
363 |
364 | pub trait RawReadable: AsProperties + Sized + Clone {
365 | #[inline]
366 | fn get_raw(&self, id: I) -> Result
367 | where
368 | I: StringId,
369 | R: ValueType + Sized + RawGetter,
370 | {
371 | self.get_raw_at(id, 0)
372 | }
373 |
374 | fn get_raw_at(&self, id: I, index: usize) -> Result
375 | where
376 | I: StringId,
377 | R: ValueType + Sized + RawGetter,
378 | {
379 | let c_buf = id.c_string()?;
380 | let c_name = c_buf.as_ptr();
381 | >::get_at(&self, c_name, index)
382 | }
383 | }
384 |
385 | pub trait Writable: AsProperties + Sized + Clone {
386 | #[inline]
387 | fn set(&mut self, new_value: &P::ValueType) -> Result<()>
388 | where
389 | P: Named + Set,
390 | P::ValueType: ValueType + Setter,
391 | {
392 | self.set_at::(0, new_value)
393 | }
394 |
395 | fn set_at
(&mut self, index: usize, new_value: &P::ValueType) -> Result<()>
396 | where
397 | P: Named + Set,
398 | P::ValueType: ValueType + Setter,
399 | {
400 | >::set_at(self, index, new_value)
401 | }
402 | }
403 |
404 | pub trait RawWritable: AsProperties + Sized + Clone {
405 | #[inline]
406 | fn set_raw(&mut self, id: I, new_value: &V) -> Result<()>
407 | where
408 | I: StringId,
409 | V: ValueType + RawSetter + ?Sized + Debug,
410 | {
411 | self.set_raw_at(id, 0, new_value)
412 | }
413 |
414 | fn set_raw_at(&mut self, id: I, index: usize, new_value: &V) -> Result<()>
415 | where
416 | I: StringId,
417 | V: ValueType + RawSetter + ?Sized + Debug,
418 | {
419 | let buf = id.c_string()?;
420 | let c_name = buf.as_ptr();
421 | >::set_at(self, c_name, index, new_value)
422 | }
423 | }
424 |
425 | impl Readable for R where R: AsProperties + Clone {}
426 |
427 | impl Writable for W where W: AsProperties + ?Sized + Clone {}
428 |
429 | pub trait StringId {
430 | fn c_string(self) -> Result;
431 | }
432 |
433 | impl StringId for &str {
434 | fn c_string(self) -> Result {
435 | Ok(CString::new(self)?)
436 | }
437 | }
438 |
439 | impl StringId for &[u8] {
440 | fn c_string(self) -> Result {
441 | Ok(CStr::from_bytes_with_nul(self)
442 | .map_err(|_| Error::InvalidNameEncoding)?
443 | .to_owned())
444 | }
445 | }
446 |
447 | pub trait ValueType {}
448 | impl ValueType for Bool {}
449 | impl ValueType for Int {}
450 | impl ValueType for Double {}
451 | impl ValueType for PointI {}
452 | impl ValueType for PointD {}
453 | impl ValueType for RangeI {}
454 | impl ValueType for RangeD {}
455 | impl ValueType for RectI {}
456 | impl ValueType for RectD {}
457 | impl ValueType for String {}
458 | impl ValueType for str {}
459 | impl ValueType for [u8] {}
460 | impl ValueType for CharPtr {}
461 | impl ValueType for VoidPtr {}
462 | impl ValueType for VoidPtrMut {}
463 | impl ValueType for CString {}
464 |
465 | type StaticName = &'static [u8];
466 | pub trait Named {
467 | fn name() -> StaticName;
468 | }
469 |
470 | pub trait Get: Named {
471 | type ReturnType: ValueType;
472 | }
473 |
474 | pub trait Set: Named {
475 | type ValueType: ValueType + ?Sized;
476 | }
477 |
478 | pub trait RawGetter
479 | where
480 | Self: ValueType + Sized,
481 | R: Readable + AsProperties,
482 | {
483 | fn get_at(readable: &R, name: CharPtr, index: usize) -> Result;
484 | }
485 |
486 | raw_getter_impl! { |readable, c_name, index| -> Bool {
487 | let mut c_int_out: Int = 0;
488 | to_result! { suite_call!(propGetInt in *readable.suite(); readable.handle(), c_name, index as Int, &mut c_int_out as *mut Int)
489 | => c_int_out != 0 }
490 | }}
491 |
492 | raw_getter_impl! { |readable, c_name, index| -> VoidPtr {
493 | let mut c_ptr_out: *mut std::ffi::c_void = std::ptr::null_mut();
494 | to_result! { suite_call!(propGetPointer in *readable.suite(); readable.handle(), c_name, index as Int, &mut c_ptr_out as *mut VoidPtrMut)
495 | => c_ptr_out as VoidPtr }
496 | }}
497 |
498 | raw_getter_impl! { |readable, c_name, index| -> VoidPtrMut {
499 | let mut c_ptr_out: *mut std::ffi::c_void = std::ptr::null_mut();
500 | to_result! { suite_call!(propGetPointer in *readable.suite(); readable.handle(), c_name, index as Int, &mut c_ptr_out as *mut VoidPtrMut)
501 | => c_ptr_out as VoidPtrMut }
502 | }}
503 |
504 | raw_getter_impl! { |readable, c_name, index| -> Int {
505 | let mut c_int_out: Int = 0;
506 | to_result! { suite_call!(propGetInt in *readable.suite(); readable.handle(), c_name, index as Int, &mut c_int_out as *mut Int)
507 | => c_int_out }
508 | }}
509 |
510 | raw_getter_impl! { |readable, c_name, index| -> PointI {
511 | let mut c_struct_out: PointI = unsafe { std::mem::zeroed() };
512 | to_result! { suite_call!(propGetIntN in *readable.suite(); readable.handle(), c_name, POINT_ELEMENTS, &mut c_struct_out.x as *mut Int)
513 | => c_struct_out}
514 | }}
515 |
516 | raw_getter_impl! { |readable, c_name, index| -> RangeI {
517 | let mut c_struct_out: RangeI = unsafe { std::mem::zeroed() };
518 | to_result! { suite_call!(propGetIntN in *readable.suite(); readable.handle(), c_name, RANGE_ELEMENTS, &mut c_struct_out.min as *mut Int)
519 | => c_struct_out}
520 | }}
521 |
522 | raw_getter_impl! { |readable, c_name, index| -> RectI {
523 | let mut c_struct_out: RectI = unsafe { std::mem::zeroed() };
524 | to_result! { suite_call!(propGetIntN in *readable.suite(); readable.handle(), c_name, RECT_ELEMENTS, &mut c_struct_out.x1 as *mut Int)
525 | => c_struct_out}
526 | }}
527 |
528 | raw_getter_impl! { |readable, c_name, index| -> Double {
529 | let mut c_double_out: Double = 0.0;
530 | to_result! { suite_call!(propGetDouble in *readable.suite(); readable.handle(), c_name, index as Int, &mut c_double_out as *mut Double)
531 | => c_double_out}
532 | }}
533 |
534 | raw_getter_impl! { |readable, c_name, index| -> PointD {
535 | let mut c_struct_out: PointD = unsafe { std::mem::zeroed() };
536 | to_result! { suite_call!(propGetDoubleN in *readable.suite(); readable.handle(), c_name, POINT_ELEMENTS, &mut c_struct_out.x as *mut Double)
537 | => c_struct_out}
538 | }}
539 |
540 | raw_getter_impl! { |readable, c_name, index| -> RangeD {
541 | let mut c_struct_out: RangeD = unsafe { std::mem::zeroed() };
542 | to_result! { suite_call!(propGetDoubleN in *readable.suite(); readable.handle(), c_name, RANGE_ELEMENTS, &mut c_struct_out.min as *mut Double)
543 | => c_struct_out}
544 | }}
545 |
546 | raw_getter_impl! { |readable, c_name, index| -> RectD {
547 | let mut c_struct_out: RectD = unsafe { std::mem::zeroed() };
548 | to_result! { suite_call!(propGetDoubleN in *readable.suite(); readable.handle(), c_name, RECT_ELEMENTS, &mut c_struct_out.x1 as *mut Double)
549 | => c_struct_out}
550 | }}
551 |
552 | raw_getter_impl! { |readable, c_name, index| -> CString {
553 | let mut c_ptr_out: CharPtr = std::ptr::null();
554 | to_result! { suite_call!(propGetString in *readable.suite(); readable.handle(), c_name, index as Int, &mut c_ptr_out as *mut CharPtr)
555 | => unsafe { CStr::from_ptr(c_ptr_out).to_owned() }}
556 | }}
557 |
558 | raw_getter_impl! { |readable, c_name, index| -> String {
559 | let mut c_ptr_out: CharPtr = std::ptr::null();
560 | to_result! { suite_call!(propGetString in *readable.suite(); readable.handle(), c_name, index as Int, &mut c_ptr_out as *mut CharPtr)
561 | => unsafe { CStr::from_ptr(c_ptr_out).to_str()?.to_owned() }}
562 | }}
563 |
564 | pub trait Getter: RawGetter
565 | where
566 | Self: ValueType + Sized,
567 | R: Readable + AsProperties,
568 | P: Named + Get,
569 | {
570 | fn get_at(readable: &R, index: usize) -> Result {
571 | let c_name = P::name().as_ptr();
572 | RawGetter::get_at(readable, c_name as CharPtr, index)
573 | }
574 | }
575 |
576 | impl Getter for T
577 | where
578 | T: RawGetter,
579 | R: Readable + AsProperties,
580 | P: Named + Get,
581 | {
582 | }
583 |
584 | pub trait RawSetter
585 | where
586 | Self: ValueType,
587 | W: Writable + AsProperties,
588 | {
589 | fn set_at(writable: &mut W, name: CharPtr, index: usize, value: &Self) -> Result<()>;
590 | }
591 |
592 | raw_setter_impl! { |writable, c_name, index, value: &str| {
593 | let c_str_in = CString::new(value)?;
594 | let c_ptr_in = c_str_in.as_c_str().as_ptr();
595 | trace_setter!(writable.handle(), c_name, index, value);
596 | suite_fn!(propSetString in *writable.suite(); writable.handle(), c_name, index as Int, c_ptr_in as CharPtrMut)
597 | }}
598 |
599 | raw_setter_impl! { |writable, c_name, index, value: &[u8]| {
600 | trace_setter!(writable.handle(), c_name, index, str value);
601 | suite_fn!(propSetString in *writable.suite(); writable.handle(), c_name, index as Int, value.as_ptr() as CharPtrMut)
602 | }}
603 |
604 | raw_setter_impl! { |writable, c_name, index, value: &VoidPtr| {
605 | trace_setter!(writable.handle(), c_name, index, value);
606 | suite_fn!(propSetPointer in *writable.suite(); writable.handle(), c_name, index as Int, *value as VoidPtrMut)
607 | }}
608 |
609 | raw_setter_impl! { |writable, c_name, index, value: &Int| {
610 | trace_setter!(writable.handle(), c_name, index, value);
611 | suite_fn!(propSetInt in *writable.suite(); writable.handle(), c_name, index as Int, *value)
612 | }}
613 |
614 | raw_setter_impl! { |writable, c_name, index, value: &PointI| {
615 | trace_setter!(writable.handle(), c_name, index, value);
616 | suite_fn!(propSetIntN in *writable.suite(); writable.handle(), c_name, POINT_ELEMENTS, &value.x as *const Int)
617 | }}
618 |
619 | raw_setter_impl! { |writable, c_name, index, value: &RangeI| {
620 | trace_setter!(writable.handle(), c_name, index, value);
621 | suite_fn!(propSetIntN in *writable.suite(); writable.handle(), c_name, RANGE_ELEMENTS, &value.min as *const Int)
622 | }}
623 |
624 | raw_setter_impl! { |writable, c_name, index, value: &RectI| {
625 | trace_setter!(writable.handle(), c_name, index, value);
626 | suite_fn!(propSetIntN in *writable.suite(); writable.handle(), c_name, RECT_ELEMENTS, &value.x1 as *const Int)
627 | }}
628 |
629 | raw_setter_impl! { |writable, c_name, index, value: &Bool| {
630 | trace_setter!(writable.handle(), c_name, index, value);
631 | suite_fn!(propSetInt in *writable.suite(); writable.handle(), c_name, index as Int, if *value { 1 } else { 0 })
632 | }}
633 |
634 | raw_setter_impl! { |writable, c_name, index, value: &Double| {
635 | trace_setter!(writable.handle(), c_name, index, value);
636 | suite_fn!(propSetDouble in *writable.suite(); writable.handle(), c_name, index as Int, *value)
637 | }}
638 |
639 | raw_setter_impl! { |writable, c_name, index, value: &PointD| {
640 | trace_setter!(writable.handle(), c_name, index, value);
641 | suite_fn!(propSetDoubleN in *writable.suite(); writable.handle(), c_name, POINT_ELEMENTS, &value.x as *const Double)
642 | }}
643 |
644 | raw_setter_impl! { |writable, c_name, index, value: &RangeD| {
645 | trace_setter!(writable.handle(), c_name, index, value);
646 | suite_fn!(propSetDoubleN in *writable.suite(); writable.handle(), c_name, RANGE_ELEMENTS, &value.min as *const Double)
647 | }}
648 |
649 | raw_setter_impl! { |writable, c_name, index, value: &RectD| {
650 | trace_setter!(writable.handle(), c_name, index, value);
651 | suite_fn!(propSetDoubleN in *writable.suite(); writable.handle(), c_name, RECT_ELEMENTS, &value.x1 as *const Double)
652 | }}
653 |
654 | pub trait Setter: RawSetter
655 | where
656 | Self: ValueType + Debug,
657 | W: Writable + AsProperties,
658 | P: Named + Set,
659 | {
660 | fn set_at(writable: &mut W, index: usize, value: &Self) -> Result<()> {
661 | let property_name = P::name();
662 | let c_name = property_name.as_ptr();
663 | RawSetter::set_at(writable, c_name as CharPtr, index, value)
664 | }
665 | }
666 |
667 | impl Setter for T
668 | where
669 | T: RawSetter + ?Sized + Debug,
670 | W: Writable + AsProperties,
671 | P: Named + Set,
672 | {
673 | }
674 |
675 | mod tests {
676 | // just compiling
677 | use super::*;
678 | pub struct DummyProperty;
679 | impl Set for DummyProperty {
680 | type ValueType = [u8];
681 | }
682 | impl Named for DummyProperty {
683 | fn name() -> &'static [u8] {
684 | b"kOfxDummyProperty\0"
685 | }
686 | }
687 | pub trait CanSetDummyProperty: Writable {
688 | fn set_dummy_property<'a>(&mut self, value: &'a [u8]) -> Result<()> {
689 | self.set::(value)
690 | }
691 | }
692 | }
693 |
694 | property! { kOfxPluginPropFilePath as FilePath {
695 | get_file_path() -> String;
696 | }}
697 |
698 | property! { kOfxPropType as Type {
699 | get_type() -> CString as enum EType;
700 | }}
701 |
702 | property! { kOfxPropName as Name {
703 | get_name() -> String;
704 | set_name(&str);
705 | }}
706 |
707 | property! { kOfxPropLabel as Label {
708 | get_label() -> String;
709 | set_label(&str);
710 | }}
711 |
712 | property! { kOfxPropShortLabel as ShortLabel {
713 | get_short_label() -> String;
714 | set_short_label(&str);
715 | }}
716 |
717 | property! { kOfxPropLongLabel as LongLabel {
718 | get_long_label() -> String;
719 | set_long_label(&str);
720 | }}
721 |
722 | property! { kOfxPropVersion as Version {
723 | get_version() -> String;
724 | }}
725 |
726 | property! { kOfxPropVersionLabel as VersionLabel {
727 | get_version_label() -> String;
728 | }}
729 |
730 | property! { kOfxPropAPIVersion as APIVersion {
731 | get_api_version() -> String;
732 | }}
733 |
734 | property! { kOfxPropTime as Time {
735 | get_time() -> Double;
736 | set_time(Double);
737 | }}
738 |
739 | property! { kOfxPropIsInteractive as IsInteractive {
740 | get_is_interactive() -> Bool;
741 | }}
742 |
743 | property! { kOfxPropPluginDescription as PluginDescription {
744 | get_plugin_description() -> String;
745 | set_plugin_description(&str);
746 | }}
747 |
748 | property! { kOfxPropChangeReason as ChangeReason {
749 | get_change_reason() -> CString as enum Change;
750 | }}
751 |
752 | property! { kOfxPropHostOSHandle as HostOSHandle {
753 | get_host_os_handle() -> VoidPtrMut;
754 | }}
755 |
756 | property! { kOfxImageEffectHostPropIsBackground as IsBackground {
757 | get_is_background() -> Bool;
758 | }}
759 |
760 | property! { kOfxImageEffectHostPropNativeOrigin as NativeOrigin {
761 | get_native_origin() -> CString as enum HostNativeOrigin;
762 | }}
763 |
764 | property! { kOfxParamHostPropSupportsCustomInteract as SupportsCustomInteract {
765 | get_supports_custom_interact() -> Bool;
766 | }}
767 |
768 | property! { kOfxParamHostPropSupportsCustomAnimation as SupportsCustomAnimation {
769 | get_supports_custom_animation() -> Bool;
770 | }}
771 |
772 | property! { kOfxParamHostPropSupportsStringAnimation as SupportsStringAnimation {
773 | get_supports_string_animation() -> Bool;
774 | }}
775 |
776 | property! { kOfxParamHostPropSupportsChoiceAnimation as SupportsChoiceAnimation {
777 | get_supports_choice_animation() -> Bool;
778 | }}
779 |
780 | property! { kOfxParamHostPropSupportsBooleanAnimation as SupportsBooleanAnimation {
781 | get_supports_boolean_animation() -> Bool;
782 | }}
783 |
784 | property! { kOfxParamHostPropSupportsParametricAnimation as SupportsParametricAnimation {
785 | get_supports_parametric_animation() -> Bool;
786 | }}
787 |
788 | property! { kOfxParamHostPropMaxParameters as MaxParameters {
789 | get_max_parameters() -> Int;
790 | }}
791 |
792 | property! { kOfxParamHostPropMaxPages as MaxPages {
793 | get_max_pages() -> Int;
794 | }}
795 |
796 | property! { kOfxParamHostPropPageRowColumnCount as PageRowColumnCount {
797 | get_page_row_column_count() -> RectI;
798 | }}
799 |
800 | property! { kOfxImageEffectPluginPropGrouping as Grouping {
801 | get_grouping() -> String;
802 | set_grouping(&str);
803 | }}
804 |
805 | property! { kOfxImageEffectPluginPropFieldRenderTwiceAlways as FieldRenderTwiceAlways {
806 | get_field_render_twice_always() -> Bool;
807 | set_field_render_twice_always(Bool);
808 | }}
809 |
810 | property! { kOfxImageEffectPluginPropSingleInstance as SingleInstance {
811 | get_single_instance() -> Bool;
812 | set_single_instance(Bool);
813 | }}
814 |
815 | property! { kOfxImageEffectPluginPropHostFrameThreading as HostFrameThreading {
816 | get_host_frame_threading() -> Bool;
817 | set_host_frame_threading(Bool);
818 | }}
819 |
820 | property! { kOfxImageEffectPluginRenderThreadSafety as RenderThreadSafety {
821 | get_render_thread_safety() -> CString as enum ImageEffectRender;
822 | set_render_thread_safety(&[u8] as enum ImageEffectRender);
823 | }}
824 |
825 | property! { kOfxImageEffectPropContext as Context {
826 | get_context() -> CString as enum ImageEffectContext;
827 | }}
828 |
829 | property! { kOfxImageEffectPropComponents as Components {
830 | get_components() -> CString as enum ImageComponent;
831 | }}
832 |
833 | property! { kOfxImageEffectPropPixelDepth as PixelDepth {
834 | get_pixel_depth() -> CString as enum BitDepth;
835 | }}
836 |
837 | property! { kOfxImageEffectPropProjectSize as ProjectSize {
838 | get_project_size() -> PointD;
839 | set_project_size(PointD);
840 | }}
841 |
842 | property! { kOfxImageEffectPropProjectOffset as ProjectOffset {
843 | get_project_offset() -> PointD;
844 | set_project_offset(PointD);
845 | }}
846 |
847 | property! { kOfxImageEffectPropProjectExtent as ProjectExtent {
848 | get_project_extent() -> PointD;
849 | set_project_extent(PointD);
850 | }}
851 |
852 | property! { kOfxImageEffectPropProjectPixelAspectRatio as ProjectPixelAspectRatio {
853 | get_project_pixel_aspect_ratio() -> Double;
854 | set_project_pixel_aspect_ratio(Double);
855 | }}
856 |
857 | property! { kOfxImageEffectPropFrameRate as FrameRate {
858 | get_frame_rate() -> Double;
859 | set_frame_rate(Double);
860 | }}
861 |
862 | property! { kOfxImageEffectPropUnmappedFrameRate as UnmappedFrameRate {
863 | get_unmapped_frame_rate() -> Double;
864 | set_unmapped_frame_rate(Double);
865 | }}
866 |
867 | property! { kOfxImageEffectPropSupportsOverlays as SupportsOverlays {
868 | get_supports_overlays() -> Bool;
869 | }}
870 |
871 | property! { kOfxImageEffectPropSupportsMultiResolution as SupportsMultiResolution {
872 | get_supports_multi_resolution() -> Bool;
873 | set_supports_multi_resolution(Bool);
874 | }}
875 |
876 | property! { kOfxImageEffectPropSupportsTiles as SupportsTiles {
877 | get_supports_tiles() -> Bool;
878 | set_supports_tiles(Bool);
879 | }}
880 |
881 | property! { kOfxImageEffectPropSupportsMultipleClipDepths as SupportsMultipleClipDepths {
882 | get_supports_multiple_clip_depths() -> Bool;
883 | set_supports_multiple_clip_depths(Bool);
884 | }}
885 |
886 | property! { kOfxImageEffectPropSupportsMultipleClipPARs as SupportsMultipleClipPARs {
887 | get_supports_multiple_clip_pars() -> Bool;
888 | set_supports_multiple_clip_pars(Bool);
889 | }}
890 |
891 | property! { kOfxImageEffectPropSetableFrameRate as SetableFrameRate {
892 | get_setable_frame_rate() -> Bool;
893 | }}
894 |
895 | property! { kOfxImageEffectPropSetableFielding as SetableFielding {
896 | get_setable_fielding() -> Bool;
897 | }}
898 |
899 | // TODO: allow multiple returns
900 | property! { kOfxImageEffectPropSupportedContexts as SupportedContexts {
901 | get_supported_contexts() -> CString;
902 | set_supported_contexts(&[u8] as &[enum ImageEffectContext]);
903 | }}
904 |
905 | property! { kOfxImageEffectPropSupportedPixelDepths as SupportedPixelDepths {
906 | get_supported_pixel_depths() -> CString;
907 | set_supported_pixel_depths(&[u8] as &[enum BitDepth]);
908 | }}
909 |
910 | property! { kOfxImageEffectPropSupportedComponents as SupportedComponents {
911 | get_supported_components() -> CString;
912 | set_supported_components(&[u8] as &[enum ImageComponent]);
913 | }}
914 |
915 | property! { kOfxImageEffectPropPreMultiplication as PreMultiplication {
916 | get_pre_multiplication() -> Bool;
917 | set_pre_multiplication(Bool);
918 | }}
919 |
920 | property! { kOfxImageEffectPropRenderWindow as RenderWindow {
921 | get_render_window() -> RectI;
922 | set_render_window(RectI);
923 | }}
924 |
925 | property! { kOfxImageEffectPropRenderScale as RenderScale {
926 | get_render_scale() -> PointD;
927 | set_render_scale(PointD);
928 | }}
929 |
930 | property! { kOfxImageEffectPropRegionOfInterest as RegionOfInterest {
931 | get_region_of_interest() -> RectD;
932 | set_region_of_interest(RectD);
933 | }}
934 |
935 | // there are two RegionOfDefinition, one for clips and one for images,
936 | property! { kOfxImageEffectPropRegionOfDefinition as EffectRegionOfDefinition{
937 | get_effect_region_of_definition() -> RectD;
938 | set_effect_region_of_definition(RectD);
939 | }}
940 |
941 | property! { kOfxImageEffectPropFrameRange as FrameRange {
942 | get_frame_range() -> RangeD;
943 | set_frame_range(RangeD);
944 | }}
945 |
946 | property! { kOfxImageEffectPropUnmappedFrameRange as UnmappedFrameRange {
947 | get_unmapped_frame_range() -> RangeD;
948 | set_unmapped_frame_range(RangeD);
949 | }}
950 |
951 | property! { kOfxImageEffectPropFrameStep as FrameStep {
952 | get_frame_step() -> Double;
953 | }}
954 |
955 | property! { kOfxImageEffectPropFieldToRender as FieldToRender {
956 | get_field_to_render() -> CString as enum ImageField;
957 | }}
958 |
959 | property! { kOfxImageEffectPropTemporalClipAccess as TemporalClipAccess {
960 | get_temporal_clip_access() -> Bool;
961 | set_temporal_clip_access(Bool);
962 | }}
963 |
964 | // todo: return multiple strings
965 | property! { kOfxImageEffectPropClipPreferencesSlaveParam as ClipPreferencesSlaveParam {
966 | get_clip_preferences_slave_param() -> String;
967 | set_clip_preferences_slave_param(&str);
968 | }}
969 |
970 | property! { kOfxImageEffectPropSequentialRenderStatus as SequentialRenderStatus {
971 | get_sequential_render_status() -> Bool;
972 | }}
973 |
974 | property! { kOfxImageEffectPropInteractiveRenderStatus as InteractiveRenderStatus {
975 | get_interactive_render_status() -> Bool;
976 | }}
977 |
978 | property! { kOfxImageEffectPropOpenGLRenderSupported as OpenGLRenderSupported {
979 | get_opengl_render_supported() -> Bool;
980 | set_opengl_render_supported(Bool);
981 | }}
982 |
983 | property! { kOfxImageEffectPropRenderQualityDraft as RenderQualityDraft {
984 | get_render_quality_draft() -> Bool;
985 | }}
986 |
987 | property! { kOfxImageEffectInstancePropEffectDuration as EffectDuration {
988 | get_effect_duration() -> Double;
989 | set_effect_duration(Double);
990 | }}
991 |
992 | property! { kOfxImageEffectInstancePropSequentialRender as SequentialRender {
993 | get_sequential_render() -> Bool;
994 | set_sequential_render(Bool);
995 | }}
996 |
997 | property! { kOfxImageClipPropConnected as Connected {
998 | get_connected() -> Bool;
999 | }}
1000 |
1001 | property! { kOfxImageClipPropUnmappedComponents as UnmappedComponents {
1002 | get_unmapped_components() -> CString as enum ImageComponent;
1003 | }}
1004 |
1005 | property! { kOfxImageClipPropUnmappedPixelDepth as UnmappedPixelDepth {
1006 | get_unmapped_pixel_depth() -> CString as enum BitDepth;
1007 | }}
1008 |
1009 | property! { kOfxImageClipPropFieldExtraction as FieldExtraction {
1010 | get_field_extraction() -> CString as enum ImageFieldExtraction;
1011 | set_field_extraction(&[u8] as enum ImageFieldExtraction);
1012 | }}
1013 |
1014 | property! { kOfxImageClipPropFieldOrder as FieldOrder {
1015 | get_field_order() -> CString as enum ImageFieldOrder;
1016 | set_field_order(&[u8] as enum ImageFieldOrder);
1017 | }}
1018 |
1019 | property! { kOfxImageClipPropOptional as Optional {
1020 | get_optional() -> Bool;
1021 | set_optional(Bool);
1022 | }}
1023 |
1024 | property! { kOfxImageClipPropIsMask as IsMask {
1025 | get_is_mask() -> Bool;
1026 | set_is_mask(Bool);
1027 | }}
1028 |
1029 | property! { kOfxImageClipPropContinuousSamples as ContinuousSamples {
1030 | get_continuous_samples() -> Bool;
1031 | set_continuous_samples(Bool);
1032 | }}
1033 |
1034 | property! { kOfxImagePropRowBytes as RowBytes {
1035 | get_row_bytes() -> Int;
1036 | }}
1037 |
1038 | property! { kOfxImagePropBounds as Bounds {
1039 | get_bounds() -> RectI;
1040 | }}
1041 |
1042 | property! { kOfxImagePropData as Data {
1043 | get_data() -> VoidPtrMut;
1044 | }}
1045 |
1046 | property! { kOfxImagePropField as Field {
1047 | get_field() -> CString as enum ImageField;
1048 | }}
1049 |
1050 | property! { kOfxImagePropPixelAspectRatio as PixelAspectRatio {
1051 | get_pixel_aspect_ratio() -> Double;
1052 | }}
1053 |
1054 | // there are two RegionOfDefinition, one for clips and one for images,
1055 | property! { kOfxImagePropRegionOfDefinition as RegionOfDefinition {
1056 | get_region_of_definition() -> RectI;
1057 | }}
1058 |
1059 | property! { kOfxImagePropUniqueIdentifier as UniqueIdentifier {
1060 | get_unique_identifier() -> String;
1061 | }}
1062 |
1063 | property! { kOfxParamPropEnabled as Enabled {
1064 | get_enabled() -> Bool;
1065 | set_enabled(Bool);
1066 | }}
1067 |
1068 | property! { kOfxPropParamSetNeedsSyncing as NeedsSyncing {
1069 | get_needs_syncing() -> Bool;
1070 | }}
1071 |
1072 | property! { kOfxParamPropHint as Hint {
1073 | get_hint() -> String;
1074 | set_hint(&str);
1075 | }}
1076 |
1077 | property! { kOfxParamPropParent as Parent {
1078 | get_parent() -> String;
1079 | set_parent(&str);
1080 | }}
1081 |
1082 | property! { kOfxParamPropScriptName as ScriptName {
1083 | get_script_name() -> String;
1084 | set_script_name(&str);
1085 | }}
1086 |
1087 | property_group! { CommonParameters {
1088 | Type read,
1089 | Label read+write,
1090 | Hint read+write,
1091 | Parent read+write,
1092 | ScriptName read+write,
1093 | Enabled read+write,
1094 | }}
1095 |
1096 | pub mod double {
1097 | use super::*;
1098 | property_assign_name!(kOfxParamPropDoubleType as DoubleType: (&[u8]) -> CString);
1099 | property_assign_name!(kOfxParamPropDefault as Default: Double);
1100 | property_assign_name!(kOfxParamPropDisplayMax as DisplayMax: Double);
1101 | property_assign_name!(kOfxParamPropDisplayMin as DisplayMin: Double);
1102 | }
1103 |
1104 | pub mod boolean {
1105 | use super::*;
1106 | property_assign_name!(kOfxParamPropDefault as Default: Bool);
1107 | }
1108 |
1109 | pub mod page {
1110 | use super::*;
1111 | property_assign_name!(kOfxParamPropPageChild as Child: (&str) -> String);
1112 | }
1113 |
1114 | #[allow(non_snake_case)]
1115 | pub mod Children {
1116 | use super::*;
1117 | property_define_setter_trait!(CanSet => set_children, page::Child, &seq[&str]);
1118 | }
1119 | pub use Children::CanSet as CanSetChildren;
1120 |
1121 | #[allow(non_snake_case)]
1122 | pub mod Labels {
1123 | use super::*;
1124 | pub trait CanSet: Label::CanSet + ShortLabel::CanSet + LongLabel::CanSet {
1125 | fn set_labels(&mut self, label: &str, short: &str, long: &str) -> Result<()> {
1126 | self.set_label(label)?;
1127 | self.set_short_label(short)?;
1128 | self.set_long_label(long)?;
1129 | Ok(())
1130 | }
1131 | }
1132 | }
1133 |
1134 | impl Labels::CanSet for T where T: Label::CanSet + ShortLabel::CanSet + LongLabel::CanSet {}
1135 |
1136 | #[allow(non_snake_case)]
1137 | pub mod NameRaw {
1138 | use super::*;
1139 | pub trait CanSet: Name::CanSet {
1140 | fn set_name_raw(&mut self, name_raw: &[u8]) -> Result<()> {
1141 | self.set_name(CStr::from_bytes_with_nul(name_raw)?.to_str()?)
1142 | }
1143 | }
1144 | }
1145 | pub use NameRaw::CanSet as CanSetNameRaw;
1146 |
1147 | #[allow(non_snake_case)]
1148 | pub mod DoubleParams {
1149 | use super::*;
1150 | pub trait CanSet: Writable {
1151 | property_define_setter_trait!(set_double_type, double::DoubleType, enum ParamDoubleType);
1152 | property_define_setter_trait!(set_default, double::Default);
1153 | property_define_setter_trait!(set_display_max, double::DisplayMax);
1154 | property_define_setter_trait!(set_display_min, double::DisplayMin);
1155 | }
1156 | }
1157 |
1158 | pub use DoubleParams::CanSet as CanSetDoubleParams;
1159 |
1160 | #[allow(non_snake_case)]
1161 | pub mod BooleanParams {
1162 | use super::*;
1163 | pub trait CanSet: Writable {
1164 | property_define_setter_trait!(set_default, boolean::Default);
1165 | }
1166 | }
1167 |
1168 | pub use BooleanParams::CanSet as CanSetBooleanParams;
1169 |
1170 | impl CommonParameters for ParamHandle where T: ParamHandleValue + Clone {}
1171 |
1172 | // https://openfx.readthedocs.io/en/doc/Reference/ofxPropertiesByObject.html#properties-on-an-effect-descriptor
1173 | object_properties! { ImageEffectHost {
1174 | Name read,
1175 | Label read,
1176 | Version read,
1177 | VersionLabel read,
1178 | IsBackground read,
1179 | SupportsOverlays read,
1180 | SupportsMultiResolution read,
1181 | SupportsTiles read,
1182 | TemporalClipAccess read,
1183 | SupportedComponents read,
1184 | SupportedContexts read,
1185 | SupportsMultipleClipDepths read,
1186 | SupportsMultipleClipPARs read,
1187 | SetableFrameRate read,
1188 | SetableFielding read,
1189 | SupportsCustomInteract read,
1190 | SupportsStringAnimation read,
1191 | SupportsChoiceAnimation read,
1192 | SupportsBooleanAnimation read,
1193 | SupportsCustomAnimation read,
1194 | MaxParameters read,
1195 | MaxPages read,
1196 | PageRowColumnCount read,
1197 | HostOSHandle read,
1198 | SupportsParametricAnimation read,
1199 | SequentialRender read,
1200 | OpenGLRenderSupported read,
1201 | RenderQualityDraft read,
1202 | NativeOrigin read,
1203 | }}
1204 |
1205 | // TODO: canset should be only exposed in the "Describe" action
1206 | object_properties! { EffectDescriptor {
1207 | Type read,
1208 | Label read+write,
1209 | ShortLabel read+write,
1210 | LongLabel read+write,
1211 | Version read,
1212 | VersionLabel read,
1213 | PluginDescription read+write,
1214 | SupportedContexts read+write,
1215 | Grouping read+write,
1216 | SingleInstance read+write,
1217 | RenderThreadSafety read+write,
1218 | HostFrameThreading read+write,
1219 | // TODO: missing yet
1220 | // OverlayInteractV1 read+write,
1221 | SupportsMultiResolution read+write,
1222 | SupportsTiles read+write,
1223 | TemporalClipAccess read+write,
1224 | SupportedPixelDepths read+write,
1225 | FieldRenderTwiceAlways read,
1226 | SupportsMultipleClipDepths read+write,
1227 | SupportsMultipleClipPARs read+write,
1228 | OpenGLRenderSupported read+write,
1229 | ClipPreferencesSlaveParam read+write,
1230 | FilePath read,
1231 | // convenience extras
1232 | Labels write,
1233 | }}
1234 |
1235 | // Image Effect Instance
1236 | object_properties! { EffectInstance {
1237 | Type read,
1238 | Context read,
1239 | Label read,
1240 | ProjectSize read,
1241 | ProjectOffset read,
1242 | ProjectExtent read,
1243 | ProjectPixelAspectRatio read,
1244 | EffectDuration read,
1245 | SequentialRender read+write,
1246 | SupportsTiles read+write,
1247 | SupportsMultiResolution read+write,
1248 | OpenGLRenderSupported read+write,
1249 | FrameRate read,
1250 | SupportedPixelDepths read+write,
1251 | IsInteractive read,
1252 | }}
1253 |
1254 | // Clip Descriptor
1255 | object_properties! { ClipDescriptor {
1256 | Type read,
1257 | Name read,
1258 | Label read+write,
1259 | ShortLabel read+write,
1260 | LongLabel read+write,
1261 | SupportedComponents read+write,
1262 | TemporalClipAccess read+write,
1263 | Optional read+write,
1264 | FieldExtraction read+write,
1265 | IsMask read+write,
1266 | SupportsTiles read+write,
1267 | }}
1268 |
1269 | // Clip Instance
1270 | object_properties! { ClipInstance {
1271 | Type read,
1272 | Name read,
1273 | Label read,
1274 | ShortLabel read,
1275 | LongLabel read,
1276 | SupportedComponents read,
1277 | TemporalClipAccess read,
1278 | Optional read,
1279 | FieldExtraction read,
1280 | IsMask read,
1281 | SupportsTiles read,
1282 | PixelDepth read,
1283 | Components read,
1284 | UnmappedPixelDepth read,
1285 | UnmappedComponents read,
1286 | PreMultiplication read,
1287 | PixelAspectRatio read,
1288 | FrameRate read,
1289 | FrameRange read,
1290 | FieldOrder read,
1291 | Connected read,
1292 | UnmappedFrameRange read,
1293 | UnmappedFrameRate read,
1294 | ContinuousSamples read,
1295 | }}
1296 |
1297 | object_properties! { Image {
1298 | Type read,
1299 | PixelDepth read,
1300 | Components read,
1301 | PreMultiplication read,
1302 | RenderScale read,
1303 | PixelAspectRatio read,
1304 | Data read,
1305 | Bounds read,
1306 | RegionOfDefinition read,
1307 | RowBytes read,
1308 | Field read,
1309 | UniqueIdentifier read,
1310 | }}
1311 |
1312 | object_properties! { ParamDouble {
1313 | CommonParameters inherit,
1314 | DoubleParams write,
1315 | }}
1316 |
1317 | object_properties! { ParamBoolean {
1318 | CommonParameters inherit,
1319 | BooleanParams write,
1320 | }}
1321 |
1322 | object_properties! { ParamPage {
1323 | CommonParameters inherit,
1324 | Children write,
1325 | }}
1326 |
1327 | object_properties! { ParamGroup {
1328 | CommonParameters inherit,
1329 | }}
1330 |
1331 | object_properties! { ParameterSet {
1332 | NeedsSyncing read,
1333 | }}
1334 |
1335 | object_properties! { DescribeInContextInArgs {
1336 | Context read,
1337 | }}
1338 |
1339 | object_properties! { IsIdentityInArgs {
1340 | Time read,
1341 | FieldToRender read,
1342 | RenderWindow read,
1343 | RenderScale read,
1344 | }}
1345 |
1346 | object_properties! { IsIdentityOutArgs {
1347 | Name write,
1348 | Time write,
1349 | }}
1350 |
1351 | object_properties! { GetRegionOfDefinitionInArgs {
1352 | Time read,
1353 | RegionOfDefinition read,
1354 | }}
1355 |
1356 | object_properties! { GetRegionOfDefinitionOutArgs {
1357 | EffectRegionOfDefinition write,
1358 | }}
1359 |
1360 | object_properties! { GetRegionsOfInterestInArgs {
1361 | RegionOfInterest read,
1362 | }}
1363 |
1364 | object_properties! { GetRegionsOfInterestOutArgs {
1365 | RawWritable inherit,
1366 | RegionOfInterest write,
1367 | }}
1368 |
1369 | object_properties! { GetClipPreferencesOutArgs {
1370 | RawWritable inherit,
1371 | }}
1372 |
1373 | object_properties! { InstanceChangedInArgs {
1374 | Type read,
1375 | Name read,
1376 | Time read,
1377 | ChangeReason read,
1378 | RenderScale read,
1379 | }}
1380 |
1381 | object_properties! { BeginInstanceChangedInArgs {
1382 | ChangeReason read,
1383 | }}
1384 |
1385 | object_properties! { EndInstanceChangedInArgs {
1386 | ChangeReason read,
1387 | }}
1388 |
1389 | object_properties! { RenderInArgs {
1390 | Time read,
1391 | FieldToRender read,
1392 | RenderWindow read,
1393 | RenderScale read,
1394 | SequentialRenderStatus read,
1395 | InteractiveRenderStatus read,
1396 | RenderQualityDraft read,
1397 | }}
1398 |
1399 | object_properties! { BeginSequenceRenderInArgs {
1400 | FrameRange read,
1401 | FrameStep read,
1402 | IsInteractive read,
1403 | RenderScale read,
1404 | SequentialRenderStatus read,
1405 | InteractiveRenderStatus read,
1406 | RenderQualityDraft read,
1407 | }}
1408 |
1409 | object_properties! { EndSequenceRenderInArgs {
1410 | FrameRange read,
1411 | FrameStep read,
1412 | IsInteractive read,
1413 | RenderScale read,
1414 | SequentialRenderStatus read,
1415 | InteractiveRenderStatus read,
1416 | RenderQualityDraft read,
1417 | }}
1418 |
1419 | object_properties! { GetTimeDomainOutArgs {
1420 | FrameRange write,
1421 | }}
1422 |
--------------------------------------------------------------------------------
/ofx/src/registry.rs:
--------------------------------------------------------------------------------
1 | use action::*;
2 | use ofx_sys::*;
3 | use plugin::*;
4 | use result::*;
5 | use std::collections::HashMap;
6 | use types::*;
7 |
8 | #[derive(Default)]
9 | pub struct Registry {
10 | plugins: Vec,
11 | plugin_modules: HashMap,
12 | }
13 |
14 | impl Registry {
15 | pub fn new() -> Registry {
16 | Self::default()
17 | }
18 |
19 | pub fn add(
20 | &mut self,
21 | module_name: &'static str,
22 | name: &'static str,
23 | api_version: ApiVersion,
24 | plugin_version: PluginVersion,
25 | instance: Box,
26 | set_host: SetHost,
27 | main_entry: MainEntry,
28 | ) -> usize {
29 | let plugin_index = self.plugins.len();
30 |
31 | self.plugin_modules
32 | .insert(module_name.to_owned(), plugin_index as usize);
33 |
34 | let plugin = PluginDescriptor::new(
35 | plugin_index,
36 | module_name,
37 | name,
38 | api_version,
39 | plugin_version,
40 | instance,
41 | set_host,
42 | main_entry,
43 | );
44 |
45 | self.plugins.push(plugin);
46 | plugin_index
47 | }
48 |
49 | pub fn count(&self) -> Int {
50 | self.plugins.len() as Int
51 | }
52 |
53 | pub fn get_plugin_mut(&mut self, index: usize) -> &mut PluginDescriptor {
54 | &mut self.plugins[index as usize]
55 | }
56 |
57 | pub fn get_plugin(&self, index: usize) -> &PluginDescriptor {
58 | &self.plugins[index as usize]
59 | }
60 |
61 | pub fn ofx_plugin(&'static self, index: Int) -> &'static OfxPlugin {
62 | &self.plugins[index as usize].ofx_plugin()
63 | }
64 |
65 | pub fn dispatch(&mut self, plugin_module: &str, message: RawMessage) -> Result {
66 | info!("{}:{:?}", plugin_module, message);
67 | let found_plugin = self.plugin_modules.get(plugin_module).cloned();
68 | if let Some(plugin_index) = found_plugin {
69 | let plugin = self.get_plugin_mut(plugin_index);
70 | plugin.dispatch(message)
71 | } else {
72 | Err(Error::PluginNotFound)
73 | }
74 | }
75 | }
76 |
77 | pub unsafe fn set_host_for_plugin(plugin_module: &str, host: *mut OfxHost) {
78 | unsafe {
79 | get_registry_mut()
80 | .dispatch(plugin_module, RawMessage::SetHost { host: *host })
81 | .ok();
82 | }
83 | }
84 |
85 | static mut _GLOBAL_REGISTRY: Option = None;
86 |
87 | pub fn main_entry_for_plugin(
88 | plugin_module: &str,
89 | action: CharPtr,
90 | handle: VoidPtr,
91 | in_args: OfxPropertySetHandle,
92 | out_args: OfxPropertySetHandle,
93 | ) -> Int {
94 | unsafe {
95 | get_registry_mut()
96 | .dispatch(
97 | plugin_module,
98 | RawMessage::MainEntry {
99 | action,
100 | handle,
101 | in_args,
102 | out_args,
103 | },
104 | )
105 | .ok()
106 | .unwrap_or(-1)
107 | }
108 | }
109 |
110 | pub fn init_registry(init_function: F)
111 | where
112 | F: Fn(&mut Registry),
113 | {
114 | unsafe {
115 | if _GLOBAL_REGISTRY.is_none() {
116 | use log4rs::append::console::*;
117 | use log4rs::config::*;
118 |
119 | if let Err(e) = log4rs::init_file("ofx_log4rs.yaml", Default::default()) {
120 | let config = Config::builder()
121 | .appender(Appender::builder().build(
122 | "stdout".to_string(),
123 | Box::new(ConsoleAppender::builder().build()),
124 | ))
125 | .logger(Logger::builder().build("ofx".to_string(), log::LevelFilter::Warn))
126 | .build(
127 | Root::builder()
128 | .appender("stdout".to_string())
129 | .build(log::LevelFilter::Error),
130 | );
131 | log4rs::init_config(config.unwrap()).unwrap();
132 | }
133 | let mut registry = Registry::new();
134 | init_function(&mut registry);
135 | for plugin in ®istry.plugins {
136 | info!("Registered plugin {}", plugin);
137 | }
138 | _GLOBAL_REGISTRY = Some(registry);
139 | }
140 | }
141 | }
142 |
143 | fn get_registry_mut() -> &'static mut Registry {
144 | unsafe { _GLOBAL_REGISTRY.as_mut().unwrap() }
145 | }
146 |
147 | pub fn get_registry() -> &'static Registry {
148 | unsafe { _GLOBAL_REGISTRY.as_ref().unwrap() }
149 | }
150 |
151 | #[macro_export]
152 | macro_rules! plugin_module {
153 | ($name:expr, $api_version:expr, $plugin_version:expr, $factory:expr) => {
154 | pub fn name() -> &'static str {
155 | $name
156 | }
157 |
158 | pub fn module_name() -> &'static str {
159 | module_path!() //.split("::").last().as_ref().unwrap()
160 | }
161 |
162 | pub fn new_instance() -> Box {
163 | Box::new($factory())
164 | }
165 |
166 | pub fn api_version() -> ApiVersion {
167 | $api_version
168 | }
169 |
170 | pub fn plugin_version() -> PluginVersion {
171 | $plugin_version
172 | }
173 |
174 | pub extern "C" fn set_host(host: *mut ofx::OfxHost) {
175 | unsafe { ofx::set_host_for_plugin(module_name(), host) }
176 | }
177 |
178 | pub extern "C" fn main_entry(
179 | action: ofx::CharPtr,
180 | handle: ofx::VoidPtr,
181 | in_args: ofx::OfxPropertySetHandle,
182 | out_args: ofx::OfxPropertySetHandle,
183 | ) -> super::Int {
184 | ofx::main_entry_for_plugin(module_name(), action, handle, in_args, out_args)
185 | }
186 | };
187 | }
188 |
189 | #[macro_export]
190 | macro_rules! register_plugin {
191 | ($registry:ident, $module:ident) => {
192 | $registry.add(
193 | $module::module_name(),
194 | $module::name(),
195 | $module::api_version(),
196 | $module::plugin_version(),
197 | $module::new_instance(),
198 | $module::set_host,
199 | $module::main_entry,
200 | );
201 | };
202 | }
203 |
204 | #[macro_export]
205 | macro_rules! build_plugin_registry {
206 | ($init_callback:ident) => {
207 | fn init() {
208 | init_registry($init_callback);
209 | }
210 |
211 | #[no_mangle]
212 | pub extern "C" fn OfxGetNumberOfPlugins() -> Int {
213 | init();
214 | get_registry().count()
215 | }
216 |
217 | #[no_mangle]
218 | pub extern "C" fn OfxGetPlugin(nth: Int) -> *const OfxPlugin {
219 | init();
220 | get_registry().ofx_plugin(nth) as *const OfxPlugin
221 | }
222 |
223 | pub fn show_plugins() -> Vec {
224 | unsafe {
225 | let n = OfxGetNumberOfPlugins();
226 | for i in 0..n {
227 | OfxGetPlugin(i);
228 | }
229 | (0..n)
230 | .map(|i| {
231 | let plugin = get_registry().get_plugin(i as usize);
232 | format!("{}", plugin)
233 | })
234 | .collect()
235 | }
236 | }
237 | };
238 | }
239 |
--------------------------------------------------------------------------------
/ofx/src/result.rs:
--------------------------------------------------------------------------------
1 | use ofx_sys::*;
2 | use std::fmt;
3 | use std::fmt::Display;
4 | use types::*;
5 |
6 | pub use ofx_sys::eOfxStatus_ErrBadHandle;
7 | pub use ofx_sys::eOfxStatus_ErrBadIndex;
8 | pub use ofx_sys::eOfxStatus_ErrValue;
9 | pub use ofx_sys::eOfxStatus_ReplyDefault;
10 | pub use ofx_sys::eOfxStatus_OK;
11 |
12 | #[derive(Debug, Clone, Copy)]
13 | pub enum Error {
14 | PluginNotFound,
15 | InvalidAction,
16 | InvalidImageEffectAction,
17 | InvalidNameEncoding,
18 | InvalidResultEncoding,
19 | InvalidHandle,
20 | InvalidValue,
21 | InvalidSuite,
22 | InvalidIndex,
23 | PluginNotReady,
24 | PropertyIndexOutOfBounds,
25 | HostNotReady,
26 | EnumNotFound,
27 | SuiteNotInitialized,
28 | Unimplemented,
29 | UnknownError,
30 | }
31 |
32 | pub const OK: Result = Ok(eOfxStatus_OK);
33 | pub const REPLY_DEFAULT: Result = Ok(eOfxStatus_ReplyDefault);
34 | pub const FAILED: Result = Ok(eOfxStatus_Failed);
35 | pub const UNIMPLEMENTED: Result = Err(Error::Unimplemented);
36 |
37 | impl From for Error {
38 | fn from(status: OfxStatus) -> Error {
39 | match status {
40 | ofx_sys::eOfxStatus_ErrBadHandle => Error::InvalidHandle,
41 | ofx_sys::eOfxStatus_ErrBadIndex => Error::InvalidIndex,
42 | ofx_sys::eOfxStatus_ErrValue => Error::InvalidValue,
43 | _ => Error::UnknownError,
44 | }
45 | }
46 | }
47 |
48 | macro_rules! to_result {
49 | {$ofx_status:expr => $result:expr} => {
50 | match $ofx_status {
51 | ofx_sys::eOfxStatus_OK => Ok($result),
52 | other => Err(Error::from(other)),
53 | }
54 | };
55 | ($ofx_status:expr) => {
56 | to_result!($ofx_status => ())
57 | };
58 | }
59 |
60 | impl From for Error {
61 | fn from(_src: std::ffi::NulError) -> Error {
62 | Error::InvalidNameEncoding
63 | }
64 | }
65 |
66 | impl From for Error {
67 | fn from(_src: std::ffi::IntoStringError) -> Error {
68 | Error::InvalidNameEncoding
69 | }
70 | }
71 |
72 | impl From for Error {
73 | fn from(_src: std::ffi::FromBytesWithNulError) -> Error {
74 | Error::InvalidResultEncoding
75 | }
76 | }
77 |
78 | impl From for Error {
79 | fn from(_src: std::str::Utf8Error) -> Error {
80 | Error::InvalidResultEncoding
81 | }
82 | }
83 |
84 | impl fmt::Display for Error {
85 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 | write!(f, "Openfx error")
87 | }
88 | }
89 |
90 | impl std::error::Error for Error {}
91 |
92 | pub type Result = std::result::Result;
93 |
--------------------------------------------------------------------------------
/ofx/src/suites.rs:
--------------------------------------------------------------------------------
1 | use ofx_sys::*;
2 | use result::*;
3 | use std::borrow::Borrow;
4 | use std::rc::Rc;
5 |
6 | #[derive(Clone)]
7 | pub struct Suites {
8 | image_effect: Rc,
9 | property: Rc,
10 | parameter: Rc,
11 | memory: Rc,
12 | pub(crate) multi_thread: Rc,
13 | message: Rc,
14 | message_v2: Option>,
15 | progress: Rc,
16 | progress_v2: Option>,
17 | time_line: Rc,
18 | parametric_parameter: Option>,
19 | image_effect_opengl_render: Option>,
20 | }
21 |
22 | macro_rules! suite_call {
23 | ($function:ident in $suite:expr; $($arg:expr),*) => {
24 | unsafe { ($suite).$function.ok_or(Error::SuiteNotInitialized)?($($arg),*) }
25 | };
26 | }
27 |
28 | macro_rules! suite_fn {
29 | ($($tail:tt)*) => { to_result!{suite_call!($($tail)*)} }
30 | }
31 |
32 |
33 |
34 | #[allow(clippy::too_many_arguments)]
35 | impl Suites {
36 | pub fn new(
37 | image_effect: OfxImageEffectSuiteV1,
38 | property: OfxPropertySuiteV1,
39 | parameter: OfxParameterSuiteV1,
40 | memory: OfxMemorySuiteV1,
41 | multi_thread: OfxMultiThreadSuiteV1,
42 | message: OfxMessageSuiteV1,
43 | message_v2: Option,
44 | progress: OfxProgressSuiteV1,
45 | progress_v2: Option