mirror of
https://github.com/taglib/taglib.git
synced 2025-05-27 21:20:26 -04:00
Finished parseFields, renderFields and asProperty methods of ChapterFrame and TableOfContentsFrame classes.
Methods setElementID of ChapterFrame and TableOfContentsFrame classes now automatically terminates new element ID with null.
This commit is contained in:
parent
3a1040d55b
commit
c5f9258462
@ -98,6 +98,8 @@ uint ChapterFrame::endOffset() const
|
||||
void ChapterFrame::setElementID(const ByteVector &eID)
|
||||
{
|
||||
d->elementID = eID;
|
||||
if(eID.at(eID.size() - 1) != char(0))
|
||||
d->elementID.append(char(0));
|
||||
}
|
||||
|
||||
void ChapterFrame::setStartTime(const uint &sT)
|
||||
@ -120,21 +122,17 @@ void ChapterFrame::setEndOffset(const uint &eO)
|
||||
d->endOffset = eO;
|
||||
}
|
||||
|
||||
String UniqueFileIdentifierFrame::toString() const
|
||||
String ChapterFrame::toString() const
|
||||
{
|
||||
return String::null;
|
||||
}
|
||||
|
||||
PropertyMap ChapterFrame::asProperties() const
|
||||
PropertyMap UniqueFileIdentifierFrame::asProperties() const
|
||||
{
|
||||
//DODELAT
|
||||
PropertyMap map;
|
||||
if(d->owner == "http://musicbrainz.org") {
|
||||
map.insert("MUSICBRAINZ_TRACKID", String(d->identifier));
|
||||
}
|
||||
else {
|
||||
map.unsupportedData().append(frameID() + String("/") + d->owner);
|
||||
}
|
||||
|
||||
map.unsupportedData().append(frameID() + String("/") + d->elementID);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@ -156,25 +154,32 @@ ChapterFrame *ChapterFrame::findByElementID(const Tag *tag, const ByteVector &eI
|
||||
|
||||
void ChapterFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
//DODELAT
|
||||
if(data.size() < 1) {
|
||||
debug("An UFID frame must contain at least 1 byte.");
|
||||
if(data.size() < 18) {
|
||||
debug("An CHAP frame must contain at least 18 bytes (1 byte element ID terminated by null and 4x4 bytes for start and end time and offset).");
|
||||
return;
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
d->owner = readStringField(data, String::Latin1, &pos);
|
||||
d->identifier = data.mid(pos);
|
||||
d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
|
||||
d->elementID.append(char(0));
|
||||
d->startTime = data.mid(pos, 4).toUInt(true);
|
||||
pos += 4;
|
||||
d->endTime = data.mid(pos, 4).toUInt(true);
|
||||
pos += 4;
|
||||
d->startOffset = data.mid(pos, 4).toUInt(true);
|
||||
pos += 4;
|
||||
d->endOffset = data.mid(pos, 4).toUInt(true);
|
||||
}
|
||||
|
||||
ByteVector ChapterFrame::renderFields() const
|
||||
{
|
||||
//DODELAT
|
||||
ByteVector data;
|
||||
|
||||
data.append(d->owner.data(String::Latin1));
|
||||
data.append(char(0));
|
||||
data.append(d->identifier);
|
||||
data.append(d->elementID);
|
||||
data.append(ByteVector.fromUInt(d->startTime, true));
|
||||
data.append(ByteVector.fromUInt(d->endTime, true));
|
||||
data.append(ByteVector.fromUInt(d->startOffset, true));
|
||||
data.append(ByteVector.fromUInt(d->endOffset, true));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ namespace TagLib {
|
||||
~ChapterFrame();
|
||||
|
||||
/*!
|
||||
* Returns the elementID of the frame. Element ID
|
||||
* Returns the element ID of the frame. Element ID
|
||||
* is a null terminated string, however it's not human-readable.
|
||||
*
|
||||
* \see setElementID()
|
||||
@ -100,9 +100,9 @@ namespace TagLib {
|
||||
uint endOffset() const;
|
||||
|
||||
/*!
|
||||
* Sets the elementID of the frame to \a eID.
|
||||
* Sets the element ID of the frame to \a eID. If \a eID isn't
|
||||
* null terminated, a null char is appended automatically.
|
||||
*
|
||||
* \warning Element ID must be null terminated.
|
||||
* \see elementID()
|
||||
*/
|
||||
void setElementID(const ByteVector &eID);
|
||||
|
@ -81,9 +81,9 @@ bool TableOfContentsFrame::isOrdered() const
|
||||
return d->isOrdered;
|
||||
}
|
||||
|
||||
unsigned char TableOfContentsFrame::entryCount() const
|
||||
uint TableOfContentsFrame::entryCount() const
|
||||
{
|
||||
return (unsigned char)(d->childElements.size());
|
||||
return d->childElements.size();
|
||||
}
|
||||
|
||||
ByteVectorList TableOfContentsFrame::childElements const
|
||||
@ -94,6 +94,8 @@ ByteVectorList TableOfContentsFrame::childElements const
|
||||
void TableOfContentsFrame::setElementID(const ByteVector &eID)
|
||||
{
|
||||
d->elementID = eID;
|
||||
if(eID.at(eID.size() - 1) != char(0))
|
||||
d->elementID.append(char(0));
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::setIsTopLevel(const bool &t)
|
||||
@ -118,23 +120,19 @@ String TableOfContentsFrame::toString() const
|
||||
|
||||
PropertyMap TableOfContentsFrame::asProperties() const
|
||||
{
|
||||
//DODELAT
|
||||
PropertyMap map;
|
||||
if(d->owner == "http://musicbrainz.org") {
|
||||
map.insert("MUSICBRAINZ_TRACKID", String(d->identifier));
|
||||
}
|
||||
else {
|
||||
map.unsupportedData().append(frameID() + String("/") + d->owner);
|
||||
}
|
||||
|
||||
map.unsupportedData().append(frameID() + String("/") + d->elementID);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) // static
|
||||
{
|
||||
ID3v2::FrameList comments = tag->frameList("CTOC");
|
||||
ID3v2::FrameList tablesOfContents = tag->frameList("CTOC");
|
||||
|
||||
for(ID3v2::FrameList::ConstIterator it = comments.begin();
|
||||
it != comments.end();
|
||||
for(ID3v2::FrameList::ConstIterator it = tablesOfContents.begin();
|
||||
it != tablesOfContents.end();
|
||||
++it)
|
||||
{
|
||||
TableOfContentsFrame *frame = dynamic_cast<TableOfContentsFrame *>(*it);
|
||||
@ -145,28 +143,63 @@ TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *ta
|
||||
return 0;
|
||||
}
|
||||
|
||||
TableOfContentsFrame *TableOfContentsFrame::findTopLevel(const Tag *tag) // static
|
||||
{
|
||||
ID3v2::FrameList tablesOfContents = tag->frameList("CTOC");
|
||||
|
||||
for(ID3v2::FrameList::ConstIterator it = tablesOfContents.begin();
|
||||
it != tablesOfContents.end();
|
||||
++it)
|
||||
{
|
||||
TableOfContentsFrame *frame = dynamic_cast<TableOfContentsFrame *>(*it);
|
||||
if(frame && frame->isTopLevel() == true)
|
||||
return frame;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
//DODELAT
|
||||
if(data.size() < 1) {
|
||||
debug("An UFID frame must contain at least 1 byte.");
|
||||
if(data.size() < 6) {
|
||||
debug("An CTOC frame must contain at least 6 bytes (1 byte element ID terminated by null, 1 byte flags, 1 byte entry count and 1 byte child element ID terminated by null.");
|
||||
return;
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
d->owner = readStringField(data, String::Latin1, &pos);
|
||||
d->identifier = data.mid(pos);
|
||||
d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
|
||||
d->elementID.append(char(0));
|
||||
d->isTopLevel = (data.at(pos++) & 2) > 0;
|
||||
d->isOrdered = (data.at(pos++) & 1) > 0;
|
||||
uint entryCount = data.at(pos++);
|
||||
for(int i = 0; i < entryCount; i++)
|
||||
{
|
||||
ByteVector childElementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
|
||||
childElementID.append(char(0));
|
||||
d->childElements.append(childElementID);
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector TableOfContentsFrame::renderFields() const
|
||||
{
|
||||
//DODELAT
|
||||
ByteVector data;
|
||||
|
||||
data.append(d->owner.data(String::Latin1));
|
||||
data.append(d->elementID);
|
||||
data.append(char(0));
|
||||
data.append(d->identifier);
|
||||
|
||||
char flags = 0;
|
||||
if(d->isTopLevel)
|
||||
flags += 2;
|
||||
if(d->isOrdered)
|
||||
flags += 1;
|
||||
data.append(flags);
|
||||
data.append((char)(entryCount()));
|
||||
ConstIterator it = d->childElements.begin();
|
||||
while(it != d->childElements.end()) {
|
||||
data.append(*it);
|
||||
data.append(char(0));
|
||||
it++;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -88,10 +88,9 @@ namespace TagLib {
|
||||
* Returns count of child elements of the frame. It allways
|
||||
* corresponds to size of child elements list.
|
||||
*
|
||||
* \note Return type should be uint8_t, not unsigned char.
|
||||
* \see childElements()
|
||||
*/
|
||||
unsigned char entryCount() const;
|
||||
uint entryCount() const;
|
||||
|
||||
/*!
|
||||
* Returns list of child elements of the frame.
|
||||
@ -101,9 +100,9 @@ namespace TagLib {
|
||||
ByteVectorList childElements() const;
|
||||
|
||||
/*!
|
||||
* Sets the elementID of the frame to \a eID.
|
||||
* Sets the elementID of the frame to \a eID. If \a eID isn't
|
||||
* null terminated, a null char is appended automatically.
|
||||
*
|
||||
* \warning Element ID must be null terminated.
|
||||
* \see elementID()
|
||||
*/
|
||||
void setElementID(const ByteVector &eID);
|
||||
@ -143,6 +142,15 @@ namespace TagLib {
|
||||
* \see elementID()
|
||||
*/
|
||||
static TableOfContentsFrame *findByElementID(const Tag *tag, const ByteVector &eID);
|
||||
|
||||
/*!
|
||||
* CTOC frames each contain a flag that indicates, if CTOC frame is top-level (there isn't
|
||||
* any frame, which contains this frame in its child elements list). Only a single frame
|
||||
* within tag can be top-level. This searches for a top-level CTOC frame.
|
||||
*
|
||||
* \see isTopLevel()
|
||||
*/
|
||||
static TableOfContentsFrame *findTopLevel(const Tag *tag);
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
|
@ -47,6 +47,8 @@
|
||||
#include "frames/ownershipframe.h"
|
||||
#include "frames/synchronizedlyricsframe.h"
|
||||
#include "frames/eventtimingcodesframe.h"
|
||||
#include "frames/chapterframe.h"
|
||||
#include "frames/tableofcontentsframe.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
@ -274,6 +276,16 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader)
|
||||
d->setTextEncoding(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
// Chapter (ID3v2 chapters 1.0)
|
||||
|
||||
if(frameID == "CHAP")
|
||||
return new ChapterFrame(data, header);
|
||||
|
||||
// Table of contents (ID3v2 chapters 1.0)
|
||||
|
||||
if(frameID == "CTOC")
|
||||
return new TableOfContentsFrame(data, header);
|
||||
|
||||
return new UnknownFrame(data, header);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user