obs-data.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  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 data_size;
  31. size_t default_size;
  32. size_t capacity;
  33. };
  34. struct obs_data {
  35. volatile long ref;
  36. char *json;
  37. struct obs_data_item *first_item;
  38. };
  39. struct obs_data_array {
  40. volatile long ref;
  41. DARRAY(obs_data_t) objects;
  42. };
  43. struct obs_data_number {
  44. enum obs_data_number_type type;
  45. union {
  46. long long int_val;
  47. double double_val;
  48. };
  49. };
  50. /* ------------------------------------------------------------------------- */
  51. /* Item structure, designed to be one allocation only */
  52. static inline size_t get_align_size(size_t size)
  53. {
  54. const size_t alignment = base_get_alignment();
  55. return (size + alignment - 1) & ~(alignment - 1);
  56. }
  57. /* ensures data after the name has alignment (in case of SSE) */
  58. static inline size_t get_name_align_size(const char *name)
  59. {
  60. size_t name_size = strlen(name) + 1;
  61. size_t alignment = base_get_alignment();
  62. size_t total_size;
  63. total_size = sizeof(struct obs_data_item) + (name_size + alignment-1);
  64. total_size &= ~(alignment-1);
  65. return total_size - sizeof(struct obs_data_item);
  66. }
  67. static inline char *get_item_name(struct obs_data_item *item)
  68. {
  69. return (char*)item + sizeof(struct obs_data_item);
  70. }
  71. static inline void *get_data_ptr(obs_data_item_t item)
  72. {
  73. return (uint8_t*)get_item_name(item) + item->name_len;
  74. }
  75. static inline void *get_item_data(struct obs_data_item *item)
  76. {
  77. if (!item->data_size && !item->default_size)
  78. return NULL;
  79. return get_data_ptr(item);
  80. }
  81. static inline void *get_default_data_ptr(obs_data_item_t item)
  82. {
  83. return (uint8_t*)get_data_ptr(item) + item->data_len;
  84. }
  85. static inline void *get_item_default_data(struct obs_data_item *item)
  86. {
  87. return item->default_size ? get_default_data_ptr(item) : NULL;
  88. }
  89. static inline size_t obs_data_item_total_size(struct obs_data_item *item)
  90. {
  91. return sizeof(struct obs_data_item) + item->name_len +
  92. item->data_len + item->default_size;
  93. }
  94. static inline obs_data_t get_item_obj(struct obs_data_item *item)
  95. {
  96. if (!item)
  97. return NULL;
  98. return *(obs_data_t*)get_item_data(item);
  99. }
  100. static inline obs_data_t get_item_default_obj(struct obs_data_item *item)
  101. {
  102. if (!item || !item->default_size)
  103. return NULL;
  104. return *(obs_data_t*)get_item_data(item);
  105. }
  106. static inline obs_data_array_t get_item_array(struct obs_data_item *item)
  107. {
  108. if (!item)
  109. return NULL;
  110. return *(obs_data_array_t*)get_item_data(item);
  111. }
  112. static inline obs_data_array_t get_item_default_array(
  113. struct obs_data_item *item)
  114. {
  115. if (!item || !item->default_size)
  116. return NULL;
  117. return *(obs_data_array_t*)get_item_data(item);
  118. }
  119. static inline void item_data_release(struct obs_data_item *item)
  120. {
  121. if (!obs_data_item_has_user_value(item))
  122. return;
  123. if (item->type == OBS_DATA_OBJECT) {
  124. obs_data_t obj = get_item_obj(item);
  125. obs_data_release(obj);
  126. } else if (item->type == OBS_DATA_ARRAY) {
  127. obs_data_array_t array = get_item_array(item);
  128. obs_data_array_release(array);
  129. }
  130. }
  131. static inline void item_default_data_release(struct obs_data_item *item)
  132. {
  133. if (item->type == OBS_DATA_OBJECT) {
  134. obs_data_t obj = get_item_default_obj(item);
  135. obs_data_release(obj);
  136. } else if (item->type == OBS_DATA_ARRAY) {
  137. obs_data_array_t array = get_item_default_array(item);
  138. obs_data_array_release(array);
  139. }
  140. }
  141. static inline void item_data_addref(struct obs_data_item *item)
  142. {
  143. if (item->type == OBS_DATA_OBJECT) {
  144. obs_data_t obj = get_item_obj(item);
  145. obs_data_addref(obj);
  146. } else if (item->type == OBS_DATA_ARRAY) {
  147. obs_data_array_t array = get_item_array(item);
  148. obs_data_array_addref(array);
  149. }
  150. }
  151. static inline void item_default_data_addref(struct obs_data_item *item)
  152. {
  153. if (!item->data_size)
  154. return;
  155. if (item->type == OBS_DATA_OBJECT) {
  156. obs_data_t obj = get_item_default_obj(item);
  157. obs_data_addref(obj);
  158. } else if (item->type == OBS_DATA_ARRAY) {
  159. obs_data_array_t array = get_item_default_array(item);
  160. obs_data_array_addref(array);
  161. }
  162. }
  163. static struct obs_data_item *obs_data_item_create(const char *name,
  164. const void *data, size_t size, enum obs_data_type type,
  165. bool default_data)
  166. {
  167. struct obs_data_item *item;
  168. size_t name_size, total_size;
  169. if (!name || !data)
  170. return NULL;
  171. name_size = get_name_align_size(name);
  172. total_size = name_size + sizeof(struct obs_data_item) + size;
  173. item = bzalloc(total_size);
  174. item->capacity = total_size;
  175. item->type = type;
  176. item->name_len = name_size;
  177. item->ref = 1;
  178. if (default_data) {
  179. item->default_size = size;
  180. } else {
  181. item->data_len = size;
  182. item->data_size = size;
  183. }
  184. strcpy(get_item_name(item), name);
  185. memcpy(get_item_data(item), data, size);
  186. item_data_addref(item);
  187. return item;
  188. }
  189. static struct obs_data_item **get_item_prev_next(struct obs_data *data,
  190. struct obs_data_item *current)
  191. {
  192. if (!current || !data)
  193. return NULL;
  194. struct obs_data_item **prev_next = &data->first_item;
  195. struct obs_data_item *item = data->first_item;
  196. while (item) {
  197. if (item == current)
  198. return prev_next;
  199. prev_next = &item->next;
  200. item = item->next;
  201. }
  202. return NULL;
  203. }
  204. static inline void obs_data_item_detach(struct obs_data_item *item)
  205. {
  206. struct obs_data_item **prev_next = get_item_prev_next(item->parent,
  207. item);
  208. if (prev_next) {
  209. *prev_next = item->next;
  210. item->next = NULL;
  211. }
  212. }
  213. static inline void obs_data_item_reattach(struct obs_data_item *old_ptr,
  214. struct obs_data_item *new_ptr)
  215. {
  216. struct obs_data_item **prev_next = get_item_prev_next(new_ptr->parent,
  217. old_ptr);
  218. if (prev_next)
  219. *prev_next = new_ptr;
  220. }
  221. static struct obs_data_item *obs_data_item_ensure_capacity(
  222. struct obs_data_item *item)
  223. {
  224. size_t new_size = obs_data_item_total_size(item);
  225. struct obs_data_item *new_item;
  226. if (item->capacity >= new_size)
  227. return item;
  228. new_item = brealloc(item, new_size);
  229. new_item->capacity = new_size;
  230. obs_data_item_reattach(item, new_item);
  231. return new_item;
  232. }
  233. static inline void obs_data_item_destroy(struct obs_data_item *item)
  234. {
  235. item_data_release(item);
  236. item_default_data_release(item);
  237. obs_data_item_detach(item);
  238. bfree(item);
  239. }
  240. static inline void move_data(obs_data_item_t old_item, void *old_data,
  241. obs_data_item_t item, void *data, size_t len)
  242. {
  243. ptrdiff_t old_offset = (uint8_t*)old_data - (uint8_t*)old_item;
  244. ptrdiff_t new_offset = (uint8_t*)data - (uint8_t*)item;
  245. if (!old_data)
  246. return;
  247. memmove((uint8_t*)item + new_offset, (uint8_t*)item + old_offset, len);
  248. }
  249. static inline void obs_data_item_setdata(
  250. struct obs_data_item **p_item, const void *data, size_t size,
  251. enum obs_data_type type)
  252. {
  253. if (!p_item || !*p_item)
  254. return;
  255. struct obs_data_item *item = *p_item;
  256. void *old_non_user_data = get_default_data_ptr(item);
  257. item_data_release(item);
  258. item->data_size = size;
  259. item->type = type;
  260. item->data_len = item->default_size ?
  261. get_align_size(size) : size;
  262. item = obs_data_item_ensure_capacity(item);
  263. if (item->default_size)
  264. move_data(*p_item, old_non_user_data, item,
  265. get_default_data_ptr(item),
  266. item->default_len + item->autoselect_size);
  267. if (size) {
  268. memcpy(get_item_data(item), data, size);
  269. item_data_addref(item);
  270. }
  271. *p_item = item;
  272. }
  273. static inline void obs_data_item_set_default_data(
  274. struct obs_data_item **p_item, const void *data, size_t size,
  275. enum obs_data_type type)
  276. {
  277. if (!p_item || !*p_item)
  278. return;
  279. struct obs_data_item *item = *p_item;
  280. item_default_data_release(item);
  281. item->type = type;
  282. item->default_size = size;
  283. item->data_len = item->data_size ?
  284. get_align_size(item->data_size) : 0;
  285. item = obs_data_item_ensure_capacity(item);
  286. if (size) {
  287. memcpy(get_item_default_data(item), data, size);
  288. item_default_data_addref(item);
  289. }
  290. *p_item = item;
  291. }
  292. /* ------------------------------------------------------------------------- */
  293. static void obs_data_add_json_item(obs_data_t data, const char *key,
  294. json_t *json);
  295. static inline void obs_data_add_json_object_data(obs_data_t data, json_t *jobj)
  296. {
  297. const char *item_key;
  298. json_t *jitem;
  299. json_object_foreach (jobj, item_key, jitem) {
  300. obs_data_add_json_item(data, item_key, jitem);
  301. }
  302. }
  303. static inline void obs_data_add_json_object(obs_data_t data, const char *key,
  304. json_t *jobj)
  305. {
  306. obs_data_t sub_obj = obs_data_create();
  307. obs_data_add_json_object_data(sub_obj, jobj);
  308. obs_data_setobj(data, key, sub_obj);
  309. obs_data_release(sub_obj);
  310. }
  311. static void obs_data_add_json_array(obs_data_t data, const char *key,
  312. json_t *jarray)
  313. {
  314. obs_data_array_t array = obs_data_array_create();
  315. size_t idx;
  316. json_t *jitem;
  317. json_array_foreach (jarray, idx, jitem) {
  318. obs_data_t item;
  319. if (!json_is_object(jitem))
  320. continue;
  321. item = obs_data_create();
  322. obs_data_add_json_object_data(item, jitem);
  323. obs_data_array_push_back(array, item);
  324. obs_data_release(item);
  325. }
  326. obs_data_setarray(data, key, array);
  327. obs_data_array_release(array);
  328. }
  329. static void obs_data_add_json_item(obs_data_t data, const char *key,
  330. json_t *json)
  331. {
  332. if (json_is_object(json))
  333. obs_data_add_json_object(data, key, json);
  334. else if (json_is_array(json))
  335. obs_data_add_json_array(data, key, json);
  336. else if (json_is_string(json))
  337. obs_data_setstring(data, key, json_string_value(json));
  338. else if (json_is_integer(json))
  339. obs_data_setint(data, key, json_integer_value(json));
  340. else if (json_is_real(json))
  341. obs_data_setdouble(data, key, json_real_value(json));
  342. else if (json_is_true(json))
  343. obs_data_setbool(data, key, true);
  344. else if (json_is_false(json))
  345. obs_data_setbool(data, key, false);
  346. }
  347. /* ------------------------------------------------------------------------- */
  348. static inline void set_json_string(json_t *json, const char *name,
  349. obs_data_item_t item)
  350. {
  351. const char *val = obs_data_item_getstring(item);
  352. json_object_set_new(json, name, json_string(val));
  353. }
  354. static inline void set_json_number(json_t *json, const char *name,
  355. obs_data_item_t item)
  356. {
  357. enum obs_data_number_type type = obs_data_item_numtype(item);
  358. if (type == OBS_DATA_NUM_INT) {
  359. long long val = obs_data_item_getint(item);
  360. json_object_set_new(json, name, json_integer(val));
  361. } else {
  362. double val = obs_data_item_getdouble(item);
  363. json_object_set_new(json, name, json_real(val));
  364. }
  365. }
  366. static inline void set_json_bool(json_t *json, const char *name,
  367. obs_data_item_t item)
  368. {
  369. bool val = obs_data_item_getbool(item);
  370. json_object_set_new(json, name, val ? json_true() : json_false());
  371. }
  372. static json_t *obs_data_to_json(obs_data_t data);
  373. static inline void set_json_obj(json_t *json, const char *name,
  374. obs_data_item_t item)
  375. {
  376. obs_data_t obj = obs_data_item_getobj(item);
  377. json_object_set_new(json, name, obs_data_to_json(obj));
  378. obs_data_release(obj);
  379. }
  380. static inline void set_json_array(json_t *json, const char *name,
  381. obs_data_item_t item)
  382. {
  383. json_t *jarray = json_array();
  384. obs_data_array_t array = obs_data_item_getarray(item);
  385. size_t count = obs_data_array_count(array);
  386. for (size_t idx = 0; idx < count; idx++) {
  387. obs_data_t sub_item = obs_data_array_item(array, idx);
  388. json_t *jitem = obs_data_to_json(sub_item);
  389. json_array_append_new(jarray, jitem);
  390. obs_data_release(sub_item);
  391. }
  392. json_object_set_new(json, name, jarray);
  393. obs_data_array_release(array);
  394. }
  395. static json_t *obs_data_to_json(obs_data_t data)
  396. {
  397. json_t *json = json_object();
  398. obs_data_item_t item = NULL;
  399. for (item = obs_data_first(data); item; obs_data_item_next(&item)) {
  400. enum obs_data_type type = obs_data_item_gettype(item);
  401. const char *name = get_item_name(item);
  402. if (!obs_data_item_has_user_value(item))
  403. continue;
  404. if (type == OBS_DATA_STRING)
  405. set_json_string(json, name, item);
  406. else if (type == OBS_DATA_NUMBER)
  407. set_json_number(json, name, item);
  408. else if (type == OBS_DATA_BOOLEAN)
  409. set_json_bool(json, name, item);
  410. else if (type == OBS_DATA_OBJECT)
  411. set_json_obj(json, name, item);
  412. else if (type == OBS_DATA_ARRAY)
  413. set_json_array(json, name, item);
  414. }
  415. return json;
  416. }
  417. /* ------------------------------------------------------------------------- */
  418. obs_data_t obs_data_create()
  419. {
  420. struct obs_data *data = bzalloc(sizeof(struct obs_data));
  421. data->ref = 1;
  422. return data;
  423. }
  424. obs_data_t obs_data_create_from_json(const char *json_string)
  425. {
  426. obs_data_t data = obs_data_create();
  427. json_error_t error;
  428. json_t *root = json_loads(json_string, JSON_REJECT_DUPLICATES, &error);
  429. if (root) {
  430. obs_data_add_json_object_data(data, root);
  431. json_decref(root);
  432. } else {
  433. blog(LOG_ERROR, "obs-data.c: [obs_data_create_from_json] "
  434. "Failed reading json string (%d): %s",
  435. error.line, error.text);
  436. }
  437. return data;
  438. }
  439. void obs_data_addref(obs_data_t data)
  440. {
  441. if (data)
  442. os_atomic_inc_long(&data->ref);
  443. }
  444. static inline void obs_data_destroy(struct obs_data *data)
  445. {
  446. struct obs_data_item *item = data->first_item;
  447. while (item) {
  448. struct obs_data_item *next = item->next;
  449. obs_data_item_release(&item);
  450. item = next;
  451. }
  452. /* NOTE: don't use bfree for json text, allocated by json */
  453. free(data->json);
  454. bfree(data);
  455. }
  456. void obs_data_release(obs_data_t data)
  457. {
  458. if (!data) return;
  459. if (os_atomic_dec_long(&data->ref) == 0)
  460. obs_data_destroy(data);
  461. }
  462. const char *obs_data_getjson(obs_data_t data)
  463. {
  464. if (!data) return NULL;
  465. /* NOTE: don't use libobs bfree for json text */
  466. free(data->json);
  467. data->json = NULL;
  468. json_t *root = obs_data_to_json(data);
  469. data->json = json_dumps(root, JSON_PRESERVE_ORDER | JSON_INDENT(4));
  470. json_decref(root);
  471. return data->json;
  472. }
  473. static struct obs_data_item *get_item(struct obs_data *data, const char *name)
  474. {
  475. if (!data) return NULL;
  476. struct obs_data_item *item = data->first_item;
  477. while (item) {
  478. if (strcmp(get_item_name(item), name) == 0)
  479. return item;
  480. item = item->next;
  481. }
  482. return NULL;
  483. }
  484. static void set_item_data(struct obs_data *data, struct obs_data_item **item,
  485. const char *name, const void *ptr, size_t size,
  486. enum obs_data_type type,
  487. bool default_data)
  488. {
  489. obs_data_item_t new_item = NULL;
  490. if ((!item || (item && !*item)) && data) {
  491. new_item = obs_data_item_create(name, ptr, size, type,
  492. default_data);
  493. new_item->next = data->first_item;
  494. new_item->parent = data;
  495. data->first_item = new_item;
  496. } else if (default_data) {
  497. obs_data_item_set_default_data(item, ptr, size, type);
  498. } else {
  499. obs_data_item_setdata(item, ptr, size, type);
  500. }
  501. }
  502. static inline void set_item(struct obs_data *data, obs_data_item_t *item,
  503. const char *name,
  504. const void *ptr, size_t size, enum obs_data_type type)
  505. {
  506. obs_data_item_t actual_item = NULL;
  507. if (!data && !item)
  508. return;
  509. if (!item) {
  510. actual_item = get_item(data, name);
  511. item = &actual_item;
  512. }
  513. set_item_data(data, item, name, ptr, size, type, false);
  514. }
  515. static inline void set_item_def(struct obs_data *data, obs_data_item_t *item,
  516. const char *name,
  517. const void *ptr, size_t size, enum obs_data_type type)
  518. {
  519. obs_data_item_t actual_item = NULL;
  520. if (!data && !item)
  521. return;
  522. if (!item) {
  523. actual_item = get_item(data, name);
  524. item = &actual_item;
  525. }
  526. if (item && *item && (*item)->type == type)
  527. return;
  528. set_item_data(data, item, name, ptr, size, type, true);
  529. }
  530. static inline void copy_item(struct obs_data *data, struct obs_data_item *item)
  531. {
  532. const char *name = get_item_name(item);
  533. void *ptr = get_item_data(item);
  534. set_item(data, NULL, name, ptr, item->data_len, item->type);
  535. }
  536. void obs_data_apply(obs_data_t target, obs_data_t apply_data)
  537. {
  538. struct obs_data_item *item;
  539. if (!target || !apply_data || target == apply_data)
  540. return;
  541. item = apply_data->first_item;
  542. while (item) {
  543. copy_item(target, item);
  544. item = item->next;
  545. }
  546. }
  547. void obs_data_erase(obs_data_t data, const char *name)
  548. {
  549. struct obs_data_item *item = get_item(data, name);
  550. if (item) {
  551. obs_data_item_detach(item);
  552. obs_data_item_release(&item);
  553. }
  554. }
  555. typedef void (*set_item_t)(obs_data_t, obs_data_item_t*, const char*,
  556. const void*, size_t, enum obs_data_type);
  557. static inline void obs_set_string(obs_data_t data, obs_data_item_t *item,
  558. const char *name,
  559. const char *val, set_item_t set_item_)
  560. {
  561. if (!val) val = "";
  562. set_item_(data, item, name, val, strlen(val)+1, OBS_DATA_STRING);
  563. }
  564. static inline void obs_set_int(obs_data_t data, obs_data_item_t *item,
  565. const char *name,
  566. long long val, set_item_t set_item_)
  567. {
  568. struct obs_data_number num;
  569. num.type = OBS_DATA_NUM_INT;
  570. num.int_val = val;
  571. set_item_(data, item, name, &num, sizeof(struct obs_data_number),
  572. OBS_DATA_NUMBER);
  573. }
  574. static inline void obs_set_double(obs_data_t data, obs_data_item_t *item,
  575. const char *name,
  576. double val, set_item_t set_item_)
  577. {
  578. struct obs_data_number num;
  579. num.type = OBS_DATA_NUM_DOUBLE;
  580. num.double_val = val;
  581. set_item_(data, item, name, &num, sizeof(struct obs_data_number),
  582. OBS_DATA_NUMBER);
  583. }
  584. static inline void obs_set_bool(obs_data_t data, obs_data_item_t *item,
  585. const char *name,
  586. bool val, set_item_t set_item_)
  587. {
  588. set_item_(data, item, name, &val, sizeof(bool), OBS_DATA_BOOLEAN);
  589. }
  590. static inline void obs_set_obj(obs_data_t data, obs_data_item_t *item,
  591. const char *name,
  592. obs_data_t obj, set_item_t set_item_)
  593. {
  594. set_item_(data, item, name, &obj, sizeof(obs_data_t), OBS_DATA_OBJECT);
  595. }
  596. static inline void obs_set_array(obs_data_t data, obs_data_item_t *item,
  597. const char *name,
  598. obs_data_array_t array, set_item_t set_item_)
  599. {
  600. set_item_(data, item, name, &array, sizeof(obs_data_t), OBS_DATA_ARRAY);
  601. }
  602. void obs_data_setstring(obs_data_t data, const char *name, const char *val)
  603. {
  604. obs_set_string(data, NULL, name, val, set_item);
  605. }
  606. void obs_data_setint(obs_data_t data, const char *name, long long val)
  607. {
  608. obs_set_int(data, NULL, name, val, set_item);
  609. }
  610. void obs_data_setdouble(obs_data_t data, const char *name, double val)
  611. {
  612. obs_set_double(data, NULL, name, val, set_item);
  613. }
  614. void obs_data_setbool(obs_data_t data, const char *name, bool val)
  615. {
  616. obs_set_bool(data, NULL, name, val, set_item);
  617. }
  618. void obs_data_setobj(obs_data_t data, const char *name, obs_data_t obj)
  619. {
  620. obs_set_obj(data, NULL, name, obj, set_item);
  621. }
  622. void obs_data_setarray(obs_data_t data, const char *name,
  623. obs_data_array_t array)
  624. {
  625. obs_set_array(data, NULL, name, array, set_item);
  626. }
  627. void obs_data_set_default_string(obs_data_t data, const char *name,
  628. const char *val)
  629. {
  630. obs_set_string(data, NULL, name, val, set_item_def);
  631. }
  632. void obs_data_set_default_int(obs_data_t data, const char *name, long long val)
  633. {
  634. obs_set_int(data, NULL, name, val, set_item_def);
  635. }
  636. void obs_data_set_default_double(obs_data_t data, const char *name, double val)
  637. {
  638. obs_set_double(data, NULL, name, val, set_item_def);
  639. }
  640. void obs_data_set_default_bool(obs_data_t data, const char *name, bool val)
  641. {
  642. obs_set_bool(data, NULL, name, val, set_item_def);
  643. }
  644. void obs_data_set_default_obj(obs_data_t data, const char *name, obs_data_t obj)
  645. {
  646. obs_set_obj(data, NULL, name, obj, set_item_def);
  647. }
  648. const char *obs_data_getstring(obs_data_t data, const char *name)
  649. {
  650. return obs_data_item_getstring(get_item(data, name));
  651. }
  652. long long obs_data_getint(obs_data_t data, const char *name)
  653. {
  654. return obs_data_item_getint(get_item(data, name));
  655. }
  656. double obs_data_getdouble(obs_data_t data, const char *name)
  657. {
  658. return obs_data_item_getdouble(get_item(data, name));
  659. }
  660. bool obs_data_getbool(obs_data_t data, const char *name)
  661. {
  662. return obs_data_item_getbool(get_item(data, name));
  663. }
  664. obs_data_t obs_data_getobj(obs_data_t data, const char *name)
  665. {
  666. return obs_data_item_getobj(get_item(data, name));
  667. }
  668. obs_data_array_t obs_data_getarray(obs_data_t data, const char *name)
  669. {
  670. return obs_data_item_getarray(get_item(data, name));
  671. }
  672. const char *obs_data_get_default_string(obs_data_t data, const char *name)
  673. {
  674. return obs_data_item_get_default_string(get_item(data, name));
  675. }
  676. long long obs_data_get_default_int(obs_data_t data, const char *name)
  677. {
  678. return obs_data_item_get_default_int(get_item(data, name));
  679. }
  680. double obs_data_get_default_double(obs_data_t data, const char *name)
  681. {
  682. return obs_data_item_get_default_double(get_item(data, name));
  683. }
  684. bool obs_data_get_default_bool(obs_data_t data, const char *name)
  685. {
  686. return obs_data_item_get_default_bool(get_item(data, name));
  687. }
  688. obs_data_t obs_data_get_default_obj(obs_data_t data, const char *name)
  689. {
  690. return obs_data_item_get_default_obj(get_item(data, name));
  691. }
  692. obs_data_array_t obs_data_get_default_array(obs_data_t data, const char *name)
  693. {
  694. return obs_data_item_get_default_array(get_item(data, name));
  695. }
  696. obs_data_array_t obs_data_array_create()
  697. {
  698. struct obs_data_array *array = bzalloc(sizeof(struct obs_data_array));
  699. array->ref = 1;
  700. return array;
  701. }
  702. void obs_data_array_addref(obs_data_array_t array)
  703. {
  704. if (array)
  705. os_atomic_inc_long(&array->ref);
  706. }
  707. static inline void obs_data_array_destroy(obs_data_array_t array)
  708. {
  709. if (array) {
  710. for (size_t i = 0; i < array->objects.num; i++)
  711. obs_data_release(array->objects.array[i]);
  712. da_free(array->objects);
  713. bfree(array);
  714. }
  715. }
  716. void obs_data_array_release(obs_data_array_t array)
  717. {
  718. if (!array)
  719. return;
  720. if (os_atomic_dec_long(&array->ref) == 0)
  721. obs_data_array_destroy(array);
  722. }
  723. size_t obs_data_array_count(obs_data_array_t array)
  724. {
  725. return array ? array->objects.num : 0;
  726. }
  727. obs_data_t obs_data_array_item(obs_data_array_t array, size_t idx)
  728. {
  729. obs_data_t data;
  730. if (!array)
  731. return NULL;
  732. data = (idx < array->objects.num) ? array->objects.array[idx] : NULL;
  733. if (data)
  734. os_atomic_inc_long(&data->ref);
  735. return data;
  736. }
  737. size_t obs_data_array_push_back(obs_data_array_t array, obs_data_t obj)
  738. {
  739. if (!array || !obj)
  740. return 0;
  741. os_atomic_inc_long(&obj->ref);
  742. return da_push_back(array->objects, &obj);
  743. }
  744. void obs_data_array_insert(obs_data_array_t array, size_t idx, obs_data_t obj)
  745. {
  746. if (!array || !obj)
  747. return;
  748. os_atomic_inc_long(&obj->ref);
  749. da_insert(array->objects, idx, &obj);
  750. }
  751. void obs_data_array_erase(obs_data_array_t array, size_t idx)
  752. {
  753. if (array) {
  754. obs_data_release(array->objects.array[idx]);
  755. da_erase(array->objects, idx);
  756. }
  757. }
  758. /* ------------------------------------------------------------------------- */
  759. /* Item status inspection */
  760. bool obs_data_has_user_value(obs_data_t data, const char *name)
  761. {
  762. return data && obs_data_item_has_user_value(get_item(data, name));
  763. }
  764. bool obs_data_has_default(obs_data_t data, const char *name)
  765. {
  766. return data && obs_data_item_has_default(get_item(data, name));
  767. }
  768. bool obs_data_item_has_user_value(obs_data_item_t item)
  769. {
  770. return item && item->data_size;
  771. }
  772. bool obs_data_item_has_default(obs_data_item_t item)
  773. {
  774. return item && item->default_size;
  775. }
  776. /* ------------------------------------------------------------------------- */
  777. /* Clearing data values */
  778. void obs_data_unset_user_value(obs_data_t data, const char *name)
  779. {
  780. obs_data_item_unset_user_value(get_item(data, name));
  781. }
  782. void obs_data_unset_default_value(obs_data_t data, const char *name)
  783. {
  784. obs_data_item_unset_default_value(get_item(data, name));
  785. }
  786. void obs_data_item_unset_user_value(obs_data_item_t item)
  787. {
  788. if (!item || !item->data_size)
  789. return;
  790. void *old_non_user_data = get_default_data_ptr(item);
  791. item_data_release(item);
  792. item->data_size = 0;
  793. item->data_len = 0;
  794. if (item->default_size)
  795. move_data(item, old_non_user_data, item,
  796. get_default_data_ptr(item),
  797. item->default_len);
  798. }
  799. void obs_data_item_unset_default_value(obs_data_item_t item)
  800. {
  801. if (!item || !item->default_size)
  802. return;
  803. item_default_data_release(item);
  804. item->default_size = 0;
  805. }
  806. /* ------------------------------------------------------------------------- */
  807. /* Item iteration */
  808. obs_data_item_t obs_data_first(obs_data_t data)
  809. {
  810. if (!data)
  811. return NULL;
  812. if (data->first_item)
  813. os_atomic_inc_long(&data->first_item->ref);
  814. return data->first_item;
  815. }
  816. obs_data_item_t obs_data_item_byname(obs_data_t data, const char *name)
  817. {
  818. if (!data)
  819. return NULL;
  820. struct obs_data_item *item = get_item(data, name);
  821. if (item)
  822. os_atomic_inc_long(&item->ref);
  823. return item;
  824. }
  825. bool obs_data_item_next(obs_data_item_t *item)
  826. {
  827. if (item && *item) {
  828. obs_data_item_t next = (*item)->next;
  829. obs_data_item_release(item);
  830. *item = next;
  831. if (next) {
  832. os_atomic_inc_long(&next->ref);
  833. return true;
  834. }
  835. }
  836. return false;
  837. }
  838. void obs_data_item_release(obs_data_item_t *item)
  839. {
  840. if (item && *item) {
  841. long ref = os_atomic_dec_long(&(*item)->ref);
  842. if (!ref) {
  843. obs_data_item_destroy(*item);
  844. *item = NULL;
  845. }
  846. }
  847. }
  848. void obs_data_item_remove(obs_data_item_t *item)
  849. {
  850. if (item && *item) {
  851. obs_data_item_detach(*item);
  852. obs_data_item_release(item);
  853. }
  854. }
  855. enum obs_data_type obs_data_item_gettype(obs_data_item_t item)
  856. {
  857. return item ? item->type : OBS_DATA_NULL;
  858. }
  859. enum obs_data_number_type obs_data_item_numtype(obs_data_item_t item)
  860. {
  861. struct obs_data_number *num;
  862. if (!item || item->type != OBS_DATA_NUMBER)
  863. return OBS_DATA_NUM_INVALID;
  864. num = get_item_data(item);
  865. return num->type;
  866. }
  867. void obs_data_item_setstring(obs_data_item_t *item, const char *val)
  868. {
  869. obs_set_string(NULL, item, NULL, val, set_item);
  870. }
  871. void obs_data_item_setint(obs_data_item_t *item, long long val)
  872. {
  873. obs_set_int(NULL, item, NULL, val, set_item);
  874. }
  875. void obs_data_item_setdouble(obs_data_item_t *item, double val)
  876. {
  877. obs_set_double(NULL, item, NULL, val, set_item);
  878. }
  879. void obs_data_item_setbool(obs_data_item_t *item, bool val)
  880. {
  881. obs_set_bool(NULL, item, NULL, val, set_item);
  882. }
  883. void obs_data_item_setobj(obs_data_item_t *item, obs_data_t val)
  884. {
  885. obs_set_obj(NULL, item, NULL, val, set_item);
  886. }
  887. void obs_data_item_setarray(obs_data_item_t *item, obs_data_array_t val)
  888. {
  889. obs_set_array(NULL, item, NULL, val, set_item);
  890. }
  891. void obs_data_item_set_default_string(obs_data_item_t *item, const char *val)
  892. {
  893. obs_set_string(NULL, item, NULL, val, set_item_def);
  894. }
  895. void obs_data_item_set_default_int(obs_data_item_t *item, long long val)
  896. {
  897. obs_set_int(NULL, item, NULL, val, set_item_def);
  898. }
  899. void obs_data_item_set_default_double(obs_data_item_t *item, double val)
  900. {
  901. obs_set_double(NULL, item, NULL, val, set_item_def);
  902. }
  903. void obs_data_item_set_default_bool(obs_data_item_t *item, bool val)
  904. {
  905. obs_set_bool(NULL, item, NULL, val, set_item_def);
  906. }
  907. void obs_data_item_set_default_obj(obs_data_item_t *item, obs_data_t val)
  908. {
  909. obs_set_obj(NULL, item, NULL, val, set_item_def);
  910. }
  911. void obs_data_item_set_default_array(obs_data_item_t *item,
  912. obs_data_array_t val)
  913. {
  914. obs_set_array(NULL, item, NULL, val, set_item_def);
  915. }
  916. static inline bool item_valid(struct obs_data_item *item,
  917. enum obs_data_type type)
  918. {
  919. return item && item->type == type;
  920. }
  921. typedef void *(*get_data_t)(obs_data_item_t);
  922. static inline const char *data_item_get_string(obs_data_item_t item,
  923. get_data_t get_data)
  924. {
  925. return item_valid(item, OBS_DATA_STRING) && get_data(item) ?
  926. get_data(item) : "";
  927. }
  928. static inline long long item_int(struct obs_data_item *item,
  929. get_data_t get_data)
  930. {
  931. if (item && get_data(item)) {
  932. struct obs_data_number *num = get_data(item);
  933. return (num->type == OBS_DATA_NUM_INT) ?
  934. num->int_val : (long long)num->double_val;
  935. }
  936. return 0;
  937. }
  938. static inline long long data_item_get_int(obs_data_item_t item,
  939. get_data_t get_data)
  940. {
  941. return item_int(item_valid(item, OBS_DATA_NUMBER) ? item : NULL,
  942. get_data);
  943. }
  944. static inline double item_double(struct obs_data_item *item,
  945. get_data_t get_data)
  946. {
  947. if (item && get_data(item)) {
  948. struct obs_data_number *num = get_data(item);
  949. return (num->type == OBS_DATA_NUM_INT) ?
  950. (double)num->int_val : num->double_val;
  951. }
  952. return 0.0;
  953. }
  954. static inline double data_item_get_double(obs_data_item_t item,
  955. get_data_t get_data)
  956. {
  957. return item_double(item_valid(item, OBS_DATA_NUMBER) ? item : NULL,
  958. get_data);
  959. }
  960. static inline bool data_item_get_bool(obs_data_item_t item, get_data_t get_data)
  961. {
  962. return item_valid(item, OBS_DATA_BOOLEAN) && get_data(item) ?
  963. *(bool*)get_data(item) : false;
  964. }
  965. typedef obs_data_t (*get_obj_t)(obs_data_item_t);
  966. static inline obs_data_t data_item_get_obj(obs_data_item_t item,
  967. get_obj_t get_obj)
  968. {
  969. obs_data_t obj = item_valid(item, OBS_DATA_OBJECT) ?
  970. get_obj(item) : NULL;
  971. if (obj)
  972. os_atomic_inc_long(&obj->ref);
  973. return obj;
  974. }
  975. typedef obs_data_array_t (*get_array_t)(obs_data_item_t);
  976. static inline obs_data_array_t data_item_get_array(obs_data_item_t item,
  977. get_array_t get_array)
  978. {
  979. obs_data_array_t array = item_valid(item, OBS_DATA_ARRAY) ?
  980. get_array(item) : NULL;
  981. if (array)
  982. os_atomic_inc_long(&array->ref);
  983. return array;
  984. }
  985. const char *obs_data_item_getstring(obs_data_item_t item)
  986. {
  987. return data_item_get_string(item, get_item_data);
  988. }
  989. long long obs_data_item_getint(obs_data_item_t item)
  990. {
  991. return data_item_get_int(item, get_item_data);
  992. }
  993. double obs_data_item_getdouble(obs_data_item_t item)
  994. {
  995. return data_item_get_double(item, get_item_data);
  996. }
  997. bool obs_data_item_getbool(obs_data_item_t item)
  998. {
  999. return data_item_get_bool(item, get_item_data);
  1000. }
  1001. obs_data_t obs_data_item_getobj(obs_data_item_t item)
  1002. {
  1003. return data_item_get_obj(item, get_item_obj);
  1004. }
  1005. obs_data_array_t obs_data_item_getarray(obs_data_item_t item)
  1006. {
  1007. return data_item_get_array(item, get_item_array);
  1008. }
  1009. const char *obs_data_item_get_default_string(obs_data_item_t item)
  1010. {
  1011. return data_item_get_string(item, get_item_default_data);
  1012. }
  1013. long long obs_data_item_get_default_int(obs_data_item_t item)
  1014. {
  1015. return data_item_get_int(item, get_item_default_data);
  1016. }
  1017. double obs_data_item_get_default_double(obs_data_item_t item)
  1018. {
  1019. return data_item_get_double(item, get_item_default_data);
  1020. }
  1021. bool obs_data_item_get_default_bool(obs_data_item_t item)
  1022. {
  1023. return data_item_get_bool(item, get_item_default_data);
  1024. }
  1025. obs_data_t obs_data_item_get_default_obj(obs_data_item_t item)
  1026. {
  1027. return data_item_get_obj(item, get_item_obj);
  1028. }
  1029. obs_data_array_t obs_data_item_get_default_array(obs_data_item_t item)
  1030. {
  1031. return data_item_get_array(item, get_item_array);
  1032. }
  1033. /* ------------------------------------------------------------------------- */
  1034. /* Helper functions for certain structures */
  1035. typedef void (*set_obj_t)(obs_data_t, const char*, obs_data_t);
  1036. static inline void set_vec2(obs_data_t data, const char *name,
  1037. const struct vec2 *val, set_obj_t set_obj)
  1038. {
  1039. obs_data_t obj = obs_data_create();
  1040. obs_data_setdouble(obj, "x", val->x);
  1041. obs_data_setdouble(obj, "y", val->y);
  1042. set_obj(data, name, obj);
  1043. obs_data_release(obj);
  1044. }
  1045. static inline void set_vec3(obs_data_t data, const char *name,
  1046. const struct vec3 *val, set_obj_t set_obj)
  1047. {
  1048. obs_data_t obj = obs_data_create();
  1049. obs_data_setdouble(obj, "x", val->x);
  1050. obs_data_setdouble(obj, "y", val->y);
  1051. obs_data_setdouble(obj, "z", val->z);
  1052. set_obj(data, name, obj);
  1053. obs_data_release(obj);
  1054. }
  1055. static inline void set_vec4(obs_data_t data, const char *name,
  1056. const struct vec4 *val, set_obj_t set_obj)
  1057. {
  1058. obs_data_t obj = obs_data_create();
  1059. obs_data_setdouble(obj, "x", val->x);
  1060. obs_data_setdouble(obj, "y", val->y);
  1061. obs_data_setdouble(obj, "z", val->z);
  1062. obs_data_setdouble(obj, "w", val->w);
  1063. set_obj(data, name, obj);
  1064. obs_data_release(obj);
  1065. }
  1066. static inline void set_quat(obs_data_t data, const char *name,
  1067. const struct quat *val, set_obj_t set_obj)
  1068. {
  1069. obs_data_t obj = obs_data_create();
  1070. obs_data_setdouble(obj, "x", val->x);
  1071. obs_data_setdouble(obj, "y", val->y);
  1072. obs_data_setdouble(obj, "z", val->z);
  1073. obs_data_setdouble(obj, "w", val->w);
  1074. set_obj(data, name, obj);
  1075. obs_data_release(obj);
  1076. }
  1077. void obs_data_set_vec2(obs_data_t data, const char *name,
  1078. const struct vec2 *val)
  1079. {
  1080. set_vec2(data, name, val, obs_data_setobj);
  1081. }
  1082. void obs_data_set_vec3(obs_data_t data, const char *name,
  1083. const struct vec3 *val)
  1084. {
  1085. set_vec3(data, name, val, obs_data_setobj);
  1086. }
  1087. void obs_data_set_vec4(obs_data_t data, const char *name,
  1088. const struct vec4 *val)
  1089. {
  1090. set_vec4(data, name, val, obs_data_setobj);
  1091. }
  1092. void obs_data_set_quat(obs_data_t data, const char *name,
  1093. const struct quat *val)
  1094. {
  1095. set_quat(data, name, val, obs_data_setobj);
  1096. }
  1097. void obs_data_set_default_vec2(obs_data_t data, const char *name,
  1098. const struct vec2 *val)
  1099. {
  1100. set_vec2(data, name, val, obs_data_set_default_obj);
  1101. }
  1102. void obs_data_set_default_vec3(obs_data_t data, const char *name,
  1103. const struct vec3 *val)
  1104. {
  1105. set_vec3(data, name, val, obs_data_set_default_obj);
  1106. }
  1107. void obs_data_set_default_vec4(obs_data_t data, const char *name,
  1108. const struct vec4 *val)
  1109. {
  1110. set_vec4(data, name, val, obs_data_set_default_obj);
  1111. }
  1112. void obs_data_set_default_quat(obs_data_t data, const char *name,
  1113. const struct quat *val)
  1114. {
  1115. set_quat(data, name, val, obs_data_set_default_obj);
  1116. }
  1117. static inline void get_vec2(obs_data_t obj, struct vec2 *val)
  1118. {
  1119. if (!obj) return;
  1120. val->x = (float)obs_data_getdouble(obj, "x");
  1121. val->y = (float)obs_data_getdouble(obj, "y");
  1122. obs_data_release(obj);
  1123. }
  1124. static inline void get_vec3(obs_data_t obj, struct vec3 *val)
  1125. {
  1126. if (!obj) return;
  1127. val->x = (float)obs_data_getdouble(obj, "x");
  1128. val->y = (float)obs_data_getdouble(obj, "y");
  1129. val->z = (float)obs_data_getdouble(obj, "z");
  1130. obs_data_release(obj);
  1131. }
  1132. static inline void get_vec4(obs_data_t obj, struct vec4 *val)
  1133. {
  1134. if (!obj) return;
  1135. val->x = (float)obs_data_getdouble(obj, "x");
  1136. val->y = (float)obs_data_getdouble(obj, "y");
  1137. val->z = (float)obs_data_getdouble(obj, "z");
  1138. val->w = (float)obs_data_getdouble(obj, "w");
  1139. obs_data_release(obj);
  1140. }
  1141. static inline void get_quat(obs_data_t obj, struct quat *val)
  1142. {
  1143. if (!obj) return;
  1144. val->x = (float)obs_data_getdouble(obj, "x");
  1145. val->y = (float)obs_data_getdouble(obj, "y");
  1146. val->z = (float)obs_data_getdouble(obj, "z");
  1147. val->w = (float)obs_data_getdouble(obj, "w");
  1148. obs_data_release(obj);
  1149. }
  1150. void obs_data_get_vec2(obs_data_t data, const char *name, struct vec2 *val)
  1151. {
  1152. get_vec2(obs_data_getobj(data, name), val);
  1153. }
  1154. void obs_data_get_vec3(obs_data_t data, const char *name, struct vec3 *val)
  1155. {
  1156. get_vec3(obs_data_getobj(data, name), val);
  1157. }
  1158. void obs_data_get_vec4(obs_data_t data, const char *name, struct vec4 *val)
  1159. {
  1160. get_vec4(obs_data_getobj(data, name), val);
  1161. }
  1162. void obs_data_get_quat(obs_data_t data, const char *name, struct quat *val)
  1163. {
  1164. get_quat(obs_data_getobj(data, name), val);
  1165. }
  1166. void obs_data_get_default_vec2(obs_data_t data, const char *name,
  1167. struct vec2 *val)
  1168. {
  1169. get_vec2(obs_data_get_default_obj(data, name), val);
  1170. }
  1171. void obs_data_get_default_vec3(obs_data_t data, const char *name,
  1172. struct vec3 *val)
  1173. {
  1174. get_vec3(obs_data_get_default_obj(data, name), val);
  1175. }
  1176. void obs_data_get_default_vec4(obs_data_t data, const char *name,
  1177. struct vec4 *val)
  1178. {
  1179. get_vec4(obs_data_get_default_obj(data, name), val);
  1180. }
  1181. void obs_data_get_default_quat(obs_data_t data, const char *name,
  1182. struct quat *val)
  1183. {
  1184. get_quat(obs_data_get_default_obj(data, name), val);
  1185. }