Switching to C++ #60
+9
-9
@@ -10,22 +10,22 @@ set(SOURCES
|
||||
src/controller/loginController.hpp
|
||||
src/controller/songController.hpp
|
||||
src/database/base_repository.cpp
|
||||
src/directory_manager.cpp
|
||||
src/dto/loginResultDto.hpp
|
||||
src/imageFile.cpp
|
||||
src/main.cpp
|
||||
src/managers/directory_manager.cpp
|
||||
src/managers/song_manager.cpp
|
||||
src/metadata_retriever.cpp
|
||||
src/token_manager.cpp
|
||||
src/managers/token_manager.cpp
|
||||
src/utilities/imageFile.cpp
|
||||
src/utilities/metadata_retriever.cpp
|
||||
)
|
||||
set(HEADERS
|
||||
include/database/base_repository.h
|
||||
include/directory_manager.h
|
||||
include/imageFile.h
|
||||
include/managers/directory_manager.h
|
||||
include/managers/song_manager.h
|
||||
include/metadata_retriever.h
|
||||
include/models.h
|
||||
include/token_manager.h
|
||||
include/managers/token_manager.h
|
||||
include/models/models.h
|
||||
include/utilities/imageFile.h
|
||||
include/utilities/metadata_retriever.h
|
||||
include/types/scopes.h
|
||||
)
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef BASE_REPOSITORY_H_
|
||||
#define BASE_REPOSITORY_H_
|
||||
|
||||
#include<string>
|
||||
#include <string>
|
||||
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
#include "models.h"
|
||||
#include "models/models.h"
|
||||
|
||||
class base_repository
|
||||
{
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#include "models.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string create_directory_process(Song, const char*);
|
||||
std::string read_cover_art(const char*);
|
||||
|
||||
bool delete_song(Song*);
|
||||
|
||||
void copy_stock_to_root(const char*, const std::string);
|
||||
void copy_song_to_path(const char*, const char*);
|
||||
void delete_cover_art_file(const std::string);
|
||||
void delete_directories(Song, const char*);
|
||||
void delete_song(Song);
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef DIRECTORY_MANAGER_H_
|
||||
#define DIRECTORY_MANAGER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "models/models.h"
|
||||
|
||||
class directory_manager
|
||||
{
|
||||
public:
|
||||
|
||||
std::string create_directory_process(Song, const std::string&);
|
||||
// Return Cover instead
|
||||
std::string read_cover_art(const std::string&);
|
||||
|
||||
|
||||
void copy_stock_to_root(const std::string&, const std::string&);
|
||||
void copy_song_to_path(const std::string&, const std::string&);
|
||||
void delete_cover_art_file(const std::string&, const std::string&);
|
||||
void delete_directories(Song, const std::string&);
|
||||
|
||||
private:
|
||||
void delete_song(const Song);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "models.h"
|
||||
#include "models/models.h"
|
||||
|
||||
class song_manager
|
||||
{
|
||||
|
||||
@@ -3,8 +3,12 @@
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "models.h"
|
||||
#include <jwt-cpp/jwt.h>
|
||||
|
||||
#include "models/models.h"
|
||||
#include "types/scopes.h"
|
||||
|
||||
class token_manager
|
||||
@@ -18,6 +22,11 @@ public:
|
||||
bool is_token_valid(std::string&, Scope);
|
||||
private:
|
||||
auth_credentials parse_auth_credentials(std::string_view);
|
||||
|
||||
std::vector<std::string> extract_scopes(const jwt::decoded_jwt&&);
|
||||
std::pair<bool, std::vector<std::string>> fetch_auth_header(const std::string&);
|
||||
|
||||
bool token_supports_scope(const std::vector<std::string>, const std::string&&);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,3 +0,0 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "models.h"
|
||||
+13
-11
@@ -6,22 +6,24 @@
|
||||
|
||||
struct Song
|
||||
{
|
||||
int Id;
|
||||
char Title[1024];
|
||||
char Artist[1024];
|
||||
char Album[1024];
|
||||
char Genre[1024];
|
||||
int Year;
|
||||
int Duration;
|
||||
char SongPath[1024];
|
||||
int id;
|
||||
std::string title;
|
||||
std::string artist;
|
||||
std::string album;
|
||||
std::string genre;
|
||||
int year;
|
||||
int duration;
|
||||
std::string songPath;
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
struct Cover
|
||||
{
|
||||
int Id;
|
||||
char SongTitle[1024];
|
||||
char ImagePath[1024];
|
||||
int id;
|
||||
std::string songTitle;
|
||||
std::string imagePath;
|
||||
// Currently not being used but it should
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
struct LoginRes
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef MODELS_H_
|
||||
#define MODELS_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct Song
|
||||
{
|
||||
int id;
|
||||
std::string title;
|
||||
std::string artist;
|
||||
std::string album;
|
||||
std::string genre;
|
||||
int year;
|
||||
int duration;
|
||||
std::string songPath;
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
struct Cover
|
||||
{
|
||||
int id;
|
||||
std::string songTitle;
|
||||
std::string imagePath;
|
||||
// Not being used but it should be
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
struct LoginRes
|
||||
{
|
||||
int UserId;
|
||||
char Username[1024];
|
||||
char Token[1024];
|
||||
char TokenType[1024];
|
||||
char Message[1024];
|
||||
int Expiration;
|
||||
};
|
||||
|
||||
struct loginResult
|
||||
{
|
||||
int user_id;
|
||||
std::string username;
|
||||
std::string access_token;
|
||||
std::string token_type;
|
||||
std::string message;
|
||||
int expiration;
|
||||
};
|
||||
|
||||
struct auth_credentials
|
||||
{
|
||||
std::string domain;
|
||||
std::string api_identifier;
|
||||
std::string client_id;
|
||||
std::string client_secret;
|
||||
std::string uri;
|
||||
std::string endpoint;
|
||||
};
|
||||
|
||||
struct database_connection
|
||||
{
|
||||
std::string server;
|
||||
std::string username;
|
||||
std::string password;
|
||||
std::string database;
|
||||
};
|
||||
|
||||
struct TokenReq
|
||||
{
|
||||
char ClientId[1024];
|
||||
char ClientSecret[1024];
|
||||
char Audience[1024];
|
||||
char GrantType[1024];
|
||||
char URI[1024];
|
||||
char Endpoint[1024];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef METADATA_RETRIEVER_H_
|
||||
#define METADATA_RETRIEVER_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "models/models.h"
|
||||
|
||||
class metadata_retriever
|
||||
{
|
||||
public:
|
||||
Song retrieve_metadata(std::string&);
|
||||
Cover update_cover_art(Cover, const Song, const std::string&);
|
||||
|
||||
void update_metadata(Song updated_song, const Song old_song);
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "oatpp/web/server/api/ApiController.hpp"
|
||||
|
||||
#include "../dto/loginResultDto.hpp"
|
||||
#include "token_manager.h"
|
||||
#include "managers/token_manager.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
#include "oatpp/web/server/api/ApiController.hpp"
|
||||
|
||||
#include "managers/song_manager.h"
|
||||
#include "models.h"
|
||||
#include "token_manager.h"
|
||||
#include "models/models.h"
|
||||
#include "managers/token_manager.h"
|
||||
#include "types/scopes.h"
|
||||
|
||||
class songController : public oatpp::web::server::api::ApiController
|
||||
@@ -38,13 +38,8 @@ public:
|
||||
|
||||
auto auth = authHeader->std_str();
|
||||
|
||||
//std::cout << "auth " << auth << std::endl;
|
||||
|
||||
token_manager tok;
|
||||
if (!tok.is_token_valid(auth, Scope::upload)) {
|
||||
// TODO: prevent user from moving forward
|
||||
// token did not have the specified scope (permission)
|
||||
}
|
||||
OATPP_ASSERT_HTTP(tok.is_token_valid(auth, Scope::upload), Status::CODE_403, "Not allowed");
|
||||
|
||||
auto mp = std::make_shared<oatpp::web::mime::multipart::Multipart>(request->getHeaders());
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
#include "loginHandler.h"
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "oatpp/web/server/HttpConnectionHandler.hpp"
|
||||
|
||||
#include "dto/loginResultDto.hpp"
|
||||
//#include "dto/loginResultDto.hpp"
|
||||
|
||||
class loginHandler : public oatpp::web::server::HttpRequestHandler
|
||||
{
|
||||
|
||||
+1
-1
@@ -4,7 +4,6 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "models.h"
|
||||
#include <mysql/mysql.h>
|
||||
#include "oatpp/network/server/Server.hpp"
|
||||
#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp"
|
||||
@@ -14,6 +13,7 @@
|
||||
#include "controller/loginController.hpp"
|
||||
#include "controller/songController.hpp"
|
||||
#include "database/base_repository.h"
|
||||
#include "models/models.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "directory_manager.h"
|
||||
#include "managers/directory_manager.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::string create_directory_process(Song song, const char *root_path)
|
||||
std::string directory_manager::create_directory_process(Song song, const std::string& root_path)
|
||||
{
|
||||
auto curr_path = fs::path(root_path);
|
||||
|
||||
@@ -19,7 +18,7 @@ std::string create_directory_process(Song song, const char *root_path)
|
||||
fs::create_directory(curr_path);
|
||||
}
|
||||
|
||||
auto art_path = fs::path(curr_path.string() + song.Artist);
|
||||
auto art_path = fs::path(curr_path.string() + song.artist);
|
||||
if (fs::exists(art_path)) {
|
||||
std::cout<<"artist path exists"<<std::endl;
|
||||
} else {
|
||||
@@ -27,7 +26,7 @@ std::string create_directory_process(Song song, const char *root_path)
|
||||
fs::create_directory(art_path);
|
||||
}
|
||||
|
||||
auto alb_path = fs::path(art_path.string() + "/" + song.Album);
|
||||
auto alb_path = fs::path(art_path.string() + "/" + song.album);
|
||||
if (fs::exists(alb_path)) {
|
||||
std::cout<<"album path exists"<<std::endl;
|
||||
} else {
|
||||
@@ -37,7 +36,7 @@ std::string create_directory_process(Song song, const char *root_path)
|
||||
|
||||
return alb_path.string() + "/";
|
||||
}
|
||||
std::string read_cover_art(const char *source)
|
||||
std::string directory_manager::read_cover_art(const std::string& source)
|
||||
{
|
||||
auto source_path = fs::path(source);
|
||||
|
||||
@@ -53,12 +52,7 @@ std::string read_cover_art(const char *source)
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
bool delete_song(Song *song)
|
||||
{
|
||||
return fs::remove(song->SongPath);
|
||||
}
|
||||
|
||||
void copy_stock_to_root(const char *target, const std::string buff)
|
||||
void directory_manager::copy_stock_to_root(const std::string& target, const std::string& buff)
|
||||
{
|
||||
std::cout<<"starting process"<<std::endl;
|
||||
auto target_path = fs::path(target);
|
||||
@@ -74,7 +68,7 @@ void copy_stock_to_root(const char *target, const std::string buff)
|
||||
|
||||
std::cout<<"copy finished"<<std::endl;
|
||||
}
|
||||
void copy_song_to_path(const char *target, const char *source)
|
||||
void directory_manager::copy_song_to_path(const std::string& target, const std::string& source)
|
||||
{
|
||||
std::cout<<"starting process to copy song"<<std::endl;
|
||||
auto target_path = fs::path(target);
|
||||
@@ -86,16 +80,21 @@ void copy_song_to_path(const char *target, const char *source)
|
||||
fs::remove(source);
|
||||
std::cout<<"copy finished"<<std::endl;
|
||||
}
|
||||
void delete_cover_art_file(const std::string cov_path)
|
||||
void directory_manager::delete_cover_art_file(const std::string& cov_path, const std::string& stock_cover_path)
|
||||
{
|
||||
auto cov = fs::path(cov_path);
|
||||
fs::remove(cov);
|
||||
if (cov_path.compare(stock_cover_path) == 0) {
|
||||
std::cout << "cover has stock cover art, will not deleted" << std::endl;
|
||||
} else {
|
||||
std::cout << "deleting song path" << std::endl;
|
||||
auto cov = fs::path(cov_path);
|
||||
fs::remove(cov);
|
||||
}
|
||||
}
|
||||
void delete_directories(Song song, const char *root_path)
|
||||
void directory_manager::delete_directories(Song song, const std::string& root_path)
|
||||
{
|
||||
std::cout<<"checking to for empty directories to delete"<<std::endl;
|
||||
const std::string art{root_path + std::string{"/"} + song.Artist};
|
||||
const std::string alb{art + "/" + song.Album};
|
||||
const std::string art{root_path + std::string{"/"} + song.artist};
|
||||
const std::string alb{art + "/" + song.album};
|
||||
|
||||
auto alb_path = fs::path(alb);
|
||||
|
||||
@@ -116,10 +115,10 @@ void delete_directories(Song song, const char *root_path)
|
||||
|
||||
std::cout<<"deleted empty directory or directories"<<std::endl;
|
||||
}
|
||||
void delete_song(Song song)
|
||||
void directory_manager::delete_song(const Song song)
|
||||
{
|
||||
std::cout<<"deleting song"<<std::endl;
|
||||
auto song_path = fs::path(song.SongPath);
|
||||
auto song_path = fs::path(song.songPath);
|
||||
|
||||
if (!fs::exists(song_path)) {
|
||||
std::cout<<"song does not exists"<<std::endl;
|
||||
@@ -130,18 +129,19 @@ void delete_song(Song song)
|
||||
std::cout<<"deleted song"<<std::endl;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
//extern "C"
|
||||
//{
|
||||
|
||||
void create_directory(Song, const char*, char*);
|
||||
void copy_stock_cover_art(const char*, const char*);
|
||||
void copy_song(const char*, const char*);
|
||||
void delete_cover_art(const char*, const char*);
|
||||
void delete_empty_directories(Song, const char*);
|
||||
void delete_from_filesystem(Song);
|
||||
void delete_song_empty_directories(Song, const char*);
|
||||
void print_song_details(const Song);
|
||||
//void create_directory(Song, const char*, char*);
|
||||
//void copy_stock_cover_art(const char*, const char*);
|
||||
//void copy_song(const char*, const char*);
|
||||
//void delete_cover_art(const char*, const char*);
|
||||
//void delete_empty_directories(Song, const char*);
|
||||
//void delete_from_filesystem(Song);
|
||||
//void delete_song_empty_directories(Song, const char*);
|
||||
//void print_song_details(const Song);
|
||||
|
||||
/**
|
||||
void create_directory(Song song, const char *root_path, char *dir)
|
||||
{
|
||||
const auto tmp = create_directory_process(song, root_path);
|
||||
@@ -153,6 +153,8 @@ void copy_stock_cover_art(const char *target, const char *source)
|
||||
const auto buff = read_cover_art(source);
|
||||
copy_stock_to_root(target, buff);
|
||||
}
|
||||
*/
|
||||
/**
|
||||
void copy_song(const char *target, const char *source)
|
||||
{
|
||||
copy_song_to_path(target, source);
|
||||
@@ -197,3 +199,4 @@ void print_song_details(const Song song)
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
@@ -5,14 +5,12 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <cpr/cpr.h>
|
||||
#include <jwt-cpp/jwt.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "token_manager.h"
|
||||
#include "managers/token_manager.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -60,62 +58,31 @@ loginResult token_manager::retrieve_token(std::string_view path)
|
||||
|
||||
bool token_manager::is_token_valid(std::string& auth, Scope scope)
|
||||
{
|
||||
std::istringstream iss(auth);
|
||||
std::vector<std::string> authHeader{std::istream_iterator<std::string>(iss),
|
||||
std::istream_iterator<std::string>()
|
||||
};
|
||||
auto authPair = fetch_auth_header(auth);
|
||||
|
||||
auto wordCount = 0;
|
||||
/**
|
||||
for (auto& word : authHeader) {
|
||||
std::cout << "word " << wordCount++ << " " << word << std::endl;
|
||||
}
|
||||
*/
|
||||
if (!std::get<0>(authPair)) {
|
||||
std::cout << "no Bearer found" << std::endl;
|
||||
|
||||
if (!std::any_of(authHeader.begin(), authHeader.end(), [](std::string word)
|
||||
{
|
||||
std::cout << "comparing " << word << " to Bearer" << std::endl;
|
||||
return (word.compare("Bearer") == 0);
|
||||
})) {
|
||||
std::cout << "Bearer not found" << std::endl;
|
||||
return false;
|
||||
return std::get<0>(authPair);
|
||||
}
|
||||
|
||||
auto authHeader = std::get<1>(authPair);
|
||||
|
||||
auto token = authHeader.at(authHeader.size()-1);
|
||||
std::cout << "going to decode " << token << std::endl;
|
||||
auto decoded = jwt::decode(token);
|
||||
|
||||
std::vector<std::string> scopes;
|
||||
for (auto d : decoded.get_payload_claims()) {
|
||||
if (d.first.compare("scope") == 0) {
|
||||
std::cout << "found scope" << std::endl;
|
||||
std::string all_scopes(d.second.to_json().get<std::string>());
|
||||
std::istringstream iss(all_scopes);
|
||||
|
||||
scopes.assign(std::istream_iterator<std::string>(iss),
|
||||
std::istream_iterator<std::string>());
|
||||
//std::cout << scopes << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "printing all scopes" << std::endl;
|
||||
|
||||
for (auto& scope_obj : scopes) {
|
||||
std::cout << scope_obj << std::endl;
|
||||
}
|
||||
|
||||
|
||||
std::cout << "goodbye" << std::endl;
|
||||
exit(1);
|
||||
auto scopes = extract_scopes(jwt::decode(token));
|
||||
|
||||
switch (scope) {
|
||||
case Scope::upload:
|
||||
return token_supports_scope(scopes, "upload:songs");
|
||||
break;
|
||||
case Scope::download:
|
||||
return token_supports_scope(scopes, "download:songs");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
auth_credentials token_manager::parse_auth_credentials(std::string_view path)
|
||||
@@ -140,3 +107,48 @@ auth_credentials token_manager::parse_auth_credentials(std::string_view path)
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
std::vector<std::string> token_manager::extract_scopes(const jwt::decoded_jwt&& decoded)
|
||||
{
|
||||
std::vector<std::string> scopes;
|
||||
|
||||
for (auto d : decoded.get_payload_claims()) {
|
||||
if (d.first.compare("scope") == 0) {
|
||||
std::cout << "found scope" << std::endl;
|
||||
std::string all_scopes(d.second.to_json().get<std::string>());
|
||||
std::istringstream iss(all_scopes);
|
||||
|
||||
scopes.assign(std::istream_iterator<std::string>(iss),
|
||||
std::istream_iterator<std::string>());
|
||||
}
|
||||
}
|
||||
|
||||
return scopes;
|
||||
}
|
||||
|
||||
std::pair<bool, std::vector<std::string>> token_manager::fetch_auth_header(const std::string& auth)
|
||||
{
|
||||
std::istringstream iss(auth);
|
||||
std::vector<std::string> authHeader{std::istream_iterator<std::string>(iss),
|
||||
std::istream_iterator<std::string>()
|
||||
};
|
||||
|
||||
bool foundBearer = false;
|
||||
if (std::any_of(authHeader.begin(), authHeader.end(),
|
||||
[](std::string word) {
|
||||
return (word.compare("Bearer") == 0);
|
||||
})) {
|
||||
std::cout << "Bearer found" << std::endl;
|
||||
foundBearer = true;
|
||||
}
|
||||
|
||||
return std::make_pair(foundBearer, authHeader);
|
||||
}
|
||||
|
||||
bool token_manager::token_supports_scope(const std::vector<std::string> scopes, const std::string&& scope)
|
||||
{
|
||||
return std::any_of(scopes.begin(), scopes.end(),
|
||||
[&](std::string foundScope) {
|
||||
return (foundScope.compare(scope) == 0);
|
||||
});
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
//#include <taglib/attachedpictureframe.h>
|
||||
#include <attachedpictureframe.h>
|
||||
//#include <taglib/fileref.h>
|
||||
#include <fileref.h>
|
||||
//#include <taglib/mpegfile.h>
|
||||
#include <mpegfile.h>
|
||||
//#include <taglib/tag.h>
|
||||
#include <tag.h>
|
||||
|
||||
#include "directory_manager.h"
|
||||
#include "metadata_retriever.h"
|
||||
#include "imageFile.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void retrieve_metadata(Song*, char*);
|
||||
void update_metadata(Song*, Song*);
|
||||
|
||||
void retrieve_metadata(Song *sng, char* song_path)
|
||||
{
|
||||
std::cout<<"extern C"<<std::endl;
|
||||
TagLib::FileRef file(song_path);
|
||||
|
||||
strcpy(sng->Title, file.tag()->title().toCString());
|
||||
strcpy(sng->Artist, file.tag()->artist().toCString());
|
||||
strcpy(sng->Album, file.tag()->album().toCString());
|
||||
strcpy(sng->Genre, file.tag()->genre().toCString());
|
||||
sng->Year = file.tag()->year();
|
||||
sng->Duration = file.audioProperties()->lengthInSeconds();
|
||||
strcpy(sng->SongPath, song_path);
|
||||
}
|
||||
void update_metadata(Song *sng_updated, Song *sng_old)
|
||||
{
|
||||
std::cout<<"updating metadata"<<std::endl;
|
||||
TagLib::FileRef file(sng_old->SongPath);
|
||||
|
||||
if (strlen(sng_updated->Title) > 0) {
|
||||
file.tag()->setTitle(sng_updated->Title);
|
||||
}
|
||||
if (strlen(sng_updated->Artist) > 0) {
|
||||
file.tag()->setArtist(sng_updated->Artist);
|
||||
}
|
||||
if (strlen(sng_updated->Album) > 0) {
|
||||
file.tag()->setAlbum(sng_updated->Album);
|
||||
}
|
||||
if (strlen(sng_updated->Genre) > 0) {
|
||||
file.tag()->setGenre(sng_updated->Genre);
|
||||
}
|
||||
if (sng_updated->Year > 0) {
|
||||
file.tag()->setYear(sng_updated->Year);
|
||||
}
|
||||
|
||||
file.save();
|
||||
}
|
||||
void update_cover_art(Cover *cov, Song *song, const char *root_path)
|
||||
{
|
||||
TagLib::MPEG::File sngF(song->SongPath);
|
||||
TagLib::ID3v2::Tag *tag = sngF.ID3v2Tag();
|
||||
auto frameList = tag->frameListMap()["APIC"];
|
||||
|
||||
if (frameList.isEmpty()) {
|
||||
std::string stock_path{root_path};
|
||||
stock_path.append("CoverArt.png");
|
||||
strcpy(cov->ImagePath, stock_path.c_str());
|
||||
|
||||
imageFile stock_img(stock_path.c_str());
|
||||
|
||||
TagLib::ID3v2::AttachedPictureFrame *pic =
|
||||
new TagLib::ID3v2::AttachedPictureFrame;
|
||||
pic->setPicture(stock_img.data());
|
||||
pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
|
||||
|
||||
tag->addFrame(pic);
|
||||
|
||||
sngF.save();
|
||||
std::cout<<"applied stock cover art"<<std::endl;
|
||||
} else {
|
||||
auto frame = dynamic_cast<TagLib::ID3v2::AttachedPictureFrame*>(
|
||||
frameList.front());
|
||||
auto img_path = create_directory_process(*song, root_path);
|
||||
img_path.append(song->Title);
|
||||
img_path.append(".png");
|
||||
strcpy(cov->ImagePath, img_path.c_str());
|
||||
std::cout<<cov->ImagePath<<std::endl;
|
||||
|
||||
std::fstream img_save(cov->ImagePath, std::ios::out |
|
||||
std::ios::binary);
|
||||
img_save.write(frame->picture().data(), frame->picture().size());
|
||||
img_save.close();
|
||||
std::cout<<"saved to "<<cov->ImagePath<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "imageFile.h"
|
||||
#include "utilities/imageFile.h"
|
||||
|
||||
imageFile::imageFile(const char *file) : TagLib::File(file)
|
||||
{
|
||||
@@ -0,0 +1,108 @@
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
#include <attachedpictureframe.h>
|
||||
#include <fileref.h>
|
||||
#include <mpegfile.h>
|
||||
#include <tag.h>
|
||||
|
||||
#include "managers/directory_manager.h"
|
||||
#include "utilities/imageFile.h"
|
||||
#include "utilities/metadata_retriever.h"
|
||||
|
||||
Song metadata_retriever::retrieve_metadata(std::string& song_path)
|
||||
{
|
||||
TagLib::FileRef file(song_path.c_str());
|
||||
Song song;
|
||||
song.title = file.tag()->title().toCString();
|
||||
song.artist = file.tag()->artist().toCString();
|
||||
song.album = file.tag()->album().toCString();
|
||||
song.genre = file.tag()->genre().toCString();
|
||||
song.year = file.tag()->year();
|
||||
song.duration = file.audioProperties()->lengthInSeconds();
|
||||
song.songPath = song_path;
|
||||
|
||||
/**
|
||||
strcpy(sng->Title, file.tag()->title().toCString());
|
||||
strcpy(sng->Artist, file.tag()->artist().toCString());
|
||||
strcpy(sng->Album, file.tag()->album().toCString());
|
||||
strcpy(sng->Genre, file.tag()->genre().toCString());
|
||||
sng->Year = file.tag()->year();
|
||||
sng->Duration = file.audioProperties()->lengthInSeconds();
|
||||
strcpy(sng->SongPath, song_path);
|
||||
*/
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
Cover metadata_retriever::update_cover_art(Cover cov, const Song song, const std::string& root_path)
|
||||
{
|
||||
TagLib::MPEG::File sngF(song.songPath.c_str());
|
||||
TagLib::ID3v2::Tag *tag = sngF.ID3v2Tag();
|
||||
auto frameList = tag->frameListMap()["APIC"];
|
||||
|
||||
if (frameList.isEmpty()) {
|
||||
std::string stock_path{root_path};
|
||||
stock_path.append("CoverArt.png");
|
||||
cov.imagePath = stock_path;
|
||||
//strcpy(cov->ImagePath, stock_path.c_str());
|
||||
|
||||
imageFile stock_img(cov.imagePath.c_str());
|
||||
|
||||
TagLib::ID3v2::AttachedPictureFrame *pic =
|
||||
new TagLib::ID3v2::AttachedPictureFrame;
|
||||
pic->setPicture(stock_img.data());
|
||||
pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
|
||||
|
||||
tag->addFrame(pic);
|
||||
|
||||
sngF.save();
|
||||
std::cout<<"applied stock cover art"<<std::endl;
|
||||
} else {
|
||||
auto frame = dynamic_cast<TagLib::ID3v2::AttachedPictureFrame*>(
|
||||
frameList.front());
|
||||
directory_manager dir;
|
||||
auto img_path = dir.create_directory_process(song, root_path);
|
||||
img_path.append(song.title);
|
||||
img_path.append(".png");
|
||||
cov.imagePath = img_path;
|
||||
//strcpy(cov->ImagePath, img_path.c_str());
|
||||
std::cout<<cov.imagePath<<std::endl;
|
||||
|
||||
std::fstream img_save(cov.imagePath, std::ios::out |
|
||||
std::ios::binary);
|
||||
img_save.write(frame->picture().data(), frame->picture().size());
|
||||
img_save.close();
|
||||
std::cout<<"saved to "<<cov.imagePath<<std::endl;
|
||||
}
|
||||
|
||||
return cov;
|
||||
}
|
||||
|
||||
void metadata_retriever::update_metadata(Song sng_updated, const Song sng_old)
|
||||
{
|
||||
std::cout<<"updating metadata"<<std::endl;
|
||||
TagLib::FileRef file(sng_old.songPath.c_str());
|
||||
|
||||
if (sng_updated.title.size() > 0) {
|
||||
file.tag()->setTitle(sng_updated.title);
|
||||
}
|
||||
if (sng_updated.artist.size() > 0) {
|
||||
file.tag()->setArtist(sng_updated.artist);
|
||||
}
|
||||
if (sng_updated.album.size() > 0) {
|
||||
file.tag()->setAlbum(sng_updated.album);
|
||||
}
|
||||
if (sng_updated.genre.size() > 0) {
|
||||
file.tag()->setGenre(sng_updated.genre);
|
||||
}
|
||||
if (sng_updated.year > 0) {
|
||||
file.tag()->setYear(sng_updated.year);
|
||||
}
|
||||
|
||||
file.save();
|
||||
}
|
||||
Reference in New Issue
Block a user