VocalEasel/mma/MMA/main.py

340 lines
8.6 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
2006-11-10 08:07:56 +00:00
import MMA.midi
2011-07-26 22:49:39 +00:00
import MMA.midifuncs
2006-11-10 08:07:56 +00:00
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
2011-07-26 22:49:39 +00:00
import MMA.paths
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)
2011-07-26 22:49:39 +00:00
if gbl.infile:
fileName=MMA.file.locFile(gbl.infile, None)
if fileName: # needed for certain doc commands.
m.addTrkName(0, "%s" % fileName.rstrip(".mma") )
m.addText(0, "Created by MMA. Input filename: %s" % fileName)
m.addTempo(0, gbl.tempo) # most user files will override this
MMA.midifuncs.setTimeSig(['4','4']) # most stdlib (and/or user) files will override this
2006-11-10 08:07:56 +00:00
#####################################
# 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:
2011-07-26 22:49:39 +00:00
if gbl.debug:
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
################################
2011-07-26 22:49:39 +00:00
# Just extract docs (-Dxh, etc) to stdout.
2006-11-10 08:07:56 +00:00
if docOption:
2011-07-26 22:49:39 +00:00
if docOption == 4:
MMA.docs.htmlGraph(gbl.infile)
else:
f=MMA.file.locFile(gbl.infile, None)
if not f:
error("File '%s' not found" % gbl.infile)
MMA.parse.parseFile(f)
MMA.docs.docDump()
2007-04-29 06:47:40 +00:00
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
2011-07-26 22:49:39 +00:00
MMA.midifuncs.setMidiFileType(['SMF=%s' % gbl.cmdSMF])
2006-11-10 08:07:56 +00:00
2011-07-26 22:49:39 +00:00
######################################
# Create the output filename
2006-11-10 08:07:56 +00:00
2011-07-26 22:49:39 +00:00
MMA.paths.createOutfileName(".mid")
2006-11-10 08:07:56 +00:00
################################################
# 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.
2011-07-26 22:49:39 +00:00
The filename "outfile" was created in paths, get a copy.
It is either the input filename with '.mma' changed to '.mid' (or kar)
OR if -f<FILE> was used then it's just <FILE>.
2006-11-10 08:07:56 +00:00
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.
"""
2011-07-26 22:49:39 +00:00
outfile = MMA.paths.outfile
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:
2011-07-26 22:49:39 +00:00
import MMA.player
MMA.player.playMidi(outfile)
2009-05-17 22:34:44 +00:00
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