More adjustments:
[orchestrallily.git] / generate_oly_score.py
blob4ce1e1ad9bca1f5011be443e89dd8ee477086ebe
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 import sys
5 import os
6 import os.path
7 import getopt
8 import re
9 import filecmp
10 import string
12 program_name = 'generate_oly_score'
13 settings_file = 'oly_structure.def'
14 output_dir = ''
15 script_path = os.path.dirname(__file__)
16 basename = ""
18 ######################################################################
19 # Options handling
20 ######################################################################
22 help_text = r"""Usage: %(program_name)s [OPTIONS]... [DEF-FILE]
23 Create a complete file structure for a score using OrchestralLily.
24 If no definitions file it given, the file oly_structure.def is used
26 Options:
27 -h, --help print this help
28 -o, --output=NAME write tely doc to NAME (default: read from settings or current directory)
29 """
31 def help (text):
32 sys.stdout.write ( text)
33 sys.exit (0)
35 (options, files) = getopt.getopt (sys.argv[1:], 'ho:',
36 ['help', 'output='])
38 for opt in options:
39 o = opt[0]
40 a = opt[1]
41 if o == '-h' or o == '--help':
42 help (help_text % vars ())
43 #elif o == '-s' or o == '--settings':
44 #settings_file = a
45 elif o == '-o' or o == '--output':
46 output_dir = a
47 else:
48 raise Exception ('unknown option: ' + o)
50 if files:
51 settings_file = files[0]
54 ######################################################################
55 # Settings loading
56 ######################################################################
58 def load_settings (file_name):
59 global output_dir, basename;
60 try:
61 in_f = open (file_name)
62 s = in_f.read()
63 in_f.close()
64 settings_expr = eval(s);
65 except IOError:
66 print ("Unable to load settings file '%s'. Exiting..." % file_name)
67 exit (-1);
68 except SyntaxError as ex:
69 print ex;
70 print ("Unable to interpret settings file '%s', it's syntax is invalid. Exiting..." % file_name);
71 exit (-1);
73 basename = settings_expr.get ("basename", "Score")
74 if not output_dir:
75 output_dir = settings_expr.get ("output_dir", output_dir) + "/";
76 return settings_expr;
79 ######################################################################
80 # File Writing
81 ######################################################################
83 def write_file (file_name, contents):
84 fn = file_name
85 if os.path.exists (file_name):
86 fn += ".new"
88 dir = os.path.dirname (fn);
89 if not os.path.exists (dir):
90 os.mkdir (dir)
92 try:
93 out_f = open (fn, "w")
94 s = out_f.write(contents)
95 out_f.close()
96 except IOError:
97 print ("Unable to write to output file '%s'. Exiting..." % fn)
98 exit (-1);
100 # If the file already existed, check if the new file is identical.
101 if (fn != file_name):
102 if filecmp.cmp (fn, file_name):
103 os.unlink (fn);
104 else:
105 print ("A file %s already existed, created new file %s." % (file_name, fn))
109 ######################################################################
110 # Templates
111 ######################################################################
113 def init_replacements (settings):
114 rep = settings.copy ();
115 del rep["parts"];
116 del rep["instruments"];
117 del rep["lyrics"];
118 del rep["scores"];
120 return rep
123 ######################################################################
124 # Templates
125 ######################################################################
127 template_names = {
128 "Makefile": "Makefile",
130 "movement": "TEMPLATE_Include_Movement.ily",
131 "snippet_def_lyrics": "TEMPLATE_Snippet_DefinitionLyrics.ily",
132 "snippet_def_music": "TEMPLATE_Snippet_DefinitionMusic.ily",
133 "snippet_def_include": "TEMPLATE_Snippet_DefinitionInclude.ily",
135 "settings": "TEMPLATE_Settings.ily",
136 "settings_global": "TEMPLATE_Settings_Global.ily",
137 "settings_fullscore": "TEMPLATE_Settings_FullScore.ily",
138 "settings_instrument": "TEMPLATE_Settings_Instrument.ily",
139 "settings_vocal": "TEMPLATE_Settings_Vocal.ily",
141 "snippet_part_score": "TEMPLATE_Snippet_PartScore.ily",
143 "score_full": "TEMPLATE_Score_FullScore.ly",
144 "score_instrument": "TEMPLATE_Score_Instrument.ly",
145 "score_vocal": "TEMPLATE_Score_VocalVoice.ly",
147 #"itex_about": "TEXTEMPLATE_Include_About.tex",
148 #"itex_contents": "TEXTEMPLATE_Include_ContentsMaterial.tex",
149 #"itex_leben": "TEXTEMPLATE_Include_Leben.tex",
150 #"itex_text": "TEXTEMPLATE_Include_Text.tex",
151 #"tex_choral": "TEXTEMPLATE_Score_ChoralScore.tex",
152 #"tex_instruments": "TEXTEMPLATE_Score_Instruments.tex",
153 #"tex_long": "TEXTEMPLATE_Score_LongScore.tex",
154 #"tex_orchestral": "TEXTEMPLATE_Score_OrchestralScore.tex",
155 #"tex_organ": "TEXTEMPLATE_Score_OrganScore.tex",
157 #"itex_snippet_textmovement": "TEXTEMPLATE_Snippet_TextMovement.itex",
158 #"itex_snippet_instrument": "TEXTEMPLATE_Snippet_Instrument.itex",
161 def load_file (file_name):
162 s = False;
163 try:
164 in_f = open (file_name, "rb")
165 s = in_f.read()
166 in_f.close()
167 except IOError:
168 print ("Unable to load file %s" % file_name);
169 return s
171 def load_templates (settings):
172 templates = {};
173 template_path = script_path + "/Templates/";
175 for id in template_names:
176 filename = template_names[id]
177 s = load_file (template_path + filename);
178 if s:
179 templates[id] = s
180 else:
181 print ("Unable to load template file %s (id %s).\n" % (filename, id));
182 return templates;
185 ######################################################################
186 # Creating settings files
187 ######################################################################
189 def generate_settings_files (settings, templates, replacements):
190 inc = "";
191 movements = settings.get ("parts", {});
192 for m in movements:
193 replacements["movement"] = m
194 replacements["movementname"] = movements[m]
195 inc += (templates["snippet_def_include"] % replacements)
196 del replacements["movement"];
197 del replacements["movementname"]
198 replacements["includefiles"] = inc
200 write_file (output_dir + basename + "_Settings.ily", templates["settings"] % replacements );
201 write_file (output_dir + basename + "_Settings_Global.ily", templates["settings_global"] % replacements );
203 if (settings.get("scores", [])):
204 write_file (output_dir + basename + "_Settings_FullScore.ily", templates["settings_fullscore"] % replacements );
205 if (settings.get("instruments", [])):
206 write_file (output_dir + basename + "_Settings_Instrument.ily", templates["settings_instrument"] % replacements );
207 else:
208 print ("WARNING: No instruments: %s" % settings.get("instruments", []));
209 if (settings.get("lyrics", [])):
210 write_file (output_dir + basename + "_Settings_Vocal.ily", templates["settings_vocal"] % replacements );
211 del replacements["includefiles"]
214 ######################################################################
215 # Creating movement files
216 ######################################################################
218 def generate_movement_files (settings, templates, replacements):
219 movements = settings.get ("parts", {});
220 instruments = settings.get ("instruments", []);
221 lyrics = settings.get ("lyrics", []);
222 if (movements == {}):
223 print ("No parts defined in settings file...");
224 exit (-1);
225 if (instruments == []):
226 print ("No instruments defined in settings file...");
227 exit (-1);
229 for m in movements:
230 replacements["movement"] = m
231 replacements["movementname"] = movements[m]
232 defs = ""
233 for i in instruments:
234 replacements["instrument"] = i
235 defs += (templates["snippet_def_music"] % replacements);
236 if (i in lyrics):
237 defs += (templates["snippet_def_lyrics"] % replacements);
238 del replacements["instrument"]
239 replacements["movementinstrumentdefinitions"] = defs
240 write_file (output_dir + basename + "_Part_" + m + ".ily", templates["movement"] % replacements);
241 del replacements["movement"]
242 del replacements["movementname"]
245 ######################################################################
246 # Creating instrumental score files
247 ######################################################################
249 def generate_instrument_files (settings, templates, replacements):
250 movements = settings.get ("parts", {});
251 instruments = settings.get ("instruments", []);
252 lyrics = settings.get ("lyrics", []);
254 for i in instruments:
255 replacements["instrument"] = i
256 defs = ""
257 for m in movements:
258 replacements["movement"] = m
259 replacements["movementname"] = movements[m]
260 defs += (templates["snippet_part_score"] % replacements);
261 del replacements["movement"]
262 del replacements["movementname"]
263 replacements["partlist"] = defs
264 if i in lyrics:
265 template = "score_vocal"
266 else:
267 template = "score_instrument"
268 write_file (output_dir + basename + "_Instrument_" + i + ".ly", templates[template] % replacements);
269 del replacements["instrument"]
272 ######################################################################
273 # Creating score files
274 ######################################################################
276 def generate_score_files (settings, templates, replacements):
277 movements = settings.get ("parts", {});
278 scores = settings.get ("scores", []);
280 for i in scores:
281 replacements["score"] = (i + "Score")
282 replacements["instrument"] = replacements["score"]
283 defs = ""
284 for m in movements:
285 replacements["movement"] = m
286 replacements["movementname"] = movements[m]
287 defs += (templates["snippet_part_score"] % replacements);
288 del replacements["movement"]
289 del replacements["movementname"]
290 replacements["partlist"] = defs
291 filename = output_dir + basename + "_Score_" + i + ".ly";
292 if i == "":
293 filename = output_dir + basename + "_Score.ly"
294 write_file (filename, templates["score_full"] % replacements);
295 del replacements["score"]
296 del replacements["instrument"]
298 #FullScoreTitle = "Partitur / FullScore"
299 #LongScoreTitle = "Partitur / FullScore"
300 #OrganScoreTitle = "Orgelauszug / Organ score"
301 #PianoScoreTitle = "Klavierauszug / Vocal score"
302 #ChoirScoreTitle = "Chorstimmen / Choir voices"
303 #SoloChoirScoreTitle = "Chorstimmen mit Soli / Choir voices with solo parts"
306 ######################################################################
307 # Creating Make files
308 ######################################################################
310 def generate_make_files (settings, templates, replacements):
311 movements = settings.get ("parts", {});
313 replacements["instruments"] = string.join (settings.get ("instruments", []));
314 replacements["scores"] = string.join (settings.get ("scores", []));
315 replacements["srcfiles"] = string.join (map ( lambda part: basename + "_Part_" + part + ".ily", movements));
317 write_file (output_dir + "Makefile", templates["Makefile"] % replacements);
319 del replacements["instruments"]
320 del replacements["scores"]
321 del replacements["srcfiles"]
322 return;
325 ######################################################################
326 # Link the orchestrallily package
327 ######################################################################
329 def generate_oly_link (settings, templates, replacements):
330 print ("Creating symlink %s to %s" % ("orchestrallily/", script_path))
331 try:
332 os.symlink ("../"+script_path, output_dir+"orchestrallily")
333 except OSError:
334 pass
336 ######################################################################
337 # Main function
338 ######################################################################
340 settings = load_settings (settings_file);
341 templates = load_templates (settings);
342 replacements = init_replacements (settings);
344 generate_settings_files (settings, templates, replacements);
345 generate_movement_files (settings, templates, replacements);
346 generate_instrument_files (settings, templates, replacements);
347 generate_score_files (settings, templates, replacements);
348 #generate_tex_files (settings, templates, replacements);
349 generate_make_files (settings, templates, replacements);
350 generate_oly_link (settings, templates, replacements);