Generalized 'disc' to 'medium' in tag parser

This commit is contained in:
emeric
2023-03-07 17:11:36 +01:00
parent 3a9bde0092
commit 59eff32377
5 changed files with 113 additions and 104 deletions
+18 -14
View File
@@ -77,7 +77,7 @@ getRelease(const Av::IAudioFile::MetadataMap& metadataMap)
res.emplace(); res.emplace();
res->name = *releaseName; res->name = *releaseName;
res->releaseMBID = findFirstValueOfAs<UUID>(metadataMap, {"MUSICBRAINZ ALBUM ID", "MUSICBRAINZ_ALBUMID", "MUSICBRAINZ/ALBUM ID"}); res->mbid = findFirstValueOfAs<UUID>(metadataMap, {"MUSICBRAINZ ALBUM ID", "MUSICBRAINZ_ALBUMID", "MUSICBRAINZ/ALBUM ID"});
return res; return res;
} }
@@ -149,20 +149,20 @@ AvFormatParser::parse(const std::filesystem::path& p, bool debug)
track.duration = mediaFile->getDuration(); track.duration = mediaFile->getDuration();
track.hasCover = mediaFile->hasAttachedPictures(); track.hasCover = mediaFile->hasAttachedPictures();
MetaData::Clusters clusters; MetaData::Tags tags;
const Av::IAudioFile::MetadataMap metadataMap {mediaFile->getMetaData()}; const Av::IAudioFile::MetadataMap metadataMap {mediaFile->getMetaData()};
track.artists = getArtists(metadataMap); track.artists = getArtists(metadataMap);
track.release = getRelease(metadataMap); track.release = getRelease(metadataMap);
if (track.release) if (track.release)
track.release->releaseArtists = getReleaseArtists(metadataMap); track.release->artists = getReleaseArtists(metadataMap);
auto getOrCreateDisc = [&]() -> Disc& auto getOrCreateMedium = [&]() -> Medium&
{ {
if (!track.disc) if (!track.medium)
track.disc.emplace(); track.medium.emplace();
return *track.disc; return *track.medium;
}; };
for (const auto& [tag, value] : metadataMap) for (const auto& [tag, value] : metadataMap)
@@ -178,10 +178,10 @@ AvFormatParser::parse(const std::filesystem::path& p, bool debug)
const std::vector<std::string_view> strings {StringUtils::splitString(value, "/") }; const std::vector<std::string_view> strings {StringUtils::splitString(value, "/") };
if (strings.size() > 0) if (strings.size() > 0)
{ {
track.trackNumber = StringUtils::readAs<std::size_t>(strings[0]); track.position = StringUtils::readAs<std::size_t>(strings[0]);
if (strings.size() > 1) if (strings.size() > 1)
getOrCreateDisc().totalTrack = StringUtils::readAs<std::size_t>(strings[1]); getOrCreateMedium().trackCount = StringUtils::readAs<std::size_t>(strings[1]);
} }
} }
else if (tag == "DISC") else if (tag == "DISC")
@@ -190,10 +190,10 @@ AvFormatParser::parse(const std::filesystem::path& p, bool debug)
const std::vector<std::string_view> strings {StringUtils::splitString(value, "/")}; const std::vector<std::string_view> strings {StringUtils::splitString(value, "/")};
if (strings.size() > 0) if (strings.size() > 0)
{ {
track.discNumber = StringUtils::readAs<std::size_t>(strings[0]); getOrCreateMedium().position = StringUtils::readAs<std::size_t>(strings[0]);
if (strings.size() > 1 && track.release) if (strings.size() > 1 && track.release)
track.release->totalDisc = StringUtils::readAs<std::size_t>(strings[1]); track.release->mediumCount = StringUtils::readAs<std::size_t>(strings[1]);
} }
} }
else if (tag == "DATE" else if (tag == "DATE"
@@ -214,18 +214,22 @@ AvFormatParser::parse(const std::filesystem::path& p, bool debug)
else if (tag == "MUSICBRAINZ RELEASE TRACK ID" else if (tag == "MUSICBRAINZ RELEASE TRACK ID"
|| tag == "MUSICBRAINZ_RELEASETRACKID") || tag == "MUSICBRAINZ_RELEASETRACKID")
{ {
track.trackMBID = UUID::fromString(value); track.mbid = UUID::fromString(value);
} }
else if (tag == "MUSICBRAINZ_TRACKID" else if (tag == "MUSICBRAINZ_TRACKID"
|| tag == "MUSICBRAINZ/TRACK ID") || tag == "MUSICBRAINZ/TRACK ID")
{ {
track.recordingMBID = UUID::fromString(value); track.recordingMBID = UUID::fromString(value);
} }
else if (tag == "MEDIA")
{
getOrCreateMedium().type = value;
}
else if (tag == "TSST" else if (tag == "TSST"
|| tag == "DISCSUBTITLE" || tag == "DISCSUBTITLE"
|| tag == "SETSUBTITLE") || tag == "SETSUBTITLE")
{ {
getOrCreateDisc().subtitle = value; getOrCreateMedium().name = value;
} }
else if (_clusterTypeNames.find(tag) != _clusterTypeNames.end()) else if (_clusterTypeNames.find(tag) != _clusterTypeNames.end())
{ {
@@ -237,7 +241,7 @@ AvFormatParser::parse(const std::filesystem::path& p, bool debug)
std::transform(std::cbegin(clusterNames), std::cend(clusterNames), std::transform(std::cbegin(clusterNames), std::cend(clusterNames),
std::inserter(values, std::begin(values)), std::inserter(values, std::begin(values)),
[](std::string_view clusterName) { return std::string {clusterName}; }); [](std::string_view clusterName) { return std::string {clusterName}; });
track.clusters[tag] = std::move(values); track.tags[tag] = std::move(values);
} }
} }
} }
+22 -21
View File
@@ -131,7 +131,7 @@ getArtists(const TagMap& tags,
if (artistNames.size() == artistsMBID.size()) if (artistNames.size() == artistsMBID.size())
{ {
for (std::size_t i {}; i < artistsMBID.size(); ++i) for (std::size_t i {}; i < artistsMBID.size(); ++i)
artists[i].artistMBID = artistsMBID[i]; artists[i].mbid = artistsMBID[i];
} }
} }
@@ -194,7 +194,7 @@ getRelease(const TagMap& tags)
release.emplace(); release.emplace();
release->name = std::move(releaseName.front()); release->name = std::move(releaseName.front());
if (!releaseMBID.empty()) if (!releaseMBID.empty())
release->releaseMBID = releaseMBID.front(); release->mbid = releaseMBID.front();
return release; return release;
} }
@@ -227,11 +227,11 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector
if (tag.empty() || values.empty()) if (tag.empty() || values.empty())
return; return;
auto getOrCreateDisc = [&]() -> Disc& auto getOrCreateMedium = [&]() -> Medium&
{ {
if (!track.disc) if (!track.medium)
track.disc.emplace(); track.medium.emplace();
return *track.disc; return *track.medium;
}; };
std::string_view value {values.front()}; std::string_view value {values.front()};
@@ -242,7 +242,7 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector
|| tag == "MUSICBRAINZ RELEASE TRACK ID" || tag == "MUSICBRAINZ RELEASE TRACK ID"
|| tag == "MUSICBRAINZ/RELEASE TRACK ID") || tag == "MUSICBRAINZ/RELEASE TRACK ID")
{ {
track.trackMBID = UUID::fromString(value); track.mbid = UUID::fromString(value);
} }
else if (tag == "MUSICBRAINZ_TRACKID" else if (tag == "MUSICBRAINZ_TRACKID"
|| tag == "MUSICBRAINZ TRACK ID" || tag == "MUSICBRAINZ TRACK ID"
@@ -252,7 +252,7 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector
track.acoustID = UUID::fromString(value); track.acoustID = UUID::fromString(value);
else if (tag == "TRACKTOTAL") else if (tag == "TRACKTOTAL")
{ {
getOrCreateDisc().totalTrack = StringUtils::readAs<std::size_t>(value); getOrCreateMedium().trackCount = StringUtils::readAs<std::size_t>(value);
} }
else if (tag == "TRACKNUMBER") else if (tag == "TRACKNUMBER")
{ {
@@ -261,17 +261,17 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector
if (!strings.empty()) if (!strings.empty())
{ {
track.trackNumber = StringUtils::readAs<std::size_t>(strings[0]); track.position = StringUtils::readAs<std::size_t>(strings[0]);
// Lower priority than TRACKTOTAL // Lower priority than TRACKTOTAL
if (strings.size() > 1 && !getOrCreateDisc().totalTrack) if (strings.size() > 1 && !getOrCreateMedium().trackCount)
getOrCreateDisc().totalTrack = StringUtils::readAs<std::size_t>(strings[1]); getOrCreateMedium().trackCount = StringUtils::readAs<std::size_t>(strings[1]);
} }
} }
else if (tag == "DISCTOTAL") else if (tag == "DISCTOTAL")
{ {
if (track.release) if (track.release)
track.release->totalDisc = StringUtils::readAs<std::size_t>(value); track.release->mediumCount = StringUtils::readAs<std::size_t>(value);
} }
else if (tag == "DISCNUMBER") else if (tag == "DISCNUMBER")
{ {
@@ -279,11 +279,11 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector
std::vector<std::string_view> strings {StringUtils::splitString(value, "/")}; std::vector<std::string_view> strings {StringUtils::splitString(value, "/")};
if (!strings.empty()) if (!strings.empty())
{ {
track.discNumber = StringUtils::readAs<std::size_t>(strings[0]); getOrCreateMedium().position = StringUtils::readAs<std::size_t>(strings[0]);
// Lower priority than DISCTOTAL // Lower priority than DISCTOTAL
if (strings.size() > 1 && track.release && !track.release->totalDisc) if (strings.size() > 1 && track.release && !track.release->mediumCount)
track.release->totalDisc = StringUtils::readAs<std::size_t>(strings[1]); track.release->mediumCount = StringUtils::readAs<std::size_t>(strings[1]);
} }
} }
else if (tag == "DATE") else if (tag == "DATE")
@@ -315,24 +315,25 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector
else if (tag == "COPYRIGHTURL") else if (tag == "COPYRIGHTURL")
track.copyrightURL = value; track.copyrightURL = value;
else if (tag == "REPLAYGAIN_ALBUM_GAIN") else if (tag == "REPLAYGAIN_ALBUM_GAIN")
getOrCreateDisc().replayGain = StringUtils::readAs<float>(value); getOrCreateMedium().replayGain = StringUtils::readAs<float>(value);
else if (tag == "REPLAYGAIN_TRACK_GAIN") else if (tag == "REPLAYGAIN_TRACK_GAIN")
track.replayGain = StringUtils::readAs<float>(value); track.replayGain = StringUtils::readAs<float>(value);
else if (tag == "DISCSUBTITLE" || tag == "SETSUBTITLE") else if (tag == "DISCSUBTITLE" || tag == "SETSUBTITLE")
getOrCreateDisc().subtitle = value; getOrCreateMedium().name = value;
else if (tag == "MEDIA")
getOrCreateMedium().type = value;
else if (_clusterTypeNames.find(tag) != _clusterTypeNames.end()) else if (_clusterTypeNames.find(tag) != _clusterTypeNames.end())
{ {
std::set<std::string> clusterNames; std::set<std::string> clusterNames;
for (const auto& valueList : values) for (std::string_view valueList : values)
{ {
const std::vector<std::string_view> splittedValues {splitAndTrimString(valueList, "/,;")}; const std::vector<std::string_view> splittedValues {splitAndTrimString(valueList, "/,;")};
for (std::string_view value : splittedValues) for (std::string_view value : splittedValues)
clusterNames.insert(std::string {value}); clusterNames.insert(std::string {value});
} }
if (!clusterNames.empty()) if (!clusterNames.empty())
track.clusters[tag] = clusterNames; track.tags[tag] = std::move(clusterNames);
} }
} }
@@ -493,7 +494,7 @@ TagLibParser::parse(const std::filesystem::path& p, bool debug)
track.release = getRelease(tags); track.release = getRelease(tags);
if (track.release) if (track.release)
track.release->releaseArtists = getArtists(tags, {"ALBUMARTISTS", "ALBUMARTIST"}, {"ALBUMARTISTSSORT", "ALBUMARTISTSORT"}, {"MUSICBRAINZ_ALBUMARTISTID", "MUSICBRAINZ ALBUM ARTIST ID", "MUSICBRAINZ/ALBUM ARTIST ID"}); track.release->artists = getArtists(tags, {"ALBUMARTISTS", "ALBUMARTIST"}, {"ALBUMARTISTSSORT", "ALBUMARTISTSORT"}, {"MUSICBRAINZ_ALBUMARTISTID", "MUSICBRAINZ ALBUM ARTIST ID", "MUSICBRAINZ/ALBUM ARTIST ID"});
track.artists = getArtists(tags, {"ARTISTS", "ARTIST"}, {"ARTISTSORT"}, {"MUSICBRAINZ_ARTISTID", "MUSICBRAINZ ARTIST ID", "MUSICBRAINZ/ARTIST ID"}); track.artists = getArtists(tags, {"ARTISTS", "ARTIST"}, {"ARTISTSORT"}, {"MUSICBRAINZ_ARTISTID", "MUSICBRAINZ ARTIST ID", "MUSICBRAINZ/ARTIST ID"});
track.conductorArtists = getArtists(tags, {"CONDUCTORS", "CONDUCTOR"}, {"CONDUCTORSSORT", "CONDUCTORSORT"}, {}); track.conductorArtists = getArtists(tags, {"CONDUCTORS", "CONDUCTOR"}, {"CONDUCTORSSORT", "CONDUCTORSORT"}, {});
track.composerArtists = getArtists(tags, {"COMPOSERS", "COMPOSER"}, {"COMPOSERSSORT", "COMPOSERSORT"}, {}); track.composerArtists = getArtists(tags, {"COMPOSERS", "COMPOSER"}, {"COMPOSERSSORT", "COMPOSERSORT"}, {});
+17 -16
View File
@@ -33,16 +33,16 @@
namespace MetaData namespace MetaData
{ {
using Clusters = std::map<std::string /* type */, std::set<std::string> /* names */>; using Tags = std::map<std::string /* type */, std::set<std::string> /* names */>;
struct Artist struct Artist
{ {
std::string name; std::string name;
std::optional<std::string> sortName; std::optional<std::string> sortName;
std::optional<UUID> artistMBID; std::optional<UUID> mbid;
Artist(std::string_view _name) : name {_name} {} Artist(std::string_view _name) : name {_name} {}
Artist(std::string_view _name, std::optional<std::string> _sortName, std::optional<UUID> _artistMBID) : name {_name}, sortName {std::move(_sortName)}, artistMBID {std::move(_artistMBID)} {} Artist(std::string_view _name, std::optional<std::string> _sortName, std::optional<UUID> _mbid) : name {_name}, sortName {std::move(_sortName)}, mbid {std::move(_mbid)} {}
}; };
using PerformerContainer = std::map<std::string /*role*/, std::vector<Artist>>; using PerformerContainer = std::map<std::string /*role*/, std::vector<Artist>>;
@@ -50,16 +50,18 @@ namespace MetaData
struct Release struct Release
{ {
std::string name; std::string name;
std::vector<Artist> releaseArtists; std::vector<Artist> artists;
std::optional<UUID> releaseMBID; std::optional<UUID> mbid;
std::optional<std::size_t> totalDisc; std::optional<std::size_t> mediumCount;
}; };
struct Disc struct Medium
{ {
std::string subtitle; std::optional<std::size_t> position;
std::string type;
std::string name;
std::optional<float> replayGain; std::optional<float> replayGain;
std::optional<std::size_t> totalTrack; std::optional<std::size_t> trackCount;
}; };
struct AudioStream struct AudioStream
@@ -71,14 +73,13 @@ namespace MetaData
{ {
std::vector<Artist> artists; std::vector<Artist> artists;
std::string title; std::string title;
std::optional<UUID> trackMBID; std::optional<UUID> mbid;
std::optional<UUID> recordingMBID; std::optional<UUID> recordingMBID;
std::optional<Release> release; std::optional<Release> release;
std::optional<Disc> disc; std::optional<Medium> medium;
Clusters clusters; Tags tags;
std::chrono::milliseconds duration; std::chrono::milliseconds duration;
std::optional<std::size_t> trackNumber; std::optional<std::size_t> position; // in medium
std::optional<std::size_t> discNumber;
Wt::WDate date; Wt::WDate date;
Wt::WDate originalDate; Wt::WDate originalDate;
bool hasCover {}; bool hasCover {};
@@ -42,8 +42,8 @@ namespace
{ {
Artist::pointer artist {session.create<Artist>(artistInfo.name)}; Artist::pointer artist {session.create<Artist>(artistInfo.name)};
if (artistInfo.artistMBID) if (artistInfo.mbid)
artist.modify()->setMBID(*artistInfo.artistMBID); artist.modify()->setMBID(*artistInfo.mbid);
if (artistInfo.sortName) if (artistInfo.sortName)
artist.modify()->setSortName(*artistInfo.sortName); artist.modify()->setSortName(*artistInfo.sortName);
@@ -76,9 +76,9 @@ namespace
Artist::pointer artist; Artist::pointer artist;
// First try to get by MBID // First try to get by MBID
if (artistInfo.artistMBID) if (artistInfo.mbid)
{ {
artist = Artist::find(session, *artistInfo.artistMBID); artist = Artist::find(session, *artistInfo.mbid);
if (!artist) if (!artist)
artist = createArtist(session, artistInfo); artist = createArtist(session, artistInfo);
else else
@@ -120,8 +120,8 @@ namespace
{ {
if (release->getName() != releaseInfo.name) if (release->getName() != releaseInfo.name)
release.modify()->setName(releaseInfo.name); release.modify()->setName(releaseInfo.name);
if (release->getTotalDisc() != releaseInfo.totalDisc) if (release->getTotalDisc() != releaseInfo.mediumCount)
release.modify()->setTotalDisc(releaseInfo.totalDisc); release.modify()->setTotalDisc(releaseInfo.mediumCount);
} }
Release::pointer Release::pointer
@@ -130,11 +130,11 @@ namespace
Release::pointer release; Release::pointer release;
// First try to get by MBID // First try to get by MBID
if (releaseInfo.releaseMBID) if (releaseInfo.mbid)
{ {
release = Release::find(session, *releaseInfo.releaseMBID); release = Release::find(session, *releaseInfo.mbid);
if (!release) if (!release)
release = session.create<Release>(releaseInfo.name, releaseInfo.releaseMBID); release = session.create<Release>(releaseInfo.name, releaseInfo.mbid);
updateReleaseIfNeeded(release, releaseInfo); updateReleaseIfNeeded(release, releaseInfo);
return release; return release;
@@ -165,17 +165,17 @@ namespace
} }
std::vector<Cluster::pointer> std::vector<Cluster::pointer>
getOrCreateClusters(Session& session, const MetaData::Clusters& clustersNames) getOrCreateClusters(Session& session, const MetaData::Tags& tags)
{ {
std::vector< Cluster::pointer > clusters; std::vector<Cluster::pointer> clusters;
for (auto clusterNames : clustersNames) for (const auto& [tag, values] : tags)
{ {
auto clusterType = ClusterType::find(session, clusterNames.first); auto clusterType = ClusterType::find(session, tag);
if (!clusterType) if (!clusterType)
continue; continue;
for (auto clusterName : clusterNames.second) for (auto clusterName : values)
{ {
auto cluster = clusterType->getCluster(clusterName); auto cluster = clusterType->getCluster(clusterName);
if (!cluster) if (!cluster)
@@ -287,9 +287,9 @@ namespace Scanner
Track::pointer track {Track::findByPath(dbSession, file) }; Track::pointer track {Track::findByPath(dbSession, file) };
if (trackInfo->trackMBID && (!track || _settings.skipDuplicateMBID)) if (trackInfo->mbid && (!track || _settings.skipDuplicateMBID))
{ {
std::vector<Track::pointer> duplicateTracks {Track::findByMBID(dbSession, *trackInfo->trackMBID)}; std::vector<Track::pointer> duplicateTracks {Track::findByMBID(dbSession, *trackInfo->mbid)};
// find for existing MBIDs as the file may have just been moved // find for existing MBIDs as the file may have just been moved
if (!track && duplicateTracks.size() == 1) if (!track && duplicateTracks.size() == 1)
@@ -395,7 +395,7 @@ namespace Scanner
if (trackInfo->release) if (trackInfo->release)
{ {
for (const Artist::pointer& releaseArtist : getOrCreateArtists(dbSession, trackInfo->release->releaseArtists, false)) for (const Artist::pointer& releaseArtist : getOrCreateArtists(dbSession, trackInfo->release->artists, false))
track.modify()->addArtistLink(TrackArtistLink::create(dbSession, track, releaseArtist, TrackArtistLinkType::ReleaseArtist)); track.modify()->addArtistLink(TrackArtistLink::create(dbSession, track, releaseArtist, TrackArtistLinkType::ReleaseArtist));
} }
@@ -430,16 +430,16 @@ namespace Scanner
track.modify()->setRelease(getOrCreateRelease(dbSession, *trackInfo->release)); track.modify()->setRelease(getOrCreateRelease(dbSession, *trackInfo->release));
else else
track.modify()->setRelease({}); track.modify()->setRelease({});
track.modify()->setTotalTrack(trackInfo->disc ? trackInfo->disc->totalTrack : std::nullopt); track.modify()->setTotalTrack(trackInfo->medium ? trackInfo->medium->trackCount : std::nullopt);
track.modify()->setReleaseReplayGain(trackInfo->disc ? trackInfo->disc->replayGain : std::nullopt); track.modify()->setReleaseReplayGain(trackInfo->medium ? trackInfo->medium->replayGain : std::nullopt);
track.modify()->setDiscSubtitle(trackInfo->disc ? trackInfo->disc->subtitle : ""); track.modify()->setDiscSubtitle(trackInfo->medium ? trackInfo->medium->name : "");
track.modify()->setClusters(getOrCreateClusters(dbSession, trackInfo->clusters)); track.modify()->setClusters(getOrCreateClusters(dbSession, trackInfo->tags));
track.modify()->setLastWriteTime(lastWriteTime); track.modify()->setLastWriteTime(lastWriteTime);
track.modify()->setName(title); track.modify()->setName(title);
track.modify()->setDuration(trackInfo->duration); track.modify()->setDuration(trackInfo->duration);
track.modify()->setAddedTime(Wt::WDateTime::currentDateTime()); track.modify()->setAddedTime(Wt::WDateTime::currentDateTime());
track.modify()->setTrackNumber(trackInfo->trackNumber ? *trackInfo->trackNumber : 0); track.modify()->setTrackNumber(trackInfo->position);
track.modify()->setDiscNumber(trackInfo->discNumber ? *trackInfo->discNumber : 0); track.modify()->setDiscNumber(trackInfo->medium ? trackInfo->medium->position : std::nullopt);
track.modify()->setDate(trackInfo->date); track.modify()->setDate(trackInfo->date);
track.modify()->setOriginalDate(trackInfo->originalDate); track.modify()->setOriginalDate(trackInfo->originalDate);
@@ -448,7 +448,7 @@ namespace Scanner
track.modify()->setDate(trackInfo->originalDate); track.modify()->setDate(trackInfo->originalDate);
track.modify()->setRecordingMBID(trackInfo->recordingMBID); track.modify()->setRecordingMBID(trackInfo->recordingMBID);
track.modify()->setTrackMBID(trackInfo->trackMBID); track.modify()->setTrackMBID(trackInfo->mbid);
if (auto trackFeatures {TrackFeatures::find(dbSession, track->getId())}) if (auto trackFeatures {TrackFeatures::find(dbSession, track->getId())})
trackFeatures.remove(); // TODO: only if MBID changed? trackFeatures.remove(); // TODO: only if MBID changed?
track.modify()->setHasCover(trackInfo->hasCover); track.modify()->setHasCover(trackInfo->hasCover);
+32 -29
View File
@@ -35,8 +35,8 @@ operator<<(std::ostream& os, const MetaData::Artist& artist)
{ {
os << artist.name; os << artist.name;
if (artist.artistMBID) if (artist.mbid)
os << " (" << artist.artistMBID->getAsString() << ")"; os << " (" << artist.mbid->getAsString() << ")";
if (artist.sortName) if (artist.sortName)
os << " '" << *artist.sortName << "'"; os << " '" << *artist.sortName << "'";
@@ -50,30 +50,36 @@ operator<<(std::ostream& os, const MetaData::Release& release)
{ {
os << release.name; os << release.name;
if (release.releaseMBID) if (release.mbid)
os << " (" << release.releaseMBID->getAsString() << ")" << std::endl; os << " (" << release.mbid->getAsString() << ")" << std::endl;
if (release.totalDisc) if (release.mediumCount)
std::cout << "\tTotalDisc: " << *release.totalDisc << std::endl; std::cout << "\tMediumCount: " << *release.mediumCount << std::endl;
for (const MetaData::Artist& artist : release.releaseArtists) for (const MetaData::Artist& artist : release.artists)
std::cout << "\tAlbum artist: " << artist << std::endl; std::cout << "\tRelease artist: " << artist << std::endl;
return os; return os;
} }
static static
std::ostream& std::ostream&
operator<<(std::ostream& os, const MetaData::Disc& disc) operator<<(std::ostream& os, const MetaData::Medium& medium)
{ {
if (!disc.subtitle.empty()) if (!medium.name.empty())
os << disc.subtitle << std::endl; os << medium.name << std::endl;
if (disc.totalTrack) if (medium.position)
std::cout << "\tTotalTrack: " << *disc.totalTrack << std::endl; os << "\tPosition: " << *medium.position << std::endl;
if (disc.replayGain) if (!medium.type.empty())
std::cout << "\tDisc replay gain: " << *disc.replayGain << std::endl; os << "\tType: " << medium.type << std::endl;
if (medium.trackCount)
std::cout << "\tTrackCount: " << *medium.trackCount << std::endl;
if (medium.replayGain)
std::cout << "\tReplay gain: " << *medium.replayGain << std::endl;
return os; return os;
} }
@@ -131,33 +137,30 @@ void parse(MetaData::IParser& parser, const std::filesystem::path& file)
if (track->release) if (track->release)
std::cout << "Release: " << *track->release; std::cout << "Release: " << *track->release;
if (track->disc) if (track->medium)
std::cout << "Disc: " << *track->disc; std::cout << "Medium: " << *track->medium;
std::cout << "Title: " << track->title << std::endl; std::cout << "Title: " << track->title << std::endl;
if (track->trackMBID) if (track->mbid)
std::cout << "track MBID = " << track->trackMBID->getAsString() << std::endl; std::cout << "Track MBID = " << track->mbid->getAsString() << std::endl;
if (track->recordingMBID) if (track->recordingMBID)
std::cout << "recording MBID = " << track->recordingMBID->getAsString() << std::endl; std::cout << "Recording MBID = " << track->recordingMBID->getAsString() << std::endl;
for (const auto& cluster : track->clusters) for (const auto& [tag, values] : track->tags)
{ {
std::cout << "Cluster: " << cluster.first << std::endl; std::cout << "Tag: " << tag << std::endl;
for (const auto& name : cluster.second) for (const auto& value : values)
{ {
std::cout << "\t" << name << std::endl; std::cout << "\t" << value << std::endl;
} }
} }
std::cout << "Duration: " << std::fixed << std::setprecision(2) << track->duration.count() / 1000. << "s" << std::endl; std::cout << "Duration: " << std::fixed << std::setprecision(2) << track->duration.count() / 1000. << "s" << std::endl;
if (track->trackNumber) if (track->position)
std::cout << "Track: " << *track->trackNumber << std::endl; std::cout << "Position: " << *track->position << std::endl;
if (track->discNumber)
std::cout << "Disc: " << *track->discNumber << std::endl;
if (track->date.isValid()) if (track->date.isValid())
std::cout << "Date: " << track->date.toString("yyyy-MM-dd") << std::endl; std::cout << "Date: " << track->date.toString("yyyy-MM-dd") << std::endl;