mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-02 09:33:33 +00:00
libobs: Use uthash for source objects
All sources are part of a hash table that allows a lookup by UUID. Public sources additionally are in a hash table allowing lookup by name.
This commit is contained in:
parent
183fa8c06c
commit
c68eeaef1d
|
@ -351,6 +351,15 @@ Libobs Objects
|
|||
|
||||
---------------------
|
||||
|
||||
.. function:: obs_source_t *obs_get_transition_by_uuid(const char *uuid)
|
||||
|
||||
Gets a transition by its UUID.
|
||||
|
||||
Increments the source reference counter, use
|
||||
:c:func:`obs_source_release()` to release it when complete.
|
||||
|
||||
---------------------
|
||||
|
||||
.. function:: obs_scene_t *obs_get_scene_by_name(const char *name)
|
||||
|
||||
Gets a scene by its name.
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "util/platform.h"
|
||||
#include "util/profiler.h"
|
||||
#include "util/task.h"
|
||||
#include "util/uthash.h"
|
||||
#include "callback/signal.h"
|
||||
#include "callback/proc.h"
|
||||
|
||||
|
@ -39,6 +40,12 @@
|
|||
|
||||
#include <caption/caption.h>
|
||||
|
||||
/* Custom helpers for the UUID hash table */
|
||||
#define HASH_FIND_UUID(head, uuid, out) \
|
||||
HASH_FIND(hh_uuid, head, uuid, UUID_STR_LENGTH, out)
|
||||
#define HASH_ADD_UUID(head, uuid_field, add) \
|
||||
HASH_ADD(hh_uuid, head, uuid_field[0], UUID_STR_LENGTH, add)
|
||||
|
||||
#define NUM_TEXTURES 2
|
||||
#define NUM_CHANNELS 3
|
||||
#define MICROSECOND_DEN 1000000
|
||||
|
@ -372,7 +379,11 @@ struct obs_core_audio {
|
|||
|
||||
/* user sources, output channels, and displays */
|
||||
struct obs_core_data {
|
||||
struct obs_source *first_source;
|
||||
/* Hash tables (uthash) */
|
||||
struct obs_source *sources; /* Lookup by UUID (hh_uuid) */
|
||||
struct obs_source *public_sources; /* Lookup by name (hh) */
|
||||
|
||||
/* Linked lists */
|
||||
struct obs_source *first_audio_source;
|
||||
struct obs_display *first_display;
|
||||
struct obs_output *first_output;
|
||||
|
@ -541,6 +552,9 @@ struct obs_context_data {
|
|||
struct obs_context_data *next;
|
||||
struct obs_context_data **prev_next;
|
||||
|
||||
UT_hash_handle hh;
|
||||
UT_hash_handle hh_uuid;
|
||||
|
||||
bool private;
|
||||
};
|
||||
|
||||
|
@ -554,11 +568,24 @@ extern void obs_context_data_free(struct obs_context_data *context);
|
|||
|
||||
extern void obs_context_data_insert(struct obs_context_data *context,
|
||||
pthread_mutex_t *mutex, void *first);
|
||||
extern void obs_context_data_insert_name(struct obs_context_data *context,
|
||||
pthread_mutex_t *mutex, void *first);
|
||||
extern void obs_context_data_insert_uuid(struct obs_context_data *context,
|
||||
pthread_mutex_t *mutex,
|
||||
void *first_uuid);
|
||||
|
||||
extern void obs_context_data_remove(struct obs_context_data *context);
|
||||
extern void obs_context_data_remove_name(struct obs_context_data *context,
|
||||
void *phead);
|
||||
extern void obs_context_data_remove_uuid(struct obs_context_data *context,
|
||||
void *puuid_head);
|
||||
|
||||
extern void obs_context_wait(struct obs_context_data *context);
|
||||
|
||||
extern void obs_context_data_setname(struct obs_context_data *context,
|
||||
const char *name);
|
||||
extern void obs_context_data_setname_ht(struct obs_context_data *context,
|
||||
const char *name, void *phead);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ref-counting */
|
||||
|
|
|
@ -960,7 +960,7 @@ static void scene_load_item(struct obs_scene *scene, obs_data_t *item_data)
|
|||
{
|
||||
const char *name = obs_data_get_string(item_data, "name");
|
||||
const char *src_uuid = obs_data_get_string(item_data, "source_uuid");
|
||||
obs_source_t *source;
|
||||
obs_source_t *source = NULL;
|
||||
const char *scale_filter_str;
|
||||
const char *blend_method_str;
|
||||
const char *blend_str;
|
||||
|
@ -973,7 +973,9 @@ static void scene_load_item(struct obs_scene *scene, obs_data_t *item_data)
|
|||
|
||||
if (src_uuid && strlen(src_uuid) == UUID_STR_LENGTH)
|
||||
source = obs_get_source_by_uuid(src_uuid);
|
||||
else
|
||||
|
||||
/* Fall back to name if UUID was not found or is not set. */
|
||||
if (!source)
|
||||
source = obs_get_source_by_name(name);
|
||||
|
||||
if (!source) {
|
||||
|
|
|
@ -244,8 +244,13 @@ static void obs_source_init_finalize(struct obs_source *source)
|
|||
pthread_mutex_unlock(&obs->data.audio_sources_mutex);
|
||||
}
|
||||
|
||||
obs_context_data_insert(&source->context, &obs->data.sources_mutex,
|
||||
&obs->data.first_source);
|
||||
if (!source->context.private) {
|
||||
obs_context_data_insert_name(&source->context,
|
||||
&obs->data.sources_mutex,
|
||||
&obs->data.public_sources);
|
||||
}
|
||||
obs_context_data_insert_uuid(&source->context, &obs->data.sources_mutex,
|
||||
&obs->data.sources);
|
||||
}
|
||||
|
||||
static bool obs_source_hotkey_mute(void *data, obs_hotkey_pair_id id,
|
||||
|
@ -662,7 +667,10 @@ void obs_source_destroy(struct obs_source *source)
|
|||
while (source->filters.num)
|
||||
obs_source_filter_remove(source, source->filters.array[0]);
|
||||
|
||||
obs_context_data_remove(&source->context);
|
||||
obs_context_data_remove_uuid(&source->context, &obs->data.sources);
|
||||
if (!source->context.private)
|
||||
obs_context_data_remove_name(&source->context,
|
||||
&obs->data.public_sources);
|
||||
|
||||
/* defer source destroy */
|
||||
os_task_queue_queue_task(obs->destruction_task_thread,
|
||||
|
@ -4259,7 +4267,13 @@ void obs_source_set_name(obs_source_t *source, const char *name)
|
|||
strcmp(name, source->context.name) != 0) {
|
||||
struct calldata data;
|
||||
char *prev_name = bstrdup(source->context.name);
|
||||
obs_context_data_setname(&source->context, name);
|
||||
|
||||
if (!source->context.private) {
|
||||
obs_context_data_setname_ht(&source->context, name,
|
||||
&obs->data.public_sources);
|
||||
} else {
|
||||
obs_context_data_setname(&source->context, name);
|
||||
}
|
||||
|
||||
calldata_init(&data);
|
||||
calldata_set_ptr(&data, "source", source);
|
||||
|
|
|
@ -60,7 +60,7 @@ static uint64_t tick_sources(uint64_t cur_time, uint64_t last_time)
|
|||
|
||||
pthread_mutex_lock(&data->sources_mutex);
|
||||
|
||||
source = data->first_source;
|
||||
source = data->sources;
|
||||
while (source) {
|
||||
obs_source_t *s = obs_source_get_ref(source);
|
||||
|
||||
|
@ -69,7 +69,7 @@ static uint64_t tick_sources(uint64_t cur_time, uint64_t last_time)
|
|||
obs_source_release(s);
|
||||
}
|
||||
|
||||
source = (struct obs_source *)source->context.next;
|
||||
source = (struct obs_source *)source->context.hh_uuid.next;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&data->sources_mutex);
|
||||
|
|
303
libobs/obs.c
303
libobs/obs.c
|
@ -1000,6 +1000,8 @@ static bool obs_init_data(void)
|
|||
if (!obs_view_init(&data->main_view))
|
||||
goto fail;
|
||||
|
||||
data->sources = NULL;
|
||||
data->public_sources = NULL;
|
||||
data->private_data = obs_data_create();
|
||||
data->valid = true;
|
||||
|
||||
|
@ -1019,6 +1021,20 @@ void obs_main_view_free(struct obs_view *view)
|
|||
pthread_mutex_destroy(&view->channels_mutex);
|
||||
}
|
||||
|
||||
#define FREE_OBS_HASH_TABLE(handle, table, type) \
|
||||
do { \
|
||||
struct obs_context_data *ctx, *tmp; \
|
||||
int unfreed = 0; \
|
||||
HASH_ITER (handle, *(struct obs_context_data **)table, ctx, \
|
||||
tmp) { \
|
||||
obs_##type##_destroy((obs_##type##_t *)ctx); \
|
||||
unfreed++; \
|
||||
} \
|
||||
if (unfreed) \
|
||||
blog(LOG_INFO, "\t%d " #type "(s) were remaining", \
|
||||
unfreed); \
|
||||
} while (false)
|
||||
|
||||
#define FREE_OBS_LINKED_LIST(type) \
|
||||
do { \
|
||||
int unfreed = 0; \
|
||||
|
@ -1042,12 +1058,14 @@ static void obs_free_data(void)
|
|||
|
||||
blog(LOG_INFO, "Freeing OBS context data");
|
||||
|
||||
FREE_OBS_LINKED_LIST(source);
|
||||
FREE_OBS_LINKED_LIST(output);
|
||||
FREE_OBS_LINKED_LIST(encoder);
|
||||
FREE_OBS_LINKED_LIST(display);
|
||||
FREE_OBS_LINKED_LIST(service);
|
||||
|
||||
FREE_OBS_HASH_TABLE(hh, &data->public_sources, source);
|
||||
FREE_OBS_HASH_TABLE(hh_uuid, &data->sources, source);
|
||||
|
||||
os_task_queue_wait(obs->destruction_task_thread);
|
||||
|
||||
pthread_mutex_destroy(&data->sources_mutex);
|
||||
|
@ -1869,17 +1887,16 @@ void obs_enum_sources(bool (*enum_proc)(void *, obs_source_t *), void *param)
|
|||
obs_source_t *source;
|
||||
|
||||
pthread_mutex_lock(&obs->data.sources_mutex);
|
||||
source = obs->data.first_source;
|
||||
source = obs->data.public_sources;
|
||||
|
||||
while (source) {
|
||||
obs_source_t *s = obs_source_get_ref(source);
|
||||
if (s) {
|
||||
if (strcmp(s->info.id, group_info.id) == 0 &&
|
||||
if (s->info.type == OBS_SOURCE_TYPE_INPUT &&
|
||||
!enum_proc(param, s)) {
|
||||
obs_source_release(s);
|
||||
break;
|
||||
} else if (s->info.type == OBS_SOURCE_TYPE_INPUT &&
|
||||
!s->context.private &&
|
||||
} else if (strcmp(s->info.id, group_info.id) == 0 &&
|
||||
!enum_proc(param, s)) {
|
||||
obs_source_release(s);
|
||||
break;
|
||||
|
@ -1887,7 +1904,7 @@ void obs_enum_sources(bool (*enum_proc)(void *, obs_source_t *), void *param)
|
|||
obs_source_release(s);
|
||||
}
|
||||
|
||||
source = (obs_source_t *)source->context.next;
|
||||
source = (obs_source_t *)source->context.hh.next;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&obs->data.sources_mutex);
|
||||
|
@ -1898,20 +1915,20 @@ void obs_enum_scenes(bool (*enum_proc)(void *, obs_source_t *), void *param)
|
|||
obs_source_t *source;
|
||||
|
||||
pthread_mutex_lock(&obs->data.sources_mutex);
|
||||
source = obs->data.first_source;
|
||||
|
||||
source = obs->data.public_sources;
|
||||
while (source) {
|
||||
obs_source_t *s = obs_source_get_ref(source);
|
||||
if (s) {
|
||||
if (source->info.type == OBS_SOURCE_TYPE_SCENE &&
|
||||
!source->context.private && !enum_proc(param, s)) {
|
||||
!enum_proc(param, s)) {
|
||||
obs_source_release(s);
|
||||
break;
|
||||
}
|
||||
obs_source_release(s);
|
||||
}
|
||||
|
||||
source = (obs_source_t *)source->context.next;
|
||||
source = (obs_source_t *)source->context.hh.next;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&obs->data.sources_mutex);
|
||||
|
@ -1940,11 +1957,31 @@ static inline void obs_enum(void *pstart, pthread_mutex_t *mutex, void *proc,
|
|||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
static inline void obs_enum_uuid(void *pstart, pthread_mutex_t *mutex,
|
||||
void *proc, void *param)
|
||||
{
|
||||
struct obs_context_data **start = pstart, *context, *tmp;
|
||||
bool (*enum_proc)(void *, void *) = proc;
|
||||
|
||||
assert(start);
|
||||
assert(mutex);
|
||||
assert(enum_proc);
|
||||
|
||||
pthread_mutex_lock(mutex);
|
||||
|
||||
HASH_ITER (hh_uuid, *start, context, tmp) {
|
||||
if (!enum_proc(param, context))
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
void obs_enum_all_sources(bool (*enum_proc)(void *, obs_source_t *),
|
||||
void *param)
|
||||
{
|
||||
obs_enum(&obs->data.first_source, &obs->data.sources_mutex, enum_proc,
|
||||
param);
|
||||
obs_enum_uuid(&obs->data.sources, &obs->data.sources_mutex, enum_proc,
|
||||
param);
|
||||
}
|
||||
|
||||
void obs_enum_outputs(bool (*enum_proc)(void *, obs_output_t *), void *param)
|
||||
|
@ -1974,15 +2011,41 @@ static inline void *get_context_by_name(void *vfirst, const char *name,
|
|||
|
||||
pthread_mutex_lock(mutex);
|
||||
|
||||
context = *first;
|
||||
while (context) {
|
||||
if (!context->private && strcmp(context->name, name) == 0) {
|
||||
context = addref(context);
|
||||
break;
|
||||
/* If context list head has a hash table, look the name up in there */
|
||||
if (*first && (*first)->hh.tbl) {
|
||||
HASH_FIND_STR(*first, name, context);
|
||||
} else {
|
||||
context = *first;
|
||||
while (context) {
|
||||
if (!context->private &&
|
||||
strcmp(context->name, name) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
context = context->next;
|
||||
}
|
||||
context = context->next;
|
||||
}
|
||||
|
||||
if (context)
|
||||
addref(context);
|
||||
|
||||
pthread_mutex_unlock(mutex);
|
||||
return context;
|
||||
}
|
||||
|
||||
static void *get_context_by_uuid(void *ptable, const char *uuid,
|
||||
pthread_mutex_t *mutex,
|
||||
void *(*addref)(void *))
|
||||
{
|
||||
struct obs_context_data **ht = ptable;
|
||||
struct obs_context_data *context;
|
||||
|
||||
pthread_mutex_lock(mutex);
|
||||
|
||||
HASH_FIND_UUID(*ht, uuid, context);
|
||||
if (context)
|
||||
addref(context);
|
||||
|
||||
pthread_mutex_unlock(mutex);
|
||||
return context;
|
||||
}
|
||||
|
@ -2014,38 +2077,27 @@ static inline void *obs_id_(void *data)
|
|||
|
||||
obs_source_t *obs_get_source_by_name(const char *name)
|
||||
{
|
||||
return get_context_by_name(&obs->data.first_source, name,
|
||||
return get_context_by_name(&obs->data.public_sources, name,
|
||||
&obs->data.sources_mutex,
|
||||
obs_source_addref_safe_);
|
||||
}
|
||||
|
||||
obs_source_t *obs_get_source_by_uuid(const char *uuid)
|
||||
{
|
||||
struct obs_source **first = &obs->data.first_source;
|
||||
struct obs_source *source;
|
||||
|
||||
pthread_mutex_lock(&obs->data.sources_mutex);
|
||||
|
||||
source = *first;
|
||||
while (source) {
|
||||
if (strcmp(source->context.uuid, uuid) == 0) {
|
||||
source = obs_source_get_ref(source);
|
||||
break;
|
||||
}
|
||||
source = (struct obs_source *)source->context.next;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&obs->data.sources_mutex);
|
||||
return source;
|
||||
return get_context_by_uuid(&obs->data.sources, uuid,
|
||||
&obs->data.sources_mutex,
|
||||
obs_source_addref_safe_);
|
||||
}
|
||||
|
||||
obs_source_t *obs_get_transition_by_name(const char *name)
|
||||
{
|
||||
struct obs_source **first = &obs->data.first_source;
|
||||
struct obs_source **first = &obs->data.sources;
|
||||
struct obs_source *source;
|
||||
|
||||
pthread_mutex_lock(&obs->data.sources_mutex);
|
||||
|
||||
/* Transitions are private but can be found via this method, so we
|
||||
* can't look them up by name in the public_sources hash table. */
|
||||
source = *first;
|
||||
while (source) {
|
||||
if (source->info.type == OBS_SOURCE_TYPE_TRANSITION &&
|
||||
|
@ -2053,13 +2105,18 @@ obs_source_t *obs_get_transition_by_name(const char *name)
|
|||
source = obs_source_addref_safe_(source);
|
||||
break;
|
||||
}
|
||||
source = (void *)source->context.next;
|
||||
source = (void *)source->context.hh_uuid.next;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&obs->data.sources_mutex);
|
||||
return source;
|
||||
}
|
||||
|
||||
obs_source_t *obs_get_transition_by_uuid(const char *uuid)
|
||||
{
|
||||
return obs_get_source_by_uuid(uuid);
|
||||
}
|
||||
|
||||
obs_output_t *obs_get_output_by_name(const char *name)
|
||||
{
|
||||
return get_context_by_name(&obs->data.first_output, name,
|
||||
|
@ -2503,19 +2560,19 @@ obs_data_array_t *obs_save_sources_filtered(obs_save_source_filter_cb cb,
|
|||
|
||||
pthread_mutex_lock(&data->sources_mutex);
|
||||
|
||||
source = data->first_source;
|
||||
source = data->public_sources;
|
||||
|
||||
while (source) {
|
||||
if ((source->info.type != OBS_SOURCE_TYPE_FILTER) != 0 &&
|
||||
!source->context.private && !source->removed &&
|
||||
!source->temp_removed && cb(data_, source)) {
|
||||
!source->removed && !source->temp_removed &&
|
||||
cb(data_, source)) {
|
||||
obs_data_t *source_data = obs_save_source(source);
|
||||
|
||||
obs_data_array_push_back(array, source_data);
|
||||
obs_data_release(source_data);
|
||||
}
|
||||
|
||||
source = (obs_source_t *)source->context.next;
|
||||
source = (obs_source_t *)source->context.hh.next;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&data->sources_mutex);
|
||||
|
@ -2539,14 +2596,25 @@ void obs_reset_source_uuids()
|
|||
{
|
||||
pthread_mutex_lock(&obs->data.sources_mutex);
|
||||
|
||||
struct obs_source *source = obs->data.first_source;
|
||||
while (source) {
|
||||
bfree((void *)source->context.uuid);
|
||||
source->context.uuid = os_generate_uuid();
|
||||
/* Move all sources to a new hash table */
|
||||
struct obs_context_data *ht =
|
||||
(struct obs_context_data *)obs->data.sources;
|
||||
struct obs_context_data *new_ht = NULL;
|
||||
|
||||
source = (struct obs_source *)source->context.next;
|
||||
struct obs_context_data *ctx, *tmp;
|
||||
HASH_ITER (hh_uuid, ht, ctx, tmp) {
|
||||
HASH_DELETE(hh_uuid, ht, ctx);
|
||||
|
||||
bfree((void *)ctx->uuid);
|
||||
ctx->uuid = os_generate_uuid();
|
||||
|
||||
HASH_ADD_UUID(new_ht, uuid, ctx);
|
||||
}
|
||||
|
||||
/* The old table will be automatically freed once the last element has
|
||||
* been removed, so we can simply overwrite the pointer. */
|
||||
obs->data.sources = (struct obs_source *)new_ht;
|
||||
|
||||
pthread_mutex_unlock(&obs->data.sources_mutex);
|
||||
}
|
||||
|
||||
|
@ -2662,6 +2730,91 @@ void obs_context_data_insert(struct obs_context_data *context,
|
|||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
static inline char *obs_context_deduplicate_name(void *phash, const char *name)
|
||||
{
|
||||
struct obs_context_data *head = phash;
|
||||
struct obs_context_data *item = NULL;
|
||||
|
||||
HASH_FIND_STR(head, name, item);
|
||||
if (!item)
|
||||
return NULL;
|
||||
|
||||
struct dstr new_name = {0};
|
||||
int suffix = 2;
|
||||
|
||||
while (item) {
|
||||
dstr_printf(&new_name, "%s %d", name, suffix++);
|
||||
HASH_FIND_STR(head, new_name.array, item);
|
||||
}
|
||||
|
||||
return new_name.array;
|
||||
}
|
||||
|
||||
void obs_context_data_insert_name(struct obs_context_data *context,
|
||||
pthread_mutex_t *mutex, void *pfirst)
|
||||
{
|
||||
struct obs_context_data **first = pfirst;
|
||||
char *new_name;
|
||||
|
||||
assert(context);
|
||||
assert(mutex);
|
||||
assert(first);
|
||||
|
||||
context->mutex = mutex;
|
||||
|
||||
pthread_mutex_lock(mutex);
|
||||
|
||||
/* Ensure name is not a duplicate. */
|
||||
new_name = obs_context_deduplicate_name(*first, context->name);
|
||||
if (new_name) {
|
||||
blog(LOG_WARNING,
|
||||
"Attempted to insert context with duplicate name \"%s\"!"
|
||||
" Name has been changed to \"%s\"",
|
||||
context->name, new_name);
|
||||
/* Since this happens before the context creation finishes,
|
||||
* do not bother to add it to the rename cache. */
|
||||
bfree(context->name);
|
||||
context->name = new_name;
|
||||
}
|
||||
|
||||
HASH_ADD_STR(*first, name, context);
|
||||
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
void obs_context_data_insert_uuid(struct obs_context_data *context,
|
||||
pthread_mutex_t *mutex, void *pfirst_uuid)
|
||||
{
|
||||
struct obs_context_data **first_uuid = pfirst_uuid;
|
||||
struct obs_context_data *item = NULL;
|
||||
|
||||
assert(context);
|
||||
assert(mutex);
|
||||
assert(first_uuid);
|
||||
|
||||
context->mutex = mutex;
|
||||
|
||||
pthread_mutex_lock(mutex);
|
||||
|
||||
/* Ensure UUID is not a duplicate.
|
||||
* This should only ever happen if a scene collection file has been
|
||||
* manually edited and an entry has been duplicated without removing
|
||||
* or regenerating the UUID. */
|
||||
HASH_FIND_UUID(*first_uuid, context->uuid, item);
|
||||
if (item) {
|
||||
blog(LOG_WARNING,
|
||||
"Attempted to insert context with duplicate UUID \"%s\"!",
|
||||
context->uuid);
|
||||
/* It is practically impossible for the new UUID to be a
|
||||
* duplicate, so don't bother checking again. */
|
||||
bfree((void *)context->uuid);
|
||||
context->uuid = os_generate_uuid();
|
||||
}
|
||||
|
||||
HASH_ADD_UUID(*first_uuid, uuid, context);
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
void obs_context_data_remove(struct obs_context_data *context)
|
||||
{
|
||||
if (context && context->prev_next) {
|
||||
|
@ -2674,6 +2827,35 @@ void obs_context_data_remove(struct obs_context_data *context)
|
|||
}
|
||||
}
|
||||
|
||||
void obs_context_data_remove_name(struct obs_context_data *context, void *phead)
|
||||
{
|
||||
struct obs_context_data **head = phead;
|
||||
|
||||
assert(head);
|
||||
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(context->mutex);
|
||||
HASH_DELETE(hh, *head, context);
|
||||
pthread_mutex_unlock(context->mutex);
|
||||
}
|
||||
|
||||
void obs_context_data_remove_uuid(struct obs_context_data *context,
|
||||
void *puuid_head)
|
||||
{
|
||||
struct obs_context_data **uuid_head = puuid_head;
|
||||
|
||||
assert(uuid_head);
|
||||
|
||||
if (!context || !context->uuid || !uuid_head)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(context->mutex);
|
||||
HASH_DELETE(hh_uuid, *uuid_head, context);
|
||||
pthread_mutex_unlock(context->mutex);
|
||||
}
|
||||
|
||||
void obs_context_wait(struct obs_context_data *context)
|
||||
{
|
||||
pthread_mutex_lock(context->mutex);
|
||||
|
@ -2692,6 +2874,37 @@ void obs_context_data_setname(struct obs_context_data *context,
|
|||
pthread_mutex_unlock(&context->rename_cache_mutex);
|
||||
}
|
||||
|
||||
void obs_context_data_setname_ht(struct obs_context_data *context,
|
||||
const char *name, void *phead)
|
||||
{
|
||||
struct obs_context_data **head = phead;
|
||||
char *new_name;
|
||||
|
||||
pthread_mutex_lock(context->mutex);
|
||||
pthread_mutex_lock(&context->rename_cache_mutex);
|
||||
|
||||
HASH_DEL(*head, context);
|
||||
if (context->name)
|
||||
da_push_back(context->rename_cache, &context->name);
|
||||
|
||||
/* Ensure new name is not a duplicate. */
|
||||
new_name = obs_context_deduplicate_name(*head, name);
|
||||
if (new_name) {
|
||||
blog(LOG_WARNING,
|
||||
"Attempted to rename context to duplicate name \"%s\"!"
|
||||
" New name has been changed to \"%s\"",
|
||||
context->name, new_name);
|
||||
context->name = new_name;
|
||||
} else {
|
||||
context->name = dup_name(name, context->private);
|
||||
}
|
||||
|
||||
HASH_ADD_STR(*head, name, context);
|
||||
|
||||
pthread_mutex_unlock(&context->rename_cache_mutex);
|
||||
pthread_mutex_unlock(context->mutex);
|
||||
}
|
||||
|
||||
profiler_name_store_t *obs_get_profiler_name_store(void)
|
||||
{
|
||||
return obs->name_store;
|
||||
|
|
|
@ -708,6 +708,9 @@ EXPORT obs_source_t *obs_get_source_by_uuid(const char *uuid);
|
|||
/** Get a transition source by its name. */
|
||||
EXPORT obs_source_t *obs_get_transition_by_name(const char *name);
|
||||
|
||||
/** Get a transition source by its UUID. */
|
||||
EXPORT obs_source_t *obs_get_transition_by_uuid(const char *uuid);
|
||||
|
||||
/** Gets an output by its name. */
|
||||
EXPORT obs_output_t *obs_get_output_by_name(const char *name);
|
||||
|
||||
|
|
Loading…
Reference in a new issue