From 15f864a7797b83525d07bc26dff043dff5b1a8cc Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Sun, 1 Aug 2004 23:29:42 +0000 Subject: [PATCH] A few changes to make the interface more flexible. It can now remove tags including ID3v2. git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@334981 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- mpc/combinedtag.h | 171 ++++++++++++++++++++++++++++++++++++++++++++ mpc/mpcfile.cpp | 101 +++++++++++++++++++++----- mpc/mpcfile.h | 18 ++++- mpc/mpctag.h | 175 ---------------------------------------------- 4 files changed, 271 insertions(+), 194 deletions(-) create mode 100644 mpc/combinedtag.h delete mode 100644 mpc/mpctag.h diff --git a/mpc/combinedtag.h b/mpc/combinedtag.h new file mode 100644 index 00000000..c2a19982 --- /dev/null +++ b/mpc/combinedtag.h @@ -0,0 +1,171 @@ +/*************************************************************************** + 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 DO_NOT_DOCUMENT // Tell Doxygen not to document this header + +#ifndef TAGLIB_COMBINEDTAG_H +#define TAGLIB_COMBINEDTAG_H + +//////////////////////////////////////////////////////////////////////////////// +// Note that this header is not installed. +//////////////////////////////////////////////////////////////////////////////// + +#include + +namespace TagLib { + + /*! + * A union of two TagLib::Tags. + */ + class CombinedTag : public TagLib::Tag + { + public: + CombinedTag(Tag *tag1 = 0, Tag *tag2 = 0) + : TagLib::Tag(), + tag1(tag1), tag2(tag2) {} + + virtual String title() const { + if(tag1 && !tag1->title().isEmpty()) + return tag1->title(); + + if(tag2) + return tag2->title(); + + return String::null; + } + + virtual String artist() const { + if(tag1 && !tag1->artist().isEmpty()) + return tag1->artist(); + + if(tag2) + return tag2->artist(); + + return String::null; + } + + virtual String album() const { + if(tag1 && !tag1->album().isEmpty()) + return tag1->album(); + + if(tag2) + return tag2->album(); + + return String::null; + } + + virtual String comment() const { + if(tag1 && !tag1->comment().isEmpty()) + return tag1->comment(); + + if(tag2) + return tag2->comment(); + + return String::null; + } + + virtual String genre() const { + if(tag1 && !tag1->genre().isEmpty()) + return tag1->genre(); + + if(tag2) + return tag2->genre(); + + return String::null; + } + + virtual uint year() const { + if(tag1 && tag1->year() > 0) + return tag1->year(); + + if(tag2) + return tag2->year(); + + return 0; + } + + virtual uint track() const { + if(tag1 && tag1->track() > 0) + return tag1->track(); + + if(tag2) + return tag2->track(); + + return 0; + } + + virtual void setTitle(const String &s) { + if(tag1) + tag1->setTitle(s); + if(tag2) + tag2->setTitle(s); + } + + virtual void setArtist(const String &s) { + if(tag1) + tag1->setArtist(s); + if(tag2) + tag2->setArtist(s); + } + + virtual void setAlbum(const String &s) { + if(tag1) + tag1->setAlbum(s); + if(tag2) + tag2->setAlbum(s); + } + + virtual void setComment(const String &s) { + if(tag1) + tag1->setComment(s); + if(tag2) + tag2->setComment(s); + } + + virtual void setGenre(const String &s) { + if(tag1) + tag1->setGenre(s); + if(tag2) + tag2->setGenre(s); + } + + virtual void setYear(uint i) { + if(tag1) + tag1->setYear(i); + if(tag2) + tag2->setYear(i); + } + + virtual void setTrack(uint i) { + if(tag1) + tag1->setTrack(i); + if(tag2) + tag2->setTrack(i); + } + + private: + Tag *tag1; + Tag *tag2; + }; +} + +#endif +#endif diff --git a/mpc/mpcfile.cpp b/mpc/mpcfile.cpp index f0e04385..53022c1e 100644 --- a/mpc/mpcfile.cpp +++ b/mpc/mpcfile.cpp @@ -28,7 +28,7 @@ #include "id3v2header.h" #include "apetag.h" #include "apefooter.h" -#include "mpctag.h" +#include "combinedtag.h" using namespace TagLib; @@ -107,19 +107,44 @@ MPC::Properties *MPC::File::audioProperties() const bool MPC::File::save() { + if(readOnly()) { + debug("MPC::File::save() -- File is read only."); + return false; + } + + // Possibly strip ID3v2 tag + + if(d->hasID3v2 && !d->ID3v2Header) { + removeBlock(d->ID3v2Location, d->ID3v2Size); + d->hasID3v2 = false; + if(d->hasID3v1) + d->ID3v1Location -= d->ID3v2Size; + if(d->hasAPE) + d->APELocation -= d->ID3v2Size; + } // Update ID3v1 tag if(d->ID3v1Tag) { if(d->hasID3v1) { - seek(-128, End); + seek(d->ID3v1Location); writeBlock(d->ID3v1Tag->render()); } else { seek(0, End); + d->ID3v1Location = tell(); writeBlock(d->ID3v1Tag->render()); + d->hasID3v1 = true; + } + } else + if(d->hasID3v1) { + removeBlock(d->ID3v1Location, 128); + d->hasID3v1 = false; + if(d->hasAPE) { + if(d->APELocation < d->ID3v1Location) + d->APELocation -= 128; + } } - } // Update APE tag @@ -128,15 +153,30 @@ bool MPC::File::save() insert(d->APETag->render(), d->APELocation, d->APESize); else { if(d->hasID3v1) { - seek(-128, End); - insert(d->APETag->render(), tell(), 0); + insert(d->APETag->render(), d->ID3v1Location, 0); + d->APESize = d->APETag->footer()->completeTagSize(); + d->hasAPE = true; + d->APELocation = d->ID3v1Location; + d->ID3v1Location += d->APESize; } else { seek(0, End); + d->APELocation = tell(); writeBlock(d->APETag->render()); + d->APESize = d->APETag->footer()->completeTagSize(); + d->hasAPE = true; } } } + else + if(d->hasAPE) { + removeBlock(d->APELocation, d->APESize); + d->hasAPE = false; + if(d->hasID3v1) { + if (d->ID3v1Location > d->APELocation) + d->ID3v1Location -= d->APESize; + } + } return true; } @@ -175,6 +215,35 @@ APE::Tag *MPC::File::APETag(bool create) return d->APETag; } +void MPC::File::remove(int tags) +{ + if(tags & ID3v1) { + delete d->ID3v1Tag; + d->ID3v1Tag = 0; + + if(d->APETag) + d->tag = d->APETag; + else + d->tag = d->APETag = new APE::Tag(); + } + + if(tags & ID3v2) { + delete d->ID3v2Header; + d->ID3v2Header = 0; + } + + if(tags & APE) { + delete d->APETag; + d->APETag = 0; + + if(d->ID3v1Tag) + d->tag = d->ID3v1Tag; + else + d->tag = d->APETag = new APE::Tag(); + } +} + + //////////////////////////////////////////////////////////////////////////////// // private members //////////////////////////////////////////////////////////////////////////////// @@ -194,8 +263,6 @@ void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesSty findAPE(); - // Look for an APE tag - d->APELocation = findAPE(); if(d->APELocation >= 0) { @@ -243,17 +310,19 @@ void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesSty long MPC::File::findAPE() { - if(isValid()) { - if(d->hasID3v1) - seek(-160, End); - else - seek(-32, End); + if(!isValid()) + return -1; - long p = tell(); + if(d->hasID3v1) + seek(-160, End); + else + seek(-32, End); + + long p = tell(); + + if(readBlock(8) == APE::Tag::fileIdentifier()) + return p; - if(readBlock(8) == APE::Tag::fileIdentifier()) - return p; - } return -1; } diff --git a/mpc/mpcfile.h b/mpc/mpcfile.h index 5443c9cb..aa40e953 100644 --- a/mpc/mpcfile.h +++ b/mpc/mpcfile.h @@ -67,10 +67,12 @@ namespace TagLib { NoTags = 0x0000, //! Matches ID3v1 tags. ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, //! Matches APE tags. APE = 0x0004, - //! Matches APE behind ID3v1 - APEID3 = 0x0005 + //! Matches all tag types. + AllTags = 0xffff }; /*! @@ -99,7 +101,7 @@ namespace TagLib { virtual Properties *audioProperties() const; /*! - * Save the file. + * Saves the file. */ virtual bool save(); @@ -131,6 +133,16 @@ namespace TagLib { */ APE::Tag *APETag(bool create = false); + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void remove(int tags = AllTags); + private: File(const File &); File &operator=(const File &); diff --git a/mpc/mpctag.h b/mpc/mpctag.h deleted file mode 100644 index 2b567bb3..00000000 --- a/mpc/mpctag.h +++ /dev/null @@ -1,175 +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 DO_NOT_DOCUMENT // Tell Doxygen not to document this header - -#ifndef TAGLIB_MPCTAG_H -#define TAGLIB_MPCTAG_H - -//////////////////////////////////////////////////////////////////////////////// -// Note that this header is not installed. -//////////////////////////////////////////////////////////////////////////////// - -#include -#include - -namespace TagLib { - - namespace MPC { - - /*! - * A union of APE and ID3v1 tags. - */ - class CombinedTag : public TagLib::Tag - { - public: - CombinedTag(APE::Tag *ape = 0, ID3v1::Tag *id3v1 = 0) : - TagLib::Tag(), - ape(ape), id3v1(id3v1) {} - - virtual String title() const { - if(ape && !ape->title().isEmpty()) - return ape->title(); - - if(id3v1) - return id3v1->title(); - - return String::null; - } - - virtual String artist() const { - if(ape && !ape->artist().isEmpty()) - return ape->artist(); - - if(id3v1) - return id3v1->artist(); - - return String::null; - } - - virtual String album() const { - if(ape && !ape->album().isEmpty()) - return ape->album(); - - if(id3v1) - return id3v1->album(); - - return String::null; - } - - virtual String comment() const { - if(ape && !ape->comment().isEmpty()) - return ape->comment(); - - if(id3v1) - return id3v1->comment(); - - return String::null; - } - - virtual String genre() const { - if(ape && !ape->genre().isEmpty()) - return ape->genre(); - - if(id3v1) - return id3v1->genre(); - - return String::null; - } - - virtual uint year() const { - if(ape && ape->year() > 0) - return ape->year(); - - if(id3v1) - return id3v1->year(); - - return 0; - } - - virtual uint track() const { - if(ape && ape->track() > 0) - return ape->track(); - - if(id3v1) - return id3v1->track(); - - return 0; - } - - virtual void setTitle(const String &s) { - if(ape) - ape->setTitle(s); - if(id3v1) - id3v1->setTitle(s); - } - - virtual void setArtist(const String &s) { - if(ape) - ape->setArtist(s); - if(id3v1) - id3v1->setArtist(s); - } - - virtual void setAlbum(const String &s) { - if(ape) - ape->setAlbum(s); - if(id3v1) - id3v1->setAlbum(s); - } - - virtual void setComment(const String &s) { - if(ape) - ape->setComment(s); - if(id3v1) - id3v1->setComment(s); - } - - virtual void setGenre(const String &s) { - if(ape) - ape->setGenre(s); - if(id3v1) - id3v1->setGenre(s); - } - - virtual void setYear(uint i) { - if(ape) - ape->setYear(i); - if(id3v1) - id3v1->setYear(i); - } - - virtual void setTrack(uint i) { - if(ape) - ape->setTrack(i); - if(id3v1) - id3v1->setTrack(i); - } - - private: - APE::Tag *ape; - ID3v1::Tag *id3v1; - }; - } -} - -#endif -#endif