mirror of
https://github.com/taglib/taglib.git
synced 2026-04-11 00:22:43 -04:00
Merge branch 'master' into merge-master-to-taglib2
# Conflicts: # taglib/ape/apefile.cpp # taglib/ape/apefile.h # taglib/fileref.cpp # taglib/flac/flacfile.cpp # taglib/flac/flacfile.h # taglib/mpc/mpcfile.cpp # taglib/mpc/mpcfile.h # taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp # taglib/mpeg/id3v2/id3v2frame.cpp # taglib/tagunion.cpp # taglib/toolkit/tiostream.cpp # taglib/trueaudio/trueaudiofile.cpp # taglib/trueaudio/trueaudiofile.h # taglib/wavpack/wavpackfile.cpp # taglib/wavpack/wavpackfile.h # tests/test_fileref.cpp # tests/test_id3v2.cpp
This commit is contained in:
2
NEWS
2
NEWS
@ -1,11 +1,13 @@
|
||||
==========================
|
||||
|
||||
* New API for creating FileRef from IOStream.
|
||||
* Added support for ID3v2 PCST and WFED frames.
|
||||
* Added String::clear().
|
||||
* Better handling of duplicate ID3v2 tags in all kinds of files.
|
||||
* Better handling of duplicate tags in WAV files.
|
||||
* Fixed crash when calling File::properties() after strip().
|
||||
* Fixed possible file corruptions when saving ASF files.
|
||||
* Fixed updating the comment field of Vorbis comments.
|
||||
* Marked ByteVector::null and ByteVector::isNull() deprecated.
|
||||
* Marked String::null and ByteVector::isNull() deprecated.
|
||||
* Many smaller bug fixes and performance improvements.
|
||||
|
||||
@ -362,6 +362,7 @@ set(tag_LIB_SRCS
|
||||
tagunion.cpp
|
||||
fileref.cpp
|
||||
audioproperties.cpp
|
||||
tagutils.cpp
|
||||
)
|
||||
|
||||
add_library(tag ${tag_LIB_SRCS} ${tag_HDRS})
|
||||
|
||||
@ -38,9 +38,9 @@
|
||||
#include <id3v1tag.h>
|
||||
#include <id3v2header.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "apefile.h"
|
||||
|
||||
#include "apetag.h"
|
||||
#include "apefooter.h"
|
||||
|
||||
@ -248,7 +248,7 @@ void APE::File::read(bool readProperties)
|
||||
{
|
||||
// Look for an ID3v2 tag
|
||||
|
||||
d->ID3v2Location = findID3v2();
|
||||
d->ID3v2Location = Utils::findID3v2(this);
|
||||
|
||||
if(d->ID3v2Location >= 0) {
|
||||
seek(d->ID3v2Location);
|
||||
@ -259,7 +259,7 @@ void APE::File::read(bool readProperties)
|
||||
|
||||
// Look for an ID3v1 tag
|
||||
|
||||
d->ID3v1Location = findID3v1();
|
||||
d->ID3v1Location = Utils::findID3v1(this);
|
||||
|
||||
if(d->ID3v1Location >= 0) {
|
||||
d->tag.set(ApeID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
||||
@ -268,7 +268,7 @@ void APE::File::read(bool readProperties)
|
||||
|
||||
// Look for an APE tag
|
||||
|
||||
d->APELocation = findAPE();
|
||||
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
|
||||
|
||||
if(d->APELocation >= 0) {
|
||||
d->tag.set(ApeAPEIndex, new APE::Tag(this, d->APELocation));
|
||||
@ -304,48 +304,3 @@ void APE::File::read(bool readProperties)
|
||||
d->properties = new AudioProperties(this, streamLength);
|
||||
}
|
||||
}
|
||||
|
||||
offset_t APE::File::findAPE()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
if(d->hasID3v1)
|
||||
seek(-160, End);
|
||||
else
|
||||
seek(-32, End);
|
||||
|
||||
offset_t p = tell();
|
||||
|
||||
if(readBlock(8) == APE::Tag::fileIdentifier())
|
||||
return p;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset_t APE::File::findID3v1()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
seek(-128, End);
|
||||
offset_t p = tell();
|
||||
|
||||
if(readBlock(3) == ID3v1::Tag::fileIdentifier())
|
||||
return p;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset_t APE::File::findID3v2()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
seek(0);
|
||||
|
||||
if(readBlock(3) == ID3v2::Header::fileIdentifier())
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -206,9 +206,6 @@ namespace TagLib {
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties);
|
||||
offset_t findAPE();
|
||||
offset_t findID3v1();
|
||||
offset_t findID3v2();
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
|
||||
@ -197,7 +197,7 @@ String APE::Item::toString() const
|
||||
if(d->type == Text && !isEmpty())
|
||||
return d->text.front();
|
||||
else
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
bool APE::Item::isEmpty() const
|
||||
|
||||
@ -81,35 +81,35 @@ ByteVector APE::Tag::fileIdentifier()
|
||||
String APE::Tag::title() const
|
||||
{
|
||||
if(d->itemListMap["TITLE"].isEmpty())
|
||||
return String::null;
|
||||
return String();
|
||||
return d->itemListMap["TITLE"].values().toString();
|
||||
}
|
||||
|
||||
String APE::Tag::artist() const
|
||||
{
|
||||
if(d->itemListMap["ARTIST"].isEmpty())
|
||||
return String::null;
|
||||
return String();
|
||||
return d->itemListMap["ARTIST"].values().toString();
|
||||
}
|
||||
|
||||
String APE::Tag::album() const
|
||||
{
|
||||
if(d->itemListMap["ALBUM"].isEmpty())
|
||||
return String::null;
|
||||
return String();
|
||||
return d->itemListMap["ALBUM"].values().toString();
|
||||
}
|
||||
|
||||
String APE::Tag::comment() const
|
||||
{
|
||||
if(d->itemListMap["COMMENT"].isEmpty())
|
||||
return String::null;
|
||||
return String();
|
||||
return d->itemListMap["COMMENT"].values().toString();
|
||||
}
|
||||
|
||||
String APE::Tag::genre() const
|
||||
{
|
||||
if(d->itemListMap["GENRE"].isEmpty())
|
||||
return String::null;
|
||||
return String();
|
||||
return d->itemListMap["GENRE"].values().toString();
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ PropertyMap APE::Tag::properties() const
|
||||
String tagName = it->first.upper();
|
||||
// if the item is Binary or Locator, or if the key is an invalid string,
|
||||
// add to unsupportedData
|
||||
if(it->second.type() != Item::Text || tagName.isNull())
|
||||
if(it->second.type() != Item::Text || tagName.isEmpty())
|
||||
properties.unsupportedData().append(it->first);
|
||||
else {
|
||||
// Some tags need to be handled specially
|
||||
@ -225,7 +225,7 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
|
||||
for(; remIt != itemListMap().end(); ++remIt) {
|
||||
String key = remIt->first.upper();
|
||||
// only remove if a) key is valid, b) type is text, c) key not contained in new properties
|
||||
if(!key.isNull() && remIt->second.type() == APE::Item::Text && !properties.contains(key))
|
||||
if(!key.isEmpty() && remIt->second.type() == APE::Item::Text && !properties.contains(key))
|
||||
toRemove.append(remIt->first);
|
||||
}
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ String ASF::Tag::album() const
|
||||
{
|
||||
if(d->attributeListMap.contains("WM/AlbumTitle"))
|
||||
return d->attributeListMap["WM/AlbumTitle"][0].toString();
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String ASF::Tag::copyright() const
|
||||
@ -107,7 +107,7 @@ String ASF::Tag::genre() const
|
||||
{
|
||||
if(d->attributeListMap.contains("WM/Genre"))
|
||||
return d->attributeListMap["WM/Genre"][0].toString();
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
void ASF::Tag::setTitle(const String &value)
|
||||
@ -329,16 +329,16 @@ PropertyMap ASF::Tag::setProperties(const PropertyMap &props)
|
||||
for(; it != origProps.end(); ++it) {
|
||||
if(!props.contains(it->first) || props[it->first].isEmpty()) {
|
||||
if(it->first == "TITLE") {
|
||||
d->title = String::null;
|
||||
d->title.clear();
|
||||
}
|
||||
else if(it->first == "ARTIST") {
|
||||
d->artist = String::null;
|
||||
d->artist.clear();
|
||||
}
|
||||
else if(it->first == "COMMENT") {
|
||||
d->comment = String::null;
|
||||
d->comment.clear();
|
||||
}
|
||||
else if(it->first == "COPYRIGHT") {
|
||||
d->copyright = String::null;
|
||||
d->copyright.clear();
|
||||
}
|
||||
else {
|
||||
d->attributeListMap.erase(reverseKeyMap[it->first]);
|
||||
|
||||
@ -27,10 +27,10 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "tfile.h"
|
||||
#include "tstring.h"
|
||||
#include "tdebug.h"
|
||||
#include "tsmartptr.h"
|
||||
#include <tfile.h>
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
#include <tsmartptr.h>
|
||||
|
||||
#include "fileref.h"
|
||||
#include "asffile.h"
|
||||
@ -58,91 +58,129 @@ using namespace TagLib;
|
||||
namespace
|
||||
{
|
||||
typedef List<const FileRef::FileTypeResolver *> ResolverList;
|
||||
typedef ResolverList::ConstIterator ResolverConstIterator;
|
||||
|
||||
ResolverList fileTypeResolvers;
|
||||
|
||||
SHARED_PTR<File> create(
|
||||
FileName fileName,
|
||||
bool readAudioProperties,
|
||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
||||
// Templatized internal functions. T should be String or IOStream*.
|
||||
|
||||
template <typename T>
|
||||
inline FileName toFileName(T arg)
|
||||
{
|
||||
SHARED_PTR<File> file;
|
||||
for(ResolverConstIterator it = fileTypeResolvers.begin(); it != fileTypeResolvers.end(); ++it)
|
||||
{
|
||||
file.reset((*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
// Should never be called.
|
||||
}
|
||||
|
||||
template <>
|
||||
inline FileName toFileName<IOStream *>(IOStream *arg)
|
||||
{
|
||||
return arg->name();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline FileName toFileName<FileName>(FileName arg)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline File *resolveFileType(T arg, bool readProperties,
|
||||
AudioProperties::ReadStyle style)
|
||||
{
|
||||
// Should never be called.
|
||||
}
|
||||
|
||||
template <>
|
||||
inline File *resolveFileType<IOStream *>(IOStream *arg, bool readProperties,
|
||||
AudioProperties::ReadStyle style)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline File *resolveFileType<FileName>(FileName arg, bool readProperties,
|
||||
AudioProperties::ReadStyle style)
|
||||
{
|
||||
ResolverList::ConstIterator it = fileTypeResolvers.begin();
|
||||
for(; it != fileTypeResolvers.end(); ++it) {
|
||||
File *file = (*it)->createFile(arg, readProperties, style);
|
||||
if(file)
|
||||
return file;
|
||||
}
|
||||
|
||||
String ext;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
File* createInternal(T arg, bool readAudioProperties,
|
||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
||||
{
|
||||
File *file = resolveFileType(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(file)
|
||||
return file;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
String s = fileName.toString();
|
||||
|
||||
const String s = toFileName(arg).toString();
|
||||
#else
|
||||
|
||||
String s = fileName;
|
||||
|
||||
const String s(toFileName(arg));
|
||||
#endif
|
||||
|
||||
const size_t pos = s.rfind(".");
|
||||
if(pos != String::npos())
|
||||
ext = s.substr(pos + 1).upper();
|
||||
}
|
||||
String ext;
|
||||
const int pos = s.rfind(".");
|
||||
if(pos != -1)
|
||||
ext = s.substr(pos + 1).upper();
|
||||
|
||||
// If this list is updated, the method defaultFileExtensions() should also be
|
||||
// updated. However at some point that list should be created at the same time
|
||||
// that a default file type resolver is created.
|
||||
|
||||
if(!ext.isEmpty()) {
|
||||
if(ext == "MP3")
|
||||
file.reset(new MPEG::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "OGG")
|
||||
file.reset(new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "OGA") {
|
||||
/* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
|
||||
file.reset(new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
if(!file->isValid())
|
||||
file.reset(new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
}
|
||||
else if(ext == "FLAC")
|
||||
file.reset(new FLAC::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "MPC")
|
||||
file.reset(new MPC::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "WV")
|
||||
file.reset(new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "SPX")
|
||||
file.reset(new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "OPUS")
|
||||
file.reset(new Ogg::Opus::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "TTA")
|
||||
file.reset(new TrueAudio::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2")
|
||||
file.reset(new MP4::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "WMA" || ext == "ASF")
|
||||
file.reset(new ASF::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
|
||||
file.reset(new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "WAV")
|
||||
file.reset(new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "APE")
|
||||
file.reset(new APE::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
// module, nst and wow are possible but uncommon extensions
|
||||
else if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
|
||||
file.reset(new Mod::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "S3M")
|
||||
file.reset(new S3M::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "IT")
|
||||
file.reset(new IT::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "XM")
|
||||
file.reset(new XM::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
else if(ext == "DSF")
|
||||
file.reset(new DSF::File(fileName, readAudioProperties, audioPropertiesStyle));
|
||||
}
|
||||
if(ext.isEmpty())
|
||||
return 0;
|
||||
|
||||
return file;
|
||||
if(ext == "MP3")
|
||||
return new MPEG::File(arg, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "OGG")
|
||||
return new Ogg::Vorbis::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "OGA") {
|
||||
/* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
|
||||
File *file = new Ogg::FLAC::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(file->isValid())
|
||||
return file;
|
||||
delete file;
|
||||
return new Ogg::Vorbis::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
}
|
||||
if(ext == "FLAC")
|
||||
return new FLAC::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "MPC")
|
||||
return new MPC::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "WV")
|
||||
return new WavPack::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "SPX")
|
||||
return new Ogg::Speex::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "OPUS")
|
||||
return new Ogg::Opus::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "TTA")
|
||||
return new TrueAudio::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2")
|
||||
return new MP4::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "WMA" || ext == "ASF")
|
||||
return new ASF::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
|
||||
return new RIFF::AIFF::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "WAV")
|
||||
return new RIFF::WAV::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "APE")
|
||||
return new APE::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
// module, nst and wow are possible but uncommon extensions
|
||||
if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
|
||||
return new Mod::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "S3M")
|
||||
return new S3M::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "IT")
|
||||
return new IT::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "XM")
|
||||
return new XM::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if (ext == "DSF")
|
||||
return new DSF::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,8 +208,14 @@ FileRef::FileRef() :
|
||||
{
|
||||
}
|
||||
|
||||
FileRef::FileRef(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle style) :
|
||||
d(new FileRefPrivate(create(fileName, readAudioProperties, style)))
|
||||
FileRef::FileRef(FileName fileName, bool readAudioProperties,
|
||||
AudioProperties::ReadStyle audioPropertiesStyle) :
|
||||
d(new FileRefPrivate(createInternal(fileName, readAudioProperties, audioPropertiesStyle)))
|
||||
{
|
||||
}
|
||||
|
||||
FileRef::FileRef(IOStream* stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) :
|
||||
d(new FileRefPrivate(createInternal(stream, readAudioProperties, audioPropertiesStyle)))
|
||||
{
|
||||
}
|
||||
|
||||
@ -306,16 +350,23 @@ bool FileRef::isNull() const
|
||||
|
||||
FileRef &FileRef::operator=(const FileRef &ref)
|
||||
{
|
||||
*d = *ref.d;
|
||||
FileRef(ref).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void FileRef::swap(FileRef &ref)
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
swap(d, ref.d);
|
||||
}
|
||||
|
||||
bool FileRef::operator==(const FileRef &ref) const
|
||||
{
|
||||
return (d->file == ref.d->file);
|
||||
return (ref.d->file == d->file);
|
||||
}
|
||||
|
||||
bool FileRef::operator!=(const FileRef &ref) const
|
||||
{
|
||||
return (d->file != ref.d->file);
|
||||
return (ref.d->file != d->file);
|
||||
}
|
||||
|
||||
@ -128,6 +128,20 @@ namespace TagLib {
|
||||
AudioProperties::ReadStyle
|
||||
audioPropertiesStyle = AudioProperties::Average);
|
||||
|
||||
/*!
|
||||
* Construct a FileRef from an opened \a IOStream. If \a readAudioProperties is true then
|
||||
* the audio properties will be read using \a audioPropertiesStyle. If
|
||||
* \a readAudioProperties is false then \a audioPropertiesStyle will be
|
||||
* ignored.
|
||||
*
|
||||
* Also see the note in the class documentation about why you may not want to
|
||||
* use this method in your application.
|
||||
*/
|
||||
explicit FileRef(IOStream* stream,
|
||||
bool readAudioProperties = true,
|
||||
AudioProperties::ReadStyle
|
||||
audioPropertiesStyle = AudioProperties::Average);
|
||||
|
||||
/*!
|
||||
* Construct a FileRef using \a file. The FileRef now takes ownership of the
|
||||
* pointer and will delete the File when it passes out of scope.
|
||||
@ -271,6 +285,11 @@ namespace TagLib {
|
||||
*/
|
||||
FileRef &operator=(const FileRef &ref);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the FileRef by the content of \a ref.
|
||||
*/
|
||||
void swap(FileRef &ref);
|
||||
|
||||
/*!
|
||||
* Returns true if this FileRef and \a ref point to the same File object.
|
||||
*/
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <tdebug.h>
|
||||
#include <tagunion.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include <id3v2header.h>
|
||||
#include <id3v2tag.h>
|
||||
@ -330,7 +331,7 @@ void FLAC::File::read(bool readProperties)
|
||||
{
|
||||
// Look for an ID3v2 tag
|
||||
|
||||
d->ID3v2Location = findID3v2();
|
||||
d->ID3v2Location = Utils::findID3v2(this);
|
||||
|
||||
if(d->ID3v2Location >= 0) {
|
||||
|
||||
@ -346,7 +347,7 @@ void FLAC::File::read(bool readProperties)
|
||||
|
||||
// Look for an ID3v1 tag
|
||||
|
||||
d->ID3v1Location = findID3v1();
|
||||
d->ID3v1Location = Utils::findID3v1(this);
|
||||
|
||||
if(d->ID3v1Location >= 0) {
|
||||
d->tag.set(FlacID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
||||
@ -507,30 +508,3 @@ void FLAC::File::scan()
|
||||
|
||||
d->scanned = true;
|
||||
}
|
||||
|
||||
offset_t FLAC::File::findID3v1()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
seek(-128, End);
|
||||
offset_t p = tell();
|
||||
|
||||
if(readBlock(3) == ID3v1::Tag::fileIdentifier())
|
||||
return p;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset_t FLAC::File::findID3v2()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
seek(0);
|
||||
|
||||
if(readBlock(3) == ID3v2::Header::fileIdentifier())
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -257,8 +257,6 @@ namespace TagLib {
|
||||
|
||||
void read(bool readProperties);
|
||||
void scan();
|
||||
offset_t findID3v2();
|
||||
offset_t findID3v1();
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
|
||||
@ -108,7 +108,7 @@ bool IT::File::save()
|
||||
if(i < lines.size())
|
||||
writeString(lines[i], 25);
|
||||
else
|
||||
writeString(String::null, 25);
|
||||
writeString(String(), 25);
|
||||
writeByte(0);
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ bool IT::File::save()
|
||||
if((TagLib::uint)(i + instrumentCount) < lines.size())
|
||||
writeString(lines[i + instrumentCount], 25);
|
||||
else
|
||||
writeString(String::null, 25);
|
||||
writeString(String(), 25);
|
||||
writeByte(0);
|
||||
}
|
||||
|
||||
|
||||
@ -89,7 +89,7 @@ bool Mod::File::save()
|
||||
}
|
||||
|
||||
for(uint i = n; i < d->properties.instrumentCount(); ++ i) {
|
||||
writeString(String::null, 22);
|
||||
writeString(String(), 22);
|
||||
seek(8, Current);
|
||||
}
|
||||
return true;
|
||||
|
||||
@ -55,12 +55,12 @@ String Mod::Tag::title() const
|
||||
|
||||
String Mod::Tag::artist() const
|
||||
{
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String Mod::Tag::album() const
|
||||
{
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String Mod::Tag::comment() const
|
||||
@ -70,7 +70,7 @@ String Mod::Tag::comment() const
|
||||
|
||||
String Mod::Tag::genre() const
|
||||
{
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
TagLib::uint Mod::Tag::year() const
|
||||
@ -128,7 +128,7 @@ PropertyMap Mod::Tag::properties() const
|
||||
PropertyMap properties;
|
||||
properties["TITLE"] = d->title;
|
||||
properties["COMMENT"] = d->comment;
|
||||
if(!(d->trackerName.isNull()))
|
||||
if(!(d->trackerName.isEmpty()))
|
||||
properties["TRACKERNAME"] = d->trackerName;
|
||||
return properties;
|
||||
}
|
||||
@ -142,19 +142,19 @@ PropertyMap Mod::Tag::setProperties(const PropertyMap &origProps)
|
||||
d->title = properties["TITLE"].front();
|
||||
oneValueSet.append("TITLE");
|
||||
} else
|
||||
d->title = String::null;
|
||||
d->title.clear();
|
||||
|
||||
if(properties.contains("COMMENT")) {
|
||||
d->comment = properties["COMMENT"].front();
|
||||
oneValueSet.append("COMMENT");
|
||||
} else
|
||||
d->comment = String::null;
|
||||
d->comment.clear();
|
||||
|
||||
if(properties.contains("TRACKERNAME")) {
|
||||
d->trackerName = properties["TRACKERNAME"].front();
|
||||
oneValueSet.append("TRACKERNAME");
|
||||
} else
|
||||
d->trackerName = String::null;
|
||||
d->trackerName.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.
|
||||
|
||||
@ -686,7 +686,7 @@ MP4::Tag::title() const
|
||||
{
|
||||
if(d->items.contains("\251nam"))
|
||||
return d->items["\251nam"].toStringList().toString(", ");
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String
|
||||
@ -694,7 +694,7 @@ MP4::Tag::artist() const
|
||||
{
|
||||
if(d->items.contains("\251ART"))
|
||||
return d->items["\251ART"].toStringList().toString(", ");
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String
|
||||
@ -702,7 +702,7 @@ MP4::Tag::album() const
|
||||
{
|
||||
if(d->items.contains("\251alb"))
|
||||
return d->items["\251alb"].toStringList().toString(", ");
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String
|
||||
@ -710,7 +710,7 @@ MP4::Tag::comment() const
|
||||
{
|
||||
if(d->items.contains("\251cmt"))
|
||||
return d->items["\251cmt"].toStringList().toString(", ");
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String
|
||||
@ -718,7 +718,7 @@ MP4::Tag::genre() const
|
||||
{
|
||||
if(d->items.contains("\251gen"))
|
||||
return d->items["\251gen"].toStringList().toString(", ");
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include <tagunion.h>
|
||||
#include <tdebug.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "mpcfile.h"
|
||||
#include "id3v1tag.h"
|
||||
@ -256,7 +257,7 @@ void MPC::File::read(bool readProperties)
|
||||
{
|
||||
// Look for an ID3v1 tag
|
||||
|
||||
d->ID3v1Location = findID3v1();
|
||||
d->ID3v1Location = Utils::findID3v1(this);
|
||||
|
||||
if(d->ID3v1Location >= 0) {
|
||||
d->tag.set(MPCID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
||||
@ -265,7 +266,7 @@ void MPC::File::read(bool readProperties)
|
||||
|
||||
// Look for an APE tag
|
||||
|
||||
d->APELocation = findAPE();
|
||||
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
|
||||
|
||||
if(d->APELocation >= 0) {
|
||||
d->tag.set(MPCAPEIndex, new APE::Tag(this, d->APELocation));
|
||||
@ -280,7 +281,7 @@ void MPC::File::read(bool readProperties)
|
||||
|
||||
// Look for an ID3v2 tag
|
||||
|
||||
d->ID3v2Location = findID3v2();
|
||||
d->ID3v2Location = Utils::findID3v2(this);
|
||||
|
||||
if(d->ID3v2Location >= 0) {
|
||||
seek(d->ID3v2Location);
|
||||
@ -313,48 +314,3 @@ void MPC::File::read(bool readProperties)
|
||||
d->properties = new AudioProperties(this, streamLength);
|
||||
}
|
||||
}
|
||||
|
||||
offset_t MPC::File::findAPE()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
if(d->hasID3v1)
|
||||
seek(-160, End);
|
||||
else
|
||||
seek(-32, End);
|
||||
|
||||
offset_t p = tell();
|
||||
|
||||
if(readBlock(8) == APE::Tag::fileIdentifier())
|
||||
return p;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset_t MPC::File::findID3v1()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
seek(-128, End);
|
||||
offset_t p = tell();
|
||||
|
||||
if(readBlock(3) == ID3v1::Tag::fileIdentifier())
|
||||
return p;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset_t MPC::File::findID3v2()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
seek(0);
|
||||
|
||||
if(readBlock(3) == ID3v2::Header::fileIdentifier())
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -213,9 +213,6 @@ namespace TagLib {
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties);
|
||||
offset_t findAPE();
|
||||
offset_t findID3v1();
|
||||
offset_t findID3v2();
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
|
||||
@ -182,7 +182,7 @@ void ID3v1::Tag::setGenre(const String &s)
|
||||
|
||||
void ID3v1::Tag::setYear(TagLib::uint i)
|
||||
{
|
||||
d->year = i > 0 ? String::number(i) : String::null;
|
||||
d->year = i > 0 ? String::number(i) : String();
|
||||
}
|
||||
|
||||
void ID3v1::Tag::setTrack(TagLib::uint i)
|
||||
|
||||
@ -116,8 +116,6 @@ PropertyMap CommentsFrame::asProperties() const
|
||||
PropertyMap map;
|
||||
if(key.isEmpty() || key == "COMMENT")
|
||||
map.insert("COMMENT", text());
|
||||
else if(key.isNull())
|
||||
map.unsupportedData().append(L"COMM/" + description());
|
||||
else
|
||||
map.insert("COMMENT:" + key, text());
|
||||
return map;
|
||||
@ -164,7 +162,7 @@ void CommentsFrame::parseFields(const ByteVector &data)
|
||||
} else {
|
||||
d->description = String(l.front(), d->textEncoding);
|
||||
d->text = String(l.back(), d->textEncoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -159,7 +159,7 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
size_t pos = 6;
|
||||
|
||||
d->description = readStringField(data, d->textEncoding, pos);
|
||||
if(d->description.isNull())
|
||||
if(d->description.isEmpty())
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -190,7 +190,7 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
}
|
||||
}
|
||||
String text = readStringField(data, enc, pos);
|
||||
if(text.isNull() || pos + 4 > end)
|
||||
if(text.isEmpty() || pos + 4 > end)
|
||||
return;
|
||||
|
||||
uint time = data.toUInt32BE(pos);
|
||||
|
||||
@ -214,7 +214,7 @@ void TableOfContentsFrame::removeEmbeddedFrames(const ByteVector &id)
|
||||
|
||||
String TableOfContentsFrame::toString() const
|
||||
{
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
PropertyMap TableOfContentsFrame::asProperties() const
|
||||
|
||||
@ -295,7 +295,7 @@ PropertyMap TextIdentificationFrame::makeTMCLProperties() const
|
||||
StringList l = fieldList();
|
||||
for(StringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
||||
String instrument = it->upper();
|
||||
if(instrument.isNull()) {
|
||||
if(instrument.isEmpty()) {
|
||||
// instrument is not a valid key -> frame unsupported
|
||||
map.clear();
|
||||
map.unsupportedData().append(frameID());
|
||||
@ -315,8 +315,8 @@ UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding)
|
||||
d(0)
|
||||
{
|
||||
StringList l;
|
||||
l.append(String::null);
|
||||
l.append(String::null);
|
||||
l.append(String());
|
||||
l.append(String());
|
||||
setText(l);
|
||||
}
|
||||
|
||||
@ -344,7 +344,7 @@ String UserTextIdentificationFrame::description() const
|
||||
{
|
||||
return !TextIdentificationFrame::fieldList().isEmpty()
|
||||
? TextIdentificationFrame::fieldList().front()
|
||||
: String::null;
|
||||
: String();
|
||||
}
|
||||
|
||||
StringList UserTextIdentificationFrame::fieldList() const
|
||||
@ -357,7 +357,7 @@ StringList UserTextIdentificationFrame::fieldList() const
|
||||
void UserTextIdentificationFrame::setText(const String &text)
|
||||
{
|
||||
if(description().isEmpty())
|
||||
setDescription(String::null);
|
||||
setDescription(String());
|
||||
|
||||
TextIdentificationFrame::setText(StringList(description()).append(text));
|
||||
}
|
||||
@ -365,7 +365,7 @@ void UserTextIdentificationFrame::setText(const String &text)
|
||||
void UserTextIdentificationFrame::setText(const StringList &fields)
|
||||
{
|
||||
if(description().isEmpty())
|
||||
setDescription(String::null);
|
||||
setDescription(String());
|
||||
|
||||
TextIdentificationFrame::setText(StringList(description()).append(fields));
|
||||
}
|
||||
@ -420,7 +420,7 @@ void UserTextIdentificationFrame::checkFields()
|
||||
const size_t fields = fieldList().size();
|
||||
|
||||
if(fields == 0)
|
||||
setDescription(String::null);
|
||||
setDescription(String());
|
||||
if(fields <= 1)
|
||||
setText(String::null);
|
||||
setText(String());
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ void UniqueFileIdentifierFrame::setIdentifier(const ByteVector &v)
|
||||
|
||||
String UniqueFileIdentifierFrame::toString() const
|
||||
{
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
PropertyMap UniqueFileIdentifierFrame::asProperties() const
|
||||
|
||||
@ -51,7 +51,7 @@ UnknownFrame::~UnknownFrame()
|
||||
|
||||
String UnknownFrame::toString() const
|
||||
{
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
ByteVector UnknownFrame::data() const
|
||||
|
||||
@ -119,8 +119,6 @@ PropertyMap UnsynchronizedLyricsFrame::asProperties() const
|
||||
String key = description().upper();
|
||||
if(key.isEmpty() || key.upper() == "LYRICS")
|
||||
map.insert("LYRICS", text());
|
||||
else if(key.isNull())
|
||||
map.unsupportedData().append(L"USLT/" + description());
|
||||
else
|
||||
map.insert("LYRICS:" + key, text());
|
||||
return map;
|
||||
@ -164,7 +162,7 @@ void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
} else {
|
||||
d->description = String(l.front(), d->textEncoding);
|
||||
d->text = String(l.back(), d->textEncoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -159,8 +159,6 @@ PropertyMap UserUrlLinkFrame::asProperties() const
|
||||
String key = description().upper();
|
||||
if(key.isEmpty() || key.upper() == "URL")
|
||||
map.insert("URL", url());
|
||||
else if(key.isNull())
|
||||
map.unsupportedData().append(L"WXXX/" + description());
|
||||
else
|
||||
map.insert("URL:" + key, url());
|
||||
return map;
|
||||
|
||||
@ -311,7 +311,7 @@ String Frame::readStringField(const ByteVector &data, String::Type encoding, siz
|
||||
|
||||
const size_t end = data.find(delimiter, position, delimiter.size());
|
||||
if(end == ByteVector::npos() || end < position)
|
||||
return String::null;
|
||||
return String();
|
||||
|
||||
String str;
|
||||
if(encoding == String::Latin1)
|
||||
|
||||
@ -504,7 +504,7 @@ void FrameFactory::updateGenre(TextIdentificationFrame *frame) const
|
||||
}
|
||||
|
||||
if(newfields.isEmpty())
|
||||
fields.append(String::null);
|
||||
fields.append(String());
|
||||
|
||||
frame->setText(newfields);
|
||||
|
||||
|
||||
@ -139,21 +139,21 @@ String ID3v2::Tag::title() const
|
||||
{
|
||||
if(!d->frameListMap["TIT2"].isEmpty())
|
||||
return d->frameListMap["TIT2"].front()->toString();
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String ID3v2::Tag::artist() const
|
||||
{
|
||||
if(!d->frameListMap["TPE1"].isEmpty())
|
||||
return d->frameListMap["TPE1"].front()->toString();
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String ID3v2::Tag::album() const
|
||||
{
|
||||
if(!d->frameListMap["TALB"].isEmpty())
|
||||
return d->frameListMap["TALB"].front()->toString();
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String ID3v2::Tag::comment() const
|
||||
@ -161,7 +161,7 @@ String ID3v2::Tag::comment() const
|
||||
const FrameList &comments = d->frameListMap["COMM"];
|
||||
|
||||
if(comments.isEmpty())
|
||||
return String::null;
|
||||
return String();
|
||||
|
||||
for(FrameList::ConstIterator it = comments.begin(); it != comments.end(); ++it)
|
||||
{
|
||||
@ -183,7 +183,7 @@ String ID3v2::Tag::genre() const
|
||||
if(d->frameListMap["TCON"].isEmpty() ||
|
||||
!dynamic_cast<TextIdentificationFrame *>(d->frameListMap["TCON"].front()))
|
||||
{
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
// ID3v2.4 lists genres as the fields in its frames field list. If the field
|
||||
|
||||
@ -62,21 +62,21 @@ Ogg::XiphComment::~XiphComment()
|
||||
String Ogg::XiphComment::title() const
|
||||
{
|
||||
if(d->fieldListMap["TITLE"].isEmpty())
|
||||
return String::null;
|
||||
return String();
|
||||
return d->fieldListMap["TITLE"].toString();
|
||||
}
|
||||
|
||||
String Ogg::XiphComment::artist() const
|
||||
{
|
||||
if(d->fieldListMap["ARTIST"].isEmpty())
|
||||
return String::null;
|
||||
return String();
|
||||
return d->fieldListMap["ARTIST"].toString();
|
||||
}
|
||||
|
||||
String Ogg::XiphComment::album() const
|
||||
{
|
||||
if(d->fieldListMap["ALBUM"].isEmpty())
|
||||
return String::null;
|
||||
return String();
|
||||
return d->fieldListMap["ALBUM"].toString();
|
||||
}
|
||||
|
||||
@ -92,13 +92,13 @@ String Ogg::XiphComment::comment() const
|
||||
return d->fieldListMap["COMMENT"].toString();
|
||||
}
|
||||
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
|
||||
String Ogg::XiphComment::genre() const
|
||||
{
|
||||
if(d->fieldListMap["GENRE"].isEmpty())
|
||||
return String::null;
|
||||
return String();
|
||||
return d->fieldListMap["GENRE"].toString();
|
||||
}
|
||||
|
||||
@ -137,7 +137,14 @@ void Ogg::XiphComment::setAlbum(const String &s)
|
||||
|
||||
void Ogg::XiphComment::setComment(const String &s)
|
||||
{
|
||||
addField(d->commentField.isEmpty() ? "DESCRIPTION" : d->commentField, s);
|
||||
if(d->commentField.isEmpty()) {
|
||||
if(!d->fieldListMap["DESCRIPTION"].isEmpty())
|
||||
d->commentField = "DESCRIPTION";
|
||||
else
|
||||
d->commentField = "COMMENT";
|
||||
}
|
||||
|
||||
addField(d->commentField, s);
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::setGenre(const String &s)
|
||||
|
||||
@ -124,7 +124,7 @@ bool S3M::File::save()
|
||||
if(i < lines.size())
|
||||
writeString(lines[i], 27);
|
||||
else
|
||||
writeString(String::null, 27);
|
||||
writeString(String(), 27);
|
||||
// string terminating NUL is not optional:
|
||||
writeByte(0);
|
||||
}
|
||||
|
||||
@ -58,15 +58,15 @@ bool Tag::isEmpty() const
|
||||
PropertyMap Tag::properties() const
|
||||
{
|
||||
PropertyMap map;
|
||||
if(!(title().isNull()))
|
||||
if(!(title().isEmpty()))
|
||||
map["TITLE"].append(title());
|
||||
if(!(artist().isNull()))
|
||||
if(!(artist().isEmpty()))
|
||||
map["ARTIST"].append(artist());
|
||||
if(!(album().isNull()))
|
||||
if(!(album().isEmpty()))
|
||||
map["ALBUM"].append(album());
|
||||
if(!(comment().isNull()))
|
||||
if(!(comment().isEmpty()))
|
||||
map["COMMENT"].append(comment());
|
||||
if(!(genre().isNull()))
|
||||
if(!(genre().isEmpty()))
|
||||
map["GENRE"].append(genre());
|
||||
if(!(year() == 0))
|
||||
map["DATE"].append(String::number(year()));
|
||||
@ -89,31 +89,31 @@ PropertyMap Tag::setProperties(const PropertyMap &origProps)
|
||||
setTitle(properties["TITLE"].front());
|
||||
oneValueSet.append("TITLE");
|
||||
} else
|
||||
setTitle(String::null);
|
||||
setTitle(String());
|
||||
|
||||
if(properties.contains("ARTIST")) {
|
||||
setArtist(properties["ARTIST"].front());
|
||||
oneValueSet.append("ARTIST");
|
||||
} else
|
||||
setArtist(String::null);
|
||||
setArtist(String());
|
||||
|
||||
if(properties.contains("ALBUM")) {
|
||||
setAlbum(properties["ALBUM"].front());
|
||||
oneValueSet.append("ALBUM");
|
||||
} else
|
||||
setAlbum(String::null);
|
||||
setAlbum(String());
|
||||
|
||||
if(properties.contains("COMMENT")) {
|
||||
setComment(properties["COMMENT"].front());
|
||||
oneValueSet.append("COMMENT");
|
||||
} else
|
||||
setComment(String::null);
|
||||
setComment(String());
|
||||
|
||||
if(properties.contains("GENRE")) {
|
||||
setGenre(properties["GENRE"].front());
|
||||
oneValueSet.append("GENRE");
|
||||
} else
|
||||
setGenre(String::null);
|
||||
setGenre(String());
|
||||
|
||||
if(properties.contains("DATE")) {
|
||||
bool ok;
|
||||
|
||||
@ -23,10 +23,10 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "tagunion.h"
|
||||
#include "tstringlist.h"
|
||||
#include "tpropertymap.h"
|
||||
#include "tsmartptr.h"
|
||||
#include <tagunion.h>
|
||||
#include <tstringlist.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tsmartptr.h>
|
||||
|
||||
#define stringUnion(method) \
|
||||
for(size_t j = 0; j < COUNT; ++j) { \
|
||||
@ -34,7 +34,7 @@
|
||||
if(!val.isEmpty()) \
|
||||
return val; \
|
||||
} \
|
||||
return String::null;
|
||||
return String();
|
||||
|
||||
#define numberUnion(method) \
|
||||
for(size_t j = 0; j < COUNT; ++j) { \
|
||||
|
||||
79
taglib/tagutils.cpp
Normal file
79
taglib/tagutils.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2015 by Tsuda Kageyu
|
||||
email : tsuda.kageyu@gmail.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 <tfile.h>
|
||||
|
||||
#include "id3v1tag.h"
|
||||
#include "id3v2header.h"
|
||||
#include "apetag.h"
|
||||
|
||||
#include "tagutils.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
offset_t Utils::findID3v1(File *file)
|
||||
{
|
||||
if(!file->isValid())
|
||||
return -1;
|
||||
|
||||
file->seek(-128, File::End);
|
||||
const offset_t p = file->tell();
|
||||
|
||||
if(file->readBlock(3) == ID3v1::Tag::fileIdentifier())
|
||||
return p;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset_t Utils::findID3v2(File *file)
|
||||
{
|
||||
if(!file->isValid())
|
||||
return -1;
|
||||
|
||||
file->seek(0);
|
||||
|
||||
if(file->readBlock(3) == ID3v2::Header::fileIdentifier())
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset_t Utils::findAPE(File *file, offset_t id3v1Location)
|
||||
{
|
||||
if(!file->isValid())
|
||||
return -1;
|
||||
|
||||
if(id3v1Location >= 0)
|
||||
file->seek(id3v1Location - 32, File::Beginning);
|
||||
else
|
||||
file->seek(-32, File::End);
|
||||
|
||||
const offset_t p = file->tell();
|
||||
|
||||
if(file->readBlock(8) == APE::Tag::fileIdentifier())
|
||||
return p;
|
||||
|
||||
return -1;
|
||||
}
|
||||
49
taglib/tagutils.h
Normal file
49
taglib/tagutils.h
Normal file
@ -0,0 +1,49 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2015 by Tsuda Kageyu
|
||||
email : tsuda.kageyu@gmail.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_TAGUTILS_H
|
||||
#define TAGLIB_TAGUTILS_H
|
||||
|
||||
// THIS FILE IS NOT A PART OF THE TAGLIB API
|
||||
|
||||
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
class File;
|
||||
|
||||
namespace Utils {
|
||||
|
||||
offset_t findID3v1(File *file);
|
||||
|
||||
offset_t findID3v2(File *file);
|
||||
|
||||
offset_t findAPE(File *file, offset_t id3v1Location);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -147,7 +147,7 @@ String FileName::toString() const
|
||||
else if(!d->data->name.empty()) {
|
||||
const int len = ::MultiByteToWideChar(CP_ACP, 0, d->data->name.c_str(), -1, NULL, 0);
|
||||
if(len == 0)
|
||||
return String::null;
|
||||
return String();
|
||||
|
||||
std::vector<wchar_t> buf(len);
|
||||
::MultiByteToWideChar(CP_ACP, 0, d->data->name.c_str(), -1, &buf[0], len);
|
||||
@ -155,7 +155,7 @@ String FileName::toString() const
|
||||
return String(&buf[0]);
|
||||
}
|
||||
else {
|
||||
return String::null;
|
||||
return String();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ PropertyMap::PropertyMap(const SimplePropertyMap &m)
|
||||
{
|
||||
for(SimplePropertyMap::ConstIterator it = m.begin(); it != m.end(); ++it){
|
||||
String key = it->first.upper();
|
||||
if(!key.isNull())
|
||||
if(!key.isEmpty())
|
||||
insert(it->first, it->second);
|
||||
else
|
||||
unsupported.append(it->first);
|
||||
@ -144,7 +144,8 @@ bool PropertyMap::operator!=(const PropertyMap &other) const
|
||||
|
||||
String PropertyMap::toString() const
|
||||
{
|
||||
String ret = "";
|
||||
String ret;
|
||||
|
||||
for(ConstIterator it = begin(); it != end(); ++it)
|
||||
ret += it->first+"="+it->second.toString(", ") + "\n";
|
||||
if(!unsupported.isEmpty())
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <tagunion.h>
|
||||
#include <tstringlist.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "trueaudiofile.h"
|
||||
#include "id3v1tag.h"
|
||||
@ -240,7 +241,7 @@ void TrueAudio::File::read(bool readProperties)
|
||||
{
|
||||
// Look for an ID3v2 tag
|
||||
|
||||
d->ID3v2Location = findID3v2();
|
||||
d->ID3v2Location = Utils::findID3v2(this);
|
||||
|
||||
if(d->ID3v2Location >= 0) {
|
||||
|
||||
@ -256,7 +257,7 @@ void TrueAudio::File::read(bool readProperties)
|
||||
|
||||
// Look for an ID3v1 tag
|
||||
|
||||
d->ID3v1Location = findID3v1();
|
||||
d->ID3v1Location = Utils::findID3v1(this);
|
||||
|
||||
if(d->ID3v1Location >= 0) {
|
||||
d->tag.set(TrueAudioID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
||||
@ -288,30 +289,3 @@ void TrueAudio::File::read(bool readProperties)
|
||||
d->properties = new AudioProperties(readBlock(HeaderSize), streamLength);
|
||||
}
|
||||
}
|
||||
|
||||
offset_t TrueAudio::File::findID3v1()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
seek(-128, End);
|
||||
offset_t p = tell();
|
||||
|
||||
if(readBlock(3) == ID3v1::Tag::fileIdentifier())
|
||||
return p;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset_t TrueAudio::File::findID3v2()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
seek(0);
|
||||
|
||||
if(readBlock(3) == ID3v2::Header::fileIdentifier())
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -231,8 +231,6 @@ namespace TagLib {
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties);
|
||||
offset_t findID3v1();
|
||||
offset_t findID3v2();
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include <tdebug.h>
|
||||
#include <tagunion.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "wavpackfile.h"
|
||||
#include "id3v1tag.h"
|
||||
@ -233,7 +234,7 @@ void WavPack::File::read(bool readProperties)
|
||||
{
|
||||
// Look for an ID3v1 tag
|
||||
|
||||
d->ID3v1Location = findID3v1();
|
||||
d->ID3v1Location = Utils::findID3v1(this);
|
||||
|
||||
if(d->ID3v1Location >= 0) {
|
||||
d->tag.set(WavID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
||||
@ -242,7 +243,7 @@ void WavPack::File::read(bool readProperties)
|
||||
|
||||
// Look for an APE tag
|
||||
|
||||
d->APELocation = findAPE();
|
||||
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
|
||||
|
||||
if(d->APELocation >= 0) {
|
||||
d->tag.set(WavAPEIndex, new APE::Tag(this, d->APELocation));
|
||||
@ -270,35 +271,3 @@ void WavPack::File::read(bool readProperties)
|
||||
d->properties = new AudioProperties(this, streamLength);
|
||||
}
|
||||
}
|
||||
|
||||
offset_t WavPack::File::findAPE()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
if(d->hasID3v1)
|
||||
seek(-160, End);
|
||||
else
|
||||
seek(-32, End);
|
||||
|
||||
offset_t p = tell();
|
||||
|
||||
if(readBlock(8) == APE::Tag::fileIdentifier())
|
||||
return p;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset_t WavPack::File::findID3v1()
|
||||
{
|
||||
if(!isValid())
|
||||
return -1;
|
||||
|
||||
seek(-128, End);
|
||||
offset_t p = tell();
|
||||
|
||||
if(readBlock(3) == ID3v1::Tag::fileIdentifier())
|
||||
return p;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -199,8 +199,6 @@ namespace TagLib {
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties);
|
||||
offset_t findID3v1();
|
||||
offset_t findAPE();
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
|
||||
@ -452,7 +452,7 @@ bool XM::File::save()
|
||||
seek(pos + 4);
|
||||
const uint len = std::min(22U, instrumentHeaderSize - 4U);
|
||||
if(i >= lines.size())
|
||||
writeString(String::null, len);
|
||||
writeString(String(), len);
|
||||
else
|
||||
writeString(lines[i], len);
|
||||
|
||||
@ -483,7 +483,7 @@ bool XM::File::save()
|
||||
seek(pos + 18);
|
||||
const uint len = std::min(sampleHeaderSize - 18U, 22U);
|
||||
if(sampleNameIndex >= lines.size())
|
||||
writeString(String::null, len);
|
||||
writeString(String(), len);
|
||||
else
|
||||
writeString(lines[sampleNameIndex ++], len);
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ public:
|
||||
ByteVector data("Test Data");
|
||||
item.setBinaryData(data);
|
||||
CPPUNIT_ASSERT(item.values().isEmpty());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, item.toString());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), item.toString());
|
||||
CPPUNIT_ASSERT_EQUAL(data, item.binaryData());
|
||||
|
||||
item.setValue("Test Text 2");
|
||||
|
||||
@ -4,12 +4,26 @@
|
||||
#include <fileref.h>
|
||||
#include <oggflacfile.h>
|
||||
#include <vorbisfile.h>
|
||||
#include <mpegfile.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include "utils.h"
|
||||
#include <tfilestream.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace TagLib;
|
||||
|
||||
namespace
|
||||
{
|
||||
class DummyResolver : public FileRef::FileTypeResolver
|
||||
{
|
||||
public:
|
||||
virtual File *createFile(FileName fileName, bool, AudioProperties::ReadStyle) const
|
||||
{
|
||||
return new Ogg::Vorbis::File(fileName);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class TestFileRef : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE(TestFileRef);
|
||||
@ -30,6 +44,7 @@ class TestFileRef : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testAIFF);
|
||||
CPPUNIT_TEST(testAIFC);
|
||||
CPPUNIT_TEST(testUnsupported);
|
||||
CPPUNIT_TEST(testFileResolver);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@ -80,26 +95,16 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(f->tag()->year(), TagLib::uint(2080));
|
||||
delete f;
|
||||
|
||||
f = new FileRef(newname.c_str());
|
||||
CPPUNIT_ASSERT(f->isValid());
|
||||
FileStream fs(newname.c_str());
|
||||
f = new FileRef(&fs);
|
||||
CPPUNIT_ASSERT(!f->isNull());
|
||||
PropertyMap prop = f->properties();
|
||||
CPPUNIT_ASSERT_EQUAL(prop["ARTIST"].front(), String("ttest artist"));
|
||||
CPPUNIT_ASSERT_EQUAL(prop["TITLE" ].front(), String("ytest title"));
|
||||
prop["ARTIST"].front() = "a test artist";
|
||||
prop["TITLE" ].front() = "b test title";
|
||||
f->setProperties(prop);
|
||||
f->save();
|
||||
CPPUNIT_ASSERT_EQUAL(f->tag()->artist(), String("ttest artist"));
|
||||
CPPUNIT_ASSERT_EQUAL(f->tag()->title(), String("ytest title"));
|
||||
CPPUNIT_ASSERT_EQUAL(f->tag()->genre(), String("uTest!"));
|
||||
CPPUNIT_ASSERT_EQUAL(f->tag()->album(), String("ialbummmm"));
|
||||
CPPUNIT_ASSERT_EQUAL(f->tag()->track(), TagLib::uint(7));
|
||||
CPPUNIT_ASSERT_EQUAL(f->tag()->year(), TagLib::uint(2080));
|
||||
delete f;
|
||||
|
||||
f = new FileRef(newname.c_str());
|
||||
CPPUNIT_ASSERT(f->isValid());
|
||||
CPPUNIT_ASSERT(!f->isNull());
|
||||
prop = f->properties();
|
||||
CPPUNIT_ASSERT_EQUAL(prop["ARTIST"].front(), String("a test artist"));
|
||||
CPPUNIT_ASSERT_EQUAL(prop["TITLE" ].front(), String("b test title"));
|
||||
delete f;
|
||||
|
||||
}
|
||||
|
||||
void testMusepack()
|
||||
@ -192,10 +197,25 @@ public:
|
||||
{
|
||||
FileRef f1(TEST_FILE_PATH_C("no-extension"));
|
||||
CPPUNIT_ASSERT(f1.isNull());
|
||||
|
||||
|
||||
FileRef f2(TEST_FILE_PATH_C("unsupported-extension.xxx"));
|
||||
CPPUNIT_ASSERT(f2.isNull());
|
||||
}
|
||||
|
||||
void testFileResolver()
|
||||
{
|
||||
FileRef *f = new FileRef(TEST_FILE_PATH_C("xing.mp3"));
|
||||
CPPUNIT_ASSERT(dynamic_cast<MPEG::File *>(f->file()) != NULL);
|
||||
delete f;
|
||||
|
||||
DummyResolver resolver;
|
||||
FileRef::addFileTypeResolver(&resolver);
|
||||
|
||||
f = new FileRef(TEST_FILE_PATH_C("xing.mp3"));
|
||||
CPPUNIT_ASSERT(dynamic_cast<Ogg::Vorbis::File *>(f->file()) != NULL);
|
||||
delete f;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestFileRef);
|
||||
|
||||
@ -38,7 +38,7 @@ class PublicFrame : public ID3v2::Frame
|
||||
size_t position = 0;
|
||||
return ID3v2::Frame::readStringField(data, encoding, position);
|
||||
}
|
||||
virtual String toString() const { return String::null; }
|
||||
virtual String toString() const { return String(); }
|
||||
virtual void parseFields(const ByteVector &) {}
|
||||
virtual ByteVector renderFields() const { return ByteVector(); }
|
||||
};
|
||||
|
||||
@ -123,10 +123,10 @@ private:
|
||||
CPPUNIT_ASSERT_EQUAL((TagLib::uchar)128, p->panningSeparation());
|
||||
CPPUNIT_ASSERT_EQUAL((TagLib::uchar) 0, p->pitchWheelDepth());
|
||||
CPPUNIT_ASSERT_EQUAL(title, t->title());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->album());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->album());
|
||||
CPPUNIT_ASSERT_EQUAL(comment, t->comment());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->genre());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->genre());
|
||||
CPPUNIT_ASSERT_EQUAL(0U, t->year());
|
||||
CPPUNIT_ASSERT_EQUAL(0U, t->track());
|
||||
CPPUNIT_ASSERT_EQUAL(String("Impulse Tracker"), t->trackerName());
|
||||
|
||||
@ -113,10 +113,10 @@ private:
|
||||
CPPUNIT_ASSERT_EQUAL(31U, p->instrumentCount());
|
||||
CPPUNIT_ASSERT_EQUAL((uchar)1, p->lengthInPatterns());
|
||||
CPPUNIT_ASSERT_EQUAL(title, t->title());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->album());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->album());
|
||||
CPPUNIT_ASSERT_EQUAL(comment, t->comment());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->genre());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->genre());
|
||||
CPPUNIT_ASSERT_EQUAL(0U, t->year());
|
||||
CPPUNIT_ASSERT_EQUAL(0U, t->track());
|
||||
CPPUNIT_ASSERT_EQUAL(String("StarTrekker"), t->trackerName());
|
||||
|
||||
@ -110,10 +110,10 @@ private:
|
||||
CPPUNIT_ASSERT_EQUAL((TagLib::uchar)125, p->tempo());
|
||||
CPPUNIT_ASSERT_EQUAL((TagLib::uchar) 6, p->bpmSpeed());
|
||||
CPPUNIT_ASSERT_EQUAL(title, t->title());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->album());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->album());
|
||||
CPPUNIT_ASSERT_EQUAL(comment, t->comment());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->genre());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->genre());
|
||||
CPPUNIT_ASSERT_EQUAL(0U, t->year());
|
||||
CPPUNIT_ASSERT_EQUAL(0U, t->track());
|
||||
CPPUNIT_ASSERT_EQUAL(String("ScreamTracker III"), t->trackerName());
|
||||
|
||||
@ -75,7 +75,7 @@ public:
|
||||
|
||||
s.clear();
|
||||
CPPUNIT_ASSERT(s.isEmpty());
|
||||
CPPUNIT_ASSERT(!s.isNull());
|
||||
CPPUNIT_ASSERT(!s.isNull()); // deprecated, but still worth it to check.
|
||||
|
||||
String unicode("José Carlos", String::UTF8);
|
||||
CPPUNIT_ASSERT(strcmp(unicode.toCString(), "Jos\xe9 Carlos") == 0);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <flacfile.h>
|
||||
#include <xiphcomment.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tdebug.h>
|
||||
@ -17,6 +18,7 @@ class TestXiphComment : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testTrack);
|
||||
CPPUNIT_TEST(testSetTrack);
|
||||
CPPUNIT_TEST(testInvalidKeys);
|
||||
CPPUNIT_TEST(testClearComment);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@ -74,6 +76,22 @@ public:
|
||||
CPPUNIT_ASSERT(cmt.properties().isEmpty());
|
||||
}
|
||||
|
||||
void testClearComment()
|
||||
{
|
||||
ScopedFileCopy copy("no-tags", ".flac");
|
||||
|
||||
{
|
||||
FLAC::File f(copy.fileName().c_str());
|
||||
f.xiphComment()->addField("COMMENT", "Comment1");
|
||||
f.save();
|
||||
}
|
||||
{
|
||||
FLAC::File f(copy.fileName().c_str());
|
||||
f.xiphComment()->setComment("");
|
||||
CPPUNIT_ASSERT_EQUAL(String(""), f.xiphComment()->comment());
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestXiphComment);
|
||||
|
||||
@ -139,13 +139,13 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL((TagLib::ushort) 6, p->tempo());
|
||||
CPPUNIT_ASSERT_EQUAL((TagLib::ushort)125, p->bpmSpeed());
|
||||
CPPUNIT_ASSERT_EQUAL(titleBefore, t->title());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->album());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->comment());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->genre());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->album());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->comment());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->genre());
|
||||
CPPUNIT_ASSERT_EQUAL(0U, t->year());
|
||||
CPPUNIT_ASSERT_EQUAL(0U, t->track());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->trackerName());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->trackerName());
|
||||
}
|
||||
|
||||
void testWriteTagsShort()
|
||||
@ -185,10 +185,10 @@ private:
|
||||
CPPUNIT_ASSERT_EQUAL((TagLib::ushort) 6, p->tempo());
|
||||
CPPUNIT_ASSERT_EQUAL((TagLib::ushort)125, p->bpmSpeed());
|
||||
CPPUNIT_ASSERT_EQUAL(title, t->title());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->album());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->album());
|
||||
CPPUNIT_ASSERT_EQUAL(comment, t->comment());
|
||||
CPPUNIT_ASSERT_EQUAL(String::null, t->genre());
|
||||
CPPUNIT_ASSERT_EQUAL(String(), t->genre());
|
||||
CPPUNIT_ASSERT_EQUAL(0U, t->year());
|
||||
CPPUNIT_ASSERT_EQUAL(0U, t->track());
|
||||
CPPUNIT_ASSERT_EQUAL(trackerName, t->trackerName());
|
||||
|
||||
Reference in New Issue
Block a user