Update interface. Just needs more documentation now.

git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@340209 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
This commit is contained in:
Allan Sandfeld Jensen 2004-08-23 20:38:47 +00:00
parent d0095d3cd7
commit 3ab81ed05d
6 changed files with 298 additions and 117 deletions

View File

@ -5,7 +5,7 @@ INCLUDES = \
noinst_LTLIBRARIES = libape.la
libape_la_SOURCES = apetag.cpp apefooter.cpp
libape_la_SOURCES = apetag.cpp apefooter.cpp apeitem.cpp
taglib_include_HEADERS = apetag.h apefooter.h
taglib_includedir = $(includedir)/taglib

View File

@ -181,7 +181,7 @@ void Footer::parse(const ByteVector &data)
d->itemCount = data.mid(16, 4).toUInt(false);
// Read the flags
std::bitset<32> flags(data.mid(8, 4).toUInt(false));
std::bitset<32> flags(data.mid(20, 4).toUInt(false));
d->headerPresent = flags[31];
d->footerPresent = !flags[30];

167
ape/apeitem.cpp Normal file
View File

@ -0,0 +1,167 @@
/***************************************************************************
copyright : (C) 2004 by Allan Sandfeld Jensen
email : kde@carewolf.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
* USA *
***************************************************************************/
#include "apeitem.h"
#include "tbytevectorlist.h"
#include "tstringlist.h"
#include <iostream>
using std::cout;
using namespace TagLib;
using namespace APE;
class APE::Item::ItemPrivate
{
public:
ItemPrivate() : type(Text), readOnly(false) {}
Item::ItemTypes type;
String key;
ByteVector value;
StringList text;
bool readOnly;
};
APE::Item::Item()
{
d = new ItemPrivate;
}
APE::Item::Item(const String& key, const String& str)
{
d = new ItemPrivate;
d->key = key;
d->text.append(str);
}
APE::Item::Item(const Item& item)
{
d = new ItemPrivate(*item.d);
}
Item& APE::Item::operator=(const Item& item)
{
delete d;
d = new ItemPrivate(*item.d);
return *this;
}
void APE::Item::setReadOnly(bool val) {
d->readOnly = val;
}
bool APE::Item::isReadOnly() const {
return d->readOnly;
}
void APE::Item::setType(APE::Item::ItemTypes val) {
d->type = val;
}
APE::Item::ItemTypes APE::Item::type() const {
return d->type;
}
String APE::Item::key() const {
return d->key;
}
ByteVector APE::Item::value() const {
return d->value;
}
int APE::Item::size() const {
return 8 + d->key.size() + 1 + d->value.size();
}
StringList APE::Item::toStringList() const {
return d->text;
}
String APE::Item::toString() const {
return d->text.front();
}
bool APE::Item::isEmpty() const {
switch(d->type) {
case 0:
case 1:
if(d->text.isEmpty()) return true;
if(d->text.size() == 1 && d->text.front() == "") return true;
return false;
case 2:
return d->value.isEmpty();
default:
return false;
}
}
void APE::Item::parse(const ByteVector& data) {
uint valueLength = data.mid(0, 4).toUInt(false);
uint flags = data.mid(4, 4).toUInt(false);
d->key = String(data.mid(8), String::UTF8);
d->value = data.mid(8 + d->key.size() + 1, valueLength);
setReadOnly(flags & 1);
setType(ItemTypes((flags >> 1) & 3));
if ((int)(d->type) < 2) {
ByteVectorList bl = ByteVectorList::split(d->value, '\0');
d->text = StringList(bl, String::UTF8);
cout << d->text.toString(",") << "\n";
}
}
ByteVector APE::Item::render()
{
ByteVector data;
TagLib::uint flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
ByteVector value;
if(isEmpty())
return data;
if(d->type != Item::Binary) {
StringList::ConstIterator it = d->text.begin();
value.append(it->data(String::UTF8));
it++;
while(it != d->text.end()) {
value.append('\0');
value.append(it->data(String::UTF8));
it++;
}
d->value = value;
} else
value.append(d->value);
data.append(ByteVector::fromUInt(value.size(), false));
data.append(ByteVector::fromUInt(flags, false));
data.append(d->key.data(String::UTF8));
data.append(ByteVector('\0'));
data.append(value);
return data;
}

90
ape/apeitem.h Normal file
View File

@ -0,0 +1,90 @@
/***************************************************************************
copyright : (C) 2004 by Allan Sandfeld Jensen
email : kde@carewolf.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
* USA *
***************************************************************************/
#ifndef TAGLIB_APEITEM_H
#define TAGLIB_APEITEM_H
#include <tbytevector.h>
#include <tstring.h>
#include <tstringlist.h>
namespace TagLib {
namespace APE {
//! An implementation of APE-items
/*!
* This class provides the features of items in the APEv2 standard.
*/
struct Item
{
enum ItemTypes {
//! Item contains text information coded in UTF-8
Text = 0,
//! Item contains binary information
Binary = 1,
//! Item is a locator of external stored information
Locator = 2
};
Item();
explicit Item(ByteVector& bin);
explicit Item(const String&, const String&);
explicit Item(const String&, const StringList &);
Item(const Item&);
Item& operator=(const Item&);
String key() const;
ByteVector value() const;
int size() const;
String toString() const;
StringList toStringList() const;
ByteVector render();
void parse(const ByteVector&);
void setReadOnly(bool);
bool isReadOnly() const;
void setType(ItemTypes type);
ItemTypes type() const;
/*
void setValue(ByteVector);
void setValue(const String&);
void setValue(const StringList&);
*/
bool isEmpty() const;
private:
class ItemPrivate;
ItemPrivate *d;
};
}
}
#endif

View File

@ -26,37 +26,11 @@
#include "apetag.h"
#include "apefooter.h"
#include "apeitem.h"
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;
@ -71,7 +45,7 @@ static StringList parseAPEString(const ByteVector &data)
value.append(String(data.mid(pOld), String::UTF8));
return value;
}
}*/
class APE::Tag::TagPrivate
{
@ -85,24 +59,8 @@ public:
Footer footer;
ItemListMap itemListMap;
Map<const String, ByteVector> binaries;
};
APE::Item::Item(const String& str) : readOnly(false), locator(false)
{
value.append(str);
}
APE::Item::Item(const StringList& values) : readOnly(false), locator(false)
{
value.append(values);
}
bool APE::Item::isEmpty() const
{
return value.isEmpty();
}
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
@ -126,40 +84,6 @@ APE::Tag::~Tag()
delete d;
}
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(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++;
}
i++;
}
}
d->footer.setItemCount(itemCount);
d->footer.setTagSize(data.size()+Footer::size());
d->footer.setHeaderPresent(true);
return d->footer.renderHeader() + data + d->footer.renderFooter();
}
ByteVector APE::Tag::fileIdentifier()
{
return ByteVector::fromCString("APETAGEX");
@ -169,49 +93,49 @@ String APE::Tag::title() const
{
if(d->itemListMap["TITLE"].isEmpty())
return String::null;
return d->itemListMap["TITLE"].value.front();
return d->itemListMap["TITLE"].toString();
}
String APE::Tag::artist() const
{
if(d->itemListMap["ARTIST"].isEmpty())
return String::null;
return d->itemListMap["ARTIST"].value.front();
return d->itemListMap["ARTIST"].toString();
}
String APE::Tag::album() const
{
if(d->itemListMap["ALBUM"].isEmpty())
return String::null;
return d->itemListMap["ALBUM"].value.front();
return d->itemListMap["ALBUM"].toString();
}
String APE::Tag::comment() const
{
if(d->itemListMap["COMMENT"].isEmpty())
return String::null;
return d->itemListMap["COMMENT"].value.front();
return d->itemListMap["COMMENT"].toString();
}
String APE::Tag::genre() const
{
if(d->itemListMap["GENRE"].isEmpty())
return String::null;
return d->itemListMap["GENRE"].value.front();
return d->itemListMap["GENRE"].toString();
}
TagLib::uint APE::Tag::year() const
{
if(d->itemListMap["YEAR"].isEmpty())
return 0;
return d->itemListMap["YEAR"].value.front().toInt();
return d->itemListMap["YEAR"].toString().toInt();
}
TagLib::uint APE::Tag::track() const
{
if(d->itemListMap["TRACK"].isEmpty())
return 0;
return d->itemListMap["TRACK"].value.front().toInt();
return d->itemListMap["TRACK"].toString().toInt();
}
void APE::Tag::setTitle(const String &s)
@ -278,9 +202,9 @@ void APE::Tag::addValue(const String &key, const String &value, bool replace)
removeItem(key);
if(!value.isEmpty()) {
if(d->itemListMap.contains(key) || !replace)
d->itemListMap[key.upper()].value.append(value);
d->itemListMap[key.upper()].toStringList().append(value);
else
setItem(key, Item(value));
setItem(key, Item(key, value));
}
}
@ -309,24 +233,38 @@ void APE::Tag::read()
}
}
ByteVector APE::Tag::render() const
{
ByteVector data;
uint itemCount = 0;
{
Map<const String,Item>::Iterator i = d->itemListMap.begin();
while(i != d->itemListMap.end()) {
data.append(i->second.render());
itemCount++;
i++;
}
}
d->footer.setItemCount(itemCount);
d->footer.setTagSize(data.size()+Footer::size());
d->footer.setHeaderPresent(true);
return d->footer.renderHeader() + data + d->footer.renderFooter();
}
void APE::Tag::parse(const ByteVector &data, uint count)
{
uint pos = 0;
while(count > 0) {
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);
APE::Item item;
item.parse(data.mid(pos));
if(flags < 4 ) {
ByteVector val = data.mid(pos + 8 + key.size() + 1, valueLength);
d->itemListMap.insert(key.upper(), Item(parseAPEString(val)));
}
else
d->binaries.insert(key.upper(), data.mid(pos, 8 + key.size() + 1 + valueLength));
d->itemListMap.insert(item.key().upper(), item);
pos += 8 + key.size() + 1 + valueLength;
pos += item.size();
count--;
}
}

View File

@ -28,6 +28,8 @@
#include "tstring.h"
#include "tstringlist.h"
#include "apeitem.h"
namespace TagLib {
class File;
@ -36,22 +38,6 @@ namespace TagLib {
class Footer;
/*!
* A non-binary APE-item.
*/
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;
};
/*!
* A mapping between a list of item names, or keys, and the associated item.
@ -120,7 +106,7 @@ namespace TagLib {
const ItemListMap &itemListMap() const;
/*!
* Removes the \a key comment from the tag
* Removes the \a key item from the tag
*/
void removeItem(const String &key);