diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f93de34e..a448f06b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,8 +49,9 @@ jobs: - name: Test Windows working-directory: ${{github.workspace}}/build run: | - $env:Path += ";$env:VCPKG_INSTALLATION_ROOT\packages\cppunit_x64-windows\bin;$PWD\taglib\Release" - $env:Path += ";$env:VCPKG_INSTALLATION_ROOT\packages\utfcpp_x64-windows\bin;$PWD\taglib\Release" - $env:Path += ";$env:VCPKG_INSTALLATION_ROOT\packages\zlib_x64-windows\bin;$PWD\taglib\Release" + $env:Path += ";$PWD\taglib\Release;$PWD\bindings\c\Release" + $env:Path += ";$env:VCPKG_INSTALLATION_ROOT\packages\cppunit_x64-windows\bin" + $env:Path += ";$env:VCPKG_INSTALLATION_ROOT\packages\utfcpp_x64-windows\bin" + $env:Path += ";$env:VCPKG_INSTALLATION_ROOT\packages\zlib_x64-windows\bin" ctest -C ${{env.BUILD_TYPE}} -V --no-tests=error if: matrix.os == 'windows-latest' diff --git a/bindings/c/tag_c.h b/bindings/c/tag_c.h index a88d6e99..6e7d85ea 100644 --- a/bindings/c/tag_c.h +++ b/bindings/c/tag_c.h @@ -43,7 +43,10 @@ extern "C" { #define TAGLIB_C_EXPORT #endif -#ifndef BOOL +#ifdef _MSC_VER +/* minwindef.h contains typedef int BOOL */ +#include +#elif !defined BOOL #define BOOL int #endif diff --git a/taglib/fileref.cpp b/taglib/fileref.cpp index b4848fcc..32ee212a 100644 --- a/taglib/fileref.cpp +++ b/taglib/fileref.cpp @@ -389,6 +389,11 @@ const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::Fil return resolver; } +void FileRef::clearFileTypeResolvers() // static +{ + fileTypeResolvers.clear(); +} + StringList FileRef::defaultFileExtensions() { StringList l; diff --git a/taglib/fileref.h b/taglib/fileref.h index 14dee450..e8c70104 100644 --- a/taglib/fileref.h +++ b/taglib/fileref.h @@ -247,6 +247,11 @@ namespace TagLib { */ static const FileTypeResolver *addFileTypeResolver(const FileTypeResolver *resolver); + /*! + * Remove all resolvers added by addFileTypeResolver(). + */ + static void clearFileTypeResolvers(); + /*! * As is mentioned elsewhere in this class's documentation, the default file * type resolution code provided by TagLib only works by comparing file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 415ae1c9..472c3b63 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../taglib ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/toolkit + ${CMAKE_CURRENT_SOURCE_DIR}/../bindings/c ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ape ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/asf ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v1 @@ -72,12 +73,13 @@ SET(test_runner_SRCS test_dsf.cpp test_sizes.cpp test_versionnumber.cpp + test_tag_c.cpp ) INCLUDE_DIRECTORIES(${CPPUNIT_INCLUDE_DIR}) ADD_EXECUTABLE(test_runner ${test_runner_SRCS}) -TARGET_LINK_LIBRARIES(test_runner tag ${CPPUNIT_LIBRARIES}) +TARGET_LINK_LIBRARIES(test_runner tag tag_c ${CPPUNIT_LIBRARIES}) ADD_TEST(test_runner test_runner) ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND} -V diff --git a/tests/test_fileref.cpp b/tests/test_fileref.cpp index 7010a025..8c6928a2 100644 --- a/tests/test_fileref.cpp +++ b/tests/test_fileref.cpp @@ -419,6 +419,8 @@ public: FileRef f(&s); CPPUNIT_ASSERT(dynamic_cast(f.file()) != nullptr); } + + FileRef::clearFileTypeResolvers(); } }; diff --git a/tests/test_tag_c.cpp b/tests/test_tag_c.cpp new file mode 100644 index 00000000..46200c01 --- /dev/null +++ b/tests/test_tag_c.cpp @@ -0,0 +1,148 @@ +/*************************************************************************** + copyright : (C) 2023 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "tag_c.h" +#include "tbytevector.h" +#include "tstring.h" +#include +#include "utils.h" + +using namespace TagLib; + +class TestTagC : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(TestTagC); + CPPUNIT_TEST(testMp3); + CPPUNIT_TEST_SUITE_END(); + +public: + void testMp3() + { + ScopedFileCopy copy("xing", ".mp3"); + + { + TagLib_File *file = taglib_file_new(copy.fileName().c_str()); + CPPUNIT_ASSERT(taglib_file_is_valid(file)); + const TagLib_AudioProperties *audioProperties = taglib_file_audioproperties(file); + CPPUNIT_ASSERT_EQUAL(32, taglib_audioproperties_bitrate(audioProperties)); + CPPUNIT_ASSERT_EQUAL(2, taglib_audioproperties_channels(audioProperties)); + CPPUNIT_ASSERT_EQUAL(2, taglib_audioproperties_length(audioProperties)); + CPPUNIT_ASSERT_EQUAL(44100, taglib_audioproperties_samplerate(audioProperties)); + + TagLib_Tag *tag = taglib_file_tag(file); + CPPUNIT_ASSERT_EQUAL(""s, std::string(taglib_tag_album(tag))); + taglib_tag_set_album(tag, "Album"); + taglib_tag_set_artist(tag, "Artist"); + taglib_tag_set_comment(tag, "Comment"); + taglib_tag_set_genre(tag, "Genre"); + taglib_tag_set_title(tag, "Title"); + taglib_tag_set_track(tag, 2); + taglib_tag_set_year(tag, 2023); + + taglib_property_set(file, "COMPOSER", "Composer 1"); + taglib_property_set_append(file, "COMPOSER", "Composer 2"); + taglib_property_set(file, "ALBUMARTIST", "Album Artist"); + + TAGLIB_COMPLEX_PROPERTY_PICTURE(props, "JPEG Data", 9, "Written by TagLib", + "image/jpeg", "Front Cover"); + taglib_complex_property_set(file, "PICTURE", props); + + taglib_file_save(file); + taglib_file_free(file); + } + { + TagLib_File *file = taglib_file_new(copy.fileName().c_str()); + CPPUNIT_ASSERT(taglib_file_is_valid(file)); + + TagLib_Tag *tag = taglib_file_tag(file); + CPPUNIT_ASSERT_EQUAL("Album"s, std::string(taglib_tag_album(tag))); + CPPUNIT_ASSERT_EQUAL("Artist"s, std::string(taglib_tag_artist(tag))); + CPPUNIT_ASSERT_EQUAL("Comment"s, std::string(taglib_tag_comment(tag))); + CPPUNIT_ASSERT_EQUAL("Genre"s, std::string(taglib_tag_genre(tag))); + CPPUNIT_ASSERT_EQUAL("Title"s, std::string(taglib_tag_title(tag))); + CPPUNIT_ASSERT_EQUAL(2U, taglib_tag_track(tag)); + CPPUNIT_ASSERT_EQUAL(2023U, taglib_tag_year(tag)); + + char **keys = taglib_property_keys(file); + CPPUNIT_ASSERT(keys); + std::unordered_map> propertyMap; + char **keyPtr = keys; + while(*keyPtr) { + char **values = taglib_property_get(file, *keyPtr); + char **valuePtr = values; + std::list valueList; + while(*valuePtr) { + valueList.push_back(*valuePtr++); + } + taglib_property_free(values); + propertyMap[*keyPtr++] = valueList; + } + taglib_property_free(keys); + const std::unordered_map> expected { + {"TRACKNUMBER"s, {"2"s}}, + {"TITLE"s, {"Title"s}}, + {"GENRE"s, {"Genre"s}}, + {"DATE"s, {"2023"s}}, + {"COMPOSER"s, {"Composer 1"s, "Composer 2"s}}, + {"COMMENT"s, {"Comment"s}}, + {"ARTIST"s, {"Artist"s}}, + {"ALBUMARTIST"s, {"Album Artist"s}}, + {"ALBUM"s, {"Album"s}} + }; + CPPUNIT_ASSERT(expected == propertyMap); + + char **complexKeys = taglib_complex_property_keys(file); + CPPUNIT_ASSERT(complexKeys); + std::list keyList; + char **complexKeyPtr = complexKeys; + while(*complexKeyPtr) { + keyList.push_back(*complexKeyPtr++); + } + taglib_complex_property_free_keys(complexKeys); + CPPUNIT_ASSERT(std::list{"PICTURE"s} == keyList); + + TagLib_Complex_Property_Attribute*** properties = + taglib_complex_property_get(file, "PICTURE"); + TagLib_Complex_Property_Picture_Data picture; + taglib_picture_from_complex_property(properties, &picture); + CPPUNIT_ASSERT_EQUAL("image/jpeg"s, std::string(picture.mimeType)); + CPPUNIT_ASSERT_EQUAL("Written by TagLib"s, std::string(picture.description)); + CPPUNIT_ASSERT_EQUAL("Front Cover"s, std::string(picture.pictureType)); + CPPUNIT_ASSERT_EQUAL(ByteVector("JPEG Data"), ByteVector(picture.data, 9)); + CPPUNIT_ASSERT_EQUAL(9U, picture.size); + taglib_complex_property_free(properties); + + taglib_file_free(file); + } + + taglib_tag_free_strings(); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TestTagC);