Format taglib sources
This commit is contained in:
419
3rdparty/taglib/mpeg/id3v1/id3v1genres.cpp
vendored
419
3rdparty/taglib/mpeg/id3v1/id3v1genres.cpp
vendored
@@ -27,237 +27,232 @@
|
||||
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
namespace
|
||||
{
|
||||
const wchar_t *genres[] = {
|
||||
L"Blues",
|
||||
L"Classic Rock",
|
||||
L"Country",
|
||||
L"Dance",
|
||||
L"Disco",
|
||||
L"Funk",
|
||||
L"Grunge",
|
||||
L"Hip-Hop",
|
||||
L"Jazz",
|
||||
L"Metal",
|
||||
L"New Age",
|
||||
L"Oldies",
|
||||
L"Other",
|
||||
L"Pop",
|
||||
L"R&B",
|
||||
L"Rap",
|
||||
L"Reggae",
|
||||
L"Rock",
|
||||
L"Techno",
|
||||
L"Industrial",
|
||||
L"Alternative",
|
||||
L"Ska",
|
||||
L"Death Metal",
|
||||
L"Pranks",
|
||||
L"Soundtrack",
|
||||
L"Euro-Techno",
|
||||
L"Ambient",
|
||||
L"Trip-Hop",
|
||||
L"Vocal",
|
||||
L"Jazz+Funk",
|
||||
L"Fusion",
|
||||
L"Trance",
|
||||
L"Classical",
|
||||
L"Instrumental",
|
||||
L"Acid",
|
||||
L"House",
|
||||
L"Game",
|
||||
L"Sound Clip",
|
||||
L"Gospel",
|
||||
L"Noise",
|
||||
L"Alternative Rock",
|
||||
L"Bass",
|
||||
L"Soul",
|
||||
L"Punk",
|
||||
L"Space",
|
||||
L"Meditative",
|
||||
L"Instrumental Pop",
|
||||
L"Instrumental Rock",
|
||||
L"Ethnic",
|
||||
L"Gothic",
|
||||
L"Darkwave",
|
||||
L"Techno-Industrial",
|
||||
L"Electronic",
|
||||
L"Pop-Folk",
|
||||
L"Eurodance",
|
||||
L"Dream",
|
||||
L"Southern Rock",
|
||||
L"Comedy",
|
||||
L"Cult",
|
||||
L"Gangsta",
|
||||
L"Top 40",
|
||||
L"Christian Rap",
|
||||
L"Pop/Funk",
|
||||
L"Jungle",
|
||||
L"Native American",
|
||||
L"Cabaret",
|
||||
L"New Wave",
|
||||
L"Psychedelic",
|
||||
L"Rave",
|
||||
L"Showtunes",
|
||||
L"Trailer",
|
||||
L"Lo-Fi",
|
||||
L"Tribal",
|
||||
L"Acid Punk",
|
||||
L"Acid Jazz",
|
||||
L"Polka",
|
||||
L"Retro",
|
||||
L"Musical",
|
||||
L"Rock & Roll",
|
||||
L"Hard Rock",
|
||||
L"Folk",
|
||||
L"Folk/Rock",
|
||||
L"National Folk",
|
||||
L"Swing",
|
||||
L"Fusion",
|
||||
L"Bebob",
|
||||
L"Latin",
|
||||
L"Revival",
|
||||
L"Celtic",
|
||||
L"Bluegrass",
|
||||
L"Avantgarde",
|
||||
L"Gothic Rock",
|
||||
L"Progressive Rock",
|
||||
L"Psychedelic Rock",
|
||||
L"Symphonic Rock",
|
||||
L"Slow Rock",
|
||||
L"Big Band",
|
||||
L"Chorus",
|
||||
L"Easy Listening",
|
||||
L"Acoustic",
|
||||
L"Humour",
|
||||
L"Speech",
|
||||
L"Chanson",
|
||||
L"Opera",
|
||||
L"Chamber Music",
|
||||
L"Sonata",
|
||||
L"Symphony",
|
||||
L"Booty Bass",
|
||||
L"Primus",
|
||||
L"Porn Groove",
|
||||
L"Satire",
|
||||
L"Slow Jam",
|
||||
L"Club",
|
||||
L"Tango",
|
||||
L"Samba",
|
||||
L"Folklore",
|
||||
L"Ballad",
|
||||
L"Power Ballad",
|
||||
L"Rhythmic Soul",
|
||||
L"Freestyle",
|
||||
L"Duet",
|
||||
L"Punk Rock",
|
||||
L"Drum Solo",
|
||||
L"A Cappella",
|
||||
L"Euro-House",
|
||||
L"Dance Hall",
|
||||
L"Goa",
|
||||
L"Drum & Bass",
|
||||
L"Club-House",
|
||||
L"Hardcore",
|
||||
L"Terror",
|
||||
L"Indie",
|
||||
L"BritPop",
|
||||
L"Negerpunk",
|
||||
L"Polsk Punk",
|
||||
L"Beat",
|
||||
L"Christian Gangsta Rap",
|
||||
L"Heavy Metal",
|
||||
L"Black Metal",
|
||||
L"Crossover",
|
||||
L"Contemporary Christian",
|
||||
L"Christian Rock",
|
||||
L"Merengue",
|
||||
L"Salsa",
|
||||
L"Thrash Metal",
|
||||
L"Anime",
|
||||
L"Jpop",
|
||||
L"Synthpop",
|
||||
L"Abstract",
|
||||
L"Art Rock",
|
||||
L"Baroque",
|
||||
L"Bhangra",
|
||||
L"Big Beat",
|
||||
L"Breakbeat",
|
||||
L"Chillout",
|
||||
L"Downtempo",
|
||||
L"Dub",
|
||||
L"EBM",
|
||||
L"Eclectic",
|
||||
L"Electro",
|
||||
L"Electroclash",
|
||||
L"Emo",
|
||||
L"Experimental",
|
||||
L"Garage",
|
||||
L"Global",
|
||||
L"IDM",
|
||||
L"Illbient",
|
||||
L"Industro-Goth",
|
||||
L"Jam Band",
|
||||
L"Krautrock",
|
||||
L"Leftfield",
|
||||
L"Lounge",
|
||||
L"Math Rock",
|
||||
L"New Romantic",
|
||||
L"Nu-Breakz",
|
||||
L"Post-Punk",
|
||||
L"Post-Rock",
|
||||
L"Psytrance",
|
||||
L"Shoegaze",
|
||||
L"Space Rock",
|
||||
L"Trop Rock",
|
||||
L"World Music",
|
||||
L"Neoclassical",
|
||||
L"Audiobook",
|
||||
L"Audio Theatre",
|
||||
L"Neue Deutsche Welle",
|
||||
L"Podcast",
|
||||
L"Indie Rock",
|
||||
L"G-Funk",
|
||||
L"Dubstep",
|
||||
L"Garage Rock",
|
||||
L"Psybient"
|
||||
};
|
||||
const int genresSize = sizeof(genres) / sizeof(genres[0]);
|
||||
}
|
||||
namespace {
|
||||
const wchar_t *genres[] = {
|
||||
L"Blues",
|
||||
L"Classic Rock",
|
||||
L"Country",
|
||||
L"Dance",
|
||||
L"Disco",
|
||||
L"Funk",
|
||||
L"Grunge",
|
||||
L"Hip-Hop",
|
||||
L"Jazz",
|
||||
L"Metal",
|
||||
L"New Age",
|
||||
L"Oldies",
|
||||
L"Other",
|
||||
L"Pop",
|
||||
L"R&B",
|
||||
L"Rap",
|
||||
L"Reggae",
|
||||
L"Rock",
|
||||
L"Techno",
|
||||
L"Industrial",
|
||||
L"Alternative",
|
||||
L"Ska",
|
||||
L"Death Metal",
|
||||
L"Pranks",
|
||||
L"Soundtrack",
|
||||
L"Euro-Techno",
|
||||
L"Ambient",
|
||||
L"Trip-Hop",
|
||||
L"Vocal",
|
||||
L"Jazz+Funk",
|
||||
L"Fusion",
|
||||
L"Trance",
|
||||
L"Classical",
|
||||
L"Instrumental",
|
||||
L"Acid",
|
||||
L"House",
|
||||
L"Game",
|
||||
L"Sound Clip",
|
||||
L"Gospel",
|
||||
L"Noise",
|
||||
L"Alternative Rock",
|
||||
L"Bass",
|
||||
L"Soul",
|
||||
L"Punk",
|
||||
L"Space",
|
||||
L"Meditative",
|
||||
L"Instrumental Pop",
|
||||
L"Instrumental Rock",
|
||||
L"Ethnic",
|
||||
L"Gothic",
|
||||
L"Darkwave",
|
||||
L"Techno-Industrial",
|
||||
L"Electronic",
|
||||
L"Pop-Folk",
|
||||
L"Eurodance",
|
||||
L"Dream",
|
||||
L"Southern Rock",
|
||||
L"Comedy",
|
||||
L"Cult",
|
||||
L"Gangsta",
|
||||
L"Top 40",
|
||||
L"Christian Rap",
|
||||
L"Pop/Funk",
|
||||
L"Jungle",
|
||||
L"Native American",
|
||||
L"Cabaret",
|
||||
L"New Wave",
|
||||
L"Psychedelic",
|
||||
L"Rave",
|
||||
L"Showtunes",
|
||||
L"Trailer",
|
||||
L"Lo-Fi",
|
||||
L"Tribal",
|
||||
L"Acid Punk",
|
||||
L"Acid Jazz",
|
||||
L"Polka",
|
||||
L"Retro",
|
||||
L"Musical",
|
||||
L"Rock & Roll",
|
||||
L"Hard Rock",
|
||||
L"Folk",
|
||||
L"Folk/Rock",
|
||||
L"National Folk",
|
||||
L"Swing",
|
||||
L"Fusion",
|
||||
L"Bebob",
|
||||
L"Latin",
|
||||
L"Revival",
|
||||
L"Celtic",
|
||||
L"Bluegrass",
|
||||
L"Avantgarde",
|
||||
L"Gothic Rock",
|
||||
L"Progressive Rock",
|
||||
L"Psychedelic Rock",
|
||||
L"Symphonic Rock",
|
||||
L"Slow Rock",
|
||||
L"Big Band",
|
||||
L"Chorus",
|
||||
L"Easy Listening",
|
||||
L"Acoustic",
|
||||
L"Humour",
|
||||
L"Speech",
|
||||
L"Chanson",
|
||||
L"Opera",
|
||||
L"Chamber Music",
|
||||
L"Sonata",
|
||||
L"Symphony",
|
||||
L"Booty Bass",
|
||||
L"Primus",
|
||||
L"Porn Groove",
|
||||
L"Satire",
|
||||
L"Slow Jam",
|
||||
L"Club",
|
||||
L"Tango",
|
||||
L"Samba",
|
||||
L"Folklore",
|
||||
L"Ballad",
|
||||
L"Power Ballad",
|
||||
L"Rhythmic Soul",
|
||||
L"Freestyle",
|
||||
L"Duet",
|
||||
L"Punk Rock",
|
||||
L"Drum Solo",
|
||||
L"A Cappella",
|
||||
L"Euro-House",
|
||||
L"Dance Hall",
|
||||
L"Goa",
|
||||
L"Drum & Bass",
|
||||
L"Club-House",
|
||||
L"Hardcore",
|
||||
L"Terror",
|
||||
L"Indie",
|
||||
L"BritPop",
|
||||
L"Negerpunk",
|
||||
L"Polsk Punk",
|
||||
L"Beat",
|
||||
L"Christian Gangsta Rap",
|
||||
L"Heavy Metal",
|
||||
L"Black Metal",
|
||||
L"Crossover",
|
||||
L"Contemporary Christian",
|
||||
L"Christian Rock",
|
||||
L"Merengue",
|
||||
L"Salsa",
|
||||
L"Thrash Metal",
|
||||
L"Anime",
|
||||
L"Jpop",
|
||||
L"Synthpop",
|
||||
L"Abstract",
|
||||
L"Art Rock",
|
||||
L"Baroque",
|
||||
L"Bhangra",
|
||||
L"Big Beat",
|
||||
L"Breakbeat",
|
||||
L"Chillout",
|
||||
L"Downtempo",
|
||||
L"Dub",
|
||||
L"EBM",
|
||||
L"Eclectic",
|
||||
L"Electro",
|
||||
L"Electroclash",
|
||||
L"Emo",
|
||||
L"Experimental",
|
||||
L"Garage",
|
||||
L"Global",
|
||||
L"IDM",
|
||||
L"Illbient",
|
||||
L"Industro-Goth",
|
||||
L"Jam Band",
|
||||
L"Krautrock",
|
||||
L"Leftfield",
|
||||
L"Lounge",
|
||||
L"Math Rock",
|
||||
L"New Romantic",
|
||||
L"Nu-Breakz",
|
||||
L"Post-Punk",
|
||||
L"Post-Rock",
|
||||
L"Psytrance",
|
||||
L"Shoegaze",
|
||||
L"Space Rock",
|
||||
L"Trop Rock",
|
||||
L"World Music",
|
||||
L"Neoclassical",
|
||||
L"Audiobook",
|
||||
L"Audio Theatre",
|
||||
L"Neue Deutsche Welle",
|
||||
L"Podcast",
|
||||
L"Indie Rock",
|
||||
L"G-Funk",
|
||||
L"Dubstep",
|
||||
L"Garage Rock",
|
||||
L"Psybient"
|
||||
};
|
||||
const int genresSize = sizeof(genres) / sizeof(genres[0]);
|
||||
} // namespace
|
||||
|
||||
StringList ID3v1::genreList()
|
||||
{
|
||||
StringList ID3v1::genreList() {
|
||||
StringList l;
|
||||
for(int i = 0; i < genresSize; i++) {
|
||||
for (int i = 0; i < genresSize; i++) {
|
||||
l.append(genres[i]);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
ID3v1::GenreMap ID3v1::genreMap()
|
||||
{
|
||||
ID3v1::GenreMap ID3v1::genreMap() {
|
||||
GenreMap m;
|
||||
for(int i = 0; i < genresSize; i++) {
|
||||
for (int i = 0; i < genresSize; i++) {
|
||||
m.insert(genres[i], i);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
String ID3v1::genre(int i)
|
||||
{
|
||||
if(i >= 0 && i < genresSize)
|
||||
return String(genres[i]); // always make a copy
|
||||
String ID3v1::genre(int i) {
|
||||
if (i >= 0 && i < genresSize)
|
||||
return String(genres[i]); // always make a copy
|
||||
else
|
||||
return String();
|
||||
}
|
||||
|
||||
int ID3v1::genreIndex(const String &name)
|
||||
{
|
||||
for(int i = 0; i < genresSize; ++i) {
|
||||
if(name == genres[i])
|
||||
int ID3v1::genreIndex(const String &name) {
|
||||
for (int i = 0; i < genresSize; ++i) {
|
||||
if (name == genres[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
26
3rdparty/taglib/mpeg/id3v1/id3v1genres.h
vendored
26
3rdparty/taglib/mpeg/id3v1/id3v1genres.h
vendored
@@ -32,37 +32,37 @@
|
||||
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
namespace ID3v1 {
|
||||
namespace ID3v1 {
|
||||
|
||||
typedef Map<String, int> GenreMap;
|
||||
typedef Map<String, int> GenreMap;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the list of canonical ID3v1 genre names in the order that they
|
||||
* are listed in the standard.
|
||||
*/
|
||||
StringList TAGLIB_EXPORT genreList();
|
||||
StringList TAGLIB_EXPORT genreList();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* A "reverse mapping" that goes from the canonical ID3v1 genre name to the
|
||||
* respective genre number. genreMap()["Rock"] ==
|
||||
*/
|
||||
GenreMap TAGLIB_EXPORT genreMap();
|
||||
GenreMap TAGLIB_EXPORT genreMap();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the name of the genre at \a index in the ID3v1 genre list. If
|
||||
* \a index is out of range -- less than zero or greater than 191 -- a null
|
||||
* string will be returned.
|
||||
*/
|
||||
String TAGLIB_EXPORT genre(int index);
|
||||
String TAGLIB_EXPORT genre(int index);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the genre index for the (case sensitive) genre \a name. If the
|
||||
* genre is not in the list 255 (which signifies an unknown genre in ID3v1)
|
||||
* will be returned.
|
||||
*/
|
||||
int TAGLIB_EXPORT genreIndex(const String &name);
|
||||
}
|
||||
}
|
||||
}
|
||||
int TAGLIB_EXPORT genreIndex(const String &name);
|
||||
} // namespace ID3v1
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
122
3rdparty/taglib/mpeg/id3v1/id3v1tag.cpp
vendored
122
3rdparty/taglib/mpeg/id3v1/id3v1tag.cpp
vendored
@@ -32,20 +32,17 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v1;
|
||||
|
||||
namespace
|
||||
{
|
||||
const ID3v1::StringHandler defaultStringHandler;
|
||||
const ID3v1::StringHandler *stringHandler = &defaultStringHandler;
|
||||
}
|
||||
namespace {
|
||||
const ID3v1::StringHandler defaultStringHandler;
|
||||
const ID3v1::StringHandler *stringHandler = &defaultStringHandler;
|
||||
} // namespace
|
||||
|
||||
class ID3v1::Tag::TagPrivate
|
||||
{
|
||||
public:
|
||||
TagPrivate() :
|
||||
file(0),
|
||||
tagOffset(0),
|
||||
track(0),
|
||||
genre(255) {}
|
||||
class ID3v1::Tag::TagPrivate {
|
||||
public:
|
||||
TagPrivate() : file(0),
|
||||
tagOffset(0),
|
||||
track(0),
|
||||
genre(255) {}
|
||||
|
||||
File *file;
|
||||
long tagOffset;
|
||||
@@ -63,18 +60,15 @@ public:
|
||||
// StringHandler implementation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
StringHandler::StringHandler()
|
||||
{
|
||||
StringHandler::StringHandler() {
|
||||
}
|
||||
|
||||
String ID3v1::StringHandler::parse(const ByteVector &data) const
|
||||
{
|
||||
String ID3v1::StringHandler::parse(const ByteVector &data) const {
|
||||
return String(data, String::Latin1).stripWhiteSpace();
|
||||
}
|
||||
|
||||
ByteVector ID3v1::StringHandler::render(const String &s) const
|
||||
{
|
||||
if(s.isLatin1())
|
||||
ByteVector ID3v1::StringHandler::render(const String &s) const {
|
||||
if (s.isLatin1())
|
||||
return s.data(String::Latin1);
|
||||
else
|
||||
return ByteVector();
|
||||
@@ -84,29 +78,23 @@ ByteVector ID3v1::StringHandler::render(const String &s) const
|
||||
// public methods
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ID3v1::Tag::Tag() :
|
||||
Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new TagPrivate())
|
||||
{
|
||||
ID3v1::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new TagPrivate()) {
|
||||
}
|
||||
|
||||
ID3v1::Tag::Tag(File *file, long tagOffset) :
|
||||
Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new TagPrivate())
|
||||
{
|
||||
ID3v1::Tag::Tag(File *file, long tagOffset) : Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new TagPrivate()) {
|
||||
d->file = file;
|
||||
d->tagOffset = tagOffset;
|
||||
|
||||
read();
|
||||
}
|
||||
|
||||
ID3v1::Tag::~Tag()
|
||||
{
|
||||
ID3v1::Tag::~Tag() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
ByteVector ID3v1::Tag::render() const
|
||||
{
|
||||
ByteVector ID3v1::Tag::render() const {
|
||||
ByteVector data;
|
||||
|
||||
data.append(fileIdentifier());
|
||||
@@ -122,94 +110,76 @@ ByteVector ID3v1::Tag::render() const
|
||||
return data;
|
||||
}
|
||||
|
||||
ByteVector ID3v1::Tag::fileIdentifier()
|
||||
{
|
||||
ByteVector ID3v1::Tag::fileIdentifier() {
|
||||
return ByteVector::fromCString("TAG");
|
||||
}
|
||||
|
||||
String ID3v1::Tag::title() const
|
||||
{
|
||||
String ID3v1::Tag::title() const {
|
||||
return d->title;
|
||||
}
|
||||
|
||||
String ID3v1::Tag::artist() const
|
||||
{
|
||||
String ID3v1::Tag::artist() const {
|
||||
return d->artist;
|
||||
}
|
||||
|
||||
String ID3v1::Tag::album() const
|
||||
{
|
||||
String ID3v1::Tag::album() const {
|
||||
return d->album;
|
||||
}
|
||||
|
||||
String ID3v1::Tag::comment() const
|
||||
{
|
||||
String ID3v1::Tag::comment() const {
|
||||
return d->comment;
|
||||
}
|
||||
|
||||
String ID3v1::Tag::genre() const
|
||||
{
|
||||
String ID3v1::Tag::genre() const {
|
||||
return ID3v1::genre(d->genre);
|
||||
}
|
||||
|
||||
unsigned int ID3v1::Tag::year() const
|
||||
{
|
||||
unsigned int ID3v1::Tag::year() const {
|
||||
return d->year.toInt();
|
||||
}
|
||||
|
||||
unsigned int ID3v1::Tag::track() const
|
||||
{
|
||||
unsigned int ID3v1::Tag::track() const {
|
||||
return d->track;
|
||||
}
|
||||
|
||||
void ID3v1::Tag::setTitle(const String &s)
|
||||
{
|
||||
void ID3v1::Tag::setTitle(const String &s) {
|
||||
d->title = s;
|
||||
}
|
||||
|
||||
void ID3v1::Tag::setArtist(const String &s)
|
||||
{
|
||||
void ID3v1::Tag::setArtist(const String &s) {
|
||||
d->artist = s;
|
||||
}
|
||||
|
||||
void ID3v1::Tag::setAlbum(const String &s)
|
||||
{
|
||||
void ID3v1::Tag::setAlbum(const String &s) {
|
||||
d->album = s;
|
||||
}
|
||||
|
||||
void ID3v1::Tag::setComment(const String &s)
|
||||
{
|
||||
void ID3v1::Tag::setComment(const String &s) {
|
||||
d->comment = s;
|
||||
}
|
||||
|
||||
void ID3v1::Tag::setGenre(const String &s)
|
||||
{
|
||||
void ID3v1::Tag::setGenre(const String &s) {
|
||||
d->genre = ID3v1::genreIndex(s);
|
||||
}
|
||||
|
||||
void ID3v1::Tag::setYear(unsigned int i)
|
||||
{
|
||||
void ID3v1::Tag::setYear(unsigned int i) {
|
||||
d->year = i > 0 ? String::number(i) : String();
|
||||
}
|
||||
|
||||
void ID3v1::Tag::setTrack(unsigned int i)
|
||||
{
|
||||
void ID3v1::Tag::setTrack(unsigned int i) {
|
||||
d->track = i < 256 ? i : 0;
|
||||
}
|
||||
|
||||
unsigned int ID3v1::Tag::genreNumber() const
|
||||
{
|
||||
unsigned int ID3v1::Tag::genreNumber() const {
|
||||
return d->genre;
|
||||
}
|
||||
|
||||
void ID3v1::Tag::setGenreNumber(unsigned int i)
|
||||
{
|
||||
void ID3v1::Tag::setGenreNumber(unsigned int i) {
|
||||
d->genre = i < 256 ? i : 255;
|
||||
}
|
||||
|
||||
void ID3v1::Tag::setStringHandler(const StringHandler *handler)
|
||||
{
|
||||
if(handler)
|
||||
void ID3v1::Tag::setStringHandler(const StringHandler *handler) {
|
||||
if (handler)
|
||||
stringHandler = handler;
|
||||
else
|
||||
stringHandler = &defaultStringHandler;
|
||||
@@ -219,23 +189,21 @@ void ID3v1::Tag::setStringHandler(const StringHandler *handler)
|
||||
// protected methods
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ID3v1::Tag::read()
|
||||
{
|
||||
if(d->file && d->file->isValid()) {
|
||||
void ID3v1::Tag::read() {
|
||||
if (d->file && d->file->isValid()) {
|
||||
d->file->seek(d->tagOffset);
|
||||
// read the tag -- always 128 bytes
|
||||
const ByteVector data = d->file->readBlock(128);
|
||||
|
||||
// some initial sanity checking
|
||||
if(data.size() == 128 && data.startsWith("TAG"))
|
||||
if (data.size() == 128 && data.startsWith("TAG"))
|
||||
parse(data);
|
||||
else
|
||||
debug("ID3v1 tag is not valid or could not be read at the specified offset.");
|
||||
}
|
||||
}
|
||||
|
||||
void ID3v1::Tag::parse(const ByteVector &data)
|
||||
{
|
||||
void ID3v1::Tag::parse(const ByteVector &data) {
|
||||
int offset = 3;
|
||||
|
||||
d->title = stringHandler->parse(data.mid(offset, 30));
|
||||
@@ -255,11 +223,11 @@ void ID3v1::Tag::parse(const ByteVector &data)
|
||||
// indicate the end of a C-String, specifically the comment string, a value of
|
||||
// zero must be assumed to be just that.
|
||||
|
||||
if(data[offset + 28] == 0 && data[offset + 29] != 0) {
|
||||
if (data[offset + 28] == 0 && data[offset + 29] != 0) {
|
||||
// ID3v1.1 detected
|
||||
|
||||
d->comment = stringHandler->parse(data.mid(offset, 28));
|
||||
d->track = static_cast<unsigned char>(data[offset + 29]);
|
||||
d->track = static_cast<unsigned char>(data[offset + 29]);
|
||||
}
|
||||
else
|
||||
d->comment = data.mid(offset, 30);
|
||||
|
||||
130
3rdparty/taglib/mpeg/id3v1/id3v1tag.h
vendored
130
3rdparty/taglib/mpeg/id3v1/id3v1tag.h
vendored
@@ -33,15 +33,15 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
class File;
|
||||
class File;
|
||||
|
||||
//! An ID3v1 implementation
|
||||
//! An ID3v1 implementation
|
||||
|
||||
namespace ID3v1 {
|
||||
namespace ID3v1 {
|
||||
|
||||
//! A abstraction for the string to data encoding in ID3v1 tags.
|
||||
//! A abstraction for the string to data encoding in ID3v1 tags.
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* ID3v1 should in theory always contain ISO-8859-1 (Latin1) data. In
|
||||
* practice it does not. TagLib by default only supports ISO-8859-1 data
|
||||
* in ID3v1 tags.
|
||||
@@ -58,20 +58,19 @@ namespace TagLib {
|
||||
* \see ID3v1::Tag::setStringHandler()
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT StringHandler
|
||||
{
|
||||
TAGLIB_IGNORE_MISSING_DESTRUCTOR
|
||||
public:
|
||||
// BIC: Add virtual destructor.
|
||||
StringHandler();
|
||||
class TAGLIB_EXPORT StringHandler {
|
||||
TAGLIB_IGNORE_MISSING_DESTRUCTOR
|
||||
public:
|
||||
// BIC: Add virtual destructor.
|
||||
StringHandler();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Decode a string from \a data. The default implementation assumes that
|
||||
* \a data is an ISO-8859-1 (Latin1) character array.
|
||||
*/
|
||||
virtual String parse(const ByteVector &data) const;
|
||||
virtual String parse(const ByteVector &data) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Encode a ByteVector with the data from \a s. The default implementation
|
||||
* assumes that \a s is an ISO-8859-1 (Latin1) string. If the string is
|
||||
* does not conform to ISO-8859-1, no value is written.
|
||||
@@ -80,12 +79,12 @@ namespace TagLib {
|
||||
* instead do not write an ID3v1 tag in the case that the data is not
|
||||
* ISO-8859-1.
|
||||
*/
|
||||
virtual ByteVector render(const String &s) const;
|
||||
};
|
||||
virtual ByteVector render(const String &s) const;
|
||||
};
|
||||
|
||||
//! The main class in the ID3v1 implementation
|
||||
//! The main class in the ID3v1 implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of the ID3v1 format. ID3v1 is both the simplest
|
||||
* and most common of tag formats but is rather limited. Because of its
|
||||
* pervasiveness and the way that applications have been written around the
|
||||
@@ -103,71 +102,70 @@ namespace TagLib {
|
||||
* truncation happens automatically when the tag is rendered.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
|
||||
public:
|
||||
/*!
|
||||
* Create an ID3v1 tag with default values.
|
||||
*/
|
||||
Tag();
|
||||
Tag();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Create an ID3v1 tag and parse the data in \a file starting at
|
||||
* \a tagOffset.
|
||||
*/
|
||||
Tag(File *file, long tagOffset);
|
||||
Tag(File *file, long tagOffset);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this Tag instance.
|
||||
*/
|
||||
virtual ~Tag();
|
||||
virtual ~Tag();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Renders the in memory values to a ByteVector suitable for writing to
|
||||
* the file.
|
||||
*/
|
||||
ByteVector render() const;
|
||||
ByteVector render() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the string "TAG" suitable for usage in locating the tag in a
|
||||
* file.
|
||||
*/
|
||||
static ByteVector fileIdentifier();
|
||||
static ByteVector fileIdentifier();
|
||||
|
||||
// Reimplementations.
|
||||
// Reimplementations.
|
||||
|
||||
virtual String title() const;
|
||||
virtual String artist() const;
|
||||
virtual String album() const;
|
||||
virtual String comment() const;
|
||||
virtual String genre() const;
|
||||
virtual unsigned int year() const;
|
||||
virtual unsigned int track() const;
|
||||
virtual String title() const;
|
||||
virtual String artist() const;
|
||||
virtual String album() const;
|
||||
virtual String comment() const;
|
||||
virtual String genre() const;
|
||||
virtual unsigned int year() const;
|
||||
virtual unsigned int track() const;
|
||||
|
||||
virtual void setTitle(const String &s);
|
||||
virtual void setArtist(const String &s);
|
||||
virtual void setAlbum(const String &s);
|
||||
virtual void setComment(const String &s);
|
||||
virtual void setGenre(const String &s);
|
||||
virtual void setYear(unsigned int i);
|
||||
virtual void setTrack(unsigned int i);
|
||||
virtual void setTitle(const String &s);
|
||||
virtual void setArtist(const String &s);
|
||||
virtual void setAlbum(const String &s);
|
||||
virtual void setComment(const String &s);
|
||||
virtual void setGenre(const String &s);
|
||||
virtual void setYear(unsigned int i);
|
||||
virtual void setTrack(unsigned int i);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the genre in number.
|
||||
*
|
||||
* \note Normally 255 indicates that this tag contains no genre.
|
||||
*/
|
||||
unsigned int genreNumber() const;
|
||||
unsigned int genreNumber() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the genre in number to \a i.
|
||||
*
|
||||
* \note Valid value is from 0 up to 255. Normally 255 indicates that
|
||||
* this tag contains no genre.
|
||||
*/
|
||||
void setGenreNumber(unsigned int i);
|
||||
void setGenreNumber(unsigned int i);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the string handler that decides how the ID3v1 data will be
|
||||
* converted to and from binary data.
|
||||
* If the parameter \a handler is null, the previous handler is
|
||||
@@ -178,27 +176,27 @@ namespace TagLib {
|
||||
*
|
||||
* \see StringHandler
|
||||
*/
|
||||
static void setStringHandler(const StringHandler *handler);
|
||||
static void setStringHandler(const StringHandler *handler);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
protected:
|
||||
/*!
|
||||
* Reads from the file specified in the constructor.
|
||||
*/
|
||||
void read();
|
||||
/*!
|
||||
void read();
|
||||
/*!
|
||||
* Pareses the body of the tag in \a data.
|
||||
*/
|
||||
void parse(const ByteVector &data);
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
private:
|
||||
Tag(const Tag &);
|
||||
Tag &operator=(const Tag &);
|
||||
private:
|
||||
Tag(const Tag &);
|
||||
Tag &operator=(const Tag &);
|
||||
|
||||
class TagPrivate;
|
||||
TagPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class TagPrivate;
|
||||
TagPrivate *d;
|
||||
};
|
||||
} // namespace ID3v1
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,9 +31,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class AttachedPictureFrame::AttachedPictureFramePrivate
|
||||
{
|
||||
public:
|
||||
class AttachedPictureFrame::AttachedPictureFramePrivate {
|
||||
public:
|
||||
AttachedPictureFramePrivate() : textEncoding(String::Latin1),
|
||||
type(AttachedPictureFrame::Other) {}
|
||||
|
||||
@@ -48,77 +47,61 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AttachedPictureFrame::AttachedPictureFrame() :
|
||||
Frame("APIC"),
|
||||
d(new AttachedPictureFramePrivate())
|
||||
{
|
||||
AttachedPictureFrame::AttachedPictureFrame() : Frame("APIC"),
|
||||
d(new AttachedPictureFramePrivate()) {
|
||||
}
|
||||
|
||||
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new AttachedPictureFramePrivate())
|
||||
{
|
||||
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : Frame(data),
|
||||
d(new AttachedPictureFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
AttachedPictureFrame::~AttachedPictureFrame()
|
||||
{
|
||||
AttachedPictureFrame::~AttachedPictureFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String AttachedPictureFrame::toString() const
|
||||
{
|
||||
String AttachedPictureFrame::toString() const {
|
||||
String s = "[" + d->mimeType + "]";
|
||||
return d->description.isEmpty() ? s : d->description + " " + s;
|
||||
}
|
||||
|
||||
String::Type AttachedPictureFrame::textEncoding() const
|
||||
{
|
||||
String::Type AttachedPictureFrame::textEncoding() const {
|
||||
return d->textEncoding;
|
||||
}
|
||||
|
||||
void AttachedPictureFrame::setTextEncoding(String::Type t)
|
||||
{
|
||||
void AttachedPictureFrame::setTextEncoding(String::Type t) {
|
||||
d->textEncoding = t;
|
||||
}
|
||||
|
||||
String AttachedPictureFrame::mimeType() const
|
||||
{
|
||||
String AttachedPictureFrame::mimeType() const {
|
||||
return d->mimeType;
|
||||
}
|
||||
|
||||
void AttachedPictureFrame::setMimeType(const String &m)
|
||||
{
|
||||
void AttachedPictureFrame::setMimeType(const String &m) {
|
||||
d->mimeType = m;
|
||||
}
|
||||
|
||||
AttachedPictureFrame::Type AttachedPictureFrame::type() const
|
||||
{
|
||||
AttachedPictureFrame::Type AttachedPictureFrame::type() const {
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void AttachedPictureFrame::setType(Type t)
|
||||
{
|
||||
void AttachedPictureFrame::setType(Type t) {
|
||||
d->type = t;
|
||||
}
|
||||
|
||||
String AttachedPictureFrame::description() const
|
||||
{
|
||||
String AttachedPictureFrame::description() const {
|
||||
return d->description;
|
||||
}
|
||||
|
||||
void AttachedPictureFrame::setDescription(const String &desc)
|
||||
{
|
||||
void AttachedPictureFrame::setDescription(const String &desc) {
|
||||
d->description = desc;
|
||||
}
|
||||
|
||||
ByteVector AttachedPictureFrame::picture() const
|
||||
{
|
||||
ByteVector AttachedPictureFrame::picture() const {
|
||||
return d->data;
|
||||
}
|
||||
|
||||
void AttachedPictureFrame::setPicture(const ByteVector &p)
|
||||
{
|
||||
void AttachedPictureFrame::setPicture(const ByteVector &p) {
|
||||
d->data = p;
|
||||
}
|
||||
|
||||
@@ -126,9 +109,8 @@ void AttachedPictureFrame::setPicture(const ByteVector &p)
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AttachedPictureFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < 5) {
|
||||
void AttachedPictureFrame::parseFields(const ByteVector &data) {
|
||||
if (data.size() < 5) {
|
||||
debug("A picture frame must contain at least 5 bytes.");
|
||||
return;
|
||||
}
|
||||
@@ -139,7 +121,7 @@ void AttachedPictureFrame::parseFields(const ByteVector &data)
|
||||
|
||||
d->mimeType = readStringField(data, String::Latin1, &pos);
|
||||
/* Now we need at least two more bytes available */
|
||||
if(static_cast<unsigned int>(pos) + 1 >= data.size()) {
|
||||
if (static_cast<unsigned int>(pos) + 1 >= data.size()) {
|
||||
debug("Truncated picture frame.");
|
||||
return;
|
||||
}
|
||||
@@ -150,8 +132,7 @@ void AttachedPictureFrame::parseFields(const ByteVector &data)
|
||||
d->data = data.mid(pos);
|
||||
}
|
||||
|
||||
ByteVector AttachedPictureFrame::renderFields() const
|
||||
{
|
||||
ByteVector AttachedPictureFrame::renderFields() const {
|
||||
ByteVector data;
|
||||
|
||||
String::Type encoding = checkTextEncoding(d->description, d->textEncoding);
|
||||
@@ -171,10 +152,8 @@ ByteVector AttachedPictureFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new AttachedPictureFramePrivate())
|
||||
{
|
||||
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new AttachedPictureFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -182,9 +161,8 @@ AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) :
|
||||
// support for ID3v2.2 PIC frames
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AttachedPictureFrameV22::parseFields(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < 5) {
|
||||
void AttachedPictureFrameV22::parseFields(const ByteVector &data) {
|
||||
if (data.size() < 5) {
|
||||
debug("A picture frame must contain at least 5 bytes.");
|
||||
return;
|
||||
}
|
||||
@@ -198,9 +176,11 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
|
||||
// convert fixed string image type to mime string
|
||||
if (fixedString.upper() == "JPG") {
|
||||
d->mimeType = "image/jpeg";
|
||||
} else if (fixedString.upper() == "PNG") {
|
||||
}
|
||||
else if (fixedString.upper() == "PNG") {
|
||||
d->mimeType = "image/png";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
debug("probably unsupported image type");
|
||||
d->mimeType = "image/" + fixedString;
|
||||
}
|
||||
@@ -211,8 +191,7 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
|
||||
d->data = data.mid(pos);
|
||||
}
|
||||
|
||||
AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header *h)
|
||||
{
|
||||
AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header *h) {
|
||||
// set v2.2 header to make fieldData work correctly
|
||||
setHeader(h, true);
|
||||
|
||||
|
||||
@@ -33,136 +33,134 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! An ID3v2 attached picture frame implementation
|
||||
//! An ID3v2 attached picture frame implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of ID3v2 attached pictures. Pictures may be
|
||||
* included in tags, one per APIC frame (but there may be multiple APIC
|
||||
* frames in a single tag). These pictures are usually in either JPEG or
|
||||
* PNG format.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT AttachedPictureFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT AttachedPictureFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* This describes the function or content of the picture.
|
||||
*/
|
||||
enum Type {
|
||||
//! A type not enumerated below
|
||||
Other = 0x00,
|
||||
//! 32x32 PNG image that should be used as the file icon
|
||||
FileIcon = 0x01,
|
||||
//! File icon of a different size or format
|
||||
OtherFileIcon = 0x02,
|
||||
//! Front cover image of the album
|
||||
FrontCover = 0x03,
|
||||
//! Back cover image of the album
|
||||
BackCover = 0x04,
|
||||
//! Inside leaflet page of the album
|
||||
LeafletPage = 0x05,
|
||||
//! Image from the album itself
|
||||
Media = 0x06,
|
||||
//! Picture of the lead artist or soloist
|
||||
LeadArtist = 0x07,
|
||||
//! Picture of the artist or performer
|
||||
Artist = 0x08,
|
||||
//! Picture of the conductor
|
||||
Conductor = 0x09,
|
||||
//! Picture of the band or orchestra
|
||||
Band = 0x0A,
|
||||
//! Picture of the composer
|
||||
Composer = 0x0B,
|
||||
//! Picture of the lyricist or text writer
|
||||
Lyricist = 0x0C,
|
||||
//! Picture of the recording location or studio
|
||||
RecordingLocation = 0x0D,
|
||||
//! Picture of the artists during recording
|
||||
DuringRecording = 0x0E,
|
||||
//! Picture of the artists during performance
|
||||
DuringPerformance = 0x0F,
|
||||
//! Picture from a movie or video related to the track
|
||||
MovieScreenCapture = 0x10,
|
||||
//! Picture of a large, coloured fish
|
||||
ColouredFish = 0x11,
|
||||
//! Illustration related to the track
|
||||
Illustration = 0x12,
|
||||
//! Logo of the band or performer
|
||||
BandLogo = 0x13,
|
||||
//! Logo of the publisher (record company)
|
||||
PublisherLogo = 0x14
|
||||
};
|
||||
enum Type {
|
||||
//! A type not enumerated below
|
||||
Other = 0x00,
|
||||
//! 32x32 PNG image that should be used as the file icon
|
||||
FileIcon = 0x01,
|
||||
//! File icon of a different size or format
|
||||
OtherFileIcon = 0x02,
|
||||
//! Front cover image of the album
|
||||
FrontCover = 0x03,
|
||||
//! Back cover image of the album
|
||||
BackCover = 0x04,
|
||||
//! Inside leaflet page of the album
|
||||
LeafletPage = 0x05,
|
||||
//! Image from the album itself
|
||||
Media = 0x06,
|
||||
//! Picture of the lead artist or soloist
|
||||
LeadArtist = 0x07,
|
||||
//! Picture of the artist or performer
|
||||
Artist = 0x08,
|
||||
//! Picture of the conductor
|
||||
Conductor = 0x09,
|
||||
//! Picture of the band or orchestra
|
||||
Band = 0x0A,
|
||||
//! Picture of the composer
|
||||
Composer = 0x0B,
|
||||
//! Picture of the lyricist or text writer
|
||||
Lyricist = 0x0C,
|
||||
//! Picture of the recording location or studio
|
||||
RecordingLocation = 0x0D,
|
||||
//! Picture of the artists during recording
|
||||
DuringRecording = 0x0E,
|
||||
//! Picture of the artists during performance
|
||||
DuringPerformance = 0x0F,
|
||||
//! Picture from a movie or video related to the track
|
||||
MovieScreenCapture = 0x10,
|
||||
//! Picture of a large, coloured fish
|
||||
ColouredFish = 0x11,
|
||||
//! Illustration related to the track
|
||||
Illustration = 0x12,
|
||||
//! Logo of the band or performer
|
||||
BandLogo = 0x13,
|
||||
//! Logo of the publisher (record company)
|
||||
PublisherLogo = 0x14
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an empty picture frame. The description, content and text
|
||||
* encoding should be set manually.
|
||||
*/
|
||||
AttachedPictureFrame();
|
||||
AttachedPictureFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an AttachedPicture frame based on \a data.
|
||||
*/
|
||||
explicit AttachedPictureFrame(const ByteVector &data);
|
||||
explicit AttachedPictureFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys the AttahcedPictureFrame instance.
|
||||
*/
|
||||
virtual ~AttachedPictureFrame();
|
||||
virtual ~AttachedPictureFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a string containing the description and mime-type
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text encoding used for the description.
|
||||
*
|
||||
* \see setTextEncoding()
|
||||
* \see description()
|
||||
*/
|
||||
String::Type textEncoding() const;
|
||||
String::Type textEncoding() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the text encoding used for the description.
|
||||
*
|
||||
* \see description()
|
||||
*/
|
||||
void setTextEncoding(String::Type t);
|
||||
void setTextEncoding(String::Type t);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the mime type of the image. This should in most cases be
|
||||
* "image/png" or "image/jpeg".
|
||||
*/
|
||||
String mimeType() const;
|
||||
String mimeType() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the mime type of the image. This should in most cases be
|
||||
* "image/png" or "image/jpeg".
|
||||
*/
|
||||
void setMimeType(const String &m);
|
||||
void setMimeType(const String &m);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the type of the image.
|
||||
*
|
||||
* \see Type
|
||||
* \see setType()
|
||||
*/
|
||||
Type type() const;
|
||||
Type type() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the type for the image.
|
||||
*
|
||||
* \see Type
|
||||
* \see type()
|
||||
*/
|
||||
void setType(Type t);
|
||||
void setType(Type t);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a text description of the image.
|
||||
*
|
||||
* \see setDescription()
|
||||
@@ -170,9 +168,9 @@ namespace TagLib {
|
||||
* \see setTextEncoding()
|
||||
*/
|
||||
|
||||
String description() const;
|
||||
String description() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets a textual description of the image to \a desc.
|
||||
*
|
||||
* \see description()
|
||||
@@ -180,9 +178,9 @@ namespace TagLib {
|
||||
* \see setTextEncoding()
|
||||
*/
|
||||
|
||||
void setDescription(const String &desc);
|
||||
void setDescription(const String &desc);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the image data as a ByteVector.
|
||||
*
|
||||
* \note ByteVector has a data() method that returns a const char * which
|
||||
@@ -191,9 +189,9 @@ namespace TagLib {
|
||||
* \see setPicture()
|
||||
* \see mimeType()
|
||||
*/
|
||||
ByteVector picture() const;
|
||||
ByteVector picture() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the image data to \a p. \a p should be of the type specified in
|
||||
* this frame's mime-type specification.
|
||||
*
|
||||
@@ -201,32 +199,31 @@ namespace TagLib {
|
||||
* \see mimeType()
|
||||
* \see setMimeType()
|
||||
*/
|
||||
void setPicture(const ByteVector &p);
|
||||
void setPicture(const ByteVector &p);
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
class AttachedPictureFramePrivate;
|
||||
AttachedPictureFramePrivate *d;
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
class AttachedPictureFramePrivate;
|
||||
AttachedPictureFramePrivate *d;
|
||||
|
||||
private:
|
||||
AttachedPictureFrame(const AttachedPictureFrame &);
|
||||
AttachedPictureFrame &operator=(const AttachedPictureFrame &);
|
||||
AttachedPictureFrame(const ByteVector &data, Header *h);
|
||||
private:
|
||||
AttachedPictureFrame(const AttachedPictureFrame &);
|
||||
AttachedPictureFrame &operator=(const AttachedPictureFrame &);
|
||||
AttachedPictureFrame(const ByteVector &data, Header *h);
|
||||
};
|
||||
|
||||
};
|
||||
//! support for ID3v2.2 PIC frames
|
||||
class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame {
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
|
||||
//! support for ID3v2.2 PIC frames
|
||||
class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame
|
||||
{
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
private:
|
||||
AttachedPictureFrameV22(const ByteVector &data, Header *h);
|
||||
friend class FrameFactory;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
AttachedPictureFrameV22(const ByteVector &data, Header *h);
|
||||
friend class FrameFactory;
|
||||
};
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
151
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.cpp
vendored
151
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.cpp
vendored
@@ -33,16 +33,13 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class ChapterFrame::ChapterFramePrivate
|
||||
{
|
||||
public:
|
||||
ChapterFramePrivate() :
|
||||
tagHeader(0),
|
||||
startTime(0),
|
||||
endTime(0),
|
||||
startOffset(0),
|
||||
endOffset(0)
|
||||
{
|
||||
class ChapterFrame::ChapterFramePrivate {
|
||||
public:
|
||||
ChapterFramePrivate() : tagHeader(0),
|
||||
startTime(0),
|
||||
endTime(0),
|
||||
startOffset(0),
|
||||
endOffset(0) {
|
||||
embeddedFrameList.setAutoDelete(true);
|
||||
}
|
||||
|
||||
@@ -60,21 +57,17 @@ public:
|
||||
// public methods
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) :
|
||||
ID3v2::Frame(data),
|
||||
d(new ChapterFramePrivate())
|
||||
{
|
||||
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) : ID3v2::Frame(data),
|
||||
d(new ChapterFramePrivate()) {
|
||||
d->tagHeader = tagHeader;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
ChapterFrame::ChapterFrame(const ByteVector &elementID,
|
||||
unsigned int startTime, unsigned int endTime,
|
||||
unsigned int startOffset, unsigned int endOffset,
|
||||
const FrameList &embeddedFrames) :
|
||||
ID3v2::Frame("CHAP"),
|
||||
d(new ChapterFramePrivate())
|
||||
{
|
||||
unsigned int startTime, unsigned int endTime,
|
||||
unsigned int startOffset, unsigned int endOffset,
|
||||
const FrameList &embeddedFrames) : ID3v2::Frame("CHAP"),
|
||||
d(new ChapterFramePrivate()) {
|
||||
// setElementID has a workaround for a previously silly API where you had to
|
||||
// specifically include the null byte.
|
||||
|
||||
@@ -85,92 +78,77 @@ ChapterFrame::ChapterFrame(const ByteVector &elementID,
|
||||
d->startOffset = startOffset;
|
||||
d->endOffset = endOffset;
|
||||
|
||||
for(FrameList::ConstIterator it = embeddedFrames.begin();
|
||||
it != embeddedFrames.end(); ++it)
|
||||
for (FrameList::ConstIterator it = embeddedFrames.begin();
|
||||
it != embeddedFrames.end();
|
||||
++it)
|
||||
addEmbeddedFrame(*it);
|
||||
}
|
||||
|
||||
ChapterFrame::~ChapterFrame()
|
||||
{
|
||||
ChapterFrame::~ChapterFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
ByteVector ChapterFrame::elementID() const
|
||||
{
|
||||
ByteVector ChapterFrame::elementID() const {
|
||||
return d->elementID;
|
||||
}
|
||||
|
||||
unsigned int ChapterFrame::startTime() const
|
||||
{
|
||||
unsigned int ChapterFrame::startTime() const {
|
||||
return d->startTime;
|
||||
}
|
||||
|
||||
unsigned int ChapterFrame::endTime() const
|
||||
{
|
||||
unsigned int ChapterFrame::endTime() const {
|
||||
return d->endTime;
|
||||
}
|
||||
|
||||
unsigned int ChapterFrame::startOffset() const
|
||||
{
|
||||
unsigned int ChapterFrame::startOffset() const {
|
||||
return d->startOffset;
|
||||
}
|
||||
|
||||
unsigned int ChapterFrame::endOffset() const
|
||||
{
|
||||
unsigned int ChapterFrame::endOffset() const {
|
||||
return d->endOffset;
|
||||
}
|
||||
|
||||
void ChapterFrame::setElementID(const ByteVector &eID)
|
||||
{
|
||||
void ChapterFrame::setElementID(const ByteVector &eID) {
|
||||
d->elementID = eID;
|
||||
|
||||
if(d->elementID.endsWith(char(0)))
|
||||
if (d->elementID.endsWith(char(0)))
|
||||
d->elementID = d->elementID.mid(0, d->elementID.size() - 1);
|
||||
}
|
||||
|
||||
void ChapterFrame::setStartTime(const unsigned int &sT)
|
||||
{
|
||||
void ChapterFrame::setStartTime(const unsigned int &sT) {
|
||||
d->startTime = sT;
|
||||
}
|
||||
|
||||
void ChapterFrame::setEndTime(const unsigned int &eT)
|
||||
{
|
||||
void ChapterFrame::setEndTime(const unsigned int &eT) {
|
||||
d->endTime = eT;
|
||||
}
|
||||
|
||||
void ChapterFrame::setStartOffset(const unsigned int &sO)
|
||||
{
|
||||
void ChapterFrame::setStartOffset(const unsigned int &sO) {
|
||||
d->startOffset = sO;
|
||||
}
|
||||
|
||||
void ChapterFrame::setEndOffset(const unsigned int &eO)
|
||||
{
|
||||
void ChapterFrame::setEndOffset(const unsigned int &eO) {
|
||||
d->endOffset = eO;
|
||||
}
|
||||
|
||||
const FrameListMap &ChapterFrame::embeddedFrameListMap() const
|
||||
{
|
||||
const FrameListMap &ChapterFrame::embeddedFrameListMap() const {
|
||||
return d->embeddedFrameListMap;
|
||||
}
|
||||
|
||||
const FrameList &ChapterFrame::embeddedFrameList() const
|
||||
{
|
||||
const FrameList &ChapterFrame::embeddedFrameList() const {
|
||||
return d->embeddedFrameList;
|
||||
}
|
||||
|
||||
const FrameList &ChapterFrame::embeddedFrameList(const ByteVector &frameID) const
|
||||
{
|
||||
const FrameList &ChapterFrame::embeddedFrameList(const ByteVector &frameID) const {
|
||||
return d->embeddedFrameListMap[frameID];
|
||||
}
|
||||
|
||||
void ChapterFrame::addEmbeddedFrame(Frame *frame)
|
||||
{
|
||||
void ChapterFrame::addEmbeddedFrame(Frame *frame) {
|
||||
d->embeddedFrameList.append(frame);
|
||||
d->embeddedFrameListMap[frame->frameID()].append(frame);
|
||||
}
|
||||
|
||||
void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del)
|
||||
{
|
||||
void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del) {
|
||||
// remove the frame from the frame list
|
||||
FrameList::Iterator it = d->embeddedFrameList.find(frame);
|
||||
d->embeddedFrameList.erase(it);
|
||||
@@ -180,33 +158,32 @@ void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del)
|
||||
d->embeddedFrameListMap[frame->frameID()].erase(it);
|
||||
|
||||
// ...and delete as desired
|
||||
if(del)
|
||||
if (del)
|
||||
delete frame;
|
||||
}
|
||||
|
||||
void ChapterFrame::removeEmbeddedFrames(const ByteVector &id)
|
||||
{
|
||||
void ChapterFrame::removeEmbeddedFrames(const ByteVector &id) {
|
||||
FrameList l = d->embeddedFrameListMap[id];
|
||||
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
removeEmbeddedFrame(*it, true);
|
||||
}
|
||||
|
||||
String ChapterFrame::toString() const
|
||||
{
|
||||
String ChapterFrame::toString() const {
|
||||
String s = String(d->elementID) +
|
||||
": start time: " + String::number(d->startTime) +
|
||||
", end time: " + String::number(d->endTime);
|
||||
": start time: " + String::number(d->startTime) +
|
||||
", end time: " + String::number(d->endTime);
|
||||
|
||||
if(d->startOffset != 0xFFFFFFFF)
|
||||
if (d->startOffset != 0xFFFFFFFF)
|
||||
s += ", start offset: " + String::number(d->startOffset);
|
||||
|
||||
if(d->endOffset != 0xFFFFFFFF)
|
||||
if (d->endOffset != 0xFFFFFFFF)
|
||||
s += ", end offset: " + String::number(d->endOffset);
|
||||
|
||||
if(!d->embeddedFrameList.isEmpty()) {
|
||||
if (!d->embeddedFrameList.isEmpty()) {
|
||||
StringList frameIDs;
|
||||
for(FrameList::ConstIterator it = d->embeddedFrameList.begin();
|
||||
it != d->embeddedFrameList.end(); ++it)
|
||||
for (FrameList::ConstIterator it = d->embeddedFrameList.begin();
|
||||
it != d->embeddedFrameList.end();
|
||||
++it)
|
||||
frameIDs.append((*it)->frameID());
|
||||
s += ", sub-frames: [ " + frameIDs.toString(", ") + " ]";
|
||||
}
|
||||
@@ -214,8 +191,7 @@ String ChapterFrame::toString() const
|
||||
return s;
|
||||
}
|
||||
|
||||
PropertyMap ChapterFrame::asProperties() const
|
||||
{
|
||||
PropertyMap ChapterFrame::asProperties() const {
|
||||
PropertyMap map;
|
||||
|
||||
map.unsupportedData().append(frameID() + String("/") + d->elementID);
|
||||
@@ -223,26 +199,24 @@ PropertyMap ChapterFrame::asProperties() const
|
||||
return map;
|
||||
}
|
||||
|
||||
ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) // static
|
||||
ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) // static
|
||||
{
|
||||
ID3v2::FrameList comments = tag->frameList("CHAP");
|
||||
|
||||
for(ID3v2::FrameList::ConstIterator it = comments.begin();
|
||||
it != comments.end();
|
||||
++it)
|
||||
{
|
||||
for (ID3v2::FrameList::ConstIterator it = comments.begin();
|
||||
it != comments.end();
|
||||
++it) {
|
||||
ChapterFrame *frame = dynamic_cast<ChapterFrame *>(*it);
|
||||
if(frame && frame->elementID() == eID)
|
||||
if (frame && frame->elementID() == eID)
|
||||
return frame;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ChapterFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void ChapterFrame::parseFields(const ByteVector &data) {
|
||||
unsigned int size = data.size();
|
||||
if(size < 18) {
|
||||
if (size < 18) {
|
||||
debug("A 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;
|
||||
@@ -263,17 +237,17 @@ void ChapterFrame::parseFields(const ByteVector &data)
|
||||
|
||||
// Embedded frames are optional
|
||||
|
||||
if(size < header()->size())
|
||||
if (size < header()->size())
|
||||
return;
|
||||
|
||||
while(embPos < size - header()->size()) {
|
||||
while (embPos < size - header()->size()) {
|
||||
Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);
|
||||
|
||||
if(!frame)
|
||||
if (!frame)
|
||||
return;
|
||||
|
||||
// Checks to make sure that frame parsed correctly.
|
||||
if(frame->size() <= 0) {
|
||||
if (frame->size() <= 0) {
|
||||
delete frame;
|
||||
return;
|
||||
}
|
||||
@@ -283,8 +257,7 @@ void ChapterFrame::parseFields(const ByteVector &data)
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector ChapterFrame::renderFields() const
|
||||
{
|
||||
ByteVector ChapterFrame::renderFields() const {
|
||||
ByteVector data;
|
||||
|
||||
data.append(d->elementID);
|
||||
@@ -294,16 +267,14 @@ ByteVector ChapterFrame::renderFields() const
|
||||
data.append(ByteVector::fromUInt(d->startOffset, true));
|
||||
data.append(ByteVector::fromUInt(d->endOffset, true));
|
||||
FrameList l = d->embeddedFrameList;
|
||||
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
data.append((*it)->render());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new ChapterFramePrivate())
|
||||
{
|
||||
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new ChapterFramePrivate()) {
|
||||
d->tagHeader = tagHeader;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
129
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.h
vendored
129
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.h
vendored
@@ -33,27 +33,26 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of ID3v2 chapter frames. The purpose of this
|
||||
* frame is to describe a single chapter within an audio file.
|
||||
*/
|
||||
|
||||
//! An implementation of ID3v2 chapter frames
|
||||
//! An implementation of ID3v2 chapter frames
|
||||
|
||||
class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Creates a chapter frame based on \a data. \a tagHeader is required as
|
||||
* the internal frames are parsed based on the tag version.
|
||||
*/
|
||||
ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data);
|
||||
ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Creates a chapter frame with the element ID \a elementID, start time
|
||||
* \a startTime, end time \a endTime, start offset \a startOffset,
|
||||
* end offset \a endOffset and optionally a list of embedded frames,
|
||||
@@ -62,95 +61,95 @@ namespace TagLib {
|
||||
*
|
||||
* All times are in milliseconds.
|
||||
*/
|
||||
ChapterFrame(const ByteVector &elementID,
|
||||
unsigned int startTime, unsigned int endTime,
|
||||
unsigned int startOffset, unsigned int endOffset,
|
||||
const FrameList &embeddedFrames = FrameList());
|
||||
ChapterFrame(const ByteVector &elementID,
|
||||
unsigned int startTime, unsigned int endTime,
|
||||
unsigned int startOffset, unsigned int endOffset,
|
||||
const FrameList &embeddedFrames = FrameList());
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys the frame.
|
||||
*/
|
||||
virtual ~ChapterFrame();
|
||||
virtual ~ChapterFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the element ID of the frame. Element ID
|
||||
* is a null terminated string, however it's not human-readable.
|
||||
*
|
||||
* \see setElementID()
|
||||
*/
|
||||
ByteVector elementID() const;
|
||||
ByteVector elementID() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns time of chapter's start (in milliseconds).
|
||||
*
|
||||
* \see setStartTime()
|
||||
*/
|
||||
unsigned int startTime() const;
|
||||
unsigned int startTime() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns time of chapter's end (in milliseconds).
|
||||
*
|
||||
* \see setEndTime()
|
||||
*/
|
||||
unsigned int endTime() const;
|
||||
unsigned int endTime() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns zero based byte offset (count of bytes from the beginning
|
||||
* of the audio file) of chapter's start.
|
||||
*
|
||||
* \note If returned value is 0xFFFFFFFF, start time should be used instead.
|
||||
* \see setStartOffset()
|
||||
*/
|
||||
unsigned int startOffset() const;
|
||||
unsigned int startOffset() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns zero based byte offset (count of bytes from the beginning
|
||||
* of the audio file) of chapter's end.
|
||||
*
|
||||
* \note If returned value is 0xFFFFFFFF, end time should be used instead.
|
||||
* \see setEndOffset()
|
||||
*/
|
||||
unsigned int endOffset() const;
|
||||
unsigned int endOffset() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the element ID of the frame to \a eID. If \a eID isn't
|
||||
* null terminated, a null char is appended automatically.
|
||||
*
|
||||
* \see elementID()
|
||||
*/
|
||||
void setElementID(const ByteVector &eID);
|
||||
void setElementID(const ByteVector &eID);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets time of chapter's start (in milliseconds) to \a sT.
|
||||
*
|
||||
* \see startTime()
|
||||
*/
|
||||
void setStartTime(const unsigned int &sT);
|
||||
void setStartTime(const unsigned int &sT);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets time of chapter's end (in milliseconds) to \a eT.
|
||||
*
|
||||
* \see endTime()
|
||||
*/
|
||||
void setEndTime(const unsigned int &eT);
|
||||
void setEndTime(const unsigned int &eT);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets zero based byte offset (count of bytes from the beginning
|
||||
* of the audio file) of chapter's start to \a sO.
|
||||
*
|
||||
* \see startOffset()
|
||||
*/
|
||||
void setStartOffset(const unsigned int &sO);
|
||||
void setStartOffset(const unsigned int &sO);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets zero based byte offset (count of bytes from the beginning
|
||||
* of the audio file) of chapter's end to \a eO.
|
||||
*
|
||||
* \see endOffset()
|
||||
*/
|
||||
void setEndOffset(const unsigned int &eO);
|
||||
void setEndOffset(const unsigned int &eO);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a reference to the frame list map. This is an FrameListMap of
|
||||
* all of the frames embedded in the CHAP frame.
|
||||
*
|
||||
@@ -164,9 +163,9 @@ namespace TagLib {
|
||||
*
|
||||
* \see embeddedFrameList()
|
||||
*/
|
||||
const FrameListMap &embeddedFrameListMap() const;
|
||||
const FrameListMap &embeddedFrameListMap() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a reference to the embedded frame list. This is an FrameList
|
||||
* of all of the frames embedded in the CHAP frame in the order that they
|
||||
* were parsed.
|
||||
@@ -177,9 +176,9 @@ namespace TagLib {
|
||||
* \warning You should not modify this data structure directly, instead
|
||||
* use addEmbeddedFrame() and removeEmbeddedFrame().
|
||||
*/
|
||||
const FrameList &embeddedFrameList() const;
|
||||
const FrameList &embeddedFrameList() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the embedded frame list for frames with the id \a frameID
|
||||
* or an empty list if there are no embedded frames of that type. This
|
||||
* is just a convenience and is equivalent to:
|
||||
@@ -190,62 +189,62 @@ namespace TagLib {
|
||||
*
|
||||
* \see embeddedFrameListMap()
|
||||
*/
|
||||
const FrameList &embeddedFrameList(const ByteVector &frameID) const;
|
||||
const FrameList &embeddedFrameList(const ByteVector &frameID) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Add an embedded frame to the CHAP frame. At this point the CHAP frame
|
||||
* takes ownership of the embedded frame and will handle freeing its memory.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
* returned by embeddedFrameList()
|
||||
*/
|
||||
void addEmbeddedFrame(Frame *frame);
|
||||
void addEmbeddedFrame(Frame *frame);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove an embedded frame from the CHAP frame. If \a del is true the frame's
|
||||
* memory will be freed; if it is false, it must be deleted by the user.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
* returned by embeddedFrameList()
|
||||
*/
|
||||
void removeEmbeddedFrame(Frame *frame, bool del = true);
|
||||
void removeEmbeddedFrame(Frame *frame, bool del = true);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove all embedded frames of type \a id from the CHAP frame and free their
|
||||
* memory.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
* returned by embeddedFrameList()
|
||||
*/
|
||||
void removeEmbeddedFrames(const ByteVector &id);
|
||||
void removeEmbeddedFrames(const ByteVector &id);
|
||||
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
PropertyMap asProperties() const;
|
||||
PropertyMap asProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* CHAP frames each have a unique element ID. This searches for a CHAP
|
||||
* frame with the element ID \a eID and returns a pointer to it. This
|
||||
* can be used to link CTOC and CHAP frames together.
|
||||
*
|
||||
* \see elementID()
|
||||
*/
|
||||
static ChapterFrame *findByElementID(const Tag *tag, const ByteVector &eID);
|
||||
static ChapterFrame *findByElementID(const Tag *tag, const ByteVector &eID);
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h);
|
||||
ChapterFrame(const ChapterFrame &);
|
||||
ChapterFrame &operator=(const ChapterFrame &);
|
||||
private:
|
||||
ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h);
|
||||
ChapterFrame(const ChapterFrame &);
|
||||
ChapterFrame &operator=(const ChapterFrame &);
|
||||
|
||||
class ChapterFramePrivate;
|
||||
ChapterFramePrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class ChapterFramePrivate;
|
||||
ChapterFramePrivate *d;
|
||||
};
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,9 +34,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class CommentsFrame::CommentsFramePrivate
|
||||
{
|
||||
public:
|
||||
class CommentsFrame::CommentsFramePrivate {
|
||||
public:
|
||||
CommentsFramePrivate() : textEncoding(String::Latin1) {}
|
||||
String::Type textEncoding;
|
||||
ByteVector language;
|
||||
@@ -48,91 +47,75 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CommentsFrame::CommentsFrame(String::Type encoding) :
|
||||
Frame("COMM"),
|
||||
d(new CommentsFramePrivate())
|
||||
{
|
||||
CommentsFrame::CommentsFrame(String::Type encoding) : Frame("COMM"),
|
||||
d(new CommentsFramePrivate()) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
CommentsFrame::CommentsFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new CommentsFramePrivate())
|
||||
{
|
||||
CommentsFrame::CommentsFrame(const ByteVector &data) : Frame(data),
|
||||
d(new CommentsFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
CommentsFrame::~CommentsFrame()
|
||||
{
|
||||
CommentsFrame::~CommentsFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String CommentsFrame::toString() const
|
||||
{
|
||||
String CommentsFrame::toString() const {
|
||||
return d->text;
|
||||
}
|
||||
|
||||
ByteVector CommentsFrame::language() const
|
||||
{
|
||||
ByteVector CommentsFrame::language() const {
|
||||
return d->language;
|
||||
}
|
||||
|
||||
String CommentsFrame::description() const
|
||||
{
|
||||
String CommentsFrame::description() const {
|
||||
return d->description;
|
||||
}
|
||||
|
||||
String CommentsFrame::text() const
|
||||
{
|
||||
String CommentsFrame::text() const {
|
||||
return d->text;
|
||||
}
|
||||
|
||||
void CommentsFrame::setLanguage(const ByteVector &languageEncoding)
|
||||
{
|
||||
void CommentsFrame::setLanguage(const ByteVector &languageEncoding) {
|
||||
d->language = languageEncoding.mid(0, 3);
|
||||
}
|
||||
|
||||
void CommentsFrame::setDescription(const String &s)
|
||||
{
|
||||
void CommentsFrame::setDescription(const String &s) {
|
||||
d->description = s;
|
||||
}
|
||||
|
||||
void CommentsFrame::setText(const String &s)
|
||||
{
|
||||
void CommentsFrame::setText(const String &s) {
|
||||
d->text = s;
|
||||
}
|
||||
|
||||
String::Type CommentsFrame::textEncoding() const
|
||||
{
|
||||
String::Type CommentsFrame::textEncoding() const {
|
||||
return d->textEncoding;
|
||||
}
|
||||
|
||||
void CommentsFrame::setTextEncoding(String::Type encoding)
|
||||
{
|
||||
void CommentsFrame::setTextEncoding(String::Type encoding) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
PropertyMap CommentsFrame::asProperties() const
|
||||
{
|
||||
PropertyMap CommentsFrame::asProperties() const {
|
||||
String key = description().upper();
|
||||
PropertyMap map;
|
||||
if(key.isEmpty() || key == "COMMENT")
|
||||
if (key.isEmpty() || key == "COMMENT")
|
||||
map.insert("COMMENT", text());
|
||||
else
|
||||
map.insert("COMMENT:" + key, text());
|
||||
return map;
|
||||
}
|
||||
|
||||
CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static
|
||||
CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static
|
||||
{
|
||||
ID3v2::FrameList comments = tag->frameList("COMM");
|
||||
|
||||
for(ID3v2::FrameList::ConstIterator it = comments.begin();
|
||||
it != comments.end();
|
||||
++it)
|
||||
{
|
||||
for (ID3v2::FrameList::ConstIterator it = comments.begin();
|
||||
it != comments.end();
|
||||
++it) {
|
||||
CommentsFrame *frame = dynamic_cast<CommentsFrame *>(*it);
|
||||
if(frame && frame->description() == d)
|
||||
if (frame && frame->description() == d)
|
||||
return frame;
|
||||
}
|
||||
|
||||
@@ -143,9 +126,8 @@ CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const Str
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CommentsFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < 5) {
|
||||
void CommentsFrame::parseFields(const ByteVector &data) {
|
||||
if (data.size() < 5) {
|
||||
debug("A comment frame must contain at least 5 bytes.");
|
||||
return;
|
||||
}
|
||||
@@ -157,19 +139,19 @@ void CommentsFrame::parseFields(const ByteVector &data)
|
||||
|
||||
ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2);
|
||||
|
||||
if(l.size() == 2) {
|
||||
if(d->textEncoding == String::Latin1) {
|
||||
if (l.size() == 2) {
|
||||
if (d->textEncoding == String::Latin1) {
|
||||
d->description = Tag::latin1StringHandler()->parse(l.front());
|
||||
d->text = Tag::latin1StringHandler()->parse(l.back());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
d->description = String(l.front(), d->textEncoding);
|
||||
d->text = String(l.back(), d->textEncoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector CommentsFrame::renderFields() const
|
||||
{
|
||||
ByteVector CommentsFrame::renderFields() const {
|
||||
ByteVector v;
|
||||
|
||||
String::Type encoding = d->textEncoding;
|
||||
@@ -190,9 +172,7 @@ ByteVector CommentsFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new CommentsFramePrivate())
|
||||
{
|
||||
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new CommentsFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -32,44 +32,43 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! An implementation of ID3v2 comments
|
||||
//! An implementation of ID3v2 comments
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This implements the ID3v2 comment format. An ID3v2 comment consists of
|
||||
* a language encoding, a description and a single text field.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT CommentsFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT CommentsFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Construct an empty comment frame that will use the text encoding
|
||||
* \a encoding.
|
||||
*/
|
||||
explicit CommentsFrame(String::Type encoding = String::Latin1);
|
||||
explicit CommentsFrame(String::Type encoding = String::Latin1);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Construct a comment based on the data in \a data.
|
||||
*/
|
||||
explicit CommentsFrame(const ByteVector &data);
|
||||
explicit CommentsFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this CommentFrame instance.
|
||||
*/
|
||||
virtual ~CommentsFrame();
|
||||
virtual ~CommentsFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text of this comment.
|
||||
*
|
||||
* \see text()
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the language encoding as a 3 byte encoding as specified by
|
||||
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
|
||||
*
|
||||
@@ -77,48 +76,48 @@ namespace TagLib {
|
||||
*
|
||||
* \see setLanguage()
|
||||
*/
|
||||
ByteVector language() const;
|
||||
ByteVector language() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the description of this comment.
|
||||
*
|
||||
* \note Most taggers simply ignore this value.
|
||||
*
|
||||
* \see setDescription()
|
||||
*/
|
||||
String description() const;
|
||||
String description() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text of this comment.
|
||||
*
|
||||
* \see setText()
|
||||
*/
|
||||
String text() const;
|
||||
String text() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the language using the 3 byte language code from
|
||||
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
|
||||
* \a languageCode.
|
||||
*
|
||||
* \see language()
|
||||
*/
|
||||
void setLanguage(const ByteVector &languageCode);
|
||||
void setLanguage(const ByteVector &languageCode);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the description of the comment to \a s.
|
||||
*
|
||||
* \see description()
|
||||
*/
|
||||
void setDescription(const String &s);
|
||||
void setDescription(const String &s);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the text portion of the comment to \a s.
|
||||
*
|
||||
* \see text()
|
||||
*/
|
||||
virtual void setText(const String &s);
|
||||
virtual void setText(const String &s);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text encoding that will be used in rendering this frame.
|
||||
* This defaults to the type that was either specified in the constructor
|
||||
* or read from the frame when parsed.
|
||||
@@ -126,18 +125,18 @@ namespace TagLib {
|
||||
* \see setTextEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
String::Type textEncoding() const;
|
||||
String::Type textEncoding() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the text encoding to be used when rendering this frame to
|
||||
* \a encoding.
|
||||
*
|
||||
* \see textEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
void setTextEncoding(String::Type encoding);
|
||||
void setTextEncoding(String::Type encoding);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Parses this frame as PropertyMap with a single key.
|
||||
* - if description() is empty or "COMMENT", the key will be "COMMENT"
|
||||
* - if description() is not a valid PropertyMap key, the frame will be
|
||||
@@ -146,36 +145,36 @@ namespace TagLib {
|
||||
* - otherwise, the key will be "COMMENT:<description>"
|
||||
* - The single value will be the frame's text().
|
||||
*/
|
||||
PropertyMap asProperties() const;
|
||||
PropertyMap asProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Comments each have a unique description. This searches for a comment
|
||||
* frame with the description \a d and returns a pointer to it. If no
|
||||
* frame is found that matches the given description null is returned.
|
||||
*
|
||||
* \see description()
|
||||
*/
|
||||
static CommentsFrame *findByDescription(const Tag *tag, const String &d);
|
||||
static CommentsFrame *findByDescription(const Tag *tag, const String &d);
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
private:
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
CommentsFrame(const ByteVector &data, Header *h);
|
||||
CommentsFrame(const CommentsFrame &);
|
||||
CommentsFrame &operator=(const CommentsFrame &);
|
||||
CommentsFrame(const ByteVector &data, Header *h);
|
||||
CommentsFrame(const CommentsFrame &);
|
||||
CommentsFrame &operator=(const CommentsFrame &);
|
||||
|
||||
class CommentsFramePrivate;
|
||||
CommentsFramePrivate *d;
|
||||
};
|
||||
class CommentsFramePrivate;
|
||||
CommentsFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
@@ -32,11 +32,9 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class EventTimingCodesFrame::EventTimingCodesFramePrivate
|
||||
{
|
||||
public:
|
||||
EventTimingCodesFramePrivate() :
|
||||
timestampFormat(EventTimingCodesFrame::AbsoluteMilliseconds) {}
|
||||
class EventTimingCodesFrame::EventTimingCodesFramePrivate {
|
||||
public:
|
||||
EventTimingCodesFramePrivate() : timestampFormat(EventTimingCodesFrame::AbsoluteMilliseconds) {}
|
||||
EventTimingCodesFrame::TimestampFormat timestampFormat;
|
||||
EventTimingCodesFrame::SynchedEventList synchedEvents;
|
||||
};
|
||||
@@ -45,50 +43,40 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EventTimingCodesFrame::EventTimingCodesFrame() :
|
||||
Frame("ETCO"),
|
||||
d(new EventTimingCodesFramePrivate())
|
||||
{
|
||||
EventTimingCodesFrame::EventTimingCodesFrame() : Frame("ETCO"),
|
||||
d(new EventTimingCodesFramePrivate()) {
|
||||
}
|
||||
|
||||
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new EventTimingCodesFramePrivate())
|
||||
{
|
||||
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) : Frame(data),
|
||||
d(new EventTimingCodesFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
EventTimingCodesFrame::~EventTimingCodesFrame()
|
||||
{
|
||||
EventTimingCodesFrame::~EventTimingCodesFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String EventTimingCodesFrame::toString() const
|
||||
{
|
||||
String EventTimingCodesFrame::toString() const {
|
||||
return String();
|
||||
}
|
||||
|
||||
EventTimingCodesFrame::TimestampFormat
|
||||
EventTimingCodesFrame::timestampFormat() const
|
||||
{
|
||||
EventTimingCodesFrame::timestampFormat() const {
|
||||
return d->timestampFormat;
|
||||
}
|
||||
|
||||
EventTimingCodesFrame::SynchedEventList
|
||||
EventTimingCodesFrame::synchedEvents() const
|
||||
{
|
||||
EventTimingCodesFrame::synchedEvents() const {
|
||||
return d->synchedEvents;
|
||||
}
|
||||
|
||||
void EventTimingCodesFrame::setTimestampFormat(
|
||||
EventTimingCodesFrame::TimestampFormat f)
|
||||
{
|
||||
EventTimingCodesFrame::TimestampFormat f) {
|
||||
d->timestampFormat = f;
|
||||
}
|
||||
|
||||
void EventTimingCodesFrame::setSynchedEvents(
|
||||
const EventTimingCodesFrame::SynchedEventList &e)
|
||||
{
|
||||
const EventTimingCodesFrame::SynchedEventList &e) {
|
||||
d->synchedEvents = e;
|
||||
}
|
||||
|
||||
@@ -96,10 +84,9 @@ void EventTimingCodesFrame::setSynchedEvents(
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EventTimingCodesFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void EventTimingCodesFrame::parseFields(const ByteVector &data) {
|
||||
const int end = data.size();
|
||||
if(end < 1) {
|
||||
if (end < 1) {
|
||||
debug("An event timing codes frame must contain at least 1 byte.");
|
||||
return;
|
||||
}
|
||||
@@ -108,7 +95,7 @@ void EventTimingCodesFrame::parseFields(const ByteVector &data)
|
||||
|
||||
int pos = 1;
|
||||
d->synchedEvents.clear();
|
||||
while(pos + 4 < end) {
|
||||
while (pos + 4 < end) {
|
||||
EventType type = static_cast<EventType>(static_cast<unsigned char>(data[pos++]));
|
||||
unsigned int time = data.toUInt(pos, true);
|
||||
pos += 4;
|
||||
@@ -116,14 +103,13 @@ void EventTimingCodesFrame::parseFields(const ByteVector &data)
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector EventTimingCodesFrame::renderFields() const
|
||||
{
|
||||
ByteVector EventTimingCodesFrame::renderFields() const {
|
||||
ByteVector v;
|
||||
|
||||
v.append(char(d->timestampFormat));
|
||||
for(SynchedEventList::ConstIterator it = d->synchedEvents.begin();
|
||||
it != d->synchedEvents.end();
|
||||
++it) {
|
||||
for (SynchedEventList::ConstIterator it = d->synchedEvents.begin();
|
||||
it != d->synchedEvents.end();
|
||||
++it) {
|
||||
const SynchedEvent &entry = *it;
|
||||
v.append(char(entry.type));
|
||||
v.append(ByteVector::fromUInt(entry.time));
|
||||
@@ -136,9 +122,7 @@ ByteVector EventTimingCodesFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new EventTimingCodesFramePrivate())
|
||||
{
|
||||
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new EventTimingCodesFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -32,156 +32,154 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! ID3v2 event timing codes frame
|
||||
/*!
|
||||
//! ID3v2 event timing codes frame
|
||||
/*!
|
||||
* An implementation of ID3v2 event timing codes.
|
||||
*/
|
||||
class TAGLIB_EXPORT EventTimingCodesFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT EventTimingCodesFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Specifies the timestamp format used.
|
||||
*/
|
||||
enum TimestampFormat {
|
||||
//! The timestamp is of unknown format.
|
||||
Unknown = 0x00,
|
||||
//! The timestamp represents the number of MPEG frames since
|
||||
//! the beginning of the audio stream.
|
||||
AbsoluteMpegFrames = 0x01,
|
||||
//! The timestamp represents the number of milliseconds since
|
||||
//! the beginning of the audio stream.
|
||||
AbsoluteMilliseconds = 0x02
|
||||
};
|
||||
enum TimestampFormat {
|
||||
//! The timestamp is of unknown format.
|
||||
Unknown = 0x00,
|
||||
//! The timestamp represents the number of MPEG frames since
|
||||
//! the beginning of the audio stream.
|
||||
AbsoluteMpegFrames = 0x01,
|
||||
//! The timestamp represents the number of milliseconds since
|
||||
//! the beginning of the audio stream.
|
||||
AbsoluteMilliseconds = 0x02
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Event types defined in id3v2.4.0-frames.txt 4.5. Event timing codes.
|
||||
*/
|
||||
enum EventType {
|
||||
Padding = 0x00,
|
||||
EndOfInitialSilence = 0x01,
|
||||
IntroStart = 0x02,
|
||||
MainPartStart = 0x03,
|
||||
OutroStart = 0x04,
|
||||
OutroEnd = 0x05,
|
||||
VerseStart = 0x06,
|
||||
RefrainStart = 0x07,
|
||||
InterludeStart = 0x08,
|
||||
ThemeStart = 0x09,
|
||||
VariationStart = 0x0a,
|
||||
KeyChange = 0x0b,
|
||||
TimeChange = 0x0c,
|
||||
MomentaryUnwantedNoise = 0x0d,
|
||||
SustainedNoise = 0x0e,
|
||||
SustainedNoiseEnd = 0x0f,
|
||||
IntroEnd = 0x10,
|
||||
MainPartEnd = 0x11,
|
||||
VerseEnd = 0x12,
|
||||
RefrainEnd = 0x13,
|
||||
ThemeEnd = 0x14,
|
||||
Profanity = 0x15,
|
||||
ProfanityEnd = 0x16,
|
||||
NotPredefinedSynch0 = 0xe0,
|
||||
NotPredefinedSynch1 = 0xe1,
|
||||
NotPredefinedSynch2 = 0xe2,
|
||||
NotPredefinedSynch3 = 0xe3,
|
||||
NotPredefinedSynch4 = 0xe4,
|
||||
NotPredefinedSynch5 = 0xe5,
|
||||
NotPredefinedSynch6 = 0xe6,
|
||||
NotPredefinedSynch7 = 0xe7,
|
||||
NotPredefinedSynch8 = 0xe8,
|
||||
NotPredefinedSynch9 = 0xe9,
|
||||
NotPredefinedSynchA = 0xea,
|
||||
NotPredefinedSynchB = 0xeb,
|
||||
NotPredefinedSynchC = 0xec,
|
||||
NotPredefinedSynchD = 0xed,
|
||||
NotPredefinedSynchE = 0xee,
|
||||
NotPredefinedSynchF = 0xef,
|
||||
AudioEnd = 0xfd,
|
||||
AudioFileEnds = 0xfe
|
||||
};
|
||||
enum EventType {
|
||||
Padding = 0x00,
|
||||
EndOfInitialSilence = 0x01,
|
||||
IntroStart = 0x02,
|
||||
MainPartStart = 0x03,
|
||||
OutroStart = 0x04,
|
||||
OutroEnd = 0x05,
|
||||
VerseStart = 0x06,
|
||||
RefrainStart = 0x07,
|
||||
InterludeStart = 0x08,
|
||||
ThemeStart = 0x09,
|
||||
VariationStart = 0x0a,
|
||||
KeyChange = 0x0b,
|
||||
TimeChange = 0x0c,
|
||||
MomentaryUnwantedNoise = 0x0d,
|
||||
SustainedNoise = 0x0e,
|
||||
SustainedNoiseEnd = 0x0f,
|
||||
IntroEnd = 0x10,
|
||||
MainPartEnd = 0x11,
|
||||
VerseEnd = 0x12,
|
||||
RefrainEnd = 0x13,
|
||||
ThemeEnd = 0x14,
|
||||
Profanity = 0x15,
|
||||
ProfanityEnd = 0x16,
|
||||
NotPredefinedSynch0 = 0xe0,
|
||||
NotPredefinedSynch1 = 0xe1,
|
||||
NotPredefinedSynch2 = 0xe2,
|
||||
NotPredefinedSynch3 = 0xe3,
|
||||
NotPredefinedSynch4 = 0xe4,
|
||||
NotPredefinedSynch5 = 0xe5,
|
||||
NotPredefinedSynch6 = 0xe6,
|
||||
NotPredefinedSynch7 = 0xe7,
|
||||
NotPredefinedSynch8 = 0xe8,
|
||||
NotPredefinedSynch9 = 0xe9,
|
||||
NotPredefinedSynchA = 0xea,
|
||||
NotPredefinedSynchB = 0xeb,
|
||||
NotPredefinedSynchC = 0xec,
|
||||
NotPredefinedSynchD = 0xed,
|
||||
NotPredefinedSynchE = 0xee,
|
||||
NotPredefinedSynchF = 0xef,
|
||||
AudioEnd = 0xfd,
|
||||
AudioFileEnds = 0xfe
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Single entry of time stamp and event.
|
||||
*/
|
||||
struct SynchedEvent {
|
||||
SynchedEvent(unsigned int ms, EventType t) : time(ms), type(t) {}
|
||||
unsigned int time;
|
||||
EventType type;
|
||||
};
|
||||
struct SynchedEvent {
|
||||
SynchedEvent(unsigned int ms, EventType t) : time(ms), type(t) {}
|
||||
unsigned int time;
|
||||
EventType type;
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* List of synchronized events.
|
||||
*/
|
||||
typedef Strawberry_TagLib::TagLib::List<SynchedEvent> SynchedEventList;
|
||||
typedef Strawberry_TagLib::TagLib::List<SynchedEvent> SynchedEventList;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Construct an empty event timing codes frame.
|
||||
*/
|
||||
explicit EventTimingCodesFrame();
|
||||
explicit EventTimingCodesFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Construct a event timing codes frame based on the data in \a data.
|
||||
*/
|
||||
explicit EventTimingCodesFrame(const ByteVector &data);
|
||||
explicit EventTimingCodesFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this EventTimingCodesFrame instance.
|
||||
*/
|
||||
virtual ~EventTimingCodesFrame();
|
||||
virtual ~EventTimingCodesFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a null string.
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the timestamp format.
|
||||
*/
|
||||
TimestampFormat timestampFormat() const;
|
||||
TimestampFormat timestampFormat() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the events with the time stamps.
|
||||
*/
|
||||
SynchedEventList synchedEvents() const;
|
||||
SynchedEventList synchedEvents() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the timestamp format.
|
||||
*
|
||||
* \see timestampFormat()
|
||||
*/
|
||||
void setTimestampFormat(TimestampFormat f);
|
||||
void setTimestampFormat(TimestampFormat f);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the text with the time stamps.
|
||||
*
|
||||
* \see text()
|
||||
*/
|
||||
void setSynchedEvents(const SynchedEventList &e);
|
||||
void setSynchedEvents(const SynchedEventList &e);
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
private:
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
EventTimingCodesFrame(const ByteVector &data, Header *h);
|
||||
EventTimingCodesFrame(const EventTimingCodesFrame &);
|
||||
EventTimingCodesFrame &operator=(const EventTimingCodesFrame &);
|
||||
EventTimingCodesFrame(const ByteVector &data, Header *h);
|
||||
EventTimingCodesFrame(const EventTimingCodesFrame &);
|
||||
EventTimingCodesFrame &operator=(const EventTimingCodesFrame &);
|
||||
|
||||
class EventTimingCodesFramePrivate;
|
||||
EventTimingCodesFramePrivate *d;
|
||||
};
|
||||
class EventTimingCodesFramePrivate;
|
||||
EventTimingCodesFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
@@ -34,9 +34,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFramePrivate
|
||||
{
|
||||
public:
|
||||
class GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFramePrivate {
|
||||
public:
|
||||
GeneralEncapsulatedObjectFramePrivate() : textEncoding(String::Latin1) {}
|
||||
|
||||
String::Type textEncoding;
|
||||
@@ -50,84 +49,68 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() :
|
||||
Frame("GEOB"),
|
||||
d(new GeneralEncapsulatedObjectFramePrivate())
|
||||
{
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() : Frame("GEOB"),
|
||||
d(new GeneralEncapsulatedObjectFramePrivate()) {
|
||||
}
|
||||
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new GeneralEncapsulatedObjectFramePrivate())
|
||||
{
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) : Frame(data),
|
||||
d(new GeneralEncapsulatedObjectFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
GeneralEncapsulatedObjectFrame::~GeneralEncapsulatedObjectFrame()
|
||||
{
|
||||
GeneralEncapsulatedObjectFrame::~GeneralEncapsulatedObjectFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String GeneralEncapsulatedObjectFrame::toString() const
|
||||
{
|
||||
String GeneralEncapsulatedObjectFrame::toString() const {
|
||||
String text = "[" + d->mimeType + "]";
|
||||
|
||||
if(!d->fileName.isEmpty())
|
||||
if (!d->fileName.isEmpty())
|
||||
text += " " + d->fileName;
|
||||
|
||||
if(!d->description.isEmpty())
|
||||
if (!d->description.isEmpty())
|
||||
text += " \"" + d->description + "\"";
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
String::Type GeneralEncapsulatedObjectFrame::textEncoding() const
|
||||
{
|
||||
String::Type GeneralEncapsulatedObjectFrame::textEncoding() const {
|
||||
return d->textEncoding;
|
||||
}
|
||||
|
||||
void GeneralEncapsulatedObjectFrame::setTextEncoding(String::Type encoding)
|
||||
{
|
||||
void GeneralEncapsulatedObjectFrame::setTextEncoding(String::Type encoding) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
String GeneralEncapsulatedObjectFrame::mimeType() const
|
||||
{
|
||||
String GeneralEncapsulatedObjectFrame::mimeType() const {
|
||||
return d->mimeType;
|
||||
}
|
||||
|
||||
void GeneralEncapsulatedObjectFrame::setMimeType(const String &type)
|
||||
{
|
||||
void GeneralEncapsulatedObjectFrame::setMimeType(const String &type) {
|
||||
d->mimeType = type;
|
||||
}
|
||||
|
||||
String GeneralEncapsulatedObjectFrame::fileName() const
|
||||
{
|
||||
String GeneralEncapsulatedObjectFrame::fileName() const {
|
||||
return d->fileName;
|
||||
}
|
||||
|
||||
void GeneralEncapsulatedObjectFrame::setFileName(const String &name)
|
||||
{
|
||||
void GeneralEncapsulatedObjectFrame::setFileName(const String &name) {
|
||||
d->fileName = name;
|
||||
}
|
||||
|
||||
String GeneralEncapsulatedObjectFrame::description() const
|
||||
{
|
||||
String GeneralEncapsulatedObjectFrame::description() const {
|
||||
return d->description;
|
||||
}
|
||||
|
||||
void GeneralEncapsulatedObjectFrame::setDescription(const String &desc)
|
||||
{
|
||||
void GeneralEncapsulatedObjectFrame::setDescription(const String &desc) {
|
||||
d->description = desc;
|
||||
}
|
||||
|
||||
ByteVector GeneralEncapsulatedObjectFrame::object() const
|
||||
{
|
||||
ByteVector GeneralEncapsulatedObjectFrame::object() const {
|
||||
return d->data;
|
||||
}
|
||||
|
||||
void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data)
|
||||
{
|
||||
void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data) {
|
||||
d->data = data;
|
||||
}
|
||||
|
||||
@@ -135,9 +118,8 @@ void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data)
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < 4) {
|
||||
void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data) {
|
||||
if (data.size() < 4) {
|
||||
debug("An object frame must contain at least 4 bytes.");
|
||||
return;
|
||||
}
|
||||
@@ -153,8 +135,7 @@ void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data)
|
||||
d->data = data.mid(pos);
|
||||
}
|
||||
|
||||
ByteVector GeneralEncapsulatedObjectFrame::renderFields() const
|
||||
{
|
||||
ByteVector GeneralEncapsulatedObjectFrame::renderFields() const {
|
||||
StringList sl;
|
||||
sl.append(d->fileName);
|
||||
sl.append(d->description);
|
||||
@@ -179,9 +160,7 @@ ByteVector GeneralEncapsulatedObjectFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new GeneralEncapsulatedObjectFramePrivate())
|
||||
{
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new GeneralEncapsulatedObjectFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -36,11 +36,11 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! An ID3v2 general encapsulated object frame implementation
|
||||
//! An ID3v2 general encapsulated object frame implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of ID3v2 general encapsulated objects.
|
||||
* Arbitrary binary data may be included in tags, stored in GEOB frames.
|
||||
* There may be multiple GEOB frames in a single tag. Each GEOB it
|
||||
@@ -49,79 +49,77 @@ namespace TagLib {
|
||||
* uniquely identifies the GEOB frame in the tag.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty object frame. The description, file name and text
|
||||
* encoding should be set manually.
|
||||
*/
|
||||
GeneralEncapsulatedObjectFrame();
|
||||
GeneralEncapsulatedObjectFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs a GeneralEncapsulatedObjectFrame frame based on \a data.
|
||||
*
|
||||
* \warning This is \em not data for the encapsulated object, for that use
|
||||
* setObject(). This constructor is used when reading the frame from the
|
||||
* disk.
|
||||
*/
|
||||
explicit GeneralEncapsulatedObjectFrame(const ByteVector &data);
|
||||
explicit GeneralEncapsulatedObjectFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys the GeneralEncapsulatedObjectFrame instance.
|
||||
*/
|
||||
virtual ~GeneralEncapsulatedObjectFrame();
|
||||
virtual ~GeneralEncapsulatedObjectFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a string containing the description, file name and mime-type
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text encoding used for the description and file name.
|
||||
*
|
||||
* \see setTextEncoding()
|
||||
* \see description()
|
||||
* \see fileName()
|
||||
*/
|
||||
String::Type textEncoding() const;
|
||||
String::Type textEncoding() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the text encoding used for the description and file name.
|
||||
*
|
||||
* \see description()
|
||||
* \see fileName()
|
||||
*/
|
||||
void setTextEncoding(String::Type encoding);
|
||||
void setTextEncoding(String::Type encoding);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the mime type of the object.
|
||||
*/
|
||||
String mimeType() const;
|
||||
String mimeType() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the mime type of the object.
|
||||
*/
|
||||
void setMimeType(const String &type);
|
||||
void setMimeType(const String &type);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the file name of the object.
|
||||
*
|
||||
* \see setFileName()
|
||||
*/
|
||||
String fileName() const;
|
||||
String fileName() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the file name for the object.
|
||||
*
|
||||
* \see fileName()
|
||||
*/
|
||||
void setFileName(const String &name);
|
||||
void setFileName(const String &name);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the content description of the object.
|
||||
*
|
||||
* \see setDescription()
|
||||
@@ -129,9 +127,9 @@ namespace TagLib {
|
||||
* \see setTextEncoding()
|
||||
*/
|
||||
|
||||
String description() const;
|
||||
String description() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the content description of the object to \a desc.
|
||||
*
|
||||
* \see description()
|
||||
@@ -139,9 +137,9 @@ namespace TagLib {
|
||||
* \see setTextEncoding()
|
||||
*/
|
||||
|
||||
void setDescription(const String &desc);
|
||||
void setDescription(const String &desc);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the object data as a ByteVector.
|
||||
*
|
||||
* \note ByteVector has a data() method that returns a const char * which
|
||||
@@ -150,9 +148,9 @@ namespace TagLib {
|
||||
* \see setObject()
|
||||
* \see mimeType()
|
||||
*/
|
||||
ByteVector object() const;
|
||||
ByteVector object() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the object data to \a data. \a data should be of the type specified in
|
||||
* this frame's mime-type specification.
|
||||
*
|
||||
@@ -160,22 +158,22 @@ namespace TagLib {
|
||||
* \see mimeType()
|
||||
* \see setMimeType()
|
||||
*/
|
||||
void setObject(const ByteVector &object);
|
||||
void setObject(const ByteVector &object);
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h);
|
||||
GeneralEncapsulatedObjectFrame(const GeneralEncapsulatedObjectFrame &);
|
||||
GeneralEncapsulatedObjectFrame &operator=(const GeneralEncapsulatedObjectFrame &);
|
||||
private:
|
||||
GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h);
|
||||
GeneralEncapsulatedObjectFrame(const GeneralEncapsulatedObjectFrame &);
|
||||
GeneralEncapsulatedObjectFrame &operator=(const GeneralEncapsulatedObjectFrame &);
|
||||
|
||||
class GeneralEncapsulatedObjectFramePrivate;
|
||||
GeneralEncapsulatedObjectFramePrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class GeneralEncapsulatedObjectFramePrivate;
|
||||
GeneralEncapsulatedObjectFramePrivate *d;
|
||||
};
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,9 +32,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class OwnershipFrame::OwnershipFramePrivate
|
||||
{
|
||||
public:
|
||||
class OwnershipFrame::OwnershipFramePrivate {
|
||||
public:
|
||||
String pricePaid;
|
||||
String datePurchased;
|
||||
String seller;
|
||||
@@ -45,67 +44,53 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OwnershipFrame::OwnershipFrame(String::Type encoding) :
|
||||
Frame("OWNE"),
|
||||
d(new OwnershipFramePrivate())
|
||||
{
|
||||
OwnershipFrame::OwnershipFrame(String::Type encoding) : Frame("OWNE"),
|
||||
d(new OwnershipFramePrivate()) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
OwnershipFrame::OwnershipFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new OwnershipFramePrivate())
|
||||
{
|
||||
OwnershipFrame::OwnershipFrame(const ByteVector &data) : Frame(data),
|
||||
d(new OwnershipFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
OwnershipFrame::~OwnershipFrame()
|
||||
{
|
||||
OwnershipFrame::~OwnershipFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String OwnershipFrame::toString() const
|
||||
{
|
||||
String OwnershipFrame::toString() const {
|
||||
return "pricePaid=" + d->pricePaid + " datePurchased=" + d->datePurchased + " seller=" + d->seller;
|
||||
}
|
||||
|
||||
String OwnershipFrame::pricePaid() const
|
||||
{
|
||||
String OwnershipFrame::pricePaid() const {
|
||||
return d->pricePaid;
|
||||
}
|
||||
|
||||
void OwnershipFrame::setPricePaid(const String &s)
|
||||
{
|
||||
void OwnershipFrame::setPricePaid(const String &s) {
|
||||
d->pricePaid = s;
|
||||
}
|
||||
|
||||
String OwnershipFrame::datePurchased() const
|
||||
{
|
||||
String OwnershipFrame::datePurchased() const {
|
||||
return d->datePurchased;
|
||||
}
|
||||
|
||||
void OwnershipFrame::setDatePurchased(const String &s)
|
||||
{
|
||||
void OwnershipFrame::setDatePurchased(const String &s) {
|
||||
d->datePurchased = s;
|
||||
}
|
||||
|
||||
String OwnershipFrame::seller() const
|
||||
{
|
||||
String OwnershipFrame::seller() const {
|
||||
return d->seller;
|
||||
}
|
||||
|
||||
void OwnershipFrame::setSeller(const String &s)
|
||||
{
|
||||
void OwnershipFrame::setSeller(const String &s) {
|
||||
d->seller = s;
|
||||
}
|
||||
|
||||
String::Type OwnershipFrame::textEncoding() const
|
||||
{
|
||||
String::Type OwnershipFrame::textEncoding() const {
|
||||
return d->textEncoding;
|
||||
}
|
||||
|
||||
void OwnershipFrame::setTextEncoding(String::Type encoding)
|
||||
{
|
||||
void OwnershipFrame::setTextEncoding(String::Type encoding) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
@@ -113,8 +98,7 @@ void OwnershipFrame::setTextEncoding(String::Type encoding)
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OwnershipFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void OwnershipFrame::parseFields(const ByteVector &data) {
|
||||
int pos = 0;
|
||||
|
||||
// Get the text encoding
|
||||
@@ -126,7 +110,7 @@ void OwnershipFrame::parseFields(const ByteVector &data)
|
||||
|
||||
// If we don't have at least 8 bytes left then don't parse the rest of the
|
||||
// data
|
||||
if(data.size() - pos < 8) {
|
||||
if (data.size() - pos < 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -135,14 +119,13 @@ void OwnershipFrame::parseFields(const ByteVector &data)
|
||||
pos += 8;
|
||||
|
||||
// Read the seller
|
||||
if(d->textEncoding == String::Latin1)
|
||||
if (d->textEncoding == String::Latin1)
|
||||
d->seller = Tag::latin1StringHandler()->parse(data.mid(pos));
|
||||
else
|
||||
d->seller = String(data.mid(pos), d->textEncoding);
|
||||
}
|
||||
|
||||
ByteVector OwnershipFrame::renderFields() const
|
||||
{
|
||||
ByteVector OwnershipFrame::renderFields() const {
|
||||
StringList sl;
|
||||
sl.append(d->seller);
|
||||
|
||||
@@ -163,9 +146,7 @@ ByteVector OwnershipFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new OwnershipFramePrivate())
|
||||
{
|
||||
OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new OwnershipFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -32,85 +32,84 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! An implementation of ID3v2 "ownership"
|
||||
//! An implementation of ID3v2 "ownership"
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This implements the ID3v2 ownership (OWNE frame). It consists of
|
||||
* a price paid, a date purchased (YYYYMMDD) and the name of the seller.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT OwnershipFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT OwnershipFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Construct an empty ownership frame.
|
||||
*/
|
||||
explicit OwnershipFrame(String::Type encoding = String::Latin1);
|
||||
explicit OwnershipFrame(String::Type encoding = String::Latin1);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Construct a ownership based on the data in \a data.
|
||||
*/
|
||||
explicit OwnershipFrame(const ByteVector &data);
|
||||
explicit OwnershipFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this OwnershipFrame instance.
|
||||
*/
|
||||
virtual ~OwnershipFrame();
|
||||
virtual ~OwnershipFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text of this popularimeter.
|
||||
*
|
||||
* \see text()
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the date purchased.
|
||||
*
|
||||
* \see setDatePurchased()
|
||||
*/
|
||||
String datePurchased() const;
|
||||
String datePurchased() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the date purchased.
|
||||
*
|
||||
* \see datePurchased()
|
||||
*/
|
||||
void setDatePurchased(const String &datePurchased);
|
||||
void setDatePurchased(const String &datePurchased);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the price paid.
|
||||
*
|
||||
* \see setPricePaid()
|
||||
*/
|
||||
String pricePaid() const;
|
||||
String pricePaid() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the price paid.
|
||||
*
|
||||
* \see pricePaid()
|
||||
*/
|
||||
void setPricePaid(const String &pricePaid);
|
||||
void setPricePaid(const String &pricePaid);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the seller.
|
||||
*
|
||||
* \see setSeller()
|
||||
*/
|
||||
String seller() const;
|
||||
String seller() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the seller.
|
||||
*
|
||||
* \see seller()
|
||||
*/
|
||||
void setSeller(const String &seller);
|
||||
void setSeller(const String &seller);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text encoding that will be used in rendering this frame.
|
||||
* This defaults to the type that was either specified in the constructor
|
||||
* or read from the frame when parsed.
|
||||
@@ -118,36 +117,36 @@ namespace TagLib {
|
||||
* \see setTextEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
String::Type textEncoding() const;
|
||||
String::Type textEncoding() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the text encoding to be used when rendering this frame to
|
||||
* \a encoding.
|
||||
*
|
||||
* \see textEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
void setTextEncoding(String::Type encoding);
|
||||
void setTextEncoding(String::Type encoding);
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
private:
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
OwnershipFrame(const ByteVector &data, Header *h);
|
||||
OwnershipFrame(const OwnershipFrame &);
|
||||
OwnershipFrame &operator=(const OwnershipFrame &);
|
||||
OwnershipFrame(const ByteVector &data, Header *h);
|
||||
OwnershipFrame(const OwnershipFrame &);
|
||||
OwnershipFrame &operator=(const OwnershipFrame &);
|
||||
|
||||
class OwnershipFramePrivate;
|
||||
OwnershipFramePrivate *d;
|
||||
};
|
||||
class OwnershipFramePrivate;
|
||||
OwnershipFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
@@ -28,9 +28,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class PodcastFrame::PodcastFramePrivate
|
||||
{
|
||||
public:
|
||||
class PodcastFrame::PodcastFramePrivate {
|
||||
public:
|
||||
ByteVector fieldData;
|
||||
};
|
||||
|
||||
@@ -38,20 +37,16 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PodcastFrame::PodcastFrame() :
|
||||
Frame("PCST"),
|
||||
d(new PodcastFramePrivate())
|
||||
{
|
||||
PodcastFrame::PodcastFrame() : Frame("PCST"),
|
||||
d(new PodcastFramePrivate()) {
|
||||
d->fieldData = ByteVector(4, '\0');
|
||||
}
|
||||
|
||||
PodcastFrame::~PodcastFrame()
|
||||
{
|
||||
PodcastFrame::~PodcastFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String PodcastFrame::toString() const
|
||||
{
|
||||
String PodcastFrame::toString() const {
|
||||
return String();
|
||||
}
|
||||
|
||||
@@ -59,13 +54,11 @@ String PodcastFrame::toString() const
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PodcastFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void PodcastFrame::parseFields(const ByteVector &data) {
|
||||
d->fieldData = data;
|
||||
}
|
||||
|
||||
ByteVector PodcastFrame::renderFields() const
|
||||
{
|
||||
ByteVector PodcastFrame::renderFields() const {
|
||||
return d->fieldData;
|
||||
}
|
||||
|
||||
@@ -73,9 +66,7 @@ ByteVector PodcastFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new PodcastFramePrivate())
|
||||
{
|
||||
PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new PodcastFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
55
3rdparty/taglib/mpeg/id3v2/frames/podcastframe.h
vendored
55
3rdparty/taglib/mpeg/id3v2/frames/podcastframe.h
vendored
@@ -32,51 +32,50 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! ID3v2 podcast frame
|
||||
/*!
|
||||
//! ID3v2 podcast frame
|
||||
/*!
|
||||
* An implementation of ID3v2 podcast flag, a frame with four zero bytes.
|
||||
*/
|
||||
class TAGLIB_EXPORT PodcastFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT PodcastFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Construct a podcast frame.
|
||||
*/
|
||||
PodcastFrame();
|
||||
PodcastFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this PodcastFrame instance.
|
||||
*/
|
||||
virtual ~PodcastFrame();
|
||||
virtual ~PodcastFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a null string.
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
private:
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
PodcastFrame(const ByteVector &data, Header *h);
|
||||
PodcastFrame(const PodcastFrame &);
|
||||
PodcastFrame &operator=(const PodcastFrame &);
|
||||
PodcastFrame(const ByteVector &data, Header *h);
|
||||
PodcastFrame(const PodcastFrame &);
|
||||
PodcastFrame &operator=(const PodcastFrame &);
|
||||
|
||||
class PodcastFramePrivate;
|
||||
PodcastFramePrivate *d;
|
||||
};
|
||||
class PodcastFramePrivate;
|
||||
PodcastFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
@@ -30,9 +30,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class PopularimeterFrame::PopularimeterFramePrivate
|
||||
{
|
||||
public:
|
||||
class PopularimeterFrame::PopularimeterFramePrivate {
|
||||
public:
|
||||
PopularimeterFramePrivate() : rating(0), counter(0) {}
|
||||
String email;
|
||||
int rating;
|
||||
@@ -43,56 +42,44 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PopularimeterFrame::PopularimeterFrame() :
|
||||
Frame("POPM"),
|
||||
d(new PopularimeterFramePrivate())
|
||||
{
|
||||
PopularimeterFrame::PopularimeterFrame() : Frame("POPM"),
|
||||
d(new PopularimeterFramePrivate()) {
|
||||
}
|
||||
|
||||
PopularimeterFrame::PopularimeterFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new PopularimeterFramePrivate())
|
||||
{
|
||||
PopularimeterFrame::PopularimeterFrame(const ByteVector &data) : Frame(data),
|
||||
d(new PopularimeterFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
PopularimeterFrame::~PopularimeterFrame()
|
||||
{
|
||||
PopularimeterFrame::~PopularimeterFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String PopularimeterFrame::toString() const
|
||||
{
|
||||
String PopularimeterFrame::toString() const {
|
||||
return d->email + " rating=" + String::number(d->rating) + " counter=" + String::number(d->counter);
|
||||
}
|
||||
|
||||
String PopularimeterFrame::email() const
|
||||
{
|
||||
String PopularimeterFrame::email() const {
|
||||
return d->email;
|
||||
}
|
||||
|
||||
void PopularimeterFrame::setEmail(const String &s)
|
||||
{
|
||||
void PopularimeterFrame::setEmail(const String &s) {
|
||||
d->email = s;
|
||||
}
|
||||
|
||||
int PopularimeterFrame::rating() const
|
||||
{
|
||||
int PopularimeterFrame::rating() const {
|
||||
return d->rating;
|
||||
}
|
||||
|
||||
void PopularimeterFrame::setRating(int s)
|
||||
{
|
||||
void PopularimeterFrame::setRating(int s) {
|
||||
d->rating = s;
|
||||
}
|
||||
|
||||
unsigned int PopularimeterFrame::counter() const
|
||||
{
|
||||
unsigned int PopularimeterFrame::counter() const {
|
||||
return d->counter;
|
||||
}
|
||||
|
||||
void PopularimeterFrame::setCounter(unsigned int s)
|
||||
{
|
||||
void PopularimeterFrame::setCounter(unsigned int s) {
|
||||
d->counter = s;
|
||||
}
|
||||
|
||||
@@ -100,24 +87,22 @@ void PopularimeterFrame::setCounter(unsigned int s)
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PopularimeterFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void PopularimeterFrame::parseFields(const ByteVector &data) {
|
||||
int pos = 0, size = int(data.size());
|
||||
|
||||
d->email = readStringField(data, String::Latin1, &pos);
|
||||
|
||||
d->rating = 0;
|
||||
d->counter = 0;
|
||||
if(pos < size) {
|
||||
if (pos < size) {
|
||||
d->rating = (unsigned char)(data[pos++]);
|
||||
if(pos < size) {
|
||||
if (pos < size) {
|
||||
d->counter = data.toUInt(static_cast<unsigned int>(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector PopularimeterFrame::renderFields() const
|
||||
{
|
||||
ByteVector PopularimeterFrame::renderFields() const {
|
||||
ByteVector data;
|
||||
|
||||
data.append(d->email.data(String::Latin1));
|
||||
@@ -132,9 +117,7 @@ ByteVector PopularimeterFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new PopularimeterFramePrivate())
|
||||
{
|
||||
PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new PopularimeterFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -32,103 +32,102 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! An implementation of ID3v2 "popularimeter"
|
||||
//! An implementation of ID3v2 "popularimeter"
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This implements the ID3v2 popularimeter (POPM frame). It consists of
|
||||
* an email, a rating and an optional counter.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT PopularimeterFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT PopularimeterFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Construct an empty popularimeter frame.
|
||||
*/
|
||||
explicit PopularimeterFrame();
|
||||
explicit PopularimeterFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Construct a popularimeter based on the data in \a data.
|
||||
*/
|
||||
explicit PopularimeterFrame(const ByteVector &data);
|
||||
explicit PopularimeterFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this PopularimeterFrame instance.
|
||||
*/
|
||||
virtual ~PopularimeterFrame();
|
||||
virtual ~PopularimeterFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text of this popularimeter.
|
||||
*
|
||||
* \see text()
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the email.
|
||||
*
|
||||
* \see setEmail()
|
||||
*/
|
||||
String email() const;
|
||||
String email() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the email.
|
||||
*
|
||||
* \see email()
|
||||
*/
|
||||
void setEmail(const String &email);
|
||||
void setEmail(const String &email);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the rating.
|
||||
*
|
||||
* \see setRating()
|
||||
*/
|
||||
int rating() const;
|
||||
int rating() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the rating.
|
||||
*
|
||||
* \see rating()
|
||||
*/
|
||||
void setRating(int rating);
|
||||
void setRating(int rating);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the counter.
|
||||
*
|
||||
* \see setCounter()
|
||||
*/
|
||||
unsigned int counter() const;
|
||||
unsigned int counter() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the counter.
|
||||
*
|
||||
* \see counter()
|
||||
*/
|
||||
void setCounter(unsigned int counter);
|
||||
void setCounter(unsigned int counter);
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
private:
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
PopularimeterFrame(const ByteVector &data, Header *h);
|
||||
PopularimeterFrame(const PopularimeterFrame &);
|
||||
PopularimeterFrame &operator=(const PopularimeterFrame &);
|
||||
PopularimeterFrame(const ByteVector &data, Header *h);
|
||||
PopularimeterFrame(const PopularimeterFrame &);
|
||||
PopularimeterFrame &operator=(const PopularimeterFrame &);
|
||||
|
||||
class PopularimeterFramePrivate;
|
||||
PopularimeterFramePrivate *d;
|
||||
};
|
||||
class PopularimeterFramePrivate;
|
||||
PopularimeterFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
@@ -34,9 +34,8 @@ using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
|
||||
class PrivateFrame::PrivateFramePrivate
|
||||
{
|
||||
public:
|
||||
class PrivateFrame::PrivateFramePrivate {
|
||||
public:
|
||||
ByteVector data;
|
||||
String owner;
|
||||
};
|
||||
@@ -45,46 +44,36 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PrivateFrame::PrivateFrame() :
|
||||
Frame("PRIV"),
|
||||
d(new PrivateFramePrivate())
|
||||
{
|
||||
PrivateFrame::PrivateFrame() : Frame("PRIV"),
|
||||
d(new PrivateFramePrivate()) {
|
||||
}
|
||||
|
||||
PrivateFrame::PrivateFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new PrivateFramePrivate())
|
||||
{
|
||||
PrivateFrame::PrivateFrame(const ByteVector &data) : Frame(data),
|
||||
d(new PrivateFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
PrivateFrame::~PrivateFrame()
|
||||
{
|
||||
PrivateFrame::~PrivateFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String PrivateFrame::toString() const
|
||||
{
|
||||
String PrivateFrame::toString() const {
|
||||
return d->owner;
|
||||
}
|
||||
|
||||
String PrivateFrame::owner() const
|
||||
{
|
||||
String PrivateFrame::owner() const {
|
||||
return d->owner;
|
||||
}
|
||||
|
||||
ByteVector PrivateFrame::data() const
|
||||
{
|
||||
ByteVector PrivateFrame::data() const {
|
||||
return d->data;
|
||||
}
|
||||
|
||||
void PrivateFrame::setOwner(const String &s)
|
||||
{
|
||||
void PrivateFrame::setOwner(const String &s) {
|
||||
d->owner = s;
|
||||
}
|
||||
|
||||
void PrivateFrame::setData(const ByteVector & data)
|
||||
{
|
||||
void PrivateFrame::setData(const ByteVector &data) {
|
||||
d->data = data;
|
||||
}
|
||||
|
||||
@@ -92,24 +81,22 @@ void PrivateFrame::setData(const ByteVector & data)
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PrivateFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < 2) {
|
||||
void PrivateFrame::parseFields(const ByteVector &data) {
|
||||
if (data.size() < 2) {
|
||||
debug("A private frame must contain at least 2 bytes.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Owner identifier is assumed to be Latin1
|
||||
|
||||
const int byteAlign = 1;
|
||||
const int byteAlign = 1;
|
||||
const int endOfOwner = data.find(textDelimiter(String::Latin1), 0, byteAlign);
|
||||
|
||||
d->owner = String(data.mid(0, endOfOwner));
|
||||
d->owner = String(data.mid(0, endOfOwner));
|
||||
d->data = data.mid(endOfOwner + 1);
|
||||
}
|
||||
|
||||
ByteVector PrivateFrame::renderFields() const
|
||||
{
|
||||
ByteVector PrivateFrame::renderFields() const {
|
||||
ByteVector v;
|
||||
|
||||
v.append(d->owner.data(String::Latin1));
|
||||
@@ -123,9 +110,7 @@ ByteVector PrivateFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new PrivateFramePrivate())
|
||||
{
|
||||
PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new PrivateFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
73
3rdparty/taglib/mpeg/id3v2/frames/privateframe.h
vendored
73
3rdparty/taglib/mpeg/id3v2/frames/privateframe.h
vendored
@@ -33,81 +33,80 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! An implementation of ID3v2 privateframe
|
||||
//! An implementation of ID3v2 privateframe
|
||||
|
||||
class TAGLIB_EXPORT PrivateFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT PrivateFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Construct an empty private frame.
|
||||
*/
|
||||
PrivateFrame();
|
||||
PrivateFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Construct a private frame based on the data in \a data.
|
||||
*
|
||||
* \note This is the constructor used when parsing the frame from a file.
|
||||
*/
|
||||
explicit PrivateFrame(const ByteVector &data);
|
||||
explicit PrivateFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this private frame instance.
|
||||
*/
|
||||
virtual ~PrivateFrame();
|
||||
virtual ~PrivateFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text of this private frame, currently just the owner.
|
||||
*
|
||||
* \see text()
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \return The owner of the private frame.
|
||||
* \note This should contain an email address or link to a website.
|
||||
*/
|
||||
String owner() const;
|
||||
String owner() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
*
|
||||
*/
|
||||
ByteVector data() const;
|
||||
ByteVector data() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the owner of the frame to \a s.
|
||||
* \note This should contain an email address or link to a website.
|
||||
*/
|
||||
void setOwner(const String &s);
|
||||
void setOwner(const String &s);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
*
|
||||
*/
|
||||
void setData(const ByteVector &v);
|
||||
void setData(const ByteVector &v);
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
private:
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
PrivateFrame(const ByteVector &data, Header *h);
|
||||
PrivateFrame(const ByteVector &data, Header *h);
|
||||
|
||||
PrivateFrame(const PrivateFrame &);
|
||||
PrivateFrame &operator=(const PrivateFrame &);
|
||||
PrivateFrame(const PrivateFrame &);
|
||||
PrivateFrame &operator=(const PrivateFrame &);
|
||||
|
||||
class PrivateFramePrivate;
|
||||
PrivateFramePrivate *d;
|
||||
};
|
||||
class PrivateFramePrivate;
|
||||
PrivateFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
@@ -31,8 +31,7 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
struct ChannelData
|
||||
{
|
||||
struct ChannelData {
|
||||
ChannelData() : channelType(RelativeVolumeFrame::Other), volumeAdjustment(0) {}
|
||||
|
||||
RelativeVolumeFrame::ChannelType channelType;
|
||||
@@ -40,9 +39,8 @@ struct ChannelData
|
||||
RelativeVolumeFrame::PeakVolume peakVolume;
|
||||
};
|
||||
|
||||
class RelativeVolumeFrame::RelativeVolumeFramePrivate
|
||||
{
|
||||
public:
|
||||
class RelativeVolumeFrame::RelativeVolumeFramePrivate {
|
||||
public:
|
||||
String identification;
|
||||
Map<ChannelType, ChannelData> channels;
|
||||
};
|
||||
@@ -51,35 +49,28 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RelativeVolumeFrame::RelativeVolumeFrame() :
|
||||
Frame("RVA2"),
|
||||
d(new RelativeVolumeFramePrivate())
|
||||
{
|
||||
RelativeVolumeFrame::RelativeVolumeFrame() : Frame("RVA2"),
|
||||
d(new RelativeVolumeFramePrivate()) {
|
||||
}
|
||||
|
||||
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new RelativeVolumeFramePrivate())
|
||||
{
|
||||
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) : Frame(data),
|
||||
d(new RelativeVolumeFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
RelativeVolumeFrame::~RelativeVolumeFrame()
|
||||
{
|
||||
RelativeVolumeFrame::~RelativeVolumeFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String RelativeVolumeFrame::toString() const
|
||||
{
|
||||
String RelativeVolumeFrame::toString() const {
|
||||
return d->identification;
|
||||
}
|
||||
|
||||
List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const
|
||||
{
|
||||
List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const {
|
||||
List<ChannelType> l;
|
||||
|
||||
Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
|
||||
for(; it != d->channels.end(); ++it)
|
||||
for (; it != d->channels.end(); ++it)
|
||||
l.append((*it).first);
|
||||
|
||||
return l;
|
||||
@@ -87,85 +78,68 @@ List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const
|
||||
|
||||
// deprecated
|
||||
|
||||
RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const
|
||||
{
|
||||
RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const {
|
||||
return MasterVolume;
|
||||
}
|
||||
|
||||
// deprecated
|
||||
|
||||
void RelativeVolumeFrame::setChannelType(ChannelType)
|
||||
{
|
||||
|
||||
void RelativeVolumeFrame::setChannelType(ChannelType) {
|
||||
}
|
||||
|
||||
short RelativeVolumeFrame::volumeAdjustmentIndex(ChannelType type) const
|
||||
{
|
||||
short RelativeVolumeFrame::volumeAdjustmentIndex(ChannelType type) const {
|
||||
return d->channels.contains(type) ? d->channels[type].volumeAdjustment : 0;
|
||||
}
|
||||
|
||||
short RelativeVolumeFrame::volumeAdjustmentIndex() const
|
||||
{
|
||||
short RelativeVolumeFrame::volumeAdjustmentIndex() const {
|
||||
return volumeAdjustmentIndex(MasterVolume);
|
||||
}
|
||||
|
||||
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index, ChannelType type)
|
||||
{
|
||||
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index, ChannelType type) {
|
||||
d->channels[type].volumeAdjustment = index;
|
||||
}
|
||||
|
||||
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index)
|
||||
{
|
||||
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index) {
|
||||
setVolumeAdjustmentIndex(index, MasterVolume);
|
||||
}
|
||||
|
||||
float RelativeVolumeFrame::volumeAdjustment(ChannelType type) const
|
||||
{
|
||||
float RelativeVolumeFrame::volumeAdjustment(ChannelType type) const {
|
||||
return d->channels.contains(type) ? float(d->channels[type].volumeAdjustment) / float(512) : 0;
|
||||
}
|
||||
|
||||
float RelativeVolumeFrame::volumeAdjustment() const
|
||||
{
|
||||
float RelativeVolumeFrame::volumeAdjustment() const {
|
||||
return volumeAdjustment(MasterVolume);
|
||||
}
|
||||
|
||||
void RelativeVolumeFrame::setVolumeAdjustment(float adjustment, ChannelType type)
|
||||
{
|
||||
void RelativeVolumeFrame::setVolumeAdjustment(float adjustment, ChannelType type) {
|
||||
d->channels[type].volumeAdjustment = short(adjustment * float(512));
|
||||
}
|
||||
|
||||
void RelativeVolumeFrame::setVolumeAdjustment(float adjustment)
|
||||
{
|
||||
void RelativeVolumeFrame::setVolumeAdjustment(float adjustment) {
|
||||
setVolumeAdjustment(adjustment, MasterVolume);
|
||||
}
|
||||
|
||||
RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume(ChannelType type) const
|
||||
{
|
||||
RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume(ChannelType type) const {
|
||||
return d->channels.contains(type) ? d->channels[type].peakVolume : PeakVolume();
|
||||
}
|
||||
|
||||
RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume() const
|
||||
{
|
||||
RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume() const {
|
||||
return peakVolume(MasterVolume);
|
||||
}
|
||||
|
||||
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak, ChannelType type)
|
||||
{
|
||||
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak, ChannelType type) {
|
||||
d->channels[type].peakVolume = peak;
|
||||
}
|
||||
|
||||
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak)
|
||||
{
|
||||
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak) {
|
||||
setPeakVolume(peak, MasterVolume);
|
||||
}
|
||||
|
||||
String RelativeVolumeFrame::identification() const
|
||||
{
|
||||
String RelativeVolumeFrame::identification() const {
|
||||
return d->identification;
|
||||
}
|
||||
|
||||
void RelativeVolumeFrame::setIdentification(const String &s)
|
||||
{
|
||||
void RelativeVolumeFrame::setIdentification(const String &s) {
|
||||
d->identification = s;
|
||||
}
|
||||
|
||||
@@ -173,14 +147,13 @@ void RelativeVolumeFrame::setIdentification(const String &s)
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RelativeVolumeFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void RelativeVolumeFrame::parseFields(const ByteVector &data) {
|
||||
int pos = 0;
|
||||
d->identification = readStringField(data, String::Latin1, &pos);
|
||||
|
||||
// Each channel is at least 4 bytes.
|
||||
|
||||
while(pos <= (int)data.size() - 4) {
|
||||
while (pos <= (int)data.size() - 4) {
|
||||
|
||||
ChannelType type = ChannelType(data[pos]);
|
||||
pos += 1;
|
||||
@@ -199,8 +172,7 @@ void RelativeVolumeFrame::parseFields(const ByteVector &data)
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector RelativeVolumeFrame::renderFields() const
|
||||
{
|
||||
ByteVector RelativeVolumeFrame::renderFields() const {
|
||||
ByteVector data;
|
||||
|
||||
data.append(d->identification.data(String::Latin1));
|
||||
@@ -208,7 +180,7 @@ ByteVector RelativeVolumeFrame::renderFields() const
|
||||
|
||||
Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
|
||||
|
||||
for(; it != d->channels.end(); ++it) {
|
||||
for (; it != d->channels.end(); ++it) {
|
||||
ChannelType type = (*it).first;
|
||||
const ChannelData &channel = (*it).second;
|
||||
|
||||
@@ -225,9 +197,7 @@ ByteVector RelativeVolumeFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new RelativeVolumeFramePrivate())
|
||||
{
|
||||
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new RelativeVolumeFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -33,11 +33,11 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! An ID3v2 relative volume adjustment frame implementation
|
||||
//! An ID3v2 relative volume adjustment frame implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of ID3v2 relative volume adjustment. The
|
||||
* presence of this frame makes it possible to specify an increase in volume
|
||||
* for an audio file or specific audio tracks in that file.
|
||||
@@ -47,99 +47,96 @@ namespace TagLib {
|
||||
* different channel types.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT RelativeVolumeFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT RelativeVolumeFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* This indicates the type of volume adjustment that should be applied.
|
||||
*/
|
||||
enum ChannelType {
|
||||
//! A type not enumerated below
|
||||
Other = 0x00,
|
||||
//! The master volume for the track
|
||||
MasterVolume = 0x01,
|
||||
//! The front right audio channel
|
||||
FrontRight = 0x02,
|
||||
//! The front left audio channel
|
||||
FrontLeft = 0x03,
|
||||
//! The back right audio channel
|
||||
BackRight = 0x04,
|
||||
//! The back left audio channel
|
||||
BackLeft = 0x05,
|
||||
//! The front center audio channel
|
||||
FrontCentre = 0x06,
|
||||
//! The back center audio channel
|
||||
BackCentre = 0x07,
|
||||
//! The subwoofer audio channel
|
||||
Subwoofer = 0x08
|
||||
};
|
||||
enum ChannelType {
|
||||
//! A type not enumerated below
|
||||
Other = 0x00,
|
||||
//! The master volume for the track
|
||||
MasterVolume = 0x01,
|
||||
//! The front right audio channel
|
||||
FrontRight = 0x02,
|
||||
//! The front left audio channel
|
||||
FrontLeft = 0x03,
|
||||
//! The back right audio channel
|
||||
BackRight = 0x04,
|
||||
//! The back left audio channel
|
||||
BackLeft = 0x05,
|
||||
//! The front center audio channel
|
||||
FrontCentre = 0x06,
|
||||
//! The back center audio channel
|
||||
BackCentre = 0x07,
|
||||
//! The subwoofer audio channel
|
||||
Subwoofer = 0x08
|
||||
};
|
||||
|
||||
//! Struct that stores the relevant values for ID3v2 peak volume
|
||||
//! Struct that stores the relevant values for ID3v2 peak volume
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* The peak volume is described as a series of bits that is padded to fill
|
||||
* a block of bytes. These two values should always be updated in tandem.
|
||||
*/
|
||||
struct PeakVolume
|
||||
{
|
||||
/*!
|
||||
struct PeakVolume {
|
||||
/*!
|
||||
* Constructs an empty peak volume description.
|
||||
*/
|
||||
PeakVolume() : bitsRepresentingPeak(0) {}
|
||||
/*!
|
||||
PeakVolume() : bitsRepresentingPeak(0) {}
|
||||
/*!
|
||||
* The number of bits (in the range of 0 to 255) used to describe the
|
||||
* peak volume.
|
||||
*/
|
||||
unsigned char bitsRepresentingPeak;
|
||||
/*!
|
||||
unsigned char bitsRepresentingPeak;
|
||||
/*!
|
||||
* The array of bits (represented as a series of bytes) used to describe
|
||||
* the peak volume.
|
||||
*/
|
||||
ByteVector peakVolume;
|
||||
};
|
||||
ByteVector peakVolume;
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs a RelativeVolumeFrame. The relevant data should be set
|
||||
* manually.
|
||||
*/
|
||||
RelativeVolumeFrame();
|
||||
RelativeVolumeFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs a RelativeVolumeFrame based on the contents of \a data.
|
||||
*/
|
||||
RelativeVolumeFrame(const ByteVector &data);
|
||||
RelativeVolumeFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys the RelativeVolumeFrame instance.
|
||||
*/
|
||||
virtual ~RelativeVolumeFrame();
|
||||
virtual ~RelativeVolumeFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the frame's identification.
|
||||
*
|
||||
* \see identification()
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a list of channels with information currently in the frame.
|
||||
*/
|
||||
List<ChannelType> channels() const;
|
||||
List<ChannelType> channels() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \deprecated Always returns master volume.
|
||||
*/
|
||||
TAGLIB_DEPRECATED ChannelType channelType() const;
|
||||
TAGLIB_DEPRECATED ChannelType channelType() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \deprecated This method no longer has any effect.
|
||||
*/
|
||||
TAGLIB_DEPRECATED void setChannelType(ChannelType t);
|
||||
TAGLIB_DEPRECATED void setChannelType(ChannelType t);
|
||||
|
||||
/*
|
||||
/*
|
||||
* There was a terrible API goof here, and while this can't be changed to
|
||||
* the way it appears below for binary compatibility reasons, let's at
|
||||
* least pretend that it looks clean.
|
||||
@@ -147,7 +144,7 @@ namespace TagLib {
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the relative volume adjustment "index". As indicated by the
|
||||
* ID3v2 standard this is a 16-bit signed integer that reflects the
|
||||
* decibels of adjustment when divided by 512.
|
||||
@@ -158,9 +155,9 @@ namespace TagLib {
|
||||
* \see setVolumeAdjustmentIndex()
|
||||
* \see volumeAjustment()
|
||||
*/
|
||||
short volumeAdjustmentIndex(ChannelType type = MasterVolume) const;
|
||||
short volumeAdjustmentIndex(ChannelType type = MasterVolume) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the volume adjustment to \a index. As indicated by the ID3v2
|
||||
* standard this is a 16-bit signed integer that reflects the decibels of
|
||||
* adjustment when divided by 512.
|
||||
@@ -170,9 +167,9 @@ namespace TagLib {
|
||||
* \see volumeAdjustmentIndex()
|
||||
* \see setVolumeAjustment()
|
||||
*/
|
||||
void setVolumeAdjustmentIndex(short index, ChannelType type = MasterVolume);
|
||||
void setVolumeAdjustmentIndex(short index, ChannelType type = MasterVolume);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the relative volume adjustment in decibels.
|
||||
*
|
||||
* \note Because this is actually stored internally as an "index" to this
|
||||
@@ -185,9 +182,9 @@ namespace TagLib {
|
||||
* \see setVolumeAdjustment()
|
||||
* \see volumeAdjustmentIndex()
|
||||
*/
|
||||
float volumeAdjustment(ChannelType type = MasterVolume) const;
|
||||
float volumeAdjustment(ChannelType type = MasterVolume) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the relative volume adjustment in decibels to \a adjustment.
|
||||
*
|
||||
* By default this sets the value for the master volume.
|
||||
@@ -199,9 +196,9 @@ namespace TagLib {
|
||||
* \see setVolumeAdjustment()
|
||||
* \see volumeAdjustmentIndex()
|
||||
*/
|
||||
void setVolumeAdjustment(float adjustment, ChannelType type = MasterVolume);
|
||||
void setVolumeAdjustment(float adjustment, ChannelType type = MasterVolume);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the peak volume (represented as a length and a string of bits).
|
||||
*
|
||||
* This defaults to returning the value for the master volume channel if
|
||||
@@ -209,68 +206,68 @@ namespace TagLib {
|
||||
*
|
||||
* \see setPeakVolume()
|
||||
*/
|
||||
PeakVolume peakVolume(ChannelType type = MasterVolume) const;
|
||||
PeakVolume peakVolume(ChannelType type = MasterVolume) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the peak volume to \a peak.
|
||||
*
|
||||
* By default this sets the value for the master volume.
|
||||
*
|
||||
* \see peakVolume()
|
||||
*/
|
||||
void setPeakVolume(const PeakVolume &peak, ChannelType type = MasterVolume);
|
||||
void setPeakVolume(const PeakVolume &peak, ChannelType type = MasterVolume);
|
||||
|
||||
#else
|
||||
|
||||
// BIC: Combine each of the following pairs of functions (or maybe just
|
||||
// rework this junk altogether).
|
||||
// BIC: Combine each of the following pairs of functions (or maybe just
|
||||
// rework this junk altogether).
|
||||
|
||||
short volumeAdjustmentIndex(ChannelType type) const;
|
||||
short volumeAdjustmentIndex() const;
|
||||
short volumeAdjustmentIndex(ChannelType type) const;
|
||||
short volumeAdjustmentIndex() const;
|
||||
|
||||
void setVolumeAdjustmentIndex(short index, ChannelType type);
|
||||
void setVolumeAdjustmentIndex(short index);
|
||||
void setVolumeAdjustmentIndex(short index, ChannelType type);
|
||||
void setVolumeAdjustmentIndex(short index);
|
||||
|
||||
float volumeAdjustment(ChannelType type) const;
|
||||
float volumeAdjustment() const;
|
||||
float volumeAdjustment(ChannelType type) const;
|
||||
float volumeAdjustment() const;
|
||||
|
||||
void setVolumeAdjustment(float adjustment, ChannelType type);
|
||||
void setVolumeAdjustment(float adjustment);
|
||||
void setVolumeAdjustment(float adjustment, ChannelType type);
|
||||
void setVolumeAdjustment(float adjustment);
|
||||
|
||||
PeakVolume peakVolume(ChannelType type) const;
|
||||
PeakVolume peakVolume() const;
|
||||
PeakVolume peakVolume(ChannelType type) const;
|
||||
PeakVolume peakVolume() const;
|
||||
|
||||
void setPeakVolume(const PeakVolume &peak, ChannelType type);
|
||||
void setPeakVolume(const PeakVolume &peak);
|
||||
void setPeakVolume(const PeakVolume &peak, ChannelType type);
|
||||
void setPeakVolume(const PeakVolume &peak);
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the identification for this frame.
|
||||
*/
|
||||
String identification() const;
|
||||
String identification() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the identification of the frame to \a s. The string
|
||||
* is used to identify the situation and/or device where this
|
||||
* adjustment should apply.
|
||||
*/
|
||||
void setIdentification(const String &s);
|
||||
void setIdentification(const String &s);
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
RelativeVolumeFrame(const ByteVector &data, Header *h);
|
||||
RelativeVolumeFrame(const RelativeVolumeFrame &);
|
||||
RelativeVolumeFrame &operator=(const RelativeVolumeFrame &);
|
||||
private:
|
||||
RelativeVolumeFrame(const ByteVector &data, Header *h);
|
||||
RelativeVolumeFrame(const RelativeVolumeFrame &);
|
||||
RelativeVolumeFrame &operator=(const RelativeVolumeFrame &);
|
||||
|
||||
class RelativeVolumeFramePrivate;
|
||||
RelativeVolumeFramePrivate *d;
|
||||
};
|
||||
class RelativeVolumeFramePrivate;
|
||||
RelativeVolumeFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
@@ -32,13 +32,11 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class SynchronizedLyricsFrame::SynchronizedLyricsFramePrivate
|
||||
{
|
||||
public:
|
||||
SynchronizedLyricsFramePrivate() :
|
||||
textEncoding(String::Latin1),
|
||||
timestampFormat(SynchronizedLyricsFrame::AbsoluteMilliseconds),
|
||||
type(SynchronizedLyricsFrame::Lyrics) {}
|
||||
class SynchronizedLyricsFrame::SynchronizedLyricsFramePrivate {
|
||||
public:
|
||||
SynchronizedLyricsFramePrivate() : textEncoding(String::Latin1),
|
||||
timestampFormat(SynchronizedLyricsFrame::AbsoluteMilliseconds),
|
||||
type(SynchronizedLyricsFrame::Lyrics) {}
|
||||
String::Type textEncoding;
|
||||
ByteVector language;
|
||||
SynchronizedLyricsFrame::TimestampFormat timestampFormat;
|
||||
@@ -51,90 +49,72 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(String::Type encoding) :
|
||||
Frame("SYLT"),
|
||||
d(new SynchronizedLyricsFramePrivate())
|
||||
{
|
||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(String::Type encoding) : Frame("SYLT"),
|
||||
d(new SynchronizedLyricsFramePrivate()) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new SynchronizedLyricsFramePrivate())
|
||||
{
|
||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data) : Frame(data),
|
||||
d(new SynchronizedLyricsFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
SynchronizedLyricsFrame::~SynchronizedLyricsFrame()
|
||||
{
|
||||
SynchronizedLyricsFrame::~SynchronizedLyricsFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String SynchronizedLyricsFrame::toString() const
|
||||
{
|
||||
String SynchronizedLyricsFrame::toString() const {
|
||||
return d->description;
|
||||
}
|
||||
|
||||
String::Type SynchronizedLyricsFrame::textEncoding() const
|
||||
{
|
||||
String::Type SynchronizedLyricsFrame::textEncoding() const {
|
||||
return d->textEncoding;
|
||||
}
|
||||
|
||||
ByteVector SynchronizedLyricsFrame::language() const
|
||||
{
|
||||
ByteVector SynchronizedLyricsFrame::language() const {
|
||||
return d->language;
|
||||
}
|
||||
|
||||
SynchronizedLyricsFrame::TimestampFormat
|
||||
SynchronizedLyricsFrame::timestampFormat() const
|
||||
{
|
||||
SynchronizedLyricsFrame::timestampFormat() const {
|
||||
return d->timestampFormat;
|
||||
}
|
||||
|
||||
SynchronizedLyricsFrame::Type SynchronizedLyricsFrame::type() const
|
||||
{
|
||||
SynchronizedLyricsFrame::Type SynchronizedLyricsFrame::type() const {
|
||||
return d->type;
|
||||
}
|
||||
|
||||
String SynchronizedLyricsFrame::description() const
|
||||
{
|
||||
String SynchronizedLyricsFrame::description() const {
|
||||
return d->description;
|
||||
}
|
||||
|
||||
SynchronizedLyricsFrame::SynchedTextList
|
||||
SynchronizedLyricsFrame::synchedText() const
|
||||
{
|
||||
SynchronizedLyricsFrame::synchedText() const {
|
||||
return d->synchedText;
|
||||
}
|
||||
|
||||
void SynchronizedLyricsFrame::setTextEncoding(String::Type encoding)
|
||||
{
|
||||
void SynchronizedLyricsFrame::setTextEncoding(String::Type encoding) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
void SynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding)
|
||||
{
|
||||
void SynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding) {
|
||||
d->language = languageEncoding.mid(0, 3);
|
||||
}
|
||||
|
||||
void SynchronizedLyricsFrame::setTimestampFormat(SynchronizedLyricsFrame::TimestampFormat f)
|
||||
{
|
||||
void SynchronizedLyricsFrame::setTimestampFormat(SynchronizedLyricsFrame::TimestampFormat f) {
|
||||
d->timestampFormat = f;
|
||||
}
|
||||
|
||||
void SynchronizedLyricsFrame::setType(SynchronizedLyricsFrame::Type t)
|
||||
{
|
||||
void SynchronizedLyricsFrame::setType(SynchronizedLyricsFrame::Type t) {
|
||||
d->type = t;
|
||||
}
|
||||
|
||||
void SynchronizedLyricsFrame::setDescription(const String &s)
|
||||
{
|
||||
void SynchronizedLyricsFrame::setDescription(const String &s) {
|
||||
d->description = s;
|
||||
}
|
||||
|
||||
void SynchronizedLyricsFrame::setSynchedText(
|
||||
const SynchronizedLyricsFrame::SynchedTextList &t)
|
||||
{
|
||||
const SynchronizedLyricsFrame::SynchedTextList &t) {
|
||||
d->synchedText = t;
|
||||
}
|
||||
|
||||
@@ -142,10 +122,9 @@ void SynchronizedLyricsFrame::setSynchedText(
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void SynchronizedLyricsFrame::parseFields(const ByteVector &data) {
|
||||
const int end = data.size();
|
||||
if(end < 7) {
|
||||
if (end < 7) {
|
||||
debug("A synchronized lyrics frame must contain at least 7 bytes.");
|
||||
return;
|
||||
}
|
||||
@@ -158,7 +137,7 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
int pos = 6;
|
||||
|
||||
d->description = readStringField(data, d->textEncoding, &pos);
|
||||
if(pos == 6)
|
||||
if (pos == 6)
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -169,27 +148,28 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
* case of strings without BOM so that readStringField() will work.
|
||||
*/
|
||||
String::Type encWithEndianness = d->textEncoding;
|
||||
if(d->textEncoding == String::UTF16) {
|
||||
if (d->textEncoding == String::UTF16) {
|
||||
unsigned short bom = data.toUShort(6, true);
|
||||
if(bom == 0xfffe) {
|
||||
if (bom == 0xfffe) {
|
||||
encWithEndianness = String::UTF16LE;
|
||||
} else if(bom == 0xfeff) {
|
||||
}
|
||||
else if (bom == 0xfeff) {
|
||||
encWithEndianness = String::UTF16BE;
|
||||
}
|
||||
}
|
||||
|
||||
d->synchedText.clear();
|
||||
while(pos < end) {
|
||||
while (pos < end) {
|
||||
String::Type enc = d->textEncoding;
|
||||
// If a UTF16 string has no BOM, use the encoding found above.
|
||||
if(enc == String::UTF16 && pos + 1 < end) {
|
||||
if (enc == String::UTF16 && pos + 1 < end) {
|
||||
unsigned short bom = data.toUShort(pos, true);
|
||||
if(bom != 0xfffe && bom != 0xfeff) {
|
||||
if (bom != 0xfffe && bom != 0xfeff) {
|
||||
enc = encWithEndianness;
|
||||
}
|
||||
}
|
||||
String text = readStringField(data, enc, &pos);
|
||||
if(pos + 4 > end)
|
||||
if (pos + 4 > end)
|
||||
return;
|
||||
|
||||
unsigned int time = data.toUInt(pos, true);
|
||||
@@ -199,16 +179,15 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector SynchronizedLyricsFrame::renderFields() const
|
||||
{
|
||||
ByteVector SynchronizedLyricsFrame::renderFields() const {
|
||||
ByteVector v;
|
||||
|
||||
String::Type encoding = d->textEncoding;
|
||||
|
||||
encoding = checkTextEncoding(d->description, encoding);
|
||||
for(SynchedTextList::ConstIterator it = d->synchedText.begin();
|
||||
it != d->synchedText.end();
|
||||
++it) {
|
||||
for (SynchedTextList::ConstIterator it = d->synchedText.begin();
|
||||
it != d->synchedText.end();
|
||||
++it) {
|
||||
encoding = checkTextEncoding(it->text, encoding);
|
||||
}
|
||||
|
||||
@@ -218,9 +197,9 @@ ByteVector SynchronizedLyricsFrame::renderFields() const
|
||||
v.append(char(d->type));
|
||||
v.append(d->description.data(encoding));
|
||||
v.append(textDelimiter(encoding));
|
||||
for(SynchedTextList::ConstIterator it = d->synchedText.begin();
|
||||
it != d->synchedText.end();
|
||||
++it) {
|
||||
for (SynchedTextList::ConstIterator it = d->synchedText.begin();
|
||||
it != d->synchedText.end();
|
||||
++it) {
|
||||
const SynchedText &entry = *it;
|
||||
v.append(entry.text.data(encoding));
|
||||
v.append(textDelimiter(encoding));
|
||||
@@ -234,9 +213,7 @@ ByteVector SynchronizedLyricsFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new SynchronizedLyricsFramePrivate())
|
||||
{
|
||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new SynchronizedLyricsFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -32,94 +32,92 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! ID3v2 synchronized lyrics frame
|
||||
/*!
|
||||
//! ID3v2 synchronized lyrics frame
|
||||
/*!
|
||||
* An implementation of ID3v2 synchronized lyrics.
|
||||
*/
|
||||
class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Specifies the timestamp format used.
|
||||
*/
|
||||
enum TimestampFormat {
|
||||
//! The timestamp is of unknown format.
|
||||
Unknown = 0x00,
|
||||
//! The timestamp represents the number of MPEG frames since
|
||||
//! the beginning of the audio stream.
|
||||
AbsoluteMpegFrames = 0x01,
|
||||
//! The timestamp represents the number of milliseconds since
|
||||
//! the beginning of the audio stream.
|
||||
AbsoluteMilliseconds = 0x02
|
||||
};
|
||||
enum TimestampFormat {
|
||||
//! The timestamp is of unknown format.
|
||||
Unknown = 0x00,
|
||||
//! The timestamp represents the number of MPEG frames since
|
||||
//! the beginning of the audio stream.
|
||||
AbsoluteMpegFrames = 0x01,
|
||||
//! The timestamp represents the number of milliseconds since
|
||||
//! the beginning of the audio stream.
|
||||
AbsoluteMilliseconds = 0x02
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Specifies the type of text contained.
|
||||
*/
|
||||
enum Type {
|
||||
//! The text is some other type of text.
|
||||
Other = 0x00,
|
||||
//! The text contains lyrical data.
|
||||
Lyrics = 0x01,
|
||||
//! The text contains a transcription.
|
||||
TextTranscription = 0x02,
|
||||
//! The text lists the movements in the piece.
|
||||
Movement = 0x03,
|
||||
//! The text describes events that occur.
|
||||
Events = 0x04,
|
||||
//! The text contains chord changes that occur in the music.
|
||||
Chord = 0x05,
|
||||
//! The text contains trivia or "pop up" information about the media.
|
||||
Trivia = 0x06,
|
||||
//! The text contains URLs for relevant webpages.
|
||||
WebpageUrls = 0x07,
|
||||
//! The text contains URLs for relevant images.
|
||||
ImageUrls = 0x08
|
||||
};
|
||||
enum Type {
|
||||
//! The text is some other type of text.
|
||||
Other = 0x00,
|
||||
//! The text contains lyrical data.
|
||||
Lyrics = 0x01,
|
||||
//! The text contains a transcription.
|
||||
TextTranscription = 0x02,
|
||||
//! The text lists the movements in the piece.
|
||||
Movement = 0x03,
|
||||
//! The text describes events that occur.
|
||||
Events = 0x04,
|
||||
//! The text contains chord changes that occur in the music.
|
||||
Chord = 0x05,
|
||||
//! The text contains trivia or "pop up" information about the media.
|
||||
Trivia = 0x06,
|
||||
//! The text contains URLs for relevant webpages.
|
||||
WebpageUrls = 0x07,
|
||||
//! The text contains URLs for relevant images.
|
||||
ImageUrls = 0x08
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Single entry of time stamp and lyrics text.
|
||||
*/
|
||||
struct SynchedText {
|
||||
SynchedText(unsigned int ms, String str) : time(ms), text(str) {}
|
||||
unsigned int time;
|
||||
String text;
|
||||
};
|
||||
struct SynchedText {
|
||||
SynchedText(unsigned int ms, String str) : time(ms), text(str) {}
|
||||
unsigned int time;
|
||||
String text;
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* List of synchronized lyrics.
|
||||
*/
|
||||
typedef Strawberry_TagLib::TagLib::List<SynchedText> SynchedTextList;
|
||||
typedef Strawberry_TagLib::TagLib::List<SynchedText> SynchedTextList;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Construct an empty synchronized lyrics frame that will use the text
|
||||
* encoding \a encoding.
|
||||
*/
|
||||
explicit SynchronizedLyricsFrame(String::Type encoding = String::Latin1);
|
||||
explicit SynchronizedLyricsFrame(String::Type encoding = String::Latin1);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Construct a synchronized lyrics frame based on the data in \a data.
|
||||
*/
|
||||
explicit SynchronizedLyricsFrame(const ByteVector &data);
|
||||
explicit SynchronizedLyricsFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this SynchronizedLyricsFrame instance.
|
||||
*/
|
||||
virtual ~SynchronizedLyricsFrame();
|
||||
virtual ~SynchronizedLyricsFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the description of this synchronized lyrics frame.
|
||||
*
|
||||
* \see description()
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text encoding that will be used in rendering this frame.
|
||||
* This defaults to the type that was either specified in the constructor
|
||||
* or read from the frame when parsed.
|
||||
@@ -127,9 +125,9 @@ namespace TagLib {
|
||||
* \see setTextEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
String::Type textEncoding() const;
|
||||
String::Type textEncoding() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the language encoding as a 3 byte encoding as specified by
|
||||
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
|
||||
*
|
||||
@@ -137,97 +135,97 @@ namespace TagLib {
|
||||
*
|
||||
* \see setLanguage()
|
||||
*/
|
||||
ByteVector language() const;
|
||||
ByteVector language() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the timestamp format.
|
||||
*/
|
||||
TimestampFormat timestampFormat() const;
|
||||
TimestampFormat timestampFormat() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the type of text contained.
|
||||
*/
|
||||
Type type() const;
|
||||
Type type() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the description of this synchronized lyrics frame.
|
||||
*
|
||||
* \note Most taggers simply ignore this value.
|
||||
*
|
||||
* \see setDescription()
|
||||
*/
|
||||
String description() const;
|
||||
String description() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text with the time stamps.
|
||||
*/
|
||||
SynchedTextList synchedText() const;
|
||||
SynchedTextList synchedText() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the text encoding to be used when rendering this frame to
|
||||
* \a encoding.
|
||||
*
|
||||
* \see textEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
void setTextEncoding(String::Type encoding);
|
||||
void setTextEncoding(String::Type encoding);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the language using the 3 byte language code from
|
||||
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
|
||||
* \a languageCode.
|
||||
*
|
||||
* \see language()
|
||||
*/
|
||||
void setLanguage(const ByteVector &languageCode);
|
||||
void setLanguage(const ByteVector &languageCode);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the timestamp format.
|
||||
*
|
||||
* \see timestampFormat()
|
||||
*/
|
||||
void setTimestampFormat(TimestampFormat f);
|
||||
void setTimestampFormat(TimestampFormat f);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the type of text contained.
|
||||
*
|
||||
* \see type()
|
||||
*/
|
||||
void setType(Type t);
|
||||
void setType(Type t);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the description of the synchronized lyrics frame to \a s.
|
||||
*
|
||||
* \see description()
|
||||
*/
|
||||
void setDescription(const String &s);
|
||||
void setDescription(const String &s);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the text with the time stamps.
|
||||
*
|
||||
* \see text()
|
||||
*/
|
||||
void setSynchedText(const SynchedTextList &t);
|
||||
void setSynchedText(const SynchedTextList &t);
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
private:
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
SynchronizedLyricsFrame(const ByteVector &data, Header *h);
|
||||
SynchronizedLyricsFrame(const SynchronizedLyricsFrame &);
|
||||
SynchronizedLyricsFrame &operator=(const SynchronizedLyricsFrame &);
|
||||
SynchronizedLyricsFrame(const ByteVector &data, Header *h);
|
||||
SynchronizedLyricsFrame(const SynchronizedLyricsFrame &);
|
||||
SynchronizedLyricsFrame &operator=(const SynchronizedLyricsFrame &);
|
||||
|
||||
class SynchronizedLyricsFramePrivate;
|
||||
SynchronizedLyricsFramePrivate *d;
|
||||
};
|
||||
class SynchronizedLyricsFramePrivate;
|
||||
SynchronizedLyricsFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
@@ -32,14 +32,11 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class TableOfContentsFrame::TableOfContentsFramePrivate
|
||||
{
|
||||
public:
|
||||
TableOfContentsFramePrivate() :
|
||||
tagHeader(0),
|
||||
isTopLevel(false),
|
||||
isOrdered(false)
|
||||
{
|
||||
class TableOfContentsFrame::TableOfContentsFramePrivate {
|
||||
public:
|
||||
TableOfContentsFramePrivate() : tagHeader(0),
|
||||
isTopLevel(false),
|
||||
isOrdered(false) {
|
||||
embeddedFrameList.setAutoDelete(true);
|
||||
}
|
||||
|
||||
@@ -54,146 +51,122 @@ public:
|
||||
|
||||
namespace {
|
||||
|
||||
// These functions are needed to try to aim for backward compatibility with
|
||||
// an API that previously (unreasonably) required null bytes to be appended
|
||||
// at the end of identifiers explicitly by the API user.
|
||||
// These functions are needed to try to aim for backward compatibility with
|
||||
// an API that previously (unreasonably) required null bytes to be appended
|
||||
// at the end of identifiers explicitly by the API user.
|
||||
|
||||
// BIC: remove these
|
||||
// BIC: remove these
|
||||
|
||||
ByteVector &strip(ByteVector &b)
|
||||
{
|
||||
if(b.endsWith('\0'))
|
||||
b.resize(b.size() - 1);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteVectorList &strip(ByteVectorList &l)
|
||||
{
|
||||
for(ByteVectorList::Iterator it = l.begin(); it != l.end(); ++it)
|
||||
{
|
||||
strip(*it);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
ByteVector &strip(ByteVector &b) {
|
||||
if (b.endsWith('\0'))
|
||||
b.resize(b.size() - 1);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteVectorList &strip(ByteVectorList &l) {
|
||||
for (ByteVectorList::Iterator it = l.begin(); it != l.end(); ++it) {
|
||||
strip(*it);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public methods
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data) :
|
||||
ID3v2::Frame(data),
|
||||
d(new TableOfContentsFramePrivate())
|
||||
{
|
||||
TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data) : ID3v2::Frame(data),
|
||||
d(new TableOfContentsFramePrivate()) {
|
||||
d->tagHeader = tagHeader;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
TableOfContentsFrame::TableOfContentsFrame(const ByteVector &elementID,
|
||||
const ByteVectorList &children,
|
||||
const FrameList &embeddedFrames) :
|
||||
ID3v2::Frame("CTOC"),
|
||||
d(new TableOfContentsFramePrivate())
|
||||
{
|
||||
const ByteVectorList &children,
|
||||
const FrameList &embeddedFrames) : ID3v2::Frame("CTOC"),
|
||||
d(new TableOfContentsFramePrivate()) {
|
||||
d->elementID = elementID;
|
||||
strip(d->elementID);
|
||||
d->childElements = children;
|
||||
|
||||
for(FrameList::ConstIterator it = embeddedFrames.begin(); it != embeddedFrames.end(); ++it)
|
||||
for (FrameList::ConstIterator it = embeddedFrames.begin(); it != embeddedFrames.end(); ++it)
|
||||
addEmbeddedFrame(*it);
|
||||
}
|
||||
|
||||
TableOfContentsFrame::~TableOfContentsFrame()
|
||||
{
|
||||
TableOfContentsFrame::~TableOfContentsFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
ByteVector TableOfContentsFrame::elementID() const
|
||||
{
|
||||
ByteVector TableOfContentsFrame::elementID() const {
|
||||
return d->elementID;
|
||||
}
|
||||
|
||||
bool TableOfContentsFrame::isTopLevel() const
|
||||
{
|
||||
bool TableOfContentsFrame::isTopLevel() const {
|
||||
return d->isTopLevel;
|
||||
}
|
||||
|
||||
bool TableOfContentsFrame::isOrdered() const
|
||||
{
|
||||
bool TableOfContentsFrame::isOrdered() const {
|
||||
return d->isOrdered;
|
||||
}
|
||||
|
||||
unsigned int TableOfContentsFrame::entryCount() const
|
||||
{
|
||||
unsigned int TableOfContentsFrame::entryCount() const {
|
||||
return d->childElements.size();
|
||||
}
|
||||
|
||||
ByteVectorList TableOfContentsFrame::childElements() const
|
||||
{
|
||||
ByteVectorList TableOfContentsFrame::childElements() const {
|
||||
return d->childElements;
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::setElementID(const ByteVector &eID)
|
||||
{
|
||||
void TableOfContentsFrame::setElementID(const ByteVector &eID) {
|
||||
d->elementID = eID;
|
||||
strip(d->elementID);
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::setIsTopLevel(const bool &t)
|
||||
{
|
||||
void TableOfContentsFrame::setIsTopLevel(const bool &t) {
|
||||
d->isTopLevel = t;
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::setIsOrdered(const bool &o)
|
||||
{
|
||||
void TableOfContentsFrame::setIsOrdered(const bool &o) {
|
||||
d->isOrdered = o;
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::setChildElements(const ByteVectorList &l)
|
||||
{
|
||||
void TableOfContentsFrame::setChildElements(const ByteVectorList &l) {
|
||||
d->childElements = l;
|
||||
strip(d->childElements);
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::addChildElement(const ByteVector &cE)
|
||||
{
|
||||
void TableOfContentsFrame::addChildElement(const ByteVector &cE) {
|
||||
d->childElements.append(cE);
|
||||
strip(d->childElements);
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::removeChildElement(const ByteVector &cE)
|
||||
{
|
||||
void TableOfContentsFrame::removeChildElement(const ByteVector &cE) {
|
||||
ByteVectorList::Iterator it = d->childElements.find(cE);
|
||||
|
||||
if(it == d->childElements.end())
|
||||
if (it == d->childElements.end())
|
||||
it = d->childElements.find(cE + ByteVector("\0"));
|
||||
|
||||
d->childElements.erase(it);
|
||||
}
|
||||
|
||||
const FrameListMap &TableOfContentsFrame::embeddedFrameListMap() const
|
||||
{
|
||||
const FrameListMap &TableOfContentsFrame::embeddedFrameListMap() const {
|
||||
return d->embeddedFrameListMap;
|
||||
}
|
||||
|
||||
const FrameList &TableOfContentsFrame::embeddedFrameList() const
|
||||
{
|
||||
const FrameList &TableOfContentsFrame::embeddedFrameList() const {
|
||||
return d->embeddedFrameList;
|
||||
}
|
||||
|
||||
const FrameList &TableOfContentsFrame::embeddedFrameList(const ByteVector &frameID) const
|
||||
{
|
||||
const FrameList &TableOfContentsFrame::embeddedFrameList(const ByteVector &frameID) const {
|
||||
return d->embeddedFrameListMap[frameID];
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::addEmbeddedFrame(Frame *frame)
|
||||
{
|
||||
void TableOfContentsFrame::addEmbeddedFrame(Frame *frame) {
|
||||
d->embeddedFrameList.append(frame);
|
||||
d->embeddedFrameListMap[frame->frameID()].append(frame);
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::removeEmbeddedFrame(Frame *frame, bool del)
|
||||
{
|
||||
void TableOfContentsFrame::removeEmbeddedFrame(Frame *frame, bool del) {
|
||||
// remove the frame from the frame list
|
||||
FrameList::Iterator it = d->embeddedFrameList.find(frame);
|
||||
d->embeddedFrameList.erase(it);
|
||||
@@ -203,31 +176,30 @@ void TableOfContentsFrame::removeEmbeddedFrame(Frame *frame, bool del)
|
||||
d->embeddedFrameListMap[frame->frameID()].erase(it);
|
||||
|
||||
// ...and delete as desired
|
||||
if(del)
|
||||
if (del)
|
||||
delete frame;
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::removeEmbeddedFrames(const ByteVector &id)
|
||||
{
|
||||
void TableOfContentsFrame::removeEmbeddedFrames(const ByteVector &id) {
|
||||
FrameList l = d->embeddedFrameListMap[id];
|
||||
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
removeEmbeddedFrame(*it, true);
|
||||
}
|
||||
|
||||
String TableOfContentsFrame::toString() const
|
||||
{
|
||||
String TableOfContentsFrame::toString() const {
|
||||
String s = String(d->elementID) +
|
||||
": top level: " + (d->isTopLevel ? "true" : "false") +
|
||||
", ordered: " + (d->isOrdered ? "true" : "false");
|
||||
": top level: " + (d->isTopLevel ? "true" : "false") +
|
||||
", ordered: " + (d->isOrdered ? "true" : "false");
|
||||
|
||||
if(!d->childElements.isEmpty()) {
|
||||
s+= ", chapters: [ " + String(d->childElements.toByteVector(", ")) + " ]";
|
||||
if (!d->childElements.isEmpty()) {
|
||||
s += ", chapters: [ " + String(d->childElements.toByteVector(", ")) + " ]";
|
||||
}
|
||||
|
||||
if(!d->embeddedFrameList.isEmpty()) {
|
||||
if (!d->embeddedFrameList.isEmpty()) {
|
||||
StringList frameIDs;
|
||||
for(FrameList::ConstIterator it = d->embeddedFrameList.begin();
|
||||
it != d->embeddedFrameList.end(); ++it)
|
||||
for (FrameList::ConstIterator it = d->embeddedFrameList.begin();
|
||||
it != d->embeddedFrameList.end();
|
||||
++it)
|
||||
frameIDs.append((*it)->frameID());
|
||||
s += ", sub-frames: [ " + frameIDs.toString(", ") + " ]";
|
||||
}
|
||||
@@ -235,8 +207,7 @@ String TableOfContentsFrame::toString() const
|
||||
return s;
|
||||
}
|
||||
|
||||
PropertyMap TableOfContentsFrame::asProperties() const
|
||||
{
|
||||
PropertyMap TableOfContentsFrame::asProperties() const {
|
||||
PropertyMap map;
|
||||
|
||||
map.unsupportedData().append(frameID() + String("/") + d->elementID);
|
||||
@@ -245,42 +216,39 @@ PropertyMap TableOfContentsFrame::asProperties() const
|
||||
}
|
||||
|
||||
TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *tag,
|
||||
const ByteVector &eID) // static
|
||||
const ByteVector &eID) // static
|
||||
{
|
||||
ID3v2::FrameList tablesOfContents = tag->frameList("CTOC");
|
||||
|
||||
for(ID3v2::FrameList::ConstIterator it = tablesOfContents.begin();
|
||||
it != tablesOfContents.end();
|
||||
++it)
|
||||
{
|
||||
for (ID3v2::FrameList::ConstIterator it = tablesOfContents.begin();
|
||||
it != tablesOfContents.end();
|
||||
++it) {
|
||||
TableOfContentsFrame *frame = dynamic_cast<TableOfContentsFrame *>(*it);
|
||||
if(frame && frame->elementID() == eID)
|
||||
if (frame && frame->elementID() == eID)
|
||||
return frame;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TableOfContentsFrame *TableOfContentsFrame::findTopLevel(const ID3v2::Tag *tag) // static
|
||||
TableOfContentsFrame *TableOfContentsFrame::findTopLevel(const ID3v2::Tag *tag) // static
|
||||
{
|
||||
ID3v2::FrameList tablesOfContents = tag->frameList("CTOC");
|
||||
|
||||
for(ID3v2::FrameList::ConstIterator it = tablesOfContents.begin();
|
||||
it != tablesOfContents.end();
|
||||
++it)
|
||||
{
|
||||
for (ID3v2::FrameList::ConstIterator it = tablesOfContents.begin();
|
||||
it != tablesOfContents.end();
|
||||
++it) {
|
||||
TableOfContentsFrame *frame = dynamic_cast<TableOfContentsFrame *>(*it);
|
||||
if(frame && frame->isTopLevel() == true)
|
||||
if (frame && frame->isTopLevel() == true)
|
||||
return frame;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TableOfContentsFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void TableOfContentsFrame::parseFields(const ByteVector &data) {
|
||||
unsigned int size = data.size();
|
||||
if(size < 6) {
|
||||
if (size < 6) {
|
||||
debug("A 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.");
|
||||
@@ -293,24 +261,24 @@ void TableOfContentsFrame::parseFields(const ByteVector &data)
|
||||
d->isTopLevel = (data.at(pos) & 2) != 0;
|
||||
d->isOrdered = (data.at(pos++) & 1) != 0;
|
||||
unsigned int entryCount = static_cast<unsigned char>(data.at(pos++));
|
||||
for(unsigned int i = 0; i < entryCount; i++) {
|
||||
for (unsigned int i = 0; i < entryCount; i++) {
|
||||
ByteVector childElementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
|
||||
d->childElements.append(childElementID);
|
||||
}
|
||||
|
||||
size -= pos;
|
||||
|
||||
if(size < header()->size())
|
||||
if (size < header()->size())
|
||||
return;
|
||||
|
||||
while(embPos < size - header()->size()) {
|
||||
while (embPos < size - header()->size()) {
|
||||
Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);
|
||||
|
||||
if(!frame)
|
||||
if (!frame)
|
||||
return;
|
||||
|
||||
// Checks to make sure that frame parsed correctly.
|
||||
if(frame->size() <= 0) {
|
||||
if (frame->size() <= 0) {
|
||||
delete frame;
|
||||
return;
|
||||
}
|
||||
@@ -320,16 +288,15 @@ void TableOfContentsFrame::parseFields(const ByteVector &data)
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector TableOfContentsFrame::renderFields() const
|
||||
{
|
||||
ByteVector TableOfContentsFrame::renderFields() const {
|
||||
ByteVector data;
|
||||
|
||||
data.append(d->elementID);
|
||||
data.append('\0');
|
||||
char flags = 0;
|
||||
if(d->isTopLevel)
|
||||
if (d->isTopLevel)
|
||||
flags += 2;
|
||||
if(d->isOrdered)
|
||||
if (d->isOrdered)
|
||||
flags += 1;
|
||||
data.append(flags);
|
||||
data.append((char)(entryCount()));
|
||||
@@ -347,10 +314,8 @@ ByteVector TableOfContentsFrame::renderFields() const
|
||||
}
|
||||
|
||||
TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader,
|
||||
const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new TableOfContentsFramePrivate())
|
||||
{
|
||||
const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new TableOfContentsFramePrivate()) {
|
||||
d->tagHeader = tagHeader;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -34,125 +34,124 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of ID3v2 table of contents frames. Purpose
|
||||
* of this frame is to allow a table of contents to be defined.
|
||||
*/
|
||||
|
||||
//! An implementation of ID3v2 table of contents frames
|
||||
//! An implementation of ID3v2 table of contents frames
|
||||
|
||||
class TAGLIB_EXPORT TableOfContentsFrame : public ID3v2::Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT TableOfContentsFrame : public ID3v2::Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Creates a table of contents frame based on \a data. \a tagHeader is
|
||||
* required as the internal frames are parsed based on the tag version.
|
||||
*/
|
||||
TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data);
|
||||
TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Creates a table of contents frame with the element ID \a elementID,
|
||||
* the child elements \a children and embedded frames, which become owned
|
||||
* by this frame, in \a embeddedFrames.
|
||||
*/
|
||||
TableOfContentsFrame(const ByteVector &elementID,
|
||||
const ByteVectorList &children = ByteVectorList(),
|
||||
const FrameList &embeddedFrames = FrameList());
|
||||
TableOfContentsFrame(const ByteVector &elementID,
|
||||
const ByteVectorList &children = ByteVectorList(),
|
||||
const FrameList &embeddedFrames = FrameList());
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys the frame.
|
||||
*/
|
||||
~TableOfContentsFrame();
|
||||
~TableOfContentsFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the elementID of the frame. Element ID
|
||||
* is a null terminated string, however it's not human-readable.
|
||||
*
|
||||
* \see setElementID()
|
||||
*/
|
||||
ByteVector elementID() const;
|
||||
ByteVector elementID() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true, if the frame is top-level (doesn't have
|
||||
* any parent CTOC frame).
|
||||
*
|
||||
* \see setIsTopLevel()
|
||||
*/
|
||||
bool isTopLevel() const;
|
||||
bool isTopLevel() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true, if the child elements list entries
|
||||
* are ordered.
|
||||
*
|
||||
* \see setIsOrdered()
|
||||
*/
|
||||
bool isOrdered() const;
|
||||
bool isOrdered() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns count of child elements of the frame. It always
|
||||
* corresponds to size of child elements list.
|
||||
*
|
||||
* \see childElements()
|
||||
*/
|
||||
unsigned int entryCount() const;
|
||||
unsigned int entryCount() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns list of child elements of the frame.
|
||||
*
|
||||
* \see setChildElements()
|
||||
*/
|
||||
ByteVectorList childElements() const;
|
||||
ByteVectorList childElements() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the elementID of the frame to \a eID. If \a eID isn't
|
||||
* null terminated, a null char is appended automatically.
|
||||
*
|
||||
* \see elementID()
|
||||
*/
|
||||
void setElementID(const ByteVector &eID);
|
||||
void setElementID(const ByteVector &eID);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets, if the frame is top-level (doesn't have
|
||||
* any parent CTOC frame).
|
||||
*
|
||||
* \see isTopLevel()
|
||||
*/
|
||||
void setIsTopLevel(const bool &t);
|
||||
void setIsTopLevel(const bool &t);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets, if the child elements list entries
|
||||
* are ordered.
|
||||
*
|
||||
* \see isOrdered()
|
||||
*/
|
||||
void setIsOrdered(const bool &o);
|
||||
void setIsOrdered(const bool &o);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets list of child elements of the frame to \a l.
|
||||
*
|
||||
* \see childElements()
|
||||
*/
|
||||
void setChildElements(const ByteVectorList &l);
|
||||
void setChildElements(const ByteVectorList &l);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Adds \a cE to list of child elements of the frame.
|
||||
*
|
||||
* \see childElements()
|
||||
*/
|
||||
void addChildElement(const ByteVector &cE);
|
||||
void addChildElement(const ByteVector &cE);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Removes \a cE to list of child elements of the frame.
|
||||
*
|
||||
* \see childElements()
|
||||
*/
|
||||
void removeChildElement(const ByteVector &cE);
|
||||
void removeChildElement(const ByteVector &cE);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a reference to the frame list map. This is an FrameListMap of
|
||||
* all of the frames embedded in the CTOC frame.
|
||||
*
|
||||
@@ -166,9 +165,9 @@ namespace TagLib {
|
||||
*
|
||||
* \see embeddedFrameList()
|
||||
*/
|
||||
const FrameListMap &embeddedFrameListMap() const;
|
||||
const FrameListMap &embeddedFrameListMap() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a reference to the embedded frame list. This is an FrameList
|
||||
* of all of the frames embedded in the CTOC frame in the order that they
|
||||
* were parsed.
|
||||
@@ -179,9 +178,9 @@ namespace TagLib {
|
||||
* \warning You should not modify this data structure directly, instead
|
||||
* use addEmbeddedFrame() and removeEmbeddedFrame().
|
||||
*/
|
||||
const FrameList &embeddedFrameList() const;
|
||||
const FrameList &embeddedFrameList() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the embedded frame list for frames with the id \a frameID
|
||||
* or an empty list if there are no embedded frames of that type. This
|
||||
* is just a convenience and is equivalent to:
|
||||
@@ -192,71 +191,71 @@ namespace TagLib {
|
||||
*
|
||||
* \see embeddedFrameListMap()
|
||||
*/
|
||||
const FrameList &embeddedFrameList(const ByteVector &frameID) const;
|
||||
const FrameList &embeddedFrameList(const ByteVector &frameID) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Add an embedded frame to the CTOC frame. At this point the CTOC frame
|
||||
* takes ownership of the embedded frame and will handle freeing its memory.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
* returned by embeddedFrameList()
|
||||
*/
|
||||
void addEmbeddedFrame(Frame *frame);
|
||||
void addEmbeddedFrame(Frame *frame);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove an embedded frame from the CTOC frame. If \a del is true the frame's
|
||||
* memory will be freed; if it is false, it must be deleted by the user.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
* returned by embeddedFrameList()
|
||||
*/
|
||||
void removeEmbeddedFrame(Frame *frame, bool del = true);
|
||||
void removeEmbeddedFrame(Frame *frame, bool del = true);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove all embedded frames of type \a id from the CTOC frame and free their
|
||||
* memory.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
* returned by embeddedFrameList()
|
||||
*/
|
||||
void removeEmbeddedFrames(const ByteVector &id);
|
||||
void removeEmbeddedFrames(const ByteVector &id);
|
||||
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
PropertyMap asProperties() const;
|
||||
PropertyMap asProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* CTOC frames each have a unique element ID. This searches for a CTOC
|
||||
* frame with the element ID \a eID and returns a pointer to it. This
|
||||
* can be used to link together parent and child CTOC frames.
|
||||
*
|
||||
* \see elementID()
|
||||
*/
|
||||
static TableOfContentsFrame *findByElementID(const Tag *tag, const ByteVector &eID);
|
||||
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);
|
||||
static TableOfContentsFrame *findTopLevel(const Tag *tag);
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h);
|
||||
TableOfContentsFrame(const TableOfContentsFrame &);
|
||||
TableOfContentsFrame &operator=(const TableOfContentsFrame &);
|
||||
private:
|
||||
TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h);
|
||||
TableOfContentsFrame(const TableOfContentsFrame &);
|
||||
TableOfContentsFrame &operator=(const TableOfContentsFrame &);
|
||||
|
||||
class TableOfContentsFramePrivate;
|
||||
TableOfContentsFramePrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class TableOfContentsFramePrivate;
|
||||
TableOfContentsFramePrivate *d;
|
||||
};
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,9 +32,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class TextIdentificationFrame::TextIdentificationFramePrivate
|
||||
{
|
||||
public:
|
||||
class TextIdentificationFrame::TextIdentificationFramePrivate {
|
||||
public:
|
||||
TextIdentificationFramePrivate() : textEncoding(String::Latin1) {}
|
||||
String::Type textEncoding;
|
||||
StringList fieldList;
|
||||
@@ -44,38 +43,34 @@ public:
|
||||
// TextIdentificationFrame public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &type, String::Type encoding) :
|
||||
Frame(type),
|
||||
d(new TextIdentificationFramePrivate())
|
||||
{
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &type, String::Type encoding) : Frame(type),
|
||||
d(new TextIdentificationFramePrivate()) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new TextIdentificationFramePrivate())
|
||||
{
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) : Frame(data),
|
||||
d(new TextIdentificationFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
TextIdentificationFrame *TextIdentificationFrame::createTIPLFrame(const PropertyMap &properties) // static
|
||||
TextIdentificationFrame *TextIdentificationFrame::createTIPLFrame(const PropertyMap &properties) // static
|
||||
{
|
||||
TextIdentificationFrame *frame = new TextIdentificationFrame("TIPL");
|
||||
StringList l;
|
||||
for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it){
|
||||
for (PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it) {
|
||||
l.append(it->first);
|
||||
l.append(it->second.toString(",")); // comma-separated list of names
|
||||
l.append(it->second.toString(",")); // comma-separated list of names
|
||||
}
|
||||
frame->setText(l);
|
||||
return frame;
|
||||
}
|
||||
|
||||
TextIdentificationFrame *TextIdentificationFrame::createTMCLFrame(const PropertyMap &properties) // static
|
||||
TextIdentificationFrame *TextIdentificationFrame::createTMCLFrame(const PropertyMap &properties) // static
|
||||
{
|
||||
TextIdentificationFrame *frame = new TextIdentificationFrame("TMCL");
|
||||
StringList l;
|
||||
for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it){
|
||||
if(!it->first.startsWith(instrumentPrefix)) // should not happen
|
||||
for (PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it) {
|
||||
if (!it->first.startsWith(instrumentPrefix)) // should not happen
|
||||
continue;
|
||||
l.append(it->first.substr(instrumentPrefix.size()));
|
||||
l.append(it->second.toString(","));
|
||||
@@ -84,92 +79,84 @@ TextIdentificationFrame *TextIdentificationFrame::createTMCLFrame(const Property
|
||||
return frame;
|
||||
}
|
||||
|
||||
TextIdentificationFrame::~TextIdentificationFrame()
|
||||
{
|
||||
TextIdentificationFrame::~TextIdentificationFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
void TextIdentificationFrame::setText(const StringList &l)
|
||||
{
|
||||
void TextIdentificationFrame::setText(const StringList &l) {
|
||||
d->fieldList = l;
|
||||
}
|
||||
|
||||
void TextIdentificationFrame::setText(const String &s)
|
||||
{
|
||||
void TextIdentificationFrame::setText(const String &s) {
|
||||
d->fieldList = s;
|
||||
}
|
||||
|
||||
String TextIdentificationFrame::toString() const
|
||||
{
|
||||
String TextIdentificationFrame::toString() const {
|
||||
return d->fieldList.toString();
|
||||
}
|
||||
|
||||
StringList TextIdentificationFrame::fieldList() const
|
||||
{
|
||||
StringList TextIdentificationFrame::fieldList() const {
|
||||
return d->fieldList;
|
||||
}
|
||||
|
||||
String::Type TextIdentificationFrame::textEncoding() const
|
||||
{
|
||||
String::Type TextIdentificationFrame::textEncoding() const {
|
||||
return d->textEncoding;
|
||||
}
|
||||
|
||||
void TextIdentificationFrame::setTextEncoding(String::Type encoding)
|
||||
{
|
||||
void TextIdentificationFrame::setTextEncoding(String::Type encoding) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// array of allowed TIPL prefixes and their corresponding key value
|
||||
const char* involvedPeople[][2] = {
|
||||
{"ARRANGER", "ARRANGER"},
|
||||
{"ENGINEER", "ENGINEER"},
|
||||
{"PRODUCER", "PRODUCER"},
|
||||
{"DJ-MIX", "DJMIXER"},
|
||||
{"MIX", "MIXER"},
|
||||
};
|
||||
const size_t involvedPeopleSize = sizeof(involvedPeople) / sizeof(involvedPeople[0]);
|
||||
}
|
||||
namespace {
|
||||
// array of allowed TIPL prefixes and their corresponding key value
|
||||
const char *involvedPeople[][2] = {
|
||||
{ "ARRANGER", "ARRANGER" },
|
||||
{ "ENGINEER", "ENGINEER" },
|
||||
{ "PRODUCER", "PRODUCER" },
|
||||
{ "DJ-MIX", "DJMIXER" },
|
||||
{ "MIX", "MIXER" },
|
||||
};
|
||||
const size_t involvedPeopleSize = sizeof(involvedPeople) / sizeof(involvedPeople[0]);
|
||||
} // namespace
|
||||
|
||||
const KeyConversionMap &TextIdentificationFrame::involvedPeopleMap() // static
|
||||
const KeyConversionMap &TextIdentificationFrame::involvedPeopleMap() // static
|
||||
{
|
||||
static KeyConversionMap m;
|
||||
if(m.isEmpty()) {
|
||||
for(size_t i = 0; i < involvedPeopleSize; ++i)
|
||||
if (m.isEmpty()) {
|
||||
for (size_t i = 0; i < involvedPeopleSize; ++i)
|
||||
m.insert(involvedPeople[i][1], involvedPeople[i][0]);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
PropertyMap TextIdentificationFrame::asProperties() const
|
||||
{
|
||||
if(frameID() == "TIPL")
|
||||
PropertyMap TextIdentificationFrame::asProperties() const {
|
||||
if (frameID() == "TIPL")
|
||||
return makeTIPLProperties();
|
||||
if(frameID() == "TMCL")
|
||||
if (frameID() == "TMCL")
|
||||
return makeTMCLProperties();
|
||||
PropertyMap map;
|
||||
String tagName = frameIDToKey(frameID());
|
||||
if(tagName.isEmpty()) {
|
||||
if (tagName.isEmpty()) {
|
||||
map.unsupportedData().append(frameID());
|
||||
return map;
|
||||
}
|
||||
StringList values = fieldList();
|
||||
if(tagName == "GENRE") {
|
||||
if (tagName == "GENRE") {
|
||||
// Special case: Support ID3v1-style genre numbers. They are not officially supported in
|
||||
// ID3v2, however it seems that still a lot of programs use them.
|
||||
for(StringList::Iterator it = values.begin(); it != values.end(); ++it) {
|
||||
for (StringList::Iterator it = values.begin(); it != values.end(); ++it) {
|
||||
bool ok = false;
|
||||
int test = it->toInt(&ok); // test if the genre value is an integer
|
||||
if(ok)
|
||||
int test = it->toInt(&ok); // test if the genre value is an integer
|
||||
if (ok)
|
||||
*it = ID3v1::genre(test);
|
||||
}
|
||||
} else if(tagName == "DATE") {
|
||||
for(StringList::Iterator it = values.begin(); it != values.end(); ++it) {
|
||||
}
|
||||
else if (tagName == "DATE") {
|
||||
for (StringList::Iterator it = values.begin(); it != values.end(); ++it) {
|
||||
// ID3v2 specifies ISO8601 timestamps which contain a 'T' as separator between date and time.
|
||||
// Since this is unusual in other formats, the T is removed.
|
||||
int tpos = it->find("T");
|
||||
if(tpos != -1)
|
||||
if (tpos != -1)
|
||||
(*it)[tpos] = ' ';
|
||||
}
|
||||
}
|
||||
@@ -182,11 +169,10 @@ PropertyMap TextIdentificationFrame::asProperties() const
|
||||
// TextIdentificationFrame protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TextIdentificationFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void TextIdentificationFrame::parseFields(const ByteVector &data) {
|
||||
// Don't try to parse invalid frames
|
||||
|
||||
if(data.size() < 2)
|
||||
if (data.size() < 2)
|
||||
return;
|
||||
|
||||
// read the string data type (the first byte of the field data)
|
||||
@@ -202,10 +188,10 @@ void TextIdentificationFrame::parseFields(const ByteVector &data)
|
||||
|
||||
int dataLength = data.size() - 1;
|
||||
|
||||
while(dataLength > 0 && data[dataLength] == 0)
|
||||
while (dataLength > 0 && data[dataLength] == 0)
|
||||
dataLength--;
|
||||
|
||||
while(dataLength % byteAlign != 0)
|
||||
while (dataLength % byteAlign != 0)
|
||||
dataLength++;
|
||||
|
||||
ByteVectorList l = ByteVectorList::split(data.mid(1, dataLength), textDelimiter(d->textEncoding), byteAlign);
|
||||
@@ -215,9 +201,9 @@ void TextIdentificationFrame::parseFields(const ByteVector &data)
|
||||
// append those split values to the list and make sure that the new string's
|
||||
// type is the same specified for this frame
|
||||
|
||||
for(ByteVectorList::ConstIterator it = l.begin(); it != l.end(); it++) {
|
||||
if(!(*it).isEmpty()) {
|
||||
if(d->textEncoding == String::Latin1)
|
||||
for (ByteVectorList::ConstIterator it = l.begin(); it != l.end(); it++) {
|
||||
if (!(*it).isEmpty()) {
|
||||
if (d->textEncoding == String::Latin1)
|
||||
d->fieldList.append(Tag::latin1StringHandler()->parse(*it));
|
||||
else
|
||||
d->fieldList.append(String(*it, d->textEncoding));
|
||||
@@ -225,21 +211,20 @@ void TextIdentificationFrame::parseFields(const ByteVector &data)
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector TextIdentificationFrame::renderFields() const
|
||||
{
|
||||
ByteVector TextIdentificationFrame::renderFields() const {
|
||||
String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding);
|
||||
|
||||
ByteVector v;
|
||||
|
||||
v.append(char(encoding));
|
||||
|
||||
for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) {
|
||||
for (StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) {
|
||||
|
||||
// Since the field list is null delimited, if this is not the first
|
||||
// element in the list, append the appropriate delimiter for this
|
||||
// encoding.
|
||||
|
||||
if(it != d->fieldList.begin())
|
||||
if (it != d->fieldList.begin())
|
||||
v.append(textDelimiter(encoding));
|
||||
|
||||
v.append((*it).data(encoding));
|
||||
@@ -252,31 +237,28 @@ ByteVector TextIdentificationFrame::renderFields() const
|
||||
// TextIdentificationFrame private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new TextIdentificationFramePrivate())
|
||||
{
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new TextIdentificationFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
PropertyMap TextIdentificationFrame::makeTIPLProperties() const
|
||||
{
|
||||
PropertyMap TextIdentificationFrame::makeTIPLProperties() const {
|
||||
PropertyMap map;
|
||||
if(fieldList().size() % 2 != 0){
|
||||
if (fieldList().size() % 2 != 0) {
|
||||
// according to the ID3 spec, TIPL must contain an even number of entries
|
||||
map.unsupportedData().append(frameID());
|
||||
return map;
|
||||
}
|
||||
StringList l = fieldList();
|
||||
for(StringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
||||
for (StringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
||||
bool found = false;
|
||||
for(size_t i = 0; i < involvedPeopleSize; ++i)
|
||||
if(*it == involvedPeople[i][0]) {
|
||||
for (size_t i = 0; i < involvedPeopleSize; ++i)
|
||||
if (*it == involvedPeople[i][0]) {
|
||||
map.insert(involvedPeople[i][1], (++it)->split(","));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if(!found){
|
||||
if (!found) {
|
||||
// invalid involved role -> mark whole frame as unsupported in order to be consistent with writing
|
||||
map.clear();
|
||||
map.unsupportedData().append(frameID());
|
||||
@@ -286,18 +268,17 @@ PropertyMap TextIdentificationFrame::makeTIPLProperties() const
|
||||
return map;
|
||||
}
|
||||
|
||||
PropertyMap TextIdentificationFrame::makeTMCLProperties() const
|
||||
{
|
||||
PropertyMap TextIdentificationFrame::makeTMCLProperties() const {
|
||||
PropertyMap map;
|
||||
if(fieldList().size() % 2 != 0){
|
||||
if (fieldList().size() % 2 != 0) {
|
||||
// according to the ID3 spec, TMCL must contain an even number of entries
|
||||
map.unsupportedData().append(frameID());
|
||||
return map;
|
||||
}
|
||||
StringList l = fieldList();
|
||||
for(StringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
||||
for (StringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
||||
String instrument = it->upper();
|
||||
if(instrument.isEmpty()) {
|
||||
if (instrument.isEmpty()) {
|
||||
// instrument is not a valid key -> frame unsupported
|
||||
map.clear();
|
||||
map.unsupportedData().append(frameID());
|
||||
@@ -312,10 +293,8 @@ PropertyMap TextIdentificationFrame::makeTMCLProperties() const
|
||||
// UserTextIdentificationFrame public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) :
|
||||
TextIdentificationFrame("TXXX", encoding),
|
||||
d(0)
|
||||
{
|
||||
UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) : TextIdentificationFrame("TXXX", encoding),
|
||||
d(0) {
|
||||
StringList l;
|
||||
l.append(String());
|
||||
l.append(String());
|
||||
@@ -323,66 +302,54 @@ UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding)
|
||||
}
|
||||
|
||||
|
||||
UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data) :
|
||||
TextIdentificationFrame(data)
|
||||
{
|
||||
UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data) : TextIdentificationFrame(data) {
|
||||
checkFields();
|
||||
}
|
||||
|
||||
UserTextIdentificationFrame::UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding) :
|
||||
TextIdentificationFrame("TXXX", encoding),
|
||||
d(0)
|
||||
{
|
||||
UserTextIdentificationFrame::UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding) : TextIdentificationFrame("TXXX", encoding),
|
||||
d(0) {
|
||||
setDescription(description);
|
||||
setText(values);
|
||||
}
|
||||
|
||||
String UserTextIdentificationFrame::toString() const
|
||||
{
|
||||
String UserTextIdentificationFrame::toString() const {
|
||||
// first entry is the description itself, drop from values list
|
||||
StringList l = fieldList();
|
||||
for(StringList::Iterator it = l.begin(); it != l.end(); ++it) {
|
||||
for (StringList::Iterator it = l.begin(); it != l.end(); ++it) {
|
||||
l.erase(it);
|
||||
break;
|
||||
}
|
||||
return "[" + description() + "] " + l.toString();
|
||||
}
|
||||
|
||||
String UserTextIdentificationFrame::description() const
|
||||
{
|
||||
return !TextIdentificationFrame::fieldList().isEmpty()
|
||||
? TextIdentificationFrame::fieldList().front()
|
||||
: String();
|
||||
String UserTextIdentificationFrame::description() const {
|
||||
return !TextIdentificationFrame::fieldList().isEmpty() ? TextIdentificationFrame::fieldList().front() : String();
|
||||
}
|
||||
|
||||
StringList UserTextIdentificationFrame::fieldList() const
|
||||
{
|
||||
StringList UserTextIdentificationFrame::fieldList() const {
|
||||
// TODO: remove this function
|
||||
|
||||
return TextIdentificationFrame::fieldList();
|
||||
}
|
||||
|
||||
void UserTextIdentificationFrame::setText(const String &text)
|
||||
{
|
||||
if(description().isEmpty())
|
||||
void UserTextIdentificationFrame::setText(const String &text) {
|
||||
if (description().isEmpty())
|
||||
setDescription(String());
|
||||
|
||||
TextIdentificationFrame::setText(StringList(description()).append(text));
|
||||
}
|
||||
|
||||
void UserTextIdentificationFrame::setText(const StringList &fields)
|
||||
{
|
||||
if(description().isEmpty())
|
||||
void UserTextIdentificationFrame::setText(const StringList &fields) {
|
||||
if (description().isEmpty())
|
||||
setDescription(String());
|
||||
|
||||
TextIdentificationFrame::setText(StringList(description()).append(fields));
|
||||
}
|
||||
|
||||
void UserTextIdentificationFrame::setDescription(const String &s)
|
||||
{
|
||||
void UserTextIdentificationFrame::setDescription(const String &s) {
|
||||
StringList l = fieldList();
|
||||
|
||||
if(l.isEmpty())
|
||||
if (l.isEmpty())
|
||||
l.append(s);
|
||||
else
|
||||
l[0] = s;
|
||||
@@ -390,24 +357,23 @@ void UserTextIdentificationFrame::setDescription(const String &s)
|
||||
TextIdentificationFrame::setText(l);
|
||||
}
|
||||
|
||||
PropertyMap UserTextIdentificationFrame::asProperties() const
|
||||
{
|
||||
PropertyMap UserTextIdentificationFrame::asProperties() const {
|
||||
PropertyMap map;
|
||||
String tagName = txxxToKey(description());
|
||||
StringList v = fieldList();
|
||||
for(StringList::ConstIterator it = v.begin(); it != v.end(); ++it)
|
||||
if(it != v.begin())
|
||||
for (StringList::ConstIterator it = v.begin(); it != v.end(); ++it)
|
||||
if (it != v.begin())
|
||||
map.insert(tagName, *it);
|
||||
return map;
|
||||
}
|
||||
|
||||
UserTextIdentificationFrame *UserTextIdentificationFrame::find(
|
||||
ID3v2::Tag *tag, const String &description) // static
|
||||
ID3v2::Tag *tag, const String &description) // static
|
||||
{
|
||||
FrameList l = tag->frameList("TXXX");
|
||||
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
||||
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
||||
UserTextIdentificationFrame *f = dynamic_cast<UserTextIdentificationFrame *>(*it);
|
||||
if(f && f->description() == description)
|
||||
if (f && f->description() == description)
|
||||
return f;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -417,18 +383,15 @@ UserTextIdentificationFrame *UserTextIdentificationFrame::find(
|
||||
// UserTextIdentificationFrame private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data, Header *h) :
|
||||
TextIdentificationFrame(data, h)
|
||||
{
|
||||
UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data, Header *h) : TextIdentificationFrame(data, h) {
|
||||
checkFields();
|
||||
}
|
||||
|
||||
void UserTextIdentificationFrame::checkFields()
|
||||
{
|
||||
void UserTextIdentificationFrame::checkFields() {
|
||||
int fields = fieldList().size();
|
||||
|
||||
if(fields == 0)
|
||||
if (fields == 0)
|
||||
setDescription(String());
|
||||
if(fields <= 1)
|
||||
if (fields <= 1)
|
||||
setText(String());
|
||||
}
|
||||
|
||||
@@ -35,14 +35,14 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
class Tag;
|
||||
typedef Map<String, String> KeyConversionMap;
|
||||
class Tag;
|
||||
typedef Map<String, String> KeyConversionMap;
|
||||
|
||||
//! An ID3v2 text identification frame implementation
|
||||
//! An ID3v2 text identification frame implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of the most common type of ID3v2 frame -- text
|
||||
* identification frames. There are a number of variations on this. Those
|
||||
* enumerated in the ID3v2.4 standard are:
|
||||
@@ -104,12 +104,11 @@ namespace TagLib {
|
||||
* (with the encoding flag appropriately set in the output).
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT TextIdentificationFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT TextIdentificationFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Construct an empty frame of type \a type. Uses \a encoding as the
|
||||
* default text encoding.
|
||||
*
|
||||
@@ -118,34 +117,34 @@ namespace TagLib {
|
||||
*
|
||||
* \note Please see the note in the class description regarding Latin1.
|
||||
*/
|
||||
TextIdentificationFrame(const ByteVector &type, String::Type encoding);
|
||||
TextIdentificationFrame(const ByteVector &type, String::Type encoding);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is a dual purpose constructor. \a data can either be binary data
|
||||
* that should be parsed or (at a minimum) the frame ID.
|
||||
*/
|
||||
explicit TextIdentificationFrame(const ByteVector &data);
|
||||
explicit TextIdentificationFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is a special factory method to create a TIPL (involved people list)
|
||||
* frame from the given \a properties. Will parse key=[list of values] data
|
||||
* into the TIPL format as specified in the ID3 standard.
|
||||
*/
|
||||
static TextIdentificationFrame *createTIPLFrame(const PropertyMap &properties);
|
||||
static TextIdentificationFrame *createTIPLFrame(const PropertyMap &properties);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is a special factory method to create a TMCL (musician credits list)
|
||||
* frame from the given \a properties. Will parse key=[list of values] data
|
||||
* into the TMCL format as specified in the ID3 standard, where key should be
|
||||
* of the form instrumentPrefix:instrument.
|
||||
*/
|
||||
static TextIdentificationFrame *createTMCLFrame(const PropertyMap &properties);
|
||||
/*!
|
||||
static TextIdentificationFrame *createTMCLFrame(const PropertyMap &properties);
|
||||
/*!
|
||||
* Destroys this TextIdentificationFrame instance.
|
||||
*/
|
||||
virtual ~TextIdentificationFrame();
|
||||
virtual ~TextIdentificationFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Text identification frames are a list of string fields.
|
||||
*
|
||||
* This function will accept either a StringList or a String (using the
|
||||
@@ -155,14 +154,14 @@ namespace TagLib {
|
||||
* strings passed in are not of the same encoding. Please use
|
||||
* setEncoding(s.type()) if you wish to change the encoding of the frame.
|
||||
*/
|
||||
void setText(const StringList &l);
|
||||
void setText(const StringList &l);
|
||||
|
||||
// Reimplementations.
|
||||
// Reimplementations.
|
||||
|
||||
virtual void setText(const String &s);
|
||||
virtual String toString() const;
|
||||
virtual void setText(const String &s);
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text encoding that will be used in rendering this frame.
|
||||
* This defaults to the type that was either specified in the constructor
|
||||
* or read from the frame when parsed.
|
||||
@@ -172,9 +171,9 @@ namespace TagLib {
|
||||
* \see setTextEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
String::Type textEncoding() const;
|
||||
String::Type textEncoding() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the text encoding to be used when rendering this frame to
|
||||
* \a encoding.
|
||||
*
|
||||
@@ -183,51 +182,51 @@ namespace TagLib {
|
||||
* \see textEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
void setTextEncoding(String::Type encoding);
|
||||
void setTextEncoding(String::Type encoding);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a list of the strings in this frame.
|
||||
*/
|
||||
StringList fieldList() const;
|
||||
StringList fieldList() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a KeyConversionMap mapping a role as it would be used in a PropertyMap
|
||||
* to the corresponding key used in a TIPL ID3 frame to describe that role.
|
||||
*/
|
||||
static const KeyConversionMap &involvedPeopleMap();
|
||||
static const KeyConversionMap &involvedPeopleMap();
|
||||
|
||||
PropertyMap asProperties() const;
|
||||
PropertyMap asProperties() const;
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
TextIdentificationFrame(const ByteVector &data, Header *h);
|
||||
TextIdentificationFrame(const ByteVector &data, Header *h);
|
||||
|
||||
private:
|
||||
TextIdentificationFrame(const TextIdentificationFrame &);
|
||||
TextIdentificationFrame &operator=(const TextIdentificationFrame &);
|
||||
private:
|
||||
TextIdentificationFrame(const TextIdentificationFrame &);
|
||||
TextIdentificationFrame &operator=(const TextIdentificationFrame &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Parses the special structure of a TIPL frame
|
||||
* Only the whitelisted roles "ARRANGER", "ENGINEER", "PRODUCER",
|
||||
* "DJMIXER" (ID3: "DJ-MIX") and "MIXER" (ID3: "MIX") are allowed.
|
||||
*/
|
||||
PropertyMap makeTIPLProperties() const;
|
||||
/*!
|
||||
PropertyMap makeTIPLProperties() const;
|
||||
/*!
|
||||
* Parses the special structure of a TMCL frame.
|
||||
*/
|
||||
PropertyMap makeTMCLProperties() const;
|
||||
class TextIdentificationFramePrivate;
|
||||
TextIdentificationFramePrivate *d;
|
||||
};
|
||||
PropertyMap makeTMCLProperties() const;
|
||||
class TextIdentificationFramePrivate;
|
||||
TextIdentificationFramePrivate *d;
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is a specialization of text identification frames that allows for
|
||||
* user defined entries. Each entry has a description in addition to the
|
||||
* normal list of fields that a text identification frame has.
|
||||
@@ -235,49 +234,48 @@ namespace TagLib {
|
||||
* This description identifies the frame and must be unique.
|
||||
*/
|
||||
|
||||
//! An ID3v2 custom text identification frame implementation
|
||||
//! An ID3v2 custom text identification frame implementation
|
||||
|
||||
class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty user defined text identification frame. For this to be
|
||||
* a useful frame both a description and text must be set.
|
||||
*/
|
||||
explicit UserTextIdentificationFrame(String::Type encoding = String::Latin1);
|
||||
explicit UserTextIdentificationFrame(String::Type encoding = String::Latin1);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Creates a frame based on \a data.
|
||||
*/
|
||||
explicit UserTextIdentificationFrame(const ByteVector &data);
|
||||
explicit UserTextIdentificationFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Creates a user defined text identification frame with the given \a description
|
||||
* and \a values.
|
||||
*/
|
||||
UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding = String::UTF8);
|
||||
UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding = String::UTF8);
|
||||
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the description for this frame.
|
||||
*/
|
||||
String description() const;
|
||||
String description() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the description of the frame to \a s. \a s must be unique. You can
|
||||
* check for the presence of another user defined text frame of the same type
|
||||
* using find() and testing for null.
|
||||
*/
|
||||
void setDescription(const String &s);
|
||||
void setDescription(const String &s);
|
||||
|
||||
StringList fieldList() const;
|
||||
void setText(const String &text);
|
||||
void setText(const StringList &fields);
|
||||
StringList fieldList() const;
|
||||
void setText(const String &text);
|
||||
void setText(const StringList &fields);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* A UserTextIdentificationFrame is parsed into a PropertyMap as follows:
|
||||
* - the key is the frame's description, uppercased
|
||||
* - if the description contains '::', only the substring after that
|
||||
@@ -290,26 +288,26 @@ namespace TagLib {
|
||||
* in the value list, in order to be compatible with TagLib which copies
|
||||
* the description() into the fieldList().
|
||||
*/
|
||||
PropertyMap asProperties() const;
|
||||
PropertyMap asProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Searches for the user defined text frame with the description \a description
|
||||
* in \a tag. This returns null if no matching frames were found.
|
||||
*/
|
||||
static UserTextIdentificationFrame *find(Tag *tag, const String &description);
|
||||
static UserTextIdentificationFrame *find(Tag *tag, const String &description);
|
||||
|
||||
private:
|
||||
UserTextIdentificationFrame(const ByteVector &data, Header *h);
|
||||
UserTextIdentificationFrame(const TextIdentificationFrame &);
|
||||
UserTextIdentificationFrame &operator=(const UserTextIdentificationFrame &);
|
||||
private:
|
||||
UserTextIdentificationFrame(const ByteVector &data, Header *h);
|
||||
UserTextIdentificationFrame(const TextIdentificationFrame &);
|
||||
UserTextIdentificationFrame &operator=(const UserTextIdentificationFrame &);
|
||||
|
||||
void checkFields();
|
||||
void checkFields();
|
||||
|
||||
class UserTextIdentificationFramePrivate;
|
||||
UserTextIdentificationFramePrivate *d;
|
||||
};
|
||||
class UserTextIdentificationFramePrivate;
|
||||
UserTextIdentificationFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
@@ -33,9 +33,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class UniqueFileIdentifierFrame::UniqueFileIdentifierFramePrivate
|
||||
{
|
||||
public:
|
||||
class UniqueFileIdentifierFrame::UniqueFileIdentifierFramePrivate {
|
||||
public:
|
||||
String owner;
|
||||
ByteVector identifier;
|
||||
};
|
||||
@@ -44,55 +43,44 @@ public:
|
||||
// public methods
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data) :
|
||||
ID3v2::Frame(data),
|
||||
d(new UniqueFileIdentifierFramePrivate())
|
||||
{
|
||||
UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data) : ID3v2::Frame(data),
|
||||
d(new UniqueFileIdentifierFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const String &owner, const ByteVector &id) :
|
||||
ID3v2::Frame("UFID"),
|
||||
d(new UniqueFileIdentifierFramePrivate())
|
||||
{
|
||||
UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const String &owner, const ByteVector &id) : ID3v2::Frame("UFID"),
|
||||
d(new UniqueFileIdentifierFramePrivate()) {
|
||||
d->owner = owner;
|
||||
d->identifier = id;
|
||||
}
|
||||
|
||||
UniqueFileIdentifierFrame::~UniqueFileIdentifierFrame()
|
||||
{
|
||||
UniqueFileIdentifierFrame::~UniqueFileIdentifierFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String UniqueFileIdentifierFrame::owner() const
|
||||
{
|
||||
return d->owner;
|
||||
String UniqueFileIdentifierFrame::owner() const {
|
||||
return d->owner;
|
||||
}
|
||||
|
||||
ByteVector UniqueFileIdentifierFrame::identifier() const
|
||||
{
|
||||
ByteVector UniqueFileIdentifierFrame::identifier() const {
|
||||
return d->identifier;
|
||||
}
|
||||
|
||||
void UniqueFileIdentifierFrame::setOwner(const String &s)
|
||||
{
|
||||
void UniqueFileIdentifierFrame::setOwner(const String &s) {
|
||||
d->owner = s;
|
||||
}
|
||||
|
||||
void UniqueFileIdentifierFrame::setIdentifier(const ByteVector &v)
|
||||
{
|
||||
void UniqueFileIdentifierFrame::setIdentifier(const ByteVector &v) {
|
||||
d->identifier = v;
|
||||
}
|
||||
|
||||
String UniqueFileIdentifierFrame::toString() const
|
||||
{
|
||||
String UniqueFileIdentifierFrame::toString() const {
|
||||
return String();
|
||||
}
|
||||
|
||||
PropertyMap UniqueFileIdentifierFrame::asProperties() const
|
||||
{
|
||||
PropertyMap UniqueFileIdentifierFrame::asProperties() const {
|
||||
PropertyMap map;
|
||||
if(d->owner == "http://musicbrainz.org") {
|
||||
if (d->owner == "http://musicbrainz.org") {
|
||||
map.insert("MUSICBRAINZ_TRACKID", String(d->identifier));
|
||||
}
|
||||
else {
|
||||
@@ -101,25 +89,23 @@ PropertyMap UniqueFileIdentifierFrame::asProperties() const
|
||||
return map;
|
||||
}
|
||||
|
||||
UniqueFileIdentifierFrame *UniqueFileIdentifierFrame::findByOwner(const ID3v2::Tag *tag, const String &o) // static
|
||||
UniqueFileIdentifierFrame *UniqueFileIdentifierFrame::findByOwner(const ID3v2::Tag *tag, const String &o) // static
|
||||
{
|
||||
ID3v2::FrameList comments = tag->frameList("UFID");
|
||||
|
||||
for(ID3v2::FrameList::ConstIterator it = comments.begin();
|
||||
it != comments.end();
|
||||
++it)
|
||||
{
|
||||
for (ID3v2::FrameList::ConstIterator it = comments.begin();
|
||||
it != comments.end();
|
||||
++it) {
|
||||
UniqueFileIdentifierFrame *frame = dynamic_cast<UniqueFileIdentifierFrame *>(*it);
|
||||
if(frame && frame->owner() == o)
|
||||
if (frame && frame->owner() == o)
|
||||
return frame;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UniqueFileIdentifierFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < 1) {
|
||||
void UniqueFileIdentifierFrame::parseFields(const ByteVector &data) {
|
||||
if (data.size() < 1) {
|
||||
debug("An UFID frame must contain at least 1 byte.");
|
||||
return;
|
||||
}
|
||||
@@ -129,8 +115,7 @@ void UniqueFileIdentifierFrame::parseFields(const ByteVector &data)
|
||||
d->identifier = data.mid(pos);
|
||||
}
|
||||
|
||||
ByteVector UniqueFileIdentifierFrame::renderFields() const
|
||||
{
|
||||
ByteVector UniqueFileIdentifierFrame::renderFields() const {
|
||||
ByteVector data;
|
||||
|
||||
data.append(d->owner.data(String::Latin1));
|
||||
@@ -140,9 +125,7 @@ ByteVector UniqueFileIdentifierFrame::renderFields() const
|
||||
return data;
|
||||
}
|
||||
|
||||
UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new UniqueFileIdentifierFramePrivate())
|
||||
{
|
||||
UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new UniqueFileIdentifierFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -31,38 +31,37 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of ID3v2 unique file identifier frames. This
|
||||
* frame is used to identify the file in an arbitrary database identified
|
||||
* by the owner field.
|
||||
*/
|
||||
|
||||
//! An implementation of ID3v2 unique identifier frames
|
||||
//! An implementation of ID3v2 unique identifier frames
|
||||
|
||||
class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Creates a unique file identifier frame based on \a data.
|
||||
*/
|
||||
UniqueFileIdentifierFrame(const ByteVector &data);
|
||||
UniqueFileIdentifierFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Creates a unique file identifier frame with the owner \a owner and
|
||||
* the identification \a id.
|
||||
*/
|
||||
UniqueFileIdentifierFrame(const String &owner, const ByteVector &id);
|
||||
UniqueFileIdentifierFrame(const String &owner, const ByteVector &id);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys the frame.
|
||||
*/
|
||||
~UniqueFileIdentifierFrame();
|
||||
~UniqueFileIdentifierFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the owner for the frame; essentially this is the key for
|
||||
* determining which identification scheme this key belongs to. This
|
||||
* will usually either be an email address or URL for the person or tool
|
||||
@@ -70,56 +69,56 @@ namespace TagLib {
|
||||
*
|
||||
* \see setOwner()
|
||||
*/
|
||||
String owner() const;
|
||||
String owner() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the unique identifier. Though sometimes this is a text string
|
||||
* it also may be binary data and as much should be assumed when handling
|
||||
* it.
|
||||
*/
|
||||
ByteVector identifier() const;
|
||||
ByteVector identifier() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the owner of the identification scheme to \a s.
|
||||
*
|
||||
* \see owner()
|
||||
*/
|
||||
void setOwner(const String &s);
|
||||
void setOwner(const String &s);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the unique file identifier to \a v.
|
||||
*
|
||||
* \see identifier()
|
||||
*/
|
||||
void setIdentifier(const ByteVector &v);
|
||||
void setIdentifier(const ByteVector &v);
|
||||
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
PropertyMap asProperties() const;
|
||||
PropertyMap asProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* UFID frames each have a unique owner. This searches for a UFID
|
||||
* frame with the owner \a o and returns a pointer to it.
|
||||
*
|
||||
* \see owner()
|
||||
*/
|
||||
static UniqueFileIdentifierFrame *findByOwner(const Tag *tag, const String &o);
|
||||
static UniqueFileIdentifierFrame *findByOwner(const Tag *tag, const String &o);
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
UniqueFileIdentifierFrame(const UniqueFileIdentifierFrame &);
|
||||
UniqueFileIdentifierFrame &operator=(const UniqueFileIdentifierFrame &);
|
||||
private:
|
||||
UniqueFileIdentifierFrame(const UniqueFileIdentifierFrame &);
|
||||
UniqueFileIdentifierFrame &operator=(const UniqueFileIdentifierFrame &);
|
||||
|
||||
UniqueFileIdentifierFrame(const ByteVector &data, Header *h);
|
||||
UniqueFileIdentifierFrame(const ByteVector &data, Header *h);
|
||||
|
||||
class UniqueFileIdentifierFramePrivate;
|
||||
UniqueFileIdentifierFramePrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class UniqueFileIdentifierFramePrivate;
|
||||
UniqueFileIdentifierFramePrivate *d;
|
||||
};
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,9 +28,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class UnknownFrame::UnknownFramePrivate
|
||||
{
|
||||
public:
|
||||
class UnknownFrame::UnknownFramePrivate {
|
||||
public:
|
||||
ByteVector fieldData;
|
||||
};
|
||||
|
||||
@@ -38,25 +37,20 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnknownFrame::UnknownFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new UnknownFramePrivate())
|
||||
{
|
||||
UnknownFrame::UnknownFrame(const ByteVector &data) : Frame(data),
|
||||
d(new UnknownFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
UnknownFrame::~UnknownFrame()
|
||||
{
|
||||
UnknownFrame::~UnknownFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String UnknownFrame::toString() const
|
||||
{
|
||||
String UnknownFrame::toString() const {
|
||||
return String();
|
||||
}
|
||||
|
||||
ByteVector UnknownFrame::data() const
|
||||
{
|
||||
ByteVector UnknownFrame::data() const {
|
||||
return d->fieldData;
|
||||
}
|
||||
|
||||
@@ -64,13 +58,11 @@ ByteVector UnknownFrame::data() const
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UnknownFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void UnknownFrame::parseFields(const ByteVector &data) {
|
||||
d->fieldData = data;
|
||||
}
|
||||
|
||||
ByteVector UnknownFrame::renderFields() const
|
||||
{
|
||||
ByteVector UnknownFrame::renderFields() const {
|
||||
return d->fieldData;
|
||||
}
|
||||
|
||||
@@ -78,9 +70,7 @@ ByteVector UnknownFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnknownFrame::UnknownFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new UnknownFramePrivate())
|
||||
{
|
||||
UnknownFrame::UnknownFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new UnknownFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
49
3rdparty/taglib/mpeg/id3v2/frames/unknownframe.h
vendored
49
3rdparty/taglib/mpeg/id3v2/frames/unknownframe.h
vendored
@@ -32,11 +32,11 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! A frame type \e unknown to TagLib.
|
||||
//! A frame type \e unknown to TagLib.
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This class represents a frame type not known (or more often simply
|
||||
* unimplemented) in TagLib. This is here provide a basic API for
|
||||
* manipulating the binary data of unknown frames and to provide a means
|
||||
@@ -47,35 +47,34 @@ namespace TagLib {
|
||||
* to have your frame type supported through the standard ID3v2 mechanism.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT UnknownFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT UnknownFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
UnknownFrame(const ByteVector &data);
|
||||
virtual ~UnknownFrame();
|
||||
public:
|
||||
UnknownFrame(const ByteVector &data);
|
||||
virtual ~UnknownFrame();
|
||||
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the field data (everything but the header) for this frame.
|
||||
*/
|
||||
ByteVector data() const;
|
||||
ByteVector data() const;
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
UnknownFrame(const ByteVector &data, Header *h);
|
||||
UnknownFrame(const UnknownFrame &);
|
||||
UnknownFrame &operator=(const UnknownFrame &);
|
||||
private:
|
||||
UnknownFrame(const ByteVector &data, Header *h);
|
||||
UnknownFrame(const UnknownFrame &);
|
||||
UnknownFrame &operator=(const UnknownFrame &);
|
||||
|
||||
class UnknownFramePrivate;
|
||||
UnknownFramePrivate *d;
|
||||
};
|
||||
class UnknownFramePrivate;
|
||||
UnknownFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
@@ -35,9 +35,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class UnsynchronizedLyricsFrame::UnsynchronizedLyricsFramePrivate
|
||||
{
|
||||
public:
|
||||
class UnsynchronizedLyricsFrame::UnsynchronizedLyricsFramePrivate {
|
||||
public:
|
||||
UnsynchronizedLyricsFramePrivate() : textEncoding(String::Latin1) {}
|
||||
String::Type textEncoding;
|
||||
ByteVector language;
|
||||
@@ -49,89 +48,74 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(String::Type encoding) :
|
||||
Frame("USLT"),
|
||||
d(new UnsynchronizedLyricsFramePrivate())
|
||||
{
|
||||
UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(String::Type encoding) : Frame("USLT"),
|
||||
d(new UnsynchronizedLyricsFramePrivate()) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new UnsynchronizedLyricsFramePrivate())
|
||||
{
|
||||
UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data) : Frame(data),
|
||||
d(new UnsynchronizedLyricsFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
UnsynchronizedLyricsFrame::~UnsynchronizedLyricsFrame()
|
||||
{
|
||||
UnsynchronizedLyricsFrame::~UnsynchronizedLyricsFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String UnsynchronizedLyricsFrame::toString() const
|
||||
{
|
||||
String UnsynchronizedLyricsFrame::toString() const {
|
||||
return d->text;
|
||||
}
|
||||
|
||||
ByteVector UnsynchronizedLyricsFrame::language() const
|
||||
{
|
||||
ByteVector UnsynchronizedLyricsFrame::language() const {
|
||||
return d->language;
|
||||
}
|
||||
|
||||
String UnsynchronizedLyricsFrame::description() const
|
||||
{
|
||||
String UnsynchronizedLyricsFrame::description() const {
|
||||
return d->description;
|
||||
}
|
||||
|
||||
String UnsynchronizedLyricsFrame::text() const
|
||||
{
|
||||
String UnsynchronizedLyricsFrame::text() const {
|
||||
return d->text;
|
||||
}
|
||||
|
||||
void UnsynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding)
|
||||
{
|
||||
void UnsynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding) {
|
||||
d->language = languageEncoding.mid(0, 3);
|
||||
}
|
||||
|
||||
void UnsynchronizedLyricsFrame::setDescription(const String &s)
|
||||
{
|
||||
void UnsynchronizedLyricsFrame::setDescription(const String &s) {
|
||||
d->description = s;
|
||||
}
|
||||
|
||||
void UnsynchronizedLyricsFrame::setText(const String &s)
|
||||
{
|
||||
void UnsynchronizedLyricsFrame::setText(const String &s) {
|
||||
d->text = s;
|
||||
}
|
||||
|
||||
|
||||
String::Type UnsynchronizedLyricsFrame::textEncoding() const
|
||||
{
|
||||
String::Type UnsynchronizedLyricsFrame::textEncoding() const {
|
||||
return d->textEncoding;
|
||||
}
|
||||
|
||||
void UnsynchronizedLyricsFrame::setTextEncoding(String::Type encoding)
|
||||
{
|
||||
void UnsynchronizedLyricsFrame::setTextEncoding(String::Type encoding) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
PropertyMap UnsynchronizedLyricsFrame::asProperties() const
|
||||
{
|
||||
PropertyMap UnsynchronizedLyricsFrame::asProperties() const {
|
||||
PropertyMap map;
|
||||
String key = description().upper();
|
||||
if(key.isEmpty() || key == "LYRICS")
|
||||
if (key.isEmpty() || key == "LYRICS")
|
||||
map.insert("LYRICS", text());
|
||||
else
|
||||
map.insert("LYRICS:" + key, text());
|
||||
return map;
|
||||
}
|
||||
|
||||
UnsynchronizedLyricsFrame *UnsynchronizedLyricsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static
|
||||
UnsynchronizedLyricsFrame *UnsynchronizedLyricsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static
|
||||
{
|
||||
ID3v2::FrameList lyrics = tag->frameList("USLT");
|
||||
|
||||
for(ID3v2::FrameList::ConstIterator it = lyrics.begin(); it != lyrics.end(); ++it){
|
||||
for (ID3v2::FrameList::ConstIterator it = lyrics.begin(); it != lyrics.end(); ++it) {
|
||||
UnsynchronizedLyricsFrame *frame = dynamic_cast<UnsynchronizedLyricsFrame *>(*it);
|
||||
if(frame && frame->description() == d)
|
||||
if (frame && frame->description() == d)
|
||||
return frame;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -140,9 +124,8 @@ UnsynchronizedLyricsFrame *UnsynchronizedLyricsFrame::findByDescription(const ID
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < 5) {
|
||||
void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data) {
|
||||
if (data.size() < 5) {
|
||||
debug("An unsynchronized lyrics frame must contain at least 5 bytes.");
|
||||
return;
|
||||
}
|
||||
@@ -150,25 +133,24 @@ void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
d->textEncoding = String::Type(data[0]);
|
||||
d->language = data.mid(1, 3);
|
||||
|
||||
int byteAlign
|
||||
= d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;
|
||||
int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;
|
||||
|
||||
ByteVectorList l =
|
||||
ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2);
|
||||
|
||||
if(l.size() == 2) {
|
||||
if(d->textEncoding == String::Latin1) {
|
||||
if (l.size() == 2) {
|
||||
if (d->textEncoding == String::Latin1) {
|
||||
d->description = Tag::latin1StringHandler()->parse(l.front());
|
||||
d->text = Tag::latin1StringHandler()->parse(l.back());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
d->description = String(l.front(), d->textEncoding);
|
||||
d->text = String(l.back(), d->textEncoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector UnsynchronizedLyricsFrame::renderFields() const
|
||||
{
|
||||
ByteVector UnsynchronizedLyricsFrame::renderFields() const {
|
||||
StringList sl;
|
||||
sl.append(d->description);
|
||||
sl.append(d->text);
|
||||
@@ -190,9 +172,7 @@ ByteVector UnsynchronizedLyricsFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new UnsynchronizedLyricsFramePrivate())
|
||||
{
|
||||
UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new UnsynchronizedLyricsFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -33,41 +33,40 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! ID3v2 unsynchronized lyrics frame
|
||||
/*!
|
||||
//! ID3v2 unsynchronized lyrics frame
|
||||
/*!
|
||||
* An implementation of ID3v2 unsynchronized lyrics.
|
||||
*/
|
||||
class TAGLIB_EXPORT UnsynchronizedLyricsFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT UnsynchronizedLyricsFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Construct an empty unsynchronized lyrics frame that will use the text encoding
|
||||
* \a encoding.
|
||||
*/
|
||||
explicit UnsynchronizedLyricsFrame(String::Type encoding = String::Latin1);
|
||||
explicit UnsynchronizedLyricsFrame(String::Type encoding = String::Latin1);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Construct a unsynchronized lyrics frame based on the data in \a data.
|
||||
*/
|
||||
explicit UnsynchronizedLyricsFrame(const ByteVector &data);
|
||||
explicit UnsynchronizedLyricsFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this UnsynchronizedLyricsFrame instance.
|
||||
*/
|
||||
virtual ~UnsynchronizedLyricsFrame();
|
||||
virtual ~UnsynchronizedLyricsFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text of this unsynchronized lyrics frame.
|
||||
*
|
||||
* \see text()
|
||||
*/
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the language encoding as a 3 byte encoding as specified by
|
||||
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
|
||||
*
|
||||
@@ -75,48 +74,48 @@ namespace TagLib {
|
||||
*
|
||||
* \see setLanguage()
|
||||
*/
|
||||
ByteVector language() const;
|
||||
ByteVector language() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the description of this unsynchronized lyrics frame.
|
||||
*
|
||||
* \note Most taggers simply ignore this value.
|
||||
*
|
||||
* \see setDescription()
|
||||
*/
|
||||
String description() const;
|
||||
String description() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text of this unsynchronized lyrics frame.
|
||||
*
|
||||
* \see setText()
|
||||
*/
|
||||
String text() const;
|
||||
String text() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the language using the 3 byte language code from
|
||||
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
|
||||
* \a languageCode.
|
||||
*
|
||||
* \see language()
|
||||
*/
|
||||
void setLanguage(const ByteVector &languageCode);
|
||||
void setLanguage(const ByteVector &languageCode);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the description of the unsynchronized lyrics frame to \a s.
|
||||
*
|
||||
* \see description()
|
||||
*/
|
||||
void setDescription(const String &s);
|
||||
void setDescription(const String &s);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the text portion of the unsynchronized lyrics frame to \a s.
|
||||
*
|
||||
* \see text()
|
||||
*/
|
||||
virtual void setText(const String &s);
|
||||
virtual void setText(const String &s);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text encoding that will be used in rendering this frame.
|
||||
* This defaults to the type that was either specified in the constructor
|
||||
* or read from the frame when parsed.
|
||||
@@ -124,19 +123,19 @@ namespace TagLib {
|
||||
* \see setTextEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
String::Type textEncoding() const;
|
||||
String::Type textEncoding() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the text encoding to be used when rendering this frame to
|
||||
* \a encoding.
|
||||
*
|
||||
* \see textEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
void setTextEncoding(String::Type encoding);
|
||||
void setTextEncoding(String::Type encoding);
|
||||
|
||||
|
||||
/*! Parses this frame as PropertyMap with a single key.
|
||||
/*! Parses this frame as PropertyMap with a single key.
|
||||
* - if description() is empty or "LYRICS", the key will be "LYRICS"
|
||||
* - if description() is not a valid PropertyMap key, the frame will be
|
||||
* marked unsupported by an entry "USLT/<description>" in the unsupportedData()
|
||||
@@ -146,36 +145,36 @@ namespace TagLib {
|
||||
* Note that currently the language() field is not supported by the PropertyMap
|
||||
* interface.
|
||||
*/
|
||||
PropertyMap asProperties() const;
|
||||
PropertyMap asProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* LyricsFrames each have a unique description. This searches for a lyrics
|
||||
* frame with the description \a d and returns a pointer to it. If no
|
||||
* frame is found that matches the given description null is returned.
|
||||
*
|
||||
* \see description()
|
||||
*/
|
||||
static UnsynchronizedLyricsFrame *findByDescription(const Tag *tag, const String &d);
|
||||
static UnsynchronizedLyricsFrame *findByDescription(const Tag *tag, const String &d);
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
private:
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
UnsynchronizedLyricsFrame(const ByteVector &data, Header *h);
|
||||
UnsynchronizedLyricsFrame(const UnsynchronizedLyricsFrame &);
|
||||
UnsynchronizedLyricsFrame &operator=(const UnsynchronizedLyricsFrame &);
|
||||
UnsynchronizedLyricsFrame(const ByteVector &data, Header *h);
|
||||
UnsynchronizedLyricsFrame(const UnsynchronizedLyricsFrame &);
|
||||
UnsynchronizedLyricsFrame &operator=(const UnsynchronizedLyricsFrame &);
|
||||
|
||||
class UnsynchronizedLyricsFramePrivate;
|
||||
UnsynchronizedLyricsFramePrivate *d;
|
||||
};
|
||||
class UnsynchronizedLyricsFramePrivate;
|
||||
UnsynchronizedLyricsFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
109
3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.cpp
vendored
109
3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.cpp
vendored
@@ -35,15 +35,13 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class UrlLinkFrame::UrlLinkFramePrivate
|
||||
{
|
||||
public:
|
||||
class UrlLinkFrame::UrlLinkFramePrivate {
|
||||
public:
|
||||
String url;
|
||||
};
|
||||
|
||||
class UserUrlLinkFrame::UserUrlLinkFramePrivate
|
||||
{
|
||||
public:
|
||||
class UserUrlLinkFrame::UserUrlLinkFramePrivate {
|
||||
public:
|
||||
UserUrlLinkFramePrivate() : textEncoding(String::Latin1) {}
|
||||
String::Type textEncoding;
|
||||
String description;
|
||||
@@ -53,43 +51,35 @@ public:
|
||||
// UrlLinkFrame public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UrlLinkFrame::UrlLinkFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new UrlLinkFramePrivate())
|
||||
{
|
||||
UrlLinkFrame::UrlLinkFrame(const ByteVector &data) : Frame(data),
|
||||
d(new UrlLinkFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
UrlLinkFrame::~UrlLinkFrame()
|
||||
{
|
||||
UrlLinkFrame::~UrlLinkFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
void UrlLinkFrame::setUrl(const String &s)
|
||||
{
|
||||
void UrlLinkFrame::setUrl(const String &s) {
|
||||
d->url = s;
|
||||
}
|
||||
|
||||
String UrlLinkFrame::url() const
|
||||
{
|
||||
String UrlLinkFrame::url() const {
|
||||
return d->url;
|
||||
}
|
||||
|
||||
void UrlLinkFrame::setText(const String &s)
|
||||
{
|
||||
void UrlLinkFrame::setText(const String &s) {
|
||||
setUrl(s);
|
||||
}
|
||||
|
||||
String UrlLinkFrame::toString() const
|
||||
{
|
||||
String UrlLinkFrame::toString() const {
|
||||
return url();
|
||||
}
|
||||
|
||||
PropertyMap UrlLinkFrame::asProperties() const
|
||||
{
|
||||
PropertyMap UrlLinkFrame::asProperties() const {
|
||||
String key = frameIDToKey(frameID());
|
||||
PropertyMap map;
|
||||
if(key.isEmpty())
|
||||
if (key.isEmpty())
|
||||
// unknown W*** frame - this normally shouldn't happen
|
||||
map.unsupportedData().append(frameID());
|
||||
else
|
||||
@@ -101,20 +91,16 @@ PropertyMap UrlLinkFrame::asProperties() const
|
||||
// UrlLinkFrame protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UrlLinkFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
void UrlLinkFrame::parseFields(const ByteVector &data) {
|
||||
d->url = String(data);
|
||||
}
|
||||
|
||||
ByteVector UrlLinkFrame::renderFields() const
|
||||
{
|
||||
ByteVector UrlLinkFrame::renderFields() const {
|
||||
return d->url.data(String::Latin1);
|
||||
}
|
||||
|
||||
UrlLinkFrame::UrlLinkFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new UrlLinkFramePrivate())
|
||||
{
|
||||
UrlLinkFrame::UrlLinkFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||
d(new UrlLinkFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@@ -122,67 +108,56 @@ UrlLinkFrame::UrlLinkFrame(const ByteVector &data, Header *h) :
|
||||
// UserUrlLinkFrame public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UserUrlLinkFrame::UserUrlLinkFrame(String::Type encoding) :
|
||||
UrlLinkFrame("WXXX"),
|
||||
d(new UserUrlLinkFramePrivate())
|
||||
{
|
||||
UserUrlLinkFrame::UserUrlLinkFrame(String::Type encoding) : UrlLinkFrame("WXXX"),
|
||||
d(new UserUrlLinkFramePrivate()) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data) :
|
||||
UrlLinkFrame(data),
|
||||
d(new UserUrlLinkFramePrivate())
|
||||
{
|
||||
UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data) : UrlLinkFrame(data),
|
||||
d(new UserUrlLinkFramePrivate()) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
UserUrlLinkFrame::~UserUrlLinkFrame()
|
||||
{
|
||||
UserUrlLinkFrame::~UserUrlLinkFrame() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String UserUrlLinkFrame::toString() const
|
||||
{
|
||||
String UserUrlLinkFrame::toString() const {
|
||||
return "[" + description() + "] " + url();
|
||||
}
|
||||
|
||||
String::Type UserUrlLinkFrame::textEncoding() const
|
||||
{
|
||||
String::Type UserUrlLinkFrame::textEncoding() const {
|
||||
return d->textEncoding;
|
||||
}
|
||||
|
||||
void UserUrlLinkFrame::setTextEncoding(String::Type encoding)
|
||||
{
|
||||
void UserUrlLinkFrame::setTextEncoding(String::Type encoding) {
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
String UserUrlLinkFrame::description() const
|
||||
{
|
||||
String UserUrlLinkFrame::description() const {
|
||||
return d->description;
|
||||
}
|
||||
|
||||
void UserUrlLinkFrame::setDescription(const String &s)
|
||||
{
|
||||
void UserUrlLinkFrame::setDescription(const String &s) {
|
||||
d->description = s;
|
||||
}
|
||||
|
||||
PropertyMap UserUrlLinkFrame::asProperties() const
|
||||
{
|
||||
PropertyMap UserUrlLinkFrame::asProperties() const {
|
||||
PropertyMap map;
|
||||
String key = description().upper();
|
||||
if(key.isEmpty() || key == "URL")
|
||||
if (key.isEmpty() || key == "URL")
|
||||
map.insert("URL", url());
|
||||
else
|
||||
map.insert("URL:" + key, url());
|
||||
return map;
|
||||
}
|
||||
|
||||
UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &description) // static
|
||||
UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &description) // static
|
||||
{
|
||||
FrameList l = tag->frameList("WXXX");
|
||||
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
||||
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
||||
UserUrlLinkFrame *f = dynamic_cast<UserUrlLinkFrame *>(*it);
|
||||
if(f && f->description() == description)
|
||||
if (f && f->description() == description)
|
||||
return f;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -192,9 +167,8 @@ UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &descript
|
||||
// UserUrlLinkFrame protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UserUrlLinkFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < 2) {
|
||||
void UserUrlLinkFrame::parseFields(const ByteVector &data) {
|
||||
if (data.size() < 2) {
|
||||
debug("A user URL link frame must contain at least 2 bytes.");
|
||||
return;
|
||||
}
|
||||
@@ -204,9 +178,9 @@ void UserUrlLinkFrame::parseFields(const ByteVector &data)
|
||||
d->textEncoding = String::Type(data[0]);
|
||||
pos += 1;
|
||||
|
||||
if(d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8) {
|
||||
if (d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8) {
|
||||
int offset = data.find(textDelimiter(d->textEncoding), pos);
|
||||
if(offset < pos)
|
||||
if (offset < pos)
|
||||
return;
|
||||
|
||||
d->description = String(data.mid(pos, offset - pos), d->textEncoding);
|
||||
@@ -214,7 +188,7 @@ void UserUrlLinkFrame::parseFields(const ByteVector &data)
|
||||
}
|
||||
else {
|
||||
int len = data.mid(pos).find(textDelimiter(d->textEncoding), 0, 2);
|
||||
if(len < 0)
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
d->description = String(data.mid(pos, len), d->textEncoding);
|
||||
@@ -224,8 +198,7 @@ void UserUrlLinkFrame::parseFields(const ByteVector &data)
|
||||
setUrl(String(data.mid(pos)));
|
||||
}
|
||||
|
||||
ByteVector UserUrlLinkFrame::renderFields() const
|
||||
{
|
||||
ByteVector UserUrlLinkFrame::renderFields() const {
|
||||
ByteVector v;
|
||||
|
||||
String::Type encoding = checkTextEncoding(d->description, d->textEncoding);
|
||||
@@ -238,9 +211,7 @@ ByteVector UserUrlLinkFrame::renderFields() const
|
||||
return v;
|
||||
}
|
||||
|
||||
UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data, Header *h) :
|
||||
UrlLinkFrame(data, h),
|
||||
d(new UserUrlLinkFramePrivate())
|
||||
{
|
||||
UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data, Header *h) : UrlLinkFrame(data, h),
|
||||
d(new UserUrlLinkFramePrivate()) {
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
138
3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.h
vendored
138
3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.h
vendored
@@ -34,97 +34,95 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! ID3v2 URL frame
|
||||
/*!
|
||||
//! ID3v2 URL frame
|
||||
/*!
|
||||
* An implementation of ID3v2 URL link frames.
|
||||
*/
|
||||
class TAGLIB_EXPORT UrlLinkFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT UrlLinkFrame : public Frame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* This is a dual purpose constructor. \a data can either be binary data
|
||||
* that should be parsed or (at a minimum) the frame ID.
|
||||
*/
|
||||
explicit UrlLinkFrame(const ByteVector &data);
|
||||
explicit UrlLinkFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this UrlLinkFrame instance.
|
||||
*/
|
||||
virtual ~UrlLinkFrame();
|
||||
virtual ~UrlLinkFrame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the URL.
|
||||
*/
|
||||
virtual String url() const;
|
||||
virtual String url() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the URL to \a s.
|
||||
*/
|
||||
virtual void setUrl(const String &s);
|
||||
virtual void setUrl(const String &s);
|
||||
|
||||
// Reimplementations.
|
||||
// Reimplementations.
|
||||
|
||||
virtual void setText(const String &s);
|
||||
virtual String toString() const;
|
||||
PropertyMap asProperties() const;
|
||||
virtual void setText(const String &s);
|
||||
virtual String toString() const;
|
||||
PropertyMap asProperties() const;
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
UrlLinkFrame(const ByteVector &data, Header *h);
|
||||
UrlLinkFrame(const ByteVector &data, Header *h);
|
||||
|
||||
private:
|
||||
UrlLinkFrame(const UrlLinkFrame &);
|
||||
UrlLinkFrame &operator=(const UrlLinkFrame &);
|
||||
private:
|
||||
UrlLinkFrame(const UrlLinkFrame &);
|
||||
UrlLinkFrame &operator=(const UrlLinkFrame &);
|
||||
|
||||
class UrlLinkFramePrivate;
|
||||
UrlLinkFramePrivate *d;
|
||||
};
|
||||
class UrlLinkFramePrivate;
|
||||
UrlLinkFramePrivate *d;
|
||||
};
|
||||
|
||||
//! ID3v2 User defined URL frame
|
||||
//! ID3v2 User defined URL frame
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is a specialization of URL link frames that allows for
|
||||
* user defined entries. Each entry has a description in addition to the
|
||||
* normal list of fields that a URL link frame has.
|
||||
*
|
||||
* This description identifies the frame and must be unique.
|
||||
*/
|
||||
class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame {
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty user defined URL link frame. For this to be
|
||||
* a useful frame both a description and text must be set.
|
||||
*/
|
||||
explicit UserUrlLinkFrame(String::Type encoding = String::Latin1);
|
||||
explicit UserUrlLinkFrame(String::Type encoding = String::Latin1);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is a dual purpose constructor. \a data can either be binary data
|
||||
* that should be parsed or (at a minimum) the frame ID.
|
||||
*/
|
||||
explicit UserUrlLinkFrame(const ByteVector &data);
|
||||
explicit UserUrlLinkFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this UserUrlLinkFrame instance.
|
||||
*/
|
||||
virtual ~UserUrlLinkFrame();
|
||||
virtual ~UserUrlLinkFrame();
|
||||
|
||||
// Reimplementations.
|
||||
// Reimplementations.
|
||||
|
||||
virtual String toString() const;
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text encoding that will be used in rendering this frame.
|
||||
* This defaults to the type that was either specified in the constructor
|
||||
* or read from the frame when parsed.
|
||||
@@ -132,28 +130,28 @@ namespace TagLib {
|
||||
* \see setTextEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
String::Type textEncoding() const;
|
||||
String::Type textEncoding() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the text encoding to be used when rendering this frame to
|
||||
* \a encoding.
|
||||
*
|
||||
* \see textEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
void setTextEncoding(String::Type encoding);
|
||||
void setTextEncoding(String::Type encoding);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the description for this frame.
|
||||
*/
|
||||
String description() const;
|
||||
String description() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the description of the frame to \a s. \a s must be unique.
|
||||
*/
|
||||
void setDescription(const String &s);
|
||||
void setDescription(const String &s);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Parses the UserUrlLinkFrame as PropertyMap. The description() is taken as key,
|
||||
* and the URL as single value.
|
||||
* - if description() is empty, the key will be "URL".
|
||||
@@ -161,32 +159,32 @@ namespace TagLib {
|
||||
* characters), the returned map will contain an entry "WXXX/<description>"
|
||||
* in its unsupportedData() list.
|
||||
*/
|
||||
PropertyMap asProperties() const;
|
||||
PropertyMap asProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Searches for the user defined url frame with the description \a description
|
||||
* in \a tag. This returns null if no matching frames were found.
|
||||
*/
|
||||
static UserUrlLinkFrame *find(Tag *tag, const String &description);
|
||||
static UserUrlLinkFrame *find(Tag *tag, const String &description);
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
UserUrlLinkFrame(const ByteVector &data, Header *h);
|
||||
UserUrlLinkFrame(const ByteVector &data, Header *h);
|
||||
|
||||
private:
|
||||
UserUrlLinkFrame(const UserUrlLinkFrame &);
|
||||
UserUrlLinkFrame &operator=(const UserUrlLinkFrame &);
|
||||
private:
|
||||
UserUrlLinkFrame(const UserUrlLinkFrame &);
|
||||
UserUrlLinkFrame &operator=(const UserUrlLinkFrame &);
|
||||
|
||||
class UserUrlLinkFramePrivate;
|
||||
UserUrlLinkFramePrivate *d;
|
||||
};
|
||||
class UserUrlLinkFramePrivate;
|
||||
UserUrlLinkFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
22
3rdparty/taglib/mpeg/id3v2/id3v2.h
vendored
22
3rdparty/taglib/mpeg/id3v2/id3v2.h
vendored
@@ -3,24 +3,24 @@
|
||||
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
//! An ID3v2 implementation
|
||||
//! An ID3v2 implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is a relatively complete and flexible framework for working with ID3v2
|
||||
* tags.
|
||||
*
|
||||
* \see ID3v2::Tag
|
||||
*/
|
||||
namespace ID3v2 {
|
||||
/*!
|
||||
namespace ID3v2 {
|
||||
/*!
|
||||
* Used to specify which version of the ID3 standard to use when saving tags.
|
||||
*/
|
||||
enum Version {
|
||||
v3 = 3, //<! ID3v2.3
|
||||
v4 = 4 //<! ID3v2.4
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
enum Version {
|
||||
v3 = 3, //<! ID3v2.3
|
||||
v4 = 4 //<! ID3v2.4
|
||||
};
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,9 +29,8 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class ExtendedHeader::ExtendedHeaderPrivate
|
||||
{
|
||||
public:
|
||||
class ExtendedHeader::ExtendedHeaderPrivate {
|
||||
public:
|
||||
ExtendedHeaderPrivate() : size(0) {}
|
||||
|
||||
unsigned int size;
|
||||
@@ -41,23 +40,18 @@ public:
|
||||
// public methods
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExtendedHeader::ExtendedHeader() :
|
||||
d(new ExtendedHeaderPrivate())
|
||||
{
|
||||
ExtendedHeader::ExtendedHeader() : d(new ExtendedHeaderPrivate()) {
|
||||
}
|
||||
|
||||
ExtendedHeader::~ExtendedHeader()
|
||||
{
|
||||
ExtendedHeader::~ExtendedHeader() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
unsigned int ExtendedHeader::size() const
|
||||
{
|
||||
unsigned int ExtendedHeader::size() const {
|
||||
return d->size;
|
||||
}
|
||||
|
||||
void ExtendedHeader::setData(const ByteVector &data)
|
||||
{
|
||||
void ExtendedHeader::setData(const ByteVector &data) {
|
||||
parse(data);
|
||||
}
|
||||
|
||||
@@ -65,7 +59,6 @@ void ExtendedHeader::setData(const ByteVector &data)
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ExtendedHeader::parse(const ByteVector &data)
|
||||
{
|
||||
d->size = SynchData::toUInt(data.mid(0, 4)); // (structure 3.2 "Extended header size")
|
||||
void ExtendedHeader::parse(const ByteVector &data) {
|
||||
d->size = SynchData::toUInt(data.mid(0, 4)); // (structure 3.2 "Extended header size")
|
||||
}
|
||||
|
||||
51
3rdparty/taglib/mpeg/id3v2/id3v2extendedheader.h
vendored
51
3rdparty/taglib/mpeg/id3v2/id3v2extendedheader.h
vendored
@@ -33,11 +33,11 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! ID3v2 extended header implementation
|
||||
//! ID3v2 extended header implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This class implements ID3v2 extended headers. It attempts to follow,
|
||||
* both semantically and programmatically, the structure specified in
|
||||
* the ID3v2 standard. The API is based on the properties of ID3v2 extended
|
||||
@@ -46,50 +46,49 @@ namespace TagLib {
|
||||
* (Structure, <a href="id3v2-structure.html#3.2">3.2</a>)
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT ExtendedHeader
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT ExtendedHeader {
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty ID3v2 extended header.
|
||||
*/
|
||||
ExtendedHeader();
|
||||
ExtendedHeader();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys the extended header.
|
||||
*/
|
||||
virtual ~ExtendedHeader();
|
||||
virtual ~ExtendedHeader();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the extended header. This is variable for the
|
||||
* extended header.
|
||||
*/
|
||||
unsigned int size() const;
|
||||
unsigned int size() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the data that will be used as the extended header. Since the
|
||||
* length is not known before the extended header has been parsed, this
|
||||
* should just be a pointer to the first byte of the extended header. It
|
||||
* will determine the length internally and make that available through
|
||||
* size().
|
||||
*/
|
||||
void setData(const ByteVector &data);
|
||||
void setData(const ByteVector &data);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
protected:
|
||||
/*!
|
||||
* Called by setData() to parse the extended header data. It makes this
|
||||
* information available through the public API.
|
||||
*/
|
||||
void parse(const ByteVector &data);
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
private:
|
||||
ExtendedHeader(const ExtendedHeader &);
|
||||
ExtendedHeader &operator=(const ExtendedHeader &);
|
||||
private:
|
||||
ExtendedHeader(const ExtendedHeader &);
|
||||
ExtendedHeader &operator=(const ExtendedHeader &);
|
||||
|
||||
class ExtendedHeaderPrivate;
|
||||
ExtendedHeaderPrivate *d;
|
||||
};
|
||||
class ExtendedHeaderPrivate;
|
||||
ExtendedHeaderPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
16
3rdparty/taglib/mpeg/id3v2/id3v2footer.cpp
vendored
16
3rdparty/taglib/mpeg/id3v2/id3v2footer.cpp
vendored
@@ -29,26 +29,20 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class Footer::FooterPrivate
|
||||
{
|
||||
class Footer::FooterPrivate {
|
||||
};
|
||||
|
||||
Footer::Footer() :
|
||||
d(0)
|
||||
{
|
||||
Footer::Footer() : d(0) {
|
||||
}
|
||||
|
||||
Footer::~Footer()
|
||||
{
|
||||
Footer::~Footer() {
|
||||
}
|
||||
|
||||
unsigned int Footer::size()
|
||||
{
|
||||
unsigned int Footer::size() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
ByteVector Footer::render(const Header *header) const
|
||||
{
|
||||
ByteVector Footer::render(const Header *header) const {
|
||||
ByteVector headerData = header->render();
|
||||
headerData[0] = '3';
|
||||
headerData[1] = 'D';
|
||||
|
||||
47
3rdparty/taglib/mpeg/id3v2/id3v2footer.h
vendored
47
3rdparty/taglib/mpeg/id3v2/id3v2footer.h
vendored
@@ -32,13 +32,13 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
class Header;
|
||||
class Header;
|
||||
|
||||
//! ID3v2 footer implementation
|
||||
//! ID3v2 footer implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Per the ID3v2 specification, the tag's footer is just a copy of the
|
||||
* information in the header. As such there is no API for reading the
|
||||
* data from the header, it can just as easily be done from the header.
|
||||
@@ -48,37 +48,36 @@ namespace TagLib {
|
||||
* has been set in the ID3v2::Tag, TagLib will render a footer.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Footer
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Footer {
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty ID3v2 footer.
|
||||
*/
|
||||
Footer();
|
||||
/*!
|
||||
Footer();
|
||||
/*!
|
||||
* Destroys the footer.
|
||||
*/
|
||||
virtual ~Footer();
|
||||
virtual ~Footer();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the footer. Presently this is always 10 bytes.
|
||||
*/
|
||||
static unsigned int size();
|
||||
static unsigned int size();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Renders the footer based on the data in \a header.
|
||||
*/
|
||||
ByteVector render(const Header *header) const;
|
||||
ByteVector render(const Header *header) const;
|
||||
|
||||
private:
|
||||
Footer(const Footer &);
|
||||
Footer &operator=(const Footer &);
|
||||
private:
|
||||
Footer(const Footer &);
|
||||
Footer &operator=(const Footer &);
|
||||
|
||||
class FooterPrivate;
|
||||
FooterPrivate *d;
|
||||
};
|
||||
class FooterPrivate;
|
||||
FooterPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
747
3rdparty/taglib/mpeg/id3v2/id3v2frame.cpp
vendored
747
3rdparty/taglib/mpeg/id3v2/id3v2frame.cpp
vendored
File diff suppressed because it is too large
Load Diff
319
3rdparty/taglib/mpeg/id3v2/id3v2frame.h
vendored
319
3rdparty/taglib/mpeg/id3v2/id3v2frame.h
vendored
@@ -33,17 +33,17 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
class StringList;
|
||||
class PropertyMap;
|
||||
class StringList;
|
||||
class PropertyMap;
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
class Tag;
|
||||
class FrameFactory;
|
||||
class Tag;
|
||||
class FrameFactory;
|
||||
|
||||
//! ID3v2 frame implementation
|
||||
//! ID3v2 frame implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This class is the main ID3v2 frame implementation. In ID3v2, a tag is
|
||||
* split between a collection of frames (which are in turn split into fields
|
||||
* (Structure, <a href="id3v2-structure.html#4">4</a>)
|
||||
@@ -52,37 +52,35 @@ namespace TagLib {
|
||||
* specific to a given frame type is handed in one of the many subclasses.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Frame
|
||||
{
|
||||
friend class Tag;
|
||||
friend class FrameFactory;
|
||||
class TAGLIB_EXPORT Frame {
|
||||
friend class Tag;
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
public:
|
||||
/*!
|
||||
* Creates a textual frame which corresponds to a single key in the PropertyMap
|
||||
* interface. These are all (User)TextIdentificationFrames except TIPL and TMCL,
|
||||
* all (User)URLLinkFrames, CommentsFrames, and UnsynchronizedLyricsFrame.
|
||||
*/
|
||||
static Frame *createTextualFrame(const String &key, const StringList &values);
|
||||
static Frame *createTextualFrame(const String &key, const StringList &values);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this Frame instance.
|
||||
*/
|
||||
virtual ~Frame();
|
||||
virtual ~Frame();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the Frame ID (Structure, <a href="id3v2-structure.html#4">4</a>)
|
||||
* (Frames, <a href="id3v2-frames.html#4">4</a>)
|
||||
*/
|
||||
ByteVector frameID() const;
|
||||
ByteVector frameID() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the frame.
|
||||
*/
|
||||
unsigned int size() const;
|
||||
unsigned int size() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the frame header
|
||||
*
|
||||
* \deprecated This is only accurate for ID3v2.3 or ID3v2.4. Please use
|
||||
@@ -90,25 +88,25 @@ namespace TagLib {
|
||||
* non-binary compatible release this will be made into a non-static
|
||||
* member that checks the internal ID3v2 version.
|
||||
*/
|
||||
static unsigned int headerSize(); // BIC: make non-static
|
||||
static unsigned int headerSize(); // BIC: make non-static
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the frame header for the given ID3v2 version.
|
||||
*
|
||||
* \deprecated Please see the explanation above.
|
||||
*/
|
||||
// BIC: remove
|
||||
static unsigned int headerSize(unsigned int version);
|
||||
// BIC: remove
|
||||
static unsigned int headerSize(unsigned int version);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the data that will be used as the frame. Since the length is not
|
||||
* known before the frame has been parsed, this should just be a pointer to
|
||||
* the first byte of the frame. It will determine the length internally
|
||||
* and make that available through size().
|
||||
*/
|
||||
void setData(const ByteVector &data);
|
||||
void setData(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the text of frame in the sanest way possible. This should only be
|
||||
* reimplemented in frames where there is some logical mapping to text.
|
||||
*
|
||||
@@ -117,176 +115,176 @@ namespace TagLib {
|
||||
* that frame's encoding. Please use the specific APIs of the frame types
|
||||
* to set the encoding if that is desired.
|
||||
*/
|
||||
virtual void setText(const String &text);
|
||||
virtual void setText(const String &text);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This returns the textual representation of the data in the frame.
|
||||
* Subclasses must reimplement this method to provide a string
|
||||
* representation of the frame's data.
|
||||
*/
|
||||
virtual String toString() const = 0;
|
||||
virtual String toString() const = 0;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Render the frame back to its binary format in a ByteVector.
|
||||
*/
|
||||
ByteVector render() const;
|
||||
ByteVector render() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the text delimiter that is used between fields for the string
|
||||
* type \a t.
|
||||
*/
|
||||
static ByteVector textDelimiter(String::Type t);
|
||||
static ByteVector textDelimiter(String::Type t);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* The string with which an instrument name is prefixed to build a key in a PropertyMap;
|
||||
* used to translate PropertyMaps to TMCL frames. In the current implementation, this
|
||||
* is "PERFORMER:".
|
||||
*/
|
||||
static const String instrumentPrefix;
|
||||
/*!
|
||||
static const String instrumentPrefix;
|
||||
/*!
|
||||
* The PropertyMap key prefix which triggers the use of a COMM frame instead of a TXXX
|
||||
* frame for a non-standard key. In the current implementation, this is "COMMENT:".
|
||||
*/
|
||||
static const String commentPrefix;
|
||||
/*!
|
||||
static const String commentPrefix;
|
||||
/*!
|
||||
* The PropertyMap key prefix which triggers the use of a USLT frame instead of a TXXX
|
||||
* frame for a non-standard key. In the current implementation, this is "LYRICS:".
|
||||
*/
|
||||
static const String lyricsPrefix;
|
||||
/*!
|
||||
static const String lyricsPrefix;
|
||||
/*!
|
||||
* The PropertyMap key prefix which triggers the use of a WXXX frame instead of a TXX
|
||||
* frame for a non-standard key. In the current implementation, this is "URL:".
|
||||
*/
|
||||
static const String urlPrefix;
|
||||
static const String urlPrefix;
|
||||
|
||||
protected:
|
||||
class Header;
|
||||
protected:
|
||||
class Header;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an ID3v2 frame using \a data to read the header information.
|
||||
* All other processing of \a data should be handled in a subclass.
|
||||
*
|
||||
* \note This need not contain anything more than a frame ID, but
|
||||
* \e must contain at least that.
|
||||
*/
|
||||
explicit Frame(const ByteVector &data);
|
||||
explicit Frame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This creates an Frame using the header \a h.
|
||||
*
|
||||
* The ownership of this header will be assigned to the frame and the
|
||||
* header will be deleted when the frame is destroyed.
|
||||
*/
|
||||
Frame(Header *h);
|
||||
Frame(Header *h);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the frame header.
|
||||
*/
|
||||
Header *header() const;
|
||||
Header *header() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the header to \a h. If \a deleteCurrent is true, this will free
|
||||
* the memory of the current header.
|
||||
*
|
||||
* The ownership of this header will be assigned to the frame and the
|
||||
* header will be deleted when the frame is destroyed.
|
||||
*/
|
||||
void setHeader(Header *h, bool deleteCurrent = true);
|
||||
void setHeader(Header *h, bool deleteCurrent = true);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Called by setData() to parse the frame data. It makes this information
|
||||
* available through the public API.
|
||||
*/
|
||||
void parse(const ByteVector &data);
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Called by parse() to parse the field data. It makes this information
|
||||
* available through the public API. This must be overridden by the
|
||||
* subclasses.
|
||||
*/
|
||||
virtual void parseFields(const ByteVector &data) = 0;
|
||||
virtual void parseFields(const ByteVector &data) = 0;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Render the field data back to a binary format in a ByteVector. This
|
||||
* must be overridden by subclasses.
|
||||
*/
|
||||
virtual ByteVector renderFields() const = 0;
|
||||
virtual ByteVector renderFields() const = 0;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a ByteVector containing the field data given the frame data.
|
||||
* This correctly adjusts for the header size plus any additional frame
|
||||
* data that's specified in the frame header flags.
|
||||
*/
|
||||
ByteVector fieldData(const ByteVector &frameData) const;
|
||||
ByteVector fieldData(const ByteVector &frameData) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Reads a String of type \a encoding from the ByteVector \a data. If \a
|
||||
* position is passed in it is used both as the starting point and is
|
||||
* updated to return the position just after the string that has been read.
|
||||
* This is useful for reading strings sequentially.
|
||||
*/
|
||||
String readStringField(const ByteVector &data, String::Type encoding,
|
||||
int *position = 0);
|
||||
String readStringField(const ByteVector &data, String::Type encoding,
|
||||
int *position = 0);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Checks a the list of string values to see if they can be used with the
|
||||
* specified encoding and returns the recommended encoding.
|
||||
*/
|
||||
// BIC: remove and make non-static
|
||||
static String::Type checkEncoding(const StringList &fields,
|
||||
String::Type encoding);
|
||||
// BIC: remove and make non-static
|
||||
static String::Type checkEncoding(const StringList &fields,
|
||||
String::Type encoding);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Checks a the list of string values to see if they can be used with the
|
||||
* specified encoding and returns the recommended encoding. This method
|
||||
* also checks the ID3v2 version and makes sure the encoding can be used
|
||||
* in the specified version.
|
||||
*/
|
||||
// BIC: remove and make non-static
|
||||
static String::Type checkEncoding(const StringList &fields,
|
||||
String::Type encoding, unsigned int version);
|
||||
// BIC: remove and make non-static
|
||||
static String::Type checkEncoding(const StringList &fields,
|
||||
String::Type encoding, unsigned int version);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Checks a the list of string values to see if they can be used with the
|
||||
* specified encoding and returns the recommended encoding. This method
|
||||
* also checks the ID3v2 version and makes sure the encoding can be used
|
||||
* in the version specified by the frame's header.
|
||||
*/
|
||||
String::Type checkTextEncoding(const StringList &fields,
|
||||
String::Type encoding) const;
|
||||
String::Type checkTextEncoding(const StringList &fields,
|
||||
String::Type encoding) const;
|
||||
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Parses the contents of this frame as PropertyMap. If that fails, the returned
|
||||
* PropertyMap will be empty, and its unsupportedData() will contain this frame's
|
||||
* ID.
|
||||
* BIC: Will be a virtual function in future releases.
|
||||
*/
|
||||
PropertyMap asProperties() const;
|
||||
PropertyMap asProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns an appropriate ID3 frame ID for the given free-form tag key. This method
|
||||
* will return an empty ByteVector if no specialized translation is found.
|
||||
*/
|
||||
static ByteVector keyToFrameID(const String &);
|
||||
static ByteVector keyToFrameID(const String &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a free-form tag name for the given ID3 frame ID. Note that this does not work
|
||||
* for general frame IDs such as TXXX or WXXX; in such a case an empty string is returned.
|
||||
*/
|
||||
static String frameIDToKey(const ByteVector &);
|
||||
static String frameIDToKey(const ByteVector &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns an appropriate TXXX frame description for the given free-form tag key.
|
||||
*/
|
||||
static String keyToTXXX(const String &);
|
||||
static String keyToTXXX(const String &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a free-form tag name for the given ID3 frame description.
|
||||
*/
|
||||
static String txxxToKey(const String &);
|
||||
static String txxxToKey(const String &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This helper function splits the PropertyMap \a original into three ProperytMaps
|
||||
* \a singleFrameProperties, \a tiplProperties, and \a tmclProperties, such that:
|
||||
* - \a singleFrameProperties contains only of keys which can be represented with
|
||||
@@ -299,21 +297,21 @@ namespace TagLib {
|
||||
* - \a tmclProperties contains the "musician credits" keys which should be mapped
|
||||
* to a TMCL frame
|
||||
*/
|
||||
static void splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties,
|
||||
PropertyMap &tiplProperties, PropertyMap &tmclProperties);
|
||||
static void splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties,
|
||||
PropertyMap &tiplProperties, PropertyMap &tmclProperties);
|
||||
|
||||
private:
|
||||
Frame(const Frame &);
|
||||
Frame &operator=(const Frame &);
|
||||
private:
|
||||
Frame(const Frame &);
|
||||
Frame &operator=(const Frame &);
|
||||
|
||||
class FramePrivate;
|
||||
friend class FramePrivate;
|
||||
FramePrivate *d;
|
||||
};
|
||||
class FramePrivate;
|
||||
friend class FramePrivate;
|
||||
FramePrivate *d;
|
||||
};
|
||||
|
||||
//! ID3v2 frame header implementation
|
||||
//! ID3v2 frame header implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* The ID3v2 Frame Header (Structure, <a href="id3v2-structure.html#4">4</a>)
|
||||
*
|
||||
* Every ID3v2::Frame has an associated header that gives some general
|
||||
@@ -325,10 +323,9 @@ namespace TagLib {
|
||||
* the type and attaches the header.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Frame::Header
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Frame::Header {
|
||||
public:
|
||||
/*!
|
||||
* Construct a Frame Header based on \a data. \a data must at least
|
||||
* contain a 4 byte frame ID, and optionally can contain flag data and the
|
||||
* frame size. i.e. Just the frame id -- "TALB" -- is a valid value.
|
||||
@@ -336,43 +333,43 @@ namespace TagLib {
|
||||
* \deprecated Please use the constructor below that accepts a version
|
||||
* number.
|
||||
*/
|
||||
TAGLIB_DEPRECATED Header(const ByteVector &data, bool synchSafeInts);
|
||||
TAGLIB_DEPRECATED Header(const ByteVector &data, bool synchSafeInts);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Construct a Frame Header based on \a data. \a data must at least
|
||||
* contain a 4 byte frame ID, and optionally can contain flag data and the
|
||||
* frame size. i.e. Just the frame id -- "TALB" -- is a valid value.
|
||||
*
|
||||
* \a version should be the ID3v2 version of the tag.
|
||||
*/
|
||||
explicit Header(const ByteVector &data, unsigned int version = 4);
|
||||
explicit Header(const ByteVector &data, unsigned int version = 4);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this Header instance.
|
||||
*/
|
||||
virtual ~Header();
|
||||
virtual ~Header();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the data for the Header.
|
||||
*
|
||||
* \deprecated Please use the version below that accepts an ID3v2 version
|
||||
* number.
|
||||
*/
|
||||
void setData(const ByteVector &data, bool synchSafeInts);
|
||||
void setData(const ByteVector &data, bool synchSafeInts);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the data for the Header. \a version should indicate the ID3v2
|
||||
* version number of the tag that this frame is contained in.
|
||||
*/
|
||||
void setData(const ByteVector &data, unsigned int version = 4);
|
||||
void setData(const ByteVector &data, unsigned int version = 4);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the Frame ID (Structure, <a href="id3v2-structure.html#4">4</a>)
|
||||
* (Frames, <a href="id3v2-frames.html#4">4</a>)
|
||||
*/
|
||||
ByteVector frameID() const;
|
||||
ByteVector frameID() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the frame's ID to \a id. Only the first four bytes of \a id will
|
||||
* be used.
|
||||
*
|
||||
@@ -380,32 +377,32 @@ namespace TagLib {
|
||||
* provide a mechanism for transforming frames from a deprecated frame type
|
||||
* to a newer one -- i.e. TYER to TDRC from ID3v2.3 to ID3v2.4.
|
||||
*/
|
||||
void setFrameID(const ByteVector &id);
|
||||
void setFrameID(const ByteVector &id);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the frame data portion, as set when setData() was
|
||||
* called or set explicitly via setFrameSize().
|
||||
*/
|
||||
unsigned int frameSize() const;
|
||||
unsigned int frameSize() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the size of the frame data portion.
|
||||
*/
|
||||
void setFrameSize(unsigned int size);
|
||||
void setFrameSize(unsigned int size);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the ID3v2 version of the header, as passed in from the
|
||||
* construction of the header or set via setVersion().
|
||||
*/
|
||||
unsigned int version() const;
|
||||
unsigned int version() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the ID3v2 version of the header, changing has impact on the
|
||||
* correct parsing/rendering of frame data.
|
||||
*/
|
||||
void setVersion(unsigned int version);
|
||||
void setVersion(unsigned int version);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the frame header in bytes.
|
||||
*
|
||||
* \deprecated Please use the version of this method that accepts a
|
||||
@@ -413,19 +410,19 @@ namespace TagLib {
|
||||
* removed in the next binary incompatible release (2.0) and will be
|
||||
* replaced with a non-static method that checks the frame version.
|
||||
*/
|
||||
// BIC: make non-static
|
||||
static unsigned int size();
|
||||
// BIC: make non-static
|
||||
static unsigned int size();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the frame header in bytes for the ID3v2 version
|
||||
* that's given.
|
||||
*
|
||||
* \deprecated Please see the explanation in the version above.
|
||||
*/
|
||||
// BIC: remove
|
||||
static unsigned int size(unsigned int version);
|
||||
// BIC: remove
|
||||
static unsigned int size(unsigned int version);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the flag for tag alter preservation is set.
|
||||
*
|
||||
* The semantics are a little backwards from what would seem natural
|
||||
@@ -434,9 +431,9 @@ namespace TagLib {
|
||||
*
|
||||
* \see setTagAlterPreservation()
|
||||
*/
|
||||
bool tagAlterPreservation() const;
|
||||
bool tagAlterPreservation() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the flag for preservation of this frame if the tag is set. If
|
||||
* this is set to true the frame will not be written when the tag is
|
||||
* saved.
|
||||
@@ -447,77 +444,77 @@ namespace TagLib {
|
||||
*
|
||||
* \see tagAlterPreservation()
|
||||
*/
|
||||
void setTagAlterPreservation(bool discard);
|
||||
void setTagAlterPreservation(bool discard);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the flag for file alter preservation is set.
|
||||
*
|
||||
* \note This flag is currently ignored internally in TagLib.
|
||||
*/
|
||||
bool fileAlterPreservation() const;
|
||||
bool fileAlterPreservation() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the frame is meant to be read only.
|
||||
*
|
||||
* \note This flag is currently ignored internally in TagLib.
|
||||
*/
|
||||
bool readOnly() const;
|
||||
bool readOnly() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the flag for the grouping identity is set.
|
||||
*
|
||||
* \note This flag is currently ignored internally in TagLib.
|
||||
*/
|
||||
bool groupingIdentity() const;
|
||||
bool groupingIdentity() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if compression is enabled for this frame.
|
||||
*
|
||||
* \note This flag is currently ignored internally in TagLib.
|
||||
*/
|
||||
bool compression() const;
|
||||
bool compression() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if encryption is enabled for this frame.
|
||||
*
|
||||
* \note This flag is currently ignored internally in TagLib.
|
||||
*/
|
||||
bool encryption() const;
|
||||
bool encryption() const;
|
||||
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
bool unsycronisation() const;
|
||||
bool unsycronisation() const;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if unsynchronisation is enabled for this frame.
|
||||
*/
|
||||
bool unsynchronisation() const;
|
||||
bool unsynchronisation() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the flag for a data length indicator is set.
|
||||
*/
|
||||
bool dataLengthIndicator() const;
|
||||
bool dataLengthIndicator() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Render the Header back to binary format in a ByteVector.
|
||||
*/
|
||||
ByteVector render() const;
|
||||
ByteVector render() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \deprecated
|
||||
*/
|
||||
TAGLIB_DEPRECATED bool frameAlterPreservation() const;
|
||||
TAGLIB_DEPRECATED bool frameAlterPreservation() const;
|
||||
|
||||
private:
|
||||
Header(const Header &);
|
||||
Header &operator=(const Header &);
|
||||
private:
|
||||
Header(const Header &);
|
||||
Header &operator=(const Header &);
|
||||
|
||||
class HeaderPrivate;
|
||||
HeaderPrivate *d;
|
||||
};
|
||||
class HeaderPrivate;
|
||||
HeaderPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
467
3rdparty/taglib/mpeg/id3v2/id3v2framefactory.cpp
vendored
467
3rdparty/taglib/mpeg/id3v2/id3v2framefactory.cpp
vendored
@@ -51,53 +51,48 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
namespace
|
||||
{
|
||||
void updateGenre(TextIdentificationFrame *frame)
|
||||
{
|
||||
StringList fields = frame->fieldList();
|
||||
StringList newfields;
|
||||
namespace {
|
||||
void updateGenre(TextIdentificationFrame *frame) {
|
||||
StringList fields = frame->fieldList();
|
||||
StringList newfields;
|
||||
|
||||
for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) {
|
||||
String s = *it;
|
||||
int end = s.find(")");
|
||||
for (StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) {
|
||||
String s = *it;
|
||||
int end = s.find(")");
|
||||
|
||||
if(s.startsWith("(") && end > 0) {
|
||||
// "(12)Genre"
|
||||
String text = s.substr(end + 1);
|
||||
bool ok;
|
||||
int number = s.substr(1, end - 1).toInt(&ok);
|
||||
if(ok && number >= 0 && number <= 255 && !(ID3v1::genre(number) == text))
|
||||
newfields.append(s.substr(1, end - 1));
|
||||
if(!text.isEmpty())
|
||||
newfields.append(text);
|
||||
}
|
||||
else {
|
||||
// "Genre" or "12"
|
||||
newfields.append(s);
|
||||
}
|
||||
if (s.startsWith("(") && end > 0) {
|
||||
// "(12)Genre"
|
||||
String text = s.substr(end + 1);
|
||||
bool ok;
|
||||
int number = s.substr(1, end - 1).toInt(&ok);
|
||||
if (ok && number >= 0 && number <= 255 && !(ID3v1::genre(number) == text))
|
||||
newfields.append(s.substr(1, end - 1));
|
||||
if (!text.isEmpty())
|
||||
newfields.append(text);
|
||||
}
|
||||
else {
|
||||
// "Genre" or "12"
|
||||
newfields.append(s);
|
||||
}
|
||||
|
||||
if(newfields.isEmpty())
|
||||
fields.append(String());
|
||||
|
||||
frame->setText(newfields);
|
||||
}
|
||||
}
|
||||
|
||||
class FrameFactory::FrameFactoryPrivate
|
||||
{
|
||||
public:
|
||||
FrameFactoryPrivate() :
|
||||
defaultEncoding(String::Latin1),
|
||||
useDefaultEncoding(false) {}
|
||||
if (newfields.isEmpty())
|
||||
fields.append(String());
|
||||
|
||||
frame->setText(newfields);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class FrameFactory::FrameFactoryPrivate {
|
||||
public:
|
||||
FrameFactoryPrivate() : defaultEncoding(String::Latin1),
|
||||
useDefaultEncoding(false) {}
|
||||
|
||||
String::Type defaultEncoding;
|
||||
bool useDefaultEncoding;
|
||||
|
||||
template <class T> void setTextEncoding(T *frame)
|
||||
{
|
||||
if(useDefaultEncoding)
|
||||
template<class T> void setTextEncoding(T *frame) {
|
||||
if (useDefaultEncoding)
|
||||
frame->setTextEncoding(defaultEncoding);
|
||||
}
|
||||
};
|
||||
@@ -108,30 +103,25 @@ FrameFactory FrameFactory::factory;
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FrameFactory *FrameFactory::instance()
|
||||
{
|
||||
FrameFactory *FrameFactory::instance() {
|
||||
return &factory;
|
||||
}
|
||||
|
||||
Frame *FrameFactory::createFrame(const ByteVector &data, bool synchSafeInts) const
|
||||
{
|
||||
Frame *FrameFactory::createFrame(const ByteVector &data, bool synchSafeInts) const {
|
||||
return createFrame(data, static_cast<unsigned int>(synchSafeInts ? 4 : 3));
|
||||
}
|
||||
|
||||
Frame *FrameFactory::createFrame(const ByteVector &data, unsigned int version) const
|
||||
{
|
||||
Frame *FrameFactory::createFrame(const ByteVector &data, unsigned int version) const {
|
||||
Header tagHeader;
|
||||
tagHeader.setMajorVersion(version);
|
||||
return createFrame(data, &tagHeader);
|
||||
}
|
||||
|
||||
Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) const
|
||||
{
|
||||
return createFrame(origData, const_cast<const Header *>(tagHeader));
|
||||
Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) const {
|
||||
return createFrame(origData, const_cast<const Header *>(tagHeader));
|
||||
}
|
||||
|
||||
Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHeader) const
|
||||
{
|
||||
Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHeader) const {
|
||||
ByteVector data = origData;
|
||||
unsigned int version = tagHeader->majorVersion();
|
||||
Frame::Header *header = new Frame::Header(data, version);
|
||||
@@ -140,16 +130,15 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
// A quick sanity check -- make sure that the frameID is 4 uppercase Latin1
|
||||
// characters. Also make sure that there is data in the frame.
|
||||
|
||||
if(frameID.size() != (version < 3 ? 3 : 4) ||
|
||||
header->frameSize() <= static_cast<unsigned int>(header->dataLengthIndicator() ? 4 : 0) ||
|
||||
header->frameSize() > data.size())
|
||||
{
|
||||
if (frameID.size() != (version < 3 ? 3 : 4) ||
|
||||
header->frameSize() <= static_cast<unsigned int>(header->dataLengthIndicator() ? 4 : 0) ||
|
||||
header->frameSize() > data.size()) {
|
||||
delete header;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifndef NO_ITUNES_HACKS
|
||||
if(version == 3 && frameID.size() == 4 && frameID[3] == '\0') {
|
||||
if (version == 3 && frameID.size() == 4 && frameID[3] == '\0') {
|
||||
// iTunes v2.3 tags store v2.2 frames - convert now
|
||||
frameID = frameID.mid(0, 3);
|
||||
header->setFrameID(frameID);
|
||||
@@ -159,14 +148,14 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
}
|
||||
#endif
|
||||
|
||||
for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) {
|
||||
if( (*it < 'A' || *it > 'Z') && (*it < '0' || *it > '9') ) {
|
||||
for (ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) {
|
||||
if ((*it < 'A' || *it > 'Z') && (*it < '0' || *it > '9')) {
|
||||
delete header;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if(version > 3 && (tagHeader->unsynchronisation() || header->unsynchronisation())) {
|
||||
if (version > 3 && (tagHeader->unsynchronisation() || header->unsynchronisation())) {
|
||||
// Data lengths are not part of the encoded data, but since they are synch-safe
|
||||
// integers they will be never actually encoded.
|
||||
ByteVector frameData = data.mid(Frame::Header::size(version), header->frameSize());
|
||||
@@ -177,17 +166,17 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
// TagLib doesn't mess with encrypted frames, so just treat them
|
||||
// as unknown frames.
|
||||
|
||||
if(!zlib::isAvailable() && header->compression()) {
|
||||
if (!zlib::isAvailable() && header->compression()) {
|
||||
debug("Compressed frames are currently not supported.");
|
||||
return new UnknownFrame(data, header);
|
||||
}
|
||||
|
||||
if(header->encryption()) {
|
||||
if (header->encryption()) {
|
||||
debug("Encrypted frames are currently not supported.");
|
||||
return new UnknownFrame(data, header);
|
||||
}
|
||||
|
||||
if(!updateFrame(header)) {
|
||||
if (!updateFrame(header)) {
|
||||
header->setTagAlterPreservation(true);
|
||||
return new UnknownFrame(data, header);
|
||||
}
|
||||
@@ -204,15 +193,13 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
// Text Identification (frames 4.2)
|
||||
|
||||
// Apple proprietary WFED (Podcast URL), MVNM (Movement Name), MVIN (Movement Number), GRP1 (Grouping) are in fact text frames.
|
||||
if(frameID.startsWith("T") || frameID == "WFED" || frameID == "MVNM" || frameID == "MVIN" || frameID == "GRP1") {
|
||||
if (frameID.startsWith("T") || frameID == "WFED" || frameID == "MVNM" || frameID == "MVIN" || frameID == "GRP1") {
|
||||
|
||||
TextIdentificationFrame *f = frameID != "TXXX"
|
||||
? new TextIdentificationFrame(data, header)
|
||||
: new UserTextIdentificationFrame(data, header);
|
||||
TextIdentificationFrame *f = frameID != "TXXX" ? new TextIdentificationFrame(data, header) : new UserTextIdentificationFrame(data, header);
|
||||
|
||||
d->setTextEncoding(f);
|
||||
|
||||
if(frameID == "TCON")
|
||||
if (frameID == "TCON")
|
||||
updateGenre(f);
|
||||
|
||||
return f;
|
||||
@@ -220,7 +207,7 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
|
||||
// Comments (frames 4.10)
|
||||
|
||||
if(frameID == "COMM") {
|
||||
if (frameID == "COMM") {
|
||||
CommentsFrame *f = new CommentsFrame(data, header);
|
||||
d->setTextEncoding(f);
|
||||
return f;
|
||||
@@ -228,7 +215,7 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
|
||||
// Attached Picture (frames 4.14)
|
||||
|
||||
if(frameID == "APIC") {
|
||||
if (frameID == "APIC") {
|
||||
AttachedPictureFrame *f = new AttachedPictureFrame(data, header);
|
||||
d->setTextEncoding(f);
|
||||
return f;
|
||||
@@ -236,7 +223,7 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
|
||||
// ID3v2.2 Attached Picture
|
||||
|
||||
if(frameID == "PIC") {
|
||||
if (frameID == "PIC") {
|
||||
AttachedPictureFrame *f = new AttachedPictureFrameV22(data, header);
|
||||
d->setTextEncoding(f);
|
||||
return f;
|
||||
@@ -244,17 +231,17 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
|
||||
// Relative Volume Adjustment (frames 4.11)
|
||||
|
||||
if(frameID == "RVA2")
|
||||
if (frameID == "RVA2")
|
||||
return new RelativeVolumeFrame(data, header);
|
||||
|
||||
// Unique File Identifier (frames 4.1)
|
||||
|
||||
if(frameID == "UFID")
|
||||
if (frameID == "UFID")
|
||||
return new UniqueFileIdentifierFrame(data, header);
|
||||
|
||||
// General Encapsulated Object (frames 4.15)
|
||||
|
||||
if(frameID == "GEOB") {
|
||||
if (frameID == "GEOB") {
|
||||
GeneralEncapsulatedObjectFrame *f = new GeneralEncapsulatedObjectFrame(data, header);
|
||||
d->setTextEncoding(f);
|
||||
return f;
|
||||
@@ -262,8 +249,8 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
|
||||
// URL link (frames 4.3)
|
||||
|
||||
if(frameID.startsWith("W")) {
|
||||
if(frameID != "WXXX") {
|
||||
if (frameID.startsWith("W")) {
|
||||
if (frameID != "WXXX") {
|
||||
return new UrlLinkFrame(data, header);
|
||||
}
|
||||
else {
|
||||
@@ -275,40 +262,40 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
|
||||
// Unsynchronized lyric/text transcription (frames 4.8)
|
||||
|
||||
if(frameID == "USLT") {
|
||||
if (frameID == "USLT") {
|
||||
UnsynchronizedLyricsFrame *f = new UnsynchronizedLyricsFrame(data, header);
|
||||
if(d->useDefaultEncoding)
|
||||
if (d->useDefaultEncoding)
|
||||
f->setTextEncoding(d->defaultEncoding);
|
||||
return f;
|
||||
}
|
||||
|
||||
// Synchronised lyrics/text (frames 4.9)
|
||||
|
||||
if(frameID == "SYLT") {
|
||||
if (frameID == "SYLT") {
|
||||
SynchronizedLyricsFrame *f = new SynchronizedLyricsFrame(data, header);
|
||||
if(d->useDefaultEncoding)
|
||||
if (d->useDefaultEncoding)
|
||||
f->setTextEncoding(d->defaultEncoding);
|
||||
return f;
|
||||
}
|
||||
|
||||
// Event timing codes (frames 4.5)
|
||||
|
||||
if(frameID == "ETCO")
|
||||
if (frameID == "ETCO")
|
||||
return new EventTimingCodesFrame(data, header);
|
||||
|
||||
// Popularimeter (frames 4.17)
|
||||
|
||||
if(frameID == "POPM")
|
||||
if (frameID == "POPM")
|
||||
return new PopularimeterFrame(data, header);
|
||||
|
||||
// Private (frames 4.27)
|
||||
|
||||
if(frameID == "PRIV")
|
||||
if (frameID == "PRIV")
|
||||
return new PrivateFrame(data, header);
|
||||
|
||||
// Ownership (frames 4.22)
|
||||
|
||||
if(frameID == "OWNE") {
|
||||
if (frameID == "OWNE") {
|
||||
OwnershipFrame *f = new OwnershipFrame(data, header);
|
||||
d->setTextEncoding(f);
|
||||
return f;
|
||||
@@ -316,45 +303,42 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
|
||||
|
||||
// Chapter (ID3v2 chapters 1.0)
|
||||
|
||||
if(frameID == "CHAP")
|
||||
if (frameID == "CHAP")
|
||||
return new ChapterFrame(tagHeader, data, header);
|
||||
|
||||
// Table of contents (ID3v2 chapters 1.0)
|
||||
|
||||
if(frameID == "CTOC")
|
||||
if (frameID == "CTOC")
|
||||
return new TableOfContentsFrame(tagHeader, data, header);
|
||||
|
||||
// Apple proprietary PCST (Podcast)
|
||||
|
||||
if(frameID == "PCST")
|
||||
if (frameID == "PCST")
|
||||
return new PodcastFrame(data, header);
|
||||
|
||||
return new UnknownFrame(data, header);
|
||||
}
|
||||
|
||||
void FrameFactory::rebuildAggregateFrames(ID3v2::Tag *tag) const
|
||||
{
|
||||
if(tag->header()->majorVersion() < 4 &&
|
||||
tag->frameList("TDRC").size() == 1 &&
|
||||
tag->frameList("TDAT").size() == 1)
|
||||
{
|
||||
void FrameFactory::rebuildAggregateFrames(ID3v2::Tag *tag) const {
|
||||
if (tag->header()->majorVersion() < 4 &&
|
||||
tag->frameList("TDRC").size() == 1 &&
|
||||
tag->frameList("TDAT").size() == 1) {
|
||||
TextIdentificationFrame *tdrc =
|
||||
dynamic_cast<TextIdentificationFrame *>(tag->frameList("TDRC").front());
|
||||
UnknownFrame *tdat = static_cast<UnknownFrame *>(tag->frameList("TDAT").front());
|
||||
|
||||
if(tdrc &&
|
||||
tdrc->fieldList().size() == 1 &&
|
||||
tdrc->fieldList().front().size() == 4 &&
|
||||
tdat->data().size() >= 5)
|
||||
{
|
||||
if (tdrc &&
|
||||
tdrc->fieldList().size() == 1 &&
|
||||
tdrc->fieldList().front().size() == 4 &&
|
||||
tdat->data().size() >= 5) {
|
||||
String date(tdat->data().mid(1), String::Type(tdat->data()[0]));
|
||||
if(date.length() == 4) {
|
||||
if (date.length() == 4) {
|
||||
tdrc->setText(tdrc->toString() + '-' + date.substr(2, 2) + '-' + date.substr(0, 2));
|
||||
if(tag->frameList("TIME").size() == 1) {
|
||||
if (tag->frameList("TIME").size() == 1) {
|
||||
UnknownFrame *timeframe = static_cast<UnknownFrame *>(tag->frameList("TIME").front());
|
||||
if(timeframe->data().size() >= 5) {
|
||||
if (timeframe->data().size() >= 5) {
|
||||
String time(timeframe->data().mid(1), String::Type(timeframe->data()[0]));
|
||||
if(time.length() == 4) {
|
||||
if (time.length() == 4) {
|
||||
tdrc->setText(tdrc->toString() + 'T' + time.substr(0, 2) + ':' + time.substr(2, 2));
|
||||
}
|
||||
}
|
||||
@@ -364,13 +348,11 @@ void FrameFactory::rebuildAggregateFrames(ID3v2::Tag *tag) const
|
||||
}
|
||||
}
|
||||
|
||||
String::Type FrameFactory::defaultTextEncoding() const
|
||||
{
|
||||
String::Type FrameFactory::defaultTextEncoding() const {
|
||||
return d->defaultEncoding;
|
||||
}
|
||||
|
||||
void FrameFactory::setDefaultTextEncoding(String::Type encoding)
|
||||
{
|
||||
void FrameFactory::setDefaultTextEncoding(String::Type encoding) {
|
||||
d->useDefaultEncoding = true;
|
||||
d->defaultEncoding = encoding;
|
||||
}
|
||||
@@ -379,171 +361,164 @@ void FrameFactory::setDefaultTextEncoding(String::Type encoding)
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FrameFactory::FrameFactory() :
|
||||
d(new FrameFactoryPrivate())
|
||||
{
|
||||
FrameFactory::FrameFactory() : d(new FrameFactoryPrivate()) {
|
||||
}
|
||||
|
||||
FrameFactory::~FrameFactory()
|
||||
{
|
||||
FrameFactory::~FrameFactory() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Frame conversion table ID3v2.2 -> 2.4
|
||||
const char *frameConversion2[][2] = {
|
||||
{ "BUF", "RBUF" },
|
||||
{ "CNT", "PCNT" },
|
||||
{ "COM", "COMM" },
|
||||
{ "CRA", "AENC" },
|
||||
{ "ETC", "ETCO" },
|
||||
{ "GEO", "GEOB" },
|
||||
{ "IPL", "TIPL" },
|
||||
{ "MCI", "MCDI" },
|
||||
{ "MLL", "MLLT" },
|
||||
{ "POP", "POPM" },
|
||||
{ "REV", "RVRB" },
|
||||
{ "SLT", "SYLT" },
|
||||
{ "STC", "SYTC" },
|
||||
{ "TAL", "TALB" },
|
||||
{ "TBP", "TBPM" },
|
||||
{ "TCM", "TCOM" },
|
||||
{ "TCO", "TCON" },
|
||||
{ "TCP", "TCMP" },
|
||||
{ "TCR", "TCOP" },
|
||||
{ "TDY", "TDLY" },
|
||||
{ "TEN", "TENC" },
|
||||
{ "TFT", "TFLT" },
|
||||
{ "TKE", "TKEY" },
|
||||
{ "TLA", "TLAN" },
|
||||
{ "TLE", "TLEN" },
|
||||
{ "TMT", "TMED" },
|
||||
{ "TOA", "TOAL" },
|
||||
{ "TOF", "TOFN" },
|
||||
{ "TOL", "TOLY" },
|
||||
{ "TOR", "TDOR" },
|
||||
{ "TOT", "TOAL" },
|
||||
{ "TP1", "TPE1" },
|
||||
{ "TP2", "TPE2" },
|
||||
{ "TP3", "TPE3" },
|
||||
{ "TP4", "TPE4" },
|
||||
{ "TPA", "TPOS" },
|
||||
{ "TPB", "TPUB" },
|
||||
{ "TRC", "TSRC" },
|
||||
{ "TRD", "TDRC" },
|
||||
{ "TRK", "TRCK" },
|
||||
{ "TS2", "TSO2" },
|
||||
{ "TSA", "TSOA" },
|
||||
{ "TSC", "TSOC" },
|
||||
{ "TSP", "TSOP" },
|
||||
{ "TSS", "TSSE" },
|
||||
{ "TST", "TSOT" },
|
||||
{ "TT1", "TIT1" },
|
||||
{ "TT2", "TIT2" },
|
||||
{ "TT3", "TIT3" },
|
||||
{ "TXT", "TOLY" },
|
||||
{ "TXX", "TXXX" },
|
||||
{ "TYE", "TDRC" },
|
||||
{ "UFI", "UFID" },
|
||||
{ "ULT", "USLT" },
|
||||
{ "WAF", "WOAF" },
|
||||
{ "WAR", "WOAR" },
|
||||
{ "WAS", "WOAS" },
|
||||
{ "WCM", "WCOM" },
|
||||
{ "WCP", "WCOP" },
|
||||
{ "WPB", "WPUB" },
|
||||
{ "WXX", "WXXX" },
|
||||
namespace {
|
||||
// Frame conversion table ID3v2.2 -> 2.4
|
||||
const char *frameConversion2[][2] = {
|
||||
{ "BUF", "RBUF" },
|
||||
{ "CNT", "PCNT" },
|
||||
{ "COM", "COMM" },
|
||||
{ "CRA", "AENC" },
|
||||
{ "ETC", "ETCO" },
|
||||
{ "GEO", "GEOB" },
|
||||
{ "IPL", "TIPL" },
|
||||
{ "MCI", "MCDI" },
|
||||
{ "MLL", "MLLT" },
|
||||
{ "POP", "POPM" },
|
||||
{ "REV", "RVRB" },
|
||||
{ "SLT", "SYLT" },
|
||||
{ "STC", "SYTC" },
|
||||
{ "TAL", "TALB" },
|
||||
{ "TBP", "TBPM" },
|
||||
{ "TCM", "TCOM" },
|
||||
{ "TCO", "TCON" },
|
||||
{ "TCP", "TCMP" },
|
||||
{ "TCR", "TCOP" },
|
||||
{ "TDY", "TDLY" },
|
||||
{ "TEN", "TENC" },
|
||||
{ "TFT", "TFLT" },
|
||||
{ "TKE", "TKEY" },
|
||||
{ "TLA", "TLAN" },
|
||||
{ "TLE", "TLEN" },
|
||||
{ "TMT", "TMED" },
|
||||
{ "TOA", "TOAL" },
|
||||
{ "TOF", "TOFN" },
|
||||
{ "TOL", "TOLY" },
|
||||
{ "TOR", "TDOR" },
|
||||
{ "TOT", "TOAL" },
|
||||
{ "TP1", "TPE1" },
|
||||
{ "TP2", "TPE2" },
|
||||
{ "TP3", "TPE3" },
|
||||
{ "TP4", "TPE4" },
|
||||
{ "TPA", "TPOS" },
|
||||
{ "TPB", "TPUB" },
|
||||
{ "TRC", "TSRC" },
|
||||
{ "TRD", "TDRC" },
|
||||
{ "TRK", "TRCK" },
|
||||
{ "TS2", "TSO2" },
|
||||
{ "TSA", "TSOA" },
|
||||
{ "TSC", "TSOC" },
|
||||
{ "TSP", "TSOP" },
|
||||
{ "TSS", "TSSE" },
|
||||
{ "TST", "TSOT" },
|
||||
{ "TT1", "TIT1" },
|
||||
{ "TT2", "TIT2" },
|
||||
{ "TT3", "TIT3" },
|
||||
{ "TXT", "TOLY" },
|
||||
{ "TXX", "TXXX" },
|
||||
{ "TYE", "TDRC" },
|
||||
{ "UFI", "UFID" },
|
||||
{ "ULT", "USLT" },
|
||||
{ "WAF", "WOAF" },
|
||||
{ "WAR", "WOAR" },
|
||||
{ "WAS", "WOAS" },
|
||||
{ "WCM", "WCOM" },
|
||||
{ "WCP", "WCOP" },
|
||||
{ "WPB", "WPUB" },
|
||||
{ "WXX", "WXXX" },
|
||||
|
||||
// Apple iTunes nonstandard frames
|
||||
{ "PCS", "PCST" },
|
||||
{ "TCT", "TCAT" },
|
||||
{ "TDR", "TDRL" },
|
||||
{ "TDS", "TDES" },
|
||||
{ "TID", "TGID" },
|
||||
{ "WFD", "WFED" },
|
||||
{ "MVN", "MVNM" },
|
||||
{ "MVI", "MVIN" },
|
||||
{ "GP1", "GRP1" },
|
||||
};
|
||||
const size_t frameConversion2Size = sizeof(frameConversion2) / sizeof(frameConversion2[0]);
|
||||
// Apple iTunes nonstandard frames
|
||||
{ "PCS", "PCST" },
|
||||
{ "TCT", "TCAT" },
|
||||
{ "TDR", "TDRL" },
|
||||
{ "TDS", "TDES" },
|
||||
{ "TID", "TGID" },
|
||||
{ "WFD", "WFED" },
|
||||
{ "MVN", "MVNM" },
|
||||
{ "MVI", "MVIN" },
|
||||
{ "GP1", "GRP1" },
|
||||
};
|
||||
const size_t frameConversion2Size = sizeof(frameConversion2) / sizeof(frameConversion2[0]);
|
||||
|
||||
// Frame conversion table ID3v2.3 -> 2.4
|
||||
const char *frameConversion3[][2] = {
|
||||
{ "TORY", "TDOR" },
|
||||
{ "TYER", "TDRC" },
|
||||
{ "IPLS", "TIPL" },
|
||||
};
|
||||
const size_t frameConversion3Size = sizeof(frameConversion3) / sizeof(frameConversion3[0]);
|
||||
}
|
||||
// Frame conversion table ID3v2.3 -> 2.4
|
||||
const char *frameConversion3[][2] = {
|
||||
{ "TORY", "TDOR" },
|
||||
{ "TYER", "TDRC" },
|
||||
{ "IPLS", "TIPL" },
|
||||
};
|
||||
const size_t frameConversion3Size = sizeof(frameConversion3) / sizeof(frameConversion3[0]);
|
||||
} // namespace
|
||||
|
||||
bool FrameFactory::updateFrame(Frame::Header *header) const
|
||||
{
|
||||
bool FrameFactory::updateFrame(Frame::Header *header) const {
|
||||
const ByteVector frameID = header->frameID();
|
||||
|
||||
switch(header->version()) {
|
||||
switch (header->version()) {
|
||||
|
||||
case 2: // ID3v2.2
|
||||
{
|
||||
if(frameID == "CRM" ||
|
||||
frameID == "EQU" ||
|
||||
frameID == "LNK" ||
|
||||
frameID == "RVA" ||
|
||||
frameID == "TIM" ||
|
||||
frameID == "TSI" ||
|
||||
frameID == "TDA")
|
||||
case 2: // ID3v2.2
|
||||
{
|
||||
debug("ID3v2.4 no longer supports the frame type " + String(frameID) +
|
||||
". It will be discarded from the tag.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ID3v2.2 only used 3 bytes for the frame ID, so we need to convert all of
|
||||
// the frames to their 4 byte ID3v2.4 equivalent.
|
||||
|
||||
for(size_t i = 0; i < frameConversion2Size; ++i) {
|
||||
if(frameID == frameConversion2[i][0]) {
|
||||
header->setFrameID(frameConversion2[i][1]);
|
||||
break;
|
||||
if (frameID == "CRM" ||
|
||||
frameID == "EQU" ||
|
||||
frameID == "LNK" ||
|
||||
frameID == "RVA" ||
|
||||
frameID == "TIM" ||
|
||||
frameID == "TSI" ||
|
||||
frameID == "TDA") {
|
||||
debug("ID3v2.4 no longer supports the frame type " + String(frameID) +
|
||||
". It will be discarded from the tag.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ID3v2.2 only used 3 bytes for the frame ID, so we need to convert all of
|
||||
// the frames to their 4 byte ID3v2.4 equivalent.
|
||||
|
||||
for (size_t i = 0; i < frameConversion2Size; ++i) {
|
||||
if (frameID == frameConversion2[i][0]) {
|
||||
header->setFrameID(frameConversion2[i][1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: // ID3v2.3
|
||||
{
|
||||
if(frameID == "EQUA" ||
|
||||
frameID == "RVAD" ||
|
||||
frameID == "TIME" ||
|
||||
frameID == "TRDA" ||
|
||||
frameID == "TSIZ" ||
|
||||
frameID == "TDAT")
|
||||
case 3: // ID3v2.3
|
||||
{
|
||||
debug("ID3v2.4 no longer supports the frame type " + String(frameID) +
|
||||
". It will be discarded from the tag.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < frameConversion3Size; ++i) {
|
||||
if(frameID == frameConversion3[i][0]) {
|
||||
header->setFrameID(frameConversion3[i][1]);
|
||||
break;
|
||||
if (frameID == "EQUA" ||
|
||||
frameID == "RVAD" ||
|
||||
frameID == "TIME" ||
|
||||
frameID == "TRDA" ||
|
||||
frameID == "TSIZ" ||
|
||||
frameID == "TDAT") {
|
||||
debug("ID3v2.4 no longer supports the frame type " + String(frameID) +
|
||||
". It will be discarded from the tag.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < frameConversion3Size; ++i) {
|
||||
if (frameID == frameConversion3[i][0]) {
|
||||
header->setFrameID(frameConversion3[i][1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
default:
|
||||
// This should catch a typo that existed in TagLib up to and including
|
||||
// version 1.1 where TRDC was used for the year rather than TDRC.
|
||||
|
||||
// This should catch a typo that existed in TagLib up to and including
|
||||
// version 1.1 where TRDC was used for the year rather than TDRC.
|
||||
if (frameID == "TRDC")
|
||||
header->setFrameID("TDRC");
|
||||
|
||||
if(frameID == "TRDC")
|
||||
header->setFrameID("TDRC");
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
85
3rdparty/taglib/mpeg/id3v2/id3v2framefactory.h
vendored
85
3rdparty/taglib/mpeg/id3v2/id3v2framefactory.h
vendored
@@ -1,4 +1,4 @@
|
||||
/***************************************************************************
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002 - 2008 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
@@ -34,13 +34,13 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
class TextIdentificationFrame;
|
||||
class TextIdentificationFrame;
|
||||
|
||||
//! A factory for creating ID3v2 frames during parsing
|
||||
//! A factory for creating ID3v2 frames during parsing
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This factory abstracts away the frame creation process and instantiates
|
||||
* the appropriate ID3v2::Frame subclasses based on the contents of the
|
||||
* data.
|
||||
@@ -63,11 +63,10 @@ namespace TagLib {
|
||||
* \see ID3v2::Tag::addFrame()
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT FrameFactory
|
||||
{
|
||||
public:
|
||||
static FrameFactory *instance();
|
||||
/*!
|
||||
class TAGLIB_EXPORT FrameFactory {
|
||||
public:
|
||||
static FrameFactory *instance();
|
||||
/*!
|
||||
* Create a frame based on \a data. \a synchSafeInts should only be set
|
||||
* false if we are parsing an old tag (v2.3 or older) that does not support
|
||||
* synchsafe ints.
|
||||
@@ -75,9 +74,9 @@ namespace TagLib {
|
||||
* \deprecated Please use the method below that accepts a ID3v2::Header
|
||||
* instance in new code.
|
||||
*/
|
||||
Frame *createFrame(const ByteVector &data, bool synchSafeInts) const;
|
||||
Frame *createFrame(const ByteVector &data, bool synchSafeInts) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Create a frame based on \a data. \a version should indicate the ID3v2
|
||||
* version of the tag. As ID3v2.4 is the most current version of the
|
||||
* standard 4 is the default.
|
||||
@@ -85,29 +84,29 @@ namespace TagLib {
|
||||
* \deprecated Please use the method below that accepts a ID3v2::Header
|
||||
* instance in new code.
|
||||
*/
|
||||
Frame *createFrame(const ByteVector &data, unsigned int version = 4) const;
|
||||
Frame *createFrame(const ByteVector &data, unsigned int version = 4) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \deprecated
|
||||
*/
|
||||
// BIC: remove
|
||||
Frame *createFrame(const ByteVector &data, Header *tagHeader) const;
|
||||
/*!
|
||||
// BIC: remove
|
||||
Frame *createFrame(const ByteVector &data, Header *tagHeader) const;
|
||||
/*!
|
||||
* Create a frame based on \a data. \a tagHeader should be a valid
|
||||
* ID3v2::Header instance.
|
||||
*/
|
||||
// BIC: make virtual
|
||||
Frame *createFrame(const ByteVector &data, const Header *tagHeader) const;
|
||||
// BIC: make virtual
|
||||
Frame *createFrame(const ByteVector &data, const Header *tagHeader) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* After a tag has been read, this tries to rebuild some of them
|
||||
* information, most notably the recording date, from frames that
|
||||
* have been deprecated and can't be upgraded directly.
|
||||
*/
|
||||
// BIC: Make virtual
|
||||
void rebuildAggregateFrames(ID3v2::Tag *tag) const;
|
||||
// BIC: Make virtual
|
||||
void rebuildAggregateFrames(ID3v2::Tag *tag) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the default text encoding for text frames. If setTextEncoding()
|
||||
* has not been explicitly called this will only be used for new text
|
||||
* frames. However, if this value has been set explicitly all frames will be
|
||||
@@ -116,9 +115,9 @@ namespace TagLib {
|
||||
*
|
||||
* \see setDefaultTextEncoding()
|
||||
*/
|
||||
String::Type defaultTextEncoding() const;
|
||||
String::Type defaultTextEncoding() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the default text encoding for all text frames that are created to
|
||||
* \a encoding. If no value is set the frames with either default to the
|
||||
* encoding type that was parsed and new frames default to Latin1.
|
||||
@@ -127,21 +126,21 @@ namespace TagLib {
|
||||
*
|
||||
* \see defaultTextEncoding()
|
||||
*/
|
||||
void setDefaultTextEncoding(String::Type encoding);
|
||||
void setDefaultTextEncoding(String::Type encoding);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
protected:
|
||||
/*!
|
||||
* Constructs a frame factory. Because this is a singleton this method is
|
||||
* protected, but may be used for subclasses.
|
||||
*/
|
||||
FrameFactory();
|
||||
FrameFactory();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys the frame factory.
|
||||
*/
|
||||
virtual ~FrameFactory();
|
||||
virtual ~FrameFactory();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This method checks for compliance to the current ID3v2 standard (2.4)
|
||||
* and does nothing in the common case. However if a frame is found that
|
||||
* is not compatible with the current standard, this method either updates
|
||||
@@ -152,20 +151,20 @@ namespace TagLib {
|
||||
*
|
||||
* See the id3v2.4.0-changes.txt document for further information.
|
||||
*/
|
||||
virtual bool updateFrame(Frame::Header *header) const;
|
||||
virtual bool updateFrame(Frame::Header *header) const;
|
||||
|
||||
private:
|
||||
FrameFactory(const FrameFactory &);
|
||||
FrameFactory &operator=(const FrameFactory &);
|
||||
private:
|
||||
FrameFactory(const FrameFactory &);
|
||||
FrameFactory &operator=(const FrameFactory &);
|
||||
|
||||
static FrameFactory factory;
|
||||
static FrameFactory factory;
|
||||
|
||||
class FrameFactoryPrivate;
|
||||
FrameFactoryPrivate *d;
|
||||
};
|
||||
class FrameFactoryPrivate;
|
||||
FrameFactoryPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
100
3rdparty/taglib/mpeg/id3v2/id3v2header.cpp
vendored
100
3rdparty/taglib/mpeg/id3v2/id3v2header.cpp
vendored
@@ -36,17 +36,15 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class Header::HeaderPrivate
|
||||
{
|
||||
public:
|
||||
HeaderPrivate() :
|
||||
majorVersion(4),
|
||||
revisionNumber(0),
|
||||
unsynchronisation(false),
|
||||
extendedHeader(false),
|
||||
experimentalIndicator(false),
|
||||
footerPresent(false),
|
||||
tagSize(0) {}
|
||||
class Header::HeaderPrivate {
|
||||
public:
|
||||
HeaderPrivate() : majorVersion(4),
|
||||
revisionNumber(0),
|
||||
unsynchronisation(false),
|
||||
extendedHeader(false),
|
||||
experimentalIndicator(false),
|
||||
footerPresent(false),
|
||||
tagSize(0) {}
|
||||
|
||||
unsigned int majorVersion;
|
||||
unsigned int revisionNumber;
|
||||
@@ -63,13 +61,11 @@ public:
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int Header::size()
|
||||
{
|
||||
unsigned int Header::size() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
ByteVector Header::fileIdentifier()
|
||||
{
|
||||
ByteVector Header::fileIdentifier() {
|
||||
return ByteVector::fromCString("ID3");
|
||||
}
|
||||
|
||||
@@ -77,82 +73,65 @@ ByteVector Header::fileIdentifier()
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Header::Header() :
|
||||
d(new HeaderPrivate())
|
||||
{
|
||||
Header::Header() : d(new HeaderPrivate()) {
|
||||
}
|
||||
|
||||
Header::Header(const ByteVector &data) :
|
||||
d(new HeaderPrivate())
|
||||
{
|
||||
Header::Header(const ByteVector &data) : d(new HeaderPrivate()) {
|
||||
parse(data);
|
||||
}
|
||||
|
||||
Header::~Header()
|
||||
{
|
||||
Header::~Header() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
unsigned int Header::majorVersion() const
|
||||
{
|
||||
unsigned int Header::majorVersion() const {
|
||||
return d->majorVersion;
|
||||
}
|
||||
|
||||
void Header::setMajorVersion(unsigned int version)
|
||||
{
|
||||
void Header::setMajorVersion(unsigned int version) {
|
||||
d->majorVersion = version;
|
||||
}
|
||||
|
||||
unsigned int Header::revisionNumber() const
|
||||
{
|
||||
unsigned int Header::revisionNumber() const {
|
||||
return d->revisionNumber;
|
||||
}
|
||||
|
||||
bool Header::unsynchronisation() const
|
||||
{
|
||||
bool Header::unsynchronisation() const {
|
||||
return d->unsynchronisation;
|
||||
}
|
||||
|
||||
bool Header::extendedHeader() const
|
||||
{
|
||||
bool Header::extendedHeader() const {
|
||||
return d->extendedHeader;
|
||||
}
|
||||
|
||||
bool Header::experimentalIndicator() const
|
||||
{
|
||||
bool Header::experimentalIndicator() const {
|
||||
return d->experimentalIndicator;
|
||||
}
|
||||
|
||||
bool Header::footerPresent() const
|
||||
{
|
||||
bool Header::footerPresent() const {
|
||||
return d->footerPresent;
|
||||
}
|
||||
|
||||
unsigned int Header::tagSize() const
|
||||
{
|
||||
unsigned int Header::tagSize() const {
|
||||
return d->tagSize;
|
||||
}
|
||||
|
||||
unsigned int Header::completeTagSize() const
|
||||
{
|
||||
if(d->footerPresent)
|
||||
unsigned int Header::completeTagSize() const {
|
||||
if (d->footerPresent)
|
||||
return d->tagSize + size() + Footer::size();
|
||||
else
|
||||
return d->tagSize + size();
|
||||
}
|
||||
|
||||
void Header::setTagSize(unsigned int s)
|
||||
{
|
||||
void Header::setTagSize(unsigned int s) {
|
||||
d->tagSize = s;
|
||||
}
|
||||
|
||||
void Header::setData(const ByteVector &data)
|
||||
{
|
||||
void Header::setData(const ByteVector &data) {
|
||||
parse(data);
|
||||
}
|
||||
|
||||
ByteVector Header::render() const
|
||||
{
|
||||
ByteVector Header::render() const {
|
||||
ByteVector v;
|
||||
|
||||
// add the file identifier -- "ID3"
|
||||
@@ -191,9 +170,8 @@ ByteVector Header::render() const
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Header::parse(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < size())
|
||||
void Header::parse(const ByteVector &data) {
|
||||
if (data.size() < size())
|
||||
return;
|
||||
|
||||
// do some sanity checking -- even in ID3v2.3.0 and less the tag size is a
|
||||
@@ -205,14 +183,14 @@ void Header::parse(const ByteVector &data)
|
||||
|
||||
ByteVector sizeData = data.mid(6, 4);
|
||||
|
||||
if(sizeData.size() != 4) {
|
||||
if (sizeData.size() != 4) {
|
||||
d->tagSize = 0;
|
||||
debug("TagLib::ID3v2::Header::parse() - The tag size as read was 0 bytes!");
|
||||
return;
|
||||
}
|
||||
|
||||
for(ByteVector::ConstIterator it = sizeData.begin(); it != sizeData.end(); it++) {
|
||||
if(static_cast<unsigned char>(*it) >= 128) {
|
||||
for (ByteVector::ConstIterator it = sizeData.begin(); it != sizeData.end(); it++) {
|
||||
if (static_cast<unsigned char>(*it) >= 128) {
|
||||
d->tagSize = 0;
|
||||
debug("TagLib::ID3v2::Header::parse() - One of the size bytes in the id3v2 header was greater than the allowed 128.");
|
||||
return;
|
||||
@@ -222,18 +200,18 @@ void Header::parse(const ByteVector &data)
|
||||
// The first three bytes, data[0..2], are the File Identifier, "ID3". (structure 3.1 "file identifier")
|
||||
|
||||
// Read the version number from the fourth and fifth bytes.
|
||||
d->majorVersion = data[3]; // (structure 3.1 "major version")
|
||||
d->revisionNumber = data[4]; // (structure 3.1 "revision number")
|
||||
d->majorVersion = data[3]; // (structure 3.1 "major version")
|
||||
d->revisionNumber = data[4]; // (structure 3.1 "revision number")
|
||||
|
||||
// Read the flags, the first four bits of the sixth byte.
|
||||
std::bitset<8> flags(data[5]);
|
||||
|
||||
d->unsynchronisation = flags[7]; // (structure 3.1.a)
|
||||
d->extendedHeader = flags[6]; // (structure 3.1.b)
|
||||
d->experimentalIndicator = flags[5]; // (structure 3.1.c)
|
||||
d->footerPresent = flags[4]; // (structure 3.1.d)
|
||||
d->unsynchronisation = flags[7]; // (structure 3.1.a)
|
||||
d->extendedHeader = flags[6]; // (structure 3.1.b)
|
||||
d->experimentalIndicator = flags[5]; // (structure 3.1.c)
|
||||
d->footerPresent = flags[4]; // (structure 3.1.d)
|
||||
|
||||
// Get the size from the remaining four bytes (read above)
|
||||
|
||||
d->tagSize = SynchData::toUInt(sizeData); // (structure 3.1 "size")
|
||||
d->tagSize = SynchData::toUInt(sizeData); // (structure 3.1 "size")
|
||||
}
|
||||
|
||||
103
3rdparty/taglib/mpeg/id3v2/id3v2header.h
vendored
103
3rdparty/taglib/mpeg/id3v2/id3v2header.h
vendored
@@ -33,11 +33,11 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! An implementation of ID3v2 headers
|
||||
//! An implementation of ID3v2 headers
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This class implements ID3v2 headers. It attempts to follow, both
|
||||
* semantically and programmatically, the structure specified in
|
||||
* the ID3v2 standard. The API is based on the properties of ID3v2 headers
|
||||
@@ -46,32 +46,31 @@ namespace TagLib {
|
||||
* (Structure, <a href="id3v2-structure.html#3.1">3.1</a>)
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Header
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Header {
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty ID3v2 header.
|
||||
*/
|
||||
Header();
|
||||
Header();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an ID3v2 header based on \a data. parse() is called
|
||||
* immediately.
|
||||
*/
|
||||
Header(const ByteVector &data);
|
||||
Header(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys the header.
|
||||
*/
|
||||
virtual ~Header();
|
||||
virtual ~Header();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the major version number. (Note: This is the 4, not the 2 in
|
||||
* ID3v2.4.0. The 2 is implied.)
|
||||
*/
|
||||
unsigned int majorVersion() const;
|
||||
unsigned int majorVersion() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the the major version number to \a version. (Note: This is
|
||||
* the 4, not the 2 in ID3v2.4.0. The 2 is implied.)
|
||||
* \see majorVersion()
|
||||
@@ -80,34 +79,34 @@ namespace TagLib {
|
||||
* version which is written and in general should not be called by API
|
||||
* users.
|
||||
*/
|
||||
void setMajorVersion(unsigned int version);
|
||||
void setMajorVersion(unsigned int version);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the revision number. (Note: This is the 0, not the 4 in
|
||||
* ID3v2.4.0. The 2 is implied.)
|
||||
*/
|
||||
unsigned int revisionNumber() const;
|
||||
unsigned int revisionNumber() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if unsynchronisation has been applied to all frames.
|
||||
*/
|
||||
bool unsynchronisation() const;
|
||||
bool unsynchronisation() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if an extended header is present in the tag.
|
||||
*/
|
||||
bool extendedHeader() const;
|
||||
bool extendedHeader() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the experimental indicator flag is set.
|
||||
*/
|
||||
bool experimentalIndicator() const;
|
||||
bool experimentalIndicator() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if a footer is present in the tag.
|
||||
*/
|
||||
bool footerPresent() const;
|
||||
/*!
|
||||
bool footerPresent() const;
|
||||
/*!
|
||||
* Returns the tag size in bytes. This is the size of the frame content.
|
||||
* The size of the \e entire tag will be this plus the header size (10
|
||||
* bytes) and, if present, the footer size (potentially another 10 bytes).
|
||||
@@ -118,61 +117,61 @@ namespace TagLib {
|
||||
*
|
||||
* \see completeTagSize()
|
||||
*/
|
||||
unsigned int tagSize() const;
|
||||
unsigned int tagSize() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the tag size, including the header and, if present, the footer
|
||||
* size.
|
||||
*
|
||||
* \see tagSize()
|
||||
*/
|
||||
unsigned int completeTagSize() const;
|
||||
unsigned int completeTagSize() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the tag size to \a s.
|
||||
* \see tagSize()
|
||||
*/
|
||||
void setTagSize(unsigned int s);
|
||||
void setTagSize(unsigned int s);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the header. Presently this is always 10 bytes.
|
||||
*/
|
||||
static unsigned int size();
|
||||
static unsigned int size();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the string used to identify and ID3v2 tag inside of a file.
|
||||
* Presently this is always "ID3".
|
||||
*/
|
||||
static ByteVector fileIdentifier();
|
||||
static ByteVector fileIdentifier();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the data that will be used as the header. 10 bytes, starting from
|
||||
* the beginning of \a data are used.
|
||||
*/
|
||||
void setData(const ByteVector &data);
|
||||
void setData(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Renders the Header back to binary format.
|
||||
*/
|
||||
ByteVector render() const;
|
||||
ByteVector render() const;
|
||||
|
||||
protected:
|
||||
/*!
|
||||
protected:
|
||||
/*!
|
||||
* Called by setData() to parse the header data. It makes this information
|
||||
* available through the public API.
|
||||
*/
|
||||
void parse(const ByteVector &data);
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
private:
|
||||
Header(const Header &);
|
||||
Header &operator=(const Header &);
|
||||
private:
|
||||
Header(const Header &);
|
||||
Header &operator=(const Header &);
|
||||
|
||||
class HeaderPrivate;
|
||||
HeaderPrivate *d;
|
||||
};
|
||||
class HeaderPrivate;
|
||||
HeaderPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
25
3rdparty/taglib/mpeg/id3v2/id3v2synchdata.cpp
vendored
25
3rdparty/taglib/mpeg/id3v2/id3v2synchdata.cpp
vendored
@@ -30,14 +30,13 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
unsigned int SynchData::toUInt(const ByteVector &data)
|
||||
{
|
||||
unsigned int SynchData::toUInt(const ByteVector &data) {
|
||||
unsigned int sum = 0;
|
||||
bool notSynchSafe = false;
|
||||
int last = data.size() > 4 ? 3 : data.size() - 1;
|
||||
|
||||
for(int i = 0; i <= last; i++) {
|
||||
if(data[i] & 0x80) {
|
||||
for (int i = 0; i <= last; i++) {
|
||||
if (data[i] & 0x80) {
|
||||
notSynchSafe = true;
|
||||
break;
|
||||
}
|
||||
@@ -45,11 +44,11 @@ unsigned int SynchData::toUInt(const ByteVector &data)
|
||||
sum |= (data[i] & 0x7f) << ((last - i) * 7);
|
||||
}
|
||||
|
||||
if(notSynchSafe) {
|
||||
if (notSynchSafe) {
|
||||
// Invalid data; assume this was created by some buggy software that just
|
||||
// put normal integers here rather than syncsafe ones, and try it that
|
||||
// way.
|
||||
if(data.size() >= 4) {
|
||||
if (data.size() >= 4) {
|
||||
sum = data.toUInt(0, true);
|
||||
}
|
||||
else {
|
||||
@@ -62,18 +61,16 @@ unsigned int SynchData::toUInt(const ByteVector &data)
|
||||
return sum;
|
||||
}
|
||||
|
||||
ByteVector SynchData::fromUInt(unsigned int value)
|
||||
{
|
||||
ByteVector SynchData::fromUInt(unsigned int value) {
|
||||
ByteVector v(4, 0);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
v[i] = static_cast<unsigned char>(value >> ((3 - i) * 7) & 0x7f);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
ByteVector SynchData::decode(const ByteVector &data)
|
||||
{
|
||||
ByteVector SynchData::decode(const ByteVector &data) {
|
||||
// We have this optimized method instead of using ByteVector::replace(),
|
||||
// since it makes a great difference when decoding huge unsynchronized frames.
|
||||
|
||||
@@ -82,14 +79,14 @@ ByteVector SynchData::decode(const ByteVector &data)
|
||||
ByteVector::ConstIterator src = data.begin();
|
||||
ByteVector::Iterator dst = result.begin();
|
||||
|
||||
while(src < data.end() - 1) {
|
||||
while (src < data.end() - 1) {
|
||||
*dst++ = *src++;
|
||||
|
||||
if(*(src - 1) == '\xff' && *src == '\x00')
|
||||
if (*(src - 1) == '\xff' && *src == '\x00')
|
||||
src++;
|
||||
}
|
||||
|
||||
if(src < data.end())
|
||||
if (src < data.end())
|
||||
*dst++ = *src++;
|
||||
|
||||
result.resize(static_cast<unsigned int>(dst - result.begin()));
|
||||
|
||||
29
3rdparty/taglib/mpeg/id3v2/id3v2synchdata.h
vendored
29
3rdparty/taglib/mpeg/id3v2/id3v2synchdata.h
vendored
@@ -32,11 +32,11 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
//! A few functions for ID3v2 synch safe integer conversion
|
||||
//! A few functions for ID3v2 synch safe integer conversion
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* In the ID3v2.4 standard most integer values are encoded as "synch safe"
|
||||
* integers which are encoded in such a way that they will not give false
|
||||
* MPEG syncs and confuse MPEG decoders. This namespace provides some
|
||||
@@ -44,29 +44,28 @@ namespace TagLib {
|
||||
* things rendering and parsing ID3v2 data.
|
||||
*/
|
||||
|
||||
namespace SynchData
|
||||
{
|
||||
/*!
|
||||
namespace SynchData {
|
||||
/*!
|
||||
* This returns the unsigned integer value of \a data where \a data is a
|
||||
* ByteVector that contains a \e synchsafe integer (Structure,
|
||||
* <a href="id3v2-structure.html#6.2">6.2</a>). The default \a length of
|
||||
* 4 is used if another value is not specified.
|
||||
*/
|
||||
TAGLIB_EXPORT unsigned int toUInt(const ByteVector &data);
|
||||
TAGLIB_EXPORT unsigned int toUInt(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a 4 byte (32 bit) synchsafe integer based on \a value.
|
||||
*/
|
||||
TAGLIB_EXPORT ByteVector fromUInt(unsigned int value);
|
||||
TAGLIB_EXPORT ByteVector fromUInt(unsigned int value);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Convert the data from unsynchronized data to its original format.
|
||||
*/
|
||||
TAGLIB_EXPORT ByteVector decode(const ByteVector &input);
|
||||
}
|
||||
TAGLIB_EXPORT ByteVector decode(const ByteVector &input);
|
||||
} // namespace SynchData
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
374
3rdparty/taglib/mpeg/id3v2/id3v2tag.cpp
vendored
374
3rdparty/taglib/mpeg/id3v2/id3v2tag.cpp
vendored
@@ -47,30 +47,25 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
namespace
|
||||
{
|
||||
const ID3v2::Latin1StringHandler defaultStringHandler;
|
||||
const ID3v2::Latin1StringHandler *stringHandler = &defaultStringHandler;
|
||||
namespace {
|
||||
const ID3v2::Latin1StringHandler defaultStringHandler;
|
||||
const ID3v2::Latin1StringHandler *stringHandler = &defaultStringHandler;
|
||||
|
||||
const long MinPaddingSize = 1024;
|
||||
const long MaxPaddingSize = 1024 * 1024;
|
||||
}
|
||||
const long MinPaddingSize = 1024;
|
||||
const long MaxPaddingSize = 1024 * 1024;
|
||||
} // namespace
|
||||
|
||||
class ID3v2::Tag::TagPrivate
|
||||
{
|
||||
public:
|
||||
TagPrivate() :
|
||||
factory(0),
|
||||
file(0),
|
||||
tagOffset(0),
|
||||
extendedHeader(0),
|
||||
footer(0)
|
||||
{
|
||||
class ID3v2::Tag::TagPrivate {
|
||||
public:
|
||||
TagPrivate() : factory(0),
|
||||
file(0),
|
||||
tagOffset(0),
|
||||
extendedHeader(0),
|
||||
footer(0) {
|
||||
frameList.setAutoDelete(true);
|
||||
}
|
||||
|
||||
~TagPrivate()
|
||||
{
|
||||
~TagPrivate() {
|
||||
delete extendedHeader;
|
||||
delete footer;
|
||||
}
|
||||
@@ -92,16 +87,13 @@ public:
|
||||
// StringHandler implementation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Latin1StringHandler::Latin1StringHandler()
|
||||
{
|
||||
Latin1StringHandler::Latin1StringHandler() {
|
||||
}
|
||||
|
||||
Latin1StringHandler::~Latin1StringHandler()
|
||||
{
|
||||
Latin1StringHandler::~Latin1StringHandler() {
|
||||
}
|
||||
|
||||
String Latin1StringHandler::parse(const ByteVector &data) const
|
||||
{
|
||||
String Latin1StringHandler::parse(const ByteVector &data) const {
|
||||
return String(data, String::Latin1);
|
||||
}
|
||||
|
||||
@@ -109,17 +101,13 @@ String Latin1StringHandler::parse(const ByteVector &data) const
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ID3v2::Tag::Tag() :
|
||||
Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new TagPrivate())
|
||||
{
|
||||
ID3v2::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new TagPrivate()) {
|
||||
d->factory = FrameFactory::instance();
|
||||
}
|
||||
|
||||
ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) :
|
||||
Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new TagPrivate())
|
||||
{
|
||||
ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) : Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new TagPrivate()) {
|
||||
d->factory = factory;
|
||||
d->file = file;
|
||||
d->tagOffset = tagOffset;
|
||||
@@ -127,59 +115,51 @@ ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) :
|
||||
read();
|
||||
}
|
||||
|
||||
ID3v2::Tag::~Tag()
|
||||
{
|
||||
ID3v2::Tag::~Tag() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String ID3v2::Tag::title() const
|
||||
{
|
||||
if(!d->frameListMap["TIT2"].isEmpty())
|
||||
String ID3v2::Tag::title() const {
|
||||
if (!d->frameListMap["TIT2"].isEmpty())
|
||||
return d->frameListMap["TIT2"].front()->toString();
|
||||
return String();
|
||||
}
|
||||
|
||||
String ID3v2::Tag::artist() const
|
||||
{
|
||||
if(!d->frameListMap["TPE1"].isEmpty())
|
||||
String ID3v2::Tag::artist() const {
|
||||
if (!d->frameListMap["TPE1"].isEmpty())
|
||||
return d->frameListMap["TPE1"].front()->toString();
|
||||
return String();
|
||||
}
|
||||
|
||||
String ID3v2::Tag::album() const
|
||||
{
|
||||
if(!d->frameListMap["TALB"].isEmpty())
|
||||
String ID3v2::Tag::album() const {
|
||||
if (!d->frameListMap["TALB"].isEmpty())
|
||||
return d->frameListMap["TALB"].front()->toString();
|
||||
return String();
|
||||
}
|
||||
|
||||
String ID3v2::Tag::comment() const
|
||||
{
|
||||
String ID3v2::Tag::comment() const {
|
||||
const FrameList &comments = d->frameListMap["COMM"];
|
||||
|
||||
if(comments.isEmpty())
|
||||
if (comments.isEmpty())
|
||||
return String();
|
||||
|
||||
for(FrameList::ConstIterator it = comments.begin(); it != comments.end(); ++it)
|
||||
{
|
||||
for (FrameList::ConstIterator it = comments.begin(); it != comments.end(); ++it) {
|
||||
CommentsFrame *frame = dynamic_cast<CommentsFrame *>(*it);
|
||||
|
||||
if(frame && frame->description().isEmpty())
|
||||
if (frame && frame->description().isEmpty())
|
||||
return (*it)->toString();
|
||||
}
|
||||
|
||||
return comments.front()->toString();
|
||||
}
|
||||
|
||||
String ID3v2::Tag::genre() const
|
||||
{
|
||||
String ID3v2::Tag::genre() const {
|
||||
// TODO: In the next major version (TagLib 2.0) a list of multiple genres
|
||||
// should be separated by " / " instead of " ". For the moment to keep
|
||||
// the behavior the same as released versions it is being left with " ".
|
||||
|
||||
if(d->frameListMap["TCON"].isEmpty() ||
|
||||
!dynamic_cast<TextIdentificationFrame *>(d->frameListMap["TCON"].front()))
|
||||
{
|
||||
if (d->frameListMap["TCON"].isEmpty() ||
|
||||
!dynamic_cast<TextIdentificationFrame *>(d->frameListMap["TCON"].front())) {
|
||||
return String();
|
||||
}
|
||||
|
||||
@@ -196,61 +176,55 @@ String ID3v2::Tag::genre() const
|
||||
|
||||
StringList genres;
|
||||
|
||||
for(StringList::Iterator it = fields.begin(); it != fields.end(); ++it) {
|
||||
for (StringList::Iterator it = fields.begin(); it != fields.end(); ++it) {
|
||||
|
||||
if((*it).isEmpty())
|
||||
if ((*it).isEmpty())
|
||||
continue;
|
||||
|
||||
bool ok;
|
||||
int number = (*it).toInt(&ok);
|
||||
if(ok && number >= 0 && number <= 255) {
|
||||
if (ok && number >= 0 && number <= 255) {
|
||||
*it = ID3v1::genre(number);
|
||||
}
|
||||
|
||||
if(std::find(genres.begin(), genres.end(), *it) == genres.end())
|
||||
if (std::find(genres.begin(), genres.end(), *it) == genres.end())
|
||||
genres.append(*it);
|
||||
}
|
||||
|
||||
return genres.toString();
|
||||
}
|
||||
|
||||
unsigned int ID3v2::Tag::year() const
|
||||
{
|
||||
if(!d->frameListMap["TDRC"].isEmpty())
|
||||
unsigned int ID3v2::Tag::year() const {
|
||||
if (!d->frameListMap["TDRC"].isEmpty())
|
||||
return d->frameListMap["TDRC"].front()->toString().substr(0, 4).toInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int ID3v2::Tag::track() const
|
||||
{
|
||||
if(!d->frameListMap["TRCK"].isEmpty())
|
||||
unsigned int ID3v2::Tag::track() const {
|
||||
if (!d->frameListMap["TRCK"].isEmpty())
|
||||
return d->frameListMap["TRCK"].front()->toString().toInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setTitle(const String &s)
|
||||
{
|
||||
void ID3v2::Tag::setTitle(const String &s) {
|
||||
setTextFrame("TIT2", s);
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setArtist(const String &s)
|
||||
{
|
||||
void ID3v2::Tag::setArtist(const String &s) {
|
||||
setTextFrame("TPE1", s);
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setAlbum(const String &s)
|
||||
{
|
||||
void ID3v2::Tag::setAlbum(const String &s) {
|
||||
setTextFrame("TALB", s);
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setComment(const String &s)
|
||||
{
|
||||
if(s.isEmpty()) {
|
||||
void ID3v2::Tag::setComment(const String &s) {
|
||||
if (s.isEmpty()) {
|
||||
removeFrames("COMM");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!d->frameListMap["COMM"].isEmpty())
|
||||
if (!d->frameListMap["COMM"].isEmpty())
|
||||
d->frameListMap["COMM"].front()->setText(s);
|
||||
else {
|
||||
CommentsFrame *f = new CommentsFrame(d->factory->defaultTextEncoding());
|
||||
@@ -259,9 +233,8 @@ void ID3v2::Tag::setComment(const String &s)
|
||||
}
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setGenre(const String &s)
|
||||
{
|
||||
if(s.isEmpty()) {
|
||||
void ID3v2::Tag::setGenre(const String &s) {
|
||||
if (s.isEmpty()) {
|
||||
removeFrames("TCON");
|
||||
return;
|
||||
}
|
||||
@@ -273,7 +246,7 @@ void ID3v2::Tag::setGenre(const String &s)
|
||||
|
||||
int index = ID3v1::genreIndex(s);
|
||||
|
||||
if(index != 255)
|
||||
if (index != 255)
|
||||
setTextFrame("TCON", String::number(index));
|
||||
else
|
||||
setTextFrame("TCON", s);
|
||||
@@ -285,67 +258,56 @@ void ID3v2::Tag::setGenre(const String &s)
|
||||
#endif
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setYear(unsigned int i)
|
||||
{
|
||||
if(i == 0) {
|
||||
void ID3v2::Tag::setYear(unsigned int i) {
|
||||
if (i == 0) {
|
||||
removeFrames("TDRC");
|
||||
return;
|
||||
}
|
||||
setTextFrame("TDRC", String::number(i));
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setTrack(unsigned int i)
|
||||
{
|
||||
if(i == 0) {
|
||||
void ID3v2::Tag::setTrack(unsigned int i) {
|
||||
if (i == 0) {
|
||||
removeFrames("TRCK");
|
||||
return;
|
||||
}
|
||||
setTextFrame("TRCK", String::number(i));
|
||||
}
|
||||
|
||||
bool ID3v2::Tag::isEmpty() const
|
||||
{
|
||||
bool ID3v2::Tag::isEmpty() const {
|
||||
return d->frameList.isEmpty();
|
||||
}
|
||||
|
||||
Header *ID3v2::Tag::header() const
|
||||
{
|
||||
Header *ID3v2::Tag::header() const {
|
||||
return &(d->header);
|
||||
}
|
||||
|
||||
ExtendedHeader *ID3v2::Tag::extendedHeader() const
|
||||
{
|
||||
ExtendedHeader *ID3v2::Tag::extendedHeader() const {
|
||||
return d->extendedHeader;
|
||||
}
|
||||
|
||||
Footer *ID3v2::Tag::footer() const
|
||||
{
|
||||
Footer *ID3v2::Tag::footer() const {
|
||||
return d->footer;
|
||||
}
|
||||
|
||||
const FrameListMap &ID3v2::Tag::frameListMap() const
|
||||
{
|
||||
const FrameListMap &ID3v2::Tag::frameListMap() const {
|
||||
return d->frameListMap;
|
||||
}
|
||||
|
||||
const FrameList &ID3v2::Tag::frameList() const
|
||||
{
|
||||
const FrameList &ID3v2::Tag::frameList() const {
|
||||
return d->frameList;
|
||||
}
|
||||
|
||||
const FrameList &ID3v2::Tag::frameList(const ByteVector &frameID) const
|
||||
{
|
||||
const FrameList &ID3v2::Tag::frameList(const ByteVector &frameID) const {
|
||||
return d->frameListMap[frameID];
|
||||
}
|
||||
|
||||
void ID3v2::Tag::addFrame(Frame *frame)
|
||||
{
|
||||
void ID3v2::Tag::addFrame(Frame *frame) {
|
||||
d->frameList.append(frame);
|
||||
d->frameListMap[frame->frameID()].append(frame);
|
||||
}
|
||||
|
||||
void ID3v2::Tag::removeFrame(Frame *frame, bool del)
|
||||
{
|
||||
void ID3v2::Tag::removeFrame(Frame *frame, bool del) {
|
||||
// remove the frame from the frame list
|
||||
FrameList::Iterator it = d->frameList.find(frame);
|
||||
d->frameList.erase(it);
|
||||
@@ -355,69 +317,65 @@ void ID3v2::Tag::removeFrame(Frame *frame, bool del)
|
||||
d->frameListMap[frame->frameID()].erase(it);
|
||||
|
||||
// ...and delete as desired
|
||||
if(del)
|
||||
if (del)
|
||||
delete frame;
|
||||
}
|
||||
|
||||
void ID3v2::Tag::removeFrames(const ByteVector &id)
|
||||
{
|
||||
void ID3v2::Tag::removeFrames(const ByteVector &id) {
|
||||
FrameList l = d->frameListMap[id];
|
||||
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
removeFrame(*it, true);
|
||||
}
|
||||
|
||||
PropertyMap ID3v2::Tag::properties() const
|
||||
{
|
||||
PropertyMap ID3v2::Tag::properties() const {
|
||||
PropertyMap properties;
|
||||
for(FrameList::ConstIterator it = frameList().begin(); it != frameList().end(); ++it) {
|
||||
for (FrameList::ConstIterator it = frameList().begin(); it != frameList().end(); ++it) {
|
||||
PropertyMap props = (*it)->asProperties();
|
||||
properties.merge(props);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties)
|
||||
{
|
||||
for(StringList::ConstIterator it = properties.begin(); it != properties.end(); ++it){
|
||||
if(it->startsWith("UNKNOWN/")) {
|
||||
void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties) {
|
||||
for (StringList::ConstIterator it = properties.begin(); it != properties.end(); ++it) {
|
||||
if (it->startsWith("UNKNOWN/")) {
|
||||
String frameID = it->substr(String("UNKNOWN/").size());
|
||||
if(frameID.size() != 4)
|
||||
continue; // invalid specification
|
||||
if (frameID.size() != 4)
|
||||
continue; // invalid specification
|
||||
ByteVector id = frameID.data(String::Latin1);
|
||||
// delete all unknown frames of given type
|
||||
FrameList l = frameList(id);
|
||||
for(FrameList::ConstIterator fit = l.begin(); fit != l.end(); fit++)
|
||||
for (FrameList::ConstIterator fit = l.begin(); fit != l.end(); fit++)
|
||||
if (dynamic_cast<const UnknownFrame *>(*fit) != 0)
|
||||
removeFrame(*fit);
|
||||
}
|
||||
else if(it->size() == 4){
|
||||
else if (it->size() == 4) {
|
||||
ByteVector id = it->data(String::Latin1);
|
||||
removeFrames(id);
|
||||
}
|
||||
else {
|
||||
ByteVector id = it->substr(0,4).data(String::Latin1);
|
||||
if(it->size() <= 5)
|
||||
continue; // invalid specification
|
||||
ByteVector id = it->substr(0, 4).data(String::Latin1);
|
||||
if (it->size() <= 5)
|
||||
continue; // invalid specification
|
||||
String description = it->substr(5);
|
||||
Frame *frame = 0;
|
||||
if(id == "TXXX")
|
||||
if (id == "TXXX")
|
||||
frame = UserTextIdentificationFrame::find(this, description);
|
||||
else if(id == "WXXX")
|
||||
else if (id == "WXXX")
|
||||
frame = UserUrlLinkFrame::find(this, description);
|
||||
else if(id == "COMM")
|
||||
else if (id == "COMM")
|
||||
frame = CommentsFrame::findByDescription(this, description);
|
||||
else if(id == "USLT")
|
||||
else if (id == "USLT")
|
||||
frame = UnsynchronizedLyricsFrame::findByDescription(this, description);
|
||||
else if(id == "UFID")
|
||||
else if (id == "UFID")
|
||||
frame = UniqueFileIdentifierFrame::findByOwner(this, description);
|
||||
if(frame)
|
||||
if (frame)
|
||||
removeFrame(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PropertyMap ID3v2::Tag::setProperties(const PropertyMap &origProps)
|
||||
{
|
||||
PropertyMap ID3v2::Tag::setProperties(const PropertyMap &origProps) {
|
||||
FrameList framesToDelete;
|
||||
// we split up the PropertyMap into the "normal" keys and the "complicated" ones,
|
||||
// which are those according to TIPL or TMCL frames.
|
||||
@@ -425,48 +383,48 @@ PropertyMap ID3v2::Tag::setProperties(const PropertyMap &origProps)
|
||||
PropertyMap tiplProperties;
|
||||
PropertyMap tmclProperties;
|
||||
Frame::splitProperties(origProps, properties, tiplProperties, tmclProperties);
|
||||
for(FrameListMap::ConstIterator it = frameListMap().begin(); it != frameListMap().end(); ++it){
|
||||
for(FrameList::ConstIterator lit = it->second.begin(); lit != it->second.end(); ++lit){
|
||||
for (FrameListMap::ConstIterator it = frameListMap().begin(); it != frameListMap().end(); ++it) {
|
||||
for (FrameList::ConstIterator lit = it->second.begin(); lit != it->second.end(); ++lit) {
|
||||
PropertyMap frameProperties = (*lit)->asProperties();
|
||||
if(it->first == "TIPL") {
|
||||
if (it->first == "TIPL") {
|
||||
if (tiplProperties != frameProperties)
|
||||
framesToDelete.append(*lit);
|
||||
else
|
||||
tiplProperties.erase(frameProperties);
|
||||
} else if(it->first == "TMCL") {
|
||||
}
|
||||
else if (it->first == "TMCL") {
|
||||
if (tmclProperties != frameProperties)
|
||||
framesToDelete.append(*lit);
|
||||
else
|
||||
tmclProperties.erase(frameProperties);
|
||||
} else if(!properties.contains(frameProperties))
|
||||
}
|
||||
else if (!properties.contains(frameProperties))
|
||||
framesToDelete.append(*lit);
|
||||
else
|
||||
properties.erase(frameProperties);
|
||||
}
|
||||
}
|
||||
for(FrameList::ConstIterator it = framesToDelete.begin(); it != framesToDelete.end(); ++it)
|
||||
for (FrameList::ConstIterator it = framesToDelete.begin(); it != framesToDelete.end(); ++it)
|
||||
removeFrame(*it);
|
||||
|
||||
// now create remaining frames:
|
||||
// start with the involved people list (TIPL)
|
||||
if(!tiplProperties.isEmpty())
|
||||
addFrame(TextIdentificationFrame::createTIPLFrame(tiplProperties));
|
||||
if (!tiplProperties.isEmpty())
|
||||
addFrame(TextIdentificationFrame::createTIPLFrame(tiplProperties));
|
||||
// proceed with the musician credit list (TMCL)
|
||||
if(!tmclProperties.isEmpty())
|
||||
addFrame(TextIdentificationFrame::createTMCLFrame(tmclProperties));
|
||||
if (!tmclProperties.isEmpty())
|
||||
addFrame(TextIdentificationFrame::createTMCLFrame(tmclProperties));
|
||||
// now create the "one key per frame" frames
|
||||
for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it)
|
||||
for (PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it)
|
||||
addFrame(Frame::createTextualFrame(it->first, it->second));
|
||||
return PropertyMap(); // ID3 implements the complete PropertyMap interface, so an empty map is returned
|
||||
return PropertyMap(); // ID3 implements the complete PropertyMap interface, so an empty map is returned
|
||||
}
|
||||
|
||||
ByteVector ID3v2::Tag::render() const
|
||||
{
|
||||
ByteVector ID3v2::Tag::render() const {
|
||||
return render(ID3v2::v4);
|
||||
}
|
||||
|
||||
void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
|
||||
{
|
||||
void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const {
|
||||
#ifdef NO_ITUNES_HACKS
|
||||
const char *unsupportedFrames[] = {
|
||||
"ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG",
|
||||
@@ -483,59 +441,58 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
|
||||
ID3v2::TextIdentificationFrame *frameTDRC = 0;
|
||||
ID3v2::TextIdentificationFrame *frameTIPL = 0;
|
||||
ID3v2::TextIdentificationFrame *frameTMCL = 0;
|
||||
for(FrameList::ConstIterator it = d->frameList.begin(); it != d->frameList.end(); it++) {
|
||||
for (FrameList::ConstIterator it = d->frameList.begin(); it != d->frameList.end(); it++) {
|
||||
ID3v2::Frame *frame = *it;
|
||||
ByteVector frameID = frame->header()->frameID();
|
||||
for(int i = 0; unsupportedFrames[i]; i++) {
|
||||
if(frameID == unsupportedFrames[i]) {
|
||||
debug("A frame that is not supported in ID3v2.3 \'"
|
||||
+ String(frameID) + "\' has been discarded");
|
||||
for (int i = 0; unsupportedFrames[i]; i++) {
|
||||
if (frameID == unsupportedFrames[i]) {
|
||||
debug("A frame that is not supported in ID3v2.3 \'" + String(frameID) + "\' has been discarded");
|
||||
frame = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(frame && frameID == "TDOR") {
|
||||
if (frame && frameID == "TDOR") {
|
||||
frameTDOR = dynamic_cast<ID3v2::TextIdentificationFrame *>(frame);
|
||||
frame = 0;
|
||||
}
|
||||
if(frame && frameID == "TDRC") {
|
||||
if (frame && frameID == "TDRC") {
|
||||
frameTDRC = dynamic_cast<ID3v2::TextIdentificationFrame *>(frame);
|
||||
frame = 0;
|
||||
}
|
||||
if(frame && frameID == "TIPL") {
|
||||
if (frame && frameID == "TIPL") {
|
||||
frameTIPL = dynamic_cast<ID3v2::TextIdentificationFrame *>(frame);
|
||||
frame = 0;
|
||||
}
|
||||
if(frame && frameID == "TMCL") {
|
||||
if (frame && frameID == "TMCL") {
|
||||
frameTMCL = dynamic_cast<ID3v2::TextIdentificationFrame *>(frame);
|
||||
frame = 0;
|
||||
}
|
||||
if(frame) {
|
||||
if (frame) {
|
||||
frames->append(frame);
|
||||
}
|
||||
}
|
||||
if(frameTDOR) {
|
||||
if (frameTDOR) {
|
||||
String content = frameTDOR->toString();
|
||||
if(content.size() >= 4) {
|
||||
if (content.size() >= 4) {
|
||||
ID3v2::TextIdentificationFrame *frameTORY = new ID3v2::TextIdentificationFrame("TORY", String::Latin1);
|
||||
frameTORY->setText(content.substr(0, 4));
|
||||
frames->append(frameTORY);
|
||||
newFrames->append(frameTORY);
|
||||
}
|
||||
}
|
||||
if(frameTDRC) {
|
||||
if (frameTDRC) {
|
||||
String content = frameTDRC->toString();
|
||||
if(content.size() >= 4) {
|
||||
if (content.size() >= 4) {
|
||||
ID3v2::TextIdentificationFrame *frameTYER = new ID3v2::TextIdentificationFrame("TYER", String::Latin1);
|
||||
frameTYER->setText(content.substr(0, 4));
|
||||
frames->append(frameTYER);
|
||||
newFrames->append(frameTYER);
|
||||
if(content.size() >= 10 && content[4] == '-' && content[7] == '-') {
|
||||
if (content.size() >= 10 && content[4] == '-' && content[7] == '-') {
|
||||
ID3v2::TextIdentificationFrame *frameTDAT = new ID3v2::TextIdentificationFrame("TDAT", String::Latin1);
|
||||
frameTDAT->setText(content.substr(8, 2) + content.substr(5, 2));
|
||||
frames->append(frameTDAT);
|
||||
newFrames->append(frameTDAT);
|
||||
if(content.size() >= 16 && content[10] == 'T' && content[13] == ':') {
|
||||
if (content.size() >= 16 && content[10] == 'T' && content[13] == ':') {
|
||||
ID3v2::TextIdentificationFrame *frameTIME = new ID3v2::TextIdentificationFrame("TIME", String::Latin1);
|
||||
frameTIME->setText(content.substr(11, 2) + content.substr(14, 2));
|
||||
frames->append(frameTIME);
|
||||
@@ -544,21 +501,21 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
|
||||
}
|
||||
}
|
||||
}
|
||||
if(frameTIPL || frameTMCL) {
|
||||
if (frameTIPL || frameTMCL) {
|
||||
ID3v2::TextIdentificationFrame *frameIPLS = new ID3v2::TextIdentificationFrame("IPLS", String::Latin1);
|
||||
StringList people;
|
||||
if(frameTMCL) {
|
||||
if (frameTMCL) {
|
||||
StringList v24People = frameTMCL->fieldList();
|
||||
for(unsigned int i = 0; i + 1 < v24People.size(); i += 2) {
|
||||
for (unsigned int i = 0; i + 1 < v24People.size(); i += 2) {
|
||||
people.append(v24People[i]);
|
||||
people.append(v24People[i+1]);
|
||||
people.append(v24People[i + 1]);
|
||||
}
|
||||
}
|
||||
if(frameTIPL) {
|
||||
if (frameTIPL) {
|
||||
StringList v24People = frameTIPL->fieldList();
|
||||
for(unsigned int i = 0; i + 1 < v24People.size(); i += 2) {
|
||||
for (unsigned int i = 0; i + 1 < v24People.size(); i += 2) {
|
||||
people.append(v24People[i]);
|
||||
people.append(v24People[i+1]);
|
||||
people.append(v24People[i + 1]);
|
||||
}
|
||||
}
|
||||
frameIPLS->setText(people);
|
||||
@@ -567,13 +524,11 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector ID3v2::Tag::render(int version) const
|
||||
{
|
||||
ByteVector ID3v2::Tag::render(int version) const {
|
||||
return render(version == 3 ? v3 : v4);
|
||||
}
|
||||
|
||||
ByteVector ID3v2::Tag::render(Version version) const
|
||||
{
|
||||
ByteVector ID3v2::Tag::render(Version version) const {
|
||||
// We need to render the "tag data" first so that we have to correct size to
|
||||
// render in the tag's header. The "tag data" -- everything that is included
|
||||
// in ID3v2::Header::tagSize() -- includes the extended header, frames and
|
||||
@@ -587,7 +542,7 @@ ByteVector ID3v2::Tag::render(Version version) const
|
||||
newFrames.setAutoDelete(true);
|
||||
|
||||
FrameList frameList;
|
||||
if(version == v4) {
|
||||
if (version == v4) {
|
||||
frameList = d->frameList;
|
||||
}
|
||||
else {
|
||||
@@ -600,18 +555,16 @@ ByteVector ID3v2::Tag::render(Version version) const
|
||||
|
||||
// Loop through the frames rendering them and adding them to the tagData.
|
||||
|
||||
for(FrameList::ConstIterator it = frameList.begin(); it != frameList.end(); it++) {
|
||||
for (FrameList::ConstIterator it = frameList.begin(); it != frameList.end(); it++) {
|
||||
(*it)->header()->setVersion(version == v3 ? 3 : 4);
|
||||
if((*it)->header()->frameID().size() != 4) {
|
||||
debug("An ID3v2 frame of unsupported or unknown type \'"
|
||||
+ String((*it)->header()->frameID()) + "\' has been discarded");
|
||||
if ((*it)->header()->frameID().size() != 4) {
|
||||
debug("An ID3v2 frame of unsupported or unknown type \'" + String((*it)->header()->frameID()) + "\' has been discarded");
|
||||
continue;
|
||||
}
|
||||
if(!(*it)->header()->tagAlterPreservation()) {
|
||||
if (!(*it)->header()->tagAlterPreservation()) {
|
||||
const ByteVector frameData = (*it)->render();
|
||||
if(frameData.size() == Frame::headerSize((*it)->header()->version())) {
|
||||
debug("An empty ID3v2 frame \'"
|
||||
+ String((*it)->header()->frameID()) + "\' has been discarded");
|
||||
if (frameData.size() == Frame::headerSize((*it)->header()->version())) {
|
||||
debug("An empty ID3v2 frame \'" + String((*it)->header()->frameID()) + "\' has been discarded");
|
||||
continue;
|
||||
}
|
||||
tagData.append(frameData);
|
||||
@@ -623,7 +576,7 @@ ByteVector ID3v2::Tag::render(Version version) const
|
||||
long originalSize = d->header.tagSize();
|
||||
long paddingSize = originalSize - (tagData.size() - Header::size());
|
||||
|
||||
if(paddingSize <= 0) {
|
||||
if (paddingSize <= 0) {
|
||||
paddingSize = MinPaddingSize;
|
||||
}
|
||||
else {
|
||||
@@ -633,7 +586,7 @@ ByteVector ID3v2::Tag::render(Version version) const
|
||||
threshold = std::max(threshold, MinPaddingSize);
|
||||
threshold = std::min(threshold, MaxPaddingSize);
|
||||
|
||||
if(paddingSize > threshold)
|
||||
if (paddingSize > threshold)
|
||||
paddingSize = MinPaddingSize;
|
||||
}
|
||||
|
||||
@@ -650,14 +603,12 @@ ByteVector ID3v2::Tag::render(Version version) const
|
||||
return tagData;
|
||||
}
|
||||
|
||||
Latin1StringHandler const *ID3v2::Tag::latin1StringHandler()
|
||||
{
|
||||
Latin1StringHandler const *ID3v2::Tag::latin1StringHandler() {
|
||||
return stringHandler;
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setLatin1StringHandler(const Latin1StringHandler *handler)
|
||||
{
|
||||
if(handler)
|
||||
void ID3v2::Tag::setLatin1StringHandler(const Latin1StringHandler *handler) {
|
||||
if (handler)
|
||||
stringHandler = handler;
|
||||
else
|
||||
stringHandler = &defaultStringHandler;
|
||||
@@ -667,12 +618,11 @@ void ID3v2::Tag::setLatin1StringHandler(const Latin1StringHandler *handler)
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ID3v2::Tag::read()
|
||||
{
|
||||
if(!d->file)
|
||||
void ID3v2::Tag::read() {
|
||||
if (!d->file)
|
||||
return;
|
||||
|
||||
if(!d->file->isOpen())
|
||||
if (!d->file->isOpen())
|
||||
return;
|
||||
|
||||
d->file->seek(d->tagOffset);
|
||||
@@ -681,7 +631,7 @@ void ID3v2::Tag::read()
|
||||
// If the tag size is 0, then this is an invalid tag (tags must contain at
|
||||
// least one frame)
|
||||
|
||||
if(d->header.tagSize() != 0)
|
||||
if (d->header.tagSize() != 0)
|
||||
parse(d->file->readBlock(d->header.tagSize()));
|
||||
|
||||
// Look for duplicate ID3v2 tags and treat them as an extra blank of this one.
|
||||
@@ -692,28 +642,27 @@ void ID3v2::Tag::read()
|
||||
|
||||
unsigned int extraSize = 0;
|
||||
|
||||
while(true) {
|
||||
while (true) {
|
||||
|
||||
d->file->seek(d->tagOffset + d->header.completeTagSize() + extraSize);
|
||||
|
||||
const ByteVector data = d->file->readBlock(Header::size());
|
||||
if(data.size() < Header::size() || !data.startsWith(Header::fileIdentifier()))
|
||||
if (data.size() < Header::size() || !data.startsWith(Header::fileIdentifier()))
|
||||
break;
|
||||
|
||||
extraSize += Header(data).completeTagSize();
|
||||
}
|
||||
|
||||
if(extraSize != 0) {
|
||||
if (extraSize != 0) {
|
||||
debug("ID3v2::Tag::read() - Duplicate ID3v2 tags found.");
|
||||
d->header.setTagSize(d->header.tagSize() + extraSize);
|
||||
}
|
||||
}
|
||||
|
||||
void ID3v2::Tag::parse(const ByteVector &origData)
|
||||
{
|
||||
void ID3v2::Tag::parse(const ByteVector &origData) {
|
||||
ByteVector data = origData;
|
||||
|
||||
if(d->header.unsynchronisation() && d->header.majorVersion() <= 3)
|
||||
if (d->header.unsynchronisation() && d->header.majorVersion() <= 3)
|
||||
data = SynchData::decode(data);
|
||||
|
||||
unsigned int frameDataPosition = 0;
|
||||
@@ -721,11 +670,11 @@ void ID3v2::Tag::parse(const ByteVector &origData)
|
||||
|
||||
// check for extended header
|
||||
|
||||
if(d->header.extendedHeader()) {
|
||||
if(!d->extendedHeader)
|
||||
if (d->header.extendedHeader()) {
|
||||
if (!d->extendedHeader)
|
||||
d->extendedHeader = new ExtendedHeader();
|
||||
d->extendedHeader->setData(data);
|
||||
if(d->extendedHeader->size() <= data.size()) {
|
||||
if (d->extendedHeader->size() <= data.size()) {
|
||||
frameDataPosition += d->extendedHeader->size();
|
||||
frameDataLength -= d->extendedHeader->size();
|
||||
}
|
||||
@@ -735,7 +684,7 @@ void ID3v2::Tag::parse(const ByteVector &origData)
|
||||
// contain the same data as the header, but we do need to account for its
|
||||
// size.
|
||||
|
||||
if(d->header.footerPresent() && Footer::size() <= frameDataLength)
|
||||
if (d->header.footerPresent() && Footer::size() <= frameDataLength)
|
||||
frameDataLength -= Footer::size();
|
||||
|
||||
// parse frames
|
||||
@@ -743,13 +692,13 @@ void ID3v2::Tag::parse(const ByteVector &origData)
|
||||
// Make sure that there is at least enough room in the remaining frame data for
|
||||
// a frame header.
|
||||
|
||||
while(frameDataPosition < frameDataLength - Frame::headerSize(d->header.majorVersion())) {
|
||||
while (frameDataPosition < frameDataLength - Frame::headerSize(d->header.majorVersion())) {
|
||||
|
||||
// If the next data is position is 0, assume that we've hit the padding
|
||||
// portion of the frame data.
|
||||
|
||||
if(data.at(frameDataPosition) == 0) {
|
||||
if(d->header.footerPresent()) {
|
||||
if (data.at(frameDataPosition) == 0) {
|
||||
if (d->header.footerPresent()) {
|
||||
debug("Padding *and* a footer found. This is not allowed by the spec.");
|
||||
}
|
||||
|
||||
@@ -757,14 +706,14 @@ void ID3v2::Tag::parse(const ByteVector &origData)
|
||||
}
|
||||
|
||||
Frame *frame = d->factory->createFrame(data.mid(frameDataPosition),
|
||||
&d->header);
|
||||
&d->header);
|
||||
|
||||
if(!frame)
|
||||
if (!frame)
|
||||
return;
|
||||
|
||||
// Checks to make sure that frame parsed correctly.
|
||||
|
||||
if(frame->size() <= 0) {
|
||||
if (frame->size() <= 0) {
|
||||
delete frame;
|
||||
return;
|
||||
}
|
||||
@@ -776,14 +725,13 @@ void ID3v2::Tag::parse(const ByteVector &origData)
|
||||
d->factory->rebuildAggregateFrames(this);
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value)
|
||||
{
|
||||
if(value.isEmpty()) {
|
||||
void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value) {
|
||||
if (value.isEmpty()) {
|
||||
removeFrames(id);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!d->frameListMap[id].isEmpty())
|
||||
if (!d->frameListMap[id].isEmpty())
|
||||
d->frameListMap[id].front()->setText(value);
|
||||
else {
|
||||
const String::Type encoding = d->factory->defaultTextEncoding();
|
||||
|
||||
192
3rdparty/taglib/mpeg/id3v2/id3v2tag.h
vendored
192
3rdparty/taglib/mpeg/id3v2/id3v2tag.h
vendored
@@ -39,20 +39,20 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
class File;
|
||||
class File;
|
||||
|
||||
namespace ID3v2 {
|
||||
namespace ID3v2 {
|
||||
|
||||
class Header;
|
||||
class ExtendedHeader;
|
||||
class Footer;
|
||||
class Header;
|
||||
class ExtendedHeader;
|
||||
class Footer;
|
||||
|
||||
typedef List<Frame *> FrameList;
|
||||
typedef Map<ByteVector, FrameList> FrameListMap;
|
||||
typedef List<Frame *> FrameList;
|
||||
typedef Map<ByteVector, FrameList> FrameListMap;
|
||||
|
||||
//! An abstraction for the ISO-8859-1 string to data encoding in ID3v2 tags.
|
||||
//! An abstraction for the ISO-8859-1 string to data encoding in ID3v2 tags.
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* ID3v2 tag can store strings in ISO-8859-1 (Latin1), and TagLib only
|
||||
* supports genuine ISO-8859-1 by default. However, in practice, non
|
||||
* ISO-8859-1 encodings are often used instead of ISO-8859-1, such as
|
||||
@@ -67,22 +67,21 @@ namespace TagLib {
|
||||
*
|
||||
* \see ID3v2::Tag::setStringHandler()
|
||||
*/
|
||||
class TAGLIB_EXPORT Latin1StringHandler
|
||||
{
|
||||
public:
|
||||
Latin1StringHandler();
|
||||
virtual ~Latin1StringHandler();
|
||||
class TAGLIB_EXPORT Latin1StringHandler {
|
||||
public:
|
||||
Latin1StringHandler();
|
||||
virtual ~Latin1StringHandler();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Decode a string from \a data. The default implementation assumes that
|
||||
* \a data is an ISO-8859-1 (Latin1) character array.
|
||||
*/
|
||||
virtual String parse(const ByteVector &data) const;
|
||||
};
|
||||
virtual String parse(const ByteVector &data) const;
|
||||
};
|
||||
|
||||
//! The main class in the ID3v2 implementation
|
||||
//! The main class in the ID3v2 implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is the main class in the ID3v2 implementation. It serves two
|
||||
* functions. This first, as is obvious from the public API, is to provide a
|
||||
* container for the other ID3v2 related classes. In addition, through the
|
||||
@@ -125,17 +124,16 @@ namespace TagLib {
|
||||
* working knowledge of ID3v2 structure. You're been warned.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty ID3v2 tag.
|
||||
*
|
||||
* \note You must create at least one frame for this tag to be valid.
|
||||
*/
|
||||
Tag();
|
||||
Tag();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an ID3v2 tag read from \a file starting at \a tagOffset.
|
||||
* \a factory specifies which FrameFactory will be used for the
|
||||
* construction of new frames.
|
||||
@@ -147,46 +145,46 @@ namespace TagLib {
|
||||
*
|
||||
* \see FrameFactory
|
||||
*/
|
||||
Tag(File *file, long tagOffset,
|
||||
const FrameFactory *factory = FrameFactory::instance());
|
||||
Tag(File *file, long tagOffset,
|
||||
const FrameFactory *factory = FrameFactory::instance());
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this Tag instance.
|
||||
*/
|
||||
virtual ~Tag();
|
||||
virtual ~Tag();
|
||||
|
||||
// Reimplementations.
|
||||
// Reimplementations.
|
||||
|
||||
virtual String title() const;
|
||||
virtual String artist() const;
|
||||
virtual String album() const;
|
||||
virtual String comment() const;
|
||||
virtual String genre() const;
|
||||
virtual unsigned int year() const;
|
||||
virtual unsigned int track() const;
|
||||
virtual String title() const;
|
||||
virtual String artist() const;
|
||||
virtual String album() const;
|
||||
virtual String comment() const;
|
||||
virtual String genre() const;
|
||||
virtual unsigned int year() const;
|
||||
virtual unsigned int track() const;
|
||||
|
||||
virtual void setTitle(const String &s);
|
||||
virtual void setArtist(const String &s);
|
||||
virtual void setAlbum(const String &s);
|
||||
virtual void setComment(const String &s);
|
||||
virtual void setGenre(const String &s);
|
||||
virtual void setYear(unsigned int i);
|
||||
virtual void setTrack(unsigned int i);
|
||||
virtual void setTitle(const String &s);
|
||||
virtual void setArtist(const String &s);
|
||||
virtual void setAlbum(const String &s);
|
||||
virtual void setComment(const String &s);
|
||||
virtual void setGenre(const String &s);
|
||||
virtual void setYear(unsigned int i);
|
||||
virtual void setTrack(unsigned int i);
|
||||
|
||||
virtual bool isEmpty() const;
|
||||
virtual bool isEmpty() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the tag's header.
|
||||
*/
|
||||
Header *header() const;
|
||||
Header *header() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the tag's extended header or null if there is no
|
||||
* extended header.
|
||||
*/
|
||||
ExtendedHeader *extendedHeader() const;
|
||||
ExtendedHeader *extendedHeader() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the tag's footer or null if there is no footer.
|
||||
*
|
||||
* \deprecated I don't see any reason to keep this around since there's
|
||||
@@ -194,9 +192,9 @@ namespace TagLib {
|
||||
* prone to change my mind, so this gets to stay around until near a
|
||||
* release.
|
||||
*/
|
||||
TAGLIB_DEPRECATED Footer *footer() const;
|
||||
TAGLIB_DEPRECATED Footer *footer() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a reference to the frame list map. This is an FrameListMap of
|
||||
* all of the frames in the tag.
|
||||
*
|
||||
@@ -230,9 +228,9 @@ namespace TagLib {
|
||||
*
|
||||
* \see frameList()
|
||||
*/
|
||||
const FrameListMap &frameListMap() const;
|
||||
const FrameListMap &frameListMap() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a reference to the frame list. This is an FrameList of all of
|
||||
* the frames in the tag in the order that they were parsed.
|
||||
*
|
||||
@@ -242,9 +240,9 @@ namespace TagLib {
|
||||
* \warning You should not modify this data structure directly, instead
|
||||
* use addFrame() and removeFrame().
|
||||
*/
|
||||
const FrameList &frameList() const;
|
||||
const FrameList &frameList() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the frame list for frames with the id \a frameID or an empty
|
||||
* list if there are no frames of that type. This is just a convenience
|
||||
* and is equivalent to:
|
||||
@@ -255,35 +253,35 @@ namespace TagLib {
|
||||
*
|
||||
* \see frameListMap()
|
||||
*/
|
||||
const FrameList &frameList(const ByteVector &frameID) const;
|
||||
const FrameList &frameList(const ByteVector &frameID) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Add a frame to the tag. At this point the tag takes ownership of
|
||||
* the frame and will handle freeing its memory.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
* returned by frameList()
|
||||
*/
|
||||
void addFrame(Frame *frame);
|
||||
void addFrame(Frame *frame);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove a frame from the tag. If \a del is true the frame's memory
|
||||
* will be freed; if it is false, it must be deleted by the user.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
* returned by frameList()
|
||||
*/
|
||||
void removeFrame(Frame *frame, bool del = true);
|
||||
void removeFrame(Frame *frame, bool del = true);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove all frames of type \a id from the tag and free their memory.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
* returned by frameList()
|
||||
*/
|
||||
void removeFrames(const ByteVector &id);
|
||||
void removeFrames(const ByteVector &id);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* This function does some work to translate the hard-specified ID3v2
|
||||
* frame types into a free-form string-to-stringlist PropertyMap:
|
||||
@@ -312,9 +310,9 @@ namespace TagLib {
|
||||
* once, the description, separated by a "/".
|
||||
*
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
PropertyMap properties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Removes unsupported frames given by \a properties. The elements of
|
||||
* \a properties must be taken from properties().unsupportedData(); they
|
||||
* are of one of the following forms:
|
||||
@@ -325,41 +323,41 @@ namespace TagLib {
|
||||
* - "UNKNOWN/" + frameID, for frames that could not be parsed by TagLib.
|
||||
* In that case, *all* unknown frames with the given ID will be removed.
|
||||
*/
|
||||
void removeUnsupportedProperties(const StringList &properties);
|
||||
void removeUnsupportedProperties(const StringList &properties);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the unified property interface -- import function.
|
||||
* See the comments in properties().
|
||||
*/
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Render the tag back to binary data, suitable to be written to disk.
|
||||
*/
|
||||
ByteVector render() const;
|
||||
ByteVector render() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \deprecated
|
||||
*/
|
||||
TAGLIB_DEPRECATED ByteVector render(int version) const;
|
||||
TAGLIB_DEPRECATED ByteVector render(int version) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Render the tag back to binary data, suitable to be written to disk.
|
||||
*
|
||||
* The \a version parameter specifies whether ID3v2.4 (default) or ID3v2.3
|
||||
* should be used.
|
||||
*/
|
||||
ByteVector render(Version version) const;
|
||||
ByteVector render(Version version) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Gets the current string handler that decides how the "Latin-1" data
|
||||
* will be converted to and from binary data.
|
||||
*
|
||||
* \see Latin1StringHandler
|
||||
*/
|
||||
static Latin1StringHandler const *latin1StringHandler();
|
||||
static Latin1StringHandler const *latin1StringHandler();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the string handler that decides how the "Latin-1" data will be
|
||||
* converted to and from binary data.
|
||||
* If the parameter \a handler is null, the previous handler is
|
||||
@@ -370,44 +368,44 @@ namespace TagLib {
|
||||
*
|
||||
* \see Latin1StringHandler
|
||||
*/
|
||||
static void setLatin1StringHandler(const Latin1StringHandler *handler);
|
||||
static void setLatin1StringHandler(const Latin1StringHandler *handler);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
protected:
|
||||
/*!
|
||||
* Reads data from the file specified in the constructor. It does basic
|
||||
* parsing of the data in the largest chunks. It partitions the tag into
|
||||
* the Header, the body of the tag (which contains the ExtendedHeader and
|
||||
* frames) and Footer.
|
||||
*/
|
||||
void read();
|
||||
void read();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is called by read to parse the body of the tag. It determines if an
|
||||
* extended header exists and adds frames to the FrameListMap.
|
||||
*/
|
||||
void parse(const ByteVector &data);
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the value of the text frame with the Frame ID \a id to \a value.
|
||||
* If the frame does not exist, it is created.
|
||||
*/
|
||||
void setTextFrame(const ByteVector &id, const String &value);
|
||||
void setTextFrame(const ByteVector &id, const String &value);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Dowgrade frames from ID3v2.4 (used internally and by default) to ID3v2.3
|
||||
*/
|
||||
void downgradeFrames(FrameList *existingFrames, FrameList *newFrames) const;
|
||||
void downgradeFrames(FrameList *existingFrames, FrameList *newFrames) const;
|
||||
|
||||
private:
|
||||
Tag(const Tag &);
|
||||
Tag &operator=(const Tag &);
|
||||
private:
|
||||
Tag(const Tag &);
|
||||
Tag &operator=(const Tag &);
|
||||
|
||||
class TagPrivate;
|
||||
TagPrivate *d;
|
||||
};
|
||||
class TagPrivate;
|
||||
TagPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ID3v2
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
288
3rdparty/taglib/mpeg/mpegfile.cpp
vendored
288
3rdparty/taglib/mpeg/mpegfile.cpp
vendored
@@ -39,25 +39,23 @@
|
||||
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
namespace
|
||||
{
|
||||
enum { ID3v2Index = 0, APEIndex = 1, ID3v1Index = 2 };
|
||||
namespace {
|
||||
enum { ID3v2Index = 0,
|
||||
APEIndex = 1,
|
||||
ID3v1Index = 2 };
|
||||
}
|
||||
|
||||
class MPEG::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
explicit FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) :
|
||||
ID3v2FrameFactory(frameFactory),
|
||||
ID3v2Location(-1),
|
||||
ID3v2OriginalSize(0),
|
||||
APELocation(-1),
|
||||
APEOriginalSize(0),
|
||||
ID3v1Location(-1),
|
||||
properties(0) {}
|
||||
class MPEG::File::FilePrivate {
|
||||
public:
|
||||
explicit FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) : ID3v2FrameFactory(frameFactory),
|
||||
ID3v2Location(-1),
|
||||
ID3v2OriginalSize(0),
|
||||
APELocation(-1),
|
||||
APEOriginalSize(0),
|
||||
ID3v1Location(-1),
|
||||
properties(0) {}
|
||||
|
||||
~FilePrivate()
|
||||
{
|
||||
~FilePrivate() {
|
||||
delete properties;
|
||||
}
|
||||
|
||||
@@ -80,24 +78,21 @@ public:
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
// Dummy file class to make a stream work with MPEG::Header.
|
||||
namespace {
|
||||
// Dummy file class to make a stream work with MPEG::Header.
|
||||
|
||||
class AdapterFile : public Strawberry_TagLib::TagLib::File
|
||||
{
|
||||
public:
|
||||
explicit AdapterFile(IOStream *stream) : File(stream) {}
|
||||
class AdapterFile : public Strawberry_TagLib::TagLib::File {
|
||||
public:
|
||||
explicit AdapterFile(IOStream *stream) : File(stream) {}
|
||||
|
||||
Tag *tag() const { return nullptr; }
|
||||
AudioProperties *audioProperties() const { return nullptr; }
|
||||
bool save() { return false; }
|
||||
};
|
||||
}
|
||||
Tag *tag() const { return nullptr; }
|
||||
AudioProperties *audioProperties() const { return nullptr; }
|
||||
bool save() { return false; }
|
||||
};
|
||||
} // namespace
|
||||
|
||||
bool MPEG::File::isSupported(IOStream *stream)
|
||||
{
|
||||
if(!stream || !stream->isOpen())
|
||||
bool MPEG::File::isSupported(IOStream *stream) {
|
||||
if (!stream || !stream->isOpen())
|
||||
return false;
|
||||
|
||||
// An MPEG file has MPEG frame headers. An ID3v2 tag may precede.
|
||||
@@ -108,16 +103,16 @@ bool MPEG::File::isSupported(IOStream *stream)
|
||||
long headerOffset;
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true, &headerOffset);
|
||||
|
||||
if(buffer.isEmpty())
|
||||
if (buffer.isEmpty())
|
||||
return false;
|
||||
|
||||
const long originalPosition = stream->tell();
|
||||
AdapterFile file(stream);
|
||||
|
||||
for(unsigned int i = 0; i < buffer.size() - 1; ++i) {
|
||||
if(isFrameSync(buffer, i)) {
|
||||
for (unsigned int i = 0; i < buffer.size() - 1; ++i) {
|
||||
if (isFrameSync(buffer, i)) {
|
||||
const Header header(&file, headerOffset + i, true);
|
||||
if(header.isValid()) {
|
||||
if (header.isValid()) {
|
||||
stream->seek(originalPosition);
|
||||
return true;
|
||||
}
|
||||
@@ -132,139 +127,121 @@ bool MPEG::File::isSupported(IOStream *stream)
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MPEG::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
||||
Strawberry_TagLib::TagLib::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
MPEG::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
|
||||
d(new FilePrivate()) {
|
||||
if (isOpen())
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
MPEG::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
|
||||
bool readProperties, Properties::ReadStyle) :
|
||||
Strawberry_TagLib::TagLib::File(file),
|
||||
d(new FilePrivate(frameFactory))
|
||||
{
|
||||
if(isOpen())
|
||||
bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
|
||||
d(new FilePrivate(frameFactory)) {
|
||||
if (isOpen())
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
MPEG::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
||||
bool readProperties, Properties::ReadStyle) :
|
||||
Strawberry_TagLib::TagLib::File(stream),
|
||||
d(new FilePrivate(frameFactory))
|
||||
{
|
||||
if(isOpen())
|
||||
bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
|
||||
d(new FilePrivate(frameFactory)) {
|
||||
if (isOpen())
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
MPEG::File::~File()
|
||||
{
|
||||
MPEG::File::~File() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
Strawberry_TagLib::TagLib::Tag *MPEG::File::tag() const
|
||||
{
|
||||
Strawberry_TagLib::TagLib::Tag *MPEG::File::tag() const {
|
||||
return &d->tag;
|
||||
}
|
||||
|
||||
PropertyMap MPEG::File::properties() const
|
||||
{
|
||||
PropertyMap MPEG::File::properties() const {
|
||||
return d->tag.properties();
|
||||
}
|
||||
|
||||
void MPEG::File::removeUnsupportedProperties(const StringList &properties)
|
||||
{
|
||||
void MPEG::File::removeUnsupportedProperties(const StringList &properties) {
|
||||
d->tag.removeUnsupportedProperties(properties);
|
||||
}
|
||||
|
||||
PropertyMap MPEG::File::setProperties(const PropertyMap &properties)
|
||||
{
|
||||
PropertyMap MPEG::File::setProperties(const PropertyMap &properties) {
|
||||
// update ID3v1 tag if it exists, but ignore the return value
|
||||
|
||||
if(ID3v1Tag())
|
||||
if (ID3v1Tag())
|
||||
ID3v1Tag()->setProperties(properties);
|
||||
|
||||
return ID3v2Tag(true)->setProperties(properties);
|
||||
}
|
||||
|
||||
MPEG::Properties *MPEG::File::audioProperties() const
|
||||
{
|
||||
MPEG::Properties *MPEG::File::audioProperties() const {
|
||||
return d->properties;
|
||||
}
|
||||
|
||||
bool MPEG::File::save()
|
||||
{
|
||||
bool MPEG::File::save() {
|
||||
return save(AllTags);
|
||||
}
|
||||
|
||||
bool MPEG::File::save(int tags)
|
||||
{
|
||||
bool MPEG::File::save(int tags) {
|
||||
return save(tags, StripOthers);
|
||||
}
|
||||
|
||||
bool MPEG::File::save(int tags, bool stripOthers)
|
||||
{
|
||||
bool MPEG::File::save(int tags, bool stripOthers) {
|
||||
return save(tags, stripOthers ? StripOthers : StripNone, ID3v2::v4);
|
||||
}
|
||||
|
||||
bool MPEG::File::save(int tags, bool stripOthers, int id3v2Version)
|
||||
{
|
||||
bool MPEG::File::save(int tags, bool stripOthers, int id3v2Version) {
|
||||
return save(tags,
|
||||
stripOthers ? StripOthers : StripNone,
|
||||
id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4);
|
||||
stripOthers ? StripOthers : StripNone,
|
||||
id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4);
|
||||
}
|
||||
|
||||
bool MPEG::File::save(int tags, bool stripOthers, int id3v2Version, bool duplicateTags)
|
||||
{
|
||||
bool MPEG::File::save(int tags, bool stripOthers, int id3v2Version, bool duplicateTags) {
|
||||
return save(tags,
|
||||
stripOthers ? StripOthers : StripNone,
|
||||
id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4,
|
||||
duplicateTags ? Duplicate : DoNotDuplicate);
|
||||
stripOthers ? StripOthers : StripNone,
|
||||
id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4,
|
||||
duplicateTags ? Duplicate : DoNotDuplicate);
|
||||
}
|
||||
|
||||
bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, DuplicateTags duplicate)
|
||||
{
|
||||
if(readOnly()) {
|
||||
bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, DuplicateTags duplicate) {
|
||||
if (readOnly()) {
|
||||
debug("MPEG::File::save() -- File is read only.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the tags if we've been asked to.
|
||||
|
||||
if(duplicate == Duplicate) {
|
||||
if (duplicate == Duplicate) {
|
||||
|
||||
// Copy the values from the tag that does exist into the new tag,
|
||||
// except if the existing tag is to be stripped.
|
||||
|
||||
if((tags & ID3v2) && ID3v1Tag() && !(strip == StripOthers && !(tags & ID3v1)))
|
||||
if ((tags & ID3v2) && ID3v1Tag() && !(strip == StripOthers && !(tags & ID3v1)))
|
||||
Tag::duplicate(ID3v1Tag(), ID3v2Tag(true), false);
|
||||
|
||||
if((tags & ID3v1) && d->tag[ID3v2Index] && !(strip == StripOthers && !(tags & ID3v2)))
|
||||
if ((tags & ID3v1) && d->tag[ID3v2Index] && !(strip == StripOthers && !(tags & ID3v2)))
|
||||
Tag::duplicate(ID3v2Tag(), ID3v1Tag(true), false);
|
||||
}
|
||||
|
||||
// Remove all the tags not going to be saved.
|
||||
|
||||
if(strip == StripOthers)
|
||||
if (strip == StripOthers)
|
||||
File::strip(~tags, false);
|
||||
|
||||
if(ID3v2 & tags) {
|
||||
if (ID3v2 & tags) {
|
||||
|
||||
if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) {
|
||||
if (ID3v2Tag() && !ID3v2Tag()->isEmpty()) {
|
||||
|
||||
// ID3v2 tag is not empty. Update the old one or create a new one.
|
||||
|
||||
if(d->ID3v2Location < 0)
|
||||
if (d->ID3v2Location < 0)
|
||||
d->ID3v2Location = 0;
|
||||
|
||||
const ByteVector data = ID3v2Tag()->render(version);
|
||||
insert(data, d->ID3v2Location, d->ID3v2OriginalSize);
|
||||
|
||||
if(d->APELocation >= 0)
|
||||
if (d->APELocation >= 0)
|
||||
d->APELocation += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
|
||||
|
||||
if(d->ID3v1Location >= 0)
|
||||
if (d->ID3v1Location >= 0)
|
||||
d->ID3v1Location += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
|
||||
|
||||
d->ID3v2OriginalSize = data.size();
|
||||
@@ -277,13 +254,13 @@ bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, Duplica
|
||||
}
|
||||
}
|
||||
|
||||
if(ID3v1 & tags) {
|
||||
if (ID3v1 & tags) {
|
||||
|
||||
if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
|
||||
if (ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
|
||||
|
||||
// ID3v1 tag is not empty. Update the old one or create a new one.
|
||||
|
||||
if(d->ID3v1Location >= 0) {
|
||||
if (d->ID3v1Location >= 0) {
|
||||
seek(d->ID3v1Location);
|
||||
}
|
||||
else {
|
||||
@@ -301,14 +278,14 @@ bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, Duplica
|
||||
}
|
||||
}
|
||||
|
||||
if(APE & tags) {
|
||||
if (APE & tags) {
|
||||
|
||||
if(APETag() && !APETag()->isEmpty()) {
|
||||
if (APETag() && !APETag()->isEmpty()) {
|
||||
|
||||
// APE tag is not empty. Update the old one or create a new one.
|
||||
|
||||
if(d->APELocation < 0) {
|
||||
if(d->ID3v1Location >= 0)
|
||||
if (d->APELocation < 0) {
|
||||
if (d->ID3v1Location >= 0)
|
||||
d->APELocation = d->ID3v1Location;
|
||||
else
|
||||
d->APELocation = length();
|
||||
@@ -317,7 +294,7 @@ bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, Duplica
|
||||
const ByteVector data = APETag()->render();
|
||||
insert(data, d->APELocation, d->APEOriginalSize);
|
||||
|
||||
if(d->ID3v1Location >= 0)
|
||||
if (d->ID3v1Location >= 0)
|
||||
d->ID3v1Location += (static_cast<long>(data.size()) - d->APEOriginalSize);
|
||||
|
||||
d->APEOriginalSize = data.size();
|
||||
@@ -333,95 +310,88 @@ bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, Duplica
|
||||
return true;
|
||||
}
|
||||
|
||||
ID3v2::Tag *MPEG::File::ID3v2Tag(bool create)
|
||||
{
|
||||
ID3v2::Tag *MPEG::File::ID3v2Tag(bool create) {
|
||||
return d->tag.access<ID3v2::Tag>(ID3v2Index, create);
|
||||
}
|
||||
|
||||
ID3v1::Tag *MPEG::File::ID3v1Tag(bool create)
|
||||
{
|
||||
ID3v1::Tag *MPEG::File::ID3v1Tag(bool create) {
|
||||
return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
|
||||
}
|
||||
|
||||
APE::Tag *MPEG::File::APETag(bool create)
|
||||
{
|
||||
APE::Tag *MPEG::File::APETag(bool create) {
|
||||
return d->tag.access<APE::Tag>(APEIndex, create);
|
||||
}
|
||||
|
||||
bool MPEG::File::strip(int tags)
|
||||
{
|
||||
bool MPEG::File::strip(int tags) {
|
||||
return strip(tags, true);
|
||||
}
|
||||
|
||||
bool MPEG::File::strip(int tags, bool freeMemory)
|
||||
{
|
||||
if(readOnly()) {
|
||||
bool MPEG::File::strip(int tags, bool freeMemory) {
|
||||
if (readOnly()) {
|
||||
debug("MPEG::File::strip() - Cannot strip tags from a read only file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((tags & ID3v2) && d->ID3v2Location >= 0) {
|
||||
if ((tags & ID3v2) && d->ID3v2Location >= 0) {
|
||||
removeBlock(d->ID3v2Location, d->ID3v2OriginalSize);
|
||||
|
||||
if(d->APELocation >= 0)
|
||||
if (d->APELocation >= 0)
|
||||
d->APELocation -= d->ID3v2OriginalSize;
|
||||
|
||||
if(d->ID3v1Location >= 0)
|
||||
if (d->ID3v1Location >= 0)
|
||||
d->ID3v1Location -= d->ID3v2OriginalSize;
|
||||
|
||||
d->ID3v2Location = -1;
|
||||
d->ID3v2OriginalSize = 0;
|
||||
|
||||
if(freeMemory)
|
||||
if (freeMemory)
|
||||
d->tag.set(ID3v2Index, 0);
|
||||
}
|
||||
|
||||
if((tags & ID3v1) && d->ID3v1Location >= 0) {
|
||||
if ((tags & ID3v1) && d->ID3v1Location >= 0) {
|
||||
truncate(d->ID3v1Location);
|
||||
|
||||
d->ID3v1Location = -1;
|
||||
|
||||
if(freeMemory)
|
||||
if (freeMemory)
|
||||
d->tag.set(ID3v1Index, 0);
|
||||
}
|
||||
|
||||
if((tags & APE) && d->APELocation >= 0) {
|
||||
if ((tags & APE) && d->APELocation >= 0) {
|
||||
removeBlock(d->APELocation, d->APEOriginalSize);
|
||||
|
||||
if(d->ID3v1Location >= 0)
|
||||
if (d->ID3v1Location >= 0)
|
||||
d->ID3v1Location -= d->APEOriginalSize;
|
||||
|
||||
d->APELocation = -1;
|
||||
d->APEOriginalSize = 0;
|
||||
|
||||
if(freeMemory)
|
||||
if (freeMemory)
|
||||
d->tag.set(APEIndex, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MPEG::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
|
||||
{
|
||||
void MPEG::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) {
|
||||
d->ID3v2FrameFactory = factory;
|
||||
}
|
||||
|
||||
long MPEG::File::nextFrameOffset(long position)
|
||||
{
|
||||
long MPEG::File::nextFrameOffset(long position) {
|
||||
ByteVector frameSyncBytes(2, '\0');
|
||||
|
||||
while(true) {
|
||||
while (true) {
|
||||
seek(position);
|
||||
const ByteVector buffer = readBlock(bufferSize());
|
||||
if(buffer.isEmpty())
|
||||
if (buffer.isEmpty())
|
||||
return -1;
|
||||
|
||||
for(unsigned int i = 0; i < buffer.size(); ++i) {
|
||||
for (unsigned int i = 0; i < buffer.size(); ++i) {
|
||||
frameSyncBytes[0] = frameSyncBytes[1];
|
||||
frameSyncBytes[1] = buffer[i];
|
||||
if(isFrameSync(frameSyncBytes)) {
|
||||
if (isFrameSync(frameSyncBytes)) {
|
||||
const Header header(this, position + i - 1, true);
|
||||
if(header.isValid())
|
||||
if (header.isValid())
|
||||
return position + i - 1;
|
||||
}
|
||||
}
|
||||
@@ -430,23 +400,22 @@ long MPEG::File::nextFrameOffset(long position)
|
||||
}
|
||||
}
|
||||
|
||||
long MPEG::File::previousFrameOffset(long position)
|
||||
{
|
||||
long MPEG::File::previousFrameOffset(long position) {
|
||||
ByteVector frameSyncBytes(2, '\0');
|
||||
|
||||
while(position > 0) {
|
||||
while (position > 0) {
|
||||
const long bufferLength = std::min<long>(position, bufferSize());
|
||||
position -= bufferLength;
|
||||
|
||||
seek(position);
|
||||
const ByteVector buffer = readBlock(bufferLength);
|
||||
|
||||
for(int i = buffer.size() - 1; i >= 0; --i) {
|
||||
for (int i = buffer.size() - 1; i >= 0; --i) {
|
||||
frameSyncBytes[1] = frameSyncBytes[0];
|
||||
frameSyncBytes[0] = buffer[i];
|
||||
if(isFrameSync(frameSyncBytes)) {
|
||||
if (isFrameSync(frameSyncBytes)) {
|
||||
const Header header(this, position + i, true);
|
||||
if(header.isValid())
|
||||
if (header.isValid())
|
||||
return position + i + header.frameLength();
|
||||
}
|
||||
}
|
||||
@@ -455,23 +424,21 @@ long MPEG::File::previousFrameOffset(long position)
|
||||
return -1;
|
||||
}
|
||||
|
||||
long MPEG::File::firstFrameOffset()
|
||||
{
|
||||
long MPEG::File::firstFrameOffset() {
|
||||
long position = 0;
|
||||
|
||||
if(hasID3v2Tag())
|
||||
if (hasID3v2Tag())
|
||||
position = d->ID3v2Location + ID3v2Tag()->header()->completeTagSize();
|
||||
|
||||
return nextFrameOffset(position);
|
||||
}
|
||||
|
||||
long MPEG::File::lastFrameOffset()
|
||||
{
|
||||
long MPEG::File::lastFrameOffset() {
|
||||
long position;
|
||||
|
||||
if(hasAPETag())
|
||||
if (hasAPETag())
|
||||
position = d->APELocation - 1;
|
||||
else if(hasID3v1Tag())
|
||||
else if (hasID3v1Tag())
|
||||
position = d->ID3v1Location - 1;
|
||||
else
|
||||
position = length();
|
||||
@@ -479,18 +446,15 @@ long MPEG::File::lastFrameOffset()
|
||||
return previousFrameOffset(position);
|
||||
}
|
||||
|
||||
bool MPEG::File::hasID3v1Tag() const
|
||||
{
|
||||
bool MPEG::File::hasID3v1Tag() const {
|
||||
return (d->ID3v1Location >= 0);
|
||||
}
|
||||
|
||||
bool MPEG::File::hasID3v2Tag() const
|
||||
{
|
||||
bool MPEG::File::hasID3v2Tag() const {
|
||||
return (d->ID3v2Location >= 0);
|
||||
}
|
||||
|
||||
bool MPEG::File::hasAPETag() const
|
||||
{
|
||||
bool MPEG::File::hasAPETag() const {
|
||||
return (d->APELocation >= 0);
|
||||
}
|
||||
|
||||
@@ -498,13 +462,12 @@ bool MPEG::File::hasAPETag() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MPEG::File::read(bool readProperties)
|
||||
{
|
||||
void MPEG::File::read(bool readProperties) {
|
||||
// Look for an ID3v2 tag
|
||||
|
||||
d->ID3v2Location = findID3v2();
|
||||
|
||||
if(d->ID3v2Location >= 0) {
|
||||
if (d->ID3v2Location >= 0) {
|
||||
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory));
|
||||
d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize();
|
||||
}
|
||||
@@ -513,20 +476,20 @@ void MPEG::File::read(bool readProperties)
|
||||
|
||||
d->ID3v1Location = Utils::findID3v1(this);
|
||||
|
||||
if(d->ID3v1Location >= 0)
|
||||
if (d->ID3v1Location >= 0)
|
||||
d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
||||
|
||||
// Look for an APE tag
|
||||
|
||||
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
|
||||
|
||||
if(d->APELocation >= 0) {
|
||||
if (d->APELocation >= 0) {
|
||||
d->tag.set(APEIndex, new APE::Tag(this, d->APELocation));
|
||||
d->APEOriginalSize = APETag()->footer()->completeTagSize();
|
||||
d->APELocation = d->APELocation + APE::Footer::size() - d->APEOriginalSize;
|
||||
}
|
||||
|
||||
if(readProperties)
|
||||
if (readProperties)
|
||||
d->properties = new Properties(this);
|
||||
|
||||
// Make sure that we have our default tag types available.
|
||||
@@ -535,9 +498,8 @@ void MPEG::File::read(bool readProperties)
|
||||
ID3v1Tag(true);
|
||||
}
|
||||
|
||||
long MPEG::File::findID3v2()
|
||||
{
|
||||
if(!isValid())
|
||||
long MPEG::File::findID3v2() {
|
||||
if (!isValid())
|
||||
return -1;
|
||||
|
||||
// An ID3v2 tag or MPEG frame is most likely be at the beginning of the file.
|
||||
@@ -545,11 +507,11 @@ long MPEG::File::findID3v2()
|
||||
const ByteVector headerID = ID3v2::Header::fileIdentifier();
|
||||
|
||||
seek(0);
|
||||
if(readBlock(headerID.size()) == headerID)
|
||||
if (readBlock(headerID.size()) == headerID)
|
||||
return 0;
|
||||
|
||||
const Header firstHeader(this, 0, true);
|
||||
if(firstHeader.isValid())
|
||||
if (firstHeader.isValid())
|
||||
return -1;
|
||||
|
||||
// Look for an ID3v2 tag until reaching the first valid MPEG frame.
|
||||
@@ -558,25 +520,25 @@ long MPEG::File::findID3v2()
|
||||
ByteVector tagHeaderBytes(3, '\0');
|
||||
long position = 0;
|
||||
|
||||
while(true) {
|
||||
while (true) {
|
||||
seek(position);
|
||||
const ByteVector buffer = readBlock(bufferSize());
|
||||
if(buffer.isEmpty())
|
||||
if (buffer.isEmpty())
|
||||
return -1;
|
||||
|
||||
for(unsigned int i = 0; i < buffer.size(); ++i) {
|
||||
for (unsigned int i = 0; i < buffer.size(); ++i) {
|
||||
frameSyncBytes[0] = frameSyncBytes[1];
|
||||
frameSyncBytes[1] = buffer[i];
|
||||
if(isFrameSync(frameSyncBytes)) {
|
||||
if (isFrameSync(frameSyncBytes)) {
|
||||
const Header header(this, position + i - 1, true);
|
||||
if(header.isValid())
|
||||
if (header.isValid())
|
||||
return -1;
|
||||
}
|
||||
|
||||
tagHeaderBytes[0] = tagHeaderBytes[1];
|
||||
tagHeaderBytes[1] = tagHeaderBytes[2];
|
||||
tagHeaderBytes[2] = buffer[i];
|
||||
if(tagHeaderBytes == headerID)
|
||||
if (tagHeaderBytes == headerID)
|
||||
return position + i - 2;
|
||||
}
|
||||
|
||||
|
||||
212
3rdparty/taglib/mpeg/mpegfile.h
vendored
212
3rdparty/taglib/mpeg/mpegfile.h
vendored
@@ -37,43 +37,49 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 { class Tag; class FrameFactory; }
|
||||
namespace ID3v1 { class Tag; }
|
||||
namespace APE { class Tag; }
|
||||
namespace ID3v2 {
|
||||
class Tag;
|
||||
class FrameFactory;
|
||||
} // namespace ID3v2
|
||||
namespace ID3v1 {
|
||||
class Tag;
|
||||
}
|
||||
namespace APE {
|
||||
class Tag;
|
||||
}
|
||||
|
||||
//! An implementation of TagLib::File with MPEG (MP3) specific methods
|
||||
//! An implementation of TagLib::File with MPEG (MP3) specific methods
|
||||
|
||||
namespace MPEG {
|
||||
namespace MPEG {
|
||||
|
||||
//! An MPEG file class with some useful methods specific to MPEG
|
||||
//! An MPEG file class with some useful methods specific to MPEG
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This implements the generic TagLib::File API and additionally provides
|
||||
* access to properties that are distinct to MPEG files, notably access
|
||||
* to the different ID3 tags.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
|
||||
public:
|
||||
/*!
|
||||
* This set of flags is used for various operations and is suitable for
|
||||
* being OR-ed together.
|
||||
*/
|
||||
enum TagTypes {
|
||||
//! Empty set. Matches no tag types.
|
||||
NoTags = 0x0000,
|
||||
//! Matches ID3v1 tags.
|
||||
ID3v1 = 0x0001,
|
||||
//! Matches ID3v2 tags.
|
||||
ID3v2 = 0x0002,
|
||||
//! Matches APE tags.
|
||||
APE = 0x0004,
|
||||
//! Matches all tag types.
|
||||
AllTags = 0xffff
|
||||
};
|
||||
enum TagTypes {
|
||||
//! Empty set. Matches no tag types.
|
||||
NoTags = 0x0000,
|
||||
//! Matches ID3v1 tags.
|
||||
ID3v1 = 0x0001,
|
||||
//! Matches ID3v2 tags.
|
||||
ID3v2 = 0x0002,
|
||||
//! Matches APE tags.
|
||||
APE = 0x0004,
|
||||
//! Matches all tag types.
|
||||
AllTags = 0xffff
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an MPEG file from \a file. If \a readProperties is true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
@@ -82,10 +88,10 @@ namespace TagLib {
|
||||
* \deprecated This constructor will be dropped in favor of the one below
|
||||
* in a future version.
|
||||
*/
|
||||
File(FileName file, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
File(FileName file, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an MPEG file from \a file. If \a readProperties is true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
@@ -94,12 +100,12 @@ namespace TagLib {
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*/
|
||||
// BIC: merge with the above constructor
|
||||
File(FileName file, ID3v2::FrameFactory *frameFactory,
|
||||
bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
// BIC: merge with the above constructor
|
||||
File(FileName file, ID3v2::FrameFactory *frameFactory,
|
||||
bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an MPEG file from \a stream. If \a readProperties is true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
@@ -111,16 +117,16 @@ namespace TagLib {
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*/
|
||||
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
||||
bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
||||
bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this instance of the File.
|
||||
*/
|
||||
virtual ~File();
|
||||
virtual ~File();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to a tag that is the union of the ID3v2 and ID3v1
|
||||
* tags. The ID3v2 tag is given priority in reading the information -- if
|
||||
* requested information exists in both the ID3v2 tag and the ID3v1 tag,
|
||||
@@ -137,19 +143,19 @@ namespace TagLib {
|
||||
* \see ID3v2Tag()
|
||||
* \see APETag()
|
||||
*/
|
||||
virtual Tag *tag() const;
|
||||
virtual Tag *tag() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the reading part of the unified property interface.
|
||||
* If the file contains more than one tag, only the
|
||||
* first one (in the order ID3v2, APE, ID3v1) will be converted to the
|
||||
* PropertyMap.
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
PropertyMap properties() const;
|
||||
|
||||
void removeUnsupportedProperties(const StringList &properties);
|
||||
void removeUnsupportedProperties(const StringList &properties);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the writing part of the unified tag dictionary interface.
|
||||
* In order to avoid problems with deprecated tag formats, this method
|
||||
* always creates an ID3v2 tag if necessary.
|
||||
@@ -157,15 +163,15 @@ namespace TagLib {
|
||||
* limitations of that format.
|
||||
* The returned PropertyMap refers to the ID3v2 tag only.
|
||||
*/
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the MPEG::Properties for this file. If no audio properties
|
||||
* were read then this will return a null pointer.
|
||||
*/
|
||||
virtual Properties *audioProperties() const;
|
||||
virtual Properties *audioProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Save the file. If at least one tag -- ID3v1 or ID3v2 -- exists this
|
||||
* will duplicate its content into the other tag. This returns true
|
||||
* if saving was successful.
|
||||
@@ -180,9 +186,9 @@ namespace TagLib {
|
||||
*
|
||||
* \see save(int tags)
|
||||
*/
|
||||
virtual bool save();
|
||||
virtual bool save();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Save the file. This will attempt to save all of the tag types that are
|
||||
* specified by OR-ing together TagTypes values. The save() method above
|
||||
* uses AllTags. This returns true if saving was successful.
|
||||
@@ -191,27 +197,27 @@ namespace TagLib {
|
||||
* in memory, so later calls to save() which make use of these tags will
|
||||
* remain valid. This also strips empty tags.
|
||||
*/
|
||||
bool save(int tags);
|
||||
bool save(int tags);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \deprecated
|
||||
*/
|
||||
// BIC: combine with the above method
|
||||
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers);
|
||||
// BIC: combine with the above method
|
||||
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \deprecated
|
||||
*/
|
||||
// BIC: combine with the above method
|
||||
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version);
|
||||
// BIC: combine with the above method
|
||||
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \deprecated
|
||||
*/
|
||||
// BIC: combine with the above method
|
||||
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version, bool duplicateTags);
|
||||
// BIC: combine with the above method
|
||||
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version, bool duplicateTags);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Save the file. This will attempt to save all of the tag types that are
|
||||
* specified by OR-ing together TagTypes values.
|
||||
*
|
||||
@@ -224,11 +230,11 @@ namespace TagLib {
|
||||
* If \a duplicate is set to DuplicateTags and at least one tag -- ID3v1
|
||||
* or ID3v2 -- exists this will duplicate its content into the other tag.
|
||||
*/
|
||||
bool save(int tags, StripTags strip,
|
||||
ID3v2::Version version = ID3v2::v4,
|
||||
DuplicateTags duplicate = Duplicate);
|
||||
bool save(int tags, StripTags strip,
|
||||
ID3v2::Version version = ID3v2::v4,
|
||||
DuplicateTags duplicate = Duplicate);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the ID3v2 tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this may return a null pointer
|
||||
@@ -245,9 +251,9 @@ namespace TagLib {
|
||||
*
|
||||
* \see hasID3v2Tag()
|
||||
*/
|
||||
ID3v2::Tag *ID3v2Tag(bool create = false);
|
||||
ID3v2::Tag *ID3v2Tag(bool create = false);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the ID3v1 tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this may return a null pointer
|
||||
@@ -264,9 +270,9 @@ namespace TagLib {
|
||||
*
|
||||
* \see hasID3v1Tag()
|
||||
*/
|
||||
ID3v1::Tag *ID3v1Tag(bool create = false);
|
||||
ID3v1::Tag *ID3v1Tag(bool create = false);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the APE tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this may return a null pointer
|
||||
@@ -283,9 +289,9 @@ namespace TagLib {
|
||||
*
|
||||
* \see hasAPETag()
|
||||
*/
|
||||
APE::Tag *APETag(bool create = false);
|
||||
APE::Tag *APETag(bool create = false);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This will strip the tags that match the OR-ed together TagTypes from the
|
||||
* file. By default it strips all tags. It returns true if the tags are
|
||||
* successfully stripped.
|
||||
@@ -297,9 +303,9 @@ namespace TagLib {
|
||||
*
|
||||
* \note This will update the file immediately.
|
||||
*/
|
||||
bool strip(int tags = AllTags);
|
||||
bool strip(int tags = AllTags);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This will strip the tags that match the OR-ed together TagTypes from the
|
||||
* file. By default it strips all tags. It returns true if the tags are
|
||||
* successfully stripped.
|
||||
@@ -309,81 +315,81 @@ namespace TagLib {
|
||||
*
|
||||
* \note This will update the file immediately.
|
||||
*/
|
||||
// BIC: merge with the method above
|
||||
bool strip(int tags, bool freeMemory);
|
||||
// BIC: merge with the method above
|
||||
bool strip(int tags, bool freeMemory);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Set the ID3v2::FrameFactory to something other than the default.
|
||||
*
|
||||
* \see ID3v2FrameFactory
|
||||
* \deprecated This value should be passed in via the constructor
|
||||
*/
|
||||
TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);
|
||||
TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the position in the file of the first MPEG frame.
|
||||
*/
|
||||
long firstFrameOffset();
|
||||
long firstFrameOffset();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the position in the file of the next MPEG frame,
|
||||
* using the current position as start
|
||||
*/
|
||||
long nextFrameOffset(long position);
|
||||
long nextFrameOffset(long position);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the position in the file of the previous MPEG frame,
|
||||
* using the current position as start
|
||||
*/
|
||||
long previousFrameOffset(long position);
|
||||
long previousFrameOffset(long position);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the position in the file of the last MPEG frame.
|
||||
*/
|
||||
long lastFrameOffset();
|
||||
long lastFrameOffset();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns whether or not the file on disk actually has an ID3v1 tag.
|
||||
*
|
||||
* \see ID3v1Tag()
|
||||
*/
|
||||
bool hasID3v1Tag() const;
|
||||
bool hasID3v1Tag() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns whether or not the file on disk actually has an ID3v2 tag.
|
||||
*
|
||||
* \see ID3v2Tag()
|
||||
*/
|
||||
bool hasID3v2Tag() const;
|
||||
bool hasID3v2Tag() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns whether or not the file on disk actually has an APE tag.
|
||||
*
|
||||
* \see APETag()
|
||||
*/
|
||||
bool hasAPETag() const;
|
||||
bool hasAPETag() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as an MPEG
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties);
|
||||
long findID3v2();
|
||||
void read(bool readProperties);
|
||||
long findID3v2();
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
} // namespace MPEG
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
159
3rdparty/taglib/mpeg/mpegheader.cpp
vendored
159
3rdparty/taglib/mpeg/mpegheader.cpp
vendored
@@ -34,22 +34,20 @@
|
||||
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
class MPEG::Header::HeaderPrivate : public RefCounter
|
||||
{
|
||||
public:
|
||||
HeaderPrivate() :
|
||||
isValid(false),
|
||||
version(Version1),
|
||||
layer(0),
|
||||
protectionEnabled(false),
|
||||
bitrate(0),
|
||||
sampleRate(0),
|
||||
isPadded(false),
|
||||
channelMode(Stereo),
|
||||
isCopyrighted(false),
|
||||
isOriginal(false),
|
||||
frameLength(0),
|
||||
samplesPerFrame(0) {}
|
||||
class MPEG::Header::HeaderPrivate : public RefCounter {
|
||||
public:
|
||||
HeaderPrivate() : isValid(false),
|
||||
version(Version1),
|
||||
layer(0),
|
||||
protectionEnabled(false),
|
||||
bitrate(0),
|
||||
sampleRate(0),
|
||||
isPadded(false),
|
||||
channelMode(Stereo),
|
||||
isCopyrighted(false),
|
||||
isOriginal(false),
|
||||
frameLength(0),
|
||||
samplesPerFrame(0) {}
|
||||
|
||||
bool isValid;
|
||||
Version version;
|
||||
@@ -69,96 +67,76 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MPEG::Header::Header(const ByteVector&) :
|
||||
d(new HeaderPrivate())
|
||||
{
|
||||
MPEG::Header::Header(const ByteVector &) : d(new HeaderPrivate()) {
|
||||
debug("MPEG::Header::Header() - This constructor is no longer used.");
|
||||
}
|
||||
|
||||
MPEG::Header::Header(File *file, long offset, bool checkLength) :
|
||||
d(new HeaderPrivate())
|
||||
{
|
||||
MPEG::Header::Header(File *file, long offset, bool checkLength) : d(new HeaderPrivate()) {
|
||||
parse(file, offset, checkLength);
|
||||
}
|
||||
|
||||
MPEG::Header::Header(const Header &h) :
|
||||
d(h.d)
|
||||
{
|
||||
MPEG::Header::Header(const Header &h) : d(h.d) {
|
||||
d->ref();
|
||||
}
|
||||
|
||||
MPEG::Header::~Header()
|
||||
{
|
||||
if(d->deref())
|
||||
MPEG::Header::~Header() {
|
||||
if (d->deref())
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool MPEG::Header::isValid() const
|
||||
{
|
||||
bool MPEG::Header::isValid() const {
|
||||
return d->isValid;
|
||||
}
|
||||
|
||||
MPEG::Header::Version MPEG::Header::version() const
|
||||
{
|
||||
MPEG::Header::Version MPEG::Header::version() const {
|
||||
return d->version;
|
||||
}
|
||||
|
||||
int MPEG::Header::layer() const
|
||||
{
|
||||
int MPEG::Header::layer() const {
|
||||
return d->layer;
|
||||
}
|
||||
|
||||
bool MPEG::Header::protectionEnabled() const
|
||||
{
|
||||
bool MPEG::Header::protectionEnabled() const {
|
||||
return d->protectionEnabled;
|
||||
}
|
||||
|
||||
int MPEG::Header::bitrate() const
|
||||
{
|
||||
int MPEG::Header::bitrate() const {
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
int MPEG::Header::sampleRate() const
|
||||
{
|
||||
int MPEG::Header::sampleRate() const {
|
||||
return d->sampleRate;
|
||||
}
|
||||
|
||||
bool MPEG::Header::isPadded() const
|
||||
{
|
||||
bool MPEG::Header::isPadded() const {
|
||||
return d->isPadded;
|
||||
}
|
||||
|
||||
MPEG::Header::ChannelMode MPEG::Header::channelMode() const
|
||||
{
|
||||
MPEG::Header::ChannelMode MPEG::Header::channelMode() const {
|
||||
return d->channelMode;
|
||||
}
|
||||
|
||||
bool MPEG::Header::isCopyrighted() const
|
||||
{
|
||||
bool MPEG::Header::isCopyrighted() const {
|
||||
return d->isCopyrighted;
|
||||
}
|
||||
|
||||
bool MPEG::Header::isOriginal() const
|
||||
{
|
||||
bool MPEG::Header::isOriginal() const {
|
||||
return d->isOriginal;
|
||||
}
|
||||
|
||||
int MPEG::Header::frameLength() const
|
||||
{
|
||||
int MPEG::Header::frameLength() const {
|
||||
return d->frameLength;
|
||||
}
|
||||
|
||||
int MPEG::Header::samplesPerFrame() const
|
||||
{
|
||||
int MPEG::Header::samplesPerFrame() const {
|
||||
return d->samplesPerFrame;
|
||||
}
|
||||
|
||||
MPEG::Header &MPEG::Header::operator=(const Header &h)
|
||||
{
|
||||
if(&h == this)
|
||||
MPEG::Header &MPEG::Header::operator=(const Header &h) {
|
||||
if (&h == this)
|
||||
return *this;
|
||||
|
||||
if(d->deref())
|
||||
if (d->deref())
|
||||
delete d;
|
||||
|
||||
d = h.d;
|
||||
@@ -170,19 +148,18 @@ MPEG::Header &MPEG::Header::operator=(const Header &h)
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
{
|
||||
void MPEG::Header::parse(File *file, long offset, bool checkLength) {
|
||||
file->seek(offset);
|
||||
const ByteVector data = file->readBlock(4);
|
||||
|
||||
if(data.size() < 4) {
|
||||
if (data.size() < 4) {
|
||||
debug("MPEG::Header::parse() -- data is too short for an MPEG frame header.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for the MPEG synch bytes.
|
||||
|
||||
if(!isFrameSync(data)) {
|
||||
if (!isFrameSync(data)) {
|
||||
debug("MPEG::Header::parse() -- MPEG header did not match MPEG synch.");
|
||||
return;
|
||||
}
|
||||
@@ -191,11 +168,11 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
|
||||
const int versionBits = (static_cast<unsigned char>(data[1]) >> 3) & 0x03;
|
||||
|
||||
if(versionBits == 0)
|
||||
if (versionBits == 0)
|
||||
d->version = Version2_5;
|
||||
else if(versionBits == 2)
|
||||
else if (versionBits == 2)
|
||||
d->version = Version2;
|
||||
else if(versionBits == 3)
|
||||
else if (versionBits == 3)
|
||||
d->version = Version1;
|
||||
else
|
||||
return;
|
||||
@@ -204,11 +181,11 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
|
||||
const int layerBits = (static_cast<unsigned char>(data[1]) >> 1) & 0x03;
|
||||
|
||||
if(layerBits == 1)
|
||||
if (layerBits == 1)
|
||||
d->layer = 3;
|
||||
else if(layerBits == 2)
|
||||
else if (layerBits == 2)
|
||||
d->layer = 2;
|
||||
else if(layerBits == 3)
|
||||
else if (layerBits == 3)
|
||||
d->layer = 1;
|
||||
else
|
||||
return;
|
||||
@@ -218,20 +195,22 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
// Set the bitrate
|
||||
|
||||
static const int bitrates[2][3][16] = {
|
||||
{ // Version 1
|
||||
{ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 }, // layer 1
|
||||
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 }, // layer 2
|
||||
{ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 } // layer 3
|
||||
{
|
||||
// Version 1
|
||||
{ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 }, // layer 1
|
||||
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 }, // layer 2
|
||||
{ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 } // layer 3
|
||||
},
|
||||
{ // Version 2 or 2.5
|
||||
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }, // layer 1
|
||||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 }, // layer 2
|
||||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 } // layer 3
|
||||
{
|
||||
// Version 2 or 2.5
|
||||
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }, // layer 1
|
||||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 }, // layer 2
|
||||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 } // layer 3
|
||||
}
|
||||
};
|
||||
|
||||
const int versionIndex = (d->version == Version1) ? 0 : 1;
|
||||
const int layerIndex = (d->layer > 0) ? d->layer - 1 : 0;
|
||||
const int layerIndex = (d->layer > 0) ? d->layer - 1 : 0;
|
||||
|
||||
// The bitrate index is encoded as the first 4 bits of the 3rd byte,
|
||||
// i.e. 1111xxxx
|
||||
@@ -240,15 +219,15 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
|
||||
d->bitrate = bitrates[versionIndex][layerIndex][bitrateIndex];
|
||||
|
||||
if(d->bitrate == 0)
|
||||
if (d->bitrate == 0)
|
||||
return;
|
||||
|
||||
// Set the sample rate
|
||||
|
||||
static const int sampleRates[3][4] = {
|
||||
{ 44100, 48000, 32000, 0 }, // Version 1
|
||||
{ 22050, 24000, 16000, 0 }, // Version 2
|
||||
{ 11025, 12000, 8000, 0 } // Version 2.5
|
||||
{ 44100, 48000, 32000, 0 }, // Version 1
|
||||
{ 22050, 24000, 16000, 0 }, // Version 2
|
||||
{ 11025, 12000, 8000, 0 } // Version 2.5
|
||||
};
|
||||
|
||||
// The sample rate index is encoded as two bits in the 3nd byte, i.e. xxxx11xx
|
||||
@@ -257,7 +236,7 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
|
||||
d->sampleRate = sampleRates[d->version][samplerateIndex];
|
||||
|
||||
if(d->sampleRate == 0) {
|
||||
if (d->sampleRate == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -268,17 +247,17 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
|
||||
// TODO: Add mode extension for completeness
|
||||
|
||||
d->isOriginal = ((static_cast<unsigned char>(data[3]) & 0x04) != 0);
|
||||
d->isOriginal = ((static_cast<unsigned char>(data[3]) & 0x04) != 0);
|
||||
d->isCopyrighted = ((static_cast<unsigned char>(data[3]) & 0x08) != 0);
|
||||
d->isPadded = ((static_cast<unsigned char>(data[2]) & 0x02) != 0);
|
||||
d->isPadded = ((static_cast<unsigned char>(data[2]) & 0x02) != 0);
|
||||
|
||||
// Samples per frame
|
||||
|
||||
static const int samplesPerFrame[3][2] = {
|
||||
// MPEG1, 2/2.5
|
||||
{ 384, 384 }, // Layer I
|
||||
{ 1152, 1152 }, // Layer II
|
||||
{ 1152, 576 } // Layer III
|
||||
{ 384, 384 }, // Layer I
|
||||
{ 1152, 1152 }, // Layer II
|
||||
{ 1152, 576 } // Layer III
|
||||
};
|
||||
|
||||
d->samplesPerFrame = samplesPerFrame[layerIndex][versionIndex];
|
||||
@@ -289,10 +268,10 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
|
||||
d->frameLength = d->samplesPerFrame * d->bitrate * 125 / d->sampleRate;
|
||||
|
||||
if(d->isPadded)
|
||||
if (d->isPadded)
|
||||
d->frameLength += paddingSize[layerIndex];
|
||||
|
||||
if(checkLength) {
|
||||
if (checkLength) {
|
||||
|
||||
// Check if the frame length has been calculated correctly, or the next frame
|
||||
// header is right next to the end of this frame.
|
||||
@@ -304,15 +283,15 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
file->seek(offset + d->frameLength);
|
||||
const ByteVector nextData = file->readBlock(4);
|
||||
|
||||
if(nextData.size() < 4)
|
||||
if (nextData.size() < 4)
|
||||
return;
|
||||
|
||||
const unsigned int HeaderMask = 0xfffe0c00;
|
||||
|
||||
const unsigned int header = data.toUInt(0, true) & HeaderMask;
|
||||
const unsigned int header = data.toUInt(0, true) & HeaderMask;
|
||||
const unsigned int nextHeader = nextData.toUInt(0, true) & HeaderMask;
|
||||
|
||||
if(header != nextHeader)
|
||||
if (header != nextHeader)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
139
3rdparty/taglib/mpeg/mpegheader.h
vendored
139
3rdparty/taglib/mpeg/mpegheader.h
vendored
@@ -31,150 +31,149 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
class ByteVector;
|
||||
class File;
|
||||
class ByteVector;
|
||||
class File;
|
||||
|
||||
namespace MPEG {
|
||||
namespace MPEG {
|
||||
|
||||
//! An implementation of MP3 frame headers
|
||||
//! An implementation of MP3 frame headers
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of MPEG Layer III headers. The API follows more
|
||||
* or less the binary format of these headers. I've used
|
||||
* <a href="http://www.mp3-tech.org/programmer/frame_header.html">this</a>
|
||||
* document as a reference.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Header
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Header {
|
||||
public:
|
||||
/*!
|
||||
* Parses an MPEG header based on \a data.
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
TAGLIB_DEPRECATED Header(const ByteVector &data);
|
||||
TAGLIB_DEPRECATED Header(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Parses an MPEG header based on \a file and \a offset.
|
||||
*
|
||||
* \note If \a checkLength is true, this requires the next MPEG frame to
|
||||
* check if the frame length is parsed and calculated correctly. So it's
|
||||
* suitable for seeking for the first valid frame.
|
||||
*/
|
||||
Header(File *file, long offset, bool checkLength = true);
|
||||
Header(File *file, long offset, bool checkLength = true);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Does a shallow copy of \a h.
|
||||
*/
|
||||
Header(const Header &h);
|
||||
Header(const Header &h);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this Header instance.
|
||||
*/
|
||||
virtual ~Header();
|
||||
virtual ~Header();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the frame is at least an appropriate size and has
|
||||
* legal values.
|
||||
*/
|
||||
bool isValid() const;
|
||||
bool isValid() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* The MPEG Version.
|
||||
*/
|
||||
enum Version {
|
||||
//! MPEG Version 1
|
||||
Version1 = 0,
|
||||
//! MPEG Version 2
|
||||
Version2 = 1,
|
||||
//! MPEG Version 2.5
|
||||
Version2_5 = 2
|
||||
};
|
||||
enum Version {
|
||||
//! MPEG Version 1
|
||||
Version1 = 0,
|
||||
//! MPEG Version 2
|
||||
Version2 = 1,
|
||||
//! MPEG Version 2.5
|
||||
Version2_5 = 2
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the MPEG Version of the header.
|
||||
*/
|
||||
Version version() const;
|
||||
Version version() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the layer version. This will be between the values 1-3.
|
||||
*/
|
||||
int layer() const;
|
||||
int layer() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the MPEG protection bit is enabled.
|
||||
*/
|
||||
bool protectionEnabled() const;
|
||||
bool protectionEnabled() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the bitrate encoded in the header.
|
||||
*/
|
||||
int bitrate() const;
|
||||
int bitrate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the sample rate in Hz.
|
||||
*/
|
||||
int sampleRate() const;
|
||||
int sampleRate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the frame is padded.
|
||||
*/
|
||||
bool isPadded() const;
|
||||
bool isPadded() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* There are a few combinations or one or two channel audio that are
|
||||
* possible:
|
||||
*/
|
||||
enum ChannelMode {
|
||||
//! Stereo
|
||||
Stereo = 0,
|
||||
//! Stereo
|
||||
JointStereo = 1,
|
||||
//! Dual Mono
|
||||
DualChannel = 2,
|
||||
//! Mono
|
||||
SingleChannel = 3
|
||||
};
|
||||
enum ChannelMode {
|
||||
//! Stereo
|
||||
Stereo = 0,
|
||||
//! Stereo
|
||||
JointStereo = 1,
|
||||
//! Dual Mono
|
||||
DualChannel = 2,
|
||||
//! Mono
|
||||
SingleChannel = 3
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the channel mode for this frame.
|
||||
*/
|
||||
ChannelMode channelMode() const;
|
||||
ChannelMode channelMode() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the copyrighted bit is set.
|
||||
*/
|
||||
bool isCopyrighted() const;
|
||||
bool isCopyrighted() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the "original" bit is set.
|
||||
*/
|
||||
bool isOriginal() const;
|
||||
bool isOriginal() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the frame length in bytes.
|
||||
*/
|
||||
int frameLength() const;
|
||||
int frameLength() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the number of frames per sample.
|
||||
*/
|
||||
int samplesPerFrame() const;
|
||||
int samplesPerFrame() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Makes a shallow copy of the header.
|
||||
*/
|
||||
Header &operator=(const Header &h);
|
||||
Header &operator=(const Header &h);
|
||||
|
||||
private:
|
||||
void parse(File *file, long offset, bool checkLength);
|
||||
private:
|
||||
void parse(File *file, long offset, bool checkLength);
|
||||
|
||||
class HeaderPrivate;
|
||||
HeaderPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class HeaderPrivate;
|
||||
HeaderPrivate *d;
|
||||
};
|
||||
} // namespace MPEG
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
110
3rdparty/taglib/mpeg/mpegproperties.cpp
vendored
110
3rdparty/taglib/mpeg/mpegproperties.cpp
vendored
@@ -34,24 +34,21 @@
|
||||
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
class MPEG::Properties::PropertiesPrivate
|
||||
{
|
||||
public:
|
||||
PropertiesPrivate() :
|
||||
xingHeader(0),
|
||||
length(0),
|
||||
bitrate(0),
|
||||
sampleRate(0),
|
||||
channels(0),
|
||||
layer(0),
|
||||
version(Header::Version1),
|
||||
channelMode(Header::Stereo),
|
||||
protectionEnabled(false),
|
||||
isCopyrighted(false),
|
||||
isOriginal(false) {}
|
||||
class MPEG::Properties::PropertiesPrivate {
|
||||
public:
|
||||
PropertiesPrivate() : xingHeader(0),
|
||||
length(0),
|
||||
bitrate(0),
|
||||
sampleRate(0),
|
||||
channels(0),
|
||||
layer(0),
|
||||
version(Header::Version1),
|
||||
channelMode(Header::Stereo),
|
||||
protectionEnabled(false),
|
||||
isCopyrighted(false),
|
||||
isOriginal(false) {}
|
||||
|
||||
~PropertiesPrivate()
|
||||
{
|
||||
~PropertiesPrivate() {
|
||||
delete xingHeader;
|
||||
}
|
||||
|
||||
@@ -72,80 +69,64 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MPEG::Properties::Properties(File *file, ReadStyle style) :
|
||||
AudioProperties(style),
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
MPEG::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style),
|
||||
d(new PropertiesPrivate()) {
|
||||
read(file);
|
||||
}
|
||||
|
||||
MPEG::Properties::~Properties()
|
||||
{
|
||||
MPEG::Properties::~Properties() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
int MPEG::Properties::length() const
|
||||
{
|
||||
int MPEG::Properties::length() const {
|
||||
return lengthInSeconds();
|
||||
}
|
||||
|
||||
int MPEG::Properties::lengthInSeconds() const
|
||||
{
|
||||
int MPEG::Properties::lengthInSeconds() const {
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int MPEG::Properties::lengthInMilliseconds() const
|
||||
{
|
||||
int MPEG::Properties::lengthInMilliseconds() const {
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int MPEG::Properties::bitrate() const
|
||||
{
|
||||
int MPEG::Properties::bitrate() const {
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
int MPEG::Properties::sampleRate() const
|
||||
{
|
||||
int MPEG::Properties::sampleRate() const {
|
||||
return d->sampleRate;
|
||||
}
|
||||
|
||||
int MPEG::Properties::channels() const
|
||||
{
|
||||
int MPEG::Properties::channels() const {
|
||||
return d->channels;
|
||||
}
|
||||
|
||||
const MPEG::XingHeader *MPEG::Properties::xingHeader() const
|
||||
{
|
||||
const MPEG::XingHeader *MPEG::Properties::xingHeader() const {
|
||||
return d->xingHeader;
|
||||
}
|
||||
|
||||
MPEG::Header::Version MPEG::Properties::version() const
|
||||
{
|
||||
MPEG::Header::Version MPEG::Properties::version() const {
|
||||
return d->version;
|
||||
}
|
||||
|
||||
int MPEG::Properties::layer() const
|
||||
{
|
||||
int MPEG::Properties::layer() const {
|
||||
return d->layer;
|
||||
}
|
||||
|
||||
bool MPEG::Properties::protectionEnabled() const
|
||||
{
|
||||
bool MPEG::Properties::protectionEnabled() const {
|
||||
return d->protectionEnabled;
|
||||
}
|
||||
|
||||
MPEG::Header::ChannelMode MPEG::Properties::channelMode() const
|
||||
{
|
||||
MPEG::Header::ChannelMode MPEG::Properties::channelMode() const {
|
||||
return d->channelMode;
|
||||
}
|
||||
|
||||
bool MPEG::Properties::isCopyrighted() const
|
||||
{
|
||||
bool MPEG::Properties::isCopyrighted() const {
|
||||
return d->isCopyrighted;
|
||||
}
|
||||
|
||||
bool MPEG::Properties::isOriginal() const
|
||||
{
|
||||
bool MPEG::Properties::isOriginal() const {
|
||||
return d->isOriginal;
|
||||
}
|
||||
|
||||
@@ -153,12 +134,11 @@ bool MPEG::Properties::isOriginal() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MPEG::Properties::read(File *file)
|
||||
{
|
||||
void MPEG::Properties::read(File *file) {
|
||||
// Only the first valid frame is required if we have a VBR header.
|
||||
|
||||
const long firstFrameOffset = file->firstFrameOffset();
|
||||
if(firstFrameOffset < 0) {
|
||||
if (firstFrameOffset < 0) {
|
||||
debug("MPEG::Properties::read() -- Could not find an MPEG frame in the stream.");
|
||||
return;
|
||||
}
|
||||
@@ -170,22 +150,22 @@ void MPEG::Properties::read(File *file)
|
||||
|
||||
file->seek(firstFrameOffset);
|
||||
d->xingHeader = new XingHeader(file->readBlock(firstHeader.frameLength()));
|
||||
if(!d->xingHeader->isValid()) {
|
||||
if (!d->xingHeader->isValid()) {
|
||||
delete d->xingHeader;
|
||||
d->xingHeader = 0;
|
||||
}
|
||||
|
||||
if(d->xingHeader && firstHeader.samplesPerFrame() > 0 && firstHeader.sampleRate() > 0) {
|
||||
if (d->xingHeader && firstHeader.samplesPerFrame() > 0 && firstHeader.sampleRate() > 0) {
|
||||
|
||||
// Read the length and the bitrate from the VBR header.
|
||||
|
||||
const double timePerFrame = firstHeader.samplesPerFrame() * 1000.0 / firstHeader.sampleRate();
|
||||
const double length = timePerFrame * d->xingHeader->totalFrames();
|
||||
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->bitrate = static_cast<int>(d->xingHeader->totalSize() * 8.0 / length + 0.5);
|
||||
}
|
||||
else if(firstHeader.bitrate() > 0) {
|
||||
else if (firstHeader.bitrate() > 0) {
|
||||
|
||||
// Since there was no valid VBR header found, we hope that we're in a constant
|
||||
// bitrate file.
|
||||
@@ -198,23 +178,23 @@ void MPEG::Properties::read(File *file)
|
||||
// Look for the last MPEG audio frame to calculate the stream length.
|
||||
|
||||
const long lastFrameOffset = file->lastFrameOffset();
|
||||
if(lastFrameOffset < 0) {
|
||||
if (lastFrameOffset < 0) {
|
||||
debug("MPEG::Properties::read() -- Could not find an MPEG frame in the stream.");
|
||||
return;
|
||||
}
|
||||
|
||||
const Header lastHeader(file, lastFrameOffset, false);
|
||||
const long streamLength = lastFrameOffset - firstFrameOffset + lastHeader.frameLength();
|
||||
if(streamLength > 0)
|
||||
if (streamLength > 0)
|
||||
d->length = static_cast<int>(streamLength * 8.0 / d->bitrate + 0.5);
|
||||
}
|
||||
|
||||
d->sampleRate = firstHeader.sampleRate();
|
||||
d->channels = firstHeader.channelMode() == Header::SingleChannel ? 1 : 2;
|
||||
d->version = firstHeader.version();
|
||||
d->layer = firstHeader.layer();
|
||||
d->sampleRate = firstHeader.sampleRate();
|
||||
d->channels = firstHeader.channelMode() == Header::SingleChannel ? 1 : 2;
|
||||
d->version = firstHeader.version();
|
||||
d->layer = firstHeader.layer();
|
||||
d->protectionEnabled = firstHeader.protectionEnabled();
|
||||
d->channelMode = firstHeader.channelMode();
|
||||
d->isCopyrighted = firstHeader.isCopyrighted();
|
||||
d->isOriginal = firstHeader.isOriginal();
|
||||
d->channelMode = firstHeader.channelMode();
|
||||
d->isCopyrighted = firstHeader.isCopyrighted();
|
||||
d->isOriginal = firstHeader.isOriginal();
|
||||
}
|
||||
|
||||
99
3rdparty/taglib/mpeg/mpegproperties.h
vendored
99
3rdparty/taglib/mpeg/mpegproperties.h
vendored
@@ -34,33 +34,32 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace MPEG {
|
||||
namespace MPEG {
|
||||
|
||||
class File;
|
||||
class XingHeader;
|
||||
class File;
|
||||
class XingHeader;
|
||||
|
||||
//! An implementation of audio property reading for MP3
|
||||
//! An implementation of audio property reading for MP3
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This reads the data from an MPEG Layer III stream found in the
|
||||
* AudioProperties API.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||
public:
|
||||
/*!
|
||||
* Create an instance of MPEG::Properties with the data read from the
|
||||
* MPEG::File \a file.
|
||||
*/
|
||||
Properties(File *file, ReadStyle style = Average);
|
||||
Properties(File *file, ReadStyle style = Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this MPEG Properties instance.
|
||||
*/
|
||||
virtual ~Properties();
|
||||
virtual ~Properties();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
@@ -68,87 +67,87 @@ namespace TagLib {
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
virtual int length() const;
|
||||
virtual int length() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
* \see lengthInMilliseconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in milliseconds.
|
||||
*
|
||||
* \see lengthInSeconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the average bit rate of the file in kb/s.
|
||||
*/
|
||||
virtual int bitrate() const;
|
||||
virtual int bitrate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the sample rate in Hz.
|
||||
*/
|
||||
virtual int sampleRate() const;
|
||||
virtual int sampleRate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the number of audio channels.
|
||||
*/
|
||||
virtual int channels() const;
|
||||
virtual int channels() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the Xing/VBRI header if one exists or null if no
|
||||
* Xing/VBRI header was found.
|
||||
*/
|
||||
const XingHeader *xingHeader() const;
|
||||
const XingHeader *xingHeader() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the MPEG Version of the file.
|
||||
*/
|
||||
Header::Version version() const;
|
||||
Header::Version version() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the layer version. This will be between the values 1-3.
|
||||
*/
|
||||
int layer() const;
|
||||
int layer() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the MPEG protection bit is enabled.
|
||||
*/
|
||||
bool protectionEnabled() const;
|
||||
bool protectionEnabled() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the channel mode for this frame.
|
||||
*/
|
||||
Header::ChannelMode channelMode() const;
|
||||
Header::ChannelMode channelMode() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the copyrighted bit is set.
|
||||
*/
|
||||
bool isCopyrighted() const;
|
||||
bool isCopyrighted() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the "original" bit is set.
|
||||
*/
|
||||
bool isOriginal() const;
|
||||
bool isOriginal() const;
|
||||
|
||||
private:
|
||||
Properties(const Properties &);
|
||||
Properties &operator=(const Properties &);
|
||||
private:
|
||||
Properties(const Properties &);
|
||||
Properties &operator=(const Properties &);
|
||||
|
||||
void read(File *file);
|
||||
void read(File *file);
|
||||
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
} // namespace MPEG
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
32
3rdparty/taglib/mpeg/mpegutils.h
vendored
32
3rdparty/taglib/mpeg/mpegutils.h
vendored
@@ -31,14 +31,11 @@
|
||||
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
|
||||
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib
|
||||
{
|
||||
namespace MPEG
|
||||
{
|
||||
namespace
|
||||
{
|
||||
namespace TagLib {
|
||||
namespace MPEG {
|
||||
namespace {
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* MPEG frames can be recognized by the bit pattern 11111111 111, so the
|
||||
* first byte is easy to check for, however checking to see if the second byte
|
||||
* starts with \e 111 is a bit more tricky, hence these functions.
|
||||
@@ -46,19 +43,18 @@ namespace TagLib
|
||||
* \note This does not check the length of the vector, since this is an
|
||||
* internal utility function.
|
||||
*/
|
||||
inline bool isFrameSync(const ByteVector &bytes, unsigned int offset = 0)
|
||||
{
|
||||
// 0xFF in the second byte is possible in theory, but it's very unlikely.
|
||||
inline bool isFrameSync(const ByteVector &bytes, unsigned int offset = 0) {
|
||||
// 0xFF in the second byte is possible in theory, but it's very unlikely.
|
||||
|
||||
const unsigned char b1 = bytes[offset + 0];
|
||||
const unsigned char b2 = bytes[offset + 1];
|
||||
return (b1 == 0xFF && b2 != 0xFF && (b2 & 0xE0) == 0xE0);
|
||||
}
|
||||
const unsigned char b1 = bytes[offset + 0];
|
||||
const unsigned char b2 = bytes[offset + 1];
|
||||
return (b1 == 0xFF && b2 != 0xFF && (b2 & 0xE0) == 0xE0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
} // namespace MPEG
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
59
3rdparty/taglib/mpeg/xingheader.cpp
vendored
59
3rdparty/taglib/mpeg/xingheader.cpp
vendored
@@ -32,13 +32,11 @@
|
||||
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
class MPEG::XingHeader::XingHeaderPrivate
|
||||
{
|
||||
public:
|
||||
XingHeaderPrivate() :
|
||||
frames(0),
|
||||
size(0),
|
||||
type(MPEG::XingHeader::Invalid) {}
|
||||
class MPEG::XingHeader::XingHeaderPrivate {
|
||||
public:
|
||||
XingHeaderPrivate() : frames(0),
|
||||
size(0),
|
||||
type(MPEG::XingHeader::Invalid) {}
|
||||
|
||||
unsigned int frames;
|
||||
unsigned int size;
|
||||
@@ -50,40 +48,32 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MPEG::XingHeader::XingHeader(const ByteVector &data) :
|
||||
d(new XingHeaderPrivate())
|
||||
{
|
||||
MPEG::XingHeader::XingHeader(const ByteVector &data) : d(new XingHeaderPrivate()) {
|
||||
parse(data);
|
||||
}
|
||||
|
||||
MPEG::XingHeader::~XingHeader()
|
||||
{
|
||||
MPEG::XingHeader::~XingHeader() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool MPEG::XingHeader::isValid() const
|
||||
{
|
||||
bool MPEG::XingHeader::isValid() const {
|
||||
return (d->type != Invalid && d->frames > 0 && d->size > 0);
|
||||
}
|
||||
|
||||
unsigned int MPEG::XingHeader::totalFrames() const
|
||||
{
|
||||
unsigned int MPEG::XingHeader::totalFrames() const {
|
||||
return d->frames;
|
||||
}
|
||||
|
||||
unsigned int MPEG::XingHeader::totalSize() const
|
||||
{
|
||||
unsigned int MPEG::XingHeader::totalSize() const {
|
||||
return d->size;
|
||||
}
|
||||
|
||||
MPEG::XingHeader::HeaderType MPEG::XingHeader::type() const
|
||||
{
|
||||
MPEG::XingHeader::HeaderType MPEG::XingHeader::type() const {
|
||||
return d->type;
|
||||
}
|
||||
|
||||
int MPEG::XingHeader::xingHeaderOffset(Strawberry_TagLib::TagLib::MPEG::Header::Version /*v*/,
|
||||
Strawberry_TagLib::TagLib::MPEG::Header::ChannelMode /*c*/)
|
||||
{
|
||||
Strawberry_TagLib::TagLib::MPEG::Header::ChannelMode /*c*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -91,31 +81,30 @@ int MPEG::XingHeader::xingHeaderOffset(Strawberry_TagLib::TagLib::MPEG::Header::
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MPEG::XingHeader::parse(const ByteVector &data)
|
||||
{
|
||||
void MPEG::XingHeader::parse(const ByteVector &data) {
|
||||
// Look for a Xing header.
|
||||
|
||||
long offset = data.find("Xing");
|
||||
if(offset < 0)
|
||||
if (offset < 0)
|
||||
offset = data.find("Info");
|
||||
|
||||
if(offset >= 0) {
|
||||
if (offset >= 0) {
|
||||
|
||||
// Xing header found.
|
||||
|
||||
if(data.size() < static_cast<unsigned long>(offset + 16)) {
|
||||
if (data.size() < static_cast<unsigned long>(offset + 16)) {
|
||||
debug("MPEG::XingHeader::parse() -- Xing header found but too short.");
|
||||
return;
|
||||
}
|
||||
|
||||
if((data[offset + 7] & 0x03) != 0x03) {
|
||||
if ((data[offset + 7] & 0x03) != 0x03) {
|
||||
debug("MPEG::XingHeader::parse() -- Xing header doesn't contain the required information.");
|
||||
return;
|
||||
}
|
||||
|
||||
d->frames = data.toUInt(offset + 8, true);
|
||||
d->size = data.toUInt(offset + 12, true);
|
||||
d->type = Xing;
|
||||
d->frames = data.toUInt(offset + 8, true);
|
||||
d->size = data.toUInt(offset + 12, true);
|
||||
d->type = Xing;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -123,18 +112,18 @@ void MPEG::XingHeader::parse(const ByteVector &data)
|
||||
|
||||
offset = data.find("VBRI");
|
||||
|
||||
if(offset >= 0) {
|
||||
if (offset >= 0) {
|
||||
|
||||
// VBRI header found.
|
||||
|
||||
if(data.size() < static_cast<unsigned long>(offset + 32)) {
|
||||
if (data.size() < static_cast<unsigned long>(offset + 32)) {
|
||||
debug("MPEG::XingHeader::parse() -- VBRI header found but too short.");
|
||||
return;
|
||||
}
|
||||
|
||||
d->frames = data.toUInt(offset + 14, true);
|
||||
d->size = data.toUInt(offset + 10, true);
|
||||
d->type = VBRI;
|
||||
d->size = data.toUInt(offset + 10, true);
|
||||
d->type = VBRI;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
84
3rdparty/taglib/mpeg/xingheader.h
vendored
84
3rdparty/taglib/mpeg/xingheader.h
vendored
@@ -32,15 +32,15 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
class ByteVector;
|
||||
class ByteVector;
|
||||
|
||||
namespace MPEG {
|
||||
namespace MPEG {
|
||||
|
||||
class File;
|
||||
class File;
|
||||
|
||||
//! An implementation of the Xing/VBRI headers
|
||||
//! An implementation of the Xing/VBRI headers
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is a minimalistic implementation of the Xing/VBRI VBR headers.
|
||||
* Xing/VBRI headers are often added to VBR (variable bit rate) MP3 streams
|
||||
* to make it easy to compute the length and quality of a VBR stream. Our
|
||||
@@ -50,82 +50,80 @@ namespace TagLib {
|
||||
* this text</a> and the XMMS sources as references.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT XingHeader
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT XingHeader {
|
||||
public:
|
||||
/*!
|
||||
* The type of the VBR header.
|
||||
*/
|
||||
enum HeaderType
|
||||
{
|
||||
/*!
|
||||
enum HeaderType {
|
||||
/*!
|
||||
* Invalid header or no VBR header found.
|
||||
*/
|
||||
Invalid = 0,
|
||||
Invalid = 0,
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Xing header.
|
||||
*/
|
||||
Xing = 1,
|
||||
Xing = 1,
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* VBRI header.
|
||||
*/
|
||||
VBRI = 2,
|
||||
};
|
||||
VBRI = 2,
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Parses an Xing/VBRI header based on \a data which contains the entire
|
||||
* first MPEG frame.
|
||||
*/
|
||||
XingHeader(const ByteVector &data);
|
||||
XingHeader(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroy this XingHeader instance.
|
||||
*/
|
||||
virtual ~XingHeader();
|
||||
virtual ~XingHeader();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the data was parsed properly and if there is a valid
|
||||
* Xing/VBRI header present.
|
||||
*/
|
||||
bool isValid() const;
|
||||
bool isValid() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the total number of frames.
|
||||
*/
|
||||
unsigned int totalFrames() const;
|
||||
unsigned int totalFrames() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the total size of stream in bytes.
|
||||
*/
|
||||
unsigned int totalSize() const;
|
||||
unsigned int totalSize() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the type of the VBR header.
|
||||
*/
|
||||
HeaderType type() const;
|
||||
HeaderType type() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the offset for the start of this Xing header, given the
|
||||
* version and channels of the frame
|
||||
*
|
||||
* \deprecated Always returns 0.
|
||||
*/
|
||||
TAGLIB_DEPRECATED static int xingHeaderOffset(Strawberry_TagLib::TagLib::MPEG::Header::Version v,
|
||||
Strawberry_TagLib::TagLib::MPEG::Header::ChannelMode c);
|
||||
TAGLIB_DEPRECATED static int xingHeaderOffset(Strawberry_TagLib::TagLib::MPEG::Header::Version v,
|
||||
Strawberry_TagLib::TagLib::MPEG::Header::ChannelMode c);
|
||||
|
||||
private:
|
||||
XingHeader(const XingHeader &);
|
||||
XingHeader &operator=(const XingHeader &);
|
||||
private:
|
||||
XingHeader(const XingHeader &);
|
||||
XingHeader &operator=(const XingHeader &);
|
||||
|
||||
void parse(const ByteVector &data);
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
class XingHeaderPrivate;
|
||||
XingHeaderPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class XingHeaderPrivate;
|
||||
XingHeaderPrivate *d;
|
||||
};
|
||||
} // namespace MPEG
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user