diff --git a/configure.ac b/configure.ac index 410889361..16549b3fd 100644 --- a/configure.ac +++ b/configure.ac @@ -117,6 +117,12 @@ AC_FUNC_FSEEKO AC_FUNC_STRTOD AC_CHECK_FUNCS([memmove memset socket strstr strtol strtoul]) +AC_ARG_ENABLE([build_jansson], + [AS_HELP_STRING([--build-jansson], [build jansson])]) +if test "x$build_jansson" = xyes; then + AC_CONFIG_SUBDIRS([deps/jansson]) +fi + AC_CONFIG_FILES([makefile build/makefile obs/makefile diff --git a/libobs/obs-defs.h b/libobs/obs-defs.h index fde45bef6..e450979ae 100644 --- a/libobs/obs-defs.h +++ b/libobs/obs-defs.h @@ -21,6 +21,7 @@ #define MODULE_ERROR -1 #define MODULE_FILENOTFOUND -2 #define MODULE_FUNCTIONNOTFOUND -3 +#define MODULE_INCOMPATIBLE_VER -4 #define SOURCE_VIDEO (1<<0) #define SOURCE_AUDIO (1<<1) diff --git a/libobs/obs-module.c b/libobs/obs-module.c index ac705500e..918001044 100644 --- a/libobs/obs-module.c +++ b/libobs/obs-module.c @@ -78,23 +78,71 @@ complete: extern char *find_plugin(const char *plugin); +/* checks API version of module and calls module_load if it exists. + * if the API version used by the module is incompatible, fails. */ +static int call_module_load(void *module, const char *path) +{ + uint32_t (*module_version)(uint32_t obs_ver) = NULL; + bool (*module_load)(void) = NULL; + uint32_t version, major, minor; + + module_load = os_dlsym(module, "module_load"); + + module_version = os_dlsym(module, "module_version"); + if (!module_version) { + blog(LOG_WARNING, "Module '%s' failed to load: " + "module_version not found.", path); + return MODULE_FUNCTIONNOTFOUND; + } + + version = module_version(LIBOBS_API_VER); + major = (version >> 16); + minor = (version & 0xFF); + + if (major != LIBOBS_API_MAJOR_VER) { + blog(LOG_WARNING, "Module '%s' failed to load: " + "incompatible major version " + "(current API: %u.%u, module version: %u.%u)", + path, + LIBOBS_API_MAJOR_VER, LIBOBS_API_MINOR_VER, + major, minor); + return MODULE_INCOMPATIBLE_VER; + } + + if (minor > LIBOBS_API_MINOR_VER) { + blog(LOG_WARNING, "Module '%s' failed to load: " + "incompatible minor version " + "(current API: %u.%u, module version: %u.%u)", + path, + LIBOBS_API_MAJOR_VER, LIBOBS_API_MINOR_VER, + major, minor); + return MODULE_INCOMPATIBLE_VER; + } + + if (module_load && !module_load()) { + blog(LOG_WARNING, "Module '%s' failed to load: " + "module_load failed", path); + return MODULE_ERROR; + } + + return MODULE_SUCCESS; +} + int obs_load_module(const char *path) { struct obs_module mod; - bool (*module_load)(void) = NULL; char *plugin_path = find_plugin(path); + int errorcode; mod.module = os_dlopen(plugin_path); bfree(plugin_path); if (!mod.module) return MODULE_FILENOTFOUND; - module_load = os_dlsym(mod.module, "module_load"); - if (module_load) { - if (!module_load()) { - os_dlclose(mod.module); - return MODULE_ERROR; - } + errorcode = call_module_load(mod.module, path); + if (errorcode != MODULE_SUCCESS) { + os_dlclose(mod.module); + return errorcode; } mod.name = bstrdup(path); diff --git a/libobs/obs-output.c b/libobs/obs-output.c index df2665f1c..a0641e62a 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -21,6 +21,8 @@ bool get_output_info(void *module, const char *module_name, const char *output_name, struct output_info *info) { + info->getname = load_module_subfunc(module, module_name, + output_name, "getname", true); info->create = load_module_subfunc(module, module_name, output_name, "create", true); info->destroy = load_module_subfunc(module, module_name, @@ -30,7 +32,8 @@ bool get_output_info(void *module, const char *module_name, info->stop = load_module_subfunc(module, module_name, output_name, "stop", true); - if (!info->create || !info->destroy || !info->start || !info->stop) + if (!info->getname || !info->create || !info->destroy || + !info->start || !info->stop) return false; info->config = load_module_subfunc(module, module_name, diff --git a/libobs/obs-output.h b/libobs/obs-output.h index 3b709c2fe..7b51211de 100644 --- a/libobs/obs-output.h +++ b/libobs/obs-output.h @@ -33,6 +33,7 @@ * * Each individual output is then exported by it's name. For example, an * output named "myoutput" would have the following exports: + * + myoutput_getname * + myoutput_create * + myoutput_destroy * + myoutput_start @@ -52,7 +53,11 @@ * =========================================== * Output Exports * =========================================== - * void *[name]_create(const char *settings, output_t output); + * const char *[name]_getname(const char *locale); + * Returns the full translated name of the output type (seen by the user). + * + * --------------------------------------------------------- + * void *[name]_create(const char *settings, obs_output_t output); * Creates an output. * * settings: Settings of the output. @@ -95,6 +100,8 @@ struct obs_output; struct output_info { const char *name; + const char *(*getname)(const char *locale); + void *(*create)(const char *settings, struct obs_output *output); void (*destroy)(void *data); diff --git a/libobs/obs-scene.c b/libobs/obs-scene.c index e3b5b6995..db75d572b 100644 --- a/libobs/obs-scene.c +++ b/libobs/obs-scene.c @@ -18,6 +18,12 @@ #include "graphics/math-defs.h" #include "obs-scene.h" +static const char *scene_getname(const char *locale) +{ + /* TODO: locale lookup of display name */ + return "Scene"; +} + static void *scene_create(const char *settings, struct obs_source *source) { struct obs_scene *scene = bmalloc(sizeof(struct obs_scene)); @@ -84,6 +90,7 @@ static bool scene_enum_children(void *data, size_t idx, obs_source_t *child) static const struct source_info scene_info = { "scene", + scene_getname, scene_create, scene_destroy, scene_get_output_flags, NULL, NULL, NULL, NULL, @@ -96,6 +103,7 @@ static const struct source_info scene_info = static const struct source_info scene_info = { .name = "scene", + .getname = scene_getname, .create = scene_create, .destroy = scene_destroy, .get_output_flags = scene_get_output_flags, diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 34557bf90..3931c37e8 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -24,6 +24,8 @@ bool get_source_info(void *module, const char *module_name, const char *source_name, struct source_info *info) { + info->getname = load_module_subfunc(module, module_name, + source_name, "getname", true); info->create = load_module_subfunc(module, module_name, source_name,"create", true); info->destroy = load_module_subfunc(module, module_name, @@ -31,7 +33,8 @@ bool get_source_info(void *module, const char *module_name, info->get_output_flags = load_module_subfunc(module, module_name, source_name, "get_output_flags", true); - if (!info->create || !info->destroy || !info->get_output_flags) + if (!info->getname || !info->create || !info->destroy || + !info->get_output_flags) return false; info->config = load_module_subfunc(module, module_name, diff --git a/libobs/obs-source.h b/libobs/obs-source.h index 6ebf9665c..899f8bb61 100644 --- a/libobs/obs-source.h +++ b/libobs/obs-source.h @@ -36,6 +36,7 @@ * * Each individual source is then exported by it's name. For example, a * source named "mysource" would have the following exports: + * + mysource_getname * + mysource_create * + mysource_destroy * + mysource_getflags @@ -59,6 +60,10 @@ * =========================================== * Source Exports * =========================================== + * const char *[name]_getname(const char *locale); + * Returns the full name of the source type (seen by the user). + * + * --------------------------------------------------------- * void *[name]_create(const char *settings, obs_source_t source); * Creates a source. * @@ -161,6 +166,8 @@ struct source_info { /* ----------------------------------------------------------------- */ /* required implementations */ + const char *(*getname)(const char *locale); + void *(*create)(const char *settings, obs_source_t source); void (*destroy)(void *data); diff --git a/libobs/obs.h b/libobs/obs.h index 0fb237437..74510cdd7 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -32,6 +32,13 @@ extern "C" { #endif +/* LIBOBS_API_VER must be returned by module_version in each module */ + +#define LIBOBS_API_MAJOR_VER 0 /* increment if major breaking changes */ +#define LIBOBS_API_MINOR_VER 1 /* increment if minor non-breaking additions */ +#define LIBOBS_API_VER ((LIBOBS_API_MAJOR_VER << 16) | \ + LIBOBS_API_MINOR_VER) + enum obs_source_type { SOURCE_INPUT, SOURCE_FILTER, @@ -214,6 +221,12 @@ EXPORT obs_source_t obs_display_getsource(obs_display_t display); /* ------------------------------------------------------------------------- */ /* Sources */ +/** + * Gets the translated display name of a source + */ +EXPORT const char *obs_source_getdisplayname(enum obs_source_type type, + const char *name, const char *locale); + /** * Creates a source of the specified type with the specified settings. * @@ -221,7 +234,7 @@ EXPORT obs_source_t obs_display_getsource(obs_display_t display); * or modifying video/audio. */ EXPORT obs_source_t obs_source_create(enum obs_source_type type, - const char *name, const char *settings); + const char *name, const char *settings); EXPORT void obs_source_destroy(obs_source_t source); /** diff --git a/obs/window-obs-basic.cpp b/obs/window-obs-basic.cpp index fb49ab23a..0f77d0134 100644 --- a/obs/window-obs-basic.cpp +++ b/obs/window-obs-basic.cpp @@ -16,7 +16,7 @@ ******************************************************************************/ #include "window-obs-basic.hpp" - +/* void OBSBasic::file_newOnMenuSelection(wxCommandEvent& event) { } @@ -80,3 +80,4 @@ void OBSBasic::sourceUpOnToolClicked(wxCommandEvent& event) void OBSBasic::sourceDownOnToolClicked(wxCommandEvent& event) { } +*/ \ No newline at end of file diff --git a/obs/window-obs-basic.hpp b/obs/window-obs-basic.hpp index 1bacc52c1..663af1f33 100644 --- a/obs/window-obs-basic.hpp +++ b/obs/window-obs-basic.hpp @@ -19,7 +19,7 @@ #include "OBSWindows.h" - +/* class OBSBasic : public OBSBasicBase { protected: virtual void file_newOnMenuSelection(wxCommandEvent& event); @@ -42,3 +42,4 @@ protected: public: inline OBSBasic() : OBSBasicBase(NULL) {} }; +*/ \ No newline at end of file diff --git a/obs/window-subclass.cpp b/obs/window-subclass.cpp index 77fa43484..08d0e80eb 100644 --- a/obs/window-subclass.cpp +++ b/obs/window-subclass.cpp @@ -64,6 +64,19 @@ WindowSubclass::WindowSubclass(wxWindow* parent, wxWindowID id, #endif } +ListCtrlFixed::ListCtrlFixed(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) + : wxListCtrl(parent, id, pos, size, style, validator, name) +{ + m_bestSizeCache.Set(wxDefaultCoord, wxDefaultCoord); + SetInitialSize(size); +} + wxSize ListCtrlFixed::DoGetBestClientSize() const { if (!InReportView()) diff --git a/obs/window-subclass.hpp b/obs/window-subclass.hpp index d578273df..ddee303c6 100644 --- a/obs/window-subclass.hpp +++ b/obs/window-subclass.hpp @@ -36,17 +36,13 @@ public: */ class ListCtrlFixed : public wxListCtrl { public: - inline ListCtrlFixed(wxWindow *parent, + ListCtrlFixed(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxLC_ICON, const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxListCtrlNameStr) - : wxListCtrl(parent, id, pos, size, style, validator, name) - { - } + const wxString& name = wxListCtrlNameStr); -protected: virtual wxSize DoGetBestClientSize() const; }; diff --git a/plugins/obs-outputs/obs-outputs.c b/plugins/obs-outputs/obs-outputs.c new file mode 100644 index 000000000..5cc83cda1 --- /dev/null +++ b/plugins/obs-outputs/obs-outputs.c @@ -0,0 +1,11 @@ +#include "obs-outputs.h" + +static const char *outputs[1] = {"rtmp_stream"}; + +const char *enum_outputs(size_t idx) +{ + if (idx < sizeof(outputs)/sizeof(const char*)) + return NULL; + + return outputs[idx]; +} diff --git a/plugins/obs-outputs/obs-outputs.h b/plugins/obs-outputs/obs-outputs.h new file mode 100644 index 000000000..4e24817cf --- /dev/null +++ b/plugins/obs-outputs/obs-outputs.h @@ -0,0 +1,5 @@ +#pragma once + +#include "util/c99defs.h" + +EXPORT const char *enum_outputs(size_t idx); diff --git a/plugins/obs-outputs/obs-stream.c b/plugins/obs-outputs/obs-stream.c new file mode 100644 index 000000000..cc0cf383d --- /dev/null +++ b/plugins/obs-outputs/obs-stream.c @@ -0,0 +1,28 @@ +#include "obs-stream.h" + +void *rtmp_stream_getname(const char *locale) +{ + /* TODO: locale stuff */ + return "RTMP Stream"; +} + +void *rtmp_stream_create(const char *settings, obs_output_t output) +{ + +} + +void *rtmp_stream_destroy(void *data) +{ +} + +void *rtmp_stream_update(void *data, const char *settings) +{ +} + +void rtmp_stream_start(void *data) +{ +} + +void rtmp_stream_stop(void *data) +{ +} diff --git a/plugins/obs-outputs/obs-stream.h b/plugins/obs-outputs/obs-stream.h new file mode 100644 index 000000000..6e0ef2375 --- /dev/null +++ b/plugins/obs-outputs/obs-stream.h @@ -0,0 +1,15 @@ +#pragma once + +#include "util/c99defs.h" +#include "obs.h" + +struct rtmp_stream { + +}; + +EXPORT void *rtmp_stream_getname(const char *locale); +EXPORT void *rtmp_stream_create(const char *settings, obs_output_t output); +EXPORT void *rtmp_stream_destroy(void *data); +EXPORT void *rtmp_stream_update(void *data, const char *settings); +EXPORT void rtmp_stream_start(void *data); +EXPORT void rtmp_stream_stop(void *data); diff --git a/test/test-input/test-filter.c b/test/test-input/test-filter.c index ae40af3bc..38a519d96 100644 --- a/test/test-input/test-filter.c +++ b/test/test-input/test-filter.c @@ -1,5 +1,10 @@ #include "test-filter.h" +const char *test_getname(const char *locale) +{ + return "Test"; +} + struct test_filter *test_create(const char *settings, obs_source_t source) { struct test_filter *tf = bmalloc(sizeof(struct test_filter)); diff --git a/test/test-input/test-filter.h b/test/test-input/test-filter.h index 3f6d94851..66d8ac10e 100644 --- a/test/test-input/test-filter.h +++ b/test/test-input/test-filter.h @@ -12,6 +12,8 @@ struct test_filter { texrender_t texrender; }; +EXPORT const char *test_getname(const char *locale); + EXPORT struct test_filter *test_create(const char *settings, obs_source_t source); EXPORT void test_destroy(struct test_filter *rt); EXPORT uint32_t test_get_output_flags(struct test_filter *rt); diff --git a/test/test-input/test-input-exports.h b/test/test-input/test-input-exports.h index 280b33a6d..9773162f2 100644 --- a/test/test-input/test-input-exports.h +++ b/test/test-input/test-input-exports.h @@ -6,6 +6,7 @@ extern "C" { #endif +EXPORT uint32_t module_version(uint32_t in_version); EXPORT bool enum_inputs(size_t idx, const char **name); EXPORT bool enum_filters(size_t idx, const char **name); diff --git a/test/test-input/test-input.c b/test/test-input/test-input.c index 9d7aaf16b..715182186 100644 --- a/test/test-input/test-input.c +++ b/test/test-input/test-input.c @@ -1,8 +1,14 @@ +#include "obs.h" #include "test-input-exports.h" const char *inputs[] = {"random"}; const char *filters[] = {"test"}; +uint32_t module_version(uint32_t in_version) +{ + return LIBOBS_API_VER; +} + bool enum_inputs(size_t idx, const char **name) { if (idx >= (sizeof(inputs)/sizeof(const char*))) diff --git a/test/test-input/test-random.c b/test/test-input/test-random.c index e007825f5..a4d3e14c5 100644 --- a/test/test-input/test-random.c +++ b/test/test-input/test-random.c @@ -1,6 +1,11 @@ #include #include "test-random.h" +const char *random_getname(const char *locale) +{ + return "Random;"; +} + struct random_tex *random_create(const char *settings, obs_source_t source) { struct random_tex *rt = bmalloc(sizeof(struct random_tex)); diff --git a/test/test-input/test-random.h b/test/test-input/test-random.h index d02afdb69..5b09a0572 100644 --- a/test/test-input/test-random.h +++ b/test/test-input/test-random.h @@ -11,6 +11,8 @@ struct random_tex { effect_t whatever; }; +EXPORT const char *random_getname(const char *locale); + EXPORT struct random_tex *random_create(const char *settings, obs_source_t source); EXPORT void random_destroy(struct random_tex *rt); EXPORT uint32_t random_get_output_flags(struct random_tex *rt);