1 # -*- coding: utf-8 -*-
13 from rational import Rational
15 # Store previously converted pitch for \relative conversion as a global state variable
17 relative_pitches = False
19 ly_dur = None # stores lilypond durations
21 def escape_instrument_string (input_string):
22 retstring = string.replace (input_string, "\"", "\\\"")
23 if re.match ('.*[\r\n]+.*', retstring):
24 rx = re.compile (r'[\n\r]+')
25 strings = rx.split (retstring)
26 retstring = "\\markup { \\center-column { "
28 retstring += "\\line {\"" + s + "\"} "
31 retstring = "\"" + retstring + "\""
34 class Output_stack_element:
36 self.factor = Rational (1)
38 o = Output_stack_element()
39 o.factor = self.factor
42 class Output_printer(object):
44 A class that takes care of formatting (eg.: indenting) a
45 Music expression as a .ly file.
51 self._file = sys.stdout
53 self._output_state_stack = [Output_stack_element()]
54 self._skipspace = False
55 self._last_duration = None
57 def set_file (self, file):
60 def dump_version (self, version):
61 self.print_verbatim ('\\version "' + version + '"')
64 def get_indent (self):
65 return self._nesting * self._indent
68 last = self._output_state_stack[-1]
69 self._output_state_stack.append (last.copy())
71 def add_factor (self, factor):
73 self._output_state_stack[-1].factor *= factor
76 del self._output_state_stack[-1]
77 if not self._output_state_stack:
80 def duration_factor (self):
81 return self._output_state_stack[-1].factor
83 def print_verbatim (self, str):
86 def unformatted_output (self, str):
87 # don't indent on \< and indent only once on <<
88 self._nesting += (str.count ('<')
89 - str.count ('\<') - str.count ('<<')
91 self._nesting -= (str.count ('>') - str.count ('\>') - str.count ('>>')
92 - str.count ('->') - str.count ('_>')
95 self.print_verbatim (str)
97 def print_duration_string (self, str):
98 if self._last_duration == str:
101 self.unformatted_output (str)
103 # def print_note_color (self, object, rgb=None):
105 # str = ("\\once\\override %s #'color = #(rgb-color %s # %s %s)" % (object, rgb[0], rgb[1], rgb[2]))
107 # str = "\\revert %s #'color" % object
112 def add_word (self, str):
113 if (len (str) + 1 + len (self._line) > self._line_len):
115 self._skipspace = True
117 if not self._skipspace:
119 self.unformatted_output (str)
120 self._skipspace = False
123 self._file.write (self._line + '\n')
124 self._line = ' ' * self._indent * self._nesting
125 self._skipspace = True
127 def skipspace (self):
128 self._skipspace = True
130 def __call__(self, arg):
133 def dump (self, str):
135 self._skipspace = False
136 self.unformatted_output (str)
138 # Avoid splitting quoted strings (e.g. "1. Wie") when indenting.
139 words = utilities.split_string_and_preserve_doublequoted_substrings(str)
151 self.duration_log = 0
153 self.factor = Rational(1)
155 def lisp_expression(self):
156 return '(ly:make-duration %d %d %d %d)' % (self.duration_log,
158 self.factor.numerator(),
159 self.factor.denominator())
161 def ly_expression(self, factor=None, scheme_mode=False):
162 global ly_dur # stores lilypond durations
166 if self.duration_log < 0:
168 longer_dict = {-1: "breve", -2: "longa"}
170 longer_dict = {-1: "\\breve", -2: "\\longa"}
171 dur_str = longer_dict.get(self.duration_log, "1")
173 dur_str = '%d' % (1 << self.duration_log)
174 dur_str += '.' * self.dots
176 if factor <> Rational(1, 1):
177 if factor.denominator() <> 1:
178 dur_str += '*%d/%d' % (factor.numerator(), factor.denominator())
180 dur_str += '*%d' % factor.numerator()
182 if dur_str.isdigit():
183 ly_dur = int(dur_str)
184 # TODO: We need to deal with dotted notes and scaled durations
185 # otherwise ly_dur won't work in combination with tremolos.
188 def print_ly(self, outputter):
189 dur_str = self.ly_expression(self.factor / outputter.duration_factor())
190 outputter.print_duration_string(dur_str)
193 return self.ly_expression()
198 d.duration_log = self.duration_log
199 d.factor = self.factor
202 def get_length(self):
203 dot_fact = Rational((1 << (1 + self.dots)) - 1,
206 log = abs(self.duration_log)
208 if self.duration_log < 0:
211 base = Rational(1, dur)
213 return base * dot_fact * self.factor
215 def set_create_midi(option):
217 Implement the midi command line option '-m' and '--midi'.
218 If True, add midi-block to .ly file (see L{musicexp.Score.print_ly}).
220 @param option: Indicates whether the midi-block has to be added or not.
221 @type option: boolean
226 def get_create_midi ():
228 Return, if exists the state of the midi-option.
230 @return: The state of the midi-option.
238 # implement the command line option '--transpose'
239 def set_transpose(option):
240 global transpose_option
241 transpose_option = option
243 def get_transpose(optType):
245 if(optType == "string"):
246 return '\\transpose c %s' % transpose_option
247 elif(optType == "integer"):
248 p = generic_tone_to_pitch(transpose_option)
251 if(optType == "string"):
253 elif(optType == "integer"):
256 # implement the command line option '--tab-clef'
257 def set_tab_clef(option):
258 global tab_clef_option
259 tab_clef_option = option
263 return ("tab", tab_clef_option)[tab_clef_option == "tab" or tab_clef_option == "moderntab"]
267 # definitions of the command line option '--string-numbers'
268 def set_string_numbers(option):
269 global string_numbers_option
270 string_numbers_option = option
272 def get_string_numbers():
274 return ("t", string_numbers_option)[string_numbers_option == "t" or string_numbers_option == "f"]
278 def generic_tone_to_pitch (tone):
289 tone_ = tone.strip().lower()
290 p.octave = tone_.count("'") - tone_.count(",")
291 tone_ = tone_.replace(",","").replace("'","")
292 p.step = ((ord (tone_[0]) - ord ('a') + 5) % 7)
293 p.alteration = accidentals_dict.get(tone_[1:], 0)
296 # Implement the different note names for the various languages
297 def pitch_generic (pitch, notenames, accidentals):
298 str = notenames[pitch.step]
299 halftones = int (pitch.alteration)
301 str += accidentals[0] * (-halftones)
302 elif pitch.alteration > 0:
303 str += accidentals[3] * (halftones)
304 # Handle remaining fraction to pitch.alteration (for microtones)
305 if (halftones != pitch.alteration):
306 if None in accidentals[1:3]:
307 ly.warning (_ ("Language does not support microtones contained in the piece"))
310 str += {-0.5: accidentals[1], 0.5: accidentals[2]}[pitch.alteration - halftones]
312 ly.warning (_ ("Language does not support microtones contained in the piece"))
315 def pitch_general (pitch):
316 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['es', 'eh', 'ih', 'is'])
317 return str.replace ('aes', 'as').replace ('ees', 'es')
319 def pitch_nederlands (pitch):
320 return pitch_general (pitch)
322 def pitch_english (pitch):
323 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['f', 'qf', 'qs', 's'])
324 return str.replace ('aes', 'as').replace ('ees', 'es')
326 def pitch_deutsch (pitch):
327 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['es', 'eh', 'ih', 'is'])
328 return str.replace ('hes', 'b').replace ('aes', 'as').replace ('ees', 'es')
330 def pitch_norsk (pitch):
331 return pitch_deutsch (pitch)
333 def pitch_svenska (pitch):
334 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', None, None, 'iss'])
335 return str.replace ('hess', 'b').replace ('aes', 'as').replace ('ees', 'es')
337 def pitch_italiano (pitch):
338 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', 'sb', 'sd', 'd'])
341 def pitch_catalan (pitch):
342 return pitch_italiano (pitch)
344 def pitch_francais (pitch):
345 str = pitch_generic (pitch, ['do', 'ré', 'mi', 'fa', 'sol', 'la', 'si'], ['b', 'sb', 'sd', 'd'])
348 def pitch_espanol (pitch):
349 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 's'])
352 def pitch_vlaams (pitch):
353 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 'k'])
356 def set_pitch_language (language):
357 global pitch_generating_function
359 "nederlands": pitch_nederlands,
360 "english": pitch_english,
361 "deutsch": pitch_deutsch,
362 "norsk": pitch_norsk,
363 "svenska": pitch_svenska,
364 "italiano": pitch_italiano,
365 "français": pitch_francais,
366 "catalan": pitch_catalan,
367 "espanol": pitch_espanol,
368 "español": pitch_espanol,
369 "vlaams": pitch_vlaams}
370 pitch_generating_function = function_dict.get (language, pitch_general)
372 # global variable to hold the formatting function.
373 pitch_generating_function = pitch_general
380 self._force_absolute_pitch = False
383 return self.ly_expression()
385 def transposed (self, interval):
387 c.alteration += interval.alteration
388 c.step += interval.step
389 c.octave += interval.octave
392 target_st = self.semitones() + interval.semitones()
393 c.alteration += target_st - c.semitones()
400 c.octave += c.step / 7
403 def lisp_expression (self):
404 return '(ly:make-pitch %d %d %d)' % (self.octave,
410 p.alteration = self.alteration
412 p.octave = self.octave
413 p._force_absolute_pitch = self._force_absolute_pitch
417 return self.step + self.octave * 7
419 def semitones (self):
420 return self.octave * 12 + [0, 2, 4, 5, 7, 9, 11][self.step] + self.alteration
422 def normalize_alteration (c):
423 if(c.alteration < 0 and [True, False, False, True, False, False, False][c.step]):
426 elif(c.alteration > 0 and [False, False, True, False, False, False, True][c.step]):
431 def add_semitones (self, number):
432 semi = number + self.alteration
436 sign = (1,-1)[semi < 0]
437 prev = self.semitones()
438 while abs((prev + semi) - self.semitones ()) > 1:
441 self.alteration += (prev + semi) - self.semitones ()
442 self.normalize_alteration ()
444 def ly_step_expression (self):
445 return pitch_generating_function (self)
447 def absolute_pitch (self):
449 return "'" * (self.octave + 1)
450 elif self.octave < -1:
451 return "," * (-self.octave - 1)
455 def relative_pitch (self):
456 global previous_pitch
457 if not previous_pitch:
458 previous_pitch = self
459 return self.absolute_pitch ()
460 previous_pitch_steps = previous_pitch.octave * 7 + previous_pitch.step
461 this_pitch_steps = self.octave * 7 + self.step
462 pitch_diff = (this_pitch_steps - previous_pitch_steps)
463 previous_pitch = self
465 return "'" * ((pitch_diff + 3) / 7)
466 elif pitch_diff < -3:
467 return "," * ((-pitch_diff + 3) / 7)
471 def ly_expression (self):
472 str = self.ly_step_expression ()
473 if relative_pitches and not self._force_absolute_pitch:
474 str += self.relative_pitch ()
476 str += self.absolute_pitch ()
479 def print_ly (self, outputter):
480 outputter (self.ly_expression())
485 self.start = Rational (0)
487 self.identifier = None
489 def get_length(self):
492 def get_properties (self):
495 def has_children (self):
498 def get_index (self):
500 return self.parent.elements.index (self)
504 return self.__class__.__name__
506 def lisp_expression (self):
509 props = self.get_properties ()
511 return "(make-music '%s %s)" % (name, props)
513 def set_start (self, start):
516 def find_first (self, predicate):
521 def print_comment (self, printer, text=None):
532 lines = string.split (text, '\n')
535 printer.unformatted_output ('% ' + l)
539 def print_with_identifier (self, printer):
541 printer ("\\%s" % self.identifier)
543 self.print_ly (printer)
545 def print_ly (self, printer):
546 printer (self.ly_expression ())
548 class MusicWrapper (Music):
552 def print_ly (self, func):
553 self.element.print_ly (func)
555 class ModeChangingMusicWrapper (MusicWrapper):
557 MusicWrapper.__init__ (self)
558 self.mode = 'notemode'
560 def print_ly (self, func):
561 func ('\\%s' % self.mode)
562 MusicWrapper.print_ly (self, func)
564 class RelativeMusic (MusicWrapper):
566 MusicWrapper.__init__ (self)
567 self.basepitch = None
569 def print_ly (self, func):
570 global previous_pitch
571 global relative_pitches
572 prev_relative_pitches = relative_pitches
573 relative_pitches = True
574 previous_pitch = self.basepitch
575 if not previous_pitch:
576 previous_pitch = Pitch ()
577 func ('\\relative %s%s' % (pitch_generating_function (previous_pitch),
578 previous_pitch.absolute_pitch ()))
579 MusicWrapper.print_ly (self, func)
580 relative_pitches = prev_relative_pitches
582 class TimeScaledMusic (MusicWrapper):
584 MusicWrapper.__init__ (self)
587 self.display_number = "actual" # valid values "actual" | "both" | None
588 # Display the basic note length for the tuplet:
589 self.display_type = None # value values "actual" | "both" | None
590 self.display_bracket = "bracket" # valid values "bracket" | "curved" | None
591 self.actual_type = None # The actually played unit of the scaling
592 self.normal_type = None # The basic unit of the scaling
593 self.display_numerator = None
594 self.display_denominator = None
596 def print_ly (self, func):
597 if self.display_bracket == None:
598 func ("\\once \\omit TupletBracket")
600 elif self.display_bracket == "curved":
601 ly.warning (_ ("Tuplet brackets of curved shape are not correctly implemented"))
602 func ("\\once \\override TupletBracket.stencil = #ly:slur::print")
605 base_number_function = {None: "#f",
606 "actual": "tuplet-number::calc-denominator-text",
607 "both": "tuplet-number::calc-fraction-text"}.get (self.display_number, None)
608 # If we have non-standard numerator/denominator, use our custom function
609 if self.display_number == "actual" and self.display_denominator:
610 base_number_function = "(tuplet-number::non-default-tuplet-denominator-text %s)" % self.display_denominator
611 elif self.display_number == "both" and (self.display_denominator or self.display_numerator):
612 if self.display_numerator:
613 num = self.display_numerator
616 if self.display_denominator:
617 den = self.display_denominator
620 base_number_function = "(tuplet-number::non-default-tuplet-fraction-text %s %s)" % (den, num)
623 if self.display_type == "actual" and self.normal_type:
624 # Obtain the note duration in scheme-mode, i.e. \longa as \\longa
625 base_duration = self.normal_type.ly_expression (None, True)
626 func ("\\once \\override TupletNumber.text = #(tuplet-number::append-note-wrapper %s \"%s\")" %
627 (base_number_function, base_duration))
629 elif self.display_type == "both": # TODO: Implement this using actual_type and normal_type!
630 if self.display_number == None:
631 func ("\\once \\omit TupletNumber")
633 elif self.display_number == "both":
634 den_duration = self.normal_type.ly_expression (None, True)
635 # If we don't have an actual type set, use the normal duration!
637 num_duration = self.actual_type.ly_expression (None, True)
639 num_duration = den_duration
640 if (self.display_denominator or self.display_numerator):
641 func ("\\once \\override TupletNumber.text = #(tuplet-number::non-default-fraction-with-notes %s \"%s\" %s \"%s\")" %
642 (self.display_denominator, den_duration,
643 self.display_numerator, num_duration))
646 func ("\\once \\override TupletNumber.text = #(tuplet-number::fraction-with-notes \"%s\" \"%s\")" %
647 (den_duration, num_duration))
650 if self.display_number == None:
651 func ("\\once \\omit TupletNumber")
653 elif self.display_number == "both":
654 func ("\\once \\override TupletNumber.text = #%s" % base_number_function)
657 func ('\\times %d/%d ' %
658 (self.numerator, self.denominator))
659 func.add_factor (Rational (self.numerator, self.denominator))
660 MusicWrapper.print_ly (self, func)
663 class NestedMusic(Music):
665 Music.__init__ (self)
668 def append (self, what):
670 self.elements.append (what)
672 def has_children (self):
675 def insert_around (self, succ, elt, dir):
676 assert elt.parent == None
677 assert succ == None or succ in self.elements
682 idx = self.elements.index (succ)
689 idx = len (self.elements)
691 self.elements.insert (idx, elt)
694 def get_properties (self):
695 return ("'elements (list %s)"
696 % string.join (map (lambda x: x.lisp_expression(),
699 def get_subset_properties (self, predicate):
700 return ("'elements (list %s)"
701 % string.join (map (lambda x: x.lisp_expression(),
702 filter (predicate, self.elements))))
703 def get_neighbor (self, music, dir):
704 assert music.parent == self
705 idx = self.elements.index (music)
707 idx = min (idx, len (self.elements) - 1)
710 return self.elements[idx]
712 def delete_element (self, element):
713 assert element in self.elements
715 self.elements.remove (element)
716 element.parent = None
718 def set_start (self, start):
720 for e in self.elements:
723 def find_first (self, predicate):
724 r = Music.find_first (self, predicate)
728 for e in self.elements:
729 r = e.find_first (predicate)
734 class SequentialMusic (NestedMusic):
735 def get_last_event_chord (self):
737 at = len(self.elements) - 1
739 not isinstance (self.elements[at], ChordEvent) and
740 not isinstance (self.elements[at], BarLine)):
743 if (at >= 0 and isinstance (self.elements[at], ChordEvent)):
744 value = self.elements[at]
747 def print_ly (self, printer, newline=True):
750 self.print_comment (printer)
754 for e in self.elements:
761 def lisp_sub_expression (self, pred):
765 props = self.get_subset_properties (pred)
767 return "(make-music '%s %s)" % (name, props)
769 def set_start (self, start):
770 for e in self.elements:
772 start += e.get_length()
776 self.repeat_type = "volta"
777 self.repeat_count = 2
780 def set_music (self, music):
781 if isinstance (music, Music):
783 elif isinstance (music, list):
784 self.music = SequentialMusic ()
785 self.music.elements = music
787 ly.warning (_ ("unable to set the music %(music)s for the repeat %(repeat)s") % \
788 {'music':music, 'repeat':self})
789 def add_ending (self, music):
790 self.endings.append (music)
791 def print_ly (self, printer):
792 printer.dump ('\\repeat %s %s' % (self.repeat_type, self.repeat_count))
794 self.music.print_ly (printer)
796 ly.warning (_ ("encountered repeat without body"))
799 printer.dump ('\\alternative {')
800 for e in self.endings:
807 self.lyrics_syllables = []
809 def print_ly (self, printer):
810 printer.dump (self.ly_expression ())
815 def ly_expression (self):
816 lstr = "\lyricmode {\set ignoreMelismata = ##t"
817 for l in self.lyrics_syllables:
825 self.header_fields = {}
827 def set_field (self, field, value):
828 self.header_fields[field] = value
830 def format_header_strings(self, key, value, printer):
831 printer.dump(key + ' = ')
833 # If a header item contains a line break, it is segmented. The
834 # substrings are formatted with the help of \markup, using
835 # \column and \line. An exception, however, are texidoc items,
836 # which should not contain LilyPond formatting commands.
837 if (key != 'texidoc') and ('\n' in value):
838 value = value.replace('"', '')
839 printer.dump(r'\markup \column {')
840 substrings = value.split('\n')
843 printer.dump(r'\line { "' + s + '"}')
850 def print_ly(self, printer):
851 printer.dump("\header {")
853 for (k, v) in self.header_fields.items():
855 self.format_header_strings(k, v, printer)
864 self.global_staff_size = -1
867 self.page_height = -1
870 self.bottom_margin = -1
871 self.left_margin = -1
872 self.right_margin = -1
873 self.system_left_margin = -1
874 self.system_right_margin = -1
875 self.system_distance = -1
876 self.top_system_distance = -1
878 self.short_indent = 0
879 self.instrument_names = []
881 def print_length_field (self, printer, field, value):
883 printer.dump ("%s = %s\\cm" % (field, value))
886 def get_longest_instrument_name(self):
888 for name in self.instrument_names:
889 lines = name.split('\n')
891 if len(line) > len(result):
895 def print_ly (self, printer):
896 if self.global_staff_size > 0:
897 printer.dump ('#(set-global-staff-size %s)' % self.global_staff_size)
899 printer.dump ('\\paper {')
901 printer.dump ("markup-system-spacing #'padding = #2")
903 self.print_length_field (printer, "paper-width", self.page_width)
904 self.print_length_field (printer, "paper-height", self.page_height)
905 self.print_length_field (printer, "top-margin", self.top_margin)
906 self.print_length_field (printer, "bottom-margin", self.bottom_margin)
907 self.print_length_field (printer, "left-margin", self.left_margin)
908 # TODO: maybe set line-width instead of right-margin?
909 self.print_length_field (printer, "right-margin", self.right_margin)
910 # TODO: What's the corresponding setting for system_left_margin and
911 # system_right_margin in LilyPond?
912 self.print_length_field (printer, "between-system-space", self.system_distance)
913 self.print_length_field (printer, "page-top-space", self.top_system_distance)
914 # TODO: Compute the indentation with the instrument name lengths
917 char_per_cm = (len(self.get_longest_instrument_name()) * 13) / self.page_width
918 if (self.indent != 0):
919 self.print_length_field (printer, "indent", self.indent/char_per_cm)
920 if (self.short_indent != 0):
921 self.print_length_field (printer, "short-indent", self.short_indent/char_per_cm)
928 self.context_dict = {}
929 def add_context (self, context):
930 if not self.context_dict.has_key (context):
931 self.context_dict[context] = []
932 def set_context_item (self, context, item):
933 self.add_context (context)
934 if not item in self.context_dict[context]:
935 self.context_dict[context].append (item)
936 def print_ly (self, printer):
937 if self.context_dict.items ():
938 printer.dump ('\\layout {')
940 for (context, defs) in self.context_dict.items ():
941 printer.dump ('\\context { \\%s' % context)
952 class ChordEvent (NestedMusic):
954 NestedMusic.__init__ (self)
955 self.after_grace_elements = None
956 self.grace_elements = None
957 self.grace_type = None
958 def append_grace (self, element):
960 if not self.grace_elements:
961 self.grace_elements = SequentialMusic ()
962 self.grace_elements.append (element)
963 def append_after_grace (self, element):
965 if not self.after_grace_elements:
966 self.after_grace_elements = SequentialMusic ()
967 self.after_grace_elements.append (element)
969 def has_elements (self):
970 return [e for e in self.elements if
971 isinstance (e, NoteEvent) or isinstance (e, RestEvent)] != []
974 def get_length (self):
976 for e in self.elements:
977 l = max(l, e.get_length())
980 def get_duration (self):
981 note_events = [e for e in self.elements if
982 isinstance (e, NoteEvent) or isinstance (e, RestEvent)]
984 return note_events[0].duration
988 def print_ly (self, printer):
989 note_events = [e for e in self.elements if
990 isinstance (e, NoteEvent)]
992 rest_events = [e for e in self.elements if
993 isinstance (e, RhythmicEvent)
994 and not isinstance (e, NoteEvent)]
996 other_events = [e for e in self.elements if
997 not isinstance (e, RhythmicEvent)]
999 if self.after_grace_elements:
1000 printer ('\\afterGrace {')
1002 if self.grace_elements and self.elements:
1004 printer ('\\%s' % self.grace_type)
1007 # don't print newlines after the { and } braces
1008 self.grace_elements.print_ly (printer, False)
1009 elif self.grace_elements: # no self.elements!
1010 ly.warning (_ ("Grace note with no following music: %s") % self.grace_elements)
1012 printer ('\\%s' % self.grace_type)
1015 self.grace_elements.print_ly (printer, False)
1018 # Print all overrides and other settings needed by the
1019 # articulations/ornaments before the note
1021 for e in other_events:
1022 e.print_before_note (printer)
1025 rest_events[0].print_ly (printer)
1026 elif len (note_events) == 1:
1027 note_events[0].print_ly (printer)
1029 global previous_pitch
1033 for x in note_events:
1034 if(x.associated_events):
1035 for aev in x.associated_events:
1036 if (isinstance(aev, StemEvent) and aev.value):
1038 pitches.append (x.chord_element_ly ())
1040 basepitch = previous_pitch
1042 printer (stem.ly_expression ())
1043 printer ('<%s>' % string.join (pitches))
1044 previous_pitch = basepitch
1045 duration = self.get_duration ()
1047 duration.print_ly (printer)
1051 for e in other_events:
1052 e.print_ly (printer)
1054 for e in other_events:
1055 e.print_after_note (printer)
1057 if self.after_grace_elements:
1059 self.after_grace_elements.print_ly (printer, False)
1061 self.print_comment (printer)
1063 class Partial (Music):
1064 def __init__ (self):
1065 Music.__init__ (self)
1067 def print_ly (self, printer):
1069 printer.dump ("\\partial %s" % self.partial.ly_expression ())
1071 class BarLine (Music):
1072 def __init__ (self):
1073 Music.__init__ (self)
1077 def print_ly (self, printer):
1078 bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': "dashed",
1079 'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
1080 'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
1081 'short': "'", 'none': "" }.get (self.type, None)
1082 if bar_symbol <> None:
1083 printer.dump ('\\bar "%s"' % bar_symbol)
1087 if self.bar_number > 0 and (self.bar_number % 10) == 0:
1088 printer.dump ("\\barNumberCheck #%d " % self.bar_number)
1089 elif self.bar_number > 0:
1090 printer.print_verbatim (' %% %d' % self.bar_number)
1093 def ly_expression (self):
1097 def __init__ (self):
1098 # strings to print before the note to which an event is attached.
1099 # Ignored for notes etc.
1100 self.before_note = None
1101 self.after_note = None
1102 # print something before the note to which an event is attached, e.g. overrides
1103 def print_before_note (self, printer):
1104 if self.before_note:
1105 printer.dump (self.before_note)
1106 # print something after the note to which an event is attached, e.g. resetting
1107 def print_after_note (self, printer):
1109 printer.dump (self.after_note)
1112 class SpanEvent (Event):
1113 def __init__ (self):
1114 Event.__init__ (self)
1115 self.span_direction = 0 # start/stop
1116 self.line_type = 'solid'
1117 self.span_type = 0 # e.g. cres/decrescendo, ottava up/down
1118 self.size = 0 # size of e.g. octave shift
1119 def wait_for_note (self):
1121 def get_properties(self):
1122 return "'span-direction %d" % self.span_direction
1123 def set_span_type (self, type):
1124 self.span_type = type
1126 class SlurEvent (SpanEvent):
1127 def print_before_note (self, printer):
1128 command = {'dotted': '\\slurDotted',
1129 'dashed' : '\\slurDashed'}.get (self.line_type, '')
1130 if command and self.span_direction == -1:
1131 printer.dump (command)
1132 def print_after_note (self, printer):
1133 # reset non-solid slur types!
1134 command = {'dotted': '\\slurSolid',
1135 'dashed' : '\\slurSolid'}.get (self.line_type, '')
1136 if command and self.span_direction == -1:
1137 printer.dump (command)
1138 def ly_expression (self):
1139 return {-1: '(', 1:')'}.get (self.span_direction, '')
1141 class BeamEvent (SpanEvent):
1142 def ly_expression (self):
1143 return {-1: '[', 1:']'}.get (self.span_direction, '')
1145 class PedalEvent (SpanEvent):
1146 def ly_expression (self):
1147 return {-1: '\\sustainOn',
1148 0:'\\sustainOff\\sustainOn',
1149 1:'\\sustainOff'}.get (self.span_direction, '')
1151 class TextSpannerEvent (SpanEvent):
1152 def print_before_note (self, printer):
1153 if hasattr(self, 'style') and self.style=="wave":
1154 printer.dump("\once \override TextSpanner #'style = #'trill")
1156 x = {-1:'\\textSpannerDown', 0:'\\textSpannerNeutral', 1: '\\textSpannerUp'}.get(self.force_direction, '')
1161 def print_after_note (self, printer):
1164 def ly_expression (self):
1166 if hasattr(self, 'style') and self.style=="ignore":
1168 # if self.style=="wave":
1169 if whatOrnament == "wave":
1170 return {-1: '\\startTextSpan',
1171 1:'\\stopTextSpan'}.get (self.span_direction, '')
1173 if hasattr(self, 'style') and self.style=="stop" and whatOrnament != "trill": return ""
1174 return {-1: '\\startTrillSpan',
1175 1:'\\stopTrillSpan'}.get (self.span_direction, '')
1177 class BracketSpannerEvent (SpanEvent):
1178 # Ligature brackets use prefix-notation!!!
1179 def print_before_note (self, printer):
1180 if self.span_direction == -1:
1181 if self.force_direction == 1:
1182 printer.dump("\once \override LigatureBracket #' direction = #UP")
1183 elif self.force_direction == -1:
1184 printer.dump("\once \override LigatureBracket #' direction = #DOWN")
1186 # the bracket after the last note
1187 def print_after_note (self, printer):
1188 if self.span_direction == 1:
1190 # we're printing everything in print_(before|after)_note...
1191 def ly_expression (self):
1195 class OctaveShiftEvent (SpanEvent):
1196 def wait_for_note (self):
1198 def set_span_type (self, type):
1199 self.span_type = {'up': 1, 'down':-1}.get (type, 0)
1200 def ly_octave_shift_indicator (self):
1201 # convert 8/15 to lilypond indicators (+-1/+-2)
1203 value = {8: 1, 15: 2}[self.size]
1205 ly.warning (_ ("Invalid octave shift size found: %s. Using no shift.") % self.size)
1207 # negative values go up!
1208 value *= -1 * self.span_type
1210 def ly_expression (self):
1211 dir = self.ly_octave_shift_indicator ()
1214 value = '\ottava #%s' % dir
1217 1: '\ottava #0'}.get (self.span_direction, '')
1219 class TrillSpanEvent (SpanEvent):
1220 def ly_expression (self):
1221 return {-1: '\\startTrillSpan',
1222 0: '', # no need to write out anything for type='continue'
1223 1:'\\stopTrillSpan'}.get (self.span_direction, '')
1225 class GlissandoEvent (SpanEvent):
1226 def print_before_note (self, printer):
1227 if self.span_direction == -1:
1229 "dashed" : "dashed-line",
1230 "dotted" : "dotted-line",
1232 }. get (self.line_type, None)
1234 printer.dump ("\\once \\override Glissando.style = #'%s" % style)
1235 def ly_expression (self):
1236 return {-1: '\\glissando',
1237 1:''}.get (self.span_direction, '')
1239 class ArpeggioEvent(Event):
1240 def __init__ (self):
1241 Event.__init__ (self)
1243 self.non_arpeggiate = False
1244 def wait_for_note (self):
1246 def print_before_note (self, printer):
1247 if self.non_arpeggiate:
1248 printer.dump ("\\arpeggioBracket")
1250 dir = { -1: "\\arpeggioArrowDown", 1: "\\arpeggioArrowUp" }.get (self.direction, '')
1253 def print_after_note (self, printer):
1254 if self.non_arpeggiate or self.direction:
1255 printer.dump ("\\arpeggioNormal")
1256 def ly_expression (self):
1257 return ('\\arpeggio')
1260 class TieEvent(Event):
1261 def ly_expression (self):
1265 class HairpinEvent (SpanEvent):
1266 def set_span_type (self, type):
1267 self.span_type = {'crescendo' : 1, 'decrescendo' :-1, 'diminuendo' :-1 }.get (type, 0)
1268 def hairpin_to_ly (self):
1269 if self.span_direction == 1:
1272 return {1: '\<', -1: '\>'}.get (self.span_type, '')
1274 def direction_mod (self):
1275 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1277 def ly_expression (self):
1278 return self.hairpin_to_ly ()
1280 def print_ly (self, printer):
1281 val = self.hairpin_to_ly ()
1283 # printer.dump (val)
1284 printer.dump ('%s%s' % (self.direction_mod (), val))
1288 class DynamicsEvent (Event):
1289 def __init__ (self):
1290 Event.__init__ (self)
1292 self.force_direction = 0
1293 def wait_for_note (self):
1295 def ly_expression (self):
1297 return '\%s' % self.type
1301 def direction_mod (self):
1302 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1304 def print_ly (self, printer):
1306 printer.dump ('%s\\%s' % (self.direction_mod (), self.type))
1308 class MarkEvent (Event):
1309 def __init__ (self, text="\\default"):
1310 Event.__init__ (self)
1312 def wait_for_note (self):
1314 def ly_contents (self):
1316 return '%s' % self.mark
1319 def ly_expression (self):
1320 return '\\mark %s' % self.ly_contents ()
1322 class MusicGlyphMarkEvent (MarkEvent):
1323 def ly_contents (self):
1325 return '\\markup { \\musicglyph #"scripts.%s" }' % self.mark
1330 class TextEvent (Event):
1331 def __init__ (self):
1332 Event.__init__ (self)
1334 self.force_direction = None
1336 def wait_for_note (self):
1337 """ This is problematic: the lilypond-markup ^"text"
1338 requires wait_for_note to be true. Otherwise the
1339 compilation will fail. So we are forced to set return to True.
1340 But in some cases this might lead to a wrong placement of the text.
1341 In case of words like Allegro the text should be put in a '\tempo'-command.
1342 In this case we don't want to wait for the next note.
1343 In some other cases the text is supposed to be used in a '\mark\markup' construct.
1344 We would not want to wait for the next note either.
1345 There might be other problematic situations.
1346 In the long run we should differentiate between various contexts in MusicXML, e.g.
1347 the following markup should be interpreted as '\tempo "Allegretto"':
1348 <direction placement="above">
1350 <words>Allegretto</words>
1352 <sound tempo="120"/>
1354 In the mean time arising problems have to be corrected manually after the conversion.
1358 def direction_mod (self):
1359 """ 1: placement="above"; -1: placement="below"; 0: no placement attribute.
1360 see musicxml_direction_to_indicator in musicxml2ly_conversion.py """
1361 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1363 def ly_expression (self):
1364 # self.text will be enclosed by quotes, and the direction
1365 # modifier must be separated from the opening quote by a space.
1366 # This is so that subsequent line breaking for the output file
1367 # using utilities.split_string_and_preserve_doublequoted_strings()
1368 # properly detects the opening quote.
1369 base_string = '%s \"%s\"'
1371 base_string = '%s\markup{ ' + self.markup + ' {%s} }'
1372 return base_string % (self.direction_mod (), self.text)
1374 class ArticulationEvent (Event):
1375 def __init__ (self):
1376 Event.__init__ (self)
1378 self.force_direction = None
1379 def wait_for_note (self):
1382 def direction_mod (self):
1383 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '')
1385 def ly_expression (self):
1386 return '%s\\%s' % (self.direction_mod (), self.type)
1388 class ShortArticulationEvent (ArticulationEvent):
1389 def direction_mod (self):
1391 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1392 def ly_expression (self):
1394 return '%s%s' % (self.direction_mod (), self.type)
1398 class NoDirectionArticulationEvent (ArticulationEvent):
1400 def is_breathing_sign(self):
1401 return self.type == 'breathe'
1403 def print_after_note(self, printer):
1404 # The breathing sign should, according to current LilyPond
1405 # praxis, be treated as an independent musical
1406 # event. Consequently, it should be printed _after_ the note
1407 # to which it is attached.
1408 if self.is_breathing_sign():
1409 printer.dump(r'\breathe')
1411 def ly_expression (self):
1412 if self.type and not self.is_breathing_sign():
1413 return '\\%s' % self.type
1417 class MarkupEvent (ShortArticulationEvent):
1418 def __init__ (self):
1419 ArticulationEvent.__init__ (self)
1420 self.contents = None
1421 def ly_expression (self):
1423 return "%s\\markup { %s }" % (self.direction_mod (), self.contents)
1427 class FretEvent (MarkupEvent):
1428 def __init__ (self):
1429 MarkupEvent.__init__ (self)
1430 self.force_direction = 1
1435 def ly_expression (self):
1437 if self.strings <> 6:
1438 val += "w:%s;" % self.strings
1440 val += "h:%s;" % self.frets
1441 if self.barre and len (self.barre) >= 3:
1442 val += "c:%s-%s-%s;" % (self.barre[0], self.barre[1], self.barre[2]+get_transpose("integer"))
1443 have_fingering = False
1444 for i in self.elements:
1446 val += "%s-%s" % (i[0], i[1]+(get_transpose("integer"),'')[isinstance(i[1],str)])
1448 have_fingering = True
1454 return "%s\\markup { \\fret-diagram #\"%s\" }" % (self.direction_mod (), val)
1458 class FretBoardNote (Music):
1459 def __init__ (self):
1460 Music.__init__ (self)
1463 self.fingering = None
1464 def ly_expression (self):
1465 str = self.pitch.ly_expression()
1467 str += "-%s" % self.fingering
1469 str += "\%s" % self.string
1472 class FretBoardEvent (NestedMusic):
1473 def __init__ (self):
1474 NestedMusic.__init__ (self)
1475 self.duration = None
1476 def print_ly (self, printer):
1477 fretboard_notes = [n for n in self.elements if isinstance (n, FretBoardNote)]
1480 for n in fretboard_notes:
1481 notes.append (n.ly_expression ())
1482 contents = string.join (notes)
1483 printer ('<%s>%s' % (contents,self.duration))
1485 class FunctionWrapperEvent (Event):
1486 def __init__ (self, function_name=None):
1487 Event.__init__ (self)
1488 self.function_name = function_name
1489 def pre_note_ly (self, is_chord_element):
1490 if self.function_name:
1491 return "\\%s" % self.function_name
1494 def pre_chord_ly (self):
1496 def ly_expression (self):
1497 if self.function_name:
1498 return "\\%s" % self.function_name
1502 class ParenthesizeEvent (FunctionWrapperEvent):
1503 def __init__ (self):
1504 FunctionWrapperEvent.__init__ (self, "parenthesize")
1506 class StemEvent (Event):
1508 A class to take care of stem values (up, down, double, none)
1510 def __init__ (self):
1511 Event.__init__ (self)
1513 def pre_chord_ly (self):
1515 return "\\%s" % self.value
1518 def pre_note_ly (self, is_chord_element):
1520 def ly_expression (self):
1521 return self.pre_chord_ly ()
1523 class NotestyleEvent (Event): #class changed by DaLa: additional attribute color
1524 def __init__ (self):
1525 Event.__init__ (self)
1529 def pre_chord_ly (self):
1532 return_string += " \\once \\override NoteHead #'style = #%s" % self.style
1534 return_string += " \\once \\override NoteHead #'color = #(rgb-color %s %s %s)" % (self.color[0], self.color[1], self.color[2])
1535 return return_string
1536 def pre_note_ly (self, is_chord_element):
1537 if self.style and is_chord_element:
1538 return "\\tweak style #%s" % self.style
1541 def ly_expression (self):
1542 return self.pre_chord_ly ()
1544 class StemstyleEvent (Event): #class added by DaLa
1545 def __init__ (self):
1546 Event.__init__ (self)
1548 def pre_chord_ly (self):
1550 return "\\once \\override Stem #'color = #(rgb-color %s %s %s)" % (self.color[0], self.color[1], self.color[2])
1553 def pre_note_ly (self, is_chord_element):
1555 def ly_expression (self):
1556 return self.pre_chord_ly ()
1560 def __init__ (self):
1564 return self.ly_expression()
1565 def ly_expression (self):
1566 return pitch_generating_function (self)
1568 class ChordModification:
1569 def __init__ (self):
1573 def ly_expression (self):
1575 val = {1: ".", -1: "^" }.get (self.type, "")
1576 val += "%s" % self.step
1577 val += {1: "+", -1: "-"}.get (self.alteration, "")
1582 class ChordNameEvent (Event):
1583 def __init__ (self):
1584 Event.__init__ (self)
1587 self.duration = None
1588 self.modifications = []
1590 def add_modification (self, mod):
1591 self.modifications.append (mod)
1592 def ly_expression (self):
1596 value = self.root.ly_expression ()
1598 value += self.duration.ly_expression ()
1600 value = self.kind.format(value)
1601 # First print all additions/changes, and only afterwards all subtractions
1602 for m in self.modifications:
1604 value += m.ly_expression ()
1605 for m in self.modifications:
1607 value += m.ly_expression ()
1609 value += "/+%s" % self.bass.ly_expression ()
1613 class TremoloEvent(ArticulationEvent):
1615 Event.__init__(self)
1618 def ly_expression(self):
1620 if self.strokes and int(self.strokes) > 0:
1621 # ly_dur is a global variable defined in class Duration
1622 # ly_dur stores the value of the reciprocal values of notes
1623 # ly_dur is used here to check the current note duration
1624 # if the duration is smaller than 8, e.g.
1625 # quarter, half and whole notes,
1626 # `:(2 ** (2 + number of tremolo strokes))'
1627 # should be appended to the pitch and duration, e.g.
1628 # 1 stroke: `c4:8' or `c2:8' or `c1:8'
1629 # 2 strokes: `c4:16' or `c2:16' or `c1:16'
1631 # else (if ly_dur is equal to or greater than 8):
1632 # we need to make sure that the tremolo value that is to
1633 # be appended to the pitch and duration is twice the
1634 # duration (if there is only one tremolo stroke.
1635 # Each additional stroke doubles the tremolo value, e.g.:
1636 # 1 stroke: `c8:16', `c16:32', `c32:64', ...
1637 # 2 strokes: `c8:32', `c16:64', `c32:128', ...
1640 ly_str += ':%s' % (2 ** (2 + int(self.strokes)))
1642 ly_str += ':%s' % (2 ** int((math.log(ly_dur, 2)) + int(self.strokes)))
1645 class BendEvent (ArticulationEvent):
1646 def __init__ (self):
1647 Event.__init__ (self)
1649 def ly_expression (self):
1650 if self.alter != None:
1651 return "-\\bendAfter #%s" % self.alter
1655 class RhythmicEvent(Event):
1656 def __init__ (self):
1657 Event.__init__ (self)
1658 self.duration = Duration()
1659 self.associated_events = []
1661 def add_associated_event (self, ev):
1663 self.associated_events.append (ev)
1665 def pre_chord_ly (self):
1666 return [ev.pre_chord_ly () for ev in self.associated_events]
1668 def pre_note_ly (self, is_chord_element):
1669 return [ev.pre_note_ly (is_chord_element) for ev in self.associated_events]
1671 def ly_expression_pre_note (self, is_chord_element):
1672 res = string.join (self.pre_note_ly (is_chord_element), ' ')
1677 def get_length (self):
1678 return self.duration.get_length()
1680 def get_properties (self):
1681 return ("'duration %s"
1682 % self.duration.lisp_expression ())
1684 class RestEvent (RhythmicEvent):
1685 def __init__ (self):
1686 RhythmicEvent.__init__ (self)
1689 def ly_expression (self):
1690 res = self.ly_expression_pre_note (False)
1692 return res + "%s%s\\rest" % (self.pitch.ly_expression (), self.duration.ly_expression ())
1694 return 'r%s' % self.duration.ly_expression ()
1696 def print_ly (self, printer):
1697 for ev in self.associated_events:
1698 ev.print_ly (printer)
1699 # if hasattr(self, 'color'):
1700 # printer.print_note_color("NoteHead", self.color)
1701 # printer.print_note_color("Stem", self.color)
1702 # printer.print_note_color("Beam", self.color)
1704 self.pitch.print_ly (printer)
1705 self.duration.print_ly (printer)
1709 self.duration.print_ly (printer)
1711 class SkipEvent (RhythmicEvent):
1712 def ly_expression (self):
1713 return 's%s' % self.duration.ly_expression ()
1715 class NoteEvent(RhythmicEvent):
1716 def __init__ (self):
1717 RhythmicEvent.__init__ (self)
1719 self.drum_type = None
1720 self.cautionary = False
1721 self.forced_accidental = False
1723 def get_properties (self):
1724 str = RhythmicEvent.get_properties (self)
1727 str += self.pitch.lisp_expression ()
1728 elif self.drum_type:
1729 str += "'drum-type '%s" % self.drum_type
1733 def pitch_mods (self):
1736 excl_question += '?'
1737 if self.forced_accidental:
1738 excl_question += '!'
1740 return excl_question
1742 def ly_expression (self):
1743 # obtain all stuff that needs to be printed before the note:
1744 res = self.ly_expression_pre_note (True)
1746 return res + '%s%s%s' % (self.pitch.ly_expression (),
1748 self.duration.ly_expression ())
1749 elif self.drum_type:
1750 return res + '%s%s' (self.drum_type,
1751 self.duration.ly_expression ())
1753 def chord_element_ly (self):
1754 # obtain all stuff that needs to be printed before the note:
1755 res = self.ly_expression_pre_note (True)
1757 return res + '%s%s' % (self.pitch.ly_expression (),
1759 elif self.drum_type:
1760 return res + '%s%s' (self.drum_type)
1763 def print_ly (self, printer):
1764 for ev in self.associated_events:
1765 ev.print_ly (printer)
1766 if hasattr(self, 'color'):
1767 printer.print_note_color("NoteHead", self.color)
1768 printer.print_note_color("Stem", self.color)
1769 printer.print_note_color("Beam", self.color)
1772 self.pitch.print_ly (printer)
1773 printer (self.pitch_mods ())
1775 printer (self.drum_type)
1777 self.duration.print_ly (printer)
1779 # if hasattr(self, 'color'):
1780 # printer.print_note_color("NoteHead")
1781 # printer.print_note_color("Stem")
1782 # printer.print_note_color("Beam")
1784 class KeySignatureChange (Music):
1785 def __init__ (self):
1786 Music.__init__ (self)
1789 self.non_standard_alterations = None
1791 def format_non_standard_alteration (self, a):
1792 alter_dict = { -2: ",DOUBLE-FLAT",
1793 - 1.5: ",THREE-Q-FLAT",
1795 - 0.5: ",SEMI-FLAT",
1799 1.5: ",THREE-Q-SHARP",
1802 accidental = alter_dict[a[1]]
1804 ly.warning (_ ("Unable to convert alteration %s to a lilypond expression") % a[1])
1807 return "( %s . %s )" % (a[0], accidental)
1809 return "(( %s . %s ) . %s )" % (a[2], a[0], accidental)
1813 def ly_expression (self):
1815 return '\\key %s \\%s' % (self.tonic.ly_step_expression (),
1817 elif self.non_standard_alterations:
1818 alterations = [self.format_non_standard_alteration (a) for
1819 a in self.non_standard_alterations]
1820 return "\\set Staff.keyAlterations = #`(%s)" % string.join (alterations, " ")
1824 class ShiftDurations (MusicWrapper):
1825 def __init__ (self):
1826 MusicWrapper.__init__ (self)
1829 def set_shift_durations_parameters(self, timeSigChange):
1830 self.params = timeSigChange.get_shift_durations_parameters()
1832 def print_ly (self, func):
1833 func (' \\shiftDurations #%d #%d ' % tuple(self.params))
1834 MusicWrapper.print_ly (self, func)
1836 class TimeSignatureChange (Music):
1837 def __init__ (self):
1838 Music.__init__ (self)
1839 self.fractions = [4, 4]
1841 # Used for the --time-signature option of musicxml2ly
1842 self.originalFractions = [4, 4]
1844 def get_fractions_ratio (self):
1846 Calculate the ratio between the original time fraction and the new one.
1847 Used for the "--time-signature" option.
1849 @return: The ratio between the two time fractions.
1852 return (float(self.originalFractions[0])/self.originalFractions[1])*(float(self.fractions[1])/self.fractions[0])
1854 def get_shift_durations_parameters (self):
1855 dur = math.ceil(math.log(self.get_fractions_ratio(),2))
1856 dots = (1/self.get_fractions_ratio())/(math.pow(2,-dur))
1857 dots = int(math.log(2-dots,0.5))
1860 def format_fraction (self, frac):
1861 if isinstance (frac, list):
1862 l = [self.format_fraction (f) for f in frac]
1863 return "(" + string.join (l, " ") + ")"
1867 def ly_expression (self):
1869 # Print out the style if we have ome, but the '() should only be
1870 # forced for 2/2 or 4/4, since in all other cases we'll get numeric
1871 # signatures anyway despite the default 'C signature style!
1872 is_common_signature = self.fractions in ([2, 2], [4, 4], [4, 2])
1874 if self.style == "common":
1875 st = "\\defaultTimeSignature"
1876 elif (self.style != "'()"):
1877 st = "\\once \\override Staff.TimeSignature.style = #%s " % self.style
1878 elif (self.style != "'()") or is_common_signature:
1879 st = "\\numericTimeSignature"
1881 # Easy case: self.fractions = [n,d] => normal \time n/d call:
1882 if len (self.fractions) == 2 and isinstance (self.fractions[0], int):
1883 return st + '\\time %d/%d ' % tuple (self.fractions)
1884 elif self.fractions:
1885 return st + "\\compoundMeter #'%s" % self.format_fraction (self.fractions)
1889 class ClefChange (Music):
1890 def __init__ (self):
1891 Music.__init__ (self)
1896 def octave_modifier (self):
1897 return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self.octave, '')
1899 def clef_name (self):
1900 return {('G', 2): "treble",
1902 ('C', 1): "soprano",
1903 ('C', 2): "mezzosoprano",
1906 ('C', 5): "baritone",
1907 ('F', 3): "varbaritone",
1909 ('F', 5): "subbass",
1910 ("percussion", 2): "percussion",
1911 # Workaround: MuseScore uses PERC instead of percussion
1912 ("PERC", 2): "percussion",
1913 ("TAB", 5): get_tab_clef ()}.get ((self.type, self.position), None)
1915 def ly_expression (self):
1916 return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ())
1919 "G": ("clefs.G", -2, -6),
1920 "C": ("clefs.C", 0, 0),
1921 "F": ("clefs.F", 2, 6),
1924 def lisp_expression (self):
1926 (glyph, pos, c0) = self.clef_dict[self.type]
1930 (make-music 'SequentialMusic
1933 (make-property-set 'clefGlyph "%s") 'Staff)
1935 (make-property-set 'clefPosition %d) 'Staff)
1937 (make-property-set 'middleCPosition %d) 'Staff)))
1938 """ % (glyph, pos, c0)
1941 class Transposition (Music):
1942 def __init__ (self):
1943 Music.__init__ (self)
1945 def ly_expression (self):
1946 self.pitch._force_absolute_pitch = True
1947 return '\\transposition %s' % self.pitch.ly_expression ()
1949 class StaffChange (Music):
1950 def __init__ (self, staff):
1951 Music.__init__ (self)
1953 def ly_expression (self):
1955 return "\\change Staff=\"%s\"" % self.staff
1959 class SetEvent (Music):
1960 def __init__ (self, contextprop, value):
1961 Music.__init__ (self)
1962 self.context_prop = contextprop
1964 def ly_expression (self):
1966 return "\\set %s = %s" % (self.context_prop, self.value)
1970 class StaffLinesEvent (Music):
1971 def __init__ (self, lines):
1972 Music.__init__ (self)
1974 def ly_expression (self):
1975 if (self.lines > 0):
1976 return "\\stopStaff \\override Staff.StaffSymbol.line-count = #%s \\startStaff" % self.lines
1978 return "\\stopStaff \\revert Staff.StaffSymbol.line-count \\startStaff"
1980 class TempoMark (Music):
1981 def __init__ (self):
1982 Music.__init__ (self)
1983 self.baseduration = None
1984 self.newduration = None
1986 self.parentheses = False
1987 def set_base_duration (self, dur):
1988 self.baseduration = dur
1989 def set_new_duration (self, dur):
1990 self.newduration = dur
1991 def set_beats_per_minute (self, beats):
1993 def set_parentheses (self, parentheses):
1994 self.parentheses = parentheses
1995 def wait_for_note (self):
1997 def duration_to_markup (self, dur):
1999 # Generate the markup to print the note, use scheme mode for
2000 # ly_expression to get longa and not \longa (which causes an error)
2001 return "\\general-align #Y #DOWN \\smaller \\note #\"%s\" #UP" % dur.ly_expression(None, True)
2004 def tempo_markup_template (self):
2005 return "\\mark\\markup { \\fontsize #-2 \\line { %s } }"
2006 def ly_expression (self):
2008 if not self.baseduration:
2011 if self.parentheses:
2012 res += "\\tempo \"\" %s=%s" % (self.baseduration.ly_expression(), self.beats)
2014 res += "\\tempo %s=%s" % (self.baseduration.ly_expression(), self.beats)
2015 elif self.newduration:
2016 dm = self.duration_to_markup (self.baseduration)
2017 ndm = self.duration_to_markup (self.newduration)
2018 if self.parentheses:
2019 contents = "\"(\" %s = %s \")\"" % (dm, ndm)
2021 contents = " %s = %s " % (dm, ndm)
2022 res += self.tempo_markup_template() % contents
2027 class FiguredBassNote (Music):
2028 def __init__ (self):
2029 Music.__init__ (self)
2033 def set_prefix (self, prefix):
2034 self.prefix = prefix
2035 def set_suffix (self, suffix):
2036 self.prefix = suffix
2037 def set_number (self, number):
2038 self.number = number
2039 def ly_expression (self):
2052 class FiguredBassEvent (NestedMusic):
2053 def __init__ (self):
2054 NestedMusic.__init__ (self)
2055 self.duration = None
2056 self.real_duration = 0
2057 self.parentheses = False
2059 def set_duration (self, dur):
2061 def set_parentheses (self, par):
2062 self.parentheses = par
2063 def set_real_duration (self, dur):
2064 self.real_duration = dur
2066 def print_ly (self, printer):
2067 figured_bass_events = [e for e in self.elements if
2068 isinstance (e, FiguredBassNote)]
2069 if figured_bass_events:
2071 for x in figured_bass_events:
2072 notes.append (x.ly_expression ())
2073 contents = string.join (notes)
2074 if self.parentheses:
2075 contents = '[%s]' % contents
2076 printer ('<%s>' % contents)
2077 self.duration.print_ly (printer)
2080 class MultiMeasureRest(Music):
2082 def lisp_expression (self):
2085 'MultiMeasureRestMusicGroup
2087 (list (make-music (quote BarCheck))
2092 'MultiMeasureRestEvent
2095 (make-music (quote BarCheck))))
2096 """ % self.duration.lisp_expression ()
2098 def ly_expression (self):
2099 return 'R%s' % self.duration.ly_expression ()
2102 class Break (Music):
2103 def __init__ (self, tp="break"):
2104 Music.__init__ (self)
2106 def print_ly (self, printer):
2108 printer.dump ("\\%s" % self.type)
2111 def __init__ (self, command="StaffGroup"):
2112 self.stafftype = command
2114 self.instrument_name = None
2116 self.short_instrument_name = None
2120 self.is_group = True
2121 self.context_modifications = []
2122 # part_information is a list with entries of the form
2123 # [staffid, voicelist]
2124 # where voicelist is a list with entries of the form
2125 # [voiceid1, [lyricsid11, lyricsid12,...] ]
2126 self.part_information = None
2128 def append_staff (self, staff):
2129 self.children.append (staff)
2131 def set_part_information (self, part_name, staves_info):
2132 if part_name == self.id:
2133 self.part_information = staves_info
2135 for c in self.children:
2136 c.set_part_information (part_name, staves_info)
2138 def add_context_modification (self, modification):
2139 self.context_modifications.append (modification)
2141 def print_ly_contents (self, printer):
2142 for c in self.children:
2144 c.print_ly (printer)
2145 #Intention: I want to put the content of new StaffGroup in angled brackets (<< >>)
2146 #printer.dump ("test")# test is printed twice at the end of a staffgroup with two staves.
2147 #printer ("test") # test is printed twice at the end of a staffgroup with two staves.
2149 def needs_with (self):
2151 needs_with |= self.spanbar == "no"
2152 needs_with |= self.instrument_name != None
2153 needs_with |= self.short_instrument_name != None
2154 needs_with |= (self.symbol != None) and (self.symbol != "bracket")
2157 def print_ly_context_mods (self, printer):
2158 if self.instrument_name or self.short_instrument_name:
2159 printer.dump ("\\consists \"Instrument_name_engraver\"")
2160 if self.spanbar == "no":
2161 printer.dump ("\\hide SpanBar")
2162 brack = {"brace": "SystemStartBrace",
2163 "none": "SystemStartBar",
2164 "line": "SystemStartSquare"}.get (self.symbol, None)
2166 printer.dump ("systemStartDelimiter = #'%s" % brack)
2168 def print_ly_overrides (self, printer):
2169 needs_with = self.needs_with () | (len (self.context_modifications) > 0);
2171 printer.dump ("\\with {")
2172 self.print_ly_context_mods (printer)
2173 for m in self.context_modifications:
2177 #print a single << after StaffGroup only when the with-block is not needed.
2178 #This doesn't work. << is printed before and after StaffGroup!
2180 # printer.dump (" <<")
2181 #prints loads off << before and after StaffGroup and before \set Staff.instrumentName
2182 #elif not needs_with:
2183 # printer.dump (" <<")
2185 def print_chords(self, printer):
2187 for [staff_id, voices] in self.part_information:
2188 for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
2190 printer ('\context ChordNames = "%s" {%s \\%s}' % (chordnames, get_transpose ("string"), chordnames))
2195 def print_fretboards(self, printer):
2197 for [staff_id, voices] in self.part_information:
2198 for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
2200 printer ('\context FretBoards = "%s" {%s \\%s}' % (fretboards, get_transpose ("string"), fretboards))
2205 def print_ly (self, printer):
2206 self.print_chords(printer)
2207 self.print_fretboards(printer)
2209 printer.dump ("\\new %s" % self.stafftype)
2210 self.print_ly_overrides (printer)
2215 if self.stafftype and self.instrument_name:
2216 printer.dump ("\\set %s.instrumentName = %s" % (self.stafftype,
2217 escape_instrument_string (self.instrument_name)))
2219 if self.stafftype and self.short_instrument_name:
2220 printer.dump ("\\set %s.shortInstrumentName = %s" % (self.stafftype,
2221 escape_instrument_string (self.short_instrument_name)))
2225 r'\set {stafftype}.midiInstrument = #"{sound}"'.format(
2226 stafftype=self.stafftype, sound=self.sound))
2228 self.print_ly_contents (printer)
2235 class Staff (StaffGroup):
2236 def __init__ (self, command="Staff"):
2237 StaffGroup.__init__ (self, command)
2238 self.is_group = False
2240 self.voice_command = "Voice"
2241 self.substafftype = None
2244 def needs_with (self):
2247 def print_ly_context_mods (self, printer):
2248 #printer.dump ("test") #does nothing.
2251 def print_ly_contents (self, printer):
2252 if not self.id or not self.part_information:
2254 sub_staff_type = self.substafftype
2255 if not sub_staff_type:
2256 sub_staff_type = self.stafftype
2257 #printer.dump ("test") #prints test in each staff after the definitions of the instrument name and before the definition of the contexts.
2260 for [staff_id, voices] in self.part_information:
2261 # now comes the real staff definition:
2263 printer ('\\context %s = "%s" << ' % (sub_staff_type, staff_id))
2265 printer ('\\context %s << ' % sub_staff_type)
2267 printer.dump("\mergeDifferentlyDottedOn\mergeDifferentlyHeadedOn")
2270 nr_voices = len (voices)
2271 for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
2273 voice_count_text = ''
2276 The next line contains a bug: The voices might not appear in numerical order! Some voices might be missing e.g. if the xml file contains only voice one, three and four, this would result in: \voiceOne, \voiceTwo and \voiceThree. This causes wrong stem directions and collisions.
2278 voice_count_text = {1: ' \\voiceOne', 2: ' \\voiceTwo', 3: ' \\voiceThree'}.get (n, ' \\voiceFour')
2279 printer ('\\context %s = "%s" {%s %s \\%s }' % (self.voice_command, v, get_transpose ("string"), voice_count_text, v))
2283 printer ('\\new Lyrics \\lyricsto "%s" { \\set stanza = "%s." \\%s }' % (v, lyrics_id, l))
2287 printer ('\context FiguredBass = "%s" \\%s' % (figuredbass, figuredbass))
2289 #printer.dump ("test") #prints test after each definition of a context.
2291 #printer.dump ("test") #prints test after each definition of a context.
2293 def print_ly (self, printer):
2294 if self.part_information and len (self.part_information) > 1:
2295 self.stafftype = "PianoStaff"
2296 self.substafftype = "Staff"
2297 #printer.dump ('test')
2298 StaffGroup.print_ly (self, printer)
2301 class TabStaff (Staff):
2302 def __init__ (self, command="TabStaff"):
2303 Staff.__init__ (self, command)
2304 self.string_tunings = []
2305 self.tablature_format = None
2306 self.voice_command = "TabVoice"
2307 def print_ly_overrides (self, printer):
2308 if self.string_tunings or self.tablature_format:
2309 printer.dump ("\\with {")
2310 if self.string_tunings:
2311 printer.dump ("stringTunings = #`(")
2312 for i in self.string_tunings:
2313 printer.dump (",%s" % i.lisp_expression ())
2315 if self.tablature_format:
2316 printer.dump ("tablatureFormat = #%s" % self.tablature_format)
2320 class DrumStaff (Staff):
2321 def __init__ (self, command="DrumStaff"):
2322 Staff.__init__ (self, command)
2323 self.drum_style_table = None
2324 self.voice_command = "DrumVoice"
2325 def print_ly_overrides (self, printer):
2326 if self.drum_style_table:
2327 printer.dump ("\with {")
2328 printer.dump ("drumStyleTable = #%s" % self.drum_style_table)
2331 class RhythmicStaff (Staff):
2332 def __init__ (self, command="RhythmicStaff"):
2333 Staff.__init__ (self, command)
2336 #def print_staffgroup_closing_brackets (self, printer): #test see class Score / class Staff
2337 # printer.dump ("test")
2340 def __init__ (self):
2342 Constructs a new Score object.
2344 self.contents = None
2345 self.create_midi = False
2347 def set_contents (self, contents):
2348 self.contents = contents
2350 def set_part_information (self, part_id, staves_info):
2352 self.contents.set_part_information (part_id, staves_info)
2354 def set_tempo (self, tempo):
2356 Set the tempo attribute of the Score.
2357 This attribute can be used in L{print_ly} for the midi output (see L{musicxml.Sound}).
2359 @param tempo: The value of the tempo, in beats per minute.
2364 # def print_staffgroup_closing_brackets (self, printer): #test see class Score / class Staff
2365 # printer.dump ("test")
2367 def print_ly (self, printer):
2369 Print the content of the score to the printer, in lilypond format.
2371 @param printer: A printer given to display correctly the output.
2372 @type printer: L{Output_printer<musicexp.Output_printer>}
2374 self.create_midi = get_create_midi()
2375 printer.dump("\\score {")
2381 self.contents.print_ly(printer)
2382 #printer.dump ("test") prints test once before the >> of the score block, independent of the existence of a staffgroup.
2383 #if StaffGroup == False: # True or False: nothing happens.
2384 # printer.dump ('>>')
2387 #StaffGroup.print_staffgroup_closing_brackets(self, printer) #TypeError: unbound method print_staffgroup_closing_brackets() must be called with StaffGroup instance as first argument (got Score instance instead)
2388 #print_staffgroup_closing_brackets(self, printer) #NameError: global name 'print_staffgroup_closing_brackets' is not defined. prints test once before the >> of the score block, independent of the existence of a staffgroup.
2389 printer.dump ("\\layout {}")
2391 # If the --midi option was not passed to musicxml2ly, that comments the "midi" line
2392 if self.create_midi:
2395 printer.dump("\\score {")
2397 printer.dump("\\unfoldRepeats \\articulate {")
2399 self.contents.print_ly(printer)
2403 printer.dump ("% To create MIDI output, uncomment the following line:")
2406 printer.dump ("\\midi {\\tempo 4 = "+self.tempo+" }")
2413 bflat.alteration = -1
2423 print bflat.semitones()
2424 print bflat.transposed (fifth), bflat.transposed (fifth).transposed (fifth)
2425 print bflat.transposed (fifth).transposed (fifth).transposed (fifth)
2427 print bflat.semitones(), 'down'
2428 print bflat.transposed (down)
2429 print bflat.transposed (down).transposed (down)
2430 print bflat.transposed (down).transposed (down).transposed (down)
2434 def test_printer ():
2442 m = SequentialMusic()
2443 m.append (make_note ())
2444 m.append (make_note ())
2445 m.append (make_note ())
2448 t = TimeScaledMusic ()
2454 m = SequentialMusic ()
2455 m.append (make_tup ())
2456 m.append (make_tup ())
2457 m.append (make_tup ())
2459 printer = Output_printer()
2460 m.print_ly (printer)
2464 m = SequentialMusic()
2468 n.duration.duration_log = l
2470 evc.insert_around (None, n, 0)
2471 m.insert_around (None, evc, 0)
2475 n.duration.duration_log = l
2477 evc.insert_around (None, n, 0)
2478 m.insert_around (None, evc, 0)
2482 n.duration.duration_log = l
2484 evc.insert_around (None, n, 0)
2485 m.insert_around (None, evc, 0)
2489 m.insert_around (None, evc, 0)
2494 tonic.alteration = -2
2495 n = KeySignatureChange()
2496 n.tonic = tonic.copy()
2497 n.scale = [0, 0, -2, 0, 0, -2, -2]
2499 evc.insert_around (None, n, 0)
2500 m.insert_around (None, evc, 0)
2505 if __name__ == '__main__':
2511 expr.set_start (Rational (0))
2512 print expr.ly_expression()
2513 start = Rational (0, 4)
2514 stop = Rational (4, 2)
2515 def sub(x, start=start, stop=stop):
2516 ok = x.start >= start and x.start + x.get_length() <= stop
2519 print expr.lisp_sub_expression(sub)