#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- import sys import re import os, errno import time import argparse import subprocess from pprint import pprint def mkdir_p(path): try: os.makedirs(path) except OSError as exc: if exc.errno != errno.EEXIST: raise def Midi2Mp3(in_file, out_file, **kwargs): verbose = kwargs.get('verbose', 0) force = kwargs.get('force', 0) dry_run = kwargs.get('dry_run', False) timid_cmd = "timidity -Ow -o -" lame_cmd = "lame - " out_dir = os.path.dirname(out_file) if not os.path.exists(out_dir): if verbose > 2: print "Creating %s" % out_dir if not dry_run: mkdir_p(out_dir) if not force: if (os.path.exists(out_file) and os.path.getmtime(out_file) > os.path.getmtime(in_file)): if verbose > 1: print "%s is up to date" % out_file return False cmd = "%s %s | %s %s" % (timid_cmd, in_file, lame_cmd, out_file) if dry_run: print cmd else: if verbose: print cmd out = subprocess.check_output(cmd, shell=True) return True # Midi2Mp3 def RebuildMp3s(**kwargs): directories = kwargs.get('directories', 0) out_root = kwargs.get('output_directory', 0) errors = kwargs.get('errors', 0) prune = kwargs.get('prune', 0) verbose = kwargs.get('verbose', 0) count = kwargs.get('count', 0) nice = kwargs.get('nice', 0) dry_run = kwargs.get('dry_run', False) nice_count = 0 for dir_start in directories: if dir_start.endswith('/'): dir_start = dir_start[:-1] # having a trailing / screws up os.path.dirname parent_dir_start = os.path.dirname(dir_start) for root, dirs, files in os.walk(dir_start): #print root, dirs, files; continue base = os.path.basename(root) if verbose > 1: print "Entering:", root # look for any .mid files for f in files: if f.endswith('.mid'): nice_count += 1 in_file = os.path.join(root, f) if out_root == dir_start: out_file = in_file # extension gets changed below elif prune: tmp = re.sub('^'+parent_dir_start+'/', '', in_file) out_file = os.path.join(out_root, tmp) else: out_file = os.path.join(out_root, root, f) out_file = re.sub('/midi/', '/mp3/', out_file) out_file = re.sub('\.mid$', '.mp3', out_file) if Midi2Mp3(in_file, out_file, **kwargs): count -= 1 if count < 0: break # This sucker can eat Manhattan, so we pause every once in a while nice_count += 1 if nice_count % nice == 0: if verbose: print >>sys.stderr, "Pausing ..." time.sleep(1) # for each file in the directory # end os.walk() # end for all directories # RebuildMp3s if __name__ == "__main__": parser = argparse.ArgumentParser(description='walk directory tree and convert .mid to .mp3 as necessary') parser.add_argument('directories', metavar='file', nargs="+", help="one or more directories containing .mid files.") parser.add_argument('output_directory', nargs="?", help="directory to put resulting MP3s into. Created if necessary.") parser.add_argument('--nice', type=int, default=10000, help='sleep for 1 second after every N [10000] files.') parser.add_argument('--count', '-c', type=int, default=(2**30), help='number of files to process. default: all') parser.add_argument('-e', '--errors', dest='errors', default=False, action="store_true", help='print errors on exit.') parser.add_argument('-f', dest='force_rebuild', default=False, action="store_true", help='force rebuilding of everything.') parser.add_argument('-p', dest='prune', default=False, action='store_true', help='prune output directory name to basename of each input directory.') parser.add_argument('-v', dest='verbose', default=0, action='count', help='print verbose debugging information.') parser.add_argument('-n', dest='dry_run', default=False, action='store_true', help="dry run -- don't actually do anything.") args = vars(parser.parse_args()) if not args['output_directory']: args['output_directory'] = args['directories'][-1] if len(args['directories']) > 1: args['directories'] = args['directories'][:-1] #print args; 1/0 RebuildMp3s(**args)