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