id3_byte_t const* id3_metadata_getuniquefileidentifier(const struct id3_tag* tag, const char* owner_identifier, id3_length_t* length) { int i=0, result; id3_ucs4_t const * ucs4; id3_latin1_t* latin1; union id3_field const *field; struct id3_frame const *frame; id3_byte_t const* identifier; for (i=0; ; ++i) { frame = id3_tag_findframe(tag, "UFID", i); if (frame == 0) return 0; field = id3_frame_field(frame, 0); if (field == 0) return 0; if (strcmp(id3_field_getlatin1(field), owner_identifier)==0) break; } field = id3_frame_field(frame, 1); if (field == 0) return 0; return id3_field_getbinarydata(field, length); }
/** * Imports the MusicBrainz TrackId from the UFID tag. */ static void tag_id3_import_ufid(struct tag *mpd_tag, struct id3_tag *id3_tag) { for (unsigned i = 0;; ++i) { const struct id3_frame *frame; union id3_field *field; const id3_latin1_t *name; const id3_byte_t *value; id3_length_t length; frame = id3_tag_findframe(id3_tag, "UFID", i); if (frame == NULL) break; field = id3_frame_field(frame, 0); if (field == NULL) continue; name = id3_field_getlatin1(field); if (name == NULL || strcmp((const char *)name, "http://musicbrainz.org") != 0) continue; field = id3_frame_field(frame, 1); if (field == NULL) continue; value = id3_field_getbinarydata(field, &length); if (value == NULL || length == 0) continue; tag_add_item_n(mpd_tag, TAG_MUSICBRAINZ_TRACKID, (const char*)value, length); } }
const id3_ucs4_t* id3_metadata_getusertext(const struct id3_tag* tag, const char* description) { id3_ucs4_t const * ucs4; id3_latin1_t* latin1; union id3_field const *field; struct id3_frame const *frame; id3_length_t length; int i=0, result; for (i=0; ; ++i) { frame = id3_tag_findframe(tag, "TXXX", i); if (frame == 0) return id3_ucs4_empty; field = id3_frame_field(frame, 1); if (field == 0) return id3_ucs4_empty; latin1=id3_ucs4_latin1duplicate(id3_field_getstring(field)); result=strcmp(latin1, description); free(latin1); if (result==0) break; } field = id3_frame_field(frame, 2); if (field == 0) return id3_ucs4_empty; return id3_field_getstring(field); }
const id3_ucs4_t* metadata_getstring(const struct id3_tag* tag, const char* id, enum id3_field_textencoding* encoding) { int nstrings, j; char const *name; id3_ucs4_t const *ucs4; union id3_field const *field; struct id3_frame const *frame; frame = id3_tag_findframe(tag, id, 0); if (frame == 0) return id3_ucs4_empty; *encoding = id3_field_gettextencoding(id3_frame_field(frame, 0)); field = id3_frame_field(frame, 1); if (field == 0) return id3_ucs4_empty; nstrings = id3_field_getnstrings(field); ucs4 = id3_ucs4_empty; for (j = 0; j < nstrings; ++j) { ucs4 = id3_field_getstrings(field, j); if (ucs4 && *ucs4) break; } return ucs4; }
const id3_ucs4_t* id3_metadata_getcomment(const struct id3_tag* tag, enum id3_field_textencoding* encoding) { union id3_field const *field; struct id3_frame const *frame; const id3_ucs4_t* ucs4 = 0; int commentNumber = 0; // return the first non-empty comment do { frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, commentNumber++); if (frame == 0) return id3_ucs4_empty; *encoding = id3_field_gettextencoding(id3_frame_field(frame, 0)); field = id3_frame_field(frame, 3); if (field == 0) return id3_ucs4_empty; ucs4 = id3_field_getfullstring(field); if (!ucs4) return id3_ucs4_empty; } while (*ucs4 == 0); return ucs4; }
id3_ucs4_list_t *metadata_getstrings(const struct id3_tag* tag, const char* id, enum id3_field_textencoding* encoding) { int nstrings, j; union id3_field const *field; struct id3_frame const *frame; id3_ucs4_list_t *list; frame = id3_tag_findframe(tag, id, 0); if (frame == 0) return 0; *encoding = id3_field_gettextencoding(id3_frame_field(frame, 0)); field = id3_frame_field(frame, 1); if (field == 0) return 0; nstrings = id3_field_getnstrings(field); list = 0; if (nstrings) { list = (id3_ucs4_list_t*)malloc(sizeof(*list)); if (list) list->strings = (const id3_ucs4_t**)malloc(nstrings * sizeof(*list->strings)); } if (list && list->strings) { list->nstrings = nstrings; for (j = 0; j < list->nstrings; ++j) list->strings[j] = id3_field_getstrings(field, j); } return list; }
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); } }
static struct id3_tag *findId3TagFromBeginning(FILE * stream) { struct id3_tag *tag; struct id3_tag *seektag; struct id3_frame *frame; int seek; tag = getId3Tag(stream, 0, SEEK_SET); if (!tag) { return NULL; } else if (isId3v1(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 = getId3Tag(stream, seek, SEEK_CUR); if (!seektag || isId3v1(seektag)) break; /* Replace the old tag with the new one */ id3_tag_delete(tag); tag = seektag; } return tag; }
char id3_metadata_getrating(const struct id3_tag* tag) { union id3_field const *field; struct id3_frame const *frame; int value; frame = id3_tag_findframe(tag, "POPM", 0); if (frame) { field = id3_frame_field(frame, 1); if (field) { // based on mediamonkey's values, simplified down a bit // http://www.mediamonkey.com/forum/viewtopic.php?f=7&t=40532 value = id3_field_getint(field); if (value == 1) return '1'; // WMP11 madness if (value < 9) return '0'; if (value < 50) return '1'; if (value < 114) return '2'; if (value < 168) return '3'; if (value < 219) return '4'; return '5'; } } else { const id3_ucs4_t *ucs4 = id3_metadata_getusertext(tag, "RATING"); if (ucs4 && *ucs4 > '0' && *ucs4 < '6') return (char)*ucs4; } return '0'; }
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; }
char * getTagString(struct id3_tag *tag, const char *frameName) { struct id3_frame *frame; union id3_field *field; int i; const id3_ucs4_t *unicode; char *ret; frame = id3_tag_findframe(tag,frameName,0); if(!frame) { fprintf(stdout,"No frame\n"); return NULL; } for(i=0;;i++) { field = id3_frame_field(frame,i); if(!field) { break; } if(id3_field_type(field) == ID3_FIELD_TYPE_STRINGLIST) { unicode = id3_field_getstrings(field,0); if(unicode) { id3_utf8_t *str; str = id3_ucs4_utf8duplicate(unicode); ret = (char *) str; } } } return ret; }
/** * 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); }
const id3_ucs4_t* id3_metadata_getcomment(const struct id3_tag* tag, enum id3_field_textencoding* encoding) { union id3_field const *field; struct id3_frame const *frame; int commentNumber = 0; const id3_ucs4_t* ucs4 = 0; // return the first non-empty comment do { frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, commentNumber++); if (frame && frame->nfields == 4) { //get short description field = id3_frame_field(frame, 2); if (field == 0) continue; ucs4 = id3_field_getstring(field); // Multiple values are allowed per comment field, but storing different comment // frames requires a different description for each frame. The first COMM frame // encountered without a description will be used as the comment field. // Source http://puddletag.sourceforge.net/source/id3.html if (ucs4 && *ucs4 == 0)//if short description on this frame is empty - consider this the wanted comment frame { //fetch encoding of the frame field = id3_frame_field(frame, 0); if(field == 0) continue; *encoding = id3_field_gettextencoding(field); //finally fetch the comment field = id3_frame_field(frame, 3); if (field == 0) continue; return id3_field_getfullstring(field); } } } while (frame); return ucs4; }
/** * 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); } }
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); }
wchar_t* GetMP3Tag(const id3_tag* tag, const char* name) { wchar_t* content = NULL; id3_frame* frame = id3_tag_findframe(tag, name, 0); if (frame != NULL) { id3_field* field = id3_frame_field(frame, 0); id3_field_textencoding encoding = id3_field_gettextencoding(field); field = id3_frame_field(frame, 1); switch (id3_field_type(field)) { case ID3_FIELD_TYPE_STRING: content = GetMP3Text(encoding, field, id3_field_getstring(field)); break; case ID3_FIELD_TYPE_STRINGFULL: content = GetMP3Text(encoding, field, id3_field_getfullstring(field)); break; case ID3_FIELD_TYPE_STRINGLIST: { DWORD dataLength = 0, bufferLength = 0; unsigned int n = id3_field_getnstrings(field); for (unsigned int i = 0; i < n; i++) { wchar_t* p = GetMP3Text(encoding, field, id3_field_getstrings(field, i)); if (p == NULL) continue; AppendBuffer((char**)&content, dataLength, bufferLength, (const char*)p, wcslen(p) * 2 + 1); SAFE_DELETE_ARRAY(p); } } break; } } return content; }
id3_byte_t const* id3_metadata_getpicturedata(const struct id3_tag* tag, enum id3_picture_type picture_type, id3_length_t* length) { union id3_field const *field; struct id3_frame const *frame; frame=id3_metadata_getpictureframebytype(tag, picture_type); if (frame==0) return 0; field = id3_frame_field(frame, 4); if (field == 0) return 0; return id3_field_getbinarydata(field, length); }
const id3_latin1_t* id3_metadata_getpicturemimetype(const struct id3_tag* tag, enum id3_picture_type picture_type) { union id3_field const *field; struct id3_frame const *frame; frame=id3_metadata_getpictureframebytype(tag, picture_type); if (frame==0) return 0; field = id3_frame_field(frame, 1); if (field == 0) return 0; return id3_field_getlatin1(field); }
static id3_utf8_t * tag_id3_getstring(const struct id3_frame *frame, unsigned i) { union id3_field *field; const id3_ucs4_t *ucs4; field = id3_frame_field(frame, i); if (field == NULL) return NULL; ucs4 = id3_field_getstring(field); if (ucs4 == NULL) return NULL; return id3_ucs4_utf8duplicate(ucs4); }
QString mpgDecoder::getID3String( id3_tag* idtag, const char* field_frame ) { QString str; id3_frame* frame = id3_tag_findframe( idtag, field_frame, 0 ); if(frame) { id3_field* field = id3_frame_field(frame, 1); if(field) { const id3_ucs4_t* id3_string = id3_field_getstrings(field, 0); if(id3_string) str = (char*)id3_ucs4_utf8duplicate(id3_string); } } return str; }
int id3_metadata_getfirstnonstandardpictype(const struct id3_tag* tag, enum id3_picture_type* picture_type) { int i=0; union id3_field const *field; struct id3_frame const *frame; for (i=0; ; ++i) { frame = id3_tag_findframe(tag, "APIC", i); if (frame == 0) return 0; field = id3_frame_field(frame, 2); if (field == 0) return 0; if ((*picture_type=id3_field_getint(field))>ID3_PICTURE_TYPE_PUBLISHERLOGO) break; } return 1; }
struct id3_frame const* id3_metadata_getpictureframebytype(const struct id3_tag* tag, enum id3_picture_type picture_type) { int i; union id3_field const *field; struct id3_frame const *frame; for (i=0; ; ++i) { frame = id3_tag_findframe(tag, "APIC", i); if (frame == 0) return 0; field = id3_frame_field(frame, 2); if (field == 0) return 0; if (id3_field_getint(field)==picture_type) break; } return 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']); }
char id3_metadata_getrating(const struct id3_tag* tag) { union id3_field const *field; struct id3_frame const *frame; frame = id3_tag_findframe(tag, "POPM", 0); if (frame) { field = id3_frame_field(frame, 1); if (field) { // media monkey's value return (id3_field_getint(field) / 50) + '0'; } } else { const id3_ucs4_t *ucs4 = id3_metadata_getusertext(tag, "RATING"); if (ucs4 && *ucs4 > '0' && *ucs4 < '6') return (char)*ucs4; } return '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); }
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; }
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; }
/* Parse mp3 RVA2 frame. Shamelessly stolen from madplay. */ static int parse_rva2(struct id3_tag * tag, struct replay_gain_info * replay_gain_info) { struct id3_frame const * frame; id3_latin1_t const *id; id3_byte_t const *data; id3_length_t length; int found; enum { CHANNEL_OTHER = 0x00, CHANNEL_MASTER_VOLUME = 0x01, CHANNEL_FRONT_RIGHT = 0x02, CHANNEL_FRONT_LEFT = 0x03, CHANNEL_BACK_RIGHT = 0x04, CHANNEL_BACK_LEFT = 0x05, CHANNEL_FRONT_CENTRE = 0x06, CHANNEL_BACK_CENTRE = 0x07, CHANNEL_SUBWOOFER = 0x08 }; found = 0; /* relative volume adjustment information */ frame = id3_tag_findframe(tag, "RVA2", 0); if (!frame) return 0; id = id3_field_getlatin1(id3_frame_field(frame, 0)); data = id3_field_getbinarydata(id3_frame_field(frame, 1), &length); if (!id || !data) return 0; /* * "The 'identification' string is used to identify the * situation and/or device where this adjustment should apply. * The following is then repeated for every channel * * Type of channel $xx * Volume adjustment $xx xx * Bits representing peak $xx * Peak volume $xx (xx ...)" */ while (length >= 4) { unsigned int peak_bytes; peak_bytes = (data[3] + 7) / 8; if (4 + peak_bytes > length) break; if (data[0] == CHANNEL_MASTER_VOLUME) { signed int voladj_fixed; double voladj_float; /* * "The volume adjustment is encoded as a fixed * point decibel value, 16 bit signed integer * representing (adjustment*512), giving +/- 64 * dB with a precision of 0.001953125 dB." */ voladj_fixed = (data[1] << 8) | (data[2] << 0); voladj_fixed |= -(voladj_fixed & 0x8000); voladj_float = (double) voladj_fixed / 512; replay_gain_info->tuples[REPLAY_GAIN_TRACK].peak = voladj_float; replay_gain_info->tuples[REPLAY_GAIN_ALBUM].peak = voladj_float; g_debug("parseRVA2: Relative Volume " "%+.1f dB adjustment (%s)\n", voladj_float, id); found = 1; break; } data += 4 + peak_bytes; length -= 4 + peak_bytes; } return found; }
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; }