/** * Import a "Comment frame" (ID3v2.4.0 section 4.10). It * contains 4 fields: * * - encoding * - language * - string * - full string (we use this one) */ static void tag_id3_import_comment(struct tag *dest, struct id3_tag *tag, const char *id, enum tag_type type) { struct id3_frame const *frame; id3_ucs4_t const *ucs4; id3_utf8_t *utf8; union id3_field const *field; frame = id3_tag_findframe(tag, id, 0); if (frame == NULL || frame->nfields != 4) return; /* for now I only read the 4th field, with the fullstring */ field = id3_frame_field(frame, 3); if (field == NULL) return; ucs4 = id3_field_getfullstring(field); if (ucs4 == NULL) return; utf8 = import_id3_string(tag_is_id3v1(tag), ucs4); if (utf8 == NULL) return; tag_add_item(dest, type, (char *)utf8); g_free(utf8); }
static struct id3_tag * tag_id3_find_from_beginning(FILE *stream) { struct id3_tag *tag; struct id3_tag *seektag; struct id3_frame *frame; int seek; tag = tag_id3_read(stream, 0, SEEK_SET); if (!tag) { return NULL; } else if (tag_is_id3v1(tag)) { /* id3v1 tags don't belong here */ id3_tag_delete(tag); return NULL; } /* We have an id3v2 tag, so let's look for SEEK frames */ while ((frame = id3_tag_findframe(tag, "SEEK", 0))) { /* Found a SEEK frame, get it's value */ seek = id3_field_getint(id3_frame_field(frame, 0)); if (seek < 0) break; /* Get the tag specified by the SEEK frame */ seektag = tag_id3_read(stream, seek, SEEK_CUR); if (!seektag || tag_is_id3v1(seektag)) break; /* Replace the old tag with the new one */ id3_tag_delete(tag); tag = seektag; } return tag; }
/** * Import a "Text information frame" (ID3v2.4.0 section 4.2). It * contains 2 fields: * * - encoding * - string list */ static void tag_id3_import_text(struct tag *dest, struct id3_tag *tag, const char *id, enum tag_type type) { struct id3_frame const *frame; id3_ucs4_t const *ucs4; id3_utf8_t *utf8; union id3_field const *field; unsigned int nstrings, i; frame = id3_tag_findframe(tag, id, 0); if (frame == NULL || frame->nfields != 2) return; /* check the encoding field */ field = id3_frame_field(frame, 0); if (field == NULL || field->type != ID3_FIELD_TYPE_TEXTENCODING) return; /* process the value(s) */ field = id3_frame_field(frame, 1); if (field == NULL || field->type != ID3_FIELD_TYPE_STRINGLIST) return; /* Get the number of strings available */ nstrings = id3_field_getnstrings(field); for (i = 0; i < nstrings; i++) { ucs4 = id3_field_getstrings(field, i); if (ucs4 == NULL) continue; if (type == TAG_GENRE) ucs4 = id3_genre_name(ucs4); utf8 = import_id3_string(tag_is_id3v1(tag), ucs4); if (utf8 == NULL) continue; tag_add_item(dest, type, (char *)utf8); g_free(utf8); } }
static int mp3_tagsize(const byte *data, size_t length) { if (tag_is_id3v1(data, length)) return 128; if (tag_is_id3v2(data, length)) { byte flags; unsigned int size; flags = data[5]; size = 10 + (data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9]; if (flags & ID3_TAG_FLAG_FOOTERPRESENT) size += 10; for ( ; size < length && !data[size]; ++size) ; /* Consume padding */ return size; } return 0; }