pipeband-music/lilydrum/makedrum

256 lines
7.8 KiB
Python

#!/usr/bin/python3.4
## Generate pdf form lilypond file
## by using standard command
##
## Most of programming was done by Sven Axelsson, http://svenax.net/
import codecs, os
from argparse import ArgumentParser
class MakeDrum:
LILYPOND = 'lilypond'
VERSION = '0.9.5'
TMP_DIR = os.path.join(os.path.abspath(os.curdir),'tmp')
TMP_PREFIX = 'tmp_'
MASTER_DIR = os.path.dirname(os.path.abspath(__file__))
RUN_DIR = os.path.abspath(os.curdir)
def __init__(self):
parser = ArgumentParser(__file__)
parser.add_argument('--version', action='version', version=self.VERSION)
parser.add_argument('--lilyversion',
action='store_true', dest='show_lilyversion', default=False,
help='show Lilypond version and exit')
# options for inclusion of files
parser.add_argument('-x', '--drumfile',
dest='lilydrum', default='lilydrum.ly',
help='Use the specified file for drums')
parser.add_argument('-c', '--pipefile',
dest='lilypipe', default='bagpipe.ly',
help='Use the specified file for pipes')
parser.add_argument('-i', '--include',
dest='includes', nargs='*', default=[],action='append',
help='Include the specified file for compiling')
# options for lilypond
parser.add_argument('-p', '--paper-size',
dest='papersize', default='a4',
help='Paper size. Default: A4')
parser.add_argument('-o', '--orientation',
dest='orientation', default='landscape',
help='Paper orientation. Default: landscape')
parser.add_argument('-s', '--staff-size',
dest='staffsize', default='20',
help='Staff size. Default: 20pt.')
parser.add_argument('-w', '--view-spacing',
action='store_const', dest='view_spacing', default='##f', const='##t',
help='Turn on "Paper.annotatespacing".')
parser.add_argument('-l', '--line-break',
action='store_const', dest='line_break', default='##t', const='##f',
help='Turn off explicit linebreaks".')
# options for generating and compiling
parser.add_argument('-g','--generated',
dest='gen_out', default=self.TMP_DIR,
help='Put generated lilyfiles in $gen_out')
parser.add_argument('--no-compile',
action='store_false', dest='compile', default=True,
help='Do not compile generated Lilypond files')
parser.add_argument('--no-log',
action='store_false', dest='log', default=True,
help='Do not generate log files.')
parser.add_argument('--no-cleanup',
action='store_false', dest='clean', default=True,
help='Leave all temporary files in place')
parser.add_argument('-d', '--out_dir',
dest='out_dir', default='pdf',
help='Output dir for the lilypond process. If it doesn\'t exist, try to create it')
# the file(s) to process
parser.add_argument('music_file',
default='', nargs='*',
help='file to process')
parser.add_argument('-@', '--list_file',
dest='list_file', default='',
help='file containing the list of files to process')
self.args = parser.parse_args()
if self.args.show_lilyversion:
print(os.system(self.LILYPOND+' --version'))
return
# Input files
if self.args.list_file != '':
self.args.music_file.append(open(self.args.list_file, 'r').readlines())
close(self.args.list_file)
# Check if there are any files
if not self.args.music_file:
parser.print_usage()
return
# Check for inclusion options
self.args.includes = [el for elements in self.args.includes for el in elements]
# Whether to clean up tmp_dir if possible
self.remove_tmp_dir = self.args.clean
# are TMP_DIR, out_dir dirs?
if not os.path.exists(self.TMP_DIR):
try: os.makedirs(self.TMP_DIR)
except:
print('Seems like no temporary directory can be created')
return
if not os.path.exists(self.args.out_dir):
try: os.makedirs(self.args.out_dir)
except:
print('Seems like no output directory can be created')
return
# do the work!
for file_path in self.args.music_file:
self.process_it(file_path)
#if dir is empty:
#os.rmdir(self.TMP_DIR)
def process_it(self, file):
tmp_file = self.maketemplate(file)
if self.args.gen_out is not None and self.args.gen_out != self.TMP_DIR:
new_tmp_file = os.path.basename(tmp_file).replace(self.TMP_PREFIX, '');
print ('Moving ', tmp_file, ' to ', new_tmp_file, end=' ', flush=True)
gen_dir = os.path.join(self.RUN_DIR, self.args.gen_out);
# if not dir $gen_out, make it
if not os.path.exists(gen_dir):
try: os.makedirs(gen_dir)
except:
print('[Error]')
print(' ! Seems like the {} directory cannot be created'.format(gen_dir))
return
# mv file to dir, remove self.TMP_PREFIX
os.rename(tmp_file, os.path.join(gen_dir, new_tmp_file))
tmp_file = new_tmp_file
print('[OK]')
if self.args.compile:
if self.args.log:
logfile = os.path.join(self.TMP_DIR, os.path.relpath(file).replace(".ly", '').replace('/', '-')+'.log')
log = ' > '+logfile+' 2>&1'
else:
log = ''
print ('Compiling ', file, end=' ', flush=True)
if not self.args.log:
print()
lilyout = os.path.join(self.args.out_dir, os.path.basename(tmp_file).replace(self.TMP_PREFIX, '').replace(".ly", ''))
print (lilyout)
lilycmd = self.LILYPOND+' --pdf --output='+lilyout+' '+tmp_file+log
if os.system(lilycmd) != 0:
self.remove_tmp_dir = False
print ('[Error]')
if self.args.log:
print (' ! Did not compile, please see the log at ', logfile)
else :
print ('[OK]')
if self.args.clean:
#remove files
if self.args.log:
os.remove(logfile)
os.remove(tmp_file)
def maketemplate(self, file):
lily_includes = ''
include_drum_file = False
include_pipe_file = False
# find out whether drum, pipes, or full score
for ext in ['full', 'side', 'tenor', 'bass', 'drum', 'snare']:
if ext in file:
include_drum_file = True
break
for ext in ['full', 'pipes']:
if ext in file:
include_pipe_file = True
break
if include_drum_file:
self.args.includes.insert(0,self.args.lilydrum)
if include_pipe_file:
self.args.includes.insert(0, self.args.lilypipe)
for f in self.args.includes:
lily_includes = lily_includes + "\n\\include \"{}\"".format(f)
# Set up a tmp file with template and file combined
tmp_file = self.TMP_PREFIX + os.path.relpath(file).replace('/', '-').replace('..', '').replace('//','').lstrip('-')
tmp_file = os.path.join(self.TMP_DIR, tmp_file)
out_file = codecs.open(tmp_file, 'w+', 'utf8')
out_file.write(u'\ufeff')
# Write the file
out_file.write(
u"""% Generated from {filename} by {script} Version {version}
\\version "2.18.0"
#(ly:set-option 'point-and-click #f)
{lily_includes}
#(set-global-staff-size {staffsize})
#(set-default-paper-size \"{papersize}\" '{orientation})
\\paper {{
annotatespacing = {view_spacing}
}}
\layout {{
\context {{
\Score {{
\override NonMusicalPaperColumn #'line-break-permission = {line_break}
}}
}}
}}
% The tune to generate.
""".format(
filename=file,
script=__file__,
version=self.VERSION,
lily_includes=lily_includes,
staffsize=self.args.staffsize,
papersize=self.args.papersize,
orientation=self.args.orientation,
view_spacing=self.args.view_spacing,
line_break=self.args.line_break
)
)
# Read lily file into tmp file
music = codecs.open(file, 'r', 'utf8').read()
if music.startswith(u'\ufeff'): music = music[1:]
music = music.split(u'\n')
printit = 1
for line in music:
if line.startswith(u'\\include'):
if line.startswith(u'\\include "lilydrum.ly"'): continue
if line.startswith(u'\\include "bagpipe.ly"'): continue
# Rewrite includes to absolute location of file
incline = line.replace('\\include', '').strip('"\' ')
if not incline.startswith('\\'): #already absolute
incline = os.path.join(os.path.abspath(os.path.dirname(file)), incline)
line = "\\include \""+incline+"\""
if printit:
out_file.write(line.replace('\r', '')+'\n')
out_file.close()
# Return tmp_file_path
return tmp_file
if __name__ == "__main__":
MakeDrum();