libobs_wrapper\sources/
mod.rs

1mod builder;
2pub use builder::*;
3
4use libobs::{
5    obs_scene_item, obs_source_create, obs_source_release, obs_source_reset_settings, obs_source_t,
6    obs_source_update,
7};
8
9use crate::{
10    data::{immutable::ImmutableObsData, ObsData},
11    impl_obs_drop, impl_signal_manager, run_with_obs,
12    runtime::ObsRuntime,
13    unsafe_send::Sendable,
14    utils::{traits::ObsUpdatable, ObsError, ObsString},
15};
16
17use std::{ptr, sync::Arc};
18
19#[derive(Debug, Clone)]
20#[allow(dead_code)]
21pub struct ObsSourceRef {
22    pub(crate) source: Sendable<*mut obs_source_t>,
23    pub(crate) id: ObsString,
24    pub(crate) name: ObsString,
25    pub(crate) settings: Arc<ImmutableObsData>,
26    pub(crate) hotkey_data: Arc<ImmutableObsData>,
27    pub(crate) scene_item: Option<Sendable<*mut obs_scene_item>>,
28
29    _guard: Arc<_ObsSourceGuard>,
30    pub(crate) runtime: ObsRuntime,
31    pub(crate) signal_manager: Arc<ObsSourceSignals>,
32}
33
34impl ObsSourceRef {
35    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
36    pub async fn new<T: Into<ObsString> + Sync + Send, K: Into<ObsString> + Sync + Send>(
37        id: T,
38        name: K,
39        mut settings: Option<ObsData>,
40        mut hotkey_data: Option<ObsData>,
41        runtime: ObsRuntime,
42    ) -> Result<Self, ObsError> {
43        let id = id.into();
44        let name = name.into();
45
46        let settings = match settings.take() {
47            Some(x) => ImmutableObsData::from(x),
48            None => ImmutableObsData::new(&runtime).await?,
49        };
50
51        let hotkey_data = match hotkey_data.take() {
52            Some(x) => ImmutableObsData::from(x),
53            None => ImmutableObsData::new(&runtime).await?,
54        };
55
56        let hotkey_data_ptr = hotkey_data.as_ptr();
57        let settings_ptr = settings.as_ptr();
58        let id_ptr = id.as_ptr();
59        let name_ptr = name.as_ptr();
60
61        let source = run_with_obs!(
62            runtime,
63            (hotkey_data_ptr, settings_ptr, id_ptr, name_ptr),
64            move || unsafe {
65                Sendable(obs_source_create(
66                    id_ptr,
67                    name_ptr,
68                    settings_ptr,
69                    hotkey_data_ptr,
70                ))
71            }
72        )
73        .await?;
74
75        if source.0 == ptr::null_mut() {
76            return Err(ObsError::NullPointer);
77        }
78
79        let signals = ObsSourceSignals::new(&source, runtime.clone()).await?;
80        Ok(Self {
81            source: source.clone(),
82            id,
83            name,
84            settings: Arc::new(settings),
85            hotkey_data: Arc::new(hotkey_data),
86            _guard: Arc::new(_ObsSourceGuard {
87                source,
88                runtime: runtime.clone(),
89            }),
90            scene_item: None,
91            runtime,
92            signal_manager: Arc::new(signals),
93        })
94    }
95
96    pub fn settings(&self) -> &ImmutableObsData {
97        &self.settings
98    }
99
100    pub fn hotkey_data(&self) -> &ImmutableObsData {
101        &self.hotkey_data
102    }
103
104    pub fn name(&self) -> String {
105        self.name.to_string()
106    }
107
108    pub fn id(&self) -> String {
109        self.id.to_string()
110    }
111
112    pub fn signal_manager(&self) -> Arc<ObsSourceSignals> {
113        self.signal_manager.clone()
114    }
115}
116
117#[cfg_attr(not(feature = "blocking"), async_trait::async_trait)]
118impl ObsUpdatable for ObsSourceRef {
119    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
120    async fn update_raw(&mut self, data: ObsData) -> Result<(), ObsError> {
121        let data_ptr = data.as_ptr();
122        let source_ptr = self.source.clone();
123        log::trace!("Updating source: {:?}", self.source);
124        run_with_obs!(self.runtime, (source_ptr, data_ptr), move || unsafe {
125            obs_source_update(source_ptr, data_ptr);
126        })
127        .await
128    }
129
130    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
131    async fn reset_and_update_raw(&mut self, data: ObsData) -> Result<(), ObsError> {
132        let source_ptr = self.source.clone();
133        run_with_obs!(self.runtime, (source_ptr), move || unsafe {
134            obs_source_reset_settings(source_ptr, data.as_ptr().0);
135        })
136        .await
137    }
138
139    fn runtime(&self) -> ObsRuntime {
140        self.runtime.clone()
141    }
142
143    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
144    async fn get_settings(&self) -> Result<ImmutableObsData, ObsError> {
145        log::trace!("Getting settings for source: {:?}", self.source);
146        let source_ptr = self.source.clone();
147        let res = run_with_obs!(self.runtime, (source_ptr), move || unsafe {
148            Sendable(libobs::obs_source_get_settings(source_ptr))
149        })
150        .await?;
151
152        log::trace!("Got settings: {:?}", res);
153        Ok(ImmutableObsData::from_raw(res, self.runtime.clone()).await)
154    }
155}
156
157impl_signal_manager!(|ptr| libobs::obs_source_get_signal_handler(ptr), ObsSourceSignals for ObsSourceRef<*mut libobs::obs_source_t>, [
158    "destroy": {},
159    "remove": {},
160    "update": {},
161    "save": {},
162    "load": {},
163    "activate": {},
164    "deactivate": {},
165    "show": {},
166    "hide": {},
167    "mute": { struct MuteSignal {
168        muted: bool
169    } },
170    "push_to_mute_changed": {struct PushToMuteChangedSignal {
171        enabled: bool
172    }},
173    "push_to_mute_delay": {struct PushToMuteDelaySignal {
174        delay: i64
175    }},
176    "push_to_talk_changed": {struct PushToTalkChangedSignal {
177        enabled: bool
178    }},
179    "push_to_talk_delay": {struct PushToTalkDelaySignal {
180        delay: i64
181    }},
182    "enable": {struct EnableSignal {
183        enabled: bool
184    }},
185    "rename": {struct NewNameSignal {
186        new_name: String,
187        prev_name: String
188    }},
189    "update_properties": {},
190    "update_flags": {struct UpdateFlagsSignal {
191        flags: i64
192    }},
193    "audio_sync": {struct AudioSyncSignal {
194        offset: i64,
195    }},
196    "audio_balance": {struct AudioBalanceSignal {
197        balance: f64,
198    }},
199    "audio_mixers": {struct AudioMixersSignal {
200        mixers: i64,
201    }},
202    "audio_activate": {},
203    "audio_deactivate": {},
204    "filter_add": {struct FilterAddSignal {
205        POINTERS {
206            filter: *mut libobs::obs_source_t,
207        }
208    }},
209    "filter_remove": {struct FilterRemoveSignal {
210        POINTERS {
211            filter: *mut libobs::obs_source_t,
212        }
213    }},
214    "reorder_filters": {},
215    "transition_start": {},
216    "transition_video_stop": {},
217    "transition_stop": {},
218    "media_started": {},
219    "media_ended":{},
220    "media_pause": {},
221    "media_play": {},
222    "media_restart": {},
223    "media_stopped": {},
224    "media_next": {},
225    "media_previous": {}
226]);
227
228#[derive(Debug)]
229struct _ObsSourceGuard {
230    source: Sendable<*mut obs_source_t>,
231    runtime: ObsRuntime,
232}
233
234impl_obs_drop!(_ObsSourceGuard, (source), move || unsafe {
235    obs_source_release(source);
236});