From 59eff32377995cf4ba13ec3d4c3e5d2a0863a378 Mon Sep 17 00:00:00 2001 From: emeric Date: Tue, 7 Mar 2023 17:11:36 +0100 Subject: [PATCH] Generalized 'disc' to 'medium' in tag parser --- src/libs/metadata/impl/AvFormatParser.cpp | 32 +++++----- src/libs/metadata/impl/TagLibParser.cpp | 43 ++++++------- .../metadata/include/metadata/IParser.hpp | 33 +++++----- .../scanner/impl/ScanStepScanFiles.cpp | 48 +++++++-------- src/tools/metadata/LmsMetadata.cpp | 61 ++++++++++--------- 5 files changed, 113 insertions(+), 104 deletions(-) diff --git a/src/libs/metadata/impl/AvFormatParser.cpp b/src/libs/metadata/impl/AvFormatParser.cpp index adba14a4..08cea3de 100644 --- a/src/libs/metadata/impl/AvFormatParser.cpp +++ b/src/libs/metadata/impl/AvFormatParser.cpp @@ -77,7 +77,7 @@ getRelease(const Av::IAudioFile::MetadataMap& metadataMap) res.emplace(); res->name = *releaseName; - res->releaseMBID = findFirstValueOfAs(metadataMap, {"MUSICBRAINZ ALBUM ID", "MUSICBRAINZ_ALBUMID", "MUSICBRAINZ/ALBUM ID"}); + res->mbid = findFirstValueOfAs(metadataMap, {"MUSICBRAINZ ALBUM ID", "MUSICBRAINZ_ALBUMID", "MUSICBRAINZ/ALBUM ID"}); return res; } @@ -149,20 +149,20 @@ AvFormatParser::parse(const std::filesystem::path& p, bool debug) track.duration = mediaFile->getDuration(); track.hasCover = mediaFile->hasAttachedPictures(); - MetaData::Clusters clusters; + MetaData::Tags tags; const Av::IAudioFile::MetadataMap metadataMap {mediaFile->getMetaData()}; track.artists = getArtists(metadataMap); track.release = getRelease(metadataMap); if (track.release) - track.release->releaseArtists = getReleaseArtists(metadataMap); + track.release->artists = getReleaseArtists(metadataMap); - auto getOrCreateDisc = [&]() -> Disc& + auto getOrCreateMedium = [&]() -> Medium& { - if (!track.disc) - track.disc.emplace(); - return *track.disc; + if (!track.medium) + track.medium.emplace(); + return *track.medium; }; for (const auto& [tag, value] : metadataMap) @@ -178,10 +178,10 @@ AvFormatParser::parse(const std::filesystem::path& p, bool debug) const std::vector strings {StringUtils::splitString(value, "/") }; if (strings.size() > 0) { - track.trackNumber = StringUtils::readAs(strings[0]); + track.position = StringUtils::readAs(strings[0]); if (strings.size() > 1) - getOrCreateDisc().totalTrack = StringUtils::readAs(strings[1]); + getOrCreateMedium().trackCount = StringUtils::readAs(strings[1]); } } else if (tag == "DISC") @@ -190,10 +190,10 @@ AvFormatParser::parse(const std::filesystem::path& p, bool debug) const std::vector strings {StringUtils::splitString(value, "/")}; if (strings.size() > 0) { - track.discNumber = StringUtils::readAs(strings[0]); + getOrCreateMedium().position = StringUtils::readAs(strings[0]); if (strings.size() > 1 && track.release) - track.release->totalDisc = StringUtils::readAs(strings[1]); + track.release->mediumCount = StringUtils::readAs(strings[1]); } } else if (tag == "DATE" @@ -214,18 +214,22 @@ AvFormatParser::parse(const std::filesystem::path& p, bool debug) else if (tag == "MUSICBRAINZ RELEASE TRACK ID" || tag == "MUSICBRAINZ_RELEASETRACKID") { - track.trackMBID = UUID::fromString(value); + track.mbid = UUID::fromString(value); } else if (tag == "MUSICBRAINZ_TRACKID" || tag == "MUSICBRAINZ/TRACK ID") { track.recordingMBID = UUID::fromString(value); } + else if (tag == "MEDIA") + { + getOrCreateMedium().type = value; + } else if (tag == "TSST" || tag == "DISCSUBTITLE" || tag == "SETSUBTITLE") { - getOrCreateDisc().subtitle = value; + getOrCreateMedium().name = value; } 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::inserter(values, std::begin(values)), [](std::string_view clusterName) { return std::string {clusterName}; }); - track.clusters[tag] = std::move(values); + track.tags[tag] = std::move(values); } } } diff --git a/src/libs/metadata/impl/TagLibParser.cpp b/src/libs/metadata/impl/TagLibParser.cpp index 62273854..a3caa7f3 100644 --- a/src/libs/metadata/impl/TagLibParser.cpp +++ b/src/libs/metadata/impl/TagLibParser.cpp @@ -131,7 +131,7 @@ getArtists(const TagMap& tags, if (artistNames.size() == artistsMBID.size()) { 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->name = std::move(releaseName.front()); if (!releaseMBID.empty()) - release->releaseMBID = releaseMBID.front(); + release->mbid = releaseMBID.front(); return release; } @@ -227,11 +227,11 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector if (tag.empty() || values.empty()) return; - auto getOrCreateDisc = [&]() -> Disc& + auto getOrCreateMedium = [&]() -> Medium& { - if (!track.disc) - track.disc.emplace(); - return *track.disc; + if (!track.medium) + track.medium.emplace(); + return *track.medium; }; 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") { - track.trackMBID = UUID::fromString(value); + track.mbid = UUID::fromString(value); } else if (tag == "MUSICBRAINZ_TRACKID" || tag == "MUSICBRAINZ TRACK ID" @@ -252,7 +252,7 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector track.acoustID = UUID::fromString(value); else if (tag == "TRACKTOTAL") { - getOrCreateDisc().totalTrack = StringUtils::readAs(value); + getOrCreateMedium().trackCount = StringUtils::readAs(value); } else if (tag == "TRACKNUMBER") { @@ -261,17 +261,17 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector if (!strings.empty()) { - track.trackNumber = StringUtils::readAs(strings[0]); + track.position = StringUtils::readAs(strings[0]); // Lower priority than TRACKTOTAL - if (strings.size() > 1 && !getOrCreateDisc().totalTrack) - getOrCreateDisc().totalTrack = StringUtils::readAs(strings[1]); + if (strings.size() > 1 && !getOrCreateMedium().trackCount) + getOrCreateMedium().trackCount = StringUtils::readAs(strings[1]); } } else if (tag == "DISCTOTAL") { if (track.release) - track.release->totalDisc = StringUtils::readAs(value); + track.release->mediumCount = StringUtils::readAs(value); } else if (tag == "DISCNUMBER") { @@ -279,11 +279,11 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector std::vector strings {StringUtils::splitString(value, "/")}; if (!strings.empty()) { - track.discNumber = StringUtils::readAs(strings[0]); + getOrCreateMedium().position = StringUtils::readAs(strings[0]); // Lower priority than DISCTOTAL - if (strings.size() > 1 && track.release && !track.release->totalDisc) - track.release->totalDisc = StringUtils::readAs(strings[1]); + if (strings.size() > 1 && track.release && !track.release->mediumCount) + track.release->mediumCount = StringUtils::readAs(strings[1]); } } else if (tag == "DATE") @@ -315,24 +315,25 @@ TagLibParser::processTag(Track& track, const std::string& tag, const std::vector else if (tag == "COPYRIGHTURL") track.copyrightURL = value; else if (tag == "REPLAYGAIN_ALBUM_GAIN") - getOrCreateDisc().replayGain = StringUtils::readAs(value); + getOrCreateMedium().replayGain = StringUtils::readAs(value); else if (tag == "REPLAYGAIN_TRACK_GAIN") track.replayGain = StringUtils::readAs(value); 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()) { std::set clusterNames; - for (const auto& valueList : values) + for (std::string_view valueList : values) { const std::vector splittedValues {splitAndTrimString(valueList, "/,;")}; - for (std::string_view value : splittedValues) clusterNames.insert(std::string {value}); } 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); 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.conductorArtists = getArtists(tags, {"CONDUCTORS", "CONDUCTOR"}, {"CONDUCTORSSORT", "CONDUCTORSORT"}, {}); track.composerArtists = getArtists(tags, {"COMPOSERS", "COMPOSER"}, {"COMPOSERSSORT", "COMPOSERSORT"}, {}); diff --git a/src/libs/metadata/include/metadata/IParser.hpp b/src/libs/metadata/include/metadata/IParser.hpp index d3adc13c..80612bd4 100644 --- a/src/libs/metadata/include/metadata/IParser.hpp +++ b/src/libs/metadata/include/metadata/IParser.hpp @@ -33,16 +33,16 @@ namespace MetaData { - using Clusters = std::map /* names */>; + using Tags = std::map /* names */>; struct Artist { - std::string name; - std::optional sortName; - std::optional artistMBID; + std::string name; + std::optional sortName; + std::optional mbid; Artist(std::string_view _name) : name {_name} {} - Artist(std::string_view _name, std::optional _sortName, std::optional _artistMBID) : name {_name}, sortName {std::move(_sortName)}, artistMBID {std::move(_artistMBID)} {} + Artist(std::string_view _name, std::optional _sortName, std::optional _mbid) : name {_name}, sortName {std::move(_sortName)}, mbid {std::move(_mbid)} {} }; using PerformerContainer = std::map>; @@ -50,16 +50,18 @@ namespace MetaData struct Release { std::string name; - std::vector releaseArtists; - std::optional releaseMBID; - std::optional totalDisc; + std::vector artists; + std::optional mbid; + std::optional mediumCount; }; - struct Disc + struct Medium { - std::string subtitle; + std::optional position; + std::string type; + std::string name; std::optional replayGain; - std::optional totalTrack; + std::optional trackCount; }; struct AudioStream @@ -71,14 +73,13 @@ namespace MetaData { std::vector artists; std::string title; - std::optional trackMBID; + std::optional mbid; std::optional recordingMBID; std::optional release; - std::optional disc; - Clusters clusters; + std::optional medium; + Tags tags; std::chrono::milliseconds duration; - std::optional trackNumber; - std::optional discNumber; + std::optional position; // in medium Wt::WDate date; Wt::WDate originalDate; bool hasCover {}; diff --git a/src/libs/services/scanner/impl/ScanStepScanFiles.cpp b/src/libs/services/scanner/impl/ScanStepScanFiles.cpp index d2207494..ea567356 100644 --- a/src/libs/services/scanner/impl/ScanStepScanFiles.cpp +++ b/src/libs/services/scanner/impl/ScanStepScanFiles.cpp @@ -42,8 +42,8 @@ namespace { Artist::pointer artist {session.create(artistInfo.name)}; - if (artistInfo.artistMBID) - artist.modify()->setMBID(*artistInfo.artistMBID); + if (artistInfo.mbid) + artist.modify()->setMBID(*artistInfo.mbid); if (artistInfo.sortName) artist.modify()->setSortName(*artistInfo.sortName); @@ -76,9 +76,9 @@ namespace Artist::pointer artist; // 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) artist = createArtist(session, artistInfo); else @@ -120,8 +120,8 @@ namespace { if (release->getName() != releaseInfo.name) release.modify()->setName(releaseInfo.name); - if (release->getTotalDisc() != releaseInfo.totalDisc) - release.modify()->setTotalDisc(releaseInfo.totalDisc); + if (release->getTotalDisc() != releaseInfo.mediumCount) + release.modify()->setTotalDisc(releaseInfo.mediumCount); } Release::pointer @@ -130,11 +130,11 @@ namespace Release::pointer release; // 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) - release = session.create(releaseInfo.name, releaseInfo.releaseMBID); + release = session.create(releaseInfo.name, releaseInfo.mbid); updateReleaseIfNeeded(release, releaseInfo); return release; @@ -165,17 +165,17 @@ namespace } std::vector - getOrCreateClusters(Session& session, const MetaData::Clusters& clustersNames) + getOrCreateClusters(Session& session, const MetaData::Tags& tags) { - std::vector< Cluster::pointer > clusters; + std::vector 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) continue; - for (auto clusterName : clusterNames.second) + for (auto clusterName : values) { auto cluster = clusterType->getCluster(clusterName); if (!cluster) @@ -287,9 +287,9 @@ namespace Scanner Track::pointer track {Track::findByPath(dbSession, file) }; - if (trackInfo->trackMBID && (!track || _settings.skipDuplicateMBID)) + if (trackInfo->mbid && (!track || _settings.skipDuplicateMBID)) { - std::vector duplicateTracks {Track::findByMBID(dbSession, *trackInfo->trackMBID)}; + std::vector duplicateTracks {Track::findByMBID(dbSession, *trackInfo->mbid)}; // find for existing MBIDs as the file may have just been moved if (!track && duplicateTracks.size() == 1) @@ -395,7 +395,7 @@ namespace Scanner 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)); } @@ -430,16 +430,16 @@ namespace Scanner track.modify()->setRelease(getOrCreateRelease(dbSession, *trackInfo->release)); else track.modify()->setRelease({}); - track.modify()->setTotalTrack(trackInfo->disc ? trackInfo->disc->totalTrack : std::nullopt); - track.modify()->setReleaseReplayGain(trackInfo->disc ? trackInfo->disc->replayGain : std::nullopt); - track.modify()->setDiscSubtitle(trackInfo->disc ? trackInfo->disc->subtitle : ""); - track.modify()->setClusters(getOrCreateClusters(dbSession, trackInfo->clusters)); + track.modify()->setTotalTrack(trackInfo->medium ? trackInfo->medium->trackCount : std::nullopt); + track.modify()->setReleaseReplayGain(trackInfo->medium ? trackInfo->medium->replayGain : std::nullopt); + track.modify()->setDiscSubtitle(trackInfo->medium ? trackInfo->medium->name : ""); + track.modify()->setClusters(getOrCreateClusters(dbSession, trackInfo->tags)); track.modify()->setLastWriteTime(lastWriteTime); track.modify()->setName(title); track.modify()->setDuration(trackInfo->duration); track.modify()->setAddedTime(Wt::WDateTime::currentDateTime()); - track.modify()->setTrackNumber(trackInfo->trackNumber ? *trackInfo->trackNumber : 0); - track.modify()->setDiscNumber(trackInfo->discNumber ? *trackInfo->discNumber : 0); + track.modify()->setTrackNumber(trackInfo->position); + track.modify()->setDiscNumber(trackInfo->medium ? trackInfo->medium->position : std::nullopt); track.modify()->setDate(trackInfo->date); track.modify()->setOriginalDate(trackInfo->originalDate); @@ -448,7 +448,7 @@ namespace Scanner track.modify()->setDate(trackInfo->originalDate); track.modify()->setRecordingMBID(trackInfo->recordingMBID); - track.modify()->setTrackMBID(trackInfo->trackMBID); + track.modify()->setTrackMBID(trackInfo->mbid); if (auto trackFeatures {TrackFeatures::find(dbSession, track->getId())}) trackFeatures.remove(); // TODO: only if MBID changed? track.modify()->setHasCover(trackInfo->hasCover); diff --git a/src/tools/metadata/LmsMetadata.cpp b/src/tools/metadata/LmsMetadata.cpp index 628a968a..d0f372a9 100644 --- a/src/tools/metadata/LmsMetadata.cpp +++ b/src/tools/metadata/LmsMetadata.cpp @@ -35,8 +35,8 @@ operator<<(std::ostream& os, const MetaData::Artist& artist) { os << artist.name; - if (artist.artistMBID) - os << " (" << artist.artistMBID->getAsString() << ")"; + if (artist.mbid) + os << " (" << artist.mbid->getAsString() << ")"; if (artist.sortName) os << " '" << *artist.sortName << "'"; @@ -50,30 +50,36 @@ operator<<(std::ostream& os, const MetaData::Release& release) { os << release.name; - if (release.releaseMBID) - os << " (" << release.releaseMBID->getAsString() << ")" << std::endl; + if (release.mbid) + os << " (" << release.mbid->getAsString() << ")" << std::endl; - if (release.totalDisc) - std::cout << "\tTotalDisc: " << *release.totalDisc << std::endl; + if (release.mediumCount) + std::cout << "\tMediumCount: " << *release.mediumCount << std::endl; - for (const MetaData::Artist& artist : release.releaseArtists) - std::cout << "\tAlbum artist: " << artist << std::endl; + for (const MetaData::Artist& artist : release.artists) + std::cout << "\tRelease artist: " << artist << std::endl; return os; } static std::ostream& -operator<<(std::ostream& os, const MetaData::Disc& disc) +operator<<(std::ostream& os, const MetaData::Medium& medium) { - if (!disc.subtitle.empty()) - os << disc.subtitle << std::endl; + if (!medium.name.empty()) + os << medium.name << std::endl; - if (disc.totalTrack) - std::cout << "\tTotalTrack: " << *disc.totalTrack << std::endl; + if (medium.position) + os << "\tPosition: " << *medium.position << std::endl; - if (disc.replayGain) - std::cout << "\tDisc replay gain: " << *disc.replayGain << std::endl; + if (!medium.type.empty()) + 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; } @@ -131,33 +137,30 @@ void parse(MetaData::IParser& parser, const std::filesystem::path& file) if (track->release) std::cout << "Release: " << *track->release; - if (track->disc) - std::cout << "Disc: " << *track->disc; + if (track->medium) + std::cout << "Medium: " << *track->medium; std::cout << "Title: " << track->title << std::endl; - if (track->trackMBID) - std::cout << "track MBID = " << track->trackMBID->getAsString() << std::endl; + if (track->mbid) + std::cout << "Track MBID = " << track->mbid->getAsString() << std::endl; 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; - for (const auto& name : cluster.second) + std::cout << "Tag: " << tag << std::endl; + 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; - if (track->trackNumber) - std::cout << "Track: " << *track->trackNumber << std::endl; - - if (track->discNumber) - std::cout << "Disc: " << *track->discNumber << std::endl; + if (track->position) + std::cout << "Position: " << *track->position << std::endl; if (track->date.isValid()) std::cout << "Date: " << track->date.toString("yyyy-MM-dd") << std::endl;