]> git.sesse.net Git - vlc/commitdiff
taglib: support for id3v2 embedded album art
authorRafaël Carré <funman@videolan.org>
Tue, 2 Oct 2007 02:11:11 +0000 (02:11 +0000)
committerRafaël Carré <funman@videolan.org>
Tue, 2 Oct 2007 02:11:11 +0000 (02:11 +0000)
the only demuxer supported is mpga, other demuxers should be updated if they demux files that can have id3v2 tags
fix some bugs in flac & ogg demuxers

include/vlc_common.h
include/vlc_demux.h
modules/codec/ffmpeg/demux.c
modules/demux/flac.c
modules/demux/mpc.c
modules/demux/mpeg/m4a.c
modules/demux/mpeg/mpga.c
modules/demux/ogg.c
modules/demux/tta.c
modules/meta_engine/id3tag.c
modules/meta_engine/taglib.cpp

index 2fd81d1e8204364fd08fb33b461fd576a65a0012..81c11928665946ea72c8cce1be2d410c46fcf949 100644 (file)
@@ -281,6 +281,7 @@ typedef struct access_sys_t access_sys_t;
 typedef struct stream_t     stream_t;
 typedef struct stream_sys_t stream_sys_t;
 typedef struct demux_t  demux_t;
+typedef struct demux_meta_t demux_meta_t;
 typedef struct demux_sys_t demux_sys_t;
 typedef struct es_out_t     es_out_t;
 typedef struct es_out_id_t  es_out_id_t;
index a34a5873484d811134e34cf36592bfe3b4b16d15..4d9b57980f9b283be4af6c76b8f648a53c6ac71e 100644 (file)
@@ -72,6 +72,16 @@ struct demux_t
     demux_sys_t *p_sys;
 };
 
+
+/* demux_meta_t is returned by "meta reader" module to the demuxer */
+struct demux_meta_t
+{
+    vlc_meta_t *p_meta;                 /**< meta data */
+
+    int i_attachments;                  /**< number of attachments */
+    input_attachment_t **attachments;    /**< array of attachments */
+};
+
 enum demux_query_e
 {
     /* I. Common queries to access_demux and demux */
index a783689958a6f865e381e15a858c64228551e265..1ac73a13f84d4d679bdc171dfe201196408d5f2b 100644 (file)
@@ -259,13 +259,25 @@ int E_(OpenDemux)( vlc_object_t *p_this )
     input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );
     if( p_input )
     {
+        p_demux->p_private = malloc( sizeof( demux_meta_t ) );
+        if( !p_demux->p_private )
+        {
+            vlc_object_release( p_input );
+            return VLC_ENOMEM;
+        }
         module_t *p_meta = module_Need( p_demux, "meta reader", NULL, 0 );
         if( p_meta )
         {
-            vlc_meta_Merge( input_GetItem(p_input)->p_meta, (vlc_meta_t*)(p_demux->p_private ) );
+            demux_meta_t *p_demux_meta = (demux_meta_t *)p_demux->p_private;
+            vlc_meta_Merge( input_GetItem(p_input)->p_meta,
+                    p_demux_meta->p_meta );
+            vlc_meta_Delete( p_demux_meta->p_meta );
             module_Unneed( p_demux, p_meta );
+            TAB_CLEAN( p_demux_meta->i_attachments,
+                    p_demux_meta->attachments );
         }
         vlc_object_release( p_input );
+        free( p_demux->p_private );
     }
 
     return VLC_SUCCESS;
index bb17b7ba677000e6874a4fe62637fc3d8731bd9e..0943d70532827a417bf92cc75c7ef5e3b38eb549 100644 (file)
@@ -78,8 +78,8 @@ struct demux_sys_t
     seekpoint_t **seekpoint;
 
     /* */
-    int                i_attachment;
-    input_attachment_t **attachment;
+    int                i_attachments;
+    input_attachment_t **attachments;
     int                i_cover_idx;
     int                i_cover_score;
 };
@@ -123,7 +123,7 @@ static int Open( vlc_object_t * p_this )
     p_sys->i_pts_start = 0;
     p_sys->p_es = NULL;
     TAB_INIT( p_sys->i_seekpoint, p_sys->seekpoint );
-    TAB_INIT( p_sys->i_attachment, p_sys->attachment );
+    TAB_INIT( p_sys->i_attachments, p_sys->attachments);
     p_sys->i_cover_idx = 0;
     p_sys->i_cover_score = 0;
 
@@ -155,9 +155,13 @@ static int Open( vlc_object_t * p_this )
     }
 
     /* Parse possible id3 header */
+    p_demux->p_private = malloc( sizeof( demux_meta_t ) );
+    if( !p_demux->p_private )
+        return VLC_ENOMEM;
     if( ( p_id3 = module_Need( p_demux, "meta reader", NULL, 0 ) ) )
     {
-        vlc_meta_t *p_meta = (vlc_meta_t *)p_demux->p_private;
+        demux_meta_t *p_demux_meta = (demux_meta_t *)p_demux->p_private;
+        vlc_meta_t *p_meta = p_demux_meta->p_meta;
 
         if( !p_sys->p_meta )
         {
@@ -170,15 +174,23 @@ static int Open( vlc_object_t * p_this )
         }
         p_demux->p_private = NULL;
         module_Unneed( p_demux, p_id3 );
+        int i;
+        for( i = 0; i < p_demux_meta->i_attachments; i++ )
+            TAB_APPEND_CAST( (input_attachment_t**),
+                    p_sys->i_attachments, p_sys->attachments,
+                    p_demux_meta->attachments[p_demux_meta->i_attachments] );
+
+        TAB_CLEAN( p_demux_meta->i_attachments, p_demux_meta->attachments );
     }
+    free( p_demux->p_private );
 
-    if( p_sys->i_cover_idx < p_sys->i_attachment )
+    if( p_sys->i_cover_idx < p_sys->i_attachments )
     {
         char psz_url[128];
         if( !p_sys->p_meta )
             p_sys->p_meta = vlc_meta_New();
         snprintf( psz_url, sizeof(psz_url), "attachment://%s",
-                  p_sys->attachment[p_sys->i_cover_idx]->psz_name );
+                  p_sys->attachments[p_sys->i_cover_idx]->psz_name );
         vlc_meta_Set( p_sys->p_meta, vlc_meta_ArtworkURL, psz_url );
     }
     vlc_audio_replay_gain_MergeFromMeta( &p_sys->replay_gain, p_sys->p_meta );
@@ -193,6 +205,9 @@ static void Close( vlc_object_t * p_this )
     demux_t     *p_demux = (demux_t*)p_this;
     demux_sys_t *p_sys = p_demux->p_sys;
 
+    TAB_CLEAN( p_sys->i_seekpoint, p_sys->seekpoint );
+    TAB_CLEAN( p_sys->i_attachments, p_sys->attachments);
+
     /* Unneed module */
     module_Unneed( p_sys->p_packetizer, p_sys->p_packetizer->p_module );
 
@@ -394,13 +409,13 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
         int *pi_int = (int*)va_arg( args, int * );
         int i;
 
-        if( p_sys->i_attachment <= 0 )
+        if( p_sys->i_attachments <= 0 )
             return VLC_EGENERIC;
 
-        *pi_int = p_sys->i_attachment;;
-        *ppp_attach = malloc( sizeof(input_attachment_t**) * p_sys->i_attachment );
-        for( i = 0; i < p_sys->i_attachment; i++ )
-            *(ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachment[i] );
+        *pi_int = p_sys->i_attachments;;
+        *ppp_attach = malloc( sizeof(input_attachment_t**) * p_sys->i_attachments );
+        for( i = 0; i < p_sys->i_attachments; i++ )
+            (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );
         return VLC_SUCCESS;
     }
 
@@ -473,8 +488,6 @@ static int  ReadMeta( demux_t *p_demux, uint8_t **pp_streaminfo, int *pi_streami
     s->i_byte_offset = 0;
     TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );
 
-
-
     b_last = (*pp_streaminfo)[4]&0x80;
     while( !b_last )
     {
@@ -699,7 +712,7 @@ static void ParsePicture( demux_t *p_demux, const uint8_t *p_data, int i_data )
     msg_Dbg( p_demux, "FLAC: Picture type=%d mime=%s description='%s' file length=%d",
              i_type, psz_mime, psz_description, i_len );
 
-    snprintf( psz_name, sizeof(psz_name), "picture%d", p_sys->i_attachment );
+    snprintf( psz_name, sizeof(psz_name), "picture%d", p_sys->i_attachments );
     if( !strcasecmp( psz_mime, "image/jpeg" ) )
         strcat( psz_name, ".jpg" );
     else if( !strcasecmp( psz_mime, "image/png" ) )
@@ -707,12 +720,12 @@ static void ParsePicture( demux_t *p_demux, const uint8_t *p_data, int i_data )
 
     p_attachment = vlc_input_attachment_New( psz_name, psz_mime, psz_description,
                                              p_data, i_data );
-    TAB_APPEND( p_sys->i_attachment, p_sys->attachment, p_attachment );
+    TAB_APPEND( p_sys->i_attachments, p_sys->attachments, p_attachment );
 
     if( i_type >= 0 && i_type < sizeof(pi_cover_score)/sizeof(pi_cover_score[0]) &&
         p_sys->i_cover_score < pi_cover_score[i_type] )
     {
-        p_sys->i_cover_idx = p_sys->i_attachment-1;
+        p_sys->i_cover_idx = p_sys->i_attachments-1;
         p_sys->i_cover_score = pi_cover_score[i_type];
     }
 error:
index d34ddba908f30aff892aacf725b6efbcd54cbc3f..7a8a0c2b63a1e47ebc846eaa8f8d29eda55765fc 100644 (file)
@@ -189,12 +189,17 @@ static int Open( vlc_object_t * p_this )
     }
 
     /* Parse possible id3 header */
+    p_demux->p_private = malloc( sizeof( demux_meta_t ) );
+    if( !p_demux->p_private )
+        return VLC_ENOMEM;
     if( ( p_id3 = module_Need( p_demux, "meta reader", NULL, 0 ) ) )
     {
-        p_sys->p_meta = (vlc_meta_t *)p_demux->p_private;
-        p_demux->p_private = NULL;
+        demux_meta_t *p_demux_meta = (demux_meta_t *)p_demux->p_private;
+        p_sys->p_meta = p_demux_meta->p_meta;
         module_Unneed( p_demux, p_id3 );
+        TAB_CLEAN( p_demux_meta->i_attachments, p_demux_meta->attachments );
     }
+    free( p_demux->p_private );
 
     if( !p_sys->p_meta )
         p_sys->p_meta = vlc_meta_New();
index 049e9a878225dc86cf70a74b379e1857d9063c79..7e17ea4bae8b68c65aeb509c7818440fb92fcdb2 100644 (file)
@@ -115,12 +115,18 @@ static int Open( vlc_object_t * p_this )
     LOAD_PACKETIZER_OR_FAIL( p_sys->p_packetizer, "mp4 audio" );
 
     /* Parse possible id3 header */
+    p_demux->p_private = malloc( sizeof( demux_meta_t ) );
+    if( !p_demux->p_private )
+        return VLC_ENOMEM;
     if( ( p_id3 = module_Need( p_demux, "meta reader", NULL, 0 ) ) )
     {
-        p_sys->meta = (vlc_meta_t *)p_demux->p_private;
+        demux_meta_t *p_demux_meta = (demux_meta_t *)p_demux->p_private;
+        p_sys->meta = p_demux_meta->p_meta;
         p_demux->p_private = NULL;
         module_Unneed( p_demux, p_id3 );
+        TAB_CLEAN( p_demux_meta->i_attachments, p_demux_meta->attachments );
     }
+    free( p_demux->p_private );
     return VLC_SUCCESS;
 }
 
index a7c9f5753627dad19aa9e8094b7c4442e7030892..a66c791ab5f5ab3e6a0fccd9550155d4c84fc682 100644 (file)
@@ -74,6 +74,9 @@ struct demux_sys_t
     int i_xing_bitrate_avg;
     int i_xing_frame_samples;
     block_t *p_block_in, *p_block_out;
+
+    int                i_attachments;
+    input_attachment_t **attachments;
 };
 
 static int HeaderCheck( uint32_t h )
@@ -252,12 +255,19 @@ static int Open( vlc_object_t * p_this )
     p_sys->p_block_out = p_block_out;
 
     /* Parse possible id3 header */
+    p_demux->p_private = malloc( sizeof( demux_meta_t ) );
+    if( !p_demux->p_private )
+        return VLC_ENOMEM;
     if( ( p_id3 = module_Need( p_demux, "meta reader", NULL, 0 ) ) )
     {
-        p_sys->meta = (vlc_meta_t *)p_demux->p_private;
+        demux_meta_t *p_demux_meta = (demux_meta_t *)p_demux->p_private;
+        p_sys->meta = p_demux_meta->p_meta;
         p_demux->p_private = NULL;
         module_Unneed( p_demux, p_id3 );
+        p_sys->i_attachments = p_demux_meta->i_attachments;
+        p_sys->attachments = p_demux_meta->attachments;
     }
+    free( p_demux->p_private );
 
     /* */
     p_sys->p_packetizer->fmt_out.b_packetized = VLC_TRUE;
@@ -337,6 +347,8 @@ static void Close( vlc_object_t * p_this )
     if( p_sys->meta ) vlc_meta_Delete( p_sys->meta );
     if( p_sys->p_block_out ) block_Release( p_sys->p_block_out );
 
+    TAB_CLEAN( p_sys->i_attachments, p_sys->attachments);
+
     free( p_sys );
 }
 
@@ -350,6 +362,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
     vlc_meta_t *p_meta;
     int i_ret;
 
+    input_attachment_t ***ppp_attach;
+    int *pi_int, i;
+
     switch( i_query )
     {
         case DEMUX_GET_META:
@@ -357,6 +372,20 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             vlc_meta_Merge( p_meta, p_sys->meta );
             return VLC_SUCCESS;
 
+        case DEMUX_GET_ATTACHMENTS:
+            ppp_attach =
+                (input_attachment_t***)va_arg( args, input_attachment_t*** );
+            pi_int = (int*)va_arg( args, int * );
+
+            if( p_sys->i_attachments <= 0 )
+                return VLC_EGENERIC;
+
+            *pi_int = p_sys->i_attachments;
+            *ppp_attach = malloc( sizeof(input_attachment_t**) * p_sys->i_attachments );
+            for( i = 0; i < p_sys->i_attachments; i++ )
+                (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );
+            return VLC_SUCCESS;
+
         case DEMUX_GET_TIME:
             pi64 = (int64_t*)va_arg( args, int64_t * );
             *pi64 = p_sys->i_pts + p_sys->i_time_offset;
index 83271d051746d32415bce8ae030351982e4630ff..fb4d4e6d34754e955e3bceb902397146f6b85722 100644 (file)
@@ -207,17 +207,25 @@ static int Open( vlc_object_t * p_this )
     p_input = (input_thread_t *)vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );
     if( p_input )
     {
+        p_demux->p_private = malloc( sizeof( demux_meta_t ) );
+        if( !p_demux->p_private )
+        {
+            vlc_object_release( p_input );
+            return VLC_ENOMEM;
+        }
         module_t *p_meta = module_Need( p_demux, "meta reader", NULL, 0 );
         if( p_meta )
         {
-            vlc_meta_Merge( input_GetItem(p_input)->p_meta, (vlc_meta_t*)(p_demux->p_private ) );
+            demux_meta_t *p_demux_meta = (demux_meta_t *)p_demux->p_private;
+            vlc_meta_Merge( input_GetItem(p_input)->p_meta,
+                    p_demux_meta->p_meta );
+            vlc_meta_Delete( p_demux_meta->p_meta );
             module_Unneed( p_demux, p_meta );
+            TAB_CLEAN( p_demux_meta->i_attachments, p_demux_meta->attachments );
         }
         vlc_object_release( p_input );
-        return VLC_SUCCESS;
+        free( p_demux->p_private );
     }
-    if( p_input )
-        vlc_object_release( p_input );
 
     /* Initialize the Ogg physical bitstream parser */
     ogg_sync_init( &p_sys->oy );
index 20d7d7e8298d5c72f00b835246c334bdc48ec588..ec9bb42d8c9412066cd00e6ce9001224fdf8a5fd 100644 (file)
@@ -105,7 +105,7 @@ static int Open( vlc_object_t * p_this )
     p_demux->pf_demux = Demux;
     p_demux->pf_control = Control;
     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
+
     /* Read the metadata */
     es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'T', 'T', 'A', '1' ) );
     fmt.audio.i_channels = GetWLE( &p_header[6] );
@@ -138,15 +138,21 @@ static int Open( vlc_object_t * p_this )
     p_sys->p_es = es_out_Add( p_demux->out, &fmt );
     free( p_seektable );
     p_sys->i_start = stream_Tell( p_demux->s );
+
 #if 0
     /* Parse possible id3 header */
+    p_demux->p_private = malloc( sizeof( demux_meta_t ) );
+    if( !p_demux->p_private )
+        return VLC_ENOMEM;
     if( ( p_id3 = module_Need( p_demux, "meta reader", NULL, 0 ) ) )
     {
-        p_sys->p_meta = (vlc_meta_t *)p_demux->p_private;
+        demux_meta_t *p_demux_meta = (demux_meta_t *)p_demux->p_private;
+        p_sys->p_meta = p_demux_meta->p_meta;
         p_demux->p_private = NULL;
         module_Unneed( p_demux, p_id3 );
+        TAB_CLEAN( p_demux_meta->i_attachments, p_demux_meta->attachments );
     }
+    free( p_demux->p_private );
 
     if( !p_sys->p_meta )
         p_sys->p_meta = vlc_meta_New();
index 13628f21c0780db51cd2cf3bf936403eff5e8f0e..c2a1c30862c33196fd52d3b0dbf4975e9a14822d 100644 (file)
@@ -61,15 +61,18 @@ static void ParseID3Tag( demux_t *p_demux, uint8_t *p_data, int i_size )
 {
     struct id3_tag   *p_id3_tag;
     struct id3_frame *p_frame;
-    vlc_meta_t *p_meta = (vlc_meta_t *)p_demux->p_private;
+    demux_meta_t     *p_demux_meta = p_demux->p_private;
+    vlc_meta_t       *p_meta;
     int i;
 
+    TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments );
+    p_demux_meta->p_meta = NULL;
+
     p_id3_tag = id3_tag_parse( p_data, i_size );
     if( !p_id3_tag )
         return;
 
-    if( !p_meta )
-        p_demux->p_private = p_meta = vlc_meta_New();
+    p_demux_meta->p_meta = p_meta = vlc_meta_New();
 
 #define ID_IS( a ) (!strcmp(  p_frame->id, a ))
 #define DESCR_IS( a) strstr( (char*)p_frame->description, a )
index 1a90d580d39777aa0de16c6408775e549046e25a..744dad0e4eeb936afbda52f3864f385520e85431 100644 (file)
@@ -35,6 +35,7 @@
 #include <tbytevector.h>
 #include <mpegfile.h>
 #include <flacfile.h>
+#include <attachedpictureframe.h>
 #if 0
 #include <oggflacfile.h>
 #endif
@@ -63,27 +64,114 @@ vlc_module_begin();
         set_callbacks( WriteMeta, NULL );
 vlc_module_end();
 
-static bool checkID3Image( const TagLib::ID3v2::Tag *p_tag )
-{
-    TagLib::ID3v2::FrameList l = p_tag->frameListMap()[ "APIC" ];
-    return !l.isEmpty();
-}
-
 /* Try detecting embedded art */
-static void DetectImage( TagLib::FileRef f, vlc_meta_t *p_meta )
+static void DetectImage( TagLib::FileRef f, demux_t *p_demux )
 {
+    demux_meta_t        *p_demux_meta   = (demux_meta_t *)p_demux->p_private;
+    vlc_meta_t          *p_meta         = p_demux_meta->p_meta;
+    TagLib::ID3v2::Tag  *p_tag;
+    int                 i_score         = -1;
+
+    /* Preferred type of image
+     * The 21 types are defined in id3v2 standard:
+     * http://www.id3.org/id3v2.4.0-frames */
+    static const int pi_cover_score[] = {
+        0,  /* Other */
+        5,  /* 32x32 PNG image that should be used as the file icon */
+        4,  /* File icon of a different size or format. */
+        20, /* Front cover image of the album. */
+        19, /* Back cover image of the album. */
+        13, /* Inside leaflet page of the album. */
+        18, /* Image from the album itself. */
+        17, /* Picture of the lead artist or soloist. */
+        16, /* Picture of the artist or performer. */
+        14, /* Picture of the conductor. */
+        15, /* Picture of the band or orchestra. */
+        9,  /* Picture of the composer. */
+        8,  /* Picture of the lyricist or text writer. */
+        7,  /* Picture of the recording location or studio. */
+        10, /* Picture of the artists during recording. */
+        11, /* Picture of the artists during performance. */
+        6,  /* Picture from a movie or video related to the track. */
+        1,  /* Picture of a large, coloured fish. */
+        12, /* Illustration related to the track. */
+        3,  /* Logo of the band or performer. */
+        2   /* Logo of the publisher (record company). */
+    };
+
     if( TagLib::MPEG::File *mpeg =
                dynamic_cast<TagLib::MPEG::File *>(f.file() ) )
     {
-        if( mpeg->ID3v2Tag() && checkID3Image( mpeg->ID3v2Tag() ) )
-            vlc_meta_SetArtURL( p_meta, "APIC" );
+        p_tag = mpeg->ID3v2Tag();
+        if( !p_tag )
+            return;
+        TagLib::ID3v2::FrameList list = p_tag->frameListMap()[ "APIC" ];
+        if( list.isEmpty() )
+            return;
+        input_thread_t *p_input = (input_thread_t *)
+                vlc_object_find( p_demux,VLC_OBJECT_INPUT, FIND_PARENT );
+        if( !p_input )
+            return;
+        input_item_t *p_item = input_GetItem( p_input );
+        TagLib::ID3v2::AttachedPictureFrame *p_apic;
+
+        TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments );
+        for( TagLib::ID3v2::FrameList::Iterator iter = list.begin();
+                iter != list.end(); iter++ )
+        {
+            p_apic = dynamic_cast<TagLib::ID3v2::AttachedPictureFrame*>(*iter);
+            input_attachment_t *p_attachment;
+
+            const char *psz_name, *psz_mime, *psz_description;
+            TagLib::ByteVector p_data_taglib; const char *p_data; int i_data;
+
+            psz_mime = p_apic->mimeType().toCString(true);
+            psz_description = p_apic->description().toCString(true);
+            psz_name = psz_description;
+
+            p_data_taglib = p_apic->picture();
+            p_data = p_data_taglib.data();
+            i_data = p_data_taglib.size();
+
+            msg_Dbg( p_demux, "Found embedded art: %s (%s) is %i bytes",
+                    psz_name, psz_mime, i_data );
+
+            p_attachment = vlc_input_attachment_New( psz_name, psz_mime,
+                    psz_description, p_data, i_data );
+            TAB_APPEND_CAST( (input_attachment_t**),
+                    p_demux_meta->i_attachments, p_demux_meta->attachments,
+                    p_attachment );
+
+            if( pi_cover_score[p_apic->type()] > i_score )
+            {
+                i_score = pi_cover_score[p_apic->type()];
+                char *psz_url;
+                if( asprintf( &psz_url, "attachment://%s",
+                        p_attachment->psz_name ) == -1 )
+                {
+                    vlc_object_release( p_input );
+                    return;
+                }
+                vlc_meta_SetArtURL( p_meta, psz_url );
+                free( psz_url );
+            }
+        }
+        vlc_object_release( p_input );
     }
+#if 0
+    //flac embedded images are extracted in the flac demuxer
     else if( TagLib::FLAC::File *flac =
              dynamic_cast<TagLib::FLAC::File *>(f.file() ) )
     {
-        if( flac->ID3v2Tag() && checkID3Image( flac->ID3v2Tag() ) )
+        p_tag = flac->ID3v2Tag();
+        if( p_tag )
+            return;
+        TagLib::ID3v2::FrameList l = p_tag->frameListMap()[ "APIC" ];
+        if( l.isEmpty() )
+            return;
             vlc_meta_SetArtURL( p_meta, "APIC" );
     }
+#endif
 #if 0
 /* This needs special additions to taglib */
  * else if( TagLib::MP4::File *mp4 =
@@ -99,10 +187,12 @@ static void DetectImage( TagLib::FileRef f, vlc_meta_t *p_meta )
 
 static int ReadMeta( vlc_object_t *p_this )
 {
-    demux_t *p_demux = (demux_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 = p_demux_meta->p_meta;
 
-    if( strncmp( p_demux->psz_access, "file", 4 ) )
-        return VLC_EGENERIC;
+    TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments );
+    p_demux_meta->p_meta = NULL;
 
     TagLib::FileRef f( p_demux->psz_path );
     if( f.isNull() )
@@ -111,9 +201,7 @@ static int ReadMeta( vlc_object_t *p_this )
     if ( !f.tag() || f.tag()->isEmpty() )
         return VLC_EGENERIC;
 
-    if( !p_demux->p_private )
-        p_demux->p_private = (void*)vlc_meta_New();
-    vlc_meta_t *p_meta = (vlc_meta_t *)(p_demux->p_private );
+    p_demux_meta->p_meta = p_meta = vlc_meta_New();
     TagLib::Tag *p_tag = f.tag();
 
     if( TagLib::MPEG::File *p_mpeg =
@@ -203,7 +291,7 @@ vlc_meta_Set##bar( p_meta, p_t->toString().toCString(true))
                         (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:
@@ -260,7 +348,7 @@ vlc_meta_Set##bar( p_meta, p_t->toString().toCString(true))
 #undef SET
 #undef SETINT
 
-    DetectImage( f, p_meta );
+    DetectImage( f, p_demux );
 
     return VLC_SUCCESS;
 }
@@ -270,7 +358,7 @@ 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 )
     {
         msg_Err( p_this, "Can't save meta data of an empty input" );
@@ -348,7 +436,7 @@ static int WriteMeta( vlc_object_t *p_this )
         WRITE( Copyright, "TCOP" );
         WRITE( EncodedBy, "TENC" );
         WRITE( Language, "TLAN" );
+
 #undef WRITE
     }