]> git.treefish.org Git - usetaglib.git/blobdiff - usetaglib.cpp
Added backslash escape of equal signs in tags.
[usetaglib.git] / usetaglib.cpp
index dbebaa85e6d3b4548533f3932596fb0a8000a07d..d8d51ed399f07ae4d3eb5b5bc196d428c822cb72 100644 (file)
 #include <taglib/tstringlist.h>
 #include <getopt.h>
 #include <vector>
+#include <sstream>
 
 using namespace std;
 
 enum action {LIST, REPLACE, INSERT, ERASE, AUDIO};
 typedef pair<action,string> actionpair;
 typedef vector<actionpair> actionqueue;
-typedef pair<string,string> tagpair;
+typedef pair<TagLib::String,TagLib::StringList> keyandvalues;
 
-TagLib::StringList argToStringList (const string &rawtagarg)
+keyandvalues toKeyAndValues (const string &rawstring)
 {
-  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;
+  stringstream tmpss;
+  TagLib::String key;
+  TagLib::StringList values;
+  int isplit=0;
+  
+  for (int ipos=0; ipos < rawstring.length(); ipos++) {
+    if ( rawstring[ipos] == '\\' ) {
+      switch (rawstring[ipos+1]) {
+      case '\\':
+       tmpss << '\\';
+       break;
+      case '=':
+       tmpss << '=';
+       break;
+      default:
+       tmpss << '\\' << rawstring[ipos+1];
+       break;
+      }
+      ipos++;
+    }
+    else
+      if ( rawstring[ipos] == '=' ) {
+       if ( isplit == 0 ) 
+         key = tmpss.str();
+       else
+         values.append(tmpss.str());
+       isplit++;
+       tmpss.str("");
+      }
+      else
+       tmpss << rawstring[ipos];
   }
-  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));
+  if (isplit==0)
+    key = tmpss.str();
+  else
+    values.append(tmpss.str());
+  
+  return make_pair(key, values);
 }
 
 void action_eraseTag (TagLib::PropertyMap &propmap, const string &key)
@@ -59,14 +80,14 @@ void action_eraseTag (TagLib::PropertyMap &propmap, const string &key)
   propmap.erase(key);
 }
 
-void action_replaceTag (TagLib::PropertyMap &propmap, const tagpair &tagPair)
+void action_replaceTag (TagLib::PropertyMap &propmap, const keyandvalues &keyAndValues)
 {
-  propmap.replace(tagPair.first, argToStringList(tagPair.second));
+  propmap.replace(keyAndValues.first, keyAndValues.second);
 }
 
-void action_insertTag (TagLib::PropertyMap &propmap, const tagpair &tagPair)
+void action_insertTag (TagLib::PropertyMap &propmap, const keyandvalues &keyAndValues)
 {
-  propmap.insert(tagPair.first, argToStringList(tagPair.second));
+  propmap.insert(keyAndValues.first, keyAndValues.second);
 }
 
 int action_printTags (const TagLib::FileRef f, TagLib::PropertyMap &propmap)
@@ -78,7 +99,7 @@ int action_printTags (const TagLib::FileRef f, TagLib::PropertyMap &propmap)
        longest = i->first.size();
       }
     }
-    cout << "-- TAG (properties) --" << endl;
+    cout << " \\_____/ TAGS \\_____ _ _ _" << endl;
     for(TagLib::PropertyMap::ConstIterator i = propmap.begin(); i != propmap.end(); ++i) {
       for(TagLib::StringList::ConstIterator j = i->second.begin(); j != i->second.end(); ++j) {
        cout << i->first << "=" << *j << endl;
@@ -96,7 +117,7 @@ int action_printAudio (const TagLib::FileRef f)
     TagLib::AudioProperties *properties = f.audioProperties();
     int seconds = properties->length() % 60;
     int minutes = (properties->length() - seconds) / 60;
-    cout << "-- AUDIO --" << endl;
+    cout << " \\_____/ AUDIO PROPERTIES \\_____ _ _ _" << endl;
     cout << "BITRATE=" << properties->bitrate() << endl;
     cout << "SAMPLERATE=" << properties->sampleRate() << endl;
     cout << "CHANNELS=" << properties->channels() << endl;
@@ -121,7 +142,7 @@ void printHelp ()
     "  If multiple actions are specified they are executed in given order.\n"
     "\n"
     "  -l, --list                    list all tags (implicit if no action given)\n"
-    "  -a, --audio                   show audio information\n"
+    "  -a, --audio                   show audio properties\n"
     "  -e, --erase=TAGNAME           erase tag TAGNAME\n"
     "  -r, --replace=TAGNAME=TAGVAL  replace tag TAGNAME with value TAGVAL\n"
     "  -i, --insert=TAGNAME=TAGVAL   insert tag TAGNAME with value TAGVAL\n";
@@ -145,15 +166,18 @@ void printExtraHelp ()
     "TAGVAL\n"
     "  TAGVAL has to be either a single string or a list of strings separated\n"
     "  by equal signs (=). If a list is given, multiple tags of type TAGNAME\n"
-    "  will be created and set to the respective values given in the list.\n"
+    "  will be created and set to the respective values given by the list.\n"
+    "  Note that equal signs have to be escaped with a leading backslash (\\=),\n"
+    "  if they shall not be interpreted as list separators.\n"
     "\n"
-    "EXAMPLES"
+    "EXAMPLES\n"
     "  usetaglib file.ogg\n"
     "  usetaglib -e ALBUM file.flac\n"
     "  usetaglib -r \"ALBUM=New Album\" -i ARTIST=Horst=Hubert file.mp3\n"
     "  usetaglib -r ARTIST=Horst -l file1.ogg file2.mp3\n"
     "  usetaglib -i \"ALBUMARTIST=Horst und Hubert\" file.ogg\n"
-    "  usetaglib --insert=\"ALBUMARTIST=Horst und Hubert\" file.ogg\n";
+    "  usetaglib --insert=\"ALBUMARTIST=Horst und Hubert\" file.ogg\n"
+    "  usetaglib --replace='ARTIST=This Band \\= Great' file.ogg\n";
 }
   
 int main(int argc, char *argv[])
@@ -227,7 +251,11 @@ int main(int argc, char *argv[])
     requestedActions.push_back( make_pair(LIST, "") );
         
   for(int i = optind; i < argc; i++) {
-    cout << "******************** \"" << argv[i] << "\" ********************" << endl;
+    cout << " _________________________________________ _ _ _" << endl;
+    cout << "/" << endl;
+    cout << "  " << argv[i] << endl;
+    cout << "\\_________________________________________ _ _ _" << endl;
+    
     TagLib::FileRef f(argv[i]);
 
     if(f.isNull())
@@ -249,11 +277,11 @@ int main(int argc, char *argv[])
        FCHANGED = true;
        break;
       case REPLACE:
-       action_replaceTag(propmap, splitToTagPair(actit->second));
+       action_replaceTag(propmap, toKeyAndValues(actit->second));
        FCHANGED = true;
        break;
       case INSERT:
-       action_insertTag(propmap, splitToTagPair(actit->second));
+       action_insertTag(propmap, toKeyAndValues(actit->second));
        FCHANGED = true;
        break;
       }