X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmeta_engine%2Ftaglib.cpp;h=33866d0b644bd7b6094d84ac635d9aa8b362411b;hb=c60652e38ac6afd74bd8225e9dae5406f13aaa4f;hp=60b4a944d8b380d61a9f3c492e6c680d8b0bc1f1;hpb=b514a038dc932f0e77021952514fefacd87ccf5c;p=vlc diff --git a/modules/meta_engine/taglib.cpp b/modules/meta_engine/taglib.cpp index 60b4a944d8..33866d0b64 100644 --- a/modules/meta_engine/taglib.cpp +++ b/modules/meta_engine/taglib.cpp @@ -1,7 +1,7 @@ /***************************************************************************** * taglib.cpp: Taglib tag parser/writer ***************************************************************************** - * Copyright (C) 2003-2008 the VideoLAN team + * Copyright (C) 2003-2009 the VideoLAN team * $Id$ * * Authors: Clément Stenac @@ -29,11 +29,13 @@ #include #include -#include #include #include #include #include +#include +#include +#include /* for attachment_new */ #ifdef WIN32 # include @@ -56,6 +58,16 @@ #include #include #include + +#ifdef TAGLIB_WITH_ASF +# include +# include +#endif + +#ifdef TAGLIB_WITH_MP4 +# include +#endif + #include #include #include @@ -68,15 +80,11 @@ // Local functions static int ReadMeta ( vlc_object_t * ); -static int DownloadArt ( vlc_object_t * ); static int WriteMeta ( vlc_object_t * ); vlc_module_begin () set_capability( "meta reader", 1000 ) set_callbacks( ReadMeta, NULL ) - add_submodule () - set_capability( "art downloader", 50 ) - set_callbacks( DownloadArt, NULL ) add_submodule () set_capability( "meta writer", 50 ) set_callbacks( WriteMeta, NULL ) @@ -86,7 +94,7 @@ using namespace TagLib; /** - * Read meta informations from APE tags + * Read meta information from APE tags * @param tag: the APE tag * @param p_demux; the demux object * @param p_demux_meta: the demuxer meta @@ -124,6 +132,8 @@ static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t* { ID3v2::UniqueFileIdentifierFrame* p_ufid = dynamic_cast(*iter); + if( !p_ufid ) + continue; const char *owner = p_ufid->owner().toCString(); if (!strcmp( owner, "http://musicbrainz.org" )) { @@ -144,11 +154,13 @@ static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t* { ID3v2::UserTextIdentificationFrame* p_txxx = dynamic_cast(*iter); + if( !p_txxx ) + continue; vlc_meta_AddExtra( p_meta, p_txxx->description().toCString( true ), p_txxx->fieldList().toString().toCString( true ) ); } - // Get some more informations + // Get some more information #define SET( tagName, metaName ) \ list = tag->frameListMap()[tagName]; \ if( !list.isEmpty() ) \ @@ -188,6 +200,7 @@ static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t* 3, /* Logo of the band or performer. */ 2 /* Logo of the publisher (record company). */ }; + #define PI_COVER_SCORE_SIZE (sizeof (pi_cover_score) / sizeof (pi_cover_score[0])) int i_score = -1; // Try now to get embedded art @@ -196,11 +209,12 @@ static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t* return; TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments ); - for( ID3v2::FrameList::Iterator iter = list.begin(); - iter != list.end(); iter++ ) + for( iter = list.begin(); iter != list.end(); iter++ ) { ID3v2::AttachedPictureFrame* p_apic = dynamic_cast(*iter); + if( !p_apic ) + continue; input_attachment_t *p_attachment; const char *psz_mime; @@ -228,7 +242,7 @@ static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t* if( !strncmp( psz_mime, "PNG", 3 ) || !strncmp( psz_name, "\xC2\x89PNG", 5 ) ) { - msg_Warn( p_demux, "Invalid picture embedded by broken iTunes version" ); + msg_Warn( p_demux_meta, "Invalid picture embedded by broken iTunes version" ); free( psz_description ); continue; } @@ -237,7 +251,7 @@ static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t* const char *p_data = picture.data(); const unsigned i_data = picture.size(); - msg_Dbg( p_demux, "Found embedded art: %s (%s) is %u bytes", + msg_Dbg( p_demux_meta, "Found embedded art: %s (%s) is %u bytes", psz_name, psz_mime, i_data ); p_attachment = vlc_input_attachment_New( psz_name, psz_mime, @@ -248,9 +262,13 @@ static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t* p_attachment ); free( psz_description ); - if( pi_cover_score[p_apic->type()] > i_score ) + unsigned i_pic_type = p_apic->type(); + if( i_pic_type >= PI_COVER_SCORE_SIZE ) + i_pic_type = 0; // Defaults to "Other" + + if( pi_cover_score[i_pic_type] > i_score ) { - i_score = pi_cover_score[p_apic->type()]; + i_score = pi_cover_score[i_pic_type]; char *psz_url; if( asprintf( &psz_url, "attachment://%s", p_attachment->psz_name ) == -1 ) @@ -264,7 +282,7 @@ static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t* /** - * Read the meta informations from XiphComments + * Read the meta information from XiphComments * @param tag: the Xiph Comment * @param p_demux; the demux object * @param p_demux_meta: the demuxer meta @@ -286,7 +304,7 @@ static void ReadMetaFromXiph( Ogg::XiphComment* tag, demux_t* p_demux, demux_met // We get only the first covert art if( mime_list.size() > 1 || art_list.size() > 1 ) - msg_Warn( p_demux, "Found %i embedded arts, so using only the first one", + msg_Warn( p_demux_meta, "Found %i embedded arts, so using only the first one", art_list.size() ); else if( mime_list.size() == 0 || art_list.size() == 0 ) return; @@ -300,7 +318,7 @@ static void ReadMetaFromXiph( Ogg::XiphComment* tag, demux_t* p_demux, demux_met uint8_t *p_data; int i_data = vlc_b64_decode_binary( &p_data, art_list[0].toCString(true) ); - msg_Dbg( p_demux, "Found embedded art: %s (%s) is %i bytes", + msg_Dbg( p_demux_meta, "Found embedded art: %s (%s) is %i bytes", psz_name, psz_mime, i_data ); TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments ); @@ -315,7 +333,28 @@ static void ReadMetaFromXiph( Ogg::XiphComment* tag, demux_t* p_demux, demux_met vlc_meta_SetArtURL( p_meta, "attachment://cover" ); } - +#if defined(TAGLIB_WITH_MP4) && defined(HAVE_TAGLIB_MP4COVERART_H) +static void ReadMetaFromMP4( MP4::Tag* tag, demux_t *p_demux, demux_meta_t *p_demux_meta, vlc_meta_t* p_meta ) +{ + if( tag->itemListMap().contains("covr") ) + { + MP4::CoverArtList list = tag->itemListMap()["covr"].toCoverArtList(); + const char *psz_format = list[0].format() == MP4::CoverArt::PNG ? "image/png" : "image/jpeg"; + + msg_Dbg( p_demux_meta, "Found embedded art (%s) is %i bytes", + psz_format, list[0].data().size() ); + + TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments ); + input_attachment_t *p_attachment = + vlc_input_attachment_New( "cover", psz_format, "cover", + list[0].data().data(), list[0].data().size() ); + TAB_APPEND_CAST( (input_attachment_t**), + p_demux_meta->i_attachments, p_demux_meta->attachments, + p_attachment ); + vlc_meta_SetArtURL( p_meta, "attachment://cover" ); + } +} +#endif /** * Get the tags from the file using TagLib @@ -324,17 +363,39 @@ static void ReadMetaFromXiph( Ogg::XiphComment* tag, demux_t* p_demux, demux_met */ static int ReadMeta( vlc_object_t* p_this) { - demux_t* p_demux = (demux_t*)p_this; - demux_meta_t* p_demux_meta = (demux_meta_t*)p_demux->p_private; + demux_meta_t* p_demux_meta = (demux_meta_t *)p_this; + demux_t* p_demux = p_demux_meta->p_demux; vlc_meta_t* p_meta; - TagLib::FileRef f; + FileRef f; p_demux_meta->p_meta = NULL; - const char* local_name = ToLocale( p_demux->psz_path ); + if( strcmp( p_demux->psz_access, "file" ) ) + return VLC_EGENERIC; + + char *psz_path = strdup( p_demux->psz_file ); + if( !psz_path ) + return VLC_ENOMEM; + +#if defined(WIN32) || defined (UNDER_CE) + wchar_t wpath[MAX_PATH + 1]; + if( !MultiByteToWideChar( CP_UTF8, 0, psz_path, -1, wpath, MAX_PATH) ) + { + free( psz_path ); + return VLC_EGENERIC; + } + wpath[MAX_PATH] = L'\0'; + f = FileRef( wpath ); +#else + const char* local_name = ToLocale( psz_path ); if( !local_name ) + { + free( psz_path ); return VLC_EGENERIC; + } f = FileRef( local_name ); LocaleFree( local_name ); +#endif + free( psz_path ); if( f.isNull() ) return VLC_EGENERIC; @@ -366,7 +427,7 @@ static int ReadMeta( vlc_object_t* p_this) SET( comment, Description ); SET( genre, Genre ); SETINT( year, Date ); - SETINT( track, Tracknum ); + SETINT( track, TrackNum ); #undef SETINT #undef SET @@ -380,6 +441,13 @@ static int ReadMeta( vlc_object_t* p_this) else if( flac->xiphComment() ) ReadMetaFromXiph( flac->xiphComment(), p_demux, p_demux_meta, p_meta ); } +#if defined(TAGLIB_WITH_MP4) && defined(HAVE_TAGLIB_MP4COVERART_H) + else if( MP4::File *mp4 = dynamic_cast(f.file()) ) + { + if( mp4->tag() ) + ReadMetaFromMP4( mp4->tag(), p_demux, p_demux_meta, p_meta ); + } +#endif else if( MPC::File* mpc = dynamic_cast(f.file()) ) { if( mpc->APETag() ) @@ -401,6 +469,15 @@ static int ReadMeta( vlc_object_t* p_this) else if( Ogg::Vorbis::File* ogg_vorbis = dynamic_cast(f.file()) ) ReadMetaFromXiph( ogg_vorbis->tag(), p_demux, p_demux_meta, p_meta ); } +#ifdef TAGLIB_WITH_ASF + else if( RIFF::File* riff = dynamic_cast(f.file()) ) + { + if( RIFF::AIFF::File* riff_aiff = dynamic_cast(f.file()) ) + ReadMetaFromId3v2( riff_aiff->tag(), p_demux, p_demux_meta, p_meta ); + else if( RIFF::WAV::File* riff_wav = dynamic_cast(f.file()) ) + ReadMetaFromId3v2( riff_wav->tag(), p_demux, p_demux_meta, p_meta ); + } +#endif else if( TrueAudio::File* trueaudio = dynamic_cast(f.file()) ) { if( trueaudio->ID3v2Tag() ) @@ -418,7 +495,7 @@ static int ReadMeta( vlc_object_t* p_this) /** - * Write meta informations to APE tags + * Write meta information to APE tags * @param tag: the APE tag * @param p_item: the input item */ @@ -476,7 +553,7 @@ static void WriteMetaToId3v2( ID3v2::Tag* tag, input_item_t* p_item ) /** - * Write the meta informations to XiphComments + * Write the meta information to XiphComments * @param tag: the Xiph Comment * @param p_input: the input item */ @@ -508,9 +585,9 @@ static void WriteMetaToXiph( Ogg::XiphComment* tag, input_item_t* p_item ) static int WriteMeta( vlc_object_t *p_this ) { - playlist_t *p_playlist = (playlist_t *)p_this; - meta_export_t *p_export = (meta_export_t *)p_playlist->p_private; + meta_export_t *p_export = (meta_export_t *)p_this; input_item_t *p_item = p_export->p_item; + FileRef f; if( !p_item ) { @@ -518,11 +595,24 @@ static int WriteMeta( vlc_object_t *p_this ) return VLC_EGENERIC; } - FileRef f( p_export->psz_file ); +#if defined(WIN32) || defined (UNDER_CE) + wchar_t wpath[MAX_PATH + 1]; + if( !MultiByteToWideChar( CP_UTF8, 0, p_export->psz_file, -1, wpath, MAX_PATH) ) + return VLC_EGENERIC; + wpath[MAX_PATH] = L'\0'; + f = FileRef( wpath ); +#else + const char* local_name = ToLocale( p_export->psz_file ); + if( !local_name ) + return VLC_EGENERIC; + f = FileRef( local_name ); + LocaleFree( local_name ); +#endif + if( f.isNull() || !f.tag() || f.file()->readOnly() ) { - msg_Err( p_this, "File %s can't be opened for tag writing\n", - p_export->psz_file ); + msg_Err( p_this, "File %s can't be opened for tag writing", + p_export->psz_file ); return VLC_EGENERIC; } @@ -532,36 +622,22 @@ static int WriteMeta( vlc_object_t *p_this ) char *psz_meta; -#define SET( a, b ) \ - if( b ) \ - { \ - String* psz_tmp = new String( b, String::UTF8 ); \ - p_tag->set##a( *psz_tmp ); \ - delete psz_tmp; \ - } +#define SET( a, b ) \ + psz_meta = input_item_Get ## a( p_item ); \ + if( psz_meta ) \ + { \ + String tmp( psz_meta, String::UTF8 ); \ + p_tag->set##b( tmp ); \ + } \ + free( psz_meta ); // Saving all common fields // If the title is empty, use the name - psz_meta = input_item_GetTitle( p_item ); - if( !psz_meta ) psz_meta = input_item_GetName( p_item ); - SET( Title, psz_meta ); - free( psz_meta ); - - psz_meta = input_item_GetArtist( p_item ); - SET( Artist, psz_meta ); - free( psz_meta ); - - psz_meta = input_item_GetAlbum( p_item ); - SET( Album, psz_meta ); - free( psz_meta ); - - psz_meta = input_item_GetDescription( p_item ); - SET( Comment, psz_meta ); - free( psz_meta ); - - psz_meta = input_item_GetGenre( p_item ); - SET( Genre, psz_meta ); - free( psz_meta ); + SET( TitleFbName, Title ); + SET( Artist, Artist ); + SET( Album, Album ); + SET( Description, Comment ); + SET( Genre, Genre ); #undef SET @@ -603,6 +679,15 @@ static int WriteMeta( vlc_object_t *p_this ) else if( Ogg::Vorbis::File* ogg_vorbis = dynamic_cast(f.file()) ) WriteMetaToXiph( ogg_vorbis->tag(), p_item ); } +#ifdef TAGLIB_WITH_ASF + else if( RIFF::File* riff = dynamic_cast(f.file()) ) + { + if( RIFF::AIFF::File* riff_aiff = dynamic_cast(f.file()) ) + WriteMetaToId3v2( riff_aiff->tag(), p_item ); + else if( RIFF::WAV::File* riff_wav = dynamic_cast(f.file()) ) + WriteMetaToId3v2( riff_wav->tag(), p_item ); + } +#endif else if( TrueAudio::File* trueaudio = dynamic_cast(f.file()) ) { if( trueaudio->ID3v2Tag() ) @@ -620,13 +705,3 @@ static int WriteMeta( vlc_object_t *p_this ) return VLC_SUCCESS; } - - -static int DownloadArt( vlc_object_t *p_this ) -{ - /* We need to be passed the file name - * Fetch the thing from the file, save it to the cache folder - */ - return VLC_EGENERIC; -} -