Sfoglia il codice sorgente

Simplify/improve UI exporting a bit more

Reduce and simplify the UI export interface.  Having to export functions
with designated names was a bit silly for this case, it makes more sense
for inputs/outputs/etc because they have more functions associated with
them, but in this case the callback can be retrieved simply through the
enumeration exports.  Makes it a bit easier and a little less awkward
for this situation.

Also, changed the exports and names to be a bit more consistent,
labelling them both as either "modal" or "modeless", and changed the UI
function calls to obs_exec_ui and obs_create_ui to imply modal/modeless
functionality a bit more.
jp9000 11 anni fa
parent
commit
6f51567c93
4 ha cambiato i file con 75 aggiunte e 125 eliminazioni
  1. 2 13
      libobs/obs-internal.h
  2. 20 39
      libobs/obs-module.c
  3. 37 56
      libobs/obs-ui.h
  4. 16 17
      libobs/obs.c

+ 2 - 13
libobs/obs-internal.h

@@ -49,17 +49,6 @@ struct obs_display {
 	/* TODO: sound output target */
 };
 
-/* TODO: optimize this later so it's not just O(N) string lookups */
-struct ui_callback {
-	struct obs_ui_info ui_info;
-	bool (*callback)(void *data, void *ui_data);
-};
-
-struct ui_modeless {
-	struct obs_ui_info ui_info;
-	void *(*callback)(void *data, void *ui_data);
-};
-
 /* ------------------------------------------------------------------------- */
 
 struct obs_video {
@@ -111,8 +100,8 @@ struct obs_subsystem {
 	DARRAY(struct output_info)  output_types;
 	DARRAY(struct encoder_info) encoder_types;
 	DARRAY(struct service_info) service_types;
-	DARRAY(struct ui_callback)  ui_callbacks;
-	DARRAY(struct ui_modeless)  ui_modeless_callbacks;
+	DARRAY(struct obs_modal_ui) ui_modal_callbacks;
+	DARRAY(struct obs_modeless_ui) ui_modeless_callbacks;
 
 	signal_handler_t            signals;
 	proc_handler_t              procs;

+ 20 - 39
libobs/obs-module.c

@@ -76,46 +76,28 @@ complete:
 	dstr_free(&enum_name);
 }
 
-struct generic_ui_callback {
-	struct obs_ui_info ui_info;
-	void *callback;
-};
-
-static void module_load_ui_exports(struct obs_module *mod,
-		const char *main_export, struct darray *array)
+static void module_load_modal_ui_exports(struct obs_module *mod)
 {
-	bool (*enum_func)(size_t idx, struct obs_ui_info *info);
-	struct obs_ui_info ui_info;
+	bool (*enum_func)(size_t idx, struct obs_modal_ui *info);
+	struct obs_modal_ui ui_info;
 	size_t i = 0;
 
-	enum_func = os_dlsym(mod->module, main_export);
-	if (!enum_func)
-		return;
+	enum_func = os_dlsym(mod->module, "enum_modal_ui");
+	if (enum_func)
+		while (enum_func(i++, &ui_info))
+			da_push_back(obs->ui_modal_callbacks, &ui_info);
+}
 
-	while (enum_func(i++, &ui_info)) {
-		struct generic_ui_callback callback;
-		struct dstr name;
-
-		dstr_init_copy(&name, ui_info.name);
-		dstr_cat(&name, "_");
-		dstr_cat(&name, ui_info.task);
-		dstr_cat(&name, "_");
-		dstr_cat(&name, ui_info.target);
-
-		callback.ui_info = ui_info;
-		callback.callback = os_dlsym(mod->module, name.array);
-
-		if (!callback.callback) {
-			blog(LOG_WARNING, "Module '%s' enumerated UI callback "
-			                  "'%s', but the function was not "
-			                  "found", mod->name, name.array);
-		} else {
-			darray_push_back(sizeof(struct generic_ui_callback),
-					array, &callback);
-		}
-
-		dstr_free(&name);
-	}
+static void module_load_modeless_ui_exports(struct obs_module *mod)
+{
+	bool (*enum_func)(size_t idx, struct obs_modeless_ui *info);
+	struct obs_modeless_ui ui_info;
+	size_t i = 0;
+
+	enum_func = os_dlsym(mod->module, "enum_modeless_ui");
+	if (enum_func)
+		while (enum_func(i++, &ui_info))
+			da_push_back(obs->ui_modeless_callbacks, &ui_info);
 }
 
 extern char *find_plugin(const char *plugin);
@@ -199,9 +181,8 @@ int obs_load_module(const char *path)
 	module_load_exports(&mod, &obs->encoder_types.da, "encoders",
 			sizeof(struct encoder_info), load_encoder_info);
 
-	module_load_ui_exports(&mod, "enum_ui", &obs->ui_callbacks.da);
-	module_load_ui_exports(&mod, "enum_modeless_ui",
-			&obs->ui_modeless_callbacks.da);
+	module_load_modal_ui_exports(&mod);
+	module_load_modeless_ui_exports(&mod);
 
 	da_push_back(obs->modules, &mod);
 	return MODULE_SUCCESS;

+ 37 - 56
libobs/obs-ui.h

@@ -23,10 +23,18 @@
 extern "C" {
 #endif
 
-struct obs_ui_info {
+struct obs_modal_ui {
 	const char *name;
 	const char *task;
 	const char *target;
+	bool (*callback)(void *object, void *ui_data);
+};
+
+struct obs_modeless_ui {
+	const char *name;
+	const char *task;
+	const char *target;
+	void *(*callback)(void *object, void *ui_data);
 };
 
 /*
@@ -44,100 +52,73 @@ struct obs_ui_info {
  * languages)
  *
  *   A module with UI calls needs to export one or both of these functions:
- *       + enum_ui
+ *       + enum_modal_ui
  *       + enum_modeless_ui
  *
  *   The enum_ui function provides an obs_ui_info structure for each
  * input/output/etc.  Modeless UI should be exported enum_modeless_ui.  For
- * example, to export Qt-specific configuration functions, the exports might
- * be something like:
- *       + mysource_config_qt
- *       + myoutput_config_qt
- *       + myencoder_config_qt
- *
- *    ..And the values given to enum_ui would be something this:
- *
- *    struct obs_ui_info ui_list[] = {
- *            {"mysource",  "config", "qt"},
- *            {"myoutput",  "config", "qt"},
- *            {"myencoder", "config", "qt"}
+ * example, to export Qt-specific configuration functions, the values given to
+ * enum_modal_ui might look something like this:
+ *
+ *    struct obs_modal_ui ui_list[] = {
+ *            {"mysource",  "config", "qt", mysource_config},
+ *            {"myoutput",  "config", "qt", myoutput_config},
+ *            {"myencoder", "config", "qt", myenoder_config}
  *    };
  *
  *   'qt' could be replaced with 'wx' or something similar if using wxWidgets,
- * or 'win32' if using bare windows API.
+ * or 'win32' if using bare windows API.  It could also specify a custom name
+ * if desired (use with discretion).
  *
  * ===========================================
  *   Primary Exports
  * ===========================================
- *   bool enum_ui(size_t idx, struct obs_ui_info *ui_info);
+ *   bool enum_modal_ui(size_t idx, struct obs_modal_ui *ui_info);
  *
  *                idx: index of the enumeration
  *            ui_info: pointer to the ui data for this enumeration
  *       Return value: false when no more available.
  *
  * ---------------------------------------------------------
- *   bool enum_modeless_ui(size_t idx, struct obs_ui_info *ui_info);
+ *   bool enum_modeless_ui(size_t idx, struct obs_modeless_ui *ui_info);
  *
  *                idx: index of the enumeration
  *            ui_info: pointer to the ui data for this enumeration
  *       Return value: false when no more available.
  *
  * ===========================================
- *   Export Format
+ *   Modal UI Callback
  * ===========================================
- *   Although the 'export' variable specifies the full export name, each
- * export should be formatted as so:
- *
- *       bool [name]_[task]_[target](void *data, void *ui_data);
+ *       bool modal_callback(void *object, void *ui_data);
  *
- *     [name]: specifies the name of the input/output/encoder/etc.
- *     [task]: specifies the task of the user interface, most often 'config'
- *   [target]: specifies the target or toolkit of the user interface, such as
- *             but not limited to 'qt', 'wx', 'win32', 'cocoa', etc.  If
- *             a custom solution is desired, it can use a program-specific
- *             name, such as 'myprogram'.
- *
- *   The 'data' variable points to the input/output/encoder/etc.  The 'ui_data'
- * varaible points to the UI parent or UI-specific data to be used with the
- * custom user interface.
+ *   The 'object' variable points to the input/output/encoder/etc.  The
+ * 'ui_data' varaible points to the UI parent or UI-specific data to be used
+ * with the custom user interface.
  *
  *   What 'ui_data' points to differs depending on the target, and you should
  * use discretion and consistency when using this variable to relay
  * information to the UI function.  For example, it would be ideal to have
  * 'ui_data' point to a parent, QWidget for Qt, or a wxWindow for wxWidgets,
- * etc.
- *
- *   For example, if I had a source called 'mysource', and I wanted to export
- * a function that handles the task 'config' with the Qt library, the export
- * would be:
- *
- *   bool mysource_config_qt(void *data, void *ui_data);
- *
- *   In this example, the ui_data variable should ideally be a pointer to the
- * QWidget parent, if any.
+ * etc., though it's up to the discretion of the developer to define that
+ * value.  Because of the nature of void pointers, discretion and consistency
+ * is advised.
  *
  * ===========================================
- *   Modeless UI
+ *   Modeless UI Callback
  * ===========================================
- *   Modeless user interface calls are supported, but they must be exported
- * through enum_modeless_ui, and the format is slightly different:
- *
- *       void *[name]_[task]_[target](void *data, void *ui_data);
+ *       void *modeless_callback(void *data, void *ui_data);
  *
  *   Modeless UI calls return immediately, and typically are supposed to return
  * a pointer or handle to the specific UI object that was created.  For
- * example, a win32 modeless would return an HWND, a Qt object would return
- * a pointer to a QWidget.
+ * example, a Qt object would ideally return a pointer to a QWidget.  Again,
+ * discretion and consistency is advised for the return value.
  */
 
 /**
  * ===========================================
- *   obs_call_ui
+ *   obs_exec_ui
  * ===========================================
- * Requests modal UI to be displayed
- *
- *   This is typically used for things like creating modal dialogs/etc for
- * specific toolkits.
+ * Requests modal UI to be displayed.  Returns when user is complete.
  *
  *           name: Name of the input/output/etc type that UI was requested for
  *           task: Task of the user interface (usually "config")
@@ -153,14 +134,14 @@ struct obs_ui_info {
 #define OBS_UI_CANCEL   -1
 #define OBS_UI_NOTFOUND -2
 
-EXPORT int obs_call_ui(const char *name, const char *task, const char *target,
+EXPORT int obs_exec_ui(const char *name, const char *task, const char *target,
 		void *data, void *ui_data);
 
 /**
  * ===========================================
  *   obs_create_ui
  * ===========================================
- * Requests modeless UI to be created
+ * Requests modeless UI to be created.  Returns immediately.
  *
  *           name: Name of the input/output/etc type that UI was requested for
  *           task: Task of the user interface

+ 16 - 17
libobs/obs.c

@@ -326,7 +326,7 @@ void obs_shutdown(void)
 	da_free(obs->transition_types);
 	da_free(obs->output_types);
 	da_free(obs->service_types);
-	da_free(obs->ui_callbacks);
+	da_free(obs->ui_modal_callbacks);
 	da_free(obs->ui_modeless_callbacks);
 
 	obs_free_data();
@@ -454,44 +454,44 @@ video_t obs_video(void)
 }
 
 /* TODO: optimize this later so it's not just O(N) string lookups */
-static inline struct ui_callback *get_ui_callback(const char *name,
+static inline struct obs_modal_ui *get_modal_ui_callback(const char *name,
 		const char *task, const char *target)
 {
-	for (size_t i = 0; i < obs->ui_callbacks.num; i++) {
-		struct ui_callback *callback = obs->ui_callbacks.array+i;
+	for (size_t i = 0; i < obs->ui_modal_callbacks.num; i++) {
+		struct obs_modal_ui *callback = obs->ui_modal_callbacks.array+i;
 
-		if (strcmp(callback->ui_info.name,   name)   == 0 &&
-		    strcmp(callback->ui_info.task,   task)   == 0 &&
-		    strcmp(callback->ui_info.target, target) == 0)
+		if (strcmp(callback->name,   name)   == 0 &&
+		    strcmp(callback->task,   task)   == 0 &&
+		    strcmp(callback->target, target) == 0)
 			return callback;
 	}
 
 	return NULL;
 }
 
-static inline struct ui_modeless *get_modeless_ui_callback(const char *name,
+static inline struct obs_modeless_ui *get_modeless_ui_callback(const char *name,
 		const char *task, const char *target)
 {
 	for (size_t i = 0; i < obs->ui_modeless_callbacks.num; i++) {
-		struct ui_modeless *callback;
+		struct obs_modeless_ui *callback;
 		callback = obs->ui_modeless_callbacks.array+i;
 
-		if (strcmp(callback->ui_info.name,   name)   == 0 &&
-		    strcmp(callback->ui_info.task,   task)   == 0 &&
-		    strcmp(callback->ui_info.target, target) == 0)
+		if (strcmp(callback->name,   name)   == 0 &&
+		    strcmp(callback->task,   task)   == 0 &&
+		    strcmp(callback->target, target) == 0)
 			return callback;
 	}
 
 	return NULL;
 }
 
-int obs_call_ui(const char *name, const char *task, const char *target,
+int obs_exec_ui(const char *name, const char *task, const char *target,
 		void *data, void *ui_data)
 {
-	struct ui_callback *callback;
+	struct obs_modal_ui *callback;
 	int errorcode = OBS_UI_NOTFOUND;
 
-	callback = get_ui_callback(name, task, target);
+	callback = get_modal_ui_callback(name, task, target);
 	if (callback) {
 		bool success = callback->callback(data, ui_data);
 		errorcode = success ? OBS_UI_SUCCESS : OBS_UI_CANCEL;
@@ -503,8 +503,7 @@ int obs_call_ui(const char *name, const char *task, const char *target,
 void *obs_create_ui(const char *name, const char *task, const char *target,
 		void *data, void *ui_data)
 {
-	struct ui_modeless *callback;
-	int errorcode = OBS_UI_NOTFOUND;
+	struct obs_modeless_ui *callback;
 
 	callback = get_modeless_ui_callback(name, task, target);
 	return callback ? callback->callback(data, ui_data) : NULL;