obs-scene.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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. #include "graphics/math-defs.h"
  15. #include "obs-scene.h"
  16. static const char *scene_getname(const char *locale)
  17. {
  18. /* TODO: locale lookup of display name */
  19. return "Scene";
  20. }
  21. static void *scene_create(const char *settings, struct obs_source *source)
  22. {
  23. struct obs_scene *scene = bmalloc(sizeof(struct obs_scene));
  24. scene->source = source;
  25. scene->first_item = NULL;
  26. if (pthread_mutex_init(&scene->mutex, NULL) != 0) {
  27. blog(LOG_ERROR, "scene_create: Couldn't initialize mutex");
  28. bfree(scene);
  29. return NULL;
  30. }
  31. return scene;
  32. }
  33. static void scene_destroy(void *data)
  34. {
  35. struct obs_scene *scene = data;
  36. struct obs_scene_item *item = scene->first_item;
  37. while (item) {
  38. struct obs_scene_item *del_item = item;
  39. item = item->next;
  40. if (del_item->source)
  41. obs_source_release(del_item->source);
  42. bfree(del_item);
  43. }
  44. pthread_mutex_destroy(&scene->mutex);
  45. bfree(scene);
  46. }
  47. static uint32_t scene_get_output_flags(void *data)
  48. {
  49. return SOURCE_VIDEO;
  50. }
  51. static inline void detach_sceneitem(struct obs_scene_item *item)
  52. {
  53. if (item->prev)
  54. item->prev->next = item->next;
  55. else
  56. item->parent->first_item = item->next;
  57. if (item->next)
  58. item->next->prev = item->prev;
  59. }
  60. static inline void attach_sceneitem(struct obs_scene_item *item,
  61. struct obs_scene_item *prev)
  62. {
  63. item->prev = prev;
  64. if (prev) {
  65. item->next = prev->next;
  66. if (prev->next)
  67. prev->next->prev = item;
  68. prev->next = item;
  69. } else {
  70. item->next = item->parent->first_item;
  71. item->parent->first_item = item;
  72. }
  73. }
  74. static void scene_video_render(void *data)
  75. {
  76. struct obs_scene *scene = data;
  77. struct obs_scene_item *item = scene->first_item;
  78. pthread_mutex_lock(&scene->mutex);
  79. while (item) {
  80. if (obs_source_removed(item->source)) {
  81. struct obs_scene_item *del_item = item;
  82. item = item->next;
  83. obs_sceneitem_destroy(del_item);
  84. continue;
  85. }
  86. gs_matrix_push();
  87. gs_matrix_translate3f(item->origin.x, item->origin.y, 0.0f);
  88. gs_matrix_scale3f(item->scale.x, item->scale.y, 1.0f);
  89. gs_matrix_rotaa4f(0.0f, 0.0f, 1.0f, RAD(-item->rot));
  90. gs_matrix_translate3f(-item->pos.x, -item->pos.y, 0.0f);
  91. obs_source_video_render(item->source);
  92. gs_matrix_pop();
  93. item = item->next;
  94. }
  95. pthread_mutex_unlock(&scene->mutex);
  96. }
  97. static uint32_t scene_getsize(void *data)
  98. {
  99. return 0;
  100. }
  101. static const struct source_info scene_info =
  102. {
  103. .id = "scene",
  104. .getname = scene_getname,
  105. .create = scene_create,
  106. .destroy = scene_destroy,
  107. .get_output_flags = scene_get_output_flags,
  108. .video_render = scene_video_render,
  109. .getwidth = scene_getsize,
  110. .getheight = scene_getsize,
  111. };
  112. obs_scene_t obs_scene_create(const char *name)
  113. {
  114. struct obs_source *source = bmalloc(sizeof(struct obs_source));
  115. struct obs_scene *scene = scene_create(NULL, source);
  116. memset(source, 0, sizeof(struct obs_source));
  117. source->data = scene;
  118. assert(source->data);
  119. if (!source->data) {
  120. bfree(source);
  121. return NULL;
  122. }
  123. source->name = bstrdup(name);
  124. source->type = SOURCE_SCENE;
  125. scene->source = source;
  126. obs_source_init(source, NULL, &scene_info);
  127. memcpy(&source->callbacks, &scene_info, sizeof(struct source_info));
  128. return scene;
  129. }
  130. int obs_scene_addref(obs_scene_t scene)
  131. {
  132. return obs_source_addref(scene->source);
  133. }
  134. int obs_scene_release(obs_scene_t scene)
  135. {
  136. if (scene)
  137. return obs_source_release(scene->source);
  138. return 0;
  139. }
  140. obs_source_t obs_scene_getsource(obs_scene_t scene)
  141. {
  142. return scene->source;
  143. }
  144. obs_scene_t obs_scene_fromsource(obs_source_t source)
  145. {
  146. if (source->type != SOURCE_SCENE)
  147. return NULL;
  148. return source->data;
  149. }
  150. obs_sceneitem_t obs_scene_findsource(obs_scene_t scene, const char *name)
  151. {
  152. struct obs_scene_item *item;
  153. pthread_mutex_lock(&scene->mutex);
  154. item = scene->first_item;
  155. while (item) {
  156. if (strcmp(item->source->name, name) == 0) {
  157. break;
  158. }
  159. item = item->next;
  160. }
  161. pthread_mutex_unlock(&scene->mutex);
  162. return item;
  163. }
  164. void obs_scene_enum_items(obs_scene_t scene,
  165. bool (*callback)(obs_scene_t, obs_sceneitem_t, void*),
  166. void *param)
  167. {
  168. struct obs_scene_item *item;
  169. pthread_mutex_lock(&scene->mutex);
  170. item = scene->first_item;
  171. while (item) {
  172. if (!callback(scene, item, param))
  173. break;
  174. item = item->next;
  175. }
  176. pthread_mutex_unlock(&scene->mutex);
  177. }
  178. obs_sceneitem_t obs_scene_add(obs_scene_t scene, obs_source_t source)
  179. {
  180. struct obs_scene_item *last;
  181. struct obs_scene_item *item = bmalloc(sizeof(struct obs_scene_item));
  182. memset(item, 0, sizeof(struct obs_scene_item));
  183. item->source = source;
  184. item->visible = true;
  185. item->parent = scene;
  186. vec2_set(&item->scale, 1.0f, 1.0f);
  187. if (source)
  188. obs_source_addref(source);
  189. pthread_mutex_lock(&scene->mutex);
  190. last = scene->first_item;
  191. if (!last) {
  192. scene->first_item = item;
  193. } else {
  194. while (last->next)
  195. last = last->next;
  196. last->next = item;
  197. item->prev = last;
  198. }
  199. pthread_mutex_unlock(&scene->mutex);
  200. return item;
  201. }
  202. int obs_sceneitem_destroy(obs_sceneitem_t item)
  203. {
  204. int ref = 0;
  205. if (item) {
  206. detach_sceneitem(item);
  207. if (item->source)
  208. ref = obs_source_release(item->source);
  209. bfree(item);
  210. }
  211. return ref;
  212. }
  213. obs_source_t obs_sceneitem_getsource(obs_sceneitem_t item)
  214. {
  215. return item->source;
  216. }
  217. void obs_sceneitem_setpos(obs_sceneitem_t item, const struct vec2 *pos)
  218. {
  219. vec2_copy(&item->pos, pos);
  220. }
  221. void obs_sceneitem_setrot(obs_sceneitem_t item, float rot)
  222. {
  223. item->rot = rot;
  224. }
  225. void obs_sceneitem_setorigin(obs_sceneitem_t item, const struct vec2 *origin)
  226. {
  227. vec2_copy(&item->origin, origin);
  228. }
  229. void obs_sceneitem_setscale(obs_sceneitem_t item, const struct vec2 *scale)
  230. {
  231. vec2_copy(&item->scale, scale);
  232. }
  233. void obs_sceneitem_setorder(obs_sceneitem_t item, enum order_movement movement)
  234. {
  235. struct obs_scene *scene = item->parent;
  236. pthread_mutex_lock(&scene->mutex);
  237. detach_sceneitem(item);
  238. if (movement == ORDER_MOVE_UP) {
  239. attach_sceneitem(item, item->prev);
  240. } else if (movement == ORDER_MOVE_DOWN) {
  241. attach_sceneitem(item, item->next);
  242. } else if (movement == ORDER_MOVE_TOP) {
  243. struct obs_scene_item *last = item->next;
  244. if (!last) {
  245. last = item->prev;
  246. } else {
  247. while (last->next)
  248. last = last->next;
  249. }
  250. attach_sceneitem(item, last);
  251. } else if (movement == ORDER_MOVE_BOTTOM) {
  252. attach_sceneitem(item, NULL);
  253. }
  254. pthread_mutex_unlock(&scene->mutex);
  255. }
  256. void obs_sceneitem_getpos(obs_sceneitem_t item, struct vec2 *pos)
  257. {
  258. vec2_copy(pos, &item->pos);
  259. }
  260. float obs_sceneitem_getrot(obs_sceneitem_t item)
  261. {
  262. return item->rot;
  263. }
  264. void obs_sceneitem_getorigin(obs_sceneitem_t item, struct vec2 *origin)
  265. {
  266. vec2_copy(origin, &item->origin);
  267. }
  268. void obs_sceneitem_getscale(obs_sceneitem_t item, struct vec2 *scale)
  269. {
  270. vec2_copy(scale, &item->scale);
  271. }