libobs_wrapper\utils/
mod.rs

1mod error;
2mod info;
3pub(crate) mod initialization;
4mod obs_string;
5mod path;
6pub(crate) mod async_sync;
7pub mod traits;
8
9use std::ffi::CStr;
10
11pub use error::*;
12pub use info::*;
13use libobs::obs_module_failure_info;
14pub use obs_string::*;
15pub use path::*;
16
17use crate::{
18    enums::ObsLogLevel, logger::internal_log_global, run_with_obs, runtime::ObsRuntime, unsafe_send::Sendable
19};
20
21#[derive(Debug)]
22pub struct ObsModules {
23    paths: StartupPaths,
24
25    /// A pointer to the module failure info structure.
26    info: Option<Sendable<obs_module_failure_info>>,
27    pub(crate) runtime: Option<ObsRuntime>,
28}
29
30impl ObsModules {
31    pub fn add_paths(paths: &StartupPaths) -> Self {
32        unsafe {
33            libobs::obs_add_data_path(paths.libobs_data_path().as_ptr().0);
34            libobs::obs_add_module_path(
35                paths.plugin_bin_path().as_ptr().0,
36                paths.plugin_data_path().as_ptr().0,
37            );
38        }
39
40        Self {
41            paths: paths.clone(),
42            info: None,
43            runtime: None,
44        }
45    }
46
47    pub fn load_modules(&mut self) {
48        unsafe {
49            let mut failure_info: obs_module_failure_info = std::mem::zeroed();
50            internal_log_global(
51                ObsLogLevel::Info,
52                "---------------------------------".to_string(),
53            );
54            libobs::obs_load_all_modules2(&mut failure_info);
55            internal_log_global(
56                ObsLogLevel::Info,
57                "---------------------------------".to_string(),
58            );
59            libobs::obs_log_loaded_modules();
60            internal_log_global(
61                ObsLogLevel::Info,
62                "---------------------------------".to_string(),
63            );
64            libobs::obs_post_load_modules();
65            self.info = Some(Sendable(failure_info));
66        }
67
68        self.log_if_failed();
69    }
70
71    pub fn log_if_failed(&self) {
72        if self.info.as_ref().is_none_or(|x| &x.0.count == &0) {
73            return;
74        }
75
76        let info = &self.info.as_ref().unwrap().0;
77        let mut failed_modules = Vec::new();
78        for i in 0..info.count {
79            let module = unsafe { info.failed_modules.offset(i as isize) };
80            let plugin_name = unsafe { CStr::from_ptr(*module) };
81            failed_modules.push(plugin_name.to_string_lossy());
82        }
83
84        internal_log_global(
85            ObsLogLevel::Warning,
86            format!("Failed to load modules: {}", failed_modules.join(", ")),
87        );
88    }
89}
90
91impl Drop for ObsModules {
92    fn drop(&mut self) {
93        let paths = self.paths.clone();
94        let runtime = self.runtime.take().unwrap();
95
96        #[cfg(not(feature="blocking"))]
97        let r = futures::executor::block_on(async {
98            return run_with_obs!(runtime, move || unsafe {
99                libobs::obs_remove_data_path(paths.libobs_data_path().as_ptr().0);
100            }).await
101        });
102
103        #[cfg(feature="blocking")]
104        let r = run_with_obs!(runtime, move || unsafe {
105            libobs::obs_remove_data_path(paths.libobs_data_path().as_ptr().0);
106        });
107
108        if std::thread::panicking() {
109            return;
110        }
111
112        r.unwrap();
113    }
114}
115
116pub const ENCODER_HIDE_FLAGS: u32 =
117    libobs::OBS_ENCODER_CAP_DEPRECATED | libobs::OBS_ENCODER_CAP_INTERNAL;