https://github.com/mixxxdj/mixxx/pull/12854 --- mixxx-2.4.1/CMakeLists.txt +++ mixxx-2.4.1/CMakeLists.txt @@ -2953,11 +2953,7 @@ find_package(TagLib 1.11 REQUIRED) target_link_libraries(mixxx-lib PUBLIC TagLib::TagLib) if (NOT TagLib_VERSION VERSION_LESS 2.0.0) - message(FATAL_ERROR "Installed Taglib ${TagLib_VERSION} is not supported. Use Version >= 1.11 and < 2.0 and its development headers.") - # Dear package maintainer: Do not patch away this fatal error - # using taglib 2.0.0 will put user data at risk!! - # Mixxx is a complex application that needs to be adapted and tested thoroughly - # https://github.com/mixxxdj/mixxx/issues/12708 + message(WARNING "Installed Taglib ${TagLib_VERSION} is not supported and might lead to data loss (https://github.com/mixxxdj/mixxx/issues/12708). Use version >= 1.11 and < 2.0 instead.") endif() # Threads --- mixxx-2.4.1/src/track/taglib/trackmetadata_common.cpp +++ mixxx-2.4.1/src/track/taglib/trackmetadata_common.cpp @@ -268,28 +268,36 @@ } } +bool isMultiValueTagEqual(const TagLib::String& taglibVal, QString mixxxVal) { + // Taglib 2 uses " / " instead of " " as a multi value separator. + // We may have read or write with either TagLib 1 or 2. + QString taglibValStripped = toQString(taglibVal).remove(" /"); + QString mixxxValStripped = mixxxVal.remove(" /"); + return taglibValStripped == mixxxValStripped; +} + void exportTrackMetadataIntoTag( TagLib::Tag* pTag, const TrackMetadata& trackMetadata, WriteTagMask writeMask) { DEBUG_ASSERT(pTag); // already validated before - pTag->setTitle(toTString(trackMetadata.getTrackInfo().getTitle())); - pTag->setAlbum(toTString(trackMetadata.getAlbumInfo().getTitle())); - // The mapping of multi-valued fields in TagLib is not bijective. // We don't want to overwrite existing values if the corresponding - // field has not been modified in Mixxx. This workaround only covers - // the most common multi-valued fields. + // field has not been modified in Mixxx. // // See also: - const auto artist = toTString(trackMetadata.getTrackInfo().getArtist()); - if (artist != pTag->artist()) { - pTag->setArtist(artist); - } - const auto genre = toTString(trackMetadata.getTrackInfo().getGenre()); - if (genre != pTag->genre()) { - pTag->setGenre(genre); + if (!isMultiValueTagEqual(pTag->title(), trackMetadata.getTrackInfo().getTitle())) { + pTag->setTitle(toTString(trackMetadata.getTrackInfo().getTitle())); + } + if (!isMultiValueTagEqual(pTag->album(), trackMetadata.getAlbumInfo().getTitle())) { + pTag->setAlbum(toTString(trackMetadata.getAlbumInfo().getTitle())); + } + if (!isMultiValueTagEqual(pTag->artist(), trackMetadata.getTrackInfo().getArtist())) { + pTag->setArtist(toTString(trackMetadata.getTrackInfo().getArtist())); + } + if (!isMultiValueTagEqual(pTag->genre(), trackMetadata.getTrackInfo().getGenre())) { + pTag->setGenre(toTString(trackMetadata.getTrackInfo().getGenre())); } // Using setComment() from TagLib::Tag might have undesirable @@ -297,7 +305,9 @@ // different purposes, e.g. ID3v2. In this case setting the // comment here should be omitted. if (0 == (writeMask & WriteTagFlag::OmitComment)) { - pTag->setComment(toTString(trackMetadata.getTrackInfo().getComment())); + if (!isMultiValueTagEqual(pTag->comment(), trackMetadata.getTrackInfo().getComment())) { + pTag->setComment(toTString(trackMetadata.getTrackInfo().getComment())); + } } // Specialized write functions for tags derived from Taglib::Tag might