/* * NAME: tag->clearframes() * DESCRIPTION: detach and delete all frames associated with a tag */ void id3_tag_clearframes(struct id3_tag *tag) { unsigned int i; for (i = 0; i < tag->nframes; ++i) { id3_frame_delref(tag->frames[i]); id3_frame_delete(tag->frames[i]); } tag->nframes = 0; }
static int v1_attachstr(struct id3_tag *tag, char const *id, char *text, unsigned long number) { struct id3_frame *frame; id3_ucs4_t ucs4[31]; if (text) { trim(text); if (*text == 0) return 0; } frame = id3_frame_new(id); if (frame == 0) return -1; if (id3_field_settextencoding(&frame->fields[0], ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1) goto fail; if (text) id3_latin1_decode(text, ucs4); else id3_ucs4_putnumber(ucs4, number); if (strcmp(id, ID3_FRAME_COMMENT) == 0) { if (id3_field_setlanguage(&frame->fields[1], "XXX") == -1 || id3_field_setstring(&frame->fields[2], id3_ucs4_empty) == -1 || id3_field_setfullstring(&frame->fields[3], ucs4) == -1) goto fail; } else { id3_ucs4_t *ptr = ucs4; if (id3_field_setstrings(&frame->fields[1], 1, &ptr) == -1) goto fail; } if (id3_tag_attachframe(tag, frame) == -1) goto fail; return 0; fail: id3_frame_delete(frame); return -1; }
int BarFlyID3AddCover(struct id3_tag* tag, uint8_t const* cover_art, size_t cover_size, BarSettings_t const* settings) { /* * http://flac.sourceforge.net/api/group__flac__format.html#ga113 */ int const PICTURE_TYPE_FRONT_COVER = 3; char const BAR_FLY_ID3_FRAME_PICTURE[] = "APIC"; int exit_status = 0; int status; struct id3_frame* frame = NULL; union id3_field* field; int index; char* mime_type; assert(tag != NULL); assert(cover_art != NULL); assert(settings != NULL); /* * Get a new picture frame. */ frame = id3_frame_new(BAR_FLY_ID3_FRAME_PICTURE); if (frame == NULL) { BarUiMsg(settings, MSG_ERR, "Failed to create new frame (type = %s).\n", BAR_FLY_ID3_FRAME_PICTURE); goto error; } /* * Go through all the frame fields setting the mime type, image type, and * the image data. */ index = 0; field = id3_frame_field(frame, index); while (field != NULL) { switch (id3_field_type(field)) { /* * Set the cover art mime type. */ case (ID3_FIELD_TYPE_LATIN1): if ((cover_art[0] == 0xFF) && (cover_art[1] == 0xD8)) { mime_type = "image/jpeg"; } else if ((cover_art[0] == 0x89) && (cover_art[1] == 0x50) && (cover_art[2] == 0x4E) && (cover_art[3] == 0x47) && (cover_art[4] == 0x0D) && (cover_art[5] == 0x0A) && (cover_art[6] == 0x1A) && (cover_art[7] == 0x0A)) { mime_type = "image/png"; } else { mime_type = NULL; } id3_field_setlatin1(field, (id3_latin1_t const*)mime_type); break; /* * Designate this as the front cover. */ case (ID3_FIELD_TYPE_INT8): id3_field_setint(field, PICTURE_TYPE_FRONT_COVER); break; /* * Set the image data. */ case (ID3_FIELD_TYPE_BINARYDATA): id3_field_setbinarydata(field, cover_art, cover_size); break; default: break; } index++; field = id3_frame_field(frame, index); } /* * Attach the frame to the tag. */ status = id3_tag_attachframe(tag, frame); if (status != 0) { BarUiMsg(settings, MSG_ERR, "Failed to attach cover art frame.\n"); goto error; } goto end; error: if (frame != NULL) { id3_frame_delete(frame); } exit_status = -1; end: return exit_status; }
int BarFlyID3AddFrame(struct id3_tag* tag, char const* type, char const* value, BarSettings_t const* settings) { int exit_status = 0; int status; struct id3_frame* frame = NULL; union id3_field* field; id3_ucs4_t* ucs4 = NULL; int index; assert(tag != NULL); assert(type != NULL); assert(value != NULL); assert(settings != NULL); /* * Create the frame. */ frame = id3_frame_new(type); if (frame == NULL) { BarUiMsg(settings, MSG_ERR, "Failed to create new frame (type = %s).\n", type); goto error; } frame->flags &= ~ID3_FRAME_FLAG_FORMATFLAGS; /* * Get the string list field of the frame. */ index = 0; do { field = id3_frame_field(frame, index); index++; } while (id3_field_type(field) != ID3_FIELD_TYPE_STRINGLIST); assert(id3_field_type(field) == ID3_FIELD_TYPE_STRINGLIST); /* * Add the value as a string to the field. */ ucs4 = id3_latin1_ucs4duplicate((id3_latin1_t*)value); if (ucs4 == NULL) { BarUiMsg(settings, MSG_ERR, "Could not allocate memory.\n"); goto error; } status = id3_field_addstring(field, ucs4); if (status != 0) { BarUiMsg(settings, MSG_ERR, "Failed to set field value (value = %s).\n", value); goto error; } /* * Attach the frame to the tag. */ status = id3_tag_attachframe(tag, frame); if (status != 0) { BarUiMsg(settings, MSG_ERR, "Failed to attach frame (type = %s).\n", type); goto error; } goto end; error: if (frame != NULL) { id3_frame_delete(frame); } exit_status = -1; end: if (ucs4 != NULL) { free(ucs4); } return exit_status; }
/* * NAME: compat->fixup() * DESCRIPTION: finish compatibility translations */ int id3_compat_fixup(struct id3_tag *tag) { struct id3_frame *frame; unsigned int index; id3_ucs4_t timestamp[17] = { 0 }; int result = 0; /* create a TDRC frame from obsolete TYER/TDAT/TIME frames */ /* * TYE/TYER: YYYY * TDA/TDAT: DDMM * TIM/TIME: HHMM * * TDRC: yyyy-MM-ddTHH:mm */ index = 0; while((frame = id3_tag_findframe(tag, ID3_FRAME_OBSOLETE, index++))) { char const *id; id3_byte_t const *data, *end; id3_length_t length; enum id3_field_textencoding encoding; id3_ucs4_t *string; id = id3_field_getframeid(&frame->fields[0]); assert(id); if(strcmp(id, "TYER") != 0 && strcmp(id, "YTYE") != 0 && strcmp(id, "TDAT") != 0 && strcmp(id, "YTDA") != 0 && strcmp(id, "TIME") != 0 && strcmp(id, "YTIM") != 0) continue; data = id3_field_getbinarydata(&frame->fields[1], &length); assert(data); if(length < 1) continue; end = data + length; encoding = (enum id3_field_textencoding)id3_parse_uint(&data, 1); string = id3_parse_string(&data, end - data, encoding, 0); if(id3_ucs4_length(string) < 4) { free(string); continue; } if(strcmp(id, "TYER") == 0 || strcmp(id, "YTYE") == 0) { timestamp[0] = string[0]; timestamp[1] = string[1]; timestamp[2] = string[2]; timestamp[3] = string[3]; } else if(strcmp(id, "TDAT") == 0 || strcmp(id, "YTDA") == 0) { timestamp[4] = '-'; timestamp[5] = string[2]; timestamp[6] = string[3]; timestamp[7] = '-'; timestamp[8] = string[0]; timestamp[9] = string[1]; } else /* TIME or YTIM */ { timestamp[10] = 'T'; timestamp[11] = string[0]; timestamp[12] = string[1]; timestamp[13] = ':'; timestamp[14] = string[2]; timestamp[15] = string[3]; } free(string); } if(timestamp[0]) { id3_ucs4_t *strings; frame = id3_frame_new("TDRC"); if(frame == 0) goto fail; strings = timestamp; if(id3_field_settextencoding(&frame->fields[0], ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1 || id3_field_setstrings(&frame->fields[1], 1, &strings) == -1 || id3_tag_attachframe(tag, frame) == -1) { id3_frame_delete(frame); goto fail; } } if(0) { fail: result = -1; } return result; }