diff options
Diffstat (limited to 'src/modules/loaders/loader_id3.c')
-rw-r--r-- | src/modules/loaders/loader_id3.c | 974 |
1 files changed, 517 insertions, 457 deletions
diff --git a/src/modules/loaders/loader_id3.c b/src/modules/loaders/loader_id3.c index 5318748..2b3ccb1 100644 --- a/src/modules/loaders/loader_id3.c +++ b/src/modules/loaders/loader_id3.c @@ -8,544 +8,604 @@ #include <id3tag.h> #if ! defined (__STDC_VERSION__) || __STDC_VERSION__ < 199901L -# if __GNUC__ >= 2 -# define inline __inline__ -# else -# define inline -# endif +#if __GNUC__ >= 2 +#define inline __inline__ +#else +#define inline +#endif #endif #ifdef __GNUC__ -# define UNLIKELY(exp) __builtin_expect ((exp), 0) +#define UNLIKELY(exp) __builtin_expect ((exp), 0) #else -# define UNLIKELY(exp) (exp) +#define UNLIKELY(exp) (exp) #endif -typedef struct context -{ - int id; - char* filename; - struct id3_tag* tag; - int refcount; - struct context* next; +typedef struct context { + int id; + char *filename; + struct id3_tag *tag; + int refcount; + struct context *next; } context; -static context* id3_ctxs = NULL; +static context *id3_ctxs = NULL; -static inline struct id3_frame* -id3_tag_get_frame (struct id3_tag* tag, size_t index) +static inline struct id3_frame * +id3_tag_get_frame(struct id3_tag *tag, size_t index) { - return tag->frames[index]; + return tag->frames[index]; } -static inline size_t id3_tag_get_numframes (struct id3_tag* tag) +static inline size_t +id3_tag_get_numframes(struct id3_tag *tag) { - return tag->nframes; + return tag->nframes; } -static inline char const* id3_frame_id (struct id3_frame* frame) +static inline char const * +id3_frame_id(struct id3_frame *frame) { - return frame->id; + return frame->id; } -static context* context_create (const char* filename) +static context * +context_create(const char *filename) { - context* node = (context*) malloc (sizeof (context)); - context *ptr, *last; - int last_id = INT_MAX; - node->refcount = 1; - { - struct id3_file* file; - struct id3_tag* tag; - unsigned int i; - file = id3_file_open (filename, ID3_FILE_MODE_READONLY); - if (! file) { - fprintf (stderr, "Unable to open tagged file %s: %s\n", - filename, strerror (errno)); - goto fail_free; - } - tag = id3_file_tag (file); - if (! tag) { - fprintf (stderr, - "Unable to find ID3v2 tags in file %s\n", - filename); - id3_file_close (file); - goto fail_free; - } - node->tag = id3_tag_new (); - for (i = 0; i < id3_tag_get_numframes (tag); i ++) - if (! strcmp (id3_frame_id - (id3_tag_get_frame (tag, i)), "APIC")) - id3_tag_attachframe (node->tag, - id3_tag_get_frame (tag, i)); - id3_file_close (file); - } - node->filename = strdup (filename); - if (! id3_ctxs) { - node->id = 1; - node->next = NULL; - id3_ctxs = node; - return node; - } - ptr = id3_ctxs; - last = NULL; - while (UNLIKELY (ptr && (ptr->id + 1) >= last_id)) { - last_id = ptr->id; - last = ptr; - ptr = ptr->next; - } - /* Paranoid! this can occur only if there are INT_MAX contexts :) */ - if (UNLIKELY (!ptr)) { - fprintf (stderr, "Too many open ID3 contexts\n"); - goto fail_close; - } - node->id = ptr->id + 1; - if (UNLIKELY (!!last)) { - node->next = last->next; - last->next = node; - } else { - node->next = id3_ctxs; - id3_ctxs = node; - } - return node; - -fail_close: - free (node->filename); - id3_tag_delete (node->tag); -fail_free: - free (node); - return NULL; + context *node = (context *) malloc(sizeof(context)); + context *ptr, *last; + int last_id = INT_MAX; + + node->refcount = 1; + { + struct id3_file *file; + struct id3_tag *tag; + unsigned int i; + + file = id3_file_open(filename, ID3_FILE_MODE_READONLY); + if (!file) + { + fprintf(stderr, "Unable to open tagged file %s: %s\n", + filename, strerror(errno)); + goto fail_free; + } + tag = id3_file_tag(file); + if (!tag) + { + fprintf(stderr, "Unable to find ID3v2 tags in file %s\n", filename); + id3_file_close(file); + goto fail_free; + } + node->tag = id3_tag_new(); + for (i = 0; i < id3_tag_get_numframes(tag); i++) + if (!strcmp(id3_frame_id(id3_tag_get_frame(tag, i)), "APIC")) + id3_tag_attachframe(node->tag, id3_tag_get_frame(tag, i)); + id3_file_close(file); + } + node->filename = strdup(filename); + if (!id3_ctxs) + { + node->id = 1; + node->next = NULL; + id3_ctxs = node; + return node; + } + ptr = id3_ctxs; + last = NULL; + while (UNLIKELY(ptr && (ptr->id + 1) >= last_id)) + { + last_id = ptr->id; + last = ptr; + ptr = ptr->next; + } + /* Paranoid! this can occur only if there are INT_MAX contexts :) */ + if (UNLIKELY(!ptr)) + { + fprintf(stderr, "Too many open ID3 contexts\n"); + goto fail_close; + } + node->id = ptr->id + 1; + if (UNLIKELY(! !last)) + { + node->next = last->next; + last->next = node; + } + else + { + node->next = id3_ctxs; + id3_ctxs = node; + } + return node; + + fail_close: + free(node->filename); + id3_tag_delete(node->tag); + fail_free: + free(node); + return NULL; } -static void context_destroy (context* ctx) +static void +context_destroy(context * ctx) { - id3_tag_delete (ctx->tag); - free (ctx->filename); - free (ctx); + id3_tag_delete(ctx->tag); + free(ctx->filename); + free(ctx); } -static inline void context_addref (context* ctx) +static inline void +context_addref(context * ctx) { - ctx->refcount ++; + ctx->refcount++; } -static context* context_get (int id) +static context * +context_get(int id) { - context* ptr = id3_ctxs; - while (ptr) { - if (ptr->id == id) { - context_addref (ptr); - return ptr; - } - ptr = ptr->next; - } - fprintf (stderr, "No context by handle %d found\n", id); - return NULL; + context *ptr = id3_ctxs; + + while (ptr) + { + if (ptr->id == id) + { + context_addref(ptr); + return ptr; + } + ptr = ptr->next; + } + fprintf(stderr, "No context by handle %d found\n", id); + return NULL; } -static context* context_get_by_name (const char* name) +static context * +context_get_by_name(const char *name) { - context* ptr = id3_ctxs; - while (ptr) { - if (! strcmp (name, ptr->filename)) { - context_addref (ptr); - return ptr; - } - ptr = ptr->next; - } - return NULL; + context *ptr = id3_ctxs; + + while (ptr) + { + if (!strcmp(name, ptr->filename)) + { + context_addref(ptr); + return ptr; + } + ptr = ptr->next; + } + return NULL; } -static void context_delref (context* ctx) +static void +context_delref(context * ctx) { - ctx->refcount --; - if (ctx->refcount <= 0) { - context *last = NULL, *ptr = id3_ctxs; - while (ptr) { - if (ptr == ctx) { - if (last) - last->next = ctx->next; - else - id3_ctxs = ctx->next; - context_destroy (ctx); - return; - } - last = ptr; - ptr = ptr->next; - } - } + ctx->refcount--; + if (ctx->refcount <= 0) + { + context *last = NULL, *ptr = id3_ctxs; + + while (ptr) + { + if (ptr == ctx) + { + if (last) + last->next = ctx->next; + else + id3_ctxs = ctx->next; + context_destroy(ctx); + return; + } + last = ptr; + ptr = ptr->next; + } + } } -static int str2int (char* str, int old) +static int +str2int(char *str, int old) { - long index; - errno = 0; - index = strtol (str, NULL, 10); - return ((errno || index > INT_MAX) ? old : (int)index); + long index; + + errno = 0; + index = strtol(str, NULL, 10); + return ((errno || index > INT_MAX) ? old : (int)index); } -static size_t str2uint (char* str, size_t old) +static size_t +str2uint(char *str, size_t old) { - unsigned long index; - errno = 0; - index = strtoul (str, NULL, 10); - return ((errno || index > UINT_MAX) ? old : (size_t)index); + unsigned long index; + + errno = 0; + index = strtoul(str, NULL, 10); + return ((errno || index > UINT_MAX) ? old : (size_t) index); } -static void destructor_data (ImlibImage* im, void* data) +static void +destructor_data(ImlibImage * im, void *data) { - free (data); + free(data); } -static void destructor_context (ImlibImage* im, void* data) +static void +destructor_context(ImlibImage * im, void *data) { - context_delref ((context*)data); + context_delref((context *) data); } -typedef struct lopt -{ - context* ctx; - size_t index; - int traverse; - char cache_level; +typedef struct lopt { + context *ctx; + size_t index; + int traverse; + char cache_level; } lopt; -static char get_options (lopt* opt, ImlibImage* im) +static char +get_options(lopt * opt, ImlibImage * im) { - size_t handle = 0, index = 0, traverse = 0; - context* ctx; - - if (im->key) { - char* key = strdup (im->key); - char* tok = strtok (key, ","); - traverse = 0; - while (tok) { - char* value = strchr (tok, '='); - if (! value) { - value = tok; - tok = "index"; - } else { - *value = '\0'; - value ++; - } - if (! strcasecmp (tok, "index")) - index = str2uint (value, index); - else if (! strcasecmp (tok, "context")) - handle = str2uint (value, handle); - else if (! strcasecmp (tok, "traverse")) - traverse = str2int (value, traverse); - tok = strtok (NULL, ","); - } - free (key); - } else - traverse = 1; - - if (! handle) { - ImlibImageTag* htag = __imlib_GetTag (im, "context"); - if (htag && htag->val) - handle = htag->val; - } - if (handle) - ctx = context_get (handle); - else if (! (ctx = context_get_by_name (im->real_file)) && - ! (ctx = context_create (im->real_file))) - return 0; - - if (! index) { - ImlibImageTag* htag = __imlib_GetTag (im, "index"); - if (htag && htag->val) - index = htag->val; - } - if (index < 0 || index > id3_tag_get_numframes (ctx->tag) || - (index == 0 && id3_tag_get_numframes (ctx->tag) < 1)) { - if (index) - fprintf (stderr, "No picture frame # %d found\n", index); - context_delref (ctx); - return 0; - } - if (! index) - index = 1; - - opt->ctx = ctx; - opt->index = index; - opt->traverse = traverse; - opt->cache_level = (id3_tag_get_numframes (ctx->tag) > 1 ? 1 : 0); - return 1; + size_t handle = 0, index = 0, traverse = 0; + context *ctx; + + if (im->key) + { + char *key = strdup(im->key); + char *tok = strtok(key, ","); + + traverse = 0; + while (tok) + { + char *value = strchr(tok, '='); + + if (!value) + { + value = tok; + tok = "index"; + } + else + { + *value = '\0'; + value++; + } + if (!strcasecmp(tok, "index")) + index = str2uint(value, index); + else if (!strcasecmp(tok, "context")) + handle = str2uint(value, handle); + else if (!strcasecmp(tok, "traverse")) + traverse = str2int(value, traverse); + tok = strtok(NULL, ","); + } + free(key); + } + else + traverse = 1; + + if (!handle) + { + ImlibImageTag *htag = __imlib_GetTag(im, "context"); + + if (htag && htag->val) + handle = htag->val; + } + if (handle) + ctx = context_get(handle); + else if (!(ctx = context_get_by_name(im->real_file)) && + !(ctx = context_create(im->real_file))) + return 0; + + if (!index) + { + ImlibImageTag *htag = __imlib_GetTag(im, "index"); + + if (htag && htag->val) + index = htag->val; + } + if (index < 0 || index > id3_tag_get_numframes(ctx->tag) || + (index == 0 && id3_tag_get_numframes(ctx->tag) < 1)) + { + if (index) + fprintf(stderr, "No picture frame # %d found\n", index); + context_delref(ctx); + return 0; + } + if (!index) + index = 1; + + opt->ctx = ctx; + opt->index = index; + opt->traverse = traverse; + opt->cache_level = (id3_tag_get_numframes(ctx->tag) > 1 ? 1 : 0); + return 1; } -static int extract_pic (struct id3_frame* frame, int dest) +static int +extract_pic(struct id3_frame *frame, int dest) { - union id3_field* field; - unsigned char const * data; - id3_length_t length; - int done = 0; - - field = id3_frame_field (frame, 4); - data = id3_field_getbinarydata (field, &length); - if (! data) { - fprintf (stderr, "No image data found for frame\n"); - return 0; - } - while (length > 0) { - ssize_t res; - if ((res = write (dest, data + done, length)) < 0) { - if (errno == EINTR) - continue; - perror ("Unable to write to file"); - return 0; - } - length -= res; - done += res; - } - return 1; + union id3_field *field; + unsigned char const *data; + id3_length_t length; + int done = 0; + + field = id3_frame_field(frame, 4); + data = id3_field_getbinarydata(field, &length); + if (!data) + { + fprintf(stderr, "No image data found for frame\n"); + return 0; + } + while (length > 0) + { + ssize_t res; + + if ((res = write(dest, data + done, length)) < 0) + { + if (errno == EINTR) + continue; + perror("Unable to write to file"); + return 0; + } + length -= res; + done += res; + } + return 1; } #define EXT_LEN 14 -static char get_loader (lopt* opt, ImlibLoader** loader) +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; + 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; } -static char* id3_pic_types [] = { - /* $00 */ "Other", - /* $01 */ "32x32 pixels file icon", - /* $02 */ "Other file icon", - /* $03 */ "Cover (front)", - /* $04 */ "Cover (back)", - /* $05 */ "Leaflet page", - /* $06 */ "Media", - /* $07 */ "Lead artist/lead performer/soloist", - /* $08 */ "Artist/performer", - /* $09 */ "Conductor", - /* $0A */ "Band/Orchestra", - /* $0B */ "Composer", - /* $0C */ "Lyricist/text writer", - /* $0D */ "Recording Location", - /* $0E */ "During recording", - /* $0F */ "During performance", - /* $10 */ "Movie/video screen capture", - /* $11 */ "A bright coloured fish", - /* $12 */ "Illustration", - /* $13 */ "Band/artist logotype", - /* $14 */ "Publisher/Studio logotype" +static char *id3_pic_types[] = { + /* $00 */ "Other", + /* $01 */ "32x32 pixels file icon", + /* $02 */ "Other file icon", + /* $03 */ "Cover (front)", + /* $04 */ "Cover (back)", + /* $05 */ "Leaflet page", + /* $06 */ "Media", + /* $07 */ "Lead artist/lead performer/soloist", + /* $08 */ "Artist/performer", + /* $09 */ "Conductor", + /* $0A */ "Band/Orchestra", + /* $0B */ "Composer", + /* $0C */ "Lyricist/text writer", + /* $0D */ "Recording Location", + /* $0E */ "During recording", + /* $0F */ "During performance", + /* $10 */ "Movie/video screen capture", + /* $11 */ "A bright coloured fish", + /* $12 */ "Illustration", + /* $13 */ "Band/artist logotype", + /* $14 */ "Publisher/Studio logotype" }; #define NUM_OF_ID3_PIC_TYPES \ (sizeof(id3_pic_types) / sizeof(id3_pic_types[0])) -static char* id3_text_encodings [] = { - /* $00 */ "ISO-8859-1", - /* $01 */ "UTF-16 encoded Unicode with BOM", - /* $02 */ "UTF-16BE encoded Unicode without BOM", - /* $03 */ "UTF-8 encoded Unicode" +static char *id3_text_encodings[] = { + /* $00 */ "ISO-8859-1", + /* $01 */ "UTF-16 encoded Unicode with BOM", + /* $02 */ "UTF-16BE encoded Unicode without BOM", + /* $03 */ "UTF-8 encoded Unicode" }; #define NUM_OF_ID3_TEXT_ENCODINGS \ (sizeof(id3_text_encodings) / sizeof(id3_text_encodings[0])) -static void write_tags (ImlibImage* im, lopt* opt) +static void +write_tags(ImlibImage * im, lopt * opt) { - struct id3_frame* frame - = id3_tag_get_frame (opt->ctx->tag, opt->index - 1); - union id3_field* field; - int num_data; - char* data; - - if ((field = id3_frame_field (frame, 1)) && - (data = (char*) id3_field_getlatin1 (field))) - __imlib_AttachTag (im, "mime-type", 0, - strdup (data), destructor_data); - if ((field = id3_frame_field (frame, 3)) && - (data = (char*) id3_field_getstring (field))) { - size_t length; - char* dup; - id3_ucs4_t* ptr = (id3_ucs4_t*)data; - while (*ptr) - ptr ++; - length = (ptr - (id3_ucs4_t*)data + 1) * sizeof (id3_ucs4_t); - dup = (char*) malloc (length); - memcpy (dup, data, length); - __imlib_AttachTag (im, "id3-description", 0, - dup, destructor_data); - } - if (field = id3_frame_field (frame, 0)) - __imlib_AttachTag (im, "id3-description-text-encoding", - (num_data = (int) - id3_field_gettextencoding (field)), - num_data < NUM_OF_ID3_TEXT_ENCODINGS ? - id3_text_encodings[num_data] : NULL, NULL); - if (field = id3_frame_field (frame, 2)) - __imlib_AttachTag (im, "id3-picture-type", - (num_data = id3_field_getint (field)), - num_data < NUM_OF_ID3_PIC_TYPES ? - id3_pic_types[num_data] : NULL, NULL); - __imlib_AttachTag (im, "count", id3_tag_get_numframes (opt->ctx->tag), - NULL, NULL); - if (opt->cache_level) { - context_addref (opt->ctx); - __imlib_AttachTag (im, "context", opt->ctx->id, - opt->ctx, destructor_context); - } - __imlib_AttachTag (im, "index", opt->index, NULL, NULL); - if (opt->traverse) { - char* buf = NULL; - if ((opt->index + opt->traverse) - <= id3_tag_get_numframes (opt->ctx->tag) - && (opt->index + opt->traverse) > 0) { - buf = (char*) malloc - ((strlen (im->real_file) + 50) * sizeof (char)); - sprintf (buf, "%s:index=%d,traverse=%d", im->real_file, - opt->index + opt->traverse, opt->traverse); - } - __imlib_AttachTag (im, "next", 0, buf, destructor_data); - } + struct id3_frame *frame = id3_tag_get_frame(opt->ctx->tag, opt->index - 1); + union id3_field *field; + int num_data; + char *data; + + if ((field = id3_frame_field(frame, 1)) && + (data = (char *)id3_field_getlatin1(field))) + __imlib_AttachTag(im, "mime-type", 0, strdup(data), destructor_data); + if ((field = id3_frame_field(frame, 3)) && + (data = (char *)id3_field_getstring(field))) + { + size_t length; + char *dup; + id3_ucs4_t *ptr = (id3_ucs4_t *) data; + + while (*ptr) + ptr++; + length = (ptr - (id3_ucs4_t *) data + 1) * sizeof(id3_ucs4_t); + dup = (char *)malloc(length); + memcpy(dup, data, length); + __imlib_AttachTag(im, "id3-description", 0, dup, destructor_data); + } + if (field = id3_frame_field(frame, 0)) + __imlib_AttachTag(im, "id3-description-text-encoding", + (num_data = (int)id3_field_gettextencoding(field)), + num_data < NUM_OF_ID3_TEXT_ENCODINGS ? + id3_text_encodings[num_data] : NULL, NULL); + if (field = id3_frame_field(frame, 2)) + __imlib_AttachTag(im, "id3-picture-type", + (num_data = id3_field_getint(field)), + num_data < NUM_OF_ID3_PIC_TYPES ? + id3_pic_types[num_data] : NULL, NULL); + __imlib_AttachTag(im, "count", id3_tag_get_numframes(opt->ctx->tag), + NULL, NULL); + if (opt->cache_level) + { + context_addref(opt->ctx); + __imlib_AttachTag(im, "context", opt->ctx->id, + opt->ctx, destructor_context); + } + __imlib_AttachTag(im, "index", opt->index, NULL, NULL); + if (opt->traverse) + { + char *buf = NULL; + + if ((opt->index + opt->traverse) + <= id3_tag_get_numframes(opt->ctx->tag) + && (opt->index + opt->traverse) > 0) + { + buf = (char *)malloc((strlen(im->real_file) + 50) * sizeof(char)); + sprintf(buf, "%s:index=%d,traverse=%d", im->real_file, + opt->index + opt->traverse, opt->traverse); + } + __imlib_AttachTag(im, "next", 0, buf, destructor_data); + } } -char load (ImlibImage *im, ImlibProgressFunction progress, - char progress_granularity, char immediate_load) +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); + 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; - } - } + 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; + context_delref(opt.ctx); + return res; -fail_context: - context_delref (opt.ctx); - return 0; + fail_context: + context_delref(opt.ctx); + return 0; } -void formats (ImlibLoader *l) +void +formats(ImlibLoader * l) { - /* this is the only bit you have to change... */ - char *list_formats[] = {"mp3"}; - int i; - - /* don't bother changing any of this - it just reads this in - * and sets the struct values and makes copies - */ - l->num_formats = sizeof (list_formats) / sizeof (char *); - l->formats = (char**) malloc (sizeof (char *) * l->num_formats); - - for (i = 0; i < l->num_formats; i++) - l->formats[i] = strdup (list_formats[i]); + /* this is the only bit you have to change... */ + char *list_formats[] = { "mp3" }; + int i; + + /* don't bother changing any of this - it just reads this in + * and sets the struct values and makes copies + */ + l->num_formats = sizeof(list_formats) / sizeof(char *); + l->formats = (char **)malloc(sizeof(char *) * l->num_formats); + + for (i = 0; i < l->num_formats; i++) + l->formats[i] = strdup(list_formats[i]); } |