From 6e570cd495c45a0672e866d586b05781de5be0fe Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 15 Sep 2019 20:57:41 -0400 Subject: [PATCH] finished updating song functionality --- include/manager/CoverArtManager.h | 7 +-- include/manager/SongManager.h | 3 ++ include/utility/MetadataRetriever.h | 5 +++ src/manager/CoverArtManager.cpp | 58 ++++++++++++++++-------- src/manager/SongManager.cpp | 68 ++++++++++++++++++++++------- src/utility/MetadataRetriever.cpp | 58 ++++++++++++++++++++++++ 6 files changed, 162 insertions(+), 37 deletions(-) diff --git a/include/manager/CoverArtManager.h b/include/manager/CoverArtManager.h index 8f819f8..4f5901b 100644 --- a/include/manager/CoverArtManager.h +++ b/include/manager/CoverArtManager.h @@ -14,15 +14,16 @@ namespace manager CoverArtManager(const std::string&); CoverArtManager(const model::BinaryPath& bConf); - model::Cover saveCover(const model::Song&, std::string&, - const std::string&); + model::Cover saveCover(const model::Song&); std::pair defaultCover(const model::Cover&); void deleteCover(const model::Song&); - void updateCover(const model::Song&); + void updateCover(const model::Song&, const model::Song&); void updateCoverRecord(const model::Song&); private: + std::string createImagePath(const model::Song&); + model::BinaryPath m_bConf; std::string path; }; diff --git a/include/manager/SongManager.h b/include/manager/SongManager.h index 8b550b4..8e4ed41 100644 --- a/include/manager/SongManager.h +++ b/include/manager/SongManager.h @@ -33,12 +33,15 @@ namespace manager private: std::map changesInSong(const model::Song&, const model::Song&); + std::string createSongPath(const model::Song&); + void assignMiscId(model::Song&, const model::Song&); void assignMiscFields(std::map&, model::Song&, const model::Song&); void saveSongTemp(model::Song&); void saveMisc(model::Song&); void deleteMisc(const model::Song&); + void deleteMiscExceptCoverArt(const model::Song&); void updateMisc(const std::map&, model::Song&, const model::Song&); void modifySongOnFilesystem(model::Song&, const model::Song&); diff --git a/include/utility/MetadataRetriever.h b/include/utility/MetadataRetriever.h index b54040c..215fe08 100644 --- a/include/utility/MetadataRetriever.h +++ b/include/utility/MetadataRetriever.h @@ -12,7 +12,12 @@ namespace utility { public: model::Song retrieveMetadata(std::string&); + model::Cover updateCoverArt(const model::Song&, model::Cover&, const std::string&); + model::Cover applyStockCoverArt(const model::Song&, model::Cover&, const std::string&); + model::Cover applyCoverArt(const model::Song&, model::Cover&); + + bool songContainsCoverArt(const model::Song&); void updateMetadata(model::Song&, const model::Song&); private: diff --git a/src/manager/CoverArtManager.cpp b/src/manager/CoverArtManager.cpp index 4810cbc..aab41e0 100644 --- a/src/manager/CoverArtManager.cpp +++ b/src/manager/CoverArtManager.cpp @@ -18,14 +18,24 @@ manager::CoverArtManager::CoverArtManager(const model::BinaryPath& bConf) : m_bC { } -model::Cover manager::CoverArtManager::saveCover(const model::Song& song, std::string& rootPath, const std::string& stockCoverPath) +model::Cover manager::CoverArtManager::saveCover(const model::Song& song) { + auto pathConfigContent = manager::DirectoryManager::pathConfigContent(m_bConf); + auto stockCoverPath = manager::DirectoryManager::configPath(m_bConf); + stockCoverPath.append("/CoverArt.png"); + utility::MetadataRetriever meta; model::Cover cov; - cov.imagePath = rootPath; - cov = meta.updateCoverArt(song, cov, stockCoverPath); cov.songTitle = song.title; + if (meta.songContainsCoverArt(song)) { + cov.imagePath = createImagePath(song); + cov = meta.applyCoverArt(song, cov); + } else { + cov.imagePath = pathConfigContent["cover_root_path"].get(); + cov = meta.applyStockCoverArt(song, cov, stockCoverPath); + } + database::CoverArtRepository covRepo(m_bConf); if (!covRepo.doesCoverArtExist(cov, type::CoverFilter::songTitle)) { std::cout << "saving image record to the database" << std::endl; @@ -76,12 +86,14 @@ void manager::CoverArtManager::deleteCover(const model::Song& song) const auto coverArtPath = result.second; } else { std::cout << "song contains the stock cover art, will not delete" << std::endl; + return; } manager::DirectoryManager::deleteDirectories(song, result.second); } -void manager::CoverArtManager::updateCover(const model::Song& updatedSong) +void manager::CoverArtManager::updateCover(const model::Song& updatedSong, + const model::Song& currSong) { database::CoverArtRepository covRepo(m_bConf); model::Cover cover(updatedSong.coverArtId); @@ -93,30 +105,38 @@ void manager::CoverArtManager::updateCover(const model::Song& updatedSong) return; } - auto imagePath = manager::DirectoryManager::createDirectoryProcess( - updatedSong, m_bConf, type::PathType::coverArt); - imagePath.append(updatedSong.title); - imagePath.append(".png"); - - if (cover.imagePath.find(".png") == std::string::npos) { - std::cout << "no file extension on image path" << std::endl; - cover.imagePath.append(".png"); - } + auto imagePath = createImagePath(updatedSong); fs::copy(cover.imagePath, imagePath); fs::remove(cover.imagePath); + + manager::DirectoryManager::deleteDirectories(currSong, result.second); } void manager::CoverArtManager::updateCoverRecord(const model::Song& updatedSong) { model::Cover updatedCover(updatedSong); - auto updatedImagePath = manager::DirectoryManager::createDirectoryProcess( - updatedSong, m_bConf, type::PathType::coverArt); - updatedImagePath.append(updatedSong.title); - - updatedCover.imagePath = std::move(updatedImagePath); - updatedCover.imagePath.append(".png"); + auto updatedImagePath = createImagePath(updatedSong); database::CoverArtRepository covRepo(m_bConf); covRepo.updateRecord(updatedCover); } + + +std::string manager::CoverArtManager::createImagePath(const model::Song& song) +{ + auto imagePath = manager::DirectoryManager::createDirectoryProcess( + song, m_bConf, type::PathType::coverArt); + + if (song.track != 0) { + imagePath.append("track"); + auto trackNum = (song.track > 9) ? + std::to_string(song.track) : "0" + std::to_string(song.track); + imagePath.append(trackNum); + } else { + imagePath.append(song.title); + } + imagePath.append(".png"); + + return imagePath; +} diff --git a/src/manager/SongManager.cpp b/src/manager/SongManager.cpp index 293cc19..a4a9601 100644 --- a/src/manager/SongManager.cpp +++ b/src/manager/SongManager.cpp @@ -157,6 +157,7 @@ model::Song manager::SongManager::songDtoConv(dto::SongDto::ObjectWrapper& songD return song; } + void manager::SongManager::printSong(const model::Song& song) { std::cout << "\nsong" << std::endl; @@ -210,12 +211,32 @@ std::map manager::SongManager::changesInSong( } +std::string manager::SongManager::createSongPath(const model::Song& song) +{ + auto songPath = manager::DirectoryManager::createDirectoryProcess( + song, m_bConf, type::PathType::music); + + if (song.track != 0) { + songPath.append("track"); + auto trackNum = (song.track > 9) ? + std::to_string(song.track) : "0" + std::to_string(song.track); + songPath.append(trackNum); + } else { + songPath.append(song.title); + } + songPath.append(".mp3"); + + return songPath; +} + + // used to prevent empty values to appear in the updated song void manager::SongManager::assignMiscFields( std::map& songChanges, model::Song& updatedSong, const model::Song& currSong) { std::cout << "assigning miscellanes fields to updated song" << std::endl; + updatedSong.track = currSong.track; for (auto scIter = songChanges.begin(); scIter != songChanges.end(); ++scIter) { type::SongChanged key = scIter->first; bool changed = songChanges.at(key); @@ -260,6 +281,7 @@ void manager::SongManager::assignMiscId(model::Song& updatedSong, updatedSong.coverArtId = currSong.coverArtId; } +// saves song to a temporary path void manager::SongManager::saveSongTemp(model::Song& song) { auto config = manager::DirectoryManager::pathConfigContent(m_bConf); @@ -283,25 +305,22 @@ void manager::SongManager::saveMisc(model::Song& song) { CoverArtManager covMgr(m_bConf); auto pathConfigContent = manager::DirectoryManager::pathConfigContent(m_bConf); - auto coverRootPath = pathConfigContent["cover_root_path"].get(); auto musicRootPath = pathConfigContent["root_music_path"].get(); - auto stockCoverPath = manager::DirectoryManager::configPath(m_bConf); - stockCoverPath.append("/CoverArt.png"); + auto cov = covMgr.saveCover(song); - auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); - - auto songPath = manager::DirectoryManager::createDirectoryProcess(song, musicRootPath); - songPath.append(song.title); - songPath.append(".mp3"); + auto songPath = createSongPath(song); if (fs::exists(songPath)) { std::cout << "deleting old song with the same metadata" << std::endl; fs::remove(songPath); } std::cout << "copying song to the appropriate directory" << std::endl; + std::cout << song.songPath << std::endl; + std::cout << songPath << std::endl; fs::copy(song.songPath, songPath); fs::remove(song.songPath); song.songPath = std::move(songPath); + std::cout << "copied song to the appropriate directory" << std::endl; AlbumManager albMgr(m_bConf); auto album = albMgr.saveAlbum(song); @@ -311,7 +330,6 @@ void manager::SongManager::saveMisc(model::Song& song) ArtistManager artMgr(m_bConf); auto artist = artMgr.saveArtist(song); artist = artMgr.retrieveArtist(artist); - std::cout << "out" << std::endl; manager::ArtistManager::printArtist(artist); GenreManager gnrMgr(m_bConf); @@ -351,6 +369,22 @@ void manager::SongManager::deleteMisc(const model::Song& song) yrMgr.deleteYear(song); } +// deletes miscellanes records +void manager::SongManager::deleteMiscExceptCoverArt(const model::Song& song) +{ + manager::AlbumManager albMgr(m_bConf); + albMgr.deleteAlbum(song); + + manager::ArtistManager artMgr(m_bConf); + artMgr.deleteArtist(song); + + manager::GenreManager gnrMgr(m_bConf); + gnrMgr.deleteGenre(song); + + manager::YearManager yrMgr(m_bConf); + yrMgr.deleteYear(song); +} + void manager::SongManager::updateMisc( const std::map& songChanges, model::Song& updatedSong, const model::Song& currSong) @@ -386,17 +420,15 @@ void manager::SongManager::updateMisc( database::SongRepository songRepo(m_bConf); songRepo.updateRecord(updatedSong); + + deleteMiscExceptCoverArt(currSong); } void manager::SongManager::modifySongOnFilesystem(model::Song& updatedSong, const model::Song& currSong) { std::cout << "preparing to modify song" << std::endl; - printSong(updatedSong); - auto songPath = manager::DirectoryManager::createDirectoryProcess( - updatedSong, m_bConf, type::PathType::music); - songPath.append(updatedSong.title); - songPath.append(".mp3"); + auto songPath = createSongPath(updatedSong); updatedSong.songPath = std::move(songPath); std::cout << "new path " << updatedSong.songPath << std::endl; @@ -404,6 +436,12 @@ void manager::SongManager::modifySongOnFilesystem(model::Song& updatedSong, fs::copy(currSong.songPath, updatedSong.songPath); fs::remove(currSong.songPath); + auto paths = manager::DirectoryManager::pathConfigContent(m_bConf); + const auto musicRootPath = + paths[manager::DirectoryManager::retrievePathType( + type::PathType::music)].get(); + manager::DirectoryManager::deleteDirectories(currSong, musicRootPath); + manager::CoverArtManager covMgr(m_bConf); - covMgr.updateCover(updatedSong); + covMgr.updateCover(updatedSong, currSong); } diff --git a/src/utility/MetadataRetriever.cpp b/src/utility/MetadataRetriever.cpp index 485c47a..18e8011 100644 --- a/src/utility/MetadataRetriever.cpp +++ b/src/utility/MetadataRetriever.cpp @@ -92,6 +92,64 @@ model::Cover utility::MetadataRetriever::updateCoverArt(const model::Song& song, return cov; } +// tags song with the stock cover art +model::Cover utility::MetadataRetriever::applyStockCoverArt( + const model::Song& song, model::Cover& cov, + const std::string& stockCoverPath) +{ + TagLib::MPEG::File songFile(song.songPath.c_str()); + auto tag = songFile.ID3v2Tag(); + + utility::ImageFile stockImg(cov.imagePath.c_str()); + TagLib::ID3v2::AttachedPictureFrame *pic = + new TagLib::ID3v2::AttachedPictureFrame; + + pic->setPicture(stockImg.data()); + pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover); + + tag->addFrame(pic); + + songFile.save(); + std::cout << "applied stock cover art" << std::endl; + + delete pic; + + return cov; +} + +// extracts cover art from the song and save it to the +// appropriate directory +model::Cover utility::MetadataRetriever::applyCoverArt(const model::Song& song, + model::Cover& cov) +{ + TagLib::MPEG::File songFile(song.songPath.c_str()); + auto tag = songFile.ID3v2Tag(); + auto frameList = tag->frameListMap()["APIC"]; + + auto frame = dynamic_cast( + frameList.front()); + + std::fstream imgSave(cov.imagePath, std::ios::out | + std::ios::binary); + imgSave.write(frame->picture().data(), frame->picture().size()); + imgSave.close(); + + std::cout << "saved to " << cov.imagePath << std::endl; + + return cov; +} + + +bool utility::MetadataRetriever::songContainsCoverArt(const model::Song& song) +{ + TagLib::MPEG::File songFile(song.songPath.c_str()); + auto tag = songFile.ID3v2Tag(); + auto frameList = tag->frameListMap()["APIC"]; + + return !frameList.isEmpty(); +} + + void utility::MetadataRetriever::updateMetadata(model::Song& sngUpdated, const model::Song& sngOld) { std::cout<<"updating metadata"<