]> git.sesse.net Git - vlc/blobdiff - modules/meta_engine/taglib.cpp
taglib: read meta from xiph.
[vlc] / modules / meta_engine / taglib.cpp
index e6b288d50e3f2b479e5443d4a8d844d2363f525a..c5f896366e229ea1998275e79681172575e79027 100644 (file)
@@ -1,11 +1,12 @@
 /*****************************************************************************
  * taglib.cpp: Taglib tag parser/writer
  *****************************************************************************
- * Copyright (C) 2003-2006 the VideoLAN team
+ * Copyright (C) 2003-2008 the VideoLAN team
  * $Id$
  *
  * Authors: Clément Stenac <zorglub@videolan.org>
  *          Rafaël Carré <funman@videolanorg>
+ *          Rémi Duraffort <ivoire@videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 # include <unistd.h>
 #endif
 
+
+// Taglib headers
 #include <fileref.h>
 #include <tag.h>
-#include <tstring.h>
-#include <id3v2tag.h>
-#include <textidentificationframe.h>
 #include <tbytevector.h>
-#include <mpegfile.h>
-#include <attachedpictureframe.h>
-//#include <oggflacfile.h> /* ogg flac files aren't auto-casted by TagLib */
+
+#include <apetag.h>
+#include <id3v2tag.h>
+#include <xiphcomment.h>
+
 #include <flacfile.h>
-#include <flacproperties.h>
+#include <mpcfile.h>
+#include <mpegfile.h>
+#include <oggfile.h>
+#include <oggflacfile.h>
+#include <speexfile.h>
+#include <trueaudiofile.h>
 #include <vorbisfile.h>
-#include <vorbisproperties.h>
-#include <xiphcomment.h>
-#include <uniquefileidentifierframe.h>
+#include <wavpackfile.h>
+
+#include <attachedpictureframe.h>
 #include <textidentificationframe.h>
-//#include <relativevolumeframe.h> /* parse the tags without TagLib helpers? */
-
-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 );
-vlc_module_end();
+#include <uniquefileidentifierframe.h>
+
+
+// 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 )
+vlc_module_end ()
 
 using namespace TagLib;
 
+
 /* Try detecting embedded art */
 static void DetectImage( FileRef f, demux_t *p_demux )
 {
@@ -239,178 +249,142 @@ static void DetectImage( FileRef f, demux_t *p_demux )
 #endif
 }
 
-static int ReadMeta( vlc_object_t *p_this )
+
+
+/**
+ * Read meta informations from APE tags
+ * @param tag: the APE tag
+ * @param p_meta: the meta
+ * @return VLC_SUCCESS if everything goes ok
+ */
+static int ReadMetaFromAPE( APE::Tag* tag, vlc_meta_t* p_meta )
 {
-    demux_t         *p_demux = (demux_t *)p_this;
-    demux_meta_t    *p_demux_meta = (demux_meta_t*)p_demux->p_private;
-    vlc_meta_t      *p_meta;
-    TagLib::FileRef  f;
+    return VLC_SUCCESS;
+}
+
 
-    TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments );
-    p_demux_meta->p_meta = NULL;
 
-#if defined(WIN32) || defined (UNDER_CE)
-    if(GetVersion() < 0x80000000)
+/**
+ * Read meta information from id3v2 tags
+ * @param tag: the id3v2 tag
+ * @param p_meta: the meta
+ * @return VLC_SUCCESS if everything goes ok
+ */
+static int ReadMetaFromId2v2( ID3v2::Tag* tag, vlc_meta_t* p_meta )
+{
+    // Get the unique file identifier
+    ID3v2::FrameList list = tag->frameListMap()["UFID"];
+    ID3v2::FrameList::Iterator iter;
+    for( iter = list.begin(); iter != list.end(); iter++ )
     {
-        wchar_t wpath[MAX_PATH + 1];
-        if( !MultiByteToWideChar( CP_UTF8, 0, p_demux->psz_path, -1, wpath, MAX_PATH) )
-            return VLC_EGENERIC;
+        ID3v2::UniqueFileIdentifierFrame* p_ufid =
+                dynamic_cast<ID3v2::UniqueFileIdentifierFrame*>(*iter);
+        const char *owner = p_ufid->owner().toCString();
+        if (!strcmp( owner, "http://musicbrainz.org" ))
+        {
+            /* ID3v2 UFID contains up to 64 bytes binary data
+             * but in our case it will be a '\0'
+             * terminated string */
+            char psz_ufid[64];
+            int j = 0;
+            int max_size = p_ufid->identifier().size() < 63 ?
+                           p_ufid->identifier().size() : 63;
+            while( j < max_size )
+                psz_ufid[j] = p_ufid->identifier()[j++];
+            psz_ufid[j] = '\0';
+            vlc_meta_SetTrackID( p_meta, psz_ufid );
+        }
+    }
 
-        wpath[MAX_PATH] = L'0';
-        f = FileRef( wpath );
+    // Get the use text
+    list = tag->frameListMap()["TXXX"];
+    for( iter = list.begin(); iter != list.end(); iter++ )
+    {
+        ID3v2::UserTextIdentificationFrame* p_txxx =
+                dynamic_cast<ID3v2::UserTextIdentificationFrame*>(*iter);
+        vlc_meta_AddExtra( p_meta, p_txxx->description().toCString( true ),
+                           p_txxx->fieldList().toString().toCString( true ) );
     }
-    else return VLC_EGENERIC;
-#else
-    const char *local_name = ToLocale( p_demux->psz_path );
 
-    if( local_name == NULL )
-        return VLC_EGENERIC;
+    // Get some more informations
+#define SET( tagName, metaName )                                               \
+    list = tag->frameListMap()[tagName];                                       \
+    if( !list.isEmpty() )                                                      \
+        vlc_meta_Set##metaName( p_meta,                                        \
+                                (*list.begin())->toString().toCString( true ) );
 
-    f = FileRef( local_name );
-    LocaleFree( local_name );
-#endif
+    SET( "TCOP", Copyright );
+    SET( "TENC", EncodedBy );
+    SET( "TLAN", Language );
+    SET( "TPUB", Publisher );
 
-    if( f.isNull() )
-        return VLC_EGENERIC;
+#undef SET
+    return VLC_SUCCESS;
+}
 
-    if ( !f.tag() || f.tag()->isEmpty() )
-        return VLC_EGENERIC;
 
-    p_demux_meta->p_meta = p_meta = vlc_meta_New();
-    Tag *p_tag = f.tag();
 
-    if( MPEG::File *p_mpeg =
-        dynamic_cast<MPEG::File *>(f.file() ) )
-    {
-        if( p_mpeg->ID3v2Tag() )
-        {
-            ID3v2::Tag *p_tag = p_mpeg->ID3v2Tag();
-            ID3v2::FrameList list = p_tag->frameListMap()["UFID"];
-            ID3v2::UniqueFileIdentifierFrame* p_ufid;
-            for( ID3v2::FrameList::Iterator iter = list.begin();
-                    iter != list.end(); iter++ )
-            {
-                p_ufid = dynamic_cast<ID3v2::UniqueFileIdentifierFrame*>(*iter);
-                const char *owner = p_ufid->owner().toCString();
-                if (!strcmp( owner, "http://musicbrainz.org" ))
-                {
-                    /* ID3v2 UFID contains up to 64 bytes binary data
-                        * but in our case it will be a '\0'
-                        * terminated string */
-                    char *psz_ufid = (char*) malloc( 64 );
-                    int j = 0;
-                    while( ( j < 63 ) &&
-                            ( j < p_ufid->identifier().size() ) )
-                        psz_ufid[j] = p_ufid->identifier()[j++];
-                    psz_ufid[j] = '\0';
-                    vlc_meta_SetTrackID( p_meta, psz_ufid );
-                    free( psz_ufid );
-                }
-            }
+/**
+ * Read the meta informations from XiphComments
+ * @param tag: the Xiph Comment
+ * @param p_meta: the meta
+ * @return VLC_SUCCESS if everything goes ok
+ */
+static int ReadMetaFromXiph( Ogg::XiphComment* tag, vlc_meta_t* p_meta )
+{
+#define SET( metaName, keyName )                                               \
+    StringList list = tag->fieldListMap()[keyName];                            \
+    if( !list.isEmpty() )                                                      \
+        vlc_meta_Set##metaName( p_meta, (*list.begin()).toCString( true ) );
 
-            list = p_tag->frameListMap()["TXXX"];
-            ID3v2::UserTextIdentificationFrame* p_txxx;
-            for( ID3v2::FrameList::Iterator iter = list.begin();
-                    iter != list.end(); iter++ )
-            {
-                p_txxx = dynamic_cast<ID3v2::UserTextIdentificationFrame*>(*iter);
-                const char *psz_desc= p_txxx->description().toCString();
-                vlc_meta_AddExtra( p_meta, psz_desc,
-                            p_txxx->fieldList().toString().toCString());
-            }
-#if 0
-            list = p_tag->frameListMap()["RVA2"];
-            ID3v2::RelativeVolumeFrame* p_rva2;
-            for( ID3v2::FrameList::Iterator iter = list.begin();
-                    iter != list.end(); iter++ )
-            {
-                p_rva2 = dynamic_cast<ID3v2::RelativeVolumeFrame*>(*iter);
-                /* TODO: process rva2 frames */
-            }
-#endif
-            list = p_tag->frameList();
-            ID3v2::Frame* p_t;
-            char psz_tag[4];
-            for( ID3v2::FrameList::Iterator iter = list.begin();
-                    iter != list.end(); iter++ )
-            {
-                p_t = dynamic_cast<ID3v2::Frame*> (*iter);
-                memcpy( psz_tag, p_t->frameID().data(), 4);
-
-#define SET( foo, bar ) if( !strncmp( psz_tag, foo, 4 ) ) \
-vlc_meta_Set##bar( p_meta, p_t->toString().toCString(true))
-                SET( "TPUB", Publisher );
-                SET( "TCOP", Copyright );
-                SET( "TENC", EncodedBy );
-                SET( "TLAN", Language );
-                //SET( "POPM", Rating ); /* rating needs special handling in id3v2 */
-                //if( !strncmp( psz_tag, "RVA2", 4 ) )
-                    /* TODO */
+    SET( Copyright, "COPYRIGHT" );
 #undef SET
-            }
-        }
-    }
+    return VLC_SUCCESS;
+}
 
-    else if( Ogg::Vorbis::File *p_ogg_v =
-        dynamic_cast<Ogg::Vorbis::File *>(f.file() ) )
-    {
-        int i_ogg_v_length = p_ogg_v->audioProperties()->length();
 
-        input_thread_t *p_input = (input_thread_t *)
-                vlc_object_find( p_demux,VLC_OBJECT_INPUT, FIND_PARENT );
-        if( p_input )
-        {
-            input_item_t *p_item = input_GetItem( p_input );
-            if( p_item )
-                input_item_SetDuration( p_item,
-                        (mtime_t) i_ogg_v_length * 1000000 );
-            vlc_object_release( p_input );
-        }
 
-    }
-#if 0 /* at this moment, taglib is unable to detect ogg/flac files
-* becauses type detection is based on file extension:
-* ogg = ogg/vorbis
-* flac = flac
-* ø = ogg/flac
-*/
-    else if( Ogg::FLAC::File *p_ogg_f =
-        dynamic_cast<Ogg::FLAC::File *>(f.file() ) )
-    {
-        long i_ogg_f_length = p_ogg_f->streamLength();
-        input_thread_t *p_input = (input_thread_t *)
-                vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );
-        if( p_input )
-        {
-            input_item_t *p_item = input_GetItem( p_input );
-            if( p_item )
-                input_item_SetDuration( p_item,
-                        (mtime_t) i_ogg_f_length * 1000000 );
-            vlc_object_release( p_input );
-        }
-    }
-#endif
-    else if( FLAC::File *p_flac =
-        dynamic_cast<FLAC::File *>(f.file() ) )
-    {
-        long i_flac_length = p_flac->audioProperties()->length();
-        input_thread_t *p_input = (input_thread_t *)
-                vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );
-        if( p_input )
-        {
-            input_item_t *p_item = input_GetItem( p_input );
-            if( p_item )
-                input_item_SetDuration( p_item,
-                        (mtime_t) i_flac_length * 1000000 );
-            vlc_object_release( p_input );
-        }
-    }
+/**
+ * Get the tags from the file using TagLib
+ * @param p_this: the demux object
+ * @return VLC_SUCCESS if the operation success
+ */
+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;
+    vlc_meta_t*     p_meta;
+    TagLib::FileRef f;
+
+    p_demux_meta->p_meta = NULL;
+    const char* local_name = ToLocale( p_demux->psz_path );
+    if( !local_name )
+        return VLC_EGENERIC;
+    f = FileRef( local_name );
+    LocaleFree( local_name );
 
-#define SET( foo, bar ) vlc_meta_Set##foo( p_meta, p_tag->bar ().toCString(true))
-#define SETINT( foo, bar ) { \
-        char psz_tmp[10]; \
-        snprintf( (char*)psz_tmp, 10, "%d", p_tag->bar() ); \
-        vlc_meta_Set##foo( p_meta, (char*)psz_tmp ); \
+    if( f.isNull() )
+        return VLC_EGENERIC;
+    if( !f.tag() || f.tag()->isEmpty() )
+        return VLC_EGENERIC;
+
+    p_demux_meta->p_meta = p_meta = vlc_meta_New();
+    if( !p_meta )
+        return VLC_ENOMEM;
+
+
+    // Read the tags from the file
+    Tag* p_tag = f.tag();
+
+#define SET( meta, tag )                                                       \
+    if( !p_tag->tag().isNull() && !p_tag->tag().isEmpty() )                    \
+        vlc_meta_Set##meta( p_meta, p_tag->tag().toCString(true) )
+#define SETINT( meta, tag )                                                    \
+    if( p_tag->tag() )                                                         \
+    {                                                                          \
+        char psz_tmp[10];                                                      \
+        snprintf( psz_tmp, 10, "%d", p_tag->tag() );                           \
+        vlc_meta_Set##meta( p_meta, psz_tmp );                                 \
     }
 
     SET( Title, title );
@@ -419,22 +393,146 @@ vlc_meta_Set##bar( p_meta, p_t->toString().toCString(true))
     SET( Description, comment );
     SET( Genre, genre );
     SETINT( Date, year );
-    SETINT( Tracknum , track );
-#undef SET
+    SETINT( Tracknum, track );
+
 #undef SETINT
+#undef SET
 
+
+    // Try now to read special tags
+    if( FLAC::File* flac = dynamic_cast<FLAC::File*>(f.file()) )
+    {
+        if( flac->ID3v2Tag() )
+            ReadMetaFromId2v2( flac->ID3v2Tag(), p_meta );
+        else if( flac->xiphComment() )
+            ReadMetaFromXiph( flac->xiphComment(), p_meta );
+    }
+    else if( MPC::File* mpc = dynamic_cast<MPC::File*>(f.file()) )
+    {
+        if( mpc->APETag() )
+            ReadMetaFromAPE( mpc->APETag(), p_meta );
+    }
+    else if( MPEG::File* mpeg = dynamic_cast<MPEG::File*>(f.file()) )
+    {
+        if( mpeg->ID3v2Tag() )
+            ReadMetaFromId2v2( mpeg->ID3v2Tag(), p_meta );
+        else if( mpeg->APETag() )
+            ReadMetaFromAPE( mpeg->APETag(), p_meta );
+    }
+    else if( Ogg::File* ogg = dynamic_cast<Ogg::File*>(f.file()) )
+    {
+        if( Ogg::FLAC::File* ogg_flac = dynamic_cast<Ogg::FLAC::File*>(f.file()))
+            ReadMetaFromXiph( ogg_flac->tag(), p_meta );
+        else if( Ogg::Speex::File* ogg_speex = dynamic_cast<Ogg::Speex::File*>(f.file()) )
+            ReadMetaFromXiph( ogg_speex->tag(), p_meta );
+        else if( Ogg::Vorbis::File* ogg_vorbis = dynamic_cast<Ogg::Vorbis::File*>(f.file()) )
+            ReadMetaFromXiph( ogg_vorbis->tag(), p_meta );
+    }
+    else if( TrueAudio::File* trueaudio = dynamic_cast<TrueAudio::File*>(f.file()) )
+    {
+        if( trueaudio->ID3v2Tag() )
+            ReadMetaFromId2v2( trueaudio->ID3v2Tag(), p_meta );
+    }
+    else if( WavPack::File* wavpack = dynamic_cast<WavPack::File*>(f.file()) )
+    {
+        if( wavpack->APETag() )
+            ReadMetaFromAPE( wavpack->APETag(), p_meta );
+    }
+
+    // Try now to find a image
     DetectImage( f, p_demux );
 
     return VLC_SUCCESS;
 }
 
+
+
+/**
+ * Write meta informations to APE tags
+ * @param tag: the APE tag
+ * @param p_input: the input item
+ * @return VLC_SUCCESS if everything goes ok
+ */
+static int WriteMetaToAPE( APE::Tag* tag, input_item_t* p_input )
+{
+    return VLC_SUCCESS;
+}
+
+
+
+/**
+ * Write meta information to id3v2 tags
+ * @param tag: the id3v2 tag
+ * @param p_input: the input item
+ * @return VLC_SUCCESS if everything goes ok
+ */
+static int WriteMetaToId2v2( ID3v2::Tag* tag, input_item_t* p_item )
+{
+    char* psz_meta;
+#define WRITE( metaName, tagName )                                            \
+    psz_meta = input_item_Get##metaName( p_item );                            \
+    if( psz_meta )                                                            \
+    {                                                                         \
+        ByteVector p_byte( tagName, 4 );                                      \
+        tag->removeFrames( p_byte );                                         \
+        ID3v2::TextIdentificationFrame* p_frame =                             \
+            new ID3v2::TextIdentificationFrame( p_byte, String::UTF8 );       \
+        p_frame->setText( psz_meta );                                         \
+        tag->addFrame( p_frame );                                             \
+    }                                                                         \
+    free( psz_meta );
+
+    WRITE( Copyright, "TCOP" );
+    WRITE( EncodedBy, "TENC" );
+    WRITE( Language,  "TLAN" );
+    WRITE( Publisher, "TPUB" );
+
+#undef WRITE
+    return VLC_SUCCESS;
+}
+
+
+
+/**
+ * Write the meta informations to XiphComments
+ * @param tag: the Xiph Comment
+ * @param p_input: the input item
+ * @return VLC_SUCCESS if everything goes ok
+ */
+static int WriteMetaToXiph( Ogg::XiphComment* tag, input_item_t* p_item )
+{
+    char* psz_meta;
+#define WRITE( metaName, keyName )                      \
+    psz_meta = input_item_Get##metaName( p_item );      \
+    if( psz_meta )                                      \
+    {                                                   \
+        String key( keyName, String::UTF8 );            \
+        String value( psz_meta, String::UTF8 );         \
+        tag->addField( key, value, true );              \
+    }                                                   \
+    free( psz_meta );
+
+    WRITE( Copyright, "COPYRIGHT" );
+
+#undef WRITE
+    return VLC_SUCCESS;
+}
+
+
+
+/**
+ * Set the tags to the file using TagLib
+ * @param p_this: the demux object
+ * @return VLC_SUCCESS if the operation success
+ */
+
 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;
     input_item_t *p_item = p_export->p_item;
 
-    if( p_item == NULL )
+    if( !p_item )
     {
         msg_Err( p_this, "Can't save meta data of an empty input" );
         return VLC_EGENERIC;
@@ -454,31 +552,33 @@ static int WriteMeta( vlc_object_t *p_this )
 
     char *psz_meta;
 
-#define SET(a,b) \
-        if(b) { \
-            String *psz_##a = new String( b, \
-                String::UTF8 ); \
-            p_tag->set##a( *psz_##a ); \
-            delete psz_##a; \
-        }
+#define SET( a, b )                                         \
+    if( b )                                                 \
+    {                                                       \
+        String* psz_tmp = new String( b, String::UTF8 );    \
+        p_tag->set##a( *psz_tmp );                          \
+        delete psz_tmp;                                     \
+    }
 
+    // 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_GetTitle( p_item );
-    if( !psz_meta ) psz_meta = input_item_GetName( p_item );
-    String *psz_title = new String( psz_meta,
-        String::UTF8 );
-    p_tag->setTitle( *psz_title );
-    delete psz_title;
-    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 );
@@ -493,32 +593,55 @@ static int WriteMeta( vlc_object_t *p_this )
     if( psz_meta ) p_tag->setTrack( atoi( psz_meta ) );
     free( psz_meta );
 
-    if( ID3v2::Tag *p_id3tag =
-        dynamic_cast<ID3v2::Tag *>(p_tag) )
-    {
-#define WRITE( foo, bar ) \
-        psz_meta = input_item_Get##foo( p_item ); \
-        if( psz_meta ) \
-        { \
-            ByteVector p_byte( bar, 4 ); \
-            ID3v2::TextIdentificationFrame p_frame( p_byte ); \
-            p_frame.setText( psz_meta ); \
-            p_id3tag->addFrame( &p_frame ); \
-            free( psz_meta ); \
-        } \
-
-        WRITE( Publisher, "TPUB" );
-        WRITE( Copyright, "TCOP" );
-        WRITE( EncodedBy, "TENC" );
-        WRITE( Language, "TLAN" );
 
-#undef WRITE
+    // Try now to write special tags
+    if( FLAC::File* flac = dynamic_cast<FLAC::File*>(f.file()) )
+    {
+        if( flac->ID3v2Tag() )
+            WriteMetaToId2v2( flac->ID3v2Tag(), p_item );
+        else if( flac->xiphComment() )
+            WriteMetaToXiph( flac->xiphComment(), p_item );
+    }
+    else if( MPC::File* mpc = dynamic_cast<MPC::File*>(f.file()) )
+    {
+        if( mpc->APETag() )
+            WriteMetaToAPE( mpc->APETag(), p_item );
+    }
+    else if( MPEG::File* mpeg = dynamic_cast<MPEG::File*>(f.file()) )
+    {
+        if( mpeg->ID3v2Tag() )
+            WriteMetaToId2v2( mpeg->ID3v2Tag(), p_item );
+        else if( mpeg->APETag() )
+            WriteMetaToAPE( mpeg->APETag(), p_item );
+    }
+    else if( Ogg::File* ogg = dynamic_cast<Ogg::File*>(f.file()) )
+    {
+        if( Ogg::FLAC::File* ogg_flac = dynamic_cast<Ogg::FLAC::File*>(f.file()))
+            WriteMetaToXiph( ogg_flac->tag(), p_item );
+        else if( Ogg::Speex::File* ogg_speex = dynamic_cast<Ogg::Speex::File*>(f.file()) )
+            WriteMetaToXiph( ogg_speex->tag(), p_item );
+        else if( Ogg::Vorbis::File* ogg_vorbis = dynamic_cast<Ogg::Vorbis::File*>(f.file()) )
+            WriteMetaToXiph( ogg_vorbis->tag(), p_item );
+    }
+    else if( TrueAudio::File* trueaudio = dynamic_cast<TrueAudio::File*>(f.file()) )
+    {
+        if( trueaudio->ID3v2Tag() )
+            WriteMetaToId2v2( trueaudio->ID3v2Tag(), p_item );
+    }
+    else if( WavPack::File* wavpack = dynamic_cast<WavPack::File*>(f.file()) )
+    {
+        if( wavpack->APETag() )
+            WriteMetaToAPE( wavpack->APETag(), p_item );
     }
 
+    // Save the meta data
     f.save();
+
     return VLC_SUCCESS;
 }
 
+
+
 static int DownloadArt( vlc_object_t *p_this )
 {
     /* We need to be passed the file name