Commit 898d2349 authored by Rémi Duraffort's avatar Rémi Duraffort Committed by Jean-Baptiste Kempf

Taglib: support for wma/ape and improve mp4 support

Notably for Cover Art support

(cherry picked from commit c21bb29ae63d827b24396a5fd0d024768709dd85)
(cherry picked from commit 277eb4cfbc9c7b37752b781029899177caade0dd)
(cherry picked from commit c405205e9a82ad0b1b63556f718580ef8ccd0205)
(cherry picked from commit 01cf70073fb52a2a8a7e504eaa2fe8a22c9e382b)
(cherry picked from commit b4b357ee09e5a99373b99d5c609bf832f484f748)
(cherry picked from commit 599eee103d3b6d597b8e5a4f3c9cd86df931e7cf)
(cherry picked from commit d158270ed7e2a3c1aea9fa137e65a42600e94f44)
(cherry picked from commit 57333f5920db4a41a2d9a7965bb4d7a1df7e61c2)
(cherry picked from commit 449b78e85a7867e38dc1fafe1b10f8339faea418)
(cherry picked from commit 7bdcc742148598bb17ebfb2eaeb4eeb378d13d81)
(cherry picked from commit 10ca2d59677fc9e6d551f420fe87887b050f354a)
(cherry picked from commit 4bdaae499b63956393104639300747fc25de28af)
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 436d36cc
...@@ -1741,9 +1741,6 @@ AC_ARG_ENABLE(taglib, ...@@ -1741,9 +1741,6 @@ AC_ARG_ENABLE(taglib,
[ VLC_ADD_PLUGIN([taglib]) [ VLC_ADD_PLUGIN([taglib])
VLC_ADD_LIBS([taglib],[$TAGLIB_LIBS -lz]) VLC_ADD_LIBS([taglib],[$TAGLIB_LIBS -lz])
VLC_ADD_CXXFLAGS([taglib],[$TAGLIB_CFLAGS]) VLC_ADD_CXXFLAGS([taglib],[$TAGLIB_CFLAGS])
AC_LANG_PUSH(C++)
AC_CHECK_HEADERS(taglib/mp4coverart.h)
AC_LANG_POP(C++)
], ],
[AC_MSG_WARN(TagLib library not found)]) [AC_MSG_WARN(TagLib library not found)])
]) ])
......
/***************************************************************************** /*****************************************************************************
* taglib.cpp: Taglib tag parser/writer * taglib.cpp: Taglib tag parser/writer
***************************************************************************** *****************************************************************************
* Copyright (C) 2003-2009 the VideoLAN team * Copyright (C) 2003-2011 the VideoLAN team
* $Id$ * $Id$
* *
* Authors: Clément Stenac <zorglub@videolan.org> * Authors: Clément Stenac <zorglub@videolan.org>
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include <vlc_demux.h> #include <vlc_demux.h>
#include <vlc_strings.h> #include <vlc_strings.h>
#include <vlc_charset.h> #include <vlc_charset.h>
#include <vlc_url.h> #include <vlc_input.h> /* for attachment_new */
#ifdef WIN32 #ifdef WIN32
# include <io.h> # include <io.h>
...@@ -44,26 +44,40 @@ ...@@ -44,26 +44,40 @@
// Taglib headers // Taglib headers
#include <taglib.h>
#define VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c))
#define TAGLIB_VERSION VERSION_INT(TAGLIB_MAJOR_VERSION, \
TAGLIB_MINOR_VERSION, \
TAGLIB_PATCH_VERSION)
#include <fileref.h> #include <fileref.h>
#include <tag.h> #include <tag.h>
#include <tbytevector.h> #include <tbytevector.h>
#include <apetag.h> #if TAGLIB_VERSION >= VERSION_INT(1,7,0)
#include <id3v2tag.h> # define TAGLIB_HAVE_APEFILE_H
#include <xiphcomment.h> # include <apefile.h>
# ifdef TAGLIB_WITH_ASF // ASF pictures comes with v1.7.0
# define TAGLIB_HAVE_ASFPICTURE_H
# include <asffile.h>
# endif
#endif
#include <apetag.h>
#include <flacfile.h> #include <flacfile.h>
#include <mpcfile.h> #include <mpcfile.h>
#include <mpegfile.h> #include <mpegfile.h>
#include <oggfile.h> #include <oggfile.h>
#include <oggflacfile.h> #include <oggflacfile.h>
#ifdef TAGLIB_WITH_ASF #if TAGLIB_VERSION >= VERSION_INT(1,6,0)
# define TAGLIB_HAVE_AIFF_WAV_H
# include <aifffile.h> # include <aifffile.h>
# include <wavfile.h> # include <wavfile.h>
#endif #endif
#ifdef TAGLIB_WITH_MP4 #if TAGLIB_VERSION >= VERSION_INT(1,6,1) && defined(TAGLIB_WITH_MP4)
# define TAGLIB_HAVE_MP4COVERTART_H
# include <mp4file.h> # include <mp4file.h>
#endif #endif
...@@ -97,11 +111,10 @@ using namespace TagLib; ...@@ -97,11 +111,10 @@ using namespace TagLib;
/** /**
* Read meta informations from APE tags * Read meta informations from APE tags
* @param tag: the APE tag * @param tag: the APE tag
* @param p_demux; the demux object
* @param p_demux_meta: the demuxer meta * @param p_demux_meta: the demuxer meta
* @param p_meta: the meta * @param p_meta: the meta
*/ */
static void ReadMetaFromAPE( APE::Tag* tag, demux_t* p_demux, demux_meta_t* p_demux_meta, vlc_meta_t* p_meta ) static void ReadMetaFromAPE( APE::Tag* tag, demux_meta_t*, vlc_meta_t* p_meta )
{ {
APE::Item item; APE::Item item;
#define SET( keyName, metaName ) \ #define SET( keyName, metaName ) \
...@@ -116,15 +129,62 @@ static void ReadMetaFromAPE( APE::Tag* tag, demux_t* p_demux, demux_meta_t* p_de ...@@ -116,15 +129,62 @@ static void ReadMetaFromAPE( APE::Tag* tag, demux_t* p_demux, demux_meta_t* p_de
} }
#ifdef TAGLIB_HAVE_ASFPICTURE_H
/**
* Read meta information from APE tags
* @param tag: the APE tag
* @param p_demux_meta: the demuxer meta
* @param p_meta: the meta
*/
static void ReadMetaFromASF( ASF::Tag* tag, demux_meta_t* p_demux_meta, vlc_meta_t* p_meta )
{
// List the pictures
ASF::AttributeList list = tag->attributeListMap()["WM/Picture"];
ASF::AttributeList::Iterator iter;
for( iter = list.begin(); iter != list.end(); iter++ )
{
const ASF::Picture asfPicture = (*iter).toPicture();
const ByteVector picture = asfPicture.picture();
const char *psz_mime = asfPicture.mimeType().toCString();
const char *p_data = picture.data();
const unsigned i_data = picture.size();
char *psz_name;
input_attachment_t *p_attachment;
if( asfPicture.description().size() > 0 )
psz_name = strdup( asfPicture.description().toCString( true ) );
else
{
if( asprintf( &psz_name, "%i", asfPicture.type() ) == -1 )
continue;
}
p_attachment = vlc_input_attachment_New( psz_name, psz_mime,
psz_name, p_data, i_data );
if( p_attachment )
TAB_APPEND_CAST( (input_attachment_t**),
p_demux_meta->i_attachments, p_demux_meta->attachments,
p_attachment );
free( psz_name );
char *psz_url;
if( asprintf( &psz_url, "attachment://%s",
p_attachment->psz_name ) == -1 )
continue;
vlc_meta_SetArtURL( p_meta, psz_url );
free( psz_url );
}
}
#endif
/** /**
* Read meta information from id3v2 tags * Read meta information from id3v2 tags
* @param tag: the id3v2 tag * @param tag: the id3v2 tag
* @param p_demux; the demux object
* @param p_demux_meta: the demuxer meta * @param p_demux_meta: the demuxer meta
* @param p_meta: the meta * @param p_meta: the meta
*/ */
static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t* p_demux_meta, vlc_meta_t* p_meta ) static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_meta_t* p_demux_meta, vlc_meta_t* p_meta )
{ {
// Get the unique file identifier // Get the unique file identifier
ID3v2::FrameList list = tag->frameListMap()["UFID"]; ID3v2::FrameList list = tag->frameListMap()["UFID"];
...@@ -281,18 +341,17 @@ static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t* ...@@ -281,18 +341,17 @@ static void ReadMetaFromId3v2( ID3v2::Tag* tag, demux_t* p_demux, demux_meta_t*
} }
/** /**
* Read the meta informations from XiphComments * Read the meta informations from XiphComments
* @param tag: the Xiph Comment * @param tag: the Xiph Comment
* @param p_demux; the demux object
* @param p_demux_meta: the demuxer meta * @param p_demux_meta: the demuxer meta
* @param p_meta: the meta * @param p_meta: the meta
*/ */
static void ReadMetaFromXiph( Ogg::XiphComment* tag, demux_t* p_demux, demux_meta_t* p_demux_meta, vlc_meta_t* p_meta ) static void ReadMetaFromXiph( Ogg::XiphComment* tag, demux_meta_t* p_demux_meta, vlc_meta_t* p_meta )
{ {
StringList list;
#define SET( keyName, metaName ) \ #define SET( keyName, metaName ) \
StringList list = tag->fieldListMap()[keyName]; \ list = tag->fieldListMap()[keyName]; \
if( !list.isEmpty() ) \ if( !list.isEmpty() ) \
vlc_meta_Set##metaName( p_meta, (*list.begin()).toCString( true ) ); vlc_meta_Set##metaName( p_meta, (*list.begin()).toCString( true ) );
...@@ -334,8 +393,15 @@ static void ReadMetaFromXiph( Ogg::XiphComment* tag, demux_t* p_demux, demux_met ...@@ -334,8 +393,15 @@ static void ReadMetaFromXiph( Ogg::XiphComment* tag, demux_t* p_demux, demux_met
vlc_meta_SetArtURL( p_meta, "attachment://cover" ); 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 ) #ifdef TAGLIB_HAVE_MP4COVERTART_H
/**
* Read the meta information from mp4 specific tags
* @param tag: the mp4 tag
* @param p_demux_meta: the demuxer meta
* @param p_meta: the meta
*/
static void ReadMetaFromMP4( MP4::Tag* tag, demux_meta_t *p_demux_meta, vlc_meta_t* p_meta )
{ {
if( tag->itemListMap().contains("covr") ) if( tag->itemListMap().contains("covr") )
{ {
...@@ -354,6 +420,7 @@ static void ReadMetaFromMP4( MP4::Tag* tag, demux_t *p_demux, demux_meta_t *p_de ...@@ -354,6 +420,7 @@ static void ReadMetaFromMP4( MP4::Tag* tag, demux_t *p_demux, demux_meta_t *p_de
} }
#endif #endif
/** /**
* Get the tags from the file using TagLib * Get the tags from the file using TagLib
* @param p_this: the demux object * @param p_this: the demux object
...@@ -421,66 +488,81 @@ static int ReadMeta( vlc_object_t* p_this) ...@@ -421,66 +488,81 @@ static int ReadMeta( vlc_object_t* p_this)
// Try now to read special tags // Try now to read special tags
#ifdef TAGLIB_HAVE_APEFILE_H
if( APE::File* ape = dynamic_cast<APE::File*>(f.file()) )
{
if( ape->APETag() )
ReadMetaFromAPE( ape->APETag(), p_demux_meta, p_meta );
}
else
#endif
#ifdef TAGLIB_HAVE_ASFPICTURE_H
if( ASF::File* asf = dynamic_cast<ASF::File*>(f.file()) )
{
if( asf->tag() )
ReadMetaFromASF( asf->tag(), p_demux_meta, p_meta );
}
else
#endif
if( FLAC::File* flac = dynamic_cast<FLAC::File*>(f.file()) ) if( FLAC::File* flac = dynamic_cast<FLAC::File*>(f.file()) )
{ {
if( flac->ID3v2Tag() ) if( flac->ID3v2Tag() )
ReadMetaFromId3v2( flac->ID3v2Tag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromId3v2( flac->ID3v2Tag(), p_demux_meta, p_meta );
else if( flac->xiphComment() ) else if( flac->xiphComment() )
ReadMetaFromXiph( flac->xiphComment(), p_demux, p_demux_meta, p_meta ); ReadMetaFromXiph( flac->xiphComment(), p_demux_meta, p_meta );
} }
#if defined(TAGLIB_WITH_MP4) && defined(HAVE_TAGLIB_MP4COVERART_H) #ifdef TAGLIB_HAVE_MP4COVERTART_H
else if( MP4::File *mp4 = dynamic_cast<MP4::File*>(f.file()) ) else if( MP4::File *mp4 = dynamic_cast<MP4::File*>(f.file()) )
{ {
if( mp4->tag() ) if( mp4->tag() )
ReadMetaFromMP4( mp4->tag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromMP4( mp4->tag(), p_demux_meta, p_meta );
} }
#endif #endif
else if( MPC::File* mpc = dynamic_cast<MPC::File*>(f.file()) ) else if( MPC::File* mpc = dynamic_cast<MPC::File*>(f.file()) )
{ {
if( mpc->APETag() ) if( mpc->APETag() )
ReadMetaFromAPE( mpc->APETag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromAPE( mpc->APETag(), p_demux_meta, p_meta );
} }
else if( MPEG::File* mpeg = dynamic_cast<MPEG::File*>(f.file()) ) else if( MPEG::File* mpeg = dynamic_cast<MPEG::File*>(f.file()) )
{ {
if( mpeg->ID3v2Tag() ) if( mpeg->ID3v2Tag() )
ReadMetaFromId3v2( mpeg->ID3v2Tag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromId3v2( mpeg->ID3v2Tag(), p_demux_meta, p_meta );
else if( mpeg->APETag() ) else if( mpeg->APETag() )
ReadMetaFromAPE( mpeg->APETag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromAPE( mpeg->APETag(), p_demux_meta, p_meta );
} }
else if( Ogg::File* ogg = dynamic_cast<Ogg::File*>(f.file()) ) else if( dynamic_cast<Ogg::File*>(f.file()) )
{ {
if( Ogg::FLAC::File* ogg_flac = dynamic_cast<Ogg::FLAC::File*>(f.file())) if( Ogg::FLAC::File* ogg_flac = dynamic_cast<Ogg::FLAC::File*>(f.file()))
ReadMetaFromXiph( ogg_flac->tag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromXiph( ogg_flac->tag(), p_demux_meta, p_meta );
else if( Ogg::Speex::File* ogg_speex = dynamic_cast<Ogg::Speex::File*>(f.file()) ) else if( Ogg::Speex::File* ogg_speex = dynamic_cast<Ogg::Speex::File*>(f.file()) )
ReadMetaFromXiph( ogg_speex->tag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromXiph( ogg_speex->tag(), p_demux_meta, p_meta );
else if( Ogg::Vorbis::File* ogg_vorbis = dynamic_cast<Ogg::Vorbis::File*>(f.file()) ) else if( Ogg::Vorbis::File* ogg_vorbis = dynamic_cast<Ogg::Vorbis::File*>(f.file()) )
ReadMetaFromXiph( ogg_vorbis->tag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromXiph( ogg_vorbis->tag(), p_demux_meta, p_meta );
} }
#ifdef TAGLIB_WITH_ASF #ifdef TAGLIB_HAVE_AIFF_WAV_H
else if( RIFF::File* riff = dynamic_cast<RIFF::File*>(f.file()) ) else if( dynamic_cast<RIFF::File*>(f.file()) )
{ {
if( RIFF::AIFF::File* riff_aiff = dynamic_cast<RIFF::AIFF::File*>(f.file()) ) if( RIFF::AIFF::File* riff_aiff = dynamic_cast<RIFF::AIFF::File*>(f.file()) )
ReadMetaFromId3v2( riff_aiff->tag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromId3v2( riff_aiff->tag(), p_demux_meta, p_meta );
else if( RIFF::WAV::File* riff_wav = dynamic_cast<RIFF::WAV::File*>(f.file()) ) else if( RIFF::WAV::File* riff_wav = dynamic_cast<RIFF::WAV::File*>(f.file()) )
ReadMetaFromId3v2( riff_wav->tag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromId3v2( riff_wav->tag(), p_demux_meta, p_meta );
} }
#endif #endif
else if( TrueAudio::File* trueaudio = dynamic_cast<TrueAudio::File*>(f.file()) ) else if( TrueAudio::File* trueaudio = dynamic_cast<TrueAudio::File*>(f.file()) )
{ {
if( trueaudio->ID3v2Tag() ) if( trueaudio->ID3v2Tag() )
ReadMetaFromId3v2( trueaudio->ID3v2Tag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromId3v2( trueaudio->ID3v2Tag(), p_demux_meta, p_meta );
} }
else if( WavPack::File* wavpack = dynamic_cast<WavPack::File*>(f.file()) ) else if( WavPack::File* wavpack = dynamic_cast<WavPack::File*>(f.file()) )
{ {
if( wavpack->APETag() ) if( wavpack->APETag() )
ReadMetaFromAPE( wavpack->APETag(), p_demux, p_demux_meta, p_meta ); ReadMetaFromAPE( wavpack->APETag(), p_demux_meta, p_meta );
} }
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/** /**
* Write meta informations to APE tags * Write meta informations to APE tags
* @param tag: the APE tag * @param tag: the APE tag
...@@ -507,7 +589,6 @@ static void WriteMetaToAPE( APE::Tag* tag, input_item_t* p_item ) ...@@ -507,7 +589,6 @@ static void WriteMetaToAPE( APE::Tag* tag, input_item_t* p_item )
} }
/** /**
* Write meta information to id3v2 tags * Write meta information to id3v2 tags
* @param tag: the id3v2 tag * @param tag: the id3v2 tag
...@@ -538,7 +619,6 @@ static void WriteMetaToId3v2( ID3v2::Tag* tag, input_item_t* p_item ) ...@@ -538,7 +619,6 @@ static void WriteMetaToId3v2( ID3v2::Tag* tag, input_item_t* p_item )
} }
/** /**
* Write the meta informations to XiphComments * Write the meta informations to XiphComments
* @param tag: the Xiph Comment * @param tag: the Xiph Comment
...@@ -563,7 +643,6 @@ static void WriteMetaToXiph( Ogg::XiphComment* tag, input_item_t* p_item ) ...@@ -563,7 +643,6 @@ static void WriteMetaToXiph( Ogg::XiphComment* tag, input_item_t* p_item )
} }
/** /**
* Set the tags to the file using TagLib * Set the tags to the file using TagLib
* @param p_this: the demux object * @param p_this: the demux object
...@@ -639,6 +718,14 @@ static int WriteMeta( vlc_object_t *p_this ) ...@@ -639,6 +718,14 @@ static int WriteMeta( vlc_object_t *p_this )
// Try now to write special tags // Try now to write special tags
#ifdef TAGLIB_HAVE_APEFILE_H
if( APE::File* ape = dynamic_cast<APE::File*>(f.file()) )
{
if( ape->APETag() )
WriteMetaToAPE( ape->APETag(), p_item );
}
else
#endif
if( FLAC::File* flac = dynamic_cast<FLAC::File*>(f.file()) ) if( FLAC::File* flac = dynamic_cast<FLAC::File*>(f.file()) )
{ {
if( flac->ID3v2Tag() ) if( flac->ID3v2Tag() )
...@@ -658,7 +745,7 @@ static int WriteMeta( vlc_object_t *p_this ) ...@@ -658,7 +745,7 @@ static int WriteMeta( vlc_object_t *p_this )
else if( mpeg->APETag() ) else if( mpeg->APETag() )
WriteMetaToAPE( mpeg->APETag(), p_item ); WriteMetaToAPE( mpeg->APETag(), p_item );
} }
else if( Ogg::File* ogg = dynamic_cast<Ogg::File*>(f.file()) ) else if( dynamic_cast<Ogg::File*>(f.file()) )
{ {
if( Ogg::FLAC::File* ogg_flac = dynamic_cast<Ogg::FLAC::File*>(f.file())) if( Ogg::FLAC::File* ogg_flac = dynamic_cast<Ogg::FLAC::File*>(f.file()))
WriteMetaToXiph( ogg_flac->tag(), p_item ); WriteMetaToXiph( ogg_flac->tag(), p_item );
...@@ -667,8 +754,8 @@ static int WriteMeta( vlc_object_t *p_this ) ...@@ -667,8 +754,8 @@ static int WriteMeta( vlc_object_t *p_this )
else if( Ogg::Vorbis::File* ogg_vorbis = dynamic_cast<Ogg::Vorbis::File*>(f.file()) ) else if( Ogg::Vorbis::File* ogg_vorbis = dynamic_cast<Ogg::Vorbis::File*>(f.file()) )
WriteMetaToXiph( ogg_vorbis->tag(), p_item ); WriteMetaToXiph( ogg_vorbis->tag(), p_item );
} }
#ifdef TAGLIB_WITH_ASF #ifdef TAGLIB_HAVE_AIFF_WAV_H
else if( RIFF::File* riff = dynamic_cast<RIFF::File*>(f.file()) ) else if( dynamic_cast<RIFF::File*>(f.file()) )
{ {
if( RIFF::AIFF::File* riff_aiff = dynamic_cast<RIFF::AIFF::File*>(f.file()) ) if( RIFF::AIFF::File* riff_aiff = dynamic_cast<RIFF::AIFF::File*>(f.file()) )
WriteMetaToId3v2( riff_aiff->tag(), p_item ); WriteMetaToId3v2( riff_aiff->tag(), p_item );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment