-#! /usr/bin/env python2.4
+#! /usr/bin/python
-'''
+"""
=head1 NAME
B<fa-flacd> - archive CDs to single FLAC files
=cut
-''' #' # python-mode is sucks
+"""
import os
import re
from org.diplodocus.util import die, flatten, nothing
from org.diplodocus.util import catch_EnvironmentError as c
+from flac_archive.tags import Tags
+
def spew(*args):
if verbose:
for i in args:
for i in tags:
argv.extend(['-T', i])
argv.append(infile)
+ # flac 1.1.3 PICTURE support
+ if os.path.exists('cover.front'):
+ argv.extend(['--picture', '3|image/jpeg|||cover.front'])
spew('Running flac\n')
status = os.spawnvp(os.P_WAIT, argv[0], argv)
c(os.rename, outfile + '.flac-tmp', outfile + '.flac')
-def flac(dir, artist, album, discnum, tracknum, track_tags, disc_artist, tags):
- '''Encode a single wav file to a single flac file, whether the wav and
- flac files represent individual tracks or whole discs.'''
+def flac(dir, tracknum, tags):
+ """Encode a single wav file to a single flac file, whether the wav and
+ flac files represent individual tracks or whole discs."""
- (artist, album) = [x.replace('/', '_') for x in (artist, album)]
+ separator = ' '
+ if len(tags.get('ALBUMARTIST')) > 0:
+ artist_tag = tags.gets('ALBUMARTIST', separator=', ')
+ else:
+ artist_tag = tags.gets('ARTIST', separator=', ')
+ artist = (artist_tag or '').replace('/', '_')
+ album = (tags.gets('ALBUM', separator=separator) or '').replace('/', '_')
+ discnum = tags.gets('DISCNUMBER')
spew('mkdir(%s)\n' % (artist,))
try:
outfile = album
if discnum != None:
outfile = ''.join([discnum, ' ', outfile])
- run_flac('wav', 'cue', '/'.join(['..', artist, outfile]), tags)
+ run_flac('wav', 'cue', '/'.join(['..', artist, outfile]), tags.all())
files = ['%s/%s.flac' % (artist, outfile)]
c(os.unlink, 'cue')
outlog = '/'.join(['..', artist, outfile + '.log'])
c(os.rename, 'log', outlog)
else:
- title = []
- for i in track_tags['TITLE']:
- title.extend(i.split())
- title = ' '.join(title).replace('/', '_')
+ title = tags.gets('TITLE', tracknum, separator).replace('/', '_')
tmp = []
if discnum != None:
tmp.append('%02d' % (int(discnum),))
tmp.extend(['%02d' % (tracknum,), title])
+ part = tags.gets('PART', tracknum)
+ if part != None:
+ tmp.extend(['-', part])
outfile = '/'.join([outdir, ' '.join(tmp)])
- tags = tags[:]
- # If we have ARTIST[n] tags for this track, they'll go in with
- # the other [n] tags. Else, prepend disc_artist to tags.
- if 'ARTIST' not in track_tags:
- for i in disc_artist:
- tags.insert(0, i)
-
- tags.append('TRACKNUMBER=%d' % (tracknum,))
- tags.extend(flatten([['='.join([key, x]) for x in track_tags[key]]
- for key in track_tags]))
-
run_flac('track%02d.cdda.wav' % (tracknum,), None,
- '../' + outfile, tags)
+ '../' + outfile, tags.track(tracknum))
outlog = ''.join(['../', outfile, '.log'])
files = [outfile + '.flac']
# Clean up if we're the last job for dir; for multi-file dirs,
# it's possible for more than one job to run cleanup at once, so
# don't fail if things are already clean.
- if os.listdir(dir) == ['using-tags']:
+ ld = os.listdir(dir)
+ if ld == ['using-tags'] or sorted(ld) == ['cover.front', 'using-tags']:
try:
+ try:
+ os.unlink(dir + '/cover.front')
+ except OSError:
+ pass
os.unlink(dir + '/using-tags')
os.rmdir(dir)
except EnvironmentError:
# The master process
def get_tags(fn):
- '''Return the ARTIST, ALBUM, and DATE followed by a list of all the
- lines in the file FN.'''
-
- artist = album = discnum = None
- tags = []
+ """Return the ARTIST, ALBUM, and DATE followed by a list of all the
+ lines in the file FN."""
+ tags = Tags()
spew('Opening tags file %s\n' % (fn,))
- fp = file(fn)
- for line in (x.rstrip() for x in fp):
- tags.append(line)
-
- (tag, value) = line.split('=', 1)
+ tags.load(open(fn))
- if re.match(r'ARTIST=', line, re.IGNORECASE):
- artist = value
- spew('ARTIST %s from %s\n' % (artist, fn))
- elif re.match(r'ALBUM=', line, re.IGNORECASE):
- album = value
- spew('ALBUM %s from %s\n' % (album, fn))
- elif re.match(r'DISCNUMBER=', line, re.IGNORECASE):
- discnum = value
- spew('DISCNUMBER %s from %s\n' % (discnum, fn))
+ spew('ARTIST %s from %s\n' % (tags.gets('ARTIST'), fn))
+ spew('ALBUM %s from %s\n' % (tags.gets('ALBUM'), fn))
+ spew('DISCNUMBER %s from %s\n' % (tags.gets('DISCNUMBER'), fn))
- return (artist, album, discnum, tags)
+ return tags
def flacloop(maxjobs):
dir = [None] # [str] instead of str for lame python closures
spew("Renaming %s/tags\n" % (dir[0],))
c(os.rename, dir[0] + '/tags', dir[0] + '/using-tags')
- (artist, album, discnum, tags) = get_tags(dir[0] + '/using-tags')
+ tags = get_tags(dir[0] + '/using-tags')
if os.path.exists(dir[0] + '/wav'):
# single-file
- jobs.append([dir[0], artist, album, discnum,
- None, None, None, tags])
+ jobs.append((dir[0], None, tags))
else:
# multi-file
# Don't need cue file.
if error.errno != ENOENT:
raise error
- # Go over @tags, store all [n] tags in a list keyed by
- # n in %tracks_to_tags, store all ARTIST (not
- # ARTIST[n]) tags in @disc_artist, and leave the rest
- # in @tags.
- tracks_to_tags = ListDictDict()
- disc_artist = []
- tmp = []
- for tag in tags:
- m = re.match(r'([^[]+)\[(\d+)]=(.*)', tag)
- if m != None:
- tracks_to_tags.append(int(m.group(2)), m.group(1), m.group(3))
- elif re.match(r'ARTIST=', tag, re.IGNORECASE):
- disc_artist.append(tag)
- else:
- tmp.append(tag)
- tags = tmp
-
- jobs.extend([[dir[0], artist, album, discnum, x,
- tracks_to_tags[x], disc_artist, tags]
- for x in sorted(map(int,
- tracks_to_tags.keys()))])
+ jobs.extend([(dir[0], x, tags)
+ for x in xrange(1, len(tags) + 1)])
except Exception, error:
sys.stderr.write(getattr(error, 'msg', ''))
traceback.print_exc()
def lamb():
log = '/'.join([job[0],
- job[4] == None and 'log' or str(job[4])
- + '.log'])
+ job[1] == None and 'log'
+ or str(job[1]) + '.log'])
try:
c(os.dup2, c(os.open, log, os.O_CREAT | os.O_WRONLY), 2)
return flac(*job)