mirror of
https://github.com/taglib/taglib.git
synced 2025-06-04 01:28:21 -04:00
Merge pull request #211 from TsudaKageyu/tagunion
RIFF::WAV::Tag() returns TagUnion
This commit is contained in:
commit
d982b846c4
@ -57,7 +57,6 @@ public:
|
||||
APELocation(-1),
|
||||
APESize(0),
|
||||
ID3v1Location(-1),
|
||||
tag(2),
|
||||
properties(0),
|
||||
hasAPE(false),
|
||||
hasID3v1(false) {}
|
||||
@ -72,7 +71,7 @@ public:
|
||||
|
||||
offset_t ID3v1Location;
|
||||
|
||||
TagUnion tag;
|
||||
DoubleTagUnion tag;
|
||||
|
||||
AudioProperties *properties;
|
||||
|
||||
|
@ -57,7 +57,6 @@ public:
|
||||
ID3v2Location(-1),
|
||||
ID3v2OriginalSize(0),
|
||||
ID3v1Location(-1),
|
||||
tag(3),
|
||||
properties(0),
|
||||
flacStart(0),
|
||||
streamStart(0),
|
||||
@ -84,7 +83,7 @@ public:
|
||||
|
||||
offset_t ID3v1Location;
|
||||
|
||||
TagUnion tag;
|
||||
TripleTagUnion tag;
|
||||
|
||||
AudioProperties *properties;
|
||||
ByteVector streamInfoData;
|
||||
@ -245,11 +244,7 @@ bool FLAC::File::save()
|
||||
|
||||
ID3v2::Tag *FLAC::File::ID3v2Tag(bool create)
|
||||
{
|
||||
if(!create || d->tag[FlacID3v2Index])
|
||||
return static_cast<ID3v2::Tag *>(d->tag[FlacID3v2Index]);
|
||||
|
||||
d->tag.set(FlacID3v2Index, new ID3v2::Tag);
|
||||
return static_cast<ID3v2::Tag *>(d->tag[FlacID3v2Index]);
|
||||
return d->tag.access<ID3v2::Tag>(FlacID3v2Index, create);
|
||||
}
|
||||
|
||||
ID3v1::Tag *FLAC::File::ID3v1Tag(bool create)
|
||||
|
@ -52,7 +52,6 @@ public:
|
||||
ID3v2Header(0),
|
||||
ID3v2Location(-1),
|
||||
ID3v2Size(0),
|
||||
tag(2),
|
||||
properties(0),
|
||||
scanned(false),
|
||||
hasAPE(false),
|
||||
@ -74,7 +73,7 @@ public:
|
||||
offset_t ID3v2Location;
|
||||
uint ID3v2Size;
|
||||
|
||||
TagUnion tag;
|
||||
DoubleTagUnion tag;
|
||||
|
||||
AudioProperties *properties;
|
||||
bool scanned;
|
||||
|
@ -55,7 +55,6 @@ public:
|
||||
APEFooterLocation(-1),
|
||||
APEOriginalSize(0),
|
||||
ID3v1Location(-1),
|
||||
tag(3),
|
||||
hasID3v2(false),
|
||||
hasID3v1(false),
|
||||
hasAPE(false),
|
||||
@ -80,7 +79,7 @@ public:
|
||||
|
||||
offset_t ID3v1Location;
|
||||
|
||||
TagUnion tag;
|
||||
TripleTagUnion tag;
|
||||
|
||||
// These indicate whether the file *on disk* has these tags, not if
|
||||
// this data structure does. This is used in computing offsets.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2012 by Tsuda Kageyu
|
||||
email : wheeler@kde.org
|
||||
email : tsuda.kageyu@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
@ -31,14 +31,15 @@
|
||||
using namespace TagLib;
|
||||
using namespace RIFF::Info;
|
||||
|
||||
namespace {
|
||||
static bool isValidChunkID(const ByteVector &name)
|
||||
namespace
|
||||
{
|
||||
bool isValidChunkID(const ByteVector &name)
|
||||
{
|
||||
if(name.size() != 4)
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(name[i] < 32 || name[i] > 127)
|
||||
if(name[i] < 32 || 127 < name[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -86,7 +87,9 @@ ByteVector RIFF::Info::StringHandler::render(const String &s) const
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RIFF::Info::Tag::Tag(const ByteVector &data) : TagLib::Tag()
|
||||
RIFF::Info::Tag::Tag(const ByteVector &data)
|
||||
: TagLib::Tag()
|
||||
, d(new TagPrivate())
|
||||
{
|
||||
parse(data);
|
||||
}
|
||||
@ -193,7 +196,7 @@ String RIFF::Info::Tag::fieldText(const ByteVector &id) const
|
||||
|
||||
void RIFF::Info::Tag::setFieldText(const ByteVector &id, const String &s)
|
||||
{
|
||||
// id must be four-byte long pure ascii string.
|
||||
// id must be four-byte long pure ASCII string.
|
||||
if(!isValidChunkID(id))
|
||||
return;
|
||||
|
||||
|
@ -45,8 +45,7 @@ class RIFF::WAV::File::FilePrivate
|
||||
public:
|
||||
FilePrivate() :
|
||||
properties(0),
|
||||
tagChunkID("ID3 "),
|
||||
tag(2)
|
||||
tagChunkID("ID3 ")
|
||||
{
|
||||
}
|
||||
|
||||
@ -59,7 +58,7 @@ public:
|
||||
|
||||
ByteVector tagChunkID;
|
||||
|
||||
TagUnion tag;
|
||||
DoubleTagUnion tag;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -87,9 +86,9 @@ RIFF::WAV::File::~File()
|
||||
delete d;
|
||||
}
|
||||
|
||||
ID3v2::Tag *RIFF::WAV::File::tag() const
|
||||
TagLib::Tag *RIFF::WAV::File::tag() const
|
||||
{
|
||||
return ID3v2Tag();
|
||||
return &d->tag;
|
||||
}
|
||||
|
||||
ID3v2::Tag *RIFF::WAV::File::ID3v2Tag() const
|
||||
|
@ -94,12 +94,10 @@ namespace TagLib {
|
||||
virtual ~File();
|
||||
|
||||
/*!
|
||||
* Returns the ID3v2 Tag for this file.
|
||||
*
|
||||
* \note This method does not return all the tags for this file for
|
||||
* backward compatibility. Will be fixed in TagLib 2.0.
|
||||
* Returns the Tag for this file. This will be an ID3v2 tag, an INFO tag
|
||||
* or a combination of the two.
|
||||
*/
|
||||
ID3v2::Tag *tag() const;
|
||||
virtual TagLib::Tag *tag() const;
|
||||
|
||||
/*!
|
||||
* Returns the ID3v2 Tag for this file.
|
||||
|
@ -27,168 +27,184 @@
|
||||
#include "tstringlist.h"
|
||||
#include "tpropertymap.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
namespace
|
||||
{
|
||||
typedef std::vector<RefCountPtr<Tag> > TagVector;
|
||||
typedef TagVector::iterator TagIterator;
|
||||
typedef TagVector::const_iterator TagConstIterator;
|
||||
}
|
||||
|
||||
#define stringUnion(method) \
|
||||
for(TagConstIterator it = d->tags.begin(); it != d->tags.end(); ++it) { \
|
||||
String val = (*it) ? (*it)->method() : String::null; \
|
||||
for(size_t j = 0; j < COUNT; ++j) { \
|
||||
String val = d->tags[j] ? d->tags[j]->method() : String::null; \
|
||||
if(!val.isEmpty()) \
|
||||
return val; \
|
||||
} \
|
||||
return String::null;
|
||||
|
||||
#define numberUnion(method) \
|
||||
for(TagConstIterator it = d->tags.begin(); it != d->tags.end(); ++it) { \
|
||||
uint val = (*it) ? (*it)->method() : 0; \
|
||||
for(size_t j = 0; j < COUNT; ++j) { \
|
||||
uint val = d->tags[j] ? d->tags[j]->method() : 0; \
|
||||
if(val > 0) \
|
||||
return val; \
|
||||
} \
|
||||
return 0;
|
||||
|
||||
#define setUnion(method, value) \
|
||||
for(TagIterator it = d->tags.begin(); it != d->tags.end(); ++it) { \
|
||||
if(*it) \
|
||||
(*it)->set##method(value); \
|
||||
for(size_t j = 0; j < COUNT; ++j) { \
|
||||
if(d->tags[j]) \
|
||||
d->tags[j]->set##method(value); \
|
||||
}
|
||||
|
||||
class TagUnion::TagUnionPrivate
|
||||
namespace TagLib
|
||||
{
|
||||
public:
|
||||
TagUnionPrivate(size_t count)
|
||||
: tags(count)
|
||||
template <size_t COUNT>
|
||||
class TagUnion<COUNT>::TagUnionPrivate
|
||||
{
|
||||
public:
|
||||
NonRefCountPtr<Tag> tags[COUNT];
|
||||
};
|
||||
|
||||
template <size_t COUNT>
|
||||
TagUnion<COUNT>::TagUnion()
|
||||
: d(new TagUnionPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
TagVector tags;
|
||||
};
|
||||
|
||||
TagUnion::TagUnion(size_t count)
|
||||
: d(new TagUnionPrivate(count))
|
||||
{
|
||||
}
|
||||
|
||||
TagUnion::~TagUnion()
|
||||
{
|
||||
}
|
||||
|
||||
Tag *TagUnion::operator[](size_t index) const
|
||||
{
|
||||
return tag(index);
|
||||
}
|
||||
|
||||
Tag *TagUnion::tag(size_t index) const
|
||||
{
|
||||
return d->tags[index].get();
|
||||
}
|
||||
|
||||
void TagUnion::set(size_t index, Tag *tag)
|
||||
{
|
||||
d->tags[index].reset(tag);
|
||||
}
|
||||
|
||||
PropertyMap TagUnion::properties() const
|
||||
{
|
||||
for(TagConstIterator it = d->tags.begin(); it != d->tags.end(); ++it) {
|
||||
if(*it)
|
||||
return (*it)->properties();
|
||||
template <size_t COUNT>
|
||||
TagUnion<COUNT>::~TagUnion()
|
||||
{
|
||||
}
|
||||
|
||||
return PropertyMap();
|
||||
}
|
||||
|
||||
void TagUnion::removeUnsupportedProperties(const StringList &unsupported)
|
||||
{
|
||||
for(TagIterator it = d->tags.begin(); it != d->tags.end(); ++it) {
|
||||
if(*it)
|
||||
(*it)->removeUnsupportedProperties(unsupported);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String TagUnion::title() const
|
||||
{
|
||||
stringUnion(title);
|
||||
}
|
||||
|
||||
String TagUnion::artist() const
|
||||
{
|
||||
stringUnion(artist);
|
||||
}
|
||||
|
||||
String TagUnion::album() const
|
||||
{
|
||||
stringUnion(album);
|
||||
}
|
||||
|
||||
String TagUnion::comment() const
|
||||
{
|
||||
stringUnion(comment);
|
||||
}
|
||||
|
||||
String TagUnion::genre() const
|
||||
{
|
||||
stringUnion(genre);
|
||||
}
|
||||
|
||||
TagLib::uint TagUnion::year() const
|
||||
{
|
||||
numberUnion(year);
|
||||
}
|
||||
|
||||
TagLib::uint TagUnion::track() const
|
||||
{
|
||||
numberUnion(track);
|
||||
}
|
||||
|
||||
void TagUnion::setTitle(const String &s)
|
||||
{
|
||||
setUnion(Title, s);
|
||||
}
|
||||
|
||||
void TagUnion::setArtist(const String &s)
|
||||
{
|
||||
setUnion(Artist, s);
|
||||
}
|
||||
|
||||
void TagUnion::setAlbum(const String &s)
|
||||
{
|
||||
setUnion(Album, s);
|
||||
}
|
||||
|
||||
void TagUnion::setComment(const String &s)
|
||||
{
|
||||
setUnion(Comment, s);
|
||||
}
|
||||
|
||||
void TagUnion::setGenre(const String &s)
|
||||
{
|
||||
setUnion(Genre, s);
|
||||
}
|
||||
|
||||
void TagUnion::setYear(uint i)
|
||||
{
|
||||
setUnion(Year, i);
|
||||
}
|
||||
|
||||
void TagUnion::setTrack(uint i)
|
||||
{
|
||||
setUnion(Track, i);
|
||||
}
|
||||
|
||||
bool TagUnion::isEmpty() const
|
||||
{
|
||||
for(TagIterator it = d->tags.begin(); it != d->tags.end(); ++it) {
|
||||
if(*it && !(*it)->isEmpty())
|
||||
return false;
|
||||
template <size_t COUNT>
|
||||
Tag *TagUnion<COUNT>::operator[](size_t index) const
|
||||
{
|
||||
return tag(index);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
template <size_t COUNT>
|
||||
Tag *TagUnion<COUNT>::tag(size_t index) const
|
||||
{
|
||||
return d->tags[index].get();
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
void TagUnion<COUNT>::set(size_t index, Tag *tag)
|
||||
{
|
||||
d->tags[index].reset(tag);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
PropertyMap TagUnion<COUNT>::properties() const
|
||||
{
|
||||
for(size_t i = 0; i < COUNT; ++i) {
|
||||
if(d->tags[i])
|
||||
return d->tags[i]->properties();
|
||||
}
|
||||
|
||||
return PropertyMap();
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
void TagUnion<COUNT>::removeUnsupportedProperties(const StringList &unsupported)
|
||||
{
|
||||
for(size_t i = 0; i < COUNT; ++i) {
|
||||
if(d->tags[i])
|
||||
d->tags[i]->removeUnsupportedProperties(unsupported);
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
String TagUnion<COUNT>::title() const
|
||||
{
|
||||
stringUnion(title);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
String TagUnion<COUNT>::artist() const
|
||||
{
|
||||
stringUnion(artist);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
String TagUnion<COUNT>::album() const
|
||||
{
|
||||
stringUnion(album);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
String TagUnion<COUNT>::comment() const
|
||||
{
|
||||
stringUnion(comment);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
String TagUnion<COUNT>::genre() const
|
||||
{
|
||||
stringUnion(genre);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
TagLib::uint TagUnion<COUNT>::year() const
|
||||
{
|
||||
numberUnion(year);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
TagLib::uint TagUnion<COUNT>::track() const
|
||||
{
|
||||
numberUnion(track);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
void TagUnion<COUNT>::setTitle(const String &s)
|
||||
{
|
||||
setUnion(Title, s);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
void TagUnion<COUNT>::setArtist(const String &s)
|
||||
{
|
||||
setUnion(Artist, s);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
void TagUnion<COUNT>::setAlbum(const String &s)
|
||||
{
|
||||
setUnion(Album, s);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
void TagUnion<COUNT>::setComment(const String &s)
|
||||
{
|
||||
setUnion(Comment, s);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
void TagUnion<COUNT>::setGenre(const String &s)
|
||||
{
|
||||
setUnion(Genre, s);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
void TagUnion<COUNT>::setYear(uint i)
|
||||
{
|
||||
setUnion(Year, i);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
void TagUnion<COUNT>::setTrack(uint i)
|
||||
{
|
||||
setUnion(Track, i);
|
||||
}
|
||||
|
||||
template <size_t COUNT>
|
||||
bool TagUnion<COUNT>::isEmpty() const
|
||||
{
|
||||
for(size_t i = 0; i < COUNT; ++i) {
|
||||
if(d->tags[i] && !d->tags[i]->isEmpty())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// All the versions of TagUnion should be explicitly instantiated here.
|
||||
|
||||
template class TagUnion<2>;
|
||||
template class TagUnion<3>;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ namespace TagLib {
|
||||
* \internal
|
||||
*/
|
||||
|
||||
template <size_t COUNT>
|
||||
class TagUnion : public Tag
|
||||
{
|
||||
public:
|
||||
@ -45,7 +46,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Creates a TagLib::Tag that is the union of \a count tags.
|
||||
*/
|
||||
TagUnion(size_t count);
|
||||
TagUnion();
|
||||
|
||||
virtual ~TagUnion();
|
||||
|
||||
@ -85,12 +86,15 @@ namespace TagLib {
|
||||
}
|
||||
|
||||
private:
|
||||
TagUnion(const Tag &);
|
||||
TagUnion &operator=(const Tag &);
|
||||
|
||||
class TagUnionPrivate;
|
||||
NonRefCountPtr<TagUnionPrivate> d;
|
||||
};
|
||||
|
||||
// If you add a new typedef here, add a corresponding explicit instantiation
|
||||
// at the end of tagunion.cpp as well.
|
||||
|
||||
typedef TagUnion<2> DoubleTagUnion;
|
||||
typedef TagUnion<3> TripleTagUnion;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -312,7 +312,8 @@ inline T toNumber(const ByteVector &v, size_t offset)
|
||||
static const bool swap = (ENDIAN == LittleEndian);
|
||||
#endif
|
||||
|
||||
if(LENGTH >= sizeof(T) && offset + LENGTH <= v.size()) {
|
||||
if(LENGTH >= sizeof(T) && offset + LENGTH <= v.size())
|
||||
{
|
||||
// Uses memcpy instead of reinterpret_cast to avoid an alignment exception.
|
||||
T tmp;
|
||||
::memcpy(&tmp, v.data() + offset, sizeof(T));
|
||||
@ -322,7 +323,8 @@ inline T toNumber(const ByteVector &v, size_t offset)
|
||||
else
|
||||
return tmp;
|
||||
}
|
||||
else {
|
||||
else if(offset < v.size())
|
||||
{
|
||||
const size_t length = std::min(LENGTH, v.size() - offset);
|
||||
T sum = 0;
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
@ -332,6 +334,11 @@ inline T toNumber(const ByteVector &v, size_t offset)
|
||||
|
||||
return sum;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("toNumber<T>() - offset is out of range. Returning 0.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, Endianness ENDIAN>
|
||||
|
@ -54,7 +54,6 @@ public:
|
||||
ID3v2Location(-1),
|
||||
ID3v2OriginalSize(0),
|
||||
ID3v1Location(-1),
|
||||
tag(2),
|
||||
properties(0),
|
||||
hasID3v1(false),
|
||||
hasID3v2(false) {}
|
||||
@ -70,7 +69,7 @@ public:
|
||||
|
||||
offset_t ID3v1Location;
|
||||
|
||||
TagUnion tag;
|
||||
DoubleTagUnion tag;
|
||||
|
||||
AudioProperties *properties;
|
||||
|
||||
|
@ -53,7 +53,6 @@ public:
|
||||
APELocation(-1),
|
||||
APESize(0),
|
||||
ID3v1Location(-1),
|
||||
tag(2),
|
||||
properties(0),
|
||||
hasAPE(false),
|
||||
hasID3v1(false) {}
|
||||
@ -68,7 +67,7 @@ public:
|
||||
|
||||
offset_t ID3v1Location;
|
||||
|
||||
TagUnion tag;
|
||||
DoubleTagUnion tag;
|
||||
|
||||
AudioProperties *properties;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user