libobs_wrapper\scenes/
mod.rs1mod transform_info;
7pub use transform_info::*;
8
9mod scene_drop_guards;
10mod scene_item;
11
12mod filter_traits;
13pub use filter_traits::*;
14
15pub use scene_item::*;
16
17use std::collections::HashMap;
18use std::fmt::Debug;
19use std::sync::{Arc, RwLock};
20
21use libobs::{obs_scene_t, obs_source_t};
22
23use crate::macros::impl_eq_of_ptr;
24use crate::scenes::scene_drop_guards::_SceneDropGuard;
25use crate::sources::{ObsFilterGuardPair, ObsSourceTrait};
26use crate::unsafe_send::SmartPointerSendable;
27use crate::utils::{GeneralTraitHashMap, ObsDropGuard};
28use crate::{
29 impl_signal_manager, run_with_obs,
30 runtime::ObsRuntime,
31 unsafe_send::Sendable,
32 utils::{ObsError, ObsString},
33};
34
35#[derive(Debug)]
36struct _NoOpDropGuard;
37impl ObsDropGuard for _NoOpDropGuard {}
38
39#[derive(Debug, Clone)]
40pub struct ObsSceneRef {
42 name: ObsString,
43 attached_scene_items:
44 GeneralTraitHashMap<dyn ObsSourceTrait, Vec<Arc<Box<dyn SceneItemTrait + 'static>>>>,
45 attached_filters: Arc<RwLock<Vec<ObsFilterGuardPair>>>,
46 runtime: ObsRuntime,
47 signals: Arc<ObsSceneSignals>,
48 scene: SmartPointerSendable<*mut obs_scene_t>,
49}
50
51impl_eq_of_ptr!(ObsSceneRef);
52
53impl ObsSceneRef {
54 pub(crate) fn new(name: ObsString, runtime: ObsRuntime) -> Result<Self, ObsError> {
55 let scene = run_with_obs!(runtime, (name), move || {
56 let name_ptr = name.as_ptr();
57
58 let scene_ptr = unsafe {
59 libobs::obs_scene_create(name_ptr.0)
61 };
62 if scene_ptr.is_null() {
63 return Err(ObsError::NullPointer(None));
64 }
65
66 let source_ptr = unsafe {
67 libobs::obs_scene_get_source(scene_ptr)
69 };
70
71 if source_ptr.is_null() {
72 unsafe {
73 libobs::obs_scene_release(scene_ptr);
75 }
76 return Err(ObsError::NullPointer(None));
77 }
78
79 Ok(Sendable(scene_ptr))
80 })??;
81
82 let drop_guard = Arc::new(_SceneDropGuard::new(scene.clone(), runtime.clone()));
83 let scene = SmartPointerSendable::new(scene.0, drop_guard);
84
85 let signals = Arc::new(ObsSceneSignals::new(&scene, runtime.clone())?);
86 Ok(Self {
87 name,
88 scene,
89 attached_scene_items: Arc::new(RwLock::new(HashMap::new())),
90 attached_filters: Arc::new(RwLock::new(Vec::new())),
91 runtime,
92 signals,
93 })
94 }
95
96 #[deprecated = "Use ObsSceneRef::set_to_channel instead"]
97 pub fn add_and_set(&self, channel: u32) -> Result<(), ObsError> {
98 self.set_to_channel(channel)
99 }
100
101 pub fn set_to_channel(&self, channel: u32) -> Result<(), ObsError> {
106 if channel >= libobs::MAX_CHANNELS {
107 return Err(ObsError::InvalidOperation(format!(
108 "Channel {} is out of bounds (max {})",
109 channel,
110 libobs::MAX_CHANNELS - 1
111 )));
112 }
113
114 let scene_source_ptr = self.get_scene_source_ptr()?;
115 run_with_obs!(self.runtime, (scene_source_ptr), move || unsafe {
116 libobs::obs_set_output_source(channel, scene_source_ptr.0);
119 })
120 }
121
122 pub fn remove_from_channel(&self, channel: u32) -> Result<(), ObsError> {
124 if channel >= libobs::MAX_CHANNELS {
125 return Err(ObsError::InvalidOperation(format!(
126 "Channel {} is out of bounds (max {})",
127 channel,
128 libobs::MAX_CHANNELS - 1
129 )));
130 }
131
132 run_with_obs!(self.runtime, (), move || unsafe {
133 libobs::obs_set_output_source(channel, std::ptr::null_mut());
135 })
136 }
137
138 pub fn get_scene_source_ptr(&self) -> Result<Sendable<*mut obs_source_t>, ObsError> {
140 let scene_ptr = self.scene.clone();
141 run_with_obs!(self.runtime, (scene_ptr), move || {
142 unsafe {
143 Sendable(libobs::obs_scene_get_source(scene_ptr.get_ptr()))
145 }
146 })
147 }
148
149 pub fn as_ptr(&self) -> SmartPointerSendable<*mut obs_scene_t> {
150 self.scene.clone()
151 }
152
153 pub fn name(&self) -> ObsString {
154 self.name.clone()
155 }
156
157 pub fn signals(&self) -> Arc<ObsSceneSignals> {
158 self.signals.clone()
159 }
160}
161
162impl_signal_manager!(|scene_ptr: SmartPointerSendable<*mut obs_scene_t>| unsafe {
163 let source_ptr = libobs::obs_scene_get_source(scene_ptr.get_ptr());
165
166 libobs::obs_source_get_signal_handler(source_ptr)
167}, ObsSceneSignals for *mut obs_scene_t, [
168 "item_add": {
169 struct ItemAddSignal {
170 POINTERS {
171 item: *mut libobs::obs_sceneitem_t,
172 }
173 }
174 },
175 "item_remove": {
176 struct ItemRemoveSignal {
177 POINTERS {
178 item: *mut libobs::obs_sceneitem_t,
179 }
180 }
181 },
182 "reorder": {},
183 "refresh": {},
184 "item_visible": {
185 struct ItemVisibleSignal {
186 visible: bool;
187 POINTERS {
188 item: *mut libobs::obs_sceneitem_t,
189 }
190 }
191 },
192 "item_locked": {
193 struct ItemLockedSignal {
194 locked: bool;
195 POINTERS {
196 item: *mut libobs::obs_sceneitem_t,
197 }
198 }
199 },
200 "item_select": {
201 struct ItemSelectSignal {
202 POINTERS {
203 item: *mut libobs::obs_sceneitem_t,
204 }
205 }
206 },
207 "item_deselect": {
208 struct ItemDeselectSignal {
209 POINTERS {
210 item: *mut libobs::obs_sceneitem_t,
211 }
212 }
213 },
214 "item_transform": {
215 struct ItemTransformSignal {
216 POINTERS {
217 item: *mut libobs::obs_sceneitem_t,
218 }
219 }
220 }
221]);