00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028 #include <string.h>
00029
00030 #include <vlc/vlc.h>
00031 #include <vlc/intf.h>
00032 #include <vlc/input.h>
00033
00034 #include <sys/types.h>
00035
00036 #include "vlc_meta.h"
00037
00038 #include <id3tag.h>
00039 #include "id3genres.h"
00040
00041
00042
00043
00044 static int ParseID3Tags ( vlc_object_t * );
00045
00046
00047
00048
00049 vlc_module_begin();
00050 set_description( _("ID3 tag parser using libid3tag" ) );
00051 set_capability( "id3", 70 );
00052 set_callbacks( ParseID3Tags, NULL );
00053 vlc_module_end();
00054
00055
00056
00057
00058
00059
00060
00061
00062 static void ParseID3Tag( demux_t *p_demux, uint8_t *p_data, int i_size )
00063 {
00064 struct id3_tag *p_id3_tag;
00065 struct id3_frame *p_frame;
00066 int i = 0;
00067
00068 p_id3_tag = id3_tag_parse( p_data, i_size );
00069 if( !p_id3_tag ) return;
00070
00071 if( !p_demux->p_private ) p_demux->p_private = (void *)vlc_meta_New();
00072
00073 while( ( p_frame = id3_tag_findframe( p_id3_tag , "T", i ) ) )
00074 {
00075 int i_strings = id3_field_getnstrings( &p_frame->fields[1] );
00076
00077 while( i_strings > 0 )
00078 {
00079 char *psz_temp = id3_ucs4_utf8duplicate(
00080 id3_field_getstrings( &p_frame->fields[1], --i_strings ) );
00081
00082 if( !strcmp( p_frame->id, ID3_FRAME_GENRE ) )
00083 {
00084 char *psz_endptr;
00085 int i_genre = strtol( psz_temp, &psz_endptr, 10 );
00086
00087 if( psz_temp != psz_endptr &&
00088 i_genre >= 0 && i_genre < NUM_GENRES )
00089 {
00090 vlc_meta_Add( (vlc_meta_t *)p_demux->p_private,
00091 VLC_META_GENRE, ppsz_genres[atoi(psz_temp)]);
00092 }
00093 else
00094 {
00095
00096 vlc_meta_Add( (vlc_meta_t *)p_demux->p_private,
00097 VLC_META_GENRE, psz_temp );
00098 }
00099 }
00100 else if( !strcmp(p_frame->id, ID3_FRAME_TITLE ) )
00101 {
00102 vlc_meta_Add( (vlc_meta_t *)p_demux->p_private,
00103 VLC_META_TITLE, psz_temp );
00104 }
00105 else if( !strcmp(p_frame->id, ID3_FRAME_ARTIST ) )
00106 {
00107 vlc_meta_Add( (vlc_meta_t *)p_demux->p_private,
00108 VLC_META_ARTIST, psz_temp );
00109 }
00110 else
00111 {
00112
00113 vlc_meta_Add( (vlc_meta_t *)p_demux->p_private,
00114 (char *)p_frame->description, psz_temp );
00115 }
00116 free( psz_temp );
00117 }
00118 i++;
00119 }
00120 id3_tag_delete( p_id3_tag );
00121 }
00122
00123
00124
00125
00126
00127 static int ParseID3Tags( vlc_object_t *p_this )
00128 {
00129 demux_t *p_demux = (demux_t *)p_this;
00130 uint8_t *p_peek;
00131 vlc_bool_t b_seekable;
00132 int64_t i_init, i_pos;
00133 int i_size;
00134
00135 p_demux->p_private = NULL;
00136
00137 msg_Dbg( p_demux, "checking for ID3 tag" );
00138
00139 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_seekable );
00140 if( !b_seekable ) return VLC_SUCCESS;
00141
00142 i_init = stream_Tell( p_demux->s );
00143
00144
00145
00146
00147 i_init = stream_Tell( p_demux->s );
00148 i_pos = stream_Size( p_demux->s );
00149
00150 while( i_pos > 128 )
00151 {
00152 stream_Seek( p_demux->s, i_pos - 128 );
00153
00154
00155 if( stream_Peek( p_demux->s, &p_peek, 10 ) < 10 ) break;
00156
00157 i_size = id3_tag_query( p_peek, 10 );
00158 if( i_size == 128 )
00159 {
00160
00161 if( stream_Peek( p_demux->s, &p_peek, i_size ) < i_size ) break;
00162
00163 msg_Dbg( p_demux, "found ID3v1 tag" );
00164 ParseID3Tag( p_demux, p_peek, i_size );
00165 }
00166
00167
00168
00169 if( stream_Peek( p_demux->s, &p_peek, 128 ) < 128 ) break;
00170
00171 i_size = id3_tag_query( p_peek + 118, 10 );
00172 if( i_size < 0 && i_pos > -i_size )
00173 {
00174
00175 stream_Seek( p_demux->s , i_pos + i_size );
00176
00177 if( stream_Peek( p_demux->s, &p_peek, i_size ) < i_size ) break;
00178
00179 msg_Dbg( p_demux, "found ID3v2 tag at end of file" );
00180 ParseID3Tag( p_demux, p_peek, i_size );
00181 }
00182 break;
00183 }
00184
00185
00186
00187
00188 stream_Seek( p_demux->s, 0 );
00189 if( stream_Peek( p_demux->s, &p_peek, 10 ) < 10 ) goto end;
00190
00191 if( (i_size = id3_tag_query( p_peek, 10 )) <= 0 ) goto end;
00192
00193 if( stream_Peek( p_demux->s, &p_peek, i_size ) < i_size ) goto end;
00194
00195 msg_Dbg( p_demux, "found ID3v2 tag" );
00196 ParseID3Tag( p_demux, p_peek, i_size );
00197
00198 end:
00199 stream_Seek( p_demux->s, i_init );
00200 return VLC_SUCCESS;
00201 }