This code puts or changes ID3 tags to media files based on their file names. It assumes the files are in this format:
morbid angel - maze of torment.mp3
The resulting tag would be:
Artist: morbid angel Title: maze of torment
I use boost::filesystem
to iterate through the directory and taglib to manipulate the tags.
#include <boost/filesystem.hpp>
#define TAGLIB_STATIC
#include <taglib/fileref.h>
#include <iostream>
#include <string>
#include <vector>
using namespace boost::filesystem;
using namespace TagLib;
void changeTag(const path& p) {
std::string filename = p.filename().string();
FileRef file(p.string().c_str());
std::string artist = filename.substr(0,filename.find(" -"));
Tag* t = file.tag();
t->setArtist(artist);
t->setTitle(filename.substr(artist.size()+3, filename.size()-artist.size()-7));
file.save();
std::cout << t->artist() << " - " << t->title() << " saved" << '\n';
}
void extractFiles(const std::string& p) {
std::vector<path> files;
std::vector<std::string> errors; // for files that might cause errors
try {
path filepath = p;
for (auto& i : directory_iterator(filepath)) {
changeTag(i.path());
}
} catch(const filesystem_error& e) {
errors.push_back(e.what()); // output later after all files have been processed
}
if (errors.size() > 0) {
std::cout << "Some operations failed with errors:" << '\n';
for (auto& i : errors) {
std::cout << i << '\n';
}
}
}
int main() {
std::string dir;
while (true) {
std::cout << "Directory: Enter 'x' to close: ";
std::cin >> dir;
if (dir == "x") {
break;
}
extractFiles(dir);
}
}
How can I improve this code? How can I make this faster, cleaner and better?