libobs_wrapper\data/
updater.rs

1use std::sync::Arc;
2
3use libobs::obs_data;
4
5use crate::{
6    run_with_obs,
7    unsafe_send::Sendable,
8    utils::{ObsError, ObsString},
9};
10
11use super::_ObsDataDropGuard;
12
13#[derive(Debug)]
14pub enum ObsDataChange {
15    String(ObsString, ObsString),
16    Int(ObsString, i64),
17    Bool(ObsString, bool),
18    Double(ObsString, f64),
19}
20
21#[derive(Debug)]
22/// Important: Make sure to call `update()` after setting the values.
23/// This will apply the changes to the `ObsData` object.
24#[must_use = "The `update()` method must be called to apply changes."]
25pub struct ObsDataUpdater {
26    pub(crate) changes: Vec<ObsDataChange>,
27    pub(crate) obs_data: Sendable<*mut obs_data>,
28    pub(crate) _drop_guard: Arc<_ObsDataDropGuard>,
29}
30
31impl ObsDataUpdater {
32    pub fn set_string_ref(&mut self, key: impl Into<ObsString>, value: impl Into<ObsString>) {
33        let key = key.into();
34        let value = value.into();
35
36        log::trace!("Setting string: {:?} = {:?}", key, value);
37        self.changes.push(ObsDataChange::String(key, value));
38    }
39
40    pub fn set_string(mut self, key: impl Into<ObsString>, value: impl Into<ObsString>) -> Self {
41        self.set_string_ref(key, value);
42        self
43    }
44
45    pub fn set_int_ref(&mut self, key: impl Into<ObsString>, value: i64) {
46        let key = key.into();
47        self.changes.push(ObsDataChange::Int(key, value));
48    }
49
50    pub fn set_int(mut self, key: impl Into<ObsString>, value: i64) -> Self {
51        self.set_int_ref(key, value);
52        self
53    }
54
55    pub fn set_bool_ref(&mut self, key: impl Into<ObsString>, value: bool) {
56        let key = key.into();
57        self.changes.push(ObsDataChange::Bool(key, value));
58    }
59
60    pub fn set_bool(mut self, key: impl Into<ObsString>, value: bool) -> Self {
61        self.set_bool_ref(key, value);
62        self
63    }
64
65    pub fn update(self) -> Result<(), ObsError> {
66        let ObsDataUpdater {
67            changes,
68            obs_data,
69            _drop_guard,
70        } = self;
71
72        let obs_data = obs_data.clone();
73        run_with_obs!(_drop_guard.runtime, (obs_data), move || unsafe {
74            for change in changes {
75                match change {
76                    ObsDataChange::String(key, value) => {
77                        libobs::obs_data_set_string(obs_data, key.as_ptr().0, value.as_ptr().0)
78                    }
79                    ObsDataChange::Int(key, value) => {
80                        libobs::obs_data_set_int(obs_data, key.as_ptr().0, value)
81                    }
82                    ObsDataChange::Bool(key, value) => {
83                        libobs::obs_data_set_bool(obs_data, key.as_ptr().0, value)
84                    }
85                    ObsDataChange::Double(key, value) => {
86                        libobs::obs_data_set_double(obs_data, key.as_ptr().0, value)
87                    }
88                };
89            }
90        })
91    }
92}