1 # -*- coding: utf-8 -*-
10 from rational import Rational
12 # Store previously converted pitch for \relative conversion as a global state variable
14 relative_pitches = False
17 ly.stderr_write ((_ ("warning: %s") % str) + "\n")
20 def escape_instrument_string (input_string):
21 retstring = string.replace (input_string, "\"", "\\\"")
22 if re.match ('.*[\r\n]+.*', retstring):
23 rx = re.compile (r'[\n\r]+')
24 strings = rx.split (retstring)
25 retstring = "\\markup { \\column { "
27 retstring += "\\line {\"" + s + "\"} "
30 retstring = "\"" + retstring + "\""
33 class Output_stack_element:
35 self.factor = Rational (1)
37 o = Output_stack_element()
38 o.factor = self.factor
43 """A class that takes care of formatting (eg.: indenting) a
44 Music expression as a .ly file.
52 self._file = sys.stdout
54 self._output_state_stack = [Output_stack_element()]
55 self._skipspace = False
56 self._last_duration = None
58 def set_file (self, file):
61 def dump_version (self):
63 self.print_verbatim ('\\version "@TOPLEVEL_VERSION@"')
66 def get_indent (self):
67 return self._nesting * self._indent
70 last = self._output_state_stack[-1]
71 self._output_state_stack.append (last.copy())
73 def add_factor (self, factor):
75 self._output_state_stack[-1].factor *= factor
78 del self._output_state_stack[-1]
79 if not self._output_state_stack:
82 def duration_factor (self):
83 return self._output_state_stack[-1].factor
85 def print_verbatim (self, str):
88 def unformatted_output (self, str):
89 # don't indent on \< and indent only once on <<
90 self._nesting += ( str.count ('<')
91 - str.count ('\<') - str.count ('<<')
93 self._nesting -= ( str.count ('>') - str.count ('\>') - str.count ('>>')
94 - str.count ('->') - str.count ('_>')
97 self.print_verbatim (str)
99 def print_duration_string (self, str):
100 if self._last_duration == str:
103 self.unformatted_output (str)
105 def add_word (self, str):
106 if (len (str) + 1 + len (self._line) > self._line_len):
108 self._skipspace = True
110 if not self._skipspace:
112 self.unformatted_output (str)
113 self._skipspace = False
116 self._file.write (self._line + '\n')
117 self._line = ' ' * self._indent * self._nesting
118 self._skipspace = True
120 def skipspace (self):
121 self._skipspace = True
123 def __call__(self, arg):
126 def dump (self, str):
128 self._skipspace = False
129 self.unformatted_output (str)
131 words = string.split (str)
144 self.duration_log = 0
146 self.factor = Rational (1)
148 def lisp_expression (self):
149 return '(ly:make-duration %d %d %d %d)' % (self.duration_log,
151 self.factor.numerator (),
152 self.factor.denominator ())
155 def ly_expression (self, factor = None, scheme_mode = False):
159 if self.duration_log < 0:
161 longer_dict = {-1: "breve", -2: "longa"}
163 longer_dict = {-1: "\\breve", -2: "\\longa"}
164 str = longer_dict.get (self.duration_log, "1")
166 str = '%d' % (1 << self.duration_log)
169 if factor <> Rational (1,1):
170 if factor.denominator () <> 1:
171 str += '*%d/%d' % (factor.numerator (), factor.denominator ())
173 str += '*%d' % factor.numerator ()
177 def print_ly (self, outputter):
178 str = self.ly_expression (self.factor / outputter.duration_factor ())
179 outputter.print_duration_string (str)
182 return self.ly_expression()
187 d.duration_log = self.duration_log
188 d.factor = self.factor
191 def get_length (self):
192 dot_fact = Rational( (1 << (1 + self.dots))-1,
195 log = abs (self.duration_log)
197 if self.duration_log < 0:
198 base = Rational (dur)
200 base = Rational (1, dur)
202 return base * dot_fact * self.factor
205 # Implement the different note names for the various languages
206 def pitch_generic (pitch, notenames, accidentals):
207 str = notenames[pitch.step]
208 halftones = int (pitch.alteration)
210 str += accidentals[0] * (-halftones)
211 elif pitch.alteration > 0:
212 str += accidentals[3] * (halftones)
213 # Handle remaining fraction to pitch.alteration (for microtones)
214 if (halftones != pitch.alteration):
215 if None in accidentals[1:3]:
216 warning (_ ("Language does not support microtones contained in the piece"))
219 str += {-0.5: accidentals[1], 0.5: accidentals[2]}[pitch.alteration-halftones]
221 warning (_ ("Language does not support microtones contained in the piece"))
224 def pitch_general (pitch):
225 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['es', 'eh', 'ih', 'is'])
226 return str.replace ('aes', 'as').replace ('ees', 'es')
228 def pitch_nederlands (pitch):
229 return pitch_general (pitch)
231 def pitch_english (pitch):
232 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['f', 'qf', 'qs', 's'])
233 return str.replace ('aes', 'as').replace ('ees', 'es')
235 def pitch_deutsch (pitch):
236 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['es', 'eh', 'ih', 'is'])
237 return str.replace ('hes', 'b').replace ('aes', 'as').replace ('ees', 'es')
239 def pitch_norsk (pitch):
240 return pitch_deutsch (pitch)
242 def pitch_svenska (pitch):
243 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', None, None, 'iss'])
244 return str.replace ('hess', 'b').replace ('aes', 'as').replace ('ees', 'es')
246 def pitch_italiano (pitch):
247 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', 'sb', 'sd', 'd'])
250 def pitch_catalan (pitch):
251 return pitch_italiano (pitch)
253 def pitch_espanol (pitch):
254 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 's'])
257 def pitch_vlaams (pitch):
258 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 'k'])
261 def set_pitch_language (language):
262 global pitch_generating_function
264 "nederlands": pitch_nederlands,
265 "english": pitch_english,
266 "deutsch": pitch_deutsch,
267 "norsk": pitch_norsk,
268 "svenska": pitch_svenska,
269 "italiano": pitch_italiano,
270 "catalan": pitch_catalan,
271 "espanol": pitch_espanol,
272 "vlaams": pitch_vlaams}
273 pitch_generating_function = function_dict.get (language, pitch_general)
275 # global variable to hold the formatting function.
276 pitch_generating_function = pitch_general
284 self._force_absolute_pitch = False
287 return self.ly_expression()
289 def transposed (self, interval):
291 c.alteration += interval.alteration
292 c.step += interval.step
293 c.octave += interval.octave
296 target_st = self.semitones() + interval.semitones()
297 c.alteration += target_st - c.semitones()
304 c.octave += c.step / 7
307 def lisp_expression (self):
308 return '(ly:make-pitch %d %d %d)' % (self.octave,
314 p.alteration = self.alteration
316 p.octave = self.octave
320 return self.step + self.octave *7
322 def semitones (self):
323 return self.octave * 12 + [0,2,4,5,7,9,11][self.step] + self.alteration
325 def ly_step_expression (self):
326 return pitch_generating_function (self)
328 def absolute_pitch (self):
330 return "'" * (self.octave + 1)
331 elif self.octave < -1:
332 return "," * (-self.octave - 1)
336 def relative_pitch (self):
337 global previous_pitch
338 if not previous_pitch:
339 previous_pitch = self
340 return self.absolute_pitch ()
341 previous_pitch_steps = previous_pitch.octave * 7 + previous_pitch.step
342 this_pitch_steps = self.octave * 7 + self.step
343 pitch_diff = (this_pitch_steps - previous_pitch_steps)
344 previous_pitch = self
346 return "'" * ((pitch_diff + 3) / 7)
347 elif pitch_diff < -3:
348 return "," * ((-pitch_diff + 3) / 7)
352 def ly_expression (self):
353 str = self.ly_step_expression ()
354 if relative_pitches and not self._force_absolute_pitch:
355 str += self.relative_pitch ()
357 str += self.absolute_pitch ()
361 def print_ly (self, outputter):
362 outputter (self.ly_expression())
367 self.start = Rational (0)
369 self.identifier = None
371 def get_length(self):
374 def get_properties (self):
377 def has_children (self):
380 def get_index (self):
382 return self.parent.elements.index (self)
386 return self.__class__.__name__
388 def lisp_expression (self):
391 props = self.get_properties ()
393 return "(make-music '%s %s)" % (name, props)
395 def set_start (self, start):
398 def find_first (self, predicate):
403 def print_comment (self, printer, text = None):
414 lines = string.split (text, '\n')
417 printer.unformatted_output ('% ' + l)
421 def print_with_identifier (self, printer):
423 printer ("\\%s" % self.identifier)
425 self.print_ly (printer)
427 def print_ly (self, printer):
428 printer (self.ly_expression ())
430 class MusicWrapper (Music):
434 def print_ly (self, func):
435 self.element.print_ly (func)
437 class ModeChangingMusicWrapper (MusicWrapper):
439 MusicWrapper.__init__ (self)
440 self.mode = 'notemode'
442 def print_ly (self, func):
443 func ('\\%s' % self.mode)
444 MusicWrapper.print_ly (self, func)
446 class RelativeMusic (MusicWrapper):
448 MusicWrapper.__init__ (self)
449 self.basepitch = None
451 def print_ly (self, func):
452 global previous_pitch
453 global relative_pitches
454 prev_relative_pitches = relative_pitches
455 relative_pitches = True
456 previous_pitch = self.basepitch
457 if not previous_pitch:
458 previous_pitch = Pitch ()
459 func ('\\relative %s%s' % (pitch_generating_function (previous_pitch),
460 previous_pitch.absolute_pitch ()))
461 MusicWrapper.print_ly (self, func)
462 relative_pitches = prev_relative_pitches
464 class TimeScaledMusic (MusicWrapper):
466 MusicWrapper.__init__ (self)
469 self.display_number = "actual" # valid values "actual" | "both" | None
470 # Display the basic note length for the tuplet:
471 self.display_type = None # value values "actual" | "both" | None
472 self.display_bracket = "bracket" # valid values "bracket" | "curved" | None
473 self.actual_type = None # The actually played unit of the scaling
474 self.normal_type = None # The basic unit of the scaling
475 self.display_numerator = None
476 self.display_denominator = None
478 def print_ly (self, func):
479 if self.display_bracket == None:
480 func ("\\once \\override TupletBracket #'stencil = ##f")
482 elif self.display_bracket == "curved":
483 warning (_ ("Tuplet brackets of curved shape are not correctly implemented"))
484 func ("\\once \\override TupletBracket #'stencil = #ly:slur::print")
487 base_number_function = {None: "#f",
488 "actual": "tuplet-number::calc-denominator-text",
489 "both": "tuplet-number::calc-fraction-text"}.get (self.display_number, None)
490 # If we have non-standard numerator/denominator, use our custom function
491 if self.display_number == "actual" and self.display_denominator:
492 base_number_function = "(tuplet-number::non-default-tuplet-denominator-text %s)" % self.display_denominator
493 elif self.display_number == "both" and (self.display_denominator or self.display_numerator):
494 if self.display_numerator:
495 num = self.display_numerator
498 if self.display_denominator:
499 den = self.display_denominator
502 base_number_function = "(tuplet-number::non-default-tuplet-fraction-text %s %s)" % (den, num)
505 if self.display_type == "actual" and self.normal_type:
506 # Obtain the note duration in scheme-mode, i.e. \longa as \\longa
507 base_duration = self.normal_type.ly_expression (None, True)
508 func ("\\once \\override TupletNumber #'text = #(tuplet-number::append-note-wrapper %s \"%s\")" %
509 (base_number_function, base_duration))
511 elif self.display_type == "both": # TODO: Implement this using actual_type and normal_type!
512 if self.display_number == None:
513 func ("\\once \\override TupletNumber #'stencil = ##f")
515 elif self.display_number == "both":
516 den_duration = self.normal_type.ly_expression (None, True)
517 # If we don't have an actual type set, use the normal duration!
519 num_duration = self.actual_type.ly_expression (None, True)
521 num_duration = den_duration
522 if (self.display_denominator or self.display_numerator):
523 func ("\\once \\override TupletNumber #'text = #(tuplet-number::non-default-fraction-with-notes %s \"%s\" %s \"%s\")" %
524 (self.display_denominator, den_duration,
525 self.display_numerator, num_duration))
528 func ("\\once \\override TupletNumber #'text = #(tuplet-number::fraction-with-notes \"%s\" \"%s\")" %
529 (den_duration, num_duration))
532 if self.display_number == None:
533 func ("\\once \\override TupletNumber #'stencil = ##f")
535 elif self.display_number == "both":
536 func ("\\once \\override TupletNumber #'text = #%s" % base_number_function)
539 func ('\\times %d/%d ' %
540 (self.numerator, self.denominator))
541 func.add_factor (Rational (self.numerator, self.denominator))
542 MusicWrapper.print_ly (self, func)
545 class NestedMusic(Music):
547 Music.__init__ (self)
550 def append (self, what):
552 self.elements.append (what)
554 def has_children (self):
557 def insert_around (self, succ, elt, dir):
558 assert elt.parent == None
559 assert succ == None or succ in self.elements
564 idx = self.elements.index (succ)
571 idx = len (self.elements)
573 self.elements.insert (idx, elt)
576 def get_properties (self):
577 return ("'elements (list %s)"
578 % string.join (map (lambda x: x.lisp_expression(),
581 def get_subset_properties (self, predicate):
582 return ("'elements (list %s)"
583 % string.join (map (lambda x: x.lisp_expression(),
584 filter ( predicate, self.elements))))
585 def get_neighbor (self, music, dir):
586 assert music.parent == self
587 idx = self.elements.index (music)
589 idx = min (idx, len (self.elements) -1)
592 return self.elements[idx]
594 def delete_element (self, element):
595 assert element in self.elements
597 self.elements.remove (element)
598 element.parent = None
600 def set_start (self, start):
602 for e in self.elements:
605 def find_first (self, predicate):
606 r = Music.find_first (self, predicate)
610 for e in self.elements:
611 r = e.find_first (predicate)
616 class SequentialMusic (NestedMusic):
617 def get_last_event_chord (self):
619 at = len( self.elements ) - 1
621 not isinstance (self.elements[at], ChordEvent) and
622 not isinstance (self.elements[at], BarLine)):
625 if (at >= 0 and isinstance (self.elements[at], ChordEvent)):
626 value = self.elements[at]
629 def print_ly (self, printer, newline = True):
632 self.print_comment (printer)
636 for e in self.elements:
643 def lisp_sub_expression (self, pred):
647 props = self.get_subset_properties (pred)
649 return "(make-music '%s %s)" % (name, props)
651 def set_start (self, start):
652 for e in self.elements:
654 start += e.get_length()
658 self.repeat_type = "volta"
659 self.repeat_count = 2
662 def set_music (self, music):
663 if isinstance (music, Music):
665 elif isinstance (music, list):
666 self.music = SequentialMusic ()
667 self.music.elements = music
669 warning (_ ("unable to set the music %(music)s for the repeat %(repeat)s") % \
670 {'music':music, 'repeat':self})
671 def add_ending (self, music):
672 self.endings.append (music)
673 def print_ly (self, printer):
674 printer.dump ('\\repeat %s %s' % (self.repeat_type, self.repeat_count))
676 self.music.print_ly (printer)
678 warning (_ ("encountered repeat without body"))
681 printer.dump ('\\alternative {')
682 for e in self.endings:
689 self.lyrics_syllables = []
691 def print_ly (self, printer):
692 printer.dump ("\lyricmode {")
693 for l in self.lyrics_syllables:
694 printer.dump ( "%s " % l )
697 def ly_expression (self):
698 lstr = "\lyricmode {\n "
699 for l in self.lyrics_syllables:
707 self.header_fields = {}
708 def set_field (self, field, value):
709 self.header_fields[field] = value
711 def print_ly (self, printer):
712 printer.dump ("\header {")
714 for (k,v) in self.header_fields.items ():
716 printer.dump ('%s = %s' % (k,v))
725 self.global_staff_size = -1
728 self.page_height = -1
731 self.bottom_margin = -1
732 self.left_margin = -1
733 self.right_margin = -1
734 self.system_left_margin = -1
735 self.system_right_margin = -1
736 self.system_distance = -1
737 self.top_system_distance = -1
739 def print_length_field (self, printer, field, value):
741 printer.dump ("%s = %s\\cm" % (field, value))
743 def print_ly (self, printer):
744 if self.global_staff_size > 0:
745 printer.dump ('#(set-global-staff-size %s)' % self.global_staff_size)
747 printer.dump ('\\paper {')
749 self.print_length_field (printer, "paper-width", self.page_width)
750 self.print_length_field (printer, "paper-height", self.page_height)
751 self.print_length_field (printer, "top-margin", self.top_margin)
752 self.print_length_field (printer, "botton-margin", self.bottom_margin)
753 self.print_length_field (printer, "left-margin", self.left_margin)
754 # TODO: maybe set line-width instead of right-margin?
755 self.print_length_field (printer, "right-margin", self.right_margin)
756 # TODO: What's the corresponding setting for system_left_margin and
757 # system_right_margin in LilyPond?
758 self.print_length_field (printer, "between-system-space", self.system_distance)
759 self.print_length_field (printer, "page-top-space", self.top_system_distance)
766 self.context_dict = {}
767 def add_context (self, context):
768 if not self.context_dict.has_key (context):
769 self.context_dict[context] = []
770 def set_context_item (self, context, item):
771 self.add_context (context)
772 if not item in self.context_dict[context]:
773 self.context_dict[context].append (item)
774 def print_ly (self, printer):
775 if self.context_dict.items ():
776 printer.dump ('\\layout {')
778 for (context, defs) in self.context_dict.items ():
779 printer.dump ('\\context { \\%s' % context)
790 class ChordEvent (NestedMusic):
792 NestedMusic.__init__ (self)
793 self.after_grace_elements = None
794 self.grace_elements = None
795 self.grace_type = None
796 def append_grace (self, element):
798 if not self.grace_elements:
799 self.grace_elements = SequentialMusic ()
800 self.grace_elements.append (element)
801 def append_after_grace (self, element):
803 if not self.after_grace_elements:
804 self.after_grace_elements = SequentialMusic ()
805 self.after_grace_elements.append (element)
807 def has_elements (self):
808 return [e for e in self.elements if
809 isinstance (e, NoteEvent) or isinstance (e, RestEvent)] != []
812 def get_length (self):
814 for e in self.elements:
815 l = max(l, e.get_length())
818 def get_duration (self):
819 note_events = [e for e in self.elements if
820 isinstance (e, NoteEvent) or isinstance (e, RestEvent)]
822 return note_events[0].duration
826 def print_ly (self, printer):
827 note_events = [e for e in self.elements if
828 isinstance (e, NoteEvent)]
830 rest_events = [e for e in self.elements if
831 isinstance (e, RhythmicEvent)
832 and not isinstance (e, NoteEvent)]
834 other_events = [e for e in self.elements if
835 not isinstance (e, RhythmicEvent)]
837 if self.after_grace_elements:
838 printer ('\\afterGrace {')
840 if self.grace_elements and self.elements:
842 printer ('\\%s' % self.grace_type)
845 # don't print newlines after the { and } braces
846 self.grace_elements.print_ly (printer, False)
847 elif self.grace_elements: # no self.elements!
848 warning (_ ("Grace note with no following music: %s") % self.grace_elements)
850 printer ('\\%s' % self.grace_type)
853 self.grace_elements.print_ly (printer, False)
856 # Print all overrides and other settings needed by the
857 # articulations/ornaments before the note
858 for e in other_events:
859 e.print_before_note (printer)
862 rest_events[0].print_ly (printer)
863 elif len (note_events) == 1:
864 note_events[0].print_ly (printer)
866 global previous_pitch
869 for x in note_events:
870 pitches.append (x.chord_element_ly ())
872 basepitch = previous_pitch
873 printer ('<%s>' % string.join (pitches))
874 previous_pitch = basepitch
875 duration = self.get_duration ()
877 duration.print_ly (printer)
881 for e in other_events:
884 for e in other_events:
885 e.print_after_note (printer)
887 if self.after_grace_elements:
889 self.after_grace_elements.print_ly (printer, False)
891 self.print_comment (printer)
893 class Partial (Music):
895 Music.__init__ (self)
897 def print_ly (self, printer):
899 printer.dump ("\\partial %s" % self.partial.ly_expression ())
901 class BarLine (Music):
903 Music.__init__ (self)
907 def print_ly (self, printer):
908 bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': "dashed",
909 'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
910 'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
911 'short': "'", 'none': "" }.get (self.type, None)
912 if bar_symbol <> None:
913 printer.dump ('\\bar "%s"' % bar_symbol)
917 if self.bar_number > 0 and (self.bar_number % 10) == 0:
918 printer.dump ("\\barNumberCheck #%d " % self.bar_number)
919 elif self.bar_number > 0:
920 printer.print_verbatim (' %% %d' % self.bar_number)
923 def ly_expression (self):
928 # strings to print before the note to which an event is attached.
929 # Ignored for notes etc.
930 self.before_note = None
931 self.after_note = None
932 # print something before the note to which an event is attached, e.g. overrides
933 def print_before_note (self, printer):
935 printer.dump (self.before_note)
936 # print something after the note to which an event is attached, e.g. resetting
937 def print_after_note (self, printer):
939 printer.dump (self.after_note)
942 class SpanEvent (Event):
944 Event.__init__ (self)
945 self.span_direction = 0 # start/stop
946 self.line_type = 'solid'
947 self.span_type = 0 # e.g. cres/decrescendo, ottava up/down
948 self.size = 0 # size of e.g. ocrave shift
949 def wait_for_note (self):
951 def get_properties(self):
952 return "'span-direction %d" % self.span_direction
953 def set_span_type (self, type):
954 self.span_type = type
956 class SlurEvent (SpanEvent):
957 def print_before_note (self, printer):
958 command = {'dotted': '\\slurDotted',
959 'dashed' : '\\slurDashed'}.get (self.line_type, '')
960 if command and self.span_direction == -1:
961 printer.dump (command)
962 def print_after_note (self, printer):
963 # reset non-solid slur types!
964 command = {'dotted': '\\slurSolid',
965 'dashed' : '\\slurSolid'}.get (self.line_type, '')
966 if command and self.span_direction == -1:
967 printer.dump (command)
968 def ly_expression (self):
969 return {-1: '(', 1:')'}.get (self.span_direction, '')
971 class BeamEvent (SpanEvent):
972 def ly_expression (self):
973 return {-1: '[', 1:']'}.get (self.span_direction, '')
975 class PedalEvent (SpanEvent):
976 def ly_expression (self):
977 return {-1: '\\sustainOn',
978 0:'\\sustainOff\\sustainOn',
979 1:'\\sustainOff'}.get (self.span_direction, '')
981 class TextSpannerEvent (SpanEvent):
982 def ly_expression (self):
983 return {-1: '\\startTextSpan',
984 1:'\\stopTextSpan'}.get (self.span_direction, '')
986 class BracketSpannerEvent (SpanEvent):
987 # Ligature brackets use prefix-notation!!!
988 def print_before_note (self, printer):
989 if self.span_direction == -1:
991 # the bracket after the last note
992 def print_after_note (self, printer):
993 if self.span_direction == 1:
995 # we're printing everything in print_(before|after)_note...
996 def ly_expression (self):
1000 class OctaveShiftEvent (SpanEvent):
1001 def wait_for_note (self):
1003 def set_span_type (self, type):
1004 self.span_type = {'up': 1, 'down': -1}.get (type, 0)
1005 def ly_octave_shift_indicator (self):
1006 # convert 8/15 to lilypond indicators (+-1/+-2)
1008 value = {8: 1, 15: 2}[self.size]
1010 warning (_ ("Invalid octave shift size found: %s. Using no shift.") % self.size)
1012 # negative values go up!
1013 value *= -1*self.span_type
1015 def ly_expression (self):
1016 dir = self.ly_octave_shift_indicator ()
1019 value = '\ottava #%s' % dir
1022 1: '\ottava #0'}.get (self.span_direction, '')
1024 class TrillSpanEvent (SpanEvent):
1025 def ly_expression (self):
1026 return {-1: '\\startTrillSpan',
1027 0: '', # no need to write out anything for type='continue'
1028 1:'\\stopTrillSpan'}.get (self.span_direction, '')
1030 class GlissandoEvent (SpanEvent):
1031 def print_before_note (self, printer):
1032 if self.span_direction == -1:
1034 "dashed" : "dashed-line",
1035 "dotted" : "dotted-line",
1037 }. get (self.line_type, None)
1039 printer.dump ("\once \override Glissando #'style = #'%s" % style)
1040 def ly_expression (self):
1041 return {-1: '\\glissando',
1042 1:''}.get (self.span_direction, '')
1044 class ArpeggioEvent(Event):
1045 def __init__ (self):
1046 Event.__init__ (self)
1048 self.non_arpeggiate = False
1049 def wait_for_note (self):
1051 def print_before_note (self, printer):
1052 if self.non_arpeggiate:
1053 printer.dump ("\\arpeggioBracket")
1055 dir = { -1: "\\arpeggioArrowDown", 1: "\\arpeggioArrowUp" }.get (self.direction, '')
1058 def print_after_note (self, printer):
1059 if self.non_arpeggiate or self.direction:
1060 printer.dump ("\\arpeggioNormal")
1061 def ly_expression (self):
1062 return ('\\arpeggio')
1065 class TieEvent(Event):
1066 def ly_expression (self):
1070 class HairpinEvent (SpanEvent):
1071 def set_span_type (self, type):
1072 self.span_type = {'crescendo' : 1, 'decrescendo' : -1, 'diminuendo' : -1 }.get (type, 0)
1073 def hairpin_to_ly (self):
1074 if self.span_direction == 1:
1077 return {1: '\<', -1: '\>'}.get (self.span_type, '')
1079 def ly_expression (self):
1080 return self.hairpin_to_ly ()
1082 def print_ly (self, printer):
1083 val = self.hairpin_to_ly ()
1089 class DynamicsEvent (Event):
1090 def __init__ (self):
1091 Event.__init__ (self)
1093 def wait_for_note (self):
1095 def ly_expression (self):
1097 return '\%s' % self.type
1101 def print_ly (self, printer):
1103 printer.dump ("\\%s" % self.type)
1105 class MarkEvent (Event):
1106 def __init__ (self, text="\\default"):
1107 Event.__init__ (self)
1109 def wait_for_note (self):
1111 def ly_contents (self):
1113 return '%s' % self.mark
1116 def ly_expression (self):
1117 return '\\mark %s' % self.ly_contents ()
1119 class MusicGlyphMarkEvent (MarkEvent):
1120 def ly_contents (self):
1122 return '\\markup { \\musicglyph #"scripts.%s" }' % self.mark
1127 class TextEvent (Event):
1128 def __init__ (self):
1129 Event.__init__ (self)
1131 self.force_direction = None
1133 def wait_for_note (self):
1136 def direction_mod (self):
1137 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1139 def ly_expression (self):
1140 base_string = '%s\"%s\"'
1142 base_string = '%s\markup{ ' + self.markup + ' {%s} }'
1143 return base_string % (self.direction_mod (), self.text)
1145 class ArticulationEvent (Event):
1146 def __init__ (self):
1147 Event.__init__ (self)
1149 self.force_direction = None
1150 def wait_for_note (self):
1153 def direction_mod (self):
1154 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '')
1156 def ly_expression (self):
1157 return '%s\\%s' % (self.direction_mod (), self.type)
1159 class ShortArticulationEvent (ArticulationEvent):
1160 def direction_mod (self):
1162 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1163 def ly_expression (self):
1165 return '%s%s' % (self.direction_mod (), self.type)
1169 class NoDirectionArticulationEvent (ArticulationEvent):
1170 def ly_expression (self):
1172 return '\\%s' % self.type
1176 class MarkupEvent (ShortArticulationEvent):
1177 def __init__ (self):
1178 ArticulationEvent.__init__ (self)
1179 self.contents = None
1180 def ly_expression (self):
1182 return "%s\\markup { %s }" % (self.direction_mod (), self.contents)
1186 class FretEvent (MarkupEvent):
1187 def __init__ (self):
1188 MarkupEvent.__init__ (self)
1189 self.force_direction = 1
1194 def ly_expression (self):
1196 if self.strings <> 6:
1197 val += "w:%s;" % self.strings
1199 val += "h:%s;" % self.frets
1200 if self.barre and len (self.barre) >= 3:
1201 val += "c:%s-%s-%s;" % (self.barre[0], self.barre[1], self.barre[2])
1202 have_fingering = False
1203 for i in self.elements:
1205 val += "%s-%s" % (i[0], i[1])
1207 have_fingering = True
1213 return "%s\\markup { \\fret-diagram #\"%s\" }" % (self.direction_mod (), val)
1218 class FunctionWrapperEvent (Event):
1219 def __init__ (self, function_name = None):
1220 Event.__init__ (self)
1221 self.function_name = function_name
1222 def pre_note_ly (self, is_chord_element):
1223 if self.function_name:
1224 return "\\%s" % self.function_name
1227 def pre_chord_ly (self):
1229 def ly_expression (self):
1230 if self.function_name:
1231 return "\\%s" % self.function_name
1235 class ParenthesizeEvent (FunctionWrapperEvent):
1236 def __init__ (self):
1237 FunctionWrapperEvent.__init__ (self, "parenthesize")
1239 class NotestyleEvent (Event):
1240 def __init__ (self):
1241 Event.__init__ (self)
1244 def pre_chord_ly (self):
1246 return "\\once \\override NoteHead #'style = #%s" % self.style
1249 def pre_note_ly (self, is_chord_element):
1250 if self.style and is_chord_element:
1251 return "\\tweak #'style #%s" % self.style
1254 def ly_expression (self):
1255 return self.pre_chord_ly ()
1259 def __init__ (self):
1263 return self.ly_expression()
1264 def ly_expression (self):
1265 return pitch_generating_function (self)
1267 class ChordModification:
1268 def __init__ (self):
1272 def ly_expression (self):
1274 val = {1: ".", -1: "^" }.get (self.type, "")
1275 val += "%s" % self.step
1276 val += {1: "+", -1: "-"}.get (self.alteration, "")
1281 class ChordNameEvent (Event):
1282 def __init__ (self):
1283 Event.__init__ (self)
1286 self.duration = None
1287 self.modifications = []
1289 def add_modification (self, mod):
1290 self.modifications.append (mod)
1291 def ly_expression (self):
1294 value = self.root.ly_expression ()
1296 value += self.duration.ly_expression ()
1300 # First print all additions/changes, and only afterwards all subtractions
1301 for m in self.modifications:
1303 value += m.ly_expression ()
1304 for m in self.modifications:
1306 value += m.ly_expression ()
1308 value += "/+%s" % self.bass.ly_expression ()
1312 class TremoloEvent (ArticulationEvent):
1313 def __init__ (self):
1314 Event.__init__ (self)
1317 def ly_expression (self):
1319 if self.bars and self.bars > 0:
1320 str += ':%s' % (2 ** (2 + string.atoi (self.bars)))
1323 class BendEvent (ArticulationEvent):
1324 def __init__ (self):
1325 Event.__init__ (self)
1327 def ly_expression (self):
1328 if self.alter != None:
1329 return "-\\bendAfter #%s" % self.alter
1333 class RhythmicEvent(Event):
1334 def __init__ (self):
1335 Event.__init__ (self)
1336 self.duration = Duration()
1337 self.associated_events = []
1339 def add_associated_event (self, ev):
1341 self.associated_events.append (ev)
1343 def pre_chord_ly (self):
1344 return [ev.pre_chord_ly () for ev in self.associated_events]
1346 def pre_note_ly (self, is_chord_element):
1347 return [ev.pre_note_ly (is_chord_element) for ev in self.associated_events]
1349 def ly_expression_pre_note (self, is_chord_element):
1350 res = string.join (self.pre_note_ly (is_chord_element), ' ')
1355 def get_length (self):
1356 return self.duration.get_length()
1358 def get_properties (self):
1359 return ("'duration %s"
1360 % self.duration.lisp_expression ())
1362 class RestEvent (RhythmicEvent):
1363 def __init__ (self):
1364 RhythmicEvent.__init__ (self)
1367 def ly_expression (self):
1368 res = self.ly_expression_pre_note (False)
1370 return res + "%s%s\\rest" % (self.pitch.ly_expression (), self.duration.ly_expression ())
1372 return 'r%s' % self.duration.ly_expression ()
1374 def print_ly (self, printer):
1375 for ev in self.associated_events:
1376 ev.print_ly (printer)
1378 self.pitch.print_ly (printer)
1379 self.duration.print_ly (printer)
1383 self.duration.print_ly (printer)
1385 class SkipEvent (RhythmicEvent):
1386 def ly_expression (self):
1387 return 's%s' % self.duration.ly_expression ()
1389 class NoteEvent(RhythmicEvent):
1390 def __init__ (self):
1391 RhythmicEvent.__init__ (self)
1393 self.drum_type = None
1394 self.cautionary = False
1395 self.forced_accidental = False
1397 def get_properties (self):
1398 str = RhythmicEvent.get_properties (self)
1401 str += self.pitch.lisp_expression ()
1402 elif self.drum_type:
1403 str += "'drum-type '%s" % self.drum_type
1407 def pitch_mods (self):
1410 excl_question += '?'
1411 if self.forced_accidental:
1412 excl_question += '!'
1414 return excl_question
1416 def ly_expression (self):
1417 # obtain all stuff that needs to be printed before the note:
1418 res = self.ly_expression_pre_note (True)
1420 return res + '%s%s%s' % (self.pitch.ly_expression (),
1422 self.duration.ly_expression ())
1423 elif self.drum_type:
1424 return res + '%s%s' (self.drum_type,
1425 self.duration.ly_expression ())
1427 def chord_element_ly (self):
1428 # obtain all stuff that needs to be printed before the note:
1429 res = self.ly_expression_pre_note (True)
1431 return res + '%s%s' % (self.pitch.ly_expression (),
1433 elif self.drum_type:
1434 return res + '%s%s' (self.drum_type)
1437 def print_ly (self, printer):
1438 for ev in self.associated_events:
1439 ev.print_ly (printer)
1441 self.pitch.print_ly (printer)
1442 printer (self.pitch_mods ())
1444 printer (self.drum_type)
1446 self.duration.print_ly (printer)
1448 class KeySignatureChange (Music):
1449 def __init__ (self):
1450 Music.__init__ (self)
1453 self.non_standard_alterations = None
1455 def format_non_standard_alteration (self, a):
1456 alter_dict = { -2: ",DOUBLE-FLAT",
1457 -1.5: ",THREE-Q-FLAT",
1463 1.5: ",THREE-Q-SHARP",
1466 accidental = alter_dict[a[1]]
1468 warning (_ ("Unable to convert alteration %s to a lilypond expression") % a[1])
1471 return "( %s . %s )" % (a[0], accidental)
1473 return "(( %s . %s ) . %s )" % (a[2], a[0], accidental)
1477 def ly_expression (self):
1479 return '\\key %s \\%s' % (self.tonic.ly_step_expression (),
1481 elif self.non_standard_alterations:
1482 alterations = [self.format_non_standard_alteration (a) for
1483 a in self.non_standard_alterations]
1484 return "\\set Staff.keySignature = #`(%s)" % string.join (alterations, " ")
1488 class TimeSignatureChange (Music):
1489 def __init__ (self):
1490 Music.__init__ (self)
1491 self.fractions = [4,4]
1493 def format_fraction (self, frac):
1494 if isinstance (frac, list):
1495 l = [self.format_fraction (f) for f in frac]
1496 return "(" + string.join (l, " ") + ")"
1500 def ly_expression (self):
1502 # Print out the style if we have ome, but the '() should only be
1503 # forced for 2/2 or 4/4, since in all other cases we'll get numeric
1504 # signatures anyway despite the default 'C signature style!
1505 is_common_signature = self.fractions in ([2,2], [4,4], [4,2])
1507 if self.style == "common":
1508 st = "\\defaultTimeSignature"
1509 elif (self.style != "'()"):
1510 st = "\\once \\override Staff.TimeSignature #'style = #%s " % self.style
1511 elif (self.style != "'()") or is_common_signature:
1512 st = "\\numericTimeSignature"
1514 # Easy case: self.fractions = [n,d] => normal \time n/d call:
1515 if len (self.fractions) == 2 and isinstance (self.fractions[0], int):
1516 return st + '\\time %d/%d ' % tuple (self.fractions)
1517 elif self.fractions:
1518 return st + "\\compoundMeter #'%s" % self.format_fraction (self.fractions)
1522 class ClefChange (Music):
1523 def __init__ (self):
1524 Music.__init__ (self)
1529 def octave_modifier (self):
1530 return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self.octave, '')
1531 def clef_name (self):
1532 return {('G', 2): "treble",
1534 ('C', 1): "soprano",
1535 ('C', 2): "mezzosoprano",
1538 ('C', 5): "baritone",
1539 ('F', 3): "varbaritone",
1541 ('F', 5): "subbass",
1542 ("percussion", 2): "percussion",
1543 # Workaround: MuseScore uses PERC instead of percussion
1544 ("PERC", 2): "percussion",
1545 ("TAB", 5): "tab"}.get ((self.type, self.position), None)
1546 def ly_expression (self):
1547 return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ())
1550 "G": ("clefs.G", -2, -6),
1551 "C": ("clefs.C", 0, 0),
1552 "F": ("clefs.F", 2, 6),
1555 def lisp_expression (self):
1557 (glyph, pos, c0) = self.clef_dict[self.type]
1561 (make-music 'SequentialMusic
1564 (make-property-set 'clefGlyph "%s") 'Staff)
1566 (make-property-set 'clefPosition %d) 'Staff)
1568 (make-property-set 'middleCPosition %d) 'Staff)))
1569 """ % (glyph, pos, c0)
1572 class Transposition (Music):
1573 def __init__ (self):
1574 Music.__init__ (self)
1576 def ly_expression (self):
1577 self.pitch._force_absolute_pitch = True
1578 return '\\transposition %s' % self.pitch.ly_expression ()
1580 class StaffChange (Music):
1581 def __init__ (self, staff):
1582 Music.__init__ (self)
1584 def ly_expression (self):
1586 return "\\change Staff=\"%s\"" % self.staff
1591 class TempoMark (Music):
1592 def __init__ (self):
1593 Music.__init__ (self)
1594 self.baseduration = None
1595 self.newduration = None
1597 self.parentheses = False
1598 def set_base_duration (self, dur):
1599 self.baseduration = dur
1600 def set_new_duration (self, dur):
1601 self.newduration = dur
1602 def set_beats_per_minute (self, beats):
1604 def set_parentheses (self, parentheses):
1605 self.parentheses = parentheses
1606 def wait_for_note (self):
1608 def duration_to_markup (self, dur):
1610 # Generate the markup to print the note, use scheme mode for
1611 # ly_expression to get longa and not \longa (which causes an error)
1612 return "\\general-align #Y #DOWN \\smaller \\note #\"%s\" #UP" % dur.ly_expression(None, True)
1615 def tempo_markup_template (self):
1616 return "\\mark\\markup { \\fontsize #-2 \\line { %s } }"
1617 def ly_expression (self):
1619 if not self.baseduration:
1622 if self.parentheses:
1623 res += "\\tempo \"\" %s=%s" % (self.baseduration.ly_expression(), self.beats)
1625 res += "\\tempo %s=%s" % (self.baseduration.ly_expression(), self.beats)
1626 elif self.newduration:
1627 dm = self.duration_to_markup (self.baseduration)
1628 ndm = self.duration_to_markup (self.newduration)
1629 if self.parentheses:
1630 contents = "\"(\" %s = %s \")\"" % (dm, ndm)
1632 contents = " %s = %s " % (dm, ndm)
1633 res += self.tempo_markup_template() % contents
1638 class FiguredBassNote (Music):
1639 def __init__ (self):
1640 Music.__init__ (self)
1644 def set_prefix (self, prefix):
1645 self.prefix = prefix
1646 def set_suffix (self, suffix):
1647 self.prefix = suffix
1648 def set_number (self, number):
1649 self.number = number
1650 def ly_expression (self):
1663 class FiguredBassEvent (NestedMusic):
1664 def __init__ (self):
1665 NestedMusic.__init__ (self)
1666 self.duration = None
1667 self.real_duration = 0
1668 self.parentheses = False
1670 def set_duration (self, dur):
1672 def set_parentheses (self, par):
1673 self.parentheses = par
1674 def set_real_duration (self, dur):
1675 self.real_duration = dur
1677 def print_ly (self, printer):
1678 figured_bass_events = [e for e in self.elements if
1679 isinstance (e, FiguredBassNote)]
1680 if figured_bass_events:
1682 for x in figured_bass_events:
1683 notes.append (x.ly_expression ())
1684 contents = string.join (notes)
1685 if self.parentheses:
1686 contents = '[%s]' % contents
1687 printer ('<%s>' % contents)
1688 self.duration.print_ly (printer)
1691 class MultiMeasureRest(Music):
1693 def lisp_expression (self):
1696 'MultiMeasureRestMusicGroup
1698 (list (make-music (quote BarCheck))
1703 'MultiMeasureRestEvent
1706 (make-music (quote BarCheck))))
1707 """ % self.duration.lisp_expression ()
1709 def ly_expression (self):
1710 return 'R%s' % self.duration.ly_expression ()
1713 class Break (Music):
1714 def __init__ (self, tp="break"):
1715 Music.__init__ (self)
1717 def print_ly (self, printer):
1719 printer.dump ("\\%s" % self.type)
1722 def __init__ (self, command = "StaffGroup"):
1723 self.stafftype = command
1725 self.instrument_name = None
1726 self.short_instrument_name = None
1730 self.is_group = True
1731 # part_information is a list with entries of the form
1732 # [staffid, voicelist]
1733 # where voicelist is a list with entries of the form
1734 # [voiceid1, [lyricsid11, lyricsid12,...] ]
1735 self.part_information = None
1737 def append_staff (self, staff):
1738 self.children.append (staff)
1740 def set_part_information (self, part_name, staves_info):
1741 if part_name == self.id:
1742 self.part_information = staves_info
1744 for c in self.children:
1745 c.set_part_information (part_name, staves_info)
1747 def print_ly_contents (self, printer):
1748 for c in self.children:
1750 c.print_ly (printer)
1751 def print_ly_overrides (self, printer):
1753 needs_with |= self.spanbar == "no"
1754 needs_with |= self.instrument_name != None
1755 needs_with |= self.short_instrument_name != None
1756 needs_with |= (self.symbol != None) and (self.symbol != "bracket")
1758 printer.dump ("\\with {")
1759 if self.instrument_name or self.short_instrument_name:
1760 printer.dump ("\\consists \"Instrument_name_engraver\"")
1761 if self.spanbar == "no":
1762 printer.dump ("\\override SpanBar #'transparent = ##t")
1763 brack = {"brace": "SystemStartBrace",
1765 "line": "SystemStartSquare"}.get (self.symbol, None)
1767 printer.dump ("systemStartDelimiter = #'%s" % brack)
1770 def print_ly (self, printer):
1772 printer.dump ("\\new %s" % self.stafftype)
1773 self.print_ly_overrides (printer)
1776 if self.stafftype and self.instrument_name:
1777 printer.dump ("\\set %s.instrumentName = %s" % (self.stafftype,
1778 escape_instrument_string (self.instrument_name)))
1780 if self.stafftype and self.short_instrument_name:
1781 printer.dump ("\\set %s.shortInstrumentName = %s" % (self.stafftype,
1782 escape_instrument_string (self.short_instrument_name)))
1784 self.print_ly_contents (printer)
1790 class Staff (StaffGroup):
1791 def __init__ (self, command = "Staff"):
1792 StaffGroup.__init__ (self, command)
1793 self.is_group = False
1795 self.voice_command = "Voice"
1796 self.substafftype = None
1798 def print_ly_overrides (self, printer):
1801 def print_ly_contents (self, printer):
1802 if not self.id or not self.part_information:
1804 sub_staff_type = self.substafftype
1805 if not sub_staff_type:
1806 sub_staff_type = self.stafftype
1808 for [staff_id, voices] in self.part_information:
1809 # Chord names need to come before the staff itself!
1810 for [v, lyrics, figuredbass, chordnames] in voices:
1812 printer ('\context ChordNames = "%s" \\%s' % (chordnames, chordnames))
1814 # now comes the real staff definition:
1816 printer ('\\context %s = "%s" << ' % (sub_staff_type, staff_id))
1818 printer ('\\context %s << ' % sub_staff_type)
1821 nr_voices = len (voices)
1822 for [v, lyrics, figuredbass, chordnames] in voices:
1824 voice_count_text = ''
1826 voice_count_text = {1: ' \\voiceOne', 2: ' \\voiceTwo',
1827 3: ' \\voiceThree'}.get (n, ' \\voiceFour')
1828 printer ('\\context %s = "%s" {%s \\%s }' % (self.voice_command, v, voice_count_text, v))
1832 printer ('\\new Lyrics \\lyricsto "%s" \\%s' % (v,l))
1835 printer ('\context FiguredBass = "%s" \\%s' % (figuredbass, figuredbass))
1838 def print_ly (self, printer):
1839 if self.part_information and len (self.part_information) > 1:
1840 self.stafftype = "PianoStaff"
1841 self.substafftype = "Staff"
1842 StaffGroup.print_ly (self, printer)
1844 class TabStaff (Staff):
1845 def __init__ (self, command = "TabStaff"):
1846 Staff.__init__ (self, command)
1847 self.string_tunings = []
1848 self.tablature_format = None
1849 self.voice_command = "TabVoice"
1850 def print_ly_overrides (self, printer):
1851 if self.string_tunings or self.tablature_format:
1852 printer.dump ("\\with {")
1853 if self.string_tunings:
1854 printer.dump ("stringTunings = #'(")
1855 for i in self.string_tunings:
1856 printer.dump ("%s" % i.semitones ())
1858 if self.tablature_format:
1859 printer.dump ("tablatureFormat = #%s" % self.tablature_format)
1863 class DrumStaff (Staff):
1864 def __init__ (self, command = "DrumStaff"):
1865 Staff.__init__ (self, command)
1866 self.drum_style_table = None
1867 self.voice_command = "DrumVoice"
1868 def print_ly_overrides (self, printer):
1869 if self.drum_style_table:
1870 printer.dump ("\with {")
1871 printer.dump ("drumStyleTable = #%s" % self.drum_style_table)
1874 class RhythmicStaff (Staff):
1875 def __init__ (self, command = "RhythmicStaff"):
1876 Staff.__init__ (self, command)
1879 def __init__ (self):
1880 self.contents = None
1881 self.create_midi = False
1883 def set_contents (self, contents):
1884 self.contents = contents
1886 def set_part_information (self, part_id, staves_info):
1888 self.contents.set_part_information (part_id, staves_info)
1890 def print_ly (self, printer):
1891 printer.dump ("\\score {");
1894 self.contents.print_ly (printer);
1895 printer.dump ("\\layout {}");
1897 if not self.create_midi:
1898 printer.dump ("% To create MIDI output, uncomment the following line:");
1900 printer.dump ("% ");
1901 printer.dump ("\\midi {}");
1909 bflat.alteration = -1
1919 print bflat.semitones()
1920 print bflat.transposed (fifth), bflat.transposed (fifth).transposed (fifth)
1921 print bflat.transposed (fifth).transposed (fifth).transposed (fifth)
1923 print bflat.semitones(), 'down'
1924 print bflat.transposed (down)
1925 print bflat.transposed (down).transposed (down)
1926 print bflat.transposed (down).transposed (down).transposed (down)
1930 def test_printer ():
1938 m = SequentialMusic()
1939 m.append (make_note ())
1940 m.append (make_note ())
1941 m.append (make_note ())
1944 t = TimeScaledMusic ()
1950 m = SequentialMusic ()
1951 m.append (make_tup ())
1952 m.append (make_tup ())
1953 m.append (make_tup ())
1955 printer = Output_printer()
1956 m.print_ly (printer)
1960 m = SequentialMusic()
1964 n.duration.duration_log = l
1966 evc.insert_around (None, n, 0)
1967 m.insert_around (None, evc, 0)
1971 n.duration.duration_log = l
1973 evc.insert_around (None, n, 0)
1974 m.insert_around (None, evc, 0)
1978 n.duration.duration_log = l
1980 evc.insert_around (None, n, 0)
1981 m.insert_around (None, evc, 0)
1985 m.insert_around (None, evc, 0)
1990 tonic.alteration = -2
1991 n = KeySignatureChange()
1992 n.tonic=tonic.copy()
1993 n.scale = [0, 0, -2, 0, 0,-2,-2]
1995 evc.insert_around (None, n, 0)
1996 m.insert_around (None, evc, 0)
2001 if __name__ == '__main__':
2007 expr.set_start (Rational (0))
2008 print expr.ly_expression()
2009 start = Rational (0,4)
2010 stop = Rational (4,2)
2011 def sub(x, start=start, stop=stop):
2012 ok = x.start >= start and x.start +x.get_length() <= stop
2015 print expr.lisp_sub_expression(sub)