#! /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
Exception.__init__(self, msg % (abs(status), command_msg))
self.status = status
self.command = command
- self.stderr = stderr
+ self.stderr = ''.join(stderr)
def get_tags(fn):
tags = Tags()
command = ['metaflac', '--no-utf8-convert', '--export-tags-to=-', fn]
- p = Popen(command, stdout=PIPE)
+ p = subprocess.Popen(command, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
tags.load(p.stdout)
status = p.wait()
if status != 0:
- raise SubprocessError(status, command=command, stderr=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 = {}
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)
coll_tags.set(tag, value, track)
for tag, values in all_tags.iteritems():
if len(values) == 1:
- # Only one value for this tag, so add it to global tags.
- coll_tags.set(tag, list(values)[0])
- # And now remove it from each track tags.
+ # Only one value for this tag, but does that one value appear on
+ # all tracks?
for track, tags in coll_tags._tracks.iteritems():
- del tags[tag]
+ if not tag in tags:
+ # Nope.
+ break
+ else:
+ # Yep, so add it to global tags.
+ coll_tags.set(tag, list(values)[0])
+ # And now remove it from each track tags.
+ 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('ALBUMARTIST')
+ if not artist:
+ artist = tags.get_path_safe('ARTIST')
+ album = tags.get_path_safe('ALBUM')
+ if not album:
+ album = tags.get_path_safe('ALBUM', track=1)
+ 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():