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 base_string = '%s\"%s\"'
1366 base_string = '%s\markup{ ' + self.markup + ' {%s} }'
1367 return base_string % (self.direction_mod (), self.text)
1369 class ArticulationEvent (Event):
1370 def __init__ (self):
1371 Event.__init__ (self)
1373 self.force_direction = None
1374 def wait_for_note (self):
1377 def direction_mod (self):
1378 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '')
1380 def ly_expression (self):
1381 return '%s\\%s' % (self.direction_mod (), self.type)
1383 class ShortArticulationEvent (ArticulationEvent):
1384 def direction_mod (self):
1386 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1387 def ly_expression (self):
1389 return '%s%s' % (self.direction_mod (), self.type)
1393 class NoDirectionArticulationEvent (ArticulationEvent):
1395 def is_breathing_sign(self):
1396 return self.type == 'breathe'
1398 def print_after_note(self, printer):
1399 # The breathing sign should, according to current LilyPond
1400 # praxis, be treated as an independent musical
1401 # event. Consequently, it should be printed _after_ the note
1402 # to which it is attached.
1403 if self.is_breathing_sign():
1404 printer.dump(r'\breathe')
1406 def ly_expression (self):
1407 if self.type and not self.is_breathing_sign():
1408 return '\\%s' % self.type
1412 class MarkupEvent (ShortArticulationEvent):
1413 def __init__ (self):
1414 ArticulationEvent.__init__ (self)
1415 self.contents = None
1416 def ly_expression (self):
1418 return "%s\\markup { %s }" % (self.direction_mod (), self.contents)
1422 class FretEvent (MarkupEvent):
1423 def __init__ (self):
1424 MarkupEvent.__init__ (self)
1425 self.force_direction = 1
1430 def ly_expression (self):
1432 if self.strings <> 6:
1433 val += "w:%s;" % self.strings
1435 val += "h:%s;" % self.frets
1436 if self.barre and len (self.barre) >= 3:
1437 val += "c:%s-%s-%s;" % (self.barre[0], self.barre[1], self.barre[2]+get_transpose("integer"))
1438 have_fingering = False
1439 for i in self.elements:
1441 val += "%s-%s" % (i[0], i[1]+(get_transpose("integer"),'')[isinstance(i[1],str)])
1443 have_fingering = True
1449 return "%s\\markup { \\fret-diagram #\"%s\" }" % (self.direction_mod (), val)
1453 class FretBoardNote (Music):
1454 def __init__ (self):
1455 Music.__init__ (self)
1458 self.fingering = None
1459 def ly_expression (self):
1460 str = self.pitch.ly_expression()
1462 str += "-%s" % self.fingering
1464 str += "\%s" % self.string
1467 class FretBoardEvent (NestedMusic):
1468 def __init__ (self):
1469 NestedMusic.__init__ (self)
1470 self.duration = None
1471 def print_ly (self, printer):
1472 fretboard_notes = [n for n in self.elements if isinstance (n, FretBoardNote)]
1475 for n in fretboard_notes:
1476 notes.append (n.ly_expression ())
1477 contents = string.join (notes)
1478 printer ('<%s>%s' % (contents,self.duration))
1480 class FunctionWrapperEvent (Event):
1481 def __init__ (self, function_name=None):
1482 Event.__init__ (self)
1483 self.function_name = function_name
1484 def pre_note_ly (self, is_chord_element):
1485 if self.function_name:
1486 return "\\%s" % self.function_name
1489 def pre_chord_ly (self):
1491 def ly_expression (self):
1492 if self.function_name:
1493 return "\\%s" % self.function_name
1497 class ParenthesizeEvent (FunctionWrapperEvent):
1498 def __init__ (self):
1499 FunctionWrapperEvent.__init__ (self, "parenthesize")
1501 class StemEvent (Event):
1503 A class to take care of stem values (up, down, double, none)
1505 def __init__ (self):
1506 Event.__init__ (self)
1508 def pre_chord_ly (self):
1510 return "\\%s" % self.value
1513 def pre_note_ly (self, is_chord_element):
1515 def ly_expression (self):
1516 return self.pre_chord_ly ()
1518 class NotestyleEvent (Event): #class changed by DaLa: additional attribute color
1519 def __init__ (self):
1520 Event.__init__ (self)
1524 def pre_chord_ly (self):
1527 return_string += " \\once \\override NoteHead #'style = #%s" % self.style
1529 return_string += " \\once \\override NoteHead #'color = #(rgb-color %s %s %s)" % (self.color[0], self.color[1], self.color[2])
1530 return return_string
1531 def pre_note_ly (self, is_chord_element):
1532 if self.style and is_chord_element:
1533 return "\\tweak style #%s" % self.style
1536 def ly_expression (self):
1537 return self.pre_chord_ly ()
1539 class StemstyleEvent (Event): #class added by DaLa
1540 def __init__ (self):
1541 Event.__init__ (self)
1543 def pre_chord_ly (self):
1545 return "\\once \\override Stem #'color = #(rgb-color %s %s %s)" % (self.color[0], self.color[1], self.color[2])
1548 def pre_note_ly (self, is_chord_element):
1550 def ly_expression (self):
1551 return self.pre_chord_ly ()
1555 def __init__ (self):
1559 return self.ly_expression()
1560 def ly_expression (self):
1561 return pitch_generating_function (self)
1563 class ChordModification:
1564 def __init__ (self):
1568 def ly_expression (self):
1570 val = {1: ".", -1: "^" }.get (self.type, "")
1571 val += "%s" % self.step
1572 val += {1: "+", -1: "-"}.get (self.alteration, "")
1577 class ChordNameEvent (Event):
1578 def __init__ (self):
1579 Event.__init__ (self)
1582 self.duration = None
1583 self.modifications = []
1585 def add_modification (self, mod):
1586 self.modifications.append (mod)
1587 def ly_expression (self):
1591 value = self.root.ly_expression ()
1593 value += self.duration.ly_expression ()
1595 value = self.kind.format(value)
1596 # First print all additions/changes, and only afterwards all subtractions
1597 for m in self.modifications:
1599 value += m.ly_expression ()
1600 for m in self.modifications:
1602 value += m.ly_expression ()
1604 value += "/+%s" % self.bass.ly_expression ()
1608 class TremoloEvent(ArticulationEvent):
1610 Event.__init__(self)
1613 def ly_expression(self):
1615 if self.strokes and int(self.strokes) > 0:
1616 # ly_dur is a global variable defined in class Duration
1617 # ly_dur stores the value of the reciprocal values of notes
1618 # ly_dur is used here to check the current note duration
1619 # if the duration is smaller than 8, e.g.
1620 # quarter, half and whole notes,
1621 # `:(2 ** (2 + number of tremolo strokes))'
1622 # should be appended to the pitch and duration, e.g.
1623 # 1 stroke: `c4:8' or `c2:8' or `c1:8'
1624 # 2 strokes: `c4:16' or `c2:16' or `c1:16'
1626 # else (if ly_dur is equal to or greater than 8):
1627 # we need to make sure that the tremolo value that is to
1628 # be appended to the pitch and duration is twice the
1629 # duration (if there is only one tremolo stroke.
1630 # Each additional stroke doubles the tremolo value, e.g.:
1631 # 1 stroke: `c8:16', `c16:32', `c32:64', ...
1632 # 2 strokes: `c8:32', `c16:64', `c32:128', ...
1635 ly_str += ':%s' % (2 ** (2 + int(self.strokes)))
1637 ly_str += ':%s' % (2 ** int((math.log(ly_dur, 2)) + int(self.strokes)))
1640 class BendEvent (ArticulationEvent):
1641 def __init__ (self):
1642 Event.__init__ (self)
1644 def ly_expression (self):
1645 if self.alter != None:
1646 return "-\\bendAfter #%s" % self.alter
1650 class RhythmicEvent(Event):
1651 def __init__ (self):
1652 Event.__init__ (self)
1653 self.duration = Duration()
1654 self.associated_events = []
1656 def add_associated_event (self, ev):
1658 self.associated_events.append (ev)
1660 def pre_chord_ly (self):
1661 return [ev.pre_chord_ly () for ev in self.associated_events]
1663 def pre_note_ly (self, is_chord_element):
1664 return [ev.pre_note_ly (is_chord_element) for ev in self.associated_events]
1666 def ly_expression_pre_note (self, is_chord_element):
1667 res = string.join (self.pre_note_ly (is_chord_element), ' ')
1672 def get_length (self):
1673 return self.duration.get_length()
1675 def get_properties (self):
1676 return ("'duration %s"
1677 % self.duration.lisp_expression ())
1679 class RestEvent (RhythmicEvent):
1680 def __init__ (self):
1681 RhythmicEvent.__init__ (self)
1684 def ly_expression (self):
1685 res = self.ly_expression_pre_note (False)
1687 return res + "%s%s\\rest" % (self.pitch.ly_expression (), self.duration.ly_expression ())
1689 return 'r%s' % self.duration.ly_expression ()
1691 def print_ly (self, printer):
1692 for ev in self.associated_events:
1693 ev.print_ly (printer)
1694 # if hasattr(self, 'color'):
1695 # printer.print_note_color("NoteHead", self.color)
1696 # printer.print_note_color("Stem", self.color)
1697 # printer.print_note_color("Beam", self.color)
1699 self.pitch.print_ly (printer)
1700 self.duration.print_ly (printer)
1704 self.duration.print_ly (printer)
1706 class SkipEvent (RhythmicEvent):
1707 def ly_expression (self):
1708 return 's%s' % self.duration.ly_expression ()
1710 class NoteEvent(RhythmicEvent):
1711 def __init__ (self):
1712 RhythmicEvent.__init__ (self)
1714 self.drum_type = None
1715 self.cautionary = False
1716 self.forced_accidental = False
1718 def get_properties (self):
1719 str = RhythmicEvent.get_properties (self)
1722 str += self.pitch.lisp_expression ()
1723 elif self.drum_type:
1724 str += "'drum-type '%s" % self.drum_type
1728 def pitch_mods (self):
1731 excl_question += '?'
1732 if self.forced_accidental:
1733 excl_question += '!'
1735 return excl_question
1737 def ly_expression (self):
1738 # obtain all stuff that needs to be printed before the note:
1739 res = self.ly_expression_pre_note (True)
1741 return res + '%s%s%s' % (self.pitch.ly_expression (),
1743 self.duration.ly_expression ())
1744 elif self.drum_type:
1745 return res + '%s%s' (self.drum_type,
1746 self.duration.ly_expression ())
1748 def chord_element_ly (self):
1749 # obtain all stuff that needs to be printed before the note:
1750 res = self.ly_expression_pre_note (True)
1752 return res + '%s%s' % (self.pitch.ly_expression (),
1754 elif self.drum_type:
1755 return res + '%s%s' (self.drum_type)
1758 def print_ly (self, printer):
1759 for ev in self.associated_events:
1760 ev.print_ly (printer)
1761 if hasattr(self, 'color'):
1762 printer.print_note_color("NoteHead", self.color)
1763 printer.print_note_color("Stem", self.color)
1764 printer.print_note_color("Beam", self.color)
1767 self.pitch.print_ly (printer)
1768 printer (self.pitch_mods ())
1770 printer (self.drum_type)
1772 self.duration.print_ly (printer)
1774 # if hasattr(self, 'color'):
1775 # printer.print_note_color("NoteHead")
1776 # printer.print_note_color("Stem")
1777 # printer.print_note_color("Beam")
1779 class KeySignatureChange (Music):
1780 def __init__ (self):
1781 Music.__init__ (self)
1784 self.non_standard_alterations = None
1786 def format_non_standard_alteration (self, a):
1787 alter_dict = { -2: ",DOUBLE-FLAT",
1788 - 1.5: ",THREE-Q-FLAT",
1790 - 0.5: ",SEMI-FLAT",
1794 1.5: ",THREE-Q-SHARP",
1797 accidental = alter_dict[a[1]]
1799 ly.warning (_ ("Unable to convert alteration %s to a lilypond expression") % a[1])
1802 return "( %s . %s )" % (a[0], accidental)
1804 return "(( %s . %s ) . %s )" % (a[2], a[0], accidental)
1808 def ly_expression (self):
1810 return '\\key %s \\%s' % (self.tonic.ly_step_expression (),
1812 elif self.non_standard_alterations:
1813 alterations = [self.format_non_standard_alteration (a) for
1814 a in self.non_standard_alterations]
1815 return "\\set Staff.keyAlterations = #`(%s)" % string.join (alterations, " ")
1819 class ShiftDurations (MusicWrapper):
1820 def __init__ (self):
1821 MusicWrapper.__init__ (self)
1824 def set_shift_durations_parameters(self, timeSigChange):
1825 self.params = timeSigChange.get_shift_durations_parameters()
1827 def print_ly (self, func):
1828 func (' \\shiftDurations #%d #%d ' % tuple(self.params))
1829 MusicWrapper.print_ly (self, func)
1831 class TimeSignatureChange (Music):
1832 def __init__ (self):
1833 Music.__init__ (self)
1834 self.fractions = [4, 4]
1836 # Used for the --time-signature option of musicxml2ly
1837 self.originalFractions = [4, 4]
1839 def get_fractions_ratio (self):
1841 Calculate the ratio between the original time fraction and the new one.
1842 Used for the "--time-signature" option.
1844 @return: The ratio between the two time fractions.
1847 return (float(self.originalFractions[0])/self.originalFractions[1])*(float(self.fractions[1])/self.fractions[0])
1849 def get_shift_durations_parameters (self):
1850 dur = math.ceil(math.log(self.get_fractions_ratio(),2))
1851 dots = (1/self.get_fractions_ratio())/(math.pow(2,-dur))
1852 dots = int(math.log(2-dots,0.5))
1855 def format_fraction (self, frac):
1856 if isinstance (frac, list):
1857 l = [self.format_fraction (f) for f in frac]
1858 return "(" + string.join (l, " ") + ")"
1862 def ly_expression (self):
1864 # Print out the style if we have ome, but the '() should only be
1865 # forced for 2/2 or 4/4, since in all other cases we'll get numeric
1866 # signatures anyway despite the default 'C signature style!
1867 is_common_signature = self.fractions in ([2, 2], [4, 4], [4, 2])
1869 if self.style == "common":
1870 st = "\\defaultTimeSignature"
1871 elif (self.style != "'()"):
1872 st = "\\once \\override Staff.TimeSignature.style = #%s " % self.style
1873 elif (self.style != "'()") or is_common_signature:
1874 st = "\\numericTimeSignature"
1876 # Easy case: self.fractions = [n,d] => normal \time n/d call:
1877 if len (self.fractions) == 2 and isinstance (self.fractions[0], int):
1878 return st + '\\time %d/%d ' % tuple (self.fractions)
1879 elif self.fractions:
1880 return st + "\\compoundMeter #'%s" % self.format_fraction (self.fractions)
1884 class ClefChange (Music):
1885 def __init__ (self):
1886 Music.__init__ (self)
1891 def octave_modifier (self):
1892 return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self.octave, '')
1894 def clef_name (self):
1895 return {('G', 2): "treble",
1897 ('C', 1): "soprano",
1898 ('C', 2): "mezzosoprano",
1901 ('C', 5): "baritone",
1902 ('F', 3): "varbaritone",
1904 ('F', 5): "subbass",
1905 ("percussion", 2): "percussion",
1906 # Workaround: MuseScore uses PERC instead of percussion
1907 ("PERC", 2): "percussion",
1908 ("TAB", 5): get_tab_clef ()}.get ((self.type, self.position), None)
1910 def ly_expression (self):
1911 return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ())
1914 "G": ("clefs.G", -2, -6),
1915 "C": ("clefs.C", 0, 0),
1916 "F": ("clefs.F", 2, 6),
1919 def lisp_expression (self):
1921 (glyph, pos, c0) = self.clef_dict[self.type]
1925 (make-music 'SequentialMusic
1928 (make-property-set 'clefGlyph "%s") 'Staff)
1930 (make-property-set 'clefPosition %d) 'Staff)
1932 (make-property-set 'middleCPosition %d) 'Staff)))
1933 """ % (glyph, pos, c0)
1936 class Transposition (Music):
1937 def __init__ (self):
1938 Music.__init__ (self)
1940 def ly_expression (self):
1941 self.pitch._force_absolute_pitch = True
1942 return '\\transposition %s' % self.pitch.ly_expression ()
1944 class StaffChange (Music):
1945 def __init__ (self, staff):
1946 Music.__init__ (self)
1948 def ly_expression (self):
1950 return "\\change Staff=\"%s\"" % self.staff
1954 class SetEvent (Music):
1955 def __init__ (self, contextprop, value):
1956 Music.__init__ (self)
1957 self.context_prop = contextprop
1959 def ly_expression (self):
1961 return "\\set %s = %s" % (self.context_prop, self.value)
1965 class StaffLinesEvent (Music):
1966 def __init__ (self, lines):
1967 Music.__init__ (self)
1969 def ly_expression (self):
1970 if (self.lines > 0):
1971 return "\\stopStaff \\override Staff.StaffSymbol.line-count = #%s \\startStaff" % self.lines
1973 return "\\stopStaff \\revert Staff.StaffSymbol.line-count \\startStaff"
1975 class TempoMark (Music):
1976 def __init__ (self):
1977 Music.__init__ (self)
1978 self.baseduration = None
1979 self.newduration = None
1981 self.parentheses = False
1982 def set_base_duration (self, dur):
1983 self.baseduration = dur
1984 def set_new_duration (self, dur):
1985 self.newduration = dur
1986 def set_beats_per_minute (self, beats):
1988 def set_parentheses (self, parentheses):
1989 self.parentheses = parentheses
1990 def wait_for_note (self):
1992 def duration_to_markup (self, dur):
1994 # Generate the markup to print the note, use scheme mode for
1995 # ly_expression to get longa and not \longa (which causes an error)
1996 return "\\general-align #Y #DOWN \\smaller \\note #\"%s\" #UP" % dur.ly_expression(None, True)
1999 def tempo_markup_template (self):
2000 return "\\mark\\markup { \\fontsize #-2 \\line { %s } }"
2001 def ly_expression (self):
2003 if not self.baseduration:
2006 if self.parentheses:
2007 res += "\\tempo \"\" %s=%s" % (self.baseduration.ly_expression(), self.beats)
2009 res += "\\tempo %s=%s" % (self.baseduration.ly_expression(), self.beats)
2010 elif self.newduration:
2011 dm = self.duration_to_markup (self.baseduration)
2012 ndm = self.duration_to_markup (self.newduration)
2013 if self.parentheses:
2014 contents = "\"(\" %s = %s \")\"" % (dm, ndm)
2016 contents = " %s = %s " % (dm, ndm)
2017 res += self.tempo_markup_template() % contents
2022 class FiguredBassNote (Music):
2023 def __init__ (self):
2024 Music.__init__ (self)
2028 def set_prefix (self, prefix):
2029 self.prefix = prefix
2030 def set_suffix (self, suffix):
2031 self.prefix = suffix
2032 def set_number (self, number):
2033 self.number = number
2034 def ly_expression (self):
2047 class FiguredBassEvent (NestedMusic):
2048 def __init__ (self):
2049 NestedMusic.__init__ (self)
2050 self.duration = None
2051 self.real_duration = 0
2052 self.parentheses = False
2054 def set_duration (self, dur):
2056 def set_parentheses (self, par):
2057 self.parentheses = par
2058 def set_real_duration (self, dur):
2059 self.real_duration = dur
2061 def print_ly (self, printer):
2062 figured_bass_events = [e for e in self.elements if
2063 isinstance (e, FiguredBassNote)]
2064 if figured_bass_events:
2066 for x in figured_bass_events:
2067 notes.append (x.ly_expression ())
2068 contents = string.join (notes)
2069 if self.parentheses:
2070 contents = '[%s]' % contents
2071 printer ('<%s>' % contents)
2072 self.duration.print_ly (printer)
2075 class MultiMeasureRest(Music):
2077 def lisp_expression (self):
2080 'MultiMeasureRestMusicGroup
2082 (list (make-music (quote BarCheck))
2087 'MultiMeasureRestEvent
2090 (make-music (quote BarCheck))))
2091 """ % self.duration.lisp_expression ()
2093 def ly_expression (self):
2094 return 'R%s' % self.duration.ly_expression ()
2097 class Break (Music):
2098 def __init__ (self, tp="break"):
2099 Music.__init__ (self)
2101 def print_ly (self, printer):
2103 printer.dump ("\\%s" % self.type)
2106 def __init__ (self, command="StaffGroup"):
2107 self.stafftype = command
2109 self.instrument_name = None
2111 self.short_instrument_name = None
2115 self.is_group = True
2116 self.context_modifications = []
2117 # part_information is a list with entries of the form
2118 # [staffid, voicelist]
2119 # where voicelist is a list with entries of the form
2120 # [voiceid1, [lyricsid11, lyricsid12,...] ]
2121 self.part_information = None
2123 def append_staff (self, staff):
2124 self.children.append (staff)
2126 def set_part_information (self, part_name, staves_info):
2127 if part_name == self.id:
2128 self.part_information = staves_info
2130 for c in self.children:
2131 c.set_part_information (part_name, staves_info)
2133 def add_context_modification (self, modification):
2134 self.context_modifications.append (modification)
2136 def print_ly_contents (self, printer):
2137 for c in self.children:
2139 c.print_ly (printer)
2140 #Intention: I want to put the content of new StaffGroup in angled brackets (<< >>)
2141 #printer.dump ("test")# test is printed twice at the end of a staffgroup with two staves.
2142 #printer ("test") # test is printed twice at the end of a staffgroup with two staves.
2144 def needs_with (self):
2146 needs_with |= self.spanbar == "no"
2147 needs_with |= self.instrument_name != None
2148 needs_with |= self.short_instrument_name != None
2149 needs_with |= (self.symbol != None) and (self.symbol != "bracket")
2152 def print_ly_context_mods (self, printer):
2153 if self.instrument_name or self.short_instrument_name:
2154 printer.dump ("\\consists \"Instrument_name_engraver\"")
2155 if self.spanbar == "no":
2156 printer.dump ("\\hide SpanBar")
2157 brack = {"brace": "SystemStartBrace",
2158 "none": "SystemStartBar",
2159 "line": "SystemStartSquare"}.get (self.symbol, None)
2161 printer.dump ("systemStartDelimiter = #'%s" % brack)
2163 def print_ly_overrides (self, printer):
2164 needs_with = self.needs_with () | (len (self.context_modifications) > 0);
2166 printer.dump ("\\with {")
2167 self.print_ly_context_mods (printer)
2168 for m in self.context_modifications:
2170 printer.dump ("} <<")
2172 #print a single << after StaffGroup only when the with-block is not needed.
2173 #This doesn't work. << is printed before and after StaffGroup!
2175 # printer.dump (" <<")
2176 #prints loads off << before and after StaffGroup and before \set Staff.instrumentName
2177 #elif not needs_with:
2178 # printer.dump (" <<")
2180 def print_chords(self, printer):
2182 for [staff_id, voices] in self.part_information:
2183 for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
2185 printer ('\context ChordNames = "%s" {%s \\%s}' % (chordnames, get_transpose ("string"), chordnames))
2190 def print_fretboards(self, printer):
2192 for [staff_id, voices] in self.part_information:
2193 for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
2195 printer ('\context FretBoards = "%s" {%s \\%s}' % (fretboards, get_transpose ("string"), fretboards))
2200 def print_ly (self, printer):
2201 self.print_chords(printer)
2202 self.print_fretboards(printer)
2204 printer.dump ("\\new %s" % self.stafftype)
2205 self.print_ly_overrides (printer)
2210 if self.stafftype and self.instrument_name:
2211 printer.dump ("\\set %s.instrumentName = %s" % (self.stafftype,
2212 escape_instrument_string (self.instrument_name)))
2214 if self.stafftype and self.short_instrument_name:
2215 printer.dump ("\\set %s.shortInstrumentName = %s" % (self.stafftype,
2216 escape_instrument_string (self.short_instrument_name)))
2220 r'\set {stafftype}.midiInstrument = #"{sound}"'.format(
2221 stafftype=self.stafftype, sound=self.sound))
2223 self.print_ly_contents (printer)
2230 class Staff (StaffGroup):
2231 def __init__ (self, command="Staff"):
2232 StaffGroup.__init__ (self, command)
2233 self.is_group = False
2235 self.voice_command = "Voice"
2236 self.substafftype = None
2239 def needs_with (self):
2242 def print_ly_context_mods (self, printer):
2243 #printer.dump ("test") #does nothing.
2246 def print_ly_contents (self, printer):
2247 if not self.id or not self.part_information:
2249 sub_staff_type = self.substafftype
2250 if not sub_staff_type:
2251 sub_staff_type = self.stafftype
2252 #printer.dump ("test") #prints test in each staff after the definitions of the instrument name and before the definition of the contexts.
2255 for [staff_id, voices] in self.part_information:
2256 # now comes the real staff definition:
2258 printer ('\\context %s = "%s" << ' % (sub_staff_type, staff_id))
2260 printer ('\\context %s << ' % sub_staff_type)
2262 printer.dump("\mergeDifferentlyDottedOn\mergeDifferentlyHeadedOn")
2265 nr_voices = len (voices)
2266 for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
2268 voice_count_text = ''
2271 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.
2273 voice_count_text = {1: ' \\voiceOne', 2: ' \\voiceTwo', 3: ' \\voiceThree'}.get (n, ' \\voiceFour')
2274 printer ('\\context %s = "%s" {%s %s \\%s }' % (self.voice_command, v, get_transpose ("string"), voice_count_text, v))
2278 printer ('\\new Lyrics \\lyricsto "%s" { \\set stanza = "%s." \\%s }' % (v, lyrics_id, l))
2282 printer ('\context FiguredBass = "%s" \\%s' % (figuredbass, figuredbass))
2284 #printer.dump ("test") #prints test after each definition of a context.
2286 #printer.dump ("test") #prints test after each definition of a context.
2288 def print_ly (self, printer):
2289 if self.part_information and len (self.part_information) > 1:
2290 self.stafftype = "PianoStaff"
2291 self.substafftype = "Staff"
2292 #printer.dump ('test')
2293 StaffGroup.print_ly (self, printer)
2296 class TabStaff (Staff):
2297 def __init__ (self, command="TabStaff"):
2298 Staff.__init__ (self, command)
2299 self.string_tunings = []
2300 self.tablature_format = None
2301 self.voice_command = "TabVoice"
2302 def print_ly_overrides (self, printer):
2303 if self.string_tunings or self.tablature_format:
2304 printer.dump ("\\with {")
2305 if self.string_tunings:
2306 printer.dump ("stringTunings = #`(")
2307 for i in self.string_tunings:
2308 printer.dump (",%s" % i.lisp_expression ())
2310 if self.tablature_format:
2311 printer.dump ("tablatureFormat = #%s" % self.tablature_format)
2315 class DrumStaff (Staff):
2316 def __init__ (self, command="DrumStaff"):
2317 Staff.__init__ (self, command)
2318 self.drum_style_table = None
2319 self.voice_command = "DrumVoice"
2320 def print_ly_overrides (self, printer):
2321 if self.drum_style_table:
2322 printer.dump ("\with {")
2323 printer.dump ("drumStyleTable = #%s" % self.drum_style_table)
2326 class RhythmicStaff (Staff):
2327 def __init__ (self, command="RhythmicStaff"):
2328 Staff.__init__ (self, command)
2331 #def print_staffgroup_closing_brackets (self, printer): #test see class Score / class Staff
2332 # printer.dump ("test")
2335 def __init__ (self):
2337 Constructs a new Score object.
2339 self.contents = None
2340 self.create_midi = False
2342 def set_contents (self, contents):
2343 self.contents = contents
2345 def set_part_information (self, part_id, staves_info):
2347 self.contents.set_part_information (part_id, staves_info)
2349 def set_tempo (self, tempo):
2351 Set the tempo attribute of the Score.
2352 This attribute can be used in L{print_ly} for the midi output (see L{musicxml.Sound}).
2354 @param tempo: The value of the tempo, in beats per minute.
2359 # def print_staffgroup_closing_brackets (self, printer): #test see class Score / class Staff
2360 # printer.dump ("test")
2362 def print_ly (self, printer):
2364 Print the content of the score to the printer, in lilypond format.
2366 @param printer: A printer given to display correctly the output.
2367 @type printer: L{Output_printer<musicexp.Output_printer>}
2369 self.create_midi = get_create_midi()
2370 printer.dump("\\score {")
2376 self.contents.print_ly(printer)
2377 #printer.dump ("test") prints test once before the >> of the score block, independent of the existence of a staffgroup.
2378 #if StaffGroup == False: # True or False: nothing happens.
2379 # printer.dump ('>>')
2382 #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)
2383 #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.
2384 printer.dump ("\\layout {}")
2386 # If the --midi option was not passed to musicxml2ly, that comments the "midi" line
2387 if self.create_midi:
2390 printer.dump("\\score {")
2392 printer.dump("\\unfoldRepeats \\articulate {")
2394 self.contents.print_ly(printer)
2398 printer.dump ("% To create MIDI output, uncomment the following line:")
2401 printer.dump ("\\midi {\\tempo 4 = "+self.tempo+" }")
2408 bflat.alteration = -1
2418 print bflat.semitones()
2419 print bflat.transposed (fifth), bflat.transposed (fifth).transposed (fifth)
2420 print bflat.transposed (fifth).transposed (fifth).transposed (fifth)
2422 print bflat.semitones(), 'down'
2423 print bflat.transposed (down)
2424 print bflat.transposed (down).transposed (down)
2425 print bflat.transposed (down).transposed (down).transposed (down)
2429 def test_printer ():
2437 m = SequentialMusic()
2438 m.append (make_note ())
2439 m.append (make_note ())
2440 m.append (make_note ())
2443 t = TimeScaledMusic ()
2449 m = SequentialMusic ()
2450 m.append (make_tup ())
2451 m.append (make_tup ())
2452 m.append (make_tup ())
2454 printer = Output_printer()
2455 m.print_ly (printer)
2459 m = SequentialMusic()
2463 n.duration.duration_log = l
2465 evc.insert_around (None, n, 0)
2466 m.insert_around (None, evc, 0)
2470 n.duration.duration_log = l
2472 evc.insert_around (None, n, 0)
2473 m.insert_around (None, evc, 0)
2477 n.duration.duration_log = l
2479 evc.insert_around (None, n, 0)
2480 m.insert_around (None, evc, 0)
2484 m.insert_around (None, evc, 0)
2489 tonic.alteration = -2
2490 n = KeySignatureChange()
2491 n.tonic = tonic.copy()
2492 n.scale = [0, 0, -2, 0, 0, -2, -2]
2494 evc.insert_around (None, n, 0)
2495 m.insert_around (None, evc, 0)
2500 if __name__ == '__main__':
2506 expr.set_start (Rational (0))
2507 print expr.ly_expression()
2508 start = Rational (0, 4)
2509 stop = Rational (4, 2)
2510 def sub(x, start=start, stop=stop):
2511 ok = x.start >= start and x.start + x.get_length() <= stop
2514 print expr.lisp_sub_expression(sub)