1 /******************************************************************************
2 Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
17
18 /* Useful C++ classes and bindings for base obs data */
19
20 #pragma once
21
22 #include "obs.h"
23
24 /* RAII wrappers */
25
26 template<typename T, void addref(T), void release(T)> class OBSRef;
27
28 using OBSSource = OBSRef<obs_source_t *, obs_source_addref, obs_source_release>;
29 using OBSScene = OBSRef<obs_scene_t *, obs_scene_addref, obs_scene_release>;
30 using OBSSceneItem =
31 OBSRef<obs_sceneitem_t *, obs_sceneitem_addref, obs_sceneitem_release>;
32 using OBSData = OBSRef<obs_data_t *, obs_data_addref, obs_data_release>;
33 using OBSDataArray = OBSRef<obs_data_array_t *, obs_data_array_addref,
34 obs_data_array_release>;
35 using OBSOutput = OBSRef<obs_output_t *, obs_output_addref, obs_output_release>;
36 using OBSEncoder =
37 OBSRef<obs_encoder_t *, obs_encoder_addref, obs_encoder_release>;
38 using OBSService =
39 OBSRef<obs_service_t *, obs_service_addref, obs_service_release>;
40
41 using OBSWeakSource = OBSRef<obs_weak_source_t *, obs_weak_source_addref,
42 obs_weak_source_release>;
43 using OBSWeakOutput = OBSRef<obs_weak_output_t *, obs_weak_output_addref,
44 obs_weak_output_release>;
45 using OBSWeakEncoder = OBSRef<obs_weak_encoder_t *, obs_weak_encoder_addref,
46 obs_weak_encoder_release>;
47 using OBSWeakService = OBSRef<obs_weak_service_t *, obs_weak_service_addref,
48 obs_weak_service_release>;
49
50 template<typename T, void addref(T), void release(T)> class OBSRef {
51 T val;
52
Replace(T valIn)53 inline OBSRef &Replace(T valIn)
54 {
55 addref(valIn);
56 release(val);
57 val = valIn;
58 return *this;
59 }
60
61 struct TakeOwnership {
62 };
OBSRef(T val,TakeOwnership)63 inline OBSRef(T val, TakeOwnership) : val(val) {}
64
65 public:
OBSRef()66 inline OBSRef() : val(nullptr) {}
OBSRef(T val_)67 inline OBSRef(T val_) : val(val_) { addref(val); }
OBSRef(const OBSRef & ref)68 inline OBSRef(const OBSRef &ref) : val(ref.val) { addref(val); }
OBSRef(OBSRef && ref)69 inline OBSRef(OBSRef &&ref) : val(ref.val) { ref.val = nullptr; }
70
~OBSRef()71 inline ~OBSRef() { release(val); }
72
operator =(T valIn)73 inline OBSRef &operator=(T valIn) { return Replace(valIn); }
operator =(const OBSRef & ref)74 inline OBSRef &operator=(const OBSRef &ref) { return Replace(ref.val); }
75
operator =(OBSRef && ref)76 inline OBSRef &operator=(OBSRef &&ref)
77 {
78 if (this != &ref) {
79 release(val);
80 val = ref.val;
81 ref.val = nullptr;
82 }
83
84 return *this;
85 }
86
operator T() const87 inline operator T() const { return val; }
Get() const88 inline T Get() const { return val; }
89
operator ==(T p) const90 inline bool operator==(T p) const { return val == p; }
operator !=(T p) const91 inline bool operator!=(T p) const { return val != p; }
92
93 friend OBSSource OBSGetStrongRef(obs_weak_source_t *weak);
94 friend OBSWeakSource OBSGetWeakRef(obs_source_t *source);
95
96 friend OBSOutput OBSGetStrongRef(obs_weak_output_t *weak);
97 friend OBSWeakOutput OBSGetWeakRef(obs_output_t *output);
98
99 friend OBSEncoder OBSGetStrongRef(obs_weak_encoder_t *weak);
100 friend OBSWeakEncoder OBSGetWeakRef(obs_encoder_t *encoder);
101
102 friend OBSService OBSGetStrongRef(obs_weak_service_t *weak);
103 friend OBSWeakService OBSGetWeakRef(obs_service_t *service);
104 };
105
OBSGetStrongRef(obs_weak_source_t * weak)106 inline OBSSource OBSGetStrongRef(obs_weak_source_t *weak)
107 {
108 return {obs_weak_source_get_source(weak), OBSSource::TakeOwnership()};
109 }
110
OBSGetWeakRef(obs_source_t * source)111 inline OBSWeakSource OBSGetWeakRef(obs_source_t *source)
112 {
113 return {obs_source_get_weak_source(source),
114 OBSWeakSource::TakeOwnership()};
115 }
116
OBSGetStrongRef(obs_weak_output_t * weak)117 inline OBSOutput OBSGetStrongRef(obs_weak_output_t *weak)
118 {
119 return {obs_weak_output_get_output(weak), OBSOutput::TakeOwnership()};
120 }
121
OBSGetWeakRef(obs_output_t * output)122 inline OBSWeakOutput OBSGetWeakRef(obs_output_t *output)
123 {
124 return {obs_output_get_weak_output(output),
125 OBSWeakOutput::TakeOwnership()};
126 }
127
OBSGetStrongRef(obs_weak_encoder_t * weak)128 inline OBSEncoder OBSGetStrongRef(obs_weak_encoder_t *weak)
129 {
130 return {obs_weak_encoder_get_encoder(weak),
131 OBSEncoder::TakeOwnership()};
132 }
133
OBSGetWeakRef(obs_encoder_t * encoder)134 inline OBSWeakEncoder OBSGetWeakRef(obs_encoder_t *encoder)
135 {
136 return {obs_encoder_get_weak_encoder(encoder),
137 OBSWeakEncoder::TakeOwnership()};
138 }
139
OBSGetStrongRef(obs_weak_service_t * weak)140 inline OBSService OBSGetStrongRef(obs_weak_service_t *weak)
141 {
142 return {obs_weak_service_get_service(weak),
143 OBSService::TakeOwnership()};
144 }
145
OBSGetWeakRef(obs_service_t * service)146 inline OBSWeakService OBSGetWeakRef(obs_service_t *service)
147 {
148 return {obs_service_get_weak_service(service),
149 OBSWeakService::TakeOwnership()};
150 }
151
152 /* objects that are not meant to be instanced */
153 template<typename T, void destroy(T)> class OBSObj {
154 T obj;
155
156 public:
OBSObj()157 inline OBSObj() : obj(nullptr) {}
OBSObj(T obj_)158 inline OBSObj(T obj_) : obj(obj_) {}
159 inline OBSObj(const OBSObj &) = delete;
OBSObj(OBSObj && other)160 inline OBSObj(OBSObj &&other) : obj(other.obj) { other.obj = nullptr; }
161
~OBSObj()162 inline ~OBSObj() { destroy(obj); }
163
operator =(T obj_)164 inline OBSObj &operator=(T obj_)
165 {
166 if (obj_ != obj)
167 destroy(obj);
168 obj = obj_;
169 return *this;
170 }
171 inline OBSObj &operator=(const OBSObj &) = delete;
operator =(OBSObj && other)172 inline OBSObj &operator=(OBSObj &&other)
173 {
174 if (obj)
175 destroy(obj);
176 obj = other.obj;
177 other.obj = nullptr;
178 return *this;
179 }
180
operator T() const181 inline operator T() const { return obj; }
182
operator ==(T p) const183 inline bool operator==(T p) const { return obj == p; }
operator !=(T p) const184 inline bool operator!=(T p) const { return obj != p; }
185 };
186
187 using OBSDisplay = OBSObj<obs_display_t *, obs_display_destroy>;
188 using OBSView = OBSObj<obs_view_t *, obs_view_destroy>;
189
190 /* signal handler connection */
191 class OBSSignal {
192 signal_handler_t *handler;
193 const char *signal;
194 signal_callback_t callback;
195 void *param;
196
197 public:
OBSSignal()198 inline OBSSignal()
199 : handler(nullptr),
200 signal(nullptr),
201 callback(nullptr),
202 param(nullptr)
203 {
204 }
205
OBSSignal(signal_handler_t * handler_,const char * signal_,signal_callback_t callback_,void * param_)206 inline OBSSignal(signal_handler_t *handler_, const char *signal_,
207 signal_callback_t callback_, void *param_)
208 : handler(handler_),
209 signal(signal_),
210 callback(callback_),
211 param(param_)
212 {
213 signal_handler_connect_ref(handler, signal, callback, param);
214 }
215
Disconnect()216 inline void Disconnect()
217 {
218 signal_handler_disconnect(handler, signal, callback, param);
219 handler = nullptr;
220 signal = nullptr;
221 callback = nullptr;
222 param = nullptr;
223 }
224
~OBSSignal()225 inline ~OBSSignal() { Disconnect(); }
226
Connect(signal_handler_t * handler_,const char * signal_,signal_callback_t callback_,void * param_)227 inline void Connect(signal_handler_t *handler_, const char *signal_,
228 signal_callback_t callback_, void *param_)
229 {
230 Disconnect();
231
232 handler = handler_;
233 signal = signal_;
234 callback = callback_;
235 param = param_;
236 signal_handler_connect_ref(handler, signal, callback, param);
237 }
238
239 OBSSignal(const OBSSignal &) = delete;
OBSSignal(OBSSignal && other)240 OBSSignal(OBSSignal &&other) noexcept
241 : handler(other.handler),
242 signal(other.signal),
243 callback(other.callback),
244 param(other.param)
245 {
246 other.handler = nullptr;
247 other.signal = nullptr;
248 other.callback = nullptr;
249 other.param = nullptr;
250 }
251
252 OBSSignal &operator=(const OBSSignal &) = delete;
operator =(OBSSignal && other)253 OBSSignal &operator=(OBSSignal &&other) noexcept
254 {
255 Disconnect();
256
257 handler = other.handler;
258 signal = other.signal;
259 callback = other.callback;
260 param = other.param;
261
262 other.handler = nullptr;
263 other.signal = nullptr;
264 other.callback = nullptr;
265 other.param = nullptr;
266
267 return *this;
268 }
269 };
270