mirror of
https://github.com/taglib/taglib.git
synced 2026-06-07 14:59:24 -04:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebf4c5bbb1 | ||
|
|
20cec27ac0 | ||
|
|
99bc87ccff | ||
|
|
7951f572b5 | ||
|
|
59ff35772e | ||
|
|
3784628155 | ||
|
|
e60df53152 | ||
|
|
1ae8e18db5 | ||
|
|
0896fb9092 | ||
|
|
920d97606b | ||
|
|
0d2c31b102 | ||
|
|
c8c4e5faec |
17
CHANGELOG.md
17
CHANGELOG.md
@@ -1,8 +1,21 @@
|
||||
TagLib 2.0.1 (Apr 9, 2024)
|
||||
==========================
|
||||
|
||||
* Fix aborting when _GLIBCXX_ASSERTIONS are enabled.
|
||||
* Fall back to utf8cpp header detection in the case that its CMake
|
||||
configuration is removed.
|
||||
* Improve compatibility with the SWIG interface compiler.
|
||||
* Build system fixes for testing without bindings, Emscripten and Illumos.
|
||||
* C bindings: Fix setting UTF-8 encoded property values.
|
||||
* Windows: Fix opening long paths.
|
||||
|
||||
TagLib 2.0 (Jan 24, 2024)
|
||||
=========================
|
||||
|
||||
* New major version, binary incompatible, but source-compatible with the
|
||||
latest 1.x release if no deprecated features are used.
|
||||
* New major version, binary incompatible, but mostly source-compatible
|
||||
with the latest 1.x release if no deprecated features are used.
|
||||
Simple applications should build without changes, more complex
|
||||
applications (e.g. extending classes of TagLib) will have to be adapted.
|
||||
* Requires a C++17 compiler and uses features of C++17.
|
||||
* Major code cleanup, fixed warnings issued by compilers and static analyzers.
|
||||
* Made methods virtual which should have been virtual but could not be
|
||||
|
||||
@@ -93,7 +93,7 @@ endif()
|
||||
# Patch version: increase it for bug fix releases.
|
||||
set(TAGLIB_SOVERSION_MAJOR 2)
|
||||
set(TAGLIB_SOVERSION_MINOR 0)
|
||||
set(TAGLIB_SOVERSION_PATCH 0)
|
||||
set(TAGLIB_SOVERSION_PATCH 1)
|
||||
|
||||
include(ConfigureChecks.cmake)
|
||||
|
||||
@@ -149,18 +149,33 @@ if(TRACE_IN_RELEASE)
|
||||
endif()
|
||||
|
||||
find_package(utf8cpp QUIET)
|
||||
if(NOT utf8cpp_FOUND)
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/utfcpp/CMakeLists.txt)
|
||||
add_subdirectory("3rdparty/utfcpp")
|
||||
message(STATUS "Using utfcpp from ${utf8cpp_SOURCE_DIR}")
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
"utfcpp not found. Either install package (probably utfcpp, utf8cpp, or libutfcpp-dev) "
|
||||
"or fetch the git submodule using\n"
|
||||
"git submodule update --init")
|
||||
endif()
|
||||
else()
|
||||
if(utf8cpp_FOUND)
|
||||
message(STATUS "Using utfcpp ${utf8cpp_VERSION} from ${utf8cpp_CONFIG}")
|
||||
else()
|
||||
find_path(utf8cpp_INCLUDE_DIR NAMES utf8.h PATH_SUFFIXES utf8cpp
|
||||
DOC "utf8cpp include directory")
|
||||
mark_as_advanced(utf8cpp_INCLUDE_DIR)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(utf8cpp REQUIRED_VARS utf8cpp_INCLUDE_DIR)
|
||||
if(utf8cpp_FOUND)
|
||||
set(utf8cpp_INCLUDE_DIRS "${utf8cpp_INCLUDE_DIR}")
|
||||
if(NOT TARGET utf8::cpp)
|
||||
add_library(utf8::cpp INTERFACE IMPORTED)
|
||||
set_target_properties(utf8::cpp PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${utf8cpp_INCLUDE_DIR}")
|
||||
endif()
|
||||
message(STATUS "Using utfcpp from ${utf8cpp_INCLUDE_DIR}")
|
||||
else()
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/utfcpp/CMakeLists.txt)
|
||||
add_subdirectory("3rdparty/utfcpp")
|
||||
message(STATUS "Using utfcpp from ${utf8cpp_SOURCE_DIR}")
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
"utfcpp not found. Either install package (probably utfcpp, utf8cpp, or libutfcpp-dev) "
|
||||
"or fetch the git submodule using\n"
|
||||
"git submodule update --init")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(taglib)
|
||||
|
||||
@@ -20,7 +20,7 @@ if(NOT ${SIZEOF_LONGLONG} EQUAL 8)
|
||||
endif()
|
||||
|
||||
check_type_size("wchar_t" SIZEOF_WCHAR_T)
|
||||
if(${SIZEOF_WCHAR_T} LESS 2)
|
||||
if(NOT ${SIZEOF_WCHAR_T} GREATER 1)
|
||||
message(FATAL_ERROR "TagLib requires that wchar_t is sufficient to store a UTF-16 char.")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
https://taglib.org/
|
||||
|
||||
TagLib is a library for reading and editing the metadata of several
|
||||
popular audio formats. Currently, it supports both ID3v1 and [ID3v2][]
|
||||
popular audio formats. Currently, it supports both ID3v1 and ID3v2
|
||||
for MP3 files, [Ogg Vorbis][] comments and ID3 tags
|
||||
in [FLAC][], MPC, Speex, WavPack, TrueAudio, WAV, AIFF, MP4, APE,
|
||||
and ASF files.
|
||||
in [FLAC][], MPC, Speex, WavPack, TrueAudio, WAV, AIFF, MP4, APE, ASF,
|
||||
DSF, DFF and AAC files.
|
||||
|
||||
TagLib is distributed under the [GNU Lesser General Public License][]
|
||||
(LGPL) and [Mozilla Public License][] (MPL). Essentially that means that
|
||||
@@ -18,7 +18,6 @@ it may be used in proprietary applications, but if changes are made to
|
||||
TagLib they must be contributed back to the project. Please review the
|
||||
licenses if you are considering using TagLib in your project.
|
||||
|
||||
[ID3v2]: https://id3.org/
|
||||
[Ogg Vorbis]: https://xiph.org/vorbis/
|
||||
[FLAC]: https://xiph.org/flac/
|
||||
[GNU Lesser General Public License]: https://www.gnu.org/licenses/lgpl.html
|
||||
|
||||
@@ -410,14 +410,14 @@ void _taglib_property_set(TagLib_File *file, const char* prop, const char* value
|
||||
if(value) {
|
||||
auto property = map.find(prop);
|
||||
if(property == map.end()) {
|
||||
map.insert(prop, StringList(value));
|
||||
map.insert(prop, StringList(charArrayToString(value)));
|
||||
}
|
||||
else {
|
||||
if(append) {
|
||||
property->second.append(value);
|
||||
property->second.append(charArrayToString(value));
|
||||
}
|
||||
else {
|
||||
property->second = StringList(value);
|
||||
property->second = StringList(charArrayToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -542,14 +542,14 @@ bool _taglib_complex_property_set(
|
||||
map.insert(attrKey, attr->value.value.doubleValue);
|
||||
break;
|
||||
case TagLib_Variant_String:
|
||||
map.insert(attrKey, attr->value.value.stringValue);
|
||||
map.insert(attrKey, charArrayToString(attr->value.value.stringValue));
|
||||
break;
|
||||
case TagLib_Variant_StringList: {
|
||||
StringList strs;
|
||||
if(attr->value.value.stringListValue) {
|
||||
char **s = attr->value.value.stringListValue;;
|
||||
while(*s) {
|
||||
strs.append(*s++);
|
||||
strs.append(charArrayToString(*s++));
|
||||
}
|
||||
}
|
||||
map.insert(attrKey, strs);
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Destroys this StreamTypeResolver instance.
|
||||
*/
|
||||
~StreamTypeResolver() override = 0;
|
||||
virtual ~StreamTypeResolver() override = 0; // virtual is needed by SWIG
|
||||
|
||||
StreamTypeResolver(const StreamTypeResolver &) = delete;
|
||||
StreamTypeResolver &operator=(const StreamTypeResolver &) = delete;
|
||||
|
||||
@@ -69,3 +69,13 @@ MP4::CoverArt::data() const
|
||||
{
|
||||
return d->data;
|
||||
}
|
||||
|
||||
bool MP4::CoverArt::operator==(const CoverArt &other) const
|
||||
{
|
||||
return format() == other.format() && data() == other.data();
|
||||
}
|
||||
|
||||
bool MP4::CoverArt::operator!=(const CoverArt &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,17 @@ namespace TagLib {
|
||||
//! The image data
|
||||
ByteVector data() const;
|
||||
|
||||
/*!
|
||||
* Returns \c true if the CoverArt and \a other are of the same format and
|
||||
* contain the same data.
|
||||
*/
|
||||
bool operator==(const CoverArt &other) const;
|
||||
|
||||
/*!
|
||||
* Returns \c true if the CoverArt and \a other differ in format or data.
|
||||
*/
|
||||
bool operator!=(const CoverArt &other) const;
|
||||
|
||||
private:
|
||||
class CoverArtPrivate;
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
|
||||
@@ -30,6 +30,7 @@ using namespace TagLib;
|
||||
class MP4::Item::ItemPrivate
|
||||
{
|
||||
public:
|
||||
Type type;
|
||||
bool valid { true };
|
||||
AtomDataType atomDataType { TypeUndefined };
|
||||
union {
|
||||
@@ -48,6 +49,7 @@ public:
|
||||
MP4::Item::Item() :
|
||||
d(std::make_shared<ItemPrivate>())
|
||||
{
|
||||
d->type = Type::Void;
|
||||
d->valid = false;
|
||||
}
|
||||
|
||||
@@ -67,36 +69,42 @@ MP4::Item::~Item() = default;
|
||||
MP4::Item::Item(bool value) :
|
||||
d(std::make_shared<ItemPrivate>())
|
||||
{
|
||||
d->type = Type::Bool;
|
||||
d->m_bool = value;
|
||||
}
|
||||
|
||||
MP4::Item::Item(int value) :
|
||||
d(std::make_shared<ItemPrivate>())
|
||||
{
|
||||
d->type = Type::Int;
|
||||
d->m_int = value;
|
||||
}
|
||||
|
||||
MP4::Item::Item(unsigned char value) :
|
||||
d(std::make_shared<ItemPrivate>())
|
||||
{
|
||||
d->type = Type::Byte;
|
||||
d->m_byte = value;
|
||||
}
|
||||
|
||||
MP4::Item::Item(unsigned int value) :
|
||||
d(std::make_shared<ItemPrivate>())
|
||||
{
|
||||
d->type = Type::UInt;
|
||||
d->m_uint = value;
|
||||
}
|
||||
|
||||
MP4::Item::Item(long long value) :
|
||||
d(std::make_shared<ItemPrivate>())
|
||||
{
|
||||
d->type = Type::LongLong;
|
||||
d->m_longlong = value;
|
||||
}
|
||||
|
||||
MP4::Item::Item(int value1, int value2) :
|
||||
d(std::make_shared<ItemPrivate>())
|
||||
{
|
||||
d->type = Type::IntPair;
|
||||
d->m_intPair.first = value1;
|
||||
d->m_intPair.second = value2;
|
||||
}
|
||||
@@ -104,18 +112,21 @@ MP4::Item::Item(int value1, int value2) :
|
||||
MP4::Item::Item(const ByteVectorList &value) :
|
||||
d(std::make_shared<ItemPrivate>())
|
||||
{
|
||||
d->type = Type::ByteVectorList;
|
||||
d->m_byteVectorList = value;
|
||||
}
|
||||
|
||||
MP4::Item::Item(const StringList &value) :
|
||||
d(std::make_shared<ItemPrivate>())
|
||||
{
|
||||
d->type = Type::StringList;
|
||||
d->m_stringList = value;
|
||||
}
|
||||
|
||||
MP4::Item::Item(const MP4::CoverArtList &value) :
|
||||
d(std::make_shared<ItemPrivate>())
|
||||
{
|
||||
d->type = Type::CoverArtList;
|
||||
d->m_coverArtList = value;
|
||||
}
|
||||
|
||||
@@ -188,3 +199,47 @@ MP4::Item::isValid() const
|
||||
{
|
||||
return d->valid;
|
||||
}
|
||||
|
||||
MP4::Item::Type MP4::Item::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
bool MP4::Item::operator==(const Item &other) const
|
||||
{
|
||||
if(isValid() && other.isValid() &&
|
||||
type() == other.type() &&
|
||||
atomDataType() == other.atomDataType()) {
|
||||
switch(type()) {
|
||||
case Type::Void:
|
||||
return true;
|
||||
case Type::Bool:
|
||||
return toBool() == other.toBool();
|
||||
case Type::Int:
|
||||
return toInt() == other.toInt();
|
||||
case Type::IntPair: {
|
||||
const auto lhs = toIntPair();
|
||||
const auto rhs = other.toIntPair();
|
||||
return lhs.first == rhs.first && lhs.second == rhs.second;
|
||||
}
|
||||
case Type::Byte:
|
||||
return toByte() == other.toByte();
|
||||
case Type::UInt:
|
||||
return toUInt() == other.toUInt();
|
||||
case Type::LongLong:
|
||||
return toLongLong() == other.toLongLong();
|
||||
case Type::StringList:
|
||||
return toStringList() == other.toStringList();
|
||||
case Type::ByteVectorList:
|
||||
return toByteVectorList() == other.toByteVectorList();
|
||||
case Type::CoverArtList:
|
||||
return toCoverArtList() == other.toCoverArtList();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MP4::Item::operator!=(const Item &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,22 @@ namespace TagLib {
|
||||
class TAGLIB_EXPORT Item
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* The data type stored in the item.
|
||||
*/
|
||||
enum class Type : unsigned char {
|
||||
Void,
|
||||
Bool,
|
||||
Int,
|
||||
IntPair,
|
||||
Byte,
|
||||
UInt,
|
||||
LongLong,
|
||||
StringList,
|
||||
ByteVectorList,
|
||||
CoverArtList
|
||||
};
|
||||
|
||||
struct IntPair {
|
||||
int first, second;
|
||||
};
|
||||
@@ -80,6 +96,19 @@ namespace TagLib {
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
Type type() const;
|
||||
|
||||
/*!
|
||||
* Returns \c true if the Item and \a other are of the same type and
|
||||
* contain the same value.
|
||||
*/
|
||||
bool operator==(const Item &other) const;
|
||||
|
||||
/*!
|
||||
* Returns \c true if the Item and \a other differ in type or value.
|
||||
*/
|
||||
bool operator!=(const Item &other) const;
|
||||
|
||||
private:
|
||||
class ItemPrivate;
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#define TAGLIB_MAJOR_VERSION 2
|
||||
#define TAGLIB_MINOR_VERSION 0
|
||||
#define TAGLIB_PATCH_VERSION 0
|
||||
#define TAGLIB_PATCH_VERSION 1
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1600)
|
||||
#define TAGLIB_CONSTRUCT_BITSET(x) static_cast<unsigned long long>(x)
|
||||
@@ -60,7 +60,7 @@ namespace TagLib {
|
||||
// In Win32, always 64bit. Otherwise, equivalent to off_t.
|
||||
#ifdef _WIN32
|
||||
using offset_t = long long;
|
||||
#else
|
||||
#elif !defined(__illumos__)
|
||||
using offset_t = off_t;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -70,7 +70,8 @@ ByteVectorList::~ByteVectorList() = default;
|
||||
ByteVectorList::ByteVectorList(const ByteVectorList &l) :
|
||||
List<ByteVector>(l)
|
||||
{
|
||||
*d = *l.d;
|
||||
// Uncomment if d is used, d.get() is nullptr and *d behavior undefined
|
||||
// *d = *l.d;
|
||||
}
|
||||
|
||||
ByteVectorList::ByteVectorList(std::initializer_list<ByteVector> init) :
|
||||
@@ -84,7 +85,8 @@ ByteVectorList &ByteVectorList::operator=(const ByteVectorList &l)
|
||||
return *this;
|
||||
|
||||
List<ByteVector>::operator=(l);
|
||||
*d = *l.d;
|
||||
// Uncomment if d is used, d.get() is nullptr and *d behavior undefined
|
||||
// *d = *l.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,21 @@ namespace
|
||||
#if defined (PLATFORM_WINRT)
|
||||
return CreateFile2(path.wstr().c_str(), access, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
|
||||
#else
|
||||
return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
constexpr wchar_t LongLocalPathPrefix[] = L"\\\\?\\";
|
||||
constexpr wchar_t UNCPathPrefix[] = L"\\\\";
|
||||
constexpr wchar_t LongUNCPathPrefix[] = L"\\\\?\\UNC\\";
|
||||
std::wstring pathWStr = path.wstr();
|
||||
if(pathWStr.length() > MAX_PATH &&
|
||||
pathWStr.compare(0, std::size(LongLocalPathPrefix) - 1, LongLocalPathPrefix) != 0 &&
|
||||
pathWStr.compare(0, std::size(LongUNCPathPrefix) - 1, LongUNCPathPrefix) != 0) {
|
||||
if(pathWStr.compare(0, std::size(UNCPathPrefix) - 1, UNCPathPrefix) == 0) {
|
||||
pathWStr = LongUNCPathPrefix + pathWStr.substr(2);
|
||||
}
|
||||
else {
|
||||
pathWStr = LongLocalPathPrefix + pathWStr;
|
||||
}
|
||||
}
|
||||
return CreateFileW(pathWStr.c_str(), access, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Explained at end of tpropertymap.cpp
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
extern template class TagLib::Map<TagLib::String, TagLib::StringList>;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -59,7 +59,8 @@ StringList::StringList() = default;
|
||||
StringList::StringList(const StringList &l) :
|
||||
List<String>(l)
|
||||
{
|
||||
*d = *l.d;
|
||||
// Uncomment if d is used, d.get() is nullptr and *d behavior undefined
|
||||
// *d = *l.d;
|
||||
}
|
||||
|
||||
StringList::StringList(std::initializer_list<String> init) :
|
||||
@@ -73,7 +74,8 @@ StringList &StringList::operator=(const StringList &l)
|
||||
return *this;
|
||||
|
||||
List<String>::operator=(l);
|
||||
*d = *l.d;
|
||||
// Uncomment if d is used, d.get() is nullptr and *d behavior undefined
|
||||
// *d = *l.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,13 +76,20 @@ SET(test_runner_SRCS
|
||||
test_dsdiff.cpp
|
||||
test_sizes.cpp
|
||||
test_versionnumber.cpp
|
||||
test_tag_c.cpp
|
||||
)
|
||||
IF(BUILD_BINDINGS)
|
||||
SET(test_runner_SRCS ${test_runner_SRCS}
|
||||
test_tag_c.cpp
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
INCLUDE_DIRECTORIES(${CPPUNIT_INCLUDE_DIR})
|
||||
|
||||
ADD_EXECUTABLE(test_runner ${test_runner_SRCS})
|
||||
TARGET_LINK_LIBRARIES(test_runner tag tag_c ${CPPUNIT_LIBRARIES})
|
||||
TARGET_LINK_LIBRARIES(test_runner tag ${CPPUNIT_LIBRARIES})
|
||||
IF(BUILD_BINDINGS)
|
||||
TARGET_LINK_LIBRARIES(test_runner tag_c)
|
||||
ENDIF()
|
||||
|
||||
ADD_TEST(test_runner test_runner)
|
||||
ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND} -V
|
||||
|
||||
@@ -39,6 +39,7 @@ class TestMP4Item : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE(TestMP4Item);
|
||||
CPPUNIT_TEST(testCoverArtList);
|
||||
CPPUNIT_TEST(testItemOperations);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@@ -58,6 +59,112 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(ByteVector("bar"), l[1].data());
|
||||
}
|
||||
|
||||
void testItemOperations()
|
||||
{
|
||||
MP4::Item e;
|
||||
MP4::Item i1(1);
|
||||
MP4::Item i2(1);
|
||||
MP4::Item i3(-1);
|
||||
MP4::Item c1(static_cast<unsigned char>('A'));
|
||||
MP4::Item c2(static_cast<unsigned char>('A'));
|
||||
MP4::Item c3(static_cast<unsigned char>('Z'));
|
||||
MP4::Item u1(2U);
|
||||
MP4::Item u2(2U);
|
||||
MP4::Item u3(0U);
|
||||
MP4::Item l1(3LL);
|
||||
MP4::Item l2(3LL);
|
||||
MP4::Item l3(-7LL);
|
||||
MP4::Item b1(true);
|
||||
MP4::Item b2(true);
|
||||
MP4::Item b3(false);
|
||||
MP4::Item p1(4, 5);
|
||||
MP4::Item p2(4, 5);
|
||||
MP4::Item p3(-4, -5);
|
||||
MP4::Item s1(StringList{"abc", "de"});
|
||||
MP4::Item s2(StringList{"abc", "de"});
|
||||
MP4::Item s3(StringList{"abc"});
|
||||
MP4::Item v1(ByteVectorList{"f", "gh"});
|
||||
MP4::Item v2(ByteVectorList{"f", "gh"});
|
||||
MP4::Item v3(ByteVectorList{});
|
||||
MP4::Item a1(MP4::CoverArtList{
|
||||
MP4::CoverArt(MP4::CoverArt::PNG, "foo"),
|
||||
MP4::CoverArt(MP4::CoverArt::JPEG, "bar")
|
||||
});
|
||||
MP4::Item a2(MP4::CoverArtList{
|
||||
MP4::CoverArt(MP4::CoverArt::PNG, "foo"),
|
||||
MP4::CoverArt(MP4::CoverArt::JPEG, "bar")
|
||||
});
|
||||
MP4::Item a3(MP4::CoverArtList{
|
||||
MP4::CoverArt(MP4::CoverArt::JPEG, "bar")
|
||||
});
|
||||
|
||||
CPPUNIT_ASSERT(i1 == i2);
|
||||
CPPUNIT_ASSERT(i2 != i3);
|
||||
CPPUNIT_ASSERT(i3 != c1);
|
||||
CPPUNIT_ASSERT(c1 == c1);
|
||||
CPPUNIT_ASSERT(c1 == c2);
|
||||
CPPUNIT_ASSERT(c2 != c3);
|
||||
CPPUNIT_ASSERT(c3 != u1);
|
||||
CPPUNIT_ASSERT(u1 == u2);
|
||||
CPPUNIT_ASSERT(u2 != u3);
|
||||
CPPUNIT_ASSERT(u3 != l1);
|
||||
CPPUNIT_ASSERT(l1 == l2);
|
||||
CPPUNIT_ASSERT(l2 != l3);
|
||||
CPPUNIT_ASSERT(l3 != b1);
|
||||
CPPUNIT_ASSERT(b1 == b2);
|
||||
CPPUNIT_ASSERT(b2 != b3);
|
||||
CPPUNIT_ASSERT(b3 != p1);
|
||||
CPPUNIT_ASSERT(p1 == p2);
|
||||
CPPUNIT_ASSERT(p2 != p3);
|
||||
CPPUNIT_ASSERT(p3 != s1);
|
||||
CPPUNIT_ASSERT(s1 == s2);
|
||||
CPPUNIT_ASSERT(s2 != s3);
|
||||
CPPUNIT_ASSERT(s3 != v1);
|
||||
CPPUNIT_ASSERT(v1 == v2);
|
||||
CPPUNIT_ASSERT(v2 != v3);
|
||||
CPPUNIT_ASSERT(v3 != a1);
|
||||
CPPUNIT_ASSERT(a1 == a2);
|
||||
CPPUNIT_ASSERT(a2 != a3);
|
||||
CPPUNIT_ASSERT(a3 != e);
|
||||
|
||||
CPPUNIT_ASSERT(!e.isValid());
|
||||
CPPUNIT_ASSERT(i1.isValid());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::Item::Type::Void, e.type());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::Item::Type::Int, i1.type());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::Item::Type::Byte, c1.type());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::Item::Type::UInt, u1.type());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::Item::Type::LongLong, l1.type());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::Item::Type::Bool, b1.type());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::Item::Type::IntPair, p1.type());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::Item::Type::StringList, s1.type());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::Item::Type::ByteVectorList, v1.type());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::Item::Type::CoverArtList, a1.type());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(1, i1.toInt());
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>('A'), c1.toByte());
|
||||
CPPUNIT_ASSERT_EQUAL(2U, u1.toUInt());
|
||||
CPPUNIT_ASSERT_EQUAL(3LL, l1.toLongLong());
|
||||
CPPUNIT_ASSERT_EQUAL(true, b1.toBool());
|
||||
CPPUNIT_ASSERT_EQUAL(4, p1.toIntPair().first);
|
||||
CPPUNIT_ASSERT_EQUAL((StringList{"abc", "de"}), s1.toStringList());
|
||||
CPPUNIT_ASSERT_EQUAL((ByteVectorList{"f", "gh"}), v1.toByteVectorList());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::CoverArt::PNG, a1.toCoverArtList().front().format());
|
||||
|
||||
s3.swap(s1);
|
||||
CPPUNIT_ASSERT_EQUAL((StringList{"abc"}), s1.toStringList());
|
||||
CPPUNIT_ASSERT_EQUAL((StringList{"abc", "de"}), s3.toStringList());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::AtomDataType::TypeUndefined, s1.atomDataType());
|
||||
s1.setAtomDataType(MP4::AtomDataType::TypeUTF8);
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::AtomDataType::TypeUTF8, s1.atomDataType());
|
||||
s1 = s3;
|
||||
CPPUNIT_ASSERT_EQUAL((StringList{"abc", "de"}), s1.toStringList());
|
||||
|
||||
MP4::ItemMap m1{{"key1", i1}, {"key2", p1}};
|
||||
MP4::ItemMap m2{{"key1", i2}, {"key2", p2}};
|
||||
MP4::ItemMap m3{{"key1", i2}, {"key2", p3}};
|
||||
CPPUNIT_ASSERT(m1 == m2);
|
||||
CPPUNIT_ASSERT(m1 != m3);
|
||||
}
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestMP4Item);
|
||||
|
||||
Reference in New Issue
Block a user