]> granicus.if.org Git - taglib/commitdiff
Make mpc use the new APETag-structure
authorAllan Sandfeld Jensen <kde@carewolf.com>
Mon, 26 Jul 2004 19:04:40 +0000 (19:04 +0000)
committerAllan Sandfeld Jensen <kde@carewolf.com>
Mon, 26 Jul 2004 19:04:40 +0000 (19:04 +0000)
git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@333012 283d02a7-25f6-0310-bc7c-ecb5cbfe19da

Makefile.am
mpc/Makefile.am
mpc/apetag.cpp [deleted file]
mpc/apetag.h [deleted file]
mpc/mpcfile.cpp
mpc/mpcfile.h

index 437e3a0e135078cd31b7c9fd6b6f97d7772b06ab..73a5e4cf36025e100e9108814050d038af48428f 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = toolkit mpeg ogg flac mpc
+SUBDIRS = toolkit mpeg ogg flac ape mpc
 
 INCLUDES = \
        -I$(top_srcdir)/taglib/toolkit \
@@ -16,7 +16,7 @@ taglib_include_HEADERS = tag.h fileref.h audioproperties.h
 taglib_includedir = $(includedir)/taglib
 
 libtag_la_LDFLAGS = $(all_libraries) -no-undefined -version-info 2:1:0
-libtag_la_LIBADD = ./mpeg/libmpeg.la ./ogg/libogg.la ./flac/libflac.la ./mpc/libmpc.la ./toolkit/libtoolkit.la
+libtag_la_LIBADD = ./mpeg/libmpeg.la ./ogg/libogg.la ./flac/libflac.la ./mpc/libmpc.la ./ape/libape.la ./toolkit/libtoolkit.la
 
 bin_SCRIPTS = taglib-config
 
index 012197775591a04f1d5266cca4bf9123e5a5476f..4d12cb660667f638f10fd058e5252152b0b65799 100644 (file)
@@ -1,13 +1,14 @@
 INCLUDES = \
        -I$(top_srcdir)/taglib \
        -I$(top_srcdir)/taglib/toolkit \
+       -I$(top_srcdir)/taglib/ape \
        -I$(top_srcdir)/taglib/mpeg/id3v1 \
        -I$(top_srcdir)/taglib/mpeg/id3v2 \
        $(all_includes)
 
 noinst_LTLIBRARIES = libmpc.la
 
-libmpc_la_SOURCES = mpcfile.cpp mpcproperties.cpp apetag.cpp
+libmpc_la_SOURCES = mpcfile.cpp mpcproperties.cpp
 
 taglib_include_HEADERS = mpcfile.h mpcproperties.h
 taglib_includedir = $(includedir)/taglib
diff --git a/mpc/apetag.cpp b/mpc/apetag.cpp
deleted file mode 100644 (file)
index 551540a..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-/***************************************************************************
-    copyright            : (C) 2004 by Allan Sandfeld Jensen
-    email                : kde@carewolf.com
- ***************************************************************************/
-
-/***************************************************************************
- *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
- *   USA                                                                   *
- ***************************************************************************/
-
-#include <tdebug.h>
-#include <tfile.h>
-#include <tstring.h>
-#include <tmap.h>
-
-#include "apetag.h"
-
-using namespace TagLib;
-using namespace APE;
-
-class APE::Tag::TagPrivate
-{
-public:
-  TagPrivate() : file(0), tagOffset(-1), tagLength(0) {}
-
-  File *file;
-  long tagOffset;
-  long tagLength;
-
-  FieldListMap fieldListMap;
-  Map<const String, ByteVector> binaries;
-};
-
-APE::Item::Item(const String& str) : readOnly(false), locator(false) {
-  value.append(str);
-}
-
-APE::Item::Item(const StringList& values) : readOnly(false), locator(false) {
-  value.append(values);
-}
-
-bool APE::Item::isEmpty() const
-{
-  return value.isEmpty();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// public methods
-////////////////////////////////////////////////////////////////////////////////
-
-APE::Tag::Tag() : TagLib::Tag()
-{
-  d = new TagPrivate;
-}
-
-APE::Tag::Tag(File *file, long tagOffset) : TagLib::Tag()
-{
-  d = new TagPrivate;
-  d->file = file;
-  d->tagOffset = tagOffset;
-
-  read();
-}
-
-APE::Tag::~Tag()
-{
-  delete d;
-}
-
-using TagLib::uint;
-
-static ByteVector _render_APEItem(String key, Item item)
-{
-  ByteVector data;
-  uint flags = ((item.readOnly) ? 1 : 0) | ((item.locator) ? 2 : 0);
-  ByteVector value;
-
-  if (item.value.isEmpty()) return data;
-
-  StringList::Iterator it = item.value.begin();
-  value.append(it->data(String::UTF8));
-  it++;
-  while (it != item.value.end()) {
-    value.append('\0');
-    value.append(it->data(String::UTF8));
-    it++;
-  }
-
-  data.append(ByteVector::fromUInt(value.size(), false));
-  data.append(ByteVector::fromUInt(flags, false));
-  data.append(key.data(String::UTF8));
-  data.append(ByteVector('\0'));
-  data.append(value);
-
-  return data;
-}
-
-static ByteVector _render_APEFrame(bool isHeader, uint dataSize, uint itemCount) {
-  ByteVector header;
-  TagLib::uint tagSize = 32 + dataSize;
-  // bit 31: Has a header
-  // bit 29: Is the header
-  TagLib::uint flags = (1U << 31) | ((isHeader) ? (1U << 29) : 0);
-
-  header.append(APE::Tag::fileIdentifier());
-  header.append(ByteVector::fromUInt(2, false));
-  header.append(ByteVector::fromUInt(tagSize, false));
-  header.append(ByteVector::fromUInt(itemCount, false));
-  header.append(ByteVector::fromUInt(flags, false));
-  header.append(ByteVector::fromLongLong(0, false));
-
-  return header;
-}
-
-ByteVector APE::Tag::render() const
-{
-  ByteVector data;
-  uint itemCount = 0;
-
-  { Map<const String,Item>::Iterator i = d->fieldListMap.begin();
-    while (i != d->fieldListMap.end()) {
-      if (!i->second.value.isEmpty()) {
-        data.append(_render_APEItem(i->first, i->second));
-        itemCount++;
-      }
-      i++;
-    }
-  }
-
-  { Map<String,ByteVector>::Iterator i = d->binaries.begin();
-    while (i != d->binaries.end()) {
-      if (!i->second.isEmpty()) {
-          data.append(i->second);
-          itemCount++;
-      }
-      i++;
-    }
-  }
-
-  ByteVector tag;
-  tag.append(_render_APEFrame(true, data.size(), itemCount));
-  tag.append(data);
-  tag.append(_render_APEFrame(false, data.size(), itemCount));
-
-  return tag;
-}
-
-ByteVector APE::Tag::fileIdentifier()
-{
-  return ByteVector::fromCString("APETAGEX");
-}
-
-String APE::Tag::title() const
-{
-  if(d->fieldListMap["TITLE"].isEmpty())
-    return String::null;
-  return d->fieldListMap["TITLE"].value.front();
-}
-
-String APE::Tag::artist() const
-{
-  if(d->fieldListMap["ARTIST"].isEmpty())
-    return String::null;
-  return d->fieldListMap["ARTIST"].value.front();
-}
-
-String APE::Tag::album() const
-{
-  if(d->fieldListMap["ALBUM"].isEmpty())
-    return String::null;
-  return d->fieldListMap["ALBUM"].value.front();
-}
-
-String APE::Tag::comment() const
-{
-  if(d->fieldListMap["COMMENT"].isEmpty())
-    return String::null;
-  return d->fieldListMap["COMMENT"].value.front();
-}
-
-String APE::Tag::genre() const
-{
-  if(d->fieldListMap["GENRE"].isEmpty())
-    return String::null;
-  return d->fieldListMap["GENRE"].value.front();
-}
-
-TagLib::uint APE::Tag::year() const
-{
-  if(d->fieldListMap["YEAR"].isEmpty())
-    return 0;
-  return d->fieldListMap["YEAR"].value.front().toInt();
-}
-
-TagLib::uint APE::Tag::track() const
-{
-  if(d->fieldListMap["TRACK"].isEmpty())
-    return 0;
-  return d->fieldListMap["TRACK"].value.front().toInt();
-}
-
-void APE::Tag::setTitle(const String &s)
-{
-  addField("TITLE", s, true);
-}
-
-void APE::Tag::setArtist(const String &s)
-{
-  addField("ARTIST", s, true);
-}
-
-void APE::Tag::setAlbum(const String &s)
-{
-  addField("ALBUM", s, true);
-}
-
-void APE::Tag::setComment(const String &s)
-{
-  addField("COMMENT", s, true);
-}
-
-void APE::Tag::setGenre(const String &s)
-{
-  addField("GENRE", s, true);
-}
-
-void APE::Tag::setYear(uint i)
-{
-  if(i <=0 )
-    removeField("YEAR");
-  else
-    addField("YEAR", String::number(i), true);
-}
-
-void APE::Tag::setTrack(uint i)
-{
-  if(i <=0 )
-    removeField("TRACK");
-  else
-    addField("TRACK", String::number(i), true);
-}
-
-const APE::FieldListMap& APE::Tag::fieldListMap() const
-{
-  return d->fieldListMap;
-}
-
-void APE::Tag::removeField(const String &key) {
-  Map<const String, Item>::Iterator it = d->fieldListMap.find(key.upper());
-  if(it != d->fieldListMap.end())
-    d->fieldListMap.erase(it);
-}
-
-void APE::Tag::addField(const String &key, const String &value, bool replace) {
-  if(replace)
-    removeField(key);
-  if(!value.isEmpty()) {
-    Map<const String, Item>::Iterator it = d->fieldListMap.find(key.upper());
-    if (it != d->fieldListMap.end())
-      d->fieldListMap[key].value.append(value);
-    else
-      addItem(key, Item(value));
-  }
-}
-
-void APE::Tag::addField(const String &key, const StringList &values) {
-  removeField(key);
-
-  if(values.isEmpty()) return;
-  else {
-    addItem(key, Item(values));
-  }
-}
-
-TagLib::uint APE::Tag::tagSize(const ByteVector &footer)
-{
-  // The reported length (excl. header)
-
-  uint length = footer.mid(12, 4).toUInt(false);
-
-  // Flags (bit 31: tag contains a header)
-
-  uint flags = footer.mid(20, 4).toUInt(false);
-
-  return length + ((flags & (1U << 31)) ? 32 : 0);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// protected methods
-////////////////////////////////////////////////////////////////////////////////
-
-void APE::Tag::addItem(const String &key, const Item &item) {
-  removeField(key);
-
-  Map<const String, Item>::Iterator it = d->fieldListMap.find(key.upper());
-  d->fieldListMap.insert(key, item);
-}
-
-void APE::Tag::read()
-{
-  if(d->file && d->file->isValid()) {
-    d->file->seek(d->tagOffset);
-    // read the footer -- always 32 bytes
-    ByteVector footer = d->file->readBlock(32);
-
-    // parse footer and some initial sanity checking
-    if(footer.size() == 32 && footer.mid(0, 8) == "APETAGEX") {
-      uint length = footer.mid(12, 4).toUInt(false);
-      uint count = footer.mid(16, 4).toUInt(false);
-      d->tagLength = length;
-      d->file->seek(d->tagOffset + 32 - length);
-      ByteVector data = d->file->readBlock(length - 32);
-      parse(data, count);
-    }
-    else
-      debug("APE tag is not valid or could not be read at the specified offset.");
-  }
-}
-
-static StringList _parse_APEString(ByteVector val)
-{
-    StringList value;
-    int pold = 0;
-    int p = val.find('\0');
-    while (p != -1) {
-        value.append(String(val.mid(pold, p), String::UTF8));
-        pold = p+1;
-        p = val.find('\0', pold);
-    };
-    value.append(String(val.mid(pold), String::UTF8));
-
-    return value;
-}
-
-void APE::Tag::parse(const ByteVector &data, uint count)
-{
-  uint pos = 0;
-  uint vallen, flags;
-  String key, value;
-  while(count > 0) {
-    vallen = data.mid(pos+0,4).toUInt(false);
-    flags = data.mid(pos+4,4).toUInt(false);
-    key = String(data.mid(pos+8), String::UTF8);
-    key = key.upper();
-    APE::Item item;
-
-    if (flags < 4 ) {
-      ByteVector val = data.mid(pos+8+key.size()+1, vallen);
-      d->fieldListMap.insert(key, Item(_parse_APEString(val)));
-    } else {
-      d->binaries.insert(key,data.mid(pos, 8+key.size()+1+vallen));
-    }
-
-    pos += 8 + key.size() + 1 + vallen;
-    count--;
-  }
-}
diff --git a/mpc/apetag.h b/mpc/apetag.h
deleted file mode 100644 (file)
index 37b102d..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/***************************************************************************
-    copyright            : (C) 2004 by Allan Sandfeld Jensen
-    email                : kde@carewolf.org
- ***************************************************************************/
-
-/***************************************************************************
- *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
- *   USA                                                                   *
- ***************************************************************************/
-
-#ifndef TAGLIB_APETAG_H
-#define TAGLIB_APETAG_H
-
-#include "tag.h"
-#include "tbytevector.h"
-#include "tmap.h"
-#include "tstring.h"
-#include "tstringlist.h"
-
-namespace TagLib {
-
-  class File;
-
-  namespace APE {
-
-    /*!
-     * A non-binary APE-item.
-     */
-    struct Item {
-        Item() {};
-        explicit Item(const String&);
-        explicit Item(const StringList&);
-        bool readOnly;
-        bool locator; // URL to external data
-        StringList value;
-        bool isEmpty() const;
-    };
-
-    /*!
-     * A mapping between a list of item names, or keys, and the associated item.
-     *
-     * \see APE::Tag::itemListMap()
-     */
-    typedef Map<const String, Item> FieldListMap;
-
-
-  //! An APE tag implementation
-
-    class Tag : public TagLib::Tag
-    {
-    public:
-      /*!
-       * Create an APE tag with default values.
-       */
-      Tag();
-
-      /*!
-       * Create an APE tag and parse the data in \a file with APE footer at
-       * \a tagOffset.
-       */
-      Tag(File *file, long tagOffset);
-
-      /*!
-       * Destroys this Tag instance.
-       */
-      virtual ~Tag();
-
-      /*!
-       * Renders the in memory values to a ByteVector suitable for writing to
-       * the file.
-       */
-      ByteVector render() const;
-
-      /*!
-       * Returns the string "APETAGEX" suitable for usage in locating the tag in a
-       * file.
-       */
-      static ByteVector fileIdentifier();
-
-      /*!
-       * Returns the size of the tag calculated based on the footer.
-       */
-      static uint tagSize(const ByteVector &footer);
-
-      // Reimplementations.
-
-      virtual String title() const;
-      virtual String artist() const;
-      virtual String album() const;
-      virtual String comment() const;
-      virtual String genre() const;
-      virtual uint year() const;
-      virtual uint track() const;
-
-      virtual void setTitle(const String &s);
-      virtual void setArtist(const String &s);
-      virtual void setAlbum(const String &s);
-      virtual void setComment(const String &s);
-      virtual void setGenre(const String &s);
-      virtual void setYear(uint i);
-      virtual void setTrack(uint i);
-
-      const FieldListMap &fieldListMap() const;
-
-      /*!
-       * Removes the \a key comment from the tag
-       */
-      void removeField(const String &key);
-
-      /*!
-       * Adds the \a key comment with \a value
-       */
-      void addField(const String &key, const String &value, bool replace = true);
-
-      /*!
-       * Adds the \a key comment with \a values
-       */
-      void addField(const String &key, const StringList &values);
-
-    protected:
-      /*!
-       * Adds the \a key comment with \a item
-       */
-      void addItem(const String &key, const Item &item);
-
-      /*!
-       * Reads from the file specified in the constructor.
-       */
-      void read();
-      /*!
-       * Parses the body of the tag in \a data with \a count items.
-       */
-      void parse(const ByteVector &data, uint count);
-
-    private:
-      Tag(const Tag &);
-      Tag &operator=(const Tag &);
-
-      class TagPrivate;
-      TagPrivate *d;
-    };
-  }
-}
-
-#endif
index f57301fb5b251de878f960ecf0dc85e6a65d5039..060934d06242ddd776bd211237e6264dac10700a 100644 (file)
@@ -27,6 +27,7 @@
 #include "id3v1tag.h"
 #include "id3v2header.h"
 #include "apetag.h"
+#include "apefooter.h"
 #include "mpctag.h"
 
 using namespace TagLib;
@@ -36,7 +37,6 @@ class MPC::File::FilePrivate
 public:
   FilePrivate() :
     APETag(0),
-    APEFooter(-1),
     APELocation(-1),
     APESize(0),
     ID3v1Tag(0),
@@ -197,8 +197,13 @@ void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesSty
 
   findAPE();
 
+  // Look for an APE tag
+
+  d->APELocation = findAPE();
+
   if(d->APELocation >= 0) {
-    d->APETag = new APE::Tag(this, d->APEFooter);
+    d->APETag = new APE::Tag(this, d->APELocation);
+    d->APESize = d->APETag->footer()->completeTagSize();
     d->hasAPE = true;
   }
 
@@ -237,26 +242,20 @@ void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesSty
   }
 }
 
-bool MPC::File::findAPE()
+long MPC::File::findAPE()
 {
-  if(!isValid())
-    return false;
+    if(isValid()) {
+    if (d->hasID3v1)
+        seek(-160, End);
+    else
+        seek(-32, End);
 
-  if (d->hasID3v1)
-    seek(-160, End);
-  else
-    seek(-32, End);
-  long p = tell();
+    long p = tell();
 
-  ByteVector footer = readBlock(32);
-  if(footer.mid(0,8) == APE::Tag::fileIdentifier()) {
-     d->APEFooter = p;
-     d->APESize = APE::Tag::tagSize(footer);
-     d->APELocation = p + 32 - d->APESize;
-     return true;
+    if(readBlock(8) == APE::Tag::fileIdentifier())
+      return p;
   }
-
-  return false;
+  return -1;
 }
 
 long MPC::File::findID3v1()
index 900cadb44a9bd850f2727251af8b1517308576b6..5443c9cb980c6ce6099031a88cd980e8daa62fc2 100644 (file)
@@ -137,7 +137,7 @@ namespace TagLib {
 
       void read(bool readProperties, Properties::ReadStyle propertiesStyle);
       void scan();
-      bool findAPE();
+      long findAPE();
       long findID3v1();
       long findID3v2();