]> diplodocus.org Git - flac-archive/blobdiff - rewrite-tags
copy VERSION values into mp3 title, in parens
[flac-archive] / rewrite-tags
index fe65a2441544f52a436a6f2c91c55e00c22e5a7e..1d4b41242b481d0a8fc66f2423b3cd9437516224 100755 (executable)
@@ -1,34 +1,52 @@
 #! /usr/bin/python
 
-import sys
-from subprocess import Popen, PIPE
-
-from org.diplodocus.util import run_or_die
+import os, sys
+import subprocess
+import tempfile
+from errno import EEXIST
 
 from flac_archive.tags import Tags
 
 class SubprocessError(Exception):
-    def __init__(self, status, stderr=None):
+    def __init__(self, status, command=None, stderr=None):
+        if command is None:
+            command_msg = None
+        else:
+            command_msg = ': ' + ' '.join(command)
         if status < 0:
-            msg = 'exited due to signal %d'
+            msg = 'exited due to signal %d%s'
         else:
-            msg = 'exit status %d'
-        Exception.__init__(self, msg % (status,))
+            msg = 'exit status %d%s'
+        Exception.__init__(self, msg % (abs(status), command_msg))
         self.status = status
-        self.stderr = stderr
+        self.command = command
+        self.stderr = ''.join(stderr)
 
 def get_tags(fn):
     tags = Tags()
-    p = Popen(['metaflac', '--no-utf8-convert', '--export-tags-to=-', fn],
-              stdout=PIPE)
+
+    command = ['metaflac', '--no-utf8-convert', '--export-tags-to=-', fn]
+    p = subprocess.Popen(command, stdout=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
     tags.load(p.stdout)
 
     status = p.wait()
     if status != 0:
-        raise SubprocessError(status, p.stderr)
+        raise SubprocessError(status, command=command, stderr=p.stdout)
 
     return tags
 
+def rewrite_track_tags(track, tags, fn, tmp):
+    tmp.write('\n'.join(tags.track(track)) + '\n')
+    tmp.close()
+    command = ['metaflac', '--no-utf8-convert', '--dont-use-padding',
+               '--remove-all-tags', '--import-tags-from', tmp.name, fn]
+    p = subprocess.Popen(command, stdout=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+    status = p.wait()
+    if status != 0:
+        raise SubprocessError(status, command=command, stderr=p.stdout)
+
 def do_read(filenames):
     # Use this mapping of tag names to sets of tag values to detect global tags.
     all_tags = {}
@@ -39,10 +57,15 @@ def do_read(filenames):
     for fn in filenames:
         tags = get_tags(fn)
         track_tags = tags.get('TRACKNUMBER')
+        # this check belongs in Tags
         if len(track_tags) != 1:
-            raise Exception('bogus TRACKNUMBER %s for %s' % (track_tags, fn))
+            sys.stderr.write('bogus TRACKNUMBER %s: %s\n' % (track_tags, fn))
+            return 4
         track = int(track_tags[0])
         for tag, values in tags._global.iteritems():
+            # Makes no sense to save TRACKNUMBER in coll_tags.
+            if tag == 'TRACKNUMBER':
+                continue
             for value in values:
                 if tag in all_tags:
                     all_tags[tag].add(value)
@@ -57,14 +80,54 @@ def do_read(filenames):
             for track, tags in coll_tags._tracks.iteritems():
                 del tags[tag]
     print '\n'.join(coll_tags.all())
+    return 0
+
+def do_write(args):
+    tags = Tags()
+    tags.load(open(args.pop(0)))
+    if len(args) != len(tags):
+        sys.stderr.write('expected %d flac files, got %d\n'
+                         % (len(tags), len(args)))
+        return 2
+    artist = tags.get_path_safe('ARTIST')
+    album = tags.get_path_safe('ALBUM')
+    try:
+        os.mkdir(artist)
+    except OSError, e:
+        if e.errno != EEXIST:
+            raise
+    album_path = artist + '/' + album
+    try:
+        os.mkdir(album_path)
+    except OSError, e:
+        if e.errno != EEXIST:
+            raise
+    for i, old_fn in enumerate(args):
+        track = i + 1
+        fn = '%s/%s/%s.flac' % (artist, album, tags.make_filename(track))
+        if fn != old_fn:
+            os.rename(old_fn, fn)
+        tmp = tempfile.NamedTemporaryFile(delete=False)
+        try:
+            rewrite_track_tags(track, tags, fn, tmp)
+        finally:
+            try:
+                os.unlink(tmp.name)
+            except:
+                pass
+    return 0
 
 def main(args):
     if len(args) < 3:
         return usage()
-    if args[1] == 'read':
-        return do_read(args[2:])
-    if args[1] == 'write':
-        return do_write(args[2:])
+    try:
+        if args[1] == 'read':
+            return do_read(args[2:])
+        if args[1] == 'write':
+            return do_write(args[2:])
+    except SubprocessError, e:
+        sys.stderr.write('%s\n%s\n' % (e.stderr, e))
+        return 3
     return usage()
 
 def usage():