properly handle multi tags like MP3 ID3 v2.4 tags

This commit is contained in:
emeric
2019-03-23 14:58:29 +01:00
parent 368766974e
commit 03074cedc8
4 changed files with 60 additions and 70 deletions
+11 -13
View File
@@ -61,24 +61,22 @@ getAlbum(const MetadataMap& metadataMap)
}
static
boost::optional<Artist>
getAlbumArtist(const MetadataMap& metadataMap)
std::vector<Artist>
getAlbumArtists(const MetadataMap& metadataMap)
{
boost::optional<Artist> res;
std::vector<Artist> 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)
{
+1 -1
View File
@@ -50,7 +50,7 @@ namespace MetaData
struct Track
{
std::vector<Artist> artists;
boost::optional<Artist> albumArtist;
std::vector<Artist> albumArtists;
std::string title;
std::string musicBrainzTrackID;
std::string musicBrainzRecordID;
+46 -54
View File
@@ -31,18 +31,15 @@
namespace MetaData
{
boost::optional<std::string>
getPropertyValue(const TagLib::PropertyMap& properties, const std::string& key)
std::vector<std::string>
getPropertyValues(const TagLib::PropertyMap& properties, const std::string& key)
{
boost::optional<std::string> res;
std::vector<std::string> 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<std::string>
getMusicBrainzArtistID(const TagLib::PropertyMap& properties)
{
boost::optional<std::string> value {getPropertyValue(properties, "MUSICBRAINZ_ARTISTID")};
if (!value)
return {};
return splitAndTrimString(*value, "/"); // Picard separator is '/'
}
static
std::vector<Artist>
getArtists(const TagLib::PropertyMap& properties)
{
std::vector<Artist> res;
boost::optional<std::string> value;
value = getPropertyValue(properties, "ARTISTS");
if (value)
{
std::vector<std::string> artists {splitAndTrimString(*value, "/;")}; // Picard separator is '/'
std::vector<std::string> 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<std::string> 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<std::string> 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<Artist>
getAlbumArtist(const TagLib::PropertyMap& properties)
std::vector<Artist>
getAlbumArtists(const TagLib::PropertyMap& properties)
{
boost::optional<Artist> res;
std::vector<Artist> res;
boost::optional<std::string> value;
value = getPropertyValue(properties, "ALBUMARTIST");
if (!value)
std::vector<std::string> artistNames {getPropertyValues(properties, "ALBUMARTIST")};
if (artistNames.empty())
return res;
res = Artist{std::move(*value), ""};
const std::vector<std::string> 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<Album>
getAlbum(const TagLib::PropertyMap& properties)
{
boost::optional<Album> res;
boost::optional<std::string> value {getPropertyValue(properties, "ALBUM")};
if (!value)
std::vector<std::string> albumName {getPropertyValues(properties, "ALBUM")};
if (albumName.empty())
return res;
res = Album{std::move(*value), ""};
std::vector<std::string> albumMBID {getPropertyValues(properties, "MUSICBRAINZ_ALBUMID")};
boost::optional<std::string> 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<std::string> 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);
}
+2 -2
View File
@@ -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;