From 4d01a1e99638899d03064a4fbeafd9351826627a Mon Sep 17 00:00:00 2001 From: emeric Date: Sun, 10 Mar 2019 13:49:51 +0100 Subject: [PATCH] WIP --- src/database/Track.cpp | 6 + src/database/Track.hpp | 54 ++-- src/metadata/AvFormat.cpp | 27 +- src/metadata/MetaData.hpp | 65 ++--- src/metadata/TagLibParser.cpp | 51 ++-- src/scanner/MediaScanner.cpp | 2 +- .../cluster/SimilarityClusterSearcher.cpp | 14 +- src/utils/Utils.cpp | 4 +- src/utils/Utils.hpp | 4 +- tools/metadata/LmsMetadata.cpp | 231 ++++++++++-------- tools/metadata/Makefile.am | 6 +- tools/similarity/LmsSimilarity.cpp | 4 +- 12 files changed, 272 insertions(+), 196 deletions(-) diff --git a/src/database/Track.cpp b/src/database/Track.cpp index 5e60049a..43b43a2d 100644 --- a/src/database/Track.cpp +++ b/src/database/Track.cpp @@ -266,6 +266,12 @@ Track::getCopyrightURL() const return _copyrightURL != "" ? boost::make_optional(_copyrightURL) : boost::none; } +std::vector> +Track::getArtists() const +{ + return std::vector>(_artists.begin(), _artists.end()); +} + Wt::Dbo::ptr Track::getTrackFeatures() const { diff --git a/src/database/Track.hpp b/src/database/Track.hpp index 663ef9cc..d0946894 100644 --- a/src/database/Track.hpp +++ b/src/database/Track.hpp @@ -96,33 +96,33 @@ class Track : public Wt::Dbo::Dbo void setMBID(const std::string& MBID) { _MBID = MBID; } void setCopyright(const std::string& copyright) { _copyright = std::string(copyright, 0, _maxCopyrightLength); } void setCopyrightURL(const std::string& copyrightURL) { _copyrightURL = std::string(copyrightURL, 0, _maxCopyrightURLLength); } - void setArtist(Wt::Dbo::ptr artist) { _artist = artist; } + void setArtists(std::vector>& artists); void setRelease(Wt::Dbo::ptr release) { _release = release; } void eraseClusters() { _clusters.clear(); } void eraseFeatures() { /*_trackFeatures.reset();*/ } - std::size_t getScanVersion() const { return _scanVersion; } - boost::optional getTrackNumber() const; - boost::optional getTotalTrackNumber() const; - boost::optional getDiscNumber() const; - boost::optional getTotalDiscNumber() const; - std::string getName() const { return _name; } - boost::filesystem::path getPath() const { return _filePath; } - std::chrono::milliseconds getDuration() const { return _duration; } - boost::optional getYear() const; - boost::optional getOriginalYear() const; - Wt::WDateTime getLastWriteTime() const { return _fileLastWrite; } - Wt::WDateTime getAddedTime() const { return _fileAdded; } - const std::vector& getChecksum() const { return _fileChecksum; } - bool hasCover() const { return _hasCover; } - const std::string& getMBID() const { return _MBID; } - boost::optional getCopyright() const; - boost::optional getCopyrightURL() const; - Wt::Dbo::ptr getArtist() const { return _artist; } - Wt::Dbo::ptr getRelease() const { return _release; } + std::size_t getScanVersion() const { return _scanVersion; } + boost::optional getTrackNumber() const; + boost::optional getTotalTrackNumber() const; + boost::optional getDiscNumber() const; + boost::optional getTotalDiscNumber() const; + std::string getName() const { return _name; } + boost::filesystem::path getPath() const { return _filePath; } + std::chrono::milliseconds getDuration() const { return _duration; } + boost::optional getYear() const; + boost::optional getOriginalYear() const; + Wt::WDateTime getLastWriteTime() const { return _fileLastWrite; } + Wt::WDateTime getAddedTime() const { return _fileAdded; } + const std::vector& getChecksum() const { return _fileChecksum; } + bool hasCover() const { return _hasCover; } + const std::string& getMBID() const { return _MBID; } + boost::optional getCopyright() const; + boost::optional getCopyrightURL() const; + std::vector> getArtists() const; + Wt::Dbo::ptr getRelease() const { return _release; } std::vector> getClusters() const; - bool hasTrackFeatures() const; - Wt::Dbo::ptr getTrackFeatures() const; + bool hasTrackFeatures() const; + Wt::Dbo::ptr getTrackFeatures() const; std::vector>> getClusterGroups(std::vector> clusterTypes, std::size_t size) const; @@ -148,7 +148,7 @@ class Track : public Wt::Dbo::Dbo Wt::Dbo::field(a, _copyright, "copyright"); Wt::Dbo::field(a, _copyrightURL, "copyright_url"); Wt::Dbo::belongsTo(a, _release, "release", Wt::Dbo::OnDeleteCascade); - Wt::Dbo::belongsTo(a, _artist, "artist", Wt::Dbo::OnDeleteCascade); + Wt::Dbo::hasMany(a, _artists, Wt::Dbo::ManyToMany, "track_artist", "", Wt::Dbo::OnDeleteCascade); Wt::Dbo::hasMany(a, _clusters, Wt::Dbo::ManyToMany, "track_cluster", "", Wt::Dbo::OnDeleteCascade); Wt::Dbo::hasMany(a, _playlistEntries, Wt::Dbo::ManyToOne, "track"); Wt::Dbo::hasOne(a, _trackFeatures); @@ -181,11 +181,11 @@ class Track : public Wt::Dbo::Dbo std::string _copyright; std::string _copyrightURL; - Wt::Dbo::ptr _artist; - Wt::Dbo::ptr _release; - Wt::Dbo::collection> _clusters; + Wt::Dbo::ptr _release; + Wt::Dbo::collection> _artists; + Wt::Dbo::collection> _clusters; Wt::Dbo::collection> _playlistEntries; - Wt::Dbo::weak_ptr _trackFeatures; + Wt::Dbo::weak_ptr _trackFeatures; }; diff --git a/src/metadata/AvFormat.cpp b/src/metadata/AvFormat.cpp index e23c8682..a0f2f044 100644 --- a/src/metadata/AvFormat.cpp +++ b/src/metadata/AvFormat.cpp @@ -72,7 +72,20 @@ AvFormat::parse(const boost::filesystem::path& p, bool debug) std::cout << "TAG = " << tag << ", VAL = " << value << std::endl; if (tag == "ARTIST") - items.insert( std::make_pair(MetaData::Type::Artist, stringTrim( value) )); + { + if (items.find(MetaData::Type::Artists) == items.end()) + items[MetaData::Type::Artists] = std::set{ stringTrim( value) }; + } + else if (tag == "ARTISTS") + { + std::vector strings {splitString(value, "/;")}; // Picard separator is '/' + + std::set artists; + for (const std::string& string : strings) + artists.insert(stringTrim(string)); + + items[MetaData::Type::Artists] = std::move(artists); + } else if (tag == "ALBUM") items.insert( std::make_pair(MetaData::Type::Album, stringTrim( value) )); else if (tag == "TITLE") @@ -133,7 +146,13 @@ AvFormat::parse(const boost::filesystem::path& p, bool debug) else if (tag == "MUSICBRAINZ ARTIST ID" || tag == "MUSICBRAINZ_ARTISTID") { - items.insert( std::make_pair(MetaData::Type::MusicBrainzArtistID, stringTrim(value)) ); + std::vector strings {splitString(value, "/")}; + + std::set mbids; + for (const std::string& string : strings) + mbids.insert(stringTrim(string)); + + items[MetaData::Type::MusicBrainzArtistID] = std::move(mbids); } else if (tag == "MUSICBRAINZ ALBUM ID" || tag == "MUSICBRAINZ_ALBUMID") @@ -152,7 +171,7 @@ AvFormat::parse(const boost::filesystem::path& p, bool debug) } else if (_clusterTypeNames.find(tag) != _clusterTypeNames.end()) { - std::vector clusterNames = splitString(value, ";,\\"); + std::vector clusterNames = splitString(value, "/,;"); if (!clusterNames.empty()) { @@ -167,7 +186,7 @@ AvFormat::parse(const boost::filesystem::path& p, bool debug) } catch(Av::MediaFileException& e) { - return items; + return boost::none; } return items; diff --git a/src/metadata/MetaData.hpp b/src/metadata/MetaData.hpp index 46192deb..c855d09f 100644 --- a/src/metadata/MetaData.hpp +++ b/src/metadata/MetaData.hpp @@ -22,54 +22,57 @@ #include #include -#include #include #include namespace MetaData { + using Clusters = std::map /* names */>; - enum class Type + struct Artist { - // Name Type of the value - Artist, // string - Title, // string - Album, // string - Clusters, // Clusters, ex: { "genre", {"death metal", "brutal death"} }, { "albumgrouping", {"metal"} } - Duration, // std::chrono::milliseconds - TrackNumber, // size_t - DiscNumber, // size_t - TotalTrack, // size_t - TotalDisc, // size_t - Year, // int - OriginalYear, // int - HasCover, // bool - AudioStreams, // vector - MusicBrainzArtistID, // string - MusicBrainzAlbumID, // string - MusicBrainzTrackID, // string - MusicBrainzRecordingID, // string - AcoustID, // string - Copyright, // string - CopyrightURL, // string + std::string name; + std::string musicBrainzArtistID; }; - // Used by Streams + struct Album + { + std::string name; + std::string musicBrainzAlbumID; + } + struct AudioStream { - // TODO codec? - std::size_t bitRate; + unsigned bitRate; }; - // Type and associated data - // See enum Type's comments - using Items = std::map; - using Clusters = std::map /* names */>; + struct Track + { + std::vector artists; + boost::optional albumArtist; + std::string title; + std::string musicBrainzTrackID; + std::string musicBrainzRecordID; + boost::optional album; + Clusters clusters; + std::chrono::milliseconds duration {}; + boost::optional trackNumber; + boost::optional totalTrack; + boost::optional discNumber; + boost::optional totalDisc; + boost::optional year; + boost::optional originalYear; + bool hasCover {false}; + std::vector audioStreams; + std::string acoustId; + std::string copyright; + std::string copyrightURL; + }; class Parser { public: - virtual boost::optional parse(const boost::filesystem::path& p, bool debug = false) = 0; + virtual boost::optional parse(const boost::filesystem::path& p, bool debug = false) = 0; void setClusterTypeNames(const std::set& clusterTypeNames) { _clusterTypeNames = clusterTypeNames; } diff --git a/src/metadata/TagLibParser.cpp b/src/metadata/TagLibParser.cpp index 35ab0406..39ef0b2a 100644 --- a/src/metadata/TagLibParser.cpp +++ b/src/metadata/TagLibParser.cpp @@ -34,9 +34,9 @@ namespace MetaData boost::optional TagLibParser::parse(const boost::filesystem::path& p, bool debug) { - TagLib::FileRef f(p.string().c_str(), + TagLib::FileRef f {p.string().c_str(), true, // read audio properties - TagLib::AudioProperties::Average); + TagLib::AudioProperties::Average}; if (f.isNull()) return boost::none; @@ -47,13 +47,12 @@ TagLibParser::parse(const boost::filesystem::path& p, bool debug) Items items; { - TagLib::AudioProperties *properties = f.audioProperties(); + const TagLib::AudioProperties *properties {f.audioProperties() }; - std::chrono::milliseconds duration(properties->length() * 1000); - items.insert( std::make_pair(MetaData::Type::Duration, duration) ); + items[MetaData::Type::Duration] = std::chrono::milliseconds {properties->length() * 1000}; - MetaData::AudioStream audioStream = { .bitRate = static_cast(properties->bitrate() * 1000) }; - items.insert( std::make_pair(MetaData::Type::AudioStreams, std::vector(1, audioStream ) )); + MetaData::AudioStream audioStream {.bitRate = static_cast(properties->bitrate() * 1000)}; + items[MetaData::Type::AudioStreams] = std::vector {audioStream}; } // Not that good embedded pictures handling @@ -71,7 +70,7 @@ TagLibParser::parse(const boost::filesystem::path& p, bool debug) if (f.tag()) { MetaData::Clusters clusters; - TagLib::PropertyMap properties = f.file()->properties(); + const TagLib::PropertyMap& properties {f.file()->properties()}; for(auto property : properties) { @@ -93,7 +92,23 @@ TagLibParser::parse(const boost::filesystem::path& p, bool debug) } if (tag == "ARTIST") - items.insert( std::make_pair(MetaData::Type::Artist, stringTrim( values.front().to8Bit(true)))); + { + // Lower priority than ARTISTS + if (items.find(MetaData::Type::Artists) == items.end()) + items[MetaData::Type::Artists] = std::vector{ stringTrim( values.front().to8Bit(true)) }; + } + else if (tag == "ARTISTS") + { + // Higher priority than ARTISTS + std::vector strings {splitString(values.front().to8Bit(), "/;")}; // Picard separator is '/' + + std::vector artists; + for (const std::string& string : strings) + artists.emplace_back(stringTrim(string)); + + items[MetaData::Type::Artists] = std::move(artists); + } + else if (tag == "ALBUM") items.insert( std::make_pair(MetaData::Type::Album, stringTrim( values.front().to8Bit(true)))); else if (tag == "TITLE") @@ -104,7 +119,15 @@ TagLibParser::parse(const boost::filesystem::path& p, bool debug) items.insert( std::make_pair(MetaData::Type::MusicBrainzTrackID, stringTrim( values.front().to8Bit(true)))); } else if (tag == "MUSICBRAINZ_ARTISTID") - items.insert( std::make_pair(MetaData::Type::MusicBrainzArtistID, stringTrim( values.front().to8Bit(true)))); + { + std::vector strings {splitString(values.front().to8Bit(), "/")}; // Picard separator is '/' + + std::vector mbids; + for (const std::string& string : strings) + mbids.emplace_back(stringTrim(string)); + + items[MetaData::Type::MusicBrainzArtistID] = std::move(mbids); + } else if (tag == "MUSICBRAINZ_ALBUMID") items.insert( std::make_pair(MetaData::Type::MusicBrainzAlbumID, stringTrim( values.front().to8Bit(true)))); else if (tag == "MUSICBRAINZ_TRACKID") @@ -113,25 +136,25 @@ TagLibParser::parse(const boost::filesystem::path& p, bool debug) items.insert( std::make_pair(MetaData::Type::AcoustID, stringTrim( values.front().to8Bit(true)))); else if (tag == "TRACKTOTAL") { - auto totalTrack = readAs(values.front().to8Bit(true)); + auto totalTrack {readAs(values.front().to8Bit(true)) }; if (totalTrack) items[MetaData::Type::TotalTrack] = *totalTrack; } else if (tag == "TRACKNUMBER") { // Expecting 'Number/Total' - auto strings = splitString(values.front().to8Bit(), "/"); + std::vector strings {splitString(values.front().to8Bit(), "/")}; if (!strings.empty()) { - auto number = readAs(strings[0]); + auto number {readAs(strings[0])}; if (number) items.insert( std::make_pair(MetaData::Type::TrackNumber, *number )); // Lower priority than TRACKTOTAL if (strings.size() > 1 && items.find(MetaData::Type::TotalTrack) == items.end()) { - auto totalTrack = readAs(strings[1]); + auto totalTrack {readAs(strings[1])}; if (totalTrack) items[MetaData::Type::TotalTrack] = *totalTrack; } diff --git a/src/scanner/MediaScanner.cpp b/src/scanner/MediaScanner.cpp index a3ad4118..be9bdc79 100644 --- a/src/scanner/MediaScanner.cpp +++ b/src/scanner/MediaScanner.cpp @@ -475,7 +475,7 @@ MediaScanner::scanAudioFile(const boost::filesystem::path& file, bool forceScan, } // ***** Artist - Artist::pointer artist; + std::set artists; { std::string artistName; std::string artistMusicBrainzID; diff --git a/src/similarity/cluster/SimilarityClusterSearcher.cpp b/src/similarity/cluster/SimilarityClusterSearcher.cpp index fe519758..58f0e6f5 100644 --- a/src/similarity/cluster/SimilarityClusterSearcher.cpp +++ b/src/similarity/cluster/SimilarityClusterSearcher.cpp @@ -153,14 +153,16 @@ getSimilarArtists(Wt::Dbo::Session& session, Database::IdType artistId, std::siz if (!track) continue; - auto trackArtist = track->getArtist(); - if (!trackArtist || trackArtist.id() == artistId) - continue; + for (auto trackArtist : track->getArtists()) + { + if (!trackArtist || trackArtist.id() == artistId) + continue; - if (std::find(res.begin(), res.end(), trackArtist.id()) != res.end()) - continue; + if (std::find(res.begin(), res.end(), trackArtist.id()) != res.end()) + continue; - res.push_back(trackArtist.id()); + res.push_back(trackArtist.id()); + } if (res.size() == maxCount) break; diff --git a/src/utils/Utils.cpp b/src/utils/Utils.cpp index 57704eac..db292efd 100644 --- a/src/utils/Utils.cpp +++ b/src/utils/Utils.cpp @@ -55,7 +55,7 @@ bool readList(const std::string& str, const std::string& separators, std::list -splitString(std::string string, std::string separators) +splitString(const std::string& string, const std::string& separators) { std::vector res; @@ -65,7 +65,7 @@ splitString(std::string string, std::string separators) } std::string -joinStrings(std::vector strings, std::string delimiter) +joinStrings(const std::vector& strings, const std::string& delimiter) { return boost::algorithm::join(strings, delimiter); } diff --git a/src/utils/Utils.hpp b/src/utils/Utils.hpp index f76bba2c..fa148c9b 100644 --- a/src/utils/Utils.hpp +++ b/src/utils/Utils.hpp @@ -34,10 +34,10 @@ bool readList(const std::string& str, const std::string& separators, std::list& results); std::vector -splitString(std::string string, std::string separators); +splitString(const std::string& string, const std::string& separators); std::string -joinStrings(std::vector strings, std::string delimiter); +joinStrings(const std::vector& strings, const std::string& delimiter); std::string stringTrim(const std::string& str, const std::string& whitespaces = " \t"); diff --git a/tools/metadata/LmsMetadata.cpp b/tools/metadata/LmsMetadata.cpp index b67f8fdf..e2b1e56b 100644 --- a/tools/metadata/LmsMetadata.cpp +++ b/tools/metadata/LmsMetadata.cpp @@ -1,13 +1,129 @@ -#include #include - #include +#include #include #include +#include "av/AvInfo.hpp" +#include "metadata/AvFormat.hpp" #include "metadata/TagLibParser.hpp" + +void parse(MetaData::Parser& parser, const boost::filesystem::path& file) +{ + parser.setClusterTypeNames( {"MOOD", "GENRE"} ); + + boost::optional items {parser.parse(file, true)}; + if (!items) + { + std::cerr << "Parsing failed" << std::endl; + return; + } + + std::cout << "Items:" << std::endl; + for (auto item : (*items)) + { + switch (item.first) + { + case MetaData::Type::Title: + std::cout << "Title: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::Artists: + for (const std::string& artist : boost::any_cast>(item.second)) + std::cout << "Artist: " << artist << std::endl; + break; + + case MetaData::Type::Album: + std::cout << "Album: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::Clusters: + for (const auto& cluster : boost::any_cast(item.second)) + { + std::cout << "Cluster: " << cluster.first << std::endl; + for (const auto name : cluster.second) + { + std::cout << "\t" << name << std::endl; + } + } + break; + + case MetaData::Type::Duration: + std::cout << "Duration: " << boost::any_cast(item.second).count() / 1000 << "s" << std::endl; + break; + + case MetaData::Type::TrackNumber: + std::cout << "Track: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::TotalTrack: + std::cout << "TotalTrack: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::DiscNumber: + std::cout << "Disc: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::TotalDisc: + std::cout << "TotalDisc: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::Year: + std::cout << "Year: " << std::to_string(boost::any_cast(item.second)) << std::endl; + break; + + case MetaData::Type::OriginalYear: + std::cout << "Original year: " << std::to_string(boost::any_cast(item.second)) << std::endl; + break; + + case MetaData::Type::HasCover: + std::cout << "HasCover = " << std::boolalpha << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::AudioStreams: + for (const auto& audioStream : boost::any_cast >(item.second)) + std::cout << "Audio stream: " << audioStream.bitRate << " bps" << std::endl; + break; + + case MetaData::Type::MusicBrainzArtistID: + for (const std::string& mbid : boost::any_cast>(item.second)) + std::cout << "MusicBrainzArtistID: " << mbid << std::endl; + break; + + case MetaData::Type::MusicBrainzAlbumID: + std::cout << "MusicBrainzAlbumID: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::MusicBrainzTrackID: + std::cout << "MusicBrainzTrackID: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::MusicBrainzRecordingID: + std::cout << "MusicBrainzRecordingID: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::AcoustID: + std::cout << "AcoustID: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::Copyright: + std::cout << "Copyright: " << boost::any_cast(item.second) << std::endl; + break; + + case MetaData::Type::CopyrightURL: + std::cout << "CopyrightURL: " << boost::any_cast(item.second) << std::endl; + break; + + default: + break; + } + } + + std::cout << std::endl; +} + int main(int argc, char *argv[]) { if (argc != 2) @@ -18,116 +134,21 @@ int main(int argc, char *argv[]) try { - MetaData::TagLibParser parser; + Av::AvInit(); + boost::filesystem::path file {argv[1]}; - parser.setClusterTypeNames( {"MOOD", "GENRE"} ); - - boost::optional items = parser.parse(argv[1], true); - if (!items) { - std::cerr << "Parsing failed" << std::endl; - return EXIT_FAILURE; + std::cout << "Using av:" << std::endl; + MetaData::AvFormat parser; + parse(parser, file); } - std::cout << "Items:" << std::endl; - for (auto item : (*items)) { - switch (item.first) - { - case MetaData::Type::Title: - std::cout << "Title: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::Artist: - std::cout << "Artist: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::Album: - std::cout << "Album: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::Clusters: - for (const auto& cluster : boost::any_cast(item.second)) - { - std::cout << "Cluster: " << cluster.first << std::endl; - for (const auto name : cluster.second) - { - std::cout << "\t" << name << std::endl; - } - } - break; - - case MetaData::Type::Duration: - std::cout << "Duration: " << boost::any_cast(item.second).count() / 1000 << "s" << std::endl; - break; - - case MetaData::Type::TrackNumber: - std::cout << "Track: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::TotalTrack: - std::cout << "TotalTrack: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::DiscNumber: - std::cout << "Disc: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::TotalDisc: - std::cout << "TotalDisc: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::Year: - std::cout << "Year: " << std::to_string(boost::any_cast(item.second)) << std::endl; - break; - - case MetaData::Type::OriginalYear: - std::cout << "Original year: " << std::to_string(boost::any_cast(item.second)) << std::endl; - break; - - case MetaData::Type::HasCover: - std::cout << "HasCover = " << std::boolalpha << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::AudioStreams: - for (auto& audioStream : boost::any_cast >(item.second)) - std::cout << "Audio stream: " << audioStream.bitRate << " bps" << std::endl; - break; - - case MetaData::Type::MusicBrainzArtistID: - std::cout << "MusicBrainzArtistID: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::MusicBrainzAlbumID: - std::cout << "MusicBrainzAlbumID: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::MusicBrainzTrackID: - std::cout << "MusicBrainzTrackID: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::MusicBrainzRecordingID: - std::cout << "MusicBrainzRecordingID: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::AcoustID: - std::cout << "AcoustID: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::Copyright: - std::cout << "Copyright: " << boost::any_cast(item.second) << std::endl; - break; - - case MetaData::Type::CopyrightURL: - std::cout << "CopyrightURL: " << boost::any_cast(item.second) << std::endl; - break; - - default: - break; - } + std::cout << "Using TagLib:" << std::endl; + MetaData::TagLibParser parser; + parse(parser, file); } - std::cout << std::endl; } catch (std::exception& e) { diff --git a/tools/metadata/Makefile.am b/tools/metadata/Makefile.am index f61b517d..1a57f924 100644 --- a/tools/metadata/Makefile.am +++ b/tools/metadata/Makefile.am @@ -2,9 +2,11 @@ bin_PROGRAMS = lms-metadata lms_metadata_SOURCES = \ $(srcdir)/LmsMetadata.cpp \ + $(top_srcdir)/src/av/AvInfo.cpp \ + $(top_srcdir)/src/metadata/AvFormat.cpp \ + $(top_srcdir)/src/metadata/TagLibParser.cpp \ $(top_srcdir)/src/utils/Logger.cpp \ - $(top_srcdir)/src/utils/Utils.cpp \ - $(top_srcdir)/src/metadata/TagLibParser.cpp + $(top_srcdir)/src/utils/Utils.cpp lms_metadata_CXXFLAGS=-std=c++14 -Wall -I$(top_srcdir)/src -D_REENTRANT diff --git a/tools/similarity/LmsSimilarity.cpp b/tools/similarity/LmsSimilarity.cpp index 011c0124..c14e1517 100644 --- a/tools/similarity/LmsSimilarity.cpp +++ b/tools/similarity/LmsSimilarity.cpp @@ -24,8 +24,8 @@ std::ostream& operator<<(std::ostream& os, const Database::Track::pointer& track auto genreClusters = track->getClusterGroups({genreClusterType}, 1); for (auto genreCluster : genreClusters) os << genreCluster.front()->getName() << " - "; - if (track->getArtist()) - os << track->getArtist()->getName() << " - "; + for (auto artist : track->getArtists()) + os << artist->getName() << " - "; if (track->getRelease()) os << track->getRelease()->getName() << " - "; os << track->getName() << "]";