Compare commits

...

5 Commits

Author SHA1 Message Date
DWW
262f8b5d71 Added saving release date 2022-08-25 16:40:20 +03:00
DWW
4f844868cd Added invokation constexpr for id3edit 2022-08-25 15:24:07 +03:00
DWW
82cc90c713 Added release prefix as a subfolder. Added release suffix to folder name. 2022-08-08 17:23:03 +03:00
DWW
588925cee8 Added array example. Implemented main. 2022-08-08 17:03:00 +03:00
DWW
74598813de Added image resizing via imagemagick 2022-07-20 18:10:16 +03:00
4 changed files with 356 additions and 38 deletions

16
README
View File

@ -26,14 +26,16 @@ metaflac
--preserve-modtime --preserve-modtime
--no-utf8-convert --no-utf8-convert
// First Step - Remove // First Step - Remove Tags
--remove --block-type=PICTURE
--remove-tag=TITLE --remove-tag=TITLE
--remove-tag=ARTIST --remove-tag=ARTIST
--remove-tag=ALBUM --remove-tag=ALBUM
--remove-tag=TRACKNUMBER --remove-tag=TRACKNUMBER
// Second Step - Add // Second Step - Remove Pictures
--remove --block-type=PICTURE
// Third Step - Add
--import-picture-from=3|image/jpeg|||"/path/to/cover" --import-picture-from=3|image/jpeg|||"/path/to/cover"
"--set-tag=TITLE=..." "--set-tag=TITLE=..."
"--set-tag=ARTIST=..." "--set-tag=ARTIST=..."
@ -42,3 +44,11 @@ metaflac
--dont-use-padding --dont-use-padding
file.flac file.flac
--- imagemagick ---
https://imagemagick.org/script/download.php
For Image Resizing
magick
Cover
-resize 750x750
Cover_small.jpg

2
TODO
View File

@ -1,2 +0,0 @@
Add Cover Resize via lib or command ???
Implement main

10
example_download2.json Normal file
View File

@ -0,0 +1,10 @@
{
"comment": "This file will attempt to download MCS1091, MCS1195, MCS1425, MCS1426",
"releases":
[
"MCS1091",
"MCS1195",
"MCS1425",
"MCS1426"
]
}

366
main.cpp
View File

@ -26,6 +26,8 @@ constexpr bool IS_FLAC = false;
constexpr bool IS_JPG = true; constexpr bool IS_JPG = true;
constexpr bool IS_PNG = false; constexpr bool IS_PNG = false;
constexpr uint32_t COVER_SIZE = 750; constexpr uint32_t COVER_SIZE = 750;
constexpr const char ID3EDIT_INVOKE[] = "id3edit";
constexpr const char MAGICK_INVOKE[] = "magick";
#ifdef _WIN32 #ifdef _WIN32
constexpr const char FOLDER_DELIM = '\\'; constexpr const char FOLDER_DELIM = '\\';
@ -63,7 +65,7 @@ void usage(const string& name)
cout << " -1 <catalog release id>" << endl; cout << " -1 <catalog release id>" << endl;
cout << " Single release" << endl; cout << " Single release" << endl;
cout << " -j <json file>" << endl; cout << " -j <json file>" << endl;
cout << " JSON file denoting release range" << endl; cout << " JSON file denoting release range or releases array" << endl;
cout << " path - root path to download to" << endl; cout << " path - root path to download to" << endl;
cout << " Default: ." << endl; cout << " Default: ." << endl;
} }
@ -170,15 +172,16 @@ pair<string, string> get_artist_title(const json& obj)
pair<string, string> artist_feat; pair<string, string> artist_feat;
string str; string str;
string feat; string feat;
string version;
bool contains; bool contains;
int pos; int pos;
artist_feat = get_artist_feat(obj["Release"]["ArtistsTitle"]); artist_feat = get_artist_feat(obj["ArtistsTitle"]);
result.first = artist_feat.first; result.first = artist_feat.first;
contains = false; contains = false;
str = obj["Release"]["Title"]; str = obj["Title"];
if (!artist_feat.second.empty()) if (!artist_feat.second.empty())
{ {
str += " ("; str += " (";
@ -187,19 +190,12 @@ pair<string, string> get_artist_title(const json& obj)
contains = true; contains = true;
} }
if (!(obj["Release"]["Version"].empty())) // Empty does not work on json string
version = obj["Version"];
if (!version.empty())
{ {
if (contains) str += contains ? " [" : " (";
{ str += version;
str += " [";
}
else
{
str += " (";
}
str += obj["Release"]["Version"];
str += contains ? ']' : ')'; str += contains ? ']' : ')';
} }
@ -305,14 +301,18 @@ string num_to_str(int num, int precision)
return result; return result;
} }
string get_release_dir_name(const string& main_path, int release_num, string get_release_dir_name(const string& main_path, const string& release_prefix,
const string& artist, const string& title, int precision) int release_num, const string& release_suffix, const string& artist,
const string& title, int precision)
{ {
string path; string path;
path = main_path; path = main_path;
path += FOLDER_DELIM; path += FOLDER_DELIM;
path += release_prefix;
path += FOLDER_DELIM;
path += num_to_str(release_num, precision); path += num_to_str(release_num, precision);
path += release_suffix;
path += " - "; path += " - ";
if ((artist != "Monstercat") && (artist != "Various Artists")) if ((artist != "Monstercat") && (artist != "Various Artists"))
@ -349,13 +349,20 @@ string get_track_filename(int track_num, const string& artist,
return filename; return filename;
} }
bool should_resize_JPG(ifstream& file) bool should_resize_JPG(const string& path)
{ {
// Do a resize by default // Do a resize by default
bool result = true; bool result = true;
ifstream file;
string filename;
int marker = 0; int marker = 0;
int symbol; int symbol;
filename = path;
filename += FOLDER_DELIM;
filename += "Cover";
file.open(filename);
// Check Header 1 // Check Header 1
symbol = file.get(); symbol = file.get();
if (symbol != 0xFF) if (symbol != 0xFF)
@ -476,17 +483,21 @@ bool should_resize_JPG(ifstream& file)
} }
} }
bool should_resize_PNG(ifstream& file) bool should_resize_PNG(const string& path)
{ {
ifstream file;
string filename;
uint8_t buf[4]; uint8_t buf[4];
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
filename = path;
filename += FOLDER_DELIM;
filename += "Cover";
file.open(filename);
// Seek // Seek
file.read(reinterpret_cast<char*>(&buf), 4); file.seekg(16);
file.read(reinterpret_cast<char*>(&buf), 4);
file.read(reinterpret_cast<char*>(&buf), 4);
file.read(reinterpret_cast<char*>(&buf), 4);
// Read width // Read width
width = 0; width = 0;
@ -506,6 +517,8 @@ bool should_resize_PNG(ifstream& file)
height += buf[i]; height += buf[i];
} }
file.close();
if ((width > COVER_SIZE) || (height > COVER_SIZE)) if ((width > COVER_SIZE) || (height > COVER_SIZE))
{ {
return true; return true;
@ -543,6 +556,45 @@ bool get_cover_type(const string& path)
throw invalid_argument(filename); throw invalid_argument(filename);
} }
bool resize_cover(const string& path, bool is_jpg)
{
string cmd;
bool should_resize;
// Should we actually resize
if (is_jpg == IS_JPG)
{
should_resize = should_resize_JPG(path);
}
else
{
should_resize = should_resize_PNG(path);
}
cmd = MAGICK_INVOKE;
cmd += " \"";
cmd += path;
cmd += FOLDER_DELIM;
cmd += "Cover";
cmd += "\" ";
if (should_resize)
{
cmd += "-resize ";
cmd += to_string(COVER_SIZE);
cmd += "x";
cmd += to_string(COVER_SIZE);
cmd += " ";
}
cmd += "\"";
cmd += path;
cmd += FOLDER_DELIM;
cmd += "Cover_small.jpg\"";
return system_command(cmd);
}
bool rename_cover(const string& path, bool is_jpg) bool rename_cover(const string& path, bool is_jpg)
{ {
string filename; string filename;
@ -578,7 +630,8 @@ bool tag_MP3(const string& path, const string& filename, bool is_single_dir,
{ {
string cmd; string cmd;
cmd = "id3edit --set-name \""; cmd = ID3EDIT_INVOKE;
cmd += " --set-name \"";
cmd += title; cmd += title;
cmd += "\" --set-album \""; cmd += "\" --set-album \"";
cmd += album; cmd += album;
@ -610,9 +663,8 @@ bool tag_FLAC(const string& path, const string& filename, bool is_single_dir,
string cmd; string cmd;
bool ok; bool ok;
// First command - remove metadata // First command - remove tags
cmd = "metaflac --preserve-modtime --no-utf8-convert "; cmd = "metaflac --preserve-modtime --no-utf8-convert ";
cmd += "--remove --block-type=PICTURE ";
cmd += "--remove-tag=TITLE "; cmd += "--remove-tag=TITLE ";
cmd += "--remove-tag=ARTIST "; cmd += "--remove-tag=ARTIST ";
cmd += "--remove-tag=ALBUM "; cmd += "--remove-tag=ALBUM ";
@ -633,7 +685,26 @@ bool tag_FLAC(const string& path, const string& filename, bool is_single_dir,
return false; return false;
} }
// Second command - set metadata // Second command - remove pictures
cmd = "metaflac --preserve-modtime --no-utf8-convert ";
cmd += "--remove --block-type=PICTURE \"";
cmd += path;
cmd += FOLDER_DELIM;
if (!is_single_dir)
{
cmd += "FLAC";
cmd += FOLDER_DELIM;
}
cmd += filename;
cmd += ".flac\"";
ok = system_command(cmd);
if (!ok)
{
return false;
}
// Third command - set metadata
cmd = "metaflac --preserve-modtime --no-utf8-convert --dont-use-padding "; cmd = "metaflac --preserve-modtime --no-utf8-convert --dont-use-padding ";
cmd += "\"--import-picture-from=3|image/jpeg|||"; cmd += "\"--import-picture-from=3|image/jpeg|||";
cmd += path; cmd += path;
@ -660,6 +731,20 @@ bool tag_FLAC(const string& path, const string& filename, bool is_single_dir,
return system_command(cmd); return system_command(cmd);
} }
void save_release_date(const string& path, const string& date)
{
ofstream file;
string filepath;
filepath = path;
filepath += FOLDER_DELIM;
filepath += "Date.txt";
file.open(filepath);
file << date << endl;
file.close();
}
bool full_donwload(const string& path, const string& release_prefix, bool full_donwload(const string& path, const string& release_prefix,
int release_num, const string& release_suffix) int release_num, const string& release_suffix)
{ {
@ -676,7 +761,7 @@ bool full_donwload(const string& path, const string& release_prefix,
catalog_release_str = release_prefix; catalog_release_str = release_prefix;
catalog_release_str += num_to_str(release_num, 3); catalog_release_str += num_to_str(release_num, 3);
catalog_release_str == release_suffix; catalog_release_str += release_suffix;
release_precision = 3; release_precision = 3;
if (release_prefix == "MCS") if (release_prefix == "MCS")
@ -695,8 +780,8 @@ bool full_donwload(const string& path, const string& release_prefix,
info = parse_json_file(RELEASE_JSON); info = parse_json_file(RELEASE_JSON);
release_artist_title = get_artist_title(info["Release"]); release_artist_title = get_artist_title(info["Release"]);
release_dir = get_release_dir_name(path, release_num, release_dir = get_release_dir_name(path, release_prefix, release_num,
release_artist_title.first, release_artist_title.second, release_suffix, release_artist_title.first, release_artist_title.second,
release_precision); release_precision);
// Make Release Folder // Make Release Folder
@ -706,6 +791,9 @@ bool full_donwload(const string& path, const string& release_prefix,
return false; return false;
} }
// Save Release Date
save_release_date(release_dir, info["Release"]["ReleaseDate"]);
is_single_dir = (info["Tracks"].size() == 1); is_single_dir = (info["Tracks"].size() == 1);
// Make MP3 & FLAC Folders (If more than 1 Track) // Make MP3 & FLAC Folders (If more than 1 Track)
@ -735,7 +823,7 @@ bool full_donwload(const string& path, const string& release_prefix,
} }
// Download Cover // Download Cover
ok = download_cover(info["Release"]["Id"], release_dir); ok = download_cover(catalog_release_str, release_dir);
if (!ok) if (!ok)
{ {
return false; return false;
@ -751,7 +839,12 @@ bool full_donwload(const string& path, const string& release_prefix,
return false; return false;
} }
// TODO: Make 750x750 Cover JPEG Image // Make 750x750 Cover JPEG Image
ok = resize_cover(release_dir, cover_is_jpg);
if (!ok)
{
return false;
}
// Rename Cover Image (Proper Extension) // Rename Cover Image (Proper Extension)
ok = rename_cover(release_dir, cover_is_jpg); ok = rename_cover(release_dir, cover_is_jpg);
@ -802,8 +895,215 @@ bool full_donwload(const string& path, const string& release_prefix,
return true; return true;
} }
bool break_down_release_str(const string& release, string& prefix, int& num, string& suffix)
{
int pos;
int pos2;
string digits = "0123456789";
prefix = "";
num = 0;
suffix = "";
pos = release.find_first_of(digits);
if (string::npos == pos)
{
return false;
}
prefix = release.substr(0, pos);
pos2 = release.find_first_not_of(digits, pos);
if (string::npos == pos2)
{
try
{
num = stod(release.substr(pos));
}
catch(const std::exception& e)
{
return false;
}
}
else
{
try
{
num = stod(release.substr(pos, pos2 - pos));
}
catch(const std::exception& e)
{
return false;
}
suffix = release.substr(pos2);
}
return true;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// TODO: Implement vector<string> args(&argv[1], &argv[argc]);
pair<bool, string> single_release = {false, ""};
pair<bool, string> json_option = {false, ""};
string path = ".";
if (argc < 3)
{
cout << "Too few arguments" << endl;
usage(argv[0]);
return -1;
}
// Ugly getopt
for (int i = 0; i < args.size(); ++i)
{
if ((args[i] == "-1") && (i + 1 < args.size()))
{
single_release.first = true;
single_release.second = args[i + 1];
args.erase(args.begin() + i);
args.erase(args.begin() + i);
--i;
continue;
}
if ((args[i] == "-j") && (i + 1 < args.size()))
{
json_option.first = true;
json_option.second = args[i + 1];
args.erase(args.begin() + i);
args.erase(args.begin() + i);
--i;
continue;
}
}
// Both selected
if (single_release.first && json_option.first)
{
cout << "Both single release and json file are selected." << endl;
usage(argv[0]);
return -1;
}
// None selected
if (!single_release.first && !json_option.first)
{
cout << "Neither single release nor json file are selected." << endl;
usage(argv[0]);
return -1;
}
// Add path from arguments
if (!args.empty())
{
path = args[0];
}
// Remove trailing slash
if (path[path.size() - 1] == FOLDER_DELIM)
{
path.erase(path.size() - 1);
}
#if 1
// BEGIN TEST PRINTS
if (single_release.first)
{
cout << "SINGLE: " << single_release.second << endl;
}
if (json_option.first)
{
cout << "JSON: " << json_option.second << endl;
}
cout << "PATH: " << path << endl;
// END TEST PRINTS
#endif
vector<string> releases;
vector<string>::iterator it;
// Add single release
if (single_release.first)
{
releases.push_back(single_release.second);
}
// Parse JSON
if (json_option.first)
{
json j = parse_json_file(json_option.second);
if (j.contains("releases") && j["releases"].is_array())
{
for (int i = 0; i < j["releases"].size(); ++i)
{
releases.push_back(j["releases"][i]);
}
}
else if (j.contains("prefix") &&
j.contains("start") && j["start"].is_number_integer() &&
j.contains("end") && j["end"].is_number_integer())
{
string tmp;
for (int i = j["start"]; i <= j["end"]; ++i)
{
// Add release
tmp = j["prefix"];
tmp += num_to_str(i, 3);
releases.push_back(tmp);
// Add release with suffix
if (j.contains("suffix_try") && !j["suffix_try"].empty())
{
tmp += j["suffix_try"];
releases.push_back(tmp);
}
}
}
else
{
cout << "JSON not recognized" << endl;
return -1;
}
}
string release_prefix;
int release_num;
string release_suffix;
bool ok;
ok = login();
if (!ok)
{
cout << "Failed to login" << endl;
return -1;
}
// Break down release string
for (it = releases.begin(); it != releases.end(); ++it)
{
ok = break_down_release_str(*it, release_prefix, release_num, release_suffix);
if (!ok)
{
cout << "Failed to break down - " << *it << endl;
continue;
}
ok = full_donwload(path, release_prefix, release_num, release_suffix);
if (!ok)
{
cout << "Could not download - " << *it << endl;
}
}
ok = logout();
if (!ok)
{
cout << "Failed to logout" << endl;
}
return 0; return 0;
} }