diff options
Diffstat (limited to 'src/loader.c')
-rw-r--r-- | src/loader.c | 116 |
1 files changed, 79 insertions, 37 deletions
diff --git a/src/loader.c b/src/loader.c index 883e857..1250289 100644 --- a/src/loader.c +++ b/src/loader.c @@ -17,10 +17,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "loader.h" #include "texture.h" +#include <limits.h> #include <stdlib.h> #include <pthread.h> #include <signal.h> +static void block_usr1_signal(void); +static int is_thread_cancelled(void); +static void *bg_new_img(void *data); +static void *bg_next_frame(void *data); +static void error_occurred(struct imv_loader *ldr); + static void block_usr1_signal(void) { sigset_t sigmask; @@ -61,10 +68,8 @@ void imv_destroy_loader(struct imv_loader *ldr) } } -static void *imv_loader_bg_new_img(void *data); -static void *imv_loader_bg_next_frame(void *data); - -void imv_loader_load_path(struct imv_loader *ldr, const char *path) +void imv_loader_load(struct imv_loader *ldr, const char *path, + const void *buffer, const size_t buffer_size) { /* cancel existing thread if already running */ if(ldr->bg_thread) { @@ -77,7 +82,13 @@ void imv_loader_load_path(struct imv_loader *ldr, const char *path) free(ldr->path); } ldr->path = strdup(path); - pthread_create(&ldr->bg_thread, NULL, &imv_loader_bg_new_img, ldr); + if (strncmp(path, "-", 2) == 0) { + ldr->buffer = (BYTE *)buffer; + ldr->buffer_size = buffer_size; + } else if (ldr->fi_buffer != NULL) { + FreeImage_CloseMemory(ldr->fi_buffer); + } + pthread_create(&ldr->bg_thread, NULL, &bg_new_img, ldr); pthread_mutex_unlock(&ldr->lock); } @@ -120,7 +131,7 @@ void imv_loader_load_next_frame(struct imv_loader *ldr) } /* kick off a new thread */ - pthread_create(&ldr->bg_thread, NULL, &imv_loader_bg_next_frame, ldr); + pthread_create(&ldr->bg_thread, NULL, &bg_next_frame, ldr); } void imv_loader_time_passed(struct imv_loader *ldr, double dt) @@ -140,33 +151,38 @@ void imv_loader_time_passed(struct imv_loader *ldr, double dt) } } -static void imv_loader_error_occurred(struct imv_loader *ldr) -{ - pthread_mutex_lock(&ldr->lock); - if(ldr->out_err) { - free(ldr->out_err); - } - ldr->out_err = strdup(ldr->path); - pthread_mutex_unlock(&ldr->lock); -} - -static void *imv_loader_bg_new_img(void *data) +static void *bg_new_img(void *data) { /* so we can poll for it */ block_usr1_signal(); struct imv_loader *ldr = data; + char path[PATH_MAX] = "-"; pthread_mutex_lock(&ldr->lock); - char *path = strdup(ldr->path); + int from_stdin = !strncmp(path, ldr->path, 2); + if(!from_stdin) { + (void)snprintf(path, PATH_MAX, "%s", ldr->path); + } pthread_mutex_unlock(&ldr->lock); - FREE_IMAGE_FORMAT fmt = FreeImage_GetFileType(path, 0); - + FREE_IMAGE_FORMAT fmt; + if (from_stdin) { + pthread_mutex_lock(&ldr->lock); + ldr->fi_buffer = FreeImage_OpenMemory(ldr->buffer, ldr->buffer_size); + fmt = FreeImage_GetFileTypeFromMemory(ldr->fi_buffer, 0); + pthread_mutex_unlock(&ldr->lock); + } else { + fmt = FreeImage_GetFileType(path, 0); + } if(fmt == FIF_UNKNOWN) { - imv_loader_error_occurred(ldr); - free(path); - return 0; + if (from_stdin) { + pthread_mutex_lock(&ldr->lock); + FreeImage_CloseMemory(ldr->fi_buffer); + pthread_mutex_unlock(&ldr->lock); + } + error_occurred(ldr); + return NULL; } int num_frames = 1; @@ -176,15 +192,21 @@ static void *imv_loader_bg_new_img(void *data) int raw_frame_time = 100; /* default to 100 */ if(fmt == FIF_GIF) { - mbmp = FreeImage_OpenMultiBitmap(FIF_GIF, path, + if(from_stdin) { + pthread_mutex_lock(&ldr->lock); + mbmp = FreeImage_LoadMultiBitmapFromMemory(FIF_GIF, ldr->fi_buffer, + GIF_LOAD256); + pthread_mutex_unlock(&ldr->lock); + } else { + mbmp = FreeImage_OpenMultiBitmap(FIF_GIF, path, /* don't create file */ 0, /* read only */ 1, /* keep in memory */ 1, /* flags */ GIF_LOAD256); - free(path); + } if(!mbmp) { - imv_loader_error_occurred(ldr); - return 0; + error_occurred(ldr); + return NULL; } num_frames = FreeImage_GetPageCount(mbmp); @@ -205,17 +227,27 @@ static void *imv_loader_bg_new_img(void *data) } else { /* Future TODO: If we load image line-by-line we could stop loading large * ones before wasting much more time/memory on them. */ - FIBITMAP *image = FreeImage_Load(fmt, path, 0); - free(path); + FIBITMAP *image; + if(from_stdin) { + pthread_mutex_lock(&ldr->lock); + image = FreeImage_LoadFromMemory(fmt, ldr->fi_buffer, 0); + pthread_mutex_unlock(&ldr->lock); + } else { + image = FreeImage_Load(fmt, path, 0); + } if(!image) { - imv_loader_error_occurred(ldr); - return 0; + error_occurred(ldr); + pthread_mutex_lock(&ldr->lock); + FreeImage_CloseMemory(ldr->fi_buffer); + ldr->fi_buffer = NULL; + pthread_mutex_unlock(&ldr->lock); + return NULL; } /* Check for cancellation before we convert pixel format */ if(is_thread_cancelled()) { FreeImage_Unload(image); - return 0; + return NULL; } width = FreeImage_GetWidth(bmp); @@ -236,7 +268,7 @@ static void *imv_loader_bg_new_img(void *data) FreeImage_Unload(bmp); } pthread_mutex_unlock(&ldr->lock); - return 0; + return NULL; } if(ldr->mbmp) { @@ -262,10 +294,10 @@ static void *imv_loader_bg_new_img(void *data) ldr->frame_time = (double)raw_frame_time * 0.0001; pthread_mutex_unlock(&ldr->lock); - return 0; + return NULL; } -static void *imv_loader_bg_next_frame(void *data) +static void *bg_next_frame(void *data) { struct imv_loader *ldr = data; @@ -273,7 +305,7 @@ static void *imv_loader_bg_next_frame(void *data) int num_frames = ldr->num_frames; if(num_frames < 2) { pthread_mutex_unlock(&ldr->lock); - return 0; + return NULL; } FITAG *tag = NULL; @@ -371,5 +403,15 @@ static void *imv_loader_bg_next_frame(void *data) ldr->out_is_new_image = 0; pthread_mutex_unlock(&ldr->lock); - return 0; + return NULL; +} + +static void error_occurred(struct imv_loader *ldr) +{ + pthread_mutex_lock(&ldr->lock); + if(ldr->out_err) { + free(ldr->out_err); + } + ldr->out_err = strdup(ldr->path); + pthread_mutex_unlock(&ldr->lock); } |