aviutl2\generic/
bridge.rs

1use crate::{
2    common::{AnyResult, LeakManager, alert_error},
3    generic::{
4        GenericPlugin, ProjectFile,
5        binding::{HostAppHandle, PluginRegistry},
6    },
7};
8
9#[doc(hidden)]
10pub struct InternalGenericPluginState<T: Send + Sync + GenericPlugin> {
11    plugin_registry: PluginRegistry,
12
13    kill_switch: std::sync::Arc<std::sync::atomic::AtomicBool>,
14    global_leak_manager: LeakManager,
15
16    instance: T,
17}
18
19impl<T: Send + Sync + GenericPlugin> InternalGenericPluginState<T> {
20    pub fn new(instance: T) -> Self {
21        Self {
22            plugin_registry: PluginRegistry::new(),
23            kill_switch: std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)),
24            global_leak_manager: LeakManager::new(),
25            instance,
26        }
27    }
28}
29
30pub trait GenericSingleton
31where
32    Self: 'static + Send + Sync + GenericPlugin,
33{
34    fn __get_singleton_state()
35    -> &'static std::sync::RwLock<Option<InternalGenericPluginState<Self>>>;
36    fn with_instance<R>(f: impl FnOnce(&Self) -> R) -> R {
37        let lock = Self::__get_singleton_state();
38        let guard = lock.read().unwrap();
39        let state = guard.as_ref().expect("Plugin not initialized");
40        f(&state.instance)
41    }
42    fn with_instance_mut<R>(f: impl FnOnce(&mut Self) -> R) -> R {
43        let lock = Self::__get_singleton_state();
44        let mut guard = lock.write().unwrap();
45        let state = guard.as_mut().expect("Plugin not initialized");
46        f(&mut state.instance)
47    }
48}
49
50pub unsafe fn initialize_plugin_c<T: GenericSingleton>(version: u32) -> bool {
51    match initialize_plugin::<T>(version) {
52        Ok(_) => true,
53        Err(e) => {
54            log::error!("Failed to initialize plugin: {}", e);
55            alert_error(&e);
56            false
57        }
58    }
59}
60
61pub(crate) fn initialize_plugin<T: GenericSingleton>(version: u32) -> AnyResult<()> {
62    let plugin_state = T::__get_singleton_state();
63    let info = crate::common::AviUtl2Info {
64        version: version.into(),
65    };
66    let internal = T::new(info)?;
67    let plugin = InternalGenericPluginState::new(internal);
68    *plugin_state.write().unwrap() = Some(plugin);
69
70    Ok(())
71}
72pub unsafe fn register_plugin<T: GenericSingleton>(
73    host: *mut aviutl2_sys::plugin2::HOST_APP_TABLE,
74) {
75    let plugin_state = T::__get_singleton_state();
76    let mut plugin_state = plugin_state.write().unwrap();
77    let plugin_state = plugin_state.as_mut().expect("Plugin not initialized");
78
79    let kill_switch = plugin_state.kill_switch.clone();
80    let mut handle = unsafe {
81        HostAppHandle::new(
82            host,
83            &mut plugin_state.global_leak_manager,
84            kill_switch,
85            &mut plugin_state.plugin_registry,
86        )
87    };
88    handle.register_project_load_handler(on_project_load::<T>);
89    handle.register_project_save_handler(on_project_save::<T>);
90    handle.register_clear_cache_handler(on_clear_cache::<T>);
91    handle.register_change_scene_handler(on_change_scene::<T>);
92    T::register(&mut plugin_state.instance, &mut handle);
93
94    extern "C" fn on_project_load<T: GenericSingleton>(
95        project: *mut aviutl2_sys::plugin2::PROJECT_FILE,
96    ) {
97        <T as GenericSingleton>::with_instance_mut(|instance| unsafe {
98            let mut project = ProjectFile::from_raw(project);
99            instance.on_project_load(&mut project);
100        });
101    }
102
103    extern "C" fn on_project_save<T: GenericSingleton>(
104        project: *mut aviutl2_sys::plugin2::PROJECT_FILE,
105    ) {
106        <T as GenericSingleton>::with_instance_mut(|instance| unsafe {
107            let mut project = ProjectFile::from_raw(project);
108            instance.on_project_save(&mut project);
109        });
110    }
111
112    extern "C" fn on_clear_cache<T: GenericSingleton>(edit_section: *mut aviutl2_sys::plugin2::EDIT_SECTION) {
113        <T as GenericSingleton>::with_instance_mut(|instance| unsafe {
114            let edit_section = crate::generic::EditSection::from_raw(edit_section);
115            instance.on_clear_cache(&edit_section);
116        });
117    }
118
119    extern "C" fn on_change_scene<T: GenericSingleton>(edit_section: *mut aviutl2_sys::plugin2::EDIT_SECTION) {
120        <T as GenericSingleton>::with_instance_mut(|instance| unsafe {
121            let edit_section = crate::generic::EditSection::from_raw(edit_section);
122            instance.on_change_scene(&edit_section);
123        });
124    }
125}
126pub unsafe fn uninitialize_plugin<T: GenericSingleton>() {
127    let plugin_state = T::__get_singleton_state();
128    *plugin_state.write().unwrap() = None;
129}
130
131/// 汎用プラグインを登録するマクロ。
132#[macro_export]
133macro_rules! register_generic_plugin {
134    ($struct:ident) => {
135        ::aviutl2::__internal_module! {
136            #[unsafe(no_mangle)]
137            unsafe extern "C" fn InitializeLogger(logger: *mut $crate::sys::logger2::LOG_HANDLE) {
138                $crate::logger::__initialize_logger(logger)
139            }
140
141            #[unsafe(no_mangle)]
142            unsafe extern "C" fn InitializePlugin(version: u32) -> bool {
143                unsafe { $crate::generic::__bridge::initialize_plugin_c::<$struct>(version) }
144            }
145
146            #[unsafe(no_mangle)]
147            unsafe extern "C" fn UninitializePlugin() {
148                unsafe { $crate::generic::__bridge::uninitialize_plugin::<$struct>() };
149            }
150
151            #[unsafe(no_mangle)]
152            unsafe extern "C" fn RegisterPlugin(host: *mut aviutl2::sys::plugin2::HOST_APP_TABLE) {
153                unsafe { $crate::generic::__bridge::register_plugin::<$struct>(host) };
154            }
155        }
156    };
157}