obs.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /******************************************************************************
  2. Copyright (C) 2013 by Hugh 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 OBSSource =
  22. OBSSafeRef<obs_source_t *, obs_source_get_ref, obs_source_release>;
  23. using OBSScene =
  24. OBSSafeRef<obs_scene_t *, obs_scene_get_ref, obs_scene_release>;
  25. using OBSSceneItem =
  26. OBSRef<obs_sceneitem_t *, obs_sceneitem_addref, obs_sceneitem_release>;
  27. using OBSData = OBSRef<obs_data_t *, obs_data_addref, obs_data_release>;
  28. using OBSDataArray = OBSRef<obs_data_array_t *, obs_data_array_addref,
  29. obs_data_array_release>;
  30. using OBSOutput =
  31. OBSSafeRef<obs_output_t *, obs_output_get_ref, obs_output_release>;
  32. using OBSEncoder =
  33. OBSSafeRef<obs_encoder_t *, obs_encoder_get_ref, obs_encoder_release>;
  34. using OBSService =
  35. OBSSafeRef<obs_service_t *, obs_service_get_ref, obs_service_release>;
  36. using OBSWeakSource = OBSRef<obs_weak_source_t *, obs_weak_source_addref,
  37. obs_weak_source_release>;
  38. using OBSWeakOutput = OBSRef<obs_weak_output_t *, obs_weak_output_addref,
  39. obs_weak_output_release>;
  40. using OBSWeakEncoder = OBSRef<obs_weak_encoder_t *, obs_weak_encoder_addref,
  41. obs_weak_encoder_release>;
  42. using OBSWeakService = OBSRef<obs_weak_service_t *, obs_weak_service_addref,
  43. obs_weak_service_release>;
  44. #define OBS_AUTORELEASE
  45. using OBSSourceAutoRelease =
  46. OBSRefAutoRelease<obs_source_t *, obs_source_release>;
  47. using OBSSceneAutoRelease = OBSRefAutoRelease<obs_scene_t *, obs_scene_release>;
  48. using OBSSceneItemAutoRelease =
  49. OBSRefAutoRelease<obs_sceneitem_t *, obs_sceneitem_release>;
  50. using OBSDataAutoRelease = OBSRefAutoRelease<obs_data_t *, obs_data_release>;
  51. using OBSDataArrayAutoRelease =
  52. OBSRefAutoRelease<obs_data_array_t *, obs_data_array_release>;
  53. using OBSOutputAutoRelease =
  54. OBSRefAutoRelease<obs_output_t *, obs_output_release>;
  55. using OBSEncoderAutoRelease =
  56. OBSRefAutoRelease<obs_encoder_t *, obs_encoder_release>;
  57. using OBSServiceAutoRelease =
  58. OBSRefAutoRelease<obs_service_t *, obs_service_release>;
  59. using OBSWeakSourceAutoRelease =
  60. OBSRefAutoRelease<obs_weak_source_t *, obs_weak_source_release>;
  61. using OBSWeakOutputAutoRelease =
  62. OBSRefAutoRelease<obs_weak_output_t *, obs_weak_output_release>;
  63. using OBSWeakEncoderAutoRelease =
  64. OBSRefAutoRelease<obs_weak_encoder_t *, obs_weak_encoder_release>;
  65. using OBSWeakServiceAutoRelease =
  66. OBSRefAutoRelease<obs_weak_service_t *, obs_weak_service_release>;
  67. template<typename T, void release(T)> class OBSRefAutoRelease {
  68. protected:
  69. T val;
  70. public:
  71. inline OBSRefAutoRelease() : val(nullptr) {}
  72. inline OBSRefAutoRelease(T val_) : val(val_) {}
  73. OBSRefAutoRelease(const OBSRefAutoRelease &ref) = delete;
  74. inline OBSRefAutoRelease(OBSRefAutoRelease &&ref) : val(ref.val)
  75. {
  76. ref.val = nullptr;
  77. }
  78. inline ~OBSRefAutoRelease() { release(val); }
  79. inline operator T() const { return val; }
  80. inline T Get() const { return val; }
  81. inline bool operator==(T p) const { return val == p; }
  82. inline bool operator!=(T p) const { return val != p; }
  83. inline OBSRefAutoRelease &operator=(OBSRefAutoRelease &&ref)
  84. {
  85. if (this != &ref) {
  86. release(val);
  87. val = ref.val;
  88. ref.val = nullptr;
  89. }
  90. return *this;
  91. }
  92. inline OBSRefAutoRelease &operator=(T new_val)
  93. {
  94. release(val);
  95. val = new_val;
  96. return *this;
  97. }
  98. };
  99. template<typename T, void addref(T), void release(T)>
  100. class OBSRef : public OBSRefAutoRelease<T, release> {
  101. inline OBSRef &Replace(T valIn)
  102. {
  103. addref(valIn);
  104. release(this->val);
  105. this->val = valIn;
  106. return *this;
  107. }
  108. struct TakeOwnership {
  109. };
  110. inline OBSRef(T val_, TakeOwnership)
  111. : OBSRefAutoRelease<T, release>::OBSRefAutoRelease(val_)
  112. {
  113. }
  114. public:
  115. inline OBSRef()
  116. : OBSRefAutoRelease<T, release>::OBSRefAutoRelease(nullptr)
  117. {
  118. }
  119. inline OBSRef(const OBSRef &ref)
  120. : OBSRefAutoRelease<T, release>::OBSRefAutoRelease(ref.val)
  121. {
  122. addref(this->val);
  123. }
  124. inline OBSRef(T val_)
  125. : OBSRefAutoRelease<T, release>::OBSRefAutoRelease(val_)
  126. {
  127. addref(this->val);
  128. }
  129. inline OBSRef &operator=(const OBSRef &ref) { return Replace(ref.val); }
  130. inline OBSRef &operator=(T valIn) { return Replace(valIn); }
  131. friend OBSWeakSource OBSGetWeakRef(obs_source_t *source);
  132. friend OBSWeakOutput OBSGetWeakRef(obs_output_t *output);
  133. friend OBSWeakEncoder OBSGetWeakRef(obs_encoder_t *encoder);
  134. friend OBSWeakService OBSGetWeakRef(obs_service_t *service);
  135. };
  136. template<typename T, T getref(T), void release(T)>
  137. class OBSSafeRef : public OBSRefAutoRelease<T, release> {
  138. inline OBSSafeRef &Replace(T valIn)
  139. {
  140. T newVal = getref(valIn);
  141. release(this->val);
  142. this->val = newVal;
  143. return *this;
  144. }
  145. struct TakeOwnership {
  146. };
  147. inline OBSSafeRef(T val_, TakeOwnership)
  148. : OBSRefAutoRelease<T, release>::OBSRefAutoRelease(val_)
  149. {
  150. }
  151. public:
  152. inline OBSSafeRef()
  153. : OBSRefAutoRelease<T, release>::OBSRefAutoRelease(nullptr)
  154. {
  155. }
  156. inline OBSSafeRef(const OBSSafeRef &ref)
  157. : OBSRefAutoRelease<T, release>::OBSRefAutoRelease(ref.val)
  158. {
  159. this->val = getref(ref.val);
  160. }
  161. inline OBSSafeRef(T val_)
  162. : OBSRefAutoRelease<T, release>::OBSRefAutoRelease(val_)
  163. {
  164. this->val = getref(this->val);
  165. }
  166. inline OBSSafeRef &operator=(const OBSSafeRef &ref)
  167. {
  168. return Replace(ref.val);
  169. }
  170. inline OBSSafeRef &operator=(T valIn) { return Replace(valIn); }
  171. friend OBSSource OBSGetStrongRef(obs_weak_source_t *weak);
  172. friend OBSOutput OBSGetStrongRef(obs_weak_output_t *weak);
  173. friend OBSEncoder OBSGetStrongRef(obs_weak_encoder_t *weak);
  174. friend OBSService OBSGetStrongRef(obs_weak_service_t *weak);
  175. };
  176. inline OBSSource OBSGetStrongRef(obs_weak_source_t *weak)
  177. {
  178. return {obs_weak_source_get_source(weak), OBSSource::TakeOwnership()};
  179. }
  180. inline OBSWeakSource OBSGetWeakRef(obs_source_t *source)
  181. {
  182. return {obs_source_get_weak_source(source),
  183. OBSWeakSource::TakeOwnership()};
  184. }
  185. inline OBSOutput OBSGetStrongRef(obs_weak_output_t *weak)
  186. {
  187. return {obs_weak_output_get_output(weak), OBSOutput::TakeOwnership()};
  188. }
  189. inline OBSWeakOutput OBSGetWeakRef(obs_output_t *output)
  190. {
  191. return {obs_output_get_weak_output(output),
  192. OBSWeakOutput::TakeOwnership()};
  193. }
  194. inline OBSEncoder OBSGetStrongRef(obs_weak_encoder_t *weak)
  195. {
  196. return {obs_weak_encoder_get_encoder(weak),
  197. OBSEncoder::TakeOwnership()};
  198. }
  199. inline OBSWeakEncoder OBSGetWeakRef(obs_encoder_t *encoder)
  200. {
  201. return {obs_encoder_get_weak_encoder(encoder),
  202. OBSWeakEncoder::TakeOwnership()};
  203. }
  204. inline OBSService OBSGetStrongRef(obs_weak_service_t *weak)
  205. {
  206. return {obs_weak_service_get_service(weak),
  207. OBSService::TakeOwnership()};
  208. }
  209. inline OBSWeakService OBSGetWeakRef(obs_service_t *service)
  210. {
  211. return {obs_service_get_weak_service(service),
  212. OBSWeakService::TakeOwnership()};
  213. }
  214. /* objects that are not meant to be instanced */
  215. template<typename T, void destroy(T)> class OBSObj {
  216. T obj;
  217. public:
  218. inline OBSObj() : obj(nullptr) {}
  219. inline OBSObj(T obj_) : obj(obj_) {}
  220. inline OBSObj(const OBSObj &) = delete;
  221. inline OBSObj(OBSObj &&other) : obj(other.obj) { other.obj = nullptr; }
  222. inline ~OBSObj() { destroy(obj); }
  223. inline OBSObj &operator=(T obj_)
  224. {
  225. if (obj_ != obj)
  226. destroy(obj);
  227. obj = obj_;
  228. return *this;
  229. }
  230. inline OBSObj &operator=(const OBSObj &) = delete;
  231. inline OBSObj &operator=(OBSObj &&other)
  232. {
  233. if (obj)
  234. destroy(obj);
  235. obj = other.obj;
  236. other.obj = nullptr;
  237. return *this;
  238. }
  239. inline operator T() const { return obj; }
  240. inline bool operator==(T p) const { return obj == p; }
  241. inline bool operator!=(T p) const { return obj != p; }
  242. };
  243. using OBSDisplay = OBSObj<obs_display_t *, obs_display_destroy>;
  244. using OBSView = OBSObj<obs_view_t *, obs_view_destroy>;
  245. /* signal handler connection */
  246. class OBSSignal {
  247. signal_handler_t *handler;
  248. const char *signal;
  249. signal_callback_t callback;
  250. void *param;
  251. public:
  252. inline OBSSignal()
  253. : handler(nullptr),
  254. signal(nullptr),
  255. callback(nullptr),
  256. param(nullptr)
  257. {
  258. }
  259. inline OBSSignal(signal_handler_t *handler_, const char *signal_,
  260. signal_callback_t callback_, void *param_)
  261. : handler(handler_),
  262. signal(signal_),
  263. callback(callback_),
  264. param(param_)
  265. {
  266. signal_handler_connect_ref(handler, signal, callback, param);
  267. }
  268. inline void Disconnect()
  269. {
  270. signal_handler_disconnect(handler, signal, callback, param);
  271. handler = nullptr;
  272. signal = nullptr;
  273. callback = nullptr;
  274. param = nullptr;
  275. }
  276. inline ~OBSSignal() { Disconnect(); }
  277. inline void Connect(signal_handler_t *handler_, const char *signal_,
  278. signal_callback_t callback_, void *param_)
  279. {
  280. Disconnect();
  281. handler = handler_;
  282. signal = signal_;
  283. callback = callback_;
  284. param = param_;
  285. signal_handler_connect_ref(handler, signal, callback, param);
  286. }
  287. OBSSignal(const OBSSignal &) = delete;
  288. OBSSignal(OBSSignal &&other) noexcept
  289. : handler(other.handler),
  290. signal(other.signal),
  291. callback(other.callback),
  292. param(other.param)
  293. {
  294. other.handler = nullptr;
  295. other.signal = nullptr;
  296. other.callback = nullptr;
  297. other.param = nullptr;
  298. }
  299. OBSSignal &operator=(const OBSSignal &) = delete;
  300. OBSSignal &operator=(OBSSignal &&other) noexcept
  301. {
  302. Disconnect();
  303. handler = other.handler;
  304. signal = other.signal;
  305. callback = other.callback;
  306. param = other.param;
  307. other.handler = nullptr;
  308. other.signal = nullptr;
  309. other.callback = nullptr;
  310. other.param = nullptr;
  311. return *this;
  312. }
  313. };