summaryrefslogtreecommitdiffstats
path: root/src/metadata/m4a/mp4file.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 19:09:31 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 19:09:31 +0000
commitf2cfda2a54780868dfe0af7bd652fcd4906547da (patch)
treec6ac23545528f5701818424f2af5f79ce3665e6c /src/metadata/m4a/mp4file.cpp
downloadsoundkonverter-f2cfda2a54780868dfe0af7bd652fcd4906547da.tar.gz
soundkonverter-f2cfda2a54780868dfe0af7bd652fcd4906547da.zip
Added KDE3 version of SoundKonverter
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/soundkonverter@1097614 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/metadata/m4a/mp4file.cpp')
-rw-r--r--src/metadata/m4a/mp4file.cpp377
1 files changed, 377 insertions, 0 deletions
diff --git a/src/metadata/m4a/mp4file.cpp b/src/metadata/m4a/mp4file.cpp
new file mode 100644
index 0000000..7d37d59
--- /dev/null
+++ b/src/metadata/m4a/mp4file.cpp
@@ -0,0 +1,377 @@
+/***************************************************************************
+ copyright : (C) 2002, 2003, 2006 by Jochen Issing
+ ***************************************************************************/
+
+/***************************************************************************
+ * This library is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Lesser General Public License version *
+ * 2.1 as published by the Free Software Foundation. *
+ * *
+ * This library is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this library; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
+ * MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include <tbytevector.h>
+#include <tstring.h>
+#include "tlist.h"
+
+#include "mp4itunestag.h"
+#include "mp4file.h"
+#include "boxfactory.h"
+#include "mp4tagsproxy.h"
+#include "mp4propsproxy.h"
+#include "mp4audioproperties.h"
+#include "itunesdatabox.h"
+
+using namespace TagLib;
+
+class MP4::File::FilePrivate
+{
+public:
+ //! list for all boxes of the mp4 file
+ TagLib::List<MP4::Mp4IsoBox*> boxes;
+ //! the box factory - will create all boxes by tag and size
+ MP4::BoxFactory boxfactory;
+ //! proxy for the tags is filled after parsing
+ MP4::Mp4TagsProxy tagsProxy;
+ //! proxy for audio properties
+ MP4::Mp4PropsProxy propsProxy;
+ //! the tag returned by tag() function
+ MP4::Tag mp4tag;
+ //! container for the audio properties returned by properties() function
+ MP4::AudioProperties mp4audioproperties;
+ //! is set to valid after successfully parsing
+ bool isValid;
+};
+
+//! function to fill the tags with converted proxy data, which has been parsed out of the file previously
+static void fillTagFromProxy( MP4::Mp4TagsProxy& proxy, MP4::Tag& mp4tag );
+
+MP4::File::File(const char *file, bool , AudioProperties::ReadStyle )
+ :TagLib::File( file )
+{
+ // create member container
+ d = new MP4::File::FilePrivate();
+
+
+ d->isValid = false;
+ TagLib::uint size;
+ MP4::Fourcc fourcc;
+
+ while( readSizeAndType( size, fourcc ) == true )
+ {
+ // create the appropriate subclass and parse it
+ MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( this, fourcc, size, tell() );
+ curbox->parsebox();
+ d->boxes.append( curbox );
+ }
+
+ for( TagLib::List<MP4::Mp4IsoBox*>::Iterator iter = d->boxes.begin();
+ iter != d->boxes.end();
+ iter++ )
+ {
+ if( (*iter)->fourcc() == MP4::Fourcc("moov") )
+ {
+ d->isValid = true;
+ break;
+ }
+ }
+
+ //if( d->isValid )
+ //debug( "file is valid" );
+ //else
+ //debug( "file is NOT valid" );
+
+ // fill tags from proxy data
+ fillTagFromProxy( d->tagsProxy, d->mp4tag );
+}
+
+MP4::File::~File()
+{
+ TagLib::List<Mp4IsoBox*>::Iterator delIter;
+ for( delIter = d->boxes.begin();
+ delIter != d->boxes.end();
+ delIter++ )
+ {
+ delete *delIter;
+ }
+ delete d;
+}
+
+Tag *MP4::File::tag() const
+{
+ return &d->mp4tag;
+}
+
+AudioProperties * MP4::File::audioProperties() const
+{
+ d->mp4audioproperties.setProxy( &d->propsProxy );
+ return &d->mp4audioproperties;
+}
+
+bool MP4::File::save()
+{
+ return false;
+}
+
+void MP4::File::remove()
+{
+}
+
+TagLib::uint MP4::File::readSystemsLen()
+{
+ TagLib::uint length = 0;
+ TagLib::uint nbytes = 0;
+ ByteVector input;
+ TagLib::uchar tmp_input;
+
+ do
+ {
+ input = readBlock(1);
+ tmp_input = static_cast<TagLib::uchar>(input[0]);
+ nbytes++;
+ length = (length<<7) | (tmp_input&0x7F);
+ } while( (tmp_input&0x80) && (nbytes<4) );
+
+ return length;
+}
+
+bool MP4::File::readSizeAndType( TagLib::uint& size, MP4::Fourcc& fourcc )
+{
+ // read the two blocks from file
+ ByteVector readsize = readBlock(4);
+ ByteVector readtype = readBlock(4);
+
+ if( (readsize.size() != 4) || (readtype.size() != 4) )
+ return false;
+
+ // set size
+ size = static_cast<unsigned char>(readsize[0]) << 24 |
+ static_cast<unsigned char>(readsize[1]) << 16 |
+ static_cast<unsigned char>(readsize[2]) << 8 |
+ static_cast<unsigned char>(readsize[3]);
+
+ // type and size seem to be part of the stored size
+ if( size < 8 )
+ return false;
+
+ // set fourcc
+ fourcc = readtype.data();
+
+ return true;
+}
+
+bool MP4::File::readInt( TagLib::uint& toRead )
+{
+ ByteVector readbuffer = readBlock(4);
+ if( readbuffer.size() != 4 )
+ return false;
+
+ toRead = static_cast<unsigned char>(readbuffer[0]) << 24 |
+ static_cast<unsigned char>(readbuffer[1]) << 16 |
+ static_cast<unsigned char>(readbuffer[2]) << 8 |
+ static_cast<unsigned char>(readbuffer[3]);
+ return true;
+}
+
+bool MP4::File::readShort( TagLib::uint& toRead )
+{
+ ByteVector readbuffer = readBlock(2);
+ if( readbuffer.size() != 2 )
+ return false;
+
+ toRead = static_cast<unsigned char>(readbuffer[0]) << 8 |
+ static_cast<unsigned char>(readbuffer[1]);
+ return true;
+}
+
+bool MP4::File::readLongLong( TagLib::ulonglong& toRead )
+{
+ ByteVector readbuffer = readBlock(8);
+ if( readbuffer.size() != 8 )
+ return false;
+
+ toRead = static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[0])) << 56 |
+ static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[1])) << 48 |
+ static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[2])) << 40 |
+ static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[3])) << 32 |
+ static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[4])) << 24 |
+ static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[5])) << 16 |
+ static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[6])) << 8 |
+ static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[7]));
+ return true;
+}
+
+bool MP4::File::readFourcc( TagLib::MP4::Fourcc& fourcc )
+{
+ ByteVector readtype = readBlock(4);
+
+ if( readtype.size() != 4)
+ return false;
+
+ // set fourcc
+ fourcc = readtype.data();
+
+ return true;
+}
+
+MP4::Mp4TagsProxy* MP4::File::tagProxy() const
+{
+ return &d->tagsProxy;
+}
+
+MP4::Mp4PropsProxy* MP4::File::propProxy() const
+{
+ return &d->propsProxy;
+}
+
+void fillTagFromProxy( MP4::Mp4TagsProxy& proxy, MP4::Tag& mp4tag )
+{
+ // tmp buffer for each tag
+ MP4::ITunesDataBox* databox;
+
+ databox = proxy.titleData();
+ if( databox != 0 )
+ {
+ // convert data to string
+ TagLib::String datastring( databox->data(), String::UTF8 );
+ // check if string was set
+ if( !datastring.isEmpty() )
+ mp4tag.setTitle( datastring );
+ }
+
+ databox = proxy.artistData();
+ if( databox != 0 )
+ {
+ // convert data to string
+ TagLib::String datastring( databox->data(), String::UTF8 );
+ // check if string was set
+ if( !datastring.isEmpty() )
+ mp4tag.setArtist( datastring );
+ }
+
+ databox = proxy.albumData();
+ if( databox != 0 )
+ {
+ // convert data to string
+ TagLib::String datastring( databox->data(), String::UTF8 );
+ // check if string was set
+ if( !datastring.isEmpty() )
+ mp4tag.setAlbum( datastring );
+ }
+
+ databox = proxy.genreData();
+ if( databox != 0 )
+ {
+ // convert data to string
+ TagLib::String datastring( databox->data(), String::UTF8 );
+ // check if string was set
+ if( !datastring.isEmpty() )
+ mp4tag.setGenre( datastring );
+ }
+
+ databox = proxy.yearData();
+ if( databox != 0 )
+ {
+ // convert data to string
+ TagLib::String datastring( databox->data(), String::UTF8 );
+ // check if string was set
+ if( !datastring.isEmpty() )
+ mp4tag.setYear( datastring.toInt() );
+ }
+
+ databox = proxy.trknData();
+ if( databox != 0 )
+ {
+ // convert data to uint
+ TagLib::ByteVector datavec = databox->data();
+ if( datavec.size() >= 4 )
+ {
+ TagLib::uint trackno = static_cast<TagLib::uint>( static_cast<unsigned char>(datavec[0]) << 24 |
+ static_cast<unsigned char>(datavec[1]) << 16 |
+ static_cast<unsigned char>(datavec[2]) << 8 |
+ static_cast<unsigned char>(datavec[3]) );
+ mp4tag.setTrack( trackno );
+ }
+ else
+ mp4tag.setTrack( 0 );
+ }
+
+ databox = proxy.commentData();
+ if( databox != 0 )
+ {
+ // convert data to string
+ TagLib::String datastring( databox->data(), String::UTF8 );
+ // check if string was set
+ if( !datastring.isEmpty() )
+ mp4tag.setComment( datastring );
+ }
+
+ databox = proxy.groupingData();
+ if( databox != 0 )
+ {
+ // convert data to string
+ TagLib::String datastring( databox->data(), String::UTF8 );
+ // check if string was set
+ if( !datastring.isEmpty() )
+ mp4tag.setGrouping( datastring );
+ }
+
+ databox = proxy.composerData();
+ if( databox != 0 )
+ {
+ // convert data to string
+ TagLib::String datastring( databox->data(), String::UTF8 );
+ // check if string was set
+ if( !datastring.isEmpty() )
+ mp4tag.setComposer( datastring );
+ }
+
+ databox = proxy.diskData();
+ if( databox != 0 )
+ {
+ // convert data to uint
+ TagLib::ByteVector datavec = databox->data();
+ if( datavec.size() >= 4 )
+ {
+ TagLib::uint discno = static_cast<TagLib::uint>( static_cast<unsigned char>(datavec[0]) << 24 |
+ static_cast<unsigned char>(datavec[1]) << 16 |
+ static_cast<unsigned char>(datavec[2]) << 8 |
+ static_cast<unsigned char>(datavec[3]) );
+ mp4tag.setDisk( discno );
+ }
+ else
+ mp4tag.setDisk( 0 );
+ }
+
+ databox = proxy.bpmData();
+ if( databox != 0 )
+ {
+ // convert data to uint
+ TagLib::ByteVector datavec = databox->data();
+
+ if( datavec.size() >= 2 )
+ {
+ TagLib::uint bpm = static_cast<TagLib::uint>( static_cast<unsigned char>(datavec[0]) << 8 |
+ static_cast<unsigned char>(datavec[1]) );
+ mp4tag.setBpm( bpm );
+ }
+ else
+ mp4tag.setBpm( 0 );
+ }
+
+ databox = proxy.coverData();
+ if( databox != 0 )
+ {
+ // get byte vector
+ mp4tag.setCover( databox->data() );
+ }
+}