summaryrefslogtreecommitdiff
path: root/extras
diff options
context:
space:
mode:
authorAndrzej Rybczak <electricityispower@gmail.com>2011-02-25 20:14:39 +0100
committerAndrzej Rybczak <electricityispower@gmail.com>2011-02-25 20:14:39 +0100
commita9a40e77e7b5173e1d2d30e9d13e8b96cee92ff4 (patch)
tree2873d0758541bc8bcef4d0f9abf77e7c993b39b9 /extras
parentdff99c4b0beed85b3636311730944c9367df543d (diff)
extras: add program that copies Artist to AlbumArtist for mp3/ogg/flac files
Diffstat (limited to 'extras')
-rw-r--r--extras/Makefile12
-rw-r--r--extras/artist_to_albumartist.cpp137
2 files changed, 149 insertions, 0 deletions
diff --git a/extras/Makefile b/extras/Makefile
new file mode 100644
index 00000000..6d4c9eea
--- /dev/null
+++ b/extras/Makefile
@@ -0,0 +1,12 @@
+CXX=g++
+CXXFLAGS=-O2 -g
+CPPFLAGS=`taglib-config --cflags`
+LDFLAGS=`taglib-config --libs`
+
+artist_to_albumartist: artist_to_albumartist.cpp
+ $(CXX) artist_to_albumartist.cpp -o artist_to_albumartist $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
+
+clean:
+ rm -f artist_to_albumartist
+
+.PHONY: clean
diff --git a/extras/artist_to_albumartist.cpp b/extras/artist_to_albumartist.cpp
new file mode 100644
index 00000000..b3c1fb7a
--- /dev/null
+++ b/extras/artist_to_albumartist.cpp
@@ -0,0 +1,137 @@
+/***************************************************************************
+ * Copyright (C) 2008-2011 by Andrzej Rybczak *
+ * electricityispower@gmail.com *
+ * *
+ * 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 2 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, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <cstring>
+#include <iostream>
+
+#include "xiphcomment.h"
+#include "id3v2tag.h"
+#include "textidentificationframe.h"
+#include "fileref.h"
+#include "mpegfile.h"
+#include "vorbisfile.h"
+#include "flacfile.h"
+
+using std::cout;
+
+bool framelist_empty(const TagLib::ID3v2::FrameList &fl)
+{
+ TagLib::ID3v2::FrameList::ConstIterator it = fl.begin();
+ while (it != fl.end())
+ if (!((*it++)->toString() == TagLib::String::null))
+ return false;
+ return true;
+}
+
+bool write_id3v2_aa(TagLib::ID3v2::Tag *tag, const TagLib::String &artist)
+{
+ using TagLib::ID3v2::TextIdentificationFrame;
+ TagLib::ByteVector type = "TPE2";
+ if (!framelist_empty(tag->frameList(type)))
+ return false;
+ TextIdentificationFrame *frame = new TextIdentificationFrame(type, TagLib::String::UTF8);
+ frame->setText(artist);
+ tag->addFrame(frame);
+ return true;
+}
+
+bool write_xiphcomment_aa(TagLib::Ogg::XiphComment *tag, const TagLib::String &artist)
+{
+ if (tag->contains("ALBUM ARTIST"))
+ return false;
+ tag->addField("ALBUM ARTIST", artist, true);
+ return true;
+}
+
+void convert(int n, char **files, bool dry_run)
+{
+ if (n == 0)
+ {
+ cout << "No files to convert, exiting.\n";
+ return;
+ }
+ if (dry_run)
+ cout << "Dry run mode enabled, pretending to modify files.\n";
+
+ for (int i = 0; i < n; ++i)
+ {
+ cout << "Modifying " << files[i] << "... ";
+
+ TagLib::FileRef f(files[i]);
+ if (!f.isNull())
+ {
+ TagLib::String artist = f.tag()->artist();
+ if (!(artist == TagLib::String::null))
+ {
+ TagLib::MPEG::File *mp3_f = 0;
+ TagLib::Ogg::Vorbis::File *ogg_f = 0;
+ TagLib::FLAC::File *flac_f = 0;
+
+ bool success;
+ if ((mp3_f = dynamic_cast<TagLib::MPEG::File *>(f.file())))
+ {
+ success = write_id3v2_aa(mp3_f->ID3v2Tag(true), artist);
+ }
+ else if ((ogg_f = dynamic_cast<TagLib::Ogg::Vorbis::File *>(f.file())))
+ {
+ success = write_xiphcomment_aa(ogg_f->tag(), artist);
+ }
+ else if ((flac_f = dynamic_cast<TagLib::FLAC::File *>(f.file())))
+ {
+ success = write_xiphcomment_aa(flac_f->xiphComment(true), artist);
+ }
+ else
+ {
+ cout << "Not mp3/ogg/flac file, skipping.\n";
+ continue;
+ }
+
+ if (success)
+ {
+ if (!dry_run)
+ f.save();
+ cout << "Done.\n";
+ }
+ else
+ cout << "AlbumArtist is already here, skipping.\n";
+ }
+ else
+ cout << "Artist not found, skipping.\n";
+ }
+ else
+ cout << "Could not open file, skipping.\n";
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2)
+ {
+ cout << "This little program copies Artist tag (if present) to\n";
+ cout << "AlbumArtist (if not present) for given mp3/ogg/flac files.\n\n";
+ cout << "Usage: " << argv[0] << " [--dry-run] files\n";
+ }
+ else
+ {
+ bool dry_run = !strcmp(argv[1], "--dry-run");
+ convert(argc-1-dry_run, &argv[1+dry_run], dry_run);
+ }
+ return 0;
+}