]> git.treefish.org Git - usetaglib.git/commitdiff
initial commit.
authorAlexander Schmidt <alex@treefish.org>
Fri, 6 Feb 2015 13:18:11 +0000 (14:18 +0100)
committerAlexander Schmidt <alex@treefish.org>
Fri, 6 Feb 2015 13:18:11 +0000 (14:18 +0100)
usetaglib.cpp [new file with mode: 0644]

diff --git a/usetaglib.cpp b/usetaglib.cpp
new file mode 100644 (file)
index 0000000..a616a2e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+*/
+
+#include <iostream>
+#include <iomanip>
+#include <iostream>
+#include <taglib/fileref.h>
+#include <taglib/tag.h>
+#include <taglib/tpropertymap.h>
+#include <taglib/tstringlist.h>
+#include <getopt.h>
+#include <vector>
+
+using namespace std;
+
+enum action {LIST, REPLACE, INSERT, ERASE, AUDIO};
+typedef pair<action,string> actionpair;
+typedef vector<actionpair> actionqueue;
+typedef pair<string,string> 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;
+}