aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--NEWS17
-rw-r--r--taglib/CMakeLists.txt2
-rw-r--r--taglib/ape/apefile.h3
-rw-r--r--taglib/asf/asffile.h6
-rw-r--r--taglib/flac/flacfile.h3
-rw-r--r--taglib/it/itfile.h3
-rw-r--r--taglib/mod/modfile.h3
-rw-r--r--taglib/mp4/mp4file.h3
-rw-r--r--taglib/mpc/mpcfile.h3
-rw-r--r--taglib/mpeg/id3v2/frames/ownershipframe.cpp162
-rw-r--r--taglib/mpeg/id3v2/frames/ownershipframe.h151
-rw-r--r--taglib/mpeg/id3v2/id3v2framefactory.cpp9
-rw-r--r--taglib/mpeg/id3v2/id3v2tag.cpp4
-rw-r--r--taglib/mpeg/id3v2/id3v2tag.h1
-rw-r--r--taglib/mpeg/mpegfile.h3
-rw-r--r--taglib/ogg/flac/oggflacfile.h3
-rw-r--r--taglib/ogg/oggfile.h3
-rw-r--r--taglib/ogg/speex/speexfile.h3
-rw-r--r--taglib/ogg/vorbis/vorbisfile.h3
-rw-r--r--taglib/riff/aiff/aifffile.h3
-rw-r--r--taglib/riff/wav/wavfile.h3
-rw-r--r--taglib/s3m/s3mfile.h3
-rw-r--r--taglib/toolkit/tfile.cpp12
-rw-r--r--taglib/toolkit/tfile.h3
-rw-r--r--taglib/trueaudio/trueaudiofile.h6
-rw-r--r--taglib/wavpack/wavpackfile.h3
-rw-r--r--taglib/xm/xmfile.h3
-rw-r--r--tests/test_id3v2.cpp48
-rw-r--r--tests/test_string.cpp8
30 files changed, 467 insertions, 14 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f4baae46..20a1141b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -56,9 +56,9 @@ set(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VE
# 2. If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0.
# 3. If any interfaces have been added since the last public release, then increment age.
# 4. If any interfaces have been removed since the last public release, then set age to 0.
-set(TAGLIB_SOVERSION_CURRENT 12)
+set(TAGLIB_SOVERSION_CURRENT 13)
set(TAGLIB_SOVERSION_REVISION 0)
-set(TAGLIB_SOVERSION_AGE 11)
+set(TAGLIB_SOVERSION_AGE 12)
math(EXPR TAGLIB_SOVERSION_MAJOR "${TAGLIB_SOVERSION_CURRENT} - ${TAGLIB_SOVERSION_AGE}")
math(EXPR TAGLIB_SOVERSION_MINOR "${TAGLIB_SOVERSION_AGE}")
diff --git a/NEWS b/NEWS
index 6c407a48..fa750f69 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,21 @@
-TagLib 1.8 BETA (Jul 14, 2012)
+TagLib 1.8 (Sep 6, 2012)
==============================
+1.8:
+
+ * Added support for OWNE ID3 frames.
+ * Changed key validation in the new PropertyMap API.
+ * ID3v1::Tag::setStringHandler will no londer delete the previous handler,
+ the caller is responsible for this.
+ * File objects will also no longer delete the passed IOStream objects. It
+ should be done in the caller code after the File object is no longer
+ used.
+ * Added ID3v2::Tag::setLatin1StringHandler for custom handling of
+ latin1-encoded text in ID3v2 frames.
+ * Fixed validation of ID3v2 frame IDs (IDs with '0' were ignored).
+
+1.8 BETA:
+
* New API for accessing tags by name.
* New abstract I/O stream layer to allow custom I/O handlers.
* Support for writing ID3v2.3 tags.
diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt
index ca62f3a4..61bcb49e 100644
--- a/taglib/CMakeLists.txt
+++ b/taglib/CMakeLists.txt
@@ -65,6 +65,7 @@ set(tag_HDRS
mpeg/id3v2/frames/attachedpictureframe.h
mpeg/id3v2/frames/commentsframe.h
mpeg/id3v2/frames/generalencapsulatedobjectframe.h
+ mpeg/id3v2/frames/ownershipframe.h
mpeg/id3v2/frames/popularimeterframe.h
mpeg/id3v2/frames/privateframe.h
mpeg/id3v2/frames/relativevolumeframe.h
@@ -151,6 +152,7 @@ set(frames_SRCS
mpeg/id3v2/frames/attachedpictureframe.cpp
mpeg/id3v2/frames/commentsframe.cpp
mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp
+ mpeg/id3v2/frames/ownershipframe.cpp
mpeg/id3v2/frames/popularimeterframe.cpp
mpeg/id3v2/frames/privateframe.cpp
mpeg/id3v2/frames/relativevolumeframe.cpp
diff --git a/taglib/ape/apefile.h b/taglib/ape/apefile.h
index 0bdbd422..8b187f6a 100644
--- a/taglib/ape/apefile.h
+++ b/taglib/ape/apefile.h
@@ -95,6 +95,9 @@ namespace TagLib {
* Contructs an WavPack file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
diff --git a/taglib/asf/asffile.h b/taglib/asf/asffile.h
index f0acd728..3a7eef56 100644
--- a/taglib/asf/asffile.h
+++ b/taglib/asf/asffile.h
@@ -54,6 +54,9 @@ namespace TagLib {
*
* \note In the current implementation, both \a readProperties and
* \a propertiesStyle are ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
@@ -64,6 +67,9 @@ namespace TagLib {
*
* \note In the current implementation, both \a readProperties and
* \a propertiesStyle are ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
diff --git a/taglib/flac/flacfile.h b/taglib/flac/flacfile.h
index 31dfebd7..716d4478 100644
--- a/taglib/flac/flacfile.h
+++ b/taglib/flac/flacfile.h
@@ -97,6 +97,9 @@ namespace TagLib {
*
* If this file contains and ID3v2 tag the frames will be created using
* \a frameFactory.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
// BIC: merge with the above constructor
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
diff --git a/taglib/it/itfile.h b/taglib/it/itfile.h
index 9c507742..5584b7cd 100644
--- a/taglib/it/itfile.h
+++ b/taglib/it/itfile.h
@@ -48,6 +48,9 @@ namespace TagLib {
* Contructs a Impulse Tracker file from \a stream. If \a readProperties
* is true the file's audio properties will also be read using
* \a propertiesStyle. If false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stram, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle =
diff --git a/taglib/mod/modfile.h b/taglib/mod/modfile.h
index 9e79659c..ad1e43b8 100644
--- a/taglib/mod/modfile.h
+++ b/taglib/mod/modfile.h
@@ -49,6 +49,9 @@ namespace TagLib {
* Contructs a Protracker file from \a stream. If \a readProperties
* is true the file's audio properties will also be read using
* \a propertiesStyle. If false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle =
diff --git a/taglib/mp4/mp4file.h b/taglib/mp4/mp4file.h
index c3613f76..2ed3bea5 100644
--- a/taglib/mp4/mp4file.h
+++ b/taglib/mp4/mp4file.h
@@ -65,6 +65,9 @@ namespace TagLib {
*
* \note In the current implementation, both \a readProperties and
* \a propertiesStyle are ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true, Properties::ReadStyle audioPropertiesStyle = Properties::Average);
diff --git a/taglib/mpc/mpcfile.h b/taglib/mpc/mpcfile.h
index 61ac6d67..167b768e 100644
--- a/taglib/mpc/mpcfile.h
+++ b/taglib/mpc/mpcfile.h
@@ -95,6 +95,9 @@ namespace TagLib {
* Contructs an MPC file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
diff --git a/taglib/mpeg/id3v2/frames/ownershipframe.cpp b/taglib/mpeg/id3v2/frames/ownershipframe.cpp
new file mode 100644
index 00000000..9451c4c4
--- /dev/null
+++ b/taglib/mpeg/id3v2/frames/ownershipframe.cpp
@@ -0,0 +1,162 @@
+/***************************************************************************
+ copyright : (C) 2012 by Rupert Daniel
+ email : rupert@cancelmonday.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., 51 Franklin Street, Fifth Floor, Boston, MA *
+ * 02110-1301 USA *
+ * *
+ * Alternatively, this file is available under the Mozilla Public *
+ * License Version 1.1. You may obtain a copy of the License at *
+ * http://www.mozilla.org/MPL/ *
+ ***************************************************************************/
+
+#include <tdebug.h>
+
+#include "ownershipframe.h"
+#include <id3v2tag.h>
+
+using namespace TagLib;
+using namespace ID3v2;
+
+class OwnershipFrame::OwnershipFramePrivate
+{
+public:
+ String pricePaid;
+ String datePurchased;
+ String seller;
+ String::Type textEncoding;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// public members
+////////////////////////////////////////////////////////////////////////////////
+
+OwnershipFrame::OwnershipFrame(String::Type encoding) : Frame("OWNE")
+{
+ d = new OwnershipFramePrivate;
+ d->textEncoding = encoding;
+}
+
+OwnershipFrame::OwnershipFrame(const ByteVector &data) : Frame(data)
+{
+ d = new OwnershipFramePrivate;
+ setData(data);
+}
+
+OwnershipFrame::~OwnershipFrame()
+{
+ delete d;
+}
+
+String OwnershipFrame::toString() const
+{
+ return "pricePaid=" + d->pricePaid + " datePurchased=" + d->datePurchased + " seller=" + d->seller;
+}
+
+String OwnershipFrame::pricePaid() const
+{
+ return d->pricePaid;
+}
+
+void OwnershipFrame::setPricePaid(const String &s)
+{
+ d->pricePaid = s;
+}
+
+String OwnershipFrame::datePurchased() const
+{
+ return d->datePurchased;
+}
+
+void OwnershipFrame::setDatePurchased(const String &s)
+{
+ d->datePurchased = s;
+}
+
+String OwnershipFrame::seller() const
+{
+ return d->seller;
+}
+
+void OwnershipFrame::setSeller(const String &s)
+{
+ d->seller = s;
+}
+
+String::Type OwnershipFrame::textEncoding() const
+{
+ return d->textEncoding;
+}
+
+void OwnershipFrame::setTextEncoding(String::Type encoding)
+{
+ d->textEncoding = encoding;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// protected members
+////////////////////////////////////////////////////////////////////////////////
+
+void OwnershipFrame::parseFields(const ByteVector &data)
+{
+ int pos = 0;
+
+ // Get the text encoding
+ d->textEncoding = String::Type(data[0]);
+ pos += 1;
+
+ // Read the price paid this is a null terminate string
+ d->pricePaid = readStringField(data, String::Latin1, &pos);
+
+ // If we don't have at least 8 bytes left then don't parse the rest of the
+ // data
+ if(data.size() - pos < 8) {
+ return;
+ }
+
+ // Read the date purchased YYYYMMDD
+ d->datePurchased = String(data.mid(pos, 8));
+ pos += 8;
+
+ // Read the seller
+ if(d->textEncoding == String::Latin1)
+ d->seller = Tag::latin1StringHandler()->parse(data.mid(pos));
+ else
+ d->seller = String(data.mid(pos), d->textEncoding);
+}
+
+ByteVector OwnershipFrame::renderFields() const
+{
+ ByteVector v;
+
+ v.append(char(d->textEncoding));
+ v.append(d->pricePaid.data(String::Latin1));
+ v.append(textDelimiter(String::Latin1));
+ v.append(d->datePurchased.data(String::Latin1));
+ v.append(d->seller.data(d->textEncoding));
+
+ return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private members
+////////////////////////////////////////////////////////////////////////////////
+
+OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) : Frame(h)
+{
+ d = new OwnershipFramePrivate;
+ parseFields(fieldData(data));
+}
diff --git a/taglib/mpeg/id3v2/frames/ownershipframe.h b/taglib/mpeg/id3v2/frames/ownershipframe.h
new file mode 100644
index 00000000..34fc9129
--- /dev/null
+++ b/taglib/mpeg/id3v2/frames/ownershipframe.h
@@ -0,0 +1,151 @@
+/***************************************************************************
+ copyright : (C) 2012 by Rupert Daniel
+ email : rupert@cancelmonday.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., 51 Franklin Street, Fifth Floor, Boston, MA *
+ * 02110-1301 USA *
+ * *
+ * Alternatively, this file is available under the Mozilla Public *
+ * License Version 1.1. You may obtain a copy of the License at *
+ * http://www.mozilla.org/MPL/ *
+ ***************************************************************************/
+
+#ifndef TAGLIB_OWNERSHIPFRAME_H
+#define TAGLIB_OWNERSHIPFRAME_H
+
+#include "id3v2frame.h"
+#include "taglib_export.h"
+
+namespace TagLib {
+
+ namespace ID3v2 {
+
+ //! An implementation of ID3v2 "ownership"
+
+ /*!
+ * This implements the ID3v2 ownership (OWNE frame). It consists of
+ * a price paid, a date purchased (YYYYMMDD) and the name of the seller.
+ */
+
+ class TAGLIB_EXPORT OwnershipFrame : public Frame
+ {
+ friend class FrameFactory;
+
+ public:
+ /*!
+ * Construct an empty ownership frame.
+ */
+ explicit OwnershipFrame(String::Type encoding = String::Latin1);
+
+ /*!
+ * Construct a ownership based on the data in \a data.
+ */
+ explicit OwnershipFrame(const ByteVector &data);
+
+ /*!
+ * Destroys this OwnershipFrame instance.
+ */
+ virtual ~OwnershipFrame();
+
+ /*!
+ * Returns the text of this popularimeter.
+ *
+ * \see text()
+ */
+ virtual String toString() const;
+
+ /*!
+ * Returns the date purchased.
+ *
+ * \see setDatePurchased()
+ */
+ String datePurchased() const;
+
+ /*!
+ * Set the date purchased.
+ *
+ * \see datePurchased()
+ */
+ void setDatePurchased(const String &datePurchased);
+
+ /*!
+ * Returns the price paid.
+ *
+ * \see setPricePaid()
+ */
+ String pricePaid() const;
+
+ /*!
+ * Set the price paid.
+ *
+ * \see pricePaid()
+ */
+ void setPricePaid(const String &pricePaid);
+
+ /*!
+ * Returns the seller.
+ *
+ * \see setSeller()
+ */
+ String seller() const;
+
+ /*!
+ * Set the seller.
+ *
+ * \see seller()
+ */
+ void setSeller(const String &seller);
+
+ /*!
+ * Returns the text encoding that will be used in rendering this frame.
+ * This defaults to the type that was either specified in the constructor
+ * or read from the frame when parsed.
+ *
+ * \see setTextEncoding()
+ * \see render()
+ */
+ String::Type textEncoding() const;
+
+ /*!
+ * Sets the text encoding to be used when rendering this frame to
+ * \a encoding.
+ *
+ * \see textEncoding()
+ * \see render()
+ */
+ void setTextEncoding(String::Type encoding);
+
+ protected:
+ // Reimplementations.
+
+ virtual void parseFields(const ByteVector &data);
+ virtual ByteVector renderFields() const;
+
+ private:
+ /*!
+ * The constructor used by the FrameFactory.
+ */
+ OwnershipFrame(const ByteVector &data, Header *h);
+ OwnershipFrame(const OwnershipFrame &);
+ OwnershipFrame &operator=(const OwnershipFrame &);
+
+ class OwnershipFramePrivate;
+ OwnershipFramePrivate *d;
+ };
+
+ }
+}
+#endif
diff --git a/taglib/mpeg/id3v2/id3v2framefactory.cpp b/taglib/mpeg/id3v2/id3v2framefactory.cpp
index bcf69e1a..7e2e98a8 100644
--- a/taglib/mpeg/id3v2/id3v2framefactory.cpp
+++ b/taglib/mpeg/id3v2/id3v2framefactory.cpp
@@ -44,6 +44,7 @@
#include "frames/unsynchronizedlyricsframe.h"
#include "frames/popularimeterframe.h"
#include "frames/privateframe.h"
+#include "frames/ownershipframe.h"
using namespace TagLib;
using namespace ID3v2;
@@ -238,6 +239,14 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader)
if(frameID == "PRIV")
return new PrivateFrame(data, header);
+
+ // Ownership (frames 4.22)
+
+ if(frameID == "OWNE") {
+ OwnershipFrame *f = new OwnershipFrame(data, header);
+ d->setTextEncoding(f);
+ return f;
+ }
return new UnknownFrame(data, header);
}
diff --git a/taglib/mpeg/id3v2/id3v2tag.cpp b/taglib/mpeg/id3v2/id3v2tag.cpp
index ffb0189c..54e63920 100644
--- a/taglib/mpeg/id3v2/id3v2tag.cpp
+++ b/taglib/mpeg/id3v2/id3v2tag.cpp
@@ -81,6 +81,10 @@ const ID3v2::Latin1StringHandler *ID3v2::Tag::TagPrivate::stringHandler = &defau
// StringHandler implementation
////////////////////////////////////////////////////////////////////////////////
+Latin1StringHandler::Latin1StringHandler()
+{
+}
+
Latin1StringHandler::~Latin1StringHandler()
{
}
diff --git a/taglib/mpeg/id3v2/id3v2tag.h b/taglib/mpeg/id3v2/id3v2tag.h
index e6d6d4fd..5fd5c1f1 100644
--- a/taglib/mpeg/id3v2/id3v2tag.h
+++ b/taglib/mpeg/id3v2/id3v2tag.h
@@ -77,6 +77,7 @@ namespace TagLib {
class TAGLIB_EXPORT Latin1StringHandler
{
public:
+ Latin1StringHandler();
virtual ~Latin1StringHandler();
/*!
diff --git a/taglib/mpeg/mpegfile.h b/taglib/mpeg/mpegfile.h
index 185fced6..9967a991 100644
--- a/taglib/mpeg/mpegfile.h
+++ b/taglib/mpeg/mpegfile.h
@@ -99,6 +99,9 @@ namespace TagLib {
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored. The frames will be created using
* \a frameFactory.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
// BIC: merge with the above constructor
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
diff --git a/taglib/ogg/flac/oggflacfile.h b/taglib/ogg/flac/oggflacfile.h
index d4373795..8558cfdf 100644
--- a/taglib/ogg/flac/oggflacfile.h
+++ b/taglib/ogg/flac/oggflacfile.h
@@ -75,6 +75,9 @@ namespace TagLib {
* Contructs an Ogg/FLAC file from \a file. If \a readProperties is true
* the file's audio properties will also be read using \a propertiesStyle.
* If false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
diff --git a/taglib/ogg/oggfile.h b/taglib/ogg/oggfile.h
index 1ecf2b9b..b36daecb 100644
--- a/taglib/ogg/oggfile.h
+++ b/taglib/ogg/oggfile.h
@@ -100,6 +100,9 @@ namespace TagLib {
* \note This constructor is protected since Ogg::File shouldn't be
* instantiated directly but rather should be used through the codec
* specific subclasses.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream);
diff --git a/taglib/ogg/speex/speexfile.h b/taglib/ogg/speex/speexfile.h
index c14cf2aa..dfe51ec4 100644
--- a/taglib/ogg/speex/speexfile.h
+++ b/taglib/ogg/speex/speexfile.h
@@ -67,6 +67,9 @@ namespace TagLib {
* Contructs a Speex file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
diff --git a/taglib/ogg/vorbis/vorbisfile.h b/taglib/ogg/vorbis/vorbisfile.h
index 15c29d99..6e4d4fc4 100644
--- a/taglib/ogg/vorbis/vorbisfile.h
+++ b/taglib/ogg/vorbis/vorbisfile.h
@@ -74,6 +74,9 @@ namespace TagLib {
* Contructs a Vorbis file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
diff --git a/taglib/riff/aiff/aifffile.h b/taglib/riff/aiff/aifffile.h
index a50c8ecb..e1284db0 100644
--- a/taglib/riff/aiff/aifffile.h
+++ b/taglib/riff/aiff/aifffile.h
@@ -69,6 +69,9 @@ namespace TagLib {
* Contructs an AIFF file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
diff --git a/taglib/riff/wav/wavfile.h b/taglib/riff/wav/wavfile.h
index 861f3f77..1c470870 100644
--- a/taglib/riff/wav/wavfile.h
+++ b/taglib/riff/wav/wavfile.h
@@ -69,6 +69,9 @@ namespace TagLib {
* Contructs an WAV file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
diff --git a/taglib/s3m/s3mfile.h b/taglib/s3m/s3mfile.h
index 0605b2bf..c862108e 100644
--- a/taglib/s3m/s3mfile.h
+++ b/taglib/s3m/s3mfile.h
@@ -48,6 +48,9 @@ namespace TagLib {
* Contructs a ScreamTracker III file from \a stream. If \a readProperties
* is true the file's audio properties will also be read using
* \a propertiesStyle. If false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle =
diff --git a/taglib/toolkit/tfile.cpp b/taglib/toolkit/tfile.cpp
index 30cc9fbc..d0a6116f 100644
--- a/taglib/toolkit/tfile.cpp
+++ b/taglib/toolkit/tfile.cpp
@@ -74,15 +74,17 @@ using namespace TagLib;
class File::FilePrivate
{
public:
- FilePrivate(IOStream *stream);
+ FilePrivate(IOStream *stream, bool owner);
IOStream *stream;
+ bool streamOwner;
bool valid;
static const uint bufferSize = 1024;
};
-File::FilePrivate::FilePrivate(IOStream *stream) :
+File::FilePrivate::FilePrivate(IOStream *stream, bool owner) :
stream(stream),
+ streamOwner(owner),
valid(true)
{
}
@@ -94,17 +96,17 @@ File::FilePrivate::FilePrivate(IOStream *stream) :
File::File(FileName fileName)
{
IOStream *stream = new FileStream(fileName);
- d = new FilePrivate(stream);
+ d = new FilePrivate(stream, true);
}
File::File(IOStream *stream)
{
- d = new FilePrivate(stream);
+ d = new FilePrivate(stream, false);
}
File::~File()
{
- if(d->stream)
+ if(d->stream && d->streamOwner)
delete d->stream;
delete d;
}
diff --git a/taglib/toolkit/tfile.h b/taglib/toolkit/tfile.h
index 7df774a0..7e6f2b93 100644
--- a/taglib/toolkit/tfile.h
+++ b/taglib/toolkit/tfile.h
@@ -260,6 +260,9 @@ namespace TagLib {
/*!
* Construct a File object and use the \a stream instance.
*
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
+ *
* \note Constructor is protected since this class should only be
* instantiated through subclasses.
*/
diff --git a/taglib/trueaudio/trueaudiofile.h b/taglib/trueaudio/trueaudiofile.h
index 9b0378f7..e3e1fe62 100644
--- a/taglib/trueaudio/trueaudiofile.h
+++ b/taglib/trueaudio/trueaudiofile.h
@@ -100,6 +100,9 @@ namespace TagLib {
* Contructs an TrueAudio file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
@@ -109,6 +112,9 @@ namespace TagLib {
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored. The frames will be created using
* \a frameFactory.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
bool readProperties = true,
diff --git a/taglib/wavpack/wavpackfile.h b/taglib/wavpack/wavpackfile.h
index 02bac023..5bbbc65a 100644
--- a/taglib/wavpack/wavpackfile.h
+++ b/taglib/wavpack/wavpackfile.h
@@ -91,6 +91,9 @@ namespace TagLib {
* Contructs an WavPack file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
diff --git a/taglib/xm/xmfile.h b/taglib/xm/xmfile.h
index 1b07010b..9d1bb71c 100644
--- a/taglib/xm/xmfile.h
+++ b/taglib/xm/xmfile.h
@@ -48,6 +48,9 @@ namespace TagLib {
* Contructs a Extended Module file from \a stream. If \a readProperties
* is true the file's audio properties will also be read using
* \a propertiesStyle. If false, \a propertiesStyle is ignored.
+ *
+ * \note TagLib will *not* take ownership of the stream, the caller is
+ * responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle =
diff --git a/tests/test_id3v2.cpp b/tests/test_id3v2.cpp
index 29758aa4..d3fbfee9 100644
--- a/tests/test_id3v2.cpp
+++ b/tests/test_id3v2.cpp
@@ -15,6 +15,7 @@
#include <relativevolumeframe.h>
#include <popularimeterframe.h>
#include <urllinkframe.h>
+#include <ownershipframe.h>
#include <tdebug.h>
#include <tpropertymap.h>
#include "utils.h"
@@ -61,6 +62,8 @@ class TestID3v2 : public CppUnit::TestFixture
CPPUNIT_TEST(testRenderUrlLinkFrame);
CPPUNIT_TEST(testParseUserUrlLinkFrame);
CPPUNIT_TEST(testRenderUserUrlLinkFrame);
+ CPPUNIT_TEST(testParseOwnershipFrame);
+ CPPUNIT_TEST(testRenderOwnershipFrame);
CPPUNIT_TEST(testSaveUTF16Comment);
CPPUNIT_TEST(testUpdateGenre23_1);
CPPUNIT_TEST(testUpdateGenre23_2);
@@ -386,6 +389,38 @@ public:
"http://example.com", 33), // URL
f.render());
}
+
+ void testParseOwnershipFrame()
+ {
+ ID3v2::OwnershipFrame f(
+ ByteVector("OWNE" // Frame ID
+ "\x00\x00\x00\x19" // Frame size
+ "\x00\x00" // Frame flags
+ "\x00" // Text encoding
+ "GBP1.99\x00" // Price paid
+ "20120905" // Date of purchase
+ "Beatport", 35)); // Seller
+ CPPUNIT_ASSERT_EQUAL(String("GBP1.99"), f.pricePaid());
+ CPPUNIT_ASSERT_EQUAL(String("20120905"), f.datePurchased());
+ CPPUNIT_ASSERT_EQUAL(String("Beatport"), f.seller());
+ }
+
+ void testRenderOwnershipFrame()
+ {
+ ID3v2::OwnershipFrame f;
+ f.setPricePaid("GBP1.99");
+ f.setDatePurchased("20120905");
+ f.setSeller("Beatport");
+ CPPUNIT_ASSERT_EQUAL(
+ ByteVector("OWNE" // Frame ID
+ "\x00\x00\x00\x19" // Frame size
+ "\x00\x00" // Frame flags
+ "\x00" // Text encoding
+ "GBP1.99\x00" // Price paid
+ "20120905" // Date of purchase
+ "Beatport", 35), // URL
+ f.render());
+ }
void testItunes24FrameSize()
{
@@ -553,13 +588,13 @@ public:
CPPUNIT_ASSERT_EQUAL(String(""), frame->description());
CPPUNIT_ASSERT_EQUAL(TagLib::uint(86414), frame->picture().size());
}
-
+
void testW000()
{
MPEG::File f(TEST_FILE_PATH_C("w000.mp3"), false);
CPPUNIT_ASSERT(f.ID3v2Tag()->frameListMap().contains("W000"));
ID3v2::UrlLinkFrame *frame =
- dynamic_cast<TagLib::ID3v2::UrlLinkFrame*>(f.ID3v2Tag()->frameListMap()["W000"].front());
+ dynamic_cast<TagLib::ID3v2::UrlLinkFrame*>(f.ID3v2Tag()->frameListMap()["W000"].front());
CPPUNIT_ASSERT(frame);
CPPUNIT_ASSERT_EQUAL(String("lukas.lalinsky@example.com____"), frame->url());
}
@@ -651,29 +686,30 @@ public:
CPPUNIT_ASSERT_EQUAL(1u, t->frameList("TCON").size());
t->removeFrame(frame, true);
f.save(MPEG::File::ID3v2);
-
+
MPEG::File f2(newname.c_str());
t = f2.ID3v2Tag();
CPPUNIT_ASSERT(t->frameList("TCON").isEmpty());
}
+
void testSaveAndStripID3v1ShouldNotAddFrameFromID3v1ToId3v2()
{
ScopedFileCopy copy("xing", ".mp3");
string newname = copy.fileName();
-
+
{
MPEG::File foo(newname.c_str());
foo.tag()->setArtist("Artist");
foo.save(MPEG::File::ID3v1 | MPEG::File::ID3v2);
}
-
+
{
MPEG::File bar(newname.c_str());
bar.ID3v2Tag()->removeFrames("TPE1");
// Should strip ID3v1 here and not add old values to ID3v2 again
bar.save(MPEG::File::ID3v2, true);
}
-
+
MPEG::File f(newname.c_str());
CPPUNIT_ASSERT(!f.ID3v2Tag()->frameListMap().contains("TPE1"));
}
diff --git a/tests/test_string.cpp b/tests/test_string.cpp
index b6ff972e..79b32c3a 100644
--- a/tests/test_string.cpp
+++ b/tests/test_string.cpp
@@ -41,6 +41,7 @@ class TestString : public CppUnit::TestFixture
CPPUNIT_TEST(testAppendCharDetach);
CPPUNIT_TEST(testAppendStringDetach);
CPPUNIT_TEST(testToInt);
+ CPPUNIT_TEST(testSubstr);
CPPUNIT_TEST_SUITE_END();
public:
@@ -193,6 +194,13 @@ public:
CPPUNIT_ASSERT_EQUAL(String("-123aa").toInt(), -123);
}
+ void testSubstr()
+ {
+ CPPUNIT_ASSERT_EQUAL(String("01"), String("0123456").substr(0, 2));
+ CPPUNIT_ASSERT_EQUAL(String("12"), String("0123456").substr(1, 2));
+ CPPUNIT_ASSERT_EQUAL(String("123456"), String("0123456").substr(1, 200));
+ }
+
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestString);