You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
amarok/amarok/src/metadata/asf/asfattribute.cpp

305 lines
6.5 KiB

/**************************************************************************
copyright : (C) 2005-2007 by Lukáš Lalinský
email : lalinsky@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 *
***************************************************************************/
#include <taglib.h>
#include "asfattribute.h"
#include "asffile.h"
using namespace TagLib;
class ASF::Attribute::AttributePrivate : public RefCounter
{
public:
AttributePrivate()
: stream(0),
language(0) {}
AttributeTypes type;
String stringValue;
ByteVector byteVectorValue;
union {
unsigned int intValue;
unsigned short shortValue;
unsigned long long longLongValue;
bool boolValue;
};
int stream;
int language;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::Attribute::Attribute()
{
d = new AttributePrivate;
d->type = UnicodeType;
}
ASF::Attribute::Attribute(const ASF::Attribute &other)
: d(other.d)
{
d->ref();
}
ASF::Attribute &
ASF::Attribute::operator=(const ASF::Attribute &other)
{
if(d->deref())
delete d;
d = other.d;
d->ref();
return *this;
}
ASF::Attribute::~Attribute()
{
if(d->deref())
delete d;
}
ASF::Attribute::Attribute(const String &value)
{
d = new AttributePrivate;
d->type = UnicodeType;
d->stringValue = value;
}
ASF::Attribute::Attribute(const ByteVector &value)
{
d = new AttributePrivate;
d->type = BytesType;
d->byteVectorValue = value;
}
ASF::Attribute::Attribute(unsigned int value)
{
d = new AttributePrivate;
d->type = DWordType;
d->intValue = value;
}
ASF::Attribute::Attribute(unsigned long long value)
{
d = new AttributePrivate;
d->type = TQWordType;
d->longLongValue = value;
}
ASF::Attribute::Attribute(unsigned short value)
{
d = new AttributePrivate;
d->type = WordType;
d->shortValue = value;
}
ASF::Attribute::Attribute(bool value)
{
d = new AttributePrivate;
d->type = BoolType;
d->boolValue = value;
}
ASF::Attribute::AttributeTypes
ASF::Attribute::type() const
{
return d->type;
}
String
ASF::Attribute::toString() const
{
return d->stringValue;
}
ByteVector
ASF::Attribute::toByteVector() const
{
return d->byteVectorValue;
}
unsigned short
ASF::Attribute::toBool() const
{
return d->shortValue;
}
unsigned short
ASF::Attribute::toUShort() const
{
return d->shortValue;
}
unsigned int
ASF::Attribute::toUInt() const
{
return d->intValue;
}
unsigned long long
ASF::Attribute::toULongLong() const
{
return d->longLongValue;
}
String
ASF::Attribute::parse(ASF::File &f, int kind)
{
int size, nameLength;
String name;
// extended content descriptor
if(kind == 0) {
nameLength = f.readWORD();
name = f.readString(nameLength);
d->type = ASF::Attribute::AttributeTypes(f.readWORD());
size = f.readWORD();
}
// metadata & metadata library
else {
int temp = f.readWORD();
// metadata library
if(kind == 2) {
d->language = temp;
}
d->stream = f.readWORD();
nameLength = f.readWORD();
d->type = ASF::Attribute::AttributeTypes(f.readWORD());
size = f.readDWORD();
name = f.readString(nameLength);
}
switch(d->type) {
case WordType:
d->shortValue = f.readWORD();
break;
case BoolType:
if(kind == 0) {
d->boolValue = f.readDWORD() == 1;
}
else {
d->boolValue = f.readWORD() == 1;
}
break;
case DWordType:
d->intValue = f.readDWORD();
break;
case TQWordType:
d->longLongValue = f.readTQWORD();
break;
case UnicodeType:
d->stringValue = f.readString(size);
break;
case BytesType:
case GuidType:
d->byteVectorValue = f.readBlock(size);
break;
}
return name;
}
ByteVector
ASF::Attribute::render(const String &name, int kind) const
{
ByteVector data;
switch (d->type) {
case WordType:
data.append(ByteVector::fromShort(d->shortValue, false));
break;
case BoolType:
if(kind == 0) {
data.append(ByteVector::fromUInt(d->boolValue ? 1 : 0, false));
}
else {
data.append(ByteVector::fromShort(d->boolValue ? 1 : 0, false));
}
break;
case DWordType:
data.append(ByteVector::fromUInt(d->intValue, false));
break;
case TQWordType:
data.append(ByteVector::fromLongLong(d->longLongValue, false));
break;
case UnicodeType:
data.append(File::renderString(d->stringValue));
break;
case BytesType:
case GuidType:
data.append(d->byteVectorValue);
break;
}
if(kind == 0) {
data = File::renderString(name, true) +
ByteVector::fromShort((int)d->type, false) +
ByteVector::fromShort(data.size(), false) +
data;
}
else {
ByteVector nameData = File::renderString(name);
data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
ByteVector::fromShort(d->stream, false) +
ByteVector::fromShort(nameData.size(), false) +
ByteVector::fromShort((int)d->type, false) +
ByteVector::fromUInt(data.size(), false) +
nameData +
data;
}
return data;
}
int
ASF::Attribute::language() const
{
return d->language;
}
void
ASF::Attribute::setLanguage(int value)
{
d->language = value;
}
int
ASF::Attribute::stream() const
{
return d->stream;
}
void
ASF::Attribute::setStream(int value)
{
d->stream = value;
}