|
@@ -14,6 +14,9 @@
|
|
|
struct image_source {
|
|
struct image_source {
|
|
|
obs_source_t *source;
|
|
obs_source_t *source;
|
|
|
|
|
|
|
|
|
|
+ char *file;
|
|
|
|
|
+ bool persistent;
|
|
|
|
|
+
|
|
|
gs_texture_t *tex;
|
|
gs_texture_t *tex;
|
|
|
uint32_t cx;
|
|
uint32_t cx;
|
|
|
uint32_t cy;
|
|
uint32_t cy;
|
|
@@ -24,19 +27,19 @@ static const char *image_source_get_name(void)
|
|
|
return obs_module_text("ImageInput");
|
|
return obs_module_text("ImageInput");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static void image_source_update(void *data, obs_data_t *settings)
|
|
|
|
|
|
|
+static void image_source_load(struct image_source *context)
|
|
|
{
|
|
{
|
|
|
- struct image_source *context = data;
|
|
|
|
|
- const char *file = obs_data_get_string(settings, "file");
|
|
|
|
|
|
|
+ char *file = context->file;
|
|
|
|
|
|
|
|
obs_enter_graphics();
|
|
obs_enter_graphics();
|
|
|
|
|
|
|
|
- if (context->tex) {
|
|
|
|
|
|
|
+ if (context->tex)
|
|
|
gs_texture_destroy(context->tex);
|
|
gs_texture_destroy(context->tex);
|
|
|
- context->tex = NULL;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ context->tex = NULL;
|
|
|
|
|
|
|
|
if (file && *file) {
|
|
if (file && *file) {
|
|
|
|
|
+ debug("loading texture '%s'", file);
|
|
|
|
|
+
|
|
|
context->tex = gs_texture_create_from_file(file);
|
|
context->tex = gs_texture_create_from_file(file);
|
|
|
if (context->tex) {
|
|
if (context->tex) {
|
|
|
context->cx = gs_texture_get_width(context->tex);
|
|
context->cx = gs_texture_get_width(context->tex);
|
|
@@ -51,6 +54,56 @@ static void image_source_update(void *data, obs_data_t *settings)
|
|
|
obs_leave_graphics();
|
|
obs_leave_graphics();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void image_source_unload(struct image_source *context)
|
|
|
|
|
+{
|
|
|
|
|
+ obs_enter_graphics();
|
|
|
|
|
+
|
|
|
|
|
+ if (context->tex)
|
|
|
|
|
+ gs_texture_destroy(context->tex);
|
|
|
|
|
+ context->tex = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ obs_leave_graphics();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void image_source_update(void *data, obs_data_t *settings)
|
|
|
|
|
+{
|
|
|
|
|
+ struct image_source *context = data;
|
|
|
|
|
+ const char *file = obs_data_get_string(settings, "file");
|
|
|
|
|
+ const bool unload = obs_data_get_bool(settings, "unload");
|
|
|
|
|
+
|
|
|
|
|
+ if (context->file)
|
|
|
|
|
+ bfree(context->file);
|
|
|
|
|
+ context->file = bstrdup(file);
|
|
|
|
|
+ context->persistent = !unload;
|
|
|
|
|
+
|
|
|
|
|
+ /* Load the image if the source is persistent or showing */
|
|
|
|
|
+ if (context->persistent || obs_source_showing(context->source))
|
|
|
|
|
+ image_source_load(data);
|
|
|
|
|
+ else
|
|
|
|
|
+ image_source_unload(data);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void image_source_defaults(obs_data_t *settings)
|
|
|
|
|
+{
|
|
|
|
|
+ obs_data_set_default_bool(settings, "unload", true);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void image_source_show(void *data)
|
|
|
|
|
+{
|
|
|
|
|
+ struct image_source *context = data;
|
|
|
|
|
+
|
|
|
|
|
+ if (!context->persistent)
|
|
|
|
|
+ image_source_load(context);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void image_source_hide(void *data)
|
|
|
|
|
+{
|
|
|
|
|
+ struct image_source *context = data;
|
|
|
|
|
+
|
|
|
|
|
+ if (!context->persistent)
|
|
|
|
|
+ image_source_unload(context);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void *image_source_create(obs_data_t *settings, obs_source_t *source)
|
|
static void *image_source_create(obs_data_t *settings, obs_source_t *source)
|
|
|
{
|
|
{
|
|
|
struct image_source *context = bzalloc(sizeof(struct image_source));
|
|
struct image_source *context = bzalloc(sizeof(struct image_source));
|
|
@@ -64,10 +117,10 @@ static void image_source_destroy(void *data)
|
|
|
{
|
|
{
|
|
|
struct image_source *context = data;
|
|
struct image_source *context = data;
|
|
|
|
|
|
|
|
- obs_enter_graphics();
|
|
|
|
|
- gs_texture_destroy(context->tex);
|
|
|
|
|
- obs_leave_graphics();
|
|
|
|
|
|
|
+ image_source_unload(context);
|
|
|
|
|
|
|
|
|
|
+ if (context->file)
|
|
|
|
|
+ bfree(context->file);
|
|
|
bfree(context);
|
|
bfree(context);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -86,6 +139,7 @@ static uint32_t image_source_getheight(void *data)
|
|
|
static void image_source_render(void *data, gs_effect_t *effect)
|
|
static void image_source_render(void *data, gs_effect_t *effect)
|
|
|
{
|
|
{
|
|
|
struct image_source *context = data;
|
|
struct image_source *context = data;
|
|
|
|
|
+
|
|
|
if (!context->tex)
|
|
if (!context->tex)
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
@@ -112,6 +166,8 @@ static obs_properties_t *image_source_properties(void *unused)
|
|
|
obs_properties_add_path(props,
|
|
obs_properties_add_path(props,
|
|
|
"file", obs_module_text("File"),
|
|
"file", obs_module_text("File"),
|
|
|
OBS_PATH_FILE, image_filter, NULL);
|
|
OBS_PATH_FILE, image_filter, NULL);
|
|
|
|
|
+ obs_properties_add_bool(props,
|
|
|
|
|
+ "unload", obs_module_text("UnloadWhenNotShowing"));
|
|
|
|
|
|
|
|
return props;
|
|
return props;
|
|
|
}
|
|
}
|
|
@@ -124,6 +180,9 @@ static struct obs_source_info image_source_info = {
|
|
|
.create = image_source_create,
|
|
.create = image_source_create,
|
|
|
.destroy = image_source_destroy,
|
|
.destroy = image_source_destroy,
|
|
|
.update = image_source_update,
|
|
.update = image_source_update,
|
|
|
|
|
+ .get_defaults = image_source_defaults,
|
|
|
|
|
+ .show = image_source_show,
|
|
|
|
|
+ .hide = image_source_hide,
|
|
|
.get_width = image_source_getwidth,
|
|
.get_width = image_source_getwidth,
|
|
|
.get_height = image_source_getheight,
|
|
.get_height = image_source_getheight,
|
|
|
.video_render = image_source_render,
|
|
.video_render = image_source_render,
|