From: Francois B <mrs...@us...> - 2006-10-10 23:45:41
|
Update of /cvsroot/openneo/openneo/firmware In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv9855 Added Files: ape.c Log Message: Added APE tag parsing --- NEW FILE: ape.c --- /*************************************************************************** * * Open Neo * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ //#include "ape.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <stddef.h> #include <ctype.h> #include "debug.h" #include "system.h" #include "metadata.h" #include "file.h" #include "buffer.h" #include "id3.h" struct ape_key_tag { const unsigned char* key; size_t offset; int (*parser)( const unsigned char *value, int value_length, unsigned char* result, size_t maxresult ); }; int parse_ape_date( const unsigned char *value, int value_length, unsigned char* result, size_t maxresult ) { (void)value_length; int len = MIN( 4,maxresult-1 ); strncpy( result, value, len ); result[len] = 0; return len; } int parse_ape_float( const unsigned char *value ) { int val; int frav; val = atof( value, &frav ); val = val * 10000; val += (frav * 1000); return val; } static struct ape_key_tag taglist[] = { { "Title", offsetof(struct meta_data, title_offset), NULL }, { "Artist", offsetof(struct meta_data, artist_offset), NULL }, { "Album", offsetof(struct meta_data, album_offset), NULL }, { "Composer", offsetof(struct meta_data, composer_offset), NULL }, { "Comment", offsetof(struct meta_data, comment_offset), NULL }, { "Track", offsetof(struct meta_data, track_offset), NULL }, { "Year", offsetof(struct meta_data, year_offset), parse_ape_date }, { "Genre", offsetof(struct meta_data, genre_offset), NULL } }; #define TAGLIST_SIZE ((int)(sizeof(taglist) / sizeof(taglist[0]))) #define APE_FLAG_HAS_HEADER 0x80000000 #define APE_FLAG_HAS_FOOTER 0x40000000 #define APE_FLAG_IS_HEADER 0x20000000 /* Returns the total length of the APE block or 0 */ int ape_parse_from_end( int fd, struct mpeg_info *mpeg, struct meta_data *meta ) { unsigned char buffer[600]; unsigned char *out_buffer; unsigned int total_size, size; unsigned int item_count; unsigned int flags; int prevpos, i; int value_len; int bytesread; int key_len; short* p_meta_offset; prevpos = lseek( fd, 0, SEEK_CUR ); //read the footer if( read( fd, buffer, 32 ) != 32 ) { lseek( fd, prevpos, SEEK_SET ); return 0; } if( memcmp( buffer, "APETAGEX", 8 ) ) { lseek( fd, prevpos, SEEK_SET ); return 0; } flags = BYTES2INT( buffer[23], buffer[22],buffer[21],buffer[20]); //Total size excluding the header (if present) total_size = size = BYTES2INT( buffer[15], buffer[14],buffer[13],buffer[12]); if( flags & APE_FLAG_HAS_HEADER ) total_size += 32; //We might not need to parse the values if we already parsed id3v2 tags if( !meta || meta->buffer[1] != 0 ) return total_size; lseek( fd, -size, SEEK_CUR ); item_count = BYTES2INT( buffer[19], buffer[18],buffer[17],buffer[16] ); // msg_error( "items: %i", item_count ); out_buffer = &meta->buffer[1]; while( item_count-- ) { //Make sure to read everything except the key value bytesread = read( fd, buffer, 600 ); if( bytesread <= 9 ) break; value_len = BYTES2INT( buffer[3], buffer[2],buffer[1],buffer[0]); flags = BYTES2INT( buffer[7], buffer[6],buffer[5],buffer[4]); key_len = strlen( &buffer[8] ); //Parse key if( strcasecmp( &buffer[8], "replaygain_track_gain" ) == 0 && !meta->rg_track_gain ) meta->rg_track_gain = parse_ape_float( buffer + 9 + key_len ); else if( strcasecmp( &buffer[8], "replaygain_track_peak" ) == 0 && !meta->rg_track_peak ) meta->rg_track_peak = parse_ape_float( buffer + 9 + key_len ); else if( strcasecmp( &buffer[8], "replaygain_album_gain" ) == 0 && !meta->rg_album_gain ) meta->rg_album_gain = parse_ape_float( buffer + 9 + key_len ); else if( strcasecmp( &buffer[8], "replaygain_album_peak" ) == 0 && !meta->rg_album_peak ) meta->rg_album_peak = parse_ape_float( buffer + 9 + key_len ); else { for( i=0; i< TAGLIST_SIZE; ++i ) { if( strcasecmp( taglist[i].key, &buffer[8]) == 0 ) { p_meta_offset = (short*) ((char*)meta + taglist[i].offset); *p_meta_offset = (size_t)out_buffer - (size_t)meta->buffer; if( taglist[i].parser ) { int len = taglist[i].parser( buffer + 9 + key_len, value_len, out_buffer, METADATA_BUFFER_SIZE - ((size_t)out_buffer - (size_t)meta->buffer) ); out_buffer += (len + 1); } else { //default text tag memcpy( out_buffer, buffer + 9 + key_len, value_len ); out_buffer[value_len] = 0; out_buffer += (value_len + 1); } } } } lseek( fd, -bytesread + (9 + key_len + value_len) , SEEK_CUR ); } return total_size; } |