mirror of
https://github.com/taglib/taglib.git
synced 2025-05-27 21:20:26 -04:00
Standard stuff -- make it fit with the coding style of the rest of TagLib
and make it build. There are still some missing API docs and I'm not sure how I feel about non-opaque types (Item in this case) since they're not used elsewhere in the API, but this will do for now. git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@333117 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
This commit is contained in:
parent
b7d9398052
commit
06122de67f
143
ape/apetag.cpp
143
ape/apetag.cpp
@ -30,6 +30,49 @@
|
||||
using namespace TagLib;
|
||||
using namespace APE;
|
||||
|
||||
static ByteVector renderAPEItem(const String &key, const Item &item)
|
||||
{
|
||||
ByteVector data;
|
||||
TagLib::uint flags = ((item.readOnly) ? 1 : 0) | ((item.locator) ? 2 : 0);
|
||||
ByteVector value;
|
||||
|
||||
if(item.value.isEmpty())
|
||||
return data;
|
||||
|
||||
StringList::ConstIterator it = item.value.begin();
|
||||
value.append(it->data(String::UTF8));
|
||||
it++;
|
||||
while(it != item.value.end()) {
|
||||
value.append('\0');
|
||||
value.append(it->data(String::UTF8));
|
||||
it++;
|
||||
}
|
||||
|
||||
data.append(ByteVector::fromUInt(value.size(), false));
|
||||
data.append(ByteVector::fromUInt(flags, false));
|
||||
data.append(key.data(String::UTF8));
|
||||
data.append(ByteVector('\0'));
|
||||
data.append(value);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static StringList parseAPEString(const ByteVector &data)
|
||||
{
|
||||
StringList value;
|
||||
int pOld = 0;
|
||||
int p = data.find('\0');
|
||||
|
||||
while (p != -1) {
|
||||
value.append(String(data.mid(pOld, p), String::UTF8));
|
||||
pOld = p + 1;
|
||||
p = data.find('\0', pOld);
|
||||
}
|
||||
value.append(String(data.mid(pOld), String::UTF8));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
class APE::Tag::TagPrivate
|
||||
{
|
||||
public:
|
||||
@ -45,11 +88,13 @@ public:
|
||||
Map<const String, ByteVector> binaries;
|
||||
};
|
||||
|
||||
APE::Item::Item(const String& str) : readOnly(false), locator(false) {
|
||||
APE::Item::Item(const String& str) : readOnly(false), locator(false)
|
||||
{
|
||||
value.append(str);
|
||||
}
|
||||
|
||||
APE::Item::Item(const StringList& values) : readOnly(false), locator(false) {
|
||||
APE::Item::Item(const StringList& values) : readOnly(false), locator(false)
|
||||
{
|
||||
value.append(values);
|
||||
}
|
||||
|
||||
@ -81,54 +126,28 @@ APE::Tag::~Tag()
|
||||
delete d;
|
||||
}
|
||||
|
||||
using TagLib::uint;
|
||||
|
||||
static ByteVector _render_APEItem(String key, Item item)
|
||||
{
|
||||
ByteVector data;
|
||||
uint flags = ((item.readOnly) ? 1 : 0) | ((item.locator) ? 2 : 0);
|
||||
ByteVector value;
|
||||
|
||||
if (item.value.isEmpty()) return data;
|
||||
|
||||
StringList::Iterator it = item.value.begin();
|
||||
value.append(it->data(String::UTF8));
|
||||
it++;
|
||||
while (it != item.value.end()) {
|
||||
value.append('\0');
|
||||
value.append(it->data(String::UTF8));
|
||||
it++;
|
||||
}
|
||||
|
||||
data.append(ByteVector::fromUInt(value.size(), false));
|
||||
data.append(ByteVector::fromUInt(flags, false));
|
||||
data.append(key.data(String::UTF8));
|
||||
data.append(ByteVector('\0'));
|
||||
data.append(value);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
ByteVector APE::Tag::render() const
|
||||
{
|
||||
ByteVector data;
|
||||
uint itemCount = 0;
|
||||
|
||||
{ Map<const String,Item>::Iterator i = d->itemListMap.begin();
|
||||
while (i != d->itemListMap.end()) {
|
||||
if (!i->second.value.isEmpty()) {
|
||||
data.append(_render_APEItem(i->first, i->second));
|
||||
{
|
||||
Map<const String,Item>::Iterator i = d->itemListMap.begin();
|
||||
while(i != d->itemListMap.end()) {
|
||||
if(!i->second.value.isEmpty()) {
|
||||
data.append(renderAPEItem(i->first, i->second));
|
||||
itemCount++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
{ Map<String,ByteVector>::Iterator i = d->binaries.begin();
|
||||
while (i != d->binaries.end()) {
|
||||
if (!i->second.isEmpty()) {
|
||||
data.append(i->second);
|
||||
itemCount++;
|
||||
{
|
||||
Map<String,ByteVector>::Iterator i = d->binaries.begin();
|
||||
while(i != d->binaries.end()) {
|
||||
if(!i->second.isEmpty()) {
|
||||
data.append(i->second);
|
||||
itemCount++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@ -235,7 +254,7 @@ void APE::Tag::setTrack(uint i)
|
||||
addValue("TRACK", String::number(i), true);
|
||||
}
|
||||
|
||||
APE::Footer* APE::Tag::footer() const
|
||||
APE::Footer *APE::Tag::footer() const
|
||||
{
|
||||
return &d->footer;
|
||||
}
|
||||
@ -245,7 +264,8 @@ const APE::ItemListMap& APE::Tag::itemListMap() const
|
||||
return d->itemListMap;
|
||||
}
|
||||
|
||||
void APE::Tag::removeItem(const String &key) {
|
||||
void APE::Tag::removeItem(const String &key)
|
||||
{
|
||||
Map<const String, Item>::Iterator it = d->itemListMap.find(key.upper());
|
||||
if(it != d->itemListMap.end())
|
||||
d->itemListMap.erase(it);
|
||||
@ -257,7 +277,7 @@ void APE::Tag::addValue(const String &key, const String &value, bool replace)
|
||||
removeItem(key);
|
||||
if(!value.isEmpty()) {
|
||||
Map<const String, Item>::Iterator it = d->itemListMap.find(key.upper());
|
||||
if (it != d->itemListMap.end())
|
||||
if(it != d->itemListMap.end())
|
||||
d->itemListMap[key].value.append(value);
|
||||
else
|
||||
setItem(key, Item(value));
|
||||
@ -280,7 +300,8 @@ void APE::Tag::read()
|
||||
d->file->seek(d->tagOffset);
|
||||
d->footer.setData(d->file->readBlock(Footer::size()));
|
||||
|
||||
if(d->footer.tagSize() == 0 || d->footer.tagSize() > d->file->length())
|
||||
if(d->footer.tagSize() == 0 ||
|
||||
d->footer.tagSize() > uint(d->file->length()))
|
||||
return;
|
||||
|
||||
d->file->seek(d->tagOffset + Footer::size() - d->footer.tagSize());
|
||||
@ -288,41 +309,25 @@ void APE::Tag::read()
|
||||
}
|
||||
}
|
||||
|
||||
static StringList _parse_APEString(ByteVector val)
|
||||
{
|
||||
StringList value;
|
||||
int pold = 0;
|
||||
int p = val.find('\0');
|
||||
while (p != -1) {
|
||||
value.append(String(val.mid(pold, p), String::UTF8));
|
||||
pold = p+1;
|
||||
p = val.find('\0', pold);
|
||||
};
|
||||
value.append(String(val.mid(pold), String::UTF8));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void APE::Tag::parse(const ByteVector &data, uint count)
|
||||
{
|
||||
uint pos = 0;
|
||||
uint vallen, flags;
|
||||
String key, value;
|
||||
|
||||
while(count > 0) {
|
||||
vallen = data.mid(pos+0,4).toUInt(false);
|
||||
flags = data.mid(pos+4,4).toUInt(false);
|
||||
key = String(data.mid(pos+8), String::UTF8);
|
||||
uint valueLength = data.mid(pos + 0, 4).toUInt(false);
|
||||
uint flags = data.mid(pos + 4, 4).toUInt(false);
|
||||
String key = String(data.mid(pos + 8), String::UTF8);
|
||||
key = key.upper();
|
||||
APE::Item item;
|
||||
|
||||
if (flags < 4 ) {
|
||||
ByteVector val = data.mid(pos+8+key.size()+1, vallen);
|
||||
d->itemListMap.insert(key, Item(_parse_APEString(val)));
|
||||
} else {
|
||||
d->binaries.insert(key,data.mid(pos, 8+key.size()+1+vallen));
|
||||
if(flags < 4 ) {
|
||||
ByteVector val = data.mid(pos + 8 + key.size() + 1, valueLength);
|
||||
d->itemListMap.insert(key, Item(parseAPEString(val)));
|
||||
}
|
||||
else
|
||||
d->binaries.insert(key, data.mid(pos, 8 + key.size() + 1 + valueLength));
|
||||
|
||||
pos += 8 + key.size() + 1 + vallen;
|
||||
pos += 8 + key.size() + 1 + valueLength;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
22
ape/apetag.h
22
ape/apetag.h
@ -39,14 +39,18 @@ namespace TagLib {
|
||||
/*!
|
||||
* A non-binary APE-item.
|
||||
*/
|
||||
struct Item {
|
||||
Item() {};
|
||||
explicit Item(const String&);
|
||||
explicit Item(const StringList&);
|
||||
bool readOnly;
|
||||
bool locator; // URL to external data
|
||||
StringList value;
|
||||
bool isEmpty() const;
|
||||
struct Item
|
||||
{
|
||||
Item() {};
|
||||
explicit Item(const String &);
|
||||
explicit Item(const StringList &);
|
||||
bool readOnly;
|
||||
/*!
|
||||
* The value is a URL to external data
|
||||
*/
|
||||
bool locator;
|
||||
StringList value;
|
||||
bool isEmpty() const;
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -57,7 +61,7 @@ namespace TagLib {
|
||||
typedef Map<const String, Item> ItemListMap;
|
||||
|
||||
|
||||
//! An APE tag implementation
|
||||
//! An APE tag implementation
|
||||
|
||||
class Tag : public TagLib::Tag
|
||||
{
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
}
|
||||
|
||||
APE::Tag *APETag;
|
||||
long APEFooter;
|
||||
// long APEFooter;
|
||||
long APELocation;
|
||||
uint APESize;
|
||||
|
||||
@ -110,39 +110,32 @@ bool MPC::File::save()
|
||||
|
||||
// Update ID3v1 tag
|
||||
|
||||
if(d->ID3v1Tag)
|
||||
{
|
||||
if(d->hasID3v1)
|
||||
{
|
||||
seek(-128, End);
|
||||
writeBlock(d->ID3v1Tag->render());
|
||||
if(d->ID3v1Tag) {
|
||||
if(d->hasID3v1) {
|
||||
seek(-128, End);
|
||||
writeBlock(d->ID3v1Tag->render());
|
||||
}
|
||||
else
|
||||
{
|
||||
seek(0, End);
|
||||
writeBlock(d->ID3v1Tag->render());
|
||||
else {
|
||||
seek(0, End);
|
||||
writeBlock(d->ID3v1Tag->render());
|
||||
}
|
||||
}
|
||||
|
||||
// Update APE tag
|
||||
|
||||
if(d->APETag)
|
||||
{
|
||||
if(d->APETag) {
|
||||
if(d->hasAPE)
|
||||
{
|
||||
insert(d->APETag->render(), d->APELocation, d->APESize);
|
||||
}
|
||||
else
|
||||
if (d->hasID3v1)
|
||||
{
|
||||
insert(d->APETag->render(), d->APELocation, d->APESize);
|
||||
else {
|
||||
if(d->hasID3v1) {
|
||||
seek(-128, End);
|
||||
insert(d->APETag->render(), tell(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
seek(0, End);
|
||||
writeBlock(d->APETag->render());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -156,10 +149,12 @@ ID3v1::Tag *MPC::File::ID3v1Tag(bool create)
|
||||
// no ID3v1 tag exists and we've been asked to create one
|
||||
|
||||
d->ID3v1Tag = new ID3v1::Tag;
|
||||
if (d->APETag)
|
||||
|
||||
if(d->APETag)
|
||||
d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
|
||||
else
|
||||
d->tag = d->ID3v1Tag;
|
||||
|
||||
return d->ID3v1Tag;
|
||||
}
|
||||
|
||||
@ -171,10 +166,12 @@ APE::Tag *MPC::File::APETag(bool create)
|
||||
// no APE tag exists and we've been asked to create one
|
||||
|
||||
d->APETag = new APE::Tag;
|
||||
if (d->ID3v1Tag)
|
||||
|
||||
if(d->ID3v1Tag)
|
||||
d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
|
||||
else
|
||||
d->tag = d->APETag;
|
||||
|
||||
return d->APETag;
|
||||
}
|
||||
|
||||
@ -207,16 +204,18 @@ void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesSty
|
||||
d->hasAPE = true;
|
||||
}
|
||||
|
||||
if (d->hasID3v1 && d->hasAPE)
|
||||
if(d->hasID3v1 && d->hasAPE)
|
||||
d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
|
||||
else
|
||||
if (d->hasID3v1)
|
||||
d->tag = d->ID3v1Tag;
|
||||
else
|
||||
if (d->hasAPE)
|
||||
d->tag = d->APETag;
|
||||
else
|
||||
d->tag = d->APETag = new APE::Tag();
|
||||
else {
|
||||
if(d->hasID3v1)
|
||||
d->tag = d->ID3v1Tag;
|
||||
else {
|
||||
if(d->hasAPE)
|
||||
d->tag = d->APETag;
|
||||
else
|
||||
d->tag = d->APETag = new APE::Tag();
|
||||
}
|
||||
}
|
||||
|
||||
// Look for and skip an ID3v2 tag
|
||||
|
||||
@ -244,11 +243,11 @@ void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesSty
|
||||
|
||||
long MPC::File::findAPE()
|
||||
{
|
||||
if(isValid()) {
|
||||
if (d->hasID3v1)
|
||||
seek(-160, End);
|
||||
if(isValid()) {
|
||||
if(d->hasID3v1)
|
||||
seek(-160, End);
|
||||
else
|
||||
seek(-32, End);
|
||||
seek(-32, End);
|
||||
|
||||
long p = tell();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user