#!/usr/bin/python2.4

import os, sys, glob, subprocess
from optparse import OptionParser


enc_commands = { 'ogg':  'oggenc %(source)s -q6 -o %(dest)s',
                 'mp3':  'lame --preset standard %(source)s %(dest)s',
                 'flac': 'flac --replay-gain -o %(dest)s %(source)s'}

valid_input_formats = { 'ogg': ('flac', 'wav', 'aif', 'aiff'),
                        'mp3': ('wav', 'aif', 'aiff'),
                        'flac': ('wav', 'aif', 'aiff')}

source_dir = None
dest_dir = None

def parse_options():
    usage = "usage: \%prog [options] srcdir destdir"
    parser = OptionParser(usage=usage, version='%prog 0.0')
    parser.add_option('-f', '--format', default='ogg',
            help="Output format [default=%default]")
    parser.add_option('-e', '--ext', default=None,
            help="comma-separated list of file extensions to process")
    parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
            help="Print encoder messages to stdout (default).")
    parser.add_option('-q', '--quiet', action='store_false', dest='verbose',
            help="Suppress normal output (default: unset).")
    parser.set_defaults(verbose=True)
    global options
    (options, args) = parser.parse_args()

    if options.format not in enc_commands.keys():
        parser.error("""Given output format unknown.\n
Sorry, I don't know how to encode to %s.""" % options.format)

    if len(args) != 2:
        parser.error("""Incorrect number of arguments.
You have to supply a source and a destination directory.""")
    else:
        global source_dir, dest_dir
        source_dir, dest_dir = args

    if not options.ext:
        options.ext = valid_input_formats[options.format]
    elif isinstance(options.ext, basestring):
        options.ext = options.ext.split(',')

    for ext in options.ext[:]:
        if ext not in valid_input_formats[options.format]:
            print """Don't know how to convert %s to %s.
Ignoring this filetype.""" % (ext, options.format)
            options.ext.remove(ext)
    if not options.ext:
        parser.error("""List of filetypes to process is empty. Nothing to do.""")

    if not os.path.isdir(source_dir):
        parser.error("Source path is not a directory.")
    if not os.path.isdir(dest_dir):
        os.makedirs(dest_dir)
        print "Created destination directory %s." % dest_dir

def encode(filename):
    dest_filename = os.path.splitext(filename)[0] + '.%s' % options.format
    dest_filename = dest_filename.replace(source_dir, dest_dir)
    command = enc_commands[options.format] % \
              { 'source': filename, 'dest': dest_filename }
    if not os.path.isdir(os.path.dirname(dest_filename)):
        os.makedirs(os.path.dirname(dest_filename))
    retval = subprocess.call(command.split())
    if retval:
        sys.stderr.write("""Error processing file %s.
Trying next one.""" % filename)

def main():
    parse_options()
    tree = os.walk(source_dir)
    for dirpath, dirnames, filenames in tree:
        print "Entering %s" % dirpath
        files = []
        for ext in options.ext:
            pattern = os.path.join(dirpath, '*.%s' % ext)
            files = glob.glob(pattern)
            for filename in (os.path.abspath(f) for f in files):
                encode(filename)

if __name__ == '__main__':
    main()

