static char get_loader(lopt * opt, ImlibLoader ** loader) { union id3_field *field; char const *data; char ext[EXT_LEN + 2]; ext[EXT_LEN + 1] = '\0'; ext[0] = '.'; field = id3_frame_field(id3_tag_get_frame(opt->ctx->tag, opt->index - 1), 1); data = (char const *)id3_field_getlatin1(field); if (!data) { fprintf(stderr, "No mime type data found for image frame\n"); return 0; } if (strncasecmp(data, "image/", 6)) { if (!strcmp(data, "-->")) { *loader = NULL; return 1; } fprintf(stderr, "Picture frame with unknown mime-type \'%s\' found\n", data); return 0; } strncpy(ext + 1, data + 6, EXT_LEN); if (!(*loader = __imlib_FindBestLoaderForFile(ext, 0))) { fprintf(stderr, "No loader found for extension %s\n", ext); return 0; } return 1; }
char load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity, char immediate_load) { ImlibLoader *loader; lopt opt; int res; struct stat st; assert(im); if (stat(im->real_file, &st) < 0) return 0; if (!get_options(&opt, im)) return 0; if (!get_loader(&opt, &loader)) goto fail_context; if (loader) { char *ofile, tmp[] = "/tmp/imlib2_loader_id3-XXXXXX"; int dest; if ((dest = mkstemp(tmp)) < 0) { fprintf(stderr, "Unable to create a temporary file\n"); goto fail_context; } res = extract_pic(id3_tag_get_frame(opt.ctx->tag, opt.index - 1), dest); close(dest); if (!res) { unlink(tmp); goto fail_context; } ofile = im->real_file; im->real_file = strdup(tmp); res = loader->load(im, progress, progress_granularity, immediate_load); free(im->real_file); im->real_file = ofile; unlink(tmp); } else { /* The tag actually provides a image url rather than image data. * Practically, dunno if such a tag exists on earth :) * Here's the code anyway... */ union id3_field *field; id3_length_t length; char const *data; char *url, *file, *ofile; field = id3_frame_field (id3_tag_get_frame(opt.ctx->tag, opt.index - 1), 4); data = (char const *)id3_field_getbinarydata(field, &length); if (!data || !length) { fprintf(stderr, "No link image URL present\n"); goto fail_context; } url = (char *)malloc((length + 1) * sizeof(char)); strncpy(url, data, length); url[length] = '\0'; file = (strncmp(url, "file://", 7) ? url : url + 7); if (!(loader = __imlib_FindBestLoaderForFile(file, 0))) { fprintf(stderr, "No loader found for file %s\n", file); free(url); goto fail_context; } ofile = im->real_file; im->real_file = file; res = loader->load(im, progress, progress_granularity, immediate_load); if (!im->loader) __imlib_AttachTag(im, "id3-link-url", 0, url, destructor_data); else free(url); im->real_file = ofile; } if (!im->loader) write_tags(im, &opt); #ifdef DEBUG if (!im->loader) { ImlibImageTag *cur = im->tags; fprintf(stderr, "Tags for file %s:\n", im->file); while (cur) { fprintf(stderr, "\t%s: (%d) %s\n", cur->key, cur->val, (char *)cur->data); cur = cur->next; } } #endif context_delref(opt.ctx); return res; fail_context: context_delref(opt.ctx); return 0; }
ImlibImage * __imlib_LoadImage(const char *file, ImlibProgressFunction progress, char progress_granularity, char immediate_load, char dont_cache, ImlibLoadError * er) { ImlibImage *im; ImlibLoader *best_loader; char loader_ret = 0; if (!file) return NULL; if (file[0] == 0) return NULL; /* see if we already have the image cached */ im = __imlib_FindCachedImage(file); /* if we found a cached image and we shoudl always check that it is */ /* accurate to the disk conents if they changed since we last loaded */ /* and that it is still a valid image */ if ((im) && (IMAGE_IS_VALID(im))) { if (IMAGE_ALWAYS_CHECK_DISK(im)) { time_t current_modified_time; current_modified_time = __imlib_FileModDate(file); /* if the file on disk is newer than the cached one */ if (current_modified_time > im->moddate) { /* invalidate image */ SET_FLAG(im->flags, F_INVALID); } else { /* image is ok to re-use - program is just being stupid loading */ /* the same data twice */ im->references++; return im; } } else { im->references++; return im; } } /* either image in cache is invalid or we dont even have it in cache */ /* so produce a new one and load an image into that */ im = __imlib_ProduceImage(); im->file = strdup(file); if (__imlib_IsRealFile(file)) { im->real_file = strdup(im->file); im->key = NULL; } else { im->real_file = __imlib_FileRealFile(file); im->key = __imlib_FileKey(file); } im->moddate = __imlib_FileModDate(file); /* ok - just check all our loaders are up to date */ __imlib_RescanLoaders(); /* take a guess by extension on the best loader to use */ best_loader = __imlib_FindBestLoaderForFile(im->real_file, 0); errno = 0; if (best_loader) loader_ret = best_loader->load(im, progress, progress_granularity, immediate_load); /* width is still 0 - the loader didnt manage to do anything */ if (im->w == 0) { ImlibLoader *l, *previous_l = NULL; errno = 0; l = loaders; /* run through all loaders and try load until one succeeds */ while ((l) && (im->w == 0)) { /* if its not the best loader that already failed - try load */ if (l != best_loader) loader_ret = l->load(im, progress, progress_granularity, immediate_load); /* if it failed - advance */ if (im->w == 0) { previous_l = l; l = l->next; } } /* if we have a loader then its the loader that succeeded */ /* move the successful loader to the head of the list */ /* as long as it's not already at the head of the list */ if ((l) && (previous_l)) { im->loader = l; previous_l->next = l->next; l->next = loaders; loaders = l; } if (im->w > 0) im->loader = l; } else im->loader = best_loader; /* all loaders have been tried and they all failed. free the skeleton */ /* image struct we had and return NULL */ if (im->w == 0) { /* if the caller wants an error return */ if (er) { /* set to a default fo no error */ *er = IMLIB_LOAD_ERROR_NONE; /* if the errno is set */ if (errno != 0) { /* default to unknown error */ *er = IMLIB_LOAD_ERROR_UNKNOWN; /* standrad fopen() type errors translated */ if (errno == EEXIST) *er = IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST; else if (errno == EISDIR) *er = IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY; else if (errno == EISDIR) *er = IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY; else if (errno == EACCES) *er = IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ; else if (errno == ENAMETOOLONG) *er = IMLIB_LOAD_ERROR_PATH_TOO_LONG; else if (errno == ENOENT) *er = IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT; else if (errno == ENOTDIR) *er = IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY; else if (errno == EFAULT) *er = IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE; else if (errno == ELOOP) *er = IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS; else if (errno == ENOMEM) *er = IMLIB_LOAD_ERROR_OUT_OF_MEMORY; else if (errno == EMFILE) *er = IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS; if (*er != IMLIB_LOAD_ERROR_UNKNOWN) { /* free the stuct we created */ __imlib_ConsumeImage(im); return NULL; } } errno = 0; } __imlib_ConsumeImage(im); return NULL; } /* the load succeeded - make sure the image is referenced then add */ /* it to our cache if dont_cache isn't set */ im->references = 1; if (loader_ret == 2) dont_cache = 1; if (!dont_cache) __imlib_AddImageToCache(im); else SET_FLAG(im->flags, F_UNCACHEABLE); return im; }