Added albumArtist field memeber to Song model. Automatically apply disc value 1 for song's metadata that have an empty disc field. Switched from TagLib::FileRef to TagLib::MPEG::File
This commit is contained in:
@@ -13,6 +13,7 @@ CREATE TABLE CoverArt (
|
|||||||
CREATE TABLE Album (
|
CREATE TABLE Album (
|
||||||
AlbumId INT NOT NULL AUTO_INCREMENT,
|
AlbumId INT NOT NULL AUTO_INCREMENT,
|
||||||
Title TEXT NOT NULL,
|
Title TEXT NOT NULL,
|
||||||
|
Artist TEXT NOT NULL,
|
||||||
Year INT NOT NULL,
|
Year INT NOT NULL,
|
||||||
|
|
||||||
PRIMARY KEY (AlbumId)
|
PRIMARY KEY (AlbumId)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "database/AlbumRepository.h"
|
#include "database/AlbumRepository.h"
|
||||||
#include "dto/AlbumDto.hpp"
|
#include "dto/AlbumDto.hpp"
|
||||||
|
#include "dto/conversion/DtoConversions.h"
|
||||||
#include "manager/AlbumManager.h"
|
#include "manager/AlbumManager.h"
|
||||||
#include "manager/TokenManager.h"
|
#include "manager/TokenManager.h"
|
||||||
#include "model/Models.h"
|
#include "model/Models.h"
|
||||||
@@ -57,10 +58,7 @@ public:
|
|||||||
auto albums = oatpp::data::mapping::type::List<dto::AlbumDto::ObjectWrapper>::createShared();
|
auto albums = oatpp::data::mapping::type::List<dto::AlbumDto::ObjectWrapper>::createShared();
|
||||||
|
|
||||||
for (auto& albDb : albsDb) {
|
for (auto& albDb : albsDb) {
|
||||||
auto alb = dto::AlbumDto::createShared();
|
auto alb = dto::conversion::DtoConversions::toAlbumDto(albDb);
|
||||||
alb->id = albDb.id;
|
|
||||||
alb->title = albDb.title.c_str();
|
|
||||||
alb->year = albDb.year;
|
|
||||||
|
|
||||||
albums->pushBack(alb);
|
albums->pushBack(alb);
|
||||||
}
|
}
|
||||||
@@ -85,10 +83,7 @@ public:
|
|||||||
std::cout << "album exists" << std::endl;
|
std::cout << "album exists" << std::endl;
|
||||||
albDb = albRepo.retrieveRecord(albDb, type::AlbumFilter::id);
|
albDb = albRepo.retrieveRecord(albDb, type::AlbumFilter::id);
|
||||||
|
|
||||||
auto album = dto::AlbumDto::createShared();
|
auto album = dto::conversion::DtoConversions::toAlbumDto(albDb);
|
||||||
album->id = albDb.id;
|
|
||||||
album->title = albDb.title.c_str();
|
|
||||||
album->year = albDb.year;
|
|
||||||
|
|
||||||
return createDtoResponse(Status::CODE_200, album);
|
return createDtoResponse(Status::CODE_200, album);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef ALBUMREPOSITORY_H_
|
#ifndef ALBUMREPOSITORY_H_
|
||||||
#define ALBUMREPOSITORY_H_
|
#define ALBUMREPOSITORY_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -30,9 +31,13 @@ namespace database
|
|||||||
|
|
||||||
std::pair<model::Album, int> parseRecordWithSongCount(MYSQL_STMT*);
|
std::pair<model::Album, int> parseRecordWithSongCount(MYSQL_STMT*);
|
||||||
|
|
||||||
// TODO: after parseRecord(MYSQL_STMT*) is implemented remove
|
std::shared_ptr<MYSQL_BIND> valueBind(model::Album&,
|
||||||
// parseRecord(MYSQL_RES*)
|
std::tuple<char*, char*>&);
|
||||||
model::Album parseRecord(MYSQL_RES*);
|
std::shared_ptr<MYSQL_BIND> valueBindWithSongCount(model::Album&,
|
||||||
|
std::tuple<char*, char*>&, int&);
|
||||||
|
|
||||||
|
std::tuple<char*, char*> metadataBuffer();
|
||||||
|
|
||||||
model::Album parseRecord(MYSQL_STMT*);
|
model::Album parseRecord(MYSQL_STMT*);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ namespace database
|
|||||||
class SongRepository : public BaseRepository
|
class SongRepository : public BaseRepository
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SongRepository(const std::string&);
|
|
||||||
SongRepository(const model::BinaryPath&);
|
SongRepository(const model::BinaryPath&);
|
||||||
|
|
||||||
std::vector<model::Song> retrieveRecords();
|
std::vector<model::Song> retrieveRecords();
|
||||||
@@ -30,9 +29,9 @@ namespace database
|
|||||||
void updateRecord(const model::Song&);
|
void updateRecord(const model::Song&);
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<MYSQL_BIND> valueBind(model::Song&,
|
std::shared_ptr<MYSQL_BIND> valueBind(model::Song&,
|
||||||
std::tuple<char*, char*, char*, char*, char*>&);
|
std::tuple<char*, char*, char*, char*, char*, char*>&);
|
||||||
|
|
||||||
std::tuple<char*, char*, char*, char*, char*> metadataBuffer();
|
std::tuple<char*, char*, char*, char*, char*, char*> metadataBuffer();
|
||||||
|
|
||||||
std::vector<model::Song> parseRecords(MYSQL_STMT*);
|
std::vector<model::Song> parseRecords(MYSQL_STMT*);
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace dto
|
|||||||
|
|
||||||
DTO_FIELD(Int32, id);
|
DTO_FIELD(Int32, id);
|
||||||
DTO_FIELD(String, title);
|
DTO_FIELD(String, title);
|
||||||
|
DTO_FIELD(String, artist);
|
||||||
DTO_FIELD(Int32, year);
|
DTO_FIELD(Int32, year);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace dto
|
|||||||
DTO_FIELD(Int32, id);
|
DTO_FIELD(Int32, id);
|
||||||
DTO_FIELD(String, title);
|
DTO_FIELD(String, title);
|
||||||
DTO_FIELD(String, artist);
|
DTO_FIELD(String, artist);
|
||||||
|
DTO_FIELD(String, album_artist);
|
||||||
DTO_FIELD(String, album);
|
DTO_FIELD(String, album);
|
||||||
DTO_FIELD(String, genre);
|
DTO_FIELD(String, genre);
|
||||||
DTO_FIELD(Int32, track);
|
DTO_FIELD(Int32, track);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef DTOCONVERSIONS_H_
|
#ifndef DTOCONVERSIONS_H_
|
||||||
#define DTOCONVERSIONS_H_
|
#define DTOCONVERSIONS_H_
|
||||||
|
|
||||||
|
#include "dto/AlbumDto.hpp"
|
||||||
#include "dto/LoginResultDto.hpp"
|
#include "dto/LoginResultDto.hpp"
|
||||||
#include "dto/SongDto.hpp"
|
#include "dto/SongDto.hpp"
|
||||||
#include "model/Models.h"
|
#include "model/Models.h"
|
||||||
@@ -13,6 +14,8 @@ namespace dto { namespace conversion {
|
|||||||
static dto::RegisterResultDto::ObjectWrapper toRegisterResultDto(
|
static dto::RegisterResultDto::ObjectWrapper toRegisterResultDto(
|
||||||
const model::RegisterResult&);
|
const model::RegisterResult&);
|
||||||
|
|
||||||
|
static dto::AlbumDto::ObjectWrapper toAlbumDto(const model::Album&);
|
||||||
|
|
||||||
static dto::SongDto::ObjectWrapper toSongDto(const model::Song&);
|
static dto::SongDto::ObjectWrapper toSongDto(const model::Song&);
|
||||||
|
|
||||||
static model::Song toSong(dto::SongDto::ObjectWrapper&);
|
static model::Song toSong(dto::SongDto::ObjectWrapper&);
|
||||||
|
|||||||
+35
-35
@@ -5,14 +5,24 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace model {
|
namespace model {
|
||||||
struct Song {
|
class Song {
|
||||||
|
public:
|
||||||
Song() = default;
|
Song() = default;
|
||||||
Song(const int id) : id(id) { }
|
Song(const int id) : id(id) { }
|
||||||
|
Song(const int id, const std::string& title, const std::string& artist,
|
||||||
|
const std::string& album, const std::string& albumArtist,
|
||||||
|
const std::string& genre, const int year, const int duration,
|
||||||
|
const int track, const int disc, const std::string songPath) :
|
||||||
|
id(id), title(title), artist(artist), album(album),
|
||||||
|
albumArtist(albumArtist), genre(genre), year(year),
|
||||||
|
duration(duration), track(track), disc(disc),
|
||||||
|
songPath(songPath) { }
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
std::string title;
|
std::string title;
|
||||||
std::string artist;
|
std::string artist;
|
||||||
std::string album;
|
std::string album;
|
||||||
|
std::string albumArtist;
|
||||||
std::string genre;
|
std::string genre;
|
||||||
int year;
|
int year;
|
||||||
int duration;
|
int duration;
|
||||||
@@ -27,42 +37,35 @@ struct Song {
|
|||||||
int yearId;
|
int yearId;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Artist {
|
class Artist {
|
||||||
|
public:
|
||||||
Artist() = default;
|
Artist() = default;
|
||||||
Artist(const Song& song)
|
Artist(const Song& song) : id(song.artistId), artist(song.artist) { }
|
||||||
{
|
|
||||||
id = song.artistId;
|
|
||||||
artist = song.artist;
|
|
||||||
}
|
|
||||||
Artist(const int id) : id(id) { }
|
Artist(const int id) : id(id) { }
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
std::string artist;
|
std::string artist;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Album {
|
class Album {
|
||||||
|
public:
|
||||||
Album() = default;
|
Album() = default;
|
||||||
Album(const Song& song)
|
Album(const Song& song) :
|
||||||
{
|
id(song.albumId), title(song.album),artist(song.artist), year(song.year) { }
|
||||||
id = song.albumId;
|
|
||||||
title = song.album;
|
|
||||||
year = song.year;
|
|
||||||
}
|
|
||||||
Album(const int id) : id(id) { }
|
Album(const int id) : id(id) { }
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
std::string title;
|
std::string title;
|
||||||
|
std::string artist;
|
||||||
int year;
|
int year;
|
||||||
std::vector<Song> songs;
|
std::vector<Song> songs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Genre {
|
class Genre {
|
||||||
|
public:
|
||||||
Genre() = default;
|
Genre() = default;
|
||||||
Genre(const Song& song)
|
Genre(const Song& song) :
|
||||||
{
|
id(song.genreId), category(song.genre) { }
|
||||||
id = song.genreId;
|
|
||||||
category = song.genre;
|
|
||||||
}
|
|
||||||
Genre(const int id) : id(id) { }
|
Genre(const int id) : id(id) { }
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
@@ -70,26 +73,22 @@ struct Genre {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Year {
|
class Year {
|
||||||
|
public:
|
||||||
Year() = default;
|
Year() = default;
|
||||||
Year(const Song& song)
|
Year(const Song& song) :
|
||||||
{
|
id(song.yearId), year(song.year) { }
|
||||||
id = song.yearId;
|
|
||||||
year = song.year;
|
|
||||||
}
|
|
||||||
Year(const int id) : id(id) { }
|
Year(const int id) : id(id) { }
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
int year;
|
int year;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Cover {
|
class Cover {
|
||||||
|
public:
|
||||||
Cover() = default;
|
Cover() = default;
|
||||||
Cover(const Song& song)
|
Cover(const Song& song) :
|
||||||
{
|
id(song.coverArtId), songTitle(song.title) { }
|
||||||
id = song.coverArtId;
|
|
||||||
songTitle = song.title;
|
|
||||||
}
|
|
||||||
Cover(const int id) : id(id) { }
|
Cover(const int id) : id(id) { }
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
@@ -163,11 +162,12 @@ struct DatabaseConnection {
|
|||||||
std::string database;
|
std::string database;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BinaryPath {
|
class BinaryPath {
|
||||||
|
public:
|
||||||
BinaryPath() = default;
|
BinaryPath() = default;
|
||||||
BinaryPath(const char *p) : path(std::move(p)) { }
|
BinaryPath(const char *p) : path(p) { }
|
||||||
BinaryPath(std::string& p) : path(p) { }
|
|
||||||
BinaryPath(const std::string& p) : path(p) { }
|
BinaryPath(const std::string& p) : path(p) { }
|
||||||
|
BinaryPath(const std::string&& p) : path(p) { }
|
||||||
|
|
||||||
std::string path;
|
std::string path;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace utility {
|
|||||||
class MetadataRetriever
|
class MetadataRetriever
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
model::Song retrieveMetadata(std::string&);
|
model::Song retrieveMetadata(model::Song&);
|
||||||
|
|
||||||
model::Cover updateCoverArt(const model::Song&, model::Cover&, const 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 applyStockCoverArt(const model::Song&, model::Cover&, const std::string&);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ std::pair<model::Album, int> AlbumRepository::retrieveRecordWithSongCount(model:
|
|||||||
auto conn = setupMysqlConnection();
|
auto conn = setupMysqlConnection();
|
||||||
auto stmt = mysql_stmt_init(conn);
|
auto stmt = mysql_stmt_init(conn);
|
||||||
|
|
||||||
MYSQL_BIND params[4];
|
MYSQL_BIND params[1];
|
||||||
std::memset(params, 0, sizeof(params));
|
std::memset(params, 0, sizeof(params));
|
||||||
|
|
||||||
qry << "SELECT alb.*, COUNT(*) AS SongCount FROM Album alb LEFT JOIN ";
|
qry << "SELECT alb.*, COUNT(*) AS SongCount FROM Album alb LEFT JOIN ";
|
||||||
@@ -181,11 +181,11 @@ void AlbumRepository::saveAlbum(const model::Album& album)
|
|||||||
auto conn = setupMysqlConnection();
|
auto conn = setupMysqlConnection();
|
||||||
MYSQL_STMT *stmt = mysql_stmt_init(conn);
|
MYSQL_STMT *stmt = mysql_stmt_init(conn);
|
||||||
|
|
||||||
const std::string query = "INSERT INTO Album(Title, Year) VALUES(?, ?)";
|
const std::string query = "INSERT INTO Album(Title, Artist, Year) VALUES(?, ?, ?)";
|
||||||
|
|
||||||
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
||||||
|
|
||||||
MYSQL_BIND params[2];
|
MYSQL_BIND params[3];
|
||||||
memset(params, 0, sizeof(params));
|
memset(params, 0, sizeof(params));
|
||||||
|
|
||||||
params[0].buffer_type = MYSQL_TYPE_STRING;
|
params[0].buffer_type = MYSQL_TYPE_STRING;
|
||||||
@@ -194,11 +194,17 @@ void AlbumRepository::saveAlbum(const model::Album& album)
|
|||||||
params[0].length= &titleLength;
|
params[0].length= &titleLength;
|
||||||
params[0].is_null = 0;
|
params[0].is_null = 0;
|
||||||
|
|
||||||
params[1].buffer_type = MYSQL_TYPE_LONG;
|
params[1].buffer_type = MYSQL_TYPE_STRING;
|
||||||
params[1].buffer = (char*)&album.year;
|
params[1].buffer = (char*)album.artist.c_str();
|
||||||
params[1].length = 0;
|
auto artistLength = album.artist.size();
|
||||||
|
params[1].length = &artistLength;
|
||||||
params[1].is_null = 0;
|
params[1].is_null = 0;
|
||||||
|
|
||||||
|
params[2].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
params[2].buffer = (char*)&album.year;
|
||||||
|
params[2].length = 0;
|
||||||
|
params[2].is_null = 0;
|
||||||
|
|
||||||
status = mysql_stmt_bind_param(stmt, params);
|
status = mysql_stmt_bind_param(stmt, params);
|
||||||
status = mysql_stmt_execute(stmt);
|
status = mysql_stmt_execute(stmt);
|
||||||
|
|
||||||
@@ -259,32 +265,9 @@ std::vector<model::Album> AlbumRepository::parseRecords(MYSQL_STMT* stmt)
|
|||||||
for (auto status = 0; status == 0; status = mysql_stmt_next_result(stmt)) {
|
for (auto status = 0; status == 0; status = mysql_stmt_next_result(stmt)) {
|
||||||
if (mysql_stmt_field_count(stmt) > 0) {
|
if (mysql_stmt_field_count(stmt) > 0) {
|
||||||
model::Album alb;
|
model::Album alb;
|
||||||
auto res = mysql_stmt_result_metadata(stmt);
|
auto metaBuff = metadataBuffer();
|
||||||
auto fields = mysql_fetch_fields(res);
|
auto bindedValues = valueBind(alb, metaBuff);
|
||||||
const auto strLen = 1024;
|
status = mysql_stmt_bind_result(stmt, bindedValues.get());
|
||||||
|
|
||||||
MYSQL_BIND val[valAmt];
|
|
||||||
memset(val, 0, sizeof(val));
|
|
||||||
|
|
||||||
char title[strLen];
|
|
||||||
|
|
||||||
val[0].buffer_type = MYSQL_TYPE_LONG;
|
|
||||||
val[0].buffer = (char*)&alb.id;
|
|
||||||
val[0].length = &len[0];
|
|
||||||
val[0].is_null = &nullRes[0];
|
|
||||||
|
|
||||||
val[1].buffer_type = MYSQL_TYPE_STRING;
|
|
||||||
val[1].buffer = (char*)title;
|
|
||||||
val[1].buffer_length = strLen;
|
|
||||||
val[1].length = &len[1];
|
|
||||||
val[1].is_null = &nullRes[1];
|
|
||||||
|
|
||||||
val[2].buffer_type = MYSQL_TYPE_LONG;
|
|
||||||
val[2].buffer = (char*)&alb.year;
|
|
||||||
val[2].length = &len[2];
|
|
||||||
val[2].is_null = &nullRes[2];
|
|
||||||
|
|
||||||
status = mysql_stmt_bind_result(stmt, val);
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
std::cout << "fetching statement result" << std::endl;
|
std::cout << "fetching statement result" << std::endl;
|
||||||
@@ -294,7 +277,8 @@ std::vector<model::Album> AlbumRepository::parseRecords(MYSQL_STMT* stmt)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
alb.title = title;
|
alb.title = std::get<0>(metaBuff);
|
||||||
|
alb.artist = std::get<1>(metaBuff);
|
||||||
albums.push_back(std::move(alb));
|
albums.push_back(std::move(alb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,31 +288,6 @@ std::vector<model::Album> AlbumRepository::parseRecords(MYSQL_STMT* stmt)
|
|||||||
return albums;
|
return albums;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check to see if this is not used, if not then remove it
|
|
||||||
model::Album AlbumRepository::parseRecord(MYSQL_RES* results)
|
|
||||||
{
|
|
||||||
std::cout << "parsing album record" << std::endl;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<model::Album, int> AlbumRepository::parseRecordWithSongCount(MYSQL_STMT *stmt)
|
std::pair<model::Album, int> AlbumRepository::parseRecordWithSongCount(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
@@ -337,54 +296,20 @@ std::pair<model::Album, int> AlbumRepository::parseRecordWithSongCount(MYSQL_STM
|
|||||||
auto rowCount = mysql_stmt_num_rows(stmt);
|
auto rowCount = mysql_stmt_num_rows(stmt);
|
||||||
|
|
||||||
model::Album album;
|
model::Album album;
|
||||||
|
auto metaBuff = metadataBuffer();
|
||||||
int songCount = 0;
|
int songCount = 0;
|
||||||
|
auto val = valueBindWithSongCount(album, metaBuff, songCount);
|
||||||
|
|
||||||
if (rowCount == 0) {
|
if (rowCount == 0) {
|
||||||
std::cout << "no results" << std::endl;
|
std::cout << "no results" << std::endl;
|
||||||
return std::make_pair(album, songCount);
|
return std::make_pair(album, songCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mysql_stmt_field_count(stmt) == 0) {
|
auto status = mysql_stmt_bind_result(stmt, val.get());
|
||||||
std::cout << "field count is 0, must be an incorrect query" << std::endl;
|
|
||||||
return std::make_pair(model::Album(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto res = mysql_stmt_result_metadata(stmt);
|
|
||||||
constexpr auto valAmt = 4;
|
|
||||||
constexpr auto strLen = 1024;
|
|
||||||
unsigned long len[valAmt];
|
|
||||||
my_bool nullRes[valAmt];
|
|
||||||
|
|
||||||
MYSQL_BIND val[valAmt];
|
|
||||||
std::memset(val, 0, sizeof(val));
|
|
||||||
|
|
||||||
char title[strLen];
|
|
||||||
|
|
||||||
val[0].buffer_type = MYSQL_TYPE_LONG;
|
|
||||||
val[0].buffer = (char*)&album.id;
|
|
||||||
val[0].length = &len[0];
|
|
||||||
val[0].is_null = &nullRes[0];
|
|
||||||
|
|
||||||
val[1].buffer_type = MYSQL_TYPE_STRING;
|
|
||||||
val[1].buffer = (char*)title;
|
|
||||||
val[1].buffer_length = strLen;
|
|
||||||
val[1].length = &len[1];
|
|
||||||
val[1].is_null = &nullRes[1];
|
|
||||||
|
|
||||||
val[2].buffer_type = MYSQL_TYPE_LONG;
|
|
||||||
val[2].buffer = (char*)&album.year;
|
|
||||||
val[2].length = &len[2];
|
|
||||||
val[2].is_null = &nullRes[2];
|
|
||||||
|
|
||||||
val[3].buffer_type = MYSQL_TYPE_LONG;
|
|
||||||
val[3].buffer = (char*)&songCount;
|
|
||||||
val[3].length = &len[3];
|
|
||||||
val[3].is_null = &nullRes[3];
|
|
||||||
|
|
||||||
auto status = mysql_stmt_bind_result(stmt, val);
|
|
||||||
status = mysql_stmt_fetch(stmt);
|
status = mysql_stmt_fetch(stmt);
|
||||||
|
|
||||||
album.title = std::move(title);
|
album.title = std::get<0>(metaBuff);
|
||||||
|
album.artist = std::get<1>(metaBuff);
|
||||||
|
|
||||||
std::cout << "done parsing album record with song count" << std::endl;
|
std::cout << "done parsing album record with song count" << std::endl;
|
||||||
|
|
||||||
@@ -393,6 +318,69 @@ std::pair<model::Album, int> AlbumRepository::parseRecordWithSongCount(MYSQL_STM
|
|||||||
return albWSC;
|
return albWSC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<MYSQL_BIND> AlbumRepository::valueBind(model::Album& album,
|
||||||
|
std::tuple<char*, char*>& metadata)
|
||||||
|
{
|
||||||
|
constexpr auto wordLen = 1024;
|
||||||
|
constexpr auto valueCount = 4;
|
||||||
|
std::shared_ptr<MYSQL_BIND> values((MYSQL_BIND*) std::calloc(valueCount, sizeof(MYSQL_BIND)));
|
||||||
|
|
||||||
|
values.get()[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
values.get()[0].buffer = (char*)&album.id;
|
||||||
|
|
||||||
|
values.get()[1].buffer_type = MYSQL_TYPE_STRING;
|
||||||
|
values.get()[1].buffer = (char*)std::get<0>(metadata);
|
||||||
|
values.get()[1].buffer_length = wordLen;
|
||||||
|
|
||||||
|
values.get()[2].buffer_type = MYSQL_TYPE_STRING;
|
||||||
|
values.get()[2].buffer = (char*)std::get<1>(metadata);
|
||||||
|
values.get()[2].buffer_length = wordLen;
|
||||||
|
|
||||||
|
values.get()[3].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
values.get()[3].buffer = (char*)&album.year;
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MYSQL_BIND> AlbumRepository::valueBindWithSongCount(model::Album& album,
|
||||||
|
std::tuple<char*, char*>& metadata, int& songCount)
|
||||||
|
{
|
||||||
|
constexpr auto wordLen = 1024;
|
||||||
|
constexpr auto valueCount = 5;
|
||||||
|
std::shared_ptr<MYSQL_BIND> values((MYSQL_BIND*) std::calloc(valueCount, sizeof(MYSQL_BIND)));
|
||||||
|
|
||||||
|
values.get()[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
values.get()[0].buffer = (char*)&album.id;
|
||||||
|
|
||||||
|
values.get()[1].buffer_type = MYSQL_TYPE_STRING;
|
||||||
|
values.get()[1].buffer = (char*)std::get<0>(metadata);
|
||||||
|
values.get()[1].buffer_length = wordLen;
|
||||||
|
|
||||||
|
values.get()[2].buffer_type = MYSQL_TYPE_STRING;
|
||||||
|
values.get()[2].buffer = (char*)std::get<1>(metadata);
|
||||||
|
values.get()[2].buffer_length = wordLen;
|
||||||
|
|
||||||
|
values.get()[3].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
values.get()[3].buffer = (char*)&album.year;
|
||||||
|
|
||||||
|
values.get()[4].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
values.get()[4].buffer = (char*)&songCount;
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::tuple<char*, char*> AlbumRepository::metadataBuffer()
|
||||||
|
{
|
||||||
|
constexpr auto wordLen = 1024;
|
||||||
|
char title[wordLen];
|
||||||
|
char artist[wordLen];
|
||||||
|
|
||||||
|
return std::make_tuple(title, artist);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
model::Album AlbumRepository::parseRecord(MYSQL_STMT *stmt)
|
model::Album AlbumRepository::parseRecord(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
std::cout << "parsing album record" << std::endl;
|
std::cout << "parsing album record" << std::endl;
|
||||||
@@ -400,49 +388,13 @@ model::Album AlbumRepository::parseRecord(MYSQL_STMT *stmt)
|
|||||||
auto rows = mysql_stmt_num_rows(stmt);
|
auto rows = mysql_stmt_num_rows(stmt);
|
||||||
|
|
||||||
model::Album album;
|
model::Album album;
|
||||||
auto status = 0;
|
auto metaBuff = metadataBuffer();
|
||||||
auto time = 0;
|
auto bindedValues = valueBind(album, metaBuff);
|
||||||
auto valAmt = 3;
|
auto status = mysql_stmt_bind_result(stmt, bindedValues.get());
|
||||||
unsigned long len[valAmt];
|
status = mysql_stmt_fetch(stmt);
|
||||||
my_bool nullRes[valAmt];
|
|
||||||
|
|
||||||
while (status == 0) {
|
album.title = std::get<0>(metaBuff);
|
||||||
if (mysql_stmt_field_count(stmt) > 0) {
|
album.artist = std::get<1>(metaBuff);
|
||||||
auto res = mysql_stmt_result_metadata(stmt);
|
|
||||||
auto fields = mysql_fetch_fields(res);
|
|
||||||
auto strLen = 1024;
|
|
||||||
|
|
||||||
MYSQL_BIND val[valAmt];
|
|
||||||
memset(val, 0, sizeof(val));
|
|
||||||
|
|
||||||
char title[strLen];
|
|
||||||
|
|
||||||
val[0].buffer_type = MYSQL_TYPE_LONG;
|
|
||||||
val[0].buffer = (char*)&album.id;
|
|
||||||
val[0].length = &len[0];
|
|
||||||
val[0].is_null = &nullRes[0];
|
|
||||||
|
|
||||||
val[1].buffer_type = MYSQL_TYPE_STRING;
|
|
||||||
val[1].buffer = (char*)title;
|
|
||||||
val[1].buffer_length = strLen;
|
|
||||||
val[1].length = &len[1];
|
|
||||||
val[1].is_null = &nullRes[1];
|
|
||||||
|
|
||||||
val[2].buffer_type = MYSQL_TYPE_LONG;
|
|
||||||
val[2].buffer = (char*)&album.year;
|
|
||||||
val[2].length = &len[2];
|
|
||||||
val[2].is_null = &nullRes[2];
|
|
||||||
|
|
||||||
status = mysql_stmt_bind_result(stmt, val);
|
|
||||||
mysql_stmt_store_result(stmt);
|
|
||||||
|
|
||||||
status = mysql_stmt_fetch(stmt);
|
|
||||||
|
|
||||||
album.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = mysql_stmt_next_result(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "done parsing album record" << std::endl;
|
std::cout << "done parsing album record" << std::endl;
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,6 @@
|
|||||||
|
|
||||||
namespace database {
|
namespace database {
|
||||||
|
|
||||||
SongRepository::SongRepository(const std::string& path) : BaseRepository(path)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
SongRepository::SongRepository(const model::BinaryPath& bConf) : BaseRepository(bConf)
|
SongRepository::SongRepository(const model::BinaryPath& bConf) : BaseRepository(bConf)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -20,7 +17,10 @@ std::vector<model::Song> SongRepository::retrieveRecords()
|
|||||||
{
|
{
|
||||||
auto conn = setupMysqlConnection();
|
auto conn = setupMysqlConnection();
|
||||||
auto stmt = mysql_stmt_init(conn);
|
auto stmt = mysql_stmt_init(conn);
|
||||||
const std::string query = "SELECT * FROM Song";
|
std::stringstream qry;
|
||||||
|
qry << "SELECT sng.*, alb.Artist AS AlbumArtist FROM Song sng ";
|
||||||
|
qry << "LEFT JOIN Album alb ON sng.AlbumId=alb.AlbumId";
|
||||||
|
const auto query = qry.str();
|
||||||
|
|
||||||
::mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
::mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
||||||
::mysql_stmt_execute(stmt);
|
::mysql_stmt_execute(stmt);
|
||||||
@@ -52,7 +52,8 @@ model::Song SongRepository::retrieveRecord(model::Song& song, type::SongFilter f
|
|||||||
MYSQL_BIND params[valueFilterCount];
|
MYSQL_BIND params[valueFilterCount];
|
||||||
memset(params, 0, sizeof(params));
|
memset(params, 0, sizeof(params));
|
||||||
|
|
||||||
qry << "SELECT * FROM Song WHERE ";
|
qry << "SELECT sng.*, alb.Artist AS AlbumArtist FROM Song sng ";
|
||||||
|
qry << "LEFT JOIN Album alb ON sng.AlbumId=alb.AlbumId WHERE ";
|
||||||
|
|
||||||
auto titleLength = song.title.size();
|
auto titleLength = song.title.size();
|
||||||
auto artistLength = song.artist.size();
|
auto artistLength = song.artist.size();
|
||||||
@@ -92,7 +93,7 @@ model::Song SongRepository::retrieveRecord(model::Song& song, type::SongFilter f
|
|||||||
|
|
||||||
qry << " LIMIT 1";
|
qry << " LIMIT 1";
|
||||||
|
|
||||||
const std::string query = qry.str();
|
const auto query = qry.str();
|
||||||
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
||||||
status = mysql_stmt_bind_param(stmt, params);
|
status = mysql_stmt_bind_param(stmt, params);
|
||||||
status = mysql_stmt_execute(stmt);
|
status = mysql_stmt_execute(stmt);
|
||||||
@@ -393,10 +394,10 @@ void SongRepository::updateRecord(const model::Song& song)
|
|||||||
|
|
||||||
|
|
||||||
std::shared_ptr<MYSQL_BIND> SongRepository::valueBind(model::Song& song,
|
std::shared_ptr<MYSQL_BIND> SongRepository::valueBind(model::Song& song,
|
||||||
std::tuple<char*, char*, char*, char*, char*>& metadata)
|
std::tuple<char*, char*, char*, char*, char*, char*>& metadata)
|
||||||
{
|
{
|
||||||
constexpr auto strLen = 1024;
|
constexpr auto strLen = 1024;
|
||||||
constexpr auto valueCount = 15;
|
constexpr auto valueCount = 16;
|
||||||
std::shared_ptr<MYSQL_BIND> values((MYSQL_BIND*) std::calloc(valueCount, sizeof(MYSQL_BIND)));
|
std::shared_ptr<MYSQL_BIND> values((MYSQL_BIND*) std::calloc(valueCount, sizeof(MYSQL_BIND)));
|
||||||
unsigned long len[valueCount];
|
unsigned long len[valueCount];
|
||||||
my_bool nullRes[valueCount];
|
my_bool nullRes[valueCount];
|
||||||
@@ -452,11 +453,15 @@ std::shared_ptr<MYSQL_BIND> SongRepository::valueBind(model::Song& song,
|
|||||||
values.get()[14].buffer_type = MYSQL_TYPE_LONG;
|
values.get()[14].buffer_type = MYSQL_TYPE_LONG;
|
||||||
values.get()[14].buffer = (char*)&song.yearId;
|
values.get()[14].buffer = (char*)&song.yearId;
|
||||||
|
|
||||||
|
values.get()[15].buffer_type = MYSQL_TYPE_STRING;
|
||||||
|
values.get()[15].buffer = (char*)std::get<5>(metadata);
|
||||||
|
values.get()[15].buffer_length = strLen;
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::tuple<char*, char*, char*, char*, char*> SongRepository::metadataBuffer()
|
std::tuple<char*, char*, char*, char*, char*, char*> SongRepository::metadataBuffer()
|
||||||
{
|
{
|
||||||
constexpr auto length = 1024;
|
constexpr auto length = 1024;
|
||||||
char title[length];
|
char title[length];
|
||||||
@@ -464,8 +469,9 @@ std::tuple<char*, char*, char*, char*, char*> SongRepository::metadataBuffer()
|
|||||||
char album[length];
|
char album[length];
|
||||||
char genre[length];
|
char genre[length];
|
||||||
char path[length];
|
char path[length];
|
||||||
|
char albumArtist[length];
|
||||||
|
|
||||||
return std::make_tuple(title, artist, album, genre, path);
|
return std::make_tuple(title, artist, album, genre, path, albumArtist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -501,6 +507,7 @@ std::vector<model::Song> SongRepository::parseRecords(MYSQL_STMT *stmt)
|
|||||||
song.album = std::get<2>(metaBuff);
|
song.album = std::get<2>(metaBuff);
|
||||||
song.genre = std::get<3>(metaBuff);
|
song.genre = std::get<3>(metaBuff);
|
||||||
song.songPath = std::get<4>(metaBuff);
|
song.songPath = std::get<4>(metaBuff);
|
||||||
|
song.albumArtist = std::get<5>(metaBuff);
|
||||||
|
|
||||||
songs.push_back(song);
|
songs.push_back(song);
|
||||||
}
|
}
|
||||||
@@ -526,6 +533,7 @@ model::Song SongRepository::parseRecord(MYSQL_STMT *stmt)
|
|||||||
song.album = std::get<2>(metaBuff);
|
song.album = std::get<2>(metaBuff);
|
||||||
song.genre = std::get<3>(metaBuff);
|
song.genre = std::get<3>(metaBuff);
|
||||||
song.songPath = std::get<4>(metaBuff);
|
song.songPath = std::get<4>(metaBuff);
|
||||||
|
song.albumArtist = std::get<5>(metaBuff);
|
||||||
|
|
||||||
std::cout << "done parsing record" << std::endl;
|
std::cout << "done parsing record" << std::endl;
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,24 @@ namespace dto { namespace conversion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dto::AlbumDto::ObjectWrapper DtoConversions::toAlbumDto(const model::Album& album) {
|
||||||
|
auto result = dto::AlbumDto::createShared();
|
||||||
|
result->id = (album.id != 0) ? album.id : 0;
|
||||||
|
result->title = (!album.title.empty()) ? album.title.c_str() : "";
|
||||||
|
result->artist = (!album.artist.empty()) ? album.artist.c_str() : "";
|
||||||
|
result->year = (album.year != 0) ? album.year : 0;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
dto::SongDto::ObjectWrapper DtoConversions::toSongDto(const model::Song& song) {
|
dto::SongDto::ObjectWrapper DtoConversions::toSongDto(const model::Song& song) {
|
||||||
auto result = dto::SongDto::createShared();
|
auto result = dto::SongDto::createShared();
|
||||||
result->id = (song.id != 0) ? song.id : 0;
|
result->id = (song.id != 0) ? song.id : 0;
|
||||||
result->title = (!song.title.empty()) ? song.title.c_str() : "";
|
result->title = (!song.title.empty()) ? song.title.c_str() : "";
|
||||||
result->album = (!song.album.empty()) ? song.album.c_str() : "";
|
result->album = (!song.album.empty()) ? song.album.c_str() : "";
|
||||||
result->artist = (!song.artist.empty()) ? song.artist.c_str() : "";
|
result->artist = (!song.artist.empty()) ? song.artist.c_str() : "";
|
||||||
|
result->album_artist = (!song.albumArtist.empty()) ? song.albumArtist.c_str() : "";
|
||||||
result->genre = (!song.genre.empty()) ? song.genre.c_str() : "";
|
result->genre = (!song.genre.empty()) ? song.genre.c_str() : "";
|
||||||
result->duration = (song.duration != 0) ? song.duration : 0;
|
result->duration = (song.duration != 0) ? song.duration : 0;
|
||||||
result->year = (song.year != 0) ? song.year : 0;
|
result->year = (song.year != 0) ? song.year : 0;
|
||||||
@@ -47,6 +59,8 @@ namespace dto { namespace conversion {
|
|||||||
song.title = (songDto->title == nullptr) ? "" : songDto->title->c_str();
|
song.title = (songDto->title == nullptr) ? "" : songDto->title->c_str();
|
||||||
song.album = (songDto->album == nullptr) ? "" : songDto->album->c_str();
|
song.album = (songDto->album == nullptr) ? "" : songDto->album->c_str();
|
||||||
song.artist = (songDto->artist == nullptr) ? "" : songDto->artist->c_str();
|
song.artist = (songDto->artist == nullptr) ? "" : songDto->artist->c_str();
|
||||||
|
song.albumArtist = (songDto->album_artist == nullptr) ?
|
||||||
|
"" : songDto->album_artist->c_str();
|
||||||
song.genre = (songDto->genre == nullptr) ? "" : songDto->genre->c_str();
|
song.genre = (songDto->genre == nullptr) ? "" : songDto->genre->c_str();
|
||||||
song.year = (songDto->year.getPtr() == nullptr) ? 0 : songDto->year->getValue();
|
song.year = (songDto->year.getPtr() == nullptr) ? 0 : songDto->year->getValue();
|
||||||
song.track = (songDto->track.getPtr() == nullptr) ? 0 : songDto->track->getValue();
|
song.track = (songDto->track.getPtr() == nullptr) ? 0 : songDto->track->getValue();
|
||||||
|
|||||||
@@ -20,11 +20,10 @@ model::Album AlbumManager::retrieveAlbum(model::Album& album)
|
|||||||
|
|
||||||
model::Album AlbumManager::saveAlbum(const model::Song& song)
|
model::Album AlbumManager::saveAlbum(const model::Song& song)
|
||||||
{
|
{
|
||||||
model::Album album;
|
model::Album album(song);
|
||||||
album.title = song.album;
|
|
||||||
album.year = song.year;
|
|
||||||
|
|
||||||
database::AlbumRepository albRepo(m_bConf);
|
database::AlbumRepository albRepo(m_bConf);
|
||||||
|
// TODO: check for existence with the title and the artist
|
||||||
if (!albRepo.doesAlbumExists(album, type::AlbumFilter::title)) {
|
if (!albRepo.doesAlbumExists(album, type::AlbumFilter::title)) {
|
||||||
albRepo.saveAlbum(album);
|
albRepo.saveAlbum(album);
|
||||||
} else {
|
} else {
|
||||||
@@ -55,9 +54,7 @@ void AlbumManager::deleteAlbum(const model::Song& song)
|
|||||||
void AlbumManager::updateAlbum(model::Song& updatedSong,
|
void AlbumManager::updateAlbum(model::Song& updatedSong,
|
||||||
const model::Song& currSong)
|
const model::Song& currSong)
|
||||||
{
|
{
|
||||||
model::Album album;
|
model::Album album(updatedSong);
|
||||||
album.title = updatedSong.album;
|
|
||||||
album.year = updatedSong.year;
|
|
||||||
|
|
||||||
database::AlbumRepository albRepo(m_bConf);
|
database::AlbumRepository albRepo(m_bConf);
|
||||||
if (!albRepo.doesAlbumExists(album, type::AlbumFilter::title)) {
|
if (!albRepo.doesAlbumExists(album, type::AlbumFilter::title)) {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ std::string DirectoryManager::createDirectoryProcess(const model::Song& song,
|
|||||||
fs::create_directory(currPath);
|
fs::create_directory(currPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto artPath = fs::path(currPath.string() + song.artist);
|
auto artPath = fs::path(currPath.string() + song.albumArtist);
|
||||||
if (fs::exists(artPath)) {
|
if (fs::exists(artPath)) {
|
||||||
std::cout << "artist path exists" << std::endl;
|
std::cout << "artist path exists" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
@@ -143,7 +143,7 @@ nlohmann::json DirectoryManager::pathConfigContent(const model::BinaryPath& bCon
|
|||||||
void DirectoryManager::deleteDirectories(model::Song song, const std::string& rootPath)
|
void DirectoryManager::deleteDirectories(model::Song song, const std::string& rootPath)
|
||||||
{
|
{
|
||||||
std::cout << "checking for empty directories to delete" << std::endl;
|
std::cout << "checking for empty directories to delete" << std::endl;
|
||||||
const std::string art(rootPath + std::string("/") + song.artist);
|
const std::string art(rootPath + std::string("/") + song.albumArtist);
|
||||||
const std::string alb(art + "/" + song.album);
|
const std::string alb(art + "/" + song.album);
|
||||||
|
|
||||||
auto albPath = fs::path(alb);
|
auto albPath = fs::path(alb);
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ void SongManager::saveSong(model::Song& song)
|
|||||||
saveSongTemp(song);
|
saveSongTemp(song);
|
||||||
utility::MetadataRetriever meta;
|
utility::MetadataRetriever meta;
|
||||||
auto data = std::move(song.data);
|
auto data = std::move(song.data);
|
||||||
song = meta.retrieveMetadata(song.songPath);
|
song = meta.retrieveMetadata(song);
|
||||||
song.data = std::move(data);
|
song.data = std::move(data);
|
||||||
|
|
||||||
saveMisc(song);
|
saveMisc(song);
|
||||||
@@ -146,6 +146,7 @@ void SongManager::printSong(const model::Song& song)
|
|||||||
std::cout << "\nsong" << std::endl;
|
std::cout << "\nsong" << std::endl;
|
||||||
std::cout << "title: " << song.title << std::endl;
|
std::cout << "title: " << song.title << std::endl;
|
||||||
std::cout << "artist: " << song.artist << std::endl;
|
std::cout << "artist: " << song.artist << std::endl;
|
||||||
|
std::cout << "album artist: " << song.albumArtist << std::endl;
|
||||||
std::cout << "album: " << song.album << std::endl;
|
std::cout << "album: " << song.album << std::endl;
|
||||||
std::cout << "genre: " << song.genre << std::endl;
|
std::cout << "genre: " << song.genre << std::endl;
|
||||||
std::cout << "duration: " << song.duration << std::endl;
|
std::cout << "duration: " << song.duration << std::endl;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <attachedpictureframe.h>
|
#include <attachedpictureframe.h>
|
||||||
|
#include <textidentificationframe.h>
|
||||||
#include <fileref.h>
|
#include <fileref.h>
|
||||||
#include <mpegfile.h>
|
#include <mpegfile.h>
|
||||||
#include <tag.h>
|
#include <tag.h>
|
||||||
@@ -18,31 +19,43 @@
|
|||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
namespace utility {
|
namespace utility {
|
||||||
model::Song MetadataRetriever::retrieveMetadata(std::string& songPath)
|
model::Song MetadataRetriever::retrieveMetadata(model::Song& song)
|
||||||
{
|
{
|
||||||
TagLib::FileRef file(songPath.c_str());
|
TagLib::MPEG::File sameFile(song.songPath.c_str());
|
||||||
model::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.track = file.tag()->track();
|
|
||||||
song.duration = file.audioProperties()->lengthInSeconds();
|
|
||||||
song.songPath = songPath;
|
|
||||||
|
|
||||||
// TODO: Move over to this eventually since at the moment
|
|
||||||
// I am only targetting mp3 files
|
|
||||||
// Used to retrieve disc
|
|
||||||
TagLib::MPEG::File sameFile(songPath.c_str());
|
|
||||||
auto tag = sameFile.ID3v2Tag();
|
auto tag = sameFile.ID3v2Tag();
|
||||||
|
song.title = tag->title().toCString();
|
||||||
|
song.artist = tag->artist().toCString();
|
||||||
|
song.album = tag->album().toCString();
|
||||||
|
song.genre = tag->genre().toCString();
|
||||||
|
song.year = tag->year();
|
||||||
|
song.track = tag->track();
|
||||||
|
song.duration = sameFile.audioProperties()->lengthInSeconds();
|
||||||
|
|
||||||
auto frame = tag->frameList("TPOS");
|
constexpr auto id3DiscName = "TPOS";
|
||||||
if (frame.isEmpty()) {
|
constexpr auto id3AlbumArtistName = "TPE2";
|
||||||
song.disc = 1;
|
|
||||||
// TODO: set default disc to 1 if none found
|
auto discFrame = tag->frameList(id3DiscName);
|
||||||
|
auto albumArtistFrame = tag->frameList(id3AlbumArtistName);
|
||||||
|
if (discFrame.isEmpty()) {
|
||||||
|
constexpr auto discDefaultVal = "1";
|
||||||
|
TagLib::ID3v2::TextIdentificationFrame *emptyFrame =
|
||||||
|
new TagLib::ID3v2::TextIdentificationFrame(id3DiscName);
|
||||||
|
tag->addFrame(emptyFrame);
|
||||||
|
emptyFrame->setText(discDefaultVal);
|
||||||
|
song.disc = std::atoi(discDefaultVal);
|
||||||
|
sameFile.save();
|
||||||
} else {
|
} else {
|
||||||
song.disc = std::stoi(frame.front()->toString().toCString());
|
song.disc = std::stoi(discFrame.front()->toString().toCString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (albumArtistFrame.isEmpty()) {
|
||||||
|
TagLib::ID3v2::TextIdentificationFrame *emptyFrame =
|
||||||
|
new TagLib::ID3v2::TextIdentificationFrame(id3DiscName);
|
||||||
|
tag->addFrame(emptyFrame);
|
||||||
|
emptyFrame->setText(song.artist.c_str());
|
||||||
|
sameFile.save();
|
||||||
|
} else {
|
||||||
|
song.albumArtist = albumArtistFrame.front()->toString().toCString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -155,7 +168,8 @@ bool MetadataRetriever::songContainsCoverArt(const model::Song& song)
|
|||||||
void MetadataRetriever::updateMetadata(model::Song& sngUpdated, const model::Song& sngOld)
|
void MetadataRetriever::updateMetadata(model::Song& sngUpdated, const model::Song& sngOld)
|
||||||
{
|
{
|
||||||
std::cout<<"updating metadata"<<std::endl;
|
std::cout<<"updating metadata"<<std::endl;
|
||||||
TagLib::FileRef file(sngOld.songPath.c_str());
|
TagLib::MPEG::File file(sngOld.songPath.c_str());
|
||||||
|
auto tag = file.ID3v2Tag();
|
||||||
|
|
||||||
if (sngUpdated.title.size() > 0) {
|
if (sngUpdated.title.size() > 0) {
|
||||||
file.tag()->setTitle(sngUpdated.title);
|
file.tag()->setTitle(sngUpdated.title);
|
||||||
@@ -163,6 +177,20 @@ void MetadataRetriever::updateMetadata(model::Song& sngUpdated, const model::Son
|
|||||||
if (sngUpdated.artist.size() > 0) {
|
if (sngUpdated.artist.size() > 0) {
|
||||||
file.tag()->setArtist(sngUpdated.artist);
|
file.tag()->setArtist(sngUpdated.artist);
|
||||||
}
|
}
|
||||||
|
if (sngUpdated.albumArtist.size() > 0) {
|
||||||
|
constexpr auto frameId = "TPE2";
|
||||||
|
auto albumArtistFrame = tag->frameList(frameId);
|
||||||
|
if (albumArtistFrame.isEmpty()) {
|
||||||
|
TagLib::ID3v2::TextIdentificationFrame *frame =
|
||||||
|
new TagLib::ID3v2::TextIdentificationFrame(frameId);
|
||||||
|
frame->setText(sngUpdated.albumArtist.c_str());
|
||||||
|
tag->addFrame(frame);
|
||||||
|
} else {
|
||||||
|
albumArtistFrame.front()->setText(sngUpdated.albumArtist.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
file.save();
|
||||||
|
}
|
||||||
if (sngUpdated.album.size() > 0) {
|
if (sngUpdated.album.size() > 0) {
|
||||||
file.tag()->setAlbum(sngUpdated.album);
|
file.tag()->setAlbum(sngUpdated.album);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user