From 03074cedc855c2918847c64568ba1db1232fc9fc Mon Sep 17 00:00:00 2001 From: emeric Date: Sat, 23 Mar 2019 14:58:29 +0100 Subject: [PATCH] properly handle multi tags like MP3 ID3 v2.4 tags --- src/metadata/AvFormat.cpp | 24 ++++---- src/metadata/MetaData.hpp | 2 +- src/metadata/TagLibParser.cpp | 100 +++++++++++++++------------------ tools/metadata/LmsMetadata.cpp | 4 +- 4 files changed, 60 insertions(+), 70 deletions(-) diff --git a/src/metadata/AvFormat.cpp b/src/metadata/AvFormat.cpp index e4b963b2..434b9a52 100644 --- a/src/metadata/AvFormat.cpp +++ b/src/metadata/AvFormat.cpp @@ -61,24 +61,22 @@ getAlbum(const MetadataMap& metadataMap) } static -boost::optional -getAlbumArtist(const MetadataMap& metadataMap) +std::vector +getAlbumArtists(const MetadataMap& metadataMap) { - boost::optional res; + std::vector res; - auto artist {findFirstValueOf(metadataMap, {"ALBUM_ARTIST"})}; - if (!artist) + auto name {findFirstValueOf(metadataMap, {"ALBUM_ARTIST"})}; + if (!name) return res; - res = Artist{*artist, ""}; + Artist artist {*name, ""}; - auto artistMBID {findFirstValueOf(metadataMap, {"MUSICBRAINZ ALBUM ARTIST ID"})}; - if (!artistMBID) - return res; + auto mbid {findFirstValueOf(metadataMap, {"MUSICBRAINZ ALBUM ARTIST ID"})}; + if (mbid) + artist.musicBrainzArtistID = *mbid; - res->musicBrainzArtistID = *artistMBID; - - return res; + return {std::move(artist)}; } static @@ -213,7 +211,7 @@ AvFormat::parse(const boost::filesystem::path& p, bool debug) track.artists = getArtists(metadataMap); track.album = getAlbum(metadataMap); - track.albumArtist = getAlbumArtist(metadataMap); + track.albumArtists = getAlbumArtists(metadataMap); } catch(Av::MediaFileException& e) { diff --git a/src/metadata/MetaData.hpp b/src/metadata/MetaData.hpp index 39633924..106d48f4 100644 --- a/src/metadata/MetaData.hpp +++ b/src/metadata/MetaData.hpp @@ -50,7 +50,7 @@ namespace MetaData struct Track { std::vector artists; - boost::optional albumArtist; + std::vector albumArtists; std::string title; std::string musicBrainzTrackID; std::string musicBrainzRecordID; diff --git a/src/metadata/TagLibParser.cpp b/src/metadata/TagLibParser.cpp index 6bafc713..0b3cff37 100644 --- a/src/metadata/TagLibParser.cpp +++ b/src/metadata/TagLibParser.cpp @@ -31,18 +31,15 @@ namespace MetaData { -boost::optional -getPropertyValue(const TagLib::PropertyMap& properties, const std::string& key) +std::vector +getPropertyValues(const TagLib::PropertyMap& properties, const std::string& key) { - boost::optional res; + std::vector res; const TagLib::StringList& values {properties[key]}; - if (values.isEmpty()) - return res; - res = stringTrim(values.front().to8Bit(true)); - if (res->empty()) - res.reset(); + res.reserve(values.size()); + std::transform(std::cbegin(values), std::cend(values), std::back_inserter(res), [](const auto& value) { return stringTrim(value.to8Bit(true)); }); return res; } @@ -60,82 +57,77 @@ splitAndTrimString(const std::string& str, const std::string& delimiters) return res; } -static -std::vector -getMusicBrainzArtistID(const TagLib::PropertyMap& properties) -{ - boost::optional value {getPropertyValue(properties, "MUSICBRAINZ_ARTISTID")}; - - if (!value) - return {}; - - return splitAndTrimString(*value, "/"); // Picard separator is '/' -} - static std::vector getArtists(const TagLib::PropertyMap& properties) { std::vector res; - boost::optional value; - - value = getPropertyValue(properties, "ARTISTS"); - if (value) - { - std::vector artists {splitAndTrimString(*value, "/;")}; // Picard separator is '/' - std::vector artistsMBID {getMusicBrainzArtistID(properties)}; - - for (std::size_t i {}; i < artists.size(); ++i) - res.emplace_back(Artist{std::move(artists[i]), artistsMBID.size() == artists.size() ? std::move(artistsMBID[i]) : ""}); + std::vector artistNames {getPropertyValues(properties, "ARTISTS")}; + if (artistNames.empty()) + artistNames = getPropertyValues(properties, "ARTIST"); + if (artistNames.empty()) return res; - } - value = getPropertyValue(properties, "ARTIST"); - if (value) - res.emplace_back(Artist{std::move(*value), ""}); + const std::vector artistsMBID {getPropertyValues(properties, "MUSICBRAINZ_ARTISTID")}; + + if (artistNames.size() == artistsMBID.size()) + { + std::transform(std::cbegin(artistNames), std::cend(artistNames), std::cbegin(artistsMBID), std::back_inserter(res), + [&](const std::string& name, const std::string& mbid) { return Artist{name, mbid}; }); + } + else + { + std::transform(std::cbegin(artistNames), std::cend(artistNames), std::back_inserter(res), + [&](const std::string& name) { return Artist{name, ""}; }); + } return res; } static -boost::optional -getAlbumArtist(const TagLib::PropertyMap& properties) +std::vector +getAlbumArtists(const TagLib::PropertyMap& properties) { - boost::optional res; + std::vector res; - boost::optional value; - - value = getPropertyValue(properties, "ALBUMARTIST"); - if (!value) + std::vector artistNames {getPropertyValues(properties, "ALBUMARTIST")}; + if (artistNames.empty()) return res; - res = Artist{std::move(*value), ""}; + const std::vector artistsMBID {getPropertyValues(properties, "MUSICBRAINZ_ALBUMARTISTID")}; - value = getPropertyValue(properties, "MUSICBRAINZ_ALBUMARTISTID"); - if (value) - res->musicBrainzArtistID = std::move(*value); + if (artistNames.size() == artistsMBID.size()) + { + std::transform(std::cbegin(artistNames), std::cend(artistNames), std::cbegin(artistsMBID), std::back_inserter(res), + [&](const std::string& name, const std::string& mbid) { return Artist{name, mbid}; }); + } + else + { + std::transform(std::cbegin(artistNames), std::cend(artistNames), std::back_inserter(res), + [&](const std::string& name) { return Artist{name, ""}; }); + } return res; } - static boost::optional getAlbum(const TagLib::PropertyMap& properties) { boost::optional res; - boost::optional value {getPropertyValue(properties, "ALBUM")}; - if (!value) + std::vector albumName {getPropertyValues(properties, "ALBUM")}; + if (albumName.empty()) return res; - res = Album{std::move(*value), ""}; + std::vector albumMBID {getPropertyValues(properties, "MUSICBRAINZ_ALBUMID")}; - boost::optional mbid {getPropertyValue(properties, "MUSICBRAINZ_ALBUMID")}; - if (mbid) - res->musicBrainzAlbumID = std::move(*mbid); + res = Album{std::move(albumName.front()), ""}; + + if (!albumMBID.empty()) + res->musicBrainzAlbumID = std::move(albumMBID.front()); return res; } @@ -192,7 +184,7 @@ TagLibParser::parse(const boost::filesystem::path& p, bool debug) std::vector strs; std::transform(values.begin(), values.end(), std::back_inserter(strs), [](const auto& value) { return value.to8Bit(true); }); - std::cout << "[" << tag << "] = " << joinStrings(strs, ",") << std::endl; + std::cout << "[" << tag << "] = " << joinStrings(strs, "*SEP*") << std::endl; } if (tag.empty() || values.isEmpty() || values.front().isEmpty()) @@ -288,7 +280,7 @@ TagLibParser::parse(const boost::filesystem::path& p, bool debug) } track.artists = getArtists(properties); - track.albumArtist = getAlbumArtist(properties); + track.albumArtists = getAlbumArtists(properties); track.album = getAlbum(properties); } diff --git a/tools/metadata/LmsMetadata.cpp b/tools/metadata/LmsMetadata.cpp index d03b14e2..a027748b 100644 --- a/tools/metadata/LmsMetadata.cpp +++ b/tools/metadata/LmsMetadata.cpp @@ -49,8 +49,8 @@ void parse(MetaData::Parser& parser, const boost::filesystem::path& file) for (const Artist& artist : track->artists) std::cout << "Artist: " << artist << std::endl; - if (track->albumArtist) - std::cout << "Album artist: " << *track->albumArtist << std::endl; + for (const Artist& artist: track->albumArtists) + std::cout << "Album artist: " << artist << std::endl; if (track->album) std::cout << "Album: " << *track->album << std::endl;