aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend_freeimage.c47
-rw-r--r--src/imv.c47
-rw-r--r--src/source.h20
3 files changed, 95 insertions, 19 deletions
diff --git a/src/backend_freeimage.c b/src/backend_freeimage.c
index a0908c5..65a768e 100644
--- a/src/backend_freeimage.c
+++ b/src/backend_freeimage.c
@@ -7,7 +7,6 @@
#include <string.h>
#include <FreeImage.h>
-#include <SDL2/SDL.h>
struct private {
FREE_IMAGE_FORMAT format;
@@ -64,22 +63,36 @@ static struct imv_bitmap *to_imv_bitmap(FIBITMAP *in_bmp)
static void report_error(struct imv_source *src)
{
- SDL_Event event;
- SDL_zero(event);
- event.type = src->error_event_id;
- event.user.data1 = strdup(src->name);
- SDL_PushEvent(&event);
+ if (!src->callback) {
+ fprintf(stderr, "imv_source(%s) has no callback configured. "
+ "Discarding error.\n", src->name);
+ return;
+ }
+
+ struct imv_source_message msg;
+ msg.source = src;
+ msg.user_data = src->user_data;
+ msg.bitmap = NULL;
+ msg.error = "Internal error";
+
+ src->callback(&msg);
}
-static void send_bitmap(struct imv_source *src, FIBITMAP *fibitmap, int is_new_image)
+static void send_bitmap(struct imv_source *src, FIBITMAP *fibitmap)
{
- SDL_Event event;
- SDL_zero(event);
- event.type = src->image_event_id;
- event.user.data1 = to_imv_bitmap(fibitmap);
- event.user.code = is_new_image;
- FreeImage_Unload(fibitmap);
- SDL_PushEvent(&event);
+ if (!src->callback) {
+ fprintf(stderr, "imv_source(%s) has no callback configured. "
+ "Discarding result.\n", src->name);
+ return;
+ }
+
+ struct imv_source_message msg;
+ msg.source = src;
+ msg.user_data = src->user_data;
+ msg.bitmap = to_imv_bitmap(fibitmap);
+ msg.error = NULL;
+
+ src->callback(&msg);
}
static void first_frame(struct imv_source *src)
@@ -128,7 +141,7 @@ static void first_frame(struct imv_source *src)
src->width = FreeImage_GetWidth(bmp);
src->height = FreeImage_GetWidth(bmp);
- send_bitmap(src, bmp, 1 /* is new image */);
+ send_bitmap(src, bmp);
private->last_frame = bmp;
}
@@ -136,7 +149,7 @@ static void next_frame(struct imv_source *src)
{
struct private *private = src->private;
if (src->num_frames == 1) {
- send_bitmap(private->last_frame, 0 /* not a new image */);
+ send_bitmap(src, private->last_frame);
return;
}
@@ -166,6 +179,8 @@ static enum backend_result open_path(const char *path, struct imv_source **src)
source->time_passed = &time_passed;
source->time_left = &time_left;
source->free = &source_free;
+ source->callback = NULL;
+ source->user_data = NULL;
source->private = private;
*src = source;
diff --git a/src/imv.c b/src/imv.c
index 8d01b35..a90082e 100644
--- a/src/imv.c
+++ b/src/imv.c
@@ -79,6 +79,7 @@ struct imv {
struct imv_navigator *navigator;
struct imv_backend *backend;
struct imv_source *source;
+ struct imv_source *last_source;
struct imv_commands *commands;
struct imv_image *image;
struct imv_viewport *view;
@@ -217,6 +218,40 @@ static bool add_bind(struct imv *imv, const char *keys, const char *commands)
return success;
}
+static void source_callback(struct imv_source_message *msg)
+{
+ struct imv *imv = msg->user_data;
+ if (msg->source != imv->source) {
+ /* We received a message from an old source, tidy up contents
+ * as required, but ignore it.
+ */
+ if (msg->bitmap) {
+ imv_bitmap_free(msg->bitmap);
+ }
+ return;
+ }
+
+ SDL_Event event;
+ SDL_zero(event);
+
+ if (msg->bitmap) {
+ event.type = imv->events.NEW_IMAGE;
+ event.user.data1 = msg->bitmap;
+
+ /* Keep track of the last source to send us a bitmap in order to detect
+ * when we're getting a new image, as opposed to a new frame from the
+ * same image.
+ */
+ event.user.code = msg->source != imv->last_source;
+ imv->last_source = msg->source;
+ } else {
+ event.type = imv->events.BAD_IMAGE;
+ event.user.data1 = strdup(msg->error);
+ }
+
+ SDL_PushEvent(&event);
+}
+
struct imv *imv_create(void)
{
struct imv *imv = malloc(sizeof(struct imv));
@@ -243,6 +278,7 @@ struct imv *imv_create(void)
imv->navigator = imv_navigator_create();
imv->backend = imv_backend_freeimage();
imv->source = NULL;
+ imv->last_source = NULL;
imv->commands = imv_commands_create();
imv->stdin_image_data = NULL;
imv->stdin_image_data_len = 0;
@@ -642,10 +678,15 @@ int imv_run(struct imv *imv)
const char *current_path = imv_navigator_selection(imv->navigator);
/* check we got a path back */
if(strcmp("", current_path)) {
- enum backend_result result = imv->backend->open_path(current_path, &imv->source);
+ struct imv_source *new_source;
+ enum backend_result result = imv->backend->open_path(current_path, &new_source);
if (result == BACKEND_SUCCESS) {
- imv->source->image_event_id = imv->events.NEW_IMAGE;
- imv->source->error_event_id = imv->events.BAD_IMAGE;
+ if (imv->source) {
+ imv->source->free(imv->source);
+ }
+ imv->source = new_source;
+ imv->source->callback = &source_callback;
+ imv->source->user_data = imv;
imv->source->load_first_frame(imv->source);
}
diff --git a/src/source.h b/src/source.h
index 6f051e3..80b1e81 100644
--- a/src/source.h
+++ b/src/source.h
@@ -4,6 +4,20 @@
#include <stdbool.h>
#include "bitmap.h"
+struct imv_source_message {
+ /* Pointer to sender of message */
+ struct imv_source *source;
+
+ /* User-supplied pointer */
+ void *user_data;
+
+ /* Receiver is responsible for destroying bitmap */
+ struct imv_bitmap *bitmap;
+
+ /* Error message if bitmap was NULL */
+ const char *error;
+};
+
/* Generic source of one or more bitmaps. Essentially a single image file */
struct imv_source {
/* usually the path of the image this is the source of */
@@ -41,6 +55,12 @@ struct imv_source {
*/
void (*free)(struct imv_source *src);
+ /* User-specified callback for returning messages */
+ void (*callback)(struct imv_source_message *message);
+
+ /* User-specified pointer, included in returned messages */
+ void *user_data;
+
/* Implementation private data */
void *private;
};