Bläddra i källkod

libobs: Add UUIDs to obs_source objects

derrod 2 år sedan
förälder
incheckning
30519768ad

+ 9 - 0
docs/sphinx/reference-core.rst

@@ -333,6 +333,15 @@ Libobs Objects
 
 ---------------------
 
+.. function:: obs_source_t *obs_get_source_by_uuid(const char *uuid)
+
+   Gets a source by its UUID.
+  
+   Increments the source reference counter, use
+   :c:func:`obs_source_release()` to release it when complete.
+
+---------------------
+
 .. function:: obs_source_t *obs_get_transition_by_name(const char *name)
 
    Gets a transition by its name.

+ 6 - 0
docs/sphinx/reference-sources.rst

@@ -941,6 +941,12 @@ General Source Functions
 
 ---------------------
 
+.. function:: const char *obs_source_get_uuid(const obs_source_t *source)
+
+   :return: The UUID of the source
+
+---------------------
+
 .. function:: void obs_source_set_name(obs_source_t *source, const char *name)
 
    Sets the name of a source.  If the source is not private and the name

+ 1 - 1
libobs/obs-encoder.c

@@ -52,7 +52,7 @@ static bool init_encoder(struct obs_encoder *encoder, const char *name,
 	pthread_mutex_init_value(&encoder->pause.mutex);
 
 	if (!obs_context_data_init(&encoder->context, OBS_OBJ_TYPE_ENCODER,
-				   settings, name, hotkey_data, false))
+				   settings, name, NULL, hotkey_data, false))
 		return false;
 	if (pthread_mutex_init_recursive(&encoder->init_mutex) != 0)
 		return false;

+ 8 - 5
libobs/obs-internal.h

@@ -520,6 +520,7 @@ typedef void (*obs_destroy_cb)(void *obj);
 
 struct obs_context_data {
 	char *name;
+	const char *uuid;
 	void *data;
 	obs_data_t *settings;
 	signal_handler_t *signals;
@@ -545,8 +546,8 @@ struct obs_context_data {
 
 extern bool obs_context_data_init(struct obs_context_data *context,
 				  enum obs_obj_type type, obs_data_t *settings,
-				  const char *name, obs_data_t *hotkey_data,
-				  bool private);
+				  const char *name, const char *uuid,
+				  obs_data_t *hotkey_data, bool private);
 extern void obs_context_init_control(struct obs_context_data *context,
 				     void *object, obs_destroy_cb destroy);
 extern void obs_context_data_free(struct obs_context_data *context);
@@ -834,7 +835,8 @@ extern struct obs_source_info *get_source_info2(const char *unversioned_id,
 						uint32_t ver);
 extern bool obs_source_init_context(struct obs_source *source,
 				    obs_data_t *settings, const char *name,
-				    obs_data_t *hotkey_data, bool private);
+				    const char *uuid, obs_data_t *hotkey_data,
+				    bool private);
 
 extern bool obs_transition_init(obs_source_t *transition);
 extern void obs_transition_free(obs_source_t *transition);
@@ -851,8 +853,9 @@ extern void audio_monitor_destroy(struct audio_monitor *monitor);
 
 extern obs_source_t *
 obs_source_create_set_last_ver(const char *id, const char *name,
-			       obs_data_t *settings, obs_data_t *hotkey_data,
-			       uint32_t last_obs_ver, bool is_private);
+			       const char *uuid, obs_data_t *settings,
+			       obs_data_t *hotkey_data, uint32_t last_obs_ver,
+			       bool is_private);
 extern void obs_source_destroy(struct obs_source *source);
 
 enum view_type {

+ 1 - 1
libobs/obs-output.c

@@ -94,7 +94,7 @@ static bool init_output_handlers(struct obs_output *output, const char *name,
 				 obs_data_t *settings, obs_data_t *hotkey_data)
 {
 	if (!obs_context_data_init(&output->context, OBS_OBJ_TYPE_OUTPUT,
-				   settings, name, hotkey_data, false))
+				   settings, name, NULL, hotkey_data, false))
 		return false;
 
 	signal_handler_add_array(output->context.signals, output_signals);

+ 2 - 1
libobs/obs-service.c

@@ -52,7 +52,8 @@ static obs_service_t *obs_service_create_internal(const char *id,
 	service = bzalloc(sizeof(struct obs_service));
 
 	if (!obs_context_data_init(&service->context, OBS_OBJ_TYPE_SERVICE,
-				   settings, name, hotkey_data, private)) {
+				   settings, name, NULL, hotkey_data,
+				   private)) {
 		bfree(service);
 		return NULL;
 	}

+ 16 - 8
libobs/obs-source.c

@@ -118,11 +118,11 @@ static const char *source_signals[] = {
 };
 
 bool obs_source_init_context(struct obs_source *source, obs_data_t *settings,
-			     const char *name, obs_data_t *hotkey_data,
-			     bool private)
+			     const char *name, const char *uuid,
+			     obs_data_t *hotkey_data, bool private)
 {
 	if (!obs_context_data_init(&source->context, OBS_OBJ_TYPE_SOURCE,
-				   settings, name, hotkey_data, private))
+				   settings, name, uuid, hotkey_data, private))
 		return false;
 
 	return signal_handler_add_array(source->context.signals,
@@ -340,7 +340,7 @@ static void obs_source_init_audio_hotkeys(struct obs_source *source)
 }
 
 static obs_source_t *
-obs_source_create_internal(const char *id, const char *name,
+obs_source_create_internal(const char *id, const char *name, const char *uuid,
 			   obs_data_t *settings, obs_data_t *hotkey_data,
 			   bool private, uint32_t last_obs_ver)
 {
@@ -370,7 +370,7 @@ obs_source_create_internal(const char *id, const char *name,
 	source->push_to_talk_key = OBS_INVALID_HOTKEY_ID;
 	source->last_obs_ver = last_obs_ver;
 
-	if (!obs_source_init_context(source, settings, name, hotkey_data,
+	if (!obs_source_init_context(source, settings, name, uuid, hotkey_data,
 				     private))
 		goto fail;
 
@@ -420,24 +420,25 @@ fail:
 obs_source_t *obs_source_create(const char *id, const char *name,
 				obs_data_t *settings, obs_data_t *hotkey_data)
 {
-	return obs_source_create_internal(id, name, settings, hotkey_data,
+	return obs_source_create_internal(id, name, NULL, settings, hotkey_data,
 					  false, LIBOBS_API_VER);
 }
 
 obs_source_t *obs_source_create_private(const char *id, const char *name,
 					obs_data_t *settings)
 {
-	return obs_source_create_internal(id, name, settings, NULL, true,
+	return obs_source_create_internal(id, name, NULL, settings, NULL, true,
 					  LIBOBS_API_VER);
 }
 
 obs_source_t *obs_source_create_set_last_ver(const char *id, const char *name,
+					     const char *uuid,
 					     obs_data_t *settings,
 					     obs_data_t *hotkey_data,
 					     uint32_t last_obs_ver,
 					     bool is_private)
 {
-	return obs_source_create_internal(id, name, settings, hotkey_data,
+	return obs_source_create_internal(id, name, uuid, settings, hotkey_data,
 					  is_private, last_obs_ver);
 }
 
@@ -4242,6 +4243,13 @@ const char *obs_source_get_name(const obs_source_t *source)
 		       : NULL;
 }
 
+const char *obs_source_get_uuid(const obs_source_t *source)
+{
+	return obs_source_valid(source, "obs_source_get_uuid")
+		       ? source->context.uuid
+		       : NULL;
+}
+
 void obs_source_set_name(obs_source_t *source, const char *name)
 {
 	if (!obs_source_valid(source, "obs_source_set_name"))

+ 41 - 11
libobs/obs.c

@@ -2019,6 +2019,26 @@ obs_source_t *obs_get_source_by_name(const char *name)
 				   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;
+}
+
 obs_source_t *obs_get_transition_by_name(const char *name)
 {
 	struct obs_source **first = &obs->data.first_source;
@@ -2203,6 +2223,7 @@ static obs_source_t *obs_load_source_type(obs_data_t *source_data,
 	obs_data_array_t *filters = obs_data_get_array(source_data, "filters");
 	obs_source_t *source;
 	const char *name = obs_data_get_string(source_data, "name");
+	const char *uuid = obs_data_get_string(source_data, "uuid");
 	const char *id = obs_data_get_string(source_data, "id");
 	const char *v_id = obs_data_get_string(source_data, "versioned_id");
 	obs_data_t *settings = obs_data_get_obj(source_data, "settings");
@@ -2223,8 +2244,9 @@ static obs_source_t *obs_load_source_type(obs_data_t *source_data,
 	if (!*v_id)
 		v_id = id;
 
-	source = obs_source_create_set_last_ver(v_id, name, settings, hotkeys,
-						prev_ver, is_private);
+	source = obs_source_create_set_last_ver(v_id, name, uuid, settings,
+						hotkeys, prev_ver, is_private);
+
 	if (source->owns_info_id) {
 		bfree((void *)source->info.unversioned_id);
 		source->info.unversioned_id = bstrdup(id);
@@ -2398,6 +2420,7 @@ obs_data_t *obs_save_source(obs_source_t *source)
 	int64_t sync = obs_source_get_sync_offset(source);
 	uint32_t flags = obs_source_get_flags(source);
 	const char *name = obs_source_get_name(source);
+	const char *uuid = obs_source_get_uuid(source);
 	const char *id = source->info.unversioned_id;
 	const char *v_id = source->info.id;
 	bool enabled = obs_source_enabled(source);
@@ -2422,6 +2445,7 @@ obs_data_t *obs_save_source(obs_source_t *source)
 	obs_data_set_int(source_data, "prev_ver", LIBOBS_API_VER);
 
 	obs_data_set_string(source_data, "name", name);
+	obs_data_set_string(source_data, "uuid", uuid);
 	obs_data_set_string(source_data, "id", id);
 	obs_data_set_string(source_data, "versioned_id", v_id);
 	obs_data_set_obj(source_data, "settings", settings);
@@ -2528,12 +2552,11 @@ static inline char *dup_name(const char *name, bool private)
 	}
 }
 
-static inline bool obs_context_data_init_wrap(struct obs_context_data *context,
-					      enum obs_obj_type type,
-					      obs_data_t *settings,
-					      const char *name,
-					      obs_data_t *hotkey_data,
-					      bool private)
+static inline bool
+obs_context_data_init_wrap(struct obs_context_data *context,
+			   enum obs_obj_type type, obs_data_t *settings,
+			   const char *name, const char *uuid,
+			   obs_data_t *hotkey_data, bool private)
 {
 	assert(context);
 	memset(context, 0, sizeof(*context));
@@ -2552,6 +2575,12 @@ static inline bool obs_context_data_init_wrap(struct obs_context_data *context,
 	if (!context->procs)
 		return false;
 
+	if (uuid && strlen(uuid) == UUID_STR_LENGTH)
+		context->uuid = bstrdup(uuid);
+	/* Only automatically generate UUIDs for sources */
+	else if (type == OBS_OBJ_TYPE_SOURCE)
+		context->uuid = os_generate_uuid();
+
 	context->name = dup_name(name, private);
 	context->settings = obs_data_newref(settings);
 	context->hotkey_data = obs_data_newref(hotkey_data);
@@ -2560,10 +2589,10 @@ static inline bool obs_context_data_init_wrap(struct obs_context_data *context,
 
 bool obs_context_data_init(struct obs_context_data *context,
 			   enum obs_obj_type type, obs_data_t *settings,
-			   const char *name, obs_data_t *hotkey_data,
-			   bool private)
+			   const char *name, const char *uuid,
+			   obs_data_t *hotkey_data, bool private)
 {
-	if (obs_context_data_init_wrap(context, type, settings, name,
+	if (obs_context_data_init_wrap(context, type, settings, name, uuid,
 				       hotkey_data, private)) {
 		return true;
 	} else {
@@ -2581,6 +2610,7 @@ void obs_context_data_free(struct obs_context_data *context)
 	obs_context_data_remove(context);
 	pthread_mutex_destroy(&context->rename_cache_mutex);
 	bfree(context->name);
+	bfree((void *)context->uuid);
 
 	for (size_t i = 0; i < context->rename_cache.num; i++)
 		bfree(context->rename_cache.array[i]);

+ 11 - 0
libobs/obs.h

@@ -697,6 +697,14 @@ EXPORT void obs_enum_services(bool (*enum_proc)(void *, obs_service_t *),
  */
 EXPORT obs_source_t *obs_get_source_by_name(const char *name);
 
+/**
+ * Gets a source by its UUID.
+ *
+ *   Increments the source reference counter, use obs_source_release to
+ * release it when complete.
+ */
+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);
 
@@ -1115,6 +1123,9 @@ EXPORT const char *obs_source_get_name(const obs_source_t *source);
 /** Sets the name of a source */
 EXPORT void obs_source_set_name(obs_source_t *source, const char *name);
 
+/** Gets the UUID of a source */
+EXPORT const char *obs_source_get_uuid(const obs_source_t *source);
+
 /** Gets the source type */
 EXPORT enum obs_source_type obs_source_get_type(const obs_source_t *source);