/* This will try to convert a string to utf-8, */ static id3_utf8_t * import_id3_string(bool is_id3v1, const id3_ucs4_t *ucs4) { id3_utf8_t *utf8, *utf8_stripped = NULL; id3_latin1_t *isostr; const char *encoding; bool is_utf8; encoding = config_get_string(CONF_ID3V1_ENCODING, NULL); isostr = id3_ucs4_latin1duplicate(ucs4); if (G_UNLIKELY(!isostr)) { return NULL; } is_utf8 = check_utf8((const unsigned char *)isostr, strlen((const char *)isostr)); if(is_utf8) { utf8 = id3_ucs4_utf8duplicate(ucs4); goto done; } /* use encoding field here? */ if (is_id3v1 && encoding) { utf8 = import_8bit_string(isostr, encoding); } else { utf8 = id3_ucs4_utf8duplicate(ucs4); if(!check_utf8((unsigned char *)utf8, strlen((const char *)utf8)) && encoding) { id3_utf8_t *tmp = import_8bit_string(isostr, encoding); if(tmp) { g_free(utf8); utf8 = tmp; } } } done: if(isostr) g_free(isostr); if(utf8) { utf8_stripped = (id3_utf8_t *)g_strdup(g_strstrip((gchar *)utf8)); g_free(utf8); return utf8_stripped; } return NULL; }
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; }
wxString GetGenreNum(int i) { #ifdef USE_LIBID3TAG id3_latin1_t i_latin1[50]; id3_ucs4_t *i_ucs4; const id3_ucs4_t *genre_ucs4; sprintf((char *)i_latin1, "%d", i); i_ucs4 = (id3_ucs4_t *)malloc((id3_latin1_length(i_latin1) + 1) * sizeof(*i_ucs4)); if (i_ucs4) { id3_latin1_decode(i_latin1, i_ucs4); genre_ucs4 = id3_genre_name(i_ucs4); char *genre_char = (char *)id3_ucs4_utf8duplicate(genre_ucs4); wxString genreStr = UTF8CTOWX(genre_char); free(genre_char); free(i_ucs4); return genreStr; } #endif // ifdef USE_LIBID3TAG return wxT(""); }
wchar_t* GetMP3Text(id3_field_textencoding encoding, const id3_field* field, const id3_ucs4_t* ucs4) { if (ucs4 == NULL) return NULL; wchar_t* content = NULL; switch(encoding) { case ID3_FIELD_TEXTENCODING_ISO_8859_1: { char* p = (char*)id3_ucs4_latin1duplicate(ucs4); content = CharToWideChar(p, strlen(p)); free(p); } break; case ID3_FIELD_TEXTENCODING_UTF_8: { char* p = (char*)id3_ucs4_utf8duplicate(ucs4); if (p != NULL) { content = UTF8toWideChar(p, strlen(p)); free(p); } } break; case ID3_FIELD_TEXTENCODING_UTF_16: { char* p = (char*)id3_ucs4_utf8duplicate(ucs4); if (p != NULL) { content = UTF8toWideChar(p, strlen(p)); free(p); } } break; default: break; } return content; }
/* This will try to convert a string to utf-8, */ static id3_utf8_t * processID3FieldString (int is_id3v1, const id3_ucs4_t *ucs4, int type, enum id3_field_textencoding id3_encoding) { id3_utf8_t *utf8, *utf8_stripped; id3_utf8_t *isostr; const char *encoding; if (type == TAG_ITEM_GENRE) ucs4 = id3_genre_name(ucs4); /* use encoding field here? */ if ((encoding = config_get_string(CONF_ID3V1_ENCODING, NULL)) != NULL) { if(!is_id3v1 && (id3_encoding == ID3_FIELD_TEXTENCODING_UTF_16 || id3_encoding == ID3_FIELD_TEXTENCODING_UTF_8)) isostr = id3_ucs4_utf8duplicate(ucs4); else isostr = (id3_utf8_t*)id3_ucs4_latin1duplicate(ucs4); if (G_UNLIKELY(!isostr)) { return NULL; } if(id3_encoding == 0xff || id3_encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1) { utf8 = (id3_utf8_t *) g_convert_with_fallback((const char*)isostr, -1, "utf-8", encoding, NULL, NULL, NULL, NULL); } else utf8 = (id3_utf8_t *) g_strdup((const char*)isostr); if (utf8 == NULL) { g_debug("Unable to convert %s string to UTF-8: '%s'", encoding, isostr); g_free(isostr); return NULL; } g_free(isostr); } else { utf8 = id3_ucs4_utf8duplicate(ucs4); if (G_UNLIKELY(!utf8)) { return NULL; } } utf8_stripped = (id3_utf8_t *)g_strdup(g_strstrip((gchar *)utf8)); g_free(utf8); return utf8_stripped; }
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; }
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; }
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); }
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; }
/* This will try to convert a string to utf-8, */ static id3_utf8_t * import_id3_string(bool is_id3v1, const id3_ucs4_t *ucs4) { id3_utf8_t *utf8, *utf8_stripped; id3_latin1_t *isostr; const char *encoding; /* use encoding field here? */ if (is_id3v1 && (encoding = config_get_string(CONF_ID3V1_ENCODING, NULL)) != NULL) { isostr = id3_ucs4_latin1duplicate(ucs4); if (G_UNLIKELY(!isostr)) { return NULL; } utf8 = (id3_utf8_t *) g_convert_with_fallback((const char*)isostr, -1, "utf-8", encoding, NULL, NULL, NULL, NULL); if (utf8 == NULL) { g_debug("Unable to convert %s string to UTF-8: '%s'", encoding, isostr); g_free(isostr); return NULL; } g_free(isostr); } else { utf8 = id3_ucs4_utf8duplicate(ucs4); if (G_UNLIKELY(!utf8)) { return NULL; } } utf8_stripped = (id3_utf8_t *)g_strdup(g_strstrip((gchar *)utf8)); g_free(utf8); return utf8_stripped; }
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(""); }
int scan_mp3_get_mp3tags(char *file, MP3FILE *pmp3) { struct id3_file *pid3file; struct id3_tag *pid3tag; struct id3_frame *pid3frame; int err; int index; int used; char *utf8_text; int genre=WINAMP_GENRE_UNKNOWN; int have_utf8; int have_text; id3_ucs4_t const *native_text; char *tmp; int got_numeric_genre; int rating; char *conversion_codepage; pid3file=id3_file_open(file,ID3_FILE_MODE_READONLY); if(!pid3file) { DPRINTF(E_WARN,L_SCAN,"Cannot open %s\n",file); return FALSE; } pid3tag=id3_file_tag(pid3file); if(!pid3tag) { err=errno; id3_file_close(pid3file); errno=err; DPRINTF(E_WARN,L_SCAN,"Cannot get ID3 tag for %s\n",file); return FALSE; } DPRINTF(E_SPAM,L_SCAN,"Starting mp3 tag scan\n"); conversion_codepage = conf_alloc_string("scanning","mp3_tag_codepage", "ISO-8859-1"); index=0; while((pid3frame=id3_tag_findframe(pid3tag,"",index))) { used=0; utf8_text=NULL; native_text=NULL; have_utf8=0; have_text=0; DPRINTF(E_SPAM,L_SCAN,"Found tag %s\n",pid3frame->id); if(!strcmp(pid3frame->id,"YTCP")) { /* for id3v2.2 */ pmp3->compilation = 1; DPRINTF(E_DBG,L_SCAN,"Compilation: %d\n", pmp3->compilation); } if(((pid3frame->id[0] == 'T')||(strcmp(pid3frame->id,"COMM")==0)) && (id3_field_getnstrings(&pid3frame->fields[1]))) have_text=1; if(have_text) { native_text=id3_field_getstrings(&pid3frame->fields[1],0); if(native_text) { have_utf8=1; utf8_text = (char*)id3_ucs4_utf8duplicate(native_text); if(utf8_text) mem_register(utf8_text,0); if(id3_field_gettextencoding(&pid3frame->fields[1]) == ID3_FIELD_TEXTENCODING_ISO_8859_1) { #ifdef HAVE_ICONV /* this is kinda cheesy, but ucs4* == char* for 8859-1 */ free(utf8_text); utf8_text = (char*)util_xtoutf8_alloc((unsigned char*)native_text, strlen((char*)native_text), conversion_codepage); #endif } if(!strcmp(pid3frame->id,"TIT2")) { /* Title */ used=1; pmp3->title = utf8_text; DPRINTF(E_DBG,L_SCAN," Title: %s\n",utf8_text); } else if(!strcmp(pid3frame->id,"TPE1")) { used=1; pmp3->artist = utf8_text; DPRINTF(E_DBG,L_SCAN," Artist: %s\n",utf8_text); } else if(!strcmp(pid3frame->id,"TALB")) { used=1; pmp3->album = utf8_text; DPRINTF(E_DBG,L_SCAN," Album: %s\n",utf8_text); } else if(!strcmp(pid3frame->id,"TCOM")) { used=1; pmp3->composer = utf8_text; DPRINTF(E_DBG,L_SCAN," Composer: %s\n",utf8_text); } else if(!strcmp(pid3frame->id,"TIT1")) { used=1; pmp3->grouping = utf8_text; DPRINTF(E_DBG,L_SCAN," Grouping: %s\n",utf8_text); } else if(!strcmp(pid3frame->id,"TPE2")) { used=1; pmp3->orchestra = utf8_text; DPRINTF(E_DBG,L_SCAN," Orchestra: %s\n",utf8_text); } else if(!strcmp(pid3frame->id,"TPE3")) { used=1; pmp3->conductor = utf8_text; DPRINTF(E_DBG,L_SCAN," Conductor: %s\n",utf8_text); } else if(!strcmp(pid3frame->id,"TCON")) { used=1; pmp3->genre = utf8_text; got_numeric_genre=0; DPRINTF(E_DBG,L_SCAN," Genre: %s\n",utf8_text); if(pmp3->genre) { if(!strlen(pmp3->genre)) { genre=WINAMP_GENRE_UNKNOWN; got_numeric_genre=1; } else if (scan_mp3_is_numeric(pmp3->genre)) { genre=atoi(pmp3->genre); got_numeric_genre=1; } else if ((pmp3->genre[0] == '(') && (isdigit(pmp3->genre[1]))) { genre=atoi((char*)&pmp3->genre[1]); got_numeric_genre=1; } if(got_numeric_genre) { if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN)) genre=WINAMP_GENRE_UNKNOWN; free(pmp3->genre); pmp3->genre=strdup(scan_winamp_genre[genre]); } } } else if(!strcmp(pid3frame->id,"COMM")) { used=1; pmp3->comment = utf8_text; DPRINTF(E_DBG,L_SCAN," Comment: %s\n",pmp3->comment); } else if(!strcmp(pid3frame->id,"TPOS")) { tmp=utf8_text; strsep(&tmp,"/"); if(tmp) { pmp3->total_discs=atoi(tmp); } pmp3->disc=atoi(utf8_text); DPRINTF(E_DBG,L_SCAN," Disc %d of %d\n",pmp3->disc,pmp3->total_discs); } else if(!strcmp(pid3frame->id,"TRCK")) { tmp=utf8_text; strsep(&tmp,"/"); if(tmp) { pmp3->total_tracks=atoi(tmp); } pmp3->track=atoi(utf8_text); DPRINTF(E_DBG,L_SCAN," Track %d of %d\n",pmp3->track,pmp3->total_tracks); } else if(!strcmp(pid3frame->id,"TDRC")) { pmp3->year = atoi(utf8_text); DPRINTF(E_DBG,L_SCAN," Year: %d\n",pmp3->year); } else if(!strcmp(pid3frame->id,"TLEN")) { pmp3->song_length = atoi(utf8_text); /* now in ms */ DPRINTF(E_DBG,L_SCAN," Length: %d\n", pmp3->song_length); } else if(!strcmp(pid3frame->id,"TBPM")) { pmp3->bpm = atoi(utf8_text); DPRINTF(E_DBG,L_SCAN,"BPM: %d\n", pmp3->bpm); } else if(!strcmp(pid3frame->id,"TCMP")) { /* for id3v2.3 */ pmp3->compilation = (char)atoi(utf8_text); DPRINTF(E_DBG,L_SCAN,"Compilation: %d\n", pmp3->compilation); } } } /* can check for non-text tags here */ if((!used) && (have_utf8) && (utf8_text)) free(utf8_text); if((!strcmp(pid3frame->id,"POPM")) && (pid3frame->nfields == 3)) { rating = id3_field_getint(&pid3frame->fields[1]); if(rating >= 0x01) pmp3->rating = 20; if(rating >= 0x40) pmp3->rating = 40; if(rating >= 0x80) pmp3->rating = 60; if(rating >= 0xC4) pmp3->rating = 80; if(rating >= 0xFF) pmp3->rating = 100; } /* v2 COMM tags are a bit different than v1 */ if((!strcmp(pid3frame->id,"COMM")) && (pid3frame->nfields == 4)) { /* Make sure it isn't a application-specific comment... * This currently includes the following: * * iTunes_CDDB_IDs * iTunNORM * * If other apps stuff crap into comment fields, then we'll ignore them * here. */ native_text=id3_field_getstring(&pid3frame->fields[2]); if(native_text) { utf8_text=(char*)id3_ucs4_utf8duplicate(native_text); if(utf8_text) mem_register(utf8_text,0); if((utf8_text) && (strncasecmp(utf8_text,"iTun",4) != 0)) { /* it's a real comment */ if(utf8_text) free(utf8_text); native_text=id3_field_getfullstring(&pid3frame->fields[3]); if(native_text) { if(pmp3->comment) free(pmp3->comment); utf8_text=(char*)id3_ucs4_utf8duplicate(native_text); if(utf8_text) { mem_register(utf8_text,0); pmp3->comment=utf8_text; } } } else { if(utf8_text) free(utf8_text); } } } index++; } free(conversion_codepage); id3_file_close(pid3file); DPRINTF(E_DBG,L_SCAN,"Got id3 tag successfully\n"); return TRUE; }
static gchar * getFrameText (struct id3_tag *tag, char *frame_name) { const id3_ucs4_t *string; struct id3_frame *frame; union id3_field *field; gchar *utf8 = NULL; enum id3_field_textencoding encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1; frame = id3_tag_findframe (tag, frame_name, 0); if (!frame) return NULL; /* Find the encoding used for the field */ field = id3_frame_field (frame, 0); //printf ("field: %p\n", field); if (field && (id3_field_type (field) == ID3_FIELD_TYPE_TEXTENCODING)) { encoding = field->number.value; //printf ("encoding: %d\n", encoding); } if (strcmp (frame_name, ID3_FRAME_COMMENT) == 0) field = id3_frame_field (frame, 3); else field = id3_frame_field (frame, 1); //printf ("field: %p\n", field); if (!field) return NULL; if (strcmp (frame_name, ID3_FRAME_COMMENT) == 0) string = id3_field_getfullstring (field); else string = id3_field_getstrings (field, 0); // g_debug("string: %s\n", string); if (!string) return NULL; if (strcmp (frame_name, ID3_FRAME_GENRE) == 0) string = id3_genre_name (string); if (encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1) { /* ISO_8859_1 is just a "marker" -- most people just drop whatever coding system they are using into it, so we use charset_to_utf8() to convert to utf8 */ id3_latin1_t *raw = id3_ucs4_latin1duplicate (string); utf8 = (gchar *) charset_to_utf8 (raw); g_free (raw); } else { /* Standard unicode is being used -- we won't have to worry about charsets then. */ // g_debug("This frame is a Unicode frame!\n"); utf8 = (gchar *) id3_ucs4_utf8duplicate (string); } // g_debug("Found tag: %s, value: %s\n", frame_name, utf8); return utf8; }
JNIEXPORT jstring JNICALL Java_com_ssb_droidsound_utils_ID3Tag_getStringInfo(JNIEnv *env, jobject obj, jint what) { struct id3_file *id3file = (struct id3_file*)env->GetLongField(obj, refField); struct id3_tag *tag = (struct id3_tag*)env->GetLongField(obj, tagRefField); __android_log_print(ANDROID_LOG_VERBOSE, "ID3Tag", "Get String Info %p %p", id3file, tag); if(!tag && id3file) tag = id3_file_tag(id3file); if(!tag) return 0; const id3_ucs4_t *title = NULL; struct id3_frame *frame = NULL; __android_log_print(ANDROID_LOG_VERBOSE, "ID3Tag", "id3tag %p", tag); switch(what) { case INFO_TITLE: frame = id3_tag_findframe(tag, ID3_FRAME_TITLE, 0); break; case INFO_AUTHOR: frame = id3_tag_findframe(tag, ID3_FRAME_ARTIST, 0); break; case INFO_COPYRIGHT: frame = id3_tag_findframe(tag, ID3_FRAME_YEAR, 0); break; case ID3INFO_GENRE: frame = id3_tag_findframe(tag, ID3_FRAME_GENRE, 0); if(frame) { title = id3_field_getstrings(&frame->fields[1], 0); title = id3_genre_name(title); } break; case ID3INFO_ALBUM: frame = id3_tag_findframe(tag, ID3_FRAME_ALBUM, 0); break; case ID3INFO_TRACK: frame = id3_tag_findframe(tag, ID3_FRAME_TRACK, 0); break; case ID3INFO_COMMENT: frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, 0); if(frame) { __android_log_print(ANDROID_LOG_VERBOSE, "ID3Tag", "COMMENT %d fields", frame->nfields); if(frame->nfields >= 4) title = id3_field_getfullstring(&frame->fields[3]); } break; } if(frame) { __android_log_print(ANDROID_LOG_VERBOSE, "ID3Tag", "frame %p %d", frame, what); if(title == NULL) title = id3_field_getstrings(&frame->fields[1], 0); if(title) { __android_log_print(ANDROID_LOG_VERBOSE, "ID3Tag", "title %p", title); id3_utf8_t *titleu8 = id3_ucs4_utf8duplicate(title); jstring j = env->NewStringUTF((const char *)titleu8); return j; } } return NULL; }
static int _get_dsftags(char *file, struct song_metadata *psong) { struct id3_tag *pid3tag; struct id3_frame *pid3frame; int err; int index; int used; unsigned char *utf8_text; int genre = WINAMP_GENRE_UNKNOWN; int have_utf8; int have_text; id3_ucs4_t const *native_text; char *tmp; int got_numeric_genre; id3_byte_t const *image; id3_length_t image_size = 0; FILE *fp; struct id3header *pid3; uint32_t len; unsigned char hdr[28] = {0}; uint64_t total_size = 0; uint64_t pointer_to_metadata_chunk = 0; uint64_t metadata_chunk_size = 0; unsigned char *id3tagbuf = NULL; //DEBUG DPRINTF(E_DEBUG,L_SCANNER,"Getting DSF file info\n"); if((fp = fopen(file, "rb")) == NULL) { DPRINTF(E_WARN, L_SCANNER, "Could not create file handle\n"); return -1; } len = 28; if(!(len = fread(hdr, len, 1,fp))) { DPRINTF(E_WARN, L_SCANNER, "Could not read DSD Chunk from %s\n", file); fclose(fp); return -1; } if(strncmp((char*)hdr, "DSD ", 4)) { DPRINTF(E_WARN, L_SCANNER, "Invalid DSD Chunk header in %s\n", file); fclose(fp); return -1; } total_size = GET_DSF_INT64(hdr + 12); pointer_to_metadata_chunk = GET_DSF_INT64(hdr + 20); //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "%llu\n", total_size); //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "%llu\n", pointer_to_metadata_chunk); //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "%llu\n", metadata_chunk_size); //check invalid metadata if(total_size == 0) { fclose(fp); DPRINTF(E_INFO, L_SCANNER, "Invalid TotalDataSize in %s\n", file); return 0; } if(pointer_to_metadata_chunk == 0) { fclose(fp); DPRINTF(E_INFO, L_SCANNER, "Metadata doesn't exist %s\n", file); return 0; } if(total_size > pointer_to_metadata_chunk) { metadata_chunk_size = total_size - pointer_to_metadata_chunk; } else { fclose(fp); DPRINTF(E_INFO, L_SCANNER, "Invalid PointerToMetadata in %s\n", file); return 0; } fseeko(fp, pointer_to_metadata_chunk,SEEK_SET); id3tagbuf = (unsigned char *)malloc(sizeof(unsigned char)*metadata_chunk_size); if(id3tagbuf == NULL) { fclose(fp); DPRINTF(E_WARN, L_SCANNER, "Out of memory.Big MetadataSize in %s\n",file); return -1; } memset(id3tagbuf, 0,sizeof(unsigned char)*metadata_chunk_size); if(!(len = fread(id3tagbuf,metadata_chunk_size,1,fp))) { fclose(fp); free(id3tagbuf); DPRINTF(E_WARN, L_SCANNER, "Could not read Metadata Chunk from %s\n", file); return -1; } pid3tag = id3_tag_parse(id3tagbuf,metadata_chunk_size); if(!pid3tag) { free(id3tagbuf); err = errno; errno = err; DPRINTF(E_WARN, L_SCANNER, "Cannot get ID3 tag for %s\n", file); return -1; } pid3 = (struct id3header*)id3tagbuf; if(strncmp((char*)pid3->id, "ID3", 3) == 0) { char tagversion[16]; /* found an ID3 header... */ snprintf(tagversion, sizeof(tagversion), "ID3v2.%d.%d", pid3->version[0], pid3->version[1]); psong->tagversion = strdup(tagversion); } pid3 = NULL; index = 0; while((pid3frame = id3_tag_findframe(pid3tag, "", index))) { used = 0; utf8_text = NULL; native_text = NULL; have_utf8 = 0; have_text = 0; if(!strcmp(pid3frame->id, "YTCP")) /* for id3v2.2 */ { psong->compilation = 1; DPRINTF(E_DEBUG, L_SCANNER, "Compilation: %d [%s]\n", psong->compilation, basename(file)); } else if(!strcmp(pid3frame->id, "APIC") && !image_size) { if( (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpeg") == 0) || (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpg") == 0) || (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "jpeg") == 0) ) { image = id3_field_getbinarydata(&pid3frame->fields[4], &image_size); if( image_size ) { psong->image = malloc(image_size); memcpy(psong->image, image, image_size); psong->image_size = image_size; //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Found thumbnail: %d\n", psong->image_size); } } } if(((pid3frame->id[0] == 'T') || (strcmp(pid3frame->id, "COMM") == 0)) && (id3_field_getnstrings(&pid3frame->fields[1]))) have_text = 1; if(have_text) { native_text = id3_field_getstrings(&pid3frame->fields[1], 0); if(native_text) { have_utf8 = 1; if(lang_index >= 0) utf8_text = _get_utf8_text(native_text); // through iconv else utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); if(!strcmp(pid3frame->id, "TIT2")) { used = 1; psong->title = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TPE1")) { used = 1; psong->contributor[ROLE_ARTIST] = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TALB")) { used = 1; psong->album = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TCOM")) { used = 1; psong->contributor[ROLE_COMPOSER] = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TIT1")) { used = 1; psong->grouping = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TPE2")) { used = 1; psong->contributor[ROLE_BAND] = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TPE3")) { used = 1; psong->contributor[ROLE_CONDUCTOR] = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TCON")) { used = 1; psong->genre = (char*)utf8_text; got_numeric_genre = 0; if(psong->genre) { if(!strlen(psong->genre)) { genre = WINAMP_GENRE_UNKNOWN; got_numeric_genre = 1; } else if(isdigit(psong->genre[0])) { genre = atoi(psong->genre); got_numeric_genre = 1; } else if((psong->genre[0] == '(') && (isdigit(psong->genre[1]))) { genre = atoi((char*)&psong->genre[1]); got_numeric_genre = 1; } if(got_numeric_genre) { if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN)) genre = WINAMP_GENRE_UNKNOWN; free(psong->genre); psong->genre = strdup(winamp_genre[genre]); } } } else if(!strcmp(pid3frame->id, "COMM")) { used = 1; psong->comment = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TPOS")) { tmp = (char*)utf8_text; strsep(&tmp, "/"); if(tmp) { psong->total_discs = atoi(tmp); } psong->disc = atoi((char*)utf8_text); } else if(!strcmp(pid3frame->id, "TRCK")) { tmp = (char*)utf8_text; strsep(&tmp, "/"); if(tmp) { psong->total_tracks = atoi(tmp); } psong->track = atoi((char*)utf8_text); } else if(!strcmp(pid3frame->id, "TDRC")) { psong->year = atoi((char*)utf8_text); } else if(!strcmp(pid3frame->id, "TLEN")) { psong->song_length = atoi((char*)utf8_text); } else if(!strcmp(pid3frame->id, "TBPM")) { psong->bpm = atoi((char*)utf8_text); } else if(!strcmp(pid3frame->id, "TCMP")) { psong->compilation = (char)atoi((char*)utf8_text); } } } // check if text tag if((!used) && (have_utf8) && (utf8_text)) free(utf8_text); // v2 COMM if((!strcmp(pid3frame->id, "COMM")) && (pid3frame->nfields == 4)) { native_text = id3_field_getstring(&pid3frame->fields[2]); if(native_text) { utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); if((utf8_text) && (strncasecmp((char*)utf8_text, "iTun", 4) != 0)) { // read comment free(utf8_text); native_text = id3_field_getfullstring(&pid3frame->fields[3]); if(native_text) { utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); if(utf8_text) { free(psong->comment); psong->comment = (char*)utf8_text; } } } else { free(utf8_text); } } } index++; } id3_tag_delete(pid3tag); free(id3tagbuf); fclose(fp); //DPRINTF(E_DEBUG, L_SCANNER, "Got id3tag successfully for file=%s\n", file); return 0; }
static unsigned char* _get_utf8_text(const id3_ucs4_t* native_text) { unsigned char *utf8_text = NULL; char *in, *in8, *iconv_buf; iconv_result rc; int i, n; in = (char*)id3_ucs4_latin1duplicate(native_text); if(!in) { goto out; } in8 = (char*)id3_ucs4_utf8duplicate(native_text); if(!in8) { free(in); goto out; } iconv_buf = (char*)calloc(MAX_ICONV_BUF, sizeof(char)); if(!iconv_buf) { free(in); free(in8); goto out; } i = lang_index; // (1) try utf8 -> default rc = do_iconv(iconv_map[i].cpnames[0], "UTF-8", in8, strlen(in8), iconv_buf, MAX_ICONV_BUF); if(rc == ICONV_OK) { utf8_text = (unsigned char*)in8; free(iconv_buf); } else if(rc == ICONV_TRYNEXT) { // (2) try default -> utf8 rc = do_iconv("UTF-8", iconv_map[i].cpnames[0], in, strlen(in), iconv_buf, MAX_ICONV_BUF); if(rc == ICONV_OK) { utf8_text = (unsigned char*)iconv_buf; } else if(rc == ICONV_TRYNEXT) { // (3) try other encodes for(n = 1; n < N_LANG_ALT && iconv_map[i].cpnames[n]; n++) { rc = do_iconv("UTF-8", iconv_map[i].cpnames[n], in, strlen(in), iconv_buf, MAX_ICONV_BUF); if(rc == ICONV_OK) { utf8_text = (unsigned char*)iconv_buf; break; } } if(!utf8_text) { // cannot iconv utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); free(iconv_buf); } } free(in8); } free(in); out: if(!utf8_text) { utf8_text = (unsigned char*)strdup("UNKNOWN"); } return utf8_text; }
void MP3ImportFileHandle::ImportID3(Tags *tags) { #ifdef USE_LIBID3TAG struct id3_file *fp = id3_file_open(OSFILENAME(mFilename), ID3_FILE_MODE_READONLY); if (!fp) { return; } struct id3_tag *tp = id3_file_tag(fp); if (!tp) { id3_file_close(fp); return; } tags->Clear(); tags->SetID3V2( tp->options & ID3_TAG_OPTION_ID3V1 ? false : true ); // Loop through all frames for (int i = 0; i < (int) tp->nframes; i++) { struct id3_frame *frame = tp->frames[i]; // printf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id); // printf("Desc: %s\n", frame->description); // printf("Num fields: %d\n", frame->nfields); // for (int j = 0; j < (int) frame->nfields; j++) { // printf("field %d type %d\n", j, frame->fields[j].type ); // if (frame->fields[j].type == ID3_FIELD_TYPE_STRINGLIST) { // printf("num strings %d\n", frame->fields[j].stringlist.nstrings); // } // } wxString n, v; // Determine the tag name if (strcmp(frame->id, ID3_FRAME_TITLE) == 0) { n = TAG_TITLE; } else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0) { n = TAG_ARTIST; } else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0) { n = TAG_ALBUM; } else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0) { n = TAG_TRACK; } else if (strcmp(frame->id, "TYER") == 0) { n = TAG_YEAR; } else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0) { n = TAG_YEAR; } else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0) { n = TAG_COMMENTS; } else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0) { n = TAG_GENRE; } else { // Use frame description as default tag name. The descriptions // may include several "meanings" separated by "/" characters, so // we just use the first meaning n = UTF8CTOWX(frame->description).BeforeFirst(wxT('/')); } const id3_ucs4_t *ustr = NULL; if (n == TAG_COMMENTS) { ustr = id3_field_getfullstring(&frame->fields[3]); } else if (frame->nfields == 3) { ustr = id3_field_getstring(&frame->fields[1]); if (ustr) { char *str = (char *)id3_ucs4_utf8duplicate(ustr); n = UTF8CTOWX(str); free(str); } ustr = id3_field_getstring(&frame->fields[2]); } else if (frame->nfields >= 2) { ustr = id3_field_getstrings(&frame->fields[1], 0); } if (ustr) { char *str = (char *)id3_ucs4_utf8duplicate(ustr); v = UTF8CTOWX(str); free(str); } if (!n.IsEmpty() && !v.IsEmpty()) { tags->SetTag(n, v); } } // Convert v1 genre to name if (tags->HasTag(TAG_GENRE)) { long g = -1; if (tags->GetTag(TAG_GENRE).ToLong(&g)) { tags->SetTag(TAG_GENRE, tags->GetGenre(g)); } } id3_file_close(fp); #endif // ifdef USE_LIBID3TAG }
/***************************************************************************** * ParseID3Tag : parse an id3tag into the info structures *****************************************************************************/ static void ParseID3Tag( demux_meta_t *p_demux_meta, const uint8_t *p_data, int i_size ) { struct id3_tag *p_id3_tag; struct id3_frame *p_frame; vlc_meta_t *p_meta; int i; p_id3_tag = id3_tag_parse( p_data, i_size ); if( !p_id3_tag ) return; if( !p_demux_meta->p_meta ) p_demux_meta->p_meta = vlc_meta_New(); p_meta = p_demux_meta->p_meta; #define ID_IS( a ) (!strcmp( p_frame->id, a )) #define DESCR_IS( a) strstr( (char*)p_frame->description, a ) #define GET_STRING(frame,fidx) id3_ucs4_latin1duplicate( id3_field_getstring( &(frame)->fields[fidx] ) ) /* */ for( i = 0; (p_frame = id3_tag_findframe( p_id3_tag, "UFID", i )) != NULL; i++ ) { const char *psz_owner = id3_field_getlatin1( &p_frame->fields[0] ); if( !strncmp( psz_owner, "http://musicbrainz.org", 22 ) ) { id3_byte_t const * p_ufid; id3_length_t i_ufidlen; p_ufid = id3_field_getbinarydata( &p_frame->fields[1], &i_ufidlen ); char *psz_ufid = strndup( p_ufid, i_ufidlen ); vlc_meta_SetTrackID( p_meta, psz_ufid ); free( psz_ufid ); } } /* User defined text (TXXX) */ for( i = 0; (p_frame = id3_tag_findframe( p_id3_tag, "TXXX", i )) != NULL; i++ ) { /* 3 fields: 'encoding', 'description', 'value' */ char *psz_name = GET_STRING( p_frame, 1 ); char *psz_value = GET_STRING( p_frame, 2 ); vlc_meta_AddExtra( p_meta, psz_name, psz_value ); #if 0 if( !strncmp( psz_name, "MusicBrainz Artist Id", 21 ) ) vlc_meta_SetArtistID( p_meta, psz_value ); if( !strncmp( psz_desc, "MusicBrainz Album Id", 20 ) ) vlc_meta_SetAlbumID( p_meta, psz_value ); #endif free( psz_name ); free( psz_value ); } /* Relative volume adjustment */ for( i = 0; (p_frame = id3_tag_findframe( p_id3_tag, "RVA2", i )) != NULL; i++ ) { /* 2 fields: 'latin1', 'binary' */ const char *psz_type = id3_field_getlatin1( &p_frame->fields[0] ); if( !strcasecmp( psz_type, "track" ) || !strcasecmp( psz_type, "album" ) || !strcasecmp( psz_type, "normalize" ) ) { id3_byte_t const * p_data; id3_length_t i_data; p_data = id3_field_getbinarydata( &p_frame->fields[1], &i_data ); while( i_data >= 4 ) { const unsigned int i_peak_size = p_data[3]; const float f_temp = GetWBE( &p_data[1] ); const float f_gain = f_temp / 512.0; char psz_value[32]; if( i_data < i_peak_size + 4 ) break; /* only master volume */ if( p_data[0] == 0x01 ) { snprintf( psz_value, sizeof(psz_value), "%f", f_gain ); if( !strcasecmp( psz_type, "album" ) ) vlc_meta_AddExtra( p_meta, "REPLAYGAIN_ALBUM_GAIN", psz_value ); else vlc_meta_AddExtra( p_meta, "REPLAYGAIN_TRACK_GAIN", psz_value ); /* XXX I have no idea what peak unit is ... */ } i_data -= 4+i_peak_size; } } } /* TODO 'RGAD' if it is used somewhere */ /* T--- Text informations */ for( i = 0; (p_frame = id3_tag_findframe( p_id3_tag, "T", i )) != NULL; i++ ) { unsigned i_strings; /* Special case TXXX is not the same beast */ if( ID_IS( "TXXX" ) ) continue; i_strings = id3_field_getnstrings( &p_frame->fields[1] ); while( i_strings > 0 ) { char *psz_temp = id3_ucs4_utf8duplicate( id3_field_getstrings( &p_frame->fields[1], --i_strings ) ); if( ID_IS( ID3_FRAME_GENRE ) ) { char *psz_endptr; int i_genre = strtol( psz_temp, &psz_endptr, 10 ); if( psz_temp != psz_endptr && i_genre >= 0 && i_genre < NUM_GENRES ) { vlc_meta_SetGenre( p_meta, ppsz_genres[atoi(psz_temp)]); } else { /* Unknown genre */ vlc_meta_SetGenre( p_meta,psz_temp ); } } else if( ID_IS( ID3_FRAME_TITLE ) ) { vlc_meta_SetTitle( p_meta, psz_temp ); } else if( ID_IS( ID3_FRAME_ARTIST ) ) { vlc_meta_SetArtist( p_meta, psz_temp ); } else if( ID_IS( ID3_FRAME_YEAR ) ) { vlc_meta_SetDate( p_meta, psz_temp ); } else if( ID_IS( ID3_FRAME_COMMENT ) ) { vlc_meta_SetDescription( p_meta, psz_temp ); } else if( DESCR_IS( "Copyright" ) ) { vlc_meta_SetCopyright( p_meta, psz_temp ); } else if( DESCR_IS( "Publisher" ) ) { vlc_meta_SetPublisher( p_meta, psz_temp ); } else if( DESCR_IS( "Track number/position in set" ) ) { vlc_meta_SetTrackNum( p_meta, psz_temp ); } else if( DESCR_IS( "Album/movie/show title" ) ) { vlc_meta_SetAlbum( p_meta, psz_temp ); } else if( DESCR_IS( "Encoded by" ) ) { vlc_meta_SetEncodedBy( p_meta, psz_temp ); } else if( ID_IS ( "APIC" ) ) { msg_Dbg( p_demux_meta, "** Has APIC **" ); } else if( p_frame->description ) { /* Unhandled meta */ vlc_meta_AddExtra( p_meta, (char*)p_frame->description, psz_temp ); } free( psz_temp ); } } id3_tag_delete( p_id3_tag ); #undef GET_STRING #undef DESCR_IS #undef ID_IS }
void MP3ImportFileHandle::ImportID3(Tags *tags) { #ifdef USE_LIBID3TAG wxFile f; // will be closed when it goes out of scope struct id3_file *fp = NULL; if (f.Open(mFilename)) { // Use id3_file_fdopen() instead of id3_file_open since wxWidgets can open a // file with a Unicode name and id3_file_open() can't (under Windows). fp = id3_file_fdopen(f.fd(), ID3_FILE_MODE_READONLY); } if (!fp) { return; } // The file descriptor is now owned by "fp", so we must tell "f" to forget // about it. f.Detach(); struct id3_tag *tp = id3_file_tag(fp); if (!tp) { id3_file_close(fp); return; } tags->Clear(); // Loop through all frames bool have_year = false; for (int i = 0; i < (int) tp->nframes; i++) { struct id3_frame *frame = tp->frames[i]; // printf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id); // printf("Desc: %s\n", frame->description); // printf("Num fields: %d\n", frame->nfields); // for (int j = 0; j < (int) frame->nfields; j++) { // printf("field %d type %d\n", j, frame->fields[j].type ); // if (frame->fields[j].type == ID3_FIELD_TYPE_STRINGLIST) { // printf("num strings %d\n", frame->fields[j].stringlist.nstrings); // } // } wxString n, v; // Determine the tag name if (strcmp(frame->id, ID3_FRAME_TITLE) == 0) { n = TAG_TITLE; } else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0) { n = TAG_ARTIST; } else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0) { n = TAG_ALBUM; } else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0) { n = TAG_TRACK; } else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0) { // LLL: When libid3tag encounters the "TYER" tag, it converts it to a // "ZOBS" (obsolete) tag and adds a "TDRC" tag at the end of the // list of tags using the first 4 characters of the "TYER" tag. // Since we write both the "TDRC" and "TYER" tags, the "TDRC" tag // will always be encountered first in the list. We want use it // since the converted "TYER" tag may have been truncated. if (have_year) { continue; } n = TAG_YEAR; have_year = true; } else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0) { n = TAG_COMMENTS; } else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0) { n = TAG_GENRE; } else { // Use frame description as default tag name. The descriptions // may include several "meanings" separated by "/" characters, so // we just use the first meaning n = UTF8CTOWX(frame->description).BeforeFirst(wxT('/')); } const id3_ucs4_t *ustr = NULL; if (n == TAG_COMMENTS) { ustr = id3_field_getfullstring(&frame->fields[3]); } else if (frame->nfields == 3) { ustr = id3_field_getstring(&frame->fields[1]); if (ustr) { char *str = (char *)id3_ucs4_utf8duplicate(ustr); n = UTF8CTOWX(str); free(str); } ustr = id3_field_getstring(&frame->fields[2]); } else if (frame->nfields >= 2) { ustr = id3_field_getstrings(&frame->fields[1], 0); } if (ustr) { char *str = (char *)id3_ucs4_utf8duplicate(ustr); v = UTF8CTOWX(str); free(str); } if (!n.IsEmpty() && !v.IsEmpty()) { tags->SetTag(n, v); } } // Convert v1 genre to name if (tags->HasTag(TAG_GENRE)) { long g = -1; if (tags->GetTag(TAG_GENRE).ToLong(&g)) { tags->SetTag(TAG_GENRE, tags->GetGenre(g)); } } id3_file_close(fp); #endif // ifdef USE_LIBID3TAG }
void Tags::ImportID3(wxString fileName) { #ifdef USE_LIBID3TAG struct id3_file *fp = id3_file_open(OSFILENAME(fileName), ID3_FILE_MODE_READONLY); if (!fp) return; struct id3_tag *tp = id3_file_tag(fp); if (!tp) return; mTitle = GetID3FieldStr(tp, ID3_FRAME_TITLE); mArtist = GetID3FieldStr(tp, ID3_FRAME_ARTIST); mAlbum = GetID3FieldStr(tp, ID3_FRAME_ALBUM); mYear = GetID3FieldStr(tp, ID3_FRAME_YEAR); mComments = GetID3FieldStr(tp, ID3_FRAME_COMMENT); long l; wxString s; if ((s = GetID3FieldStr(tp, ID3_FRAME_TRACK)).ToLong(&l)) mTrackNum = l; mID3V2 = ( tp->options & ID3_TAG_OPTION_ID3V1 ) ? false : true; s = GetID3FieldStr(tp, ID3_FRAME_GENRE); if( mID3V2 ) { int numGenres = GetNumGenres(); for(int i=0; i<numGenres; i++) if (0 == s.CmpNoCase(GetGenreNum(i))) mGenre = i; } else { if( s.ToLong( &l ) ) mGenre = l; } // Loop through all remaining frames int i; for(i=0; i<(int)tp->nframes; i++) { struct id3_frame *frame = tp->frames[i]; //printf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id); //printf("Desc: %s\n", frame->description); //printf("Num fields: %d\n", frame->nfields); if (!strcmp(frame->id, ID3_FRAME_TITLE) || !strcmp(frame->id, ID3_FRAME_ARTIST) || !strcmp(frame->id, ID3_FRAME_ALBUM) || !strcmp(frame->id, ID3_FRAME_YEAR) || !strcmp(frame->id, ID3_FRAME_COMMENT) || !strcmp(frame->id, ID3_FRAME_GENRE) || !strcmp(frame->id, ID3_FRAME_TRACK)) { continue; } const id3_ucs4_t *ustr; if (frame->nfields>=2) { ustr = id3_field_getstrings(&frame->fields[1], 0); if (ustr) { wxString name = UTF8CTOWX(frame->description); char *str = (char *)id3_ucs4_utf8duplicate(ustr); wxString value = UTF8CTOWX(str); free(str); mExtraNames.Add(name); mExtraValues.Add(value); } } if (frame->nfields==3) { wxString name, value; ustr = id3_field_getstring(&frame->fields[2]); if (ustr) { char *str = (char *)id3_ucs4_utf8duplicate(ustr); value = UTF8CTOWX(str); free(str); } ustr = id3_field_getstring(&frame->fields[1]); if (ustr) { char *str = (char *)id3_ucs4_utf8duplicate(ustr); name = UTF8CTOWX(str); free(str); } mExtraNames.Add(name); mExtraValues.Add(value); } } id3_file_close(fp); #endif // ifdef USE_LIBID3TAG }
static int _get_mp3tags(char *file, struct song_metadata *psong) { struct id3_file *pid3file; struct id3_tag *pid3tag; struct id3_frame *pid3frame; int err; int index; int used; unsigned char *utf8_text; int genre = WINAMP_GENRE_UNKNOWN; int have_utf8; int have_text; id3_ucs4_t const *native_text; char *tmp; int got_numeric_genre; id3_byte_t const *image; id3_length_t image_size = 0; pid3file = id3_file_open(file, ID3_FILE_MODE_READONLY); if(!pid3file) { DPRINTF(E_ERROR, L_SCANNER, "Cannot open %s\n", file); return -1; } pid3tag = id3_file_tag(pid3file); if(!pid3tag) { err = errno; id3_file_close(pid3file); errno = err; DPRINTF(E_WARN, L_SCANNER, "Cannot get ID3 tag for %s\n", file); return -1; } index = 0; while((pid3frame = id3_tag_findframe(pid3tag, "", index))) { used = 0; utf8_text = NULL; native_text = NULL; have_utf8 = 0; have_text = 0; if(!strcmp(pid3frame->id, "YTCP")) /* for id3v2.2 */ { psong->compilation = 1; DPRINTF(E_DEBUG, L_SCANNER, "Compilation: %d [%s]\n", psong->compilation, basename(file)); } else if(!strcmp(pid3frame->id, "APIC") && !image_size) { if( (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpeg") == 0) || (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpg") == 0) || (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "jpeg") == 0) #if HAVE_LIBPNG || (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/png") == 0) || (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "png") == 0) #endif ) { image = id3_field_getbinarydata(&pid3frame->fields[4], &image_size); if( image_size ) { psong->image = malloc(image_size); memcpy(psong->image, image, image_size); psong->image_size = image_size; //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Found thumbnail: %d\n", psong->image_size); } } } if(((pid3frame->id[0] == 'T') || (strcmp(pid3frame->id, "COMM") == 0)) && (id3_field_getnstrings(&pid3frame->fields[1]))) have_text = 1; if(have_text) { native_text = id3_field_getstrings(&pid3frame->fields[1], 0); if(native_text) { have_utf8 = 1; if(lang_index >= 0) utf8_text = _get_utf8_text(native_text); // through iconv else utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); if(!strcmp(pid3frame->id, "TIT2")) { used = 1; psong->title = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TPE1")) { used = 1; psong->contributor[ROLE_ARTIST] = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TALB")) { used = 1; psong->album = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TCOM")) { used = 1; psong->contributor[ROLE_COMPOSER] = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TIT1")) { used = 1; psong->grouping = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TPE2")) { used = 1; psong->contributor[ROLE_BAND] = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TPE3")) { used = 1; psong->contributor[ROLE_CONDUCTOR] = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TCON")) { used = 1; psong->genre = (char*)utf8_text; got_numeric_genre = 0; if(psong->genre) { if(!strlen(psong->genre)) { genre = WINAMP_GENRE_UNKNOWN; got_numeric_genre = 1; } else if(isdigit(psong->genre[0])) { genre = atoi(psong->genre); got_numeric_genre = 1; } else if((psong->genre[0] == '(') && (isdigit(psong->genre[1]))) { genre = atoi((char*)&psong->genre[1]); got_numeric_genre = 1; } if(got_numeric_genre) { if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN)) genre = WINAMP_GENRE_UNKNOWN; free(psong->genre); psong->genre = strdup(winamp_genre[genre]); } } } else if(!strcmp(pid3frame->id, "COMM")) { used = 1; psong->comment = (char*)utf8_text; } else if(!strcmp(pid3frame->id, "TPOS")) { tmp = (char*)utf8_text; strsep(&tmp, "/"); if(tmp) { psong->total_discs = atoi(tmp); } psong->disc = atoi((char*)utf8_text); } else if(!strcmp(pid3frame->id, "TRCK")) { tmp = (char*)utf8_text; strsep(&tmp, "/"); if(tmp) { psong->total_tracks = atoi(tmp); } psong->track = atoi((char*)utf8_text); } else if(!strcmp(pid3frame->id, "TDRC")) { psong->year = atoi((char*)utf8_text); } else if(!strcmp(pid3frame->id, "TLEN")) { psong->song_length = atoi((char*)utf8_text); } else if(!strcmp(pid3frame->id, "TBPM")) { psong->bpm = atoi((char*)utf8_text); } else if(!strcmp(pid3frame->id, "TCMP")) { psong->compilation = (char)atoi((char*)utf8_text); } } } // check if text tag if((!used) && (have_utf8) && (utf8_text)) free(utf8_text); // v2 COMM if((!strcmp(pid3frame->id, "COMM")) && (pid3frame->nfields == 4)) { native_text = id3_field_getstring(&pid3frame->fields[2]); if(native_text) { utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); if((utf8_text) && (strncasecmp((char*)utf8_text, "iTun", 4) != 0)) { // read comment free(utf8_text); native_text = id3_field_getfullstring(&pid3frame->fields[3]); if(native_text) { utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text); if(utf8_text) { free(psong->comment); psong->comment = (char*)utf8_text; } } } else { free(utf8_text); } } } index++; } id3_file_close(pid3file); //DEBUG DPRINTF(E_INFO, L_SCANNER, "Got id3 tag successfully for file=%s\n", file); return 0; }