From: Alexander Schmidt Date: Fri, 6 Feb 2015 13:18:11 +0000 (+0100) Subject: initial commit. X-Git-Url: http://git.treefish.org/~alex/usetaglib.git/commitdiff_plain/5e2119a394e8163a0ac1105fae0e4ec8727eb2c3 initial commit. --- 5e2119a394e8163a0ac1105fae0e4ec8727eb2c3 diff --git a/usetaglib.cpp b/usetaglib.cpp new file mode 100644 index 0000000..a616a2e --- /dev/null +++ b/usetaglib.cpp @@ -0,0 +1,236 @@ +/* + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +enum action {LIST, REPLACE, INSERT, ERASE, AUDIO}; +typedef pair actionpair; +typedef vector actionqueue; +typedef pair tagpair; + +TagLib::StringList argToStringList (const string &rawtagarg) +{ + TagLib::StringList newlist; + + size_t delpos = 0; + while (1) { + size_t nextdelpos = rawtagarg.find('=', delpos+1); + if (nextdelpos == -1) + break; + newlist.append(rawtagarg.substr(delpos,nextdelpos-delpos)); + delpos = nextdelpos+1; + } + newlist.append(rawtagarg.substr(delpos,string::npos)); + + return newlist; +} + +tagpair splitToTagPair (const string &rawarg) +{ + const size_t delpos = rawarg.find('='); + return make_pair(rawarg.substr(0, delpos), rawarg.substr(delpos+1, string::npos)); +} + +void action_eraseTag (const TagLib::FileRef f, const string &key) +{ + TagLib::PropertyMap propmap = f.file()->properties(); + propmap.erase(key); + f.file()->setProperties(propmap); +} + +void action_replaceTag (const TagLib::FileRef f, const tagpair &tagPair) +{ + TagLib::PropertyMap propmap = f.file()->properties(); + propmap.replace(tagPair.first, argToStringList(tagPair.second)); + f.file()->setProperties(propmap); +} + +void action_insertTag (const TagLib::FileRef f, const tagpair &tagPair) +{ + TagLib::PropertyMap propmap = f.file()->properties(); + propmap.insert(tagPair.first, argToStringList(tagPair.second)); + f.file()->setProperties(propmap); +} + +int action_printTags (const TagLib::FileRef f) +{ + if(f.tag()) { + TagLib::PropertyMap tags = f.file()->properties(); + unsigned int longest = 0; + for(TagLib::PropertyMap::ConstIterator i = tags.begin(); i != tags.end(); ++i) { + if (i->first.size() > longest) { + longest = i->first.size(); + } + } + cout << "-- TAG (properties) --" << endl; + for(TagLib::PropertyMap::ConstIterator i = tags.begin(); i != tags.end(); ++i) { + for(TagLib::StringList::ConstIterator j = i->second.begin(); j != i->second.end(); ++j) { + cout << i->first << "=" << *j << endl; + } + } + return 0; + } + else + return 1; +} + +int action_printAudio (const TagLib::FileRef f) +{ + if(f.audioProperties()) { + TagLib::AudioProperties *properties = f.audioProperties(); + int seconds = properties->length() % 60; + int minutes = (properties->length() - seconds) / 60; + cout << "-- AUDIO --" << endl; + cout << "BITRATE=" << properties->bitrate() << endl; + cout << "SAMPLERATE=" << properties->sampleRate() << endl; + cout << "CHANNELS=" << properties->channels() << endl; + cout << "LENGTH=" << minutes << ":" << setfill('0') << setw(2) << seconds << endl; + return 0; + } + else + return 1; +} + +void printHelp () +{ + cout << "Usage: usetaglib [ACTION]... [FILE]..." << endl; + cout << "List and edit tags on mediafiles in formats supported by libtag." << endl; + cout << endl; + cout << "-h, --help Show this help" << endl; + cout << endl; + cout << "ACTIONS" << endl; + cout << setfill(' ') << setw(45) << left << " -l, --list" + << "list all tags (implicit if no action specified)"<< endl; + cout << setfill(' ') << setw(45) << left << " -e, --erase=TAGNAME" + << "erase tag with name TAGNAME"<< endl; + cout << setfill(' ') << setw(45) << left << " -r, --replace=TAGNAME=TAGVAL[=TAGVAL...]" + << "replace tag TAGNAME with list of values TAGVAL"<< endl; + cout << setfill(' ') << setw(45) << left << " -i, --insert=TAGNAME=TAGVAL[=TAGVAL...]" + << "insert list of values TAGVAL for tag TAGNAME"<< endl; +} + +int main(int argc, char *argv[]) +{ + int c; + actionqueue requestedActions; + + while (1) + { + static struct option long_options[] = + { + {"help", no_argument, 0, 'h'}, + {"list", no_argument, 0, 'l'}, + {"listaudio", no_argument, 0, 'a'}, + {"insert", required_argument, 0, 'i'}, + {"erase", required_argument, 0, 'e'}, + {"replace", required_argument, 0, 'r'}, + {0, 0, 0, 0} + }; + + int option_index = 0; + c = getopt_long (argc, argv, "hlai:e:r:", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) + { + case 0: + if (long_options[option_index].flag != 0) + break; + + case 'h': + printHelp(); + return 0; + break; + + case 'l': + requestedActions.push_back( make_pair(LIST, "") ); + break; + + case 'a': + requestedActions.push_back( make_pair(AUDIO, "") ); + break; + + case 'i': + requestedActions.push_back( make_pair(INSERT, optarg) ); + break; + + case 'e': + requestedActions.push_back( make_pair(ERASE, optarg) ); + break; + + case 'r': + requestedActions.push_back( make_pair(REPLACE, optarg) ); + break; + + case '?': + break; + + default: + abort (); + } + } + + if (requestedActions.size() == 0) + requestedActions.push_back( make_pair(LIST, "") ); + + for(int i = optind; i < argc; i++) { + cout << "******************** \"" << argv[i] << "\" ********************" << endl; + TagLib::FileRef f(argv[i]); + + if(f.isNull()) + continue; + + for (actionqueue::iterator actit = requestedActions.begin(); actit != requestedActions.end(); ++actit) { + switch (actit->first) { + case LIST: + action_printTags(f); + break; + + case AUDIO: + action_printAudio(f); + break; + + case ERASE: + action_eraseTag(f, actit->second); + break; + + case REPLACE: + action_replaceTag(f, splitToTagPair(actit->second)); + break; + + case INSERT: + action_insertTag(f, splitToTagPair(actit->second)); + break; + } + } + + f.file()->save(); + } + + return 0; +}