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