struct id3_frame *MakeID3Frame(const char *name, const char *data0, const char *data1) { struct id3_frame *frame; id3_latin1_t *latin1; id3_ucs4_t *ucs4; frame = id3_frame_new(name); latin1 = (id3_latin1_t *)data1; ucs4 = (id3_ucs4_t *)malloc((id3_latin1_length(latin1) + 1) * sizeof(*ucs4)); id3_latin1_decode(latin1, ucs4); if (strcmp(name, ID3_FRAME_COMMENT) == 0) { id3_field_setfullstring(&frame->fields[3], ucs4); } else if (strcmp(name, "TXXX") == 0) { id3_field_setstring(&frame->fields[2], ucs4); if (data0) { free(ucs4); latin1 = (id3_latin1_t *)data0; ucs4 = (id3_ucs4_t *)malloc((id3_latin1_length(latin1) + 1) * sizeof(*ucs4)); id3_latin1_decode(latin1, ucs4); id3_field_setstring(&frame->fields[1], ucs4); } } else id3_field_setstrings(&frame->fields[1], 1, &ucs4); free(ucs4); return frame; }
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 id3_metadata_setcomment(struct id3_tag* tag, id3_ucs4_t* value) { union id3_field *field; struct id3_frame *frame; frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, 0); if (frame == 0) { frame = id3_frame_new(ID3_FRAME_COMMENT); id3_tag_attachframe(tag, frame); } id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_UTF_16); field = id3_frame_field(frame, 3); if (field == 0) return 0; return id3_field_setfullstring(field, value); }
int metadata_setstring(struct id3_tag* tag, const char* id, id3_ucs4_t* value) { union id3_field *field; struct id3_frame *frame; frame = id3_tag_findframe(tag, id, 0); if (frame == 0) { frame = id3_frame_new(id); id3_tag_attachframe(tag, frame); } id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_UTF_16); field = id3_frame_field(frame, 1); if (field == 0) return 0; return (id3_field_setstrings(field, 1, &value)==0); }
void ExportMP2::AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name) { struct id3_frame *frame = id3_frame_new(name); if (!n.IsAscii() || !v.IsAscii()) { id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_UTF_16); } else { id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1); } id3_ucs4_t *ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)); if (strcmp(name, ID3_FRAME_COMMENT) == 0) { // A hack to get around iTunes not recognizing the comment. The // language defaults to XXX and, since it's not a valid language, // iTunes just ignores the tag. So, either set it to a valid language // (which one???) or just clear it. Unfortunately, there's no supported // way of clearing the field, so do it directly. id3_field *f = id3_frame_field(frame, 1); memset(f->immediate.value, 0, sizeof(f->immediate.value)); id3_field_setfullstring(id3_frame_field(frame, 3), ucs4); } else if (strcmp(name, "TXXX") == 0) { id3_field_setstring(id3_frame_field(frame, 2), ucs4); free(ucs4); ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)); id3_field_setstring(id3_frame_field(frame, 1), ucs4); } else { id3_field_setstrings(id3_frame_field(frame, 1), 1, &ucs4); } free(ucs4); id3_tag_attachframe(tp, frame); }
int id3_metadata_setrating(struct id3_tag* tag, char value) { union id3_field *field; struct id3_frame *frame; char popm[] = { 3, 53, 104, 154, 205, 255 }; if (value < '0' || value > '5') return -1; frame = id3_tag_findframe(tag, "POPM", 0); if (frame == 0) { frame = id3_frame_new("POPM"); id3_tag_attachframe(tag, frame); } field = id3_frame_field(frame, 1); if (field == 0) return 0; return id3_field_setint(field, popm[value - '0']); }
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; }