diff --git a/3rdparty/taglib/ConfigureChecks.cmake b/3rdparty/taglib/ConfigureChecks.cmake index 5e5fca2fd..a06736250 100644 --- a/3rdparty/taglib/ConfigureChecks.cmake +++ b/3rdparty/taglib/ConfigureChecks.cmake @@ -1,5 +1,6 @@ include(CheckLibraryExists) include(CheckTypeSize) +include(CheckCXXCompilerFlag) include(CheckCXXSourceCompiles) # Check if the size of numeric types are suitable. diff --git a/3rdparty/taglib/ape/apefile.cpp b/3rdparty/taglib/ape/apefile.cpp index 56330005d..f074ae5bd 100644 --- a/3rdparty/taglib/ape/apefile.cpp +++ b/3rdparty/taglib/ape/apefile.cpp @@ -56,10 +56,10 @@ class APE::File::FilePrivate { FilePrivate() : APELocation(-1), APESize(0), ID3v1Location(-1), - ID3v2Header(0), + ID3v2Header(nullptr), ID3v2Location(-1), ID3v2Size(0), - properties(0) {} + properties(nullptr) {} ~FilePrivate() { delete ID3v2Header; @@ -98,16 +98,18 @@ bool APE::File::isSupported(IOStream *) { // public members //////////////////////////////////////////////////////////////////////////////// -APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate()) { +APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } -APE::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate()) { +APE::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } APE::File::~File() { @@ -127,10 +129,12 @@ void APE::File::removeUnsupportedProperties(const StringList &properties) { } PropertyMap APE::File::setProperties(const PropertyMap &properties) { + if (ID3v1Tag()) ID3v1Tag()->setProperties(properties); return APETag(true)->setProperties(properties); + } APE::Properties *APE::File::audioProperties() const { @@ -138,6 +142,7 @@ APE::Properties *APE::File::audioProperties() const { } bool APE::File::save() { + if (readOnly()) { debug("APE::File::save() -- File is read only."); return false; @@ -206,6 +211,7 @@ bool APE::File::save() { } return true; + } ID3v1::Tag *APE::File::ID3v1Tag(bool create) { @@ -217,14 +223,16 @@ APE::Tag *APE::File::APETag(bool create) { } void APE::File::strip(int tags) { + if (tags & ID3v1) - d->tag.set(ApeID3v1Index, 0); + d->tag.set(ApeID3v1Index, nullptr); if (tags & APE) - d->tag.set(ApeAPEIndex, 0); + d->tag.set(ApeAPEIndex, nullptr); if (!ID3v1Tag()) APETag(true); + } bool APE::File::hasAPETag() const { @@ -240,6 +248,7 @@ bool APE::File::hasID3v1Tag() const { //////////////////////////////////////////////////////////////////////////////// void APE::File::read(bool readProperties) { + // Look for an ID3v2 tag d->ID3v2Location = Utils::findID3v2(this); @@ -293,4 +302,5 @@ void APE::File::read(bool readProperties) { d->properties = new Properties(this, streamLength); } + } diff --git a/3rdparty/taglib/ape/apefile.h b/3rdparty/taglib/ape/apefile.h index 33f5401b6..756ce57c8 100644 --- a/3rdparty/taglib/ape/apefile.h +++ b/3rdparty/taglib/ape/apefile.h @@ -53,29 +53,28 @@ class Tag; //! An implementation of APE metadata /*! - * This is implementation of APE metadata. - * - * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream - * properties from the file. - */ + * This is implementation of APE metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream properties from the file. + * + */ namespace APE { //! An implementation of TagLib::File with APE specific methods /*! - * This implements and provides an interface for APE files to the - * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing - * the abstract TagLib::File API as well as providing some additional - * information specific to APE files. - */ + * This implements and provides an interface for APE files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional information specific to APE files. + * + */ 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. - */ + * 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, @@ -88,140 +87,128 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { }; /*! - * Constructs an APE file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ + * Constructs an APE file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs an APE file from \a stream. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ + * Constructs an APE file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag - * or a combination of the two. - */ + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag or a combination of the two. + */ virtual Strawberry_TagLib::TagLib::Tag *tag() const; /*! - * Implements the unified property interface -- export function. - * If the file contains both an APE and an ID3v1 tag, only APE - * will be converted to the PropertyMap. - */ + * Implements the unified property interface -- export function. + * If the file contains both an APE and an ID3v1 tag, only APE will be converted to the PropertyMap. + */ PropertyMap properties() const; /*! - * Removes unsupported properties. Forwards to the actual Tag's - * removeUnsupportedProperties() function. - */ + * Removes unsupported properties. Forwards to the actual Tag's removeUnsupportedProperties() function. + */ void removeUnsupportedProperties(const StringList &properties); /*! - * Implements the unified property interface -- import function. - * Creates an APEv2 tag if necessary. A potentially existing ID3v1 - * tag will be updated as well. - */ + * Implements the unified property interface -- import function. + * Creates an APEv2 tag if necessary. + * A potentially existing ID3v1 tag will be updated as well. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the APE::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the APE::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Saves the file. - * - * \note According to the official Monkey's Audio SDK, an APE file - * can only have either ID3V1 or APE tags, so a parameter is used here. - */ + * Saves the file. + * + * \note According to the official Monkey's Audio SDK, an APE file + * can only have either ID3V1 or APE tags, so a parameter is used here. + */ virtual bool save(); /*! - * Returns a pointer to the ID3v1 tag of the file. - * - * If \a create is false (the default) this may return a null pointer - * if there is no valid ID3v1 tag. If \a create is true it will create - * an ID3v1 tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file - * on disk actually has an ID3v1 tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasID3v1Tag() - */ + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer if there is no valid ID3v1 tag. + * If \a create is true it will create an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v1 tag. + * Use hasID3v1Tag() to check if the file on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasID3v1Tag() + */ 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 - * if there is no valid APE tag. If \a create is true it will create - * an APE tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an APE tag. Use hasAPETag() to check if the file - * on disk actually has an APE tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasAPETag() - */ + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer if there is no valid APE tag. + * If \a create is true it will create an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an APE tag. + * Use hasAPETag() to check if the file on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasAPETag() + */ APE::Tag *APETag(bool create = false); /*! - * This will remove the tags that match the OR-ed together TagTypes from the - * file. By default it removes all tags. - * - * \note This will also invalidate pointers to the tags - * as their memory will be freed. - * \note In order to make the removal permanent save() still needs to be called - */ + * This will remove the tags that match the OR-ed together TagTypes from the file. + * By default it removes all tags. + * + * \note This will also invalidate pointers to the tags as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ void strip(int tags = AllTags); /*! - * Returns whether or not the file on disk actually has an APE tag. - * - * \see APETag() - */ + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ bool hasAPETag() const; /*! - * Returns whether or not the file on disk actually has an ID3v1 tag. - * - * \see ID3v1Tag() - */ + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ bool hasID3v1Tag() const; /*! - * Returns whether or not the given \a stream can be opened as an APE - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as an APE file. + * + * \note This method is designed to do a quick check. + * The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: diff --git a/3rdparty/taglib/ape/apefooter.cpp b/3rdparty/taglib/ape/apefooter.cpp index 356f31db4..ccc031fb4 100644 --- a/3rdparty/taglib/ape/apefooter.cpp +++ b/3rdparty/taglib/ape/apefooter.cpp @@ -134,10 +134,12 @@ ByteVector APE::Footer::renderFooter() const { } ByteVector APE::Footer::renderHeader() const { + if (!d->headerPresent) return ByteVector(); else return render(true); + } //////////////////////////////////////////////////////////////////////////////// @@ -145,6 +147,7 @@ ByteVector APE::Footer::renderHeader() const { //////////////////////////////////////////////////////////////////////////////// void APE::Footer::parse(const ByteVector &data) { + if (data.size() < size()) return; @@ -169,9 +172,11 @@ void APE::Footer::parse(const ByteVector &data) { d->headerPresent = flags[31]; d->footerPresent = !flags[30]; d->isHeader = flags[29]; + } ByteVector APE::Footer::render(bool isHeader) const { + ByteVector v; // add the file identifier -- "APETAGEX" @@ -206,4 +211,5 @@ ByteVector APE::Footer::render(bool isHeader) const { v.append(ByteVector::fromLongLong(0)); return v; + } diff --git a/3rdparty/taglib/ape/apefooter.h b/3rdparty/taglib/ape/apefooter.h index ed3a1cab7..9bcbf6aa1 100644 --- a/3rdparty/taglib/ape/apefooter.h +++ b/3rdparty/taglib/ape/apefooter.h @@ -37,126 +37,127 @@ namespace APE { //! An implementation of APE footers /*! - * This class implements APE footers (and headers). It attempts to follow, both - * semantically and programmatically, the structure specified in - * the APE v2.0 standard. The API is based on the properties of APE footer and - * headers specified there. - */ + * This class implements APE footers (and headers). + * It attempts to follow, both semantically and programmatically, + * the structure specified in the APE v2.0 standard. + * The API is based on the properties of APE footer and headers specified there. + * + */ class TAGLIB_EXPORT Footer { public: /*! - * Constructs an empty APE footer. - */ + * Constructs an empty APE footer. + */ Footer(); /*! - * Constructs an APE footer based on \a data. parse() is called - * immediately. - */ + * Constructs an APE footer based on \a data. parse() is called immediately. + */ Footer(const ByteVector &data); /*! - * Destroys the footer. - */ + * Destroys the footer. + */ virtual ~Footer(); /*! - * Returns the version number. (Note: This is the 1000 or 2000.) - */ + * Returns the version number. (Note: This is the 1000 or 2000.) + */ unsigned int version() const; /*! - * Returns true if a header is present in the tag. - */ + * Returns true if a header is present in the tag. + */ bool headerPresent() const; /*! - * Returns true if a footer is present in the tag. - */ + * Returns true if a footer is present in the tag. + */ bool footerPresent() const; /*! - * Returns true this is actually the header. - */ + * Returns true this is actually the header. + */ bool isHeader() const; /*! - * Sets whether the header should be rendered or not - */ + * Sets whether the header should be rendered or not + */ void setHeaderPresent(bool b) const; /*! - * Returns the number of items in the tag. - */ + * Returns the number of items in the tag. + */ unsigned int itemCount() const; /*! - * Set the item count to \a s. - * \see itemCount() - */ + * Set the item count to \a s. + * \see itemCount() + */ void setItemCount(unsigned int s); /*! - * Returns the tag size in bytes. This is the size of the frame content and footer. - * The size of the \e entire tag will be this plus the header size, if present. - * - * \see completeTagSize() - */ + * Returns the tag size in bytes. + * This is the size of the frame content and footer. + * The size of the \e entire tag will be this plus the header size, if present. + * + * \see completeTagSize() + */ unsigned int tagSize() const; /*! - * Returns the tag size, including if present, the header - * size. - * - * \see tagSize() - */ + * Returns the tag size, including if present, the header + * size. + * + * \see tagSize() + */ unsigned int completeTagSize() const; /*! - * Set the tag size to \a s. - * \see tagSize() - */ + * Set the tag size to \a s. + * \see tagSize() + */ void setTagSize(unsigned int s); /*! - * Returns the size of the footer. Presently this is always 32 bytes. - */ + * Returns the size of the footer. Presently this is always 32 bytes. + */ static unsigned int size(); /*! - * Returns the string used to identify an APE tag inside of a file. - * Presently this is always "APETAGEX". - */ + * Returns the string used to identify an APE tag inside of a file. + * Presently this is always "APETAGEX". + */ static ByteVector fileIdentifier(); /*! - * Sets the data that will be used as the footer. 32 bytes, - * starting from \a data will be used. - */ + * Sets the data that will be used as the footer. 32 bytes, + * starting from \a data will be used. + */ void setData(const ByteVector &data); /*! - * Renders the footer back to binary format. - */ + * Renders the footer back to binary format. + */ ByteVector renderFooter() const; /*! - * Renders the header corresponding to the footer. If headerPresent is - * set to false, it returns an empty ByteVector. - */ + * Renders the header corresponding to the footer. + * If headerPresent is set to false, it returns an empty ByteVector. + */ ByteVector renderHeader() const; protected: /*! - * Called by setData() to parse the footer data. It makes this information - * available through the public API. - */ + * Called by setData() to parse the footer data. + * It makes this information available through the public API. + */ void parse(const ByteVector &data); /*! - * Called by renderFooter and renderHeader - */ + * Called by renderFooter and renderHeader + */ ByteVector render(bool isHeader) const; private: diff --git a/3rdparty/taglib/ape/apeitem.cpp b/3rdparty/taglib/ape/apeitem.cpp index 5799470fa..9f6a19540 100644 --- a/3rdparty/taglib/ape/apeitem.cpp +++ b/3rdparty/taglib/ape/apeitem.cpp @@ -33,8 +33,7 @@ using namespace APE; class APE::Item::ItemPrivate { public: - ItemPrivate() : type(Text), - readOnly(false) {} + ItemPrivate() : type(Text), readOnly(false) {} Item::ItemTypes type; String key; @@ -47,8 +46,7 @@ class APE::Item::ItemPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -APE::Item::Item() : d(new ItemPrivate()) { -} +APE::Item::Item() : d(new ItemPrivate()) {} APE::Item::Item(const String &key, const String &value) : d(new ItemPrivate()) { d->key = key; @@ -61,6 +59,7 @@ APE::Item::Item(const String &key, const StringList &values) : d(new ItemPrivate } APE::Item::Item(const String &key, const ByteVector &value, bool binary) : d(new ItemPrivate()) { + d->key = key; if (binary) { d->type = Binary; @@ -69,24 +68,28 @@ APE::Item::Item(const String &key, const ByteVector &value, bool binary) : d(new else { d->text.append(value); } + } -APE::Item::Item(const Item &item) : d(new ItemPrivate(*item.d)) { -} +APE::Item::Item(const Item &item) : d(new ItemPrivate(*item.d)) {} APE::Item::~Item() { delete d; } Item &APE::Item::operator=(const Item &item) { + Item(item).swap(*this); return *this; + } void APE::Item::swap(Item &item) { + using std::swap; swap(d, item.d); + } void APE::Item::setReadOnly(bool readOnly) { @@ -114,14 +117,16 @@ ByteVector APE::Item::binaryData() const { } void APE::Item::setBinaryData(const ByteVector &value) { + d->type = Binary; d->value = value; d->text.clear(); + } ByteVector APE::Item::value() const { - // This seems incorrect as it won't be actually rendering the value to keep it - // up to date. + + // This seems incorrect as it won't be actually rendering the value to keep it up to date. return d->value; } @@ -131,30 +136,39 @@ void APE::Item::setKey(const String &key) { } void APE::Item::setValue(const String &value) { + d->type = Text; d->text = value; d->value.clear(); + } void APE::Item::setValues(const StringList &value) { + d->type = Text; d->text = value; d->value.clear(); + } void APE::Item::appendValue(const String &value) { + d->type = Text; d->text.append(value); d->value.clear(); + } void APE::Item::appendValues(const StringList &values) { + d->type = Text; d->text.append(values); d->value.clear(); + } int APE::Item::size() const { + int result = 8 + d->key.size() + 1; switch (d->type) { case Text: @@ -174,6 +188,7 @@ int APE::Item::size() const { break; } return result; + } StringList APE::Item::toStringList() const { @@ -185,13 +200,16 @@ StringList APE::Item::values() const { } String APE::Item::toString() const { + if (d->type == Text && !isEmpty()) return d->text.front(); else return String(); + } bool APE::Item::isEmpty() const { + switch (d->type) { case Text: if (d->text.isEmpty()) @@ -205,9 +223,11 @@ bool APE::Item::isEmpty() const { default: return false; } + } void APE::Item::parse(const ByteVector &data) { + // 11 bytes is the minimum size for an APE item if (data.size() < 11) { @@ -232,9 +252,11 @@ void APE::Item::parse(const ByteVector &data) { d->text = StringList(ByteVectorList::split(value, '\0'), String::UTF8); else d->value = value; + } ByteVector APE::Item::render() const { + ByteVector data; unsigned int flags = ((d->readOnly) ? 1 : 0) | (d->type << 1); ByteVector value; @@ -263,4 +285,5 @@ ByteVector APE::Item::render() const { data.append(value); return data; + } diff --git a/3rdparty/taglib/ape/apeitem.h b/3rdparty/taglib/ape/apeitem.h index f5e7fd2d1..d5cfe17dd 100644 --- a/3rdparty/taglib/ape/apeitem.h +++ b/3rdparty/taglib/ape/apeitem.h @@ -32,19 +32,18 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace APE { //! An implementation of APE-items /*! - * This class provides the features of items in the APEv2 standard. - */ + * This class provides the features of items in the APEv2 standard. + */ class TAGLIB_EXPORT Item { public: /*! - * Enum of types an Item can have. The value of 3 is reserved. - */ + * Enum of types an Item can have. The value of 3 is reserved. + */ enum ItemTypes { //! Item contains text information coded in UTF-8 Text = 0, @@ -54,62 +53,62 @@ class TAGLIB_EXPORT Item { Locator = 2 }; /*! - * Constructs an empty item. - */ + * Constructs an empty item. + */ Item(); /*! - * Constructs a text item with \a key and \a value. - */ + * Constructs a text item with \a key and \a value. + */ // BIC: Remove this, StringList has a constructor from a single string Item(const String &key, const String &value); /*! - * Constructs a text item with \a key and \a values. - */ + * Constructs a text item with \a key and \a values. + */ Item(const String &key, const StringList &values); /*! - * Constructs an item with \a key and \a value. - * If \a binary is true a Binary item will be created, otherwise \a value will be interpreted as text - */ + * Constructs an item with \a key and \a value. + * If \a binary is true a Binary item will be created, otherwise \a value will be interpreted as text + */ Item(const String &key, const ByteVector &value, bool binary); /*! - * Construct an item as a copy of \a item. - */ + * Construct an item as a copy of \a item. + */ Item(const Item &item); /*! - * Destroys the item. - */ + * Destroys the item. + */ virtual ~Item(); /*! - * Copies the contents of \a item into this item. - */ + * Copies the contents of \a item into this item. + */ Item &operator=(const Item &item); /*! - * Exchanges the content of this item by the content of \a item. - */ + * Exchanges the content of this item by the content of \a item. + */ void swap(Item &item); /*! - * Returns the key. - */ + * Returns the key. + */ String key() const; /*! - * Returns the binary value. - * If the item type is not \a Binary, always returns an empty ByteVector. - */ + * Returns the binary value. + * If the item type is not \a Binary, always returns an empty ByteVector. + */ ByteVector binaryData() const; /*! - * Set the binary value to \a value - * The item's type will also be set to \a Binary - */ + * Set the binary value to \a value + * The item's type will also be set to \a Binary + */ void setBinaryData(const ByteVector &value); #ifndef DO_NOT_DOCUMENT @@ -118,97 +117,90 @@ class TAGLIB_EXPORT Item { #endif /*! - * Sets the key for the item to \a key. - */ + * Sets the key for the item to \a key. + */ void setKey(const String &key); /*! - * Sets the text value of the item to \a value and clears any previous contents. - * - * \see toString() - */ + * Sets the text value of the item to \a value and clears any previous contents. + * + * \see toString() + */ void setValue(const String &value); /*! - * Sets the text value of the item to the list of values in \a value and clears - * any previous contents. - * - * \see toStringList() - */ + * Sets the text value of the item to the list of values in \a value and clears any previous contents. + * + * \see toStringList() + */ void setValues(const StringList &values); /*! - * Appends \a value to create (or extend) the current list of text values. - * - * \see toString() - */ + * Appends \a value to create (or extend) the current list of text values. + * + * \see toString() + */ void appendValue(const String &value); /*! - * Appends \a values to extend the current list of text values. - * - * \see toStringList() - */ + * Appends \a values to extend the current list of text values. + * + * \see toStringList() + */ void appendValues(const StringList &values); /*! - * Returns the size of the full item. - */ + * Returns the size of the full item. + */ int size() const; /*! - * Returns the value as a single string. In case of multiple strings, - * the first is returned. If the data type is not \a Text, always returns - * an empty String. - */ + * Returns the value as a single string. In case of multiple strings, the first is returned. + * If the data type is not \a Text, always returns an empty String. + */ String toString() const; - -#ifndef DO_NOT_DOCUMENT - /* Remove in next binary incompatible release */ StringList toStringList() const; -#endif /*! - * Returns the list of text values. If the data type is not \a Text, always - * returns an empty StringList. - */ + * Returns the list of text values. If the data type is not \a Text, always returns an empty StringList. + */ StringList values() const; /*! - * Render the item to a ByteVector. - */ + * Render the item to a ByteVector. + */ ByteVector render() const; /*! - * Parse the item from the ByteVector \a data. - */ + * Parse the item from the ByteVector \a data. + */ void parse(const ByteVector &data); /*! - * Set the item to read-only. - */ + * Set the item to read-only. + */ void setReadOnly(bool readOnly); /*! - * Return true if the item is read-only. - */ + * Return true if the item is read-only. + */ bool isReadOnly() const; /*! - * Sets the type of the item to \a type. - * - * \see ItemTypes - */ + * Sets the type of the item to \a type. + * + * \see ItemTypes + */ void setType(ItemTypes type); /*! - * Returns the type of the item. - */ + * Returns the type of the item. + */ ItemTypes type() const; /*! - * Returns if the item has any real content. - */ + * Returns if the item has any real content. + */ bool isEmpty() const; private: @@ -216,7 +208,6 @@ class TAGLIB_EXPORT Item { ItemPrivate *d; }; } // namespace APE - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/ape/apeproperties.cpp b/3rdparty/taglib/ape/apeproperties.cpp index 28bc2cf4f..5270fb74e 100644 --- a/3rdparty/taglib/ape/apeproperties.cpp +++ b/3rdparty/taglib/ape/apeproperties.cpp @@ -61,13 +61,7 @@ class APE::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -APE::Properties::Properties(File *, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { - debug("APE::Properties::Properties() -- This constructor is no longer used."); -} - -APE::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +APE::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { read(file, streamLength); } @@ -75,10 +69,6 @@ APE::Properties::~Properties() { delete d; } -int APE::Properties::length() const { - return lengthInSeconds(); -} - int APE::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -125,6 +115,7 @@ int headerVersion(const ByteVector &header) { } // namespace void APE::Properties::read(File *file, long streamLength) { + // First, we assume that the file pointer is set at the first descriptor. long offset = file->tell(); int version = headerVersion(file->readBlock(6)); @@ -153,9 +144,11 @@ void APE::Properties::read(File *file, long streamLength) { d->length = static_cast(length + 0.5); d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); } + } void APE::Properties::analyzeCurrent(File *file) { + // Read the descriptor file->seek(2, File::Current); const ByteVector descriptor = file->readBlock(44); @@ -188,9 +181,11 @@ void APE::Properties::analyzeCurrent(File *file) { const unsigned int blocksPerFrame = header.toUInt(4, false); const unsigned int finalFrameBlocks = header.toUInt(8, false); d->sampleFrames = (totalFrames - 1) * blocksPerFrame + finalFrameBlocks; + } void APE::Properties::analyzeOld(File *file) { + const ByteVector header = file->readBlock(26); if (header.size() < 26) { debug("APE::Properties::analyzeOld() -- MAC header is too short."); @@ -228,4 +223,5 @@ void APE::Properties::analyzeOld(File *file) { } d->bitsPerSample = fmt.toShort(26, false); + } diff --git a/3rdparty/taglib/ape/apeproperties.h b/3rdparty/taglib/ape/apeproperties.h index 71dc416ca..3bb421715 100644 --- a/3rdparty/taglib/ape/apeproperties.h +++ b/3rdparty/taglib/ape/apeproperties.h @@ -35,7 +35,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace APE { class File; @@ -43,86 +42,66 @@ class File; //! An implementation of audio property reading for APE /*! - * This reads the data from an APE stream found in the AudioProperties - * API. - */ + * This reads the data from an APE stream found in the AudioProperties API. + */ class TAGLIB_EXPORT Properties : public AudioProperties { public: - /*! - * Create an instance of APE::Properties with the data read from the - * APE::File \a file. - * - * \deprecated - */ - TAGLIB_DEPRECATED Properties(File *file, ReadStyle style = Average); /*! - * Create an instance of APE::Properties with the data read from the - * APE::File \a file. - */ + * Create an instance of APE::Properties with the data read from the APE::File \a file. + */ Properties(File *file, long streamLength, ReadStyle style = Average); /*! - * Destroys this APE::Properties instance. - */ + * Destroys this APE::Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - TAGLIB_DEPRECATED virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the number of bits per audio sample. - */ + * Returns the number of bits per audio sample. + */ int bitsPerSample() const; /*! - * Returns the total number of audio samples in file. - */ + * Returns the total number of audio samples in file. + */ unsigned int sampleFrames() const; /*! - * Returns APE version. - */ + * Returns APE version. + */ int version() const; private: diff --git a/3rdparty/taglib/ape/apetag.cpp b/3rdparty/taglib/ape/apetag.cpp index f74db48dd..df8e10596 100644 --- a/3rdparty/taglib/ape/apetag.cpp +++ b/3rdparty/taglib/ape/apetag.cpp @@ -51,7 +51,7 @@ const unsigned int MaxKeyLength = 255; bool isKeyValid(const ByteVector &key) { - const char *invalidKeys[] = { "ID3", "TAG", "OGGS", "MP+", 0 }; + const char *invalidKeys[] = { "ID3", "TAG", "OGGS", "MP+", nullptr }; // only allow printable ASCII including space (32..126) @@ -62,7 +62,7 @@ bool isKeyValid(const ByteVector &key) { } const String upperKey = String(key).upper(); - for (size_t i = 0; invalidKeys[i] != 0; ++i) { + for (size_t i = 0; invalidKeys[i] != nullptr; ++i) { if (upperKey == invalidKeys[i]) return false; } @@ -73,7 +73,7 @@ bool isKeyValid(const ByteVector &key) { class APE::Tag::TagPrivate { public: - TagPrivate() : file(0), footerLocation(0) {} + TagPrivate() : file(nullptr), footerLocation(0) {} File *file; long footerLocation; @@ -207,6 +207,7 @@ const size_t keyConversionsSize = sizeof(keyConversions) / sizeof(keyConversions } // namespace PropertyMap APE::Tag::properties() const { + PropertyMap properties; ItemListMap::ConstIterator it = itemListMap().begin(); for (; it != itemListMap().end(); ++it) { @@ -226,15 +227,19 @@ PropertyMap APE::Tag::properties() const { } } return properties; + } void APE::Tag::removeUnsupportedProperties(const StringList &properties) { + StringList::ConstIterator it = properties.begin(); for (; it != properties.end(); ++it) removeItem(*it); + } PropertyMap APE::Tag::setProperties(const PropertyMap &origProps) { + PropertyMap properties(origProps); // make a local copy that can be modified // see comment in properties() @@ -280,10 +285,12 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps) { } bool APE::Tag::checkKey(const String &key) { + if (key.size() < MinKeyLength || key.size() > MaxKeyLength) return false; return isKeyValid(key.data(String::UTF8)); + } APE::Footer *APE::Tag::footer() const { @@ -299,6 +306,7 @@ void APE::Tag::removeItem(const String &key) { } void APE::Tag::addValue(const String &key, const String &value, bool replace) { + if (replace) removeItem(key); @@ -314,24 +322,29 @@ void APE::Tag::addValue(const String &key, const String &value, bool replace) { it->second.appendValue(value); else setItem(key, Item(key, value)); + } void APE::Tag::setData(const String &key, const ByteVector &value) { + removeItem(key); if (value.isEmpty()) return; setItem(key, Item(key, value, true)); + } void APE::Tag::setItem(const String &key, const Item &item) { + if (!checkKey(key)) { debug("APE::Tag::setItem() - Couldn't set an item due to an invalid key."); return; } d->itemListMap[key.upper()] = item; + } bool APE::Tag::isEmpty() const { @@ -343,6 +356,7 @@ bool APE::Tag::isEmpty() const { //////////////////////////////////////////////////////////////////////////////// void APE::Tag::read() { + if (d->file && d->file->isValid()) { d->file->seek(d->footerLocation); @@ -355,9 +369,11 @@ void APE::Tag::read() { d->file->seek(d->footerLocation + Footer::size() - d->footer.tagSize()); parse(d->file->readBlock(d->footer.tagSize() - Footer::size())); } + } ByteVector APE::Tag::render() const { + ByteVector data; unsigned int itemCount = 0; @@ -371,9 +387,11 @@ ByteVector APE::Tag::render() const { d->footer.setHeaderPresent(true); return d->footer.renderHeader() + data + d->footer.renderFooter(); + } void APE::Tag::parse(const ByteVector &data) { + // 11 bytes is the minimum size for an APE item if (data.size() < 11) @@ -404,4 +422,5 @@ void APE::Tag::parse(const ByteVector &data) { pos += keyLength + valLegnth + 9; } + } diff --git a/3rdparty/taglib/ape/apetag.h b/3rdparty/taglib/ape/apetag.h index 95e2bef91..c742f4196 100644 --- a/3rdparty/taglib/ape/apetag.h +++ b/3rdparty/taglib/ape/apetag.h @@ -46,10 +46,10 @@ namespace APE { class Footer; /*! - * A mapping between a list of item names, or keys, and the associated item. - * - * \see APE::Tag::itemListMap() - */ + * A mapping between a list of item names, or keys, and the associated item. + * + * \see APE::Tag::itemListMap() + */ typedef Map ItemListMap; @@ -58,31 +58,29 @@ typedef Map ItemListMap; class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { public: /*! - * Create an APE tag with default values. - */ + * Create an APE tag with default values. + */ Tag(); /*! - * Create an APE tag and parse the data in \a file with APE footer at - * \a tagOffset. - */ + * Create an APE tag and parse the data in \a file with APE footer at + * \a tagOffset. + */ Tag(Strawberry_TagLib::TagLib::File *file, long footerLocation); /*! - * Destroys this Tag instance. - */ + * Destroys this Tag instance. + */ virtual ~Tag(); /*! - * Renders the in memory values to a ByteVector suitable for writing to - * the file. - */ + * Renders the in memory values to a ByteVector suitable for writing to the file. + */ ByteVector render() const; /*! - * Returns the string "APETAGEX" suitable for usage in locating the tag in a - * file. - */ + * Returns the string "APETAGEX" suitable for usage in locating the tag in a file. + */ static ByteVector fileIdentifier(); // Reimplementations. @@ -104,94 +102,91 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { virtual void setTrack(unsigned int i); /*! - * Implements the unified tag dictionary interface -- export function. - * APE tags are perfectly compatible with the dictionary interface because they - * support both arbitrary tag names and multiple values. Currently only - * APE items of type *Text* are handled by the dictionary interface; all *Binary* - * and *Locator* items will be put into the unsupportedData list and can be - * deleted on request using removeUnsupportedProperties(). The same happens - * to Text items if their key is invalid for PropertyMap (which should actually - * never happen). - * - * The only conversion done by this export function is to rename the APE tags - * TRACK to TRACKNUMBER, YEAR to DATE, and ALBUM ARTIST to ALBUMARTIST, respectively, - * in order to be compliant with the names used in other formats. - */ + * Implements the unified tag dictionary interface -- export function. + * APE tags are perfectly compatible with the dictionary interface because they + * support both arbitrary tag names and multiple values. + * Currently only APE items of type *Text* are handled by the dictionary interface; all *Binary* + * and *Locator* items will be put into the unsupportedData list and can be + * deleted on request using removeUnsupportedProperties(). + * The same happens to Text items if their key is invalid for PropertyMap (which should actually never happen). + * + * The only conversion done by this export function is to rename the APE tags + * TRACK to TRACKNUMBER, YEAR to DATE, and ALBUM ARTIST to ALBUMARTIST, + * respectively, in order to be compliant with the names used in other formats. + */ PropertyMap properties() const; void removeUnsupportedProperties(const StringList &properties); /*! - * Implements the unified tag dictionary interface -- import function. The same - * comments as for the export function apply; additionally note that the APE tag - * specification requires keys to have between 2 and 16 printable ASCII characters - * with the exception of the fixed strings "ID3", "TAG", "OGGS", and "MP+". - */ + * Implements the unified tag dictionary interface -- import function. + * The same comments as for the export function apply; additionally note that the APE tag + * specification requires keys to have between 2 and 16 printable ASCII characters + * with the exception of the fixed strings "ID3", "TAG", "OGGS", and "MP+". + */ PropertyMap setProperties(const PropertyMap &); /*! - * Check if the given String is a valid APE tag key. - */ + * Check if the given String is a valid APE tag key. + */ static bool checkKey(const String &); /*! - * Returns a pointer to the tag's footer. - */ + * Returns a pointer to the tag's footer. + */ Footer *footer() const; /*! - * Returns a reference to the item list map. This is an ItemListMap of - * all of the items in the tag. - * - * This is the most powerful structure for accessing the items of the tag. - * - * APE tags are case-insensitive, all keys in this map have been converted - * to upper case. - * - * \warning You should not modify this data structure directly, instead - * use setItem() and removeItem(). - */ + * Returns a reference to the item list map. + * This is an ItemListMap of all of the items in the tag. + * + * This is the most powerful structure for accessing the items of the tag. + * + * APE tags are case-insensitive, all keys in this map have been converted + * to upper case. + * + * \warning You should not modify this data structure directly, instead + * use setItem() and removeItem(). + */ const ItemListMap &itemListMap() const; /*! - * Removes the \a key item from the tag - */ + * Removes the \a key item from the tag + */ void removeItem(const String &key); /*! - * Adds to the text item specified by \a key the data \a value. If \a replace - * is true, then all of the other values on the same key will be removed - * first. If a binary item exists for \a key it will be removed first. - */ + * Adds to the text item specified by \a key the data \a value. + * If \a replace is true, then all of the other values on the same key will be removed first. + * If a binary item exists for \a key it will be removed first. + */ void addValue(const String &key, const String &value, bool replace = true); /*! - * Set the binary data for the key specified by \a item to \a value - * This will convert the item to type \a Binary if it isn't already and - * all of the other values on the same key will be removed. - */ + * Set the binary data for the key specified by \a item to \a value + * This will convert the item to type \a Binary if it isn't already and all of the other values on the same key will be removed. + */ void setData(const String &key, const ByteVector &value); /*! - * Sets the \a key item to the value of \a item. If an item with the \a key is already - * present, it will be replaced. - */ + * Sets the \a key item to the value of \a item. If an item with the \a key is already present, it will be replaced. + */ void setItem(const String &key, const Item &item); /*! - * Returns true if the tag does not contain any data. - */ + * Returns true if the tag does not contain any data. + */ bool isEmpty() const; protected: /*! - * Reads from the file specified in the constructor. - */ + * Reads from the file specified in the constructor. + */ void read(); /*! - * Parses the body of the tag in \a data. - */ + * Parses the body of the tag in \a data. + */ void parse(const ByteVector &data); private: diff --git a/3rdparty/taglib/asf/asfattribute.cpp b/3rdparty/taglib/asf/asfattribute.cpp index 2c9e162fd..337571f76 100644 --- a/3rdparty/taglib/asf/asfattribute.cpp +++ b/3rdparty/taglib/asf/asfattribute.cpp @@ -35,10 +35,7 @@ using namespace Strawberry_TagLib::TagLib; class ASF::Attribute::AttributePrivate : public RefCounter { public: - AttributePrivate() : pictureValue(ASF::Picture::fromInvalid()), - numericValue(0), - stream(0), - language(0) {} + AttributePrivate() : pictureValue(ASF::Picture::fromInvalid()), numericValue(0), stream(0), language(0) {} AttributeTypes type; String stringValue; ByteVector byteVectorValue; @@ -146,6 +143,7 @@ ASF::Picture ASF::Attribute::toPicture() const { } String ASF::Attribute::parse(ASF::File &f, int kind) { + unsigned int size, nameLength; String name; d->pictureValue = Picture::fromInvalid(); @@ -214,9 +212,11 @@ String ASF::Attribute::parse(ASF::File &f, int kind) { } return name; + } int ASF::Attribute::dataSize() const { + switch (d->type) { case WordType: return 2; @@ -236,9 +236,11 @@ int ASF::Attribute::dataSize() const { return d->byteVectorValue.size(); } return 0; + } ByteVector ASF::Attribute::render(const String &name, int kind) const { + ByteVector data; switch (d->type) { @@ -296,6 +298,7 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const { } return data; + } int ASF::Attribute::language() const { diff --git a/3rdparty/taglib/asf/asfattribute.h b/3rdparty/taglib/asf/asfattribute.h index aaa32a0df..42f187fdb 100644 --- a/3rdparty/taglib/asf/asfattribute.h +++ b/3rdparty/taglib/asf/asfattribute.h @@ -33,7 +33,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ASF { class File; @@ -42,8 +41,8 @@ class Picture; class TAGLIB_EXPORT Attribute { public: /*! - * Enum of types an Attribute can have. - */ + * Enum of types an Attribute can have. + */ enum AttributeTypes { UnicodeType = 0, BytesType = 1, @@ -55,131 +54,131 @@ class TAGLIB_EXPORT Attribute { }; /*! - * Constructs an empty attribute. - */ + * Constructs an empty attribute. + */ Attribute(); /*! - * Constructs an attribute with \a key and a UnicodeType \a value. - */ + * Constructs an attribute with \a key and a UnicodeType \a value. + */ Attribute(const String &value); /*! - * Constructs an attribute with \a key and a BytesType \a value. - */ + * Constructs an attribute with \a key and a BytesType \a value. + */ Attribute(const ByteVector &value); /*! - * Constructs an attribute with \a key and a Picture \a value. - * - * This attribute is compatible with the ID3 frame, APIC. The ID3 specification for the APIC frame stipulates that, - * while there may be any number of APIC frames associated with a file, - * only one may be of type 1 and only one may be of type 2. - * - * The specification also states that the description of the picture can be no longer than 64 characters, but can be empty. - * WM/Picture attributes added with TagLib::ASF are not automatically validated to conform to ID3 specifications. - * You must add code in your application to perform validations if you want to maintain complete compatibility with ID3. - */ + * Constructs an attribute with \a key and a Picture \a value. + * + * This attribute is compatible with the ID3 frame, APIC. The ID3 specification for the APIC frame stipulates that, + * while there may be any number of APIC frames associated with a file, + * only one may be of type 1 and only one may be of type 2. + * + * The specification also states that the description of the picture can be no longer than 64 characters, but can be empty. + * WM/Picture attributes added with TagLib::ASF are not automatically validated to conform to ID3 specifications. + * You must add code in your application to perform validations if you want to maintain complete compatibility with ID3. + */ Attribute(const Picture &value); /*! - * Constructs an attribute with \a key and a DWordType \a value. - */ + * Constructs an attribute with \a key and a DWordType \a value. + */ Attribute(unsigned int value); /*! - * Constructs an attribute with \a key and a QWordType \a value. - */ + * Constructs an attribute with \a key and a QWordType \a value. + */ Attribute(unsigned long long value); /*! - * Constructs an attribute with \a key and a WordType \a value. - */ + * Constructs an attribute with \a key and a WordType \a value. + */ Attribute(unsigned short value); /*! - * Constructs an attribute with \a key and a BoolType \a value. - */ + * Constructs an attribute with \a key and a BoolType \a value. + */ Attribute(bool value); /*! - * Construct an attribute as a copy of \a other. - */ + * Construct an attribute as a copy of \a other. + */ Attribute(const Attribute &item); /*! - * Copies the contents of \a other into this item. - */ + * Copies the contents of \a other into this item. + */ Attribute &operator=(const Attribute &other); /*! - * Exchanges the content of the Attribute by the content of \a other. - */ + * Exchanges the content of the Attribute by the content of \a other. + */ void swap(Attribute &other); /*! - * Destroys the attribute. - */ + * Destroys the attribute. + */ virtual ~Attribute(); /*! - * Returns type of the value. - */ + * Returns type of the value. + */ AttributeTypes type() const; /*! - * Returns the BoolType \a value. - */ + * Returns the BoolType \a value. + */ unsigned short toBool() const; /*! - * Returns the WordType \a value. - */ + * Returns the WordType \a value. + */ unsigned short toUShort() const; /*! - * Returns the DWordType \a value. - */ + * Returns the DWordType \a value. + */ unsigned int toUInt() const; /*! - * Returns the QWordType \a value. - */ + * Returns the QWordType \a value. + */ unsigned long long toULongLong() const; /*! - * Returns the UnicodeType \a value. - */ + * Returns the UnicodeType \a value. + */ String toString() const; /*! - * Returns the BytesType \a value. - */ + * Returns the BytesType \a value. + */ ByteVector toByteVector() const; /*! - * Returns the Picture \a value. - */ + * Returns the Picture \a value. + */ Picture toPicture() const; /*! - * Returns the language number, or 0 is no stream number was set. - */ + * Returns the language number, or 0 is no stream number was set. + */ int language() const; /*! - * Sets the language number. - */ + * Sets the language number. + */ void setLanguage(int value); /*! - * Returns the stream number, or 0 is no stream number was set. - */ + * Returns the stream number, or 0 is no stream number was set. + */ int stream() const; /*! - * Sets the stream number. - */ + * Sets the stream number. + */ void setStream(int value); #ifndef DO_NOT_DOCUMENT @@ -199,7 +198,6 @@ class TAGLIB_EXPORT Attribute { AttributePrivate *d; }; } // namespace ASF - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/asf/asffile.cpp b/3rdparty/taglib/asf/asffile.cpp index e64d7a2e0..112e731cf 100644 --- a/3rdparty/taglib/asf/asffile.cpp +++ b/3rdparty/taglib/asf/asffile.cpp @@ -50,13 +50,13 @@ class ASF::File::FilePrivate { class MetadataLibraryObject; FilePrivate() : headerSize(0), - tag(0), - properties(0), - contentDescriptionObject(0), - extendedContentDescriptionObject(0), - headerExtensionObject(0), - metadataObject(0), - metadataLibraryObject(0) { + tag(nullptr), + properties(nullptr), + contentDescriptionObject(nullptr), + extendedContentDescriptionObject(nullptr), + headerExtensionObject(nullptr), + metadataObject(nullptr), + metadataLibraryObject(nullptr) { objects.setAutoDelete(true); } @@ -177,19 +177,20 @@ class ASF::File::FilePrivate::CodecListObject : public ASF::File::FilePrivate::B }; void ASF::File::FilePrivate::BaseObject::parse(ASF::File *file, unsigned int size) { + data.clear(); if (size > 24 && size <= (unsigned int)(file->length())) data = file->readBlock(size - 24); else data = ByteVector(); + } ByteVector ASF::File::FilePrivate::BaseObject::render(ASF::File * /*file*/) { return guid() + ByteVector::fromLongLong(data.size() + 24, false) + data; } -ASF::File::FilePrivate::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid) { -} +ASF::File::FilePrivate::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid) {} ByteVector ASF::File::FilePrivate::UnknownObject::guid() const { return myGuid; @@ -200,6 +201,7 @@ ByteVector ASF::File::FilePrivate::FilePropertiesObject::guid() const { } void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, unsigned int size) { + BaseObject::parse(file, size); if (data.size() < 64) { debug("ASF::File::FilePrivate::FilePropertiesObject::parse() -- data is too short."); @@ -209,6 +211,7 @@ void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, unsign const long long duration = data.toLongLong(40, false); const long long preroll = data.toLongLong(56, false); file->d->properties->setLengthInMilliseconds(static_cast(duration / 10000.0 - preroll + 0.5)); + } ByteVector ASF::File::FilePrivate::StreamPropertiesObject::guid() const { @@ -216,6 +219,7 @@ ByteVector ASF::File::FilePrivate::StreamPropertiesObject::guid() const { } void ASF::File::FilePrivate::StreamPropertiesObject::parse(ASF::File *file, unsigned int size) { + BaseObject::parse(file, size); if (data.size() < 70) { debug("ASF::File::FilePrivate::StreamPropertiesObject::parse() -- data is too short."); @@ -227,6 +231,7 @@ void ASF::File::FilePrivate::StreamPropertiesObject::parse(ASF::File *file, unsi file->d->properties->setSampleRate(data.toUInt(58, false)); file->d->properties->setBitrate(static_cast(data.toUInt(62, false) * 8.0 / 1000.0 + 0.5)); file->d->properties->setBitsPerSample(data.toUShort(68, false)); + } ByteVector ASF::File::FilePrivate::ContentDescriptionObject::guid() const { @@ -234,6 +239,7 @@ ByteVector ASF::File::FilePrivate::ContentDescriptionObject::guid() const { } void ASF::File::FilePrivate::ContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/) { + const int titleLength = readWORD(file); const int artistLength = readWORD(file); const int copyrightLength = readWORD(file); @@ -244,9 +250,11 @@ void ASF::File::FilePrivate::ContentDescriptionObject::parse(ASF::File *file, un file->d->tag->setCopyright(readString(file, copyrightLength)); file->d->tag->setComment(readString(file, commentLength)); file->d->tag->setRating(readString(file, ratingLength)); + } ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *file) { + const ByteVector v1 = renderString(file->d->tag->title()); const ByteVector v2 = renderString(file->d->tag->artist()); const ByteVector v3 = renderString(file->d->tag->copyright()); @@ -264,6 +272,7 @@ ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *f data.append(v4); data.append(v5); return BaseObject::render(file); + } ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::guid() const { @@ -271,19 +280,23 @@ ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::guid() cons } void ASF::File::FilePrivate::ExtendedContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/) { + int count = readWORD(file); while (count--) { ASF::Attribute attribute; String name = attribute.parse(*file); file->d->tag->addAttribute(name, attribute); } + } ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::render(ASF::File *file) { + data.clear(); data.append(ByteVector::fromShort(attributeData.size(), false)); data.append(attributeData.toByteVector("")); return BaseObject::render(file); + } ByteVector ASF::File::FilePrivate::MetadataObject::guid() const { @@ -291,19 +304,23 @@ ByteVector ASF::File::FilePrivate::MetadataObject::guid() const { } void ASF::File::FilePrivate::MetadataObject::parse(ASF::File *file, unsigned int /*size*/) { + int count = readWORD(file); while (count--) { ASF::Attribute attribute; String name = attribute.parse(*file, 1); file->d->tag->addAttribute(name, attribute); } + } ByteVector ASF::File::FilePrivate::MetadataObject::render(ASF::File *file) { + data.clear(); data.append(ByteVector::fromShort(attributeData.size(), false)); data.append(attributeData.toByteVector("")); return BaseObject::render(file); + } ByteVector ASF::File::FilePrivate::MetadataLibraryObject::guid() const { @@ -311,19 +328,23 @@ ByteVector ASF::File::FilePrivate::MetadataLibraryObject::guid() const { } void ASF::File::FilePrivate::MetadataLibraryObject::parse(ASF::File *file, unsigned int /*size*/) { + int count = readWORD(file); while (count--) { ASF::Attribute attribute; String name = attribute.parse(*file, 2); file->d->tag->addAttribute(name, attribute); } + } ByteVector ASF::File::FilePrivate::MetadataLibraryObject::render(ASF::File *file) { + data.clear(); data.append(ByteVector::fromShort(attributeData.size(), false)); data.append(attributeData.toByteVector("")); return BaseObject::render(file); + } ASF::File::FilePrivate::HeaderExtensionObject::HeaderExtensionObject() { @@ -335,6 +356,7 @@ ByteVector ASF::File::FilePrivate::HeaderExtensionObject::guid() const { } void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsigned int /*size*/) { + file->seek(18, File::Current); long long dataSize = readDWORD(file); long long dataPos = 0; @@ -366,15 +388,18 @@ void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsig objects.append(obj); dataPos += size; } + } ByteVector ASF::File::FilePrivate::HeaderExtensionObject::render(ASF::File *file) { + data.clear(); for (List::ConstIterator it = objects.begin(); it != objects.end(); ++it) { data.append((*it)->render(file)); } data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt(data.size(), false) + data; return BaseObject::render(file); + } ByteVector ASF::File::FilePrivate::CodecListObject::guid() const { @@ -382,6 +407,7 @@ ByteVector ASF::File::FilePrivate::CodecListObject::guid() const { } void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned int size) { + BaseObject::parse(file, size); if (data.size() <= 20) { debug("ASF::File::FilePrivate::CodecListObject::parse() -- data is too short."); @@ -428,6 +454,7 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in break; } } + } //////////////////////////////////////////////////////////////////////////////// @@ -435,24 +462,24 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in //////////////////////////////////////////////////////////////////////////////// bool ASF::File::isSupported(IOStream *stream) { + // An ASF file has to start with the designated GUID. const ByteVector id = Utils::readHeader(stream, 16, false); return (id == headerGuid); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -ASF::File::File(FileName file, bool, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate()) { +ASF::File::File(FileName file, bool, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate()) { if (isOpen()) read(); } -ASF::File::File(IOStream *stream, bool, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate()) { +ASF::File::File(IOStream *stream, bool, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate()) { if (isOpen()) read(); } @@ -482,6 +509,7 @@ ASF::Properties *ASF::File::audioProperties() const { } bool ASF::File::save() { + if (readOnly()) { debug("ASF::File::save() -- File is read only."); return false; @@ -562,6 +590,7 @@ bool ASF::File::save() { d->headerSize = data.size() + 30; return true; + } //////////////////////////////////////////////////////////////////////////////// @@ -569,6 +598,7 @@ bool ASF::File::save() { //////////////////////////////////////////////////////////////////////////////// void ASF::File::read() { + if (!isValid()) return; @@ -594,8 +624,8 @@ void ASF::File::read() { } seek(2, Current); - FilePrivate::FilePropertiesObject *filePropertiesObject = 0; - FilePrivate::StreamPropertiesObject *streamPropertiesObject = 0; + FilePrivate::FilePropertiesObject *filePropertiesObject = nullptr; + FilePrivate::StreamPropertiesObject *streamPropertiesObject = nullptr; for (int i = 0; i < numObjects; i++) { const ByteVector guid = readBlock(16); if (guid.size() != 16) { @@ -648,4 +678,5 @@ void ASF::File::read() { setValid(false); return; } + } diff --git a/3rdparty/taglib/asf/asffile.h b/3rdparty/taglib/asf/asffile.h index 7a45cbccb..6ffb9f4e3 100644 --- a/3rdparty/taglib/asf/asffile.h +++ b/3rdparty/taglib/asf/asffile.h @@ -39,88 +39,84 @@ namespace TagLib { namespace ASF { /*! - * This implements and provides an interface for ASF files to the - * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing - * the abstract TagLib::File API as well as providing some additional - * information specific to ASF files. - */ + * This implements and provides an interface for ASF files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to ASF files. + */ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { public: /*! - * Constructs an ASF file from \a file. - * - * \note In the current implementation, both \a readProperties and - * \a propertiesStyle are ignored. The audio properties are always - * read. - */ + * Constructs an ASF file from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs an ASF file from \a stream. - * - * \note In the current implementation, both \a readProperties and - * \a propertiesStyle are ignored. The audio properties are always - * read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - */ - File(IOStream *stream, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs an ASF file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns a pointer to the ASF tag of the file. - * - * ASF::Tag implements the tag interface, so this serves as the - * reimplementation of TagLib::File::tag(). - * - * \note The Tag is still owned by the ASF::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - */ + * Returns a pointer to the ASF tag of the file. + * + * ASF::Tag implements the tag interface, so this serves as the + * reimplementation of TagLib::File::tag(). + * + * \note The Tag is still owned by the ASF::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ virtual Tag *tag() const; /*! - * Implements the unified property interface -- export function. - */ + * Implements the unified property interface -- export function. + */ PropertyMap properties() const; /*! - * Removes unsupported properties. Forwards to the actual Tag's - * removeUnsupportedProperties() function. - */ + * Removes unsupported properties. Forwards to the actual Tag's removeUnsupportedProperties() function. + */ void removeUnsupportedProperties(const StringList &properties); /*! - * Implements the unified property interface -- import function. - */ + * Implements the unified property interface -- import function. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the ASF audio properties for this file. - */ + * Returns the ASF audio properties for this file. + */ virtual Properties *audioProperties() const; /*! - * Save the file. - * - * This returns true if the save was successful. - */ + * Save the file. + * + * This returns true if the save was successful. + */ virtual bool save(); /*! - * Returns whether or not the given \a stream can be opened as an ASF - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as an ASF file. + * + * \note This method is designed to do a quick check. The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: diff --git a/3rdparty/taglib/asf/asfpicture.cpp b/3rdparty/taglib/asf/asfpicture.cpp index de0eb23d7..4464efd58 100644 --- a/3rdparty/taglib/asf/asfpicture.cpp +++ b/3rdparty/taglib/asf/asfpicture.cpp @@ -76,7 +76,7 @@ ASF::Picture::Type ASF::Picture::type() const { return d->type; } -void ASF::Picture::setType(const ASF::Picture::Type& t) { +void ASF::Picture::setType(const ASF::Picture::Type &t) { d->type = t; } @@ -92,7 +92,7 @@ ByteVector ASF::Picture::picture() const { return d->picture; } -void ASF::Picture::setPicture(const ByteVector& p) { +void ASF::Picture::setPicture(const ByteVector &p) { d->picture = p; } @@ -113,6 +113,7 @@ void ASF::Picture::swap(Picture& other) { } ByteVector ASF::Picture::render() const { + if (!isValid()) return ByteVector(); @@ -121,9 +122,11 @@ ByteVector ASF::Picture::render() const { renderString(d->mimeType) + renderString(d->description) + d->picture; + } -void ASF::Picture::parse(const ByteVector& bytes) { +void ASF::Picture::parse(const ByteVector &bytes) { + d->valid = false; if (bytes.size() < 9) return; @@ -152,11 +155,13 @@ void ASF::Picture::parse(const ByteVector& bytes) { d->picture = bytes.mid(pos, dataLen); d->valid = true; - return; + } ASF::Picture ASF::Picture::fromInvalid() { + Picture ret; ret.d->valid = false; return ret; + } diff --git a/3rdparty/taglib/asf/asfpicture.h b/3rdparty/taglib/asf/asfpicture.h index 07fa284df..854390d83 100644 --- a/3rdparty/taglib/asf/asfpicture.h +++ b/3rdparty/taglib/asf/asfpicture.h @@ -38,18 +38,17 @@ namespace ASF { //! An ASF attached picture interface implementation /*! - * This is an implementation of ASF attached pictures interface. Pictures may be - * included in attributes, one per WM/Picture attribute (but there may be multiple WM/Picture - * attribute in a single tag). These pictures are usually in either JPEG or - * PNG format. - * \see Attribute::toPicture() - * \see Attribute::Attribute(const Picture& picture) - */ + * This is an implementation of ASF attached pictures interface. + * Pictures may be included in attributes, one per WM/Picture attribute (but there may be multiple WM/Picture attribute in a single tag). + * These pictures are usually in either JPEG or PNG format. + * \see Attribute::toPicture() + * \see Attribute::Attribute(const Picture& picture) + */ class TAGLIB_EXPORT Picture { public: /*! - * This describes the function or content of the picture. - */ + * This describes the function or content of the picture. + */ enum Type { //! A type not enumerated below Other = 0x00, @@ -96,112 +95,109 @@ class TAGLIB_EXPORT Picture { }; /*! - * Constructs an empty picture. - */ + * Constructs an empty picture. + */ Picture(); /*! - * Construct an picture as a copy of \a other. - */ + * Construct an picture as a copy of \a other. + */ Picture(const Picture& other); /*! - * Destroys the picture. - */ + * Destroys the picture. + */ virtual ~Picture(); /*! - * Copies the contents of \a other into this picture. - */ + * Copies the contents of \a other into this picture. + */ Picture& operator=(const Picture& other); /*! - * Exchanges the content of the Picture by the content of \a other. - */ + * Exchanges the content of the Picture by the content of \a other. + */ void swap(Picture& other); /*! - * Returns true if Picture stores valid picture - */ + * Returns true if Picture stores valid picture + */ bool isValid() const; /*! - * Returns the mime type of the image. This should in most cases be - * "image/png" or "image/jpeg". - * \see setMimeType(const String &) - * \see picture() - * \see setPicture(const ByteArray&) - */ + * Returns the mime type of the image. This should in most cases be "image/png" or "image/jpeg". + * \see setMimeType(const String &) + * \see picture() + * \see setPicture(const ByteArray&) + */ String mimeType() const; /*! - * Sets the mime type of the image. This should in most cases be - * "image/png" or "image/jpeg". - * \see setMimeType(const String &) - * \see picture() - * \see setPicture(const ByteArray&) - */ + * Sets the mime type of the image. This should in most cases be "image/png" or "image/jpeg". + * \see setMimeType(const String &) + * \see picture() + * \see setPicture(const ByteArray&) + */ void setMimeType(const String& value); /*! - * Returns the type of the image. - * - * \see Type - * \see setType() - */ + * Returns the type of the image. + * + * \see Type + * \see setType() + */ Type type() const; /*! - * Sets the type for the image. - * - * \see Type - * \see type() - */ + * Sets the type for the image. + * + * \see Type + * \see type() + */ void setType(const ASF::Picture::Type& t); /*! - * Returns a text description of the image. - * - * \see setDescription() - */ + * Returns a text description of the image. + * + * \see setDescription() + */ String description() const; /*! - * Sets a textual description of the image to \a desc. - * - * \see description() - */ + * Sets a textual description of the image to \a desc. + * + * \see description() + */ void setDescription(const String& desc); /*! - * Returns the image data as a ByteVector. - * - * \note ByteVector has a data() method that returns a const char * which - * should make it easy to export this data to external programs. - * - * \see setPicture() - * \see mimeType() - */ + * Returns the image data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which should make it easy to export this data to external programs. + * + * \see setPicture() + * \see mimeType() + */ 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. - * - * \see picture() - * \see mimeType() - * \see setMimeType() - */ + * Sets the image data to \a p. + * \a p should be of the type specified in this frame's mime-type specification. + * + * \see picture() + * \see mimeType() + * \see setMimeType() + */ void setPicture(const ByteVector& p); /*! - * Returns picture as binary raw data \a value - */ + * Returns picture as binary raw data \a value + */ ByteVector render() const; /*! - * Returns picture as binary raw data \a value - */ + * Returns picture as binary raw data \a value + */ int dataSize() const; #ifndef DO_NOT_DOCUMENT diff --git a/3rdparty/taglib/asf/asfproperties.cpp b/3rdparty/taglib/asf/asfproperties.cpp index 843da75e9..1b8e69c34 100644 --- a/3rdparty/taglib/asf/asfproperties.cpp +++ b/3rdparty/taglib/asf/asfproperties.cpp @@ -62,10 +62,6 @@ ASF::Properties::~Properties() { delete d; } -int ASF::Properties::length() const { - return lengthInSeconds(); -} - int ASF::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -135,6 +131,7 @@ void ASF::Properties::setBitsPerSample(int value) { } void ASF::Properties::setCodec(int value) { + switch (value) { case 0x0160: d->codec = WMA1; @@ -152,6 +149,7 @@ void ASF::Properties::setCodec(int value) { d->codec = Unknown; break; } + } void ASF::Properties::setCodecName(const String &value) { diff --git a/3rdparty/taglib/asf/asfproperties.h b/3rdparty/taglib/asf/asfproperties.h index 29100d0d7..47090b926 100644 --- a/3rdparty/taglib/asf/asfproperties.h +++ b/3rdparty/taglib/asf/asfproperties.h @@ -32,129 +32,116 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ASF { //! An implementation of ASF audio properties class TAGLIB_EXPORT Properties : public AudioProperties { public: /*! - * Audio codec types can be used in ASF file. - */ + * Audio codec types can be used in ASF file. + */ enum Codec { /*! - * Couldn't detect the codec. - */ + * Couldn't detect the codec. + */ Unknown = 0, /*! - * Windows Media Audio 1 - */ + * Windows Media Audio 1 + */ WMA1, /*! - * Windows Media Audio 2 or above - */ + * Windows Media Audio 2 or above + */ WMA2, /*! - * Windows Media Audio 9 Professional - */ + * Windows Media Audio 9 Professional + */ WMA9Pro, /*! - * Windows Media Audio 9 Lossless - */ + * Windows Media Audio 9 Lossless + */ WMA9Lossless, }; /*! - * Creates an instance of ASF::Properties. - */ + * Creates an instance of ASF::Properties. + */ Properties(); /*! - * Destroys this ASF::Properties instance. - */ + * Destroys this ASF::Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the number of bits per audio sample. - */ + * Returns the number of bits per audio sample. + */ int bitsPerSample() const; /*! - * Returns the codec used in the file. - * - * \see codecName() - * \see codecDescription() - */ + * Returns the codec used in the file. + * + * \see codecName() + * \see codecDescription() + */ Codec codec() const; /*! - * Returns the concrete codec name, for example "Windows Media Audio 9.1" - * used in the file if available, otherwise an empty string. - * - * \see codec() - * \see codecDescription() - */ + * Returns the concrete codec name, for example "Windows Media Audio 9.1" used in the file if available, otherwise an empty string. + * + * \see codec() + * \see codecDescription() + */ String codecName() const; /*! - * Returns the codec description, typically contains the encoder settings, - * for example "VBR Quality 50, 44kHz, stereo 1-pass VBR" if available, - * otherwise an empty string. - * - * \see codec() - * \see codecName() - */ + * Returns the codec description, typically contains the encoder settings, + * for example "VBR Quality 50, 44kHz, stereo 1-pass VBR" if available, otherwise an empty string. + * + * \see codec() + * \see codecName() + */ String codecDescription() const; /*! - * Returns whether or not the file is encrypted. - */ + * Returns whether or not the file is encrypted. + */ bool isEncrypted() const; #ifndef DO_NOT_DOCUMENT diff --git a/3rdparty/taglib/asf/asftag.cpp b/3rdparty/taglib/asf/asftag.cpp index 7f7ca7977..41bb59c00 100644 --- a/3rdparty/taglib/asf/asftag.cpp +++ b/3rdparty/taglib/asf/asftag.cpp @@ -38,8 +38,7 @@ class ASF::Tag::TagPrivate { AttributeListMap attributeListMap; }; -ASF::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), - d(new TagPrivate()) { +ASF::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) { } ASF::Tag::~Tag() { @@ -55,9 +54,11 @@ String ASF::Tag::artist() const { } String ASF::Tag::album() const { + if (d->attributeListMap.contains("WM/AlbumTitle")) return d->attributeListMap["WM/AlbumTitle"][0].toString(); return String(); + } String ASF::Tag::copyright() const { @@ -73,12 +74,15 @@ String ASF::Tag::rating() const { } unsigned int ASF::Tag::year() const { + if (d->attributeListMap.contains("WM/Year")) return d->attributeListMap["WM/Year"][0].toString().toInt(); return 0; + } unsigned int ASF::Tag::track() const { + if (d->attributeListMap.contains("WM/TrackNumber")) { const ASF::Attribute attr = d->attributeListMap["WM/TrackNumber"][0]; if (attr.type() == ASF::Attribute::DWordType) @@ -89,12 +93,15 @@ unsigned int ASF::Tag::track() const { if (d->attributeListMap.contains("WM/Track")) return d->attributeListMap["WM/Track"][0].toUInt(); return 0; + } String ASF::Tag::genre() const { + if (d->attributeListMap.contains("WM/Genre")) return d->attributeListMap["WM/Genre"][0].toString(); return String(); + } void ASF::Tag::setTitle(const String &value) { @@ -133,11 +140,7 @@ void ASF::Tag::setTrack(unsigned int value) { setAttribute("WM/TrackNumber", String::number(value)); } -ASF::AttributeListMap &ASF::Tag::attributeListMap() { - return d->attributeListMap; -} - -const ASF::AttributeListMap &ASF::Tag::attributeListMap() const { +const ASF::AttributeListMap ASF::Tag::attributeListMap() const { return d->attributeListMap; } @@ -154,9 +157,11 @@ ASF::AttributeList ASF::Tag::attribute(const String &name) const { } void ASF::Tag::setAttribute(const String &name, const Attribute &attribute) { + AttributeList value; value.append(attribute); d->attributeListMap.insert(name, value); + } void ASF::Tag::setAttribute(const String &name, const AttributeList &values) { @@ -164,19 +169,23 @@ void ASF::Tag::setAttribute(const String &name, const AttributeList &values) { } void ASF::Tag::addAttribute(const String &name, const Attribute &attribute) { + if (d->attributeListMap.contains(name)) { d->attributeListMap[name].append(attribute); } else { setAttribute(name, attribute); } + } bool ASF::Tag::isEmpty() const { + return Strawberry_TagLib::TagLib::Tag::isEmpty() && copyright().isEmpty() && rating().isEmpty() && d->attributeListMap.isEmpty(); + } namespace { @@ -224,16 +233,19 @@ const char *keyTranslation[][2] = { const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]); String translateKey(const String &key) { + for (size_t i = 0; i < keyTranslationSize; ++i) { if (key == keyTranslation[i][0]) return keyTranslation[i][1]; } return String(); + } } // namespace PropertyMap ASF::Tag::properties() const { + PropertyMap props; if (!d->title.isEmpty()) { @@ -271,15 +283,19 @@ PropertyMap ASF::Tag::properties() const { } } return props; + } void ASF::Tag::removeUnsupportedProperties(const StringList &props) { + StringList::ConstIterator it = props.begin(); for (; it != props.end(); ++it) d->attributeListMap.erase(*it); + } PropertyMap ASF::Tag::setProperties(const PropertyMap &props) { + static Map reverseKeyMap; if (reverseKeyMap.isEmpty()) { int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]); @@ -339,4 +355,5 @@ PropertyMap ASF::Tag::setProperties(const PropertyMap &props) { } return ignoredProps; + } diff --git a/3rdparty/taglib/asf/asftag.h b/3rdparty/taglib/asf/asftag.h index 8a8786e6a..d3d935cf6 100644 --- a/3rdparty/taglib/asf/asftag.h +++ b/3rdparty/taglib/asf/asftag.h @@ -50,150 +50,135 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { virtual ~Tag(); /*! - * Returns the track name. - */ + * Returns the track name. + */ virtual String title() const; /*! - * Returns the artist name. - */ + * Returns the artist name. + */ virtual String artist() const; /*! - * Returns the album name; if no album name is present in the tag - * String::null will be returned. - */ + * Returns the album name; if no album name is present in the tag String::null will be returned. + */ virtual String album() const; /*! - * Returns the track comment. - */ + * Returns the track comment. + */ virtual String comment() const; /*! - * Returns the genre name; if no genre is present in the tag String::null - * will be returned. - */ + * Returns the genre name; if no genre is present in the tag String::null will be returned. + */ virtual String genre() const; /*! - * Returns the rating. - */ + * Returns the rating. + */ virtual String rating() const; /*! - * Returns the genre name; if no genre is present in the tag String::null - * will be returned. - */ + * Returns the genre name; if no genre is present in the tag String::null will be returned. + */ virtual String copyright() const; /*! - * Returns the year; if there is no year set, this will return 0. - */ + * Returns the year; if there is no year set, this will return 0. + */ virtual unsigned int year() const; /*! - * Returns the track number; if there is no track number set, this will - * return 0. - */ + * Returns the track number; if there is no track number set, this will return 0. + */ virtual unsigned int track() const; /*! - * Sets the title to \a s. - */ + * Sets the title to \a s. + */ virtual void setTitle(const String &s); /*! - * Sets the artist to \a s. - */ + * Sets the artist to \a s. + */ virtual void setArtist(const String &s); /*! - * Sets the album to \a s. If \a s is String::null then this value will be - * cleared. - */ + * Sets the album to \a s. If \a s is String::null then this value will be cleared. + */ virtual void setAlbum(const String &s); /*! - * Sets the comment to \a s. - */ + * Sets the comment to \a s. + */ virtual void setComment(const String &s); /*! - * Sets the rating to \a s. - */ + * Sets the rating to \a s. + */ virtual void setRating(const String &s); /*! - * Sets the copyright to \a s. - */ + * Sets the copyright to \a s. + */ virtual void setCopyright(const String &s); /*! - * Sets the genre to \a s. - */ + * Sets the genre to \a s. + */ virtual void setGenre(const String &s); /*! - * Sets the year to \a i. If \a s is 0 then this value will be cleared. - */ + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ virtual void setYear(unsigned int i); /*! - * Sets the track to \a i. If \a s is 0 then this value will be cleared. - */ + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ virtual void setTrack(unsigned int i); /*! - * Returns true if the tag does not contain any data. This should be - * reimplemented in subclasses that provide more than the basic tagging - * abilities in this class. - */ + * Returns true if the tag does not contain any data. + * This should be reimplemented in subclasses that provide more than the basic tagging abilities in this class. + */ virtual bool isEmpty() const; /*! - * \deprecated - */ - AttributeListMap &attributeListMap(); + * Returns a reference to the item list map. This is an AttributeListMap of all of the items in the tag. + */ + const AttributeListMap attributeListMap() const; /*! - * Returns a reference to the item list map. This is an AttributeListMap of - * all of the items in the tag. - */ - // BIC: return by value - const AttributeListMap &attributeListMap() const; - - /*! - * \return True if a value for \a attribute is currently set. - */ + * \return True if a value for \a attribute is currently set. + */ bool contains(const String &name) const; /*! - * Removes the \a key attribute from the tag - */ + * Removes the \a key attribute from the tag + */ void removeItem(const String &name); /*! - * \return The list of values for the key \a name, or an empty list if no - * values have been set. - */ + * \return The list of values for the key \a name, or an empty list if no values have been set. + */ AttributeList attribute(const String &name) const; /*! - * Sets the \a key attribute to the value of \a attribute. If an attribute - * with the \a key is already present, it will be replaced. - */ + * Sets the \a key attribute to the value of \a attribute. If an attribute with the \a key is already present, it will be replaced. + */ void setAttribute(const String &name, const Attribute &attribute); /*! - * Sets multiple \a values to the key \a name. - */ + * Sets multiple \a values to the key \a name. + */ void setAttribute(const String &name, const AttributeList &values); /*! - * Sets the \a key attribute to the value of \a attribute. If an attribute - * with the \a key is already present, it will be added to the list. - */ + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be added to the list. + */ void addAttribute(const String &name, const Attribute &attribute); PropertyMap properties() const; diff --git a/3rdparty/taglib/audioproperties.cpp b/3rdparty/taglib/audioproperties.cpp index 87deebf29..792f44747 100644 --- a/3rdparty/taglib/audioproperties.cpp +++ b/3rdparty/taglib/audioproperties.cpp @@ -89,8 +89,7 @@ class AudioProperties::AudioPropertiesPrivate { // public methods //////////////////////////////////////////////////////////////////////////////// -AudioProperties::~AudioProperties() { -} +AudioProperties::~AudioProperties() {} int AudioProperties::lengthInSeconds() const { VIRTUAL_FUNCTION_WORKAROUND(lengthInSeconds, 0) @@ -104,5 +103,4 @@ int AudioProperties::lengthInMilliseconds() const { // protected methods //////////////////////////////////////////////////////////////////////////////// -AudioProperties::AudioProperties(ReadStyle) : d(0) { -} +AudioProperties::AudioProperties(ReadStyle) : d(nullptr) {} diff --git a/3rdparty/taglib/audioproperties.h b/3rdparty/taglib/audioproperties.h index cacb62230..74d650dc4 100644 --- a/3rdparty/taglib/audioproperties.h +++ b/3rdparty/taglib/audioproperties.h @@ -34,21 +34,20 @@ namespace TagLib { //! A simple, abstract interface to common audio properties /*! - * The values here are common to most audio formats. For more specific, codec - * dependent values, please see see the subclasses APIs. This is meant to - * compliment the TagLib::File and TagLib::Tag APIs in providing a simple + * The values here are common to most audio formats. + * For more specific, codec dependent values, please see see the subclasses APIs. + * This is meant to compliment the TagLib::File and TagLib::Tag APIs in providing a simple * interface that is sufficient for most applications. */ class TAGLIB_EXPORT AudioProperties { public: /*! - * Reading audio properties from a file can sometimes be very time consuming - * and for the most accurate results can often involve reading the entire - * file. Because in many situations speed is critical or the accuracy of the - * values is not particularly important this allows the level of desired - * accuracy to be set. - */ + * Reading audio properties from a file can sometimes be very time consuming + * and for the most accurate results can often involve reading the entire file. + * Because in many situations speed is critical or the accuracy of the values + * is not particularly important this allows the level of desired accuracy to be set. + */ enum ReadStyle { //! Read as little of the file as possible Fast, @@ -59,57 +58,55 @@ class TAGLIB_EXPORT AudioProperties { }; /*! - * Destroys this AudioProperties instance. - */ + * Destroys this AudioProperties instance. + */ virtual ~AudioProperties(); /*! - * Returns the length of the file in seconds. - */ - virtual int length() const = 0; + * Returns the length of the file in seconds. + */ + //virtual int length() const = 0; /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the most appropriate bit rate for the file in kb/s. For constant - * bitrate formats this is simply the bitrate of the file. For variable - * bitrate formats this is either the average or nominal bitrate. - */ + * Returns the most appropriate bit rate for the file in kb/s. For constant bitrate formats this is simply the bitrate of the file. + * For variable bitrate formats this is either the average or nominal bitrate. + */ virtual int bitrate() const = 0; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const = 0; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const = 0; protected: /*! - * Construct an audio properties instance. This is protected as this class - * should not be instantiated directly, but should be instantiated via its - * subclasses and can be fetched from the FileRef or File APIs. - * - * \see ReadStyle - */ + * Construct an audio properties instance. + * This is protected as this class should not be instantiated directly, + * but should be instantiated via its subclasses and can be fetched from the FileRef or File APIs. + * + * \see ReadStyle + */ AudioProperties(ReadStyle style); private: diff --git a/3rdparty/taglib/dsdiff/dsdiffdiintag.cpp b/3rdparty/taglib/dsdiff/dsdiffdiintag.cpp index aed84c1c4..7a620e4f8 100644 --- a/3rdparty/taglib/dsdiff/dsdiffdiintag.cpp +++ b/3rdparty/taglib/dsdiff/dsdiffdiintag.cpp @@ -76,42 +76,44 @@ unsigned int DSDIFF::DIIN::Tag::track() const { } void DSDIFF::DIIN::Tag::setTitle(const String &title) { + if (title.isNull() || title.isEmpty()) d->title = String(); else d->title = title; + } void DSDIFF::DIIN::Tag::setArtist(const String &artist) { + if (artist.isNull() || artist.isEmpty()) d->artist = String(); else d->artist = artist; + } -void DSDIFF::DIIN::Tag::setAlbum(const String &) { -} +void DSDIFF::DIIN::Tag::setAlbum(const String &) {} -void DSDIFF::DIIN::Tag::setComment(const String &) { -} +void DSDIFF::DIIN::Tag::setComment(const String &) {} -void DSDIFF::DIIN::Tag::setGenre(const String &) { -} +void DSDIFF::DIIN::Tag::setGenre(const String &) {} -void DSDIFF::DIIN::Tag::setYear(unsigned int) { -} +void DSDIFF::DIIN::Tag::setYear(unsigned int) {} -void DSDIFF::DIIN::Tag::setTrack(unsigned int) { -} +void DSDIFF::DIIN::Tag::setTrack(unsigned int) {} PropertyMap DSDIFF::DIIN::Tag::properties() const { + PropertyMap properties; properties["TITLE"] = d->title; properties["ARTIST"] = d->artist; return properties; + } PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps) { + PropertyMap properties(origProps); properties.removeEmpty(); StringList oneValueSet; @@ -140,4 +142,5 @@ PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps) { } return properties; + } diff --git a/3rdparty/taglib/dsdiff/dsdiffdiintag.h b/3rdparty/taglib/dsdiff/dsdiffdiintag.h index f129281a4..66c2eb221 100644 --- a/3rdparty/taglib/dsdiff/dsdiffdiintag.h +++ b/3rdparty/taglib/dsdiff/dsdiffdiintag.h @@ -30,109 +30,103 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace DSDIFF { - namespace DIIN { /*! - * Tags from the Edited Master Chunk Info - * - * Only Title and Artist tags are supported - */ + * Tags from the Edited Master Chunk Info + * + * Only Title and Artist tags are supported + */ + class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { public: Tag(); virtual ~Tag(); /*! - * Returns the track name; if no track name is present in the tag - * String() will be returned. - */ + * Returns the track name; if no track name is present in the tag String() will be returned. + */ String title() const; /*! - * Returns the artist name; if no artist name is present in the tag - * String() will be returned. - */ + * Returns the artist name; if no artist name is present in the tag String() will be returned. + */ String artist() const; /*! - * Not supported. Therefore always returns String(). - */ + * Not supported. Therefore always returns String(). + */ String album() const; /*! - * Not supported. Therefore always returns String(). - */ + * Not supported. Therefore always returns String(). + */ String comment() const; /*! - * Not supported. Therefore always returns String(). - */ + * Not supported. Therefore always returns String(). + */ String genre() const; /*! - * Not supported. Therefore always returns 0. - */ + * Not supported. Therefore always returns 0. + */ unsigned int year() const; /*! - * Not supported. Therefore always returns 0. - */ + * Not supported. Therefore always returns 0. + */ unsigned int track() const; /*! - * Sets the title to \a title. If \a title is String() then this - * value will be cleared. - */ + * Sets the title to \a title. If \a title is String() then this value will be cleared. + */ void setTitle(const String &title); /*! - * Sets the artist to \a artist. If \a artist is String() then this - * value will be cleared. - */ + * Sets the artist to \a artist. If \a artist is String() then this value will be cleared. + */ void setArtist(const String &artist); /*! - * Not supported and therefore ignored. - */ + * Not supported and therefore ignored. + */ void setAlbum(const String &album); /*! - * Not supported and therefore ignored. - */ + * Not supported and therefore ignored. + */ void setComment(const String &comment); /*! - * Not supported and therefore ignored. - */ + * Not supported and therefore ignored. + */ void setGenre(const String &genre); /*! - * Not supported and therefore ignored. - */ + * Not supported and therefore ignored. + */ void setYear(unsigned int year); /*! - * Not supported and therefore ignored. - */ + * Not supported and therefore ignored. + */ void setTrack(unsigned int track); /*! - * Implements the unified property interface -- export function. - * Since the DIIN tag is very limited, the exported map is as well. - */ + * Implements the unified property interface -- export function. + * Since the DIIN tag is very limited, the exported map is as well. + */ PropertyMap properties() const; /*! - * Implements the unified property interface -- import function. - * Because of the limitations of the DIIN file tag, any tags besides - * TITLE and ARTIST, will be - * returned. Additionally, if the map contains tags with multiple values, - * all but the first will be contained in the returned map of unsupported - * properties. - */ + * Implements the unified property interface -- import function. + * Because of the limitations of the DIIN file tag, any tags besides + * TITLE and ARTIST, will be returned. + * Additionally, if the map contains tags with multiple values, + * all but the first will be contained in the returned map of unsupported properties. + */ PropertyMap setProperties(const PropertyMap &); private: diff --git a/3rdparty/taglib/dsdiff/dsdifffile.cpp b/3rdparty/taglib/dsdiff/dsdifffile.cpp index 1bbc2e846..41a905f11 100644 --- a/3rdparty/taglib/dsdiff/dsdifffile.cpp +++ b/3rdparty/taglib/dsdiff/dsdifffile.cpp @@ -23,6 +23,7 @@ * http://www.mozilla.org/MPL/ * ***************************************************************************/ +#include #include #include #include @@ -48,15 +49,18 @@ struct Chunk64 { typedef std::vector ChunkList; int chunkIndex(const ChunkList &chunks, const ByteVector &id) { + for (unsigned long int i = 0; i < chunks.size(); i++) { if (chunks[i].name == id) return i; } return -1; + } bool isValidChunkID(const ByteVector &name) { + if (name.size() != 4) return false; @@ -66,6 +70,7 @@ bool isValidChunkID(const ByteVector &name) { } return true; + } enum { @@ -84,7 +89,7 @@ class DSDIFF::File::FilePrivate { size(0), isID3InPropChunk(false), duplicateID3V2chunkIndex(-1), - properties(0), + properties(nullptr), id3v2TagChunkID("ID3 "), hasID3v2(false), hasDiin(false) { @@ -128,30 +133,34 @@ class DSDIFF::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool DSDIFF::File::isSupported(IOStream *stream) { + // A DSDIFF file has to start with "FRM8????????DSD ". const ByteVector id = Utils::readHeader(stream, 16, false); return (id.startsWith("FRM8") && id.containsAt("DSD ", 12)); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -DSDIFF::File::File(FileName file, bool readProperties, - Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(file) { +DSDIFF::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(file) { + d = new FilePrivate; d->endianness = BigEndian; if (isOpen()) read(readProperties, propertiesStyle); + } -DSDIFF::File::File(IOStream *stream, bool readProperties, - Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(stream) { +DSDIFF::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(stream) { + d = new FilePrivate; d->endianness = BigEndian; if (isOpen()) read(readProperties, propertiesStyle); + } DSDIFF::File::~File() { @@ -179,18 +188,22 @@ bool DSDIFF::File::hasDIINTag() const { } PropertyMap DSDIFF::File::properties() const { + if (d->hasID3v2) return d->tag.access(ID3v2Index, false)->properties(); return PropertyMap(); + } void DSDIFF::File::removeUnsupportedProperties(const StringList &unsupported) { + if (d->hasID3v2) d->tag.access(ID3v2Index, false)->removeUnsupportedProperties(unsupported); if (d->hasDiin) d->tag.access(DIINIndex, false)->removeUnsupportedProperties(unsupported); + } PropertyMap DSDIFF::File::setProperties(const PropertyMap &properties) { @@ -206,6 +219,7 @@ bool DSDIFF::File::save() { } bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version) { + if (readOnly()) { debug("DSDIFF::File::save() -- File is read only."); return false; @@ -279,9 +293,11 @@ bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version) { } return true; + } void DSDIFF::File::strip(TagTypes tags) { + if (tags & ID3v2) { removeRootChunk("ID3 "); removeRootChunk("id3 "); @@ -296,6 +312,7 @@ void DSDIFF::File::strip(TagTypes tags) { d->hasDiin = false; d->tag.set(DIINIndex, new DIIN::Tag); } + } //////////////////////////////////////////////////////////////////////////////// @@ -303,6 +320,7 @@ void DSDIFF::File::strip(TagTypes tags) { //////////////////////////////////////////////////////////////////////////////// void DSDIFF::File::removeRootChunk(unsigned int i) { + unsigned long long chunkSize = d->chunks[i].size + d->chunks[i].padding + 12; d->size -= chunkSize; @@ -316,16 +334,20 @@ void DSDIFF::File::removeRootChunk(unsigned int i) { d->chunks[r].offset = d->chunks[r - 1].offset + 12 + d->chunks[r - 1].size + d->chunks[r - 1].padding; d->chunks.erase(d->chunks.begin() + i); + } void DSDIFF::File::removeRootChunk(const ByteVector &id) { + int i = chunkIndex(d->chunks, id); if (i >= 0) removeRootChunk(i); + } void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data) { + if (data.isEmpty()) { removeRootChunk(i); return; @@ -350,9 +372,11 @@ void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data) { // Finally update the internal offsets updateRootChunksStructure(i + 1); + } void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &data) { + if (d->chunks.size() == 0) { debug("DSDIFF::File::setPropChunkData - No valid chunks found."); return; @@ -387,9 +411,11 @@ void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &da chunk.padding = (data.size() & 0x01) ? 1 : 0; d->chunks.push_back(chunk); + } void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum) { + ChunkList &childChunks = d->childChunks[childChunkNum]; // Update global size @@ -424,11 +450,11 @@ void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum) d->chunks[i].offset = d->chunks[i - 1].offset + 12 + d->chunks[i - 1].size + d->chunks[i - 1].padding; childChunks.erase(childChunks.begin() + i); + } -void DSDIFF::File::setChildChunkData(unsigned int i, - const ByteVector &data, - unsigned int childChunkNum) { +void DSDIFF::File::setChildChunkData(unsigned int i, const ByteVector &data, unsigned int childChunkNum) { + ChunkList &childChunks = d->childChunks[childChunkNum]; if (data.isEmpty()) { @@ -445,11 +471,8 @@ void DSDIFF::File::setChildChunkData(unsigned int i, // And the PROP chunk size - d->chunks[d->childChunkIndex[childChunkNum]].size += - ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding); - insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size, - d->endianness == BigEndian), - d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8); + d->chunks[d->childChunkIndex[childChunkNum]].size += ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding); + insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size, d->endianness == BigEndian), d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8); // Now update the specific chunk @@ -468,11 +491,11 @@ void DSDIFF::File::setChildChunkData(unsigned int i, // And for root chunks updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1); + } -void DSDIFF::File::setChildChunkData(const ByteVector &name, - const ByteVector &data, - unsigned int childChunkNum) { +void DSDIFF::File::setChildChunkData(const ByteVector &name, const ByteVector &data, unsigned int childChunkNum) { + ChunkList &childChunks = d->childChunks[childChunkNum]; if (childChunks.size() == 0) { @@ -530,9 +553,11 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name, chunk.padding = (data.size() & 0x01) ? 1 : 0; childChunks.push_back(chunk); + } void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk) { + for (unsigned int i = startingChunk; i < d->chunks.size(); i++) d->chunks[i].offset = d->chunks[i - 1].offset + 12 + d->chunks[i - 1].size + d->chunks[i - 1].padding; @@ -554,9 +579,11 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk) { childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12 + childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding; } } + } void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) { + bool bigEndian = (d->endianness == BigEndian); d->type = readBlock(4); @@ -856,11 +883,11 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty d->isID3InPropChunk = false; d->hasID3v2 = false; } + } -void DSDIFF::File::writeChunk(const ByteVector &name, const ByteVector &data, - unsigned long long offset, unsigned long replace, - unsigned int leadingPadding) { +void DSDIFF::File::writeChunk(const ByteVector &name, const ByteVector &data, unsigned long long offset, unsigned long replace, unsigned int leadingPadding) { + ByteVector combined; if (leadingPadding) combined.append(ByteVector(leadingPadding, '\x00')); @@ -872,4 +899,5 @@ void DSDIFF::File::writeChunk(const ByteVector &name, const ByteVector &data, combined.append('\x00'); insert(combined, offset, replace); + } diff --git a/3rdparty/taglib/dsdiff/dsdifffile.h b/3rdparty/taglib/dsdiff/dsdifffile.h index f68cdcf1d..1df808828 100644 --- a/3rdparty/taglib/dsdiff/dsdifffile.h +++ b/3rdparty/taglib/dsdiff/dsdifffile.h @@ -37,34 +37,32 @@ namespace TagLib { //! An implementation of DSDIFF metadata /*! - * This is implementation of DSDIFF metadata. - * - * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF - * chunk as well as properties from the file. - * Description of the DSDIFF format is available - * at http://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf - * DSDIFF standard does not explicitly specify the ID3V2 chunk - * It can be found at the root level, but also sometimes inside the PROP chunk - * In addition, title and artist info are stored as part of the standard - */ + * This is implementation of DSDIFF metadata. + * + * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF + * chunk as well as properties from the file. + * Description of the DSDIFF format is available at http://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf + * DSDIFF standard does not explicitly specify the ID3V2 chunk + * It can be found at the root level, but also sometimes inside the PROP chunk. + * In addition, title and artist info are stored as part of the standard + */ namespace DSDIFF { //! An implementation of TagLib::File with DSDIFF specific methods /*! - * This implements and provides an interface for DSDIFF files to the - * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing - * the abstract TagLib::File API as well as providing some additional - * information specific to DSDIFF files. - */ + * This implements and provides an interface for DSDIFF files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing the + * abstract TagLib::File API as well as providing some additional information specific to DSDIFF files. + */ 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. - */ + * 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, @@ -77,147 +75,136 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { }; /*! - * Constructs an DSDIFF file from \a file. If \a readProperties is true - * the file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(FileName file, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs an DSDIFF file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs an DSDIFF file from \a stream. If \a readProperties is true - * the file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ + * Constructs an DSDIFF file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns a pointer to a tag that is the union of the ID3v2 and DIIN - * tags. The ID3v2 tag is given priority in reading the information -- if - * requested information exists in both the ID3v2 tag and the ID3v1 tag, - * the information from the ID3v2 tag will be returned. - * - * If you would like more granular control over the content of the tags, - * with the concession of generality, use the tag-type specific calls. - * - * \note As this tag is not implemented as an ID3v2 tag or a DIIN tag, - * but a union of the two this pointer may not be cast to the specific - * tag types. - * - * \see ID3v2Tag() - * \see DIINTag() - */ + * Returns a pointer to a tag that is the union of the ID3v2 and DIIN tags. + * The ID3v2 tag is given priority in reading the information -- if requested information exists in both the ID3v2 tag and the ID3v1 tag, + * the information from the ID3v2 tag will be returned. + * + * If you would like more granular control over the content of the tags, with the concession of generality, use the tag-type specific calls. + * + * \note As this tag is not implemented as an ID3v2 tag or a DIIN tag, + * but a union of the two this pointer may not be cast to the specific tag types. + * + * \see ID3v2Tag() + * \see DIINTag() + */ virtual Tag *tag() const; /*! - * Returns the ID3V2 Tag for this file. - * - * \note This always returns a valid pointer regardless of whether or not - * the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the - * file on disk actually has an ID3v2 tag. - * - * \see hasID3v2Tag() - */ + * Returns the ID3V2 Tag for this file. + * + * \note This always returns a valid pointer regardless of whether or not the file on disk has an ID3v2 tag. + * Use hasID3v2Tag() to check if the file on disk actually has an ID3v2 tag. + * + * \see hasID3v2Tag() + */ ID3v2::Tag *ID3v2Tag(bool create = false) const; /*! - * Returns the DSDIFF DIIN Tag for this file - * - */ + * Returns the DSDIFF DIIN Tag for this file + * + */ DSDIFF::DIIN::Tag *DIINTag(bool create = false) const; /*! - * Implements the unified property interface -- export function. - * This method forwards to ID3v2::Tag::properties(). - */ + * Implements the unified property interface -- export function. + * This method forwards to ID3v2::Tag::properties(). + */ PropertyMap properties() const; void removeUnsupportedProperties(const StringList &properties); /*! - * Implements the unified property interface -- import function. - * This method forwards to ID3v2::Tag::setProperties(). - */ + * Implements the unified property interface -- import function. + * This method forwards to ID3v2::Tag::setProperties(). + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the AIFF::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the AIFF::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Save the file. If at least one tag -- ID3v1 or DIIN -- exists this - * will duplicate its content into the other tag. This returns true - * if saving was successful. - * - * If neither exists or if both tags are empty, this will strip the tags - * from the file. - * - * This is the same as calling save(AllTags); - * - * If you would like more granular control over the content of the tags, - * with the concession of generality, use paramaterized save call below. - * - * \see save(int tags) - */ + * Save the file. If at least one tag -- ID3v1 or DIIN -- exists this will duplicate its content into the other tag. + * This returns true if saving was successful. + * + * If neither exists or if both tags are empty, this will strip the tags from the file. + * + * This is the same as calling save(AllTags); + * + * If you would like more granular control over the content of the tags, + * with the concession of generality, use paramaterized save call below. + * + * \see save(int tags) + */ virtual bool save(); /*! - * Save the file. If \a strip is specified, it is possible to choose if - * tags not specified in \a tags should be stripped from the file or - * retained. With \a version, it is possible to specify whether ID3v2.4 - * or ID3v2.3 should be used. - */ + * Save the file. If \a strip is specified, + * it is possible to choose if tags not specified in \a tags should be stripped from the file or retained. + * With \a version, it is possible to specify whether ID3v2.4 or ID3v2.3 should be used. + */ bool save(TagTypes tags, StripTags strip = StripOthers, ID3v2::Version version = ID3v2::v4); /*! - * 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. - * - * \note This will update the file immediately. - */ + * 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. + * + * \note This will update the file immediately. + */ void strip(TagTypes tags = AllTags); /*! - * Returns whether or not the file on disk actually has an ID3v2 tag. - * - * \see ID3v2Tag() - */ + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ bool hasID3v2Tag() const; /*! - * Returns whether or not the file on disk actually has the DSDIFF - * title and artist tags. - * - * \see DIINTag() - */ + * Returns whether or not the file on disk actually has the DSDIFF title and artist tags. + * + * \see DIINTag() + */ bool hasDIINTag() const; /*! - * Returns whether or not the given \a stream can be opened as a DSDIFF - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as a DSDIFF file. + * + * \note This method is designed to do a quick check. The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); protected: - enum Endianness { BigEndian, - LittleEndian }; + enum Endianness { + BigEndian, + LittleEndian + }; File(FileName file, Endianness endianness); File(IOStream *stream, Endianness endianness); @@ -231,50 +218,44 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { void removeChildChunk(unsigned int i, unsigned int chunk); /*! - * Sets the data for the the specified chunk at root level to \a data. - * - * \warning This will update the file immediately. - */ + * Sets the data for the the specified chunk at root level to \a data. + * + * \warning This will update the file immediately. + */ void setRootChunkData(unsigned int i, const ByteVector &data); /*! - * Sets the data for the root-level chunk \a name to \a data. - * If a root-level chunk with the given name already exists - * it will be overwritten, otherwise it will be - * created after the existing chunks. - * - * \warning This will update the file immediately. - */ + * Sets the data for the root-level chunk \a name to \a data. + * If a root-level chunk with the given name already exists it will be overwritten, otherwise it will be created after the existing chunks. + * + * \warning This will update the file immediately. + */ void setRootChunkData(const ByteVector &name, const ByteVector &data); /*! - * Sets the data for the the specified child chunk to \a data. - * - * If data is null, then remove the chunk - * - * \warning This will update the file immediately. - */ - void setChildChunkData(unsigned int i, const ByteVector &data, - unsigned int childChunkNum); + * Sets the data for the the specified child chunk to \a data. + * + * If data is null, then remove the chunk + * + * \warning This will update the file immediately. + */ + void setChildChunkData(unsigned int i, const ByteVector &data, unsigned int childChunkNum); /*! - * Sets the data for the child chunk \a name to \a data. If a chunk with - * the given name already exists it will be overwritten, otherwise it will - * be created after the existing chunks inside child chunk. - * - * If data is null, then remove the chunks with \a name name - * - * \warning This will update the file immediately. - */ + * Sets the data for the child chunk \a name to \a data. + * If a chunk with the given name already exists it will be overwritten, otherwise it will be created after the existing chunks inside child chunk. + * + * If data is null, then remove the chunks with \a name name + * + * \warning This will update the file immediately. + */ void setChildChunkData(const ByteVector &name, const ByteVector &data, unsigned int childChunkNum); void updateRootChunksStructure(unsigned int startingChunk); void read(bool readProperties, Properties::ReadStyle propertiesStyle); - void writeChunk(const ByteVector &name, const ByteVector &data, - unsigned long long offset, unsigned long replace = 0, - unsigned int leadingPadding = 0); + void writeChunk(const ByteVector &name, const ByteVector &data, unsigned long long offset, unsigned long replace = 0, unsigned int leadingPadding = 0); class FilePrivate; FilePrivate *d; diff --git a/3rdparty/taglib/dsdiff/dsdiffproperties.cpp b/3rdparty/taglib/dsdiff/dsdiffproperties.cpp index 2f6d62cfe..c86186d86 100644 --- a/3rdparty/taglib/dsdiff/dsdiffproperties.cpp +++ b/3rdparty/taglib/dsdiff/dsdiffproperties.cpp @@ -52,11 +52,8 @@ class DSDIFF::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -DSDIFF::Properties::Properties(const unsigned int sampleRate, - const unsigned short channels, - const unsigned long long samplesCount, - const int bitrate, - ReadStyle style) : AudioProperties(style) { +DSDIFF::Properties::Properties(const unsigned int sampleRate, const unsigned short channels, const unsigned long long samplesCount, const int bitrate, ReadStyle style) : AudioProperties(style) { + d = new PropertiesPrivate; d->channels = channels; @@ -65,6 +62,7 @@ DSDIFF::Properties::Properties(const unsigned int sampleRate, d->sampleRate = sampleRate; d->bitrate = bitrate; d->length = d->sampleRate > 0 ? static_cast((d->sampleCount * 1000.0) / d->sampleRate + 0.5) : 0; + } DSDIFF::Properties::~Properties() { diff --git a/3rdparty/taglib/dsdiff/dsdiffproperties.h b/3rdparty/taglib/dsdiff/dsdiffproperties.h index 27785c5e5..bef37259d 100644 --- a/3rdparty/taglib/dsdiff/dsdiffproperties.h +++ b/3rdparty/taglib/dsdiff/dsdiffproperties.h @@ -30,7 +30,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace DSDIFF { class File; @@ -38,23 +37,19 @@ class File; //! An implementation of audio property reading for DSDIFF /*! - * This reads the data from an DSDIFF stream found in the AudioProperties - * API. - */ + * This reads the data from an DSDIFF stream found in the AudioProperties API. + */ -class TAGLIB_EXPORT Properties : public AudioProperties { +class TAGLIB_EXPORT Properties : public Strawberry_TagLib::TagLib::AudioProperties { public: /*! - * Create an instance of DSDIFF::Properties with the data read from the - * ByteVector \a data. - */ - Properties(const unsigned int sampleRate, const unsigned short channels, - const unsigned long long samplesCount, const int bitrate, - ReadStyle style); + * Create an instance of DSDIFF::Properties with the data read from the ByteVector \a data. + */ + Properties(const unsigned int sampleRate, const unsigned short channels, const unsigned long long samplesCount, const int bitrate, ReadStyle style); /*! - * Destroys this DSDIFF::Properties instance. - */ + * Destroys this DSDIFF::Properties instance. + */ virtual ~Properties(); // Reimplementations. @@ -76,6 +71,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties { class PropertiesPrivate; PropertiesPrivate *d; }; + } // namespace DSDIFF } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/dsf/dsffile.cpp b/3rdparty/taglib/dsf/dsffile.cpp index 6dfed0653..090293091 100644 --- a/3rdparty/taglib/dsf/dsffile.cpp +++ b/3rdparty/taglib/dsf/dsffile.cpp @@ -60,9 +60,11 @@ class DSF::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool DSF::File::isSupported(IOStream *stream) { + // A DSF file has to start with "DSD " const ByteVector id = Utils::readHeader(stream, 4, false); return id.startsWith("DSD "); + } //////////////////////////////////////////////////////////////////////////////// @@ -70,17 +72,18 @@ bool DSF::File::isSupported(IOStream *stream) { //////////////////////////////////////////////////////////////////////////////// DSF::File::File(FileName file, bool readProperties, - Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate()) { + Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate()) { + if (isOpen()) read(readProperties, propertiesStyle); + } -DSF::File::File(IOStream *stream, bool readProperties, - Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate()) { +DSF::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate()) { + if (isOpen()) read(readProperties, propertiesStyle); + } DSF::File::~File() { @@ -104,6 +107,7 @@ DSF::Properties *DSF::File::audioProperties() const { } bool DSF::File::save() { + if (readOnly()) { debug("DSF::File::save() -- File is read only."); return false; @@ -158,6 +162,7 @@ bool DSF::File::save() { } return true; + } //////////////////////////////////////////////////////////////////////////////// @@ -166,6 +171,7 @@ bool DSF::File::save() { void DSF::File::read(bool, Properties::ReadStyle propertiesStyle) { + // A DSF file consists of four chunks: DSD chunk, format chunk, data chunk, and metadata chunk // The file format is not chunked in the sense of a RIFF File, though @@ -223,4 +229,5 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle) { d->tag = new ID3v2::Tag(); else d->tag = new ID3v2::Tag(this, d->metadataOffset); + } diff --git a/3rdparty/taglib/dsf/dsffile.h b/3rdparty/taglib/dsf/dsffile.h index be53e34f3..98691df0f 100644 --- a/3rdparty/taglib/dsf/dsffile.h +++ b/3rdparty/taglib/dsf/dsffile.h @@ -36,80 +36,79 @@ namespace TagLib { //! An implementation of DSF metadata /*! - * This is implementation of DSF metadata. - * - * This supports an ID3v2 tag as well as properties from the file. - */ + * This is implementation of DSF metadata. + * + * This supports an ID3v2 tag as well as properties from the file. + */ namespace DSF { //! An implementation of Strawberry_TagLib::TagLib::File with DSF specific methods /*! - * This implements and provides an interface for DSF files to the - * Strawberry_TagLib::TagLib::Tag and Strawberry_TagLib::TagLib::AudioProperties interfaces by way of implementing - * the abstract Strawberry_TagLib::TagLib::File API as well as providing some additional - * information specific to DSF files. - */ + * This implements and provides an interface for DSF files to the + * Strawberry_TagLib::TagLib::Tag and Strawberry_TagLib::TagLib::AudioProperties interfaces by way of implementing + * the abstract Strawberry_TagLib::TagLib::File API as well as providing some additional information specific to DSF files. + * + */ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { public: /*! - * Constructs an DSF file from \a file. If \a readProperties is true the - * file's audio properties will also be read using \a propertiesStyle. If - * false, \a propertiesStyle is ignored. - */ + * Constructs an DSF file from \a file. + * If \a readProperties is true the file's audio properties will also be read using \a propertiesStyle. + * If false, \a propertiesStyle is ignored. + */ File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs an DSF file from \a file. If \a readProperties is true the - * file's audio properties will also be read using \a propertiesStyle. If - * false, \a propertiesStyle is ignored. - */ + * Constructs an DSF file from \a file. + * If \a readProperties is true the file's audio properties will also be read using \a propertiesStyle. + * If false, \a propertiesStyle is ignored. + */ File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the Tag for this file. - */ + * Returns the Tag for this file. + */ ID3v2::Tag *tag() const; /*! - * Implements the unified property interface -- export function. - * This method forwards to ID3v2::Tag::properties(). - */ + * Implements the unified property interface -- export function. + * This method forwards to ID3v2::Tag::properties(). + */ PropertyMap properties() const; /*! - * Implements the unified property interface -- import function. - * This method forwards to ID3v2::Tag::setProperties(). - */ + * Implements the unified property interface -- import function. + * This method forwards to ID3v2::Tag::setProperties(). + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the DSF::AudioProperties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the DSF::AudioProperties for this file. + * If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Saves the file. - */ + * Saves the file. + */ virtual bool save(); /*! - * Returns whether or not the given \a stream can be opened as a DSF - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as a DSF file. + * + * \note This method is designed to do a quick check. + * The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: diff --git a/3rdparty/taglib/dsf/dsfproperties.h b/3rdparty/taglib/dsf/dsfproperties.h index f3c2492fd..2b13c27c3 100644 --- a/3rdparty/taglib/dsf/dsfproperties.h +++ b/3rdparty/taglib/dsf/dsfproperties.h @@ -30,7 +30,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace DSF { class File; @@ -38,21 +37,19 @@ class File; //! An implementation of audio property reading for DSF /*! - * This reads the data from a DSF stream found in the AudioProperties - * API. - */ + * This reads the data from a DSF stream found in the AudioProperties API. + */ class TAGLIB_EXPORT Properties : public Strawberry_TagLib::TagLib::AudioProperties { public: /*! - * Create an instance of DSF::AudioProperties with the data read from the - * ByteVector \a data. - */ + * Create an instance of DSF::AudioProperties with the data read from the ByteVector \a data. + */ Properties(const ByteVector &data, ReadStyle style); /*! - * Destroys this DSF::AudioProperties instance. - */ + * Destroys this DSF::AudioProperties instance. + */ virtual ~Properties(); // Reimplementations. @@ -68,9 +65,15 @@ class TAGLIB_EXPORT Properties : public Strawberry_TagLib::TagLib::AudioProperti int formatID() const; /*! - * Channel type values: 1 = mono, 2 = stereo, 3 = 3 channels, - * 4 = quad, 5 = 4 channels, 6 = 5 channels, 7 = 5.1 channels - */ + * Channel type values: + * 1 = mono, + * 2 = stereo, + * 3 = 3 channels, + * 4 = quad, + * 5 = 4 channels, + * 6 = 5 channels, + * 7 = 5.1 channels + */ int channelType() const; int bitsPerSample() const; long long sampleCount() const; diff --git a/3rdparty/taglib/fileref.cpp b/3rdparty/taglib/fileref.cpp index 922bdf52e..14d954244 100644 --- a/3rdparty/taglib/fileref.cpp +++ b/3rdparty/taglib/fileref.cpp @@ -63,8 +63,8 @@ ResolverList fileTypeResolvers; // Detect the file type by user-defined resolvers. -File *detectByResolvers(FileName fileName, bool readAudioProperties, - AudioProperties::ReadStyle audioPropertiesStyle) { +File *detectByResolvers(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) { + ResolverList::ConstIterator it = fileTypeResolvers.begin(); for (; it != fileTypeResolvers.end(); ++it) { File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle); @@ -73,12 +73,13 @@ File *detectByResolvers(FileName fileName, bool readAudioProperties, } return nullptr; + } // Detect the file type based on the file extension. -File *detectByExtension(IOStream *stream, bool readAudioProperties, - AudioProperties::ReadStyle audioPropertiesStyle) { +File *detectByExtension(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) { + #ifdef _WIN32 const String s = stream->name().toString(); #else @@ -140,13 +141,14 @@ File *detectByExtension(IOStream *stream, bool readAudioProperties, return new DSF::File(stream, readAudioProperties, audioPropertiesStyle); return nullptr; + } // Detect the file type based on the actual content of the stream. -File *detectByContent(IOStream *stream, bool readAudioProperties, - AudioProperties::ReadStyle audioPropertiesStyle) { - File *file = 0; +File *detectByContent(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) { + + File *file = nullptr; if (MPEG::File::isSupported(stream)) file = new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle); @@ -191,17 +193,17 @@ File *detectByContent(IOStream *stream, bool readAudioProperties, } return nullptr; + } // Internal function that supports FileRef::create(). // This looks redundant, but necessary in order not to change the previous // behavior of FileRef::create(). -File *createInternal(FileName fileName, bool readAudioProperties, - AudioProperties::ReadStyle audioPropertiesStyle) { +File *createInternal(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) { + File *file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle); - if (file) - return file; + if (file) return file; #ifdef _WIN32 const String s = fileName.toString(); @@ -266,14 +268,13 @@ File *createInternal(FileName fileName, bool readAudioProperties, return new DSF::File(fileName, readAudioProperties, audioPropertiesStyle); return nullptr; + } } // namespace class FileRef::FileRefPrivate : public RefCounter { public: - FileRefPrivate() : RefCounter(), - file(0), - stream(0) {} + FileRefPrivate() : RefCounter(), file(nullptr), stream(nullptr) {} ~FileRefPrivate() { delete file; @@ -288,11 +289,9 @@ class FileRef::FileRefPrivate : public RefCounter { // public members //////////////////////////////////////////////////////////////////////////////// -FileRef::FileRef() : d(new FileRefPrivate()) { -} +FileRef::FileRef() : d(new FileRefPrivate()) {} -FileRef::FileRef(FileName fileName, bool readAudioProperties, - AudioProperties::ReadStyle audioPropertiesStyle) : d(new FileRefPrivate()) { +FileRef::FileRef(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) : d(new FileRefPrivate()) { parse(fileName, readAudioProperties, audioPropertiesStyle); } @@ -309,24 +308,30 @@ FileRef::FileRef(const FileRef &ref) : d(ref.d) { } FileRef::~FileRef() { + if (d->deref()) delete d; + } Tag *FileRef::tag() const { + if (isNull()) { debug("FileRef::tag() - Called without a valid file."); return nullptr; } return d->file->tag(); + } AudioProperties *FileRef::audioProperties() const { + if (isNull()) { debug("FileRef::audioProperties() - Called without a valid file."); return nullptr; } return d->file->audioProperties(); + } File *FileRef::file() const { @@ -334,20 +339,22 @@ File *FileRef::file() const { } bool FileRef::save() { + if (isNull()) { debug("FileRef::save() - Called without a valid file."); return false; } return d->file->save(); + } -const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::FileTypeResolver *resolver) // static -{ +const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::FileTypeResolver *resolver) { // static fileTypeResolvers.prepend(resolver); return resolver; } StringList FileRef::defaultFileExtensions() { + StringList l; l.append("ogg"); @@ -383,6 +390,7 @@ StringList FileRef::defaultFileExtensions() { l.append("dsdiff"); // alias for "dff" return l; + } bool FileRef::isNull() const { @@ -408,9 +416,7 @@ bool FileRef::operator!=(const FileRef &ref) const { return (ref.d->file != d->file); } -File *FileRef::create(FileName fileName, bool readAudioProperties, - AudioProperties::ReadStyle audioPropertiesStyle) // static -{ +File *FileRef::create(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) { // static return createInternal(fileName, readAudioProperties, audioPropertiesStyle); } @@ -418,8 +424,8 @@ File *FileRef::create(FileName fileName, bool readAudioProperties, // private members //////////////////////////////////////////////////////////////////////////////// -void FileRef::parse(FileName fileName, bool readAudioProperties, - AudioProperties::ReadStyle audioPropertiesStyle) { +void FileRef::parse(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) { + // Try user-defined resolvers. d->file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle); @@ -442,11 +448,12 @@ void FileRef::parse(FileName fileName, bool readAudioProperties, // Stream have to be closed here if failed to resolve file types. delete d->stream; - d->stream = 0; + d->stream = nullptr; + } -void FileRef::parse(IOStream *stream, bool readAudioProperties, - AudioProperties::ReadStyle audioPropertiesStyle) { +void FileRef::parse(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) { + // User-defined resolvers won't work with a stream. // Try to resolve file types based on the file extension. @@ -458,4 +465,5 @@ void FileRef::parse(IOStream *stream, bool readAudioProperties, // At last, try to resolve file types based on the actual content of the file. d->file = detectByContent(stream, readAudioProperties, audioPropertiesStyle); + } diff --git a/3rdparty/taglib/fileref.h b/3rdparty/taglib/fileref.h index d18aaef2b..d7efc5721 100644 --- a/3rdparty/taglib/fileref.h +++ b/3rdparty/taglib/fileref.h @@ -40,18 +40,15 @@ class Tag; //! This class provides a simple abstraction for creating and handling files /*! - * FileRef exists to provide a minimal, generic and value-based wrapper around - * a File. It is lightweight and implicitly shared, and as such suitable for - * pass-by-value use. This hides some of the uglier details of TagLib::File - * and the non-generic portions of the concrete file implementations. + * FileRef exists to provide a minimal, generic and value-based wrapper around a File. + * It is lightweight and implicitly shared, and as such suitable for pass-by-value use. + * This hides some of the uglier details of TagLib::File and the non-generic portions of the concrete file implementations. * * This class is useful in a "simple usage" situation where it is desirable - * to be able to get and set some of the tag information that is similar - * across file types. + * to be able to get and set some of the tag information that is similar across file types. * * Also note that it is probably a good idea to plug this into your mime - * type system rather than using the constructor that accepts a file name using - * the FileTypeResolver. + * type system rather than using the constructor that accepts a file name using the FileTypeResolver. * * \see FileTypeResolver * \see addFileTypeResolver() @@ -62,8 +59,7 @@ class TAGLIB_EXPORT FileRef { //! A class for pluggable file type resolution. /*! - * This class is used to add extend TagLib's very basic file name based file - * type resolution. + * This class is used to add extend TagLib's very basic file name based file type resolution. * * This can be accomplished with: * @@ -83,191 +79,177 @@ class TAGLIB_EXPORT FileRef { * * \endcode * - * Naturally a less contrived example would be slightly more complex. This - * can be used to plug in mime-type detection systems or to add new file types - * to TagLib. + * Naturally a less contrived example would be slightly more complex. + * This can be used to plug in mime-type detection systems or to add new file types to TagLib. */ class TAGLIB_EXPORT FileTypeResolver { public: virtual ~FileTypeResolver(); /*! - * This method must be overridden to provide an additional file type - * resolver. If the resolver is able to determine the file type it should - * return a valid File object; if not it should return 0. - * - * \note The created file is then owned by the FileRef and should not be - * deleted. Deletion will happen automatically when the FileRef passes - * out of scope. - */ + * This method must be overridden to provide an additional file type resolver. + * If the resolver is able to determine the file type it should return a valid File object; if not it should return 0. + * + * \note The created file is then owned by the FileRef and should not be deleted. + * Deletion will happen automatically when the FileRef passes out of scope. + */ virtual File *createFile(FileName fileName, bool readAudioProperties = true, - AudioProperties::ReadStyle - audioPropertiesStyle = AudioProperties::Average) const = 0; + AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average) const = 0; }; /*! - * Creates a null FileRef. - */ + * Creates a null FileRef. + */ FileRef(); /*! - * Create a FileRef from \a fileName. If \a readAudioProperties is true then - * the audio properties will be read using \a audioPropertiesStyle. If - * \a readAudioProperties is false then \a audioPropertiesStyle will be - * ignored. - * - * Also see the note in the class documentation about why you may not want to - * use this method in your application. - */ + * Create a FileRef from \a fileName. + * If \a readAudioProperties is true then the audio properties will be read using \a audioPropertiesStyle. + * If \a readAudioProperties is false then \a audioPropertiesStyle will be ignored. + * + * Also see the note in the class documentation about why you may not want to + * use this method in your application. + */ explicit FileRef(FileName fileName, bool readAudioProperties = true, AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average); /*! - * Construct a FileRef from an opened \a IOStream. If \a readAudioProperties - * is true then the audio properties will be read using \a audioPropertiesStyle. - * If \a readAudioProperties is false then \a audioPropertiesStyle will be - * ignored. - * - * Also see the note in the class documentation about why you may not want to - * use this method in your application. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - */ + * Construct a FileRef from an opened \a IOStream. + * If \a readAudioProperties is true then the audio properties will be read using \a audioPropertiesStyle. + * If \a readAudioProperties is false then \a audioPropertiesStyle will be ignored. + * + * Also see the note in the class documentation about why you may not want to use this method in your application. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + */ explicit FileRef(IOStream *stream, bool readAudioProperties = true, AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average); /*! - * Construct a FileRef using \a file. The FileRef now takes ownership of the - * pointer and will delete the File when it passes out of scope. - */ + * Construct a FileRef using \a file. + * The FileRef now takes ownership of the pointer and will delete the File when it passes out of scope. + */ explicit FileRef(File *file); /*! - * Make a copy of \a ref. - */ + * Make a copy of \a ref. + */ FileRef(const FileRef &ref); /*! - * Destroys this FileRef instance. - */ + * Destroys this FileRef instance. + */ virtual ~FileRef(); /*! - * Returns a pointer to represented file's tag. - * - * \warning This pointer will become invalid when this FileRef and all - * copies pass out of scope. - * - * \warning Do not cast it to any subclasses of \class Tag. - * Use tag returning methods of appropriate subclasses of \class File instead. - * - * \see File::tag() - */ + * Returns a pointer to represented file's tag. + * + * \warning This pointer will become invalid when this FileRef and all + * copies pass out of scope. + * + * \warning Do not cast it to any subclasses of \class Tag. + * Use tag returning methods of appropriate subclasses of \class File instead. + * + * \see File::tag() + */ Tag *tag() const; /*! - * Returns the audio properties for this FileRef. If no audio properties - * were read then this will returns a null pointer. - */ + * Returns the audio properties for this FileRef. + * If no audio properties were read then this will returns a null pointer. + */ AudioProperties *audioProperties() const; /*! - * Returns a pointer to the file represented by this handler class. - * - * As a general rule this call should be avoided since if you need to work - * with file objects directly, you are probably better served instantiating - * the File subclasses (i.e. MPEG::File) manually and working with their APIs. - * - * This handle exists to provide a minimal, generic and value-based - * wrapper around a File. Accessing the file directly generally indicates - * a moving away from this simplicity (and into things beyond the scope of - * FileRef). - * - * \warning This pointer will become invalid when this FileRef and all - * copies pass out of scope. - */ + * Returns a pointer to the file represented by this handler class. + * + * As a general rule this call should be avoided since if you need to work + * with file objects directly, you are probably better served instantiating + * the File subclasses (i.e. MPEG::File) manually and working with their APIs. + * + * This handle exists to provide a minimal, generic and value-based + * wrapper around a File. Accessing the file directly generally indicates + * a moving away from this simplicity (and into things beyond the scope of + * FileRef). + * + * \warning This pointer will become invalid when this FileRef and all + * copies pass out of scope. + */ File *file() const; /*! - * Saves the file. Returns true on success. - */ + * Saves the file. Returns true on success. + */ bool save(); /*! - * Adds a FileTypeResolver to the list of those used by TagLib. Each - * additional FileTypeResolver is added to the front of a list of resolvers - * that are tried. If the FileTypeResolver returns zero the next resolver - * is tried. - * - * Returns a pointer to the added resolver (the same one that's passed in -- - * this is mostly so that static initializers have something to use for - * assignment). - * - * \see FileTypeResolver - */ + * Adds a FileTypeResolver to the list of those used by TagLib. + * Each additional FileTypeResolver is added to the front of a list of resolvers that are tried. + * If the FileTypeResolver returns zero the next resolver is tried. + * + * Returns a pointer to the added resolver (the same one that's passed in -- + * this is mostly so that static initializers have something to use for assignment). + * + * \see FileTypeResolver + */ static const FileTypeResolver *addFileTypeResolver(const FileTypeResolver *resolver); /*! - * As is mentioned elsewhere in this class's documentation, the default file - * type resolution code provided by TagLib only works by comparing file - * extensions. - * - * This method returns the list of file extensions that are used by default. - * - * The extensions are all returned in lowercase, though the comparison used - * by TagLib for resolution is case-insensitive. - * - * \note This does not account for any additional file type resolvers that - * are plugged in. Also note that this is not intended to replace a proper - * mime-type resolution system, but is just here for reference. - * - * \see FileTypeResolver - */ + * As is mentioned elsewhere in this class's documentation, the default file + * type resolution code provided by TagLib only works by comparing file extensions. + * + * This method returns the list of file extensions that are used by default. + * + * The extensions are all returned in lowercase, though the comparison used + * by TagLib for resolution is case-insensitive. + * + * \note This does not account for any additional file type resolvers that + * are plugged in. Also note that this is not intended to replace a proper + * mime-type resolution system, but is just here for reference. + * + * \see FileTypeResolver + */ static StringList defaultFileExtensions(); /*! - * Returns true if the file (and as such other pointers) are null. - */ + * Returns true if the file (and as such other pointers) are null. + */ bool isNull() const; /*! - * Assign the file pointed to by \a ref to this FileRef. - */ + * Assign the file pointed to by \a ref to this FileRef. + */ FileRef &operator=(const FileRef &ref); /*! - * Exchanges the content of the FileRef by the content of \a ref. - */ + * Exchanges the content of the FileRef by the content of \a ref. + */ void swap(FileRef &ref); /*! - * Returns true if this FileRef and \a ref point to the same File object. - */ + * Returns true if this FileRef and \a ref point to the same File object. + */ bool operator==(const FileRef &ref) const; /*! - * Returns true if this FileRef and \a ref do not point to the same File - * object. - */ + * Returns true if this FileRef and \a ref do not point to the same File object. + */ bool operator!=(const FileRef &ref) const; /*! - * A simple implementation of file type guessing. If \a readAudioProperties - * is true then the audio properties will be read using - * \a audioPropertiesStyle. If \a readAudioProperties is false then - * \a audioPropertiesStyle will be ignored. - * - * \note You generally shouldn't use this method, but instead the constructor - * directly. - * - * \deprecated - */ + * A simple implementation of file type guessing. + * If \a readAudioProperties is true then the audio properties will be read using \a audioPropertiesStyle. + * If \a readAudioProperties is false then \a audioPropertiesStyle will be ignored. + * + * \note You generally shouldn't use this method, but instead the constructor directly. + * + * \deprecated + */ static File *create(FileName fileName, bool readAudioProperties = true, AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average); diff --git a/3rdparty/taglib/flac/flacfile.cpp b/3rdparty/taglib/flac/flacfile.cpp index 328cd758a..44eac5545 100644 --- a/3rdparty/taglib/flac/flacfile.cpp +++ b/3rdparty/taglib/flac/flacfile.cpp @@ -64,7 +64,7 @@ class FLAC::File::FilePrivate { ID3v2Location(-1), ID3v2OriginalSize(0), ID3v1Location(-1), - properties(0), + properties(nullptr), flacStart(0), streamStart(0), scanned(false) { @@ -97,34 +97,30 @@ class FLAC::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool FLAC::File::isSupported(IOStream *stream) { + // A FLAC file has an ID "fLaC" somewhere. An ID3v2 tag may precede. const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true); return (buffer.find("fLaC") >= 0); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate()) { +FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate(frameFactory)) { + if (isOpen()) read(readProperties); + } -FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory, - bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate(frameFactory)) { - if (isOpen()) - read(readProperties); -} +FLAC::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate(frameFactory)) { -FLAC::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory, - bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate(frameFactory)) { if (isOpen()) read(readProperties); + } FLAC::File::~File() { @@ -152,6 +148,7 @@ FLAC::Properties *FLAC::File::audioProperties() const { } bool FLAC::File::save() { + if (readOnly()) { debug("FLAC::File::save() - Cannot save to a read only file."); return false; @@ -288,6 +285,7 @@ bool FLAC::File::save() { } return true; + } ID3v2::Tag *FLAC::File::ID3v2Tag(bool create) { @@ -302,21 +300,8 @@ Ogg::XiphComment *FLAC::File::xiphComment(bool create) { return d->tag.access(FlacXiphIndex, create); } -void FLAC::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) { - d->ID3v2FrameFactory = factory; -} - -ByteVector FLAC::File::streamInfoData() { - debug("FLAC::File::streamInfoData() -- This function is obsolete. Returning an empty ByteVector."); - return ByteVector(); -} - -long FLAC::File::streamLength() { - debug("FLAC::File::streamLength() -- This function is obsolete. Returning zero."); - return 0; -} - List FLAC::File::pictureList() { + List pictures; for (BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) { Picture *picture = dynamic_cast(*it); @@ -325,6 +310,7 @@ List FLAC::File::pictureList() { } } return pictures; + } void FLAC::File::addPicture(Picture *picture) { @@ -332,15 +318,18 @@ void FLAC::File::addPicture(Picture *picture) { } void FLAC::File::removePicture(Picture *picture, bool del) { + BlockIterator it = d->blocks.find(picture); if (it != d->blocks.end()) d->blocks.erase(it); if (del) delete picture; + } void FLAC::File::removePictures() { + for (BlockIterator it = d->blocks.begin(); it != d->blocks.end();) { if (dynamic_cast(*it)) { delete *it; @@ -350,19 +339,22 @@ void FLAC::File::removePictures() { ++it; } } + } void FLAC::File::strip(int tags) { + if (tags & ID3v1) - d->tag.set(FlacID3v1Index, 0); + d->tag.set(FlacID3v1Index, nullptr); if (tags & ID3v2) - d->tag.set(FlacID3v2Index, 0); + d->tag.set(FlacID3v2Index, nullptr); if (tags & XiphComment) { xiphComment()->removeAllFields(); xiphComment()->removeAllPictures(); } + } bool FLAC::File::hasXiphComment() const { @@ -382,6 +374,7 @@ bool FLAC::File::hasID3v2Tag() const { //////////////////////////////////////////////////////////////////////////////// void FLAC::File::read(bool readProperties) { + // Look for an ID3v2 tag d->ID3v2Location = Utils::findID3v2(this); @@ -425,9 +418,11 @@ void FLAC::File::read(bool readProperties) { d->properties = new Properties(infoData, streamLength); } + } void FLAC::File::scan() { + // Scan the metadata pages if (d->scanned) @@ -494,7 +489,7 @@ void FLAC::File::scan() { return; } - MetadataBlock *block = 0; + MetadataBlock *block = nullptr; // Found the vorbis-comment if (blockType == MetadataBlock::VorbisComment) { @@ -537,4 +532,5 @@ void FLAC::File::scan() { d->streamStart = nextBlockOffset; d->scanned = true; + } diff --git a/3rdparty/taglib/flac/flacfile.h b/3rdparty/taglib/flac/flacfile.h index a870f44da..af0da76a2 100644 --- a/3rdparty/taglib/flac/flacfile.h +++ b/3rdparty/taglib/flac/flacfile.h @@ -52,31 +52,30 @@ class XiphComment; //! An implementation of FLAC metadata /*! - * This is implementation of FLAC metadata for non-Ogg FLAC files. At some - * point when Ogg / FLAC is more common there will be a similar implementation - * under the Ogg hierarchy. - * - * This supports ID3v1, ID3v2 and Xiph style comments as well as reading stream - * properties from the file. - */ + * This is implementation of FLAC metadata for non-Ogg FLAC files. At some + * point when Ogg / FLAC is more common there will be a similar implementation + * under the Ogg hierarchy. + * + * This supports ID3v1, ID3v2 and Xiph style comments as well as reading stream + * properties from the file. + */ namespace FLAC { //! An implementation of TagLib::File with FLAC specific methods /*! - * This implements and provides an interface for FLAC files to the - * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing - * the abstract TagLib::File API as well as providing some additional - * information specific to FLAC files. - */ + * This implements and provides an interface for FLAC files to the TagLib::Tag and TagLib::AudioProperties interfaces + * by way of implementing the abstract TagLib::File API as well as providing some additional information specific to FLAC files. + * + */ 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. - */ + * 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, @@ -91,247 +90,182 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { }; /*! - * Constructs a FLAC file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - * - * \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); + * Constructs an FLAC file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * If this file contains and ID3v2 tag the frames will be created using \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs an FLAC file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * If this file contains and ID3v2 tag the frames will be created using - * \a frameFactory. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ + * Constructs a FLAC file from \a stream. If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * If this file contains and ID3v2 tag the frames will be created using \a frameFactory. + * + * \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); + File(IOStream *stream, ID3v2::FrameFactory *frameFactory, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs a FLAC file from \a stream. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * If this file contains and ID3v2 tag the frames will be created using - * \a frameFactory. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - // BIC: merge with the above constructor - File(IOStream *stream, ID3v2::FrameFactory *frameFactory, - bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); - - /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the Tag for this file. This will be a union of XiphComment, - * ID3v1 and ID3v2 tags. - * - * \see ID3v2Tag() - * \see ID3v1Tag() - * \see XiphComment() - */ + * Returns the Tag for this file. This will be a union of XiphComment, ID3v1 and ID3v2 tags. + * + * \see ID3v2Tag() + * \see ID3v1Tag() + * \see XiphComment() + */ virtual Strawberry_TagLib::TagLib::Tag *tag() const; /*! - * Implements the unified property interface -- export function. - * If the file contains more than one tag (e.g. XiphComment and ID3v1), - * only the first one (in the order XiphComment, ID3v2, ID3v1) will be - * converted to the PropertyMap. - */ + * Implements the unified property interface -- export function. + * If the file contains more than one tag (e.g. XiphComment and ID3v1), only the first one (in the order XiphComment, ID3v2, ID3v1) will be converted to the PropertyMap. + */ PropertyMap properties() const; void removeUnsupportedProperties(const StringList &); /*! - * Implements the unified property interface -- import function. - * This always creates a Xiph comment, if none exists. The return value - * relates to the Xiph comment only. - * Ignores any changes to ID3v1 or ID3v2 comments since they are not allowed - * in the FLAC specification. - */ + * Implements the unified property interface -- import function. + * This always creates a Xiph comment, if none exists. The return value relates to the Xiph comment only. + * Ignores any changes to ID3v1 or ID3v2 comments since they are not allowed in the FLAC specification. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the FLAC::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the FLAC::Properties for this file. If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Save the file. This will primarily save the XiphComment, but - * will also keep any old ID3-tags up to date. If the file - * has no XiphComment, one will be constructed from the ID3-tags. - * - * This returns true if the save was successful. - */ + * Save the file. This will primarily save the XiphComment, but will also keep any old ID3-tags up to date. + * If the file has no XiphComment, one will be constructed from the ID3-tags. + * + * This returns true if the save was successful. + */ virtual bool save(); /*! - * Returns a pointer to the ID3v2 tag of the file. - * - * If \a create is false (the default) this returns a null pointer - * if there is no valid ID3v2 tag. If \a create is true it will create - * an ID3v2 tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file - * on disk actually has an ID3v2 tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasID3v2Tag() - */ + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this returns a null pointer + * if there is no valid ID3v2 tag. + * If \a create is true it will create an ID3v2 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v2 tag. + * Use hasID3v2Tag() to check if the file on disk actually has an ID3v2 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is destroyed. + * + * \see hasID3v2Tag() + */ ID3v2::Tag *ID3v2Tag(bool create = false); /*! - * Returns a pointer to the ID3v1 tag of the file. - * - * If \a create is false (the default) this returns a null pointer - * if there is no valid APE tag. If \a create is true it will create - * an APE tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file - * on disk actually has an ID3v1 tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasID3v1Tag() - */ + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this returns a null pointer if there is no valid APE tag. + * If \a create is true it will create an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v1 tag. + * Use hasID3v1Tag() to check if the file on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasID3v1Tag() + */ ID3v1::Tag *ID3v1Tag(bool create = false); /*! - * Returns a pointer to the XiphComment for the file. - * - * If \a create is false (the default) this returns a null pointer - * if there is no valid XiphComment. If \a create is true it will create - * a XiphComment if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has a XiphComment. Use hasXiphComment() to check if the - * file on disk actually has a XiphComment. - * - * \note The Tag is still owned by the FLAC::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasXiphComment() - */ + * Returns a pointer to the XiphComment for the file. + * + * If \a create is false (the default) this returns a null pointer if there is no valid XiphComment. + * If \a create is true it will create a XiphComment if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has a XiphComment. + * Use hasXiphComment() to check if the file on disk actually has a XiphComment. + * + * \note The Tag is still owned by the FLAC::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasXiphComment() + */ Ogg::XiphComment *xiphComment(bool create = false); /*! - * Set the ID3v2::FrameFactory to something other than the default. This - * can be used to specify the way that ID3v2 frames will be interpreted - * when - * - * \see ID3v2FrameFactory - * \deprecated This value should be passed in via the constructor - */ - TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); - - /*! - * Returns the block of data used by FLAC::Properties for parsing the - * stream properties. - * - * \deprecated Always returns an empty vector. - */ - TAGLIB_DEPRECATED ByteVector streamInfoData(); // BIC: remove - - /*! - * Returns the length of the audio-stream, used by FLAC::Properties for - * calculating the bitrate. - * - * \deprecated Always returns zero. - */ - TAGLIB_DEPRECATED long streamLength(); // BIC: remove - - /*! - * Returns a list of pictures attached to the FLAC file. - */ + * Returns a list of pictures attached to the FLAC file. + */ List pictureList(); /*! - * Removes an attached picture. If \a del is true the picture's memory - * will be freed; if it is false, it must be deleted by the user. - */ + * Removes an attached picture. + * If \a del is true the picture's memory will be freed; if it is false, it must be deleted by the user. + */ void removePicture(Picture *picture, bool del = true); /*! - * Remove all attached images. - */ + * Remove all attached images. + */ void removePictures(); /*! - * Add a new picture to the file. The file takes ownership of the - * picture and will handle freeing its memory. - * - * \note The file will be saved only after calling save(). - */ + * Add a new picture to the file. + * The file takes ownership of the picture and will handle freeing its memory. + * + * \note The file will be saved only after calling save(). + */ void addPicture(Picture *picture); /*! - * This will remove the tags that match the OR-ed together TagTypes from - * the file. By default it removes all tags. - * - * \warning This will also invalidate pointers to the tags as their memory - * will be freed. - * - * \note In order to make the removal permanent save() still needs to be - * called. - * - * \note This won't remove the Vorbis comment block completely. The - * vendor ID will be preserved. - */ + * This will remove the tags that match the OR-ed together TagTypes from the file. + * By default it removes all tags. + * + * \warning This will also invalidate pointers to the tags as their memory will be freed. + * + * \note In order to make the removal permanent save() still needs to be called. + * + * \note This won't remove the Vorbis comment block completely. + * The vendor ID will be preserved. + */ void strip(int tags = AllTags); /*! - * Returns whether or not the file on disk actually has a XiphComment. - * - * \see xiphComment() - */ + * Returns whether or not the file on disk actually has a XiphComment. + * + * \see xiphComment() + */ bool hasXiphComment() const; /*! - * Returns whether or not the file on disk actually has an ID3v1 tag. - * - * \see ID3v1Tag() - */ + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ bool hasID3v1Tag() const; /*! - * Returns whether or not the file on disk actually has an ID3v2 tag. - * - * \see ID3v2Tag() - */ + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ bool hasID3v2Tag() const; /*! - * Returns whether or not the given \a stream can be opened as a FLAC - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as a FLAC file. + * + * \note This method is designed to do a quick check. + * The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: diff --git a/3rdparty/taglib/flac/flacmetadatablock.cpp b/3rdparty/taglib/flac/flacmetadatablock.cpp index 70b6cedd3..30871c7af 100644 --- a/3rdparty/taglib/flac/flacmetadatablock.cpp +++ b/3rdparty/taglib/flac/flacmetadatablock.cpp @@ -34,9 +34,6 @@ class FLAC::MetadataBlock::MetadataBlockPrivate { MetadataBlockPrivate() {} }; -FLAC::MetadataBlock::MetadataBlock() { - d = 0; -} +FLAC::MetadataBlock::MetadataBlock() : d(nullptr) {} -FLAC::MetadataBlock::~MetadataBlock() { -} +FLAC::MetadataBlock::~MetadataBlock() {} diff --git a/3rdparty/taglib/flac/flacmetadatablock.h b/3rdparty/taglib/flac/flacmetadatablock.h index da5f5ce49..d3221a22a 100644 --- a/3rdparty/taglib/flac/flacmetadatablock.h +++ b/3rdparty/taglib/flac/flacmetadatablock.h @@ -32,7 +32,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace FLAC { class TAGLIB_EXPORT MetadataBlock { @@ -69,7 +68,6 @@ class TAGLIB_EXPORT MetadataBlock { }; } // namespace FLAC - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/flac/flacpicture.cpp b/3rdparty/taglib/flac/flacpicture.cpp index 1ef8e42ab..0546a0377 100644 --- a/3rdparty/taglib/flac/flacpicture.cpp +++ b/3rdparty/taglib/flac/flacpicture.cpp @@ -64,6 +64,7 @@ int FLAC::Picture::code() const { } bool FLAC::Picture::parse(const ByteVector &data) { + if (data.size() < 32) { debug("A picture block must contain at least 5 bytes."); return false; @@ -105,9 +106,11 @@ bool FLAC::Picture::parse(const ByteVector &data) { d->data = data.mid(pos, dataLength); return true; + } ByteVector FLAC::Picture::render() const { + ByteVector result; result.append(ByteVector::fromUInt(d->type)); ByteVector mimeTypeData = d->mimeType.data(String::UTF8); @@ -123,6 +126,7 @@ ByteVector FLAC::Picture::render() const { result.append(ByteVector::fromUInt(d->data.size())); result.append(d->data); return result; + } FLAC::Picture::Type FLAC::Picture::type() const { diff --git a/3rdparty/taglib/flac/flacpicture.h b/3rdparty/taglib/flac/flacpicture.h index 8ae5781dd..19b99344c 100644 --- a/3rdparty/taglib/flac/flacpicture.h +++ b/3rdparty/taglib/flac/flacpicture.h @@ -40,8 +40,8 @@ namespace FLAC { class TAGLIB_EXPORT Picture : public MetadataBlock { public: /*! - * This describes the function or content of the picture. - */ + * This describes the function or content of the picture. + */ enum Type { //! A type not enumerated below Other = 0x00, @@ -92,102 +92,100 @@ class TAGLIB_EXPORT Picture : public MetadataBlock { ~Picture(); /*! - * Returns the type of the image. - */ + * Returns the type of the image. + */ Type type() const; /*! - * Sets the type of the image. - */ + * Sets the type of the image. + */ void setType(Type type); /*! - * Returns the mime type of the image. This should in most cases be - * "image/png" or "image/jpeg". - */ + * Returns the mime type of the image. This should in most cases be "image/png" or "image/jpeg". + */ String mimeType() const; /*! - * Sets the mime type of the image. This should in most cases be - * "image/png" or "image/jpeg". - */ + * Sets the mime type of the image. This should in most cases be "image/png" or "image/jpeg". + */ void setMimeType(const String &m); /*! - * Returns a text description of the image. - */ + * Returns a text description of the image. + */ String description() const; /*! - * Sets a textual description of the image to \a desc. - */ + * Sets a textual description of the image to \a desc. + */ void setDescription(const String &desc); /*! - * Returns the width of the image. - */ + * Returns the width of the image. + */ int width() const; /*! - * Sets the width of the image. - */ + * Sets the width of the image. + */ void setWidth(int w); /*! - * Returns the height of the image. - */ + * Returns the height of the image. + */ int height() const; /*! - * Sets the height of the image. - */ + * Sets the height of the image. + */ void setHeight(int h); /*! - * Returns the color depth (in bits-per-pixel) of the image. - */ + * Returns the color depth (in bits-per-pixel) of the image. + */ int colorDepth() const; /*! - * Sets the color depth (in bits-per-pixel) of the image. - */ + * Sets the color depth (in bits-per-pixel) of the image. + */ void setColorDepth(int depth); /*! - * Returns the number of colors used on the image.. - */ + * Returns the number of colors used on the image.. + */ int numColors() const; /*! - * Sets the number of colors used on the image (for indexed images). - */ + * Sets the number of colors used on the image (for indexed images). + */ void setNumColors(int numColors); /*! - * Returns the image data. - */ + * Returns the image data. + */ ByteVector data() const; /*! - * Sets the image data. - */ + * Sets the image data. + */ void setData(const ByteVector &data); /*! - * Returns the FLAC metadata block type. - */ + * Returns the FLAC metadata block type. + */ int code() const; /*! - * Render the content to the FLAC picture block format. - */ + * Render the content to the FLAC picture block format. + */ ByteVector render() const; /*! - * Parse the picture data in the FLAC picture block format. - */ + * Parse the picture data in the FLAC picture block format. + */ bool parse(const ByteVector &rawData); private: @@ -201,7 +199,6 @@ class TAGLIB_EXPORT Picture : public MetadataBlock { typedef List PictureList; } // namespace FLAC - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/flac/flacproperties.cpp b/3rdparty/taglib/flac/flacproperties.cpp index aff061189..c19231c27 100644 --- a/3rdparty/taglib/flac/flacproperties.cpp +++ b/3rdparty/taglib/flac/flacproperties.cpp @@ -53,24 +53,14 @@ class FLAC::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +FLAC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { read(data, streamLength); } -FLAC::Properties::Properties(File *, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { - debug("FLAC::Properties::Properties() - This constructor is no longer used."); -} - FLAC::Properties::~Properties() { delete d; } -int FLAC::Properties::length() const { - return lengthInSeconds(); -} - int FLAC::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -91,10 +81,6 @@ int FLAC::Properties::bitsPerSample() const { return d->bitsPerSample; } -int FLAC::Properties::sampleWidth() const { - return bitsPerSample(); -} - int FLAC::Properties::channels() const { return d->channels; } @@ -112,6 +98,7 @@ ByteVector FLAC::Properties::signature() const { //////////////////////////////////////////////////////////////////////////////// void FLAC::Properties::read(const ByteVector &data, long streamLength) { + if (data.size() < 18) { debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes."); return; @@ -155,4 +142,5 @@ void FLAC::Properties::read(const ByteVector &data, long streamLength) { if (data.size() >= pos + 16) d->signature = data.mid(pos, 16); + } diff --git a/3rdparty/taglib/flac/flacproperties.h b/3rdparty/taglib/flac/flacproperties.h index 664e36464..d1b722aa1 100644 --- a/3rdparty/taglib/flac/flacproperties.h +++ b/3rdparty/taglib/flac/flacproperties.h @@ -39,98 +39,65 @@ class File; //! An implementation of audio property reading for FLAC /*! - * This reads the data from an FLAC stream found in the AudioProperties - * API. - */ + * This reads the data from an FLAC stream found in the AudioProperties API. + */ class TAGLIB_EXPORT Properties : public AudioProperties { public: /*! - * Create an instance of FLAC::Properties with the data read from the - * ByteVector \a data. - */ - // BIC: switch to const reference - Properties(ByteVector data, long streamLength, ReadStyle style = Average); + * Create an instance of FLAC::Properties with the data read from the ByteVector \a data. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); /*! - * Create an instance of FLAC::Properties with the data read from the - * FLAC::File \a file. - */ - // BIC: remove - Properties(File *file, ReadStyle style = Average); - - /*! - * Destroys this FLAC::Properties instance. - */ + * Destroys this FLAC::Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - TAGLIB_DEPRECATED virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the number of bits per audio sample as read from the FLAC - * identification header. - */ + * Returns the number of bits per audio sample as read from the FLAC identification header. + */ int bitsPerSample() const; /*! - * Returns the sample width as read from the FLAC identification - * header. - * - * \note This method is just an alias of bitsPerSample(). - * - * \deprecated - */ - TAGLIB_DEPRECATED int sampleWidth() const; - - /*! - * Return the number of sample frames. - */ + * Return the number of sample frames. + */ unsigned long long sampleFrames() const; /*! - * Returns the MD5 signature of the uncompressed audio stream as read - * from the stream info header. - */ + * Returns the MD5 signature of the uncompressed audio stream as read from the stream info header. + */ ByteVector signature() const; private: diff --git a/3rdparty/taglib/flac/flacunknownmetadatablock.h b/3rdparty/taglib/flac/flacunknownmetadatablock.h index d79cf6d4b..832cd9eca 100644 --- a/3rdparty/taglib/flac/flacunknownmetadatablock.h +++ b/3rdparty/taglib/flac/flacunknownmetadatablock.h @@ -33,7 +33,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace FLAC { class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock { @@ -42,28 +41,28 @@ class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock { ~UnknownMetadataBlock(); /*! - * Returns the FLAC metadata block type. - */ + * Returns the FLAC metadata block type. + */ int code() const; /*! - * Sets the FLAC metadata block type. - */ + * Sets the FLAC metadata block type. + */ void setCode(int code); /*! - * Returns the FLAC metadata block type. - */ + * Returns the FLAC metadata block type. + */ ByteVector data() const; /*! - * Sets the FLAC metadata block type. - */ + * Sets the FLAC metadata block type. + */ void setData(const ByteVector &data); /*! - * Render the content of the block. - */ + * Render the content of the block. + */ ByteVector render() const; private: @@ -75,7 +74,6 @@ class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock { }; } // namespace FLAC - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/it/itfile.cpp b/3rdparty/taglib/it/itfile.cpp index 6f1557d18..4eaf728e5 100644 --- a/3rdparty/taglib/it/itfile.cpp +++ b/3rdparty/taglib/it/itfile.cpp @@ -35,26 +35,26 @@ using namespace IT; class IT::File::FilePrivate { public: - explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle) - : tag(), properties(propertiesStyle) { - } + explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle) : tag(), properties(propertiesStyle) {} Mod::Tag tag; IT::Properties properties; }; IT::File::File(FileName file, bool readProperties, - AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(file), - d(new FilePrivate(propertiesStyle)) { + AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(file), d(new FilePrivate(propertiesStyle)) { + if (isOpen()) read(readProperties); + } IT::File::File(IOStream *stream, bool readProperties, - AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(stream), - d(new FilePrivate(propertiesStyle)) { + AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(stream), d(new FilePrivate(propertiesStyle)) { + if (isOpen()) read(readProperties); + } IT::File::~File() { @@ -78,6 +78,7 @@ IT::Properties *IT::File::audioProperties() const { } bool IT::File::save() { + if (readOnly()) { debug("IT::File::save() - Cannot save to a read only file."); return false; @@ -317,4 +318,5 @@ void IT::File::read(bool) { comment.append(message); d->tag.setComment(comment.toString("\n")); d->tag.setTrackerName("Impulse Tracker"); + } diff --git a/3rdparty/taglib/it/itfile.h b/3rdparty/taglib/it/itfile.h index e1393d4ae..80c851a8d 100644 --- a/3rdparty/taglib/it/itfile.h +++ b/3rdparty/taglib/it/itfile.h @@ -31,67 +31,63 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace IT { class TAGLIB_EXPORT File : public Mod::FileBase { public: /*! - * Constructs a Impulse Tracker file from \a file. - * - * \note In the current implementation, both \a readProperties and - * \a propertiesStyle are ignored. The audio properties are always - * read. - */ + * Constructs a Impulse Tracker file from \a file. + * + * \note In the current implementation, both \a readProperties and \a propertiesStyle are ignored. + * The audio properties are always read. + */ File(FileName file, bool readProperties = true, AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average); /*! - * Constructs a Impulse Tracker file from \a stream. - * - * \note In the current implementation, both \a readProperties and - * \a propertiesStyle are ignored. The audio properties are always - * read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - */ + * Constructs a Impulse Tracker file from \a stream. + * + * \note In the current implementation, both \a readProperties and \a propertiesStyle are ignored. + * The audio properties are always read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + */ File(IOStream *stream, bool readProperties = true, AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); Mod::Tag *tag() const; /*! - * Forwards to Mod::Tag::properties(). - * BIC: will be removed once File::toDict() is made virtual - */ + * Forwards to Mod::Tag::properties(). + * BIC: will be removed once File::toDict() is made virtual + */ PropertyMap properties() const; /*! - * Forwards to Mod::Tag::setProperties(). - * BIC: will be removed once File::setProperties() is made virtual - */ + * Forwards to Mod::Tag::setProperties(). + * BIC: will be removed once File::setProperties() is made virtual + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the IT::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the IT::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ IT::Properties *audioProperties() const; /*! - * Save the file. - * This is the same as calling save(AllTags); - * - * \note Saving Impulse Tracker tags is not supported. - */ + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving Impulse Tracker tags is not supported. + */ bool save(); @@ -104,6 +100,7 @@ class TAGLIB_EXPORT File : public Mod::FileBase { class FilePrivate; FilePrivate *d; }; + } // namespace IT } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/it/itproperties.cpp b/3rdparty/taglib/it/itproperties.cpp index bbe765228..f85f83af2 100644 --- a/3rdparty/taglib/it/itproperties.cpp +++ b/3rdparty/taglib/it/itproperties.cpp @@ -65,9 +65,7 @@ class IT::Properties::PropertiesPrivate { unsigned char pitchWheelDepth; }; -IT::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle), - d(new PropertiesPrivate()) { -} +IT::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle), d(new PropertiesPrivate()) {} IT::Properties::~Properties() { delete d; diff --git a/3rdparty/taglib/mod/modfile.cpp b/3rdparty/taglib/mod/modfile.cpp index c9db57e5b..55732f713 100644 --- a/3rdparty/taglib/mod/modfile.cpp +++ b/3rdparty/taglib/mod/modfile.cpp @@ -35,26 +35,24 @@ using namespace Mod; class Mod::File::FilePrivate { public: - explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle) - : properties(propertiesStyle) { - } + explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle) : properties(propertiesStyle) {} Mod::Tag tag; Mod::Properties properties; }; -Mod::File::File(FileName file, bool readProperties, - AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(file), - d(new FilePrivate(propertiesStyle)) { +Mod::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(file), d(new FilePrivate(propertiesStyle)) { + if (isOpen()) read(readProperties); + } -Mod::File::File(IOStream *stream, bool readProperties, - AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(stream), - d(new FilePrivate(propertiesStyle)) { +Mod::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(stream), d(new FilePrivate(propertiesStyle)) { + if (isOpen()) read(readProperties); + } Mod::File::~File() { @@ -78,6 +76,7 @@ PropertyMap Mod::File::setProperties(const PropertyMap &properties) { } bool Mod::File::save() { + if (readOnly()) { debug("Mod::File::save() - Cannot save to a read only file."); return false; @@ -96,9 +95,11 @@ bool Mod::File::save() { seek(8, Current); } return true; + } void Mod::File::read(bool) { + if (!isOpen()) return; @@ -176,4 +177,5 @@ void Mod::File::read(bool) { READ_BYTE(d->properties.setLengthInPatterns); d->tag.setComment(comment.toString("\n")); + } diff --git a/3rdparty/taglib/mod/modfile.h b/3rdparty/taglib/mod/modfile.h index 37ce9cff4..342e4f98e 100644 --- a/3rdparty/taglib/mod/modfile.h +++ b/3rdparty/taglib/mod/modfile.h @@ -35,66 +35,58 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace Mod { class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::Mod::FileBase { public: /*! - * Constructs a Protracker file from \a file. - * - * \note In the current implementation, both \a readProperties and - * \a propertiesStyle are ignored. The audio properties are always - * read. - */ - File(FileName file, bool readProperties = true, - AudioProperties::ReadStyle propertiesStyle = - AudioProperties::Average); + * Constructs a Protracker file from \a file. + * + * \note In the current implementation, both \a readProperties and \a propertiesStyle are ignored. + * The audio properties are always read. + */ + File(FileName file, bool readProperties = true, AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average); /*! - * Constructs a Protracker file from \a stream. - * - * \note In the current implementation, both \a readProperties and - * \a propertiesStyle are ignored. The audio properties are always - * read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - */ - File(IOStream *stream, bool readProperties = true, - AudioProperties::ReadStyle propertiesStyle = - AudioProperties::Average); + * Constructs a Protracker file from \a stream. + * + * \note In the current implementation, both \a readProperties and \a propertiesStyle are ignored. + * The audio properties are always read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); Mod::Tag *tag() const; /*! - * Implements the unified property interface -- export function. - * Forwards to Mod::Tag::properties(). - */ + * Implements the unified property interface -- export function. + * Forwards to Mod::Tag::properties(). + */ PropertyMap properties() const; /*! - * Implements the unified property interface -- import function. - * Forwards to Mod::Tag::setProperties(). - */ + * Implements the unified property interface -- import function. + * Forwards to Mod::Tag::setProperties(). + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the Mod::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the Mod::Properties for this file. If no audio properties were read then this will return a null pointer. + */ Mod::Properties *audioProperties() const; /*! - * Save the file. - * This is the same as calling save(AllTags); - * - * \note Saving Protracker tags is not supported. - */ + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving Protracker tags is not supported. + */ bool save(); private: @@ -108,7 +100,6 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::Mod::FileBase { }; } // namespace Mod - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mod/modfilebase.cpp b/3rdparty/taglib/mod/modfilebase.cpp index 36a0bfe13..06de3183a 100644 --- a/3rdparty/taglib/mod/modfilebase.cpp +++ b/3rdparty/taglib/mod/modfilebase.cpp @@ -30,11 +30,9 @@ using namespace Strawberry_TagLib::TagLib; using namespace Mod; -Mod::FileBase::FileBase(FileName file) : Strawberry_TagLib::TagLib::File(file) { -} +Mod::FileBase::FileBase(FileName file) : Strawberry_TagLib::TagLib::File(file) {} -Mod::FileBase::FileBase(IOStream *stream) : Strawberry_TagLib::TagLib::File(stream) { -} +Mod::FileBase::FileBase(IOStream *stream) : Strawberry_TagLib::TagLib::File(stream) {} void Mod::FileBase::writeString(const String &s, unsigned long size, char padding) { ByteVector data(s.data(String::Latin1)); @@ -43,6 +41,7 @@ void Mod::FileBase::writeString(const String &s, unsigned long size, char paddin } bool Mod::FileBase::readString(String &s, unsigned long size) { + ByteVector data(readBlock(size)); if (data.size() < size) return false; int index = data.find((char)0); @@ -53,6 +52,7 @@ bool Mod::FileBase::readString(String &s, unsigned long size) { s = data; return true; + } void Mod::FileBase::writeByte(unsigned char _byte) { @@ -77,36 +77,46 @@ void Mod::FileBase::writeU32B(unsigned long number) { } bool Mod::FileBase::readByte(unsigned char &_byte) { + ByteVector data(readBlock(1)); if (data.size() < 1) return false; _byte = data[0]; return true; + } bool Mod::FileBase::readU16L(unsigned short &number) { + ByteVector data(readBlock(2)); if (data.size() < 2) return false; number = data.toUShort(false); return true; + } bool Mod::FileBase::readU32L(unsigned long &number) { + ByteVector data(readBlock(4)); if (data.size() < 4) return false; number = data.toUInt(false); return true; + } bool Mod::FileBase::readU16B(unsigned short &number) { + ByteVector data(readBlock(2)); if (data.size() < 2) return false; number = data.toUShort(true); return true; + } bool Mod::FileBase::readU32B(unsigned long &number) { + ByteVector data(readBlock(4)); if (data.size() < 4) return false; number = data.toUInt(true); return true; + } diff --git a/3rdparty/taglib/mod/modfilebase.h b/3rdparty/taglib/mod/modfilebase.h index 7ac600e37..f93ad01b8 100644 --- a/3rdparty/taglib/mod/modfilebase.h +++ b/3rdparty/taglib/mod/modfilebase.h @@ -36,7 +36,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace Mod { class TAGLIB_EXPORT FileBase : public Strawberry_TagLib::TagLib::File { @@ -60,7 +59,6 @@ class TAGLIB_EXPORT FileBase : public Strawberry_TagLib::TagLib::File { }; } // namespace Mod - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mod/modproperties.cpp b/3rdparty/taglib/mod/modproperties.cpp index c727aff84..8489c6410 100644 --- a/3rdparty/taglib/mod/modproperties.cpp +++ b/3rdparty/taglib/mod/modproperties.cpp @@ -31,18 +31,14 @@ using namespace Mod; class Mod::Properties::PropertiesPrivate { public: - PropertiesPrivate() : channels(0), - instrumentCount(0), - lengthInPatterns(0) { - } + PropertiesPrivate() : channels(0), instrumentCount(0), lengthInPatterns(0) {} int channels; unsigned int instrumentCount; unsigned char lengthInPatterns; }; -Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle), - d(new PropertiesPrivate()) { +Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle), d(new PropertiesPrivate()) { } Mod::Properties::~Properties() { diff --git a/3rdparty/taglib/mod/modproperties.h b/3rdparty/taglib/mod/modproperties.h index 370c4a454..f2b95d75c 100644 --- a/3rdparty/taglib/mod/modproperties.h +++ b/3rdparty/taglib/mod/modproperties.h @@ -31,7 +31,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace Mod { class TAGLIB_EXPORT Properties : public AudioProperties { @@ -65,7 +64,6 @@ class TAGLIB_EXPORT Properties : public AudioProperties { }; } // namespace Mod - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mod/modtag.cpp b/3rdparty/taglib/mod/modtag.cpp index 710fed387..9fb9de377 100644 --- a/3rdparty/taglib/mod/modtag.cpp +++ b/3rdparty/taglib/mod/modtag.cpp @@ -33,17 +33,14 @@ using namespace Mod; class Mod::Tag::TagPrivate { public: - TagPrivate() { - } + TagPrivate() {} String title; String comment; String trackerName; }; -Mod::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), - d(new TagPrivate()) { -} +Mod::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {} Mod::Tag::~Tag() { delete d; @@ -109,15 +106,18 @@ void Mod::Tag::setTrackerName(const String &trackerName) { } PropertyMap Mod::Tag::properties() const { + PropertyMap properties; properties["TITLE"] = d->title; properties["COMMENT"] = d->comment; if (!(d->trackerName.isEmpty())) properties["TRACKERNAME"] = d->trackerName; return properties; + } PropertyMap Mod::Tag::setProperties(const PropertyMap &origProps) { + PropertyMap properties(origProps); properties.removeEmpty(); StringList oneValueSet; @@ -151,4 +151,5 @@ PropertyMap Mod::Tag::setProperties(const PropertyMap &origProps) { properties[*it].erase(properties[*it].begin()); } return properties; + } diff --git a/3rdparty/taglib/mod/modtag.h b/3rdparty/taglib/mod/modtag.h index 9fffec77f..d443d9615 100644 --- a/3rdparty/taglib/mod/modtag.h +++ b/3rdparty/taglib/mod/modtag.h @@ -30,153 +30,141 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace Mod { /*! - * Tags for module files (Mod, S3M, IT, XM). - * - * Note that only the \a title is supported as such by most - * module file formats. Except for XM files the \a trackerName - * is derived from the file format or the flavour of the file - * format. For XM files it is stored in the file. - * - * The \a comment tag is not strictly supported by module files, - * but it is common practice to abuse instrument/sample/pattern - * names as multiline comments. TagLib does so as well. - */ + * Tags for module files (Mod, S3M, IT, XM). + * + * Note that only the \a title is supported as such by most module file formats. + * Except for XM files the \a trackerName is derived from the file format or the flavour of the file format. + * For XM files it is stored in the file. + * + * The \a comment tag is not strictly supported by module files, + * but it is common practice to abuse instrument/sample/pattern names as multiline comments. + * TagLib does so as well. + * + */ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { public: Tag(); virtual ~Tag(); /*! - * Returns the track name; if no track name is present in the tag - * String::null will be returned. - */ + * Returns the track name; if no track name is present in the tag String::null will be returned. + */ virtual String title() const; /*! - * Not supported by module files. Therefore always returns String::null. - */ + * Not supported by module files. Therefore always returns String::null. + */ virtual String artist() const; /*! - * Not supported by module files. Therefore always returns String::null. - */ + * Not supported by module files. Therefore always returns String::null. + */ virtual String album() const; /*! - * Returns the track comment derived from the instrument/sample/pattern - * names; if no comment is present in the tag String::null will be - * returned. - */ + * Returns the track comment derived from the instrument/sample/pattern + * names; if no comment is present in the tag String::null will be returned. + */ virtual String comment() const; /*! - * Not supported by module files. Therefore always returns String::null. - */ + * Not supported by module files. Therefore always returns String::null. + */ virtual String genre() const; /*! - * Not supported by module files. Therefore always returns 0. - */ + * Not supported by module files. Therefore always returns 0. + */ virtual unsigned int year() const; /*! - * Not supported by module files. Therefore always returns 0. - */ + * Not supported by module files. Therefore always returns 0. + */ virtual unsigned int track() const; /*! - * Returns the name of the tracker used to create/edit the module file. - * Only XM files store this tag to the file as such, for other formats - * (Mod, S3M, IT) this is derived from the file type or the flavour of - * the file type. Therefore only XM files might have an empty - * (String::null) tracker name. - */ + * Returns the name of the tracker used to create/edit the module file. + * Only XM files store this tag to the file as such, for other formats + * (Mod, S3M, IT) this is derived from the file type or the flavour of the file type. + * Therefore only XM files might have an empty (String::null) tracker name. + */ String trackerName() const; /*! - * Sets the title to \a title. If \a title is String::null then this - * value will be cleared. - * - * The length limits per file type are (1 character = 1 byte): - * Mod 20 characters, S3M 27 characters, IT 25 characters and XM 20 - * characters. - */ + * Sets the title to \a title. + * If \a title is String::null then this value will be cleared. + * + * The length limits per file type are (1 character = 1 byte): + * Mod 20 characters, S3M 27 characters, IT 25 characters and XM 20 characters. + */ virtual void setTitle(const String &title); /*! - * Not supported by module files and therefore ignored. - */ + * Not supported by module files and therefore ignored. + */ virtual void setArtist(const String &artist); /*! - * Not supported by module files and therefore ignored. - */ + * Not supported by module files and therefore ignored. + */ virtual void setAlbum(const String &album); /*! - * Sets the comment to \a comment. If \a comment is String::null then - * this value will be cleared. - * - * Note that module file formats don't actually support a comment tag. - * Instead the names of instruments/patterns/samples are abused as - * a multiline comment. Because of this the number of lines in a - * module file is fixed to the number of instruments/patterns/samples. - * - * Also note that the instrument/pattern/sample name length is limited - * an thus the line length in comments are limited. Too big comments - * will be truncated. - * - * The line length limits per file type are (1 character = 1 byte): - * Mod 22 characters, S3M 27 characters, IT 25 characters and XM 22 - * characters. - */ + * Sets the comment to \a comment. + * If \a comment is String::null then this value will be cleared. + * + * Note that module file formats don't actually support a comment tag. + * Instead the names of instruments/patterns/samples are abused as a multiline comment. + * Because of this the number of lines in a module file is fixed to the number of instruments/patterns/samples. + * + * Also note that the instrument/pattern/sample name length is limited an thus the line length in comments are limited. + * Too big comments will be truncated. + * + * The line length limits per file type are (1 character = 1 byte): + * Mod 22 characters, S3M 27 characters, IT 25 characters and XM 22 characters. + */ virtual void setComment(const String &comment); /*! - * Not supported by module files and therefore ignored. - */ + * Not supported by module files and therefore ignored. + */ virtual void setGenre(const String &genre); /*! - * Not supported by module files and therefore ignored. - */ + * Not supported by module files and therefore ignored. + */ virtual void setYear(unsigned int year); /*! - * Not supported by module files and therefore ignored. - */ + * Not supported by module files and therefore ignored. + */ virtual void setTrack(unsigned int track); /*! - * Sets the tracker name to \a trackerName. If \a trackerName is - * String::null then this value will be cleared. - * - * Note that only XM files support this tag. Setting the - * tracker name for other module file formats will be ignored. - * - * The length of this tag is limited to 20 characters (1 character - * = 1 byte). - */ + * Sets the tracker name to \a trackerName. + * If \a trackerName is String::null then this value will be cleared. + * + * Note that only XM files support this tag. + * Setting the tracker name for other module file formats will be ignored. + * + * The length of this tag is limited to 20 characters (1 character = 1 byte). + */ void setTrackerName(const String &trackerName); /*! - * Implements the unified property interface -- export function. - * Since the module tag is very limited, the exported map is as well. - */ + * Implements the unified property interface -- export function. + * Since the module tag is very limited, the exported map is as well. + */ PropertyMap properties() const; /*! - * Implements the unified property interface -- import function. - * Because of the limitations of the module file tag, any tags besides - * COMMENT, TITLE and, if it is an XM file, TRACKERNAME, will be - * returned. Additionally, if the map contains tags with multiple values, - * all but the first will be contained in the returned map of unsupported - * properties. - */ + * Implements the unified property interface -- import function. + * Because of the limitations of the module file tag, any tags besides COMMENT, TITLE and, if it is an XM file, TRACKERNAME, will be returned. + * Additionally, if the map contains tags with multiple values, all but the first will be contained in the returned map of unsupported properties. + */ PropertyMap setProperties(const PropertyMap &); private: @@ -188,7 +176,6 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { }; } // namespace Mod - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mp4/mp4atom.cpp b/3rdparty/taglib/mp4/mp4atom.cpp index a90e16ab5..e157c7b91 100644 --- a/3rdparty/taglib/mp4/mp4atom.cpp +++ b/3rdparty/taglib/mp4/mp4atom.cpp @@ -31,13 +31,10 @@ using namespace Strawberry_TagLib::TagLib; -const char *MP4::Atom::containers[11] = { - "moov", "udta", "mdia", "meta", "ilst", - "stbl", "minf", "moof", "traf", "trak", - "stsd" -}; +const char *MP4::Atom::containers[11] = { "moov", "udta", "mdia", "meta", "ilst", "stbl", "minf", "moof", "traf", "trak", "stsd" }; MP4::Atom::Atom(File *file) { + children.setAutoDelete(true); offset = file->tell(); @@ -100,14 +97,14 @@ MP4::Atom::Atom(File *file) { } file->seek(offset + length); + } -MP4::Atom::~Atom() { -} +MP4::Atom::~Atom() {} -MP4::Atom * -MP4::Atom::find(const char *name1, const char *name2, const char *name3, const char *name4) { - if (name1 == 0) { +MP4::Atom *MP4::Atom::find(const char *name1, const char *name2, const char *name3, const char *name4) { + + if (!name1) { return this; } for (AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) { @@ -116,10 +113,11 @@ MP4::Atom::find(const char *name1, const char *name2, const char *name3, const c } } return nullptr; + } -MP4::AtomList -MP4::Atom::findall(const char *_name, bool recursive) { +MP4::AtomList MP4::Atom::findall(const char *_name, bool recursive) { + MP4::AtomList result; for (AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) { if ((*it)->name == _name) { @@ -130,11 +128,13 @@ MP4::Atom::findall(const char *_name, bool recursive) { } } return result; + } bool MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const char *name3) { + path.append(this); - if (name1 == 0) { + if (!name1) { return true; } for (AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) { @@ -143,9 +143,11 @@ bool MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, } } return false; + } MP4::Atoms::Atoms(File *file) { + atoms.setAutoDelete(true); file->seek(0, File::End); @@ -157,23 +159,24 @@ MP4::Atoms::Atoms(File *file) { if (atom->length == 0) break; } + } -MP4::Atoms::~Atoms() { -} +MP4::Atoms::~Atoms() {} + +MP4::Atom *MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4) { -MP4::Atom * -MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4) { for (AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) { if ((*it)->name == name1) { return (*it)->find(name2, name3, name4); } } return nullptr; + } -MP4::AtomList -MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4) { +MP4::AtomList MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4) { + MP4::AtomList path; for (AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) { if ((*it)->name == name1) { @@ -184,4 +187,5 @@ MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const } } return path; + } diff --git a/3rdparty/taglib/mp4/mp4atom.h b/3rdparty/taglib/mp4/mp4atom.h index c580baceb..b8085f3bb 100644 --- a/3rdparty/taglib/mp4/mp4atom.h +++ b/3rdparty/taglib/mp4/mp4atom.h @@ -35,7 +35,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace MP4 { class Atom; @@ -78,6 +77,7 @@ class Atom { public: Atom(File *file); ~Atom(); + Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0); AtomList findall(const char *name, bool recursive = false); @@ -96,13 +96,13 @@ class Atoms { public: Atoms(File *file); ~Atoms(); + Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); AtomList path(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); AtomList atoms; }; } // namespace MP4 - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mp4/mp4coverart.cpp b/3rdparty/taglib/mp4/mp4coverart.cpp index 7dc2e69f6..d6659a0f7 100644 --- a/3rdparty/taglib/mp4/mp4coverart.cpp +++ b/3rdparty/taglib/mp4/mp4coverart.cpp @@ -32,8 +32,7 @@ using namespace Strawberry_TagLib::TagLib; class MP4::CoverArt::CoverArtPrivate : public RefCounter { public: - CoverArtPrivate() : RefCounter(), - format(MP4::CoverArt::JPEG) {} + CoverArtPrivate() : RefCounter(), format(MP4::CoverArt::JPEG) {} Format format; ByteVector data; diff --git a/3rdparty/taglib/mp4/mp4coverart.h b/3rdparty/taglib/mp4/mp4coverart.h index 1100c1b01..93d1f8109 100644 --- a/3rdparty/taglib/mp4/mp4coverart.h +++ b/3rdparty/taglib/mp4/mp4coverart.h @@ -33,14 +33,13 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace MP4 { class TAGLIB_EXPORT CoverArt { public: /*! - * This describes the image type. - */ + * This describes the image type. + */ enum Format { JPEG = TypeJPEG, PNG = TypePNG, @@ -55,13 +54,13 @@ class TAGLIB_EXPORT CoverArt { CoverArt(const CoverArt &item); /*! - * Copies the contents of \a item into this CoverArt. - */ + * Copies the contents of \a item into this CoverArt. + */ CoverArt &operator=(const CoverArt &item); /*! - * Exchanges the content of the CoverArt by the content of \a item. - */ + * Exchanges the content of the CoverArt by the content of \a item. + */ void swap(CoverArt &item); //! Format of the image @@ -78,7 +77,6 @@ class TAGLIB_EXPORT CoverArt { typedef List CoverArtList; } // namespace MP4 - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mp4/mp4file.cpp b/3rdparty/taglib/mp4/mp4file.cpp index 31a59c68c..f22daf037 100644 --- a/3rdparty/taglib/mp4/mp4file.cpp +++ b/3rdparty/taglib/mp4/mp4file.cpp @@ -36,6 +36,7 @@ using namespace Strawberry_TagLib::TagLib; namespace { bool checkValid(const MP4::AtomList &list) { + for (MP4::AtomList::ConstIterator it = list.begin(); it != list.end(); ++it) { if ((*it)->length == 0) @@ -46,14 +47,13 @@ bool checkValid(const MP4::AtomList &list) { } return true; + } } // namespace class MP4::File::FilePrivate { public: - FilePrivate() : tag(0), - atoms(0), - properties(0) {} + FilePrivate() : tag(nullptr), atoms(nullptr), properties(nullptr) {} ~FilePrivate() { delete atoms; @@ -71,26 +71,30 @@ class MP4::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool MP4::File::isSupported(IOStream *stream) { + // An MP4 file has to have an "ftyp" box first. const ByteVector id = Utils::readHeader(stream, 8, false); return id.containsAt("ftyp", 4); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate()) { +MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } -MP4::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate()) { +MP4::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } MP4::File::~File() { @@ -120,6 +124,7 @@ MP4::File::audioProperties() const { } void MP4::File::read(bool readProperties) { + if (!isValid()) return; @@ -139,9 +144,11 @@ void MP4::File::read(bool readProperties) { if (readProperties) { d->properties = new Properties(this, d->atoms); } + } bool MP4::File::save() { + if (readOnly()) { debug("MP4::File::save() -- File is read only."); return false; @@ -153,8 +160,9 @@ bool MP4::File::save() { } return d->tag->save(); + } bool MP4::File::hasMP4Tag() const { - return (d->atoms->find("moov", "udta", "meta", "ilst") != 0); + return (d->atoms->find("moov", "udta", "meta", "ilst") != nullptr); } diff --git a/3rdparty/taglib/mp4/mp4file.h b/3rdparty/taglib/mp4/mp4file.h index b0d93ea6f..0fb5c7bad 100644 --- a/3rdparty/taglib/mp4/mp4file.h +++ b/3rdparty/taglib/mp4/mp4file.h @@ -41,92 +41,85 @@ namespace MP4 { class Atoms; /*! - * This implements and provides an interface for MP4 files to the - * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing - * the abstract TagLib::File API as well as providing some additional - * information specific to MP4 files. - */ + * This implements and provides an interface for MP4 files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to MP4 files. + */ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { public: /*! - * Constructs an MP4 file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(FileName file, bool readProperties = true, - Properties::ReadStyle audioPropertiesStyle = Properties::Average); + * Constructs an MP4 file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, Properties::ReadStyle audioPropertiesStyle = Properties::Average); /*! - * Constructs an MP4 file from \a stream. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ + * Constructs an MP4 file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ File(IOStream *stream, bool readProperties = true, Properties::ReadStyle audioPropertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns a pointer to the MP4 tag of the file. - * - * MP4::Tag implements the tag interface, so this serves as the - * reimplementation of TagLib::File::tag(). - * - * \note The Tag is still owned by the MP4::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - */ + * Returns a pointer to the MP4 tag of the file. + * + * MP4::Tag implements the tag interface, so this serves as the reimplementation of TagLib::File::tag(). + * + * \note The Tag is still owned by the MP4::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + */ Tag *tag() const; /*! - * Implements the unified property interface -- export function. - */ + * Implements the unified property interface -- export function. + */ PropertyMap properties() const; /*! - * Removes unsupported properties. Forwards to the actual Tag's - * removeUnsupportedProperties() function. - */ + * Removes unsupported properties. Forwards to the actual Tag's removeUnsupportedProperties() function. + */ void removeUnsupportedProperties(const StringList &properties); /*! - * Implements the unified property interface -- import function. - */ + * Implements the unified property interface -- import function. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the MP4 audio properties for this file. - */ + * Returns the MP4 audio properties for this file. + */ Properties *audioProperties() const; /*! - * Save the file. - * - * This returns true if the save was successful. - */ + * Save the file. + * + * This returns true if the save was successful. + */ bool save(); /*! - * Returns whether or not the file on disk actually has an MP4 tag, or the - * file has a Metadata Item List (ilst) atom. - */ + * Returns whether or not the file on disk actually has an MP4 tag, or the file has a Metadata Item List (ilst) atom. + */ bool hasMP4Tag() const; /*! - * Returns whether or not the given \a stream can be opened as an ASF - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as an ASF file. + * + * \note This method is designed to do a quick check. The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: @@ -137,7 +130,6 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { }; } // namespace MP4 - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mp4/mp4item.cpp b/3rdparty/taglib/mp4/mp4item.cpp index 4427c6988..3b0f6fc30 100644 --- a/3rdparty/taglib/mp4/mp4item.cpp +++ b/3rdparty/taglib/mp4/mp4item.cpp @@ -32,9 +32,7 @@ using namespace Strawberry_TagLib::TagLib; class MP4::Item::ItemPrivate : public RefCounter { public: - ItemPrivate() : RefCounter(), - valid(true), - atomDataType(TypeUndefined) {} + ItemPrivate() : RefCounter(), valid(true), atomDataType(TypeUndefined) {} bool valid; AtomDataType atomDataType; @@ -59,8 +57,7 @@ MP4::Item::Item(const Item &item) : d(item.d) { d->ref(); } -MP4::Item & -MP4::Item::operator=(const Item &item) { +MP4::Item &MP4::Item::operator=(const Item &item) { Item(item).swap(*this); return *this; } @@ -129,38 +126,31 @@ int MP4::Item::toInt() const { return d->m_int; } -unsigned char -MP4::Item::toByte() const { +unsigned char MP4::Item::toByte() const { return d->m_byte; } -unsigned int -MP4::Item::toUInt() const { +unsigned int MP4::Item::toUInt() const { return d->m_uint; } -long long -MP4::Item::toLongLong() const { +long long MP4::Item::toLongLong() const { return d->m_longlong; } -MP4::Item::IntPair -MP4::Item::toIntPair() const { +MP4::Item::IntPair MP4::Item::toIntPair() const { return d->m_intPair; } -StringList -MP4::Item::toStringList() const { +StringList MP4::Item::toStringList() const { return d->m_stringList; } -ByteVectorList -MP4::Item::toByteVectorList() const { +ByteVectorList MP4::Item::toByteVectorList() const { return d->m_byteVectorList; } -MP4::CoverArtList -MP4::Item::toCoverArtList() const { +MP4::CoverArtList MP4::Item::toCoverArtList() const { return d->m_coverArtList; } diff --git a/3rdparty/taglib/mp4/mp4item.h b/3rdparty/taglib/mp4/mp4item.h index 73fa40daf..b53088ce5 100644 --- a/3rdparty/taglib/mp4/mp4item.h +++ b/3rdparty/taglib/mp4/mp4item.h @@ -32,7 +32,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace MP4 { class TAGLIB_EXPORT Item { @@ -45,13 +44,13 @@ class TAGLIB_EXPORT Item { Item(const Item &item); /*! - * Copies the contents of \a item into this Item. - */ + * Copies the contents of \a item into this Item. + */ Item &operator=(const Item &item); /*! - * Exchanges the content of the Item by the content of \a item. - */ + * Exchanges the content of the Item by the content of \a item. + */ void swap(Item &item); ~Item(); @@ -87,7 +86,6 @@ class TAGLIB_EXPORT Item { }; } // namespace MP4 - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mp4/mp4properties.cpp b/3rdparty/taglib/mp4/mp4properties.cpp index 74ec6579d..0a4099615 100644 --- a/3rdparty/taglib/mp4/mp4properties.cpp +++ b/3rdparty/taglib/mp4/mp4properties.cpp @@ -54,8 +54,7 @@ class MP4::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { read(file, atoms); } @@ -71,10 +70,6 @@ int MP4::Properties::sampleRate() const { return d->sampleRate; } -int MP4::Properties::length() const { - return lengthInSeconds(); -} - int MP4::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -105,13 +100,14 @@ MP4::Properties::codec() const { //////////////////////////////////////////////////////////////////////////////// void MP4::Properties::read(File *file, Atoms *atoms) { + MP4::Atom *moov = atoms->find("moov"); if (!moov) { debug("MP4: Atom 'moov' not found"); return; } - MP4::Atom *trak = 0; + MP4::Atom *trak = nullptr; ByteVector data; const MP4::AtomList trakList = moov->findall("trak"); @@ -127,7 +123,7 @@ void MP4::Properties::read(File *file, Atoms *atoms) { if (data.containsAt("soun", 16)) { break; } - trak = 0; + trak = nullptr; } if (!trak) { debug("MP4: No audio tracks"); @@ -207,4 +203,5 @@ void MP4::Properties::read(File *file, Atoms *atoms) { if (drms) { d->encrypted = true; } + } diff --git a/3rdparty/taglib/mp4/mp4properties.h b/3rdparty/taglib/mp4/mp4properties.h index d5d743cf2..0456e5494 100644 --- a/3rdparty/taglib/mp4/mp4properties.h +++ b/3rdparty/taglib/mp4/mp4properties.h @@ -31,7 +31,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace MP4 { class Atoms; @@ -50,60 +49,49 @@ class TAGLIB_EXPORT Properties : public AudioProperties { virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - TAGLIB_DEPRECATED virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the number of bits per audio sample. - */ + * Returns the number of bits per audio sample. + */ virtual int bitsPerSample() const; /*! - * Returns whether or not the file is encrypted. - */ + * Returns whether or not the file is encrypted. + */ bool isEncrypted() const; /*! - * Returns the codec used in the file. - */ + * Returns the codec used in the file. + */ Codec codec() const; private: @@ -114,7 +102,6 @@ class TAGLIB_EXPORT Properties : public AudioProperties { }; } // namespace MP4 - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mp4/mp4tag.cpp b/3rdparty/taglib/mp4/mp4tag.cpp index 4870485a3..89a2c2365 100644 --- a/3rdparty/taglib/mp4/mp4tag.cpp +++ b/3rdparty/taglib/mp4/mp4tag.cpp @@ -34,18 +34,17 @@ using namespace Strawberry_TagLib::TagLib; class MP4::Tag::TagPrivate { public: - TagPrivate() : file(0), - atoms(0) {} + TagPrivate() : file(nullptr), atoms(nullptr) {} Strawberry_TagLib::TagLib::File *file; Atoms *atoms; ItemMap items; }; -MP4::Tag::Tag() : d(new TagPrivate()) { -} +MP4::Tag::Tag() : d(new TagPrivate()) {} MP4::Tag::Tag(Strawberry_TagLib::TagLib::File *file, MP4::Atoms *atoms) : d(new TagPrivate()) { + d->file = file; d->atoms = atoms; @@ -113,8 +112,8 @@ MP4::Tag::~Tag() { delete d; } -MP4::AtomDataList -MP4::Tag::parseData2(const MP4::Atom *atom, int expectedFlags, bool freeForm) { +MP4::AtomDataList MP4::Tag::parseData2(const MP4::Atom *atom, int expectedFlags, bool freeForm) { + AtomDataList result; ByteVector data = d->file->readBlock(atom->length - 8); int i = 0; @@ -152,47 +151,58 @@ MP4::Tag::parseData2(const MP4::Atom *atom, int expectedFlags, bool freeForm) { i++; } return result; + } -ByteVectorList -MP4::Tag::parseData(const MP4::Atom *atom, int expectedFlags, bool freeForm) { +ByteVectorList MP4::Tag::parseData(const MP4::Atom *atom, int expectedFlags, bool freeForm) { + AtomDataList data = parseData2(atom, expectedFlags, freeForm); ByteVectorList result; for (AtomDataList::ConstIterator it = data.begin(); it != data.end(); ++it) { result.append(it->data); } return result; + } void MP4::Tag::parseInt(const MP4::Atom *atom) { + ByteVectorList data = parseData(atom); if (!data.isEmpty()) { addItem(atom->name, (int)data[0].toShort()); } + } void MP4::Tag::parseUInt(const MP4::Atom *atom) { + ByteVectorList data = parseData(atom); if (!data.isEmpty()) { addItem(atom->name, data[0].toUInt()); } + } void MP4::Tag::parseLongLong(const MP4::Atom *atom) { + ByteVectorList data = parseData(atom); if (!data.isEmpty()) { addItem(atom->name, data[0].toLongLong()); } + } void MP4::Tag::parseByte(const MP4::Atom *atom) { + ByteVectorList data = parseData(atom); if (!data.isEmpty()) { addItem(atom->name, static_cast(data[0].at(0))); } + } void MP4::Tag::parseGnre(const MP4::Atom *atom) { + ByteVectorList data = parseData(atom); if (!data.isEmpty()) { int idx = (int)data[0].toShort(); @@ -200,26 +210,32 @@ void MP4::Tag::parseGnre(const MP4::Atom *atom) { addItem("\251gen", StringList(ID3v1::genre(idx - 1))); } } + } void MP4::Tag::parseIntPair(const MP4::Atom *atom) { + ByteVectorList data = parseData(atom); if (!data.isEmpty()) { const int a = data[0].toShort(2U); const int b = data[0].toShort(4U); addItem(atom->name, MP4::Item(a, b)); } + } void MP4::Tag::parseBool(const MP4::Atom *atom) { + ByteVectorList data = parseData(atom); if (!data.isEmpty()) { bool value = data[0].size() ? data[0][0] != '\0' : false; addItem(atom->name, value); } + } void MP4::Tag::parseText(const MP4::Atom *atom, int expectedFlags) { + ByteVectorList data = parseData(atom, expectedFlags); if (!data.isEmpty()) { StringList value; @@ -228,9 +244,11 @@ void MP4::Tag::parseText(const MP4::Atom *atom, int expectedFlags) { } addItem(atom->name, value); } + } void MP4::Tag::parseFreeForm(const MP4::Atom *atom) { + AtomDataList data = parseData2(atom, -1, true); if (data.size() > 2) { AtomDataList::ConstIterator itBegin = data.begin(); @@ -267,9 +285,11 @@ void MP4::Tag::parseFreeForm(const MP4::Atom *atom) { addItem(name, item); } } + } void MP4::Tag::parseCovr(const MP4::Atom *atom) { + MP4::CoverArtList value; ByteVector data = d->file->readBlock(atom->length - 8); unsigned int pos = 0; @@ -299,106 +319,117 @@ void MP4::Tag::parseCovr(const MP4::Atom *atom) { } if (!value.isEmpty()) addItem(atom->name, value); + } -ByteVector -MP4::Tag::padIlst(const ByteVector &data, int length) const { +ByteVector MP4::Tag::padIlst(const ByteVector &data, int length) const { + if (length == -1) { length = ((data.size() + 1023) & ~1023) - data.size(); } return renderAtom("free", ByteVector(length, '\1')); + } -ByteVector -MP4::Tag::renderAtom(const ByteVector &name, const ByteVector &data) const { +ByteVector MP4::Tag::renderAtom(const ByteVector &name, const ByteVector &data) const { return ByteVector::fromUInt(data.size() + 8) + name + data; } -ByteVector -MP4::Tag::renderData(const ByteVector &name, int flags, const ByteVectorList &data) const { +ByteVector MP4::Tag::renderData(const ByteVector &name, int flags, const ByteVectorList &data) const { + ByteVector result; for (ByteVectorList::ConstIterator it = data.begin(); it != data.end(); ++it) { result.append(renderAtom("data", ByteVector::fromUInt(flags) + ByteVector(4, '\0') + *it)); } return renderAtom(name, result); + } -ByteVector -MP4::Tag::renderBool(const ByteVector &name, const MP4::Item &item) const { +ByteVector MP4::Tag::renderBool(const ByteVector &name, const MP4::Item &item) const { + ByteVectorList data; data.append(ByteVector(1, item.toBool() ? '\1' : '\0')); return renderData(name, TypeInteger, data); + } -ByteVector -MP4::Tag::renderInt(const ByteVector &name, const MP4::Item &item) const { +ByteVector MP4::Tag::renderInt(const ByteVector &name, const MP4::Item &item) const { + ByteVectorList data; data.append(ByteVector::fromShort(item.toInt())); return renderData(name, TypeInteger, data); + } -ByteVector -MP4::Tag::renderUInt(const ByteVector &name, const MP4::Item &item) const { +ByteVector MP4::Tag::renderUInt(const ByteVector &name, const MP4::Item &item) const { + ByteVectorList data; data.append(ByteVector::fromUInt(item.toUInt())); return renderData(name, TypeInteger, data); + } -ByteVector -MP4::Tag::renderLongLong(const ByteVector &name, const MP4::Item &item) const { +ByteVector MP4::Tag::renderLongLong(const ByteVector &name, const MP4::Item &item) const { + ByteVectorList data; data.append(ByteVector::fromLongLong(item.toLongLong())); return renderData(name, TypeInteger, data); + } -ByteVector -MP4::Tag::renderByte(const ByteVector &name, const MP4::Item &item) const { +ByteVector MP4::Tag::renderByte(const ByteVector &name, const MP4::Item &item) const { + ByteVectorList data; data.append(ByteVector(1, item.toByte())); return renderData(name, TypeInteger, data); + } -ByteVector -MP4::Tag::renderIntPair(const ByteVector &name, const MP4::Item &item) const { +ByteVector MP4::Tag::renderIntPair(const ByteVector &name, const MP4::Item &item) const { + ByteVectorList data; data.append(ByteVector(2, '\0') + ByteVector::fromShort(item.toIntPair().first) + ByteVector::fromShort(item.toIntPair().second) + ByteVector(2, '\0')); return renderData(name, TypeImplicit, data); + } -ByteVector -MP4::Tag::renderIntPairNoTrailing(const ByteVector &name, const MP4::Item &item) const { +ByteVector MP4::Tag::renderIntPairNoTrailing(const ByteVector &name, const MP4::Item &item) const { + ByteVectorList data; data.append(ByteVector(2, '\0') + ByteVector::fromShort(item.toIntPair().first) + ByteVector::fromShort(item.toIntPair().second)); return renderData(name, TypeImplicit, data); + } -ByteVector -MP4::Tag::renderText(const ByteVector &name, const MP4::Item &item, int flags) const { +ByteVector MP4::Tag::renderText(const ByteVector &name, const MP4::Item &item, int flags) const { + ByteVectorList data; StringList value = item.toStringList(); for (StringList::ConstIterator it = value.begin(); it != value.end(); ++it) { data.append(it->data(String::UTF8)); } return renderData(name, flags, data); + } -ByteVector -MP4::Tag::renderCovr(const ByteVector &name, const MP4::Item &item) const { +ByteVector MP4::Tag::renderCovr(const ByteVector &name, const MP4::Item &item) const { + ByteVector data; MP4::CoverArtList value = item.toCoverArtList(); for (MP4::CoverArtList::ConstIterator it = value.begin(); it != value.end(); ++it) { data.append(renderAtom("data", ByteVector::fromUInt(it->format()) + ByteVector(4, '\0') + it->data())); } return renderAtom(name, data); + } -ByteVector -MP4::Tag::renderFreeForm(const String &name, const MP4::Item &item) const { +ByteVector MP4::Tag::renderFreeForm(const String &name, const MP4::Item &item) const { + StringList header = StringList::split(name, ":"); if (header.size() != 3) { debug("MP4: Invalid free-form item name \"" + name + "\""); @@ -429,9 +460,11 @@ MP4::Tag::renderFreeForm(const String &name, const MP4::Item &item) const { } } return renderAtom("----", data); + } bool MP4::Tag::save() { + ByteVector data; for (MP4::ItemMap::ConstIterator it = d->items.begin(); it != d->items.end(); ++it) { const String name = it->first; @@ -496,9 +529,11 @@ bool MP4::Tag::save() { } return true; + } void MP4::Tag::updateParents(const AtomList &path, long delta, int ignore) { + if (static_cast(path.size()) <= ignore) return; @@ -525,6 +560,7 @@ void MP4::Tag::updateParents(const AtomList &path, long delta, int ignore) { } void MP4::Tag::updateOffsets(long delta, long offset) { + MP4::Atom *moov = d->atoms->find("moov"); if (moov) { MP4::AtomList stco = moov->findall("stco", true); @@ -591,9 +627,11 @@ void MP4::Tag::updateOffsets(long delta, long offset) { } } } + } void MP4::Tag::saveNew(ByteVector data) { + data = renderAtom("meta", ByteVector(4, '\0') + renderAtom("hdlr", ByteVector(8, '\0') + ByteVector("mdirappl") + ByteVector(9, '\0')) + data + padIlst(data)); AtomList path = d->atoms->path("moov", "udta"); @@ -612,9 +650,11 @@ void MP4::Tag::saveNew(ByteVector data) { d->file->seek(offset); path.back()->children.prepend(new Atom(d->file)); + } void MP4::Tag::saveExisting(ByteVector data, const AtomList &path) { + AtomList::ConstIterator it = path.end(); MP4::Atom *ilst = *(--it); @@ -660,52 +700,46 @@ void MP4::Tag::saveExisting(ByteVector data, const AtomList &path) { updateParents(path, delta, 1); updateOffsets(delta, offset); } + } -String -MP4::Tag::title() const { +String MP4::Tag::title() const { if (d->items.contains("\251nam")) return d->items["\251nam"].toStringList().toString(", "); return String(); } -String -MP4::Tag::artist() const { +String MP4::Tag::artist() const { if (d->items.contains("\251ART")) return d->items["\251ART"].toStringList().toString(", "); return String(); } -String -MP4::Tag::album() const { +String MP4::Tag::album() const { if (d->items.contains("\251alb")) return d->items["\251alb"].toStringList().toString(", "); return String(); } -String -MP4::Tag::comment() const { +String MP4::Tag::comment() const { if (d->items.contains("\251cmt")) return d->items["\251cmt"].toStringList().toString(", "); return String(); } -String -MP4::Tag::genre() const { +String MP4::Tag::genre() const { if (d->items.contains("\251gen")) return d->items["\251gen"].toStringList().toString(", "); return String(); } -unsigned int -MP4::Tag::year() const { +unsigned int MP4::Tag::year() const { if (d->items.contains("\251day")) return d->items["\251day"].toStringList().toString().toInt(); return 0; } -unsigned int -MP4::Tag::track() const { +unsigned int MP4::Tag::track() const { if (d->items.contains("trkn")) return d->items["trkn"].toIntPair().first; return 0; @@ -732,31 +766,31 @@ void MP4::Tag::setGenre(const String &value) { } void MP4::Tag::setYear(unsigned int value) { + if (value == 0) { d->items.erase("\251day"); } else { d->items["\251day"] = StringList(String::number(value)); } + } void MP4::Tag::setTrack(unsigned int value) { + if (value == 0) { d->items.erase("trkn"); } else { d->items["trkn"] = MP4::Item(value, 0); } + } bool MP4::Tag::isEmpty() const { return d->items.isEmpty(); } -MP4::ItemMap &MP4::Tag::itemListMap() { - return d->items; -} - const MP4::ItemMap &MP4::Tag::itemMap() const { return d->items; } @@ -835,16 +869,19 @@ const char *keyTranslation[][2] = { const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]); String translateKey(const String &key) { + for (size_t i = 0; i < keyTranslationSize; ++i) { if (key == keyTranslation[i][0]) return keyTranslation[i][1]; } return String(); + } } // namespace PropertyMap MP4::Tag::properties() const { + PropertyMap props; for (MP4::ItemMap::ConstIterator it = d->items.begin(); it != d->items.end(); ++it) { const String key = translateKey(it->first); @@ -872,14 +909,18 @@ PropertyMap MP4::Tag::properties() const { } } return props; + } void MP4::Tag::removeUnsupportedProperties(const StringList &props) { + for (StringList::ConstIterator it = props.begin(); it != props.end(); ++it) d->items.erase(*it); + } PropertyMap MP4::Tag::setProperties(const PropertyMap &props) { + static Map reverseKeyMap; if (reverseKeyMap.isEmpty()) { int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]); @@ -928,13 +969,16 @@ PropertyMap MP4::Tag::setProperties(const PropertyMap &props) { } return ignoredProps; + } void MP4::Tag::addItem(const String &name, const Item &value) { + if (!d->items.contains(name)) { d->items.insert(name, value); } else { debug("MP4: Ignoring duplicate atom \"" + name + "\""); } + } diff --git a/3rdparty/taglib/mp4/mp4tag.h b/3rdparty/taglib/mp4/mp4tag.h index 421831a9d..06a594a7c 100644 --- a/3rdparty/taglib/mp4/mp4tag.h +++ b/3rdparty/taglib/mp4/mp4tag.h @@ -37,13 +37,8 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace MP4 { -/*! - * \deprecated - */ -TAGLIB_DEPRECATED typedef Strawberry_TagLib::TagLib::Map ItemListMap; typedef Strawberry_TagLib::TagLib::Map ItemMap; class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { @@ -70,36 +65,29 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { virtual void setTrack(unsigned int value); virtual bool isEmpty() const; - /*! - * \deprecated Use the item() and setItem() API instead - */ - TAGLIB_DEPRECATED ItemMap &itemListMap(); - - /*! - * Returns a string-keyed map of the MP4::Items for this tag. - */ + * Returns a string-keyed map of the MP4::Items for this tag. + */ const ItemMap &itemMap() const; /*! - * \return The item, if any, corresponding to \a key. - */ + * \return The item, if any, corresponding to \a key. + */ Item item(const String &key) const; /*! - * Sets the value of \a key to \a value, overwriting any previous value. - */ + * Sets the value of \a key to \a value, overwriting any previous value. + */ void setItem(const String &key, const Item &value); /*! - * Removes the entry with \a key from the tag, or does nothing if it does - * not exist. - */ + * Removes the entry with \a key from the tag, or does nothing if it does not exist. + */ void removeItem(const String &key); /*! - * \return True if the tag contains an entry for \a key. - */ + * \return True if the tag contains an entry for \a key. + */ bool contains(const String &key) const; PropertyMap properties() const; @@ -107,10 +95,8 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { PropertyMap setProperties(const PropertyMap &properties); private: - AtomDataList parseData2(const Atom *atom, int expectedFlags = -1, - bool freeForm = false); - ByteVectorList parseData(const Atom *atom, int expectedFlags = -1, - bool freeForm = false); + AtomDataList parseData2(const Atom *atom, int expectedFlags = -1, bool freeForm = false); + ByteVectorList parseData(const Atom *atom, int expectedFlags = -1, bool freeForm = false); void parseText(const Atom *atom, int expectedFlags = 1); void parseFreeForm(const Atom *atom); void parseInt(const Atom *atom); @@ -124,10 +110,8 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { ByteVector padIlst(const ByteVector &data, int length = -1) const; ByteVector renderAtom(const ByteVector &name, const ByteVector &data) const; - ByteVector renderData(const ByteVector &name, int flags, - const ByteVectorList &data) const; - ByteVector renderText(const ByteVector &name, const Item &item, - int flags = TypeUTF8) const; + ByteVector renderData(const ByteVector &name, int flags, const ByteVectorList &data) const; + ByteVector renderText(const ByteVector &name, const Item &item, int flags = TypeUTF8) const; ByteVector renderFreeForm(const String &name, const Item &item) const; ByteVector renderBool(const ByteVector &name, const Item &item) const; ByteVector renderInt(const ByteVector &name, const Item &item) const; @@ -151,7 +135,6 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { }; } // namespace MP4 - } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mpc/mpcfile.cpp b/3rdparty/taglib/mpc/mpcfile.cpp index b76845381..01c212bd6 100644 --- a/3rdparty/taglib/mpc/mpcfile.cpp +++ b/3rdparty/taglib/mpc/mpcfile.cpp @@ -48,10 +48,10 @@ class MPC::File::FilePrivate { FilePrivate() : APELocation(-1), APESize(0), ID3v1Location(-1), - ID3v2Header(0), + ID3v2Header(nullptr), ID3v2Location(-1), ID3v2Size(0), - properties(0) {} + properties(nullptr) {} ~FilePrivate() { delete ID3v2Header; @@ -77,27 +77,31 @@ class MPC::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool MPC::File::isSupported(IOStream *stream) { + // A newer MPC file has to start with "MPCK" or "MP+", but older files don't // have keys to do a quick check. const ByteVector id = Utils::readHeader(stream, 4, false); return (id == "MPCK" || id.startsWith("MP+")); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate()) { +MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } -MPC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate()) { +MPC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } MPC::File::~File() { @@ -128,6 +132,7 @@ MPC::Properties *MPC::File::audioProperties() const { } bool MPC::File::save() { + if (readOnly()) { debug("MPC::File::save() -- File is read only."); return false; @@ -211,6 +216,7 @@ bool MPC::File::save() { } return true; + } ID3v1::Tag *MPC::File::ID3v1Tag(bool create) { @@ -222,23 +228,21 @@ APE::Tag *MPC::File::APETag(bool create) { } void MPC::File::strip(int tags) { + if (tags & ID3v1) - d->tag.set(MPCID3v1Index, 0); + d->tag.set(MPCID3v1Index, nullptr); if (tags & APE) - d->tag.set(MPCAPEIndex, 0); + d->tag.set(MPCAPEIndex, nullptr); if (!ID3v1Tag()) APETag(true); if (tags & ID3v2) { delete d->ID3v2Header; - d->ID3v2Header = 0; + d->ID3v2Header = nullptr; } -} -void MPC::File::remove(int tags) { - strip(tags); } bool MPC::File::hasID3v1Tag() const { @@ -254,6 +258,7 @@ bool MPC::File::hasAPETag() const { //////////////////////////////////////////////////////////////////////////////// void MPC::File::read(bool readProperties) { + // Look for an ID3v2 tag d->ID3v2Location = Utils::findID3v2(this); @@ -307,4 +312,5 @@ void MPC::File::read(bool readProperties) { d->properties = new Properties(this, streamLength); } + } diff --git a/3rdparty/taglib/mpc/mpcfile.h b/3rdparty/taglib/mpc/mpcfile.h index 7931a7066..a24610873 100644 --- a/3rdparty/taglib/mpc/mpcfile.h +++ b/3rdparty/taglib/mpc/mpcfile.h @@ -49,31 +49,27 @@ class Tag; //! An implementation of MPC metadata /*! - * This is implementation of MPC metadata. - * - * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream - * properties from the file. ID3v2 tags are invalid in MPC-files, but will be skipped - * and ignored. - */ + * This is implementation of MPC metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream properties from the file. + * ID3v2 tags are invalid in MPC-files, but will be skipped and ignored. + * + */ namespace MPC { //! An implementation of TagLib::File with MPC specific methods /*! - * This implements and provides an interface for MPC files to the - * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing - * the abstract TagLib::File API as well as providing some additional - * information specific to MPC files. - * The only invalid tag combination supported is an ID3v1 tag after an APE tag. - */ + * This implements and provides an interface for MPC files to the TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing the abstract TagLib::File API as well as providing some additional information specific to MPC files. + * The only invalid tag combination supported is an ID3v1 tag after an APE tag. + */ 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. - */ + * 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, @@ -88,143 +84,124 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { }; /*! - * Constructs an MPC file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(FileName file, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs an MPC file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs an MPC file from \a stream. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(IOStream *stream, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs an MPC file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag - * or a combination of the two. - */ + * Returns the Tag for this file. + * This will be an APE tag, an ID3v1 tag or a combination of the two. + */ virtual Strawberry_TagLib::TagLib::Tag *tag() const; /*! - * Implements the unified property interface -- export function. - * If the file contains both an APE and an ID3v1 tag, only the APE - * tag will be converted to the PropertyMap. - */ + * Implements the unified property interface -- export function. + * If the file contains both an APE and an ID3v1 tag, only the APE tag will be converted to the PropertyMap. + */ PropertyMap properties() const; void removeUnsupportedProperties(const StringList &properties); /*! - * Implements the unified property interface -- import function. - * Affects only the APEv2 tag which will be created if necessary. - * If an ID3v1 tag exists, it will be updated as well. - */ + * Implements the unified property interface -- import function. + * Affects only the APEv2 tag which will be created if necessary. + * If an ID3v1 tag exists, it will be updated as well. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the MPC::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the MPC::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Saves the file. - * - * This returns true if the save was successful. - */ + * Saves the file. + * + * This returns true if the save was successful. + */ virtual bool save(); /*! - * Returns a pointer to the ID3v1 tag of the file. - * - * If \a create is false (the default) this returns a null pointer - * if there is no valid APE tag. If \a create is true it will create - * an APE tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file - * on disk actually has an ID3v1 tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasID3v1Tag() - */ + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this returns a null pointer if there is no valid APE tag. + * If \a create is true it will create an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v1 tag. + * Use hasID3v1Tag() to check if the file on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasID3v1Tag() + */ 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 - * if there is no valid APE tag. If \a create is true it will create - * an APE tag if one does not exist and returns a valid pointer. If - * there already be an ID3v1 tag, the new APE tag will be placed before it. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an APE tag. Use hasAPETag() to check if the file - * on disk actually has an APE tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasAPETag() - */ + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid APE tag. + * If \a create is true it will create an APE tag if one does not exist and returns a valid pointer. + * If there already be an ID3v1 tag, the new APE tag will be placed before it. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an APE tag. + * Use hasAPETag() to check if the file on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasAPETag() + */ APE::Tag *APETag(bool create = false); /*! - * This will remove the tags that match the OR-ed together TagTypes from the - * file. By default it removes all tags. - * - * \warning This will also invalidate pointers to the tags - * as their memory will be freed. - * - * \note In order to make the removal permanent save() still needs to be called. - */ + * This will remove the tags that match the OR-ed together TagTypes from the file. By default it removes all tags. + * + * \warning This will also invalidate pointers to the tags as their memory will be freed. + * + * \note In order to make the removal permanent save() still needs to be called. + */ void strip(int tags = AllTags); /*! - * \deprecated - * \see strip - */ - TAGLIB_DEPRECATED void remove(int tags = AllTags); - - /*! - * Returns whether or not the file on disk actually has an ID3v1 tag. - * - * \see ID3v1Tag() - */ + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ bool hasID3v1Tag() const; /*! - * Returns whether or not the file on disk actually has an APE tag. - * - * \see APETag() - */ + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ bool hasAPETag() const; /*! - * Returns whether or not the given \a stream can be opened as an MPC - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as an MPC file. + * + * \note This method is designed to do a quick check. The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: diff --git a/3rdparty/taglib/mpc/mpcproperties.cpp b/3rdparty/taglib/mpc/mpcproperties.cpp index cd551dc88..d0c2161c4 100644 --- a/3rdparty/taglib/mpc/mpcproperties.cpp +++ b/3rdparty/taglib/mpc/mpcproperties.cpp @@ -64,13 +64,12 @@ class MPC::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { readSV7(data, streamLength); } -MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { + ByteVector magic = file->readBlock(4); if (magic == "MPCK") { // Musepack version 8 @@ -80,16 +79,13 @@ MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) : Au // Musepack version 7 or older, fixed size header readSV7(magic + file->readBlock(MPC::HeaderSize - 4), streamLength); } + } MPC::Properties::~Properties() { delete d; } -int MPC::Properties::length() const { - return lengthInSeconds(); -} - int MPC::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -144,6 +140,7 @@ int MPC::Properties::albumPeak() const { namespace { unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof) { + sizeLength = 0; eof = false; @@ -160,19 +157,26 @@ unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof) { tmp = b[0]; size = (size << 7) | (tmp & 0x7F); sizeLength++; - } while ((tmp & 0x80)); + } + while ((tmp & 0x80)); + return size; + } unsigned long readSize(const ByteVector &data, unsigned int &pos) { + unsigned char tmp; unsigned long size = 0; do { tmp = data[pos++]; size = (size << 7) | (tmp & 0x7F); - } while ((tmp & 0x80) && (pos < data.size())); + } + while ((tmp & 0x80) && (pos < data.size())); + return size; + } // This array looks weird, but the same as original MusePack code found at: @@ -181,6 +185,7 @@ const unsigned short sftable[8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 }; } // namespace void MPC::Properties::readSV8(File *file, long streamLength) { + bool readSH = false, readRG = false; while (!readSH && !readRG) { @@ -269,9 +274,11 @@ void MPC::Properties::readSV8(File *file, long streamLength) { file->seek(dataSize, File::Current); } } + } void MPC::Properties::readSV7(const ByteVector &data, long streamLength) { + if (data.startsWith("MP+")) { d->version = data[3] & 15; if (d->version < 7) @@ -340,4 +347,5 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength) { if (d->bitrate == 0) d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); } + } diff --git a/3rdparty/taglib/mpc/mpcproperties.h b/3rdparty/taglib/mpc/mpcproperties.h index 857351a69..bef35c416 100644 --- a/3rdparty/taglib/mpc/mpcproperties.h +++ b/3rdparty/taglib/mpc/mpcproperties.h @@ -41,105 +41,92 @@ static const unsigned int HeaderSize = 8 * 7; //! An implementation of audio property reading for MPC /*! - * This reads the data from an MPC stream found in the AudioProperties - * API. - */ + * This reads the data from an MPC stream found in the AudioProperties API. + */ class TAGLIB_EXPORT Properties : public AudioProperties { public: /*! - * Create an instance of MPC::Properties with the data read from the - * ByteVector \a data. - * - * This constructor is deprecated. It only works for MPC version up to 7. - */ + * Create an instance of MPC::Properties with the data read from the ByteVector \a data. + * + * This constructor is deprecated. It only works for MPC version up to 7. + */ Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); /*! - * Create an instance of MPC::Properties with the data read directly - * from a MPC::File. - */ + * Create an instance of MPC::Properties with the data read directly from a MPC::File. + */ Properties(File *file, long streamLength, ReadStyle style = Average); /*! - * Destroys this MPC::Properties instance. - */ + * Destroys this MPC::Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - TAGLIB_DEPRECATED virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the version of the bitstream (SV4-SV8) - */ + * Returns the version of the bitstream (SV4-SV8) + */ int mpcVersion() const; unsigned int totalFrames() const; unsigned int sampleFrames() const; /*! - * Returns the track gain as an integer value, - * to convert to dB: trackGain in dB = 64.82 - (trackGain / 256) - */ + * Returns the track gain as an integer value, + * to convert to dB: trackGain in dB = 64.82 - (trackGain / 256) + */ int trackGain() const; /*! - * Returns the track peak as an integer value, - * to convert to dB: trackPeak in dB = trackPeak / 256 - * to convert to floating [-1..1]: trackPeak = 10^(trackPeak / 256 / 20)/32768 - */ + * Returns the track peak as an integer value, + * to convert to dB: trackPeak in dB = trackPeak / 256 + * to convert to floating [-1..1]: trackPeak = 10^(trackPeak / 256 / 20)/32768 + */ int trackPeak() const; /*! - * Returns the album gain as an integer value, - * to convert to dB: albumGain in dB = 64.82 - (albumGain / 256) - */ + * Returns the album gain as an integer value, + * to convert to dB: albumGain in dB = 64.82 - (albumGain / 256) + */ int albumGain() const; /*! - * Returns the album peak as an integer value, - * to convert to dB: albumPeak in dB = albumPeak / 256 - * to convert to floating [-1..1]: albumPeak = 10^(albumPeak / 256 / 20)/32768 - */ + * Returns the album peak as an integer value, + * to convert to dB: albumPeak in dB = albumPeak / 256 + * to convert to floating [-1..1]: albumPeak = 10^(albumPeak / 256 / 20)/32768 + */ int albumPeak() const; private: diff --git a/3rdparty/taglib/mpeg/id3v1/id3v1genres.cpp b/3rdparty/taglib/mpeg/id3v1/id3v1genres.cpp index 652e0d96a..b22e89926 100644 --- a/3rdparty/taglib/mpeg/id3v1/id3v1genres.cpp +++ b/3rdparty/taglib/mpeg/id3v1/id3v1genres.cpp @@ -226,35 +226,43 @@ const int genresSize = sizeof(genres) / sizeof(genres[0]); } // namespace StringList ID3v1::genreList() { + StringList l; for (int i = 0; i < genresSize; i++) { l.append(genres[i]); } return l; + } ID3v1::GenreMap ID3v1::genreMap() { + GenreMap m; 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 else return String(); + } int ID3v1::genreIndex(const String &name) { + for (int i = 0; i < genresSize; ++i) { if (name == genres[i]) return i; } return 255; + } diff --git a/3rdparty/taglib/mpeg/id3v1/id3v1genres.h b/3rdparty/taglib/mpeg/id3v1/id3v1genres.h index 5f8bbffa3..1ae5a4bba 100644 --- a/3rdparty/taglib/mpeg/id3v1/id3v1genres.h +++ b/3rdparty/taglib/mpeg/id3v1/id3v1genres.h @@ -37,29 +37,25 @@ namespace ID3v1 { typedef Map GenreMap; /*! - * Returns the list of canonical ID3v1 genre names in the order that they - * are listed in the standard. - */ + * Returns the list of canonical ID3v1 genre names in the order that they are listed in the standard. + */ StringList TAGLIB_EXPORT genreList(); /*! - * A "reverse mapping" that goes from the canonical ID3v1 genre name to the - * respective genre number. genreMap()["Rock"] == - */ + * A "reverse mapping" that goes from the canonical ID3v1 genre name to the respective genre number. genreMap()["Rock"] == + */ 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. - */ + * 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); /*! - * 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. - */ + * 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); } // namespace ID3v1 } // namespace TagLib diff --git a/3rdparty/taglib/mpeg/id3v1/id3v1tag.cpp b/3rdparty/taglib/mpeg/id3v1/id3v1tag.cpp index 78348287d..d75c74f77 100644 --- a/3rdparty/taglib/mpeg/id3v1/id3v1tag.cpp +++ b/3rdparty/taglib/mpeg/id3v1/id3v1tag.cpp @@ -39,7 +39,7 @@ const ID3v1::StringHandler *stringHandler = &defaultStringHandler; class ID3v1::Tag::TagPrivate { public: - TagPrivate() : file(0), + TagPrivate() : file(nullptr), tagOffset(0), track(0), genre(255) {} @@ -68,22 +68,22 @@ String ID3v1::StringHandler::parse(const ByteVector &data) const { } ByteVector ID3v1::StringHandler::render(const String &s) const { + if (s.isLatin1()) return s.data(String::Latin1); else return ByteVector(); + } //////////////////////////////////////////////////////////////////////////////// // 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; @@ -95,6 +95,7 @@ ID3v1::Tag::~Tag() { } ByteVector ID3v1::Tag::render() const { + ByteVector data; data.append(fileIdentifier()); @@ -108,6 +109,7 @@ ByteVector ID3v1::Tag::render() const { data.append(char(d->genre)); return data; + } ByteVector ID3v1::Tag::fileIdentifier() { @@ -190,6 +192,7 @@ void ID3v1::Tag::setStringHandler(const StringHandler *handler) { //////////////////////////////////////////////////////////////////////////////// void ID3v1::Tag::read() { + if (d->file && d->file->isValid()) { d->file->seek(d->tagOffset); // read the tag -- always 128 bytes @@ -201,9 +204,11 @@ void ID3v1::Tag::read() { else debug("ID3v1 tag is not valid or could not be read at the specified offset."); } + } void ID3v1::Tag::parse(const ByteVector &data) { + int offset = 3; d->title = stringHandler->parse(data.mid(offset, 30)); @@ -235,4 +240,5 @@ void ID3v1::Tag::parse(const ByteVector &data) { offset += 30; d->genre = static_cast(data[offset]); + } diff --git a/3rdparty/taglib/mpeg/id3v1/id3v1tag.h b/3rdparty/taglib/mpeg/id3v1/id3v1tag.h index 114cc408c..325ba24e6 100644 --- a/3rdparty/taglib/mpeg/id3v1/id3v1tag.h +++ b/3rdparty/taglib/mpeg/id3v1/id3v1tag.h @@ -42,94 +42,86 @@ namespace ID3v1 { //! 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. - * - * However by subclassing this class and reimplementing parse() and render() - * and setting your reimplementation as the default with - * ID3v1::Tag::setStringHandler() you can define how you would like these - * transformations to be done. - * - * \warning It is advisable not to write non-ISO-8859-1 data to ID3v1 - * tags. Please consider disabling the writing of ID3v1 tags in the case - * that the data is not ISO-8859-1. - * - * \see ID3v1::Tag::setStringHandler() - */ + * 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. + * + * However by subclassing this class and reimplementing parse() and render() and setting your reimplementation as the default with + * ID3v1::Tag::setStringHandler() you can define how you would like these transformations to be done. + * + * \warning It is advisable not to write non-ISO-8859-1 data to ID3v1 tags. + * Please consider disabling the writing of ID3v1 tags in the case that the data is not ISO-8859-1. + * + * \see ID3v1::Tag::setStringHandler() + */ 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. - */ + * 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; /*! - * 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. - * - * \warning It is recommended that you not override this method, but - * instead do not write an ID3v1 tag in the case that the data is not - * ISO-8859-1. - */ + * 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. + * + * \warning It is recommended that you not override this method, but + * 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; }; //! 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 - * fields that it provides, the generic TagLib::Tag API is a mirror of what is - * provided by ID3v1. - * - * ID3v1 tags should generally only contain Latin1 information. However because - * many applications do not follow this rule there is now support for overriding - * the ID3v1 string handling using the ID3v1::StringHandler class. Please see - * the documentation for that class for more information. - * - * \see StringHandler - * - * \note Most fields are truncated to a maximum of 28-30 bytes. The - * truncation happens automatically when the tag is rendered. - */ + * 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 + * fields that it provides, the generic TagLib::Tag API is a mirror of what is provided by ID3v1. + * + * ID3v1 tags should generally only contain Latin1 information. + * However because many applications do not follow this rule there is now support for overriding + * the ID3v1 string handling using the ID3v1::StringHandler class. + * Please see the documentation for that class for more information. + * + * \see StringHandler + * + * \note Most fields are truncated to a maximum of 28-30 bytes. + * The truncation happens automatically when the tag is rendered. + */ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { public: /*! - * Create an ID3v1 tag with default values. - */ + * Create an ID3v1 tag with default values. + */ Tag(); /*! - * Create an ID3v1 tag and parse the data in \a file starting at - * \a tagOffset. - */ + * Create an ID3v1 tag and parse the data in \a file starting at \a tagOffset. + */ Tag(File *file, long tagOffset); /*! - * Destroys this Tag instance. - */ + * Destroys this Tag instance. + */ virtual ~Tag(); /*! - * Renders the in memory values to a ByteVector suitable for writing to - * the file. - */ + * Renders the in memory values to a ByteVector suitable for writing to the file. + */ ByteVector render() const; /*! - * Returns the string "TAG" suitable for usage in locating the tag in a - * file. - */ + * Returns the string "TAG" suitable for usage in locating the tag in a file. + */ static ByteVector fileIdentifier(); // Reimplementations. @@ -151,41 +143,37 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { virtual void setTrack(unsigned int i); /*! - * Returns the genre in number. - * - * \note Normally 255 indicates that this tag contains no genre. - */ + * Returns the genre in number. + * + * \note Normally 255 indicates that this tag contains no genre. + */ 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. - */ + * 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); /*! - * 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 - * released and default ISO-8859-1 handler is restored. - * - * \note The caller is responsible for deleting the previous handler - * as needed after it is released. - * - * \see StringHandler - */ + * 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 released and default ISO-8859-1 handler is restored. + * + * \note The caller is responsible for deleting the previous handler as needed after it is released. + * + * \see StringHandler + */ static void setStringHandler(const StringHandler *handler); protected: /*! - * Reads from the file specified in the constructor. - */ + * Reads from the file specified in the constructor. + */ void read(); /*! - * Pareses the body of the tag in \a data. - */ + * Pareses the body of the tag in \a data. + */ void parse(const ByteVector &data); private: @@ -195,6 +183,7 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { class TagPrivate; TagPrivate *d; }; + } // namespace ID3v1 } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp index 85e44df5a..762a38494 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp @@ -33,8 +33,7 @@ using namespace ID3v2; class AttachedPictureFrame::AttachedPictureFramePrivate { public: - AttachedPictureFramePrivate() : textEncoding(String::Latin1), - type(AttachedPictureFrame::Other) {} + AttachedPictureFramePrivate() : textEncoding(String::Latin1), type(AttachedPictureFrame::Other) {} String::Type textEncoding; String mimeType; @@ -47,12 +46,9 @@ class AttachedPictureFrame::AttachedPictureFramePrivate { // 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); } @@ -110,6 +106,7 @@ void AttachedPictureFrame::setPicture(const ByteVector &p) { //////////////////////////////////////////////////////////////////////////////// void AttachedPictureFrame::parseFields(const ByteVector &data) { + if (data.size() < 5) { debug("A picture frame must contain at least 5 bytes."); return; @@ -130,9 +127,11 @@ void AttachedPictureFrame::parseFields(const ByteVector &data) { d->description = readStringField(data, d->textEncoding, &pos); d->data = data.mid(pos); + } ByteVector AttachedPictureFrame::renderFields() const { + ByteVector data; String::Type encoding = checkTextEncoding(d->description, d->textEncoding); @@ -146,14 +145,14 @@ ByteVector AttachedPictureFrame::renderFields() const { data.append(d->data); return data; + } //////////////////////////////////////////////////////////////////////////////// // 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)); } @@ -162,6 +161,7 @@ AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) : //////////////////////////////////////////////////////////////////////////////// void AttachedPictureFrameV22::parseFields(const ByteVector &data) { + if (data.size() < 5) { debug("A picture frame must contain at least 5 bytes."); return; @@ -189,9 +189,11 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data) { d->description = readStringField(data, d->textEncoding, &pos); d->data = data.mid(pos); + } AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header *h) { + // set v2.2 header to make fieldData work correctly setHeader(h, true); @@ -201,4 +203,5 @@ AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header Frame::Header *newHeader = new Frame::Header("APIC"); newHeader->setFrameSize(h->frameSize()); setHeader(newHeader, true); + } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/attachedpictureframe.h b/3rdparty/taglib/mpeg/id3v2/frames/attachedpictureframe.h index be5e314dd..4ca003e23 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/attachedpictureframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/attachedpictureframe.h @@ -32,25 +32,23 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! 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. - */ + * 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; public: /*! - * This describes the function or content of the picture. - */ + * This describes the function or content of the picture. + */ enum Type { //! A type not enumerated below Other = 0x00, @@ -97,108 +95,106 @@ class TAGLIB_EXPORT AttachedPictureFrame : public Frame { }; /*! - * Constructs an empty picture frame. The description, content and text - * encoding should be set manually. - */ + * Constructs an empty picture frame. + * The description, content and text encoding should be set manually. + */ AttachedPictureFrame(); /*! - * Constructs an AttachedPicture frame based on \a data. - */ + * Constructs an AttachedPicture frame based on \a data. + */ explicit AttachedPictureFrame(const ByteVector &data); /*! - * Destroys the AttahcedPictureFrame instance. - */ + * Destroys the AttahcedPictureFrame instance. + */ virtual ~AttachedPictureFrame(); /*! - * Returns a string containing the description and mime-type - */ + * Returns a string containing the description and mime-type + */ virtual String toString() const; /*! - * Returns the text encoding used for the description. - * - * \see setTextEncoding() - * \see description() - */ + * Returns the text encoding used for the description. + * + * \see setTextEncoding() + * \see description() + */ String::Type textEncoding() const; /*! - * Set the text encoding used for the description. - * - * \see description() - */ + * Set the text encoding used for the description. + * + * \see description() + */ void setTextEncoding(String::Type t); /*! - * Returns the mime type of the image. This should in most cases be - * "image/png" or "image/jpeg". - */ + * Returns the mime type of the image. + * This should in most cases be "image/png" or "image/jpeg". + */ String mimeType() const; /*! - * Sets the mime type of the image. This should in most cases be - * "image/png" or "image/jpeg". - */ + * Sets the mime type of the image. + * This should in most cases be "image/png" or "image/jpeg". + */ void setMimeType(const String &m); /*! - * Returns the type of the image. - * - * \see Type - * \see setType() - */ + * Returns the type of the image. + * + * \see Type + * \see setType() + */ Type type() const; /*! - * Sets the type for the image. - * - * \see Type - * \see type() - */ + * Sets the type for the image. + * + * \see Type + * \see type() + */ void setType(Type t); /*! - * Returns a text description of the image. - * - * \see setDescription() - * \see textEncoding() - * \see setTextEncoding() - */ + * Returns a text description of the image. + * + * \see setDescription() + * \see textEncoding() + * \see setTextEncoding() + */ String description() const; /*! - * Sets a textual description of the image to \a desc. - * - * \see description() - * \see textEncoding() - * \see setTextEncoding() - */ + * Sets a textual description of the image to \a desc. + * + * \see description() + * \see textEncoding() + * \see setTextEncoding() + */ void setDescription(const String &desc); /*! - * Returns the image data as a ByteVector. - * - * \note ByteVector has a data() method that returns a const char * which - * should make it easy to export this data to external programs. - * - * \see setPicture() - * \see mimeType() - */ + * Returns the image data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which should make it easy to export this data to external programs. + * + * \see setPicture() + * \see mimeType() + */ 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. - * - * \see picture() - * \see mimeType() - * \see setMimeType() - */ + * Sets the image data to \a p. \a p should be of the type specified in this frame's mime-type specification. + * + * \see picture() + * \see mimeType() + * \see setMimeType() + */ void setPicture(const ByteVector &p); protected: @@ -222,6 +218,7 @@ class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame { AttachedPictureFrameV22(const ByteVector &data, Header *h); friend class FrameFactory; }; + } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mpeg/id3v2/frames/chapterframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/chapterframe.cpp index 37498ace3..facd0defd 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/chapterframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/chapterframe.cpp @@ -35,7 +35,7 @@ using namespace ID3v2; class ChapterFrame::ChapterFramePrivate { public: - ChapterFramePrivate() : tagHeader(0), + ChapterFramePrivate() : tagHeader(nullptr), startTime(0), endTime(0), startOffset(0), @@ -57,19 +57,14 @@ class ChapterFrame::ChapterFramePrivate { // 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()) { - // setElementID has a workaround for a previously silly API where you had to - // specifically include the null byte. +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()) { + + // setElementID has a workaround for a previously silly API where you had to specifically include the null byte. setElementID(elementID); @@ -82,6 +77,7 @@ ChapterFrame::ChapterFrame(const ByteVector &elementID, it != embeddedFrames.end(); ++it) addEmbeddedFrame(*it); + } ChapterFrame::~ChapterFrame() { @@ -109,10 +105,12 @@ unsigned int ChapterFrame::endOffset() const { } void ChapterFrame::setElementID(const ByteVector &eID) { + d->elementID = eID; if (d->elementID.endsWith(char(0))) d->elementID = d->elementID.mid(0, d->elementID.size() - 1); + } void ChapterFrame::setStartTime(const unsigned int &sT) { @@ -149,6 +147,7 @@ void ChapterFrame::addEmbeddedFrame(Frame *frame) { } 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); @@ -160,15 +159,19 @@ void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del) { // ...and delete as desired if (del) delete frame; + } void ChapterFrame::removeEmbeddedFrames(const ByteVector &id) { + FrameList l = d->embeddedFrameListMap[id]; for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) removeEmbeddedFrame(*it, true); + } String ChapterFrame::toString() const { + String s = String(d->elementID) + ": start time: " + String::number(d->startTime) + ", end time: " + String::number(d->endTime); @@ -189,18 +192,21 @@ String ChapterFrame::toString() const { } return s; + } PropertyMap ChapterFrame::asProperties() const { + PropertyMap map; map.unsupportedData().append(frameID() + String("/") + d->elementID); 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(); @@ -212,9 +218,11 @@ ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVec } return nullptr; + } void ChapterFrame::parseFields(const ByteVector &data) { + unsigned int size = data.size(); if (size < 18) { debug("A CHAP frame must contain at least 18 bytes (1 byte element ID " @@ -255,9 +263,11 @@ void ChapterFrame::parseFields(const ByteVector &data) { embPos += frame->size() + header()->size(); addEmbeddedFrame(frame); } + } ByteVector ChapterFrame::renderFields() const { + ByteVector data; data.append(d->elementID); @@ -271,10 +281,12 @@ ByteVector ChapterFrame::renderFields() const { 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)); + } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/chapterframe.h b/3rdparty/taglib/mpeg/id3v2/frames/chapterframe.h index 3ea060385..dab0bf560 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/chapterframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/chapterframe.h @@ -32,13 +32,12 @@ namespace Strawberry_TagLib { namespace TagLib { - 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. - */ + * 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 @@ -47,175 +46,162 @@ class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame { public: /*! - * Creates a chapter frame based on \a data. \a tagHeader is required as - * the internal frames are parsed based on the tag version. - */ + * 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); /*! - * 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, - * whose ownership will then be taken over by this Frame, in - * \a embeededFrames; - * - * All times are in milliseconds. - */ + * 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, + * whose ownership will then be taken over by this Frame, in \a embeededFrames; + * + * 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()); /*! - * Destroys the frame. - */ + * Destroys the frame. + */ virtual ~ChapterFrame(); /*! - * Returns the element ID of the frame. Element ID - * is a null terminated string, however it's not human-readable. - * - * \see setElementID() - */ + * 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; /*! - * Returns time of chapter's start (in milliseconds). - * - * \see setStartTime() - */ + * Returns time of chapter's start (in milliseconds). + * + * \see setStartTime() + */ unsigned int startTime() const; /*! - * Returns time of chapter's end (in milliseconds). - * - * \see setEndTime() - */ + * Returns time of chapter's end (in milliseconds). + * + * \see setEndTime() + */ 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() - */ + * 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; /*! - * 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() - */ + * 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; /*! - * 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() - */ + * 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); /*! - * Sets time of chapter's start (in milliseconds) to \a sT. - * - * \see startTime() - */ + * Sets time of chapter's start (in milliseconds) to \a sT. + * + * \see startTime() + */ void setStartTime(const unsigned int &sT); /*! - * Sets time of chapter's end (in milliseconds) to \a eT. - * - * \see endTime() - */ + * Sets time of chapter's end (in milliseconds) to \a eT. + * + * \see endTime() + */ 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() - */ + * 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); /*! - * Sets zero based byte offset (count of bytes from the beginning - * of the audio file) of chapter's end to \a eO. - * - * \see endOffset() - */ + * 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); /*! - * Returns a reference to the frame list map. This is an FrameListMap of - * all of the frames embedded in the CHAP frame. - * - * This is the most convenient structure for accessing the CHAP frame's - * embedded frames. Many frame types allow multiple instances of the same - * frame type so this is a map of lists. In most cases however there will - * only be a single frame of a certain type. - * - * \warning You should not modify this data structure directly, instead - * use addEmbeddedFrame() and removeEmbeddedFrame(). - * - * \see embeddedFrameList() - */ + * Returns a reference to the frame list map. + * This is an FrameListMap of all of the frames embedded in the CHAP frame. + * + * This is the most convenient structure for accessing the CHAP frame's embedded frames. + * Many frame types allow multiple instances of the same rame type so this is a map of lists. + * In most cases however there will only be a single frame of a certain type. + * + * \warning You should not modify this data structure directly, instead + * use addEmbeddedFrame() and removeEmbeddedFrame(). + * + * \see embeddedFrameList() + */ 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. - * - * This can be useful if for example you want iterate over the CHAP frame's - * embedded frames in the order that they occur in the CHAP frame. - * - * \warning You should not modify this data structure directly, instead - * use addEmbeddedFrame() and removeEmbeddedFrame(). - */ + * 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. + * + * This can be useful if for example you want iterate over the CHAP frame's + * embedded frames in the order that they occur in the CHAP frame. + * + * \warning You should not modify this data structure directly, + * instead use addEmbeddedFrame() and removeEmbeddedFrame(). + */ 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: - * - * \code - * embeddedFrameListMap()[frameID]; - * \endcode - * - * \see embeddedFrameListMap() - */ + * 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: + * + * \code + * embeddedFrameListMap()[frameID]; + * \endcode + * + * \see embeddedFrameListMap() + */ 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() - */ + * 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); /*! - * 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() - */ + * 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); /*! - * 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() - */ + * 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); virtual String toString() const; @@ -223,12 +209,11 @@ class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame { 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() - */ + * 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); protected: @@ -243,6 +228,7 @@ class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame { class ChapterFramePrivate; ChapterFramePrivate *d; }; + } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mpeg/id3v2/frames/commentsframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/commentsframe.cpp index 03cafec61..25172f956 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/commentsframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/commentsframe.cpp @@ -47,13 +47,11 @@ class CommentsFrame::CommentsFramePrivate { // 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); } @@ -98,6 +96,7 @@ void CommentsFrame::setTextEncoding(String::Type encoding) { } PropertyMap CommentsFrame::asProperties() const { + String key = description().upper(); PropertyMap map; if (key.isEmpty() || key == "COMMENT") @@ -105,10 +104,11 @@ PropertyMap CommentsFrame::asProperties() const { 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(); @@ -120,6 +120,7 @@ CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const Str } return nullptr; + } //////////////////////////////////////////////////////////////////////////////// @@ -127,6 +128,7 @@ CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const Str //////////////////////////////////////////////////////////////////////////////// void CommentsFrame::parseFields(const ByteVector &data) { + if (data.size() < 5) { debug("A comment frame must contain at least 5 bytes."); return; @@ -149,9 +151,11 @@ void CommentsFrame::parseFields(const ByteVector &data) { d->text = String(l.back(), d->textEncoding); } } + } ByteVector CommentsFrame::renderFields() const { + ByteVector v; String::Type encoding = d->textEncoding; @@ -166,13 +170,13 @@ ByteVector CommentsFrame::renderFields() const { v.append(d->text.data(encoding)); return v; + } //////////////////////////////////////////////////////////////////////////////// // 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)); } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/commentsframe.h b/3rdparty/taglib/mpeg/id3v2/frames/commentsframe.h index e753c07d7..c0fabfbd5 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/commentsframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/commentsframe.h @@ -31,129 +31,124 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! 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. - */ + * 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; public: /*! - * Construct an empty comment frame that will use the text encoding - * \a encoding. - */ + * Construct an empty comment frame that will use the text encoding \a encoding. + */ explicit CommentsFrame(String::Type encoding = String::Latin1); /*! - * Construct a comment based on the data in \a data. - */ + * Construct a comment based on the data in \a data. + */ explicit CommentsFrame(const ByteVector &data); /*! - * Destroys this CommentFrame instance. - */ + * Destroys this CommentFrame instance. + */ virtual ~CommentsFrame(); /*! - * Returns the text of this comment. - * - * \see text() - */ + * Returns the text of this comment. + * + * \see text() + */ virtual String toString() const; /*! - * Returns the language encoding as a 3 byte encoding as specified by - * ISO-639-2. - * - * \note Most taggers simply ignore this value. - * - * \see setLanguage() - */ + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ ByteVector language() const; /*! - * Returns the description of this comment. - * - * \note Most taggers simply ignore this value. - * - * \see setDescription() - */ + * Returns the description of this comment. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ String description() const; /*! - * Returns the text of this comment. - * - * \see setText() - */ + * Returns the text of this comment. + * + * \see setText() + */ String text() const; /*! - * Set the language using the 3 byte language code from - * ISO-639-2 to - * \a languageCode. - * - * \see language() - */ + * Set the language using the 3 byte language code from + * ISO-639-2 to \a languageCode. + * + * \see language() + */ void setLanguage(const ByteVector &languageCode); /*! - * Sets the description of the comment to \a s. - * - * \see description() - */ + * Sets the description of the comment to \a s. + * + * \see description() + */ void setDescription(const String &s); /*! - * Sets the text portion of the comment to \a s. - * - * \see text() - */ + * Sets the text portion of the comment to \a s. + * + * \see text() + */ 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. - * - * \see setTextEncoding() - * \see render() - */ + * 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. + * + * \see setTextEncoding() + * \see render() + */ String::Type textEncoding() const; /*! - * Sets the text encoding to be used when rendering this frame to - * \a encoding. - * - * \see textEncoding() - * \see render() - */ + * Sets the text encoding to be used when rendering this frame to \a encoding. + * + * \see textEncoding() + * \see render() + */ 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 - * marked unsupported by an entry "COMM/" in the unsupportedData() - * attribute of the returned map. - * - otherwise, the key will be "COMMENT:" - * - The single value will be the frame's text(). - */ + * 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 + * marked unsupported by an entry "COMM/" in the unsupportedData() + * attribute of the returned map. + * - otherwise, the key will be "COMMENT:" + * - The single value will be the frame's text(). + */ 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() - */ + * 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); protected: @@ -164,8 +159,8 @@ class TAGLIB_EXPORT CommentsFrame : public Frame { private: /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ CommentsFrame(const ByteVector &data, Header *h); CommentsFrame(const CommentsFrame &); CommentsFrame &operator=(const CommentsFrame &); @@ -177,4 +172,5 @@ class TAGLIB_EXPORT CommentsFrame : public Frame { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/frames/eventtimingcodesframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/eventtimingcodesframe.cpp index 4078e54e3..062bda4f5 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/eventtimingcodesframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/eventtimingcodesframe.cpp @@ -43,12 +43,9 @@ class EventTimingCodesFrame::EventTimingCodesFramePrivate { // 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); } @@ -85,6 +82,7 @@ void EventTimingCodesFrame::setSynchedEvents( //////////////////////////////////////////////////////////////////////////////// void EventTimingCodesFrame::parseFields(const ByteVector &data) { + const int end = data.size(); if (end < 1) { debug("An event timing codes frame must contain at least 1 byte."); @@ -101,28 +99,28 @@ void EventTimingCodesFrame::parseFields(const ByteVector &data) { pos += 4; d->synchedEvents.append(SynchedEvent(time, type)); } + } 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)); } return v; + } //////////////////////////////////////////////////////////////////////////////// // 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)); } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/eventtimingcodesframe.h b/3rdparty/taglib/mpeg/id3v2/frames/eventtimingcodesframe.h index 3334c8f64..97bb2e6a5 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/eventtimingcodesframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/eventtimingcodesframe.h @@ -31,20 +31,19 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! ID3v2 event timing codes frame /*! - * An implementation of ID3v2 event timing codes. - */ + * An implementation of ID3v2 event timing codes. + */ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame { friend class FrameFactory; public: /*! - * Specifies the timestamp format used. - */ + * Specifies the timestamp format used. + */ enum TimestampFormat { //! The timestamp is of unknown format. Unknown = 0x00, @@ -57,8 +56,8 @@ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame { }; /*! - * Event types defined in id3v2.4.0-frames.txt 4.5. Event timing codes. - */ + * Event types defined in id3v2.4.0-frames.txt 4.5. Event timing codes. + */ enum EventType { Padding = 0x00, EndOfInitialSilence = 0x01, @@ -104,8 +103,8 @@ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame { }; /*! - * Single entry of time stamp and event. - */ + * Single entry of time stamp and event. + */ struct SynchedEvent { SynchedEvent(unsigned int ms, EventType t) : time(ms), type(t) {} unsigned int time; @@ -113,52 +112,52 @@ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame { }; /*! - * List of synchronized events. - */ + * List of synchronized events. + */ typedef Strawberry_TagLib::TagLib::List SynchedEventList; /*! - * Construct an empty event timing codes frame. - */ + * Construct an empty event timing codes frame. + */ explicit EventTimingCodesFrame(); /*! - * Construct a event timing codes frame based on the data in \a data. - */ + * Construct a event timing codes frame based on the data in \a data. + */ explicit EventTimingCodesFrame(const ByteVector &data); /*! - * Destroys this EventTimingCodesFrame instance. - */ + * Destroys this EventTimingCodesFrame instance. + */ virtual ~EventTimingCodesFrame(); /*! - * Returns a null string. - */ + * Returns a null string. + */ virtual String toString() const; /*! - * Returns the timestamp format. - */ + * Returns the timestamp format. + */ TimestampFormat timestampFormat() const; /*! - * Returns the events with the time stamps. - */ + * Returns the events with the time stamps. + */ SynchedEventList synchedEvents() const; /*! - * Set the timestamp format. - * - * \see timestampFormat() - */ + * Set the timestamp format. + * + * \see timestampFormat() + */ void setTimestampFormat(TimestampFormat f); /*! - * Sets the text with the time stamps. - * - * \see text() - */ + * Sets the text with the time stamps. + * + * \see text() + */ void setSynchedEvents(const SynchedEventList &e); protected: @@ -169,8 +168,8 @@ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame { private: /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ EventTimingCodesFrame(const ByteVector &data, Header *h); EventTimingCodesFrame(const EventTimingCodesFrame &); EventTimingCodesFrame &operator=(const EventTimingCodesFrame &); @@ -182,4 +181,5 @@ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp index dffe30a06..344615a85 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp @@ -49,12 +49,9 @@ class GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFramePrivate { // 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); } @@ -63,6 +60,7 @@ GeneralEncapsulatedObjectFrame::~GeneralEncapsulatedObjectFrame() { } String GeneralEncapsulatedObjectFrame::toString() const { + String text = "[" + d->mimeType + "]"; if (!d->fileName.isEmpty()) @@ -72,6 +70,7 @@ String GeneralEncapsulatedObjectFrame::toString() const { text += " \"" + d->description + "\""; return text; + } String::Type GeneralEncapsulatedObjectFrame::textEncoding() const { @@ -119,6 +118,7 @@ void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data) { //////////////////////////////////////////////////////////////////////////////// void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data) { + if (data.size() < 4) { debug("An object frame must contain at least 4 bytes."); return; @@ -133,9 +133,11 @@ void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data) { d->description = readStringField(data, d->textEncoding, &pos); d->data = data.mid(pos); + } ByteVector GeneralEncapsulatedObjectFrame::renderFields() const { + StringList sl; sl.append(d->fileName); sl.append(d->description); @@ -154,13 +156,13 @@ ByteVector GeneralEncapsulatedObjectFrame::renderFields() const { data.append(d->data); return data; + } //////////////////////////////////////////////////////////////////////////////// // 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)); } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h b/3rdparty/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h index d814ce7da..196114096 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h @@ -35,129 +35,128 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! 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 - * labelled with a content description (which may be blank), a required - * mime-type, and a file name (may be blank). The content description - * uniquely identifies the GEOB frame in the tag. - */ + * 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 labelled with a content description (which may be blank), + * a required mime-type, and a file name (may be blank). + * The content description uniquely identifies the GEOB frame in the tag. + */ class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame { friend class FrameFactory; public: /*! - * Constructs an empty object frame. The description, file name and text - * encoding should be set manually. - */ + * Constructs an empty object frame. + * The description, file name and text encoding should be set manually. + */ 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. - */ + * 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); /*! - * Destroys the GeneralEncapsulatedObjectFrame instance. - */ + * Destroys the GeneralEncapsulatedObjectFrame instance. + */ virtual ~GeneralEncapsulatedObjectFrame(); /*! - * Returns a string containing the description, file name and mime-type - */ + * Returns a string containing the description, file name and mime-type + */ virtual String toString() const; /*! - * Returns the text encoding used for the description and file name. - * - * \see setTextEncoding() - * \see description() - * \see fileName() - */ + * Returns the text encoding used for the description and file name. + * + * \see setTextEncoding() + * \see description() + * \see fileName() + */ String::Type textEncoding() const; /*! - * Set the text encoding used for the description and file name. - * - * \see description() - * \see fileName() - */ + * Set the text encoding used for the description and file name. + * + * \see description() + * \see fileName() + */ void setTextEncoding(String::Type encoding); /*! - * Returns the mime type of the object. - */ + * Returns the mime type of the object. + */ String mimeType() const; /*! - * Sets the mime type of the object. - */ + * Sets the mime type of the object. + */ void setMimeType(const String &type); /*! - * Returns the file name of the object. - * - * \see setFileName() - */ + * Returns the file name of the object. + * + * \see setFileName() + */ String fileName() const; /*! - * Sets the file name for the object. - * - * \see fileName() - */ + * Sets the file name for the object. + * + * \see fileName() + */ void setFileName(const String &name); /*! - * Returns the content description of the object. - * - * \see setDescription() - * \see textEncoding() - * \see setTextEncoding() - */ + * Returns the content description of the object. + * + * \see setDescription() + * \see textEncoding() + * \see setTextEncoding() + */ String description() const; /*! - * Sets the content description of the object to \a desc. - * - * \see description() - * \see textEncoding() - * \see setTextEncoding() - */ + * Sets the content description of the object to \a desc. + * + * \see description() + * \see textEncoding() + * \see setTextEncoding() + */ void setDescription(const String &desc); /*! - * Returns the object data as a ByteVector. - * - * \note ByteVector has a data() method that returns a const char * which - * should make it easy to export this data to external programs. - * - * \see setObject() - * \see mimeType() - */ + * Returns the object data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setObject() + * \see mimeType() + */ 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. - * - * \see object() - * \see mimeType() - * \see setMimeType() - */ + * Sets the object data to \a data. + * \a data should be of the type specified in this frame's mime-type specification. + * + * \see object() + * \see mimeType() + * \see setMimeType() + */ void setObject(const ByteVector &object); protected: @@ -172,6 +171,7 @@ class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame { class GeneralEncapsulatedObjectFramePrivate; GeneralEncapsulatedObjectFramePrivate *d; }; + } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mpeg/id3v2/frames/ownershipframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/ownershipframe.cpp index dc4319602..e6e19186f 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/ownershipframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/ownershipframe.cpp @@ -44,13 +44,11 @@ class OwnershipFrame::OwnershipFramePrivate { // 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); } @@ -99,6 +97,7 @@ void OwnershipFrame::setTextEncoding(String::Type encoding) { //////////////////////////////////////////////////////////////////////////////// void OwnershipFrame::parseFields(const ByteVector &data) { + int pos = 0; // Get the text encoding @@ -123,9 +122,11 @@ void OwnershipFrame::parseFields(const ByteVector &data) { d->seller = Tag::latin1StringHandler()->parse(data.mid(pos)); else d->seller = String(data.mid(pos), d->textEncoding); + } ByteVector OwnershipFrame::renderFields() const { + StringList sl; sl.append(d->seller); @@ -140,13 +141,13 @@ ByteVector OwnershipFrame::renderFields() const { v.append(d->seller.data(encoding)); return v; + } //////////////////////////////////////////////////////////////////////////////// // 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)); } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/ownershipframe.h b/3rdparty/taglib/mpeg/id3v2/frames/ownershipframe.h index 8efbf69c2..dce2ec2e6 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/ownershipframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/ownershipframe.h @@ -31,101 +31,98 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! 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. - */ + * 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; public: /*! - * Construct an empty ownership frame. - */ + * Construct an empty ownership frame. + */ explicit OwnershipFrame(String::Type encoding = String::Latin1); /*! - * Construct a ownership based on the data in \a data. - */ + * Construct a ownership based on the data in \a data. + */ explicit OwnershipFrame(const ByteVector &data); /*! - * Destroys this OwnershipFrame instance. - */ + * Destroys this OwnershipFrame instance. + */ virtual ~OwnershipFrame(); /*! - * Returns the text of this popularimeter. - * - * \see text() - */ + * Returns the text of this popularimeter. + * + * \see text() + */ virtual String toString() const; /*! - * Returns the date purchased. - * - * \see setDatePurchased() - */ + * Returns the date purchased. + * + * \see setDatePurchased() + */ String datePurchased() const; /*! - * Set the date purchased. - * - * \see datePurchased() - */ + * Set the date purchased. + * + * \see datePurchased() + */ void setDatePurchased(const String &datePurchased); /*! - * Returns the price paid. - * - * \see setPricePaid() - */ + * Returns the price paid. + * + * \see setPricePaid() + */ String pricePaid() const; /*! - * Set the price paid. - * - * \see pricePaid() - */ + * Set the price paid. + * + * \see pricePaid() + */ void setPricePaid(const String &pricePaid); /*! - * Returns the seller. - * - * \see setSeller() - */ + * Returns the seller. + * + * \see setSeller() + */ String seller() const; /*! - * Set the seller. - * - * \see seller() - */ + * Set the seller. + * + * \see 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. - * - * \see setTextEncoding() - * \see render() - */ + * 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. + * + * \see setTextEncoding() + * \see render() + */ String::Type textEncoding() const; /*! - * Sets the text encoding to be used when rendering this frame to - * \a encoding. - * - * \see textEncoding() - * \see render() - */ + * Sets the text encoding to be used when rendering this frame to \a encoding. + * + * \see textEncoding() + * \see render() + */ void setTextEncoding(String::Type encoding); protected: @@ -136,8 +133,8 @@ class TAGLIB_EXPORT OwnershipFrame : public Frame { private: /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ OwnershipFrame(const ByteVector &data, Header *h); OwnershipFrame(const OwnershipFrame &); OwnershipFrame &operator=(const OwnershipFrame &); @@ -149,4 +146,5 @@ class TAGLIB_EXPORT OwnershipFrame : public Frame { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/frames/podcastframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/podcastframe.cpp index aeb2e8388..a2b8a1419 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/podcastframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/podcastframe.cpp @@ -37,8 +37,7 @@ class PodcastFrame::PodcastFramePrivate { // public members //////////////////////////////////////////////////////////////////////////////// -PodcastFrame::PodcastFrame() : Frame("PCST"), - d(new PodcastFramePrivate()) { +PodcastFrame::PodcastFrame() : Frame("PCST"), d(new PodcastFramePrivate()) { d->fieldData = ByteVector(4, '\0'); } @@ -66,7 +65,6 @@ 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)); } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/podcastframe.h b/3rdparty/taglib/mpeg/id3v2/frames/podcastframe.h index 9c3c34e26..8ae29cd73 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/podcastframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/podcastframe.h @@ -31,30 +31,29 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! ID3v2 podcast frame /*! - * An implementation of ID3v2 podcast flag, a frame with four zero bytes. - */ + * An implementation of ID3v2 podcast flag, a frame with four zero bytes. + */ class TAGLIB_EXPORT PodcastFrame : public Frame { friend class FrameFactory; public: /*! - * Construct a podcast frame. - */ + * Construct a podcast frame. + */ PodcastFrame(); /*! - * Destroys this PodcastFrame instance. - */ + * Destroys this PodcastFrame instance. + */ virtual ~PodcastFrame(); /*! - * Returns a null string. - */ + * Returns a null string. + */ virtual String toString() const; protected: @@ -65,8 +64,8 @@ class TAGLIB_EXPORT PodcastFrame : public Frame { private: /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ PodcastFrame(const ByteVector &data, Header *h); PodcastFrame(const PodcastFrame &); PodcastFrame &operator=(const PodcastFrame &); @@ -78,4 +77,5 @@ class TAGLIB_EXPORT PodcastFrame : public Frame { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/frames/popularimeterframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/popularimeterframe.cpp index 5be0f8003..a47b93f25 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/popularimeterframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/popularimeterframe.cpp @@ -42,12 +42,9 @@ class PopularimeterFrame::PopularimeterFramePrivate { // 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); } @@ -88,6 +85,7 @@ void PopularimeterFrame::setCounter(unsigned int s) { //////////////////////////////////////////////////////////////////////////////// void PopularimeterFrame::parseFields(const ByteVector &data) { + int pos = 0, size = int(data.size()); d->email = readStringField(data, String::Latin1, &pos); @@ -100,9 +98,11 @@ void PopularimeterFrame::parseFields(const ByteVector &data) { d->counter = data.toUInt(static_cast(pos)); } } + } ByteVector PopularimeterFrame::renderFields() const { + ByteVector data; data.append(d->email.data(String::Latin1)); @@ -111,13 +111,13 @@ ByteVector PopularimeterFrame::renderFields() const { data.append(ByteVector::fromUInt(d->counter)); return data; + } //////////////////////////////////////////////////////////////////////////////// // 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)); } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/popularimeterframe.h b/3rdparty/taglib/mpeg/id3v2/frames/popularimeterframe.h index 96216c29b..693970028 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/popularimeterframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/popularimeterframe.h @@ -31,82 +31,81 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! An implementation of ID3v2 "popularimeter" /*! - * This implements the ID3v2 popularimeter (POPM frame). It consists of - * an email, a rating and an optional counter. - */ + * 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; public: /*! - * Construct an empty popularimeter frame. - */ + * Construct an empty popularimeter frame. + */ explicit PopularimeterFrame(); /*! - * Construct a popularimeter based on the data in \a data. - */ + * Construct a popularimeter based on the data in \a data. + */ explicit PopularimeterFrame(const ByteVector &data); /*! - * Destroys this PopularimeterFrame instance. - */ + * Destroys this PopularimeterFrame instance. + */ virtual ~PopularimeterFrame(); /*! - * Returns the text of this popularimeter. - * - * \see text() - */ + * Returns the text of this popularimeter. + * + * \see text() + */ virtual String toString() const; /*! - * Returns the email. - * - * \see setEmail() - */ + * Returns the email. + * + * \see setEmail() + */ String email() const; /*! - * Set the email. - * - * \see email() - */ + * Set the email. + * + * \see email() + */ void setEmail(const String &email); /*! - * Returns the rating. - * - * \see setRating() - */ + * Returns the rating. + * + * \see setRating() + */ int rating() const; /*! - * Set the rating. - * - * \see rating() - */ + * Set the rating. + * + * \see rating() + */ void setRating(int rating); /*! - * Returns the counter. - * - * \see setCounter() - */ + * Returns the counter. + * + * \see setCounter() + */ unsigned int counter() const; /*! - * Set the counter. - * - * \see counter() - */ + * Set the counter. + * + * \see counter() + */ void setCounter(unsigned int counter); protected: @@ -117,8 +116,8 @@ class TAGLIB_EXPORT PopularimeterFrame : public Frame { private: /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ PopularimeterFrame(const ByteVector &data, Header *h); PopularimeterFrame(const PopularimeterFrame &); PopularimeterFrame &operator=(const PopularimeterFrame &); @@ -130,4 +129,5 @@ class TAGLIB_EXPORT PopularimeterFrame : public Frame { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/frames/privateframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/privateframe.cpp index 53bba7061..4abfe123a 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/privateframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/privateframe.cpp @@ -44,12 +44,9 @@ class PrivateFrame::PrivateFramePrivate { // 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); } @@ -82,6 +79,7 @@ void PrivateFrame::setData(const ByteVector &data) { //////////////////////////////////////////////////////////////////////////////// void PrivateFrame::parseFields(const ByteVector &data) { + if (data.size() < 2) { debug("A private frame must contain at least 2 bytes."); return; @@ -94,9 +92,11 @@ void PrivateFrame::parseFields(const ByteVector &data) { d->owner = String(data.mid(0, endOfOwner)); d->data = data.mid(endOfOwner + 1); + } ByteVector PrivateFrame::renderFields() const { + ByteVector v; v.append(d->owner.data(String::Latin1)); @@ -104,13 +104,13 @@ ByteVector PrivateFrame::renderFields() const { v.append(d->data); return v; + } //////////////////////////////////////////////////////////////////////////////// // 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)); } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/privateframe.h b/3rdparty/taglib/mpeg/id3v2/frames/privateframe.h index add5d19e1..31560b0c4 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/privateframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/privateframe.h @@ -32,7 +32,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! An implementation of ID3v2 privateframe @@ -42,49 +41,49 @@ class TAGLIB_EXPORT PrivateFrame : public Frame { public: /*! - * Construct an empty private frame. - */ + * Construct an empty private frame. + */ 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. - */ + * 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); /*! - * Destroys this private frame instance. - */ + * Destroys this private frame instance. + */ virtual ~PrivateFrame(); /*! - * Returns the text of this private frame, currently just the owner. - * - * \see text() - */ + * Returns the text of this private frame, currently just the owner. + * + * \see text() + */ virtual String toString() const; /*! - * \return The owner of the private frame. - * \note This should contain an email address or link to a website. - */ + * \return The owner of the private frame. + * \note This should contain an email address or link to a website. + */ String owner() 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. - */ + * 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 setData(const ByteVector &v); protected: @@ -95,8 +94,8 @@ class TAGLIB_EXPORT PrivateFrame : public Frame { private: /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ PrivateFrame(const ByteVector &data, Header *h); PrivateFrame(const PrivateFrame &); @@ -109,4 +108,5 @@ class TAGLIB_EXPORT PrivateFrame : public Frame { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp index 0cd67e31f..e968286b4 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp @@ -49,12 +49,9 @@ class RelativeVolumeFrame::RelativeVolumeFramePrivate { // 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); } @@ -67,6 +64,7 @@ String RelativeVolumeFrame::toString() const { } List RelativeVolumeFrame::channels() const { + List l; Map::ConstIterator it = d->channels.begin(); @@ -74,17 +72,7 @@ List RelativeVolumeFrame::channels() const { l.append((*it).first); return l; -} -// deprecated - -RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const { - return MasterVolume; -} - -// deprecated - -void RelativeVolumeFrame::setChannelType(ChannelType) { } short RelativeVolumeFrame::volumeAdjustmentIndex(ChannelType type) const { @@ -148,6 +136,7 @@ void RelativeVolumeFrame::setIdentification(const String &s) { //////////////////////////////////////////////////////////////////////////////// void RelativeVolumeFrame::parseFields(const ByteVector &data) { + int pos = 0; d->identification = readStringField(data, String::Latin1, &pos); @@ -170,9 +159,11 @@ void RelativeVolumeFrame::parseFields(const ByteVector &data) { channel.peakVolume.peakVolume = data.mid(pos, bytes); pos += bytes; } + } ByteVector RelativeVolumeFrame::renderFields() const { + ByteVector data; data.append(d->identification.data(String::Latin1)); @@ -191,13 +182,13 @@ ByteVector RelativeVolumeFrame::renderFields() const { } return data; + } //////////////////////////////////////////////////////////////////////////////// // 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)); } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/relativevolumeframe.h b/3rdparty/taglib/mpeg/id3v2/frames/relativevolumeframe.h index fb7947958..b77929052 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/relativevolumeframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/relativevolumeframe.h @@ -32,28 +32,24 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! 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. - * - * Multiple relative volume adjustment frames may be present in the tag - * each with a unique identification and describing volume adjustment for - * different channel types. - */ + * 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. + * + * Multiple relative volume adjustment frames may be present in the tag each with a unique identification and describing volume adjustment for different channel types. + */ class TAGLIB_EXPORT RelativeVolumeFrame : public Frame { friend class FrameFactory; public: /*! - * This indicates the type of volume adjustment that should be applied. - */ + * This indicates the type of volume adjustment that should be applied. + */ enum ChannelType { //! A type not enumerated below Other = 0x00, @@ -78,149 +74,125 @@ class TAGLIB_EXPORT RelativeVolumeFrame : public Frame { //! 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. - */ + * 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 { /*! - * Constructs an empty peak volume description. - */ + * Constructs an empty peak volume description. + */ PeakVolume() : bitsRepresentingPeak(0) {} /*! - * The number of bits (in the range of 0 to 255) used to describe the - * peak volume. - */ + * The number of bits (in the range of 0 to 255) used to describe the peak volume. + */ unsigned char bitsRepresentingPeak; /*! - * The array of bits (represented as a series of bytes) used to describe - * the peak volume. - */ + * The array of bits (represented as a series of bytes) used to describe the peak volume. + */ ByteVector peakVolume; }; /*! - * Constructs a RelativeVolumeFrame. The relevant data should be set - * manually. - */ + * Constructs a RelativeVolumeFrame. The relevant data should be set manually. + */ RelativeVolumeFrame(); /*! - * Constructs a RelativeVolumeFrame based on the contents of \a data. - */ + * Constructs a RelativeVolumeFrame based on the contents of \a data. + */ RelativeVolumeFrame(const ByteVector &data); /*! - * Destroys the RelativeVolumeFrame instance. - */ + * Destroys the RelativeVolumeFrame instance. + */ virtual ~RelativeVolumeFrame(); /*! - * Returns the frame's identification. - * - * \see identification() - */ + * Returns the frame's identification. + * + * \see identification() + */ virtual String toString() const; /*! - * Returns a list of channels with information currently in the frame. - */ + * Returns a list of channels with information currently in the frame. + */ List channels() const; - /*! - * \deprecated Always returns master volume. - */ - TAGLIB_DEPRECATED ChannelType channelType() const; - - /*! - * \deprecated This method no longer has any effect. - */ - 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. - */ + * 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. + */ #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. - * - * This defaults to returning the value for the master volume channel if - * available and returns 0 if the specified channel does not exist. - * - * \see setVolumeAdjustmentIndex() - * \see volumeAjustment() - */ + * 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. + * + * This defaults to returning the value for the master volume channel if available and returns 0 if the specified channel does not exist. + * + * \see setVolumeAdjustmentIndex() + * \see volumeAjustment() + */ 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. - * - * By default this sets the value for the master volume. - * - * \see volumeAdjustmentIndex() - * \see setVolumeAjustment() - */ + * 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. + * + * By default this sets the value for the master volume. + * + * \see volumeAdjustmentIndex() + * \see setVolumeAjustment() + */ 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 - * value the value returned by this method may not be identical to the - * value set using setVolumeAdjustment(). - * - * This defaults to returning the value for the master volume channel if - * available and returns 0 if the specified channel does not exist. - * - * \see setVolumeAdjustment() - * \see volumeAdjustmentIndex() - */ + * Returns the relative volume adjustment in decibels. + * + * \note Because this is actually stored internally as an "index" to this + * value the value returned by this method may not be identical to the value set using setVolumeAdjustment(). + * + * This defaults to returning the value for the master volume channel if available and returns 0 if the specified channel does not exist. + * + * \see setVolumeAdjustment() + * \see volumeAdjustmentIndex() + */ 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. - * - * \note Because this is actually stored internally as an "index" to this - * value the value set by this method may not be identical to the one - * returned by volumeAdjustment(). - * - * \see setVolumeAdjustment() - * \see volumeAdjustmentIndex() - */ + * Set the relative volume adjustment in decibels to \a adjustment. + * + * By default this sets the value for the master volume. + * + * \note Because this is actually stored internally as an "index" to this value the value set by this method may not be identical to the one returned by volumeAdjustment(). + * + * \see setVolumeAdjustment() + * \see volumeAdjustmentIndex() + */ 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 - * available and returns 0 if the specified channel does not exist. - * - * \see setPeakVolume() - */ + * 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 available and returns 0 if the specified channel does not exist. + * + * \see setPeakVolume() + */ 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() - */ + * 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); #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; @@ -243,15 +215,14 @@ class TAGLIB_EXPORT RelativeVolumeFrame : public Frame { #endif /*! - * Returns the identification for this frame. - */ + * Returns the identification for this frame. + */ 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. - */ + * 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); protected: @@ -270,4 +241,5 @@ class TAGLIB_EXPORT RelativeVolumeFrame : public Frame { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp index 6a53a855e..1d9dcad7a 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp @@ -123,6 +123,7 @@ void SynchronizedLyricsFrame::setSynchedText( //////////////////////////////////////////////////////////////////////////////// void SynchronizedLyricsFrame::parseFields(const ByteVector &data) { + const int end = data.size(); if (end < 7) { debug("A synchronized lyrics frame must contain at least 7 bytes."); @@ -177,9 +178,11 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data) { d->synchedText.append(SynchedText(time, text)); } + } ByteVector SynchronizedLyricsFrame::renderFields() const { + ByteVector v; String::Type encoding = d->textEncoding; @@ -207,6 +210,7 @@ ByteVector SynchronizedLyricsFrame::renderFields() const { } return v; + } //////////////////////////////////////////////////////////////////////////////// diff --git a/3rdparty/taglib/mpeg/id3v2/frames/synchronizedlyricsframe.h b/3rdparty/taglib/mpeg/id3v2/frames/synchronizedlyricsframe.h index 3ceeb641f..eb95c4023 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/synchronizedlyricsframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/synchronizedlyricsframe.h @@ -31,20 +31,19 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! ID3v2 synchronized lyrics frame /*! - * An implementation of ID3v2 synchronized lyrics. - */ + * An implementation of ID3v2 synchronized lyrics. + */ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame { friend class FrameFactory; public: /*! - * Specifies the timestamp format used. - */ + * Specifies the timestamp format used. + */ enum TimestampFormat { //! The timestamp is of unknown format. Unknown = 0x00, @@ -57,8 +56,8 @@ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame { }; /*! - * Specifies the type of text contained. - */ + * Specifies the type of text contained. + */ enum Type { //! The text is some other type of text. Other = 0x00, @@ -81,8 +80,8 @@ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame { }; /*! - * Single entry of time stamp and lyrics text. - */ + * Single entry of time stamp and lyrics text. + */ struct SynchedText { SynchedText(unsigned int ms, String str) : time(ms), text(str) {} unsigned int time; @@ -90,121 +89,117 @@ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame { }; /*! - * List of synchronized lyrics. - */ + * List of synchronized lyrics. + */ typedef Strawberry_TagLib::TagLib::List SynchedTextList; /*! - * Construct an empty synchronized lyrics frame that will use the text - * encoding \a encoding. - */ + * Construct an empty synchronized lyrics frame that will use the text encoding \a encoding. + */ explicit SynchronizedLyricsFrame(String::Type encoding = String::Latin1); /*! - * Construct a synchronized lyrics frame based on the data in \a data. - */ + * Construct a synchronized lyrics frame based on the data in \a data. + */ explicit SynchronizedLyricsFrame(const ByteVector &data); /*! - * Destroys this SynchronizedLyricsFrame instance. - */ + * Destroys this SynchronizedLyricsFrame instance. + */ virtual ~SynchronizedLyricsFrame(); /*! - * Returns the description of this synchronized lyrics frame. - * - * \see description() - */ + * Returns the description of this synchronized lyrics frame. + * + * \see description() + */ 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. - * - * \see setTextEncoding() - * \see render() - */ + * 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. + * + * \see setTextEncoding() + * \see render() + */ String::Type textEncoding() const; /*! - * Returns the language encoding as a 3 byte encoding as specified by - * ISO-639-2. - * - * \note Most taggers simply ignore this value. - * - * \see setLanguage() - */ + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ ByteVector language() const; /*! - * Returns the timestamp format. - */ + * Returns the timestamp format. + */ TimestampFormat timestampFormat() const; /*! - * Returns the type of text contained. - */ + * Returns the type of text contained. + */ Type type() const; /*! - * Returns the description of this synchronized lyrics frame. - * - * \note Most taggers simply ignore this value. - * - * \see setDescription() - */ + * Returns the description of this synchronized lyrics frame. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ String description() const; /*! - * Returns the text with the time stamps. - */ + * Returns the text with the time stamps. + */ SynchedTextList synchedText() const; /*! - * Sets the text encoding to be used when rendering this frame to - * \a encoding. - * - * \see textEncoding() - * \see render() - */ + * Sets the text encoding to be used when rendering this frame to \a encoding. + * + * \see textEncoding() + * \see render() + */ void setTextEncoding(String::Type encoding); /*! - * Set the language using the 3 byte language code from - * ISO-639-2 to - * \a languageCode. - * - * \see language() - */ + * Set the language using the 3 byte language code from + * ISO-639-2 to \a languageCode. + * + * \see language() + */ void setLanguage(const ByteVector &languageCode); /*! - * Set the timestamp format. - * - * \see timestampFormat() - */ + * Set the timestamp format. + * + * \see timestampFormat() + */ void setTimestampFormat(TimestampFormat f); /*! - * Set the type of text contained. - * - * \see type() - */ + * Set the type of text contained. + * + * \see type() + */ void setType(Type t); /*! - * Sets the description of the synchronized lyrics frame to \a s. - * - * \see description() - */ + * Sets the description of the synchronized lyrics frame to \a s. + * + * \see description() + */ void setDescription(const String &s); /*! - * Sets the text with the time stamps. - * - * \see text() - */ + * Sets the text with the time stamps. + * + * \see text() + */ void setSynchedText(const SynchedTextList &t); protected: @@ -215,8 +210,8 @@ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame { private: /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ SynchronizedLyricsFrame(const ByteVector &data, Header *h); SynchronizedLyricsFrame(const SynchronizedLyricsFrame &); SynchronizedLyricsFrame &operator=(const SynchronizedLyricsFrame &); @@ -228,4 +223,5 @@ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp index 1caf549db..5a7ce2972 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp @@ -34,9 +34,7 @@ using namespace ID3v2; class TableOfContentsFrame::TableOfContentsFramePrivate { public: - TableOfContentsFramePrivate() : tagHeader(0), - isTopLevel(false), - isOrdered(false) { + TableOfContentsFramePrivate() : tagHeader(nullptr), isTopLevel(false), isOrdered(false) { embeddedFrameList.setAutoDelete(true); } @@ -69,6 +67,7 @@ ByteVectorList &strip(ByteVectorList &l) { } return l; } + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -81,16 +80,15 @@ TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, const setData(data); } -TableOfContentsFrame::TableOfContentsFrame(const ByteVector &elementID, - const ByteVectorList &children, - const FrameList &embeddedFrames) : ID3v2::Frame("CTOC"), - d(new TableOfContentsFramePrivate()) { +TableOfContentsFrame::TableOfContentsFrame(const ByteVector &elementID, 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) addEmbeddedFrame(*it); + } TableOfContentsFrame::~TableOfContentsFrame() { @@ -167,6 +165,7 @@ void TableOfContentsFrame::addEmbeddedFrame(Frame *frame) { } 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); @@ -178,15 +177,19 @@ void TableOfContentsFrame::removeEmbeddedFrame(Frame *frame, bool del) { // ...and delete as desired if (del) delete frame; + } void TableOfContentsFrame::removeEmbeddedFrames(const ByteVector &id) { + FrameList l = d->embeddedFrameListMap[id]; for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) removeEmbeddedFrame(*it, true); + } String TableOfContentsFrame::toString() const { + String s = String(d->elementID) + ": top level: " + (d->isTopLevel ? "true" : "false") + ", ordered: " + (d->isOrdered ? "true" : "false"); @@ -205,19 +208,21 @@ String TableOfContentsFrame::toString() const { } return s; + } PropertyMap TableOfContentsFrame::asProperties() const { + PropertyMap map; map.unsupportedData().append(frameID() + String("/") + d->elementID); return map; + } -TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *tag, - const ByteVector &eID) // static -{ +TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) { // static + ID3v2::FrameList tablesOfContents = tag->frameList("CTOC"); for (ID3v2::FrameList::ConstIterator it = tablesOfContents.begin(); @@ -229,10 +234,11 @@ TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *ta } 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(); @@ -244,9 +250,11 @@ TableOfContentsFrame *TableOfContentsFrame::findTopLevel(const ID3v2::Tag *tag) } return nullptr; + } void TableOfContentsFrame::parseFields(const ByteVector &data) { + unsigned int size = data.size(); if (size < 6) { debug("A CTOC frame must contain at least 6 bytes (1 byte element ID terminated by " @@ -286,9 +294,11 @@ void TableOfContentsFrame::parseFields(const ByteVector &data) { embPos += frame->size() + header()->size(); addEmbeddedFrame(frame); } + } ByteVector TableOfContentsFrame::renderFields() const { + ByteVector data; data.append(d->elementID); @@ -311,11 +321,10 @@ ByteVector TableOfContentsFrame::renderFields() const { data.append((*it2)->render()); return data; + } -TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, - const ByteVector &data, Header *h) : Frame(h), - d(new TableOfContentsFramePrivate()) { +TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) : Frame(h), d(new TableOfContentsFramePrivate()) { d->tagHeader = tagHeader; parseFields(fieldData(data)); } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/tableofcontentsframe.h b/3rdparty/taglib/mpeg/id3v2/frames/tableofcontentsframe.h index 26cbf3ce5..0bd3c7ad7 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/tableofcontentsframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/tableofcontentsframe.h @@ -33,13 +33,12 @@ namespace Strawberry_TagLib { namespace TagLib { - 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. - */ + * 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 @@ -48,176 +47,159 @@ class TAGLIB_EXPORT TableOfContentsFrame : public ID3v2::Frame { 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. - */ + * 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); /*! - * 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. - */ + * 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()); /*! - * Destroys the frame. - */ + * Destroys the frame. + */ ~TableOfContentsFrame(); /*! - * Returns the elementID of the frame. Element ID - * is a null terminated string, however it's not human-readable. - * - * \see setElementID() - */ + * Returns the elementID of the frame. + * Element ID is a null terminated string, however it's not human-readable. + * + * \see setElementID() + */ ByteVector elementID() const; /*! - * Returns true, if the frame is top-level (doesn't have - * any parent CTOC frame). - * - * \see setIsTopLevel() - */ + * Returns true, if the frame is top-level (doesn't have any parent CTOC frame). + * + * \see setIsTopLevel() + */ bool isTopLevel() const; /*! - * Returns true, if the child elements list entries - * are ordered. - * - * \see setIsOrdered() - */ + * Returns true, if the child elements list entries are ordered. + * + * \see setIsOrdered() + */ bool isOrdered() const; /*! - * Returns count of child elements of the frame. It always - * corresponds to size of child elements list. - * - * \see childElements() - */ + * Returns count of child elements of the frame. It always corresponds to size of child elements list. + * + * \see childElements() + */ unsigned int entryCount() const; /*! - * Returns list of child elements of the frame. - * - * \see setChildElements() - */ + * Returns list of child elements of the frame. + * + * \see setChildElements() + */ 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() - */ + * 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); /*! - * Sets, if the frame is top-level (doesn't have - * any parent CTOC frame). - * - * \see isTopLevel() - */ + * Sets, if the frame is top-level (doesn't have any parent CTOC frame). + * + * \see isTopLevel() + */ void setIsTopLevel(const bool &t); /*! - * Sets, if the child elements list entries - * are ordered. - * - * \see isOrdered() - */ + * Sets, if the child elements list entries are ordered. + * + * \see isOrdered() + */ void setIsOrdered(const bool &o); /*! - * Sets list of child elements of the frame to \a l. - * - * \see childElements() - */ + * Sets list of child elements of the frame to \a l. + * + * \see childElements() + */ void setChildElements(const ByteVectorList &l); /*! - * Adds \a cE to list of child elements of the frame. - * - * \see childElements() - */ + * Adds \a cE to list of child elements of the frame. + * + * \see childElements() + */ void addChildElement(const ByteVector &cE); /*! - * Removes \a cE to list of child elements of the frame. - * - * \see childElements() - */ + * Removes \a cE to list of child elements of the frame. + * + * \see childElements() + */ 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. - * - * This is the most convenient structure for accessing the CTOC frame's - * embedded frames. Many frame types allow multiple instances of the same - * frame type so this is a map of lists. In most cases however there will - * only be a single frame of a certain type. - * - * \warning You should not modify this data structure directly, instead - * use addEmbeddedFrame() and removeEmbeddedFrame(). - * - * \see embeddedFrameList() - */ + * Returns a reference to the frame list map. + * This is an FrameListMap of all of the frames embedded in the CTOC frame. + * + * This is the most convenient structure for accessing the CTOC frame's embedded frames. + * Many frame types allow multiple instances of the same frame type so this is a map of lists. + * In most cases however there will only be a single frame of a certain type. + * + * \warning You should not modify this data structure directly, instead use addEmbeddedFrame() and removeEmbeddedFrame(). + * + * \see embeddedFrameList() + */ 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. - * - * This can be useful if for example you want iterate over the CTOC frame's - * embedded frames in the order that they occur in the CTOC frame. - * - * \warning You should not modify this data structure directly, instead - * use addEmbeddedFrame() and removeEmbeddedFrame(). - */ + * 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. + * + * This can be useful if for example you want iterate over the CTOC frame's embedded frames in the order that they occur in the CTOC frame. + * + * \warning You should not modify this data structure directly, instead use addEmbeddedFrame() and removeEmbeddedFrame(). + */ 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: - * - * \code - * embeddedFrameListMap()[frameID]; - * \endcode - * - * \see embeddedFrameListMap() - */ + * 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: + * + * \code + * embeddedFrameListMap()[frameID]; + * \endcode + * + * \see embeddedFrameListMap() + */ 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() - */ + * 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); /*! - * 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() - */ + * 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); /*! - * 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() - */ + * 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); virtual String toString() const; @@ -225,21 +207,21 @@ class TAGLIB_EXPORT TableOfContentsFrame : public ID3v2::Frame { 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() - */ + * 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); /*! - * 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() - */ + * CTOC frames each contain a flag that indicates, + * if CTOC frame is top-level (there isn't any frame, which contains this frame in its child elements list). + * Only a single frame within tag can be top-level. This searches for a top-level CTOC frame. + * + * \see isTopLevel() + */ static TableOfContentsFrame *findTopLevel(const Tag *tag); protected: @@ -254,6 +236,7 @@ class TAGLIB_EXPORT TableOfContentsFrame : public ID3v2::Frame { class TableOfContentsFramePrivate; TableOfContentsFramePrivate *d; }; + } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mpeg/id3v2/frames/textidentificationframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/textidentificationframe.cpp index 8376ad3d1..89e473036 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/textidentificationframe.cpp @@ -53,8 +53,8 @@ TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) : Frame 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) { @@ -63,10 +63,11 @@ TextIdentificationFrame *TextIdentificationFrame::createTIPLFrame(const Property } 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) { @@ -77,6 +78,7 @@ TextIdentificationFrame *TextIdentificationFrame::createTMCLFrame(const Property } frame->setText(l); return frame; + } TextIdentificationFrame::~TextIdentificationFrame() { @@ -119,17 +121,19 @@ const char *involvedPeople[][2] = { 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) m.insert(involvedPeople[i][1], involvedPeople[i][0]); } return m; + } PropertyMap TextIdentificationFrame::asProperties() const { + if (frameID() == "TIPL") return makeTIPLProperties(); if (frameID() == "TMCL") @@ -163,6 +167,7 @@ PropertyMap TextIdentificationFrame::asProperties() const { PropertyMap ret; ret.insert(tagName, values); return ret; + } //////////////////////////////////////////////////////////////////////////////// @@ -170,6 +175,7 @@ PropertyMap TextIdentificationFrame::asProperties() const { //////////////////////////////////////////////////////////////////////////////// void TextIdentificationFrame::parseFields(const ByteVector &data) { + // Don't try to parse invalid frames if (data.size() < 2) @@ -209,9 +215,11 @@ void TextIdentificationFrame::parseFields(const ByteVector &data) { d->fieldList.append(String(*it, d->textEncoding)); } } + } ByteVector TextIdentificationFrame::renderFields() const { + String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding); ByteVector v; @@ -231,6 +239,7 @@ ByteVector TextIdentificationFrame::renderFields() const { } return v; + } //////////////////////////////////////////////////////////////////////////////// @@ -243,6 +252,7 @@ TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header } PropertyMap TextIdentificationFrame::makeTIPLProperties() const { + PropertyMap map; if (fieldList().size() % 2 != 0) { // according to the ID3 spec, TIPL must contain an even number of entries @@ -266,9 +276,11 @@ PropertyMap TextIdentificationFrame::makeTIPLProperties() const { } } return map; + } PropertyMap TextIdentificationFrame::makeTMCLProperties() const { + PropertyMap map; if (fieldList().size() % 2 != 0) { // according to the ID3 spec, TMCL must contain an even number of entries @@ -287,14 +299,14 @@ PropertyMap TextIdentificationFrame::makeTMCLProperties() const { map.insert(L"PERFORMER:" + instrument, (++it)->split(",")); } return map; + } //////////////////////////////////////////////////////////////////////////////// // UserTextIdentificationFrame public members //////////////////////////////////////////////////////////////////////////////// -UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) : TextIdentificationFrame("TXXX", encoding), - d(0) { +UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) : TextIdentificationFrame("TXXX", encoding), d(nullptr) { StringList l; l.append(String()); l.append(String()); @@ -306,13 +318,13 @@ UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &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(nullptr) { setDescription(description); setText(values); } 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) { @@ -320,6 +332,7 @@ String UserTextIdentificationFrame::toString() const { break; } return "[" + description() + "] " + l.toString(); + } String UserTextIdentificationFrame::description() const { @@ -347,6 +360,7 @@ void UserTextIdentificationFrame::setText(const StringList &fields) { } void UserTextIdentificationFrame::setDescription(const String &s) { + StringList l = fieldList(); if (l.isEmpty()) @@ -355,21 +369,22 @@ void UserTextIdentificationFrame::setDescription(const String &s) { l[0] = s; TextIdentificationFrame::setText(l); + } 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()) - map.insert(tagName, *it); + if (it != v.begin()) map.insert(tagName, *it); return map; + } -UserTextIdentificationFrame *UserTextIdentificationFrame::find( - ID3v2::Tag *tag, const String &description) // static -{ +UserTextIdentificationFrame *UserTextIdentificationFrame::find(ID3v2::Tag *tag, const String &description) { // static + FrameList l = tag->frameList("TXXX"); for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) { UserTextIdentificationFrame *f = dynamic_cast(*it); @@ -377,6 +392,7 @@ UserTextIdentificationFrame *UserTextIdentificationFrame::find( return f; } return nullptr; + } //////////////////////////////////////////////////////////////////////////////// @@ -388,10 +404,12 @@ UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data, } void UserTextIdentificationFrame::checkFields() { + int fields = fieldList().size(); if (fields == 0) setDescription(String()); if (fields <= 1) setText(String()); + } diff --git a/3rdparty/taglib/mpeg/id3v2/frames/textidentificationframe.h b/3rdparty/taglib/mpeg/id3v2/frames/textidentificationframe.h index 1670629df..5206e6e0f 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/textidentificationframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/textidentificationframe.h @@ -34,7 +34,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { class Tag; @@ -43,117 +42,111 @@ typedef Map KeyConversionMap; //! 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: - * - *
    - *
  • TALB Album/Movie/Show title
  • - *
  • TBPM BPM (beats per minute)
  • - *
  • TCOM Composer
  • - *
  • TCON Content type
  • - *
  • TCOP Copyright message
  • - *
  • TDEN Encoding time
  • - *
  • TDLY Playlist delay
  • - *
  • TDOR Original release time
  • - *
  • TDRC Recording time
  • - *
  • TDRL Release time
  • - *
  • TDTG Tagging time
  • - *
  • TENC Encoded by
  • - *
  • TEXT Lyricist/Text writer
  • - *
  • TFLT File type
  • - *
  • TIPL Involved people list
  • - *
  • TIT1 Content group description
  • - *
  • TIT2 Title/songname/content description
  • - *
  • TIT3 Subtitle/Description refinement
  • - *
  • TKEY Initial key
  • - *
  • TLAN Language(s)
  • - *
  • TLEN Length
  • - *
  • TMCL Musician credits list
  • - *
  • TMED Media type
  • - *
  • TMOO Mood
  • - *
  • TOAL Original album/movie/show title
  • - *
  • TOFN Original filename
  • - *
  • TOLY Original lyricist(s)/text writer(s)
  • - *
  • TOPE Original artist(s)/performer(s)
  • - *
  • TOWN File owner/licensee
  • - *
  • TPE1 Lead performer(s)/Soloist(s)
  • - *
  • TPE2 Band/orchestra/accompaniment
  • - *
  • TPE3 Conductor/performer refinement
  • - *
  • TPE4 Interpreted, remixed, or otherwise modified by
  • - *
  • TPOS Part of a set
  • - *
  • TPRO Produced notice
  • - *
  • TPUB Publisher
  • - *
  • TRCK Track number/Position in set
  • - *
  • TRSN Internet radio station name
  • - *
  • TRSO Internet radio station owner
  • - *
  • TSOA Album sort order
  • - *
  • TSOP Performer sort order
  • - *
  • TSOT Title sort order
  • - *
  • TSRC ISRC (international standard recording code)
  • - *
  • TSSE Software/Hardware and settings used for encoding
  • - *
  • TSST Set subtitle
  • - *
- * - * The ID3v2 Frames document gives a description of each of these formats - * and the expected order of strings in each. ID3v2::Header::frameID() can - * be used to determine the frame type. - * - * \note If non-Latin1 compatible strings are used with this class, even if - * the text encoding is set to Latin1, the frame will be written using UTF8 - * (with the encoding flag appropriately set in the output). - */ + * 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: + * + *
    + *
  • TALB Album/Movie/Show title
  • + *
  • TBPM BPM (beats per minute)
  • + *
  • TCOM Composer
  • + *
  • TCON Content type
  • + *
  • TCOP Copyright message
  • + *
  • TDEN Encoding time
  • + *
  • TDLY Playlist delay
  • + *
  • TDOR Original release time
  • + *
  • TDRC Recording time
  • + *
  • TDRL Release time
  • + *
  • TDTG Tagging time
  • + *
  • TENC Encoded by
  • + *
  • TEXT Lyricist/Text writer
  • + *
  • TFLT File type
  • + *
  • TIPL Involved people list
  • + *
  • TIT1 Content group description
  • + *
  • TIT2 Title/songname/content description
  • + *
  • TIT3 Subtitle/Description refinement
  • + *
  • TKEY Initial key
  • + *
  • TLAN Language(s)
  • + *
  • TLEN Length
  • + *
  • TMCL Musician credits list
  • + *
  • TMED Media type
  • + *
  • TMOO Mood
  • + *
  • TOAL Original album/movie/show title
  • + *
  • TOFN Original filename
  • + *
  • TOLY Original lyricist(s)/text writer(s)
  • + *
  • TOPE Original artist(s)/performer(s)
  • + *
  • TOWN File owner/licensee
  • + *
  • TPE1 Lead performer(s)/Soloist(s)
  • + *
  • TPE2 Band/orchestra/accompaniment
  • + *
  • TPE3 Conductor/performer refinement
  • + *
  • TPE4 Interpreted, remixed, or otherwise modified by
  • + *
  • TPOS Part of a set
  • + *
  • TPRO Produced notice
  • + *
  • TPUB Publisher
  • + *
  • TRCK Track number/Position in set
  • + *
  • TRSN Internet radio station name
  • + *
  • TRSO Internet radio station owner
  • + *
  • TSOA Album sort order
  • + *
  • TSOP Performer sort order
  • + *
  • TSOT Title sort order
  • + *
  • TSRC ISRC (international standard recording code)
  • + *
  • TSSE Software/Hardware and settings used for encoding
  • + *
  • TSST Set subtitle
  • + *
+ * + * The ID3v2 Frames document gives a description of each of these formats + * and the expected order of strings in each. + * ID3v2::Header::frameID() can be used to determine the frame type. + * + * \note If non-Latin1 compatible strings are used with this class, + * even if the text encoding is set to Latin1, the frame will be written using UTF8 + * (with the encoding flag appropriately set in the output). + */ class TAGLIB_EXPORT TextIdentificationFrame : public Frame { friend class FrameFactory; public: /*! - * Construct an empty frame of type \a type. Uses \a encoding as the - * default text encoding. - * - * \note In this case you must specify the text encoding as it - * resolves the ambiguity between constructors. - * - * \note Please see the note in the class description regarding Latin1. - */ + * Construct an empty frame of type \a type. + * Uses \a encoding as the default text encoding. + * + * \note In this case you must specify the text encoding as it resolves the ambiguity between constructors. + * + * \note Please see the note in the class description regarding Latin1. + */ 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. - */ + * 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); /*! - * 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. - */ + * 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); /*! - * 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. - */ + * 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); /*! - * Destroys this TextIdentificationFrame instance. - */ + * Destroys this TextIdentificationFrame instance. + */ virtual ~TextIdentificationFrame(); /*! - * Text identification frames are a list of string fields. - * - * This function will accept either a StringList or a String (using the - * StringList constructor that accepts a single String). - * - * \note This will not change the text encoding of the frame even if the - * strings passed in are not of the same encoding. Please use - * setEncoding(s.type()) if you wish to change the encoding of the frame. - */ + * Text identification frames are a list of string fields. + * + * This function will accept either a StringList or a String (using the + * StringList constructor that accepts a single String). + * + * \note This will not change the text encoding of the frame even if the 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); // Reimplementations. @@ -162,37 +155,34 @@ class TAGLIB_EXPORT TextIdentificationFrame : public Frame { 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. - * - * \note Please see the note in the class description regarding Latin1. - * - * \see setTextEncoding() - * \see render() - */ + * 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. + * + * \note Please see the note in the class description regarding Latin1. + * + * \see setTextEncoding() + * \see render() + */ String::Type textEncoding() const; /*! - * Sets the text encoding to be used when rendering this frame to - * \a encoding. - * - * \note Please see the note in the class description regarding Latin1. - * - * \see textEncoding() - * \see render() - */ + * Sets the text encoding to be used when rendering this frame to \a encoding. + * + * \note Please see the note in the class description regarding Latin1. + * + * \see textEncoding() + * \see render() + */ void setTextEncoding(String::Type encoding); /*! - * Returns a list of the strings in this frame. - */ + * Returns a list of the strings in this frame. + */ 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. - */ + * 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(); PropertyMap asProperties() const; @@ -204,8 +194,8 @@ class TAGLIB_EXPORT TextIdentificationFrame : public Frame { virtual ByteVector renderFields() const; /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ TextIdentificationFrame(const ByteVector &data, Header *h); private: @@ -213,26 +203,25 @@ class TAGLIB_EXPORT TextIdentificationFrame : public Frame { 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. - */ + * 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; /*! - * Parses the special structure of a TMCL frame. - */ + * Parses the special structure of a TMCL frame. + */ 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. - * - * This description identifies the frame and must be unique. - */ + * 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. + * + * This description identifies the frame and must be unique. + */ //! An ID3v2 custom text identification frame implementation @@ -241,34 +230,32 @@ class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame public: /*! - * Constructs an empty user defined text identification frame. For this to be - * a useful frame both a description and text must be set. - */ + * 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); /*! - * Creates a frame based on \a data. - */ + * Creates a frame based on \a data. + */ explicit UserTextIdentificationFrame(const ByteVector &data); /*! - * Creates a user defined text identification frame with the given \a description - * and \a values. - */ + * 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); virtual String toString() const; /*! - * Returns the description for this frame. - */ + * Returns the description for this frame. + */ 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. - */ + * 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); StringList fieldList() const; @@ -276,24 +263,19 @@ class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame 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 - * separator is considered as key (compatibility with exfalso) - * - if the above rules don't yield a valid key (e.g. containing non-ASCII - * characters), the returned map will contain an entry "TXXX/" - * in its unsupportedData() list. - * - The values will be copies of the fieldList(). - * - If the description() appears as value in fieldList(), it will be omitted - * in the value list, in order to be compatible with TagLib which copies - * the description() into the fieldList(). - */ + * 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 separator is considered as key (compatibility with exfalso) + * - if the above rules don't yield a valid key (e.g. containing non-ASCII characters), the returned map will contain an entry "TXXX/" in its unsupportedData() list. + * - The values will be copies of the fieldList(). + * - If the description() appears as value in fieldList(), it will be omitted in the value list, in order to be compatible with TagLib which copies the description() into the fieldList(). + */ 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. - */ + * 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); private: @@ -310,4 +292,5 @@ class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp index 18d8acf94..1d65374ea 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp @@ -89,8 +89,8 @@ 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(); @@ -102,9 +102,11 @@ UniqueFileIdentifierFrame *UniqueFileIdentifierFrame::findByOwner(const ID3v2::T } return nullptr; + } void UniqueFileIdentifierFrame::parseFields(const ByteVector &data) { + if (data.size() < 1) { debug("An UFID frame must contain at least 1 byte."); return; @@ -113,9 +115,11 @@ void UniqueFileIdentifierFrame::parseFields(const ByteVector &data) { int pos = 0; d->owner = readStringField(data, String::Latin1, &pos); d->identifier = data.mid(pos); + } ByteVector UniqueFileIdentifierFrame::renderFields() const { + ByteVector data; data.append(d->owner.data(String::Latin1)); @@ -123,6 +127,7 @@ ByteVector UniqueFileIdentifierFrame::renderFields() const { data.append(d->identifier); return data; + } UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data, Header *h) : Frame(h), diff --git a/3rdparty/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.h b/3rdparty/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.h index 5b37347ed..de0be5fd5 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.h @@ -30,14 +30,12 @@ namespace Strawberry_TagLib { namespace TagLib { - 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. - */ + * 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 @@ -46,50 +44,47 @@ class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame { public: /*! - * Creates a unique file identifier frame based on \a data. - */ + * Creates a unique file identifier frame based on \a data. + */ UniqueFileIdentifierFrame(const ByteVector &data); /*! - * Creates a unique file identifier frame with the owner \a owner and - * the identification \a id. - */ + * Creates a unique file identifier frame with the owner \a owner and the identification \a id. + */ UniqueFileIdentifierFrame(const String &owner, const ByteVector &id); /*! - * Destroys the frame. - */ + * Destroys the frame. + */ ~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 - * used to create the unique identifier. - * - * \see setOwner() - */ + * 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 used to create the unique identifier. + * + * \see setOwner() + */ 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. - */ + * 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; /*! - * Sets the owner of the identification scheme to \a s. - * - * \see owner() - */ + * Sets the owner of the identification scheme to \a s. + * + * \see owner() + */ void setOwner(const String &s); /*! - * Sets the unique file identifier to \a v. - * - * \see identifier() - */ + * Sets the unique file identifier to \a v. + * + * \see identifier() + */ void setIdentifier(const ByteVector &v); virtual String toString() const; @@ -97,11 +92,10 @@ class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame { 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() - */ + * 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); protected: @@ -117,6 +111,7 @@ class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame { class UniqueFileIdentifierFramePrivate; UniqueFileIdentifierFramePrivate *d; }; + } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mpeg/id3v2/frames/unknownframe.h b/3rdparty/taglib/mpeg/id3v2/frames/unknownframe.h index cf766e9f6..ff6b6b62c 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/unknownframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/unknownframe.h @@ -31,21 +31,19 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! 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 - * of rendering such \e unknown frames. - * - * Please note that a cleaner way of handling frame types that TagLib - * does not understand is to subclass ID3v2::Frame and ID3v2::FrameFactory - * to have your frame type supported through the standard ID3v2 mechanism. - */ + * 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 of rendering such \e unknown frames. + * + * Please note that a cleaner way of handling frame types that TagLib does + * not understand is to subclass ID3v2::Frame and ID3v2::FrameFactory to have + * your frame type supported through the standard ID3v2 mechanism. + */ class TAGLIB_EXPORT UnknownFrame : public Frame { friend class FrameFactory; @@ -57,8 +55,8 @@ class TAGLIB_EXPORT UnknownFrame : public Frame { virtual String toString() const; /*! - * Returns the field data (everything but the header) for this frame. - */ + * Returns the field data (everything but the header) for this frame. + */ ByteVector data() const; protected: @@ -77,4 +75,5 @@ class TAGLIB_EXPORT UnknownFrame : public Frame { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp index c9d3cbea0..a31a5716a 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp @@ -100,6 +100,7 @@ void UnsynchronizedLyricsFrame::setTextEncoding(String::Type encoding) { } PropertyMap UnsynchronizedLyricsFrame::asProperties() const { + PropertyMap map; String key = description().upper(); if (key.isEmpty() || key == "LYRICS") @@ -107,10 +108,11 @@ PropertyMap UnsynchronizedLyricsFrame::asProperties() const { 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) { @@ -119,12 +121,14 @@ UnsynchronizedLyricsFrame *UnsynchronizedLyricsFrame::findByDescription(const ID return frame; } return nullptr; + } //////////////////////////////////////////////////////////////////////////////// // protected members //////////////////////////////////////////////////////////////////////////////// void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data) { + if (data.size() < 5) { debug("An unsynchronized lyrics frame must contain at least 5 bytes."); return; @@ -148,9 +152,11 @@ void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data) { d->text = String(l.back(), d->textEncoding); } } + } ByteVector UnsynchronizedLyricsFrame::renderFields() const { + StringList sl; sl.append(d->description); sl.append(d->text); @@ -166,6 +172,7 @@ ByteVector UnsynchronizedLyricsFrame::renderFields() const { v.append(d->text.data(encoding)); return v; + } //////////////////////////////////////////////////////////////////////////////// diff --git a/3rdparty/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h b/3rdparty/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h index e25d87332..f0c5a4b78 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h @@ -32,128 +32,123 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! ID3v2 unsynchronized lyrics frame /*! - * An implementation of ID3v2 unsynchronized lyrics. - */ + * An implementation of ID3v2 unsynchronized lyrics. + */ class TAGLIB_EXPORT UnsynchronizedLyricsFrame : public Frame { friend class FrameFactory; public: /*! - * Construct an empty unsynchronized lyrics frame that will use the text encoding - * \a encoding. - */ + * Construct an empty unsynchronized lyrics frame that will use the text encoding \a encoding. + */ explicit UnsynchronizedLyricsFrame(String::Type encoding = String::Latin1); /*! - * Construct a unsynchronized lyrics frame based on the data in \a data. - */ + * Construct a unsynchronized lyrics frame based on the data in \a data. + */ explicit UnsynchronizedLyricsFrame(const ByteVector &data); /*! - * Destroys this UnsynchronizedLyricsFrame instance. - */ + * Destroys this UnsynchronizedLyricsFrame instance. + */ virtual ~UnsynchronizedLyricsFrame(); /*! - * Returns the text of this unsynchronized lyrics frame. - * - * \see text() - */ + * Returns the text of this unsynchronized lyrics frame. + * + * \see text() + */ virtual String toString() const; /*! - * Returns the language encoding as a 3 byte encoding as specified by - * ISO-639-2. - * - * \note Most taggers simply ignore this value. - * - * \see setLanguage() - */ + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ ByteVector language() const; /*! - * Returns the description of this unsynchronized lyrics frame. - * - * \note Most taggers simply ignore this value. - * - * \see setDescription() - */ + * Returns the description of this unsynchronized lyrics frame. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ String description() const; /*! - * Returns the text of this unsynchronized lyrics frame. - * - * \see setText() - */ + * Returns the text of this unsynchronized lyrics frame. + * + * \see setText() + */ String text() const; /*! - * Set the language using the 3 byte language code from - * ISO-639-2 to - * \a languageCode. - * - * \see language() - */ + * Set the language using the 3 byte language code from + * ISO-639-2 to + * \a languageCode. + * + * \see language() + */ void setLanguage(const ByteVector &languageCode); /*! - * Sets the description of the unsynchronized lyrics frame to \a s. - * - * \see description() - */ + * Sets the description of the unsynchronized lyrics frame to \a s. + * + * \see description() + */ void setDescription(const String &s); /*! - * Sets the text portion of the unsynchronized lyrics frame to \a s. - * - * \see text() - */ + * Sets the text portion of the unsynchronized lyrics frame to \a s. + * + * \see text() + */ 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. - * - * \see setTextEncoding() - * \see render() - */ + * 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. + * + * \see setTextEncoding() + * \see render() + */ String::Type textEncoding() const; /*! - * Sets the text encoding to be used when rendering this frame to - * \a encoding. - * - * \see textEncoding() - * \see render() - */ + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ void setTextEncoding(String::Type encoding); /*! 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/" in the unsupportedData() - * attribute of the returned map. - * - otherwise, the key will be "LYRICS:" - * - The single value will be the frame's text(). - * Note that currently the language() field is not supported by the PropertyMap - * interface. - */ + * - 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/" in the unsupportedData() attribute of the returned map. + * - otherwise, the key will be "LYRICS:" + * - The single value will be the frame's text(). + * Note that currently the language() field is not supported by the PropertyMap interface. + */ 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() - */ + * 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); protected: @@ -164,8 +159,8 @@ class TAGLIB_EXPORT UnsynchronizedLyricsFrame : public Frame { private: /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ UnsynchronizedLyricsFrame(const ByteVector &data, Header *h); UnsynchronizedLyricsFrame(const UnsynchronizedLyricsFrame &); UnsynchronizedLyricsFrame &operator=(const UnsynchronizedLyricsFrame &); diff --git a/3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.cpp b/3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.cpp index 18ad80303..09ce05dbf 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.cpp +++ b/3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.cpp @@ -77,6 +77,7 @@ String UrlLinkFrame::toString() const { } PropertyMap UrlLinkFrame::asProperties() const { + String key = frameIDToKey(frameID()); PropertyMap map; if (key.isEmpty()) @@ -85,6 +86,7 @@ PropertyMap UrlLinkFrame::asProperties() const { else map.insert(key, url()); return map; + } //////////////////////////////////////////////////////////////////////////////// @@ -143,6 +145,7 @@ void UserUrlLinkFrame::setDescription(const String &s) { } PropertyMap UserUrlLinkFrame::asProperties() const { + PropertyMap map; String key = description().upper(); if (key.isEmpty() || key == "URL") @@ -150,10 +153,11 @@ PropertyMap UserUrlLinkFrame::asProperties() const { 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) { UserUrlLinkFrame *f = dynamic_cast(*it); @@ -161,6 +165,7 @@ UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &descript return f; } return nullptr; + } //////////////////////////////////////////////////////////////////////////////// @@ -168,6 +173,7 @@ UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &descript //////////////////////////////////////////////////////////////////////////////// void UserUrlLinkFrame::parseFields(const ByteVector &data) { + if (data.size() < 2) { debug("A user URL link frame must contain at least 2 bytes."); return; @@ -196,9 +202,11 @@ void UserUrlLinkFrame::parseFields(const ByteVector &data) { } setUrl(String(data.mid(pos))); + } ByteVector UserUrlLinkFrame::renderFields() const { + ByteVector v; String::Type encoding = checkTextEncoding(d->description, d->textEncoding); @@ -209,6 +217,7 @@ ByteVector UserUrlLinkFrame::renderFields() const { v.append(url().data(String::Latin1)); return v; + } UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data, Header *h) : UrlLinkFrame(data, h), diff --git a/3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.h b/3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.h index ffac9799d..aee3f7ca1 100644 --- a/3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.h +++ b/3rdparty/taglib/mpeg/id3v2/frames/urllinkframe.h @@ -33,36 +33,35 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! ID3v2 URL frame /*! - * An implementation of ID3v2 URL link frames. - */ + * An implementation of ID3v2 URL link frames. + */ class TAGLIB_EXPORT UrlLinkFrame : public Frame { friend class FrameFactory; 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. - */ + * 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); /*! - * Destroys this UrlLinkFrame instance. - */ + * Destroys this UrlLinkFrame instance. + */ virtual ~UrlLinkFrame(); /*! - * Returns the URL. - */ + * Returns the URL. + */ virtual String url() const; /*! - * Sets the URL to \a s. - */ + * Sets the URL to \a s. + */ virtual void setUrl(const String &s); // Reimplementations. @@ -76,8 +75,8 @@ class TAGLIB_EXPORT UrlLinkFrame : public Frame { virtual ByteVector renderFields() const; /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ UrlLinkFrame(const ByteVector &data, Header *h); private: @@ -91,31 +90,30 @@ class TAGLIB_EXPORT UrlLinkFrame : public 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. - */ + * 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; public: /*! - * Constructs an empty user defined URL link frame. For this to be - * a useful frame both a description and text must be set. - */ + * 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); /*! - * This is a dual purpose constructor. \a data can either be binary data - * that should be parsed or (at a minimum) the frame ID. - */ + * 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); /*! - * Destroys this UserUrlLinkFrame instance. - */ + * Destroys this UserUrlLinkFrame instance. + */ virtual ~UserUrlLinkFrame(); // Reimplementations. @@ -123,48 +121,46 @@ class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame { 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. - * - * \see setTextEncoding() - * \see render() - */ + * 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. + * + * \see setTextEncoding() + * \see render() + */ String::Type textEncoding() const; /*! - * Sets the text encoding to be used when rendering this frame to - * \a encoding. - * - * \see textEncoding() - * \see render() - */ + * Sets the text encoding to be used when rendering this frame to \a encoding. + * + * \see textEncoding() + * \see render() + */ void setTextEncoding(String::Type encoding); /*! - * Returns the description for this frame. - */ + * Returns the description for this frame. + */ String description() const; /*! - * Sets the description of the frame to \a s. \a s must be unique. - */ + * Sets the description of the frame to \a s. \a s must be unique. + */ 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". - * - otherwise, if description() is not a valid key (e.g. containing non-ASCII - * characters), the returned map will contain an entry "WXXX/" - * in its unsupportedData() list. - */ + * 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". + * - otherwise, if description() is not a valid key (e.g. containing non-ASCII + * characters), the returned map will contain an entry "WXXX/" + * in its unsupportedData() list. + */ 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. - */ + * 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); protected: @@ -172,8 +168,8 @@ class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame { virtual ByteVector renderFields() const; /*! - * The constructor used by the FrameFactory. - */ + * The constructor used by the FrameFactory. + */ UserUrlLinkFrame(const ByteVector &data, Header *h); private: @@ -187,4 +183,5 @@ class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2.h b/3rdparty/taglib/mpeg/id3v2/id3v2.h index d8ca26966..c528f0049 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2.h +++ b/3rdparty/taglib/mpeg/id3v2/id3v2.h @@ -19,6 +19,7 @@ enum Version { v3 = 3, //3.2) - */ + * 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 headers specified there. + * If any of the terms used in this documentation are unclear please check the specification in the linked section. + * (Structure, 3.2) + */ class TAGLIB_EXPORT ExtendedHeader { public: /*! - * Constructs an empty ID3v2 extended header. - */ + * Constructs an empty ID3v2 extended header. + */ ExtendedHeader(); /*! - * Destroys the extended header. - */ + * Destroys the extended header. + */ virtual ~ExtendedHeader(); /*! - * Returns the size of the extended header. This is variable for the - * extended header. - */ + * Returns the size of the extended header. This is variable for the extended header. + */ 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(). - */ + * 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); protected: /*! - * Called by setData() to parse the extended header data. It makes this - * information available through the public API. - */ + * Called by setData() to parse the extended header data. + * It makes this information available through the public API. + */ void parse(const ByteVector &data); private: @@ -91,4 +88,5 @@ class TAGLIB_EXPORT ExtendedHeader { } // namespace ID3v2 } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2footer.cpp b/3rdparty/taglib/mpeg/id3v2/id3v2footer.cpp index 2d4e5c298..adc9bb446 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2footer.cpp +++ b/3rdparty/taglib/mpeg/id3v2/id3v2footer.cpp @@ -29,14 +29,11 @@ using namespace Strawberry_TagLib::TagLib; using namespace ID3v2; -class Footer::FooterPrivate { -}; +class Footer::FooterPrivate {}; -Footer::Footer() : d(0) { -} +Footer::Footer() : d(nullptr) {} -Footer::~Footer() { -} +Footer::~Footer() {} unsigned int Footer::size() { return 10; diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2footer.h b/3rdparty/taglib/mpeg/id3v2/id3v2footer.h index a6b07cd17..5572655f6 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2footer.h +++ b/3rdparty/taglib/mpeg/id3v2/id3v2footer.h @@ -31,7 +31,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { class Header; @@ -39,34 +38,33 @@ class Header; //! 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. - * - * In fact, at this point, TagLib does not even parse the footer since - * it is not useful internally. However, if the flag to include a footer - * has been set in the ID3v2::Tag, TagLib will render a footer. - */ + * 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. + * + * In fact, at this point, TagLib does not even parse the footer since it is not useful internally. + * However, if the flag to include a footer has been set in the ID3v2::Tag, TagLib will render a footer. + */ class TAGLIB_EXPORT Footer { public: /*! - * Constructs an empty ID3v2 footer. - */ + * Constructs an empty ID3v2 footer. + */ Footer(); /*! - * Destroys the footer. - */ + * Destroys the footer. + */ virtual ~Footer(); /*! - * Returns the size of the footer. Presently this is always 10 bytes. - */ + * Returns the size of the footer. Presently this is always 10 bytes. + */ static unsigned int size(); /*! - * Renders the footer based on the data in \a header. - */ + * Renders the footer based on the data in \a header. + */ ByteVector render(const Header *header) const; private: diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2frame.cpp b/3rdparty/taglib/mpeg/id3v2/id3v2frame.cpp index aa96c45e4..24032a485 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2frame.cpp +++ b/3rdparty/taglib/mpeg/id3v2/id3v2frame.cpp @@ -46,8 +46,7 @@ using namespace ID3v2; class Frame::FramePrivate { public: - FramePrivate() : header(0) { - } + FramePrivate() : header(nullptr) {} ~FramePrivate() { delete header; @@ -58,6 +57,7 @@ class Frame::FramePrivate { namespace { bool isValidFrameID(const ByteVector &frameID) { + if (frameID.size() != 4) return false; @@ -67,6 +67,7 @@ bool isValidFrameID(const ByteVector &frameID) { } } return true; + } } // namespace @@ -98,8 +99,8 @@ const String Frame::urlPrefix("URL:"); // public members //////////////////////////////////////////////////////////////////////////////// -Frame *Frame::createTextualFrame(const String &key, const StringList &values) //static -{ +Frame *Frame::createTextualFrame(const String &key, const StringList &values) { //static + // check if the key is contained in the key<=>frameID mapping ByteVector frameID = keyToFrameID(key); if (!frameID.isEmpty()) { @@ -145,6 +146,7 @@ Frame *Frame::createTextualFrame(const String &key, const StringList &values) / } // if non of the above cases apply, we use a TXXX frame with the key as description return new UserTextIdentificationFrame(keyToTXXX(key), values, String::UTF8); + } Frame::~Frame() { @@ -152,17 +154,21 @@ Frame::~Frame() { } ByteVector Frame::frameID() const { + if (d->header) return d->header->frameID(); else return ByteVector(); + } unsigned int Frame::size() const { + if (d->header) return d->header->frameSize(); else return 0; + } void Frame::setData(const ByteVector &data) { @@ -173,11 +179,13 @@ void Frame::setText(const String &) { } ByteVector Frame::render() const { + ByteVector fieldData = renderFields(); d->header->setFrameSize(fieldData.size()); ByteVector headerData = d->header->render(); return headerData + fieldData; + } //////////////////////////////////////////////////////////////////////////////// @@ -213,6 +221,7 @@ void Frame::parse(const ByteVector &data) { } ByteVector Frame::fieldData(const ByteVector &frameData) const { + unsigned int headerSize = Header::size(d->header->version()); unsigned int frameDataOffset = headerSize; @@ -238,9 +247,11 @@ ByteVector Frame::fieldData(const ByteVector &frameData) const { } return frameData.mid(frameDataOffset, frameDataLength); + } String Frame::readStringField(const ByteVector &data, String::Type encoding, int *position) { + int start = 0; if (!position) @@ -262,15 +273,16 @@ String Frame::readStringField(const ByteVector &data, String::Type encoding, int *position = end + delimiter.size(); return str; + } -String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding) // static -{ +String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding) { // static + return checkEncoding(fields, encoding, 4); } -String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding, unsigned int version) // static -{ +String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding, unsigned int version) { // static + if ((encoding == String::UTF8 || encoding == String::UTF16BE) && version != 4) return String::UTF16; @@ -291,6 +303,7 @@ String::Type Frame::checkEncoding(const StringList &fields, String::Type encodin } return String::Latin1; + } String::Type Frame::checkTextEncoding(const StringList &fields, String::Type encoding) const { @@ -438,6 +451,7 @@ String Frame::keyToTXXX(const String &s) { } PropertyMap Frame::asProperties() const { + if (dynamic_cast(this)) { PropertyMap m; m.unsupportedData().append("UNKNOWN/" + frameID()); @@ -463,10 +477,11 @@ PropertyMap Frame::asProperties() const { PropertyMap m; m.unsupportedData().append(id); return m; + } -void Frame::splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties, - PropertyMap &tiplProperties, PropertyMap &tmclProperties) { +void Frame::splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties, PropertyMap &tiplProperties, PropertyMap &tmclProperties) { + singleFrameProperties.clear(); tiplProperties.clear(); tmclProperties.clear(); @@ -478,6 +493,7 @@ void Frame::splitProperties(const PropertyMap &original, PropertyMap &singleFram else singleFrameProperties.insert(it->first, it->second); } + } //////////////////////////////////////////////////////////////////////////////// @@ -539,10 +555,6 @@ unsigned int Frame::Header::size(unsigned int version) { // public members (Frame::Header) //////////////////////////////////////////////////////////////////////////////// -Frame::Header::Header(const ByteVector &data, bool synchSafeInts) : d(new HeaderPrivate()) { - setData(data, synchSafeInts); -} - Frame::Header::Header(const ByteVector &data, unsigned int version) : d(new HeaderPrivate()) { setData(data, version); } @@ -556,6 +568,7 @@ void Frame::Header::setData(const ByteVector &data, bool synchSafeInts) { } void Frame::Header::setData(const ByteVector &data, unsigned int version) { + d->version = version; switch (version) { @@ -680,6 +693,7 @@ void Frame::Header::setData(const ByteVector &data, unsigned int version) { break; } } + } ByteVector Frame::Header::frameID() const { @@ -747,6 +761,7 @@ bool Frame::Header::dataLengthIndicator() const { } ByteVector Frame::Header::render() const { + ByteVector flags(2, char(0)); // just blank for the moment ByteVector v = d->frameID + @@ -754,8 +769,5 @@ ByteVector Frame::Header::render() const { flags; return v; -} -bool Frame::Header::frameAlterPreservation() const { - return fileAlterPreservation(); } diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2frame.h b/3rdparty/taglib/mpeg/id3v2/id3v2frame.h index 97304f547..a27978852 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2frame.h +++ b/3rdparty/taglib/mpeg/id3v2/id3v2frame.h @@ -44,13 +44,13 @@ class FrameFactory; //! 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, 4) - * (Frames). This class provides an API for - * gathering information about and modifying ID3v2 frames. Funtionallity - * specific to a given frame type is handed in one of the many subclasses. - */ + * 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, 4) + * (Frames). + * This class provides an API for gathering information about and modifying ID3v2 frames. + * Funtionallity specific to a given frame type is handed in one of the many subclasses. + */ class TAGLIB_EXPORT Frame { friend class Tag; @@ -58,247 +58,217 @@ class TAGLIB_EXPORT Frame { 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. - */ + * 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); /*! - * Destroys this Frame instance. - */ + * Destroys this Frame instance. + */ virtual ~Frame(); /*! - * Returns the Frame ID (Structure, 4) - * (Frames, 4) - */ + * Returns the Frame ID (Structure, 4) + * (Frames, 4) + */ ByteVector frameID() const; /*! - * Returns the size of the frame. - */ + * Returns the size of the frame. + */ unsigned int size() const; /*! - * Returns the size of the frame header - * - * \deprecated This is only accurate for ID3v2.3 or ID3v2.4. Please use - * the call below which accepts an ID3v2 version number. In the next - * non-binary compatible release this will be made into a non-static - * member that checks the internal ID3v2 version. - */ + * Returns the size of the frame header + * + * \deprecated This is only accurate for ID3v2.3 or ID3v2.4. + * Please use the call below which accepts an ID3v2 version number. + * In the next 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 /*! - * Returns the size of the frame header for the given ID3v2 version. - * - * \deprecated Please see the explanation above. - */ + * 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); /*! - * 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(). - */ + * 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); /*! - * 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. - * - * \note If the frame type supports multiple text encodings, this will not - * change the text encoding of the frame; the string will be converted to - * that frame's encoding. Please use the specific APIs of the frame types - * to set the encoding if that is desired. - */ + * 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. + * + * \note If the frame type supports multiple text encodings, + * this will not change the text encoding of the frame; the string will be converted to 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); /*! - * 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. - */ + * 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; /*! - * Render the frame back to its binary format in a ByteVector. - */ + * Render the frame back to its binary format in a ByteVector. + */ ByteVector render() const; /*! - * Returns the text delimiter that is used between fields for the string - * type \a t. - */ + * Returns the text delimiter that is used between fields for the string type \a 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:". - */ + * 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; /*! - * 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:". - */ + * 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; /*! - * 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:". - */ + * 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; /*! - * 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:". - */ + * 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; 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. - */ + * 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); /*! - * 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. - */ + * 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); /*! - * Returns a pointer to the frame header. - */ + * Returns a pointer to the frame header. + */ 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. - */ + * 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); /*! - * Called by setData() to parse the frame data. It makes this information - * available through the public API. - */ + * Called by setData() to parse the frame data. It makes this information available through the public API. + */ 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. - */ + * 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; /*! - * Render the field data back to a binary format in a ByteVector. This - * must be overridden by subclasses. - */ + * Render the field data back to a binary format in a ByteVector. This must be overridden by subclasses. + */ 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. - */ + * 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; /*! - * 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); + * 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); /*! - * Checks a the list of string values to see if they can be used with the - * specified encoding and returns the recommended encoding. - */ + * 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); + 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. - */ + * 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); + 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; + * 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; /*! - * 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. - */ + * 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; /*! - * 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. - */ + * 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 &); /*! - * 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. - */ + * 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 &); /*! - * Returns an appropriate TXXX frame description for the given free-form tag key. - */ + * Returns an appropriate TXXX frame description for the given free-form tag key. + */ static String keyToTXXX(const String &); /*! - * Returns a free-form tag name for the given ID3 frame description. - */ + * Returns a free-form tag name for the given ID3 frame description. + */ 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 - * exactly one ID3 frame per key. In the current implementation - * this is everything except for the fixed "involved people" keys and keys of the - * form "TextIdentificationFrame::instrumentPrefix" + "instrument", which are - * mapped to a TMCL frame. - * - \a tiplProperties will consist of those keys that are present in - * TextIdentificationFrame::involvedPeopleMap() - * - \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); + * 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 exactly one ID3 frame per key. + * In the current implementation this is everything except for the fixed "involved people" keys and keys of the + * form "TextIdentificationFrame::instrumentPrefix" + "instrument", which are mapped to a TMCL frame. + * - \a tiplProperties will consist of those keys that are present in TextIdentificationFrame::involvedPeopleMap() + * - \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); private: Frame(const Frame &); @@ -312,173 +282,157 @@ class TAGLIB_EXPORT Frame { //! ID3v2 frame header implementation /*! - * The ID3v2 Frame Header (Structure, 4) - * - * Every ID3v2::Frame has an associated header that gives some general - * properties of the frame and also makes it possible to identify the frame - * type. - * - * As such when reading an ID3v2 tag ID3v2::FrameFactory first creates the - * frame headers and then creates the appropriate Frame subclass based on - * the type and attaches the header. - */ + * The ID3v2 Frame Header (Structure, 4) + * + * Every ID3v2::Frame has an associated header that gives some general + * properties of the frame and also makes it possible to identify the frame type. + * + * As such when reading an ID3v2 tag ID3v2::FrameFactory first creates the + * frame headers and then creates the appropriate Frame subclass based on the type and attaches the header. + */ 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. - * - * \deprecated Please use the constructor below that accepts a version - * number. - */ - 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. - */ + * 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); /*! - * Destroys this Header instance. - */ + * Destroys this Header instance. + */ virtual ~Header(); /*! - * Sets the data for the Header. - * - * \deprecated Please use the version below that accepts an ID3v2 version - * number. - */ + * 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); /*! - * Sets the data for the Header. \a version should indicate the ID3v2 - * version number of the tag that this frame is contained in. - */ + * 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); /*! - * Returns the Frame ID (Structure, 4) - * (Frames, 4) - */ + * Returns the Frame ID (Structure, 4) + * (Frames, 4) + */ ByteVector frameID() const; /*! - * Sets the frame's ID to \a id. Only the first four bytes of \a id will - * be used. - * - * \warning This method should in general be avoided. It exists simply to - * 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. - */ + * Sets the frame's ID to \a id. Only the first four bytes of \a id will be used. + * + * \warning This method should in general be avoided. It exists simply to + * 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); /*! - * Returns the size of the frame data portion, as set when setData() was - * called or set explicitly via setFrameSize(). - */ + * Returns the size of the frame data portion, as set when setData() was called or set explicitly via setFrameSize(). + */ unsigned int frameSize() const; /*! - * Sets the size of the frame data portion. - */ + * Sets the size of the frame data portion. + */ 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(). - */ + * Returns the ID3v2 version of the header, as passed in from the construction of the header or set via setVersion(). + */ unsigned int version() const; /*! - * Sets the ID3v2 version of the header, changing has impact on the - * correct parsing/rendering of frame data. - */ + * Sets the ID3v2 version of the header, changing has impact on the correct parsing/rendering of frame data. + */ 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 - * version. This is only accurate for ID3v2.3 and ID3v2.4. This will be - * removed in the next binary incompatible release (2.0) and will be - * replaced with a non-static method that checks the frame version. - */ + * Returns the size of the frame header in bytes. + * + * \deprecated Please use the version of this method that accepts a + * version. This is only accurate for ID3v2.3 and ID3v2.4. This will be + * 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(); /*! - * 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. - */ + * 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); /*! - * Returns true if the flag for tag alter preservation is set. - * - * The semantics are a little backwards from what would seem natural - * (setting the preservation flag to throw away the frame), but this - * follows the ID3v2 standard. - * - * \see setTagAlterPreservation() - */ + * Returns true if the flag for tag alter preservation is set. + * + * The semantics are a little backwards from what would seem natural + * (setting the preservation flag to throw away the frame), but this + * follows the ID3v2 standard. + * + * \see setTagAlterPreservation() + */ 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. - * - * The semantics are a little backwards from what would seem natural - * (setting the preservation flag to throw away the frame), but this - * follows the ID3v2 standard. - * - * \see tagAlterPreservation() - */ + * 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. + * + * The semantics are a little backwards from what would seem natural + * (setting the preservation flag to throw away the frame), but this + * follows the ID3v2 standard. + * + * \see tagAlterPreservation() + */ void setTagAlterPreservation(bool discard); /*! - * Returns true if the flag for file alter preservation is set. - * - * \note This flag is currently ignored internally in TagLib. - */ + * Returns true if the flag for file alter preservation is set. + * + * \note This flag is currently ignored internally in TagLib. + */ bool fileAlterPreservation() const; /*! - * Returns true if the frame is meant to be read only. - * - * \note This flag is currently ignored internally in TagLib. - */ + * Returns true if the frame is meant to be read only. + * + * \note This flag is currently ignored internally in TagLib. + */ bool readOnly() const; /*! - * Returns true if the flag for the grouping identity is set. - * - * \note This flag is currently ignored internally in TagLib. - */ + * Returns true if the flag for the grouping identity is set. + * + * \note This flag is currently ignored internally in TagLib. + */ bool groupingIdentity() const; /*! - * Returns true if compression is enabled for this frame. - * - * \note This flag is currently ignored internally in TagLib. - */ + * Returns true if compression is enabled for this frame. + * + * \note This flag is currently ignored internally in TagLib. + */ bool compression() const; /*! - * Returns true if encryption is enabled for this frame. - * - * \note This flag is currently ignored internally in TagLib. - */ + * Returns true if encryption is enabled for this frame. + * + * \note This flag is currently ignored internally in TagLib. + */ bool encryption() const; #ifndef DO_NOT_DOCUMENT @@ -486,25 +440,20 @@ class TAGLIB_EXPORT Frame::Header { #endif /*! - * Returns true if unsynchronisation is enabled for this frame. - */ + * Returns true if unsynchronisation is enabled for this frame. + */ bool unsynchronisation() const; /*! - * Returns true if the flag for a data length indicator is set. - */ + * Returns true if the flag for a data length indicator is set. + */ bool dataLengthIndicator() const; /*! - * Render the Header back to binary format in a ByteVector. - */ + * Render the Header back to binary format in a ByteVector. + */ ByteVector render() const; - /*! - * \deprecated - */ - TAGLIB_DEPRECATED bool frameAlterPreservation() const; - private: Header(const Header &); Header &operator=(const Header &); diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2framefactory.cpp b/3rdparty/taglib/mpeg/id3v2/id3v2framefactory.cpp index 3a6eb11d7..6815f359e 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2framefactory.cpp +++ b/3rdparty/taglib/mpeg/id3v2/id3v2framefactory.cpp @@ -53,6 +53,7 @@ using namespace ID3v2; namespace { void updateGenre(TextIdentificationFrame *frame) { + StringList fields = frame->fieldList(); StringList newfields; @@ -80,13 +81,13 @@ void updateGenre(TextIdentificationFrame *frame) { fields.append(String()); frame->setText(newfields); + } } // namespace class FrameFactory::FrameFactoryPrivate { public: - FrameFactoryPrivate() : defaultEncoding(String::Latin1), - useDefaultEncoding(false) {} + FrameFactoryPrivate() : defaultEncoding(String::Latin1), useDefaultEncoding(false) {} String::Type defaultEncoding; bool useDefaultEncoding; @@ -107,21 +108,8 @@ FrameFactory *FrameFactory::instance() { return &factory; } -Frame *FrameFactory::createFrame(const ByteVector &data, bool synchSafeInts) const { - return createFrame(data, static_cast(synchSafeInts ? 4 : 3)); -} - -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(tagHeader)); -} - 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); @@ -317,9 +305,11 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe 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) { @@ -346,6 +336,7 @@ void FrameFactory::rebuildAggregateFrames(ID3v2::Tag *tag) const { } } } + } String::Type FrameFactory::defaultTextEncoding() const { @@ -456,6 +447,7 @@ const size_t frameConversion3Size = sizeof(frameConversion3) / sizeof(frameConve } // namespace bool FrameFactory::updateFrame(Frame::Header *header) const { + const ByteVector frameID = header->frameID(); switch (header->version()) { @@ -522,4 +514,5 @@ bool FrameFactory::updateFrame(Frame::Header *header) const { } return true; + } diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2framefactory.h b/3rdparty/taglib/mpeg/id3v2/id3v2framefactory.h index 82df9055a..d653cc04e 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2framefactory.h +++ b/3rdparty/taglib/mpeg/id3v2/id3v2framefactory.h @@ -33,7 +33,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { class TextIdentificationFrame; @@ -41,116 +40,79 @@ class TextIdentificationFrame; //! 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. - * - * Reimplementing this factory is the key to adding support for frame types - * not directly supported by TagLib to your application. To do so you would - * subclass this factory reimplement createFrame(). Then by setting your - * factory to be the default factory in ID3v2::Tag constructor you can - * implement behavior that will allow for new ID3v2::Frame subclasses (also - * provided by you) to be used. - * - * This implements both abstract factory and singleton patterns - * of which more information is available on the web and in software design - * textbooks (Notably Design Patters). - * - * \note You do not need to use this factory to create new frames to add to - * an ID3v2::Tag. You can instantiate frame subclasses directly (with new) - * and add them to a tag using ID3v2::Tag::addFrame() - * - * \see ID3v2::Tag::addFrame() - */ + * This factory abstracts away the frame creation process and instantiates + * the appropriate ID3v2::Frame subclasses based on the contents of the data. + * + * Reimplementing this factory is the key to adding support for frame types not directly supported by TagLib to your application. + * To do so you would subclass this factory reimplement createFrame(). + * Then by setting your factory to be the default factory in ID3v2::Tag constructor you can + * implement behavior that will allow for new ID3v2::Frame subclasses (also provided by you) to be used. + * + * This implements both abstract factory and singleton patterns + * of which more information is available on the web and in software design textbooks (Notably Design Patters). + * + * \note You do not need to use this factory to create new frames to add to an ID3v2::Tag. + * You can instantiate frame subclasses directly (with new) and add them to a tag using ID3v2::Tag::addFrame() + * + * \see ID3v2::Tag::addFrame() + */ 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. - * - * \deprecated Please use the method below that accepts a ID3v2::Header - * instance in new code. - */ - 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. - * - * \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; - - /*! - * \deprecated - */ - // 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. - */ + * 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; /*! - * 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. - */ + * 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; /*! - * 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 - * converted to this type (unless it's explicitly set differently for the - * individual frame) when being rendered. - * - * \see setDefaultTextEncoding() - */ + * 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 converted to this type + * (unless it's explicitly set differently for the individual frame) when being rendered. + * + * \see setDefaultTextEncoding() + */ 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. - * - * Valid string types for ID3v2 tags are Latin1, UTF8, UTF16 and UTF16BE. - * - * \see defaultTextEncoding() - */ + * 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. + * + * Valid string types for ID3v2 tags are Latin1, UTF8, UTF16 and UTF16BE. + * + * \see defaultTextEncoding() + */ void setDefaultTextEncoding(String::Type encoding); protected: /*! - * Constructs a frame factory. Because this is a singleton this method is - * protected, but may be used for subclasses. - */ + * Constructs a frame factory. Because this is a singleton this method is protected, but may be used for subclasses. + */ FrameFactory(); /*! - * Destroys the frame factory. - */ + * Destroys the frame factory. + */ 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 - * the frame or indicates that it should be discarded. - * - * This method with return true (with or without changes to the frame) if - * this frame should be kept or false if it should be discarded. - * - * See the id3v2.4.0-changes.txt document for further information. - */ + * 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 the frame or indicates that it should be discarded. + * + * This method with return true (with or without changes to the frame) if this frame should be kept or false if it should be discarded. + * + * See the id3v2.4.0-changes.txt document for further information. + */ virtual bool updateFrame(Frame::Header *header) const; private: diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2header.cpp b/3rdparty/taglib/mpeg/id3v2/id3v2header.cpp index e95d1455b..8fa4d3aff 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2header.cpp +++ b/3rdparty/taglib/mpeg/id3v2/id3v2header.cpp @@ -132,19 +132,18 @@ void Header::setData(const ByteVector &data) { } ByteVector Header::render() const { + ByteVector v; // add the file identifier -- "ID3" v.append(fileIdentifier()); - // add the version number -- we always render a 2.4.0 tag regardless of what - // the tag originally was. + // add the version number -- we always render a 2.4.0 tag regardless of what the tag originally was. v.append(char(majorVersion())); v.append(char(0)); - // Currently we don't actually support writing extended headers, footers or - // unsynchronized tags, make sure that the flags are set accordingly. + // Currently we don't actually support writing extended headers, footers or unsynchronized tags, make sure that the flags are set accordingly. d->extendedHeader = false; d->footerPresent = false; @@ -164,6 +163,7 @@ ByteVector Header::render() const { v.append(SynchData::fromUInt(d->tagSize)); return v; + } //////////////////////////////////////////////////////////////////////////////// @@ -171,15 +171,14 @@ ByteVector Header::render() const { //////////////////////////////////////////////////////////////////////////////// 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 - // synch-safe integer, so all bytes must be less than 128. If this is not - // true then this is an invalid tag. + // do some sanity checking -- even in ID3v2.3.0 and less the tag size is a synch-safe integer, so all bytes must be less than 128. + // If this is not true then this is an invalid tag. - // note that we're doing things a little out of order here -- the size is - // later in the bytestream than the version + // note that we're doing things a little out of order here -- the size is later in the bytestream than the version ByteVector sizeData = data.mid(6, 4); @@ -214,4 +213,5 @@ void Header::parse(const ByteVector &data) { // Get the size from the remaining four bytes (read above) d->tagSize = SynchData::toUInt(sizeData); // (structure 3.1 "size") + } diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2header.h b/3rdparty/taglib/mpeg/id3v2/id3v2header.h index 4a6d37f46..58e76e682 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2header.h +++ b/3rdparty/taglib/mpeg/id3v2/id3v2header.h @@ -32,134 +32,122 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! 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 - * specified there. If any of the terms used in this documentation are - * unclear please check the specification in the linked section. - * (Structure, 3.1) - */ + * 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 specified there. + * If any of the terms used in this documentation are unclear please check the specification in the linked section. + * (Structure, 3.1) + */ class TAGLIB_EXPORT Header { public: /*! - * Constructs an empty ID3v2 header. - */ + * Constructs an empty ID3v2 header. + */ Header(); /*! - * Constructs an ID3v2 header based on \a data. parse() is called - * immediately. - */ + * Constructs an ID3v2 header based on \a data. parse() is called immediately. + */ Header(const ByteVector &data); /*! - * Destroys the header. - */ + * Destroys the header. + */ virtual ~Header(); /*! - * Returns the major version number. (Note: This is the 4, not the 2 in - * ID3v2.4.0. The 2 is implied.) - */ + * 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; /*! - * 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() - * - * \note This is used by the internal parser; this will not change the - * version which is written and in general should not be called by API - * users. - */ + * 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() + * + * \note This is used by the internal parser; this will not change the version which is written and in general should not be called by API users. + */ 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.) - */ + * Returns the revision number. (Note: This is the 0, not the 4 in ID3v2.4.0. The 2 is implied.) + */ unsigned int revisionNumber() const; /*! - * Returns true if unsynchronisation has been applied to all frames. - */ + * Returns true if unsynchronisation has been applied to all frames. + */ bool unsynchronisation() const; /*! - * Returns true if an extended header is present in the tag. - */ + * Returns true if an extended header is present in the tag. + */ bool extendedHeader() const; /*! - * Returns true if the experimental indicator flag is set. - */ + * Returns true if the experimental indicator flag is set. + */ bool experimentalIndicator() const; /*! - * Returns true if a footer is present in the tag. - */ + * Returns true if a footer is present in the tag. + */ 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). - * - * \note This is the value as read from the header to which TagLib attempts - * to provide an API to; it was not a design decision on the part of TagLib - * to not include the mentioned portions of the tag in the \e size. - * - * \see completeTagSize() - */ + * 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). + * + * \note This is the value as read from the header to which TagLib attempts to provide an API to; + * it was not a design decision on the part of TagLib to not include the mentioned portions of the tag in the \e size. + * + * \see completeTagSize() + */ unsigned int tagSize() const; /*! - * Returns the tag size, including the header and, if present, the footer - * size. - * - * \see tagSize() - */ + * Returns the tag size, including the header and, if present, the footer size. + * + * \see tagSize() + */ unsigned int completeTagSize() const; /*! - * Set the tag size to \a s. - * \see tagSize() - */ + * Set the tag size to \a s. + * \see tagSize() + */ void setTagSize(unsigned int s); /*! - * Returns the size of the header. Presently this is always 10 bytes. - */ + * Returns the size of the header. Presently this is always 10 bytes. + */ static unsigned int size(); /*! - * Returns the string used to identify and ID3v2 tag inside of a file. - * Presently this is always "ID3". - */ + * Returns the string used to identify and ID3v2 tag inside of a file. + * Presently this is always "ID3". + */ static ByteVector fileIdentifier(); /*! - * Sets the data that will be used as the header. 10 bytes, starting from - * the beginning of \a data are used. - */ + * 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); /*! - * Renders the Header back to binary format. - */ + * Renders the Header back to binary format. + */ ByteVector render() const; protected: /*! - * Called by setData() to parse the header data. It makes this information - * available through the public API. - */ + * Called by setData() to parse the header data. It makes this information available through the public API. + */ void parse(const ByteVector &data); private: diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2synchdata.cpp b/3rdparty/taglib/mpeg/id3v2/id3v2synchdata.cpp index 55128c895..57700387b 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2synchdata.cpp +++ b/3rdparty/taglib/mpeg/id3v2/id3v2synchdata.cpp @@ -31,6 +31,7 @@ using namespace Strawberry_TagLib::TagLib; using namespace ID3v2; unsigned int SynchData::toUInt(const ByteVector &data) { + unsigned int sum = 0; bool notSynchSafe = false; int last = data.size() > 4 ? 3 : data.size() - 1; @@ -46,8 +47,7 @@ unsigned int SynchData::toUInt(const ByteVector &data) { 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. + // put normal integers here rather than syncsafe ones, and try it that way. if (data.size() >= 4) { sum = data.toUInt(0, true); } @@ -59,18 +59,22 @@ unsigned int SynchData::toUInt(const ByteVector &data) { } return sum; + } ByteVector SynchData::fromUInt(unsigned int value) { + ByteVector v(4, 0); for (int i = 0; i < 4; i++) v[i] = static_cast(value >> ((3 - i) * 7) & 0x7f); return v; + } 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. @@ -92,4 +96,5 @@ ByteVector SynchData::decode(const ByteVector &data) { result.resize(static_cast(dst - result.begin())); return result; + } diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2synchdata.h b/3rdparty/taglib/mpeg/id3v2/id3v2synchdata.h index f70451ebf..0ac6a762f 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2synchdata.h +++ b/3rdparty/taglib/mpeg/id3v2/id3v2synchdata.h @@ -31,36 +31,32 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace ID3v2 { //! 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 - * methods for converting to and from these values to ByteVectors for - * things rendering and parsing ID3v2 data. - */ + * 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 methods for converting to and from these values to ByteVectors for things rendering and parsing ID3v2 data. + */ namespace SynchData { /*! - * This returns the unsigned integer value of \a data where \a data is a - * ByteVector that contains a \e synchsafe integer (Structure, - * 6.2). The default \a length of - * 4 is used if another value is not specified. - */ + * This returns the unsigned integer value of \a data where \a data is a ByteVector that contains a \e synchsafe integer (Structure, + * 6.2). + * The default \a length of 4 is used if another value is not specified. + */ TAGLIB_EXPORT unsigned int toUInt(const ByteVector &data); /*! - * Returns a 4 byte (32 bit) synchsafe integer based on \a value. - */ + * Returns a 4 byte (32 bit) synchsafe integer based on \a value. + */ TAGLIB_EXPORT ByteVector fromUInt(unsigned int value); /*! - * Convert the data from unsynchronized data to its original format. - */ + * Convert the data from unsynchronized data to its original format. + */ TAGLIB_EXPORT ByteVector decode(const ByteVector &input); } // namespace SynchData diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2tag.cpp b/3rdparty/taglib/mpeg/id3v2/id3v2tag.cpp index 468562ba5..51d52ef59 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2tag.cpp +++ b/3rdparty/taglib/mpeg/id3v2/id3v2tag.cpp @@ -57,11 +57,11 @@ const long MaxPaddingSize = 1024 * 1024; class ID3v2::Tag::TagPrivate { public: - TagPrivate() : factory(0), - file(0), + TagPrivate() : factory(nullptr), + file(nullptr), tagOffset(0), - extendedHeader(0), - footer(0) { + extendedHeader(nullptr), + footer(nullptr) { frameList.setAutoDelete(true); } @@ -87,11 +87,9 @@ class ID3v2::Tag::TagPrivate { // StringHandler implementation //////////////////////////////////////////////////////////////////////////////// -Latin1StringHandler::Latin1StringHandler() { -} +Latin1StringHandler::Latin1StringHandler() {} -Latin1StringHandler::~Latin1StringHandler() { -} +Latin1StringHandler::~Latin1StringHandler() {} String Latin1StringHandler::parse(const ByteVector &data) const { return String(data, String::Latin1); @@ -101,13 +99,11 @@ 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; @@ -138,6 +134,7 @@ String ID3v2::Tag::album() const { } String ID3v2::Tag::comment() const { + const FrameList &comments = d->frameListMap["COMM"]; if (comments.isEmpty()) @@ -151,9 +148,11 @@ String ID3v2::Tag::comment() const { } return comments.front()->toString(); + } 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 " ". @@ -192,18 +191,23 @@ String ID3v2::Tag::genre() const { } return genres.toString(); + } 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()) return d->frameListMap["TRCK"].front()->toString().toInt(); return 0; + } void ID3v2::Tag::setTitle(const String &s) { @@ -219,6 +223,7 @@ void ID3v2::Tag::setAlbum(const String &s) { } void ID3v2::Tag::setComment(const String &s) { + if (s.isEmpty()) { removeFrames("COMM"); return; @@ -231,9 +236,11 @@ void ID3v2::Tag::setComment(const String &s) { addFrame(f); f->setText(s); } + } void ID3v2::Tag::setGenre(const String &s) { + if (s.isEmpty()) { removeFrames("TCON"); return; @@ -256,6 +263,7 @@ void ID3v2::Tag::setGenre(const String &s) { setTextFrame("TCON", s); #endif + } void ID3v2::Tag::setYear(unsigned int i) { @@ -286,10 +294,6 @@ ExtendedHeader *ID3v2::Tag::extendedHeader() const { return d->extendedHeader; } -Footer *ID3v2::Tag::footer() const { - return d->footer; -} - const FrameListMap &ID3v2::Tag::frameListMap() const { return d->frameListMap; } @@ -308,6 +312,7 @@ void ID3v2::Tag::addFrame(Frame *frame) { } 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); @@ -319,6 +324,7 @@ void ID3v2::Tag::removeFrame(Frame *frame, bool del) { // ...and delete as desired if (del) delete frame; + } void ID3v2::Tag::removeFrames(const ByteVector &id) { @@ -337,6 +343,7 @@ PropertyMap ID3v2::Tag::properties() const { } 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()); @@ -346,7 +353,7 @@ void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties) { // delete all unknown frames of given type FrameList l = frameList(id); for (FrameList::ConstIterator fit = l.begin(); fit != l.end(); fit++) - if (dynamic_cast(*fit) != 0) + if (dynamic_cast(*fit) != nullptr) removeFrame(*fit); } else if (it->size() == 4) { @@ -358,7 +365,7 @@ void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties) { if (it->size() <= 5) continue; // invalid specification String description = it->substr(5); - Frame *frame = 0; + Frame *frame = nullptr; if (id == "TXXX") frame = UserTextIdentificationFrame::find(this, description); else if (id == "WXXX") @@ -373,9 +380,11 @@ void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties) { removeFrame(frame); } } + } 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. @@ -418,6 +427,7 @@ PropertyMap ID3v2::Tag::setProperties(const PropertyMap &origProps) { 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 + } ByteVector ID3v2::Tag::render() const { @@ -426,46 +436,40 @@ ByteVector ID3v2::Tag::render() const { void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const { #ifdef NO_ITUNES_HACKS - const char *unsupportedFrames[] = { - "ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG", - "TMOO", "TPRO", "TSOA", "TSOT", "TSST", "TSOP", 0 - }; + const char *unsupportedFrames[] = { "ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG", "TMOO", "TPRO", "TSOA", "TSOT", "TSST", "TSOP", nullptr }; #else // iTunes writes and reads TSOA, TSOT, TSOP to ID3v2.3. - const char *unsupportedFrames[] = { - "ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG", - "TMOO", "TPRO", "TSST", 0 - }; + const char *unsupportedFrames[] = { "ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG", "TMOO", "TPRO", "TSST", nullptr }; #endif - ID3v2::TextIdentificationFrame *frameTDOR = 0; - ID3v2::TextIdentificationFrame *frameTDRC = 0; - ID3v2::TextIdentificationFrame *frameTIPL = 0; - ID3v2::TextIdentificationFrame *frameTMCL = 0; + ID3v2::TextIdentificationFrame *frameTDOR = nullptr; + ID3v2::TextIdentificationFrame *frameTDRC = nullptr; + ID3v2::TextIdentificationFrame *frameTIPL = nullptr; + ID3v2::TextIdentificationFrame *frameTMCL = nullptr; 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"); - frame = 0; + frame = nullptr; break; } } if (frame && frameID == "TDOR") { frameTDOR = dynamic_cast(frame); - frame = 0; + frame = nullptr; } if (frame && frameID == "TDRC") { frameTDRC = dynamic_cast(frame); - frame = 0; + frame = nullptr; } if (frame && frameID == "TIPL") { frameTIPL = dynamic_cast(frame); - frame = 0; + frame = nullptr; } if (frame && frameID == "TMCL") { frameTMCL = dynamic_cast(frame); - frame = 0; + frame = nullptr; } if (frame) { frames->append(frame); @@ -522,13 +526,11 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const frames->append(frameIPLS); newFrames->append(frameIPLS); } -} -ByteVector ID3v2::Tag::render(int version) const { - return render(version == 3 ? v3 : v4); } 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 @@ -601,6 +603,7 @@ ByteVector ID3v2::Tag::render(Version version) const { std::copy(headerData.begin(), headerData.end(), tagData.begin()); return tagData; + } Latin1StringHandler const *ID3v2::Tag::latin1StringHandler() { @@ -619,6 +622,7 @@ void ID3v2::Tag::setLatin1StringHandler(const Latin1StringHandler *handler) { //////////////////////////////////////////////////////////////////////////////// void ID3v2::Tag::read() { + if (!d->file) return; @@ -657,9 +661,11 @@ void ID3v2::Tag::read() { debug("ID3v2::Tag::read() - Duplicate ID3v2 tags found."); d->header.setTagSize(d->header.tagSize() + extraSize); } + } void ID3v2::Tag::parse(const ByteVector &origData) { + ByteVector data = origData; if (d->header.unsynchronisation() && d->header.majorVersion() <= 3) @@ -723,9 +729,11 @@ void ID3v2::Tag::parse(const ByteVector &origData) { } d->factory->rebuildAggregateFrames(this); + } void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value) { + if (value.isEmpty()) { removeFrames(id); return; @@ -739,4 +747,5 @@ void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value) { addFrame(f); f->setText(value); } + } diff --git a/3rdparty/taglib/mpeg/id3v2/id3v2tag.h b/3rdparty/taglib/mpeg/id3v2/id3v2tag.h index cf604bf19..ff710c871 100644 --- a/3rdparty/taglib/mpeg/id3v2/id3v2tag.h +++ b/3rdparty/taglib/mpeg/id3v2/id3v2tag.h @@ -53,104 +53,92 @@ typedef Map FrameListMap; //! 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 - * Windows-1252 for western languages, Shift_JIS for Japanese and so on. - * - * Here is an option to read such tags by subclassing this class, - * reimplementing parse() and setting your reimplementation as the default - * with ID3v2::Tag::setStringHandler(). - * - * \note Writing non-ISO-8859-1 tags is not implemented intentionally. - * Use UTF-16 or UTF-8 instead. - * - * \see ID3v2::Tag::setStringHandler() - */ + * 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 Windows-1252 for western languages, Shift_JIS for Japanese and so on. + * + * Here is an option to read such tags by subclassing this class, + * reimplementing parse() and setting your reimplementation as the default + * with ID3v2::Tag::setStringHandler(). + * + * \note Writing non-ISO-8859-1 tags is not implemented intentionally. + * Use UTF-16 or UTF-8 instead. + * + * \see ID3v2::Tag::setStringHandler() + */ 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. - */ + * 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; }; //! 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 - * read() and parse() protected methods, it provides the most basic level of - * parsing. In these methods the ID3v2 tag is extracted from the file and - * split into data components. - * - * ID3v2 tags have several parts, TagLib attempts to provide an interface - * for them all. header(), footer() and extendedHeader() correspond to those - * data structures in the ID3v2 standard and the APIs for the classes that - * they return attempt to reflect this. - * - * Also ID3v2 tags are built up from a list of frames, which are in turn - * have a header and a list of fields. TagLib provides two ways of accessing - * the list of frames that are in a given ID3v2 tag. The first is simply - * via the frameList() method. This is just a list of pointers to the frames. - * The second is a map from the frame type -- i.e. "COMM" for comments -- and - * a list of frames of that type. (In some cases ID3v2 allows for multiple - * frames of the same type, hence this being a map to a list rather than just - * a map to an individual frame.) - * - * More information on the structure of frames can be found in the ID3v2::Frame - * class. - * - * read() and parse() pass binary data to the other ID3v2 class structures, - * they do not handle parsing of flags or fields, for instance. Those are - * handled by similar functions within those classes. - * - * \note All pointers to data structures within the tag will become invalid - * when the tag is destroyed. - * - * \warning Dealing with the nasty details of ID3v2 is not for the faint of - * heart and should not be done without much meditation on the spec. It's - * rather long, but if you're planning on messing with this class and others - * that deal with the details of ID3v2 (rather than the nice, safe, abstract - * TagLib::Tag and friends), it's worth your time to familiarize yourself - * with said spec (which is distributed with the TagLib sources). TagLib - * tries to do most of the work, but with a little luck, you can still - * convince it to generate invalid ID3v2 tags. The APIs for ID3v2 assume a - * working knowledge of ID3v2 structure. You're been warned. - */ + * 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 read() and parse() protected methods, + * it provides the most basic level of parsing. + * In these methods the ID3v2 tag is extracted from the file and split into data components. + * + * ID3v2 tags have several parts, TagLib attempts to provide an interface for them all. + * header(), footer() and extendedHeader() correspond to those data structures in + * the ID3v2 standard and the APIs for the classes that they return attempt to reflect this. + * + * Also ID3v2 tags are built up from a list of frames, which are in turn have a header and a list of fields. + * TagLib provides two ways of accessing the list of frames that are in a given ID3v2 tag. + * The first is simply via the frameList() method. This is just a list of pointers to the frames. + * The second is a map from the frame type -- i.e. "COMM" for comments -- and a list of frames of that type. + * (In some cases ID3v2 allows for multiple frames of the same type, hence this being a map to a list rather than just a map to an individual frame.) + * + * More information on the structure of frames can be found in the ID3v2::Frame class. + * + * read() and parse() pass binary data to the other ID3v2 class structures, they do not handle parsing of flags or fields, for instance. + * Those are handled by similar functions within those classes. + * + * \note All pointers to data structures within the tag will become invalid when the tag is destroyed. + * + * \warning Dealing with the nasty details of ID3v2 is not for the faint of + * heart and should not be done without much meditation on the spec. + * It's rather long, but if you're planning on messing with this class and others that deal with the details of ID3v2 + * (rather than the nice, safe, abstract TagLib::Tag and friends), it's worth your time to familiarize yourself with said spec + * (which is distributed with the TagLib sources). + * TagLib tries to do most of the work, but with a little luck, you can still convince it to generate invalid ID3v2 tags. + * The APIs for ID3v2 assume a working knowledge of ID3v2 structure. You're been warned. + */ 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. - */ + * Constructs an empty ID3v2 tag. + * + * \note You must create at least one frame for this tag to be valid. + */ 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. - * - * \note You should be able to ignore the \a factory parameter in almost - * all situations. You would want to specify your own FrameFactory - * subclass in the case that you are extending TagLib to support additional - * frame types, which would be incorporated into your factory. - * - * \see FrameFactory - */ + * 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. + * + * \note You should be able to ignore the \a factory parameter in almost all situations. + * You would want to specify your own FrameFactory subclass in the case that you are extending TagLib + * to support additional frame types, which would be incorporated into your factory. + * + * \see FrameFactory + */ Tag(File *file, long tagOffset, const FrameFactory *factory = FrameFactory::instance()); /*! - * Destroys this Tag instance. - */ + * Destroys this Tag instance. + */ virtual ~Tag(); // Reimplementations. @@ -174,226 +162,190 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { virtual bool isEmpty() const; /*! - * Returns a pointer to the tag's header. - */ + * Returns a pointer to the tag's header. + */ Header *header() const; /*! - * Returns a pointer to the tag's extended header or null if there is no - * extended header. - */ + * Returns a pointer to the tag's extended header or null if there is no extended header. + */ 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 - * nothing useful to be retrieved from the footer, but well, again, I'm - * prone to change my mind, so this gets to stay around until near a - * release. - */ - 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. - * - * This is the most convenient structure for accessing the tag's frames. - * Many frame types allow multiple instances of the same frame type so this - * is a map of lists. In most cases however there will only be a single - * frame of a certain type. - * - * Let's say for instance that you wanted to access the frame for total - * beats per minute -- the TBPM frame. - * - * \code - * TagLib::MPEG::File f("foo.mp3"); - * - * // Check to make sure that it has an ID3v2 tag - * - * if(f.ID3v2Tag()) { - * - * // Get the list of frames for a specific frame type - * - * TagLib::ID3v2::FrameList l = f.ID3v2Tag()->frameListMap()["TBPM"]; - * - * if(!l.isEmpty()) - * std::cout << l.front()->toString() << std::endl; - * } - * - * \endcode - * - * \warning You should not modify this data structure directly, instead - * use addFrame() and removeFrame(). - * - * \see frameList() - */ + * Returns a reference to the frame list map. This is an FrameListMap of all of the frames in the tag. + * + * This is the most convenient structure for accessing the tag's frames. + * Many frame types allow multiple instances of the same frame type so this is a map of lists. + * In most cases however there will only be a single frame of a certain type. + * + * Let's say for instance that you wanted to access the frame for total beats per minute -- the TBPM frame. + * + * \code + * TagLib::MPEG::File f("foo.mp3"); + * + * // Check to make sure that it has an ID3v2 tag + * + * if(f.ID3v2Tag()) { + * + * // Get the list of frames for a specific frame type + * + * TagLib::ID3v2::FrameList l = f.ID3v2Tag()->frameListMap()["TBPM"]; + * + * if(!l.isEmpty()) + * std::cout << l.front()->toString() << std::endl; + * } + * + * \endcode + * + * \warning You should not modify this data structure directly, instead use addFrame() and removeFrame(). + * + * \see frameList() + */ 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. - * - * This can be useful if for example you want iterate over the tag's frames - * in the order that they occur in the tag. - * - * \warning You should not modify this data structure directly, instead - * use addFrame() and removeFrame(). - */ + * 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. + * + * This can be useful if for example you want iterate over the tag's frames in the order that they occur in the tag. + * + * \warning You should not modify this data structure directly, instead use addFrame() and removeFrame(). + */ 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: - * - * \code - * frameListMap()[frameID]; - * \endcode - * - * \see frameListMap() - */ + * 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: + * + * \code + * frameListMap()[frameID]; + * \endcode + * + * \see frameListMap() + */ 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() - */ + * 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); /*! - * 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() - */ + * 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); /*! - * 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() - */ + * 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); /*! - * 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: - * - if ID3v2 frame ID is known by Frame::frameIDToKey(), the returned - * key is used - * - if the frame ID is "TXXX" (user text frame), the description() is - * used as key - * - if the frame ID is "WXXX" (user url frame), - * - if the description is empty or "URL", the key "URL" is used - * - otherwise, the key "URL:" is used; - * - if the frame ID is "COMM" (comments frame), - * - if the description is empty or "COMMENT", the key "COMMENT" - * is used - * - otherwise, the key "COMMENT:" is used; - * - if the frame ID is "USLT" (unsynchronized lyrics), - * - if the description is empty or "LYRICS", the key "LYRICS" is used - * - otherwise, the key "LYRICS:" is used; - * - if the frame ID is "TIPL" (involved peoples list), and if all the - * roles defined in the frame are known in TextIdentificationFrame::involvedPeopleMap(), - * then "=" will be contained in the returned object for each - * - if the frame ID is "TMCL" (musician credit list), then - * "PERFORMER:=" will be contained in the returned - * PropertyMap for each defined musician - * In any other case, the unsupportedData() of the returned object will contain - * the frame's ID and, in case of a frame ID which is allowed to appear more than - * once, the description, separated by a "/". - * - */ + * 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: + * - if ID3v2 frame ID is known by Frame::frameIDToKey(), the returned key is used + * - if the frame ID is "TXXX" (user text frame), the description() is used as key + * - if the frame ID is "WXXX" (user url frame), + * - if the description is empty or "URL", the key "URL" is used + * - otherwise, the key "URL:" is used; + * - if the frame ID is "COMM" (comments frame), + * - if the description is empty or "COMMENT", the key "COMMENT" is used + * - otherwise, the key "COMMENT:" is used; + * - if the frame ID is "USLT" (unsynchronized lyrics), + * - if the description is empty or "LYRICS", the key "LYRICS" is used + * - otherwise, the key "LYRICS:" is used; + * - if the frame ID is "TIPL" (involved peoples list), and if all the + * roles defined in the frame are known in TextIdentificationFrame::involvedPeopleMap(), + * then "=" will be contained in the returned object for each + * - if the frame ID is "TMCL" (musician credit list), then + * "PERFORMER:=" will be contained in the returned PropertyMap for each defined musician + * In any other case, the unsupportedData() of the returned object will contain + * the frame's ID and, in case of a frame ID which is allowed to appear more than + * once, the description, separated by a "/". + * + */ 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: - * - a four-character frame ID, if the ID3 specification allows only one - * frame with that ID (thus, the frame is uniquely determined) - * - frameID + "/" + description(), when the ID is one of "TXXX", "WXXX", - * "COMM", or "USLT", - * - "UNKNOWN/" + frameID, for frames that could not be parsed by TagLib. - * In that case, *all* unknown frames with the given ID will be removed. - */ + * 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: + * - a four-character frame ID, if the ID3 specification allows only one + * frame with that ID (thus, the frame is uniquely determined) + * - frameID + "/" + description(), when the ID is one of "TXXX", "WXXX", + * "COMM", or "USLT", + * - "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); /*! - * Implements the unified property interface -- import function. - * See the comments in properties(). - */ + * Implements the unified property interface -- import function. + * See the comments in properties(). + */ PropertyMap setProperties(const PropertyMap &); /*! - * Render the tag back to binary data, suitable to be written to disk. - */ + * Render the tag back to binary data, suitable to be written to disk. + */ ByteVector render() const; /*! - * \deprecated - */ - 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. - */ + * 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; /*! - * Gets the current string handler that decides how the "Latin-1" data - * will be converted to and from binary data. - * - * \see Latin1StringHandler - */ + * 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(); /*! - * 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 - * released and default ISO-8859-1 handler is restored. - * - * \note The caller is responsible for deleting the previous handler - * as needed after it is released. - * - * \see 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 released and default ISO-8859-1 handler is restored. + * + * \note The caller is responsible for deleting the previous handler as needed after it is released. + * + * \see Latin1StringHandler + */ static void setLatin1StringHandler(const Latin1StringHandler *handler); 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. - */ + * 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(); /*! - * 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. - */ + * 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); /*! - * 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. - */ + * 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); /*! - * Dowgrade frames from ID3v2.4 (used internally and by default) to ID3v2.3 - */ + * Dowgrade frames from ID3v2.4 (used internally and by default) to ID3v2.3 + */ void downgradeFrames(FrameList *existingFrames, FrameList *newFrames) const; private: diff --git a/3rdparty/taglib/mpeg/mpegfile.cpp b/3rdparty/taglib/mpeg/mpegfile.cpp index 653881abc..7091d6a9e 100644 --- a/3rdparty/taglib/mpeg/mpegfile.cpp +++ b/3rdparty/taglib/mpeg/mpegfile.cpp @@ -53,7 +53,7 @@ class MPEG::File::FilePrivate { APELocation(-1), APEOriginalSize(0), ID3v1Location(-1), - properties(0) {} + properties(nullptr) {} ~FilePrivate() { delete properties; @@ -92,6 +92,7 @@ class AdapterFile : public Strawberry_TagLib::TagLib::File { } // namespace bool MPEG::File::isSupported(IOStream *stream) { + if (!stream || !stream->isOpen()) return false; @@ -121,30 +122,25 @@ bool MPEG::File::isSupported(IOStream *stream) { stream->seek(originalPosition); return false; + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -MPEG::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate()) { +MPEG::File::File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate(frameFactory)) { + 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()) - read(readProperties); -} +MPEG::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate(frameFactory)) { -MPEG::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory, - bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate(frameFactory)) { if (isOpen()) read(readProperties); + } MPEG::File::~File() { @@ -164,12 +160,14 @@ void MPEG::File::removeUnsupportedProperties(const StringList &properties) { } PropertyMap MPEG::File::setProperties(const PropertyMap &properties) { + // update ID3v1 tag if it exists, but ignore the return value if (ID3v1Tag()) ID3v1Tag()->setProperties(properties); return ID3v2Tag(true)->setProperties(properties); + } MPEG::Properties *MPEG::File::audioProperties() const { @@ -184,24 +182,8 @@ bool MPEG::File::save(int tags) { return save(tags, 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) { - return save(tags, - stripOthers ? StripOthers : StripNone, - id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4); -} - -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); -} - 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; @@ -308,6 +290,7 @@ bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, Duplica } return true; + } ID3v2::Tag *MPEG::File::ID3v2Tag(bool create) { @@ -327,6 +310,7 @@ bool MPEG::File::strip(int tags) { } bool MPEG::File::strip(int tags, bool freeMemory) { + if (readOnly()) { debug("MPEG::File::strip() - Cannot strip tags from a read only file."); return false; @@ -345,7 +329,7 @@ bool MPEG::File::strip(int tags, bool freeMemory) { d->ID3v2OriginalSize = 0; if (freeMemory) - d->tag.set(ID3v2Index, 0); + d->tag.set(ID3v2Index, nullptr); } if ((tags & ID3v1) && d->ID3v1Location >= 0) { @@ -354,7 +338,7 @@ bool MPEG::File::strip(int tags, bool freeMemory) { d->ID3v1Location = -1; if (freeMemory) - d->tag.set(ID3v1Index, 0); + d->tag.set(ID3v1Index, nullptr); } if ((tags & APE) && d->APELocation >= 0) { @@ -367,17 +351,15 @@ bool MPEG::File::strip(int tags, bool freeMemory) { d->APEOriginalSize = 0; if (freeMemory) - d->tag.set(APEIndex, 0); + d->tag.set(APEIndex, nullptr); } return true; -} -void MPEG::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) { - d->ID3v2FrameFactory = factory; } long MPEG::File::nextFrameOffset(long position) { + ByteVector frameSyncBytes(2, '\0'); while (true) { @@ -398,9 +380,11 @@ long MPEG::File::nextFrameOffset(long position) { position += bufferSize(); } + } long MPEG::File::previousFrameOffset(long position) { + ByteVector frameSyncBytes(2, '\0'); while (position > 0) { @@ -422,18 +406,22 @@ long MPEG::File::previousFrameOffset(long position) { } return -1; + } long MPEG::File::firstFrameOffset() { + long position = 0; if (hasID3v2Tag()) position = d->ID3v2Location + ID3v2Tag()->header()->completeTagSize(); return nextFrameOffset(position); + } long MPEG::File::lastFrameOffset() { + long position; if (hasAPETag()) @@ -444,6 +432,7 @@ long MPEG::File::lastFrameOffset() { position = length(); return previousFrameOffset(position); + } bool MPEG::File::hasID3v1Tag() const { @@ -463,6 +452,7 @@ bool MPEG::File::hasAPETag() const { //////////////////////////////////////////////////////////////////////////////// void MPEG::File::read(bool readProperties) { + // Look for an ID3v2 tag d->ID3v2Location = findID3v2(); @@ -496,9 +486,11 @@ void MPEG::File::read(bool readProperties) { ID3v2Tag(true); ID3v1Tag(true); + } long MPEG::File::findID3v2() { + if (!isValid()) return -1; @@ -544,4 +536,5 @@ long MPEG::File::findID3v2() { position += bufferSize(); } + } diff --git a/3rdparty/taglib/mpeg/mpegfile.h b/3rdparty/taglib/mpeg/mpegfile.h index 7b06cb3e4..74679cfaf 100644 --- a/3rdparty/taglib/mpeg/mpegfile.h +++ b/3rdparty/taglib/mpeg/mpegfile.h @@ -55,17 +55,16 @@ namespace 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. - */ + * 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: /*! - * This set of flags is used for various operations and is suitable for - * being OR-ed together. - */ + * 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, @@ -80,302 +79,238 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { }; /*! - * Constructs an MPEG file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - * - * \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); - - /*! - * Constructs an MPEG file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * If this file contains and ID3v2 tag the frames will be created using - * \a frameFactory. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ + * Constructs an MPEG file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \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); + 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. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * If this file contains and ID3v2 tag the frames will be created using - * \a frameFactory. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ + * Constructs an MPEG file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * If this file contains and ID3v2 tag the frames will be created using \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ File(IOStream *stream, ID3v2::FrameFactory *frameFactory, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the 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, - * the information from the ID3v2 tag will be returned. - * - * If you would like more granular control over the content of the tags, - * with the concession of generality, use the tag-type specific calls. - * - * \note As this tag is not implemented as an ID3v2 tag or an ID3v1 tag, - * but a union of the two this pointer may not be cast to the specific - * tag types. - * - * \see ID3v1Tag() - * \see ID3v2Tag() - * \see APETag() - */ + * 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, + * the information from the ID3v2 tag will be returned. + * + * If you would like more granular control over the content of the tags, + * with the concession of generality, use the tag-type specific calls. + * + * \note As this tag is not implemented as an ID3v2 tag or an ID3v1 tag, + * but a union of the two this pointer may not be cast to the specific tag types. + * + * \see ID3v1Tag() + * \see ID3v2Tag() + * \see APETag() + */ 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. - */ + * 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; 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. - * If an ID3v1 tag exists, it will be updated as well, within the - * limitations of that format. - * The returned PropertyMap refers to the ID3v2 tag only. - */ + * 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. + * If an ID3v1 tag exists, it will be updated as well, within the limitations of that format. + * The returned PropertyMap refers to the ID3v2 tag only. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the MPEG::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the MPEG::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ 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. - * - * If neither exists or if both tags are empty, this will strip the tags - * from the file. - * - * This is the same as calling save(AllTags); - * - * If you would like more granular control over the content of the tags, - * with the concession of generality, use parameterized save call below. - * - * \see save(int tags) - */ + * 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. + * + * If neither exists or if both tags are empty, this will strip the tags from the file. + * + * This is the same as calling save(AllTags); + * + * If you would like more granular control over the content of the tags, + * with the concession of generality, use parameterized save call below. + * + * \see save(int tags) + */ 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. - * - * This strips all tags not included in the mask, but does not modify them - * in memory, so later calls to save() which make use of these tags will - * remain valid. This also strips empty tags. - */ + * 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. + * + * This strips all tags not included in the mask, but does not modify them + * 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); /*! - * \deprecated - */ - // BIC: combine with the above method - TAGLIB_DEPRECATED bool save(int tags, bool stripOthers); + * Save the file. This will attempt to save all of the tag types that are + * specified by OR-ing together TagTypes values. + * + * \a strip can be set to strip all tags except those in \a tags. + * Those tags will not be modified in memory, and thus remain valid. + * + * \a version specifies the ID3v2 version to be used for writing tags. + * By default, the latest standard, ID3v2.4 is used. + * + * 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); /*! - * \deprecated - */ - // 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); - - /*! - * Save the file. This will attempt to save all of the tag types that are - * specified by OR-ing together TagTypes values. - * - * \a strip can be set to strip all tags except those in \a tags. Those - * tags will not be modified in memory, and thus remain valid. - * - * \a version specifies the ID3v2 version to be used for writing tags. By - * default, the latest standard, ID3v2.4 is used. - * - * 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); - - /*! - * Returns a pointer to the ID3v2 tag of the file. - * - * If \a create is false (the default) this may return a null pointer - * if there is no valid ID3v2 tag. If \a create is true it will create - * an ID3v2 tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file - * on disk actually has an ID3v2 tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasID3v2Tag() - */ + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v2 tag. + * If \a create is true it will create an ID3v2 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v2 tag. + * Use hasID3v2Tag() to check if the file on disk actually has an ID3v2 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasID3v2Tag() + */ 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 - * if there is no valid ID3v1 tag. If \a create is true it will create - * an ID3v1 tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file - * on disk actually has an ID3v1 tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasID3v1Tag() - */ + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v1 tag. + * If \a create is true it will create an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v1 tag. + * Use hasID3v1Tag() to check if the file on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasID3v1Tag() + */ 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 - * if there is no valid APE tag. If \a create is true it will create - * an APE tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an APE tag. Use hasAPETag() to check if the file - * on disk actually has an APE tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasAPETag() - */ + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer if there is no valid APE tag. + * If \a create is true it will create an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an APE tag. + * Use hasAPETag() to check if the file on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasAPETag() + */ 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. - * - * This is equivalent to strip(tags, true) - * - * \note This will also invalidate pointers to the ID3 and APE tags - * as their memory will be freed. - * - * \note This will update the file immediately. - */ + * 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. + * + * This is equivalent to strip(tags, true) + * + * \note This will also invalidate pointers to the ID3 and APE tags as their memory will be freed. + * + * \note This will update the file immediately. + */ 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. - * - * If \a freeMemory is true the ID3 and APE tags will be deleted and - * pointers to them will be invalidated. - * - * \note This will update the file immediately. - */ + * 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. + * + * If \a freeMemory is true the ID3 and APE tags will be deleted and pointers to them will be invalidated. + * + * \note This will update the file immediately. + */ // 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); - - /*! - * Returns the position in the file of the first MPEG frame. - */ + * Returns the position in the file of the first MPEG frame. + */ long firstFrameOffset(); /*! - * Returns the position in the file of the next MPEG frame, - * using the current position as start - */ + * Returns the position in the file of the next MPEG frame, using the current position as start + */ long nextFrameOffset(long position); /*! - * Returns the position in the file of the previous MPEG frame, - * using the current position as start - */ + * Returns the position in the file of the previous MPEG frame, using the current position as start + */ long previousFrameOffset(long position); /*! - * Returns the position in the file of the last MPEG frame. - */ + * Returns the position in the file of the last MPEG frame. + */ long lastFrameOffset(); /*! - * Returns whether or not the file on disk actually has an ID3v1 tag. - * - * \see ID3v1Tag() - */ + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ bool hasID3v1Tag() const; /*! - * Returns whether or not the file on disk actually has an ID3v2 tag. - * - * \see ID3v2Tag() - */ + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ bool hasID3v2Tag() const; /*! - * Returns whether or not the file on disk actually has an APE tag. - * - * \see APETag() - */ + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ 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. - */ + * 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); private: @@ -388,6 +323,7 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { class FilePrivate; FilePrivate *d; }; + } // namespace MPEG } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mpeg/mpegheader.cpp b/3rdparty/taglib/mpeg/mpegheader.cpp index caaa97776..4bee43f50 100644 --- a/3rdparty/taglib/mpeg/mpegheader.cpp +++ b/3rdparty/taglib/mpeg/mpegheader.cpp @@ -67,10 +67,6 @@ class MPEG::Header::HeaderPrivate : public RefCounter { // public members //////////////////////////////////////////////////////////////////////////////// -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()) { parse(file, offset, checkLength); } @@ -133,6 +129,7 @@ int MPEG::Header::samplesPerFrame() const { } MPEG::Header &MPEG::Header::operator=(const Header &h) { + if (&h == this) return *this; @@ -142,6 +139,7 @@ MPEG::Header &MPEG::Header::operator=(const Header &h) { d = h.d; d->ref(); return *this; + } //////////////////////////////////////////////////////////////////////////////// @@ -149,6 +147,7 @@ MPEG::Header &MPEG::Header::operator=(const Header &h) { //////////////////////////////////////////////////////////////////////////////// void MPEG::Header::parse(File *file, long offset, bool checkLength) { + file->seek(offset); const ByteVector data = file->readBlock(4); @@ -298,4 +297,5 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength) { // Now that we're done parsing, set this to be a valid frame. d->isValid = true; + } diff --git a/3rdparty/taglib/mpeg/mpegheader.h b/3rdparty/taglib/mpeg/mpegheader.h index 9a0b7e387..af1170a8a 100644 --- a/3rdparty/taglib/mpeg/mpegheader.h +++ b/3rdparty/taglib/mpeg/mpegheader.h @@ -39,49 +39,41 @@ namespace MPEG { //! 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 - * this - * document as a reference. - */ + * This is an implementation of MPEG Layer III headers. The API follows more + * or less the binary format of these headers. I've used + * this + * document as a reference. + */ class TAGLIB_EXPORT Header { public: /*! - * Parses an MPEG header based on \a data. - * - * \deprecated - */ - 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. - */ + * 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); /*! - * Does a shallow copy of \a h. - */ + * Does a shallow copy of \a h. + */ Header(const Header &h); /*! - * Destroys this Header instance. - */ + * Destroys this Header instance. + */ virtual ~Header(); /*! - * Returns true if the frame is at least an appropriate size and has - * legal values. - */ + * Returns true if the frame is at least an appropriate size and has legal values. + */ bool isValid() const; /*! - * The MPEG Version. - */ + * The MPEG Version. + */ enum Version { //! MPEG Version 1 Version1 = 0, @@ -92,39 +84,39 @@ class TAGLIB_EXPORT Header { }; /*! - * Returns the MPEG Version of the header. - */ + * Returns the MPEG Version of the header. + */ Version version() const; /*! - * Returns the layer version. This will be between the values 1-3. - */ + * Returns the layer version. This will be between the values 1-3. + */ int layer() const; /*! - * Returns true if the MPEG protection bit is enabled. - */ + * Returns true if the MPEG protection bit is enabled. + */ bool protectionEnabled() const; /*! - * Returns the bitrate encoded in the header. - */ + * Returns the bitrate encoded in the header. + */ int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ int sampleRate() const; /*! - * Returns true if the frame is padded. - */ + * Returns true if the frame is padded. + */ bool isPadded() const; /*! - * There are a few combinations or one or two channel audio that are - * possible: - */ + * There are a few combinations or one or two channel audio that are + * possible: + */ enum ChannelMode { //! Stereo Stereo = 0, @@ -137,33 +129,33 @@ class TAGLIB_EXPORT Header { }; /*! - * Returns the channel mode for this frame. - */ + * Returns the channel mode for this frame. + */ ChannelMode channelMode() const; /*! - * Returns true if the copyrighted bit is set. - */ + * Returns true if the copyrighted bit is set. + */ bool isCopyrighted() const; /*! - * Returns true if the "original" bit is set. - */ + * Returns true if the "original" bit is set. + */ bool isOriginal() const; /*! - * Returns the frame length in bytes. - */ + * Returns the frame length in bytes. + */ int frameLength() const; /*! - * Returns the number of frames per sample. - */ + * Returns the number of frames per sample. + */ int samplesPerFrame() const; /*! - * Makes a shallow copy of the header. - */ + * Makes a shallow copy of the header. + */ Header &operator=(const Header &h); private: @@ -172,6 +164,7 @@ class TAGLIB_EXPORT Header { class HeaderPrivate; HeaderPrivate *d; }; + } // namespace MPEG } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mpeg/mpegproperties.cpp b/3rdparty/taglib/mpeg/mpegproperties.cpp index 425e80a75..dab2dd5e6 100644 --- a/3rdparty/taglib/mpeg/mpegproperties.cpp +++ b/3rdparty/taglib/mpeg/mpegproperties.cpp @@ -36,7 +36,7 @@ using namespace Strawberry_TagLib::TagLib; class MPEG::Properties::PropertiesPrivate { public: - PropertiesPrivate() : xingHeader(0), + PropertiesPrivate() : xingHeader(nullptr), length(0), bitrate(0), sampleRate(0), @@ -69,8 +69,7 @@ class MPEG::Properties::PropertiesPrivate { // 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); } @@ -135,6 +134,7 @@ bool MPEG::Properties::isOriginal() const { //////////////////////////////////////////////////////////////////////////////// void MPEG::Properties::read(File *file) { + // Only the first valid frame is required if we have a VBR header. const long firstFrameOffset = file->firstFrameOffset(); @@ -152,7 +152,7 @@ void MPEG::Properties::read(File *file) { d->xingHeader = new XingHeader(file->readBlock(firstHeader.frameLength())); if (!d->xingHeader->isValid()) { delete d->xingHeader; - d->xingHeader = 0; + d->xingHeader = nullptr; } if (d->xingHeader && firstHeader.samplesPerFrame() > 0 && firstHeader.sampleRate() > 0) { @@ -197,4 +197,5 @@ void MPEG::Properties::read(File *file) { d->channelMode = firstHeader.channelMode(); d->isCopyrighted = firstHeader.isCopyrighted(); d->isOriginal = firstHeader.isOriginal(); + } diff --git a/3rdparty/taglib/mpeg/mpegproperties.h b/3rdparty/taglib/mpeg/mpegproperties.h index 39de90743..7cca92256 100644 --- a/3rdparty/taglib/mpeg/mpegproperties.h +++ b/3rdparty/taglib/mpeg/mpegproperties.h @@ -33,7 +33,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace MPEG { class File; @@ -42,99 +41,95 @@ class XingHeader; //! An implementation of audio property reading for MP3 /*! - * This reads the data from an MPEG Layer III stream found in the - * AudioProperties API. - */ + * This reads the data from an MPEG Layer III stream found in the AudioProperties API. + */ class TAGLIB_EXPORT Properties : public AudioProperties { public: /*! - * Create an instance of MPEG::Properties with the data read from the - * MPEG::File \a file. - */ + * Create an instance of MPEG::Properties with the data read from the MPEG::File \a file. + */ Properties(File *file, ReadStyle style = Average); /*! - * Destroys this MPEG Properties instance. - */ + * Destroys this MPEG Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ + * Returns the length of the file in seconds. + * The length is rounded down to the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ virtual int length() const; /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns a pointer to the Xing/VBRI header if one exists or null if no - * Xing/VBRI header was found. - */ + * Returns a pointer to the Xing/VBRI header if one exists or null if no Xing/VBRI header was found. + */ const XingHeader *xingHeader() const; /*! - * Returns the MPEG Version of the file. - */ + * Returns the MPEG Version of the file. + */ Header::Version version() const; /*! - * Returns the layer version. This will be between the values 1-3. - */ + * Returns the layer version. This will be between the values 1-3. + */ int layer() const; /*! - * Returns true if the MPEG protection bit is enabled. - */ + * Returns true if the MPEG protection bit is enabled. + */ bool protectionEnabled() const; /*! - * Returns the channel mode for this frame. - */ + * Returns the channel mode for this frame. + */ Header::ChannelMode channelMode() const; /*! - * Returns true if the copyrighted bit is set. - */ + * Returns true if the copyrighted bit is set. + */ bool isCopyrighted() const; /*! - * Returns true if the "original" bit is set. - */ + * Returns true if the "original" bit is set. + */ bool isOriginal() const; private: @@ -146,6 +141,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties { class PropertiesPrivate; PropertiesPrivate *d; }; + } // namespace MPEG } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/mpeg/mpegutils.h b/3rdparty/taglib/mpeg/mpegutils.h index 29cbd4ea0..3fc37ce29 100644 --- a/3rdparty/taglib/mpeg/mpegutils.h +++ b/3rdparty/taglib/mpeg/mpegutils.h @@ -36,13 +36,13 @@ 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. - * - * \note This does not check the length of the vector, since this is an - * internal utility function. - */ + * 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. + * + * \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. diff --git a/3rdparty/taglib/mpeg/xingheader.cpp b/3rdparty/taglib/mpeg/xingheader.cpp index ba6de9a77..3755d0586 100644 --- a/3rdparty/taglib/mpeg/xingheader.cpp +++ b/3rdparty/taglib/mpeg/xingheader.cpp @@ -34,9 +34,7 @@ using namespace Strawberry_TagLib::TagLib; class MPEG::XingHeader::XingHeaderPrivate { public: - XingHeaderPrivate() : frames(0), - size(0), - type(MPEG::XingHeader::Invalid) {} + XingHeaderPrivate() : frames(0), size(0), type(MPEG::XingHeader::Invalid) {} unsigned int frames; unsigned int size; @@ -72,16 +70,12 @@ 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*/) { - return 0; -} - //////////////////////////////////////////////////////////////////////////////// // private members //////////////////////////////////////////////////////////////////////////////// void MPEG::XingHeader::parse(const ByteVector &data) { + // Look for a Xing header. long offset = data.find("Xing"); @@ -126,4 +120,5 @@ void MPEG::XingHeader::parse(const ByteVector &data) { d->type = VBRI; } } + } diff --git a/3rdparty/taglib/mpeg/xingheader.h b/3rdparty/taglib/mpeg/xingheader.h index 9bfa6c7bc..b61bff9c9 100644 --- a/3rdparty/taglib/mpeg/xingheader.h +++ b/3rdparty/taglib/mpeg/xingheader.h @@ -41,78 +41,67 @@ class File; //! 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 - * implementation is only concerned with the total size of the stream (so - * that we can calculate the total playing time and the average bitrate). - * It uses - * this text and the XMMS sources as references. - */ + * 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 implementation is only concerned with the total size of the stream + * (so that we can calculate the total playing time and the average bitrate). + * It uses + * this text and the XMMS sources as references. + */ class TAGLIB_EXPORT XingHeader { public: /*! - * The type of the VBR header. - */ + * The type of the VBR header. + */ enum HeaderType { /*! - * Invalid header or no VBR header found. - */ + * Invalid header or no VBR header found. + */ Invalid = 0, /*! - * Xing header. - */ + * Xing header. + */ Xing = 1, /*! - * VBRI header. - */ + * VBRI header. + */ VBRI = 2, }; /*! - * Parses an Xing/VBRI header based on \a data which contains the entire - * first MPEG frame. - */ + * Parses an Xing/VBRI header based on \a data which contains the entire first MPEG frame. + */ XingHeader(const ByteVector &data); /*! - * Destroy this XingHeader instance. - */ + * Destroy this XingHeader instance. + */ virtual ~XingHeader(); /*! - * Returns true if the data was parsed properly and if there is a valid - * Xing/VBRI header present. - */ + * Returns true if the data was parsed properly and if there is a valid Xing/VBRI header present. + */ bool isValid() const; /*! - * Returns the total number of frames. - */ + * Returns the total number of frames. + */ unsigned int totalFrames() const; /*! - * Returns the total size of stream in bytes. - */ + * Returns the total size of stream in bytes. + */ unsigned int totalSize() const; /*! - * Returns the type of the VBR header. - */ + * Returns the type of the VBR header. + */ 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); - private: XingHeader(const XingHeader &); XingHeader &operator=(const XingHeader &); diff --git a/3rdparty/taglib/ogg/flac/oggflacfile.cpp b/3rdparty/taglib/ogg/flac/oggflacfile.cpp index ddc88ca70..5c7f98f22 100644 --- a/3rdparty/taglib/ogg/flac/oggflacfile.cpp +++ b/3rdparty/taglib/ogg/flac/oggflacfile.cpp @@ -37,8 +37,8 @@ using Strawberry_TagLib::TagLib::FLAC::Properties; class Ogg::FLAC::File::FilePrivate { public: - FilePrivate() : comment(0), - properties(0), + FilePrivate() : comment(nullptr), + properties(nullptr), streamStart(0), streamLength(0), scanned(false), @@ -78,18 +78,18 @@ bool Ogg::FLAC::File::isSupported(IOStream *stream) { // public members //////////////////////////////////////////////////////////////////////////////// -Ogg::FLAC::File::File(FileName file, bool readProperties, - Properties::ReadStyle propertiesStyle) : Ogg::File(file), - d(new FilePrivate()) { +Ogg::FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle) : Ogg::File(file), d(new FilePrivate()) { + if (isOpen()) read(readProperties, propertiesStyle); + } -Ogg::FLAC::File::File(IOStream *stream, bool readProperties, - Properties::ReadStyle propertiesStyle) : Ogg::File(stream), - d(new FilePrivate()) { +Ogg::FLAC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle propertiesStyle) : Ogg::File(stream), d(new FilePrivate()) { + if (isOpen()) read(readProperties, propertiesStyle); + } Ogg::FLAC::File::~File() { @@ -114,6 +114,7 @@ Properties *Ogg::FLAC::File::audioProperties() const { bool Ogg::FLAC::File::save() { + d->xiphCommentData = d->comment->render(false); // Create FLAC metadata-block: @@ -136,6 +137,7 @@ bool Ogg::FLAC::File::save() { setPacket(d->commentPacket, v); return Ogg::File::save(); + } bool Ogg::FLAC::File::hasXiphComment() const { @@ -147,6 +149,7 @@ bool Ogg::FLAC::File::hasXiphComment() const { //////////////////////////////////////////////////////////////////////////////// void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) { + // Sanity: Check if we really have an Ogg/FLAC file /* @@ -176,6 +179,7 @@ void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle properties if (readProperties) d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle); + } ByteVector Ogg::FLAC::File::streamInfoData() { @@ -194,6 +198,7 @@ long Ogg::FLAC::File::streamLength() { } void Ogg::FLAC::File::scan() { + // Scan the metadata pages if (d->scanned) @@ -298,4 +303,5 @@ void Ogg::FLAC::File::scan() { d->streamLength = File::length() - d->streamStart; d->scanned = true; + } diff --git a/3rdparty/taglib/ogg/flac/oggflacfile.h b/3rdparty/taglib/ogg/flac/oggflacfile.h index 71a3222d3..809d41458 100644 --- a/3rdparty/taglib/ogg/flac/oggflacfile.h +++ b/3rdparty/taglib/ogg/flac/oggflacfile.h @@ -55,100 +55,93 @@ using Strawberry_TagLib::TagLib::FLAC::Properties; //! An implementation of TagLib::File with Ogg/FLAC specific methods /*! - * This implements and provides an interface for Ogg/FLAC files to the - * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing - * the abstract TagLib::File API as well as providing some additional - * information specific to Ogg FLAC files. - */ + * This implements and provides an interface for Ogg/FLAC files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to Ogg FLAC files. + */ class TAGLIB_EXPORT File : public Ogg::File { public: /*! - * Constructs an Ogg/FLAC file from \a file. If \a readProperties is true - * the file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(FileName file, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs an Ogg/FLAC file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs an Ogg/FLAC file from \a stream. If \a readProperties is true - * the file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(IOStream *stream, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs an Ogg/FLAC file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the Tag for this file. This will always be a XiphComment. - * - * \note This always returns a valid pointer regardless of whether or not - * the file on disk has a XiphComment. Use hasXiphComment() to check if - * the file on disk actually has a XiphComment. - * - * \note The Tag is still owned by the FLAC::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasXiphComment() - */ + * Returns the Tag for this file. This will always be a XiphComment. + * + * \note This always returns a valid pointer regardless of whether or not the file on disk has a XiphComment. + * Use hasXiphComment() to check if the file on disk actually has a XiphComment. + * + * \note The Tag is still owned by the FLAC::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasXiphComment() + */ virtual XiphComment *tag() const; /*! - * Returns the FLAC::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the FLAC::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Implements the unified property interface -- export function. - * This forwards directly to XiphComment::properties(). - */ + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ PropertyMap properties() const; /*! - * Implements the unified tag dictionary interface -- import function. - * Like properties(), this is a forwarder to the file's XiphComment. - */ + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Save the file. This will primarily save and update the XiphComment. - * Returns true if the save is successful. - */ + * Save the file. This will primarily save and update the XiphComment. + * Returns true if the save is successful. + */ virtual bool save(); /*! - * Returns the length of the audio-stream, used by FLAC::Properties for - * calculating the bitrate. - */ + * Returns the length of the audio-stream, used by FLAC::Properties for calculating the bitrate. + */ long streamLength(); /*! - * Returns whether or not the file on disk actually has a XiphComment. - * - * \see tag() - */ + * Returns whether or not the file on disk actually has a XiphComment. + * + * \see tag() + */ bool hasXiphComment() const; /*! - * Check if the given \a stream can be opened as an Ogg FLAC file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Check if the given \a stream can be opened as an Ogg FLAC file. + * + * \note This method is designed to do a quick check. The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: @@ -163,6 +156,7 @@ class TAGLIB_EXPORT File : public Ogg::File { class FilePrivate; FilePrivate *d; }; + } // namespace FLAC } // namespace Ogg } // namespace TagLib diff --git a/3rdparty/taglib/ogg/oggfile.cpp b/3rdparty/taglib/ogg/oggfile.cpp index c380ea6d9..1a9c58052 100644 --- a/3rdparty/taglib/ogg/oggfile.cpp +++ b/3rdparty/taglib/ogg/oggfile.cpp @@ -37,18 +37,18 @@ using namespace Strawberry_TagLib::TagLib; namespace { // Returns the first packet index of the right next page to the given one. unsigned int nextPacketIndex(const Ogg::Page *page) { + if (page->header()->lastPacketCompleted()) return page->firstPacketIndex() + page->packetCount(); else return page->firstPacketIndex() + page->packetCount() - 1; + } } // namespace class Ogg::File::FilePrivate { public: - FilePrivate() : streamSerialNumber(0), - firstPageHeader(0), - lastPageHeader(0) { + FilePrivate() : streamSerialNumber(0), firstPageHeader(nullptr), lastPageHeader(nullptr) { pages.setAutoDelete(true); } @@ -58,7 +58,7 @@ class Ogg::File::FilePrivate { } unsigned int streamSerialNumber; - List pages; + List pages; PageHeader *firstPageHeader; PageHeader *lastPageHeader; Map dirtyPackets; @@ -73,6 +73,7 @@ Ogg::File::~File() { } ByteVector Ogg::File::packet(unsigned int i) { + // Check to see if we're called setPacket() for this packet since the last // save: @@ -108,42 +109,50 @@ ByteVector Ogg::File::packet(unsigned int i) { } return packet; + } void Ogg::File::setPacket(unsigned int i, const ByteVector &p) { + if (!readPages(i)) { debug("Ogg::File::setPacket() -- Could not set the requested packet."); return; } d->dirtyPackets[i] = p; + } const Ogg::PageHeader *Ogg::File::firstPageHeader() { + if (!d->firstPageHeader) { const long firstPageHeaderOffset = find("OggS"); if (firstPageHeaderOffset < 0) - return 0; + return nullptr; d->firstPageHeader = new PageHeader(this, firstPageHeaderOffset); } - return d->firstPageHeader->isValid() ? d->firstPageHeader : 0; + return d->firstPageHeader->isValid() ? d->firstPageHeader : nullptr; + } const Ogg::PageHeader *Ogg::File::lastPageHeader() { + if (!d->lastPageHeader) { const long lastPageHeaderOffset = rfind("OggS"); if (lastPageHeaderOffset < 0) - return 0; + return nullptr; d->lastPageHeader = new PageHeader(this, lastPageHeaderOffset); } - return d->lastPageHeader->isValid() ? d->lastPageHeader : 0; + return d->lastPageHeader->isValid() ? d->lastPageHeader : nullptr; + } bool Ogg::File::save() { + if (readOnly()) { debug("Ogg::File::save() - Cannot save to a read only file."); return false; @@ -156,25 +165,23 @@ bool Ogg::File::save() { d->dirtyPackets.clear(); return true; + } //////////////////////////////////////////////////////////////////////////////// // protected members //////////////////////////////////////////////////////////////////////////////// -Ogg::File::File(FileName file) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate()) { -} +Ogg::File::File(FileName file) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate()) {} -Ogg::File::File(IOStream *stream) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate()) { -} +Ogg::File::File(IOStream *stream) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate()) {} //////////////////////////////////////////////////////////////////////////////// // private members //////////////////////////////////////////////////////////////////////////////// bool Ogg::File::readPages(unsigned int i) { + while (true) { unsigned int packetIndex; long offset; @@ -210,9 +217,11 @@ bool Ogg::File::readPages(unsigned int i) { if (nextPage->header()->lastPageOfStream()) return false; } + } void Ogg::File::writePacket(unsigned int i, const ByteVector &packet) { + if (!readPages(i)) { debug("Ogg::File::writePacket() -- Could not find the requested packet."); return; @@ -292,4 +301,5 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet) { // Discard all the pages to keep them up-to-date by fetching them again. d->pages.clear(); + } diff --git a/3rdparty/taglib/ogg/oggfile.h b/3rdparty/taglib/ogg/oggfile.h index 0c916fb63..b0e20c51b 100644 --- a/3rdparty/taglib/ogg/oggfile.h +++ b/3rdparty/taglib/ogg/oggfile.h @@ -28,7 +28,7 @@ #include "tbytevectorlist.h" #ifndef TAGLIB_OGGFILE_H -# define TAGLIB_OGGFILE_H +#define TAGLIB_OGGFILE_H namespace Strawberry_TagLib { namespace TagLib { @@ -42,64 +42,54 @@ class PageHeader; //! An implementation of Strawberry_TagLib::TagLib::File with some helpers for Ogg based formats /*! - * This is an implementation of Ogg file page and packet rendering and is of - * use to Ogg based formats. While the API is small this handles the - * non-trivial details of breaking up an Ogg stream into packets and makes - * these available (via subclassing) to the codec meta data implementations. - */ + * This is an implementation of Ogg file page and packet rendering and is of use to Ogg based formats. + * While the API is small this handles the non-trivial details of breaking up an Ogg stream into packets and makes + * these available (via subclassing) to the codec meta data implementations. + */ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { public: virtual ~File(); /*! - * Returns the packet contents for the i-th packet (starting from zero) - * in the Ogg bitstream. - * - * \warning This requires reading at least the packet header for every page - * up to the requested page. - */ + * Returns the packet contents for the i-th packet (starting from zero) in the Ogg bitstream. + * + * \warning This requires reading at least the packet header for every page up to the requested page. + */ ByteVector packet(unsigned int i); /*! - * Sets the packet with index \a i to the value \a p. - */ + * Sets the packet with index \a i to the value \a p. + */ void setPacket(unsigned int i, const ByteVector &p); /*! - * Returns a pointer to the PageHeader for the first page in the stream or - * null if the page could not be found. - */ + * Returns a pointer to the PageHeader for the first page in the stream or null if the page could not be found. + */ const PageHeader *firstPageHeader(); /*! - * Returns a pointer to the PageHeader for the last page in the stream or - * null if the page could not be found. - */ + * Returns a pointer to the PageHeader for the last page in the stream or null if the page could not be found. + */ const PageHeader *lastPageHeader(); virtual bool save(); protected: /*! - * Constructs an Ogg file from \a file. - * - * \note This constructor is protected since Ogg::File shouldn't be - * instantiated directly but rather should be used through the codec - * specific subclasses. - */ + * Constructs an Ogg file from \a file. + * + * \note This constructor is protected since Ogg::File shouldn't be instantiated directly but rather should be used through the codec specific subclasses. + */ File(FileName file); /*! - * Constructs an Ogg file from \a stream. - * - * \note This constructor is protected since Ogg::File shouldn't be - * instantiated directly but rather should be used through the codec - * specific subclasses. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - */ + * Constructs an Ogg file from \a stream. + * + * \note This constructor is protected since Ogg::File shouldn't be instantiated directly but rather should be used through the codec specific subclasses. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + */ File(IOStream *stream); private: @@ -107,14 +97,14 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { File &operator=(const File &); /*! - * Reads the pages from the beginning of the file until enough to compose - * the requested packet. - */ + * Reads the pages from the beginning of the file until enough to compose + * the requested packet. + */ bool readPages(unsigned int i); /*! - * Writes the requested packet to the file. - */ + * Writes the requested packet to the file. + */ void writePacket(unsigned int i, const ByteVector &packet); class FilePrivate; diff --git a/3rdparty/taglib/ogg/oggpage.cpp b/3rdparty/taglib/ogg/oggpage.cpp index 9f40a1f6e..ed5279a14 100644 --- a/3rdparty/taglib/ogg/oggpage.cpp +++ b/3rdparty/taglib/ogg/oggpage.cpp @@ -36,10 +36,7 @@ using namespace Strawberry_TagLib::TagLib; class Ogg::Page::PagePrivate { public: - PagePrivate(File *f = 0, long pageOffset = -1) : file(f), - fileOffset(pageOffset), - header(f, pageOffset), - firstPacketIndex(-1) {} + PagePrivate(File *f = nullptr, long pageOffset = -1) : file(f), fileOffset(pageOffset), header(f, pageOffset), firstPacketIndex(-1) {} File *file; long fileOffset; @@ -52,8 +49,7 @@ class Ogg::Page::PagePrivate { // public members //////////////////////////////////////////////////////////////////////////////// -Ogg::Page::Page(Ogg::File *file, long pageOffset) : d(new PagePrivate(file, pageOffset)) { -} +Ogg::Page::Page(Ogg::File *file, long pageOffset) : d(new PagePrivate(file, pageOffset)) {} Ogg::Page::~Page() { delete d; @@ -84,6 +80,7 @@ void Ogg::Page::setFirstPacketIndex(int index) { } Ogg::Page::ContainsPacketFlags Ogg::Page::containsPacket(int index) const { + const int lastPacketIndex = d->firstPacketIndex + packetCount() - 1; if (index < d->firstPacketIndex || index > lastPacketIndex) return DoesNotContainPacket; @@ -116,6 +113,7 @@ Ogg::Page::ContainsPacketFlags Ogg::Page::containsPacket(int index) const { } return flags; + } unsigned int Ogg::Page::packetCount() const { @@ -123,6 +121,7 @@ unsigned int Ogg::Page::packetCount() const { } ByteVectorList Ogg::Page::packets() const { + if (!d->packets.isEmpty()) return d->packets; @@ -142,6 +141,7 @@ ByteVectorList Ogg::Page::packets() const { debug("Ogg::Page::packets() -- attempting to read packets from an invalid page."); return l; + } int Ogg::Page::size() const { @@ -149,6 +149,7 @@ int Ogg::Page::size() const { } ByteVector Ogg::Page::render() const { + ByteVector data; data.append(d->header.render()); @@ -175,15 +176,11 @@ ByteVector Ogg::Page::render() const { std::copy(checksum.begin(), checksum.end(), data.begin() + 22); return data; + } -List Ogg::Page::paginate(const ByteVectorList &packets, - PaginationStrategy strategy, - unsigned int streamSerialNumber, - int firstPage, - bool firstPacketContinued, - bool lastPacketCompleted, - bool containsLastPacket) { +List Ogg::Page::paginate(const ByteVectorList &packets, PaginationStrategy strategy, unsigned int streamSerialNumber, int firstPage, bool firstPacketContinued, bool lastPacketCompleted, bool containsLastPacket) { + // SplitSize must be a multiple of 255 in order to get the lacing values right // create pages of about 8KB each @@ -248,23 +245,15 @@ List Ogg::Page::paginate(const ByteVectorList &packets, } return l; -} -Ogg::Page *Ogg::Page::getCopyWithNewPageSequenceNumber(int /*sequenceNumber*/) { - debug("Ogg::Page::getCopyWithNewPageSequenceNumber() -- This function is obsolete. Returning null."); - return nullptr; } //////////////////////////////////////////////////////////////////////////////// // protected members //////////////////////////////////////////////////////////////////////////////// -Ogg::Page::Page(const ByteVectorList &packets, - unsigned int streamSerialNumber, - int pageNumber, - bool firstPacketContinued, - bool lastPacketCompleted, - bool containsLastPacket) : d(new PagePrivate()) { +Ogg::Page::Page(const ByteVectorList &packets, unsigned int streamSerialNumber, int pageNumber, bool firstPacketContinued, bool lastPacketCompleted, bool containsLastPacket) : d(new PagePrivate()) { + d->header.setFirstPageOfStream(pageNumber == 0 && !firstPacketContinued); d->header.setLastPageOfStream(containsLastPacket); d->header.setFirstPacketContinued(firstPacketContinued); @@ -283,4 +272,5 @@ Ogg::Page::Page(const ByteVectorList &packets, } d->packets = packets; d->header.setPacketSizes(packetSizes); + } diff --git a/3rdparty/taglib/ogg/oggpage.h b/3rdparty/taglib/ogg/oggpage.h index 68a7bf6ba..22cd2170d 100644 --- a/3rdparty/taglib/ogg/oggpage.h +++ b/3rdparty/taglib/ogg/oggpage.h @@ -40,82 +40,67 @@ class PageHeader; //! An implementation of Ogg pages /*! - * This is an implementation of the pages that make up an Ogg stream. - * This handles parsing pages and breaking them down into packets and handles - * the details of packets spanning multiple pages and pages that contain - * multiple packets. - * - * In most Xiph.org formats the comments are found in the first few packets, - * this however is a reasonably complete implementation of Ogg pages that - * could potentially be useful for non-meta data purposes. - */ + * This is an implementation of the pages that make up an Ogg stream. + * This handles parsing pages and breaking them down into packets and handles + * the details of packets spanning multiple pages and pages that contain multiple packets. + * + * In most Xiph.org formats the comments are found in the first few packets, + * this however is a reasonably complete implementation of Ogg pages that + * could potentially be useful for non-meta data purposes. + */ class TAGLIB_EXPORT Page { public: /*! - * Read an Ogg page from the \a file at the position \a pageOffset. - */ + * Read an Ogg page from the \a file at the position \a pageOffset. + */ Page(File *file, long pageOffset); virtual ~Page(); /*! - * Returns the page's position within the file (in bytes). - */ + * Returns the page's position within the file (in bytes). + */ long fileOffset() const; /*! - * Returns a pointer to the header for this page. This pointer will become - * invalid when the page is deleted. - */ + * Returns a pointer to the header for this page. This pointer will become invalid when the page is deleted. + */ const PageHeader *header() const; /*! - * Returns the index of the page within the Ogg stream. This helps make it - * possible to determine if pages have been lost. - * - * \see setPageSequenceNumber() - */ + * Returns the index of the page within the Ogg stream. This helps make it possible to determine if pages have been lost. + * + * \see setPageSequenceNumber() + */ int pageSequenceNumber() const; /*! - * Sets the page's position in the stream to \a sequenceNumber. - * - * \see pageSequenceNumber() - */ + * Sets the page's position in the stream to \a sequenceNumber. + * + * \see pageSequenceNumber() + */ void setPageSequenceNumber(int sequenceNumber); /*! - * Returns a copy of the page with \a sequenceNumber set as sequence number. - * - * \see header() - * \see PageHeader::setPageSequenceNumber() - * - * \deprecated Always returns null. - */ - TAGLIB_DEPRECATED Page *getCopyWithNewPageSequenceNumber(int sequenceNumber); - - /*! - * Returns the index of the first packet wholly or partially contained in - * this page. - * - * \see setFirstPacketIndex() - */ + * Returns the index of the first packet wholly or partially contained in this page. + * + * \see setFirstPacketIndex() + */ int firstPacketIndex() const; /*! - * Sets the index of the first packet in the page. - * - * \see firstPacketIndex() - */ + * Sets the index of the first packet in the page. + * + * \see firstPacketIndex() + */ void setFirstPacketIndex(int index); /*! - * When checking to see if a page contains a given packet this set of flags - * represents the possible values for that packets status in the page. - * - * \see containsPacket() - */ + * When checking to see if a page contains a given packet this set of flags represents the possible values for that packets status in the page. + * + * \see containsPacket() + */ enum ContainsPacketFlags { //! No part of the packet is contained in the page DoesNotContainPacket = 0x0000, @@ -128,74 +113,66 @@ class TAGLIB_EXPORT Page { }; /*! - * Checks to see if the specified \a packet is contained in the current - * page. - * - * \see ContainsPacketFlags - */ + * Checks to see if the specified \a packet is contained in the current page. + * + * \see ContainsPacketFlags + */ ContainsPacketFlags containsPacket(int index) const; /*! - * Returns the number of packets (whole or partial) in this page. - */ + * Returns the number of packets (whole or partial) in this page. + */ unsigned int packetCount() const; /*! - * Returns a list of the packets in this page. - * - * \note Either or both the first and last packets may be only partial. - * \see PageHeader::firstPacketContinued() - */ + * Returns a list of the packets in this page. + * + * \note Either or both the first and last packets may be only partial. + * \see PageHeader::firstPacketContinued() + */ ByteVectorList packets() const; /*! - * Returns the size of the page in bytes. - */ + * Returns the size of the page in bytes. + */ int size() const; ByteVector render() const; /*! - * Defines a strategy for pagination, or grouping pages into Ogg packets, - * for use with pagination methods. - * - * \note Yes, I'm aware that this is not a canonical "Strategy Pattern", - * the term was simply convenient. - */ + * Defines a strategy for pagination, or grouping pages into Ogg packets, for use with pagination methods. + * + * \note Yes, I'm aware that this is not a canonical "Strategy Pattern", the term was simply convenient. + */ enum PaginationStrategy { /*! - * Attempt to put the specified set of packets into a single Ogg packet. - * If the sum of the packet data is greater than will fit into a single - * Ogg page -- 65280 bytes -- this will fall back to repagination using - * the recommended page sizes. - */ + * Attempt to put the specified set of packets into a single Ogg packet. + * If the sum of the packet data is greater than will fit into a single + * Ogg page -- 65280 bytes -- this will fall back to repagination using + * the recommended page sizes. + */ SinglePagePerGroup, /*! - * Split the packet or group of packets into pages that conform to the - * sizes recommended in the Ogg standard. - */ + * Split the packet or group of packets into pages that conform to the sizes recommended in the Ogg standard. + */ Repaginate }; /*! - * Pack \a packets into Ogg pages using the \a strategy for pagination. - * The page number indicator inside of the rendered packets will start - * with \a firstPage and be incremented for each page rendered. - * \a containsLastPacket should be set to true if \a packets contains the - * last page in the stream and will set the appropriate flag in the last - * rendered Ogg page's header. \a streamSerialNumber should be set to - * the serial number for this stream. - * - * \note The "absolute granule position" is currently always zeroed using - * this method as this suffices for the comment headers. - * - * \warning The pages returned by this method must be deleted by the user. - * You can use List::setAutoDelete(true) to set these pages to be - * automatically deleted when this list passes out of scope. - * - * \see PaginationStrategy - * \see List::setAutoDelete() - */ + * Pack \a packets into Ogg pages using the \a strategy for pagination. + * The page number indicator inside of the rendered packets will start with \a firstPage and be incremented for each page rendered. + * \a containsLastPacket should be set to true if \a packets contains the + * last page in the stream and will set the appropriate flag in the last rendered Ogg page's header. + * \a streamSerialNumber should be set to the serial number for this stream. + * + * \note The "absolute granule position" is currently always zeroed using this method as this suffices for the comment headers. + * + * \warning The pages returned by this method must be deleted by the user. + * You can use List::setAutoDelete(true) to set these pages to be automatically deleted when this list passes out of scope. + * + * \see PaginationStrategy + * \see List::setAutoDelete() + */ static List paginate(const ByteVectorList &packets, PaginationStrategy strategy, unsigned int streamSerialNumber, @@ -206,9 +183,8 @@ class TAGLIB_EXPORT Page { protected: /*! - * Creates an Ogg packet based on the data in \a packets. The page number - * for each page will be set to \a pageNumber. - */ + * Creates an Ogg packet based on the data in \a packets. The page number for each page will be set to \a pageNumber. + */ Page(const ByteVectorList &packets, unsigned int streamSerialNumber, int pageNumber, @@ -223,7 +199,9 @@ class TAGLIB_EXPORT Page { class PagePrivate; PagePrivate *d; }; + } // namespace Ogg } // namespace TagLib } // namespace Strawberry_TagLib + #endif diff --git a/3rdparty/taglib/ogg/oggpageheader.cpp b/3rdparty/taglib/ogg/oggpageheader.cpp index d972bafc7..464993efb 100644 --- a/3rdparty/taglib/ogg/oggpageheader.cpp +++ b/3rdparty/taglib/ogg/oggpageheader.cpp @@ -65,8 +65,10 @@ class Ogg::PageHeader::PageHeaderPrivate { //////////////////////////////////////////////////////////////////////////////// Ogg::PageHeader::PageHeader(Ogg::File *file, long pageOffset) : d(new PageHeaderPrivate()) { + if (file && pageOffset >= 0) read(file, pageOffset); + } Ogg::PageHeader::~PageHeader() { @@ -150,6 +152,7 @@ int Ogg::PageHeader::dataSize() const { } ByteVector Ogg::PageHeader::render() const { + ByteVector data; // capture pattern @@ -194,6 +197,7 @@ ByteVector Ogg::PageHeader::render() const { data.append(pageSegments); return data; + } //////////////////////////////////////////////////////////////////////////////// @@ -201,6 +205,7 @@ ByteVector Ogg::PageHeader::render() const { //////////////////////////////////////////////////////////////////////////////// void Ogg::PageHeader::read(Ogg::File *file, long pageOffset) { + file->seek(pageOffset); // An Ogg page header is at least 27 bytes, so we'll go ahead and read that @@ -263,9 +268,11 @@ void Ogg::PageHeader::read(Ogg::File *file, long pageOffset) { d->lastPacketCompleted = true; d->isValid = true; + } ByteVector Ogg::PageHeader::lacingValues() const { + ByteVector data; for (List::ConstIterator it = d->packetSizes.begin(); it != d->packetSizes.end(); ++it) { @@ -282,4 +289,5 @@ ByteVector Ogg::PageHeader::lacingValues() const { } return data; + } diff --git a/3rdparty/taglib/ogg/oggpageheader.h b/3rdparty/taglib/ogg/oggpageheader.h index 09145ccb0..a3f3d2698 100644 --- a/3rdparty/taglib/ogg/oggpageheader.h +++ b/3rdparty/taglib/ogg/oggpageheader.h @@ -32,7 +32,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace Ogg { class File; @@ -40,179 +39,164 @@ class File; //! An implementation of the page headers associated with each Ogg::Page /*! - * This class implements Ogg page headers which contain the information - * about Ogg pages needed to break them into packets which can be passed on - * to the codecs. - */ + * This class implements Ogg page headers which contain the information about Ogg pages needed to break them into packets which can be passed on to the codecs. + */ class TAGLIB_EXPORT PageHeader { public: /*! - * Reads a PageHeader from \a file starting at \a pageOffset. The defaults - * create a page with no (and as such, invalid) data that must be set - * later. - */ + * Reads a PageHeader from \a file starting at \a pageOffset. + * The defaults create a page with no (and as such, invalid) data that must be set later. + */ PageHeader(File *file = 0, long pageOffset = -1); /*! - * Deletes this instance of the PageHeader. - */ + * Deletes this instance of the PageHeader. + */ virtual ~PageHeader(); /*! - * Returns true if the header parsed properly and is valid. - */ + * Returns true if the header parsed properly and is valid. + */ bool isValid() const; /*! - * Ogg pages contain a list of packets (which are used by the contained - * codecs). The sizes of these pages is encoded in the page header. This - * returns a list of the packet sizes in bytes. - * - * \see setPacketSizes() - */ + * Ogg pages contain a list of packets (which are used by the contained codecs). + * The sizes of these pages is encoded in the page header. This returns a list of the packet sizes in bytes. + * + * \see setPacketSizes() + */ List packetSizes() const; /*! - * Sets the sizes of the packets in this page to \a sizes. Internally this - * updates the lacing values in the header. - * - * \see packetSizes() - */ + * Sets the sizes of the packets in this page to \a sizes. Internally this updates the lacing values in the header. + * + * \see packetSizes() + */ void setPacketSizes(const List &sizes); /*! - * Some packets can be continued across multiple pages. If the - * first packet in the current page is a continuation this will return - * true. If this is page starts with a new packet this will return false. - * - * \see lastPacketCompleted() - * \see setFirstPacketContinued() - */ + * Some packets can be continued across multiple pages. + * If the first packet in the current page is a continuation this will return true. + * If this is page starts with a new packet this will return false. + * + * \see lastPacketCompleted() + * \see setFirstPacketContinued() + */ bool firstPacketContinued() const; /*! - * Sets the internal flag indicating if the first packet in this page is - * continued to \a continued. - * - * \see firstPacketContinued() - */ + * Sets the internal flag indicating if the first packet in this page is continued to \a continued. + * + * \see firstPacketContinued() + */ void setFirstPacketContinued(bool continued); /*! - * Returns true if the last packet of this page is completely contained in - * this page. - * - * \see firstPacketContinued() - * \see setLastPacketCompleted() - */ + * Returns true if the last packet of this page is completely contained in this page. + * + * \see firstPacketContinued() + * \see setLastPacketCompleted() + */ bool lastPacketCompleted() const; /*! - * Sets the internal flag indicating if the last packet in this page is - * complete to \a completed. - * - * \see lastPacketCompleted() - */ + * Sets the internal flag indicating if the last packet in this page is complete to \a completed. + * + * \see lastPacketCompleted() + */ void setLastPacketCompleted(bool completed); /*! - * This returns true if this is the first page of the Ogg (logical) stream. - * - * \see setFirstPageOfStream() - */ + * This returns true if this is the first page of the Ogg (logical) stream. + * + * \see setFirstPageOfStream() + */ bool firstPageOfStream() const; /*! - * Marks this page as the first page of the Ogg stream. - * - * \see firstPageOfStream() - */ + * Marks this page as the first page of the Ogg stream. + * + * \see firstPageOfStream() + */ void setFirstPageOfStream(bool first); /*! - * This returns true if this is the last page of the Ogg (logical) stream. - * - * \see setLastPageOfStream() - */ + * This returns true if this is the last page of the Ogg (logical) stream. + * + * \see setLastPageOfStream() + */ bool lastPageOfStream() const; /*! - * Marks this page as the last page of the Ogg stream. - * - * \see lastPageOfStream() - */ + * Marks this page as the last page of the Ogg stream. + * + * \see lastPageOfStream() + */ void setLastPageOfStream(bool last); /*! - * A special value of containing the position of the packet to be - * interpreted by the codec. In the case of Vorbis this contains the PCM - * value and is used to calculate the length of the stream. - * - * \see setAbsoluteGranularPosition() - */ + * A special value of containing the position of the packet to be interpreted by the codec. + * In the case of Vorbis this contains the PCM value and is used to calculate the length of the stream. + * + * \see setAbsoluteGranularPosition() + */ long long absoluteGranularPosition() const; /*! - * A special value of containing the position of the packet to be - * interpreted by the codec. It is only supported here so that it may be - * copied from one page to another. - * - * \see absoluteGranularPosition() - */ + * A special value of containing the position of the packet to be interpreted by the codec. + * It is only supported here so that it may be copied from one page to another. + * + * \see absoluteGranularPosition() + */ void setAbsoluteGranularPosition(long long agp); /*! - * Every Ogg logical stream is given a random serial number which is common - * to every page in that logical stream. This returns the serial number of - * the stream associated with this packet. - * - * \see setStreamSerialNumber() - */ + * Every Ogg logical stream is given a random serial number which is common to every page in that logical stream. + * This returns the serial number of the stream associated with this packet. + * + * \see setStreamSerialNumber() + */ unsigned int streamSerialNumber() const; /*! - * Every Ogg logical stream is given a random serial number which is common - * to every page in that logical stream. This sets this pages serial - * number. This method should be used when adding new pages to a logical - * stream. - * - * \see streamSerialNumber() - */ + * Every Ogg logical stream is given a random serial number which is common to every page in that logical stream. + * This sets this pages serial number. + * This method should be used when adding new pages to a logical stream. + * + * \see streamSerialNumber() + */ void setStreamSerialNumber(unsigned int n); /*! - * Returns the index of the page within the Ogg stream. This helps make it - * possible to determine if pages have been lost. - * - * \see setPageSequenceNumber() - */ + * Returns the index of the page within the Ogg stream. This helps make it possible to determine if pages have been lost. + * + * \see setPageSequenceNumber() + */ int pageSequenceNumber() const; /*! - * Sets the page's position in the stream to \a sequenceNumber. - * - * \see pageSequenceNumber() - */ + * Sets the page's position in the stream to \a sequenceNumber. + * + * \see pageSequenceNumber() + */ void setPageSequenceNumber(int sequenceNumber); /*! - * Returns the complete header size. - */ + * Returns the complete header size. + */ int size() const; /*! - * Returns the size of the data portion of the page -- i.e. the size of the - * page less the header size. - */ + * Returns the size of the data portion of the page -- i.e. the size of the page less the header size. + */ int dataSize() const; /*! - * Render the page header to binary data. - * - * \note The checksum -- bytes 22 - 25 -- will be left empty and must be - * filled in when rendering the entire page. - */ + * Render the page header to binary data. + * + * \note The checksum -- bytes 22 - 25 -- will be left empty and must be filled in when rendering the entire page. + */ ByteVector render() const; private: diff --git a/3rdparty/taglib/ogg/opus/opusfile.cpp b/3rdparty/taglib/ogg/opus/opusfile.cpp index 31a4b33b6..0a8ba0bf0 100644 --- a/3rdparty/taglib/ogg/opus/opusfile.cpp +++ b/3rdparty/taglib/ogg/opus/opusfile.cpp @@ -39,8 +39,7 @@ using namespace Strawberry_TagLib::TagLib::Ogg; class Opus::File::FilePrivate { public: - FilePrivate() : comment(0), - properties(0) {} + FilePrivate() : comment(nullptr), properties(nullptr) {} ~FilePrivate() { delete comment; @@ -56,26 +55,30 @@ class Opus::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool Ogg::Opus::File::isSupported(IOStream *stream) { + // An Opus file has IDs "OggS" and "OpusHead" somewhere. const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false); return (buffer.find("OggS") >= 0 && buffer.find("OpusHead") >= 0); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -Opus::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Ogg::File(file), - d(new FilePrivate()) { +Opus::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Ogg::File(file), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } -Opus::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Ogg::File(stream), - d(new FilePrivate()) { +Opus::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Ogg::File(stream), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } Opus::File::~File() { @@ -99,12 +102,14 @@ Opus::Properties *Opus::File::audioProperties() const { } bool Opus::File::save() { + if (!d->comment) d->comment = new Ogg::XiphComment(); setPacket(1, ByteVector("OpusTags", 8) + d->comment->render(false)); return Ogg::File::save(); + } //////////////////////////////////////////////////////////////////////////////// @@ -112,6 +117,7 @@ bool Opus::File::save() { //////////////////////////////////////////////////////////////////////////////// void Opus::File::read(bool readProperties) { + ByteVector opusHeaderData = packet(0); if (!opusHeaderData.startsWith("OpusHead")) { @@ -132,4 +138,5 @@ void Opus::File::read(bool readProperties) { if (readProperties) d->properties = new Properties(this); + } diff --git a/3rdparty/taglib/ogg/opus/opusfile.h b/3rdparty/taglib/ogg/opus/opusfile.h index d9e6fc126..0e36b75de 100644 --- a/3rdparty/taglib/ogg/opus/opusfile.h +++ b/3rdparty/taglib/ogg/opus/opusfile.h @@ -37,7 +37,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace Ogg { //! A namespace containing classes for Opus metadata @@ -47,79 +46,74 @@ namespace Opus { //! An implementation of Ogg::File with Opus specific methods /*! - * This is the central class in the Ogg Opus metadata processing collection - * of classes. It's built upon Ogg::File which handles processing of the Ogg - * logical bitstream and breaking it down into pages which are handled by - * the codec implementations, in this case Opus specifically. - */ + * This is the central class in the Ogg Opus metadata processing collection of classes. + * It's built upon Ogg::File which handles processing of the Ogg logical bitstream and + * breaking it down into pages which are handled by the codec implementations, + * in this case Opus specifically. + * + */ class TAGLIB_EXPORT File : public Ogg::File { public: /*! - * Constructs an Opus file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(FileName file, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs an Opus file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs an Opus file from \a stream. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(IOStream *stream, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs an Opus file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the XiphComment for this file. XiphComment implements the tag - * interface, so this serves as the reimplementation of - * TagLib::File::tag(). - */ + * Returns the XiphComment for this file. + * XiphComment implements the tag interface, so this serves as the reimplementation of TagLib::File::tag(). + */ virtual Ogg::XiphComment *tag() const; /*! - * Implements the unified property interface -- export function. - * This forwards directly to XiphComment::properties(). - */ + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ PropertyMap properties() const; /*! - * Implements the unified tag dictionary interface -- import function. - * Like properties(), this is a forwarder to the file's XiphComment. - */ + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the Opus::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the Opus::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Save the file. - * - * This returns true if the save was successful. - */ + * Save the file. + * + * This returns true if the save was successful. + */ virtual bool save(); /*! - * Returns whether or not the given \a stream can be opened as an Opus - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as an Opus file. + * + * \note This method is designed to do a quick check. The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: @@ -131,6 +125,7 @@ class TAGLIB_EXPORT File : public Ogg::File { class FilePrivate; FilePrivate *d; }; + } // namespace Opus } // namespace Ogg } // namespace TagLib diff --git a/3rdparty/taglib/ogg/opus/opusproperties.cpp b/3rdparty/taglib/ogg/opus/opusproperties.cpp index 7bb69b21f..50baff7b4 100644 --- a/3rdparty/taglib/ogg/opus/opusproperties.cpp +++ b/3rdparty/taglib/ogg/opus/opusproperties.cpp @@ -57,8 +57,7 @@ class Opus::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -Opus::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +Opus::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { read(file); } @@ -66,10 +65,6 @@ Opus::Properties::~Properties() { delete d; } -int Opus::Properties::length() const { - return lengthInSeconds(); -} - int Ogg::Opus::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -83,10 +78,12 @@ int Opus::Properties::bitrate() const { } int Opus::Properties::sampleRate() const { + // Opus can decode any stream at a sample rate of 8, 12, 16, 24, or 48 kHz, // so there is no single sample rate. Let's assume it's the highest // possible. return 48000; + } int Opus::Properties::channels() const { @@ -106,6 +103,7 @@ int Opus::Properties::opusVersion() const { //////////////////////////////////////////////////////////////////////////////// void Opus::Properties::read(File *file) { + // Get the identification header from the Ogg implementation. // http://tools.ietf.org/html/draft-terriberry-oggopus-01#section-5.1 @@ -166,4 +164,5 @@ void Opus::Properties::read(File *file) { } else debug("Opus::Properties::read() -- Could not find valid first and last Ogg pages."); + } diff --git a/3rdparty/taglib/ogg/opus/opusproperties.h b/3rdparty/taglib/ogg/opus/opusproperties.h index d387c1a2b..ba93fb8a8 100644 --- a/3rdparty/taglib/ogg/opus/opusproperties.h +++ b/3rdparty/taglib/ogg/opus/opusproperties.h @@ -44,78 +44,64 @@ class File; //! An implementation of audio property reading for Ogg Opus /*! - * This reads the data from an Ogg Opus stream found in the AudioProperties - * API. - */ + * This reads the data from an Ogg Opus stream found in the AudioProperties API. + */ class TAGLIB_EXPORT Properties : public AudioProperties { public: /*! - * Create an instance of Opus::Properties with the data read from the - * Opus::File \a file. - */ + * Create an instance of Opus::Properties with the data read from the + * Opus::File \a file. + */ Properties(File *file, ReadStyle style = Average); /*! - * Destroys this Opus::Properties instance. - */ + * Destroys this Opus::Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - TAGLIB_DEPRECATED virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - * - * \note Always returns 48000, because Opus can decode any stream at a - * sample rate of 8, 12, 16, 24, or 48 kHz, - */ + * Returns the sample rate in Hz. + * + * \note Always returns 48000, because Opus can decode any stream at a sample rate of 8, 12, 16, 24, or 48 kHz, + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * The Opus codec supports decoding at multiple sample rates, there is no - * single sample rate of the encoded stream. This returns the sample rate - * of the original audio stream. - */ + * The Opus codec supports decoding at multiple sample rates, there is no single sample rate of the encoded stream. + * This returns the sample rate of the original audio stream. + */ int inputSampleRate() const; /*! - * Returns the Opus version, in the range 0...255. - */ + * Returns the Opus version, in the range 0...255. + */ int opusVersion() const; private: @@ -127,6 +113,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties { class PropertiesPrivate; PropertiesPrivate *d; }; + } // namespace Opus } // namespace Ogg } // namespace TagLib diff --git a/3rdparty/taglib/ogg/speex/speexfile.cpp b/3rdparty/taglib/ogg/speex/speexfile.cpp index 1c823cde1..2fa50ac5e 100644 --- a/3rdparty/taglib/ogg/speex/speexfile.cpp +++ b/3rdparty/taglib/ogg/speex/speexfile.cpp @@ -39,8 +39,7 @@ using namespace Strawberry_TagLib::TagLib::Ogg; class Speex::File::FilePrivate { public: - FilePrivate() : comment(0), - properties(0) {} + FilePrivate() : comment(nullptr), properties(nullptr) {} ~FilePrivate() { delete comment; @@ -56,24 +55,24 @@ class Speex::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool Ogg::Speex::File::isSupported(IOStream *stream) { + // A Speex file has IDs "OggS" and "Speex " somewhere. const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false); return (buffer.find("OggS") >= 0 && buffer.find("Speex ") >= 0); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -Speex::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Ogg::File(file), - d(new FilePrivate()) { +Speex::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Ogg::File(file), d(new FilePrivate()) { if (isOpen()) read(readProperties); } -Speex::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Ogg::File(stream), - d(new FilePrivate()) { +Speex::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Ogg::File(stream), d(new FilePrivate()) { if (isOpen()) read(readProperties); } @@ -99,12 +98,14 @@ Speex::Properties *Speex::File::audioProperties() const { } bool Speex::File::save() { + if (!d->comment) d->comment = new Ogg::XiphComment(); setPacket(1, d->comment->render()); return Ogg::File::save(); + } //////////////////////////////////////////////////////////////////////////////// @@ -112,6 +113,7 @@ bool Speex::File::save() { //////////////////////////////////////////////////////////////////////////////// void Speex::File::read(bool readProperties) { + ByteVector speexHeaderData = packet(0); if (!speexHeaderData.startsWith("Speex ")) { @@ -126,4 +128,5 @@ void Speex::File::read(bool readProperties) { if (readProperties) d->properties = new Properties(this); + } diff --git a/3rdparty/taglib/ogg/speex/speexfile.h b/3rdparty/taglib/ogg/speex/speexfile.h index 7ddd528db..d63d52422 100644 --- a/3rdparty/taglib/ogg/speex/speexfile.h +++ b/3rdparty/taglib/ogg/speex/speexfile.h @@ -47,79 +47,73 @@ namespace Speex { //! An implementation of Ogg::File with Speex specific methods /*! - * This is the central class in the Ogg Speex metadata processing collection - * of classes. It's built upon Ogg::File which handles processing of the Ogg - * logical bitstream and breaking it down into pages which are handled by - * the codec implementations, in this case Speex specifically. - */ + * This is the central class in the Ogg Speex metadata processing collection of classes. + * It's built upon Ogg::File which handles processing of the Ogg logical bitstream + * and breaking it down into pages which are handled by the codec implementations, + * in this case Speex specifically. + * + */ class TAGLIB_EXPORT File : public Ogg::File { public: /*! - * Constructs a Speex file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(FileName file, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs a Speex file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs a Speex file from \a stream. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(IOStream *stream, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs a Speex file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the XiphComment for this file. XiphComment implements the tag - * interface, so this serves as the reimplementation of - * TagLib::File::tag(). - */ + * Returns the XiphComment for this file. XiphComment implements the tag interface, so this serves as the reimplementation of TagLib::File::tag(). + */ virtual Ogg::XiphComment *tag() const; /*! - * Implements the unified property interface -- export function. - * This forwards directly to XiphComment::properties(). - */ + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ PropertyMap properties() const; /*! - * Implements the unified tag dictionary interface -- import function. - * Like properties(), this is a forwarder to the file's XiphComment. - */ + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the Speex::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the Speex::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Save the file. - * - * This returns true if the save was successful. - */ + * Save the file. + * + * This returns true if the save was successful. + */ virtual bool save(); /*! - * Returns whether or not the given \a stream can be opened as a Speex - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as a Speex file. + * + * \note This method is designed to do a quick check. The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: @@ -131,6 +125,7 @@ class TAGLIB_EXPORT File : public Ogg::File { class FilePrivate; FilePrivate *d; }; + } // namespace Speex } // namespace Ogg } // namespace TagLib diff --git a/3rdparty/taglib/ogg/speex/speexproperties.cpp b/3rdparty/taglib/ogg/speex/speexproperties.cpp index 864a1cfba..93be4e6c4 100644 --- a/3rdparty/taglib/ogg/speex/speexproperties.cpp +++ b/3rdparty/taglib/ogg/speex/speexproperties.cpp @@ -63,8 +63,7 @@ class Speex::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -Speex::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +Speex::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { read(file); } @@ -72,10 +71,6 @@ Speex::Properties::~Properties() { delete d; } -int Speex::Properties::length() const { - return lengthInSeconds(); -} - int Speex::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -109,6 +104,7 @@ int Speex::Properties::speexVersion() const { //////////////////////////////////////////////////////////////////////////////// void Speex::Properties::read(File *file) { + // Get the identification header from the Ogg implementation. const ByteVector data = file->packet(0); @@ -190,4 +186,5 @@ void Speex::Properties::read(File *file) { if (d->bitrate == 0 && d->bitrateNominal > 0) d->bitrate = static_cast(d->bitrateNominal / 1000.0 + 0.5); + } diff --git a/3rdparty/taglib/ogg/speex/speexproperties.h b/3rdparty/taglib/ogg/speex/speexproperties.h index 395f81737..9b65f7ce1 100644 --- a/3rdparty/taglib/ogg/speex/speexproperties.h +++ b/3rdparty/taglib/ogg/speex/speexproperties.h @@ -34,83 +34,65 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace Ogg { - namespace Speex { class File; //! An implementation of audio property reading for Ogg Speex - -/*! - * This reads the data from an Ogg Speex stream found in the AudioProperties - * API. - */ +//! This reads the data from an Ogg Speex stream found in the AudioProperties API. class TAGLIB_EXPORT Properties : public AudioProperties { public: /*! - * Create an instance of Speex::Properties with the data read from the - * Speex::File \a file. - */ + * Create an instance of Speex::Properties with the data read from the Speex::File \a file. + */ Properties(File *file, ReadStyle style = Average); /*! - * Destroys this Speex::Properties instance. - */ + * Destroys this Speex::Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - TAGLIB_DEPRECATED virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the nominal bit rate as read from the Speex header in kb/s. - */ + * Returns the nominal bit rate as read from the Speex header in kb/s. + */ int bitrateNominal() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the Speex version, currently "0" (as specified by the spec). - */ + * Returns the Speex version, currently "0" (as specified by the spec). + */ int speexVersion() const; private: @@ -122,6 +104,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties { class PropertiesPrivate; PropertiesPrivate *d; }; + } // namespace Speex } // namespace Ogg } // namespace TagLib diff --git a/3rdparty/taglib/ogg/vorbis/vorbisfile.cpp b/3rdparty/taglib/ogg/vorbis/vorbisfile.cpp index 474e24ac5..8be957de9 100644 --- a/3rdparty/taglib/ogg/vorbis/vorbisfile.cpp +++ b/3rdparty/taglib/ogg/vorbis/vorbisfile.cpp @@ -36,8 +36,7 @@ using namespace Strawberry_TagLib::TagLib; class Vorbis::File::FilePrivate { public: - FilePrivate() : comment(0), - properties(0) {} + FilePrivate() : comment(nullptr), properties(nullptr) {} ~FilePrivate() { delete comment; @@ -106,6 +105,7 @@ Vorbis::Properties *Vorbis::File::audioProperties() const { } bool Vorbis::File::save() { + ByteVector v(vorbisCommentHeaderID); if (!d->comment) @@ -115,6 +115,7 @@ bool Vorbis::File::save() { setPacket(1, v); return Ogg::File::save(); + } //////////////////////////////////////////////////////////////////////////////// @@ -122,6 +123,7 @@ bool Vorbis::File::save() { //////////////////////////////////////////////////////////////////////////////// void Vorbis::File::read(bool readProperties) { + ByteVector commentHeaderData = packet(1); if (commentHeaderData.mid(0, 7) != vorbisCommentHeaderID) { @@ -134,4 +136,5 @@ void Vorbis::File::read(bool readProperties) { if (readProperties) d->properties = new Properties(this); + } diff --git a/3rdparty/taglib/ogg/vorbis/vorbisfile.h b/3rdparty/taglib/ogg/vorbis/vorbisfile.h index 4068050bf..5d376748f 100644 --- a/3rdparty/taglib/ogg/vorbis/vorbisfile.h +++ b/3rdparty/taglib/ogg/vorbis/vorbisfile.h @@ -36,10 +36,9 @@ namespace Strawberry_TagLib { namespace TagLib { /* - * This is just to make this appear to be in the Ogg namespace in the - * documentation. The typedef below will make this work with the current code. - * In the next BIC version of TagLib this will be really moved into the Ogg - * namespace. + * This is just to make this appear to be in the Ogg namespace in the documentation. + * The typedef below will make this work with the current code. + * In the next BIC version of TagLib this will be really moved into the Ogg namespace. */ #ifdef DOXYGEN @@ -50,83 +49,74 @@ namespace Ogg { namespace Vorbis { - //! An implementation of Ogg::File with Vorbis specific methods /*! - * This is the central class in the Ogg Vorbis metadata processing collection - * of classes. It's built upon Ogg::File which handles processing of the Ogg - * logical bitstream and breaking it down into pages which are handled by - * the codec implementations, in this case Vorbis specifically. - */ + * This is the central class in the Ogg Vorbis metadata processing collection of classes. + * It's built upon Ogg::File which handles processing of the Ogg logical bitstream and breaking + * it down into pages which are handled by the codec implementations, in this case Vorbis specifically. + */ class TAGLIB_EXPORT File : public Ogg::File { public: /*! - * Constructs a Vorbis file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(FileName file, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs a Vorbis file from \a file. If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs a Vorbis file from \a stream. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(IOStream *stream, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs a Vorbis file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the XiphComment for this file. XiphComment implements the tag - * interface, so this serves as the reimplementation of - * TagLib::File::tag(). - */ + * Returns the XiphComment for this file. + * XiphComment implements the tag interface, so this serves as the reimplementation of TagLib::File::tag(). + */ virtual Ogg::XiphComment *tag() const; /*! - * Implements the unified property interface -- export function. - * This forwards directly to XiphComment::properties(). - */ + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ PropertyMap properties() const; /*! - * Implements the unified tag dictionary interface -- import function. - * Like properties(), this is a forwarder to the file's XiphComment. - */ + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the Vorbis::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the Vorbis::Properties for this file. If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Save the file. - * - * This returns true if the save was successful. - */ + * Save the file. + * + * This returns true if the save was successful. + */ virtual bool save(); /*! - * Check if the given \a stream can be opened as an Ogg Vorbis file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Check if the given \a stream can be opened as an Ogg Vorbis file. + * + * \note This method is designed to do a quick check. The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: @@ -141,9 +131,8 @@ class TAGLIB_EXPORT File : public Ogg::File { } // namespace Vorbis /* - * To keep compatibility with the current version put Vorbis in the Ogg namespace - * only in the docs and provide a typedef to make it work. In the next BIC - * version this will be removed and it will only exist in the Ogg namespace. + * To keep compatibility with the current version put Vorbis in the Ogg namespace only in the docs and provide a typedef to make it work. + * In the next BIC version this will be removed and it will only exist in the Ogg namespace. */ #ifdef DOXYGEN diff --git a/3rdparty/taglib/ogg/vorbis/vorbisproperties.cpp b/3rdparty/taglib/ogg/vorbis/vorbisproperties.cpp index eb0944555..373ce727b 100644 --- a/3rdparty/taglib/ogg/vorbis/vorbisproperties.cpp +++ b/3rdparty/taglib/ogg/vorbis/vorbisproperties.cpp @@ -68,8 +68,7 @@ static const char vorbisSetupHeaderID[] = { 0x01, 'v', 'o', 'r', 'b', 'i', 's', // public members //////////////////////////////////////////////////////////////////////////////// -Vorbis::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +Vorbis::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { read(file); } @@ -77,10 +76,6 @@ Vorbis::Properties::~Properties() { delete d; } -int Vorbis::Properties::length() const { - return lengthInSeconds(); -} - int Vorbis::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -122,6 +117,7 @@ int Vorbis::Properties::bitrateMinimum() const { //////////////////////////////////////////////////////////////////////////////// void Vorbis::Properties::read(File *file) { + // Get the identification header from the Ogg implementation. const ByteVector data = file->packet(0); @@ -194,4 +190,5 @@ void Vorbis::Properties::read(File *file) { if (d->bitrate == 0 && d->bitrateNominal > 0) d->bitrate = static_cast(d->bitrateNominal / 1000.0 + 0.5); + } diff --git a/3rdparty/taglib/ogg/vorbis/vorbisproperties.h b/3rdparty/taglib/ogg/vorbis/vorbisproperties.h index 17ce9b89d..ce1a3ac0a 100644 --- a/3rdparty/taglib/ogg/vorbis/vorbisproperties.h +++ b/3rdparty/taglib/ogg/vorbis/vorbisproperties.h @@ -33,10 +33,9 @@ namespace Strawberry_TagLib { namespace TagLib { /* - * This is just to make this appear to be in the Ogg namespace in the - * documentation. The typedef below will make this work with the current code. - * In the next BIC version of TagLib this will be really moved into the Ogg - * namespace. + * This is just to make this appear to be in the Ogg namespace in the documentation. + * The typedef below will make this work with the current code. + * In the next BIC version of TagLib this will be really moved into the Ogg namespace. */ #ifdef DOXYGEN @@ -50,86 +49,70 @@ class File; //! An implementation of audio property reading for Ogg Vorbis /*! - * This reads the data from an Ogg Vorbis stream found in the AudioProperties - * API. - */ + * This reads the data from an Ogg Vorbis stream found in the AudioProperties API. + */ class TAGLIB_EXPORT Properties : public AudioProperties { public: /*! - * Create an instance of Vorbis::Properties with the data read from the - * Vorbis::File \a file. - */ + * Create an instance of Vorbis::Properties with the data read from the Vorbis::File \a file. + */ Properties(File *file, ReadStyle style = Average); /*! - * Destroys this VorbisProperties instance. - */ + * Destroys this VorbisProperties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - TAGLIB_DEPRECATED virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the Vorbis version, currently "0" (as specified by the spec). - */ + * Returns the Vorbis version, currently "0" (as specified by the spec). + */ int vorbisVersion() const; /*! - * Returns the maximum bitrate as read from the Vorbis identification - * header. - */ + * Returns the maximum bitrate as read from the Vorbis identification header. + */ int bitrateMaximum() const; /*! - * Returns the nominal bitrate as read from the Vorbis identification - * header. - */ + * Returns the nominal bitrate as read from the Vorbis identification header. + */ int bitrateNominal() const; /*! - * Returns the minimum bitrate as read from the Vorbis identification - * header. - */ + * Returns the minimum bitrate as read from the Vorbis identification header. + */ int bitrateMinimum() const; private: @@ -144,9 +127,8 @@ class TAGLIB_EXPORT Properties : public AudioProperties { } // namespace Vorbis /* - * To keep compatibility with the current version put Vorbis in the Ogg namespace - * only in the docs and provide a typedef to make it work. In the next BIC - * version this will be removed and it will only exist in the Ogg namespace. + * To keep compatibility with the current version put Vorbis in the Ogg namespace only in the docs and provide a typedef to make it work. + * In the next BIC version this will be removed and it will only exist in the Ogg namespace. */ #ifdef DOXYGEN diff --git a/3rdparty/taglib/ogg/xiphcomment.cpp b/3rdparty/taglib/ogg/xiphcomment.cpp index a3fe52bb2..acde2a594 100644 --- a/3rdparty/taglib/ogg/xiphcomment.cpp +++ b/3rdparty/taglib/ogg/xiphcomment.cpp @@ -57,12 +57,9 @@ class Ogg::XiphComment::XiphCommentPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -Ogg::XiphComment::XiphComment() : Strawberry_TagLib::TagLib::Tag(), - d(new XiphCommentPrivate()) { -} +Ogg::XiphComment::XiphComment() : Strawberry_TagLib::TagLib::Tag(), d(new XiphCommentPrivate()) {} -Ogg::XiphComment::XiphComment(const ByteVector &data) : Strawberry_TagLib::TagLib::Tag(), - d(new XiphCommentPrivate()) { +Ogg::XiphComment::XiphComment(const ByteVector &data) : Strawberry_TagLib::TagLib::Tag(), d(new XiphCommentPrivate()) { parse(data); } @@ -71,24 +68,31 @@ Ogg::XiphComment::~XiphComment() { } String Ogg::XiphComment::title() const { + if (d->fieldListMap["TITLE"].isEmpty()) return String(); return d->fieldListMap["TITLE"].toString(); + } String Ogg::XiphComment::artist() const { + if (d->fieldListMap["ARTIST"].isEmpty()) return String(); return d->fieldListMap["ARTIST"].toString(); + } String Ogg::XiphComment::album() const { + if (d->fieldListMap["ALBUM"].isEmpty()) return String(); return d->fieldListMap["ALBUM"].toString(); + } String Ogg::XiphComment::comment() const { + if (!d->fieldListMap["DESCRIPTION"].isEmpty()) { d->commentField = "DESCRIPTION"; return d->fieldListMap["DESCRIPTION"].toString(); @@ -100,28 +104,35 @@ String Ogg::XiphComment::comment() const { } return String(); + } String Ogg::XiphComment::genre() const { + if (d->fieldListMap["GENRE"].isEmpty()) return String(); return d->fieldListMap["GENRE"].toString(); + } unsigned int Ogg::XiphComment::year() const { + if (!d->fieldListMap["DATE"].isEmpty()) return d->fieldListMap["DATE"].front().toInt(); if (!d->fieldListMap["YEAR"].isEmpty()) return d->fieldListMap["YEAR"].front().toInt(); return 0; + } unsigned int Ogg::XiphComment::track() const { + if (!d->fieldListMap["TRACKNUMBER"].isEmpty()) return d->fieldListMap["TRACKNUMBER"].front().toInt(); if (!d->fieldListMap["TRACKNUM"].isEmpty()) return d->fieldListMap["TRACKNUM"].front().toInt(); return 0; + } void Ogg::XiphComment::setTitle(const String &s) { @@ -137,6 +148,7 @@ void Ogg::XiphComment::setAlbum(const String &s) { } void Ogg::XiphComment::setComment(const String &s) { + if (d->commentField.isEmpty()) { if (!d->fieldListMap["DESCRIPTION"].isEmpty()) d->commentField = "DESCRIPTION"; @@ -145,6 +157,7 @@ void Ogg::XiphComment::setComment(const String &s) { } addField(d->commentField, s); + } void Ogg::XiphComment::setGenre(const String &s) { @@ -152,31 +165,38 @@ void Ogg::XiphComment::setGenre(const String &s) { } void Ogg::XiphComment::setYear(unsigned int i) { + removeFields("YEAR"); if (i == 0) removeFields("DATE"); else addField("DATE", String::number(i)); + } void Ogg::XiphComment::setTrack(unsigned int i) { + removeFields("TRACKNUM"); if (i == 0) removeFields("TRACKNUMBER"); else addField("TRACKNUMBER", String::number(i)); + } bool Ogg::XiphComment::isEmpty() const { + for (FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) { if (!(*it).second.isEmpty()) return false; } return true; + } unsigned int Ogg::XiphComment::fieldCount() const { + unsigned int count = 0; for (FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) @@ -185,6 +205,7 @@ unsigned int Ogg::XiphComment::fieldCount() const { count += d->pictureList.size(); return count; + } const Ogg::FieldListMap &Ogg::XiphComment::fieldListMap() const { @@ -196,6 +217,7 @@ PropertyMap Ogg::XiphComment::properties() const { } PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties) { + // check which keys are to be deleted StringList toRemove; for (FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) @@ -227,9 +249,11 @@ PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties) { } } return invalid; + } bool Ogg::XiphComment::checkKey(const String &key) { + if (key.size() < 1) return false; @@ -241,6 +265,7 @@ bool Ogg::XiphComment::checkKey(const String &key) { } return true; + } String Ogg::XiphComment::vendorID() const { @@ -248,6 +273,7 @@ String Ogg::XiphComment::vendorID() const { } void Ogg::XiphComment::addField(const String &key, const String &value, bool replace) { + if (!checkKey(key)) { debug("Ogg::XiphComment::addField() - Invalid key. Field not added."); return; @@ -260,13 +286,7 @@ void Ogg::XiphComment::addField(const String &key, const String &value, bool rep if (!key.isEmpty() && !value.isEmpty()) d->fieldListMap[upperKey].append(value); -} -void Ogg::XiphComment::removeField(const String &key, const String &value) { - if (!value.isNull()) - removeFields(key, value); - else - removeFields(key); } void Ogg::XiphComment::removeFields(const String &key) { @@ -274,6 +294,7 @@ void Ogg::XiphComment::removeFields(const String &key) { } void Ogg::XiphComment::removeFields(const String &key, const String &value) { + StringList &fields = d->fieldListMap[key.upper()]; for (StringList::Iterator it = fields.begin(); it != fields.end();) { if (*it == value) @@ -281,6 +302,7 @@ void Ogg::XiphComment::removeFields(const String &key, const String &value) { else ++it; } + } void Ogg::XiphComment::removeAllFields() { @@ -292,12 +314,14 @@ bool Ogg::XiphComment::contains(const String &key) const { } void Ogg::XiphComment::removePicture(FLAC::Picture *picture, bool del) { + PictureIterator it = d->pictureList.find(picture); if (it != d->pictureList.end()) d->pictureList.erase(it); if (del) delete picture; + } void Ogg::XiphComment::removeAllPictures() { @@ -317,6 +341,7 @@ ByteVector Ogg::XiphComment::render() const { } ByteVector Ogg::XiphComment::render(bool addFramingBit) const { + ByteVector data; // Add the vendor ID length and the vendor ID. It's important to use the @@ -368,6 +393,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const { data.append(char(1)); return data; + } //////////////////////////////////////////////////////////////////////////////// @@ -375,6 +401,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const { //////////////////////////////////////////////////////////////////////////////// void Ogg::XiphComment::parse(const ByteVector &data) { + // The first thing in the comment data is the vendor ID length, followed by a // UTF8 string with the vendor ID. @@ -468,4 +495,5 @@ void Ogg::XiphComment::parse(const ByteVector &data) { addField(key, String(entry.mid(sep + 1), String::UTF8), false); } } + } diff --git a/3rdparty/taglib/ogg/xiphcomment.h b/3rdparty/taglib/ogg/xiphcomment.h index b38540ab1..ca2e5b1b1 100644 --- a/3rdparty/taglib/ogg/xiphcomment.h +++ b/3rdparty/taglib/ogg/xiphcomment.h @@ -41,43 +41,41 @@ namespace TagLib { namespace Ogg { /*! - * A mapping between a list of field names, or keys, and a list of values - * associated with that field. - * - * \see XiphComment::fieldListMap() - */ + * A mapping between a list of field names, or keys, and a list of values associated with that field. + * + * \see XiphComment::fieldListMap() + */ typedef Map FieldListMap; //! Ogg Vorbis comment implementation /*! - * This class is an implementation of the Ogg Vorbis comment specification, - * to be found in section 5 of the Ogg Vorbis specification. Because this - * format is also used in other (currently unsupported) Xiph.org formats, it - * has been made part of a generic implementation rather than being limited - * to strictly Vorbis. - * - * Vorbis comments are a simple vector of keys and values, called fields. - * Multiple values for a given key are supported. - * - * \see fieldListMap() - */ + * This class is an implementation of the Ogg Vorbis comment specification, + * to be found in section 5 of the Ogg Vorbis specification. + * Because this format is also used in other (currently unsupported) Xiph.org formats, + * it has been made part of a generic implementation rather than being limited to strictly Vorbis. + * + * Vorbis comments are a simple vector of keys and values, called fields. + * Multiple values for a given key are supported. + * + * \see fieldListMap() + */ class TAGLIB_EXPORT XiphComment : public Strawberry_TagLib::TagLib::Tag { public: /*! - * Constructs an empty Vorbis comment. - */ + * Constructs an empty Vorbis comment. + */ XiphComment(); /*! - * Constructs a Vorbis comment from \a data. - */ + * Constructs a Vorbis comment from \a data. + */ XiphComment(const ByteVector &data); /*! - * Destroys this instance of the XiphComment. - */ + * Destroys this instance of the XiphComment. + */ virtual ~XiphComment(); virtual String title() const; @@ -99,167 +97,149 @@ class TAGLIB_EXPORT XiphComment : public Strawberry_TagLib::TagLib::Tag { virtual bool isEmpty() const; /*! - * Returns the number of fields present in the comment. - */ + * Returns the number of fields present in the comment. + */ unsigned int fieldCount() const; /*! - * Returns a reference to the map of field lists. Because Xiph comments - * support multiple fields with the same key, a pure Map would not work. - * As such this is a Map of string lists, keyed on the comment field name. - * - * The standard set of Xiph/Vorbis fields (which may or may not be - * contained in any specific comment) is: - * - *
    - *
  • TITLE
  • - *
  • VERSION
  • - *
  • ALBUM
  • - *
  • ARTIST
  • - *
  • PERFORMER
  • - *
  • COPYRIGHT
  • - *
  • ORGANIZATION
  • - *
  • DESCRIPTION
  • - *
  • GENRE
  • - *
  • DATE
  • - *
  • LOCATION
  • - *
  • CONTACT
  • - *
  • ISRC
  • - *
- * - * For a more detailed description of these fields, please see the Ogg - * Vorbis specification, section 5.2.2.1. - * - * \note The Ogg Vorbis comment specification does allow these key values - * to be either upper or lower case. However, it is conventional for them - * to be upper case. As such, TagLib, when parsing a Xiph/Vorbis comment, - * converts all fields to uppercase. When you are using this data - * structure, you will need to specify the field name in upper case. - * - * \warning You should not modify this data structure directly, instead - * use addField() and removeField(). - */ + * Returns a reference to the map of field lists. + * Because Xiph comments support multiple fields with the same key, a pure Map would not work. + * As such this is a Map of string lists, keyed on the comment field name. + * + * The standard set of Xiph/Vorbis fields (which may or may not be contained in any specific comment) is: + * + *
    + *
  • TITLE
  • + *
  • VERSION
  • + *
  • ALBUM
  • + *
  • ARTIST
  • + *
  • PERFORMER
  • + *
  • COPYRIGHT
  • + *
  • ORGANIZATION
  • + *
  • DESCRIPTION
  • + *
  • GENRE
  • + *
  • DATE
  • + *
  • LOCATION
  • + *
  • CONTACT
  • + *
  • ISRC
  • + *
+ * + * For a more detailed description of these fields, please see the Ogg + * Vorbis specification, section 5.2.2.1. + * + * \note The Ogg Vorbis comment specification does allow these key values to be either upper or lower case. + * However, it is conventional for them to be upper case. + * As such, TagLib, when parsing a Xiph/Vorbis comment, converts all fields to uppercase. + * When you are using this data structure, you will need to specify the field name in upper case. + * + * \warning You should not modify this data structure directly, instead use addField() and removeField(). + */ const FieldListMap &fieldListMap() const; /*! - * Implements the unified property interface -- export function. - * The result is a one-to-one match of the Xiph comment, since it is - * completely compatible with the property interface (in fact, a Xiph - * comment is nothing more than a map from tag names to list of values, - * as is the dict interface). - */ + * Implements the unified property interface -- export function. + * The result is a one-to-one match of the Xiph comment, + * since it is completely compatible with the property interface + * (in fact, a Xiph comment is nothing more than a map from tag names to list of values, as is the dict interface). + */ PropertyMap properties() const; /*! - * Implements the unified property interface -- import function. - * The tags from the given map will be stored one-to-one in the file, - * except for invalid keys (less than one character, non-ASCII, or - * containing '=' or '~') in which case the according values will - * be contained in the returned PropertyMap. - */ + * Implements the unified property interface -- import function. + * The tags from the given map will be stored one-to-one in the file, + * except for invalid keys (less than one character, non-ASCII, + * or containing '=' or '~') in which case the according values will be contained in the returned PropertyMap. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Check if the given String is a valid Xiph comment key. - */ + * Check if the given String is a valid Xiph comment key. + */ static bool checkKey(const String &); /*! - * Returns the vendor ID of the Ogg Vorbis encoder. libvorbis 1.0 as the - * most common case always returns "Xiph.Org libVorbis I 20020717". - */ + * Returns the vendor ID of the Ogg Vorbis encoder. + * libvorbis 1.0 as the most common case always returns "Xiph.Org libVorbis I 20020717". + */ String vendorID() const; /*! - * Add the field specified by \a key with the data \a value. If \a replace - * is true, then all of the other fields with the same key will be removed - * first. - * - * If the field value is empty, the field will be removed. - */ + * Add the field specified by \a key with the data \a value. + * If \a replace is true, then all of the other fields with the same key will be removed first. + * + * If the field value is empty, the field will be removed. + */ void addField(const String &key, const String &value, bool replace = true); /*! - * Remove the field specified by \a key with the data \a value. If - * \a value is null, all of the fields with the given key will be removed. - * - * \deprecated Using this method may lead to a linkage error. - */ - // BIC: remove and merge with below - TAGLIB_DEPRECATED void removeField(const String &key, const String &value = String()); - - /*! - * Remove all the fields specified by \a key. - * - * \see removeAllFields() - */ + * Remove all the fields specified by \a key. + * + * \see removeAllFields() + */ void removeFields(const String &key); /*! - * Remove all the fields specified by \a key with the data \a value. - * - * \see removeAllFields() - */ + * Remove all the fields specified by \a key with the data \a value. + * + * \see removeAllFields() + */ void removeFields(const String &key, const String &value); /*! - * Remove all the fields in the comment. - * - * \see removeFields() - */ + * Remove all the fields in the comment. + * + * \see removeFields() + */ void removeAllFields(); /*! - * Returns true if the field is contained within the comment. - * - * \note This is safer than checking for membership in the FieldListMap. - */ + * Returns true if the field is contained within the comment. + * + * \note This is safer than checking for membership in the FieldListMap. + */ bool contains(const String &key) const; /*! - * Renders the comment to a ByteVector suitable for inserting into a file. - */ + * Renders the comment to a ByteVector suitable for inserting into a file. + */ ByteVector render() const; // BIC: remove and merge with below /*! - * Renders the comment to a ByteVector suitable for inserting into a file. - * - * If \a addFramingBit is true the standard Vorbis comment framing bit will - * be appended. However some formats (notably FLAC) do not work with this - * in place. - */ + * Renders the comment to a ByteVector suitable for inserting into a file. + * + * If \a addFramingBit is true the standard Vorbis comment framing bit will + * be appended. However some formats (notably FLAC) do not work with this + * in place. + */ ByteVector render(bool addFramingBit) const; /*! - * Returns a list of pictures attached to the xiph comment. - */ + * Returns a list of pictures attached to the xiph comment. + */ List pictureList(); /*! - * Removes an picture. If \a del is true the picture's memory - * will be freed; if it is false, it must be deleted by the user. - */ + * Removes an picture. If \a del is true the picture's memory will be freed; if it is false, it must be deleted by the user. + */ void removePicture(FLAC::Picture *picture, bool del = true); /*! - * Remove all pictures. - */ + * Remove all pictures. + */ void removeAllPictures(); /*! - * Add a new picture to the comment block. The comment block takes ownership of the - * picture and will handle freeing its memory. - * - * \note The file will be saved only after calling save(). - */ + * Add a new picture to the comment block. The comment block takes ownership of the picture and will handle freeing its memory. + * + * \note The file will be saved only after calling save(). + */ void addPicture(FLAC::Picture *picture); protected: /*! - * Reads the tag from the file specified in the constructor and fills the - * FieldListMap. - */ + * Reads the tag from the file specified in the constructor and fills the FieldListMap. + */ void parse(const ByteVector &data); private: diff --git a/3rdparty/taglib/riff/aiff/aifffile.cpp b/3rdparty/taglib/riff/aiff/aifffile.cpp index 14fe3f5aa..492d4a63b 100644 --- a/3rdparty/taglib/riff/aiff/aifffile.cpp +++ b/3rdparty/taglib/riff/aiff/aifffile.cpp @@ -36,9 +36,7 @@ using namespace Strawberry_TagLib::TagLib; class RIFF::AIFF::File::FilePrivate { public: - FilePrivate() : properties(0), - tag(0), - hasID3v2(false) {} + FilePrivate() : properties(nullptr), tag(nullptr), hasID3v2(false) {} ~FilePrivate() { delete properties; @@ -56,24 +54,26 @@ class RIFF::AIFF::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool RIFF::AIFF::File::isSupported(IOStream *stream) { + // An AIFF file has to start with "FORM????AIFF" or "FORM????AIFC". const ByteVector id = Utils::readHeader(stream, 12, false); return (id.startsWith("FORM") && (id.containsAt("AIFF", 8) || id.containsAt("AIFC", 8))); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -RIFF::AIFF::File::File(FileName file, bool readProperties, Properties::ReadStyle) : RIFF::File(file, BigEndian), - d(new FilePrivate()) { +RIFF::AIFF::File::File(FileName file, bool readProperties, Properties::ReadStyle) : RIFF::File(file, BigEndian), d(new FilePrivate()) { + if (isOpen()) read(readProperties); } -RIFF::AIFF::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : RIFF::File(stream, BigEndian), - d(new FilePrivate()) { +RIFF::AIFF::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : RIFF::File(stream, BigEndian), d(new FilePrivate()) { + if (isOpen()) read(readProperties); } @@ -107,6 +107,7 @@ bool RIFF::AIFF::File::save() { } bool RIFF::AIFF::File::save(ID3v2::Version version) { + if (readOnly()) { debug("RIFF::AIFF::File::save() -- File is read only."); return false; @@ -129,6 +130,7 @@ bool RIFF::AIFF::File::save(ID3v2::Version version) { } return true; + } bool RIFF::AIFF::File::hasID3v2Tag() const { @@ -140,6 +142,7 @@ bool RIFF::AIFF::File::hasID3v2Tag() const { //////////////////////////////////////////////////////////////////////////////// void RIFF::AIFF::File::read(bool readProperties) { + for (unsigned int i = 0; i < chunkCount(); ++i) { const ByteVector name = chunkName(i); if (name == "ID3 " || name == "id3 ") { @@ -158,4 +161,5 @@ void RIFF::AIFF::File::read(bool readProperties) { if (readProperties) d->properties = new Properties(this, Properties::Average); + } diff --git a/3rdparty/taglib/riff/aiff/aifffile.h b/3rdparty/taglib/riff/aiff/aifffile.h index d525c1c59..55643e5c2 100644 --- a/3rdparty/taglib/riff/aiff/aifffile.h +++ b/3rdparty/taglib/riff/aiff/aifffile.h @@ -32,111 +32,109 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace RIFF { //! An implementation of AIFF metadata /*! - * This is implementation of AIFF metadata. - * - * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF - * chunk as well as properties from the file. - */ + * This is implementation of AIFF metadata. + * + * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF + * chunk as well as properties from the file. + */ namespace AIFF { //! An implementation of TagLib::File with AIFF specific methods /*! - * This implements and provides an interface for AIFF files to the - * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing - * the abstract TagLib::File API as well as providing some additional - * information specific to AIFF files. - */ + * This implements and provides an interface for AIFF files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to AIFF files. + */ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::RIFF::File { public: /*! - * Constructs an AIFF file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ + * Constructs an AIFF file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs an AIFF file from \a stream. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ + * Constructs an AIFF file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the Tag for this file. - * - * \note This always returns a valid pointer regardless of whether or not - * the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file - * on disk actually has an ID3v2 tag. - * - * \see hasID3v2Tag() - */ + * Returns the Tag for this file. + * + * \note This always returns a valid pointer regardless of whether or not the file on disk has an ID3v2 tag. + * Use hasID3v2Tag() to check if the file on disk actually has an ID3v2 tag. + * + * \see hasID3v2Tag() + */ virtual ID3v2::Tag *tag() const; /*! - * Implements the unified property interface -- export function. - * This method forwards to ID3v2::Tag::properties(). - */ + * Implements the unified property interface -- export function. + * This method forwards to ID3v2::Tag::properties(). + */ PropertyMap properties() const; void removeUnsupportedProperties(const StringList &properties); /*! - * Implements the unified property interface -- import function. - * This method forwards to ID3v2::Tag::setProperties(). - */ + * Implements the unified property interface -- import function. + * This method forwards to ID3v2::Tag::setProperties(). + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the AIFF::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the AIFF::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Saves the file. - */ + * Saves the file. + */ virtual bool save(); /*! - * Save using a specific ID3v2 version (e.g. v3) - */ + * Save using a specific ID3v2 version (e.g. v3) + */ bool save(ID3v2::Version version); /*! - * Returns whether or not the file on disk actually has an ID3v2 tag. - * - * \see ID3v2Tag() - */ + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ bool hasID3v2Tag() const; /*! - * Check if the given \a stream can be opened as an AIFF file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Check if the given \a stream can be opened as an AIFF file. + * + * \note This method is designed to do a quick check. + * The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: @@ -150,6 +148,7 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::RIFF::File { class FilePrivate; FilePrivate *d; }; + } // namespace AIFF } // namespace RIFF } // namespace TagLib diff --git a/3rdparty/taglib/riff/aiff/aiffproperties.cpp b/3rdparty/taglib/riff/aiff/aiffproperties.cpp index d762e9204..1967e8fba 100644 --- a/3rdparty/taglib/riff/aiff/aiffproperties.cpp +++ b/3rdparty/taglib/riff/aiff/aiffproperties.cpp @@ -55,13 +55,7 @@ class RIFF::AIFF::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -RIFF::AIFF::Properties::Properties(const ByteVector &, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { - debug("RIFF::AIFF::Properties::Properties() - This constructor is no longer used."); -} - -RIFF::AIFF::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +RIFF::AIFF::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { read(file); } @@ -69,10 +63,6 @@ RIFF::AIFF::Properties::~Properties() { delete d; } -int RIFF::AIFF::Properties::length() const { - return lengthInSeconds(); -} - int RIFF::AIFF::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -97,10 +87,6 @@ int RIFF::AIFF::Properties::bitsPerSample() const { return d->bitsPerSample; } -int RIFF::AIFF::Properties::sampleWidth() const { - return bitsPerSample(); -} - unsigned int RIFF::AIFF::Properties::sampleFrames() const { return d->sampleFrames; } @@ -122,6 +108,7 @@ String RIFF::AIFF::Properties::compressionName() const { //////////////////////////////////////////////////////////////////////////////// void RIFF::AIFF::Properties::read(File *file) { + ByteVector data; unsigned int streamLength = 0; for (unsigned int i = 0; i < file->chunkCount(); i++) { @@ -168,4 +155,5 @@ void RIFF::AIFF::Properties::read(File *file) { d->compressionType = data.mid(18, 4); d->compressionName = String(data.mid(23, static_cast(data[22])), String::Latin1); } + } diff --git a/3rdparty/taglib/riff/aiff/aiffproperties.h b/3rdparty/taglib/riff/aiff/aiffproperties.h index d331682ad..02336dcb5 100644 --- a/3rdparty/taglib/riff/aiff/aiffproperties.h +++ b/3rdparty/taglib/riff/aiff/aiffproperties.h @@ -30,9 +30,7 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace RIFF { - namespace AIFF { class File; @@ -40,114 +38,84 @@ class File; //! An implementation of audio property reading for AIFF /*! - * This reads the data from an AIFF stream found in the AudioProperties - * API. - */ + * This reads the data from an AIFF stream found in the AudioProperties API. + */ class TAGLIB_EXPORT Properties : public AudioProperties { public: - /*! - * Create an instance of AIFF::Properties with the data read from the - * ByteVector \a data. - * - * \deprecated - */ - TAGLIB_DEPRECATED Properties(const ByteVector &data, ReadStyle style); /*! - * Create an instance of AIFF::Properties with the data read from the - * AIFF::File \a file. - */ + * Create an instance of AIFF::Properties with the data read from the AIFF::File \a file. + */ Properties(File *file, ReadStyle style); /*! - * Destroys this AIFF::Properties instance. - */ + * Destroys this AIFF::Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - TAGLIB_DEPRECATED virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the number of bits per audio sample. - */ + * Returns the number of bits per audio sample. + */ int bitsPerSample() const; /*! - * Returns the number of bits per audio sample. - * - * \note This method is just an alias of bitsPerSample(). - * - * \deprecated - */ - TAGLIB_DEPRECATED int sampleWidth() const; - - /*! - * Returns the number of sample frames - */ + * Returns the number of sample frames + */ unsigned int sampleFrames() const; /*! - * Returns true if the file is in AIFF-C format, false if AIFF format. - */ + * Returns true if the file is in AIFF-C format, false if AIFF format. + */ bool isAiffC() const; /*! - * Returns the compression type of the AIFF-C file. For example, "NONE" for - * not compressed, "ACE2" for ACE 2-to-1. - * - * If the file is in AIFF format, always returns an empty vector. - * - * \see isAiffC() - */ + * Returns the compression type of the AIFF-C file. For example, "NONE" for not compressed, "ACE2" for ACE 2-to-1. + * + * If the file is in AIFF format, always returns an empty vector. + * + * \see isAiffC() + */ ByteVector compressionType() const; /*! - * Returns the concrete compression name of the AIFF-C file. - * - * If the file is in AIFF format, always returns an empty string. - * - * \see isAiffC() - */ + * Returns the concrete compression name of the AIFF-C file. + * + * If the file is in AIFF format, always returns an empty string. + * + * \see isAiffC() + */ String compressionName() const; private: diff --git a/3rdparty/taglib/riff/rifffile.cpp b/3rdparty/taglib/riff/rifffile.cpp index 7ffe8b808..80bc3f6f5 100644 --- a/3rdparty/taglib/riff/rifffile.cpp +++ b/3rdparty/taglib/riff/rifffile.cpp @@ -44,9 +44,7 @@ struct Chunk { class RIFF::File::FilePrivate { public: - explicit FilePrivate(Endianness _endianness) : endianness(_endianness), - size(0), - sizeOffset(0) {} + explicit FilePrivate(Endianness _endianness) : endianness(_endianness), size(0), sizeOffset(0) {} const Endianness endianness; @@ -68,14 +66,12 @@ RIFF::File::~File() { // protected members //////////////////////////////////////////////////////////////////////////////// -RIFF::File::File(FileName file, Endianness endianness) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate(endianness)) { +RIFF::File::File(FileName file, Endianness endianness) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate(endianness)) { if (isOpen()) read(); } -RIFF::File::File(IOStream *stream, Endianness endianness) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate(endianness)) { +RIFF::File::File(IOStream *stream, Endianness endianness) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate(endianness)) { if (isOpen()) read(); } @@ -89,42 +85,51 @@ unsigned int RIFF::File::chunkCount() const { } unsigned int RIFF::File::chunkDataSize(unsigned int i) const { + if (i >= d->chunks.size()) { debug("RIFF::File::chunkDataSize() - Index out of range. Returning 0."); return 0; } return d->chunks[i].size; + } unsigned int RIFF::File::chunkOffset(unsigned int i) const { + if (i >= d->chunks.size()) { debug("RIFF::File::chunkOffset() - Index out of range. Returning 0."); return 0; } return d->chunks[i].offset; + } unsigned int RIFF::File::chunkPadding(unsigned int i) const { + if (i >= d->chunks.size()) { debug("RIFF::File::chunkPadding() - Index out of range. Returning 0."); return 0; } return d->chunks[i].padding; + } ByteVector RIFF::File::chunkName(unsigned int i) const { + if (i >= d->chunks.size()) { debug("RIFF::File::chunkName() - Index out of range. Returning an empty vector."); return ByteVector(); } return d->chunks[i].name; + } ByteVector RIFF::File::chunkData(unsigned int i) { + if (i >= d->chunks.size()) { debug("RIFF::File::chunkData() - Index out of range. Returning an empty vector."); return ByteVector(); @@ -132,9 +137,11 @@ ByteVector RIFF::File::chunkData(unsigned int i) { seek(d->chunks[i].offset); return readBlock(d->chunks[i].size); + } void RIFF::File::setChunkData(unsigned int i, const ByteVector &data) { + if (i >= d->chunks.size()) { debug("RIFF::File::setChunkData() - Index out of range."); return; @@ -162,6 +169,7 @@ void RIFF::File::setChunkData(unsigned int i, const ByteVector &data) { // Update the global size. updateGlobalSize(); + } void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data) { @@ -169,6 +177,7 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data) { } void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bool alwaysCreate) { + if (d->chunks.empty()) { debug("RIFF::File::setChunkData - No valid chunks found."); return; @@ -225,9 +234,11 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bo // Update the global size. updateGlobalSize(); + } void RIFF::File::removeChunk(unsigned int i) { + if (i >= d->chunks.size()) { debug("RIFF::File::removeChunk() - Index out of range."); return; @@ -246,13 +257,16 @@ void RIFF::File::removeChunk(unsigned int i) { // Update the global size. updateGlobalSize(); + } void RIFF::File::removeChunk(const ByteVector &name) { + for (int i = static_cast(d->chunks.size()) - 1; i >= 0; --i) { if (d->chunks[i].name == name) removeChunk(i); } + } //////////////////////////////////////////////////////////////////////////////// @@ -260,6 +274,7 @@ void RIFF::File::removeChunk(const ByteVector &name) { //////////////////////////////////////////////////////////////////////////////// void RIFF::File::read() { + const bool bigEndian = (d->endianness == BigEndian); long offset = tell(); @@ -323,10 +338,11 @@ void RIFF::File::read() { d->chunks.push_back(chunk); } + } -void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data, - unsigned long offset, unsigned long replace) { +void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data, unsigned long offset, unsigned long replace) { + ByteVector combined; combined.append(name); @@ -337,13 +353,16 @@ void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data, combined.resize(combined.size() + 1, '\0'); insert(combined, offset, replace); + } void RIFF::File::updateGlobalSize() { + const Chunk first = d->chunks.front(); const Chunk last = d->chunks.back(); d->size = last.offset + last.size + last.padding - first.offset + 12; const ByteVector data = ByteVector::fromUInt(d->size, d->endianness == BigEndian); insert(data, d->sizeOffset, 4); + } diff --git a/3rdparty/taglib/riff/rifffile.h b/3rdparty/taglib/riff/rifffile.h index 46ff40ae2..cf388b451 100644 --- a/3rdparty/taglib/riff/rifffile.h +++ b/3rdparty/taglib/riff/rifffile.h @@ -39,16 +39,16 @@ namespace RIFF { //! An RIFF file class with some useful methods specific to RIFF /*! - * This implements the generic TagLib::File API and additionally provides - * access to properties that are distinct to RIFF files, notably access - * to the different ID3 tags. - */ + * This implements the generic TagLib::File API and additionally provides + * access to properties that are distinct to RIFF files, notably access + * to the different ID3 tags. + */ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { public: /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); protected: @@ -59,84 +59,82 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { File(IOStream *stream, Endianness endianness); /*! - * \return The size of the main RIFF chunk. - */ + * \return The size of the main RIFF chunk. + */ unsigned int riffSize() const; /*! - * \return The number of chunks in the file. - */ + * \return The number of chunks in the file. + */ unsigned int chunkCount() const; /*! - * \return The offset within the file for the selected chunk number. - */ + * \return The offset within the file for the selected chunk number. + */ unsigned int chunkOffset(unsigned int i) const; /*! - * \return The size of the chunk data. - */ + * \return The size of the chunk data. + */ unsigned int chunkDataSize(unsigned int i) const; /*! - * \return The size of the padding after the chunk (can be either 0 or 1). - */ + * \return The size of the padding after the chunk (can be either 0 or 1). + */ unsigned int chunkPadding(unsigned int i) const; /*! - * \return The name of the specified chunk, for instance, "COMM" or "ID3 " - */ + * \return The name of the specified chunk, for instance, "COMM" or "ID3 " + */ ByteVector chunkName(unsigned int i) const; /*! - * Reads the chunk data from the file and returns it. - * - * \note This \e will move the read pointer for the file. - */ + * Reads the chunk data from the file and returns it. + * + * \note This \e will move the read pointer for the file. + */ ByteVector chunkData(unsigned int i); /*! - * Sets the data for the specified chunk to \a data. - * - * \warning This will update the file immediately. - */ + * Sets the data for the specified chunk to \a data. + * + * \warning This will update the file immediately. + */ void setChunkData(unsigned int i, const ByteVector &data); /*! - * Sets the data for the chunk \a name to \a data. If a chunk with the - * given name already exists it will be overwritten, otherwise it will be - * created after the existing chunks. - * - * \warning This will update the file immediately. - */ + * Sets the data for the chunk \a name to \a data. + * If a chunk with the given name already exists it will be overwritten, otherwise it will be created after the existing chunks. + * + * \warning This will update the file immediately. + */ void setChunkData(const ByteVector &name, const ByteVector &data); /*! - * Sets the data for the chunk \a name to \a data. If a chunk with the - * given name already exists it will be overwritten, otherwise it will be - * created after the existing chunks. - * - * \note If \a alwaysCreate is true, a new chunk is created regardless of - * whether or not the chunk \a name exists. It should only be used for - * "LIST" chunks. - * - * \warning This will update the file immediately. - */ + * Sets the data for the chunk \a name to \a data. + * If a chunk with the given name already exists it will be overwritten, otherwise it will be created after the existing chunks. + * + * \note If \a alwaysCreate is true, a new chunk is created regardless of + * whether or not the chunk \a name exists. It should only be used for + * "LIST" chunks. + * + * \warning This will update the file immediately. + */ void setChunkData(const ByteVector &name, const ByteVector &data, bool alwaysCreate); /*! - * Removes the specified chunk. - * - * \warning This will update the file immediately. - */ + * Removes the specified chunk. + * + * \warning This will update the file immediately. + */ void removeChunk(unsigned int i); /*! - * Removes the chunk \a name. - * - * \warning This will update the file immediately. - * \warning This removes all the chunks with the given name. - */ + * Removes the chunk \a name. + * + * \warning This will update the file immediately. + * \warning This removes all the chunks with the given name. + */ void removeChunk(const ByteVector &name); private: @@ -148,13 +146,14 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { unsigned long offset, unsigned long replace = 0); /*! - * Update the global RIFF size based on the current internal structure. - */ + * Update the global RIFF size based on the current internal structure. + */ void updateGlobalSize(); class FilePrivate; FilePrivate *d; }; + } // namespace RIFF } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/riff/riffutils.h b/3rdparty/taglib/riff/riffutils.h index 3eca4854e..710d35e51 100644 --- a/3rdparty/taglib/riff/riffutils.h +++ b/3rdparty/taglib/riff/riffutils.h @@ -36,6 +36,7 @@ namespace RIFF { namespace { inline bool isValidChunkName(const ByteVector &name) { + if (name.size() != 4) return false; @@ -46,6 +47,7 @@ inline bool isValidChunkName(const ByteVector &name) { } return true; + } } // namespace diff --git a/3rdparty/taglib/riff/wav/infotag.cpp b/3rdparty/taglib/riff/wav/infotag.cpp index b81c251b0..73f6ca26a 100644 --- a/3rdparty/taglib/riff/wav/infotag.cpp +++ b/3rdparty/taglib/riff/wav/infotag.cpp @@ -46,11 +46,9 @@ class RIFF::Info::Tag::TagPrivate { // StringHandler implementation //////////////////////////////////////////////////////////////////////////////// -StringHandler::StringHandler() { -} +StringHandler::StringHandler() {} -StringHandler::~StringHandler() { -} +StringHandler::~StringHandler() {} String RIFF::Info::StringHandler::parse(const ByteVector &data) const { return String(data, String::UTF8); @@ -64,14 +62,11 @@ ByteVector RIFF::Info::StringHandler::render(const String &s) const { // public members //////////////////////////////////////////////////////////////////////////////// -RIFF::Info::Tag::Tag(const ByteVector &data) : Strawberry_TagLib::TagLib::Tag(), - d(new TagPrivate()) { +RIFF::Info::Tag::Tag(const ByteVector &data) : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) { parse(data); } -RIFF::Info::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), - d(new TagPrivate()) { -} +RIFF::Info::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {} RIFF::Info::Tag::~Tag() { delete d; @@ -148,13 +143,16 @@ FieldListMap RIFF::Info::Tag::fieldListMap() const { } String RIFF::Info::Tag::fieldText(const ByteVector &id) const { + if (d->fieldListMap.contains(id)) return String(d->fieldListMap[id]); else return String(); + } void RIFF::Info::Tag::setFieldText(const ByteVector &id, const String &s) { + // id must be four-byte long pure ascii string. if (!isValidChunkName(id)) return; @@ -163,14 +161,18 @@ void RIFF::Info::Tag::setFieldText(const ByteVector &id, const String &s) { d->fieldListMap[id] = s; else removeField(id); + } void RIFF::Info::Tag::removeField(const ByteVector &id) { + if (d->fieldListMap.contains(id)) d->fieldListMap.erase(id); + } ByteVector RIFF::Info::Tag::render() const { + ByteVector data("INFO"); FieldListMap::ConstIterator it = d->fieldListMap.begin(); @@ -192,13 +194,16 @@ ByteVector RIFF::Info::Tag::render() const { return ByteVector(); else return data; + } void RIFF::Info::Tag::setStringHandler(const StringHandler *handler) { + if (handler) stringHandler = handler; else stringHandler = &defaultStringHandler; + } //////////////////////////////////////////////////////////////////////////////// @@ -206,6 +211,7 @@ void RIFF::Info::Tag::setStringHandler(const StringHandler *handler) { //////////////////////////////////////////////////////////////////////////////// void RIFF::Info::Tag::parse(const ByteVector &data) { + unsigned int p = 4; while (p < data.size()) { const unsigned int size = data.toUInt(p + 4, false); @@ -220,4 +226,5 @@ void RIFF::Info::Tag::parse(const ByteVector &data) { p += ((size + 1) & ~1) + 8; } + } diff --git a/3rdparty/taglib/riff/wav/infotag.h b/3rdparty/taglib/riff/wav/infotag.h index f49749ce2..6813d8997 100644 --- a/3rdparty/taglib/riff/wav/infotag.h +++ b/3rdparty/taglib/riff/wav/infotag.h @@ -47,16 +47,14 @@ typedef Map FieldListMap; //! A abstraction for the string to data encoding in Info tags. /*! - * RIFF INFO tag has no clear definitions about character encodings. - * In practice, local encoding of each system is largely used and UTF-8 is - * popular too. - * - * Here is an option to read and write tags in your preferred encoding - * by subclassing this class, reimplementing parse() and render() and setting - * your reimplementation as the default with Info::Tag::setStringHandler(). - * - * \see ID3v1::Tag::setStringHandler() - */ + * RIFF INFO tag has no clear definitions about character encodings. + * In practice, local encoding of each system is largely used and UTF-8 is popular too. + * + * Here is an option to read and write tags in your preferred encoding by subclassing this class, + * reimplementing parse() and render() and setting your reimplementation as the default with Info::Tag::setStringHandler(). + * + * \see ID3v1::Tag::setStringHandler() + */ class TAGLIB_EXPORT StringHandler { public: @@ -64,37 +62,38 @@ class TAGLIB_EXPORT StringHandler { ~StringHandler(); /*! - * Decode a string from \a data. The default implementation assumes that - * \a data is an UTF-8 character array. - */ + * Decode a string from \a data. + * The default implementation assumes that \a data is an UTF-8 character array. + */ 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 UTF-8 string. - */ + * Encode a ByteVector with the data from \a s. + * The default implementation assumes that \a s is an UTF-8 string. + */ virtual ByteVector render(const String &s) const; }; //! The main class in the ID3v2 implementation /*! - * This is the main class in the INFO tag implementation. RIFF INFO tag is a - * metadata format found in WAV audio and AVI video files. Though it is a part - * of Microsoft/IBM's RIFF specification, the author could not find the official - * documents about it. So, this implementation is referring to unofficial documents - * online and some applications' behaviors especially Windows Explorer. - */ + * This is the main class in the INFO tag implementation. + * RIFF INFO tag is a metadata format found in WAV audio and AVI video files. + * Though it is a part of Microsoft/IBM's RIFF specification, + * the author could not find the official documents about it. + * So, this implementation is referring to unofficial documents online and some applications' + * behaviors especially Windows Explorer. + */ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { public: /*! - * Constructs an empty INFO tag. - */ + * Constructs an empty INFO tag. + */ Tag(); /*! - * Constructs an INFO tag read from \a data which is contents of "LIST" chunk. - */ + * Constructs an INFO tag read from \a data which is contents of "LIST" chunk. + */ Tag(const ByteVector &data); virtual ~Tag(); @@ -120,61 +119,59 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { virtual bool isEmpty() const; /*! - * Returns a copy of the internal fields of the tag. The returned map directly - * reflects the contents of the "INFO" chunk. - * - * \note Modifying this map does not affect the tag's internal data. - * Use setFieldText() and removeField() instead. - * - * \see setFieldText() - * \see removeField() - */ + * Returns a copy of the internal fields of the tag. + * The returned map directly reflects the contents of the "INFO" chunk. + * + * \note Modifying this map does not affect the tag's internal data. + * Use setFieldText() and removeField() instead. + * + * \see setFieldText() + * \see removeField() + */ FieldListMap fieldListMap() const; /* - * Gets the value of the field with the ID \a id. - */ + * Gets the value of the field with the ID \a id. + */ String fieldText(const ByteVector &id) const; /* - * Sets the value of the field with the ID \a id to \a s. - * If the field does not exist, it is created. - * If \s is empty, the field is removed. - * - * \note fieldId must be four-byte long pure ASCII string. This function - * performs nothing if fieldId is invalid. - */ + * Sets the value of the field with the ID \a id to \a s. + * If the field does not exist, it is created. + * If \s is empty, the field is removed. + * + * \note fieldId must be four-byte long pure ASCII string. + * This function performs nothing if fieldId is invalid. + */ void setFieldText(const ByteVector &id, const String &s); /* - * Removes the field with the ID \a id. - */ + * Removes the field with the ID \a id. + */ void removeField(const ByteVector &id); /*! - * Render the tag back to binary data, suitable to be written to disk. - * - * \note Returns empty ByteVector is the tag contains no fields. - */ + * Render the tag back to binary data, suitable to be written to disk. + * + * \note Returns empty ByteVector is the tag contains no fields. + */ ByteVector render() const; /*! - * Sets the string handler that decides how the text data will be - * converted to and from binary data. - * If the parameter \a handler is null, the previous handler is - * released and default UTF-8 handler is restored. - * - * \note The caller is responsible for deleting the previous handler - * as needed after it is released. - * - * \see StringHandler - */ + * Sets the string handler that decides how the text data will be + * converted to and from binary data. + * If the parameter \a handler is null, the previous handler is released and default UTF-8 handler is restored. + * + * \note The caller is responsible for deleting the previous handler as needed after it is released. + * + * \see StringHandler + */ static void setStringHandler(const StringHandler *handler); protected: /*! - * Pareses the body of the tag in \a data. - */ + * Pareses the body of the tag in \a data. + */ void parse(const ByteVector &data); @@ -185,6 +182,7 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag { class TagPrivate; TagPrivate *d; }; + } // namespace Info } // namespace RIFF } // namespace TagLib diff --git a/3rdparty/taglib/riff/wav/wavfile.cpp b/3rdparty/taglib/riff/wav/wavfile.cpp index 9f89f6ce0..d319fad50 100644 --- a/3rdparty/taglib/riff/wav/wavfile.cpp +++ b/3rdparty/taglib/riff/wav/wavfile.cpp @@ -37,15 +37,15 @@ using namespace Strawberry_TagLib::TagLib; namespace { -enum { ID3v2Index = 0, - InfoIndex = 1 }; +enum { + ID3v2Index = 0, + InfoIndex = 1 +}; } class RIFF::WAV::File::FilePrivate { public: - FilePrivate() : properties(0), - hasID3v2(false), - hasInfo(false) {} + FilePrivate() : properties(nullptr), hasID3v2(false), hasInfo(false) {} ~FilePrivate() { delete properties; @@ -63,26 +63,30 @@ class RIFF::WAV::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool RIFF::WAV::File::isSupported(IOStream *stream) { + // A WAV file has to start with "RIFF????WAVE". const ByteVector id = Utils::readHeader(stream, 12, false); return (id.startsWith("RIFF") && id.containsAt("WAVE", 8)); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -RIFF::WAV::File::File(FileName file, bool readProperties, Properties::ReadStyle) : RIFF::File(file, LittleEndian), - d(new FilePrivate()) { +RIFF::WAV::File::File(FileName file, bool readProperties, Properties::ReadStyle) : RIFF::File(file, LittleEndian), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } -RIFF::WAV::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : RIFF::File(stream, LittleEndian), - d(new FilePrivate()) { +RIFF::WAV::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : RIFF::File(stream, LittleEndian), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } RIFF::WAV::File::~File() { @@ -102,6 +106,7 @@ RIFF::Info::Tag *RIFF::WAV::File::InfoTag() const { } void RIFF::WAV::File::strip(TagTypes tags) { + removeTagChunks(tags); if (tags & ID3v2) @@ -109,6 +114,7 @@ void RIFF::WAV::File::strip(TagTypes tags) { if (tags & Info) d->tag.set(InfoIndex, new RIFF::Info::Tag()); + } PropertyMap RIFF::WAV::File::properties() const { @@ -120,8 +126,10 @@ void RIFF::WAV::File::removeUnsupportedProperties(const StringList &unsupported) } PropertyMap RIFF::WAV::File::setProperties(const PropertyMap &properties) { + InfoTag()->setProperties(properties); return ID3v2Tag()->setProperties(properties); + } RIFF::WAV::Properties *RIFF::WAV::File::audioProperties() const { @@ -132,13 +140,8 @@ bool RIFF::WAV::File::save() { return RIFF::WAV::File::save(AllTags); } -bool RIFF::WAV::File::save(TagTypes tags, bool stripOthers, int id3v2Version) { - return save(tags, - stripOthers ? StripOthers : StripNone, - id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4); -} - bool RIFF::WAV::File::save(TagTypes tags, StripTags strip, ID3v2::Version version) { + if (readOnly()) { debug("RIFF::WAV::File::save() -- File is read only."); return false; @@ -171,6 +174,7 @@ bool RIFF::WAV::File::save(TagTypes tags, StripTags strip, ID3v2::Version versio } return true; + } bool RIFF::WAV::File::hasID3v2Tag() const { @@ -186,6 +190,7 @@ bool RIFF::WAV::File::hasInfoTag() const { //////////////////////////////////////////////////////////////////////////////// void RIFF::WAV::File::read(bool readProperties) { + for (unsigned int i = 0; i < chunkCount(); ++i) { const ByteVector name = chunkName(i); if (name == "ID3 " || name == "id3 ") { @@ -222,6 +227,7 @@ void RIFF::WAV::File::read(bool readProperties) { } void RIFF::WAV::File::removeTagChunks(TagTypes tags) { + if ((tags & ID3v2) && d->hasID3v2) { removeChunk("ID3 "); removeChunk("id3 "); @@ -237,4 +243,5 @@ void RIFF::WAV::File::removeTagChunks(TagTypes tags) { d->hasInfo = false; } + } diff --git a/3rdparty/taglib/riff/wav/wavfile.h b/3rdparty/taglib/riff/wav/wavfile.h index fa3021901..83d55bad7 100644 --- a/3rdparty/taglib/riff/wav/wavfile.h +++ b/3rdparty/taglib/riff/wav/wavfile.h @@ -39,22 +39,22 @@ namespace RIFF { //! An implementation of WAV metadata /*! - * This is implementation of WAV metadata. - * - * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF - * chunk as well as properties from the file. - */ + * This is implementation of WAV metadata. + * + * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF + * chunk as well as properties from the file. + */ namespace WAV { //! An implementation of TagLib::File with WAV specific methods /*! - * This implements and provides an interface for WAV files to the - * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing - * the abstract TagLib::File API as well as providing some additional - * information specific to WAV files. - */ + * This implements and provides an interface for WAV files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to WAV files. + */ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::RIFF::File { public: @@ -70,130 +70,114 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::RIFF::File { }; /*! - * Constructs a WAV file from \a file. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(FileName file, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs a WAV file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs a WAV file from \a stream. If \a readProperties is true the - * file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(IOStream *stream, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs a WAV file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the ID3v2 Tag for this file. - * - * \note This method does not return all the tags for this file for - * backward compatibility. Will be fixed in TagLib 2.0. - */ + * Returns the ID3v2 Tag for this file. + * + * \note This method does not return all the tags for this file for backward compatibility. Will be fixed in TagLib 2.0. + */ ID3v2::Tag *tag() const; /*! - * Returns the ID3v2 Tag for this file. - * - * \note This always returns a valid pointer regardless of whether or not - * the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the - * file on disk actually has an ID3v2 tag. - * - * \see hasID3v2Tag() - */ + * Returns the ID3v2 Tag for this file. + * + * \note This always returns a valid pointer regardless of whether or not the file on disk has an ID3v2 tag. + * Use hasID3v2Tag() to check if the file on disk actually has an ID3v2 tag. + * + * \see hasID3v2Tag() + */ ID3v2::Tag *ID3v2Tag() const; /*! - * Returns the RIFF INFO Tag for this file. - * - * \note This always returns a valid pointer regardless of whether or not - * the file on disk has a RIFF INFO tag. Use hasInfoTag() to check if the - * file on disk actually has a RIFF INFO tag. - * - * \see hasInfoTag() - */ + * Returns the RIFF INFO Tag for this file. + * + * \note This always returns a valid pointer regardless of whether or not the file on disk has a RIFF INFO tag. + * Use hasInfoTag() to check if the file on disk actually has a RIFF INFO tag. + * + * \see hasInfoTag() + */ Info::Tag *InfoTag() const; /*! - * 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. - * - * \note This will update the file immediately. - */ + * 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. + * + * \note This will update the file immediately. + */ void strip(TagTypes tags = AllTags); /*! - * Implements the unified property interface -- export function. - * This method forwards to ID3v2::Tag::properties(). - */ + * Implements the unified property interface -- export function. + * This method forwards to ID3v2::Tag::properties(). + */ PropertyMap properties() const; void removeUnsupportedProperties(const StringList &properties); /*! - * Implements the unified property interface -- import function. - * This method forwards to ID3v2::Tag::setProperties(). - */ + * Implements the unified property interface -- import function. + * This method forwards to ID3v2::Tag::setProperties(). + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the WAV::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the WAV::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Saves the file. - */ + * Saves the file. + */ virtual bool save(); /*! - * \deprecated - */ - TAGLIB_DEPRECATED bool save(TagTypes tags, bool stripOthers, int id3v2Version = 4); + * Save the file. + * If \a strip is specified, it is possible to choose if tags not specified in \a tags should be stripped from the file or retained. + * With \a version, it is possible to specify whether ID3v2.4 or ID3v2.3 should be used. + */ + bool save(TagTypes tags, StripTags strip = StripOthers, ID3v2::Version version = ID3v2::v4); /*! - * Save the file. If \a strip is specified, it is possible to choose if - * tags not specified in \a tags should be stripped from the file or - * retained. With \a version, it is possible to specify whether ID3v2.4 - * or ID3v2.3 should be used. - */ - bool save(TagTypes tags, StripTags strip = StripOthers, - ID3v2::Version version = ID3v2::v4); - - /*! - * Returns whether or not the file on disk actually has an ID3v2 tag. - * - * \see ID3v2Tag() - */ + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ bool hasID3v2Tag() const; /*! - * Returns whether or not the file on disk actually has a RIFF INFO tag. - * - * \see InfoTag() - */ + * Returns whether or not the file on disk actually has a RIFF INFO tag. + * + * \see InfoTag() + */ bool hasInfoTag() const; /*! - * Returns whether or not the given \a stream can be opened as a WAV - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as a WAV file. + * + * \note This method is designed to do a quick check. The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: @@ -208,6 +192,7 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::RIFF::File { class FilePrivate; FilePrivate *d; }; + } // namespace WAV } // namespace RIFF } // namespace TagLib diff --git a/3rdparty/taglib/riff/wav/wavproperties.cpp b/3rdparty/taglib/riff/wav/wavproperties.cpp index 017fd3413..d9dbcfa0d 100644 --- a/3rdparty/taglib/riff/wav/wavproperties.cpp +++ b/3rdparty/taglib/riff/wav/wavproperties.cpp @@ -60,18 +60,7 @@ class RIFF::WAV::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -RIFF::WAV::Properties::Properties(const ByteVector &, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { - debug("RIFF::WAV::Properties::Properties() -- This constructor is no longer used."); -} - -RIFF::WAV::Properties::Properties(const ByteVector &, unsigned int, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { - debug("RIFF::WAV::Properties::Properties() -- This constructor is no longer used."); -} - -Strawberry_TagLib::TagLib::RIFF::WAV::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +Strawberry_TagLib::TagLib::RIFF::WAV::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style),d(new PropertiesPrivate()) { read(file); } @@ -79,10 +68,6 @@ RIFF::WAV::Properties::~Properties() { delete d; } -int RIFF::WAV::Properties::length() const { - return lengthInSeconds(); -} - int RIFF::WAV::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -107,10 +92,6 @@ int RIFF::WAV::Properties::bitsPerSample() const { return d->bitsPerSample; } -int RIFF::WAV::Properties::sampleWidth() const { - return bitsPerSample(); -} - unsigned int RIFF::WAV::Properties::sampleFrames() const { return d->sampleFrames; } @@ -124,6 +105,7 @@ int RIFF::WAV::Properties::format() const { //////////////////////////////////////////////////////////////////////////////// void RIFF::WAV::Properties::read(File *file) { + ByteVector data; unsigned int streamLength = 0; unsigned int totalSamples = 0; @@ -187,4 +169,5 @@ void RIFF::WAV::Properties::read(File *file) { d->bitrate = static_cast(byteRate * 8.0 / 1000.0 + 0.5); } } + } diff --git a/3rdparty/taglib/riff/wav/wavproperties.h b/3rdparty/taglib/riff/wav/wavproperties.h index 1795cdcb6..78ee5596e 100644 --- a/3rdparty/taglib/riff/wav/wavproperties.h +++ b/3rdparty/taglib/riff/wav/wavproperties.h @@ -35,7 +35,6 @@ namespace TagLib { class ByteVector; namespace RIFF { - namespace WAV { class File; @@ -43,108 +42,70 @@ class File; //! An implementation of audio property reading for WAV /*! - * This reads the data from an WAV stream found in the AudioProperties - * API. - */ + * This reads the data from an WAV stream found in the AudioProperties + * API. + */ class TAGLIB_EXPORT Properties : public AudioProperties { public: /*! - * Create an instance of WAV::Properties with the data read from the - * ByteVector \a data. - * - * \deprecated - */ - TAGLIB_DEPRECATED Properties(const ByteVector &data, ReadStyle style); - - /*! - * Create an instance of WAV::Properties with the data read from the - * ByteVector \a data and the length calculated using \a streamLength. - * - * \deprecated - */ - TAGLIB_DEPRECATED Properties(const ByteVector &data, unsigned int streamLength, ReadStyle style); - - /*! - * Create an instance of WAV::Properties with the data read from the - * WAV::File \a file. - */ + * Create an instance of WAV::Properties with the data read from the WAV::File \a file. + */ Properties(File *file, ReadStyle style); /*! - * Destroys this WAV::Properties instance. - */ + * Destroys this WAV::Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - TAGLIB_DEPRECATED virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the number of bits per audio sample. - */ + * Returns the number of bits per audio sample. + */ int bitsPerSample() const; /*! - * Returns the number of bits per audio sample. - * - * \note This method is just an alias of bitsPerSample(). - * - * \deprecated - */ - TAGLIB_DEPRECATED int sampleWidth() const; - - /*! - * Returns the number of sample frames. - */ + * Returns the number of sample frames. + */ unsigned int sampleFrames() const; /*! - * Returns the format ID of the file. - * 0 for unknown, 1 for PCM, 2 for ADPCM, 3 for 32/64-bit IEEE754, and - * so forth. - * - * \note For further information, refer to the WAVE Form Registration - * Numbers in RFC 2361. - */ + * Returns the format ID of the file. + * 0 for unknown, 1 for PCM, 2 for ADPCM, 3 for 32/64-bit IEEE754, and so forth. + * + * \note For further information, refer to the WAVE Form Registration Numbers in RFC 2361. + */ int format() const; private: @@ -156,6 +117,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties { class PropertiesPrivate; PropertiesPrivate *d; }; + } // namespace WAV } // namespace RIFF } // namespace TagLib diff --git a/3rdparty/taglib/s3m/s3mfile.cpp b/3rdparty/taglib/s3m/s3mfile.cpp index ad3353c16..f7ff470ff 100644 --- a/3rdparty/taglib/s3m/s3mfile.cpp +++ b/3rdparty/taglib/s3m/s3mfile.cpp @@ -37,26 +37,24 @@ using namespace S3M; class S3M::File::FilePrivate { public: - explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle) - : properties(propertiesStyle) { - } + explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle) : properties(propertiesStyle) {} Mod::Tag tag; S3M::Properties properties; }; -S3M::File::File(FileName file, bool readProperties, - AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(file), - d(new FilePrivate(propertiesStyle)) { +S3M::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(file), d(new FilePrivate(propertiesStyle)) { + if (isOpen()) read(readProperties); + } -S3M::File::File(IOStream *stream, bool readProperties, - AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(stream), - d(new FilePrivate(propertiesStyle)) { +S3M::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(stream), d(new FilePrivate(propertiesStyle)) { + if (isOpen()) read(readProperties); + } S3M::File::~File() { @@ -80,6 +78,7 @@ S3M::Properties *S3M::File::audioProperties() const { } bool S3M::File::save() { + if (readOnly()) { debug("S3M::File::save() - Cannot save to a read only file."); return false; @@ -132,9 +131,11 @@ bool S3M::File::save() { writeByte(0); } return true; + } void S3M::File::read(bool) { + if (!isOpen()) return; @@ -232,4 +233,5 @@ void S3M::File::read(bool) { d->tag.setComment(comment.toString("\n")); d->tag.setTrackerName("ScreamTracker III"); + } diff --git a/3rdparty/taglib/s3m/s3mfile.h b/3rdparty/taglib/s3m/s3mfile.h index 96846ef33..f2d8f60e9 100644 --- a/3rdparty/taglib/s3m/s3mfile.h +++ b/3rdparty/taglib/s3m/s3mfile.h @@ -35,67 +35,59 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace S3M { class TAGLIB_EXPORT File : public Mod::FileBase { public: /*! - * Constructs a ScreamTracker III from \a file. - * - * \note In the current implementation, both \a readProperties and - * \a propertiesStyle are ignored. The audio properties are always - * read. - */ - File(FileName file, bool readProperties = true, - AudioProperties::ReadStyle propertiesStyle = - AudioProperties::Average); + * Constructs a ScreamTracker III from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always read. + */ + File(FileName file, bool readProperties = true, AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average); /*! - * Constructs a ScreamTracker III file from \a stream. - * - * \note In the current implementation, both \a readProperties and - * \a propertiesStyle are ignored. The audio properties are always - * read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - */ - File(IOStream *stream, bool readProperties = true, - AudioProperties::ReadStyle propertiesStyle = - AudioProperties::Average); + * Constructs a ScreamTracker III file from \a stream. + * + * \note In the current implementation, both \a readProperties and \a propertiesStyle are ignored. + * The audio properties are always read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); Mod::Tag *tag() const; /*! - * Implements the unified property interface -- export function. - * Forwards to Mod::Tag::properties(). - */ + * Implements the unified property interface -- export function. + * Forwards to Mod::Tag::properties(). + */ PropertyMap properties() const; /*! - * Implements the unified property interface -- import function. - * Forwards to Mod::Tag::setProperties(). - */ + * Implements the unified property interface -- import function. + * Forwards to Mod::Tag::setProperties(). + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the S3M::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the S3M::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ S3M::Properties *audioProperties() const; /*! - * Save the file. - * This is the same as calling save(AllTags); - * - * \note Saving ScreamTracker III tags is not supported. - */ + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving ScreamTracker III tags is not supported. + */ bool save(); private: @@ -107,6 +99,7 @@ class TAGLIB_EXPORT File : public Mod::FileBase { class FilePrivate; FilePrivate *d; }; + } // namespace S3M } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/s3m/s3mproperties.cpp b/3rdparty/taglib/s3m/s3mproperties.cpp index ddeaeb145..698b47ec3 100644 --- a/3rdparty/taglib/s3m/s3mproperties.cpp +++ b/3rdparty/taglib/s3m/s3mproperties.cpp @@ -59,9 +59,7 @@ class S3M::Properties::PropertiesPrivate { unsigned char bpmSpeed; }; -S3M::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle), - d(new PropertiesPrivate()) { -} +S3M::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle), d(new PropertiesPrivate()) {} S3M::Properties::~Properties() { delete d; diff --git a/3rdparty/taglib/s3m/s3mproperties.h b/3rdparty/taglib/s3m/s3mproperties.h index 23ce91ab3..17111ca91 100644 --- a/3rdparty/taglib/s3m/s3mproperties.h +++ b/3rdparty/taglib/s3m/s3mproperties.h @@ -32,6 +32,7 @@ namespace Strawberry_TagLib { namespace TagLib { namespace S3M { + class TAGLIB_EXPORT Properties : public AudioProperties { friend class File; @@ -90,6 +91,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties { class PropertiesPrivate; PropertiesPrivate *d; }; + } // namespace S3M } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/tag.cpp b/3rdparty/taglib/tag.cpp index 6da9709fc..3bbb495ad 100644 --- a/3rdparty/taglib/tag.cpp +++ b/3rdparty/taglib/tag.cpp @@ -29,14 +29,11 @@ using namespace Strawberry_TagLib::TagLib; -class Tag::TagPrivate { -}; +class Tag::TagPrivate {}; -Tag::Tag() : d(nullptr) { -} +Tag::Tag() : d(nullptr) {} -Tag::~Tag() { -} +Tag::~Tag() {} bool Tag::isEmpty() const { return (title().isEmpty() && @@ -49,6 +46,7 @@ bool Tag::isEmpty() const { } PropertyMap Tag::properties() const { + PropertyMap map; if (!(title().isEmpty())) map["TITLE"].append(title()); @@ -65,12 +63,13 @@ PropertyMap Tag::properties() const { if (!(track() == 0)) map["TRACKNUMBER"].append(String::number(track())); return map; + } -void Tag::removeUnsupportedProperties(const StringList &) { -} +void Tag::removeUnsupportedProperties(const StringList &) {} PropertyMap Tag::setProperties(const PropertyMap &origProps) { + PropertyMap properties(origProps); properties.removeEmpty(); StringList oneValueSet; @@ -145,10 +144,11 @@ PropertyMap Tag::setProperties(const PropertyMap &origProps) { properties[*it].erase(properties[*it].begin()); } return properties; + } -void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) // static -{ +void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) { // static + if (overwrite) { target->setTitle(source->title()); target->setArtist(source->artist()); @@ -174,4 +174,5 @@ void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) // static if (target->track() == 0) target->setTrack(source->track()); } + } diff --git a/3rdparty/taglib/tag.h b/3rdparty/taglib/tag.h index d19775b2f..82fa1ac7a 100644 --- a/3rdparty/taglib/tag.h +++ b/3rdparty/taglib/tag.h @@ -35,11 +35,9 @@ namespace TagLib { //! A simple, generic interface to common audio meta data fields /*! - * This is an attempt to abstract away the difference in the meta data formats - * of various audio codecs and tagging schemes. As such it is generally a - * subset of what is available in the specific formats but should be suitable - * for most applications. This is meant to compliment the generic APIs found - * in TagLib::AudioProperties, TagLib::File and TagLib::FileRef. + * This is an attempt to abstract away the difference in the meta data formats of various audio codecs and tagging schemes. + * As such it is generally a subset of what is available in the specific formats but should be suitable for most applications. + * This is meant to compliment the generic APIs found in TagLib::AudioProperties, TagLib::File and TagLib::FileRef. */ class PropertyMap; @@ -47,145 +45,127 @@ class PropertyMap; class TAGLIB_EXPORT Tag { public: /*! - * Destroys this Tag instance. - */ + * Destroys this Tag instance. + */ virtual ~Tag(); /*! - * Exports the tags of the file as dictionary mapping (human readable) tag - * names (Strings) to StringLists of tag values. - * The default implementation in this class considers only the usual built-in - * tags (artist, album, ...) and only one value per key. - */ + * Exports the tags of the file as dictionary mapping (human readable) tag names (Strings) to StringLists of tag values. + * The default implementation in this class considers only the usual built-in tags (artist, album, ...) and only one value per key. + */ PropertyMap properties() const; /*! - * Removes unsupported properties, or a subset of them, from the tag. - * The parameter \a properties must contain only entries from - * properties().unsupportedData(). - * BIC: Will become virtual in future releases. Currently the non-virtual - * standard implementation of TagLib::Tag does nothing, since there are - * no unsupported elements. - */ + * Removes unsupported properties, or a subset of them, from the tag. + * The parameter \a properties must contain only entries from properties().unsupportedData(). + * BIC: Will become virtual in future releases. Currently the non-virtual + * standard implementation of TagLib::Tag does nothing, since there are no unsupported elements. + */ void removeUnsupportedProperties(const StringList &properties); /*! - * Sets the tags of this File to those specified in \a properties. This default - * implementation sets only the tags for which setter methods exist in this class - * (artist, album, ...), and only one value per key; the rest will be contained - * in the returned PropertyMap. - */ + * Sets the tags of this File to those specified in \a properties. + * This default implementation sets only the tags for which setter methods exist in this class + * (artist, album, ...), and only one value per key; the rest will be contained in the returned PropertyMap. + */ PropertyMap setProperties(const PropertyMap &properties); /*! - * Returns the track name; if no track name is present in the tag - * String::null will be returned. - */ + * Returns the track name; if no track name is present in the tag String::null will be returned. + */ virtual String title() const = 0; /*! - * Returns the artist name; if no artist name is present in the tag - * String::null will be returned. - */ + * Returns the artist name; if no artist name is present in the tag String::null will be returned. + */ virtual String artist() const = 0; /*! - * Returns the album name; if no album name is present in the tag - * String::null will be returned. - */ + * Returns the album name; if no album name is present in the tag String::null will be returned. + */ virtual String album() const = 0; /*! - * Returns the track comment; if no comment is present in the tag - * String::null will be returned. - */ + * Returns the track comment; if no comment is present in the tag String::null will be returned. + */ virtual String comment() const = 0; /*! - * Returns the genre name; if no genre is present in the tag String::null - * will be returned. - */ + * Returns the genre name; if no genre is present in the tag String::null will be returned. + */ virtual String genre() const = 0; /*! - * Returns the year; if there is no year set, this will return 0. - */ + * Returns the year; if there is no year set, this will return 0. + */ virtual unsigned int year() const = 0; /*! - * Returns the track number; if there is no track number set, this will - * return 0. - */ + * Returns the track number; if there is no track number set, this will + * return 0. + */ virtual unsigned int track() const = 0; /*! - * Sets the title to \a s. If \a s is String::null then this value will be - * cleared. - */ + * Sets the title to \a s. If \a s is String::null then this value will be cleared. + */ virtual void setTitle(const String &s) = 0; /*! - * Sets the artist to \a s. If \a s is String::null then this value will be - * cleared. - */ + * Sets the artist to \a s. If \a s is String::null then this value will be cleared. + */ virtual void setArtist(const String &s) = 0; /*! - * Sets the album to \a s. If \a s is String::null then this value will be - * cleared. - */ + * Sets the album to \a s. If \a s is String::null then this value will be cleared. + */ virtual void setAlbum(const String &s) = 0; /*! - * Sets the comment to \a s. If \a s is String::null then this value will be - * cleared. - */ + * Sets the comment to \a s. If \a s is String::null then this value will be cleared. + */ virtual void setComment(const String &s) = 0; /*! - * Sets the genre to \a s. If \a s is String::null then this value will be - * cleared. For tag formats that use a fixed set of genres, the appropriate - * value will be selected based on a string comparison. A list of available - * genres for those formats should be available in that type's - * implementation. - */ + * Sets the genre to \a s. If \a s is String::null then this value will be cleared. + * For tag formats that use a fixed set of genres, the appropriate value will be selected based on a string comparison. + * A list of available genres for those formats should be available in that type's implementation. + */ virtual void setGenre(const String &s) = 0; /*! - * Sets the year to \a i. If \a s is 0 then this value will be cleared. - */ + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ virtual void setYear(unsigned int i) = 0; /*! - * Sets the track to \a i. If \a s is 0 then this value will be cleared. - */ + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ virtual void setTrack(unsigned int i) = 0; /*! - * Returns true if the tag does not contain any data. This should be - * reimplemented in subclasses that provide more than the basic tagging - * abilities in this class. - */ + * Returns true if the tag does not contain any data. + * This should be reimplemented in subclasses that provide more than the basic tagging abilities in this class. + */ virtual bool isEmpty() const; /*! - * Copies the generic data from one tag to another. - * - * \note This will no affect any of the lower level details of the tag. For - * instance if any of the tag type specific data (maybe a URL for a band) is - * set, this will not modify or copy that. This just copies using the API - * in this class. - * - * If \a overwrite is true then the values will be unconditionally copied. - * If false only empty values will be overwritten. - */ + * Copies the generic data from one tag to another. + * + * \note This will no affect any of the lower level details of the tag. + * For instance if any of the tag type specific data (maybe a URL for a band) is set, + * this will not modify or copy that. + * This just copies using the API in this class. + * + * If \a overwrite is true then the values will be unconditionally copied. + * If false only empty values will be overwritten. + */ static void duplicate(const Tag *source, Tag *target, bool overwrite = true); protected: /*! - * Construct a Tag. This is protected since tags should only be instantiated - * through subclasses. - */ + * Construct a Tag. This is protected since tags should only be instantiated through subclasses. + */ Tag(); private: diff --git a/3rdparty/taglib/taglib_config.h.cmake b/3rdparty/taglib/taglib_config.h.cmake index 915f130aa..179953f13 100644 --- a/3rdparty/taglib/taglib_config.h.cmake +++ b/3rdparty/taglib/taglib_config.h.cmake @@ -3,9 +3,4 @@ #ifndef TAGLIB_TAGLIB_CONFIG_H #define TAGLIB_TAGLIB_CONFIG_H -/* These values are no longer used. This file is present only for compatibility reasons. */ - -#define TAGLIB_WITH_ASF 1 -#define TAGLIB_WITH_MP4 1 - #endif diff --git a/3rdparty/taglib/tagunion.cpp b/3rdparty/taglib/tagunion.cpp index 995476f52..aa33c6a5e 100644 --- a/3rdparty/taglib/tagunion.cpp +++ b/3rdparty/taglib/tagunion.cpp @@ -63,8 +63,7 @@ using namespace Strawberry_TagLib::TagLib; class TagUnion::TagUnionPrivate { public: - TagUnionPrivate() : tags(3, static_cast(0)) { - } + TagUnionPrivate() : tags(3, static_cast(nullptr)) {} ~TagUnionPrivate() { delete tags[0]; @@ -99,6 +98,7 @@ void TagUnion::set(int index, Tag *tag) { } PropertyMap TagUnion::properties() const { + // This is an ugly workaround but we can't add a virtual function. // Should be virtual in taglib2. @@ -124,9 +124,11 @@ PropertyMap TagUnion::properties() const { } return PropertyMap(); + } void TagUnion::removeUnsupportedProperties(const StringList &unsupported) { + // This is an ugly workaround but we can't add a virtual function. // Should be virtual in taglib2. @@ -150,6 +152,7 @@ void TagUnion::removeUnsupportedProperties(const StringList &unsupported) { dynamic_cast(d->tags[i])->removeUnsupportedProperties(unsupported); } } + } String TagUnion::title() const { @@ -209,6 +212,7 @@ void TagUnion::setTrack(unsigned int i) { } bool TagUnion::isEmpty() const { + if (d->tags[0] && !d->tags[0]->isEmpty()) return false; if (d->tags[1] && !d->tags[1]->isEmpty()) @@ -217,4 +221,5 @@ bool TagUnion::isEmpty() const { return false; return true; + } diff --git a/3rdparty/taglib/tagunion.h b/3rdparty/taglib/tagunion.h index f54f38c9f..f360651d0 100644 --- a/3rdparty/taglib/tagunion.h +++ b/3rdparty/taglib/tagunion.h @@ -43,11 +43,10 @@ class TagUnion : public Tag { Write }; /*! - * Creates a TagLib::Tag that is the union of \a first, \a second, and - * \a third. The TagUnion takes ownership of these tags and will handle - * their deletion. - */ - TagUnion(Tag *first = 0, Tag *second = 0, Tag *third = 0); + * Creates a TagLib::Tag that is the union of \a first, \a second, and \a third. + * The TagUnion takes ownership of these tags and will handle their deletion. + */ + TagUnion(Tag *first = nullptr, Tag *second = nullptr, Tag *third = nullptr); virtual ~TagUnion(); @@ -77,11 +76,13 @@ class TagUnion : public Tag { virtual bool isEmpty() const; template T *access(int index, bool create) { + if (!create || tag(index)) return static_cast(tag(index)); set(index, new T); return static_cast(tag(index)); + } private: diff --git a/3rdparty/taglib/tagutils.cpp b/3rdparty/taglib/tagutils.cpp index 1e2a8bb11..b632e4f45 100644 --- a/3rdparty/taglib/tagutils.cpp +++ b/3rdparty/taglib/tagutils.cpp @@ -34,6 +34,7 @@ using namespace Strawberry_TagLib::TagLib; long Utils::findID3v1(File *file) { + if (!file->isValid()) return -1; @@ -44,9 +45,11 @@ long Utils::findID3v1(File *file) { return p; return -1; + } long Utils::findID3v2(File *file) { + if (!file->isValid()) return -1; @@ -56,9 +59,11 @@ long Utils::findID3v2(File *file) { return 0; return -1; + } long Utils::findAPE(File *file, long id3v1Location) { + if (!file->isValid()) return -1; @@ -73,10 +78,11 @@ long Utils::findAPE(File *file, long id3v1Location) { return p; return -1; + } -ByteVector Strawberry_TagLib::TagLib::Utils::readHeader(IOStream *stream, unsigned int length, - bool skipID3v2, long *headerOffset) { +ByteVector Strawberry_TagLib::TagLib::Utils::readHeader(IOStream *stream, unsigned int length, bool skipID3v2, long *headerOffset) { + if (!stream || !stream->isOpen()) return ByteVector(); @@ -98,4 +104,5 @@ ByteVector Strawberry_TagLib::TagLib::Utils::readHeader(IOStream *stream, unsign *headerOffset = bufferOffset; return header; + } diff --git a/3rdparty/taglib/tagutils.h b/3rdparty/taglib/tagutils.h index 3b4f52928..ab454777f 100644 --- a/3rdparty/taglib/tagutils.h +++ b/3rdparty/taglib/tagutils.h @@ -41,13 +41,10 @@ class IOStream; namespace Utils { long findID3v1(File *file); - long findID3v2(File *file); - long findAPE(File *file, long id3v1Location); -ByteVector readHeader(IOStream *stream, unsigned int length, bool skipID3v2, - long *headerOffset = 0); +ByteVector readHeader(IOStream *stream, unsigned int length, bool skipID3v2, long *headerOffset = 0); } // namespace Utils } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/toolkit/tbytevector.cpp b/3rdparty/taglib/toolkit/tbytevector.cpp index 57e79fb6f..d90787598 100644 --- a/3rdparty/taglib/toolkit/tbytevector.cpp +++ b/3rdparty/taglib/toolkit/tbytevector.cpp @@ -39,18 +39,16 @@ // This is a bit ugly to keep writing over and over again. -// A rather obscure feature of the C++ spec that I hadn't thought of that makes -// working with C libs much more efficient. There's more here: -// +// A rather obscure feature of the C++ spec that I hadn't thought of that makes working with C libs much more efficient. +// There's more here: // http://www.informit.com/isapi/product_id~{9C84DAB4-FE6E-49C5-BB0A-FB50331233EA}/content/index.asp namespace Strawberry_TagLib { namespace TagLib { template -int findChar( - const TIterator dataBegin, const TIterator dataEnd, - char c, unsigned int offset, int byteAlign) { +int findChar(const TIterator dataBegin, const TIterator dataEnd, char c, unsigned int offset, int byteAlign) { + const size_t dataSize = dataEnd - dataBegin; if (offset + 1 > dataSize) return -1; @@ -66,13 +64,12 @@ int findChar( } return -1; + } template -int findVector( - const TIterator dataBegin, const TIterator dataEnd, - const TIterator patternBegin, const TIterator patternEnd, - unsigned int offset, int byteAlign) { +int findVector(const TIterator dataBegin, const TIterator dataEnd, const TIterator patternBegin, const TIterator patternEnd, unsigned int offset, int byteAlign) { + const size_t dataSize = dataEnd - dataBegin; const size_t patternSize = patternEnd - patternBegin; if (patternSize == 0 || offset + patternSize > dataSize) @@ -108,10 +105,12 @@ int findVector( } return -1; + } template T toNumber(const ByteVector &v, size_t offset, size_t length, bool mostSignificantByteFirst) { + if (offset >= v.size()) { debug("toNumber() -- No data to convert. Returning 0."); return 0; @@ -126,10 +125,12 @@ T toNumber(const ByteVector &v, size_t offset, size_t length, bool mostSignifica } return sum; + } template T toNumber(const ByteVector &v, size_t offset, bool mostSignificantByteFirst) { + const bool isBigEndian = (Utils::systemByteOrder() == Utils::BigEndian); const bool swap = (mostSignificantByteFirst != isBigEndian); @@ -144,10 +145,12 @@ T toNumber(const ByteVector &v, size_t offset, bool mostSignificantByteFirst) { return Utils::byteSwap(tmp); else return tmp; + } template ByteVector fromNumber(T value, bool mostSignificantByteFirst) { + const bool isBigEndian = (Utils::systemByteOrder() == Utils::BigEndian); const bool swap = (mostSignificantByteFirst != isBigEndian); @@ -155,10 +158,12 @@ ByteVector fromNumber(T value, bool mostSignificantByteFirst) { value = Utils::byteSwap(value); return ByteVector(reinterpret_cast(&value), sizeof(T)); + } template TFloat toFloat(const ByteVector &v, size_t offset) { + if (offset > v.size() - sizeof(TInt)) { debug("toFloat() - offset is out of range. Returning 0."); return 0.0; @@ -174,10 +179,12 @@ TFloat toFloat(const ByteVector &v, size_t offset) { tmp.i = Utils::byteSwap(tmp.i); return tmp.f; + } template ByteVector fromFloat(TFloat value) { + union { TInt i; TFloat f; @@ -188,10 +195,12 @@ ByteVector fromFloat(TFloat value) { tmp.i = Utils::byteSwap(tmp.i); return ByteVector(reinterpret_cast(&tmp), sizeof(TInt)); + } template long double toFloat80(const ByteVector &v, size_t offset) { + using std::swap; if (offset > v.size() - 10) { @@ -235,6 +244,7 @@ long double toFloat80(const ByteVector &v, size_t offset) { return -val; else return val; + } class ByteVector::ByteVectorPrivate { @@ -351,18 +361,20 @@ ByteVector &ByteVector::setData(const char *data) { char *ByteVector::data() { detach(); - return (size() > 0) ? (&(*d->data)[d->offset]) : 0; + return (size() > 0) ? (&(*d->data)[d->offset]) : nullptr; } const char *ByteVector::data() const { - return (size() > 0) ? (&(*d->data)[d->offset]) : 0; + return (size() > 0) ? (&(*d->data)[d->offset]) : nullptr; } ByteVector ByteVector::mid(unsigned int index, unsigned int length) const { + index = std::min(index, size()); length = std::min(length, size() - index); return ByteVector(*this, index, length); + } char ByteVector::at(unsigned int index) const { @@ -370,8 +382,10 @@ char ByteVector::at(unsigned int index) const { } int ByteVector::find(const ByteVector &pattern, unsigned int offset, int byteAlign) const { + return findVector( begin(), end(), pattern.begin(), pattern.end(), offset, byteAlign); + } int ByteVector::find(char c, unsigned int offset, int byteAlign) const { @@ -395,6 +409,7 @@ int ByteVector::rfind(const ByteVector &pattern, unsigned int offset, int byteAl } bool ByteVector::containsAt(const ByteVector &pattern, unsigned int offset, unsigned int patternOffset, unsigned int patternLength) const { + if (pattern.size() < patternLength) patternLength = pattern.size(); @@ -404,6 +419,7 @@ bool ByteVector::containsAt(const ByteVector &pattern, unsigned int offset, unsi return false; return (::memcmp(data() + offset, pattern.data() + patternOffset, compareLength) == 0); + } bool ByteVector::startsWith(const ByteVector &pattern) const { @@ -415,6 +431,7 @@ bool ByteVector::endsWith(const ByteVector &pattern) const { } ByteVector &ByteVector::replace(char oldByte, char newByte) { + detach(); for (ByteVector::Iterator it = begin(); it != end(); ++it) { @@ -423,9 +440,11 @@ ByteVector &ByteVector::replace(char oldByte, char newByte) { } return *this; + } ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &with) { + if (pattern.size() == 1 && with.size() == 1) return replace(pattern[0], with[0]); @@ -481,9 +500,11 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit } return *this; + } int ByteVector::endsWithPartialMatch(const ByteVector &pattern) const { + if (pattern.size() > size()) return -1; @@ -498,9 +519,11 @@ int ByteVector::endsWithPartialMatch(const ByteVector &pattern) const { } return -1; + } ByteVector &ByteVector::append(const ByteVector &v) { + if (v.isEmpty()) return *this; @@ -513,6 +536,7 @@ ByteVector &ByteVector::append(const ByteVector &v) { ::memcpy(data() + originalSize, v.data(), appendSize); return *this; + } ByteVector &ByteVector::append(char c) { @@ -530,6 +554,7 @@ unsigned int ByteVector::size() const { } ByteVector &ByteVector::resize(unsigned int size, char padding) { + if (size != d->length) { detach(); @@ -544,6 +569,7 @@ ByteVector &ByteVector::resize(unsigned int size, char padding) { } return *this; + } ByteVector::Iterator ByteVector::begin() { @@ -570,10 +596,12 @@ ByteVector::ReverseIterator ByteVector::rbegin() { } ByteVector::ConstReverseIterator ByteVector::rbegin() const { + // Workaround for the Solaris Studio 12.4 compiler. // We need a const reference to the data vector so we can ensure the const version of rbegin() is called. const std::vector &v = *d->data; return v.rbegin() + (v.size() - (d->offset + d->length)); + } ByteVector::ReverseIterator ByteVector::rend() { @@ -582,10 +610,12 @@ ByteVector::ReverseIterator ByteVector::rend() { } ByteVector::ConstReverseIterator ByteVector::rend() const { + // Workaround for the Solaris Studio 12.4 compiler. // We need a const reference to the data vector so we can ensure the const version of rbegin() is called. const std::vector &v = *d->data; return v.rbegin() + (v.size() - d->offset); + } bool ByteVector::isNull() const { @@ -876,6 +906,7 @@ ByteVector ByteVector::fromBase64(const ByteVector &input) { } ByteVector ByteVector::toBase64() const { + static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; if (!isEmpty()) { unsigned int len = size(); @@ -906,6 +937,7 @@ ByteVector ByteVector::toBase64() const { return output; } return ByteVector(); + } diff --git a/3rdparty/taglib/toolkit/tbytevector.h b/3rdparty/taglib/toolkit/tbytevector.h index 70eb4d2e0..a9e2d68de 100644 --- a/3rdparty/taglib/toolkit/tbytevector.h +++ b/3rdparty/taglib/toolkit/tbytevector.h @@ -38,10 +38,9 @@ namespace TagLib { //! A byte vector /*! - * This class provides a byte vector with some methods that are useful for - * tagging purposes. Many of the search functions are tailored to what is - * useful for finding tag related patterns in a data array. - */ + * This class provides a byte vector with some methods that are useful for tagging purposes. + * Many of the search functions are tailored to what is useful for finding tag related patterns in a data array. + */ class TAGLIB_EXPORT ByteVector { public: @@ -53,571 +52,531 @@ class TAGLIB_EXPORT ByteVector { #endif /*! - * Constructs an empty byte vector. - */ + * Constructs an empty byte vector. + */ ByteVector(); /*! - * Construct a vector of size \a size with all values set to \a value by - * default. - */ + * Construct a vector of size \a size with all values set to \a value by default. + */ ByteVector(unsigned int size, char value = 0); /*! - * Constructs a byte vector that is a copy of \a v. - */ + * Constructs a byte vector that is a copy of \a v. + */ ByteVector(const ByteVector &v); /*! - * Constructs a byte vector that is a copy of \a v. - */ + * Constructs a byte vector that is a copy of \a v. + */ ByteVector(const ByteVector &v, unsigned int offset, unsigned int length); /*! - * Constructs a byte vector that contains \a c. - */ + * Constructs a byte vector that contains \a c. + */ ByteVector(char c); /*! - * Constructs a byte vector that copies \a data for up to \a length bytes. - */ + * Constructs a byte vector that copies \a data for up to \a length bytes. + */ ByteVector(const char *data, unsigned int length); /*! - * Constructs a byte vector that copies \a data up to the first null - * byte. This is particularly useful for constructing byte arrays from - * string constants. - * - * \warning The behavior is undefined if \a data is not null terminated. - */ + * Constructs a byte vector that copies \a data up to the first null byte. + * This is particularly useful for constructing byte arrays from string constants. + * + * \warning The behavior is undefined if \a data is not null terminated. + */ ByteVector(const char *data); /*! - * Destroys this ByteVector instance. - */ + * Destroys this ByteVector instance. + */ virtual ~ByteVector(); /*! - * Sets the data for the byte array using the first \a length bytes of \a data - */ + * Sets the data for the byte array using the first \a length bytes of \a data + */ ByteVector &setData(const char *data, unsigned int length); /*! - * Sets the data for the byte array copies \a data up to the first null - * byte. The behavior is undefined if \a data is not null terminated. - */ + * Sets the data for the byte array copies \a data up to the first null byte. + * The behavior is undefined if \a data is not null terminated. + */ ByteVector &setData(const char *data); /*! - * Returns a pointer to the internal data structure. - * - * \warning Care should be taken when modifying this data structure as it is - * easy to corrupt the ByteVector when doing so. Specifically, while the - * data may be changed, its length may not be. - */ + * Returns a pointer to the internal data structure. + * + * \warning Care should be taken when modifying this data structure as it is easy to corrupt the ByteVector when doing so. + * Specifically, while the data may be changed, its length may not be. + */ char *data(); /*! - * Returns a pointer to the internal data structure which may not be modified. - */ + * Returns a pointer to the internal data structure which may not be modified. + */ const char *data() const; /*! - * Returns a byte vector made up of the bytes starting at \a index and - * for \a length bytes. If \a length is not specified it will return the bytes - * from \a index to the end of the vector. - */ + * Returns a byte vector made up of the bytes starting at \a index and for \a length bytes. + * If \a length is not specified it will return the bytes from \a index to the end of the vector. + */ ByteVector mid(unsigned int index, unsigned int length = 0xffffffff) const; /*! - * This essentially performs the same as operator[](), but instead of causing - * a runtime error if the index is out of bounds, it will return a null byte. - */ + * This essentially performs the same as operator[](), but instead of causing + * a runtime error if the index is out of bounds, it will return a null byte. + */ char at(unsigned int index) const; /*! - * Searches the ByteVector for \a pattern starting at \a offset and returns - * the offset. Returns -1 if the pattern was not found. If \a byteAlign is - * specified the pattern will only be matched if it starts on a byte divisible - * by \a byteAlign (starting from \a offset). - */ + * Searches the ByteVector for \a pattern starting at \a offset and returns + * the offset. Returns -1 if the pattern was not found. + * If \a byteAlign is specified the pattern will only be matched if it starts on a byte divisible + * by \a byteAlign (starting from \a offset). + */ int find(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const; /*! - * Searches the char for \a c starting at \a offset and returns - * the offset. Returns \a -1 if the pattern was not found. If \a byteAlign is - * specified the pattern will only be matched if it starts on a byte divisible - * by \a byteAlign (starting from \a offset). - */ + * Searches the char for \a c starting at \a offset and returns the offset. + * Returns \a -1 if the pattern was not found. + * If \a byteAlign is specified the pattern will only be matched if it starts on a byte divisible + * by \a byteAlign (starting from \a offset). + */ int find(char c, unsigned int offset = 0, int byteAlign = 1) const; /*! - * Searches the ByteVector for \a pattern starting from either the end of the - * vector or \a offset and returns the offset. Returns -1 if the pattern was - * not found. If \a byteAlign is specified the pattern will only be matched - * if it starts on a byte divisible by \a byteAlign (starting from \a offset). - */ + * Searches the ByteVector for \a pattern starting from either the end of the vector or \a offset and returns the offset. + * Returns -1 if the pattern was not found. + * If \a byteAlign is specified the pattern will only be matched if it starts on a byte divisible by \a byteAlign (starting from \a offset). + */ int rfind(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const; /*! - * Checks to see if the vector contains the \a pattern starting at position - * \a offset. Optionally, if you only want to search for part of the pattern - * you can specify an offset within the pattern to start from. Also, you can - * specify to only check for the first \a patternLength bytes of \a pattern with - * the \a patternLength argument. - */ + * Checks to see if the vector contains the \a pattern starting at position \a offset. + * Optionally, if you only want to search for part of the pattern you can specify an offset within the pattern to start from. + * Also, you can specify to only check for the first \a patternLength bytes of \a pattern with the \a patternLength argument. + */ bool containsAt(const ByteVector &pattern, unsigned int offset, unsigned int patternOffset = 0, unsigned int patternLength = 0xffffffff) const; /*! - * Returns true if the vector starts with \a pattern. - */ + * Returns true if the vector starts with \a pattern. + */ bool startsWith(const ByteVector &pattern) const; /*! - * Returns true if the vector ends with \a pattern. - */ + * Returns true if the vector ends with \a pattern. + */ bool endsWith(const ByteVector &pattern) const; /*! - * Replaces \a oldByte with \a newByte and returns a reference to the - * ByteVector after the operation. This \e does modify the vector. - */ + * Replaces \a oldByte with \a newByte and returns a reference to the ByteVector after the operation. This \e does modify the vector. + */ ByteVector &replace(char oldByte, char newByte); /*! - * Replaces \a pattern with \a with and returns a reference to the ByteVector - * after the operation. This \e does modify the vector. - */ + * Replaces \a pattern with \a with and returns a reference to the ByteVector after the operation. This \e does modify the vector. + */ ByteVector &replace(const ByteVector &pattern, const ByteVector &with); /*! - * Checks for a partial match of \a pattern at the end of the vector. It - * returns the offset of the partial match within the vector, or -1 if the - * pattern is not found. This method is particularly useful when searching for - * patterns that start in one vector and end in another. When combined with - * startsWith() it can be used to find a pattern that overlaps two buffers. - * - * \note This will not match the complete pattern at the end of the string; use - * endsWith() for that. - */ + * Checks for a partial match of \a pattern at the end of the vector. + * It returns the offset of the partial match within the vector, or -1 if the pattern is not found. + * This method is particularly useful when searching for patterns that start in one vector and end in another. + * When combined with startsWith() it can be used to find a pattern that overlaps two buffers. + * + * \note This will not match the complete pattern at the end of the string; use endsWith() for that. + */ int endsWithPartialMatch(const ByteVector &pattern) const; /*! - * Appends \a v to the end of the ByteVector. - */ + * Appends \a v to the end of the ByteVector. + */ ByteVector &append(const ByteVector &v); /*! - * Appends \a c to the end of the ByteVector. - */ + * Appends \a c to the end of the ByteVector. + */ ByteVector &append(char c); /*! - * Clears the data. - */ + * Clears the data. + */ ByteVector &clear(); /*! - * Returns the size of the array. - */ + * Returns the size of the array. + */ unsigned int size() const; /*! - * Resize the vector to \a size. If the vector is currently less than - * \a size, pad the remaining spaces with \a padding. Returns a reference - * to the resized vector. - */ + * Resize the vector to \a size. + * If the vector is currently less than \a size, pad the remaining spaces with \a padding. + * Returns a reference to the resized vector. + */ ByteVector &resize(unsigned int size, char padding = 0); /*! - * Returns an Iterator that points to the front of the vector. - */ + * Returns an Iterator that points to the front of the vector. + */ Iterator begin(); /*! - * Returns a ConstIterator that points to the front of the vector. - */ + * Returns a ConstIterator that points to the front of the vector. + */ ConstIterator begin() const; /*! - * Returns an Iterator that points to the back of the vector. - */ + * Returns an Iterator that points to the back of the vector. + */ Iterator end(); /*! - * Returns a ConstIterator that points to the back of the vector. - */ + * Returns a ConstIterator that points to the back of the vector. + */ ConstIterator end() const; /*! - * Returns a ReverseIterator that points to the front of the vector. - */ + * Returns a ReverseIterator that points to the front of the vector. + */ ReverseIterator rbegin(); /*! - * Returns a ConstReverseIterator that points to the front of the vector. - */ + * Returns a ConstReverseIterator that points to the front of the vector. + */ ConstReverseIterator rbegin() const; /*! - * Returns a ReverseIterator that points to the back of the vector. - */ + * Returns a ReverseIterator that points to the back of the vector. + */ ReverseIterator rend(); /*! - * Returns a ConstReverseIterator that points to the back of the vector. - */ + * Returns a ConstReverseIterator that points to the back of the vector. + */ ConstReverseIterator rend() const; /*! - * Returns true if the vector is null. - * - * \note A vector may be empty without being null. So do not use this - * method to check if the vector is empty. - * - * \see isEmpty() - * - * \deprecated - */ + * Returns true if the vector is null. + * + * \note A vector may be empty without being null. So do not use this method to check if the vector is empty. + * + * \see isEmpty() + * + * \deprecated + */ // BIC: remove bool isNull() const; /*! - * Returns true if the ByteVector is empty. - * - * \see size() - * \see isNull() - */ + * Returns true if the ByteVector is empty. + * + * \see size() + * \see isNull() + */ bool isEmpty() const; /*! - * Returns a CRC checksum of the byte vector's data. - * - * \note This uses an uncommon variant of CRC32 specializes in Ogg. - */ + * Returns a CRC checksum of the byte vector's data. + * + * \note This uses an uncommon variant of CRC32 specializes in Ogg. + */ // BIC: Remove or make generic. unsigned int checksum() const; /*! - * Converts the first 4 bytes of the vector to an unsigned integer. - * - * If \a mostSignificantByteFirst is true this will operate left to right - * evaluating the integer. For example if \a mostSignificantByteFirst is - * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == - * 0x01000000 == 1. - * - * \see fromUInt() - */ + * Converts the first 4 bytes of the vector to an unsigned integer. + * + * If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer. + * For example if \a mostSignificantByteFirst is + * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == 0x01000000 == 1. + * + * \see fromUInt() + */ unsigned int toUInt(bool mostSignificantByteFirst = true) const; /*! - * Converts the 4 bytes at \a offset of the vector to an unsigned integer. - * - * If \a mostSignificantByteFirst is true this will operate left to right - * evaluating the integer. For example if \a mostSignificantByteFirst is - * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == - * 0x01000000 == 1. - * - * \see fromUInt() - */ + * Converts the 4 bytes at \a offset of the vector to an unsigned integer. + * + * If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer. + * For example if \a mostSignificantByteFirst is true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == 0x01000000 == 1. + * + * \see fromUInt() + */ unsigned int toUInt(unsigned int offset, bool mostSignificantByteFirst = true) const; /*! - * Converts the \a length bytes at \a offset of the vector to an unsigned - * integer. If \a length is larger than 4, the excess is ignored. - * - * If \a mostSignificantByteFirst is true this will operate left to right - * evaluating the integer. For example if \a mostSignificantByteFirst is - * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == - * 0x01000000 == 1. - * - * \see fromUInt() - */ + * Converts the \a length bytes at \a offset of the vector to an unsigned integer. + * If \a length is larger than 4, the excess is ignored. + * + * If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer. + * For example if \a mostSignificantByteFirst is true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == 0x01000000 == 1. + * + * \see fromUInt() + */ unsigned int toUInt(unsigned int offset, unsigned int length, bool mostSignificantByteFirst = true) const; /*! - * Converts the first 2 bytes of the vector to a (signed) short. - * - * If \a mostSignificantByteFirst is true this will operate left to right - * evaluating the integer. For example if \a mostSignificantByteFirst is - * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. - * - * \see fromShort() - */ + * Converts the first 2 bytes of the vector to a (signed) short. + * + * If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer. + * For example if \a mostSignificantByteFirst is true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ short toShort(bool mostSignificantByteFirst = true) const; /*! - * Converts the 2 bytes at \a offset of the vector to a (signed) short. - * - * If \a mostSignificantByteFirst is true this will operate left to right - * evaluating the integer. For example if \a mostSignificantByteFirst is - * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. - * - * \see fromShort() - */ + * Converts the 2 bytes at \a offset of the vector to a (signed) short. + * + * If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer. + * For example if \a mostSignificantByteFirst is true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ short toShort(unsigned int offset, bool mostSignificantByteFirst = true) const; /*! - * Converts the first 2 bytes of the vector to a unsigned short. - * - * If \a mostSignificantByteFirst is true this will operate left to right - * evaluating the integer. For example if \a mostSignificantByteFirst is - * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. - * - * \see fromShort() - */ + * Converts the first 2 bytes of the vector to a unsigned short. + * + * If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer. + * For example if \a mostSignificantByteFirst is true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ unsigned short toUShort(bool mostSignificantByteFirst = true) const; /*! - * Converts the 2 bytes at \a offset of the vector to a unsigned short. - * - * If \a mostSignificantByteFirst is true this will operate left to right - * evaluating the integer. For example if \a mostSignificantByteFirst is - * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. - * - * \see fromShort() - */ + * Converts the 2 bytes at \a offset of the vector to a unsigned short. + * + * If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer. + * For example if \a mostSignificantByteFirst is true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ unsigned short toUShort(unsigned int offset, bool mostSignificantByteFirst = true) const; /*! - * Converts the first 8 bytes of the vector to a (signed) long long. - * - * If \a mostSignificantByteFirst is true this will operate left to right - * evaluating the integer. For example if \a mostSignificantByteFirst is - * true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1, - * if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. - * - * \see fromUInt() - */ + * Converts the first 8 bytes of the vector to a (signed) long long. + * + * If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer. + * For example if \a mostSignificantByteFirst is true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1, + * if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see fromUInt() + */ long long toLongLong(bool mostSignificantByteFirst = true) const; /*! - * Converts the 8 bytes at \a offset of the vector to a (signed) long long. - * - * If \a mostSignificantByteFirst is true this will operate left to right - * evaluating the integer. For example if \a mostSignificantByteFirst is - * true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1, - * if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. - * - * \see fromUInt() - */ + * Converts the 8 bytes at \a offset of the vector to a (signed) long long. + * + * If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer. + * For example if \a mostSignificantByteFirst is true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1, + * if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see fromUInt() + */ long long toLongLong(unsigned int offset, bool mostSignificantByteFirst = true) const; /* - * Converts the 4 bytes at \a offset of the vector to a float as an IEEE754 - * 32-bit little-endian floating point number. - */ + * Converts the 4 bytes at \a offset of the vector to a float as an IEEE754 32-bit little-endian floating point number. + */ float toFloat32LE(size_t offset) const; /* - * Converts the 4 bytes at \a offset of the vector to a float as an IEEE754 - * 32-bit big-endian floating point number. - */ + * Converts the 4 bytes at \a offset of the vector to a float as an IEEE754 32-bit big-endian floating point number. + */ float toFloat32BE(size_t offset) const; /* - * Converts the 8 bytes at \a offset of the vector to a double as an IEEE754 - * 64-bit little-endian floating point number. - */ + * Converts the 8 bytes at \a offset of the vector to a double as an IEEE754 64-bit little-endian floating point number. + */ double toFloat64LE(size_t offset) const; /* - * Converts the 8 bytes at \a offset of the vector to a double as an IEEE754 - * 64-bit big-endian floating point number. - */ + * Converts the 8 bytes at \a offset of the vector to a double as an IEEE754 64-bit big-endian floating point number. + */ double toFloat64BE(size_t offset) const; /* - * Converts the 10 bytes at \a offset of the vector to a long double as an - * IEEE754 80-bit little-endian floating point number. - * - * \note This may compromise the precision depends on the size of long double. - */ + * Converts the 10 bytes at \a offset of the vector to a long double as an IEEE754 80-bit little-endian floating point number. + * + * \note This may compromise the precision depends on the size of long double. + */ long double toFloat80LE(size_t offset) const; /* - * Converts the 10 bytes at \a offset of the vector to a long double as an - * IEEE754 80-bit big-endian floating point number. - * - * \note This may compromise the precision depends on the size of long double. - */ + * Converts the 10 bytes at \a offset of the vector to a long double as an IEEE754 80-bit big-endian floating point number. + * + * \note This may compromise the precision depends on the size of long double. + */ long double toFloat80BE(size_t offset) const; /*! - * Creates a 4 byte ByteVector based on \a value. If - * \a mostSignificantByteFirst is true, then this will operate left to right - * in building the ByteVector. For example if \a mostSignificantByteFirst is - * true then $00 00 00 01 == 0x00000001 == 1, if false, $01 00 00 00 == - * 0x01000000 == 1. - * - * \see toUInt() - */ + * Creates a 4 byte ByteVector based on \a value. + * If \a mostSignificantByteFirst is true, then this will operate left to right + * in building the ByteVector. + * For example if \a mostSignificantByteFirst is true then $00 00 00 01 == 0x00000001 == 1, if false, $01 00 00 00 == 0x01000000 == 1. + * + * \see toUInt() + */ static ByteVector fromUInt(unsigned int value, bool mostSignificantByteFirst = true); /*! - * Creates a 2 byte ByteVector based on \a value. If - * \a mostSignificantByteFirst is true, then this will operate left to right - * in building the ByteVector. For example if \a mostSignificantByteFirst is - * true then $00 01 == 0x0001 == 1, if false, $01 00 == 0x0100 == 1. - * - * \see toShort() - */ + * Creates a 2 byte ByteVector based on \a value. + * If \a mostSignificantByteFirst is true, then this will operate left to right in building the ByteVector. + * For example if \a mostSignificantByteFirst is true then $00 01 == 0x0001 == 1, if false, $01 00 == 0x0100 == 1. + * + * \see toShort() + */ static ByteVector fromShort(short value, bool mostSignificantByteFirst = true); /*! - * Creates a 8 byte ByteVector based on \a value. If - * \a mostSignificantByteFirst is true, then this will operate left to right - * in building the ByteVector. For example if \a mostSignificantByteFirst is - * true then $00 00 00 01 == 0x0000000000000001 == 1, if false, - * $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. - * - * \see toLongLong() - */ + * Creates a 8 byte ByteVector based on \a value. + * If \a mostSignificantByteFirst is true, then this will operate left to right in building the ByteVector. + * For example if \a mostSignificantByteFirst is true then $00 00 00 01 == 0x0000000000000001 == 1, + * if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see toLongLong() + */ static ByteVector fromLongLong(long long value, bool mostSignificantByteFirst = true); /*! - * Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit - * little-endian floating point number. - * - * \see fromFloat32BE() - */ + * Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit little-endian floating point number. + * + * \see fromFloat32BE() + */ static ByteVector fromFloat32LE(float value); /*! - * Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit - * big-endian floating point number. - * - * \see fromFloat32LE() - */ + * Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit big-endian floating point number. + * + * \see fromFloat32LE() + */ static ByteVector fromFloat32BE(float value); /*! - * Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit - * little-endian floating point number. - * - * \see fromFloat64BE() - */ + * Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit little-endian floating point number. + * + * \see fromFloat64BE() + */ static ByteVector fromFloat64LE(double value); /*! - * Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit - * big-endian floating point number. - * - * \see fromFloat64LE() - */ + * Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit big-endian floating point number. + * + * \see fromFloat64LE() + */ static ByteVector fromFloat64BE(double value); /*! - * Returns a ByteVector based on the CString \a s. - */ + * Returns a ByteVector based on the CString \a s. + */ static ByteVector fromCString(const char *s, unsigned int length = 0xffffffff); /*! - * Returns a const reference to the byte at \a index. - */ + * Returns a const reference to the byte at \a index. + */ const char &operator[](int index) const; /*! - * Returns a reference to the byte at \a index. - */ + * Returns a reference to the byte at \a index. + */ char &operator[](int index); /*! - * Returns true if this ByteVector and \a v are equal. - */ + * Returns true if this ByteVector and \a v are equal. + */ bool operator==(const ByteVector &v) const; /*! - * Returns true if this ByteVector and \a v are not equal. - */ + * Returns true if this ByteVector and \a v are not equal. + */ bool operator!=(const ByteVector &v) const; /*! - * Returns true if this ByteVector and the null terminated C string \a s - * contain the same data. - */ + * Returns true if this ByteVector and the null terminated C string \a s contain the same data. + */ bool operator==(const char *s) const; /*! - * Returns true if this ByteVector and the null terminated C string \a s - * do not contain the same data. - */ + * Returns true if this ByteVector and the null terminated C string \a s do not contain the same data. + */ bool operator!=(const char *s) const; /*! - * Returns true if this ByteVector is less than \a v. The value of the - * vectors is determined by evaluating the character from left to right, and - * in the event one vector is a superset of the other, the size is used. - */ + * Returns true if this ByteVector is less than \a v. + * The value of the vectors is determined by evaluating the character from left to right, + * and in the event one vector is a superset of the other, the size is used. + */ bool operator<(const ByteVector &v) const; /*! - * Returns true if this ByteVector is greater than \a v. - */ + * Returns true if this ByteVector is greater than \a v. + */ bool operator>(const ByteVector &v) const; /*! - * Returns a vector that is \a v appended to this vector. - */ + * Returns a vector that is \a v appended to this vector. + */ ByteVector operator+(const ByteVector &v) const; /*! - * Copies ByteVector \a v. - */ + * Copies ByteVector \a v. + */ ByteVector &operator=(const ByteVector &v); /*! - * Copies a byte \a c. - */ + * Copies a byte \a c. + */ ByteVector &operator=(char c); /*! - * Copies \a data up to the first null byte. - * - * \warning The behavior is undefined if \a data is not null terminated. - */ + * Copies \a data up to the first null byte. + * + * \warning The behavior is undefined if \a data is not null terminated. + */ ByteVector &operator=(const char *data); /*! - * Exchanges the content of the ByteVector by the content of \a v. - */ + * Exchanges the content of the ByteVector by the content of \a v. + */ void swap(ByteVector &v); /*! - * A static, empty ByteVector which is convenient and fast (since returning - * an empty or "null" value does not require instantiating a new ByteVector). - * - * \warning Do not modify this variable. It will mess up the internal state - * of TagLib. - * - * \deprecated - */ + * A static, empty ByteVector which is convenient and fast (since returning an empty or "null" value does not require instantiating a new ByteVector). + * + * \warning Do not modify this variable. It will mess up the internal state + * of TagLib. + * + * \deprecated + */ // BIC: remove static ByteVector null; /*! - * Returns a hex-encoded copy of the byte vector. - */ + * Returns a hex-encoded copy of the byte vector. + */ ByteVector toHex() const; /*! - * Returns a base64 encoded copy of the byte vector - */ + * Returns a base64 encoded copy of the byte vector + */ ByteVector toBase64() const; /*! - * Decodes the base64 encoded byte vector. - */ + * Decodes the base64 encoded byte vector. + */ static ByteVector fromBase64(const ByteVector &); protected: /* - * If this ByteVector is being shared via implicit sharing, do a deep copy - * of the data and separate from the shared members. This should be called - * by all non-const subclass members. - */ + * If this ByteVector is being shared via implicit sharing, do a deep copy of the data and separate from the shared members. + * This should be called by all non-const subclass members. + */ void detach(); private: diff --git a/3rdparty/taglib/toolkit/tbytevectorlist.cpp b/3rdparty/taglib/toolkit/tbytevectorlist.cpp index 3b9ce0381..a282f0763 100644 --- a/3rdparty/taglib/toolkit/tbytevectorlist.cpp +++ b/3rdparty/taglib/toolkit/tbytevectorlist.cpp @@ -27,26 +27,18 @@ using namespace Strawberry_TagLib::TagLib; -class ByteVectorListPrivate { -}; +class ByteVectorListPrivate {}; //////////////////////////////////////////////////////////////////////////////// // static members //////////////////////////////////////////////////////////////////////////////// -ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern, - int byteAlign) { - return split(v, pattern, byteAlign, 0); -} +ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern, int byteAlign, int max) { -ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern, - int byteAlign, int max) { ByteVectorList l; unsigned int previousOffset = 0; - for (int offset = v.find(pattern, 0, byteAlign); - offset != -1 && (max == 0 || max > int(l.size()) + 1); - offset = v.find(pattern, offset + pattern.size(), byteAlign)) { + for (int offset = v.find(pattern, 0, byteAlign); offset != -1 && (max == 0 || max > int(l.size()) + 1); offset = v.find(pattern, offset + pattern.size(), byteAlign)) { if (offset - previousOffset >= 1) l.append(v.mid(previousOffset, offset - previousOffset)); else @@ -59,20 +51,19 @@ ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &patt l.append(v.mid(previousOffset, v.size() - previousOffset)); return l; + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -ByteVectorList::ByteVectorList() : List(), - d(nullptr) { -} +ByteVectorList::ByteVectorList() : List(), d(nullptr) {} -ByteVectorList::~ByteVectorList() { -} +ByteVectorList::~ByteVectorList() {} ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const { + ByteVector v; ConstIterator it = begin(); @@ -80,9 +71,9 @@ ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const { while (it != end()) { v.append(*it); it++; - if (it != end()) - v.append(separator); + if (it != end()) v.append(separator); } return v; + } diff --git a/3rdparty/taglib/toolkit/tbytevectorlist.h b/3rdparty/taglib/toolkit/tbytevectorlist.h index 68c1f89ce..456c80717 100644 --- a/3rdparty/taglib/toolkit/tbytevectorlist.h +++ b/3rdparty/taglib/toolkit/tbytevectorlist.h @@ -36,43 +36,34 @@ namespace TagLib { //! A list of ByteVectors /*! - * A List specialization with some handy features useful for ByteVectors. - */ + * A List specialization with some handy features useful for ByteVectors. + */ class TAGLIB_EXPORT ByteVectorList : public List { public: /*! - * Construct an empty ByteVectorList. - */ + * Construct an empty ByteVectorList. + */ ByteVectorList(); /*! - * Destroys this ByteVectorList instance. - */ + * Destroys this ByteVectorList instance. + */ virtual ~ByteVectorList(); /*! - * Convert the ByteVectorList to a ByteVector separated by \a separator. By - * default a space is used. - */ + * Convert the ByteVectorList to a ByteVector separated by \a separator. By default a space is used. + */ ByteVector toByteVector(const ByteVector &separator = " ") const; /*! - * Splits the ByteVector \a v into several strings at \a pattern. This will - * not include the pattern in the returned ByteVectors. - */ - static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, - int byteAlign = 1); - /*! - * Splits the ByteVector \a v into several strings at \a pattern. This will - * not include the pattern in the returned ByteVectors. \a max is the - * maximum number of entries that will be separated. If \a max for instance - * is 2 then a maximum of 1 match will be found and the vector will be split - * on that match. - */ - // BIC: merge with the function above - static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, - int byteAlign, int max); + * Splits the ByteVector \a v into several strings at \a pattern. + * This will not include the pattern in the returned ByteVectors. + * \a max is the maximum number of entries that will be separated. + * If \a max for instance is 2 then a maximum of 1 match will be found and the vector will be split on that match. + */ + + static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, int byteAlign = 1, int max = 0); private: class ByteVectorListPrivate; diff --git a/3rdparty/taglib/toolkit/tbytevectorstream.cpp b/3rdparty/taglib/toolkit/tbytevectorstream.cpp index 03d7b919a..b2f512612 100644 --- a/3rdparty/taglib/toolkit/tbytevectorstream.cpp +++ b/3rdparty/taglib/toolkit/tbytevectorstream.cpp @@ -42,16 +42,13 @@ class ByteVectorStream::ByteVectorStreamPrivate { long position; }; -ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &_data) : data(_data), - position(0) { -} +ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &_data) : data(_data), position(0) {} //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -ByteVectorStream::ByteVectorStream(const ByteVector &data) : d(new ByteVectorStreamPrivate(data)) { -} +ByteVectorStream::ByteVectorStream(const ByteVector &data) : d(new ByteVectorStreamPrivate(data)) {} ByteVectorStream::~ByteVectorStream() { delete d; @@ -62,24 +59,29 @@ FileName ByteVectorStream::name() const { } ByteVector ByteVectorStream::readBlock(unsigned long length) { + if (length == 0) return ByteVector(); ByteVector v = d->data.mid(d->position, length); d->position += v.size(); return v; + } void ByteVectorStream::writeBlock(const ByteVector &data) { + unsigned int size = data.size(); if (long(d->position + size) > length()) { truncate(d->position + size); } memcpy(d->data.data() + d->position, data.data(), size); d->position += size; + } void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsigned long replace) { + long sizeDiff = data.size() - replace; if (sizeDiff < 0) { removeBlock(start + data.size(), -sizeDiff); @@ -92,9 +94,11 @@ void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsig } seek(start); writeBlock(data); + } void ByteVectorStream::removeBlock(unsigned long start, unsigned long length) { + unsigned long readPosition = start + length; unsigned long writePosition = start; if (readPosition < static_cast(ByteVectorStream::length())) { @@ -104,6 +108,7 @@ void ByteVectorStream::removeBlock(unsigned long start, unsigned long length) { } d->position = writePosition; truncate(writePosition); + } bool ByteVectorStream::readOnly() const { @@ -115,6 +120,7 @@ bool ByteVectorStream::isOpen() const { } void ByteVectorStream::seek(long offset, Position p) { + switch (p) { case Beginning: d->position = offset; @@ -126,10 +132,10 @@ void ByteVectorStream::seek(long offset, Position p) { d->position = length() + offset; // offset is expected to be negative break; } + } -void ByteVectorStream::clear() { -} +void ByteVectorStream::clear() {} long ByteVectorStream::tell() const { return d->position; diff --git a/3rdparty/taglib/toolkit/tbytevectorstream.h b/3rdparty/taglib/toolkit/tbytevectorstream.h index 0dba6b95f..dc2e4fece 100644 --- a/3rdparty/taglib/toolkit/tbytevectorstream.h +++ b/3rdparty/taglib/toolkit/tbytevectorstream.h @@ -43,92 +43,84 @@ class AudioProperties; class TAGLIB_EXPORT ByteVectorStream : public IOStream { public: /*! - * Construct a File object and opens the \a file. \a file should be a - * be a C-string in the local file system encoding. - */ + * Construct a File object and opens the \a file. \a file should be a be a C-string in the local file system encoding. + */ ByteVectorStream(const ByteVector &data); /*! - * Destroys this ByteVectorStream instance. - */ + * Destroys this ByteVectorStream instance. + */ virtual ~ByteVectorStream(); /*! - * Returns the file name in the local file system encoding. - */ + * Returns the file name in the local file system encoding. + */ FileName name() const; /*! - * Reads a block of size \a length at the current get pointer. - */ + * Reads a block of size \a length at the current get pointer. + */ ByteVector readBlock(unsigned long length); /*! - * Attempts to write the block \a data at the current get pointer. If the - * file is currently only opened read only -- i.e. readOnly() returns true -- - * this attempts to reopen the file in read/write mode. - * - * \note This should be used instead of using the streaming output operator - * for a ByteVector. And even this function is significantly slower than - * doing output with a char[]. - */ + * Attempts to write the block \a data at the current get pointer. + * If the file is currently only opened read only -- i.e. readOnly() returns true -- this attempts to reopen the file in read/write mode. + * + * \note This should be used instead of using the streaming output operator for a ByteVector. + * And even this function is significantly slower than doing output with a char[]. + */ void writeBlock(const ByteVector &data); /*! - * Insert \a data at position \a start in the file overwriting \a replace - * bytes of the original content. - * - * \note This method is slow since it requires rewriting all of the file - * after the insertion point. - */ + * Insert \a data at position \a start in the file overwriting \a replace bytes of the original content. + * + * \note This method is slow since it requires rewriting all of the file after the insertion point. + */ void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0); /*! - * Removes a block of the file starting a \a start and continuing for - * \a length bytes. - * - * \note This method is slow since it involves rewriting all of the file - * after the removed portion. - */ + * Removes a block of the file starting a \a start and continuing for \a length bytes. + * + * \note This method is slow since it involves rewriting all of the file after the removed portion. + */ void removeBlock(unsigned long start = 0, unsigned long length = 0); /*! - * Returns true if the file is read only (or if the file can not be opened). - */ + * Returns true if the file is read only (or if the file can not be opened). + */ bool readOnly() const; /*! - * Since the file can currently only be opened as an argument to the - * constructor (sort-of by design), this returns if that open succeeded. - */ + * Since the file can currently only be opened as an argument to the constructor (sort-of by design), this returns if that open succeeded. + */ bool isOpen() const; /*! - * Move the I/O pointer to \a offset in the file from position \a p. This - * defaults to seeking from the beginning of the file. - * - * \see Position - */ + * Move the I/O pointer to \a offset in the file from position \a p. + * This defaults to seeking from the beginning of the file. + * + * \see Position + */ void seek(long offset, Position p = Beginning); /*! - * Reset the end-of-file and error flags on the file. - */ + * Reset the end-of-file and error flags on the file. + */ void clear(); /*! - * Returns the current offset within the file. - */ + * Returns the current offset within the file. + */ long tell() const; /*! - * Returns the length of the file. - */ + * Returns the length of the file. + */ long length(); /*! - * Truncates the file to a \a length. - */ + * Truncates the file to a \a length. + */ void truncate(long length); ByteVector *data(); diff --git a/3rdparty/taglib/toolkit/tdebug.cpp b/3rdparty/taglib/toolkit/tdebug.cpp index 751689576..e17f8ccf0 100644 --- a/3rdparty/taglib/toolkit/tdebug.cpp +++ b/3rdparty/taglib/toolkit/tdebug.cpp @@ -48,6 +48,7 @@ void debug(const String &s) { } void debugData(const ByteVector &v) { + for (unsigned int i = 0; i < v.size(); ++i) { const std::string bits = std::bitset<8>(v[i]).to_string(); const String msg = Utils::formatString( @@ -56,6 +57,7 @@ void debugData(const ByteVector &v) { debugListener->printMessage(msg); } + } } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/toolkit/tdebuglistener.cpp b/3rdparty/taglib/toolkit/tdebuglistener.cpp index cb90c8d64..8b2af117c 100644 --- a/3rdparty/taglib/toolkit/tdebuglistener.cpp +++ b/3rdparty/taglib/toolkit/tdebuglistener.cpp @@ -64,17 +64,17 @@ namespace Strawberry_TagLib { namespace TagLib { DebugListener *debugListener = &defaultListener; -DebugListener::DebugListener() { -} +DebugListener::DebugListener() {} -DebugListener::~DebugListener() { -} +DebugListener::~DebugListener() {} void setDebugListener(DebugListener *listener) { + if (listener) debugListener = listener; else debugListener = &defaultListener; + } } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/toolkit/tdebuglistener.h b/3rdparty/taglib/toolkit/tdebuglistener.h index a7e2b19cf..362293c3f 100644 --- a/3rdparty/taglib/toolkit/tdebuglistener.h +++ b/3rdparty/taglib/toolkit/tdebuglistener.h @@ -34,21 +34,21 @@ namespace TagLib { //! An abstraction for the listener to the debug messages. /*! - * This class enables you to handle the debug messages in your preferred - * way by subclassing this class, reimplementing printMessage() and setting - * your reimplementation as the default with setDebugListener(). - * - * \see setDebugListener() - */ + * This class enables you to handle the debug messages in your preferred + * way by subclassing this class, reimplementing printMessage() and setting + * your reimplementation as the default with setDebugListener(). + * + * \see setDebugListener() + */ class TAGLIB_EXPORT DebugListener { public: DebugListener(); virtual ~DebugListener(); /*! - * When overridden in a derived class, redirects \a msg to your preferred - * channel such as stderr, Windows debugger or so forth. - */ + * When overridden in a derived class, redirects \a msg to your preferred + * channel such as stderr, Windows debugger or so forth. + */ virtual void printMessage(const String &msg) = 0; private: @@ -58,15 +58,13 @@ class TAGLIB_EXPORT DebugListener { }; /*! - * Sets the listener that decides how the debug messages are redirected. - * If the parameter \a listener is null, the previous listener is released - * and default stderr listener is restored. - * - * \note The caller is responsible for deleting the previous listener - * as needed after it is released. - * - * \see DebugListener - */ + * Sets the listener that decides how the debug messages are redirected. + * If the parameter \a listener is null, the previous listener is released and default stderr listener is restored. + * + * \note The caller is responsible for deleting the previous listener as needed after it is released. + * + * \see DebugListener + */ TAGLIB_EXPORT void setDebugListener(DebugListener *listener); } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/toolkit/tfile.cpp b/3rdparty/taglib/toolkit/tfile.cpp index d4ae28d44..8aad965ac 100644 --- a/3rdparty/taglib/toolkit/tfile.cpp +++ b/3rdparty/taglib/toolkit/tfile.cpp @@ -70,9 +70,7 @@ using namespace Strawberry_TagLib::TagLib; class File::FilePrivate { public: - FilePrivate(IOStream* _stream, bool _owner) : stream(_stream), - streamOwner(_owner), - valid(true) {} + FilePrivate(IOStream* _stream, bool _owner) : stream(_stream), streamOwner(_owner), valid(true) {} ~FilePrivate() { if (streamOwner) @@ -88,11 +86,9 @@ class File::FilePrivate { // public members //////////////////////////////////////////////////////////////////////////////// -File::File(const FileName fileName) : d(new FilePrivate(new FileStream(fileName), true)) { -} +File::File(const FileName fileName) : d(new FilePrivate(new FileStream(fileName), true)) {} -File::File(IOStream* stream) : d(new FilePrivate(stream, false)) { -} +File::File(IOStream* stream) : d(new FilePrivate(stream, false)) {} File::~File() { delete d; @@ -103,6 +99,7 @@ FileName File::name() const { } PropertyMap File::properties() const { + // ugly workaround until this method is virtual if (dynamic_cast(this)) return dynamic_cast(this)->properties(); @@ -145,11 +142,12 @@ PropertyMap File::properties() const { if (dynamic_cast(this)) return dynamic_cast(this)->properties(); return tag()->properties(); + } void File::removeUnsupportedProperties(const StringList& properties) { - // here we only consider those formats that could possibly contain - // unsupported properties + + // here we only consider those formats that could possibly contain unsupported properties if (dynamic_cast(this)) dynamic_cast(this)->removeUnsupportedProperties(properties); else if (dynamic_cast(this)) @@ -178,9 +176,11 @@ void File::removeUnsupportedProperties(const StringList& properties) { dynamic_cast(this)->removeUnsupportedProperties(properties); else tag()->removeUnsupportedProperties(properties); + } PropertyMap File::setProperties(const PropertyMap& properties) { + if (dynamic_cast(this)) return dynamic_cast(this)->setProperties(properties); else if (dynamic_cast(this)) @@ -223,6 +223,7 @@ PropertyMap File::setProperties(const PropertyMap& properties) { return dynamic_cast(this)->setProperties(properties); else return tag()->setProperties(properties); + } ByteVector File::readBlock(unsigned long length) { @@ -234,6 +235,7 @@ void File::writeBlock(const ByteVector& data) { } long File::find(const ByteVector& pattern, long fromOffset, const ByteVector& before) { + if (!d->stream || pattern.size() > bufferSize()) return -1; @@ -325,10 +327,12 @@ long File::find(const ByteVector& pattern, long fromOffset, const ByteVector& be seek(originalPosition); return -1; + } long File::rfind(const ByteVector& pattern, long fromOffset, const ByteVector& before) { + if (!d->stream || pattern.size() > bufferSize()) return -1; @@ -399,6 +403,7 @@ long File::rfind(const ByteVector& pattern, long fromOffset, const ByteVector& b seek(originalPosition); return -1; + } void File::insert(const ByteVector& data, unsigned long start, unsigned long replace) { @@ -441,32 +446,6 @@ long File::length() { return d->stream->length(); } -bool File::isReadable(const char* file) { - -#if defined(_MSC_VER) && (_MSC_VER >= 1400) // VC++2005 or later - - return _access_s(file, R_OK) == 0; - -#else - - return access(file, R_OK) == 0; - -#endif -} - -bool File::isWritable(const char* file) { - -#if defined(_MSC_VER) && (_MSC_VER >= 1400) // VC++2005 or later - - return _access_s(file, W_OK) == 0; - -#else - - return access(file, W_OK) == 0; - -#endif -} - //////////////////////////////////////////////////////////////////////////////// // protected members //////////////////////////////////////////////////////////////////////////////// diff --git a/3rdparty/taglib/toolkit/tfile.h b/3rdparty/taglib/toolkit/tfile.h index e7ea94e23..c97123552 100644 --- a/3rdparty/taglib/toolkit/tfile.h +++ b/3rdparty/taglib/toolkit/tfile.h @@ -43,16 +43,16 @@ class PropertyMap; //! A file class with some useful methods for tag manipulation /*! - * This class is a basic file class with some methods that are particularly - * useful for tag editors. It has methods to take advantage of - * ByteVector and a binary search method for finding patterns in a file. - */ + * This class is a basic file class with some methods that are particularly + * useful for tag editors. It has methods to take advantage of + * ByteVector and a binary search method for finding patterns in a file. + */ class TAGLIB_EXPORT File { public: /*! - * Position in the file used for seeking. - */ + * Position in the file used for seeking. + */ enum Position { //! Seek from the beginning of the file. Beginning, @@ -63,251 +63,220 @@ class TAGLIB_EXPORT File { }; /*! - * Specify which tags to strip either explicitly, or on save. - */ + * Specify which tags to strip either explicitly, or on save. + */ enum StripTags { StripNone, //(buffer.size()), &length, NULL)) return static_cast(length); else return 0; + } size_t writeFile(FileHandle file, const ByteVector &buffer) { + DWORD length; if (WriteFile(file, buffer.data(), static_cast(buffer.size()), &length, NULL)) return static_cast(length); else return 0; + } #else // _WIN32 @@ -89,7 +94,7 @@ struct FileNameHandle : public std::string { typedef FILE *FileHandle; -const FileHandle InvalidFileHandle = 0; +const FileHandle InvalidFileHandle = nullptr; FileHandle openFile(const FileName &path, bool readOnly) { return fopen(path, readOnly ? "rb" : "rb+"); @@ -131,6 +136,7 @@ class FileStream::FileStreamPrivate { FileStream::FileStream(FileName fileName, bool openReadOnly) : d(new FileStreamPrivate(fileName)) { + // First try with read / write mode, if that fails, fall back to read only. if (!openReadOnly) @@ -147,10 +153,11 @@ FileStream::FileStream(FileName fileName, bool openReadOnly) #else debug("Could not open file " + String(static_cast(d->name))); #endif + } -FileStream::FileStream(int fileDescriptor, bool openReadOnly) - : d(new FileStreamPrivate("")) { +FileStream::FileStream(int fileDescriptor, bool openReadOnly) : d(new FileStreamPrivate("")) { + // First try with read / write mode, if that fails, fall back to read only. if (!openReadOnly) @@ -163,13 +170,16 @@ FileStream::FileStream(int fileDescriptor, bool openReadOnly) if (d->file == InvalidFileHandle) debug("Could not open file using file descriptor"); + } FileStream::~FileStream() { + if (isOpen()) closeFile(d->file); delete d; + } FileName FileStream::name() const { @@ -177,6 +187,7 @@ FileName FileStream::name() const { } ByteVector FileStream::readBlock(unsigned long length) { + if (!isOpen()) { debug("FileStream::readBlock() -- invalid file."); return ByteVector(); @@ -195,9 +206,11 @@ ByteVector FileStream::readBlock(unsigned long length) { buffer.resize(static_cast(count)); return buffer; + } void FileStream::writeBlock(const ByteVector &data) { + if (!isOpen()) { debug("FileStream::writeBlock() -- invalid file."); return; @@ -209,9 +222,11 @@ void FileStream::writeBlock(const ByteVector &data) { } writeFile(d->file, data); + } void FileStream::insert(const ByteVector &data, unsigned long start, unsigned long replace) { + if (!isOpen()) { debug("FileStream::insert() -- invalid file."); return; @@ -289,9 +304,11 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo buffer = aboutToOverwrite; } + } void FileStream::removeBlock(unsigned long start, unsigned long length) { + if (!isOpen()) { debug("FileStream::removeBlock() -- invalid file."); return; @@ -324,6 +341,7 @@ void FileStream::removeBlock(unsigned long start, unsigned long length) { } truncate(writePosition); + } bool FileStream::readOnly() const { @@ -335,6 +353,7 @@ bool FileStream::isOpen() const { } void FileStream::seek(long offset, Position p) { + if (!isOpen()) { debug("FileStream::seek() -- invalid file."); return; @@ -375,6 +394,7 @@ void FileStream::seek(long offset, Position p) { fseek(d->file, offset, whence); #endif + } void FileStream::clear() { @@ -412,6 +432,7 @@ long FileStream::tell() const { } long FileStream::length() { + if (!isOpen()) { debug("FileStream::length() -- invalid file."); return 0; diff --git a/3rdparty/taglib/toolkit/tfilestream.h b/3rdparty/taglib/toolkit/tfilestream.h index 3594b7cc6..a43d6716f 100644 --- a/3rdparty/taglib/toolkit/tfilestream.h +++ b/3rdparty/taglib/toolkit/tfilestream.h @@ -41,111 +41,104 @@ class AudioProperties; //! A file class with some useful methods for tag manipulation /*! - * This class is a basic file class with some methods that are particularly - * useful for tag editors. It has methods to take advantage of - * ByteVector and a binary search method for finding patterns in a file. - */ + * This class is a basic file class with some methods that are particularly useful for tag editors. + * It has methods to take advantage of ByteVector and a binary search method for finding patterns in a file. + */ class TAGLIB_EXPORT FileStream : public IOStream { public: /*! - * Construct a File object and opens the \a file. \a file should be a - * be a C-string in the local file system encoding. - */ + * Construct a File object and opens the \a file. + * \a file should be a be a C-string in the local file system encoding. + */ FileStream(FileName file, bool openReadOnly = false); /*! - * Construct a File object and opens the \a file using file descriptor. - */ + * Construct a File object and opens the \a file using file descriptor. + */ FileStream(int fileDescriptor, bool openReadOnly = false); /*! - * Destroys this FileStream instance. - */ + * Destroys this FileStream instance. + */ virtual ~FileStream(); /*! - * Returns the file name in the local file system encoding. - */ + * Returns the file name in the local file system encoding. + */ FileName name() const; /*! - * Reads a block of size \a length at the current get pointer. - */ + * Reads a block of size \a length at the current get pointer. + */ ByteVector readBlock(unsigned long length); /*! - * Attempts to write the block \a data at the current get pointer. If the - * file is currently only opened read only -- i.e. readOnly() returns true -- - * this attempts to reopen the file in read/write mode. - * - * \note This should be used instead of using the streaming output operator - * for a ByteVector. And even this function is significantly slower than - * doing output with a char[]. - */ + * Attempts to write the block \a data at the current get pointer. + * If the file is currently only opened read only -- i.e. readOnly() returns true -- this attempts to reopen the file in read/write mode. + * + * \note This should be used instead of using the streaming output operator for a ByteVector. + * And even this function is significantly slower than doing output with a char[]. + */ void writeBlock(const ByteVector &data); /*! - * Insert \a data at position \a start in the file overwriting \a replace - * bytes of the original content. - * - * \note This method is slow since it requires rewriting all of the file - * after the insertion point. - */ + * Insert \a data at position \a start in the file overwriting \a replace bytes of the original content. + * + * \note This method is slow since it requires rewriting all of the file after the insertion point. + */ void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0); /*! - * Removes a block of the file starting a \a start and continuing for - * \a length bytes. - * - * \note This method is slow since it involves rewriting all of the file - * after the removed portion. - */ + * Removes a block of the file starting a \a start and continuing for \a length bytes. + * + * \note This method is slow since it involves rewriting all of the file + * after the removed portion. + */ void removeBlock(unsigned long start = 0, unsigned long length = 0); /*! - * Returns true if the file is read only (or if the file can not be opened). - */ + * Returns true if the file is read only (or if the file can not be opened). + */ bool readOnly() const; /*! - * Since the file can currently only be opened as an argument to the - * constructor (sort-of by design), this returns if that open succeeded. - */ + * Since the file can currently only be opened as an argument to the constructor (sort-of by design), this returns if that open succeeded. + */ bool isOpen() const; /*! - * Move the I/O pointer to \a offset in the file from position \a p. This - * defaults to seeking from the beginning of the file. - * - * \see Position - */ + * Move the I/O pointer to \a offset in the file from position \a p. + * This defaults to seeking from the beginning of the file. + * + * \see Position + */ void seek(long offset, Position p = Beginning); /*! - * Reset the end-of-file and error flags on the file. - */ + * Reset the end-of-file and error flags on the file. + */ void clear(); /*! - * Returns the current offset within the file. - */ + * Returns the current offset within the file. + */ long tell() const; /*! - * Returns the length of the file. - */ + * Returns the length of the file. + */ long length(); /*! - * Truncates the file to a \a length. - */ + * Truncates the file to a \a length. + */ void truncate(long length); protected: /*! - * Returns the buffer size that is used for internal buffering. - */ + * Returns the buffer size that is used for internal buffering. + */ static unsigned int bufferSize(); private: diff --git a/3rdparty/taglib/toolkit/tiostream.cpp b/3rdparty/taglib/toolkit/tiostream.cpp index 67bcfdad9..f8b40a006 100644 --- a/3rdparty/taglib/toolkit/tiostream.cpp +++ b/3rdparty/taglib/toolkit/tiostream.cpp @@ -36,6 +36,7 @@ using namespace Strawberry_TagLib::TagLib; namespace { std::wstring ansiToUnicode(const char *str) { + const int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); if (len == 0) return std::wstring(); @@ -44,22 +45,17 @@ std::wstring ansiToUnicode(const char *str) { MultiByteToWideChar(CP_ACP, 0, str, -1, &wstr[0], len); return wstr; + } } // namespace // m_name is no longer used, but kept for backward compatibility. -FileName::FileName(const wchar_t *name) : m_name(), - m_wname(name) { -} +FileName::FileName(const wchar_t *name) : m_name(), m_wname(name) {} -FileName::FileName(const char *name) : m_name(), - m_wname(ansiToUnicode(name)) { -} +FileName::FileName(const char *name) : m_name(), m_wname(ansiToUnicode(name)) {} -FileName::FileName(const FileName &name) : m_name(), - m_wname(name.m_wname) { -} +FileName::FileName(const FileName &name) : m_name(), m_wname(name.m_wname) {} FileName::operator const wchar_t *() const { return m_wname.c_str(); @@ -87,11 +83,8 @@ String FileName::toString() const { // public members //////////////////////////////////////////////////////////////////////////////// -IOStream::IOStream() { -} +IOStream::IOStream() {} -IOStream::~IOStream() { -} +IOStream::~IOStream() {} -void IOStream::clear() { -} +void IOStream::clear() {} diff --git a/3rdparty/taglib/toolkit/tiostream.h b/3rdparty/taglib/toolkit/tiostream.h index 83846ccd0..1027bed24 100644 --- a/3rdparty/taglib/toolkit/tiostream.h +++ b/3rdparty/taglib/toolkit/tiostream.h @@ -62,8 +62,8 @@ typedef const char *FileName; class TAGLIB_EXPORT IOStream { public: /*! - * Position in the file used for seeking. - */ + * Position in the file used for seeking. + */ enum Position { //! Seek from the beginning of the file. Beginning, @@ -76,87 +76,80 @@ class TAGLIB_EXPORT IOStream { IOStream(); /*! - * Destroys this IOStream instance. - */ + * Destroys this IOStream instance. + */ virtual ~IOStream(); /*! - * Returns the stream name in the local file system encoding. - */ + * Returns the stream name in the local file system encoding. + */ virtual FileName name() const = 0; /*! - * Reads a block of size \a length at the current get pointer. - */ + * Reads a block of size \a length at the current get pointer. + */ virtual ByteVector readBlock(unsigned long length) = 0; /*! - * Attempts to write the block \a data at the current get pointer. If the - * file is currently only opened read only -- i.e. readOnly() returns true -- - * this attempts to reopen the file in read/write mode. - * - * \note This should be used instead of using the streaming output operator - * for a ByteVector. And even this function is significantly slower than - * doing output with a char[]. - */ + * Attempts to write the block \a data at the current get pointer. + * If the file is currently only opened read only -- i.e. readOnly() returns true -- this attempts to reopen the file in read/write mode. + * + * \note This should be used instead of using the streaming output operator for a ByteVector. + * And even this function is significantly slower than doing output with a char[]. + */ virtual void writeBlock(const ByteVector &data) = 0; /*! - * Insert \a data at position \a start in the file overwriting \a replace - * bytes of the original content. - * - * \note This method is slow since it requires rewriting all of the file - * after the insertion point. - */ + * Insert \a data at position \a start in the file overwriting \a replace bytes of the original content. + * + * \note This method is slow since it requires rewriting all of the file after the insertion point. + */ virtual void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0) = 0; /*! - * Removes a block of the file starting a \a start and continuing for - * \a length bytes. - * - * \note This method is slow since it involves rewriting all of the file - * after the removed portion. - */ + * Removes a block of the file starting a \a start and continuing for \a length bytes. + * + * \note This method is slow since it involves rewriting all of the file after the removed portion. + */ virtual void removeBlock(unsigned long start = 0, unsigned long length = 0) = 0; /*! - * Returns true if the file is read only (or if the file can not be opened). - */ + * Returns true if the file is read only (or if the file can not be opened). + */ virtual bool readOnly() const = 0; /*! - * Since the file can currently only be opened as an argument to the - * constructor (sort-of by design), this returns if that open succeeded. - */ + * Since the file can currently only be opened as an argument to the constructor (sort-of by design), this returns if that open succeeded. + */ virtual bool isOpen() const = 0; /*! - * Move the I/O pointer to \a offset in the stream from position \a p. This - * defaults to seeking from the beginning of the stream. - * - * \see Position - */ + * Move the I/O pointer to \a offset in the stream from position \a p. + * This defaults to seeking from the beginning of the stream. + * + * \see Position + */ virtual void seek(long offset, Position p = Beginning) = 0; /*! - * Reset the end-of-stream and error flags on the stream. - */ + * Reset the end-of-stream and error flags on the stream. + */ virtual void clear(); /*! - * Returns the current offset within the stream. - */ + * Returns the current offset within the stream. + */ virtual long tell() const = 0; /*! - * Returns the length of the stream. - */ + * Returns the length of the stream. + */ virtual long length() = 0; /*! - * Truncates the stream to a \a length. - */ + * Truncates the stream to a \a length. + */ virtual void truncate(long length) = 0; private: diff --git a/3rdparty/taglib/toolkit/tlist.h b/3rdparty/taglib/toolkit/tlist.h index 7cfe1b514..5a4395350 100644 --- a/3rdparty/taglib/toolkit/tlist.h +++ b/3rdparty/taglib/toolkit/tlist.h @@ -36,8 +36,8 @@ namespace TagLib { //! A generic, implicitly shared list. /*! - * This is basic generic list that's somewhere between a std::list and a - * QValueList. This class is implicitly shared. For example: + * This is basic generic list that's somewhere between a std::list and a QValueList. + * This class is implicitly shared. For example: * * \code * @@ -45,10 +45,10 @@ namespace TagLib { * * \endcode * - * The above example is very cheap. This also makes lists suitable for the - * return types of functions. The above example will just copy a pointer rather - * than copying the data in the list. When your \e shared list's data changes, - * only \e then will the data be copied. + * The above example is very cheap. + * This also makes lists suitable for the return types of functions. + * The above example will just copy a pointer rather than copying the data in the list. + * When your \e shared list's data changes, only \e then will the data be copied. */ template class List { @@ -59,198 +59,185 @@ template class List { #endif /*! - * Constructs an empty list. - */ + * Constructs an empty list. + */ List(); /*! - * Make a shallow, implicitly shared, copy of \a l. Because this is - * implicitly shared, this method is lightweight and suitable for - * pass-by-value usage. - */ + * Make a shallow, implicitly shared, copy of \a l. + * Because this is implicitly shared, this method is lightweight and suitable for pass-by-value usage. + */ List(const List &l); /*! - * Destroys this List instance. If auto deletion is enabled and this list - * contains a pointer type all of the members are also deleted. - */ + * Destroys this List instance. If auto deletion is enabled and this list contains a pointer type all of the members are also deleted. + */ virtual ~List(); /*! - * Returns an STL style iterator to the beginning of the list. See - * std::list::const_iterator for the semantics. - */ + * Returns an STL style iterator to the beginning of the list. + * See std::list::const_iterator for the semantics. + */ Iterator begin(); /*! - * Returns an STL style constant iterator to the beginning of the list. See - * std::list::iterator for the semantics. - */ + * Returns an STL style constant iterator to the beginning of the list. + * See std::list::iterator for the semantics. + */ ConstIterator begin() const; /*! - * Returns an STL style iterator to the end of the list. See - * std::list::iterator for the semantics. - */ + * Returns an STL style iterator to the end of the list. + * See std::list::iterator for the semantics. + */ Iterator end(); /*! - * Returns an STL style constant iterator to the end of the list. See - * std::list::const_iterator for the semantics. - */ + * Returns an STL style constant iterator to the end of the list. + * See std::list::const_iterator for the semantics. + */ ConstIterator end() const; /*! - * Inserts a copy of \a value before \a it. - */ + * Inserts a copy of \a value before \a it. + */ Iterator insert(Iterator it, const T &value); /*! - * Inserts the \a value into the list. This assumes that the list is - * currently sorted. If \a unique is true then the value will not - * be inserted if it is already in the list. - */ + * Inserts the \a value into the list. This assumes that the list is currently sorted. + * If \a unique is true then the value will not be inserted if it is already in the list. + */ List &sortedInsert(const T &value, bool unique = false); /*! - * Appends \a item to the end of the list and returns a reference to the - * list. - */ + * Appends \a item to the end of the list and returns a reference to the list. + */ List &append(const T &item); /*! - * Appends all of the values in \a l to the end of the list and returns a - * reference to the list. - */ + * Appends all of the values in \a l to the end of the list and returns a reference to the list. + */ List &append(const List &l); /*! - * Prepends \a item to the beginning list and returns a reference to the - * list. - */ + * Prepends \a item to the beginning list and returns a reference to the list. + */ List &prepend(const T &item); /*! - * Prepends all of the items in \a l to the beginning list and returns a - * reference to the list. - */ + * Prepends all of the items in \a l to the beginning list and returns a reference to the list. + */ List &prepend(const List &l); /*! - * Clears the list. If auto deletion is enabled and this list contains a - * pointer type the members are also deleted. - * - * \see setAutoDelete() - */ + * Clears the list. If auto deletion is enabled and this list contains a pointer type the members are also deleted. + * + * \see setAutoDelete() + */ List &clear(); /*! - * Returns the number of elements in the list. - * - * \see isEmpty() - */ + * Returns the number of elements in the list. + * + * \see isEmpty() + */ unsigned int size() const; /*! - * Returns whether or not the list is empty. - * - * \see size() - */ + * Returns whether or not the list is empty. + * + * \see size() + */ bool isEmpty() const; /*! - * Find the first occurrence of \a value. - */ + * Find the first occurrence of \a value. + */ Iterator find(const T &value); /*! - * Find the first occurrence of \a value. - */ + * Find the first occurrence of \a value. + */ ConstIterator find(const T &value) const; /*! - * Returns true if the list contains \a value. - */ + * Returns true if the list contains \a value. + */ bool contains(const T &value) const; /*! - * Erase the item at \a it from the list. - */ + * Erase the item at \a it from the list. + */ Iterator erase(Iterator it); /*! - * Returns a reference to the first item in the list. - */ + * Returns a reference to the first item in the list. + */ const T &front() const; /*! - * Returns a reference to the first item in the list. - */ + * Returns a reference to the first item in the list. + */ T &front(); /*! - * Returns a reference to the last item in the list. - */ + * Returns a reference to the last item in the list. + */ const T &back() const; /*! - * Returns a reference to the last item in the list. - */ + * Returns a reference to the last item in the list. + */ T &back(); /*! - * Auto delete the members of the list when the last reference to the list - * passes out of scope. This will have no effect on lists which do not - * contain a pointer type. - * - * \note This relies on partial template instantiation -- most modern C++ - * compilers should now support this. - */ + * Auto delete the members of the list when the last reference to the list passes out of scope. + * This will have no effect on lists which do not contain a pointer type. + * + * \note This relies on partial template instantiation -- most modern C++ compilers should now support this. + */ void setAutoDelete(bool autoDelete); /*! - * Returns a reference to item \a i in the list. - * - * \warning This method is slow. Use iterators to loop through the list. - */ + * Returns a reference to item \a i in the list. + * + * \warning This method is slow. Use iterators to loop through the list. + */ T &operator[](unsigned int i); /*! - * Returns a const reference to item \a i in the list. - * - * \warning This method is slow. Use iterators to loop through the list. - */ + * Returns a const reference to item \a i in the list. + * + * \warning This method is slow. Use iterators to loop through the list. + */ const T &operator[](unsigned int i) const; /*! - * Make a shallow, implicitly shared, copy of \a l. Because this is - * implicitly shared, this method is lightweight and suitable for - * pass-by-value usage. - */ + * Make a shallow, implicitly shared, copy of \a l. + * Because this is implicitly shared, this method is lightweight and suitable for pass-by-value usage. + */ List &operator=(const List &l); /*! - * Exchanges the content of this list by the content of \a l. - */ + * Exchanges the content of this list by the content of \a l. + */ void swap(List &l); /*! - * Compares this list with \a l and returns true if all of the elements are - * the same. - */ + * Compares this list with \a l and returns true if all of the elements are the same. + */ bool operator==(const List &l) const; /*! - * Compares this list with \a l and returns true if the lists differ. - */ + * Compares this list with \a l and returns true if the lists differ. + */ bool operator!=(const List &l) const; protected: /* - * If this List is being shared via implicit sharing, do a deep copy of the - * data and separate from the shared members. This should be called by all - * non-const subclass members. - */ + * If this List is being shared via implicit sharing, do a deep copy of the data and separate from the shared members. + * This should be called by all non-const subclass members. + */ void detach(); private: @@ -263,8 +250,7 @@ template class List { } // namespace TagLib } // namespace Strawberry_TagLib -// Since GCC doesn't support the "export" keyword, we have to include the -// implementation. +// Since GCC doesn't support the "export" keyword, we have to include the implementation. #include "tlist.tcc" diff --git a/3rdparty/taglib/toolkit/tlist.tcc b/3rdparty/taglib/toolkit/tlist.tcc index 9d9d0ea72..60a81d36c 100644 --- a/3rdparty/taglib/toolkit/tlist.tcc +++ b/3rdparty/taglib/toolkit/tlist.tcc @@ -33,16 +33,14 @@ namespace TagLib { // public members //////////////////////////////////////////////////////////////////////////////// -// The functionality of List::setAutoDelete() is implemented here partial -// template specialization. This is implemented in such a way that calling -// setAutoDelete() on non-pointer types will simply have no effect. +// The functionality of List::setAutoDelete() is implemented here partial template specialization. +// This is implemented in such a way that calling setAutoDelete() on non-pointer types will simply have no effect. -// A base for the generic and specialized private class types. New -// non-templatized members should be added here. +// A base for the generic and specialized private class types. +// New non-templatized members should be added here. // BIC change to RefCounter -class ListPrivateBase : public RefCounterOld -{ +class ListPrivateBase : public RefCounterOld { public: ListPrivateBase() : autoDelete(false) {} bool autoDelete; @@ -62,8 +60,7 @@ public: std::list list; }; -// A partial specialization for all pointer types that implements the -// setAutoDelete() functionality. +// A partial specialization for all pointer types that implements the setAutoDelete() functionality. template template class List::ListPrivate : public ListPrivateBase @@ -90,60 +87,49 @@ public: //////////////////////////////////////////////////////////////////////////////// template -List::List() : - d(new ListPrivate()) -{ -} +List::List() : d(new ListPrivate()){} template -List::List(const List &l) : d(l.d) -{ +List::List(const List &l) : d(l.d) { d->ref(); } template -List::~List() -{ +List::~List() { if(d->deref()) delete d; } template -typename List::Iterator List::begin() -{ +typename List::Iterator List::begin() { detach(); return d->list.begin(); } template -typename List::ConstIterator List::begin() const -{ +typename List::ConstIterator List::begin() const { return d->list.begin(); } template -typename List::Iterator List::end() -{ +typename List::Iterator List::end() { detach(); return d->list.end(); } template -typename List::ConstIterator List::end() const -{ +typename List::ConstIterator List::end() const { return d->list.end(); } template -typename List::Iterator List::insert(Iterator it, const T &item) -{ +typename List::Iterator List::insert(Iterator it, const T &item) { detach(); return d->list.insert(it, item); } template -List &List::sortedInsert(const T &value, bool unique) -{ +List &List::sortedInsert(const T &value, bool unique) { detach(); Iterator it = begin(); while(it != end() && *it < value) @@ -155,117 +141,100 @@ List &List::sortedInsert(const T &value, bool unique) } template -List &List::append(const T &item) -{ +List &List::append(const T &item) { detach(); d->list.push_back(item); return *this; } template -List &List::append(const List &l) -{ +List &List::append(const List &l) { detach(); d->list.insert(d->list.end(), l.begin(), l.end()); return *this; } template -List &List::prepend(const T &item) -{ +List &List::prepend(const T &item) { detach(); d->list.push_front(item); return *this; } template -List &List::prepend(const List &l) -{ +List &List::prepend(const List &l) { detach(); d->list.insert(d->list.begin(), l.begin(), l.end()); return *this; } template -List &List::clear() -{ +List &List::clear() { detach(); d->clear(); return *this; } template -unsigned int List::size() const -{ +unsigned int List::size() const { return static_cast(d->list.size()); } template -bool List::isEmpty() const -{ +bool List::isEmpty() const { return d->list.empty(); } template -typename List::Iterator List::find(const T &value) -{ +typename List::Iterator List::find(const T &value) { detach(); return std::find(d->list.begin(), d->list.end(), value); } template -typename List::ConstIterator List::find(const T &value) const -{ +typename List::ConstIterator List::find(const T &value) const { return std::find(d->list.begin(), d->list.end(), value); } template -bool List::contains(const T &value) const -{ +bool List::contains(const T &value) const { return std::find(d->list.begin(), d->list.end(), value) != d->list.end(); } template -typename List::Iterator List::erase(Iterator it) -{ +typename List::Iterator List::erase(Iterator it) { return d->list.erase(it); } template -const T &List::front() const -{ +const T &List::front() const { return d->list.front(); } template -T &List::front() -{ +T &List::front() { detach(); return d->list.front(); } template -const T &List::back() const -{ +const T &List::back() const { return d->list.back(); } template -void List::setAutoDelete(bool autoDelete) -{ +void List::setAutoDelete(bool autoDelete) { d->autoDelete = autoDelete; } template -T &List::back() -{ +T &List::back() { detach(); return d->list.back(); } template -T &List::operator[](unsigned int i) -{ +T &List::operator[](unsigned int i) { Iterator it = d->list.begin(); std::advance(it, i); @@ -273,8 +242,7 @@ T &List::operator[](unsigned int i) } template -const T &List::operator[](unsigned int i) const -{ +const T &List::operator[](unsigned int i) const { ConstIterator it = d->list.begin(); std::advance(it, i); @@ -282,29 +250,25 @@ const T &List::operator[](unsigned int i) const } template -List &List::operator=(const List &l) -{ +List &List::operator=(const List &l) { List(l).swap(*this); return *this; } template -void List::swap(List &l) -{ +void List::swap(List &l) { using std::swap; swap(d, l.d); } template -bool List::operator==(const List &l) const -{ +bool List::operator==(const List &l) const { return d->list == l.d->list; } template -bool List::operator!=(const List &l) const -{ +bool List::operator!=(const List &l) const { return d->list != l.d->list; } @@ -313,8 +277,7 @@ bool List::operator!=(const List &l) const //////////////////////////////////////////////////////////////////////////////// template -void List::detach() -{ +void List::detach() { if(d->count() > 1) { d->deref(); d = new ListPrivate(d->list); diff --git a/3rdparty/taglib/toolkit/tmap.h b/3rdparty/taglib/toolkit/tmap.h index 8869d87c9..d49658a14 100644 --- a/3rdparty/taglib/toolkit/tmap.h +++ b/3rdparty/taglib/toolkit/tmap.h @@ -36,23 +36,19 @@ namespace TagLib { //! A generic, implicitly shared map. /*! - * This implements a standard map container that associates a key with a value - * and has fast key-based lookups. This map is also implicitly shared making - * it suitable for pass-by-value usage. - */ + * This implements a standard map container that associates a key with a value and has fast key-based lookups. + * This map is also implicitly shared making it suitable for pass-by-value usage. + */ template class Map { public: #ifndef DO_NOT_DOCUMENT # ifdef WANT_CLASS_INSTANTIATION_OF_MAP - // Some STL implementations get snippy over the use of the - // class keyword to distinguish different templates; Sun Studio - // in particular finds multiple specializations in certain rare - // cases and complains about that. GCC doesn't seem to mind, - // and uses the typedefs further below without the class keyword. - // Not all the specializations of Map can use the class keyword - // (when T is not actually a class type), so don't apply this - // generally. + // Some STL implementations get snippy over the use of the class keyword to distinguish different templates; Sun Studio + // in particular finds multiple specializations in certain rare cases and complains about that. + // GCC doesn't seem to mind, and uses the typedefs further below without the class keyword. + // Not all the specializations of Map can use the class keyword (when T is not actually a class type), + // so don't apply this generally. typedef typename std::map::iterator Iterator; typedef typename std::map::const_iterator ConstIterator; # else @@ -62,129 +58,126 @@ template class Map { #endif /*! - * Constructs an empty Map. - */ + * Constructs an empty Map. + */ Map(); /*! - * Make a shallow, implicitly shared, copy of \a m. Because this is - * implicitly shared, this method is lightweight and suitable for - * pass-by-value usage. - */ + * Make a shallow, implicitly shared, copy of \a m. + * Because this is implicitly shared, this method is lightweight and suitable for pass-by-value usage. + */ Map(const Map &m); /*! - * Destroys this instance of the Map. - */ + * Destroys this instance of the Map. + */ virtual ~Map(); /*! - * Returns an STL style iterator to the beginning of the map. See - * std::map::iterator for the semantics. - */ + * Returns an STL style iterator to the beginning of the map. + * See std::map::iterator for the semantics. + */ Iterator begin(); /*! - * Returns an STL style iterator to the beginning of the map. See - * std::map::const_iterator for the semantics. - */ + * Returns an STL style iterator to the beginning of the map. + * See std::map::const_iterator for the semantics. + */ ConstIterator begin() const; /*! - * Returns an STL style iterator to the end of the map. See - * std::map::iterator for the semantics. - */ + * Returns an STL style iterator to the end of the map. + * See std::map::iterator for the semantics. + */ Iterator end(); /*! - * Returns an STL style iterator to the end of the map. See - * std::map::const_iterator for the semantics. - */ + * Returns an STL style iterator to the end of the map. + * See std::map::const_iterator for the semantics. + */ ConstIterator end() const; /*! - * Inserts \a value under \a key in the map. If a value for \a key already - * exists it will be overwritten. - */ + * Inserts \a value under \a key in the map. + * If a value for \a key already exists it will be overwritten. + */ Map &insert(const Key &key, const T &value); /*! - * Removes all of the elements from elements from the map. This however - * will not delete pointers if the mapped type is a pointer type. - */ + * Removes all of the elements from elements from the map. + * This however will not delete pointers if the mapped type is a pointer type. + */ Map &clear(); /*! - * The number of elements in the map. - * - * \see isEmpty() - */ + * The number of elements in the map. + * + * \see isEmpty() + */ unsigned int size() const; /*! - * Returns true if the map is empty. - * - * \see size() - */ + * Returns true if the map is empty. + * + * \see size() + */ bool isEmpty() const; /*! - * Find the first occurrence of \a key. - */ + * Find the first occurrence of \a key. + */ Iterator find(const Key &key); /*! - * Find the first occurrence of \a key. - */ + * Find the first occurrence of \a key. + */ ConstIterator find(const Key &key) const; /*! - * Returns true if the map contains an instance of \a key. - */ + * Returns true if the map contains an instance of \a key. + */ bool contains(const Key &key) const; /*! - * Erase the item at \a it from the list. - */ + * Erase the item at \a it from the list. + */ Map &erase(Iterator it); /*! - * Erase the item with \a key from the list. - */ + * Erase the item with \a key from the list. + */ Map &erase(const Key &key); /*! - * Returns a reference to the value associated with \a key. - * - * \note This has undefined behavior if the key is not present in the map. - */ + * Returns a reference to the value associated with \a key. + * + * \note This has undefined behavior if the key is not present in the map. + */ const T &operator[](const Key &key) const; /*! - * Returns a reference to the value associated with \a key. - * - * \note This has undefined behavior if the key is not present in the map. - */ + * Returns a reference to the value associated with \a key. + * + * \note This has undefined behavior if the key is not present in the map. + */ T &operator[](const Key &key); /*! - * Make a shallow, implicitly shared, copy of \a m. Because this is - * implicitly shared, this method is lightweight and suitable for - * pass-by-value usage. - */ + * Make a shallow, implicitly shared, copy of \a m. + * Because this is implicitly shared, this method is lightweight and suitable for pass-by-value usage. + */ Map &operator=(const Map &m); /*! - * Exchanges the content of this map by the content of \a m. - */ + * Exchanges the content of this map by the content of \a m. + */ void swap(Map &m); protected: /* - * If this List is being shared via implicit sharing, do a deep copy of the - * data and separate from the shared members. This should be called by all - * non-const subclass members. - */ + * If this List is being shared via implicit sharing, do a deep copy of the data and separate from the shared members. + * This should be called by all non-const subclass members. + */ void detach(); private: @@ -197,8 +190,7 @@ template class Map { } // namespace TagLib } // namespace Strawberry_TagLib -// Since GCC doesn't support the "export" keyword, we have to include the -// implementation. +// Since GCC doesn't support the "export" keyword, we have to include the implementation. #include "tmap.tcc" diff --git a/3rdparty/taglib/toolkit/tmap.tcc b/3rdparty/taglib/toolkit/tmap.tcc index f9fe55c28..4abdc617e 100644 --- a/3rdparty/taglib/toolkit/tmap.tcc +++ b/3rdparty/taglib/toolkit/tmap.tcc @@ -35,8 +35,7 @@ namespace TagLib { // BIC change to RefCounter template template -class Map::MapPrivate : public RefCounterOld -{ +class Map::MapPrivate : public RefCounterOld { public: MapPrivate() : RefCounterOld() {} #ifdef WANT_CLASS_INSTANTIATION_OF_MAP @@ -49,136 +48,114 @@ public: }; template -Map::Map() : - d(new MapPrivate()) -{ -} +Map::Map() : d(new MapPrivate()){} template -Map::Map(const Map &m) : d(m.d) -{ +Map::Map(const Map &m) : d(m.d) { d->ref(); } template -Map::~Map() -{ +Map::~Map() { if(d->deref()) delete(d); } template -typename Map::Iterator Map::begin() -{ +typename Map::Iterator Map::begin() { detach(); return d->map.begin(); } template -typename Map::ConstIterator Map::begin() const -{ +typename Map::ConstIterator Map::begin() const { return d->map.begin(); } template -typename Map::Iterator Map::end() -{ +typename Map::Iterator Map::end() { detach(); return d->map.end(); } template -typename Map::ConstIterator Map::end() const -{ +typename Map::ConstIterator Map::end() const { return d->map.end(); } template -Map &Map::insert(const Key &key, const T &value) -{ +Map &Map::insert(const Key &key, const T &value) { detach(); d->map[key] = value; return *this; } template -Map &Map::clear() -{ +Map &Map::clear() { detach(); d->map.clear(); return *this; } template -bool Map::isEmpty() const -{ +bool Map::isEmpty() const { return d->map.empty(); } template -typename Map::Iterator Map::find(const Key &key) -{ +typename Map::Iterator Map::find(const Key &key) { detach(); return d->map.find(key); } template -typename Map::ConstIterator Map::find(const Key &key) const -{ +typename Map::ConstIterator Map::find(const Key &key) const { return d->map.find(key); } template -bool Map::contains(const Key &key) const -{ +bool Map::contains(const Key &key) const { return d->map.find(key) != d->map.end(); } template -Map &Map::erase(Iterator it) -{ +Map &Map::erase(Iterator it) { detach(); d->map.erase(it); return *this; } template -Map &Map::erase(const Key &key) -{ +Map &Map::erase(const Key &key) { detach(); d->map.erase(key); return *this; } template -unsigned int Map::size() const -{ +unsigned int Map::size() const { return static_cast(d->map.size()); } template -const T &Map::operator[](const Key &key) const -{ +const T &Map::operator[](const Key &key) const { return d->map[key]; } template -T &Map::operator[](const Key &key) -{ +T &Map::operator[](const Key &key) { detach(); return d->map[key]; } template -Map &Map::operator=(const Map &m) -{ +Map &Map::operator=(const Map &m) { Map(m).swap(*this); return *this; } template -void Map::swap(Map &m) -{ +void Map::swap(Map &m) { using std::swap; swap(d, m.d); @@ -189,8 +166,7 @@ void Map::swap(Map &m) //////////////////////////////////////////////////////////////////////////////// template -void Map::detach() -{ +void Map::detach() { if(d->count() > 1) { d->deref(); d = new MapPrivate(d->map); diff --git a/3rdparty/taglib/toolkit/tpropertymap.cpp b/3rdparty/taglib/toolkit/tpropertymap.cpp index 72c1d525f..fd5cad2b2 100644 --- a/3rdparty/taglib/toolkit/tpropertymap.cpp +++ b/3rdparty/taglib/toolkit/tpropertymap.cpp @@ -52,13 +52,16 @@ bool PropertyMap::insert(const String &key, const StringList &values) { else SimplePropertyMap::operator[](realKey).append(values); return true; + } bool PropertyMap::replace(const String &key, const StringList &values) { + String realKey = key.upper(); SimplePropertyMap::erase(realKey); SimplePropertyMap::insert(realKey, values); return true; + } PropertyMap::Iterator PropertyMap::find(const String &key) { @@ -74,13 +77,16 @@ bool PropertyMap::contains(const String &key) const { } bool PropertyMap::contains(const PropertyMap &other) const { + for (ConstIterator it = other.begin(); it != other.end(); ++it) { if (!SimplePropertyMap::contains(it->first)) return false; if ((*this)[it->first] != it->second) return false; } + return true; + } PropertyMap &PropertyMap::erase(const String &key) { @@ -95,10 +101,12 @@ PropertyMap &PropertyMap::erase(const PropertyMap &other) { } PropertyMap &PropertyMap::merge(const PropertyMap &other) { + for (PropertyMap::ConstIterator it = other.begin(); it != other.end(); ++it) insert(it->first, it->second); unsupported.append(other.unsupported); return *this; + } const StringList &PropertyMap::operator[](const String &key) const { @@ -110,6 +118,7 @@ StringList &PropertyMap::operator[](const String &key) { } bool PropertyMap::operator==(const PropertyMap &other) const { + for (ConstIterator it = other.begin(); it != other.end(); ++it) { ConstIterator thisFind = find(it->first); if (thisFind == end() || (thisFind->second != it->second)) @@ -121,6 +130,7 @@ bool PropertyMap::operator==(const PropertyMap &other) const { return false; } return unsupported == other.unsupported; + } bool PropertyMap::operator!=(const PropertyMap &other) const { @@ -128,6 +138,7 @@ bool PropertyMap::operator!=(const PropertyMap &other) const { } String PropertyMap::toString() const { + String ret; for (ConstIterator it = begin(); it != end(); ++it) @@ -135,15 +146,18 @@ String PropertyMap::toString() const { if (!unsupported.isEmpty()) ret += "Unsupported Data: " + unsupported.toString(", ") + "\n"; return ret; + } void PropertyMap::removeEmpty() { + PropertyMap m; for (ConstIterator it = begin(); it != end(); ++it) { if (!it->second.isEmpty()) m.insert(it->first, it->second); } *this = m; + } StringList &PropertyMap::unsupportedData() { diff --git a/3rdparty/taglib/toolkit/tpropertymap.h b/3rdparty/taglib/toolkit/tpropertymap.h index c3254edad..f0e590d27 100644 --- a/3rdparty/taglib/toolkit/tpropertymap.h +++ b/3rdparty/taglib/toolkit/tpropertymap.h @@ -37,74 +37,70 @@ typedef Map SimplePropertyMap; //! A map for format-independent tag representations. /*! - * This map implements a generic representation of textual audio metadata - * ("tags") realized as pairs of a case-insensitive key - * and a nonempty list of corresponding values, each value being an arbitrary - * unicode String. - * - * Note that most metadata formats pose additional conditions on the tag keys. The - * most popular ones (Vorbis, APE, ID3v2) should support all ASCII only words of - * length between 2 and 16. - * - * This class can contain any tags, but here is a list of "well-known" tags that - * you might want to use: - * - * Basic tags: - * - * - TITLE - * - ALBUM - * - ARTIST - * - ALBUMARTIST - * - SUBTITLE - * - TRACKNUMBER - * - DISCNUMBER - * - DATE - * - ORIGINALDATE - * - GENRE - * - COMMENT - * - * Sort names: - * - * - TITLESORT - * - ALBUMSORT - * - ARTISTSORT - * - ALBUMARTISTSORT - * - * Credits: - * - * - COMPOSER - * - LYRICIST - * - CONDUCTOR - * - REMIXER - * - PERFORMER: - * - * Other tags: - * - * - ISRC - * - ASIN - * - BPM - * - COPYRIGHT - * - ENCODEDBY - * - MOOD - * - COMMENT - * - MEDIA - * - LABEL - * - CATALOGNUMBER - * - BARCODE - * - * MusicBrainz identifiers: - * - * - MUSICBRAINZ_TRACKID - * - MUSICBRAINZ_ALBUMID - * - MUSICBRAINZ_RELEASEGROUPID - * - MUSICBRAINZ_WORKID - * - MUSICBRAINZ_ARTISTID - * - MUSICBRAINZ_ALBUMARTISTID - * - ACOUSTID_ID - * - ACOUSTID_FINGERPRINT - * - MUSICIP_PUID - * - */ + * This map implements a generic representation of textual audio metadata ("tags") realized as pairs of a case-insensitive key and a nonempty list of corresponding values, + * each value being an arbitrary unicode String. + * + * Note that most metadata formats pose additional conditions on the tag keys. + * The most popular ones (Vorbis, APE, ID3v2) should support all ASCII only words of length between 2 and 16. + * + * This class can contain any tags, but here is a list of "well-known" tags that you might want to use: + * + * Basic tags: + * + * - TITLE + * - ALBUM + * - ARTIST + * - ALBUMARTIST + * - SUBTITLE + * - TRACKNUMBER + * - DISCNUMBER + * - DATE + * - ORIGINALDATE + * - GENRE + * - COMMENT + * + * Sort names: + * + * - TITLESORT + * - ALBUMSORT + * - ARTISTSORT + * - ALBUMARTISTSORT + * + * Credits: + * + * - COMPOSER + * - LYRICIST + * - CONDUCTOR + * - REMIXER + * - PERFORMER: + * + * Other tags: + * + * - ISRC + * - ASIN + * - BPM + * - COPYRIGHT + * - ENCODEDBY + * - MOOD + * - COMMENT + * - MEDIA + * - LABEL + * - CATALOGNUMBER + * - BARCODE + * + * MusicBrainz identifiers: + * + * - MUSICBRAINZ_TRACKID + * - MUSICBRAINZ_ALBUMID + * - MUSICBRAINZ_RELEASEGROUPID + * - MUSICBRAINZ_WORKID + * - MUSICBRAINZ_ARTISTID + * - MUSICBRAINZ_ALBUMARTISTID + * - ACOUSTID_ID + * - ACOUSTID_FINGERPRINT + * - MUSICIP_PUID + * + */ class TAGLIB_EXPORT PropertyMap : public SimplePropertyMap { public: @@ -114,112 +110,105 @@ class TAGLIB_EXPORT PropertyMap : public SimplePropertyMap { PropertyMap(); /*! - * Creates a PropertyMap initialized from a SimplePropertyMap. Copies all - * entries from \a m that have valid keys. - * Invalid keys will be appended to the unsupportedData() list. - */ + * Creates a PropertyMap initialized from a SimplePropertyMap. + * Copies all entries from \a m that have valid keys. + * Invalid keys will be appended to the unsupportedData() list. + */ PropertyMap(const SimplePropertyMap &m); virtual ~PropertyMap(); /*! - * Inserts \a values under \a key in the map. If \a key already exists, - * then \a values will be appended to the existing StringList. - * The returned value indicates success, i.e. whether \a key is a - * valid key. - */ + * Inserts \a values under \a key in the map. + * If \a key already exists, then \a values will be appended to the existing StringList. + * The returned value indicates success, i.e. whether \a key is a valid key. + */ bool insert(const String &key, const StringList &values); /*! - * Replaces any existing values for \a key with the given \a values, - * and simply insert them if \a key did not exist before. - * The returned value indicates success, i.e. whether \a key is a - * valid key. - */ + * Replaces any existing values for \a key with the given \a values, and simply insert them if \a key did not exist before. + * The returned value indicates success, i.e. whether \a key is a valid key. + */ bool replace(const String &key, const StringList &values); /*! - * Find the first occurrence of \a key. - */ + * Find the first occurrence of \a key. + */ Iterator find(const String &key); /*! - * Find the first occurrence of \a key. - */ + * Find the first occurrence of \a key. + */ ConstIterator find(const String &key) const; /*! - * Returns true if the map contains values for \a key. - */ + * Returns true if the map contains values for \a key. + */ bool contains(const String &key) const; /*! - * Returns true if this map contains all keys of \a other - * and the values coincide for that keys. Does not take - * the unsupportedData list into account. - */ + * Returns true if this map contains all keys of \a other and the values coincide for that keys. + * Does not take the unsupportedData list into account. + */ bool contains(const PropertyMap &other) const; /*! - * Erase the \a key and its values from the map. - */ + * Erase the \a key and its values from the map. + */ PropertyMap &erase(const String &key); /*! - * Erases from this map all keys that appear in \a other. - */ + * Erases from this map all keys that appear in \a other. + */ PropertyMap &erase(const PropertyMap &other); /*! - * Merge the contents of \a other into this PropertyMap. - * If a key is contained in both maps, the values of the second - * are appended to that of the first. - * The unsupportedData() lists are concatenated as well. - */ + * Merge the contents of \a other into this PropertyMap. + * If a key is contained in both maps, the values of the second are appended to that of the first. + * The unsupportedData() lists are concatenated as well. + */ PropertyMap &merge(const PropertyMap &other); /*! - * Returns a reference to the value associated with \a key. - * - * \note: If \a key is not contained in the map, an empty - * StringList is returned without error. - */ + * Returns a reference to the value associated with \a key. + * + * \note: If \a key is not contained in the map, an empty StringList is returned without error. + */ const StringList &operator[](const String &key) const; /*! - * Returns a reference to the value associated with \a key. - * - * \note: If \a key is not contained in the map, an empty - * StringList is returned. You can also directly add entries - * by using this function as an lvalue. - */ + * Returns a reference to the value associated with \a key. + * + * \note: If \a key is not contained in the map, an empty StringList is returned. + * You can also directly add entries by using this function as an lvalue. + */ StringList &operator[](const String &key); /*! - * Returns true if and only if \other has the same contents as this map. - */ + * Returns true if and only if \other has the same contents as this map. + */ bool operator==(const PropertyMap &other) const; /*! - * Returns false if and only \other has the same contents as this map. - */ + * Returns false if and only \other has the same contents as this map. + */ bool operator!=(const PropertyMap &other) const; /*! - * If a PropertyMap is read from a File object using File::properties(), - * the StringList returned from this function will represent metadata - * that could not be parsed into the PropertyMap representation. This could - * be e.g. binary data, unknown ID3 frames, etc. - * You can remove items from the returned list, which tells TagLib to remove - * those unsupported elements if you call File::setProperties() with the - * same PropertyMap as argument. - */ + * If a PropertyMap is read from a File object using File::properties(), + * the StringList returned from this function will represent metadata + * that could not be parsed into the PropertyMap representation. + * This could be e.g. binary data, unknown ID3 frames, etc. + * You can remove items from the returned list, which tells TagLib to remove + * those unsupported elements if you call File::setProperties() with the + * same PropertyMap as argument. + */ StringList &unsupportedData(); const StringList &unsupportedData() const; /*! - * Removes all entries which have an empty value list. - */ + * Removes all entries which have an empty value list. + */ void removeEmpty(); String toString() const; diff --git a/3rdparty/taglib/toolkit/trefcounter.cpp b/3rdparty/taglib/toolkit/trefcounter.cpp index 78d50ee00..226575639 100644 --- a/3rdparty/taglib/toolkit/trefcounter.cpp +++ b/3rdparty/taglib/toolkit/trefcounter.cpp @@ -72,8 +72,7 @@ class RefCounter::RefCounterPrivate { volatile ATOMIC_INT refCount; }; -RefCounter::RefCounter() : d(new RefCounterPrivate()) { -} +RefCounter::RefCounter() : d(new RefCounterPrivate()) {} RefCounter::~RefCounter() { delete d; diff --git a/3rdparty/taglib/toolkit/tstring.cpp b/3rdparty/taglib/toolkit/tstring.cpp index c4ebbe6da..51e747219 100644 --- a/3rdparty/taglib/toolkit/tstring.cpp +++ b/3rdparty/taglib/toolkit/tstring.cpp @@ -40,34 +40,41 @@ using namespace Strawberry_TagLib::TagLib; // Returns the native format of std::wstring. String::Type wcharByteOrder() { + if (Utils::systemByteOrder() == Utils::LittleEndian) return String::UTF16LE; else return String::UTF16BE; + } // Converts a Latin-1 string into UTF-16(without BOM/CPU byte order) // and copies it to the internal buffer. void copyFromLatin1(std::wstring &data, const char *s, size_t length) { + data.resize(length); for (size_t i = 0; i < length; ++i) data[i] = static_cast(s[i]); + } // Converts a UTF-8 string into UTF-16(without BOM/CPU byte order) // and copies it to the internal buffer. void copyFromUTF8(std::wstring &data, const char *s, size_t length) { + data.resize(length); try { const std::wstring::iterator dstEnd = utf8::utf8to16(s, s + length, data.begin()); data.resize(dstEnd - data.begin()); - } catch (const utf8::exception &e) { + } + catch (const utf8::exception &e) { const String message(e.what()); debug("String::copyFromUTF8() - UTF8-CPP error: " + message); data.clear(); } + } // Helper functions to read a UTF-16 character from an array. @@ -81,6 +88,7 @@ unsigned short nextUTF16(const wchar_t **p) { template<> unsigned short nextUTF16(const char **p) { + union { unsigned short w; char c[2]; @@ -88,12 +96,14 @@ unsigned short nextUTF16(const char **p) { u.c[0] = *(*p)++; u.c[1] = *(*p)++; return u.w; + } // Converts a UTF-16 (with BOM), UTF-16LE or UTF16-BE string into // UTF-16(without BOM/CPU byte order) and copies it to the internal buffer. template void copyFromUTF16(std::wstring &data, const T *s, size_t length, String::Type t) { + bool swap; if (t == String::UTF16) { if (length < 1) { @@ -125,7 +135,9 @@ void copyFromUTF16(std::wstring &data, const T *s, size_t length, String::Type t else data[i] = c; } + } + } // namespace namespace Strawberry_TagLib { @@ -160,16 +172,19 @@ String::String(const String &s) : d(s.d) { } String::String(const std::string &s, Type t) : d(new StringPrivate()) { + if (t == Latin1) copyFromLatin1(d->data, s.c_str(), s.length()); else if (t == String::UTF8) copyFromUTF8(d->data, s.c_str(), s.length()); else { debug("String::String() -- std::string should not contain UTF16."); + } } String::String(const wstring &s, Type t) : d(new StringPrivate()) { + if (t == UTF16 || t == UTF16BE || t == UTF16LE) { // This looks ugly but needed for the compatibility with TagLib1.8. // Should be removed in TabLib2.0. @@ -183,9 +198,11 @@ String::String(const wstring &s, Type t) : d(new StringPrivate()) { else { debug("String::String() -- TagLib::wstring should not contain Latin1 or UTF-8."); } + } String::String(const wchar_t *s, Type t) : d(new StringPrivate()) { + if (t == UTF16 || t == UTF16BE || t == UTF16LE) { // This looks ugly but needed for the compatibility with TagLib1.8. // Should be removed in TabLib2.0. @@ -199,9 +216,11 @@ String::String(const wchar_t *s, Type t) : d(new StringPrivate()) { else { debug("String::String() -- const wchar_t * should not contain Latin1 or UTF-8."); } + } String::String(const char *s, Type t) : d(new StringPrivate()) { + if (t == Latin1) copyFromLatin1(d->data, s, ::strlen(s)); else if (t == String::UTF8) @@ -209,17 +228,21 @@ String::String(const char *s, Type t) : d(new StringPrivate()) { else { debug("String::String() -- const char * should not contain UTF16."); } + } String::String(wchar_t c, Type t) : d(new StringPrivate()) { + if (t == UTF16 || t == UTF16BE || t == UTF16LE) copyFromUTF16(d->data, &c, 1, t); else { debug("String::String() -- wchar_t should not contain Latin1 or UTF-8."); } + } String::String(char c, Type t) : d(new StringPrivate()) { + if (t == Latin1) copyFromLatin1(d->data, &c, 1); else if (t == String::UTF8) @@ -227,9 +250,11 @@ String::String(char c, Type t) : d(new StringPrivate()) { else { debug("String::String() -- char should not contain UTF16."); } + } String::String(const ByteVector &v, Type t) : d(new StringPrivate()) { + if (v.isEmpty()) return; @@ -242,6 +267,7 @@ String::String(const ByteVector &v, Type t) : d(new StringPrivate()) { // If we hit a null in the ByteVector, shrink the string again. d->data.resize(::wcslen(d->data.c_str())); + } //////////////////////////////////////////////////////////////////////////////// @@ -252,8 +278,10 @@ String::~String() { } std::string String::to8Bit(bool unicode) const { + const ByteVector v = data(unicode ? UTF8 : Latin1); return std::string(v.data(), v.size()); + } Strawberry_TagLib::TagLib::wstring String::toWString() const { @@ -296,6 +324,7 @@ int String::rfind(const String &s, int offset) const { } StringList String::split(const String &separator) const { + StringList list; for (int index = 0;;) { int sep = find(separator, index); @@ -309,6 +338,7 @@ StringList String::split(const String &separator) const { } } return list; + } bool String::startsWith(const String &s) const { @@ -319,24 +349,31 @@ bool String::startsWith(const String &s) const { } String String::substr(unsigned int position, unsigned int n) const { + if (position == 0 && n >= size()) return *this; else return String(d->data.substr(position, n)); + } String &String::append(const String &s) { + detach(); d->data += s.d->data; return *this; + } String &String::clear() { + *this = String(); return *this; + } String String::upper() const { + String s; s.d->data.reserve(size()); @@ -348,6 +385,7 @@ String String::upper() const { } return s; + } unsigned int String::size() const { @@ -367,6 +405,7 @@ bool String::isNull() const { } ByteVector String::data(Type t) const { + switch (t) { case Latin1: { ByteVector v(size(), 0); @@ -434,13 +473,15 @@ ByteVector String::data(Type t) const { return ByteVector(); } } + } int String::toInt() const { - return toInt(0); + return toInt(nullptr); } int String::toInt(bool *ok) const { + const wchar_t *begin = d->data.c_str(); wchar_t *end; errno = 0; @@ -453,9 +494,11 @@ int String::toInt(bool *ok) const { } return static_cast(value); + } String String::stripWhiteSpace() const { + static const wchar_t *WhiteSpaceChars = L"\t\n\f\r "; const size_t pos1 = d->data.find_first_not_of(WhiteSpaceChars); @@ -464,26 +507,30 @@ String String::stripWhiteSpace() const { const size_t pos2 = d->data.find_last_not_of(WhiteSpaceChars); return substr(static_cast(pos1), static_cast(pos2 - pos1 + 1)); + } bool String::isLatin1() const { + for (ConstIterator it = begin(); it != end(); ++it) { if (*it >= 256) return false; } return true; + } bool String::isAscii() const { + for (ConstIterator it = begin(); it != end(); ++it) { if (*it >= 128) return false; } return true; + } -String String::number(int n) // static -{ +String String::number(int n) { // static return Utils::formatString("%d", n); } @@ -505,6 +552,7 @@ bool String::operator!=(const String &s) const { } bool String::operator==(const char *s) const { + const wchar_t *p = toCWString(); while (*p != L'\0' || *s != '\0') { @@ -512,6 +560,7 @@ bool String::operator==(const char *s) const { return false; } return true; + } bool String::operator!=(const char *s) const { @@ -621,11 +670,6 @@ void String::detach() { String(d->data.c_str()).swap(*this); } -//////////////////////////////////////////////////////////////////////////////// -// private members -//////////////////////////////////////////////////////////////////////////////// - -const String::Type String::WCharByteOrder = wcharByteOrder(); } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/toolkit/tstring.h b/3rdparty/taglib/toolkit/tstring.h index a385a55b7..c8de8b315 100644 --- a/3rdparty/taglib/toolkit/tstring.h +++ b/3rdparty/taglib/toolkit/tstring.h @@ -68,15 +68,13 @@ class StringList; //! A \e wide string class suitable for unicode. /*! - * This is an implicitly shared \e wide string. For storage it uses - * TagLib::wstring, but as this is an implementation detail this of - * course could change. Strings are stored internally as UTF-16(without BOM/ - * CPU byte order) + * This is an implicitly shared \e wide string. + * For storage it uses TagLib::wstring, but as this is an implementation detail this of course could change. + * Strings are stored internally as UTF-16(without BOM/ CPU byte order) * - * The use of implicit sharing means that copying a string is cheap, the only - * \e cost comes into play when the copy is modified. Prior to that the string - * just has a pointer to the data of the \e parent String. This also makes - * this class suitable as a function return type. + * The use of implicit sharing means that copying a string is cheap, the only \e cost comes into play when the copy is modified. + * Prior to that the string just has a pointer to the data of the \e parent String. + * This also makes this class suitable as a function return type. * * In addition to adding implicit sharing, this class keeps track of four * possible encodings, which are the four supported by the ID3v2 standard. @@ -90,458 +88,416 @@ class TAGLIB_EXPORT String { #endif /** - * The four types of string encodings supported by the ID3v2 specification. - * ID3v1 is assumed to be Latin1 and Ogg Vorbis comments use UTF8. - */ + * The four types of string encodings supported by the ID3v2 specification. + * ID3v1 is assumed to be Latin1 and Ogg Vorbis comments use UTF8. + */ enum Type { /*! - * IS08859-1, or Latin1 encoding. 8 bit characters. - */ + * IS08859-1, or Latin1 encoding. 8 bit characters. + */ Latin1 = 0, /*! - * UTF16 with a byte order mark. 16 bit characters. - */ + * UTF16 with a byte order mark. 16 bit characters. + */ UTF16 = 1, /*! - * UTF16 big endian. 16 bit characters. This is the encoding used - * internally by TagLib. - */ + * UTF16 big endian. 16 bit characters. This is the encoding used internally by TagLib. + */ UTF16BE = 2, /*! - * UTF8 encoding. Characters are usually 8 bits but can be up to 32. - */ + * UTF8 encoding. Characters are usually 8 bits but can be up to 32. + */ UTF8 = 3, /*! - * UTF16 little endian. 16 bit characters. - */ + * UTF16 little endian. 16 bit characters. + */ UTF16LE = 4 }; /*! - * Constructs an empty String. - */ + * Constructs an empty String. + */ String(); /*! - * Make a shallow, implicitly shared, copy of \a s. Because this is - * implicitly shared, this method is lightweight and suitable for - * pass-by-value usage. - */ + * Make a shallow, implicitly shared, copy of \a s. + * Because this is implicitly shared, this method is lightweight and suitable for pass-by-value usage. + */ String(const String &s); /*! - * Makes a deep copy of the data in \a s. - * - * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when - * used with other codecs it will simply print a warning and exit. - */ + * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when used with other codecs it will simply print a warning and exit. + */ String(const std::string &s, Type t = Latin1); /*! - * Makes a deep copy of the data in \a s. - * - * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless - * of the CPU byte order. If UTF16BE, it will not be swapped. This behavior - * will be changed in TagLib2.0. - */ + * Makes a deep copy of the data in \a s. + * + * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless of the CPU byte order. + * If UTF16BE, it will not be swapped. This behavior will be changed in TagLib2.0. + */ String(const wstring &s, Type t = UTF16BE); /*! - * Makes a deep copy of the data in \a s. - * - * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless - * of the CPU byte order. If UTF16BE, it will not be swapped. This behavior - * will be changed in TagLib2.0. - */ + * Makes a deep copy of the data in \a s. + * + * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless of the CPU byte order. + * If UTF16BE, it will not be swapped. + * This behavior will be changed in TagLib2.0. + */ String(const wchar_t *s, Type t = UTF16BE); /*! - * Makes a deep copy of the data in \a c. - * - * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when - * used with other codecs it will simply print a warning and exit. - */ + * Makes a deep copy of the data in \a c. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when used with other codecs it will simply print a warning and exit. + */ String(char c, Type t = Latin1); /*! - * Makes a deep copy of the data in \a c. - */ + * Makes a deep copy of the data in \a c. + */ String(wchar_t c, Type t = Latin1); /*! - * Makes a deep copy of the data in \a s. - * - * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when - * used with other codecs it will simply print a warning and exit. - */ + * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when used with other codecs it will simply print a warning and exit. + */ String(const char *s, Type t = Latin1); /*! - * Makes a deep copy of the data in \a v. - */ + * Makes a deep copy of the data in \a v. + */ String(const ByteVector &v, Type t = Latin1); /*! - * Destroys this String instance. - */ + * Destroys this String instance. + */ virtual ~String(); /*! - * Returns a deep copy of this String as an std::string. The returned string - * is encoded in UTF8 if \a unicode is true, otherwise Latin1. - * - * \see toCString() - */ + * Returns a deep copy of this String as an std::string. + * The returned string is encoded in UTF8 if \a unicode is true, otherwise Latin1. + * + * \see toCString() + */ std::string to8Bit(bool unicode = false) const; /*! - * Returns a deep copy of this String as a wstring. The returned string is - * encoded in UTF-16 (without BOM/CPU byte order), not UTF-32 even if wchar_t - * is 32-bit wide. - * - * \see toCWString() - */ + * Returns a deep copy of this String as a wstring. + * The returned string is encoded in UTF-16 (without BOM/CPU byte order), not UTF-32 even if wchar_t is 32-bit wide. + * + * \see toCWString() + */ wstring toWString() const; /*! - * Creates and returns a standard C-style (null-terminated) version of this - * String. The returned string is encoded in UTF8 if \a unicode is true, - * otherwise Latin1. - * - * The returned string is still owned by this String and should not be deleted - * by the user. - * - * The returned pointer remains valid until this String instance is destroyed - * or toCString() is called again. - * - * \warning This however has the side effect that the returned string will remain - * in memory in addition to other memory that is consumed by this - * String instance. So, this method should not be used on large strings or - * where memory is critical. Consider using to8Bit() instead to avoid it. - * - * \see to8Bit() - */ + * Creates and returns a standard C-style (null-terminated) version of this String. + * The returned string is encoded in UTF8 if \a unicode is true, otherwise Latin1. + * + * The returned string is still owned by this String and should not be deleted by the user. + * + * The returned pointer remains valid until this String instance is destroyed or toCString() is called again. + * + * \warning This however has the side effect that the returned string will remain + * in memory in addition to other memory that is consumed by this String instance. + * So, this method should not be used on large strings or where memory is critical. Consider using to8Bit() instead to avoid it. + * + * \see to8Bit() + */ const char *toCString(bool unicode = false) const; /*! - * Returns a standard C-style (null-terminated) wide character version of - * this String. The returned string is encoded in UTF-16 (without BOM/CPU byte - * order), not UTF-32 even if wchar_t is 32-bit wide. - * - * The returned string is still owned by this String and should not be deleted - * by the user. - * - * The returned pointer remains valid until this String instance is destroyed - * or any other method of this String is called. - * - * \note This returns a pointer to the String's internal data without any - * conversions. - * - * \see toWString() - */ + * Returns a standard C-style (null-terminated) wide character version of this String. + * The returned string is encoded in UTF-16 (without BOM/CPU byte order), not UTF-32 even if wchar_t is 32-bit wide. + * + * The returned string is still owned by this String and should not be deleted by the user. + * + * The returned pointer remains valid until this String instance is destroyed or any other method of this String is called. + * + * \note This returns a pointer to the String's internal data without any conversions. + * + * \see toWString() + */ const wchar_t *toCWString() const; /*! - * Returns an iterator pointing to the beginning of the string. - */ + * Returns an iterator pointing to the beginning of the string. + */ Iterator begin(); /*! - * Returns a const iterator pointing to the beginning of the string. - */ + * Returns a const iterator pointing to the beginning of the string. + */ ConstIterator begin() const; /*! - * Returns an iterator pointing to the end of the string (the position - * after the last character). - */ + * Returns an iterator pointing to the end of the string (the position after the last character). + */ Iterator end(); /*! - * Returns a const iterator pointing to the end of the string (the position - * after the last character). - */ + * Returns a const iterator pointing to the end of the string (the position after the last character). + */ ConstIterator end() const; /*! - * Finds the first occurrence of pattern \a s in this string starting from - * \a offset. If the pattern is not found, -1 is returned. - */ + * Finds the first occurrence of pattern \a s in this string starting from \a offset. + * If the pattern is not found, -1 is returned. + */ int find(const String &s, int offset = 0) const; /*! - * Finds the last occurrence of pattern \a s in this string, searched backwards, - * either from the end of the string or starting from \a offset. If the pattern - * is not found, -1 is returned. - */ + * Finds the last occurrence of pattern \a s in this string, searched backwards, + * either from the end of the string or starting from \a offset. + * If the pattern is not found, -1 is returned. + */ int rfind(const String &s, int offset = -1) const; /*! - * Splits the string on each occurrence of \a separator. - */ + * Splits the string on each occurrence of \a separator. + */ StringList split(const String &separator = " ") const; /*! - * Returns true if the strings starts with the substring \a s. - */ + * Returns true if the strings starts with the substring \a s. + */ bool startsWith(const String &s) const; /*! - * Extract a substring from this string starting at \a position and - * continuing for \a n characters. - */ + * Extract a substring from this string starting at \a position and continuing for \a n characters. + */ String substr(unsigned int position, unsigned int n = 0xffffffff) const; /*! - * Append \a s to the current string and return a reference to the current - * string. - */ + * Append \a s to the current string and return a reference to the current string. + */ String &append(const String &s); /*! - * Clears the string. - */ + * Clears the string. + */ String &clear(); /*! - * Returns an upper case version of the string. - * - * \warning This only works for the characters in US-ASCII, i.e. A-Z. - */ + * Returns an upper case version of the string. + * + * \warning This only works for the characters in US-ASCII, i.e. A-Z. + */ String upper() const; /*! - * Returns the size of the string. - */ + * Returns the size of the string. + */ unsigned int size() const; /*! - * Returns the length of the string. Equivalent to size(). - */ + * Returns the length of the string. Equivalent to size(). + */ unsigned int length() const; /*! - * Returns true if the string is empty. - * - * \see isNull() - */ + * Returns true if the string is empty. + * + * \see isNull() + */ bool isEmpty() const; /*! - * Returns true if this string is null -- i.e. it is a copy of the - * String::null string. - * - * \note A string can be empty and not null. So do not use this method to - * check if the string is empty. - * - * \see isEmpty() - * - * \deprecated - */ + * Returns true if this string is null -- i.e. it is a copy of the String::null string. + * + * \note A string can be empty and not null. So do not use this method to check if the string is empty. + * + * \see isEmpty() + * + * \deprecated + */ // BIC: remove bool isNull() const; /*! - * Returns a ByteVector containing the string's data. If \a t is Latin1 or - * UTF8, this will return a vector of 8 bit characters, otherwise it will use - * 16 bit characters. - * - * \note If \a t is UTF16, the returned data is encoded in little-endian - * format and has a BOM. - * - * \note The returned data is not null terminated. - */ + * Returns a ByteVector containing the string's data. + * If \a t is Latin1 or UTF8, this will return a vector of 8 bit characters, otherwise it will use 16 bit characters. + * + * \note If \a t is UTF16, the returned data is encoded in little-endian format and has a BOM. + * + * \note The returned data is not null terminated. + */ ByteVector data(Type t) const; /*! - * Convert the string to an integer. - * - * Returns the integer if the conversion was successful or 0 if the - * string does not represent a number. - */ + * Convert the string to an integer. + * + * Returns the integer if the conversion was successful or 0 if the string does not represent a number. + */ // BIC: merge with the method below int toInt() const; /*! - * Convert the string to an integer. - * - * If the conversion was successful, it sets the value of \a *ok to - * true and returns the integer. Otherwise it sets \a *ok to false - * and the result is undefined. - */ + * Convert the string to an integer. + * + * If the conversion was successful, it sets the value of \a *ok to true and returns the integer. + * Otherwise it sets \a *ok to false and the result is undefined. + */ int toInt(bool *ok) const; /*! - * Returns a string with the leading and trailing whitespace stripped. - */ + * Returns a string with the leading and trailing whitespace stripped. + */ String stripWhiteSpace() const; /*! - * Returns true if the file only uses characters required by Latin1. - */ + * Returns true if the file only uses characters required by Latin1. + */ bool isLatin1() const; /*! - * Returns true if the file only uses characters required by (7-bit) ASCII. - */ + * Returns true if the file only uses characters required by (7-bit) ASCII. + */ bool isAscii() const; /*! - * Converts the base-10 integer \a n to a string. - */ + * Converts the base-10 integer \a n to a string. + */ static String number(int n); /*! - * Returns a reference to the character at position \a i. - */ + * Returns a reference to the character at position \a i. + */ wchar_t &operator[](int i); /*! - * Returns a const reference to the character at position \a i. - */ + * Returns a const reference to the character at position \a i. + */ const wchar_t &operator[](int i) const; /*! - * Compares each character of the String with each character of \a s and - * returns true if the strings match. - */ + * Compares each character of the String with each character of \a s and returns true if the strings match. + */ bool operator==(const String &s) const; /*! - * Compares each character of the String with each character of \a s and - * returns false if the strings match. - */ + * Compares each character of the String with each character of \a s and returns false if the strings match. + */ bool operator!=(const String &s) const; /*! - * Compares each character of the String with each character of \a s and - * returns true if the strings match. - */ + * Compares each character of the String with each character of \a s and returns true if the strings match. + */ bool operator==(const char *s) const; /*! - * Compares each character of the String with each character of \a s and - * returns false if the strings match. - */ + * Compares each character of the String with each character of \a s and returns false if the strings match. + */ bool operator!=(const char *s) const; /*! - * Compares each character of the String with each character of \a s and - * returns true if the strings match. - */ + * Compares each character of the String with each character of \a s and returns true if the strings match. + */ bool operator==(const wchar_t *s) const; /*! - * Compares each character of the String with each character of \a s and - * returns false if the strings match. - */ + * Compares each character of the String with each character of \a s and returns false if the strings match. + */ bool operator!=(const wchar_t *s) const; /*! - * Appends \a s to the end of the String. - */ + * Appends \a s to the end of the String. + */ String &operator+=(const String &s); /*! - * Appends \a s to the end of the String. - */ + * Appends \a s to the end of the String. + */ String &operator+=(const wchar_t *s); /*! - * Appends \a s to the end of the String. - */ + * Appends \a s to the end of the String. + */ String &operator+=(const char *s); /*! - * Appends \a s to the end of the String. - */ + * Appends \a s to the end of the String. + */ String &operator+=(wchar_t c); /*! - * Appends \a c to the end of the String. - */ + * Appends \a c to the end of the String. + */ String &operator+=(char c); /*! - * Performs a shallow, implicitly shared, copy of \a s, overwriting the - * String's current data. - */ + * Performs a shallow, implicitly shared, copy of \a s, overwriting the String's current data. + */ String &operator=(const String &s); /*! - * Performs a deep copy of the data in \a s. - */ + * Performs a deep copy of the data in \a s. + */ String &operator=(const std::string &s); /*! - * Performs a deep copy of the data in \a s. - */ + * Performs a deep copy of the data in \a s. + */ String &operator=(const wstring &s); /*! - * Performs a deep copy of the data in \a s. - */ + * Performs a deep copy of the data in \a s. + */ String &operator=(const wchar_t *s); /*! - * Performs a deep copy of the data in \a s. - */ + * Performs a deep copy of the data in \a s. + */ String &operator=(char c); /*! - * Performs a deep copy of the data in \a s. - */ + * Performs a deep copy of the data in \a s. + */ String &operator=(wchar_t c); /*! - * Performs a deep copy of the data in \a s. - */ + * Performs a deep copy of the data in \a s. + */ String &operator=(const char *s); /*! - * Performs a deep copy of the data in \a v. - */ + * Performs a deep copy of the data in \a v. + */ String &operator=(const ByteVector &v); /*! - * Exchanges the content of the String by the content of \a s. - */ + * Exchanges the content of the String by the content of \a s. + */ void swap(String &s); /*! - * To be able to use this class in a Map, this operator needed to be - * implemented. Returns true if \a s is less than this string in a byte-wise - * comparison. - */ + * To be able to use this class in a Map, this operator needed to be implemented. + * Returns true if \a s is less than this string in a byte-wise comparison. + */ bool operator<(const String &s) const; /*! - * A null string provided for convenience. - * - * \warning Do not modify this variable. It will mess up the internal state - * of TagLib. - * - * \deprecated - */ + * A null string provided for convenience. + * + * \warning Do not modify this variable. It will mess up the internal state of TagLib. + * + * \deprecated + */ // BIC: remove static String null; protected: /*! - * If this String is being shared via implicit sharing, do a deep copy of the - * data and separate from the shared members. This should be called by all - * non-const subclass members. - */ + * If this String is being shared via implicit sharing, do a deep copy of the data and separate from the shared members. + * This should be called by all non-const subclass members. + */ void detach(); private: - /*! - * \deprecated This variable is no longer used, but NEVER remove this. It - * may lead to a linkage error. - */ - // BIC: remove - TAGLIB_DEPRECATED static const Type WCharByteOrder; - class StringPrivate; StringPrivate *d; }; diff --git a/3rdparty/taglib/toolkit/tstringlist.cpp b/3rdparty/taglib/toolkit/tstringlist.cpp index 797a9a2cb..9d6820fa9 100644 --- a/3rdparty/taglib/toolkit/tstringlist.cpp +++ b/3rdparty/taglib/toolkit/tstringlist.cpp @@ -35,6 +35,7 @@ class StringListPrivate { //////////////////////////////////////////////////////////////////////////////// StringList StringList::split(const String &s, const String &pattern) { + StringList l; int previousOffset = 0; @@ -46,32 +47,32 @@ StringList StringList::split(const String &s, const String &pattern) { l.append(s.substr(previousOffset, s.size() - previousOffset)); return l; + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -StringList::StringList() : List(), - d(nullptr) { -} +StringList::StringList() : List(), d(nullptr) {} -StringList::StringList(const String &s) : List(), - d(nullptr) { +StringList::StringList(const String &s) : List(), d(nullptr) { append(s); } StringList::StringList(const ByteVectorList &bl, String::Type t) : List() { + ByteVectorList::ConstIterator i = bl.begin(); for (; i != bl.end(); i++) { append(String(*i, t)); } + } -StringList::~StringList() { -} +StringList::~StringList() {} String StringList::toString(const String &separator) const { + String s; ConstIterator it = begin(); @@ -85,16 +86,21 @@ String StringList::toString(const String &separator) const { } return s; + } StringList &StringList::append(const String &s) { + List::append(s); return *this; + } StringList &StringList::append(const StringList &l) { + List::append(l); return *this; + } //////////////////////////////////////////////////////////////////////////////// diff --git a/3rdparty/taglib/toolkit/tstringlist.h b/3rdparty/taglib/toolkit/tstringlist.h index 28d60e837..3eeabf1ad 100644 --- a/3rdparty/taglib/toolkit/tstringlist.h +++ b/3rdparty/taglib/toolkit/tstringlist.h @@ -39,63 +39,59 @@ namespace TagLib { //! A list of strings /*! - * This is a specialization of the List class with some members convention for - * string operations. + * This is a specialization of the List class with some members convention for string operations. */ class TAGLIB_EXPORT StringList : public List { public: /*! - * Constructs an empty StringList. - */ + * Constructs an empty StringList. + */ StringList(); /*! - * Make a shallow, implicitly shared, copy of \a l. Because this is - * implicitly shared, this method is lightweight and suitable for - * pass-by-value usage. - */ + * Make a shallow, implicitly shared, copy of \a l. + * Because this is implicitly shared, this method is lightweight and suitable for pass-by-value usage. + */ StringList(const StringList &l) = default; /*! - * Constructs a StringList with \a s as a member. - */ + * Constructs a StringList with \a s as a member. + */ StringList(const String &s); /*! - * Makes a deep copy of the data in \a vl. - * - * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when - * used with other codecs it will simply print a warning and exit. - */ + * Makes a deep copy of the data in \a vl. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, + * when used with other codecs it will simply print a warning and exit. + */ StringList(const ByteVectorList &vl, String::Type t = String::Latin1); /*! - * Destroys this StringList instance. - */ + * Destroys this StringList instance. + */ virtual ~StringList(); /*! - * Concatenate the list of strings into one string separated by \a separator. - */ + * Concatenate the list of strings into one string separated by \a separator. + */ String toString(const String &separator = " ") const; /*! - * Appends \a s to the end of the list and returns a reference to the - * list. - */ + * Appends \a s to the end of the list and returns a reference to the list. + */ StringList &append(const String &s); /*! - * Appends all of the values in \a l to the end of the list and returns a - * reference to the list. - */ + * Appends all of the values in \a l to the end of the list and returns a reference to the list. + */ StringList &append(const StringList &l); /*! - * Splits the String \a s into several strings at \a pattern. This will not include - * the pattern in the returned strings. - */ + * Splits the String \a s into several strings at \a pattern. + * This will not include the pattern in the returned strings. + */ static StringList split(const String &s, const String &pattern); private: diff --git a/3rdparty/taglib/toolkit/tutils.h b/3rdparty/taglib/toolkit/tutils.h index 2a91d05a8..7cd97c2f2 100644 --- a/3rdparty/taglib/toolkit/tutils.h +++ b/3rdparty/taglib/toolkit/tutils.h @@ -55,8 +55,8 @@ namespace Utils { namespace { /*! - * Reverses the order of bytes in an 16-bit integer. - */ + * Reverses the order of bytes in an 16-bit integer. + */ inline unsigned short byteSwap(unsigned short x) { # if defined(HAVE_GCC_BYTESWAP) @@ -86,8 +86,8 @@ inline unsigned short byteSwap(unsigned short x) { } /*! - * Reverses the order of bytes in an 32-bit integer. - */ + * Reverses the order of bytes in an 32-bit integer. + */ inline unsigned int byteSwap(unsigned int x) { # if defined(HAVE_GCC_BYTESWAP) @@ -117,8 +117,8 @@ inline unsigned int byteSwap(unsigned int x) { } /*! - * Reverses the order of bytes in an 64-bit integer. - */ + * Reverses the order of bytes in an 64-bit integer. + */ inline unsigned long long byteSwap(unsigned long long x) { # if defined(HAVE_GCC_BYTESWAP) @@ -148,9 +148,8 @@ inline unsigned long long byteSwap(unsigned long long x) { } /*! - * Returns a formatted string just like standard sprintf(), but makes use of - * safer functions such as snprintf() if available. - */ + * Returns a formatted string just like standard sprintf(), but makes use of safer functions such as snprintf() if available. + */ inline String formatString(const char *format, ...) { // Sufficient buffer size for the current internal uses. // Consider changing this value when you use this function. @@ -192,8 +191,8 @@ inline String formatString(const char *format, ...) { } /*! - * The types of byte order of the running system. - */ + * The types of byte order of the running system. + */ enum ByteOrder { //! Little endian systems. LittleEndian, @@ -202,8 +201,8 @@ enum ByteOrder { }; /*! - * Returns the byte order of the system. - */ + * Returns the byte order of the system. + */ inline ByteOrder systemByteOrder() { union { int i; diff --git a/3rdparty/taglib/toolkit/tzlib.h b/3rdparty/taglib/toolkit/tzlib.h index d90fa2dd3..0006d5aaa 100644 --- a/3rdparty/taglib/toolkit/tzlib.h +++ b/3rdparty/taglib/toolkit/tzlib.h @@ -38,8 +38,8 @@ namespace TagLib { namespace zlib { /*! - * Returns whether or not zlib is installed and ready to use. - */ + * Returns whether or not zlib is installed and ready to use. + */ bool isAvailable(); /*! diff --git a/3rdparty/taglib/trueaudio/trueaudiofile.cpp b/3rdparty/taglib/trueaudio/trueaudiofile.cpp index 723e8d314..4849e8579 100644 --- a/3rdparty/taglib/trueaudio/trueaudiofile.cpp +++ b/3rdparty/taglib/trueaudio/trueaudiofile.cpp @@ -43,8 +43,10 @@ using namespace Strawberry_TagLib::TagLib; namespace { -enum { TrueAudioID3v2Index = 0, - TrueAudioID3v1Index = 1 }; +enum { + TrueAudioID3v2Index = 0, + TrueAudioID3v1Index = 1 +}; } class TrueAudio::File::FilePrivate { @@ -53,7 +55,7 @@ class TrueAudio::File::FilePrivate { ID3v2Location(-1), ID3v2OriginalSize(0), ID3v1Location(-1), - properties(0) {} + properties(nullptr) {} ~FilePrivate() { delete properties; @@ -75,40 +77,44 @@ class TrueAudio::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool TrueAudio::File::isSupported(IOStream *stream) { + // A TrueAudio file has to start with "TTA". An ID3v2 tag may precede. const ByteVector id = Utils::readHeader(stream, 3, true); return (id == "TTA"); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -TrueAudio::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate()) { +TrueAudio::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } -TrueAudio::File::File(FileName file, ID3v2::FrameFactory *frameFactory, - bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate(frameFactory)) { +TrueAudio::File::File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate(frameFactory)) { + if (isOpen()) read(readProperties); + } -TrueAudio::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate()) { +TrueAudio::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } -TrueAudio::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory, - bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate(frameFactory)) { +TrueAudio::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate(frameFactory)) { + if (isOpen()) read(readProperties); + } TrueAudio::File::~File() { @@ -128,21 +134,20 @@ void TrueAudio::File::removeUnsupportedProperties(const StringList &unsupported) } PropertyMap TrueAudio::File::setProperties(const PropertyMap &properties) { + if (ID3v1Tag()) ID3v1Tag()->setProperties(properties); return ID3v2Tag(true)->setProperties(properties); + } TrueAudio::Properties *TrueAudio::File::audioProperties() const { return d->properties; } -void TrueAudio::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) { - d->ID3v2FrameFactory = factory; -} - bool TrueAudio::File::save() { + if (readOnly()) { debug("TrueAudio::File::save() -- File is read only."); return false; @@ -207,6 +212,7 @@ bool TrueAudio::File::save() { } return true; + } ID3v1::Tag *TrueAudio::File::ID3v1Tag(bool create) { @@ -218,14 +224,16 @@ ID3v2::Tag *TrueAudio::File::ID3v2Tag(bool create) { } void TrueAudio::File::strip(int tags) { + if (tags & ID3v1) - d->tag.set(TrueAudioID3v1Index, 0); + d->tag.set(TrueAudioID3v1Index, nullptr); if (tags & ID3v2) - d->tag.set(TrueAudioID3v2Index, 0); + d->tag.set(TrueAudioID3v2Index, nullptr); if (!ID3v1Tag()) ID3v2Tag(true); + } bool TrueAudio::File::hasID3v1Tag() const { @@ -241,6 +249,7 @@ bool TrueAudio::File::hasID3v2Tag() const { //////////////////////////////////////////////////////////////////////////////// void TrueAudio::File::read(bool readProperties) { + // Look for an ID3v2 tag d->ID3v2Location = Utils::findID3v2(this); @@ -281,4 +290,5 @@ void TrueAudio::File::read(bool readProperties) { d->properties = new Properties(readBlock(TrueAudio::HeaderSize), streamLength); } + } diff --git a/3rdparty/taglib/trueaudio/trueaudiofile.h b/3rdparty/taglib/trueaudio/trueaudiofile.h index 986e6af6c..9e491c177 100644 --- a/3rdparty/taglib/trueaudio/trueaudiofile.h +++ b/3rdparty/taglib/trueaudio/trueaudiofile.h @@ -49,29 +49,26 @@ class Tag; //! An implementation of TrueAudio metadata /*! - * This is implementation of TrueAudio metadata. - * - * This supports ID3v1 and ID3v2 tags as well as reading stream - * properties from the file. - */ + * This is implementation of TrueAudio metadata. + * + * This supports ID3v1 and ID3v2 tags as well as reading stream properties from the file. + */ namespace TrueAudio { //! An implementation of TagLib::File with TrueAudio specific methods /*! - * This implements and provides an interface for TrueAudio files to the - * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing - * the abstract TagLib::File API as well as providing some additional - * information specific to TrueAudio files. - */ + * This implements and provides an interface for TrueAudio files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing the + * abstract TagLib::File API as well as providing some additional information specific to TrueAudio files. + */ 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. - */ + * 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, @@ -84,169 +81,140 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { }; /*! - * Constructs a TrueAudio file from \a file. If \a readProperties is true - * the file's audio properties will also be read. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ + * Constructs a TrueAudio file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs a TrueAudio file from \a file. If \a readProperties is true - * the file's audio properties will also be read. - * - * If this file contains and ID3v2 tag the frames will be created using - * \a frameFactory. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(FileName file, ID3v2::FrameFactory *frameFactory, - bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs a TrueAudio file from \a file. + * If \a readProperties is true the file's audio properties will also be read. + * + * If this file contains and ID3v2 tag the frames will be created using \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs a TrueAudio file from \a stream. If \a readProperties is true - * the file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(IOStream *stream, bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs a TrueAudio file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs a TrueAudio file from \a stream. If \a readProperties is true - * the file's audio properties will also be read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - * - * If this file contains and ID3v2 tag the frames will be created using - * \a frameFactory. - * - * \note In the current implementation, \a propertiesStyle is ignored. - */ - File(IOStream *stream, ID3v2::FrameFactory *frameFactory, - bool readProperties = true, - Properties::ReadStyle propertiesStyle = Properties::Average); + * Constructs a TrueAudio file from \a stream. + * If \a readProperties is true the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + * + * If this file contains and ID3v2 tag the frames will be created using \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, ID3v2::FrameFactory *frameFactory, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the Tag for this file. - */ + * Returns the Tag for this file. + */ virtual Strawberry_TagLib::TagLib::Tag *tag() const; /*! - * Implements the unified property interface -- export function. - * If the file contains both ID3v1 and v2 tags, only ID3v2 will be - * converted to the PropertyMap. - */ + * Implements the unified property interface -- export function. + * If the file contains both ID3v1 and v2 tags, only ID3v2 will be converted to the PropertyMap. + */ PropertyMap properties() const; /*! - * Implements the unified property interface -- import function. - * Creates in ID3v2 tag if necessary. If an ID3v1 tag exists, it will - * be updated as well, within the limitations of ID3v1. - */ + * Implements the unified property interface -- import function. + * Creates in ID3v2 tag if necessary. If an ID3v1 tag exists, it will be updated as well, within the limitations of ID3v1. + */ PropertyMap setProperties(const PropertyMap &); void removeUnsupportedProperties(const StringList &properties); /*! - * Returns the TrueAudio::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the TrueAudio::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; - /*! - * 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); - - /*! - * Saves the file. - */ + * Saves the file. + */ virtual bool save(); /*! - * Returns a pointer to the ID3v1 tag of the file. - * - * If \a create is false (the default) this may return a null pointer - * if there is no valid ID3v1 tag. If \a create is true it will create - * an ID3v1 tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file - * on disk actually has an ID3v1 tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasID3v1Tag() - */ + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer if there is no valid ID3v1 tag. + * If \a create is true it will create an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v1 tag. + * Use hasID3v1Tag() to check if the file on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasID3v1Tag() + */ ID3v1::Tag *ID3v1Tag(bool create = false); /*! - * Returns a pointer to the ID3v2 tag of the file. - * - * If \a create is false (the default) this may return a null pointer - * if there is no valid ID3v2 tag. If \a create is true it will create - * an ID3v2 tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file - * on disk actually has an ID3v2 tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasID3v2Tag() - */ + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this may return a null pointer if there is no valid ID3v2 tag. + * If \a create is true it will create an ID3v2 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v2 tag. + * Use hasID3v2Tag() to check if the file on disk actually has an ID3v2 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasID3v2Tag() + */ ID3v2::Tag *ID3v2Tag(bool create = false); /*! - * This will remove the tags that match the OR-ed together TagTypes from the - * file. By default it removes all tags. - * - * \note This will also invalidate pointers to the tags - * as their memory will be freed. - * \note In order to make the removal permanent save() still needs to be called - */ + * This will remove the tags that match the OR-ed together TagTypes from the file. + * By default it removes all tags. + * + * \note This will also invalidate pointers to the tags as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ void strip(int tags = AllTags); /*! - * Returns whether or not the file on disk actually has an ID3v1 tag. - * - * \see ID3v1Tag() - */ + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ bool hasID3v1Tag() const; /*! - * Returns whether or not the file on disk actually has an ID3v2 tag. - * - * \see ID3v2Tag() - */ + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ bool hasID3v2Tag() const; /*! - * Returns whether or not the given \a stream can be opened as a TrueAudio - * file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Returns whether or not the given \a stream can be opened as a TrueAudio file. + * + * \note This method is designed to do a quick check. The result may not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: @@ -258,6 +226,7 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { class FilePrivate; FilePrivate *d; }; + } // namespace TrueAudio } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/trueaudio/trueaudioproperties.cpp b/3rdparty/taglib/trueaudio/trueaudioproperties.cpp index ce972a0ce..a6d22100c 100644 --- a/3rdparty/taglib/trueaudio/trueaudioproperties.cpp +++ b/3rdparty/taglib/trueaudio/trueaudioproperties.cpp @@ -59,8 +59,7 @@ class TrueAudio::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -TrueAudio::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +TrueAudio::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { read(data, streamLength); } @@ -68,10 +67,6 @@ TrueAudio::Properties::~Properties() { delete d; } -int TrueAudio::Properties::length() const { - return lengthInSeconds(); -} - int TrueAudio::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -109,6 +104,7 @@ int TrueAudio::Properties::ttaVersion() const { //////////////////////////////////////////////////////////////////////////////// void TrueAudio::Properties::read(const ByteVector &data, long streamLength) { + if (data.size() < 4) { debug("TrueAudio::Properties::read() -- data is too short."); return; @@ -152,4 +148,5 @@ void TrueAudio::Properties::read(const ByteVector &data, long streamLength) { d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); } } + } diff --git a/3rdparty/taglib/trueaudio/trueaudioproperties.h b/3rdparty/taglib/trueaudio/trueaudioproperties.h index a6ae07dfc..8e698d2a8 100644 --- a/3rdparty/taglib/trueaudio/trueaudioproperties.h +++ b/3rdparty/taglib/trueaudio/trueaudioproperties.h @@ -34,7 +34,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace TrueAudio { class File; @@ -44,78 +43,65 @@ static const unsigned int HeaderSize = 18; //! An implementation of audio property reading for TrueAudio /*! - * This reads the data from an TrueAudio stream found in the AudioProperties - * API. - */ + * This reads the data from an TrueAudio stream found in the AudioProperties API. + */ class TAGLIB_EXPORT Properties : public AudioProperties { public: /*! - * Create an instance of TrueAudio::Properties with the data read from the - * ByteVector \a data. - */ + * Create an instance of TrueAudio::Properties with the data read from the ByteVector \a data. + */ Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); /*! - * Destroys this TrueAudio::Properties instance. - */ + * Destroys this TrueAudio::Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. - */ + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the number of bits per audio sample. - */ + * Returns the number of bits per audio sample. + */ int bitsPerSample() const; /*! - * Returns the total number of sample frames - */ + * Returns the total number of sample frames + */ unsigned int sampleFrames() const; /*! - * Returns the major version number. - */ + * Returns the major version number. + */ int ttaVersion() const; private: @@ -127,6 +113,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties { class PropertiesPrivate; PropertiesPrivate *d; }; + } // namespace TrueAudio } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/wavpack/wavpackfile.cpp b/3rdparty/taglib/wavpack/wavpackfile.cpp index 91db5f8bc..6e715cd24 100644 --- a/3rdparty/taglib/wavpack/wavpackfile.cpp +++ b/3rdparty/taglib/wavpack/wavpackfile.cpp @@ -43,8 +43,10 @@ using namespace Strawberry_TagLib::TagLib; namespace { -enum { WavAPEIndex, - WavID3v1Index }; +enum { + WavAPEIndex, + WavID3v1Index +}; } class WavPack::File::FilePrivate { @@ -52,7 +54,7 @@ class WavPack::File::FilePrivate { FilePrivate() : APELocation(-1), APESize(0), ID3v1Location(-1), - properties(0) {} + properties(nullptr) {} ~FilePrivate() { delete properties; @@ -73,26 +75,30 @@ class WavPack::File::FilePrivate { //////////////////////////////////////////////////////////////////////////////// bool WavPack::File::isSupported(IOStream *stream) { + // A WavPack file has to start with "wvpk". const ByteVector id = Utils::readHeader(stream, 4, false); return (id == "wvpk"); + } //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// -WavPack::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), - d(new FilePrivate()) { +WavPack::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } -WavPack::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), - d(new FilePrivate()) { +WavPack::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate()) { + if (isOpen()) read(readProperties); + } WavPack::File::~File() { @@ -112,10 +118,12 @@ void WavPack::File::removeUnsupportedProperties(const StringList &unsupported) { } PropertyMap WavPack::File::setProperties(const PropertyMap &properties) { + if (ID3v1Tag()) ID3v1Tag()->setProperties(properties); return APETag(true)->setProperties(properties); + } WavPack::Properties *WavPack::File::audioProperties() const { @@ -123,6 +131,7 @@ WavPack::Properties *WavPack::File::audioProperties() const { } bool WavPack::File::save() { + if (readOnly()) { debug("WavPack::File::save() -- File is read only."); return false; @@ -191,6 +200,7 @@ bool WavPack::File::save() { } return true; + } ID3v1::Tag *WavPack::File::ID3v1Tag(bool create) { @@ -202,14 +212,16 @@ APE::Tag *WavPack::File::APETag(bool create) { } void WavPack::File::strip(int tags) { + if (tags & ID3v1) - d->tag.set(WavID3v1Index, 0); + d->tag.set(WavID3v1Index, nullptr); if (tags & APE) - d->tag.set(WavAPEIndex, 0); + d->tag.set(WavAPEIndex, nullptr); if (!ID3v1Tag()) APETag(true); + } bool WavPack::File::hasID3v1Tag() const { @@ -225,6 +237,7 @@ bool WavPack::File::hasAPETag() const { //////////////////////////////////////////////////////////////////////////////// void WavPack::File::read(bool readProperties) { + // Look for an ID3v1 tag d->ID3v1Location = Utils::findID3v1(this); @@ -260,4 +273,5 @@ void WavPack::File::read(bool readProperties) { d->properties = new Properties(this, streamLength); } + } diff --git a/3rdparty/taglib/wavpack/wavpackfile.h b/3rdparty/taglib/wavpack/wavpackfile.h index 773688b40..2cdaa7b38 100644 --- a/3rdparty/taglib/wavpack/wavpackfile.h +++ b/3rdparty/taglib/wavpack/wavpackfile.h @@ -49,29 +49,30 @@ class Tag; //! An implementation of WavPack metadata /*! - * This is implementation of WavPack metadata. - * - * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream - * properties from the file. - */ + * This is implementation of WavPack metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. + * + */ namespace WavPack { //! An implementation of Strawberry_TagLib::TagLib::File with WavPack specific methods /*! - * This implements and provides an interface for WavPack files to the - * Strawberry_TagLib::TagLib::Tag and Strawberry_TagLib::TagLib::AudioProperties interfaces by way of implementing - * the abstract Strawberry_TagLib::TagLib::File API as well as providing some additional - * information specific to WavPack files. - */ + * This implements and provides an interface for WavPack files to the + * Strawberry_TagLib::TagLib::Tag and Strawberry_TagLib::TagLib::AudioProperties interfaces by way of implementing + * the abstract Strawberry_TagLib::TagLib::File API as well as providing some additional + * information specific to WavPack files. + * + */ 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. - */ + * 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, @@ -84,132 +85,125 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { }; /*! - * Constructs a WavPack file from \a file. If \a readProperties is true the - * file's audio properties will also be read using \a propertiesStyle. If - * false, \a propertiesStyle is ignored - */ + * Constructs a WavPack file from \a file. + * If \a readProperties is true the file's audio properties will also be read using \a propertiesStyle. + * If false, \a propertiesStyle is ignored + */ File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Constructs an WavPack file from \a file. If \a readProperties is true the - * file's audio properties will also be read using \a propertiesStyle. If - * false, \a propertiesStyle is ignored. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - */ + * Constructs an WavPack file from \a file. + * If \a readProperties is true the file's audio properties will also be read using \a propertiesStyle. + * If false, \a propertiesStyle is ignored. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); /*! - * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag - * or a combination of the two. - */ + * Returns the Tag for this file. + * This will be an APE tag, an ID3v1 tag or a combination of the two. + */ virtual Strawberry_TagLib::TagLib::Tag *tag() const; /*! - * Implements the unified property interface -- export function. - * If the file contains both an APE and an ID3v1 tag, only APE - * will be converted to the PropertyMap. - */ + * Implements the unified property interface -- export function. + * If the file contains both an APE and an ID3v1 tag, + * only APE will be converted to the PropertyMap. + */ PropertyMap properties() const; void removeUnsupportedProperties(const StringList &properties); /*! - * Implements the unified property interface -- import function. - * Creates an APE tag if it does not exists and calls setProperties() on - * that. Any existing ID3v1 tag will be updated as well. - */ + * Implements the unified property interface -- import function. + * Creates an APE tag if it does not exists and calls setProperties() on that. + * Any existing ID3v1 tag will be updated as well. + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the MPC::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the MPC::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ virtual Properties *audioProperties() const; /*! - * Saves the file. - * - * This returns true if the save was successful. - */ + * Saves the file. + * + * This returns true if the save was successful. + */ virtual bool save(); /*! - * Returns a pointer to the ID3v1 tag of the file. - * - * If \a create is false (the default) this may return a null pointer - * if there is no valid ID3v1 tag. If \a create is true it will create - * an ID3v1 tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file - * on disk actually has an ID3v1 tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasID3v1Tag() - */ + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer if there is no valid ID3v1 tag. + * If \a create is true it will create an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v1 tag. + * Use hasID3v1Tag() to check if the file on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasID3v1Tag() + */ 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 - * if there is no valid APE tag. If \a create is true it will create - * an APE tag if one does not exist and returns a valid pointer. - * - * \note This may return a valid pointer regardless of whether or not the - * file on disk has an APE tag. Use hasAPETag() to check if the file - * on disk actually has an APE tag. - * - * \note The Tag is still owned by the MPEG::File and should not be - * deleted by the user. It will be deleted when the file (object) is - * destroyed. - * - * \see hasAPETag() - */ + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer if there is no valid APE tag. + * If \a create is true it will create an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the file on disk has an APE tag. + * Use hasAPETag() to check if the file on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be deleted by the user. + * It will be deleted when the file (object) is destroyed. + * + * \see hasAPETag() + */ APE::Tag *APETag(bool create = false); /*! - * This will remove the tags that match the OR-ed together TagTypes from the - * file. By default it removes all tags. - * - * \note This will also invalidate pointers to the tags - * as their memory will be freed. - * \note In order to make the removal permanent save() still needs to be called - */ + * This will remove the tags that match the OR-ed together TagTypes from the file. + * By default it removes all tags. + * + * \note This will also invalidate pointers to the tags as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ void strip(int tags = AllTags); /*! - * Returns whether or not the file on disk actually has an ID3v1 tag. - * - * \see ID3v1Tag() - */ + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ bool hasID3v1Tag() const; /*! - * Returns whether or not the file on disk actually has an APE tag. - * - * \see APETag() - */ + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ bool hasAPETag() const; /*! - * Check if the given \a stream can be opened as a WavPack file. - * - * \note This method is designed to do a quick check. The result may - * not necessarily be correct. - */ + * Check if the given \a stream can be opened as a WavPack file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ static bool isSupported(IOStream *stream); private: @@ -221,6 +215,7 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File { class FilePrivate; FilePrivate *d; }; + } // namespace WavPack } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/wavpack/wavpackproperties.cpp b/3rdparty/taglib/wavpack/wavpackproperties.cpp index 7ec87b2ca..47e82e16e 100644 --- a/3rdparty/taglib/wavpack/wavpackproperties.cpp +++ b/3rdparty/taglib/wavpack/wavpackproperties.cpp @@ -63,13 +63,7 @@ class WavPack::Properties::PropertiesPrivate { // public members //////////////////////////////////////////////////////////////////////////////// -WavPack::Properties::Properties(const ByteVector &, long, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { - debug("WavPack::Properties::Properties() -- This constructor is no longer used."); -} - -WavPack::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style), - d(new PropertiesPrivate()) { +WavPack::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { read(file, streamLength); } @@ -77,10 +71,6 @@ WavPack::Properties::~Properties() { delete d; } -int WavPack::Properties::length() const { - return lengthInSeconds(); -} - int WavPack::Properties::lengthInSeconds() const { return d->length / 1000; } @@ -144,6 +134,7 @@ const unsigned int sample_rates[] = { #define FINAL_BLOCK 0x1000 void WavPack::Properties::read(File *file, long streamLength) { + long offset = 0; while (true) { @@ -190,9 +181,11 @@ void WavPack::Properties::read(File *file, long streamLength) { d->length = static_cast(length + 0.5); d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); } + } unsigned int WavPack::Properties::seekFinalIndex(File *file, long streamLength) { + const long offset = file->rfind("wvpk", streamLength); if (offset == -1) return 0; @@ -214,4 +207,5 @@ unsigned int WavPack::Properties::seekFinalIndex(File *file, long streamLength) const unsigned int blockSamples = data.toUInt(20, false); return blockIndex + blockSamples; + } diff --git a/3rdparty/taglib/wavpack/wavpackproperties.h b/3rdparty/taglib/wavpack/wavpackproperties.h index a2927328a..70cc80b16 100644 --- a/3rdparty/taglib/wavpack/wavpackproperties.h +++ b/3rdparty/taglib/wavpack/wavpackproperties.h @@ -35,7 +35,6 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace WavPack { class File; @@ -45,92 +44,73 @@ static const unsigned int HeaderSize = 32; //! An implementation of audio property reading for WavPack /*! - * This reads the data from an WavPack stream found in the AudioProperties - * API. - */ + * This reads the data from an WavPack stream found in the AudioProperties + * API. + */ class TAGLIB_EXPORT Properties : public AudioProperties { public: - /*! - * Create an instance of WavPack::Properties with the data read from the - * ByteVector \a data. - * - * \deprecated This constructor will be dropped in favor of the one below - * in a future version. - */ - TAGLIB_DEPRECATED Properties(const ByteVector &data, long streamLength, - ReadStyle style = Average); /*! - * Create an instance of WavPack::Properties. - */ + * Create an instance of WavPack::Properties. + */ Properties(File *file, long streamLength, ReadStyle style = Average); /*! - * Destroys this WavPack::Properties instance. - */ + * Destroys this WavPack::Properties instance. + */ virtual ~Properties(); /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \note This method is just an alias of lengthInSeconds(). - * - * \deprecated - */ - TAGLIB_DEPRECATED virtual int length() const; - - /*! - * Returns the length of the file in seconds. The length is rounded down to - * the nearest whole second. - * - * \see lengthInMilliseconds() - */ + * 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; /*! - * Returns the length of the file in milliseconds. - * - * \see lengthInSeconds() - */ + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ // BIC: make virtual int lengthInMilliseconds() const; /*! - * Returns the average bit rate of the file in kb/s. - */ + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; /*! - * Returns the sample rate in Hz. 0 means unknown or custom. - */ + * Returns the sample rate in Hz. 0 means unknown or custom. + */ virtual int sampleRate() const; /*! - * Returns the number of audio channels. - */ + * Returns the number of audio channels. + */ virtual int channels() const; /*! - * Returns the number of bits per audio sample. - */ + * Returns the number of bits per audio sample. + */ int bitsPerSample() const; /*! - * Returns whether or not the file is lossless encoded. - */ + * Returns whether or not the file is lossless encoded. + */ bool isLossless() const; /*! - * Returns the total number of audio samples in file. - */ + * Returns the total number of audio samples in file. + */ unsigned int sampleFrames() const; /*! - * Returns WavPack version. - */ + * Returns WavPack version. + */ int version() const; private: @@ -143,6 +123,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties { class PropertiesPrivate; PropertiesPrivate *d; }; + } // namespace WavPack } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/xm/xmfile.cpp b/3rdparty/taglib/xm/xmfile.cpp index ffef76be3..1b0e6510b 100644 --- a/3rdparty/taglib/xm/xmfile.cpp +++ b/3rdparty/taglib/xm/xmfile.cpp @@ -70,8 +70,7 @@ class Reader { } /*! - * Reads associated values from \a file, but never reads more - * then \a limit bytes. + * Reads associated values from \a file, but never reads more then \a limit bytes. */ virtual unsigned int read(Strawberry_TagLib::TagLib::File &file, unsigned int limit) = 0; @@ -112,10 +111,10 @@ class ValueReader : public Reader { class StringReader : public ValueReader { public: - StringReader(String &string, unsigned int size) : ValueReader(string), m_size(size) { - } + StringReader(String &string, unsigned int size) : ValueReader(string), m_size(size) {} unsigned int read(Strawberry_TagLib::TagLib::File &file, unsigned int limit) { + ByteVector data = file.readBlock(std::min(m_size, limit)); unsigned int count = data.size(); int index = data.find((char)0); @@ -125,6 +124,7 @@ class StringReader : public ValueReader { data.replace('\xff', ' '); value = data; return count; + } unsigned int size() const { @@ -349,6 +349,7 @@ XM::Properties *XM::File::audioProperties() const { } bool XM::File::save() { + if (readOnly()) { debug("XM::File::save() - Cannot save to a read only file."); return false; @@ -440,9 +441,11 @@ bool XM::File::save() { } return true; + } void XM::File::read(bool) { + if (!isOpen()) return; @@ -589,4 +592,5 @@ void XM::File::read(bool) { comment += sampleNames.toString("\n"); } d->tag.setComment(comment); + } diff --git a/3rdparty/taglib/xm/xmfile.h b/3rdparty/taglib/xm/xmfile.h index 1baba1b1b..817062489 100644 --- a/3rdparty/taglib/xm/xmfile.h +++ b/3rdparty/taglib/xm/xmfile.h @@ -35,67 +35,59 @@ namespace Strawberry_TagLib { namespace TagLib { - namespace XM { class TAGLIB_EXPORT File : public Mod::FileBase { public: /*! - * Constructs an Extended Module file from \a file. - * - * \note In the current implementation, both \a readProperties and - * \a propertiesStyle are ignored. The audio properties are always - * read. - */ - File(FileName file, bool readProperties = true, - AudioProperties::ReadStyle propertiesStyle = - AudioProperties::Average); + * Constructs an Extended Module file from \a file. + * + * \note In the current implementation, both \a readProperties and \a propertiesStyle are ignored. + * The audio properties are always read. + */ + File(FileName file, bool readProperties = true, AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average); /*! - * Constructs an Extended Module file from \a stream. - * - * \note In the current implementation, both \a readProperties and - * \a propertiesStyle are ignored. The audio properties are always - * read. - * - * \note TagLib will *not* take ownership of the stream, the caller is - * responsible for deleting it after the File object. - */ - File(IOStream *stream, bool readProperties = true, - AudioProperties::ReadStyle propertiesStyle = - AudioProperties::Average); + * Constructs an Extended Module file from \a stream. + * + * \note In the current implementation, both \a readProperties and \a propertiesStyle are ignored. + * The audio properties are always read. + * + * \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average); /*! - * Destroys this instance of the File. - */ + * Destroys this instance of the File. + */ virtual ~File(); Mod::Tag *tag() const; /*! - * Implements the unified property interface -- export function. - * Forwards to Mod::Tag::properties(). - */ + * Implements the unified property interface -- export function. + * Forwards to Mod::Tag::properties(). + */ PropertyMap properties() const; /*! - * Implements the unified property interface -- import function. - * Forwards to Mod::Tag::setProperties(). - */ + * Implements the unified property interface -- import function. + * Forwards to Mod::Tag::setProperties(). + */ PropertyMap setProperties(const PropertyMap &); /*! - * Returns the XM::Properties for this file. If no audio properties - * were read then this will return a null pointer. - */ + * Returns the XM::Properties for this file. + * If no audio properties were read then this will return a null pointer. + */ XM::Properties *audioProperties() const; /*! - * Save the file. - * This is the same as calling save(AllTags); - * - * \note Saving Extended Module tags is not supported. - */ + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving Extended Module tags is not supported. + */ bool save(); private: @@ -107,6 +99,7 @@ class TAGLIB_EXPORT File : public Mod::FileBase { class FilePrivate; FilePrivate *d; }; + } // namespace XM } // namespace TagLib } // namespace Strawberry_TagLib diff --git a/3rdparty/taglib/xm/xmproperties.cpp b/3rdparty/taglib/xm/xmproperties.cpp index db9fbc403..d4e518118 100644 --- a/3rdparty/taglib/xm/xmproperties.cpp +++ b/3rdparty/taglib/xm/xmproperties.cpp @@ -55,9 +55,7 @@ class XM::Properties::PropertiesPrivate { unsigned short bpmSpeed; }; -XM::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle), - d(new PropertiesPrivate()) { -} +XM::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle), d(new PropertiesPrivate()) {} XM::Properties::~Properties() { delete d; diff --git a/3rdparty/taglib/xm/xmproperties.h b/3rdparty/taglib/xm/xmproperties.h index 16759bc1a..7b8b68a16 100644 --- a/3rdparty/taglib/xm/xmproperties.h +++ b/3rdparty/taglib/xm/xmproperties.h @@ -81,6 +81,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties { class PropertiesPrivate; PropertiesPrivate *d; }; + } // namespace XM } // namespace TagLib } // namespace Strawberry_TagLib