obs.hpp 11 KB

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