mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-08-28 17:42:28 +08:00
rtmp-services: Extract Twitch specific info from ingest update code
This commit is contained in:
@@ -7,31 +7,45 @@
|
||||
|
||||
#include "twitch.h"
|
||||
|
||||
static update_info_t *twitch_update_info = NULL;
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool ingests_refreshed = false;
|
||||
static bool ingests_refreshing = false;
|
||||
static bool ingests_loaded = false;
|
||||
|
||||
struct ingest {
|
||||
char *name;
|
||||
char *url;
|
||||
};
|
||||
|
||||
static DARRAY(struct ingest) cur_ingests;
|
||||
struct service_ingests {
|
||||
update_info_t *update_info;
|
||||
pthread_mutex_t mutex;
|
||||
bool ingests_refreshed;
|
||||
bool ingests_refreshing;
|
||||
bool ingests_loaded;
|
||||
DARRAY(struct ingest) cur_ingests;
|
||||
const char *cache_old_filename;
|
||||
const char *cache_new_filename;
|
||||
};
|
||||
|
||||
static void free_ingests(void)
|
||||
static struct service_ingests twitch = {
|
||||
.update_info = NULL,
|
||||
.mutex = PTHREAD_MUTEX_INITIALIZER,
|
||||
.ingests_refreshed = false,
|
||||
.ingests_refreshing = false,
|
||||
.ingests_loaded = false,
|
||||
.cur_ingests = {0},
|
||||
.cache_old_filename = "twitch_ingests.json",
|
||||
.cache_new_filename = "twitch_ingests.new.json"};
|
||||
|
||||
static void free_ingests(struct service_ingests *si)
|
||||
{
|
||||
for (size_t i = 0; i < cur_ingests.num; i++) {
|
||||
struct ingest *ingest = cur_ingests.array + i;
|
||||
for (size_t i = 0; i < si->cur_ingests.num; i++) {
|
||||
struct ingest *ingest = si->cur_ingests.array + i;
|
||||
bfree(ingest->name);
|
||||
bfree(ingest->url);
|
||||
}
|
||||
|
||||
da_free(cur_ingests);
|
||||
da_free(si->cur_ingests);
|
||||
}
|
||||
|
||||
static bool load_ingests(const char *json, bool write_file)
|
||||
static bool load_ingests(struct service_ingests *si, const char *json,
|
||||
bool write_file)
|
||||
{
|
||||
json_t *root;
|
||||
json_t *ingests;
|
||||
@@ -49,10 +63,10 @@ static bool load_ingests(const char *json, bool write_file)
|
||||
goto finish;
|
||||
|
||||
count = json_array_size(ingests);
|
||||
if (count <= 1 && cur_ingests.num)
|
||||
if (count <= 1 && si->cur_ingests.num)
|
||||
goto finish;
|
||||
|
||||
free_ingests();
|
||||
free_ingests(si);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
json_t *item = json_array_get(ingests, i);
|
||||
@@ -79,10 +93,10 @@ static bool load_ingests(const char *json, bool write_file)
|
||||
ingest.name = bstrdup(name_str);
|
||||
ingest.url = url.array;
|
||||
|
||||
da_push_back(cur_ingests, &ingest);
|
||||
da_push_back(si->cur_ingests, &ingest);
|
||||
}
|
||||
|
||||
if (!cur_ingests.num)
|
||||
if (!si->cur_ingests.num)
|
||||
goto finish;
|
||||
|
||||
success = true;
|
||||
@@ -90,8 +104,8 @@ static bool load_ingests(const char *json, bool write_file)
|
||||
if (!write_file)
|
||||
goto finish;
|
||||
|
||||
cache_old = obs_module_config_path("twitch_ingests.json");
|
||||
cache_new = obs_module_config_path("twitch_ingests.new.json");
|
||||
cache_old = obs_module_config_path(si->cache_old_filename);
|
||||
cache_new = obs_module_config_path(si->cache_new_filename);
|
||||
|
||||
os_quick_write_utf8_file(cache_new, json, strlen(json), false);
|
||||
os_safe_replace(cache_old, cache_new, NULL);
|
||||
@@ -105,78 +119,88 @@ finish:
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool twitch_ingest_update(void *param, struct file_download_data *data)
|
||||
static bool ingest_update(void *param, struct file_download_data *data)
|
||||
{
|
||||
struct service_ingests *service = param;
|
||||
bool success;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
success = load_ingests((const char *)data->buffer.array, true);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
pthread_mutex_lock(&service->mutex);
|
||||
success = load_ingests(service, (const char *)data->buffer.array, true);
|
||||
pthread_mutex_unlock(&service->mutex);
|
||||
|
||||
if (success) {
|
||||
os_atomic_set_bool(&ingests_refreshed, true);
|
||||
os_atomic_set_bool(&ingests_loaded, true);
|
||||
os_atomic_set_bool(&service->ingests_refreshed, true);
|
||||
os_atomic_set_bool(&service->ingests_loaded, true);
|
||||
}
|
||||
|
||||
UNUSED_PARAMETER(param);
|
||||
return true;
|
||||
}
|
||||
|
||||
void twitch_ingests_lock(void)
|
||||
{
|
||||
pthread_mutex_lock(&mutex);
|
||||
pthread_mutex_lock(&twitch.mutex);
|
||||
}
|
||||
|
||||
void twitch_ingests_unlock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
pthread_mutex_unlock(&twitch.mutex);
|
||||
}
|
||||
|
||||
size_t twitch_ingest_count(void)
|
||||
{
|
||||
return cur_ingests.num;
|
||||
return twitch.cur_ingests.num;
|
||||
}
|
||||
|
||||
struct twitch_ingest twitch_ingest(size_t idx)
|
||||
struct twitch_ingest get_ingest(struct service_ingests *si, size_t idx)
|
||||
{
|
||||
struct twitch_ingest ingest;
|
||||
|
||||
if (cur_ingests.num <= idx) {
|
||||
if (si->cur_ingests.num <= idx) {
|
||||
ingest.name = NULL;
|
||||
ingest.url = NULL;
|
||||
} else {
|
||||
ingest = *(struct twitch_ingest *)(cur_ingests.array + idx);
|
||||
ingest = *(struct twitch_ingest *)(si->cur_ingests.array + idx);
|
||||
}
|
||||
|
||||
return ingest;
|
||||
}
|
||||
|
||||
struct twitch_ingest twitch_ingest(size_t idx)
|
||||
{
|
||||
return get_ingest(&twitch, idx);
|
||||
}
|
||||
|
||||
void init_service_data(struct service_ingests *si)
|
||||
{
|
||||
da_init(si->cur_ingests);
|
||||
pthread_mutex_init(&si->mutex, NULL);
|
||||
}
|
||||
|
||||
void init_twitch_data(void)
|
||||
{
|
||||
da_init(cur_ingests);
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
init_service_data(&twitch);
|
||||
}
|
||||
|
||||
extern const char *get_module_name(void);
|
||||
|
||||
void twitch_ingests_refresh(int seconds)
|
||||
void service_ingests_refresh(struct service_ingests *si, int seconds,
|
||||
const char *log_prefix, const char *file_url)
|
||||
{
|
||||
if (os_atomic_load_bool(&ingests_refreshed))
|
||||
if (os_atomic_load_bool(&si->ingests_refreshed))
|
||||
return;
|
||||
|
||||
if (!os_atomic_load_bool(&ingests_refreshing)) {
|
||||
os_atomic_set_bool(&ingests_refreshing, true);
|
||||
if (!os_atomic_load_bool(&si->ingests_refreshing)) {
|
||||
os_atomic_set_bool(&si->ingests_refreshing, true);
|
||||
|
||||
twitch_update_info = update_info_create_single(
|
||||
"[twitch ingest update] ", get_module_name(),
|
||||
"https://ingest.twitch.tv/ingests",
|
||||
twitch_ingest_update, NULL);
|
||||
si->update_info =
|
||||
update_info_create_single(log_prefix, get_module_name(),
|
||||
file_url, ingest_update, si);
|
||||
}
|
||||
|
||||
/* wait five seconds max when loading ingests for the first time */
|
||||
if (!os_atomic_load_bool(&ingests_loaded)) {
|
||||
if (!os_atomic_load_bool(&si->ingests_loaded)) {
|
||||
for (int i = 0; i < seconds * 100; i++) {
|
||||
if (os_atomic_load_bool(&ingests_refreshed)) {
|
||||
if (os_atomic_load_bool(&si->ingests_refreshed)) {
|
||||
break;
|
||||
}
|
||||
os_sleep_ms(10);
|
||||
@@ -184,38 +208,54 @@ void twitch_ingests_refresh(int seconds)
|
||||
}
|
||||
}
|
||||
|
||||
void load_twitch_data(void)
|
||||
void twitch_ingests_refresh(int seconds)
|
||||
{
|
||||
char *twitch_cache = obs_module_config_path("twitch_ingests.json");
|
||||
service_ingests_refresh(&twitch, seconds, "[twitch ingest update] ",
|
||||
"https://ingest.twitch.tv/ingests");
|
||||
}
|
||||
|
||||
struct ingest def = {.name = bstrdup("Default"),
|
||||
.url = bstrdup("rtmp://live.twitch.tv/app")};
|
||||
void load_service_data(struct service_ingests *si, const char *cache_filename,
|
||||
struct ingest *def)
|
||||
{
|
||||
char *service_cache = obs_module_config_path(cache_filename);
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
da_push_back(cur_ingests, &def);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
pthread_mutex_lock(&si->mutex);
|
||||
da_push_back(si->cur_ingests, def);
|
||||
pthread_mutex_unlock(&si->mutex);
|
||||
|
||||
if (os_file_exists(twitch_cache)) {
|
||||
char *data = os_quick_read_utf8_file(twitch_cache);
|
||||
if (os_file_exists(service_cache)) {
|
||||
char *data = os_quick_read_utf8_file(service_cache);
|
||||
bool success;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
success = load_ingests(data, false);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
pthread_mutex_lock(&si->mutex);
|
||||
success = load_ingests(si, data, false);
|
||||
pthread_mutex_unlock(&si->mutex);
|
||||
|
||||
if (success) {
|
||||
os_atomic_set_bool(&ingests_loaded, true);
|
||||
os_atomic_set_bool(&si->ingests_loaded, true);
|
||||
}
|
||||
|
||||
bfree(data);
|
||||
}
|
||||
|
||||
bfree(twitch_cache);
|
||||
bfree(service_cache);
|
||||
}
|
||||
|
||||
void load_twitch_data(void)
|
||||
{
|
||||
struct ingest def = {.name = bstrdup("Default"),
|
||||
.url = bstrdup("rtmp://live.twitch.tv/app")};
|
||||
load_service_data(&twitch, "twitch_ingests.json", &def);
|
||||
}
|
||||
|
||||
void unload_service_data(struct service_ingests *si)
|
||||
{
|
||||
update_info_destroy(si->update_info);
|
||||
free_ingests(si);
|
||||
pthread_mutex_destroy(&si->mutex);
|
||||
}
|
||||
|
||||
void unload_twitch_data(void)
|
||||
{
|
||||
update_info_destroy(twitch_update_info);
|
||||
free_ingests();
|
||||
pthread_mutex_destroy(&mutex);
|
||||
unload_service_data(&twitch);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user