diff --git a/taglib/dsdiff/dsdiffdiintag.cpp b/taglib/dsdiff/dsdiffdiintag.cpp index c67b7a31..6f4e1633 100644 --- a/taglib/dsdiff/dsdiffdiintag.cpp +++ b/taglib/dsdiff/dsdiffdiintag.cpp @@ -1,6 +1,6 @@ /*************************************************************************** - copyright : (C) 2016 by Damien Plisson, Audirvana - email : damien78@audirvana.com + copyright : (C) 2016 by Damien Plisson, Audirvana + email : damien78@audirvana.com ***************************************************************************/ /*************************************************************************** @@ -24,9 +24,12 @@ ***************************************************************************/ #include "dsdiffdiintag.h" -#include "tdebug.h" + +#include + #include "tstringlist.h" #include "tpropertymap.h" +#include "tdebug.h" using namespace TagLib; using namespace DSDIFF::DIIN; @@ -34,23 +37,16 @@ using namespace DSDIFF::DIIN; class DSDIFF::DIIN::Tag::TagPrivate { public: - TagPrivate() - { - } - String title; String artist; }; DSDIFF::DIIN::Tag::Tag() : - d(new TagPrivate()) + d(std::make_unique()) { } -DSDIFF::DIIN::Tag::~Tag() -{ - delete d; -} +DSDIFF::DIIN::Tag::~Tag() = default; String DSDIFF::DIIN::Tag::title() const { @@ -89,18 +85,12 @@ unsigned int DSDIFF::DIIN::Tag::track() const void DSDIFF::DIIN::Tag::setTitle(const String &title) { - if(title.isEmpty()) - d->title = String(); - else - d->title = title; + d->title = title; } void DSDIFF::DIIN::Tag::setArtist(const String &artist) { - if(artist.isEmpty()) - d->artist = String(); - else - d->artist = artist; + d->artist = artist; } void DSDIFF::DIIN::Tag::setAlbum(const String &) @@ -146,22 +136,21 @@ PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps) d->title = properties["TITLE"].front(); oneValueSet.append("TITLE"); } else - d->title = String(); + d->title.clear(); if(properties.contains("ARTIST")) { d->artist = properties["ARTIST"].front(); oneValueSet.append("ARTIST"); } else - d->artist = String(); + d->artist.clear(); // for each tag that has been set above, remove the first entry in the corresponding // value list. The others will be returned as unsupported by this format. - for(StringList::Iterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) { - if(properties[*it].size() == 1) - properties.erase(*it); + for(const auto &entry : std::as_const(oneValueSet)) { + if(properties[entry].size() == 1) + properties.erase(entry); else - properties[*it].erase(properties[*it].begin()); + properties[entry].erase(properties[entry].begin()); } - return properties; } diff --git a/taglib/dsdiff/dsdiffdiintag.h b/taglib/dsdiff/dsdiffdiintag.h index 62de949b..124a4da6 100644 --- a/taglib/dsdiff/dsdiffdiintag.h +++ b/taglib/dsdiff/dsdiffdiintag.h @@ -1,6 +1,6 @@ /*************************************************************************** - copyright : (C) 2016 by Damien Plisson, Audirvana - email : damien78@audirvana.com + copyright : (C) 2016 by Damien Plisson, Audirvana + email : damien78@audirvana.com ***************************************************************************/ /*************************************************************************** @@ -136,14 +136,11 @@ namespace TagLib { PropertyMap setProperties(const PropertyMap &) override; private: - Tag(const Tag &) = delete; - Tag &operator=(const Tag &) = delete; - class TagPrivate; - TagPrivate *d; + std::unique_ptr d; }; - } - } -} + } // namespace DIIN + } // namespace DSDIFF +} // namespace TagLib #endif diff --git a/taglib/dsdiff/dsdifffile.cpp b/taglib/dsdiff/dsdifffile.cpp index 0d75ac8d..8b38be05 100644 --- a/taglib/dsdiff/dsdifffile.cpp +++ b/taglib/dsdiff/dsdifffile.cpp @@ -1,6 +1,6 @@ /*************************************************************************** - copyright : (C) 2016 by Damien Plisson, Audirvana - email : damien78@audirvana.com + copyright : (C) 2016 by Damien Plisson, Audirvana + email : damien78@audirvana.com ***************************************************************************/ /*************************************************************************** @@ -23,17 +23,18 @@ * http://www.mozilla.org/MPL/ * ***************************************************************************/ -#include "tbytevector.h" -#include "tdebug.h" -#include "id3v2tag.h" -#include "tstringlist.h" -#include "tpropertymap.h" -#include "tagutils.h" - -#include "tagunion.h" #include "dsdifffile.h" #include +#include + +#include "tbytevector.h" +#include "tstringlist.h" +#include "tpropertymap.h" +#include "tdebug.h" +#include "id3v2tag.h" +#include "tagutils.h" +#include "tagunion.h" using namespace TagLib; @@ -51,7 +52,7 @@ namespace int chunkIndex(const ChunkList &chunks, const ByteVector &id) { - for(int i = 0; i < chunks.size(); i++) { + for(size_t i = 0; i < chunks.size(); i++) { if(chunks[i].name == id) return i; } @@ -85,50 +86,40 @@ namespace class DSDIFF::File::FilePrivate { public: - FilePrivate() : - endianness(BigEndian), - size(0), - isID3InPropChunk(false), - duplicateID3V2chunkIndex(-1), - properties(0), - id3v2TagChunkID("ID3 "), - hasID3v2(false), - hasDiin(false) + FilePrivate(ID3v2::FrameFactory *frameFactory) + : ID3v2FrameFactory(frameFactory ? frameFactory + : ID3v2::FrameFactory::instance()) { - childChunkIndex[ID3v2Index] = -1; - childChunkIndex[DIINIndex] = -1; } - ~FilePrivate() - { - delete properties; - } + ~FilePrivate() = default; - Endianness endianness; + const ID3v2::FrameFactory *ID3v2FrameFactory; + Endianness endianness { BigEndian }; ByteVector type; - unsigned long long size; + unsigned long long size { 0 }; ByteVector format; ChunkList chunks; std::array childChunks; - std::array childChunkIndex; + std::array childChunkIndex { -1, -1 }; /* * Two possibilities can be found: ID3V2 chunk inside PROP chunk or at root level */ - bool isID3InPropChunk; + bool isID3InPropChunk { false }; /* * ID3 chunks are present. This is then the index of the one in PROP chunk that * will be removed upon next save to remove duplicates. */ - int duplicateID3V2chunkIndex; + int duplicateID3V2chunkIndex { -1 }; - Properties *properties; + std::unique_ptr properties; TagUnion tag; - ByteVector id3v2TagChunkID; + ByteVector id3v2TagChunkID { "ID3 " }; - bool hasID3v2; - bool hasDiin; + bool hasID3v2 { false }; + bool hasDiin { false }; }; //////////////////////////////////////////////////////////////////////////////// @@ -137,10 +128,9 @@ public: bool DSDIFF::File::isSupported(IOStream *stream) { - // A DSDIFF file has to start with "FRM8????????DSD ". - - const ByteVector id = Utils::readHeader(stream, 16, false); - return (id.startsWith("FRM8") && id.containsAt("DSD ", 12)); + // A DSDIFF file has to start with "FRM8????????DSD ". + const ByteVector id = Utils::readHeader(stream, 16, false); + return (id.startsWith("FRM8") && id.containsAt("DSD ", 12)); } //////////////////////////////////////////////////////////////////////////////// @@ -148,29 +138,26 @@ bool DSDIFF::File::isSupported(IOStream *stream) //////////////////////////////////////////////////////////////////////////////// DSDIFF::File::File(FileName file, bool readProperties, - Properties::ReadStyle propertiesStyle) : + Properties::ReadStyle propertiesStyle, + ID3v2::FrameFactory *frameFactory) : TagLib::File(file), - d(new FilePrivate()) + d(std::make_unique(frameFactory)) { - d->endianness = BigEndian; if(isOpen()) read(readProperties, propertiesStyle); } DSDIFF::File::File(IOStream *stream, bool readProperties, - Properties::ReadStyle propertiesStyle) : + Properties::ReadStyle propertiesStyle, + ID3v2::FrameFactory *frameFactory) : TagLib::File(stream), - d(new FilePrivate()) + d(std::make_unique(frameFactory)) { - d->endianness = BigEndian; if(isOpen()) read(readProperties, propertiesStyle); } -DSDIFF::File::~File() -{ - delete d; -} +DSDIFF::File::~File() = default; TagLib::Tag *DSDIFF::File::tag() const { @@ -199,32 +186,22 @@ bool DSDIFF::File::hasDIINTag() const PropertyMap DSDIFF::File::properties() const { - if(d->hasID3v2) - return d->tag.access(ID3v2Index, false)->properties(); - - if(d->hasDiin) - return d->tag.access(DIINIndex, false)->properties(); - - return PropertyMap(); + return d->tag.properties(); } void DSDIFF::File::removeUnsupportedProperties(const StringList &unsupported) { - if(d->hasID3v2) - d->tag.access(ID3v2Index, false)->removeUnsupportedProperties(unsupported); - - if(d->hasDiin) - d->tag.access(DIINIndex, false)->removeUnsupportedProperties(unsupported); + d->tag.removeUnsupportedProperties(unsupported); } PropertyMap DSDIFF::File::setProperties(const PropertyMap &properties) { - return d->tag.access(ID3v2Index, true)->setProperties(properties); + return ID3v2Tag(true)->setProperties(properties); } DSDIFF::Properties *DSDIFF::File::audioProperties() const { - return d->properties; + return d->properties.get(); } bool DSDIFF::File::save() @@ -244,16 +221,14 @@ bool DSDIFF::File::save(int tags, StripTags strip, ID3v2::Version version) return false; } - // TODO: Should duplicate be supported? - if(strip == StripOthers) File::strip(~tags); // First: save ID3V2 chunk - ID3v2::Tag *id3v2Tag = d->tag.access(ID3v2Index, false); + ID3v2::Tag *id3v2Tag = ID3v2Tag(); - if(tags & ID3v2 && id3v2Tag) { + if((tags & ID3v2) && id3v2Tag) { if(d->isID3InPropChunk) { if(!id3v2Tag->isEmpty()) { setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(version), PROPChunk); @@ -280,9 +255,9 @@ bool DSDIFF::File::save(int tags, StripTags strip, ID3v2::Version version) // Second: save the DIIN chunk - DSDIFF::DIIN::Tag *diinTag = d->tag.access(DIINIndex, false); + DSDIFF::DIIN::Tag *diinTag = DIINTag(); - if(tags & DIIN && diinTag) { + if((tags & DIIN) && diinTag) { if(!diinTag->title().isEmpty()) { ByteVector diinTitle; diinTitle.append(ByteVector::fromUInt(diinTag->title().size(), d->endianness == BigEndian)); @@ -303,7 +278,7 @@ bool DSDIFF::File::save(int tags, StripTags strip, ID3v2::Version version) } // Third: remove the duplicate ID3V2 chunk (inside PROP chunk) if any - if(d->duplicateID3V2chunkIndex>=0) { + if(d->duplicateID3V2chunkIndex >= 0) { setChildChunkData(d->duplicateID3V2chunkIndex, ByteVector(), PROPChunk); d->duplicateID3V2chunkIndex = -1; } @@ -316,14 +291,21 @@ void DSDIFF::File::strip(int tags) if(tags & ID3v2) { removeRootChunk("ID3 "); removeRootChunk("id3 "); + removeChildChunk("ID3 ", PROPChunk); + removeChildChunk("id3 ", PROPChunk); d->hasID3v2 = false; d->tag.set(ID3v2Index, new ID3v2::Tag); - - /// TODO: needs to also account for ID3v2 tags under the PROP chunk + d->duplicateID3V2chunkIndex = -1; + d->isID3InPropChunk = false; + d->id3v2TagChunkID.setData("ID3 "); } if(tags & DIIN) { - removeRootChunk("DITI"); - removeRootChunk("DIAR"); + removeChildChunk("DITI", DIINChunk); + removeChildChunk("DIAR", DIINChunk); + if(d->childChunks[DIINIndex].size() == 0) { + removeRootChunk("DIIN"); + } + d->hasDiin = false; d->tag.set(DIINIndex, new DIIN::Tag); } @@ -344,11 +326,13 @@ void DSDIFF::File::removeRootChunk(unsigned int i) // Update the internal offsets - for(unsigned long r = i + 1; r < d->chunks.size(); r++) - d->chunks[r].offset = d->chunks[r - 1].offset + 12 - + d->chunks[r - 1].size + d->chunks[r - 1].padding; - d->chunks.erase(d->chunks.begin() + i); + for(int &cci : d->childChunkIndex) { + if(cci > static_cast(i)) { + --cci; + } + } + updateRootChunksStructure(i); } void DSDIFF::File::removeRootChunk(const ByteVector &id) @@ -410,10 +394,11 @@ void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &da insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8); // Now add the chunk to the file + const unsigned long long fileLength = length(); writeChunk(name, data, offset, - std::max(0, length() - offset), + fileLength > offset ? fileLength - offset : 0, (offset & 1) ? 1 : 0); Chunk64 chunk; @@ -450,19 +435,23 @@ void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum) if((i + 1) < childChunks.size()) { childChunks[i + 1].offset = childChunks[i].offset; - i++; - for(i++; i < childChunks.size(); i++) - childChunks[i].offset = childChunks[i - 1].offset + 12 - + childChunks[i - 1].size + childChunks[i - 1].padding; + for(unsigned int c = i + 2; c < childChunks.size(); ++c) + childChunks[c].offset = childChunks[c - 1].offset + 12 + + childChunks[c - 1].size + childChunks[c - 1].padding; } // And for root chunks - for(i = d->childChunkIndex[childChunkNum] + 1; i < d->chunks.size(); i++) - d->chunks[i].offset = d->chunks[i - 1].offset + 12 - + d->chunks[i - 1].size + d->chunks[i - 1].padding; - childChunks.erase(childChunks.begin() + i); + updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1); +} + +void DSDIFF::File::removeChildChunk(const ByteVector &id, unsigned int childChunkNum) +{ + int i = chunkIndex(d->childChunks[childChunkNum], id); + + if(i >= 0) + removeChildChunk(i, childChunkNum); } void DSDIFF::File::setChildChunkData(unsigned int i, @@ -517,18 +506,11 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name, { ChunkList &childChunks = d->childChunks[childChunkNum]; - if(childChunks.size() == 0) { - debug("DSDIFF::File::setChildChunkData - No valid chunks found."); + if(int i = chunkIndex(childChunks, name); i >= 0) { + setChildChunkData(i, data, childChunkNum); return; } - for(unsigned int i = 0; i < childChunks.size(); i++) { - if(childChunks[i].name == name) { - setChildChunkData(i, data, childChunkNum); - return; - } - } - // Do not attempt to remove a non existing chunk if(data.isEmpty()) @@ -536,8 +518,30 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name, // Couldn't find an existing chunk, so let's create a new one. - unsigned int i = childChunks.size() - 1; - unsigned long offset = childChunks[i].offset + childChunks[i].size + childChunks[i].padding; + unsigned long long offset = 0; + if(childChunks.size() > 0) { + unsigned int i = childChunks.size() - 1; + offset = childChunks[i].offset + childChunks[i].size + childChunks[i].padding; + } + else if(childChunkNum == DIINChunk) { + int i = d->childChunkIndex[DIINChunk]; + if(i < 0) { + setRootChunkData("DIIN", ByteVector()); + const int lastChunkIndex = d->chunks.size() - 1; + if(lastChunkIndex >= 0 && d->chunks[lastChunkIndex].name == "DIIN") { + i = lastChunkIndex; + d->childChunkIndex[DIINChunk] = lastChunkIndex; + d->hasDiin = true; + } + } + if(i >= 0) { + offset = d->chunks[i].offset; // 12 is already added in setRootChunkData() + } + } + if(offset == 0) { + debug("DSDIFF::File::setChildChunkData - No valid chunks found."); + return; + } // First we update the global size @@ -559,7 +563,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name, nextRootChunkIdx = d->chunks[d->childChunkIndex[childChunkNum] + 1].offset - 12; writeChunk(name, data, offset, - std::max(0, nextRootChunkIdx - offset), + nextRootChunkIdx > offset ? nextRootChunkIdx - offset : 0, (offset & 1) ? 1 : 0); // For root chunks @@ -581,7 +585,7 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk) d->chunks[i].offset = d->chunks[i - 1].offset + 12 + d->chunks[i - 1].size + d->chunks[i - 1].padding; - // Update childchunks structure as well + // Update child chunks structure as well if(d->childChunkIndex[PROPChunk] >= static_cast(startingChunk)) { ChunkList &childChunksToUpdate = d->childChunks[PROPChunk]; @@ -606,7 +610,7 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk) void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) { - bool bigEndian = (d->endianness == BigEndian); + bool bigEndian = d->endianness == BigEndian; d->type = readBlock(4); d->size = readBlock(8).toLongLong(bigEndian); @@ -824,8 +828,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty // Read properties - unsigned int sampleRate=0; - unsigned short channels=0; + unsigned int sampleRate = 0; + unsigned short channels = 0; for(unsigned int i = 0; i < d->childChunks[PROPChunk].size(); i++) { if(d->childChunks[PROPChunk][i].name == "ID3 " || @@ -896,11 +900,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty if(lengthDSDSamplesTimeChannels > 0) bitrate = (audioDataSizeinBytes * 8 * sampleRate) / lengthDSDSamplesTimeChannels / 1000; - d->properties = new Properties(sampleRate, - channels, - lengthDSDSamplesTimeChannels, - bitrate, - propertiesStyle); + d->properties = std::make_unique(sampleRate, channels, + lengthDSDSamplesTimeChannels, bitrate, propertiesStyle); } if(!ID3v2Tag()) { diff --git a/taglib/dsdiff/dsdifffile.h b/taglib/dsdiff/dsdifffile.h index d1cb8248..dea91b4a 100644 --- a/taglib/dsdiff/dsdifffile.h +++ b/taglib/dsdiff/dsdifffile.h @@ -1,6 +1,6 @@ /*************************************************************************** - copyright : (C) 2016 by Damien Plisson, Audirvana - email : damien78@audirvana.com + copyright : (C) 2016 by Damien Plisson, Audirvana + email : damien78@audirvana.com ***************************************************************************/ /*************************************************************************** @@ -70,33 +70,41 @@ namespace TagLib { //! Empty set. Matches no tag types. NoTags = 0x0000, //! Matches DIIN tags. - DIIN = 0x0002, - //! Matches ID3v1 tags. + DIIN = 0x0001, + //! Matches ID3v2 tags. ID3v2 = 0x0002, //! Matches all tag types. AllTags = 0xffff }; /*! - * Constructs an DSDIFF file from \a file. If \a readProperties is true + * Constructs a DSDIFF file from \a file. If \a readProperties is true * the file's audio properties will also be read. * * \note In the current implementation, \a propertiesStyle is ignored. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory (default if null). */ File(FileName file, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + Properties::ReadStyle propertiesStyle = Properties::Average, + ID3v2::FrameFactory *frameFactory = nullptr); /*! * Constructs an DSDIFF file from \a stream. If \a readProperties is true * the file's audio properties will also be read. * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory (default if null). + * * \note TagLib will *not* take ownership of the stream, the caller is * responsible for deleting it after the File object. * * \note In the current implementation, \a propertiesStyle is ignored. */ File(IOStream *stream, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + Properties::ReadStyle propertiesStyle = Properties::Average, + ID3v2::FrameFactory *frameFactory = nullptr); /*! * Destroys this instance of the File. @@ -223,12 +231,10 @@ namespace TagLib { File(IOStream *stream, Endianness endianness); private: - File(const File &) = delete; - File &operator=(const File &) = delete; - void removeRootChunk(const ByteVector &id); - void removeRootChunk(unsigned int chunk); - void removeChildChunk(unsigned int i, unsigned int chunk); + void removeRootChunk(unsigned int i); + void removeChildChunk(const ByteVector &id, unsigned int childChunkNum); + void removeChildChunk(unsigned int i, unsigned int childChunkNum); /*! * Sets the data for the the specified chunk at root level to \a data. @@ -277,9 +283,9 @@ namespace TagLib { unsigned int leadingPadding = 0); class FilePrivate; - FilePrivate *d; + std::unique_ptr d; }; - } -} + } // namespace DSDIFF +} // namespace TagLib #endif diff --git a/taglib/dsdiff/dsdiffproperties.cpp b/taglib/dsdiff/dsdiffproperties.cpp index afa12f3a..0d1a032f 100644 --- a/taglib/dsdiff/dsdiffproperties.cpp +++ b/taglib/dsdiff/dsdiffproperties.cpp @@ -1,6 +1,6 @@ /*************************************************************************** - copyright : (C) 2016 by Damien Plisson, Audirvana - email : damien78@audirvana.com + copyright : (C) 2016 by Damien Plisson, Audirvana + email : damien78@audirvana.com ***************************************************************************/ /*************************************************************************** @@ -23,32 +23,22 @@ * http://www.mozilla.org/MPL/ * ***************************************************************************/ +#include "dsdiffproperties.h" + #include "tstring.h" #include "tdebug.h" -#include "dsdiffproperties.h" - using namespace TagLib; class DSDIFF::Properties::PropertiesPrivate { public: - PropertiesPrivate() : - length(0), - bitrate(0), - sampleRate(0), - channels(0), - sampleWidth(0), - sampleCount(0) - { - } - - int length; - int bitrate; - int sampleRate; - int channels; - int sampleWidth; - unsigned long long sampleCount; + int length { 0 }; + int bitrate { 0 }; + int sampleRate { 0 }; + int channels { 0 }; + int sampleWidth { 0 }; + unsigned long long sampleCount { 0 }; }; //////////////////////////////////////////////////////////////////////////////// @@ -61,27 +51,19 @@ DSDIFF::Properties::Properties(const unsigned int sampleRate, const int bitrate, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) + d(std::make_unique()) { - d->channels = channels; + d->channels = channels; d->sampleCount = samplesCount; d->sampleWidth = 1; - d->sampleRate = sampleRate; - d->bitrate = bitrate; - d->length = d->sampleRate > 0 + d->sampleRate = sampleRate; + d->bitrate = bitrate; + d->length = d->sampleRate > 0 ? static_cast((d->sampleCount * 1000.0) / d->sampleRate + 0.5) : 0; } -DSDIFF::Properties::~Properties() -{ - delete d; -} - -int DSDIFF::Properties::length() const -{ - return lengthInSeconds(); -} +DSDIFF::Properties::~Properties() = default; int DSDIFF::Properties::lengthInSeconds() const { diff --git a/taglib/dsdiff/dsdiffproperties.h b/taglib/dsdiff/dsdiffproperties.h index 577afedb..b7aaf29d 100644 --- a/taglib/dsdiff/dsdiffproperties.h +++ b/taglib/dsdiff/dsdiffproperties.h @@ -55,28 +55,24 @@ namespace TagLib { /*! * Destroys this DSDIFF::Properties instance. */ - virtual ~Properties(); + ~Properties() override; // Reimplementations. - virtual int length() const; - virtual int lengthInSeconds() const; - virtual int lengthInMilliseconds() const; - virtual int bitrate() const; - virtual int sampleRate() const; - virtual int channels() const; + int lengthInSeconds() const override; + int lengthInMilliseconds() const override; + int bitrate() const override; + int sampleRate() const override; + int channels() const override; int bitsPerSample() const; long long sampleCount() const; private: - Properties(const Properties &); - Properties &operator=(const Properties &); - class PropertiesPrivate; - PropertiesPrivate *d; + std::unique_ptr d; }; - } -} + } // namespace DSDIFF +} // namespace TagLib #endif diff --git a/tests/test_dsdiff.cpp b/tests/test_dsdiff.cpp index 27761bdc..08a7ef62 100644 --- a/tests/test_dsdiff.cpp +++ b/tests/test_dsdiff.cpp @@ -1,8 +1,31 @@ -#include -#include -#include -#include -#include +/*************************************************************************** + copyright : (C) 2013-2023 Stephen F. Booth + email : me@sbooth.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., 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 "tbytevectorlist.h" +#include "dsdifffile.h" +#include "plainfile.h" #include #include "utils.h" @@ -26,7 +49,6 @@ public: { DSDIFF::File f(TEST_FILE_PATH_C("empty10ms.dff")); CPPUNIT_ASSERT(f.audioProperties()); - CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->length()); CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->lengthInSeconds()); CPPUNIT_ASSERT_EQUAL(10, f.audioProperties()->lengthInMilliseconds()); CPPUNIT_ASSERT_EQUAL(5644, f.audioProperties()->bitrate()); @@ -41,15 +63,16 @@ public: ScopedFileCopy copy("empty10ms", ".dff"); string newname = copy.fileName(); - DSDIFF::File *f = new DSDIFF::File(newname.c_str()); - CPPUNIT_ASSERT_EQUAL(String(""), f->tag()->artist()); - f->tag()->setArtist("The Artist"); - f->save(); - delete f; - - f = new DSDIFF::File(newname.c_str()); - CPPUNIT_ASSERT_EQUAL(String("The Artist"), f->tag()->artist()); - delete f; + { + DSDIFF::File f(newname.c_str()); + CPPUNIT_ASSERT_EQUAL(String(""), f.tag()->artist()); + f.tag()->setArtist("The Artist"); + f.save(); + } + { + DSDIFF::File f(newname.c_str()); + CPPUNIT_ASSERT_EQUAL(String("The Artist"), f.tag()->artist()); + } } void testSaveID3v2() @@ -77,7 +100,7 @@ public: { DSDIFF::File f(newname.c_str()); CPPUNIT_ASSERT(!f.hasID3v2Tag()); - f.tag()->setTitle(L"TitleXXX"); + f.ID3v2Tag(true)->setTitle(L"TitleXXX"); f.save(); CPPUNIT_ASSERT(f.hasID3v2Tag()); } @@ -117,7 +140,8 @@ public: ScopedFileCopy copy("empty10ms", ".dff"); { DSDIFF::File f(copy.fileName().c_str()); - f.tag()->setArtist("X"); + f.ID3v2Tag(true)->setArtist("X"); + f.DIINTag(true)->setArtist("Y"); f.save(); } { @@ -183,6 +207,7 @@ public: { DSDIFF::File f(newname.c_str()); + CPPUNIT_ASSERT_EQUAL(static_cast(7186), f.length()); CPPUNIT_ASSERT_EQUAL(String(""), f.tag()->title()); f.tag()->setTitle("NEW TITLE"); f.save(); @@ -190,14 +215,21 @@ public: f.tag()->setTitle("NEW TITLE 2"); f.save(); CPPUNIT_ASSERT_EQUAL(String("NEW TITLE 2"), f.tag()->title()); - CPPUNIT_ASSERT_EQUAL(static_cast(8252), f.length()); + CPPUNIT_ASSERT_EQUAL(static_cast(8292), f.length()); f.save(); - CPPUNIT_ASSERT_EQUAL(static_cast(8252), f.length()); + CPPUNIT_ASSERT_EQUAL(static_cast(8292), f.length()); } { DSDIFF::File f(newname.c_str()); CPPUNIT_ASSERT_EQUAL(String("NEW TITLE 2"), f.tag()->title()); + f.strip(); + CPPUNIT_ASSERT_EQUAL(static_cast(7186), f.length()); } + + // Check if file without tags is same as original empty file + const ByteVector dsfData = PlainFile(TEST_FILE_PATH_C("empty10ms.dff")).readAll(); + const ByteVector fileData = PlainFile(newname.c_str()).readAll(); + CPPUNIT_ASSERT(dsfData == fileData); } };