rtmp-common.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #include <util/platform.h>
  2. #include <obs-module.h>
  3. #include <jansson.h>
  4. struct rtmp_common {
  5. char *service;
  6. char *server;
  7. char *key;
  8. };
  9. static const char *rtmp_common_getname(const char *locale)
  10. {
  11. UNUSED_PARAMETER(locale);
  12. /* TODO: locale */
  13. return "Other Streaming Services";
  14. }
  15. static void rtmp_common_update(void *data, obs_data_t settings)
  16. {
  17. struct rtmp_common *service = data;
  18. bfree(service->service);
  19. bfree(service->server);
  20. bfree(service->key);
  21. service->service = bstrdup(obs_data_getstring(settings, "service"));
  22. service->server = bstrdup(obs_data_getstring(settings, "server"));
  23. service->key = bstrdup(obs_data_getstring(settings, "key"));
  24. }
  25. static void rtmp_common_destroy(void *data)
  26. {
  27. struct rtmp_common *service = data;
  28. bfree(service->service);
  29. bfree(service->server);
  30. bfree(service->key);
  31. bfree(service);
  32. }
  33. static void *rtmp_common_create(obs_data_t settings, obs_service_t service)
  34. {
  35. struct rtmp_common *data = bzalloc(sizeof(struct rtmp_common));
  36. rtmp_common_update(data, settings);
  37. UNUSED_PARAMETER(service);
  38. return data;
  39. }
  40. static inline const char *get_string_val(json_t *service, const char *key)
  41. {
  42. json_t *str_val = json_object_get(service, key);
  43. if (!str_val || !json_is_string(str_val))
  44. return NULL;
  45. return json_string_value(str_val);
  46. }
  47. static void add_service(obs_property_t list, json_t *service)
  48. {
  49. json_t *servers;
  50. const char *name;
  51. if (!json_is_object(service)) {
  52. blog(LOG_WARNING, "rtmp-common.c: [add_service] service "
  53. "is not an object");
  54. return;
  55. }
  56. name = get_string_val(service, "name");
  57. if (!name) {
  58. blog(LOG_WARNING, "rtmp-common.c: [add_service] service "
  59. "has no name");
  60. return;
  61. }
  62. servers = json_object_get(service, "servers");
  63. if (!servers || !json_is_array(servers)) {
  64. blog(LOG_WARNING, "rtmp-common.c: [add_service] service "
  65. "'%s' has no servers", name);
  66. return;
  67. }
  68. obs_property_list_add_string(list, name, name);
  69. }
  70. static void add_services(obs_property_t list, const char *file, json_t *root)
  71. {
  72. json_t *service;
  73. size_t index;
  74. if (!json_is_array(root)) {
  75. blog(LOG_WARNING, "rtmp-common.c: [add_services] JSON file "
  76. "'%s' root is not an array", file);
  77. return;
  78. }
  79. json_array_foreach (root, index, service) {
  80. add_service(list, service);
  81. }
  82. }
  83. static json_t *build_service_list(obs_property_t list, const char *file)
  84. {
  85. char *file_data = os_quick_read_utf8_file(file);
  86. json_error_t error;
  87. json_t *root;
  88. if (!file_data)
  89. return NULL;
  90. root = json_loads(file_data, JSON_REJECT_DUPLICATES, &error);
  91. bfree(file_data);
  92. if (!root) {
  93. blog(LOG_WARNING, "rtmp-common.c: [build_service_list] "
  94. "Error reading JSON file '%s' (%d): %s",
  95. file, error.line, error.text);
  96. return NULL;
  97. }
  98. add_services(list, file, root);
  99. return root;
  100. }
  101. static void properties_data_destroy(void *data)
  102. {
  103. json_t *root = data;
  104. if (root)
  105. json_decref(root);
  106. }
  107. static void fill_servers(obs_property_t servers_prop, json_t *service,
  108. const char *name)
  109. {
  110. json_t *servers, *server;
  111. size_t index;
  112. obs_property_list_clear(servers_prop);
  113. servers = json_object_get(service, "servers");
  114. if (!json_is_array(servers)) {
  115. blog(LOG_WARNING, "rtmp-common.c: [fill_servers] "
  116. "Servers for service '%s' not a valid object",
  117. name);
  118. return;
  119. }
  120. json_array_foreach (servers, index, server) {
  121. const char *server_name = get_string_val(server, "name");
  122. const char *url = get_string_val(server, "url");
  123. if (!server_name || !url)
  124. continue;
  125. obs_property_list_add_string(servers_prop, server_name, url);
  126. }
  127. }
  128. static inline json_t *find_service(json_t *root, const char *name)
  129. {
  130. size_t index;
  131. json_t *service;
  132. json_array_foreach (root, index, service) {
  133. const char *cur_name = get_string_val(service, "name");
  134. if (strcmp(name, cur_name) == 0)
  135. return service;
  136. }
  137. return NULL;
  138. }
  139. static bool service_selected(obs_properties_t props, obs_property_t p,
  140. obs_data_t settings)
  141. {
  142. const char *name = obs_data_getstring(settings, "service");
  143. json_t *root = obs_properties_get_param(props);
  144. json_t *service;
  145. if (!name || !*name)
  146. return false;
  147. service = find_service(root, name);
  148. if (!service)
  149. return false;
  150. fill_servers(obs_properties_get(props, "server"), service, name);
  151. UNUSED_PARAMETER(p);
  152. return true;
  153. }
  154. static obs_properties_t rtmp_common_properties(const char *locale)
  155. {
  156. obs_properties_t ppts = obs_properties_create(locale);
  157. obs_property_t list;
  158. char *file;
  159. /* TODO: locale */
  160. list = obs_properties_add_list(ppts, "service", "Service",
  161. OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
  162. file = obs_find_plugin_file("rtmp-services/services.json");
  163. if (file) {
  164. json_t *root = build_service_list(list, file);
  165. obs_properties_set_param(ppts, root, properties_data_destroy);
  166. obs_property_set_modified_callback(list, service_selected);
  167. bfree(file);
  168. }
  169. obs_properties_add_list(ppts, "server", "Server",
  170. OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
  171. obs_properties_add_text(ppts, "key", "Stream Key", OBS_TEXT_PASSWORD);
  172. return ppts;
  173. }
  174. static const char *rtmp_common_url(void *data)
  175. {
  176. struct rtmp_common *service = data;
  177. return service->server;
  178. }
  179. static const char *rtmp_common_key(void *data)
  180. {
  181. struct rtmp_common *service = data;
  182. return service->key;
  183. }
  184. struct obs_service_info rtmp_common_service = {
  185. .id = "rtmp_common",
  186. .getname = rtmp_common_getname,
  187. .create = rtmp_common_create,
  188. .destroy = rtmp_common_destroy,
  189. .update = rtmp_common_update,
  190. .properties = rtmp_common_properties,
  191. .get_url = rtmp_common_url,
  192. .get_key = rtmp_common_key
  193. };