diff --git a/CMakeLists.txt b/CMakeLists.txt index aa0aef0..e86a9fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) set(SOURCES - src/appComponent.hpp src/database/albumRepository.cpp src/database/artistRepository.cpp src/database/base_repository.cpp @@ -27,6 +26,7 @@ set(SOURCES src/utilities/metadata_retriever.cpp ) set(HEADERS + include/component/appComponent.hpp include/controller/loginController.hpp include/controller/songController.hpp include/database/albumRepository.h @@ -49,9 +49,13 @@ set(HEADERS include/models/models.h include/utilities/imageFile.h include/utilities/metadata_retriever.h + include/types/albumFilter.h + include/types/artistFilter.h include/types/coverFilter.h + include/types/genreFilter.h include/types/scopes.h include/types/songFilter.h + include/types/yearFilter.h ) set (TAGLIB diff --git a/Scripts/MySQL/create_database.sql b/Scripts/MySQL/create_database.sql index 7e0d410..8594eb5 100644 --- a/Scripts/MySQL/create_database.sql +++ b/Scripts/MySQL/create_database.sql @@ -10,6 +10,34 @@ CREATE TABLE CoverArt ( PRIMARY KEY (CoverArtId) ); +CREATE TABLE Album ( + AlbumId INT NOT NULL AUTO_INCREMENT, + Title TEXT NOT NULL, + Year INT NOT NULL, + + PRIMARY KEY (AlbumId) +); + +CREATE TABLE Artist ( + ArtistId INT NOT NULL AUTO_INCREMENT, + Artist TEXT NOT NULL, + + PRIMARY KEY (ArtistId) +); + +CREATE TABLE Genre ( + GenreId INT NOT NULL AUTO_INCREMENT, + Category TEXT NOT NULL, + + PRIMARY KEY (GenreId) +); + +CREATE TABLE Year ( + YearId INT NOT NULL AUTO_INCREMENT, + + PRIMARY KEY (YearId) +); + CREATE TABLE Song ( SongId INT NOT NULL AUTO_INCREMENT, Title TEXT NOT NULL, @@ -22,13 +50,25 @@ CREATE TABLE Song ( Disc INT NOT NULL, SongPath TEXT NOT NULL, CoverArtId INT NOT NULL, + ArtistId INT NOT NULL, + AlbumId INT NOT NULL, + GenreId INT NOT NULL, + YearId INT NOT NULL, PRIMARY KEY (SongId), - CONSTRAINT FK_CoverArtId FOREIGN KEY (CoverArtId) REFERENCES CoverArt(CoverArtId) + CONSTRAINT FK_CoverArtId FOREIGN KEY (CoverArtId) REFERENCES CoverArt (CoverArtId), + CONSTRAINT FK_ArtistId FOREIGN KEY (ArtistId) REFERENCES Artist (ArtistId), + CONSTRAINT FK_AlbumId FOREIGN KEY (AlbumId) REFERENCES Album (AlbumId), + CONSTRAINT FK_GenreId FOREIGN KEY (GenreId) REFERENCES Genre (GenreId), + CONSTRAINT FK_YearId FOREIGN KEY (YearId) REFERENCES Year (YearId) ); CREATE TABLE User ( UserId INT NOT NULL AUTO_INCREMENT, + Firstname TEXT NOT NULL, + Lastname TEXT NOT NULL, + Email TEXT NOT NULL, + Phone TEXT NOT NULL, Username TEXT NOT NULL, Password TEXT NOT NULL, diff --git a/include/component/appComponent.hpp b/include/component/appComponent.hpp new file mode 100644 index 0000000..78837d3 --- /dev/null +++ b/include/component/appComponent.hpp @@ -0,0 +1,38 @@ +#ifndef APPCOMPONENT_H_ +#define APPCOMPONENT_H_ + +#include + +#include "oatpp/core/macro/component.hpp" +#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" +#include "oatpp/parser/json/mapping/ObjectMapper.hpp" +#include "oatpp/web/server/HttpConnectionHandler.hpp" + +namespace Component +{ + + class appComponent + { + public: + OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionProvider)([] { + return oatpp::network::server::SimpleTCPConnectionProvider::createShared(5002); + }()); + + OATPP_CREATE_COMPONENT(std::shared_ptr, httpRouter)([] { + return oatpp::web::server::HttpRouter::createShared(); + }()); + + OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionHandler)([] { + OATPP_COMPONENT(std::shared_ptr, router); + + return oatpp::web::server::HttpConnectionHandler::createShared(router); + }()); + + OATPP_CREATE_COMPONENT(std::shared_ptr, apiObjectMapper)([] { + return oatpp::parser::json::mapping::ObjectMapper::createShared(); + }()); + private: + }; +} + +#endif diff --git a/include/database/albumRepository.h b/include/database/albumRepository.h index 6525da2..d2b7be0 100644 --- a/include/database/albumRepository.h +++ b/include/database/albumRepository.h @@ -1,8 +1,11 @@ #ifndef ALBUMREPOSITORY_H_ #define ALBUMREPOSITORY_H_ +#include + #include "database/base_repository.h" #include "models/models.h" +#include "types/albumFilter.h" namespace Database { @@ -10,7 +13,15 @@ namespace Database { public: albumRepository(const Model::BinaryPath&); + + std::vector retrieveRecords(); + + Model::Album retrieveRecord(Model::Album&, Type::albumFilter); + + void saveAlbum(const Model::Album&); private: + std::vector parseRecords(MYSQL_RES*); + Model::Album parseRecord(MYSQL_RES*); }; } diff --git a/include/managers/albumManager.h b/include/managers/albumManager.h index c6a83a2..2dac3a2 100644 --- a/include/managers/albumManager.h +++ b/include/managers/albumManager.h @@ -9,6 +9,8 @@ namespace Manager { public: albumManager(const Model::BinaryPath&); + + void saveAlbum(const Model::Song&); private: Model::BinaryPath m_bConf; }; diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h index 1865b19..f49c1d8 100644 --- a/include/managers/song_manager.h +++ b/include/managers/song_manager.h @@ -22,6 +22,7 @@ namespace Manager static void printSong(const Model::Song&); private: void saveSongTemp(Model::Song&); + void saveMisc(Model::Song&); Model::BinaryPath m_bConf; std::string exe_path; diff --git a/include/models/models.h b/include/models/models.h index 2d30e01..06a1373 100644 --- a/include/models/models.h +++ b/include/models/models.h @@ -92,6 +92,8 @@ namespace Model struct BinaryPath { + BinaryPath() = default; + BinaryPath(const char *p) : path(std::move(p)) { } std::string path; }; } diff --git a/include/types/albumFilter.h b/include/types/albumFilter.h new file mode 100644 index 0000000..c9e2b83 --- /dev/null +++ b/include/types/albumFilter.h @@ -0,0 +1,14 @@ +#ifndef ALBUMFILTER_H_ +#define ALBUMFILTER_H_ + +namespace Type +{ + enum class albumFilter + { + id = 0, + title, + year + }; +} + +#endif diff --git a/include/types/artistFilter.h b/include/types/artistFilter.h new file mode 100644 index 0000000..a5243c7 --- /dev/null +++ b/include/types/artistFilter.h @@ -0,0 +1,13 @@ +#ifndef ARTISTFILTER_H_ +#define ARTISTFILTER_H_ + +namespace Type +{ + enum class artistFilter + { + id = 0, + artist + }; +} + +#endif diff --git a/include/types/genreFilter.h b/include/types/genreFilter.h new file mode 100644 index 0000000..27cf279 --- /dev/null +++ b/include/types/genreFilter.h @@ -0,0 +1,13 @@ +#ifndef GENREFILTER_H_ +#define GENREFILTER_H_ + +namespace Type +{ + enum class genreFilter + { + id = 0, + category + }; +} + +#endif diff --git a/include/types/yearFilter.h b/include/types/yearFilter.h new file mode 100644 index 0000000..6161d6c --- /dev/null +++ b/include/types/yearFilter.h @@ -0,0 +1,13 @@ +#ifndef YEARFILTER_H_ +#define YEARFILTER_H_ + +namespace Type +{ + enum class yearFilter + { + id = 0, + year + }; +} + +#endif diff --git a/src/appComponent.hpp b/src/appComponent.hpp deleted file mode 100644 index 2ddc5b7..0000000 --- a/src/appComponent.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef APPCOMPONENT_H_ -#define APPCOMPONENT_H_ - -#include - -#include "oatpp/core/macro/component.hpp" -#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" -#include "oatpp/parser/json/mapping/ObjectMapper.hpp" -#include "oatpp/web/server/HttpConnectionHandler.hpp" - -class appComponent -{ -public: - OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionProvider)([] { - return oatpp::network::server::SimpleTCPConnectionProvider::createShared(5002); - }()); - - OATPP_CREATE_COMPONENT(std::shared_ptr, httpRouter)([] { - return oatpp::web::server::HttpRouter::createShared(); - }()); - - OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionHandler)([] { - OATPP_COMPONENT(std::shared_ptr, router); - - return oatpp::web::server::HttpConnectionHandler::createShared(router); - }()); - - OATPP_CREATE_COMPONENT(std::shared_ptr, apiObjectMapper)([] { - return oatpp::parser::json::mapping::ObjectMapper::createShared(); - }()); -private: -}; - -#endif diff --git a/src/database/albumRepository.cpp b/src/database/albumRepository.cpp index 99d41f1..f3cebb0 100644 --- a/src/database/albumRepository.cpp +++ b/src/database/albumRepository.cpp @@ -1,5 +1,122 @@ #include "database/albumRepository.h" +#include +#include +#include +#include +#include + Database::albumRepository::albumRepository(const Model::BinaryPath& bConf) : base_repository(bConf) { } + + +// TODO: implement this later on +std::vector Database::albumRepository::retrieveRecords() +{ + std::vector albums; + + return albums; +} + +Model::Album Database::albumRepository::retrieveRecord(Model::Album& album, Type::albumFilter filter) +{ + std::stringstream qry; + auto conn = setup_mysql_connection(); + qry << "SELECT alb.* FROM Album alb WHERE "; + + std::unique_ptr param; + switch (filter) { + case Type::albumFilter::id: + qry << "alb.AlbumId = " << album.id; + break; + case Type::albumFilter::title: + param = std::make_unique(new char[album.title.size()]); + mysql_real_escape_string(conn, *param, album.title.c_str(), album.title.size()); + qry << "alb.Title = '" << *param << "'"; + break; + case Type::albumFilter::year: + break; + default: + break; + } + + const std::string query = qry.str(); + auto results = perform_mysql_query(conn, query); + + album = parseRecord(results); + + mysql_close(conn); + std::cout << "done" << std::endl; + + return album; +} + +void Database::albumRepository::saveAlbum(const Model::Album& album) +{ + std::cout << "beginning to insert album record" << std::endl; + + auto conn = setup_mysql_connection(); + auto status = 0; + + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + std::string query = "INSERT INTO Album(Title, Year) VALUES(?, ?)"; + + status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[2]; + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)album.title.c_str(); + auto titleLength = album.title.size(); + params[0].buffer = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_LONG; + params[1].buffer = (char*)&album.year; + params[1].length = 0; + params[1].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "done inserting album record" << std::endl; +} + + +// TODO: implement this +std::vector Database::albumRepository::parseRecords(MYSQL_RES* results) +{ + std::vector albums; + + return albums; +} + +Model::Album Database::albumRepository::parseRecord(MYSQL_RES* results) +{ + Model::Album album; + auto fieldNum = mysql_num_fields(results); + + auto row = mysql_fetch_row(results); + + for (auto i = 0; i != fieldNum; ++i) { + const std::string field(mysql_fetch_field(results)->name); + + if (field.compare("AlbumId") == 0) { + album.id = std::stoi(row[i]); + } + if (field.compare("Title") == 0) { + album.title = row[i]; + } + if (field.compare("Year") == 0) { + album.year = std::stoi(row[i]); + } + } + + return album; +} diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 4e9262b..026f7e7 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -74,6 +74,7 @@ void Database::songRepository::deleteRecord(const Model::Song& song) void Database::songRepository::saveRecord(const Model::Song& song) { + std::cout << "beginning to insert song record" << std::endl; auto conn = setup_mysql_connection(); auto status = 0; diff --git a/src/main.cpp b/src/main.cpp index ca0a705..6326d5b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,7 +9,7 @@ #include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" #include "oatpp/web/server/HttpConnectionHandler.hpp" -#include "appComponent.hpp" +#include "component/appComponent.hpp" #include "controller/loginController.hpp" #include "controller/songController.hpp" #include "database/base_repository.h" @@ -20,7 +20,7 @@ namespace fs = std::filesystem; //void run(const std::string& working_path) void run(const Model::BinaryPath& bConf) { - appComponent component; + Component::appComponent component; OATPP_COMPONENT(std::shared_ptr, router); @@ -43,11 +43,8 @@ void run(const Model::BinaryPath& bConf) int main(int argc, char **argv) { oatpp::base::Environment::init(); - //const std::string working_path = argv[0]; - Model::BinaryPath bConf; - bConf.path = argv[0]; + Model::BinaryPath bConf(argv[0]); - //run(working_path); run(bConf); oatpp::base::Environment::destroy(); diff --git a/src/managers/albumManager.cpp b/src/managers/albumManager.cpp index 46f4d6e..af0de69 100644 --- a/src/managers/albumManager.cpp +++ b/src/managers/albumManager.cpp @@ -1,5 +1,19 @@ #include "managers/albumManager.h" +#include "database/albumRepository.h" +#include "models/models.h" + Manager::albumManager::albumManager(const Model::BinaryPath& bConf) : m_bConf(bConf) { } + + +void Manager::albumManager::saveAlbum(const Model::Song& song) +{ + Model::Album album; + album.title = song.album; + album.year = song.year; + + Database::albumRepository albRepo(m_bConf); + albRepo.saveAlbum(album); +} diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index d59100c..b49d8e0 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -8,8 +8,12 @@ #include "database/coverArtRepository.h" #include "database/songRepository.h" +#include "managers/albumManager.h" +#include "managers/artistManager.h" #include "managers/coverArtManager.h" #include "managers/directory_manager.h" +#include "managers/genreManager.h" +#include "managers/yearManager.h" #include "utilities/metadata_retriever.h" namespace fs = std::filesystem; @@ -31,25 +35,9 @@ void Manager::song_manager::saveSong(Model::Song& song) song = meta.retrieve_metadata(song.songPath); song.data = std::move(data); - coverArtManager covMgr(m_bConf); - auto pathConfigContent = Manager::directory_manager::pathConfigContent(m_bConf); - auto coverRootPath = pathConfigContent["cover_root_path"].get(); - auto musicRootPath = pathConfigContent["root_music_path"].get(); - auto stockCoverPath = Manager::directory_manager::configPath(m_bConf); - stockCoverPath.append("/CoverArt.png"); + saveMisc(song); - auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); - song.coverArtId = cov.id; - - auto songPath = Manager::directory_manager::create_directory_process(song, musicRootPath); - songPath.append(song.title); - songPath.append(".mp3"); - std::cout << "\n\ntemp path: " << song.songPath << std::endl; - std::cout << "new path: " << songPath << std::endl; - fs::copy(song.songPath, songPath); - fs::remove(song.songPath); - song.songPath = std::move(songPath); printSong(song); @@ -120,3 +108,30 @@ void Manager::song_manager::saveSongTemp(Model::Song& song) song.songPath = tmp_song; } +void Manager::song_manager::saveMisc(Model::Song& song) +{ + coverArtManager covMgr(m_bConf); + auto pathConfigContent = Manager::directory_manager::pathConfigContent(m_bConf); + auto coverRootPath = pathConfigContent["cover_root_path"].get(); + auto musicRootPath = pathConfigContent["root_music_path"].get(); + + auto stockCoverPath = Manager::directory_manager::configPath(m_bConf); + stockCoverPath.append("/CoverArt.png"); + + auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); + song.coverArtId = cov.id; + + auto songPath = Manager::directory_manager::create_directory_process(song, musicRootPath); + songPath.append(song.title); + songPath.append(".mp3"); + std::cout << "\n\ntemp path: " << song.songPath << std::endl; + std::cout << "new path: " << songPath << std::endl; + fs::copy(song.songPath, songPath); + fs::remove(song.songPath); + song.songPath = std::move(songPath); + + artistManager artMgr(m_bConf); + albumManager albMgr(m_bConf); + genreManager gnrMgr(m_bConf); + yearManager yrMgr(m_bConf); +}