libobs_wrapper\data/
immutable.rs

1use std::{ffi::CStr, sync::Arc};
2
3use libobs::obs_data_t;
4
5use crate::{
6    data::ObsDataGetters, impl_obs_drop, run_with_obs, runtime::ObsRuntime, unsafe_send::Sendable,
7    utils::ObsError,
8};
9
10use super::{ObsData, _ObsDataDropGuard};
11
12#[derive(Clone, Debug)]
13/// Immutable wrapper around obs_data_t to be prevent modification and to be used in creation of other objects.
14/// This should not be updated directly using the pointer, but instead through the corresponding update methods on the holder of this data.
15pub struct ImmutableObsData {
16    ptr: Sendable<*mut obs_data_t>,
17    runtime: ObsRuntime,
18    _drop_guard: Arc<_ObsDataDropGuard>,
19}
20
21impl ImmutableObsData {
22    pub fn new(runtime: &ObsRuntime) -> Result<Self, ObsError> {
23        let ptr = run_with_obs!(runtime, move || unsafe {
24            Sendable(libobs::obs_data_create())
25        })?;
26
27        Ok(ImmutableObsData {
28            ptr: ptr.clone(),
29            runtime: runtime.clone(),
30            _drop_guard: Arc::new(_ObsDataDropGuard {
31                obs_data: ptr,
32                runtime: runtime.clone(),
33            }),
34        })
35    }
36
37    pub fn from_raw(data: Sendable<*mut obs_data_t>, runtime: ObsRuntime) -> Self {
38        ImmutableObsData {
39            ptr: data.clone(),
40            runtime: runtime.clone(),
41            _drop_guard: Arc::new(_ObsDataDropGuard {
42                obs_data: data.clone(),
43                runtime,
44            }),
45        }
46    }
47
48    pub fn to_mutable(&self) -> Result<ObsData, ObsError> {
49        let ptr = self.ptr.clone();
50        let json = run_with_obs!(self.runtime, (ptr), move || unsafe {
51            Sendable(libobs::obs_data_get_json(ptr))
52        })?;
53
54        let json = unsafe { CStr::from_ptr(json.0) }
55            .to_str()
56            .map_err(|_| ObsError::JsonParseError)?
57            .to_string();
58
59        ObsData::from_json(json.as_ref(), self.runtime.clone())
60    }
61
62    pub fn as_ptr(&self) -> Sendable<*mut obs_data_t> {
63        self.ptr.clone()
64    }
65}
66
67impl ObsDataGetters for ImmutableObsData {
68    fn runtime(&self) -> &ObsRuntime {
69        &self.runtime
70    }
71
72    fn as_ptr(&self) -> Sendable<*mut obs_data_t> {
73        self.ptr.clone()
74    }
75}
76
77impl From<ObsData> for ImmutableObsData {
78    fn from(mut data: ObsData) -> Self {
79        // Set to null pointer to prevent double free
80        let ptr = data.obs_data.0;
81
82        data.obs_data.0 = std::ptr::null_mut();
83        ImmutableObsData {
84            ptr: Sendable(ptr),
85            runtime: data.runtime.clone(),
86            _drop_guard: data._drop_guard,
87        }
88    }
89}
90
91impl_obs_drop!(ImmutableObsData, (ptr), move || unsafe {
92    libobs::obs_data_release(ptr)
93});