obs-scripting-python-frontend.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /******************************************************************************
  2. Copyright (C) 2017 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 <obs-module.h>
  15. #include <obs-frontend-api.h>
  16. #include "obs-scripting-python.h"
  17. #define libobs_to_py(type, obs_obj, ownership, py_obj) \
  18. libobs_to_py_(#type " *", obs_obj, ownership, py_obj, \
  19. NULL, __func__, __LINE__)
  20. #define py_to_libobs(type, py_obj, libobs_out) \
  21. py_to_libobs_(#type " *", py_obj, libobs_out, \
  22. NULL, __func__, __LINE__)
  23. /* ----------------------------------- */
  24. static PyObject *get_scene_names(PyObject *self, PyObject *args)
  25. {
  26. char **names = obs_frontend_get_scene_names();
  27. char **name = names;
  28. PyObject *list = PyList_New(0);
  29. while (name && *name) {
  30. PyObject *py_name = PyUnicode_FromString(*name);
  31. if (py_name) {
  32. PyList_Append(list, py_name);
  33. Py_DECREF(py_name);
  34. }
  35. name++;
  36. }
  37. UNUSED_PARAMETER(self);
  38. UNUSED_PARAMETER(args);
  39. bfree(names);
  40. return list;
  41. }
  42. static PyObject *get_scenes(PyObject *self, PyObject *args)
  43. {
  44. struct obs_frontend_source_list list = {0};
  45. obs_frontend_get_scenes(&list);
  46. PyObject *ret = PyList_New(0);
  47. for (size_t i = 0; i < list.sources.num; i++) {
  48. obs_source_t *source = list.sources.array[i];
  49. PyObject *py_source;
  50. if (libobs_to_py(obs_source_t, source, false, &py_source)) {
  51. PyList_Append(ret, py_source);
  52. Py_DECREF(py_source);
  53. }
  54. }
  55. UNUSED_PARAMETER(self);
  56. UNUSED_PARAMETER(args);
  57. da_free(list.sources);
  58. return ret;
  59. }
  60. static PyObject *get_current_scene(PyObject *self, PyObject *args)
  61. {
  62. obs_source_t *source = obs_frontend_get_current_scene();
  63. PyObject *py_source;
  64. if (!libobs_to_py(obs_source_t, source, false, &py_source)) {
  65. obs_source_release(source);
  66. return python_none();
  67. }
  68. UNUSED_PARAMETER(self);
  69. UNUSED_PARAMETER(args);
  70. return py_source;
  71. }
  72. static PyObject *set_current_scene(PyObject *self, PyObject *args)
  73. {
  74. PyObject *py_source;
  75. obs_source_t *source = NULL;
  76. if (!parse_args(args, "O", &py_source))
  77. return python_none();
  78. if (!py_to_libobs(obs_source_t, py_source, &source))
  79. return python_none();
  80. UNUSED_PARAMETER(self);
  81. obs_frontend_set_current_scene(source);
  82. return python_none();
  83. }
  84. static PyObject *get_transitions(PyObject *self, PyObject *args)
  85. {
  86. struct obs_frontend_source_list list = {0};
  87. obs_frontend_get_transitions(&list);
  88. PyObject *ret = PyList_New(0);
  89. for (size_t i = 0; i < list.sources.num; i++) {
  90. obs_source_t *source = list.sources.array[i];
  91. PyObject *py_source;
  92. if (libobs_to_py(obs_source_t, source, false, &py_source)) {
  93. PyList_Append(ret, py_source);
  94. Py_DECREF(py_source);
  95. }
  96. }
  97. UNUSED_PARAMETER(self);
  98. UNUSED_PARAMETER(args);
  99. da_free(list.sources);
  100. return ret;
  101. }
  102. static PyObject *get_current_transition(PyObject *self, PyObject *args)
  103. {
  104. obs_source_t *source = obs_frontend_get_current_transition();
  105. PyObject *py_source;
  106. if (!libobs_to_py(obs_source_t, source, false, &py_source)) {
  107. obs_source_release(source);
  108. return python_none();
  109. }
  110. UNUSED_PARAMETER(self);
  111. UNUSED_PARAMETER(args);
  112. return py_source;
  113. }
  114. static PyObject *set_current_transition(PyObject *self, PyObject *args)
  115. {
  116. PyObject *py_source;
  117. obs_source_t *source = NULL;
  118. if (!parse_args(args, "O", &py_source))
  119. return python_none();
  120. if (!py_to_libobs(obs_source_t, py_source, &source))
  121. return python_none();
  122. UNUSED_PARAMETER(self);
  123. obs_frontend_set_current_transition(source);
  124. return python_none();
  125. }
  126. static PyObject *get_scene_collections(PyObject *self, PyObject *args)
  127. {
  128. char **names = obs_frontend_get_scene_collections();
  129. char **name = names;
  130. PyObject *list = PyList_New(0);
  131. while (name && *name) {
  132. PyObject *py_name = PyUnicode_FromString(*name);
  133. if (py_name) {
  134. PyList_Append(list, py_name);
  135. Py_DECREF(py_name);
  136. }
  137. name++;
  138. }
  139. UNUSED_PARAMETER(self);
  140. UNUSED_PARAMETER(args);
  141. bfree(names);
  142. return list;
  143. }
  144. static PyObject *get_current_scene_collection(PyObject *self, PyObject *args)
  145. {
  146. char *name = obs_frontend_get_current_scene_collection();
  147. PyObject *ret = PyUnicode_FromString(name);
  148. bfree(name);
  149. UNUSED_PARAMETER(self);
  150. UNUSED_PARAMETER(args);
  151. return ret;
  152. }
  153. static PyObject *set_current_scene_collection(PyObject *self, PyObject *args)
  154. {
  155. const char *name;
  156. if (!parse_args(args, "s", &name))
  157. return python_none();
  158. UNUSED_PARAMETER(self);
  159. obs_frontend_set_current_scene_collection(name);
  160. return python_none();
  161. }
  162. static PyObject *get_profiles(PyObject *self, PyObject *args)
  163. {
  164. char **names = obs_frontend_get_profiles();
  165. char **name = names;
  166. PyObject *list = PyList_New(0);
  167. while (name && *name) {
  168. PyObject *py_name = PyUnicode_FromString(*name);
  169. if (py_name) {
  170. PyList_Append(list, py_name);
  171. Py_DECREF(py_name);
  172. }
  173. name++;
  174. }
  175. UNUSED_PARAMETER(self);
  176. UNUSED_PARAMETER(args);
  177. bfree(names);
  178. return list;
  179. }
  180. static PyObject *get_current_profile(PyObject *self, PyObject *args)
  181. {
  182. char *name = obs_frontend_get_current_profile();
  183. PyObject *ret = PyUnicode_FromString(name);
  184. bfree(name);
  185. UNUSED_PARAMETER(self);
  186. UNUSED_PARAMETER(args);
  187. return ret;
  188. }
  189. static PyObject *set_current_profile(PyObject *self, PyObject *args)
  190. {
  191. const char *name;
  192. if (!parse_args(args, "s", &name))
  193. return python_none();
  194. UNUSED_PARAMETER(self);
  195. obs_frontend_set_current_profile(name);
  196. return python_none();
  197. }
  198. /* ----------------------------------- */
  199. static void frontend_save_callback(obs_data_t *save_data, bool saving,
  200. void *priv)
  201. {
  202. struct python_obs_callback *cb = priv;
  203. if (cb->base.removed) {
  204. obs_frontend_remove_save_callback(frontend_save_callback, cb);
  205. return;
  206. }
  207. lock_python();
  208. PyObject *py_save_data;
  209. if (libobs_to_py(obs_data_t, save_data, false, &py_save_data)) {
  210. PyObject *args = Py_BuildValue("(Op)", py_save_data, saving);
  211. struct python_obs_callback *last_cb = cur_python_cb;
  212. cur_python_cb = cb;
  213. cur_python_script = (struct obs_python_script *)cb->base.script;
  214. PyObject *py_ret = PyObject_CallObject(cb->func, args);
  215. Py_XDECREF(py_ret);
  216. py_error();
  217. cur_python_script = NULL;
  218. cur_python_cb = last_cb;
  219. Py_XDECREF(args);
  220. Py_XDECREF(py_save_data);
  221. }
  222. unlock_python();
  223. }
  224. static PyObject *remove_save_callback(PyObject *self, PyObject *args)
  225. {
  226. struct obs_python_script *script = cur_python_script;
  227. PyObject *py_cb = NULL;
  228. UNUSED_PARAMETER(self);
  229. if (!parse_args(args, "O", &py_cb))
  230. return python_none();
  231. if (!py_cb || !PyFunction_Check(py_cb))
  232. return python_none();
  233. struct python_obs_callback *cb = find_python_obs_callback(script, py_cb);
  234. if (cb) remove_python_obs_callback(cb);
  235. return python_none();
  236. }
  237. static void add_save_callback_defer(void *cb)
  238. {
  239. obs_frontend_add_save_callback(frontend_save_callback, cb);
  240. }
  241. static PyObject *add_save_callback(PyObject *self, PyObject *args)
  242. {
  243. struct obs_python_script *script = cur_python_script;
  244. PyObject *py_cb = NULL;
  245. UNUSED_PARAMETER(self);
  246. if (!parse_args(args, "O", &py_cb))
  247. return python_none();
  248. if (!py_cb || !PyFunction_Check(py_cb))
  249. return python_none();
  250. struct python_obs_callback *cb = add_python_obs_callback(script, py_cb);
  251. defer_call_post(add_save_callback_defer, cb);
  252. return python_none();
  253. }
  254. /* ----------------------------------- */
  255. void add_python_frontend_funcs(PyObject *module)
  256. {
  257. static PyMethodDef funcs[] = {
  258. #define DEF_FUNC(c) {"obs_frontend_" #c, c, METH_VARARGS, NULL}
  259. DEF_FUNC(get_scene_names),
  260. DEF_FUNC(get_scenes),
  261. DEF_FUNC(get_current_scene),
  262. DEF_FUNC(set_current_scene),
  263. DEF_FUNC(get_transitions),
  264. DEF_FUNC(get_current_transition),
  265. DEF_FUNC(set_current_transition),
  266. DEF_FUNC(get_scene_collections),
  267. DEF_FUNC(get_current_scene_collection),
  268. DEF_FUNC(set_current_scene_collection),
  269. DEF_FUNC(get_profiles),
  270. DEF_FUNC(get_current_profile),
  271. DEF_FUNC(set_current_profile),
  272. DEF_FUNC(remove_save_callback),
  273. DEF_FUNC(add_save_callback),
  274. #undef DEF_FUNC
  275. {0}
  276. };
  277. add_functions_to_py_module(module, funcs);
  278. }