VocalEasel/mma/MMA/main.py

351 lines
8.8 KiB
Python
Raw Normal View History

2006-11-10 08:07:56 +00:00
# main.py
"""
The program "MMA - Musical Midi Accompaniment" and the associated
modules distributed with it are protected by copyright.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2007-04-29 06:47:40 +00:00
Bob van der Poel <bob@mellowood.ca>
2006-11-10 08:07:56 +00:00
"""
import os
2009-05-17 22:34:44 +00:00
import time
2006-11-10 08:07:56 +00:00
import MMA.midi
import MMA.parse
2009-05-17 22:34:44 +00:00
import MMA.file
2006-11-10 08:07:56 +00:00
import MMA.options
2009-05-17 22:34:44 +00:00
import MMA.auto
import MMA.docs
import gbl
from MMA.common import *
from MMA.lyric import lyric
2006-11-10 08:07:56 +00:00
########################################
########################################
# This is the program mainline. It is called/executed
# exactly once from a call in the stub program mma.py.
###########################
# Get our command line stuff
MMA.options.opts()
"""
2007-04-29 06:47:40 +00:00
LibPath and IncPath are set in MMA.globals. Debug setting isn't set
when the default is done.
2006-11-10 08:07:56 +00:00
"""
if gbl.debug:
2007-04-29 06:47:40 +00:00
print "Initialization has set LibPath set to", gbl.libPath
print "Initialization has set IncPath set to", gbl.incPath
2006-11-10 08:07:56 +00:00
#######################################
# Set up initial meta track stuff. Track 0 == meta
m = gbl.mtrks[0] = MMA.midi.Mtrk(0)
m.addText(0, "Created by MMA.")
m.addTrkName(0, 'MetaTrack')
m.addTempo(0, gbl.tempo)
MMA.parse.setTimeSig(['4','4']) # most stdlib files will override this
#####################################
# Read an RC file. All found files are processed.
2009-05-17 22:34:44 +00:00
docOption = gbl.createDocs # Disable doc printing for RC file
gbl.createDocs = 0
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
#rcread=0
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
rcfiles = ('mmarc', 'c:\\mma\\mmarc', '~/.mmarc', '/usr/local/etc/mmarc', '/etc/mmarc' )
2006-11-10 08:07:56 +00:00
if gbl.mmaRC:
2007-04-29 06:47:40 +00:00
rcfiles = [ gbl.mmaRC ]
2006-11-10 08:07:56 +00:00
for i in rcfiles:
2009-05-17 22:34:44 +00:00
f = MMA.file.locFile(i, None)
2007-04-29 06:47:40 +00:00
if f:
if gbl.showrun:
print "Reading RC file '%s'" % f
MMA.parse.parseFile(f)
2009-05-17 22:34:44 +00:00
#rcread+=1
2007-04-29 06:47:40 +00:00
break
else:
if gbl.mmaRC:
error("Specified init file '%s' not found" % gbl.mmaRC)
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
else: #if not rcread:
2007-04-29 06:47:40 +00:00
gbl.lineno = -1
warning("No RC file was found or processed")
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
gbl.createDocs = docOption # Restore doc options
2006-11-10 08:07:56 +00:00
################################################
# Update the library database file(s) (-g option)
# Note: This needs to be here, after reading of RC files
if gbl.makeGrvDefs:
2007-04-29 06:47:40 +00:00
if gbl.infile:
error("No filename is permitted with the -g option")
2009-05-17 22:34:44 +00:00
MMA.auto.libUpdate() # update and EXIT
2006-11-10 08:07:56 +00:00
################################
# We need an input file for anything after this point.
if not gbl.infile:
2007-04-29 06:47:40 +00:00
MMA.options.usage("No input filename specified.")
2006-11-10 08:07:56 +00:00
# Add filename to meta track.
gbl.mtrks[0].addText(0, "Input filename: %s" % gbl.infile)
################################
# Just extract docs (-Dx) to stdout.
if docOption:
2009-05-17 22:34:44 +00:00
f=MMA.file.locFile(gbl.infile, None)
2007-04-29 06:47:40 +00:00
if not f:
error("File '%s' not found" % gbl.infile)
MMA.parse.parseFile(f)
sys.exit(0)
2006-11-10 08:07:56 +00:00
#########################################################
# These cmdline options override settings in RC files
if gbl.cmdSMF:
2007-04-29 06:47:40 +00:00
gbl.lineno = -1
MMA.parse.setMidiFileType(['SMF=%s' % gbl.cmdSMF])
2006-11-10 08:07:56 +00:00
##########################################
# Create the output filename.
# If outfile was specified on cmd line then leave it alone.
2007-04-29 06:47:40 +00:00
# Otherwise ...
# 1. strip off the extension if it is .mma,
# 2. append .mid
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
if gbl.playFile and gbl.outfile:
error("You cannot use the -f option with -P")
2006-11-10 08:07:56 +00:00
if gbl.outfile:
2007-04-29 06:47:40 +00:00
outfile = gbl.outfile
2009-05-17 22:34:44 +00:00
elif gbl.playFile:
outfile = "MMAtmp%s.mid" % os.getpid()
2006-11-10 08:07:56 +00:00
else:
2007-04-29 06:47:40 +00:00
outfile, ext = os.path.splitext(gbl.infile)
if ext != gbl.ext:
outfile=gbl.infile
outfile += '.mid'
2006-11-10 08:07:56 +00:00
outfile=os.path.expanduser(outfile)
################################################
# Read/process files....
# First the mmastart files
for f in gbl.mmaStart:
2009-05-17 22:34:44 +00:00
fn = MMA.file.locFile(f, gbl.incPath)
2007-04-29 06:47:40 +00:00
if not fn:
warning("MmaStart file '%s' not found/processed" % fn)
MMA.parse.parseFile(fn)
gbl.lineno = -1
2006-11-10 08:07:56 +00:00
# The song file specified on the command line
2009-05-17 22:34:44 +00:00
f = MMA.file.locFile(gbl.infile, None)
2006-11-10 08:07:56 +00:00
if not f:
2007-04-29 06:47:40 +00:00
gbl.lineno = -1
error("Input file '%s' not found" % gbl.infile)
2006-11-10 08:07:56 +00:00
MMA.parse.parseFile(f)
# Finally, the mmaend files
for f in gbl.mmaEnd:
2009-05-17 22:34:44 +00:00
fn = MMA.file.locFile(f, None)
2007-04-29 06:47:40 +00:00
if not fn:
warning("MmaEnd file '%s' not found/processed" % f)
MMA.parse.parseFile(fn)
2006-11-10 08:07:56 +00:00
#################################################
# Just display the channel assignments (-c) and exit...
if gbl.chshow:
2007-04-29 06:47:40 +00:00
print "\nFile '%s' parsed, but no MIDI file produced!" % gbl.infile
print
print "Tracks allocated:"
k=gbl.tnames.keys()
k.sort()
max=0
for a in k + gbl.deletedTracks:
if len(a)>max:
max = len(a)
max+=1
wrap=0
for a in k:
wrap += max
if wrap>60:
wrap = max
print
print " %-*s" %( max, a),
print
print
if gbl.deletedTracks:
print "Deleted Tracks:"
wrap=0
for a in gbl.deletedTracks:
wrap += max
if wrap>60:
wrap=max
print
print " %-*s" %( max,a),
print
print
print "Channel assignments:"
for c, n in sorted(gbl.midiAssigns.items()):
if n:
wrap = 3
print " %2s" % c,
for nn in n:
wrap += max
if wrap>63:
print "\n ",
wrap=max+3
print "%-*s" % (max,nn),
print
print
sys.exit(0)
2006-11-10 08:07:56 +00:00
####################################
# Dry run, no output
if gbl.noOutput:
2007-04-29 06:47:40 +00:00
warning( "Input file parsed successfully. No midi file generated")
sys.exit(0)
2006-11-10 08:07:56 +00:00
##############################
# Create the output (MIDI) file
2007-04-29 06:47:40 +00:00
gbl.lineno=-1 # disable line nums for error/warning
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00
2006-11-10 08:07:56 +00:00
""" We fix the outPath now. This lets you set outpath in the song file.
The filename "outfile" was created above. It is either the input filename
with '.mma' changed to '.mid' OR if -f<FILE> was used then it's just <FILE>.
If any of the following is true we skip inserting the outputpath into the
filename:
- if outfile starts with a '/'
- if outPath was not set
- if -f was used
Next, the outPath is inserted into the filename. If outPath starts with
a ".", "/" or "\ " then it is inserted at the start of the path;
otherwise it is inserted before the filename portion.
"""
2009-05-17 22:34:44 +00:00
if (not outfile.startswith('/')) and gbl.outPath and not gbl.outfile and not gbl.playFile:
2007-04-29 06:47:40 +00:00
if gbl.outPath[0] in '.\\/':
outfile = "%s/%s" % (gbl.outPath, outfile)
else:
head, tail = os.path.split(outfile)
outfile = "%s/%s/%s" % (head, gbl.outPath, tail)
2006-11-10 08:07:56 +00:00
fileExist = os.path.exists(outfile)
""" Check if any pending midi events are still around. Mostly
this will be a DRUM event which was assigned to the 'DRUM'
track, but no DRUM track was used, just DRUM-xx tracks used.
"""
for n in gbl.tnames.values():
2007-04-29 06:47:40 +00:00
if n.channel:
n.doMidiClear()
n.clearPending()
2009-05-17 22:34:44 +00:00
n.doChannelReset()
2007-04-29 06:47:40 +00:00
if n.riff:
warning("%s has pending Riff(s)" % n.name)
2006-11-10 08:07:56 +00:00
""" Check all the tracks and find total number used. When
initializing each track (class) we made an initial entry
in the track at offset 0 for the track name, etc. So, if the
track only has one entry we can safely skip the entire track.
"""
2007-04-29 06:47:40 +00:00
trackCount=1 # account for meta track
2006-11-10 08:07:56 +00:00
2007-04-29 06:47:40 +00:00
for n in sorted(gbl.mtrks.keys())[1:]: # check all but 0 (meta)
if len(gbl.mtrks[n].miditrk) > 1:
trackCount += 1
2006-11-10 08:07:56 +00:00
if trackCount == 1: # only meta track
2007-04-29 06:47:40 +00:00
if fileExist:
print
print "No data created. Did you remember to set a groove/sequence?"
if fileExist:
print "Existing file '%s' has not been modified." % outfile
sys.exit(1)
2006-11-10 08:07:56 +00:00
lyric.leftovers()
if fileExist:
2007-04-29 06:47:40 +00:00
print "Overwriting existing",
2006-11-10 08:07:56 +00:00
else:
2007-04-29 06:47:40 +00:00
print "Creating new",
2009-05-17 22:34:44 +00:00
print "midi file (%s bars, %.2f min): '%s'" % (gbl.barNum, gbl.totTime, outfile)
2006-11-10 08:07:56 +00:00
try:
2007-04-29 06:47:40 +00:00
out = file(outfile, 'wb')
2006-11-10 08:07:56 +00:00
except:
2007-04-29 06:47:40 +00:00
error("Can't open file '%s' for writing" % outfile)
2006-11-10 08:07:56 +00:00
MMA.midi.writeTracks(out)
out.close()
2009-05-17 22:34:44 +00:00
if gbl.playFile:
print "Playing %s with %s" % (outfile, gbl.midiPlayer)
t=time.time()
os.system("%s %s" % (gbl.midiPlayer, outfile))
os.remove(outfile)
print "Play complete (%.2f min), file has been deleted." % ((time.time()-t)/60)
2006-11-10 08:07:56 +00:00
if gbl.debug:
2007-04-29 06:47:40 +00:00
print "Completed processing file '%s'." % outfile
2006-11-10 08:07:56 +00:00
2009-05-17 22:34:44 +00:00