mcopy/mcopy.cpp

179 lines
5.1 KiB
C++
Raw Normal View History

2023-08-16 07:59:24 +02:00
/* mcopy
*
* Rename music by specifying a format
* Licensed under the GNU General Public License version 3.
* See included LICENSE file for copyright and license details.
*/
2023-08-15 20:51:29 +02:00
#include <iostream>
#include <filesystem>
#include <string>
#include <fstream>
#include <regex>
#include <cstdlib>
2023-08-15 20:51:29 +02:00
#include <tag.h>
#include <fileref.h>
#ifndef VERSION
#define VERSION "0.1"
#endif
2023-08-16 07:59:24 +02:00
bool ask = true;
2023-08-16 08:22:23 +02:00
bool quiet = false;
2023-08-16 07:59:24 +02:00
2023-08-15 20:51:29 +02:00
void help() {
std::cout <<
"mcopy " << VERSION << "\n\n" <<
2023-08-16 08:22:23 +02:00
"mcopy -f, --format Specify a format to output files using\n" <<
"mcopy -a, --ask Ask the user if metadata cannot be retrieved from file\n" <<
"mcopy -na, --no-ask Don't ask if metadata cannot be retrieved from file\n" <<
"mcopy -q, --quiet Don't print status messages. Warnings will still be printed\n" <<
"mcopy -nq, --no-quiet Print status messages\n" <<
"mcopy -h, --help Display help\n" <<
"mcopy -v, --version Display version\n" <<
2023-08-15 20:51:29 +02:00
"\n" <<
2023-08-15 21:17:56 +02:00
"Example: mcopy --format \"/home/anon/Music/Albums/@A/@a/@n. @A - @t.flac\" \"~/Downloads/myflac1.flac\" \"~/Downloads/myflac2.flac\n" <<
2023-08-15 20:51:29 +02:00
"\n" <<
"Formats:\n" <<
"\n" <<
"@A Artist\n" <<
"@a Album name\n" <<
"@t Title\n" <<
"@n Track number\n";
}
2023-08-16 08:02:27 +02:00
TagLib::FileRef getFile(std::string str) {
2023-08-15 20:51:29 +02:00
const char *cstr = str.c_str();
TagLib::FileName fn(cstr);
TagLib::FileRef file(fn);
return file;
}
void getMetadataFromFile(std::string format, std::string str) {
2023-08-16 08:02:27 +02:00
TagLib::FileRef file = getFile(str);
2023-08-15 20:51:29 +02:00
TagLib::Tag *tag = file.tag();
if (file.isNull() || !file.audioProperties()) {
std::cerr << "File '" << str << "' is not valid. Skipping.\n";
2023-08-15 20:51:29 +02:00
return;
}
std::string title = tag->title().to8Bit(true);
std::string album = tag->album().to8Bit(true);
std::string artist = tag->artist().to8Bit(true);
std::string track = std::to_string(tag->track());
2023-08-16 07:59:24 +02:00
// If information is missing, ask for the missing details
if (title.empty()) {
title = "Unknown";
if (ask) {
std::cerr << "mcopy: Could not retrieve title; please specify\n> ";
2023-08-16 07:59:24 +02:00
std::getline(std::cin, title);
}
} else if (album.empty()) {
album = "Unknown";
if (ask) {
std::cerr << "mcopy: Could not retrieve album; please specify\n> ";
2023-08-16 07:59:24 +02:00
std::getline(std::cin, album);
}
} else if (artist.empty()) {
artist = "Unknown";
if (ask) {
std::cerr << "mcopy: Could not retrieve artist; please specify\n> ";
2023-08-16 07:59:24 +02:00
std::getline(std::cin, artist);
}
} else if (track.empty()) {
track = "Unknown";
if (ask) {
std::cerr << "mcopy: Could not retrieve track; please specify\n> ";
2023-08-16 07:59:24 +02:00
std::getline(std::cin, track);
}
}
2023-08-15 20:51:29 +02:00
std::string filename = format;
// TODO: Replace this junk
2023-08-16 07:59:24 +02:00
filename = std::regex_replace(filename, std::regex("@t"), title);
2023-08-15 20:51:29 +02:00
filename = std::regex_replace(filename, std::regex("@a"), album);
filename = std::regex_replace(filename, std::regex("@A"), artist);
filename = std::regex_replace(filename, std::regex("@n"), track);
2023-08-16 07:59:24 +02:00
std::ifstream ef(filename);
if (static_cast<bool>(ef.good())) {
std::cerr << "mcopy: File already exists, skipping.\n";
2023-08-16 07:59:24 +02:00
return;
}
2023-08-15 20:51:29 +02:00
std::filesystem::path fs;
std::string dir = (fs = filename).remove_filename();
std::filesystem::create_directories(dir);
if (!std::filesystem::copy_file(str, filename)) {
std::cerr << "mcopy: Failed to copy file " << str << " to " << filename << "\n";
std::exit(1);
2023-08-16 08:22:23 +02:00
} else if (!quiet) {
2023-08-15 20:51:29 +02:00
std::cout << "mcopy: Copied file " << str << " to " << filename << "\n";
}
}
int main(int argc, char **argv) {
std::string format = "";
for (int i{1}; i < argc; i++) {
std::string arg = argv[i];
2023-08-16 07:59:24 +02:00
if (!arg.compare("-h") || !arg.compare("--help")) {
2023-08-15 20:51:29 +02:00
help();
std::exit(0);
2023-08-16 07:59:24 +02:00
} else if (!arg.compare("-v") || !arg.compare("--version")) {
2023-08-15 20:51:29 +02:00
std::cout << "mcopy " << VERSION << '\n';
std::exit(0);
2023-08-16 07:59:24 +02:00
} else if (!arg.compare("-a") || !arg.compare("--ask")) {
ask = true;
} else if (!arg.compare("-na") || !arg.compare("--no-ask")) {
ask = false;
2023-08-16 08:22:23 +02:00
} else if (!arg.compare("-q") || !arg.compare("--quiet")) {
quiet = true;
} else if (!arg.compare("-nq") || !arg.compare("--no-quiet")) {
quiet = false;
2023-08-16 07:59:24 +02:00
} else if (!arg.compare("-f") || !arg.compare("--format")) {
if (argc > i+1) {
format = argv[i++];
2023-08-16 07:59:24 +02:00
}
2023-08-15 20:51:29 +02:00
continue;
}
}
if (!format.compare("")) {
std::cerr << "mcopy: You must specify a format.\n";
std::exit(1);
2023-08-15 20:51:29 +02:00
}
if (argc < 4) {
std::cerr << "mcopy: You must specify a file to copy.\n";
std::exit(1);
}
2023-08-16 08:12:29 +02:00
int set{0};
for (int i{1}; i < argc; i++) {
std::ifstream f(argv[i]);
2023-08-15 20:51:29 +02:00
if (static_cast<bool>(f.good())) {
2023-08-16 08:12:29 +02:00
set = 1;
getMetadataFromFile(format, argv[i]);
2023-08-15 20:51:29 +02:00
}
}
2023-08-16 08:12:29 +02:00
if (!set) {
std::cerr << "mcopy: File not found.\n";
std::exit(1);
2023-08-16 08:12:29 +02:00
}
2023-08-15 20:51:29 +02:00
}