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; }
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; }
/* ** ustring getFrame(const char *frameID) ** ** Return frame text by frameID. Frame ID is a four character string defined to uniquely ** identify a frame. Details see http://www.id3.org ** */ ustring CMP3ID3::getFrame(const char *frameID){ if ( m_pID3Tag == NULL || m_pID3File == NULL ) return ustring((unsigned char *)""); ustring str = ustring((unsigned char *)""); //Search for given frame by frame id struct id3_frame *pFrame = id3_tag_findframe(m_pID3Tag,frameID,0); if ( pFrame == NULL ) return ustring((unsigned char *)""); union id3_field field = pFrame->fields[1]; id3_ucs4_t const *pTemp = id3_field_getstrings(&field,0); if ( !strcmp(frameID,"TCON") ){ //If the frameID is TCON, we then retreive genre name using id3_genre_name id3_ucs4_t const *pGenre = id3_genre_name(pTemp); pTemp = pGenre; } id3_latin1_t *pStrLatinl; if ( pTemp != NULL ){ pStrLatinl = id3_ucs4_latin1duplicate(pTemp); str = pStrLatinl; delete pStrLatinl; } return str; }
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); }
/** * 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* 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; }
/** * 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); } }
/** * Import all known MusicBrainz tags from TXXX frames. */ static void tag_id3_import_musicbrainz(struct tag *mpd_tag, struct id3_tag *id3_tag) { for (unsigned i = 0;; ++i) { const struct id3_frame *frame; id3_utf8_t *name, *value; enum tag_type type; frame = id3_tag_findframe(id3_tag, "TXXX", i); if (frame == NULL) break; name = tag_id3_getstring(frame, 1); if (name == NULL) continue; type = tag_id3_parse_txxx_name((const char*)name); free(name); if (type == TAG_NUM_OF_ITEM_TYPES) continue; value = tag_id3_getstring(frame, 2); if (value == NULL) continue; tag_add_item(mpd_tag, type, (const char*)value); free(value); } }
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; }
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'; }
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); }
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; }
/* * NAME: v1->render() * DESCRIPTION: render an ID3v1 (or ID3v1.1) tag */ static id3_length_t v1_render(struct id3_tag const *tag, id3_byte_t *buffer) { struct id3_frame *frame; unsigned int number, i; if (buffer == 0) return 128; id3_render_immediate(&buffer, "TAG", 3); v1_renderstr(tag, ID3_FRAME_TITLE, &buffer, 30); v1_renderstr(tag, ID3_FRAME_ARTIST, &buffer, 30); v1_renderstr(tag, ID3_FRAME_ALBUM, &buffer, 30); v1_renderstr(tag, ID3_FRAME_YEAR, &buffer, 4); v1_renderstr(tag, ID3_FRAME_COMMENT, &buffer, 30); frame = id3_tag_findframe(tag, ID3_FRAME_TRACK, 0); if (frame) { number = id3_ucs4_getnumber(id3_field_getstrings(&frame->fields[1], 0)); if (number & 0xff) { buffer[-2] = 0; buffer[-1] = number; } } frame = id3_tag_findframe(tag, ID3_FRAME_GENRE, 0); number = frame ? id3_ucs4_getnumber(id3_field_getstrings(&frame->fields[1], 0)) : 0xff; id3_render_int(&buffer, number, 1); /* make sure the tag is not empty */ buffer -= 128; for (i = 3; i < 127; ++i) { if (buffer[i] != ' ') break; } return (i == 127 && buffer[127] == 0xff) ? 0 : 128; }
static struct replay_gain_info * parse_id3_replay_gain_info(struct id3_tag *tag) { int i; char *key; char *value; struct id3_frame *frame; bool found = false; struct replay_gain_info *replay_gain_info; replay_gain_info = replay_gain_info_new(); for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) { if (frame->nfields < 3) continue; key = (char *) id3_ucs4_latin1duplicate(id3_field_getstring (&frame->fields[1])); value = (char *) id3_ucs4_latin1duplicate(id3_field_getstring (&frame->fields[2])); if (strcasecmp(key, "replaygain_track_gain") == 0) { replay_gain_info->tuples[REPLAY_GAIN_TRACK].gain = atof(value); found = true; } else if (strcasecmp(key, "replaygain_album_gain") == 0) { replay_gain_info->tuples[REPLAY_GAIN_ALBUM].gain = atof(value); found = true; } else if (strcasecmp(key, "replaygain_track_peak") == 0) { replay_gain_info->tuples[REPLAY_GAIN_TRACK].peak = atof(value); found = true; } else if (strcasecmp(key, "replaygain_album_peak") == 0) { replay_gain_info->tuples[REPLAY_GAIN_ALBUM].peak = atof(value); found = true; } free(key); free(value); } if (!found) { /* fall back on RVA2 if no replaygain tags found */ found = parse_rva2(tag, replay_gain_info); } if (found) return replay_gain_info; replay_gain_info_free(replay_gain_info); return NULL; }
static char *get_tag (struct id3_tag *tag, const char *what) { struct id3_frame *frame; union id3_field *field; const id3_ucs4_t *ucs4; char *comm = NULL; frame = id3_tag_findframe (tag, what, 0); if (frame && (field = &frame->fields[1])) { ucs4 = id3_field_getstrings (field, 0); if (ucs4) comm = (char *)id3_ucs4_utf8duplicate (ucs4); } return comm; }
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; }
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); } }
static void v1_renderstr(struct id3_tag const *tag, char const *frameid, id3_byte_t **buffer, id3_length_t length) { struct id3_frame *frame; id3_ucs4_t const *string; frame = id3_tag_findframe(tag, frameid, 0); if (frame == 0) string = id3_ucs4_empty; else { if (strcmp(frameid, ID3_FRAME_COMMENT) == 0) string = id3_field_getfullstring(&frame->fields[3]); else string = id3_field_getstrings(&frame->fields[1], 0); } id3_render_paddedstring(buffer, string, length); }
static char *get_tag (struct id3_tag *tag, const char *what) { struct id3_frame *frame; union id3_field *field; const id3_ucs4_t *ucs4; char *comm = NULL; frame = id3_tag_findframe (tag, what, 0); if (frame && (field = &frame->fields[1])) { ucs4 = id3_field_getstrings (field, 0); if (ucs4) { /* Workaround for ID3 tags v1/v1.1 where the encoding * is latin1. */ union id3_field *encoding_field = &frame->fields[0]; if ((id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1) || ((options_get_int ("EnforceTagsEncoding") && (id3_field_gettextencoding((encoding_field)) == ID3_FIELD_TEXTENCODING_ISO_8859_1)))) { char *t; comm = (char *)id3_ucs4_latin1duplicate (ucs4); #ifdef HAVE_RCC if (options_get_int("UseRCC")) comm = do_rcc (comm); else { #endif /* HAVE_RCC */ t = comm; comm = id3v1_fix (comm); free (t); #ifdef HAVE_RCC } #endif /* HAVE_RCC */ } else comm = (char *)id3_ucs4_utf8duplicate (ucs4); } } return comm; }
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; }
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']); }
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_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; }
static bool parse_id3_mixramp(char **mixramp_start, char **mixramp_end, struct id3_tag *tag) { int i; char *key; char *value; struct id3_frame *frame; bool found = false; *mixramp_start = NULL; *mixramp_end = NULL; for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) { if (frame->nfields < 3) continue; key = (char *) id3_ucs4_latin1duplicate(id3_field_getstring (&frame->fields[1])); value = (char *) id3_ucs4_latin1duplicate(id3_field_getstring (&frame->fields[2])); if (g_ascii_strcasecmp(key, "mixramp_start") == 0) { *mixramp_start = g_strdup(value); found = true; } else if (g_ascii_strcasecmp(key, "mixramp_end") == 0) { *mixramp_end = g_strdup(value); found = true; } free(key); free(value); } return found; }
wxString GetID3FieldStr(struct id3_tag *tp, const char *name) { struct id3_frame *frame; frame = id3_tag_findframe(tp, name, 0); if (frame) { const id3_ucs4_t *ustr; if (strcmp(name, ID3_FRAME_COMMENT) == 0) ustr = id3_field_getfullstring(&frame->fields[3]); else ustr = id3_field_getstrings(&frame->fields[1], 0); if (ustr) { char *str = (char *)id3_ucs4_utf8duplicate(ustr); wxString s = UTF8CTOWX(str); free(str); return s; } } return wxT(""); }
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'; }
/* stolen from mpg321 * * Convenience for retrieving already formatted id3 data * what parameter is one of * ID3_FRAME_TITLE * ID3_FRAME_ARTIST * ID3_FRAME_ALBUM * ID3_FRAME_YEAR * ID3_FRAME_COMMENT * ID3_FRAME_GENRE */ string LibMadWrapper::id3_get_tag(struct id3_tag const *tag, char const *what) { struct id3_frame const *frame = NULL; union id3_field const *field = NULL; int nstrings; int avail; int j; int tocopy; int len; char printable[1024]; id3_ucs4_t const *ucs4 = NULL; id3_latin1_t *latin1 = NULL; memset(printable, '\0', 1024); avail = 1024; if (strcmp(what, ID3_FRAME_COMMENT) == 0) { /*There may be sth wrong. I did not fully understand how to use libid3tag for retrieving comments */ j = 0; frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, j++); if (!frame) { return ""; } ucs4 = id3_field_getfullstring(&frame->fields[3]); if (!ucs4) { return ""; } latin1 = id3_ucs4_latin1duplicate(ucs4); if (!latin1 || strlen(reinterpret_cast<char *>(latin1)) == 0) { return ""; } len = strlen(reinterpret_cast<char *>(latin1)); if (avail > len) { tocopy = len; } else { tocopy = 0; } if (!tocopy) { return ""; } avail -= tocopy; strncat(printable, reinterpret_cast<char *>(latin1), tocopy); free(latin1); } else { frame = id3_tag_findframe(tag, what, 0); if (!frame) { return ""; } field = &frame->fields[1]; nstrings = id3_field_getnstrings(field); for (j = 0; j < nstrings; ++j) { ucs4 = id3_field_getstrings(field, j); if (!ucs4) { return ""; } if (strcmp(what, ID3_FRAME_GENRE) == 0) { ucs4 = id3_genre_name(ucs4); } latin1 = id3_ucs4_latin1duplicate(ucs4); if (!latin1) { break; } len = strlen(reinterpret_cast<char *>(latin1)); if (avail > len) { tocopy = len; } else { tocopy = 0; } if (!tocopy) { break; } avail -= tocopy; strncat(printable, reinterpret_cast<char *>(latin1), tocopy); free(latin1); } } return string(printable); }