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);
 
 
  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...