static struct id3_tag * tag_id3_riff_aiff_load(FILE *file) { size_t size; void *buffer; size_t ret; struct id3_tag *tag; size = riff_seek_id3(file); if (size == 0) size = aiff_seek_id3(file); if (size == 0) return NULL; if (size > 4 * 1024 * 1024) /* too large, don't allocate so much memory */ return NULL; buffer = g_malloc(size); ret = fread(buffer, size, 1, file); if (ret != 1) { g_warning("Failed to read RIFF chunk"); g_free(buffer); return NULL; } tag = id3_tag_parse(buffer, size); g_free(buffer); return tag; }
JNIEXPORT jboolean JNICALL Java_com_ssb_droidsound_utils_ID3Tag_parseTag(JNIEnv *env, jobject obj, jbyteArray bArray, jint offset, jint size) { if(tagRefField != 0) { struct id3_tag *tag = (struct id3_tag*)env->GetLongField(obj, tagRefField); if(tag) id3_tag_delete(tag); } jbyte *ptr = env->GetByteArrayElements(bArray, NULL); const id3_byte_t*cptr = (const id3_byte_t*)(ptr + offset); __android_log_print(ANDROID_LOG_VERBOSE, "ID3Tag", "Checking at %p (%c %c)", cptr, cptr[0], cptr[1]); struct id3_tag *tag = id3_tag_parse(cptr, size); __android_log_print(ANDROID_LOG_VERBOSE, "ID3Tag", "DONE"); jclass cl = env->GetObjectClass(obj); tagRefField = env->GetFieldID(cl, "tagRef", "J"); env->SetLongField(obj, tagRefField, (jlong)tag); cl = env->GetObjectClass(obj); refField = env->GetFieldID(cl, "id3Ref", "J"); env->SetLongField(obj, refField, (jlong)0); env->ReleaseByteArrayElements(bArray, ptr, 0); return tag != NULL; }
static struct id3_tag * tag_id3_read(FILE *stream, long offset, int whence) { struct id3_tag *tag; id3_byte_t query_buffer[ID3_TAG_QUERYSIZE]; id3_byte_t *tag_buffer; int tag_size; int query_buffer_size; int tag_buffer_size; /* It's ok if we get less than we asked for */ query_buffer_size = fill_buffer(query_buffer, ID3_TAG_QUERYSIZE, stream, offset, whence); if (query_buffer_size <= 0) return NULL; /* Look for a tag header */ tag_size = id3_tag_query(query_buffer, query_buffer_size); if (tag_size <= 0) return NULL; /* Found a tag. Allocate a buffer and read it in. */ tag_buffer = g_malloc(tag_size); if (!tag_buffer) return NULL; tag_buffer_size = fill_buffer(tag_buffer, tag_size, stream, offset, whence); if (tag_buffer_size < tag_size) { g_free(tag_buffer); return NULL; } tag = id3_tag_parse(tag_buffer, tag_buffer_size); g_free(tag_buffer); return tag; }
/* * NAME: read_tag() * DESCRIPTION: read and parse a tag at a file's current position */ static struct id3_tag *read_tag(FILE *iofile, id3_length_t size) { id3_byte_t *data; struct id3_tag *tag = 0; data = malloc(size); if (data) { if (fread(data, size, 1, iofile) == 1) tag = id3_tag_parse(data, size); free(data); } return tag; }
static void mp3_parse_id3(struct mp3_data *data, size_t tagsize, struct tag **mpd_tag, struct replay_gain_info **replay_gain_info_r) { struct id3_tag *id3_tag = NULL; id3_length_t count; id3_byte_t const *id3_data; id3_byte_t *allocated = NULL; count = data->stream.bufend - data->stream.this_frame; if (tagsize <= count) { id3_data = data->stream.this_frame; mad_stream_skip(&(data->stream), tagsize); } else { allocated = g_malloc(tagsize); memcpy(allocated, data->stream.this_frame, count); mad_stream_skip(&(data->stream), count); while (count < tagsize) { size_t len; len = decoder_read(data->decoder, data->input_stream, allocated + count, tagsize - count); if (len == 0) break; else count += len; } if (count != tagsize) { g_debug("error parsing ID3 tag"); g_free(allocated); return; } id3_data = allocated; } id3_tag = id3_tag_parse(id3_data, tagsize); if (id3_tag == NULL) { g_free(allocated); return; } if (mpd_tag) { struct tag *tmp_tag = tag_id3_import(id3_tag); if (tmp_tag != NULL) { if (*mpd_tag != NULL) tag_free(*mpd_tag); *mpd_tag = tmp_tag; } } if (replay_gain_info_r) { struct replay_gain_info *tmp_rgi = parse_id3_replay_gain_info(id3_tag); if (tmp_rgi != NULL) { if (*replay_gain_info_r) replay_gain_info_free(*replay_gain_info_r); *replay_gain_info_r = tmp_rgi; } } id3_tag_delete(id3_tag); g_free(allocated); }
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 void mp3_parse_id3(struct mp3_data *data, size_t tagsize, struct tag **mpd_tag) { #ifdef HAVE_ID3TAG struct id3_tag *id3_tag = NULL; id3_length_t count; id3_byte_t const *id3_data; id3_byte_t *allocated = NULL; count = data->stream.bufend - data->stream.this_frame; if (tagsize <= count) { id3_data = data->stream.this_frame; mad_stream_skip(&(data->stream), tagsize); } else { allocated = g_malloc(tagsize); memcpy(allocated, data->stream.this_frame, count); mad_stream_skip(&(data->stream), count); while (count < tagsize) { size_t len; len = decoder_read(data->decoder, data->input_stream, allocated + count, tagsize - count); if (len == 0) break; else count += len; } if (count != tagsize) { g_debug("error parsing ID3 tag"); g_free(allocated); return; } id3_data = allocated; } id3_tag = id3_tag_parse(id3_data, tagsize); if (id3_tag == NULL) { g_free(allocated); return; } if (mpd_tag) { struct tag *tmp_tag = tag_id3_import(id3_tag); if (tmp_tag != NULL) { if (*mpd_tag != NULL) tag_free(*mpd_tag); *mpd_tag = tmp_tag; } } if (data->decoder != NULL) { struct replay_gain_info rgi; char *mixramp_start; char *mixramp_end; float replay_gain_db = 0; if (parse_id3_replay_gain_info(&rgi, id3_tag)) { replay_gain_db = decoder_replay_gain(data->decoder, &rgi); data->found_replay_gain = true; } if (parse_id3_mixramp(&mixramp_start, &mixramp_end, id3_tag)) { g_debug("setting mixramp_tags"); decoder_mixramp(data->decoder, replay_gain_db, mixramp_start, mixramp_end); } } id3_tag_delete(id3_tag); g_free(allocated); #else /* !HAVE_ID3TAG */ (void)mpd_tag; /* This code is enabled when libid3tag is disabled. Instead of parsing the ID3 frame, it just skips it. */ size_t count = data->stream.bufend - data->stream.this_frame; if (tagsize <= count) { mad_stream_skip(&data->stream, tagsize); } else { mad_stream_skip(&data->stream, count); while (count < tagsize) { size_t len = tagsize - count; char ignored[1024]; if (len > sizeof(ignored)) len = sizeof(ignored); len = decoder_read(data->decoder, data->input_stream, ignored, len); if (len == 0) break; else count += len; } } #endif }
kal_bool get_aud_meta_data_file(kal_wchar *filename, aud_info_struct *aud_info_p) { /*----------------------------------------------------------------*/ /* Local Variables */ /*----------------------------------------------------------------*/ kal_uint32 size; FS_HANDLE file; audio_input_stream_struct *input_stream; /*----------------------------------------------------------------*/ /* Code Body */ /*----------------------------------------------------------------*/ if ((file = DRM_open_file(filename, FS_READ_ONLY | FS_OPEN_NO_DIR, DRM_PERMISSION_PLAY)) < 0) { return KAL_FALSE; } input_stream = audio_file_input_stream_alloc(file); size = audio_input_stream_get_data_size(input_stream); /* get id3 tags info */ memset(aud_info_p, 0, sizeof(aud_info_struct)); daf_set_data_info(aud_info_p, 0, 0, size, 0, 0); if (id3_tag_parse(input_stream, &id3_tag)) { /* copy title to info_p */ if (id3_tag.frames[ID3_FRAME_TITLE].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->title, (const kal_wchar*)id3_tag.frames[ID3_FRAME_TITLE].text, MAX_ID3_TITLE_LEN); } /* copy artist to info_p */ if (id3_tag.frames[ID3_FRAME_ARTIST].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->artist, (const kal_wchar*)id3_tag.frames[ID3_FRAME_ARTIST].text, MAX_ID3_ARTIST_LEN); } /* copy album to info_p */ if (id3_tag.frames[ID3_FRAME_ALBUM].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->album, (const kal_wchar*)id3_tag.frames[ID3_FRAME_ALBUM].text, MAX_ID3_ALBUM_LEN); } /* copy genre to info_p */ if (id3_tag.frames[ID3_FRAME_GENRE].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->genre, (const kal_wchar*)id3_tag.frames[ID3_FRAME_GENRE].text, MAX_ID3_GENRE_LEN); } /* copy year to info_p */ if (id3_tag.frames[ID3_FRAME_YEAR].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->year, (const kal_wchar*)id3_tag.frames[ID3_FRAME_YEAR].text, MAX_ID3_YEAR_LEN); } if (id3_tag.frames[ID3_FRAME_COPYRIGHT].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->copyright, (const kal_wchar*)id3_tag.frames[ID3_FRAME_COPYRIGHT].text, MAX_ID3_COPYRIGHT_LEN); } } DRM_close_file(file); audio_input_stream_free(input_stream); return KAL_TRUE; }
kal_bool get_aud_meta_data_array(kal_char *ptr, kal_uint32 size, aud_info_struct *aud_info_p) { /*----------------------------------------------------------------*/ /* Local Variables */ /*----------------------------------------------------------------*/ audio_input_stream_struct *input_stream; /*----------------------------------------------------------------*/ /* Code Body */ /*----------------------------------------------------------------*/ input_stream = audio_byte_input_stream_alloc( (kal_uint8 *)ptr, size); /* get id3 tags info */ memset(aud_info_p, 0, sizeof(aud_info_struct)); daf_set_data_info(aud_info_p, 0, 0, size, 0, 0); if (id3_tag_parse(input_stream, &id3_tag)) { /* copy title to info_p */ if (id3_tag.frames[ID3_FRAME_TITLE].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->title, (const kal_wchar*)id3_tag.frames[ID3_FRAME_TITLE].text, MAX_ID3_TITLE_LEN); } /* copy artist to info_p */ if (id3_tag.frames[ID3_FRAME_ARTIST].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->artist, (const kal_wchar*)id3_tag.frames[ID3_FRAME_ARTIST].text, MAX_ID3_ARTIST_LEN); } /* copy album to info_p */ if (id3_tag.frames[ID3_FRAME_ALBUM].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->album, (const kal_wchar*)id3_tag.frames[ID3_FRAME_ALBUM].text, MAX_ID3_ALBUM_LEN); } /* copy genre to info_p */ if (id3_tag.frames[ID3_FRAME_GENRE].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->genre, (const kal_wchar*)id3_tag.frames[ID3_FRAME_GENRE].text, MAX_ID3_GENRE_LEN); } /* copy year to info_p */ if (id3_tag.frames[ID3_FRAME_YEAR].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->year, (const kal_wchar*)id3_tag.frames[ID3_FRAME_YEAR].text, MAX_ID3_YEAR_LEN); } if (id3_tag.frames[ID3_FRAME_COPYRIGHT].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->copyright, (const kal_wchar*)id3_tag.frames[ID3_FRAME_COPYRIGHT].text, MAX_ID3_COPYRIGHT_LEN); } } audio_input_stream_free(input_stream); return KAL_TRUE; }
/***************************************************************************** * FUNCTION * get_aud_info * DESCRIPTION * * PARAMETERS * filename [?] * aud_info_p [?] * RETURNS * kal_bool *****************************************************************************/ kal_bool get_aud_info(kal_wchar *filename, aud_info_struct *aud_info_p) { /*----------------------------------------------------------------*/ /* Local Variables */ /*----------------------------------------------------------------*/ kal_int16 format; kal_uint32 size; FS_HANDLE file; STFSAL fsal_handle; audInfoStruct *aud_info; kal_uint32 channel_num; audio_input_stream_struct *input_stream; /*----------------------------------------------------------------*/ /* Code Body */ /*----------------------------------------------------------------*/ Media_Status(*get_aud_info_func) (STFSAL * pstFSAL, audInfoStruct * contentInfo, void *param) = NULL; if ((file = DRM_open_file(filename, FS_READ_ONLY | FS_OPEN_NO_DIR, DRM_PERMISSION_PLAY)) < 0) { return KAL_FALSE; } format = med_get_media_type(filename); input_stream = audio_file_input_stream_alloc(file); size = audio_input_stream_get_data_size(input_stream); /* get id3 tags info */ memset(aud_info_p, 0, sizeof(aud_info_struct)); daf_set_data_info(aud_info_p, 0, 0, size, 0, 0); if (id3_tag_parse(input_stream, &id3_tag)) { /* copy title to info_p */ if (id3_tag.frames[ID3_FRAME_TITLE].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->title, (const kal_wchar*)id3_tag.frames[ID3_FRAME_TITLE].text, MAX_ID3_TITLE_LEN); } /* copy artist to info_p */ if (id3_tag.frames[ID3_FRAME_ARTIST].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->artist, (const kal_wchar*)id3_tag.frames[ID3_FRAME_ARTIST].text, MAX_ID3_ARTIST_LEN); } /* copy album to info_p */ if (id3_tag.frames[ID3_FRAME_ALBUM].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->album, (const kal_wchar*)id3_tag.frames[ID3_FRAME_ALBUM].text, MAX_ID3_ALBUM_LEN); } /* copy genre to info_p */ if (id3_tag.frames[ID3_FRAME_GENRE].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->genre, (const kal_wchar*)id3_tag.frames[ID3_FRAME_GENRE].text, MAX_ID3_GENRE_LEN); } /* copy year to info_p */ if (id3_tag.frames[ID3_FRAME_YEAR].text != NULL) { kal_wstrncpy( (kal_wchar*) aud_info_p->year, (const kal_wchar*)id3_tag.frames[ID3_FRAME_YEAR].text, MAX_ID3_YEAR_LEN); } } DRM_close_file(file); switch (format) { #ifdef AU_DECODE case MED_TYPE_AU: get_aud_info_func = AU_GetContentDescInfo; break; #endif /* AU_DECODE */ #ifdef AIFF_DECODE case MED_TYPE_AIFF: get_aud_info_func = AIFF_GetContentDescInfo; break; #endif /* AIFF_DECODE */ case MED_TYPE_WAV: get_aud_info_func = WAV_GetContentDescInfo; break; #ifdef AMR_DECODE case MED_TYPE_AMR: case MED_TYPE_AMR_WB: get_aud_info_func = AMR_GetContentDescInfo; break; #endif /* AMR_DECODE */ #ifdef AAC_DECODE case MED_TYPE_AAC: get_aud_info_func = AAC_GetContentDescInfo; break; case MED_TYPE_M4A: get_aud_info_func = M4A_GetContentDescInfo; break; #endif /* AAC_DECODE */ #ifdef WMA_DECODE case MED_TYPE_WMA: get_aud_info_func = WMA_GetContentDescInfo; break; #endif /* WMA_DECODE */ #if defined(MED_PURE_AUDIO) case MED_TYPE_MP4: case MED_TYPE_3GP: get_aud_info_func = M4A_GetContentDescInfo; break; #endif /* defined(MED_PURE_AUDIO) */ #ifdef DAF_DECODE case MED_TYPE_DAF: #ifdef MUSICAM_DECODE case MED_TYPE_MUSICAM: #endif get_aud_info_func = DAF_GetContentDescInfo; break; #endif /* DAF_DECODE */ case MED_TYPE_PCM_8K: case MED_TYPE_PCM_16K: get_aud_info_func = PCM_GetContentDescInfo; break; case MED_TYPE_GSM_EFR: get_aud_info_func = VM_GetContentDescInfo; break; } if (get_aud_info_func != NULL) { aud_info = (audInfoStruct*) & id3_tag; /* reuse id3_tag memory for aud_info */ if (FSAL_Open(&fsal_handle, filename, FSAL_READ) == FSAL_OK) { if (get_aud_info_func(&fsal_handle, aud_info, (void*)format) == MEDIA_SUCCESS) { #ifdef WMA_DECODE if (format == MED_TYPE_WMA) { kal_wstrncpy( (kal_wchar*) aud_info_p->title, (const kal_wchar*)aud_info->title, MAX_ID3_TITLE_LEN); kal_wstrncpy( (kal_wchar*) aud_info_p->artist, (const kal_wchar*)aud_info->artist, MAX_ID3_ARTIST_LEN); kal_wstrncpy( (kal_wchar*) aud_info_p->album, (const kal_wchar*)aud_info->album, MAX_ID3_ALBUM_LEN); } #endif /* WMA_DECODE */ channel_num = (aud_info->stereo ? 2 : 1); daf_set_data_info( aud_info_p, channel_num, aud_info->time, size, aud_info->bitRate, aud_info->sampleRate); } FSAL_Close(&fsal_handle); } } audio_input_stream_free(input_stream); return KAL_TRUE; }
/***************************************************************************** * 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 }
/***************************************************************************** * FUNCTION * get_aud_info * DESCRIPTION * * IMPACT * * PARAMETERS * kal_wchar* filename * aud_info_struct* aud_info_p * RETURNS * kal_bool * GLOBALS AFFECTED * *****************************************************************************/ kal_bool get_aud_info( kal_wchar* filename, aud_info_struct* aud_info_p ) { kal_int16 format; kal_uint32 size; FS_HANDLE file; #ifdef __AUD_NEW_INTERFACE__ STFSAL fsal_handle; audInfoStruct* aud_info; #endif // __AUD_NEW_INTERFACE__ audio_input_stream_struct* input_stream; mmi_trace(1,"chenhe,get_aud_info"); if( (file = DRM_open_file( (const UINT8 *)filename, FS_READ_ONLY|FS_OPEN_NO_DIR, 0 )) < 0 ) return KAL_FALSE; format = med_get_media_type( filename ); input_stream = audio_file_input_stream_alloc( file ); size = audio_input_stream_get_data_size( input_stream ); memset(aud_info_p, 0, sizeof(aud_info_struct) ); daf_set_data_info( aud_info_p, 0, 0, size, 0, 0 ); mmi_trace(1,"chenhe,get_aud_info,format is %d,size is %p",format,size); if( format == MED_TYPE_DAF ) daf_parse_data_info( aud_info_p, input_stream, &id3_tag ); else { #ifdef AAC_DECODE if( format == MED_TYPE_AAC ) { if( id3_tag_parse( input_stream, &id3_tag ) ) { // copy title to info_p if( id3_tag.frames[ID3_FRAME_TITLE].text != NULL ) kal_wstrncpy( (kal_wchar*)aud_info_p->title, (const kal_wchar*)id3_tag.frames[ID3_FRAME_TITLE].text, MAX_ID3_TITLE_LEN ); // copy artist to info_p if( id3_tag.frames[ID3_FRAME_ARTIST].text != NULL ) kal_wstrncpy( (kal_wchar*)aud_info_p->artist, (const kal_wchar*)id3_tag.frames[ID3_FRAME_ARTIST].text, MAX_ID3_ARTIST_LEN ); // copy album to info_p if( id3_tag.frames[ID3_FRAME_ALBUM].text != NULL ) kal_wstrncpy( (kal_wchar*)aud_info_p->album, (const kal_wchar*)id3_tag.frames[ID3_FRAME_ALBUM].text, MAX_ID3_ALBUM_LEN ); // copy genre to info_p if( id3_tag.frames[ID3_FRAME_GENRE].text != NULL ) kal_wstrncpy( (kal_wchar*)aud_info_p->genre, (const kal_wchar*)id3_tag.frames[ID3_FRAME_GENRE].text, MAX_ID3_GENRE_LEN ); // copy year to info_p if( id3_tag.frames[ID3_FRAME_YEAR].text != NULL ) kal_wstrncpy( (kal_wchar*)aud_info_p->year, (const kal_wchar*)id3_tag.frames[ID3_FRAME_YEAR].text, MAX_ID3_YEAR_LEN ); } } #endif // AAC_DECODE } DRM_close_file( file ); #ifdef __AUD_NEW_INTERFACE__ if( format == MED_TYPE_AAC || format == MED_TYPE_WMA ) { aud_info = (audInfoStruct*) &id3_tag; // reuse id3_tag memory for aud_info if( FSAL_Open( &fsal_handle, filename, FSAL_READ ) == FSAL_OK ) { media_get_info_func_ptr getInfoFunc; switch( format ) { #ifdef AAC_DECODE case MED_TYPE_AAC: getInfoFunc = AAC_GetContentDescInfo; break; #endif // AAC_DECODE #ifdef WMA_DECODE case MED_TYPE_WMA: getInfoFunc = WMA_GetContentDescInfo; break; #endif // WMA_DECODE default: ASSERT(0); break; } if( getInfoFunc( &fsal_handle, aud_info ) == MEDIA_SUCCESS ) { #ifdef WMA_DECODE if( format == MED_TYPE_WMA ) { kal_wstrncpy( (kal_wchar*)aud_info_p->title, (const kal_wchar*)aud_info->title, MAX_ID3_TITLE_LEN ); kal_wstrncpy( (kal_wchar*)aud_info_p->artist, (const kal_wchar*)aud_info->artist, MAX_ID3_ARTIST_LEN ); kal_wstrncpy( (kal_wchar*)aud_info_p->album, (const kal_wchar*)aud_info->album, MAX_ID3_ALBUM_LEN ); } #endif // WMA_DECODE channel_num = (aud_info->stereo ? 2: 1); daf_set_data_info( aud_info_p, channel_num, aud_info->time, size, aud_info->bitRate, aud_info->sampleRate ); } FSAL_Close( &fsal_handle ); } } #endif // __AUD_NEW_INTERFACE__ audio_input_stream_free( input_stream ); return KAL_TRUE; }