allow MIME type in specification to be blank and filled in automatically; allow speci...
authorJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 6 Feb 2007 01:40:37 +0000 (01:40 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 6 Feb 2007 01:40:37 +0000 (01:40 +0000)
src/share/grabbag/picture.c

index ba3ff43..09aff7d 100644 (file)
@@ -42,7 +42,7 @@ static FLAC__bool local__parse_type_(const char *s, size_t len, FLAC__StreamMeta
        size_t i;
        FLAC__uint32 val = 0;
 
-       picture->type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;;
+       picture->type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
 
        if(len == 0)
                return true; /* empty string implies default to 'front cover' */
@@ -112,6 +112,17 @@ static FLAC__bool local__parse_resolution_(const char *s, size_t len, FLAC__Stre
        return true;
 }
 
+static FLAC__bool local__extract_mime_type_(FLAC__StreamMetadata *obj)
+{
+       if(obj->data.picture.data_length >= 8 && 0 == memcmp(obj->data.picture.data, "\x89PNG\x0d\x0a\x1a\x0a", 8))
+               return FLAC__metadata_object_picture_set_mime_type(obj, "image/png", /*copy=*/true);
+       else if(obj->data.picture.data_length >= 6 && (0 == memcmp(obj->data.picture.data, "GIF87a", 6) || 0 == memcmp(obj->data.picture.data, "GIF89a", 6)))
+               return FLAC__metadata_object_picture_set_mime_type(obj, "image/gif", /*copy=*/true);
+       else if(obj->data.picture.data_length >= 2 && 0 == memcmp(obj->data.picture.data, "\xff\xd8", 2))
+               return FLAC__metadata_object_picture_set_mime_type(obj, "image/jpeg", /*copy=*/true);
+       return false;
+}
+
 static FLAC__bool local__extract_resolution_color_info_(FLAC__StreamMetadata_Picture *picture)
 {
        const FLAC__byte *data = picture->data;
@@ -251,8 +262,6 @@ FLAC__StreamMetadata *grabbag__picture_parse_specification(const char *spec, con
 {
        FLAC__StreamMetadata *obj;
        int state = 0;
-       const char *p;
-       char *q;
        static const char *error_messages[] = {
                "memory allocation error",
                "invalid picture specification",
@@ -262,7 +271,7 @@ FLAC__StreamMetadata *grabbag__picture_parse_specification(const char *spec, con
                "error opening picture file",
                "error reading picture file",
                "invalid picture type",
-               "invalid MIME type",
+               "unable to guess MIME type from file, user must set explicitly",
                "type 1 icon must be a 32x32 pixel PNG"
        };
 
@@ -280,42 +289,58 @@ FLAC__StreamMetadata *grabbag__picture_parse_specification(const char *spec, con
        if(0 == (obj = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE)))
                *error_message = error_messages[0];
 
-       for(p = spec; *error_message==0 && *p; ) {
-               if(*p == '|') {
-                       switch(state) {
-                               case 0: /* type */
-                                       if(!local__parse_type_(spec, p-spec, &obj->data.picture))
-                                               *error_message = error_messages[7];
-                                       break;
-                               case 1: /* mime type */
-                                       if(p-spec == 0)
-                                               *error_message = error_messages[8];
-                                       else if(0 == (q = local__strndup_(spec, p-spec)))
-                                               *error_message = error_messages[0];
-                                       else if(!FLAC__metadata_object_picture_set_mime_type(obj, q, /*copy=*/false))
-                                               *error_message = error_messages[0];
-                                       break;
-                               case 2: /* description */
-                                       if(0 == (q = local__strndup_(spec, p-spec)))
-                                               *error_message = error_messages[0];
-                                       else if(!FLAC__metadata_object_picture_set_description(obj, (FLAC__byte*)q, /*copy=*/false))
-                                               *error_message = error_messages[0];
-                                       break;
-                               case 3: /* resolution/color (e.g. [300x300x16[/1234]] */
-                                       if(!local__parse_resolution_(spec, p-spec, &obj->data.picture))
-                                               *error_message = error_messages[2];
-                                       break;
-                               default:
-                                       *error_message = error_messages[1];
-                                       break;
+       if(strchr(spec, '|')) { /* full format */
+               const char *p;
+               char *q;
+               for(p = spec; *error_message==0 && *p; ) {
+                       if(*p == '|') {
+                               switch(state) {
+                                       case 0: /* type */
+                                               if(!local__parse_type_(spec, p-spec, &obj->data.picture))
+                                                       *error_message = error_messages[7];
+                                               break;
+                                       case 1: /* mime type */
+                                               if(p-spec) { /* if blank, we'll try to guess later from the picture data */
+                                                       if(0 == (q = local__strndup_(spec, p-spec)))
+                                                               *error_message = error_messages[0];
+                                                       else if(!FLAC__metadata_object_picture_set_mime_type(obj, q, /*copy=*/false))
+                                                               *error_message = error_messages[0];
+                                               }
+                                               break;
+                                       case 2: /* description */
+                                               if(0 == (q = local__strndup_(spec, p-spec)))
+                                                       *error_message = error_messages[0];
+                                               else if(!FLAC__metadata_object_picture_set_description(obj, (FLAC__byte*)q, /*copy=*/false))
+                                                       *error_message = error_messages[0];
+                                               break;
+                                       case 3: /* resolution/color (e.g. [300x300x16[/1234]] */
+                                               if(!local__parse_resolution_(spec, p-spec, &obj->data.picture))
+                                                       *error_message = error_messages[2];
+                                               break;
+                                       default:
+                                               *error_message = error_messages[1];
+                                               break;
+                               }
+                               p++;
+                               spec = p;
+                               state++;
                        }
-                       p++;
-                       spec = p;
-                       state++;
+                       else
+                               p++;
                }
+       }
+       else { /* simple format, filename only, everything else guessed */
+               if(!local__parse_type_("", 0, &obj->data.picture)) /* use default picture type */
+                       *error_message = error_messages[7];
+               /* leave MIME type to be filled in later */
+               /* leave description empty */
+               /* leave the rest to be filled in later: */
+               else if(!local__parse_resolution_("", 0, &obj->data.picture))
+                       *error_message = error_messages[2];
                else
-                       p++;
+                       state = 4;
        }
+
        /* parse filename, read file, try to extract resolution/color info if needed */
        if(*error_message == 0) {
                if(state != 4)
@@ -346,11 +371,12 @@ FLAC__StreamMetadata *grabbag__picture_parse_specification(const char *spec, con
                                                        if(0 == *error_message) {
                                                                if(!FLAC__metadata_object_picture_set_data(obj, buffer, size, /*copy=*/false))
                                                                        *error_message = error_messages[6];
+                                                               /* try to extract MIME type if user left it blank */
+                                                               else if(*obj->data.picture.mime_type == '\0' && !local__extract_mime_type_(obj))
+                                                                       *error_message = error_messages[8];
                                                                /* try to extract resolution/color info if user left it blank */
-                                                               else if(obj->data.picture.width == 0 || obj->data.picture.height == 0 || obj->data.picture.depth == 0) {
-                                                                       if(!local__extract_resolution_color_info_(&obj->data.picture))
-                                                                               *error_message = error_messages[4];
-                                                               }
+                                                               else if((obj->data.picture.width == 0 || obj->data.picture.height == 0 || obj->data.picture.depth == 0) && !local__extract_resolution_color_info_(&obj->data.picture))
+                                                                       *error_message = error_messages[4];
                                                        }
                                                }
                                        }