mirror of
				https://github.com/kastdeur/pipeband-music.git
				synced 2025-10-31 02:16:34 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			277 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			277 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| 
 | |
| ## Generate pdf form lilypond file
 | |
| ## by using standard command
 | |
| ##
 | |
| ## Most of programming was done by Sven Axelsson, http://svenax.net/
 | |
| 
 | |
| import io, os
 | |
| from argparse import ArgumentParser
 | |
| 
 | |
| class MakeDrum:
 | |
| 	LILYPOND = 'lilypond'
 | |
| 	VERSION  = '0.9.7'
 | |
| 	MASTER_DIR = os.path.dirname(os.path.abspath(__file__))
 | |
| 	RUN_DIR = os.path.abspath(os.curdir)
 | |
| 	TMP_DIR  = 'tmp'
 | |
| 	TMP_PREFIX = 'tmp_'
 | |
| 	OUT_DIR = '.'
 | |
| 
 | |
| 	def __init__(self):
 | |
| 		# Gather options and create the template file
 | |
| 		usage = __file__
 | |
| 		parser = ArgumentParser(usage)
 | |
| 
 | |
| 		parser.add_argument('--version',
 | |
| 			action='store_true', dest='show_version', default=False,
 | |
| 			help='show makeDrum version and exit')
 | |
| 		parser.add_argument('--lilyversion',
 | |
| 			action='store_true', dest='show_lilyversion', default=False,
 | |
| 			help='show Lilypond version and exit')
 | |
| 		parser.add_argument('-l', '--lilycommand',
 | |
| 			default=self.LILYPOND, dest='lilypond',
 | |
| 			help='Command used to compile')
 | |
| 			
 | |
| 
 | |
| 		parser.add_argument('-i', '--include',
 | |
| 			dest='includes', nargs='*', default=[],action='append',
 | |
| 			help='Include the specified file for compiling')
 | |
| 		parser.add_argument('-I', '--path-include',
 | |
| 			dest='search_paths', nargs='*', default=[], action='append',
 | |
| 			help='Paths for lilypond to search through while compiling')
 | |
| 
 | |
| 		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='18',
 | |
| 			help='Staff size. Default: 18pt.')
 | |
| 		parser.add_argument('-w', '--view-spacing',
 | |
| 			action='store_true', dest='view_spacing', default=False,
 | |
| 			help='Turn on "Paper.annotatespacing".')
 | |
| 
 | |
| 		parser.add_argument('--rename',
 | |
| 			action='store_true', dest='rename', default=False,
 | |
| 			help='Rename the final output to it\'s relative location, replacing /\'s with -\'s')
 | |
| 		parser.add_argument('-r', '--suffix',
 | |
| 			dest='suffix', default='',
 | |
| 			help='String added at end of pdf\'s filename')
 | |
| 		parser.add_argument('-g', '--generated',
 | |
| 			dest='gen_out', default=self.TMP_DIR,
 | |
| 			help='Put generated lilyfiles in $gen_out')
 | |
| 		parser.add_argument('-q', '--self-compilable', default=False,
 | |
| 			action='store_true', dest='compilable',
 | |
| 			help='Make a self compilable file')
 | |
| 		parser.add_argument('--no-compile', default=True,
 | |
| 			action='store_false', dest='compile',
 | |
| 			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=self.OUT_DIR,
 | |
| 			help='Output dir, for lilypond. If it doesn\'t exist, try to create it')
 | |
| 		parser.add_argument('music_file',
 | |
| 			default='', nargs='*',
 | |
| 			help='file to process')
 | |
| 		parser.add_argument('-@', '--list_file',
 | |
| 			dest='list_file', default='',
 | |
| 			help='list of files to process')
 | |
| 
 | |
| 		# All unknown args are passed on to the lilypond command
 | |
| 		self.args, self.unknownargs = parser.parse_known_args()
 | |
| 
 | |
| 		if self.args.show_version:
 | |
| 			print(__name__, ' ', self.VERSION)
 | |
| 			return
 | |
| 
 | |
| 		if self.args.show_lilyversion:
 | |
| 			print(os.system(self.LILYPOND+' --version'))
 | |
| 			return
 | |
| 
 | |
| 		if self.args.view_spacing:
 | |
| 			self.args.view_spacing = "##t"
 | |
| 		else:
 | |
| 			self.args.view_spacing = "##f"
 | |
| 
 | |
| 		# Input files
 | |
| 		if self.args.list_file != '':
 | |
| 			with io.open(self.args.list_file, 'r', encoding='utf8') as list_file:
 | |
| 				for line in list_file.readlines():
 | |
| 					self.args.music_file.append(line)
 | |
| 
 | |
| 		# Check for files
 | |
| 		if not self.args.music_file:
 | |
| 			parser.print_usage()
 | |
| 			return
 | |
| 
 | |
| 		# Check for files to include
 | |
| 		self.args.includes = [el for elements in self.args.includes for el in elements]
 | |
| 
 | |
| 		# Clean up of files
 | |
| 		self.remove_tmp_dir = self.args.clean
 | |
| 
 | |
| 		if not os.path.exists(os.path.join(os.path.curdir, self.TMP_DIR)):
 | |
| 			try: os.makedirs(os.path.join(os.path.curdir, self.TMP_DIR))
 | |
| 			except:
 | |
| 				print('Seems like no temporary directory can be created')
 | |
| 				return
 | |
| 		if not os.path.exists(os.path.join(os.path.curdir, self.args.out_dir)):
 | |
| 			try: os.makedirs(os.path.join(os.path.curdir, self.args.out_dir))
 | |
| 			except:
 | |
| 				print('Seems like no output directory can be created')
 | |
| 				return
 | |
| 
 | |
| 		for file_path in self.args.music_file:
 | |
| 			self.processit(self.TMP_DIR, os.path.join(self.RUN_DIR, file_path), self.args.gen_out, self.args.compile)
 | |
| 
 | |
| 		if not os.listdir(self.TMP_DIR):
 | |
| 			os.rmdir(self.TMP_DIR)
 | |
| 
 | |
| 
 | |
| 	def processit(self, tmp_dir, file, gen_out, compile):
 | |
| 		print ('Generating for ',file, end=' ', flush=True)
 | |
| 		tmp_file = self.maketemplate(tmp_dir, file, self.args.compilable)
 | |
| 		print ('[OK]')
 | |
| 
 | |
| 
 | |
| 		if gen_out is not None and gen_out != 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, 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 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()
 | |
| 
 | |
| 			# stringify search paths
 | |
| 			#TODO: this is ugly code
 | |
| 			paths = ' -I '.join(str(x)[1:-1] for x in self.args.search_paths)
 | |
| 			if paths:
 | |
| 			    paths = ' -I ' + paths
 | |
| 
 | |
| 			if self.args.rename:
 | |
| 			    lilyout = os.path.join(self.RUN_DIR, self.args.out_dir, os.path.basename(tmp_file).replace(self.TMP_PREFIX, '').rsplit( ".", 1 )[ 0 ])
 | |
| 			else:
 | |
| 			    lilyout = os.path.basename(file).rsplit( ".", 1 )[ 0 ]
 | |
| 
 | |
| 
 | |
| 			unknownargs = " " + " ".join(self.unknownargs)
 | |
| 
 | |
| 			lilycmd = self.LILYPOND + unknownargs + paths + ' --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)
 | |
| 					if not self.args.compilable:
 | |
| 						os.remove(tmp_file)
 | |
| 
 | |
| 
 | |
| 	def maketemplate(self, tmp_dir, file, compilable):
 | |
| 
 | |
| 		lily_includes = ''
 | |
| 
 | |
| 		# set up a tmp file with template and file combined
 | |
| 		tmp_file = os.path.join(tmp_dir, self.TMP_PREFIX + os.path.relpath(file).replace('../','').replace('music/','',1).replace('/', '-')[:-3] + self.args.suffix + '.ly')
 | |
| 
 | |
| 		# Make the file
 | |
| 		with io.open(tmp_file, 'w+', encoding='utf8') as out_file:
 | |
| 
 | |
| 			def printline(line, relpath = file):
 | |
| 
 | |
| 				# Check if there's an include in the line, if there is try to copy it all (Recursive)
 | |
| 				if line.startswith(u'\\include'):
 | |
| 					# Rewrite includes to absolute location of file
 | |
| 					incline = line.replace('\\include', '').strip('"\'\n ')
 | |
| 					printline(u"\n %%%% \"{}\"\n".format(incline))
 | |
| 
 | |
| 					# Only rewrite if it begins with a dot
 | |
| 					# if / it's absolute, and something else means search_path
 | |
| 					if incline.startswith('.'): #
 | |
| 						incline = os.path.join(os.path.abspath(os.path.dirname(relpath)), incline)
 | |
| 
 | |
| 					if compilable:
 | |
| 						try:
 | |
| 							inc_file = io.open(incline,'r',encoding='utf8')
 | |
| 						except IOError:
 | |
| 							out_file.write(line + "%% Error to copy %%\n")
 | |
| 							return
 | |
| 						with inc_file:
 | |
| 							for subline in inc_file.readlines():
 | |
| 								printline(subline, incline)
 | |
| 					else:
 | |
| 						out_file.write(u"\\include \""+incline+"\"\n")
 | |
| 					return
 | |
| 
 | |
| 				out_file.write(line.replace('\r', ''))
 | |
| 
 | |
| 			# Go do things with it
 | |
| 			printline(u'\ufeff')
 | |
| 
 | |
| 			printline(
 | |
| u"""% Generated from """+file+""" by """+__file__+""" version """+self.VERSION+"""
 | |
| \\version "2.18.0"
 | |
| 
 | |
| #(ly:set-option 'point-and-click #f)
 | |
| %\layout {
 | |
| % \context {
 | |
| %   \Score {
 | |
| %	 \override NonMusicalPaperColumn #'line-break-permission = ##f
 | |
| %   }
 | |
| % }
 | |
| %}
 | |
| """)
 | |
| 			for f in self.args.includes:
 | |
| 				printline(u"\n")
 | |
| 				printline(u"\\include \"{}\"".format(f), self.RUN_DIR+'/build')
 | |
| 
 | |
| 			printline(u"""
 | |
| #(set-global-staff-size """+self.args.staffsize+""")
 | |
| #(set-default-paper-size \""""+self.args.papersize+"""\" '"""+self.args.orientation+""")
 | |
| 
 | |
| % The tune to generate.
 | |
| """)
 | |
| 
 | |
| 			# Read lily file into tmp file
 | |
| 			with io.open(file, 'r', encoding='utf8') as in_file:
 | |
| 				for line in in_file.readlines():
 | |
| 					if line.startswith(u'\ufeff'): continue
 | |
| 
 | |
| 					printline(line)
 | |
| 		# Return tmp_file_path
 | |
| 		return tmp_file
 | |
| 
 | |
| MakeDrum();
 | 
