25#include <cereal/archives/binary.hpp>
26#include <cereal/types/map.hpp>
27#include <cereal/types/string.hpp>
28#include <cereal/types/vector.hpp>
100 std::map<std::string, std::map<std::string, std::map<unsigned int, std::map<unsigned int, Song>>>>
127 int totalArtists = 0, totalAlbums = 0, totalDiscs = 0, totalSongs = 0;
128 std::set<std::string> uniqueGenres;
130 std::cout <<
"\n=== Music Library Overview ===\n";
131 std::cout <<
"─────────────────────────────────────────────────────────────────────────────\n";
133 for (
const auto& artistPair : tree)
136 std::cout <<
"\n🎤 Artist: " << artistPair.first <<
"\n";
137 for (
const auto& albumPair : artistPair.second)
140 std::cout <<
" ├─── 📀 Album: " << albumPair.first <<
"\n";
141 for (
const auto& discPair : albumPair.second)
144 std::cout <<
" │ 💿 Disc " << discPair.first <<
"\n";
145 for (
const auto& trackPair : discPair.second)
148 const auto& song = trackPair.second;
149 uniqueGenres.insert(song.metadata.genre);
150 std::cout <<
" │ │ Track " << std::setw(2) << trackPair.first <<
": "
151 << song.metadata.title <<
"\n";
157 std::cout <<
"\n=== Library Summary ===\n";
158 std::cout <<
"─────────────────────────────────────────────────────────────────────────────\n";
159 std::cout <<
"🎤 Total Artists: " << totalArtists <<
"\n";
160 std::cout <<
"📀 Total Albums: " << totalAlbums <<
"\n";
161 std::cout <<
"💿 Total Discs: " << totalDiscs <<
"\n";
162 std::cout <<
"🎵 Total Songs: " << totalSongs <<
"\n";
163 std::cout <<
"🎼 Unique Genres: " << uniqueGenres.size() <<
"\n";
164 std::cout <<
"=========================\n";
174 std::cout <<
"\n=== Artists List ===\n";
175 for (
const auto& artistPair : tree)
177 std::cout <<
"- " << artistPair.first <<
"\n";
179 std::cout <<
"=====================\n";
193 std::cout <<
"No songs found.\n";
198 std::map<std::string, std::vector<Song>> albums;
199 for (
const auto& song : songs)
201 albums[song.metadata.album].push_back(song);
204 std::cout <<
"\n" <<
"\033[1mSongs List\033[0m:\n";
205 std::cout <<
"─────────────────────────────────────\n";
207 for (
const auto& albumPair : albums)
209 const auto& album = albumPair.first;
210 const auto& albumSongs = albumPair.second;
212 std::cout <<
"├─── 📀 Album: " << album <<
"\n";
213 std::cout <<
"└─ Total Songs: " << albumSongs.size() <<
"\n";
215 for (
const auto& song : albumSongs)
217 std::cout <<
" │ Track: " << song.metadata.title <<
"\n";
220 std::cout <<
"─────────────────────────────────────\n";
235 std::vector<Song> result;
236 auto artistIt = tree.find(artist);
237 if (artistIt != tree.end())
239 for (
const auto& albumPair : artistIt->second)
241 for (
const auto& discPair : albumPair.second)
243 for (
const auto& trackPair : discPair.second)
245 result.push_back(trackPair.second);
263 [[nodiscard]]
auto getSongsByAlbum(
const std::string& artist,
const std::string& album)
const
265 std::vector<Song> result;
266 auto artistIt = tree.find(artist);
267 if (artistIt != tree.end())
269 auto albumIt = artistIt->second.find(album);
270 if (albumIt != artistIt->second.end())
272 for (
const auto& discPair : albumIt->second)
274 for (
const auto& trackPair : discPair.second)
276 result.push_back(trackPair.second);
263 [[nodiscard]]
auto getSongsByAlbum(
const std::string& artist,
const std::string& album)
const {
…}
291 std::map<std::string, std::vector<Song>> genreMap;
294 for (
const auto& artistPair : tree)
296 for (
const auto& albumPair : artistPair.second)
298 for (
const auto& discPair : albumPair.second)
300 for (
const auto& trackPair : discPair.second)
302 genreMap[trackPair.second.metadata.genre].push_back(trackPair.second);
308 std::cout <<
"\n=== Songs Grouped by Genre ===\n";
309 std::cout <<
"──────────────────────────────────────\n";
312 for (
const auto& genrePair : genreMap)
314 const auto& genre = genrePair.first;
315 const auto& songs = genrePair.second;
317 std::cout <<
"\n🎶 Genre: " << genre <<
"\n";
318 std::cout <<
"──────────────────────────────────────\n";
320 for (
const auto& song : songs)
322 std::cout <<
"├─── " << song.metadata.title <<
" by " << song.metadata.artist
323 <<
" (Album: " << song.metadata.album <<
")\n";
326 std::cout <<
"──────────────────────────────────────\n";
347 template <
class Archive>
void serialize(Archive& ar) { ar(tree); }
359 std::ofstream file(filename, std::ios::binary);
362 throw std::runtime_error(
"Failed to open file for saving.");
364 cereal::BinaryOutputArchive archive(file);
378 std::ifstream file(filename, std::ios::binary);
381 throw std::runtime_error(
"Failed to open file for loading.");
383 cereal::BinaryInputArchive archive(file);
398 bool isFilePath = input.find(
'/') != std::string::npos || input.find(
'\\') != std::string::npos;
400 std::optional<Song> foundSong;
405 std::cout << std::endl <<
"> Taking argument as a possible audio file path..." << std::endl;
406 struct stat fileStat;
407 if (stat(input.c_str(), &fileStat) == 0)
409 unsigned int inode = fileStat.st_ino;
410 for (
const auto& artistPair : tree)
412 for (
const auto& albumPair : artistPair.second)
414 for (
const auto& discPair : albumPair.second)
416 for (
const auto& trackPair : discPair.second)
418 if (trackPair.second.inode == inode)
420 foundSong = trackPair.second;
432 for (
const auto& artistPair : tree)
434 for (
const auto& albumPair : artistPair.second)
436 for (
const auto& discPair : albumPair.second)
438 for (
const auto& trackPair : discPair.second)
442 foundSong = trackPair.second;
453 const auto& song = *foundSong;
454 std::cout <<
"\n🎵 Song Information:\n";
455 std::cout <<
"──────────────────────────────────────\n";
456 std::cout <<
"Title : " << song.metadata.title <<
"\n";
457 std::cout <<
"Artist : " << song.metadata.artist <<
"\n";
458 std::cout <<
"Album : " << song.metadata.album <<
"\n";
459 std::cout <<
"Disc : " << song.metadata.discNumber <<
"\n";
460 std::cout <<
"Track : " << song.metadata.track <<
"\n";
461 std::cout <<
"Genre : " << song.metadata.genre <<
"\n";
462 std::cout <<
"Inode : " << song.inode <<
"\n";
464 if (!song.metadata.additionalProperties.empty())
466 std::cout <<
"Additional Properties:\n";
467 for (
const auto& prop : song.metadata.additionalProperties)
469 if (prop.first ==
"LYRICS")
471 std::cout <<
"\n📜 Lyrics:\n";
472 std::cout <<
"──────────────────────────────────────\n";
475 const std::string& lyrics = prop.second;
476 size_t lineLength = 80;
478 while (start < lyrics.size())
480 size_t end = start + lineLength;
481 if (end > lyrics.size()) end = lyrics.size();
482 std::cout << lyrics.substr(start, end - start) <<
"\n";
485 std::cout <<
"──────────────────────────────────────\n";
489 std::cout <<
" - " << prop.first <<
" : " << prop.second <<
"\n";
495 std::cout <<
"No additional properties found!" << std::endl;
497 std::cout <<
"──────────────────────────────────────\n";
501 std::cout <<
"⚠️ Song not found: " << input <<
"\n";
Represents a hierarchical tree structure to store songs by artist, album, disc number,...
Definition songmap.hpp:90
auto returnSongMap() const
Returns the internal song map.
Definition songmap.hpp:337
void printSongInfo(const std::string &input)
Prints metadata and additional properties of a song.
Definition songmap.hpp:396
auto getSongsByArtist(const std::string &artist)
Retrieves all songs by a specific artist.
Definition songmap.hpp:233
void printSongs(const std::vector< Song > &songs)
Prints the songs by album.
Definition songmap.hpp:189
void serialize(Archive &ar)
Serializes the SongTree object.
Definition songmap.hpp:347
void display() const
Displays all songs in the tree hierarchically.
Definition songmap.hpp:125
void addSong(const Song &song)
Adds a song to the tree.
Definition songmap.hpp:112
void saveToFile(const std::string &filename) const
Saves the SongTree to a file.
Definition songmap.hpp:357
auto getSongsByAlbum(const std::string &artist, const std::string &album) const
Retrieves all songs from a specific album by a given artist.
Definition songmap.hpp:263
void loadFromFile(const std::string &filename)
Loads a SongTree from a file.
Definition songmap.hpp:376
void getSongsByGenreAndPrint() const
Groups and prints songs by genre.
Definition songmap.hpp:289
void printAllArtists() const
Prints all the artists in the song tree.
Definition songmap.hpp:172
auto levenshteinDistance(const std::string &s1, const std::string &s2) -> size_t
Computes the Levenshtein distance between two strings.
Definition levenshtein.hpp:36
Represents a song with associated metadata and inode.
Definition songmap.hpp:46
Song()
Default constructor for a Song, initializing with default values.
Definition songmap.hpp:63
unsigned int inode
Definition songmap.hpp:47
Metadata metadata
Definition songmap.hpp:48
void serialize(Archive &ar)
Serializes the Song object.
Definition songmap.hpp:73
Song(unsigned int inode, const Metadata &metadata)
Constructs a Song with the given inode and metadata.
Definition songmap.hpp:58
A header file for the TagLibParser class and Metadata structure, used to parse metadata from audio fi...