obs-data.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  1. /******************************************************************************
  2. Copyright (C) 2014 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 "util/bmem.h"
  15. #include "util/threading.h"
  16. #include "util/darray.h"
  17. #include "graphics/vec2.h"
  18. #include "graphics/vec3.h"
  19. #include "graphics/vec4.h"
  20. #include "graphics/quat.h"
  21. #include "obs-data.h"
  22. #include <jansson.h>
  23. struct obs_data_item {
  24. volatile long ref;
  25. struct obs_data *parent;
  26. struct obs_data_item *next;
  27. enum obs_data_type type;
  28. size_t name_len;
  29. size_t data_len;
  30. size_t capacity;
  31. };
  32. struct obs_data {
  33. volatile long ref;
  34. char *json;
  35. struct obs_data_item *first_item;
  36. };
  37. struct obs_data_array {
  38. volatile long ref;
  39. DARRAY(obs_data_t) objects;
  40. };
  41. struct obs_data_number {
  42. enum obs_data_number_type type;
  43. union {
  44. long long int_val;
  45. double double_val;
  46. };
  47. };
  48. /* ------------------------------------------------------------------------- */
  49. /* Item structure, designed to be one allocation only */
  50. /* ensures data after the name has alignment (in case of SSE) */
  51. static inline size_t get_name_align_size(const char *name)
  52. {
  53. size_t name_size = strlen(name) + 1;
  54. size_t alignment = base_get_alignment();
  55. size_t total_size;
  56. total_size = sizeof(struct obs_data_item) + (name_size + alignment-1);
  57. total_size &= ~(alignment-1);
  58. return total_size - sizeof(struct obs_data_item);
  59. }
  60. static inline char *get_item_name(struct obs_data_item *item)
  61. {
  62. return (char*)item + sizeof(struct obs_data_item);
  63. }
  64. static inline void *get_item_data(struct obs_data_item *item)
  65. {
  66. return (uint8_t*)get_item_name(item) + item->name_len;
  67. }
  68. static inline size_t obs_data_item_total_size(struct obs_data_item *item)
  69. {
  70. return sizeof(struct obs_data_item) + item->data_len + item->name_len;
  71. }
  72. static inline obs_data_t get_item_obj(struct obs_data_item *item)
  73. {
  74. if (!item)
  75. return NULL;
  76. return *(obs_data_t*)get_item_data(item);
  77. }
  78. static inline obs_data_array_t get_item_array(struct obs_data_item *item)
  79. {
  80. if (!item)
  81. return NULL;
  82. return *(obs_data_array_t*)get_item_data(item);
  83. }
  84. static inline void item_data_release(struct obs_data_item *item)
  85. {
  86. if (item->type == OBS_DATA_OBJECT) {
  87. obs_data_t obj = get_item_obj(item);
  88. obs_data_release(obj);
  89. } else if (item->type == OBS_DATA_ARRAY) {
  90. obs_data_array_t array = get_item_array(item);
  91. obs_data_array_release(array);
  92. }
  93. }
  94. static inline void item_data_addref(struct obs_data_item *item)
  95. {
  96. if (item->type == OBS_DATA_OBJECT) {
  97. obs_data_t obj = get_item_obj(item);
  98. obs_data_addref(obj);
  99. } else if (item->type == OBS_DATA_ARRAY) {
  100. obs_data_array_t array = get_item_array(item);
  101. obs_data_array_addref(array);
  102. }
  103. }
  104. static struct obs_data_item *obs_data_item_create(const char *name,
  105. const void *data, size_t size, enum obs_data_type type)
  106. {
  107. struct obs_data_item *item;
  108. size_t name_size, total_size;
  109. if (!name || !data)
  110. return NULL;
  111. name_size = get_name_align_size(name);
  112. total_size = name_size + sizeof(struct obs_data_item) + size;
  113. item = bzalloc(total_size);
  114. item->capacity = total_size;
  115. item->type = type;
  116. item->name_len = name_size;
  117. item->data_len = size;
  118. item->ref = 1;
  119. strcpy(get_item_name(item), name);
  120. memcpy(get_item_data(item), data, size);
  121. item_data_addref(item);
  122. return item;
  123. }
  124. static struct obs_data_item **get_item_prev_next(struct obs_data *data,
  125. struct obs_data_item *current)
  126. {
  127. if (!current || !data)
  128. return NULL;
  129. struct obs_data_item **prev_next = &data->first_item;
  130. struct obs_data_item *item = data->first_item;
  131. while (item) {
  132. if (item == current)
  133. return prev_next;
  134. prev_next = &item->next;
  135. item = item->next;
  136. }
  137. return NULL;
  138. }
  139. static inline void obs_data_item_detach(struct obs_data_item *item)
  140. {
  141. struct obs_data_item **prev_next = get_item_prev_next(item->parent,
  142. item);
  143. if (prev_next) {
  144. *prev_next = item->next;
  145. item->next = NULL;
  146. }
  147. }
  148. static inline void obs_data_item_reattach(struct obs_data_item *old_ptr,
  149. struct obs_data_item *new_ptr)
  150. {
  151. struct obs_data_item **prev_next = get_item_prev_next(new_ptr->parent,
  152. old_ptr);
  153. if (prev_next)
  154. *prev_next = new_ptr;
  155. }
  156. static struct obs_data_item *obs_data_item_ensure_capacity(
  157. struct obs_data_item *item)
  158. {
  159. size_t new_size = obs_data_item_total_size(item);
  160. struct obs_data_item *new_item;
  161. if (item->capacity >= new_size)
  162. return item;
  163. new_item = brealloc(item, new_size);
  164. new_item->capacity = new_size;
  165. obs_data_item_reattach(item, new_item);
  166. return new_item;
  167. }
  168. static inline void obs_data_item_destroy(struct obs_data_item *item)
  169. {
  170. item_data_release(item);
  171. obs_data_item_detach(item);
  172. bfree(item);
  173. }
  174. static inline void obs_data_item_setdata(
  175. struct obs_data_item **p_item, const void *data, size_t size,
  176. enum obs_data_type type)
  177. {
  178. if (!p_item || !*p_item)
  179. return;
  180. struct obs_data_item *item = *p_item;
  181. item_data_release(item);
  182. item->data_len = size;
  183. item->type = type;
  184. item = obs_data_item_ensure_capacity(item);
  185. if (size) {
  186. memcpy(get_item_data(item), data, size);
  187. item_data_addref(item);
  188. }
  189. *p_item = item;
  190. }
  191. /* ------------------------------------------------------------------------- */
  192. static void obs_data_add_json_item(obs_data_t data, const char *key,
  193. json_t *json);
  194. static inline void obs_data_add_json_object_data(obs_data_t data, json_t *jobj)
  195. {
  196. const char *item_key;
  197. json_t *jitem;
  198. json_object_foreach (jobj, item_key, jitem) {
  199. obs_data_add_json_item(data, item_key, jitem);
  200. }
  201. }
  202. static inline void obs_data_add_json_object(obs_data_t data, const char *key,
  203. json_t *jobj)
  204. {
  205. obs_data_t sub_obj = obs_data_create();
  206. obs_data_add_json_object_data(sub_obj, jobj);
  207. obs_data_setobj(data, key, sub_obj);
  208. obs_data_release(sub_obj);
  209. }
  210. static void obs_data_add_json_array(obs_data_t data, const char *key,
  211. json_t *jarray)
  212. {
  213. obs_data_array_t array = obs_data_array_create();
  214. size_t idx;
  215. json_t *jitem;
  216. json_array_foreach (jarray, idx, jitem) {
  217. obs_data_t item;
  218. if (!json_is_object(jitem))
  219. continue;
  220. item = obs_data_create();
  221. obs_data_add_json_object_data(item, jitem);
  222. obs_data_array_push_back(array, item);
  223. obs_data_release(item);
  224. }
  225. obs_data_setarray(data, key, array);
  226. obs_data_array_release(array);
  227. }
  228. static void obs_data_add_json_item(obs_data_t data, const char *key,
  229. json_t *json)
  230. {
  231. if (json_is_object(json))
  232. obs_data_add_json_object(data, key, json);
  233. else if (json_is_array(json))
  234. obs_data_add_json_array(data, key, json);
  235. else if (json_is_string(json))
  236. obs_data_setstring(data, key, json_string_value(json));
  237. else if (json_is_integer(json))
  238. obs_data_setint(data, key, json_integer_value(json));
  239. else if (json_is_real(json))
  240. obs_data_setdouble(data, key, json_real_value(json));
  241. else if (json_is_true(json))
  242. obs_data_setbool(data, key, true);
  243. else if (json_is_false(json))
  244. obs_data_setbool(data, key, false);
  245. }
  246. /* ------------------------------------------------------------------------- */
  247. static inline void set_json_string(json_t *json, const char *name,
  248. obs_data_item_t item)
  249. {
  250. const char *val = obs_data_item_getstring(item);
  251. json_object_set_new(json, name, json_string(val));
  252. }
  253. static inline void set_json_number(json_t *json, const char *name,
  254. obs_data_item_t item)
  255. {
  256. enum obs_data_number_type type = obs_data_item_numtype(item);
  257. if (type == OBS_DATA_NUM_INT) {
  258. long long val = obs_data_item_getint(item);
  259. json_object_set_new(json, name, json_integer(val));
  260. } else {
  261. double val = obs_data_item_getdouble(item);
  262. json_object_set_new(json, name, json_real(val));
  263. }
  264. }
  265. static inline void set_json_bool(json_t *json, const char *name,
  266. obs_data_item_t item)
  267. {
  268. bool val = obs_data_item_getbool(item);
  269. json_object_set_new(json, name, val ? json_true() : json_false());
  270. }
  271. static json_t *obs_data_to_json(obs_data_t data);
  272. static inline void set_json_obj(json_t *json, const char *name,
  273. obs_data_item_t item)
  274. {
  275. obs_data_t obj = obs_data_item_getobj(item);
  276. json_object_set_new(json, name, obs_data_to_json(obj));
  277. obs_data_release(obj);
  278. }
  279. static inline void set_json_array(json_t *json, const char *name,
  280. obs_data_item_t item)
  281. {
  282. json_t *jarray = json_array();
  283. obs_data_array_t array = obs_data_item_getarray(item);
  284. size_t count = obs_data_array_count(array);
  285. for (size_t idx = 0; idx < count; idx++) {
  286. obs_data_t sub_item = obs_data_array_item(array, idx);
  287. json_t *jitem = obs_data_to_json(sub_item);
  288. json_array_append_new(jarray, jitem);
  289. obs_data_release(sub_item);
  290. }
  291. json_object_set_new(json, name, jarray);
  292. obs_data_array_release(array);
  293. }
  294. static json_t *obs_data_to_json(obs_data_t data)
  295. {
  296. json_t *json = json_object();
  297. obs_data_item_t item = obs_data_first(data);
  298. while (item) {
  299. enum obs_data_type type = obs_data_item_gettype(item);
  300. const char *name = get_item_name(item);
  301. if (type == OBS_DATA_STRING)
  302. set_json_string(json, name, item);
  303. else if (type == OBS_DATA_NUMBER)
  304. set_json_number(json, name, item);
  305. else if (type == OBS_DATA_BOOLEAN)
  306. set_json_bool(json, name, item);
  307. else if (type == OBS_DATA_OBJECT)
  308. set_json_obj(json, name, item);
  309. else if (type == OBS_DATA_ARRAY)
  310. set_json_array(json, name, item);
  311. obs_data_item_next(&item);
  312. }
  313. return json;
  314. }
  315. /* ------------------------------------------------------------------------- */
  316. obs_data_t obs_data_create()
  317. {
  318. struct obs_data *data = bzalloc(sizeof(struct obs_data));
  319. data->ref = 1;
  320. return data;
  321. }
  322. obs_data_t obs_data_create_from_json(const char *json_string)
  323. {
  324. obs_data_t data = obs_data_create();
  325. json_error_t error;
  326. json_t *root = json_loads(json_string, JSON_REJECT_DUPLICATES, &error);
  327. if (root) {
  328. obs_data_add_json_object_data(data, root);
  329. json_decref(root);
  330. } else {
  331. blog(LOG_ERROR, "obs-data.c: [obs_data_create_from_json] "
  332. "Failed reading json string (%d): %s",
  333. error.line, error.text);
  334. }
  335. return data;
  336. }
  337. void obs_data_addref(obs_data_t data)
  338. {
  339. if (data)
  340. os_atomic_inc_long(&data->ref);
  341. }
  342. static inline void obs_data_destroy(struct obs_data *data)
  343. {
  344. struct obs_data_item *item = data->first_item;
  345. while (item) {
  346. struct obs_data_item *next = item->next;
  347. obs_data_item_release(&item);
  348. item = next;
  349. }
  350. /* NOTE: don't use bfree for json text, allocated by json */
  351. free(data->json);
  352. bfree(data);
  353. }
  354. void obs_data_release(obs_data_t data)
  355. {
  356. if (!data) return;
  357. if (os_atomic_dec_long(&data->ref) == 0)
  358. obs_data_destroy(data);
  359. }
  360. const char *obs_data_getjson(obs_data_t data)
  361. {
  362. if (!data) return NULL;
  363. /* NOTE: don't use libobs bfree for json text */
  364. free(data->json);
  365. data->json = NULL;
  366. json_t *root = obs_data_to_json(data);
  367. data->json = json_dumps(root, JSON_PRESERVE_ORDER | JSON_INDENT(4));
  368. json_decref(root);
  369. return data->json;
  370. }
  371. static struct obs_data_item *get_item(struct obs_data *data, const char *name)
  372. {
  373. if (!data) return NULL;
  374. struct obs_data_item *item = data->first_item;
  375. while (item) {
  376. if (strcmp(get_item_name(item), name) == 0)
  377. return item;
  378. item = item->next;
  379. }
  380. return NULL;
  381. }
  382. static void set_item_data(struct obs_data *data, struct obs_data_item *item,
  383. const char *name, const void *ptr, size_t size,
  384. enum obs_data_type type)
  385. {
  386. if (!item) {
  387. item = obs_data_item_create(name, ptr, size, type);
  388. item->next = data->first_item;
  389. item->parent = data;
  390. data->first_item = item;
  391. } else {
  392. obs_data_item_setdata(&item, ptr, size, type);
  393. }
  394. }
  395. static inline void set_item(struct obs_data *data, const char *name,
  396. const void *ptr, size_t size, enum obs_data_type type)
  397. {
  398. if (!data)
  399. return;
  400. struct obs_data_item *item = get_item(data, name);
  401. set_item_data(data, item, name, ptr, size, type);
  402. }
  403. static inline void set_item_def(struct obs_data *data, const char *name,
  404. const void *ptr, size_t size, enum obs_data_type type)
  405. {
  406. if (!data)
  407. return;
  408. struct obs_data_item *item = get_item(data, name);
  409. if (item && item->type == type)
  410. return;
  411. set_item_data(data, item, name, ptr, size, type);
  412. }
  413. static inline void copy_item(struct obs_data *data, struct obs_data_item *item)
  414. {
  415. const char *name = get_item_name(item);
  416. void *ptr = get_item_data(item);
  417. set_item(data, name, ptr, item->data_len, item->type);
  418. }
  419. void obs_data_apply(obs_data_t target, obs_data_t apply_data)
  420. {
  421. struct obs_data_item *item;
  422. if (!target || !apply_data || target == apply_data)
  423. return;
  424. item = apply_data->first_item;
  425. while (item) {
  426. copy_item(target, item);
  427. item = item->next;
  428. }
  429. }
  430. void obs_data_erase(obs_data_t data, const char *name)
  431. {
  432. struct obs_data_item *item = get_item(data, name);
  433. if (item) {
  434. obs_data_item_detach(item);
  435. obs_data_item_release(&item);
  436. }
  437. }
  438. typedef void (*set_item_t)(obs_data_t, const char*, const void*, size_t,
  439. enum obs_data_type);
  440. static inline void data_set_string(obs_data_t data, const char *name,
  441. const char *val, set_item_t set_item_)
  442. {
  443. if (!val) val = "";
  444. set_item_(data, name, val, strlen(val)+1, OBS_DATA_STRING);
  445. }
  446. static inline void data_set_int(obs_data_t data, const char *name,
  447. long long val, set_item_t set_item_)
  448. {
  449. struct obs_data_number num;
  450. num.type = OBS_DATA_NUM_INT;
  451. num.int_val = val;
  452. set_item_(data, name, &num, sizeof(struct obs_data_number),
  453. OBS_DATA_NUMBER);
  454. }
  455. static inline void data_set_double(obs_data_t data, const char *name,
  456. double val, set_item_t set_item_)
  457. {
  458. struct obs_data_number num;
  459. num.type = OBS_DATA_NUM_DOUBLE;
  460. num.double_val = val;
  461. set_item_(data, name, &num, sizeof(struct obs_data_number),
  462. OBS_DATA_NUMBER);
  463. }
  464. static inline void data_set_bool(obs_data_t data, const char *name, bool val,
  465. set_item_t set_item_)
  466. {
  467. set_item_(data, name, &val, sizeof(bool), OBS_DATA_BOOLEAN);
  468. }
  469. static inline void data_set_obj(obs_data_t data, const char *name,
  470. obs_data_t obj, set_item_t set_item_)
  471. {
  472. set_item_(data, name, &obj, sizeof(obs_data_t), OBS_DATA_OBJECT);
  473. }
  474. static inline void data_set_array(obs_data_t data, const char *name,
  475. obs_data_array_t array, set_item_t set_item_)
  476. {
  477. set_item_(data, name, &array, sizeof(obs_data_t), OBS_DATA_ARRAY);
  478. }
  479. void obs_data_setstring(obs_data_t data, const char *name, const char *val)
  480. {
  481. data_set_string(data, name, val, set_item);
  482. }
  483. void obs_data_setint(obs_data_t data, const char *name, long long val)
  484. {
  485. data_set_int(data, name, val, set_item);
  486. }
  487. void obs_data_setdouble(obs_data_t data, const char *name, double val)
  488. {
  489. data_set_double(data, name, val, set_item);
  490. }
  491. void obs_data_setbool(obs_data_t data, const char *name, bool val)
  492. {
  493. data_set_bool(data, name, val, set_item);
  494. }
  495. void obs_data_setobj(obs_data_t data, const char *name, obs_data_t obj)
  496. {
  497. data_set_obj(data, name, obj, set_item);
  498. }
  499. void obs_data_setarray(obs_data_t data, const char *name,
  500. obs_data_array_t array)
  501. {
  502. data_set_array(data, name, array, set_item);
  503. }
  504. void obs_data_set_default_string(obs_data_t data, const char *name,
  505. const char *val)
  506. {
  507. data_set_string(data, name, val, set_item_def);
  508. }
  509. void obs_data_set_default_int(obs_data_t data, const char *name, long long val)
  510. {
  511. data_set_int(data, name, val, set_item_def);
  512. }
  513. void obs_data_set_default_double(obs_data_t data, const char *name, double val)
  514. {
  515. data_set_double(data, name, val, set_item_def);
  516. }
  517. void obs_data_set_default_bool(obs_data_t data, const char *name, bool val)
  518. {
  519. data_set_bool(data, name, val, set_item_def);
  520. }
  521. void obs_data_set_default_obj(obs_data_t data, const char *name, obs_data_t obj)
  522. {
  523. data_set_obj(data, name, obj, set_item_def);
  524. }
  525. const char *obs_data_getstring(obs_data_t data, const char *name)
  526. {
  527. return obs_data_item_getstring(get_item(data, name));
  528. }
  529. long long obs_data_getint(obs_data_t data, const char *name)
  530. {
  531. return obs_data_item_getint(get_item(data, name));
  532. }
  533. double obs_data_getdouble(obs_data_t data, const char *name)
  534. {
  535. return obs_data_item_getdouble(get_item(data, name));
  536. }
  537. bool obs_data_getbool(obs_data_t data, const char *name)
  538. {
  539. return obs_data_item_getbool(get_item(data, name));
  540. }
  541. obs_data_t obs_data_getobj(obs_data_t data, const char *name)
  542. {
  543. return obs_data_item_getobj(get_item(data, name));
  544. }
  545. obs_data_array_t obs_data_getarray(obs_data_t data, const char *name)
  546. {
  547. return obs_data_item_getarray(get_item(data, name));
  548. }
  549. obs_data_array_t obs_data_array_create()
  550. {
  551. struct obs_data_array *array = bzalloc(sizeof(struct obs_data_array));
  552. array->ref = 1;
  553. return array;
  554. }
  555. void obs_data_array_addref(obs_data_array_t array)
  556. {
  557. if (array)
  558. os_atomic_inc_long(&array->ref);
  559. }
  560. static inline void obs_data_array_destroy(obs_data_array_t array)
  561. {
  562. if (array) {
  563. for (size_t i = 0; i < array->objects.num; i++)
  564. obs_data_release(array->objects.array[i]);
  565. da_free(array->objects);
  566. bfree(array);
  567. }
  568. }
  569. void obs_data_array_release(obs_data_array_t array)
  570. {
  571. if (!array)
  572. return;
  573. if (os_atomic_dec_long(&array->ref) == 0)
  574. obs_data_array_destroy(array);
  575. }
  576. size_t obs_data_array_count(obs_data_array_t array)
  577. {
  578. return array ? array->objects.num : 0;
  579. }
  580. obs_data_t obs_data_array_item(obs_data_array_t array, size_t idx)
  581. {
  582. obs_data_t data;
  583. if (!array)
  584. return NULL;
  585. data = (idx < array->objects.num) ? array->objects.array[idx] : NULL;
  586. if (data)
  587. os_atomic_inc_long(&data->ref);
  588. return data;
  589. }
  590. size_t obs_data_array_push_back(obs_data_array_t array, obs_data_t obj)
  591. {
  592. if (!array || !obj)
  593. return 0;
  594. os_atomic_inc_long(&obj->ref);
  595. return da_push_back(array->objects, &obj);
  596. }
  597. void obs_data_array_insert(obs_data_array_t array, size_t idx, obs_data_t obj)
  598. {
  599. if (!array || !obj)
  600. return;
  601. os_atomic_inc_long(&obj->ref);
  602. da_insert(array->objects, idx, &obj);
  603. }
  604. void obs_data_array_erase(obs_data_array_t array, size_t idx)
  605. {
  606. if (array) {
  607. obs_data_release(array->objects.array[idx]);
  608. da_erase(array->objects, idx);
  609. }
  610. }
  611. /* ------------------------------------------------------------------------- */
  612. /* Item iteration */
  613. obs_data_item_t obs_data_first(obs_data_t data)
  614. {
  615. if (!data)
  616. return NULL;
  617. if (data->first_item)
  618. os_atomic_inc_long(&data->first_item->ref);
  619. return data->first_item;
  620. }
  621. obs_data_item_t obs_data_item_byname(obs_data_t data, const char *name)
  622. {
  623. if (!data)
  624. return NULL;
  625. struct obs_data_item *item = get_item(data, name);
  626. if (item)
  627. os_atomic_inc_long(&item->ref);
  628. return item;
  629. }
  630. bool obs_data_item_next(obs_data_item_t *item)
  631. {
  632. if (item && *item) {
  633. obs_data_item_t next = (*item)->next;
  634. obs_data_item_release(item);
  635. *item = next;
  636. if (next) {
  637. os_atomic_inc_long(&next->ref);
  638. return true;
  639. }
  640. }
  641. return false;
  642. }
  643. void obs_data_item_release(obs_data_item_t *item)
  644. {
  645. if (item && *item) {
  646. long ref = os_atomic_dec_long(&(*item)->ref);
  647. if (!ref) {
  648. obs_data_item_destroy(*item);
  649. *item = NULL;
  650. }
  651. }
  652. }
  653. void obs_data_item_remove(obs_data_item_t *item)
  654. {
  655. if (item && *item) {
  656. obs_data_item_detach(*item);
  657. obs_data_item_release(item);
  658. }
  659. }
  660. enum obs_data_type obs_data_item_gettype(obs_data_item_t item)
  661. {
  662. return item ? item->type : OBS_DATA_NULL;
  663. }
  664. enum obs_data_number_type obs_data_item_numtype(obs_data_item_t item)
  665. {
  666. struct obs_data_number *num;
  667. if (!item || item->type != OBS_DATA_NUMBER)
  668. return OBS_DATA_NUM_INVALID;
  669. num = get_item_data(item);
  670. return num->type;
  671. }
  672. void obs_data_item_setstring(obs_data_item_t *item, const char *val)
  673. {
  674. if (!val) val = "";
  675. obs_data_item_setdata(item, val, strlen(val)+1, OBS_DATA_STRING);
  676. }
  677. void obs_data_item_setint(obs_data_item_t *item, long long val)
  678. {
  679. struct obs_data_number num;
  680. num.type = OBS_DATA_NUM_INT;
  681. num.int_val = val;
  682. obs_data_item_setdata(item, &num, sizeof(struct obs_data_number),
  683. OBS_DATA_NUMBER);
  684. }
  685. void obs_data_item_setdouble(obs_data_item_t *item, double val)
  686. {
  687. struct obs_data_number num;
  688. num.type = OBS_DATA_NUM_DOUBLE;
  689. num.double_val = val;
  690. obs_data_item_setdata(item, &num, sizeof(struct obs_data_number),
  691. OBS_DATA_NUMBER);
  692. }
  693. void obs_data_item_setbool(obs_data_item_t *item, bool val)
  694. {
  695. obs_data_item_setdata(item, &val, sizeof(bool), OBS_DATA_BOOLEAN);
  696. }
  697. void obs_data_item_setobj(obs_data_item_t *item, obs_data_t val)
  698. {
  699. obs_data_item_setdata(item, &val, sizeof(obs_data_t), OBS_DATA_OBJECT);
  700. }
  701. void obs_data_item_setarray(obs_data_item_t *item, obs_data_array_t val)
  702. {
  703. obs_data_item_setdata(item, &val, sizeof(obs_data_array_t),
  704. OBS_DATA_ARRAY);
  705. }
  706. static inline bool item_valid(struct obs_data_item *item,
  707. enum obs_data_type type)
  708. {
  709. return item && item->type == type;
  710. }
  711. const char *obs_data_item_getstring(obs_data_item_t item)
  712. {
  713. return item_valid(item, OBS_DATA_STRING) ? get_item_data(item) : "";
  714. }
  715. static inline long long item_int(struct obs_data_item *item)
  716. {
  717. if (item) {
  718. struct obs_data_number *num = get_item_data(item);
  719. return (num->type == OBS_DATA_NUM_INT) ?
  720. num->int_val : (long long)num->double_val;
  721. }
  722. return 0;
  723. }
  724. long long obs_data_item_getint(obs_data_item_t item)
  725. {
  726. return item_valid(item, OBS_DATA_NUMBER) ?
  727. item_int(item) : 0;
  728. }
  729. static inline double item_double(struct obs_data_item *item)
  730. {
  731. if (item) {
  732. struct obs_data_number *num = get_item_data(item);
  733. return (num->type == OBS_DATA_NUM_INT) ?
  734. (double)num->int_val : num->double_val;
  735. }
  736. return 0.0;
  737. }
  738. double obs_data_item_getdouble(obs_data_item_t item)
  739. {
  740. return item_valid(item, OBS_DATA_NUMBER) ?
  741. item_double(item) : 0.0;
  742. }
  743. bool obs_data_item_getbool(obs_data_item_t item)
  744. {
  745. return item_valid(item, OBS_DATA_BOOLEAN) ?
  746. *(bool*)get_item_data(item) : false;
  747. }
  748. obs_data_t obs_data_item_getobj(obs_data_item_t item)
  749. {
  750. obs_data_t obj = item_valid(item, OBS_DATA_OBJECT) ?
  751. get_item_obj(item) : NULL;
  752. if (obj)
  753. os_atomic_inc_long(&obj->ref);
  754. return obj;
  755. }
  756. obs_data_array_t obs_data_item_getarray(obs_data_item_t item)
  757. {
  758. obs_data_array_t array = item_valid(item, OBS_DATA_ARRAY) ?
  759. get_item_array(item) : NULL;
  760. if (array)
  761. os_atomic_inc_long(&array->ref);
  762. return array;
  763. }
  764. /* ------------------------------------------------------------------------- */
  765. /* Helper functions for certain structures */
  766. typedef void (*set_obj_t)(obs_data_t, const char*, obs_data_t);
  767. static inline void set_vec2(obs_data_t data, const char *name,
  768. const struct vec2 *val, set_obj_t set_obj)
  769. {
  770. obs_data_t obj = obs_data_create();
  771. obs_data_setdouble(obj, "x", val->x);
  772. obs_data_setdouble(obj, "y", val->y);
  773. set_obj(data, name, obj);
  774. obs_data_release(obj);
  775. }
  776. static inline void set_vec3(obs_data_t data, const char *name,
  777. const struct vec3 *val, set_obj_t set_obj)
  778. {
  779. obs_data_t obj = obs_data_create();
  780. obs_data_setdouble(obj, "x", val->x);
  781. obs_data_setdouble(obj, "y", val->y);
  782. obs_data_setdouble(obj, "z", val->z);
  783. set_obj(data, name, obj);
  784. obs_data_release(obj);
  785. }
  786. static inline void set_vec4(obs_data_t data, const char *name,
  787. const struct vec4 *val, set_obj_t set_obj)
  788. {
  789. obs_data_t obj = obs_data_create();
  790. obs_data_setdouble(obj, "x", val->x);
  791. obs_data_setdouble(obj, "y", val->y);
  792. obs_data_setdouble(obj, "z", val->z);
  793. obs_data_setdouble(obj, "w", val->w);
  794. set_obj(data, name, obj);
  795. obs_data_release(obj);
  796. }
  797. static inline void set_quat(obs_data_t data, const char *name,
  798. const struct quat *val, set_obj_t set_obj)
  799. {
  800. obs_data_t obj = obs_data_create();
  801. obs_data_setdouble(obj, "x", val->x);
  802. obs_data_setdouble(obj, "y", val->y);
  803. obs_data_setdouble(obj, "z", val->z);
  804. obs_data_setdouble(obj, "w", val->w);
  805. set_obj(data, name, obj);
  806. obs_data_release(obj);
  807. }
  808. void obs_data_set_vec2(obs_data_t data, const char *name,
  809. const struct vec2 *val)
  810. {
  811. set_vec2(data, name, val, obs_data_setobj);
  812. }
  813. void obs_data_set_vec3(obs_data_t data, const char *name,
  814. const struct vec3 *val)
  815. {
  816. set_vec3(data, name, val, obs_data_setobj);
  817. }
  818. void obs_data_set_vec4(obs_data_t data, const char *name,
  819. const struct vec4 *val)
  820. {
  821. set_vec4(data, name, val, obs_data_setobj);
  822. }
  823. void obs_data_set_quat(obs_data_t data, const char *name,
  824. const struct quat *val)
  825. {
  826. set_quat(data, name, val, obs_data_setobj);
  827. }
  828. void obs_data_set_default_vec2(obs_data_t data, const char *name,
  829. const struct vec2 *val)
  830. {
  831. set_vec2(data, name, val, obs_data_set_default_obj);
  832. }
  833. void obs_data_set_default_vec3(obs_data_t data, const char *name,
  834. const struct vec3 *val)
  835. {
  836. set_vec3(data, name, val, obs_data_set_default_obj);
  837. }
  838. void obs_data_set_default_vec4(obs_data_t data, const char *name,
  839. const struct vec4 *val)
  840. {
  841. set_vec4(data, name, val, obs_data_set_default_obj);
  842. }
  843. void obs_data_set_default_quat(obs_data_t data, const char *name,
  844. const struct quat *val)
  845. {
  846. set_quat(data, name, val, obs_data_set_default_obj);
  847. }
  848. void obs_data_get_vec2(obs_data_t data, const char *name, struct vec2 *val)
  849. {
  850. obs_data_t obj = obs_data_getobj(data, name);
  851. if (!obj) return;
  852. val->x = (float)obs_data_getdouble(obj, "x");
  853. val->y = (float)obs_data_getdouble(obj, "y");
  854. obs_data_release(obj);
  855. }
  856. void obs_data_get_vec3(obs_data_t data, const char *name, struct vec3 *val)
  857. {
  858. obs_data_t obj = obs_data_getobj(data, name);
  859. if (!obj) return;
  860. val->x = (float)obs_data_getdouble(obj, "x");
  861. val->y = (float)obs_data_getdouble(obj, "y");
  862. val->z = (float)obs_data_getdouble(obj, "z");
  863. obs_data_release(obj);
  864. }
  865. void obs_data_get_vec4(obs_data_t data, const char *name, struct vec4 *val)
  866. {
  867. obs_data_t obj = obs_data_getobj(data, name);
  868. if (!obj) return;
  869. val->x = (float)obs_data_getdouble(obj, "x");
  870. val->y = (float)obs_data_getdouble(obj, "y");
  871. val->z = (float)obs_data_getdouble(obj, "z");
  872. val->w = (float)obs_data_getdouble(obj, "w");
  873. obs_data_release(obj);
  874. }
  875. void obs_data_get_quat(obs_data_t data, const char *name, struct quat *val)
  876. {
  877. obs_data_t obj = obs_data_getobj(data, name);
  878. if (!obj) return;
  879. val->x = (float)obs_data_getdouble(obj, "x");
  880. val->y = (float)obs_data_getdouble(obj, "y");
  881. val->z = (float)obs_data_getdouble(obj, "z");
  882. val->w = (float)obs_data_getdouble(obj, "w");
  883. obs_data_release(obj);
  884. }