9 from rational import Rational
11 # Store previously converted pitch for \relative conversion as a global state variable
13 relative_pitches = False
16 ly.stderr_write ((_ ("warning: %s") % str) + "\n")
19 def escape_instrument_string (input_string):
20 retstring = string.replace (input_string, "\"", "\\\"")
21 if re.match ('.*[\r\n]+.*', retstring):
22 rx = re.compile (r'[\n\r]+')
23 strings = rx.split (retstring)
24 retstring = "\\markup { \\column { "
26 retstring += "\\line {\"" + s + "\"} "
29 retstring = "\"" + retstring + "\""
32 class Output_stack_element:
34 self.factor = Rational (1)
36 o = Output_stack_element()
37 o.factor = self.factor
42 """A class that takes care of formatting (eg.: indenting) a
43 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):
62 self.print_verbatim ('\\version "@TOPLEVEL_VERSION@"')
65 def get_indent (self):
66 return self._nesting * self._indent
69 last = self._output_state_stack[-1]
70 self._output_state_stack.append (last.copy())
72 def add_factor (self, factor):
74 self._output_state_stack[-1].factor *= factor
77 del self._output_state_stack[-1]
78 if not self._output_state_stack:
81 def duration_factor (self):
82 return self._output_state_stack[-1].factor
84 def print_verbatim (self, str):
87 def unformatted_output (self, str):
88 # don't indent on \< and indent only once on <<
89 self._nesting += ( str.count ('<')
90 - str.count ('\<') - str.count ('<<')
92 self._nesting -= ( str.count ('>') - str.count ('\>') - str.count ('>>')
93 - str.count ('->') - str.count ('_>')
96 self.print_verbatim (str)
98 def print_duration_string (self, str):
99 if self._last_duration == str:
102 self.unformatted_output (str)
104 def add_word (self, str):
105 if (len (str) + 1 + len (self._line) > self._line_len):
107 self._skipspace = True
109 if not self._skipspace:
111 self.unformatted_output (str)
112 self._skipspace = False
115 self._file.write (self._line + '\n')
116 self._line = ' ' * self._indent * self._nesting
117 self._skipspace = True
119 def skipspace (self):
120 self._skipspace = True
122 def __call__(self, arg):
125 def dump (self, str):
127 self._skipspace = False
128 self.unformatted_output (str)
130 words = string.split (str)
143 self.duration_log = 0
145 self.factor = Rational (1)
147 def lisp_expression (self):
148 return '(ly:make-duration %d %d %d %d)' % (self.duration_log,
150 self.factor.numerator (),
151 self.factor.denominator ())
154 def ly_expression (self, factor = None, scheme_mode = False):
158 if self.duration_log < 0:
160 longer_dict = {-1: "breve", -2: "longa"}
162 longer_dict = {-1: "\\breve", -2: "\\longa"}
163 str = longer_dict.get (self.duration_log, "1")
165 str = '%d' % (1 << self.duration_log)
168 if factor <> Rational (1,1):
169 if factor.denominator () <> 1:
170 str += '*%d/%d' % (factor.numerator (), factor.denominator ())
172 str += '*%d' % factor.numerator ()
176 def print_ly (self, outputter):
177 str = self.ly_expression (self.factor / outputter.duration_factor ())
178 outputter.print_duration_string (str)
181 return self.ly_expression()
186 d.duration_log = self.duration_log
187 d.factor = self.factor
190 def get_length (self):
191 dot_fact = Rational( (1 << (1 + self.dots))-1,
194 log = abs (self.duration_log)
196 if self.duration_log < 0:
197 base = Rational (dur)
199 base = Rational (1, dur)
201 return base * dot_fact * self.factor
204 # Implement the different note names for the various languages
205 def pitch_generic (pitch, notenames, accidentals):
206 str = notenames[pitch.step]
207 halftones = int (pitch.alteration)
209 str += accidentals[0] * (-halftones)
210 elif pitch.alteration > 0:
211 str += accidentals[3] * (halftones)
212 # Handle remaining fraction to pitch.alteration (for microtones)
213 if (halftones != pitch.alteration):
214 if None in accidentals[1:3]:
215 warning (_ ("Language does not support microtones contained in the piece"))
218 str += {-0.5: accidentals[1], 0.5: accidentals[2]}[pitch.alteration-halftones]
220 warning (_ ("Language does not support microtones contained in the piece"))
223 def pitch_general (pitch):
224 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['es', 'eh', 'ih', 'is'])
225 return str.replace ('aes', 'as').replace ('ees', 'es')
227 def pitch_nederlands (pitch):
228 return pitch_general (pitch)
230 def pitch_english (pitch):
231 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['f', 'qf', 'qs', 's'])
232 return str.replace ('aes', 'as').replace ('ees', 'es')
234 def pitch_deutsch (pitch):
235 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['es', 'eh', 'ih', 'is'])
236 return str.replace ('hes', 'b').replace ('aes', 'as').replace ('ees', 'es')
238 def pitch_norsk (pitch):
239 return pitch_deutsch (pitch)
241 def pitch_svenska (pitch):
242 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', None, None, 'iss'])
243 return str.replace ('hess', 'b').replace ('aes', 'as').replace ('ees', 'es')
245 def pitch_italiano (pitch):
246 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', 'sb', 'sd', 'd'])
249 def pitch_catalan (pitch):
250 return pitch_italiano (pitch)
252 def pitch_espanol (pitch):
253 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 's'])
256 def pitch_vlaams (pitch):
257 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 'k'])
260 def set_pitch_language (language):
261 global pitch_generating_function
263 "nederlands": pitch_nederlands,
264 "english": pitch_english,
265 "deutsch": pitch_deutsch,
266 "norsk": pitch_norsk,
267 "svenska": pitch_svenska,
268 "italiano": pitch_italiano,
269 "catalan": pitch_catalan,
270 "espanol": pitch_espanol,
271 "vlaams": pitch_vlaams}
272 pitch_generating_function = function_dict.get (language, pitch_general)
274 # global variable to hold the formatting function.
275 pitch_generating_function = pitch_general
283 self._force_absolute_pitch = False
286 return self.ly_expression()
288 def transposed (self, interval):
290 c.alteration += interval.alteration
291 c.step += interval.step
292 c.octave += interval.octave
295 target_st = self.semitones() + interval.semitones()
296 c.alteration += target_st - c.semitones()
303 c.octave += c.step / 7
306 def lisp_expression (self):
307 return '(ly:make-pitch %d %d %d)' % (self.octave,
313 p.alteration = self.alteration
315 p.octave = self.octave
319 return self.step + self.octave *7
321 def semitones (self):
322 return self.octave * 12 + [0,2,4,5,7,9,11][self.step] + self.alteration
324 def ly_step_expression (self):
325 return pitch_generating_function (self)
327 def absolute_pitch (self):
329 return "'" * (self.octave + 1)
330 elif self.octave < -1:
331 return "," * (-self.octave - 1)
335 def relative_pitch (self):
336 global previous_pitch
337 if not previous_pitch:
338 previous_pitch = self
339 return self.absolute_pitch ()
340 previous_pitch_steps = previous_pitch.octave * 7 + previous_pitch.step
341 this_pitch_steps = self.octave * 7 + self.step
342 pitch_diff = (this_pitch_steps - previous_pitch_steps)
343 previous_pitch = self
345 return "'" * ((pitch_diff + 3) / 7)
346 elif pitch_diff < -3:
347 return "," * ((-pitch_diff + 3) / 7)
351 def ly_expression (self):
352 str = self.ly_step_expression ()
353 if relative_pitches and not self._force_absolute_pitch:
354 str += self.relative_pitch ()
356 str += self.absolute_pitch ()
360 def print_ly (self, outputter):
361 outputter (self.ly_expression())
366 self.start = Rational (0)
368 self.identifier = None
370 def get_length(self):
373 def get_properties (self):
376 def has_children (self):
379 def get_index (self):
381 return self.parent.elements.index (self)
385 return self.__class__.__name__
387 def lisp_expression (self):
390 props = self.get_properties ()
392 return "(make-music '%s %s)" % (name, props)
394 def set_start (self, start):
397 def find_first (self, predicate):
402 def print_comment (self, printer, text = None):
413 lines = string.split (text, '\n')
416 printer.unformatted_output ('% ' + l)
420 def print_with_identifier (self, printer):
422 printer ("\\%s" % self.identifier)
424 self.print_ly (printer)
426 def print_ly (self, printer):
427 printer (self.ly_expression ())
429 class MusicWrapper (Music):
433 def print_ly (self, func):
434 self.element.print_ly (func)
436 class ModeChangingMusicWrapper (MusicWrapper):
438 MusicWrapper.__init__ (self)
439 self.mode = 'notemode'
441 def print_ly (self, func):
442 func ('\\%s' % self.mode)
443 MusicWrapper.print_ly (self, func)
445 class RelativeMusic (MusicWrapper):
447 MusicWrapper.__init__ (self)
448 self.basepitch = None
450 def print_ly (self, func):
451 global previous_pitch
452 global relative_pitches
453 prev_relative_pitches = relative_pitches
454 relative_pitches = True
455 previous_pitch = self.basepitch
456 if not previous_pitch:
457 previous_pitch = Pitch ()
458 func ('\\relative %s%s' % (pitch_generating_function (previous_pitch),
459 previous_pitch.absolute_pitch ()))
460 MusicWrapper.print_ly (self, func)
461 relative_pitches = prev_relative_pitches
463 class TimeScaledMusic (MusicWrapper):
465 MusicWrapper.__init__ (self)
468 self.display_number = "actual" # valid values "actual" | "both" | None
469 # Display the basic note length for the tuplet:
470 self.display_type = None # value values "actual" | "both" | None
471 self.display_bracket = "bracket" # valid values "bracket" | "curved" | None
472 self.actual_type = None # The actually played unit of the scaling
473 self.normal_type = None # The basic unit of the scaling
474 self.display_numerator = None
475 self.display_denominator = None
477 def print_ly (self, func):
478 if self.display_bracket == None:
479 func ("\\once \\override TupletBracket #'stencil = ##f")
481 elif self.display_bracket == "curved":
482 warning (_ ("Tuplet brackets of curved shape are not correctly implemented"))
483 func ("\\once \\override TupletBracket #'stencil = #ly:slur::print")
486 base_number_function = {None: "#f",
487 "actual": "tuplet-number::calc-denominator-text",
488 "both": "tuplet-number::calc-fraction-text"}.get (self.display_number, None)
489 # If we have non-standard numerator/denominator, use our custom function
490 if self.display_number == "actual" and self.display_denominator:
491 base_number_function = "(tuplet-number::non-default-tuplet-denominator-text %s)" % self.display_denominator
492 elif self.display_number == "both" and (self.display_denominator or self.display_numerator):
493 if self.display_numerator:
494 num = self.display_numerator
497 if self.display_denominator:
498 den = self.display_denominator
501 base_number_function = "(tuplet-number::non-default-tuplet-fraction-text %s %s)" % (den, num)
504 if self.display_type == "actual" and self.normal_type:
505 # Obtain the note duration in scheme-mode, i.e. \longa as \\longa
506 base_duration = self.normal_type.ly_expression (None, True)
507 func ("\\once \\override TupletNumber #'text = #(tuplet-number::append-note-wrapper %s \"%s\")" %
508 (base_number_function, base_duration))
510 elif self.display_type == "both": # TODO: Implement this using actual_type and normal_type!
511 if self.display_number == None:
512 func ("\\once \\override TupletNumber #'stencil = ##f")
514 elif self.display_number == "both":
515 den_duration = self.normal_type.ly_expression (None, True)
516 # If we don't have an actual type set, use the normal duration!
518 num_duration = self.actual_type.ly_expression (None, True)
520 num_duration = den_duration
521 if (self.display_denominator or self.display_numerator):
522 func ("\\once \\override TupletNumber #'text = #(tuplet-number::non-default-fraction-with-notes %s \"%s\" %s \"%s\")" %
523 (self.display_denominator, den_duration,
524 self.display_numerator, num_duration))
527 func ("\\once \\override TupletNumber #'text = #(tuplet-number::fraction-with-notes \"%s\" \"%s\")" %
528 (den_duration, num_duration))
531 if self.display_number == None:
532 func ("\\once \\override TupletNumber #'stencil = ##f")
534 elif self.display_number == "both":
535 func ("\\once \\override TupletNumber #'text = #%s" % base_number_function)
538 func ('\\times %d/%d ' %
539 (self.numerator, self.denominator))
540 func.add_factor (Rational (self.numerator, self.denominator))
541 MusicWrapper.print_ly (self, func)
544 class NestedMusic(Music):
546 Music.__init__ (self)
549 def append (self, what):
551 self.elements.append (what)
553 def has_children (self):
556 def insert_around (self, succ, elt, dir):
557 assert elt.parent == None
558 assert succ == None or succ in self.elements
563 idx = self.elements.index (succ)
570 idx = len (self.elements)
572 self.elements.insert (idx, elt)
575 def get_properties (self):
576 return ("'elements (list %s)"
577 % string.join (map (lambda x: x.lisp_expression(),
580 def get_subset_properties (self, predicate):
581 return ("'elements (list %s)"
582 % string.join (map (lambda x: x.lisp_expression(),
583 filter ( predicate, self.elements))))
584 def get_neighbor (self, music, dir):
585 assert music.parent == self
586 idx = self.elements.index (music)
588 idx = min (idx, len (self.elements) -1)
591 return self.elements[idx]
593 def delete_element (self, element):
594 assert element in self.elements
596 self.elements.remove (element)
597 element.parent = None
599 def set_start (self, start):
601 for e in self.elements:
604 def find_first (self, predicate):
605 r = Music.find_first (self, predicate)
609 for e in self.elements:
610 r = e.find_first (predicate)
615 class SequentialMusic (NestedMusic):
616 def get_last_event_chord (self):
618 at = len( self.elements ) - 1
620 not isinstance (self.elements[at], ChordEvent) and
621 not isinstance (self.elements[at], BarLine)):
624 if (at >= 0 and isinstance (self.elements[at], ChordEvent)):
625 value = self.elements[at]
628 def print_ly (self, printer, newline = True):
631 self.print_comment (printer)
635 for e in self.elements:
642 def lisp_sub_expression (self, pred):
646 props = self.get_subset_properties (pred)
648 return "(make-music '%s %s)" % (name, props)
650 def set_start (self, start):
651 for e in self.elements:
653 start += e.get_length()
657 self.repeat_type = "volta"
658 self.repeat_count = 2
661 def set_music (self, music):
662 if isinstance (music, Music):
664 elif isinstance (music, list):
665 self.music = SequentialMusic ()
666 self.music.elements = music
668 warning (_ ("unable to set the music %(music)s for the repeat %(repeat)s") % \
669 {'music':music, 'repeat':self})
670 def add_ending (self, music):
671 self.endings.append (music)
672 def print_ly (self, printer):
673 printer.dump ('\\repeat %s %s' % (self.repeat_type, self.repeat_count))
675 self.music.print_ly (printer)
677 warning (_ ("encountered repeat without body"))
680 printer.dump ('\\alternative {')
681 for e in self.endings:
688 self.lyrics_syllables = []
690 def print_ly (self, printer):
691 printer.dump ("\lyricmode {")
692 for l in self.lyrics_syllables:
693 printer.dump ( "%s " % l )
696 def ly_expression (self):
697 lstr = "\lyricmode {\n "
698 for l in self.lyrics_syllables:
706 self.header_fields = {}
707 def set_field (self, field, value):
708 self.header_fields[field] = value
710 def print_ly (self, printer):
711 printer.dump ("\header {")
713 for (k,v) in self.header_fields.items ():
715 printer.dump ('%s = %s' % (k,v))
724 self.global_staff_size = -1
727 self.page_height = -1
730 self.bottom_margin = -1
731 self.left_margin = -1
732 self.right_margin = -1
733 self.system_left_margin = -1
734 self.system_right_margin = -1
735 self.system_distance = -1
736 self.top_system_distance = -1
738 def print_length_field (self, printer, field, value):
740 printer.dump ("%s = %s\\cm" % (field, value))
742 def print_ly (self, printer):
743 if self.global_staff_size > 0:
744 printer.dump ('#(set-global-staff-size %s)' % self.global_staff_size)
746 printer.dump ('\\paper {')
748 self.print_length_field (printer, "paper-width", self.page_width)
749 self.print_length_field (printer, "paper-height", self.page_height)
750 self.print_length_field (printer, "top-margin", self.top_margin)
751 self.print_length_field (printer, "botton-margin", self.bottom_margin)
752 self.print_length_field (printer, "left-margin", self.left_margin)
753 # TODO: maybe set line-width instead of right-margin?
754 self.print_length_field (printer, "right-margin", self.right_margin)
755 # TODO: What's the corresponding setting for system_left_margin and
756 # system_right_margin in LilyPond?
757 self.print_length_field (printer, "between-system-space", self.system_distance)
758 self.print_length_field (printer, "page-top-space", self.top_system_distance)
765 self.context_dict = {}
766 def add_context (self, context):
767 if not self.context_dict.has_key (context):
768 self.context_dict[context] = []
769 def set_context_item (self, context, item):
770 self.add_context (context)
771 if not item in self.context_dict[context]:
772 self.context_dict[context].append (item)
773 def print_ly (self, printer):
774 if self.context_dict.items ():
775 printer.dump ('\\layout {')
777 for (context, defs) in self.context_dict.items ():
778 printer.dump ('\\context { \\%s' % context)
789 class ChordEvent (NestedMusic):
791 NestedMusic.__init__ (self)
792 self.after_grace_elements = None
793 self.grace_elements = None
794 self.grace_type = None
795 def append_grace (self, element):
797 if not self.grace_elements:
798 self.grace_elements = SequentialMusic ()
799 self.grace_elements.append (element)
800 def append_after_grace (self, element):
802 if not self.after_grace_elements:
803 self.after_grace_elements = SequentialMusic ()
804 self.after_grace_elements.append (element)
806 def has_elements (self):
807 return [e for e in self.elements if
808 isinstance (e, NoteEvent) or isinstance (e, RestEvent)] != []
811 def get_length (self):
813 for e in self.elements:
814 l = max(l, e.get_length())
817 def get_duration (self):
818 note_events = [e for e in self.elements if
819 isinstance (e, NoteEvent) or isinstance (e, RestEvent)]
821 return note_events[0].duration
825 def print_ly (self, printer):
826 note_events = [e for e in self.elements if
827 isinstance (e, NoteEvent)]
829 rest_events = [e for e in self.elements if
830 isinstance (e, RhythmicEvent)
831 and not isinstance (e, NoteEvent)]
833 other_events = [e for e in self.elements if
834 not isinstance (e, RhythmicEvent)]
836 if self.after_grace_elements:
837 printer ('\\afterGrace {')
839 if self.grace_elements and self.elements:
841 printer ('\\%s' % self.grace_type)
844 # don't print newlines after the { and } braces
845 self.grace_elements.print_ly (printer, False)
846 elif self.grace_elements: # no self.elements!
847 warning (_ ("Grace note with no following music: %s") % self.grace_elements)
849 printer ('\\%s' % self.grace_type)
852 self.grace_elements.print_ly (printer, False)
855 # Print all overrides and other settings needed by the
856 # articulations/ornaments before the note
857 for e in other_events:
858 e.print_before_note (printer)
861 rest_events[0].print_ly (printer)
862 elif len (note_events) == 1:
863 note_events[0].print_ly (printer)
865 global previous_pitch
868 for x in note_events:
869 pitches.append (x.chord_element_ly ())
871 basepitch = previous_pitch
872 printer ('<%s>' % string.join (pitches))
873 previous_pitch = basepitch
874 duration = self.get_duration ()
876 duration.print_ly (printer)
880 for e in other_events:
883 for e in other_events:
884 e.print_after_note (printer)
886 if self.after_grace_elements:
888 self.after_grace_elements.print_ly (printer, False)
890 self.print_comment (printer)
892 class Partial (Music):
894 Music.__init__ (self)
896 def print_ly (self, printer):
898 printer.dump ("\\partial %s" % self.partial.ly_expression ())
900 class BarLine (Music):
902 Music.__init__ (self)
906 def print_ly (self, printer):
907 bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': "dashed",
908 'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
909 'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
910 'short': "'|", 'none': "" }.get (self.type, None)
911 if bar_symbol <> None:
912 printer.dump ('\\bar "%s"' % bar_symbol)
916 if self.bar_number > 0 and (self.bar_number % 10) == 0:
917 printer.dump ("\\barNumberCheck #%d " % self.bar_number)
918 elif self.bar_number > 0:
919 printer.print_verbatim (' %% %d' % self.bar_number)
922 def ly_expression (self):
927 # strings to print before the note to which an event is attached.
928 # Ignored for notes etc.
929 self.before_note = None
930 self.after_note = None
931 # print something before the note to which an event is attached, e.g. overrides
932 def print_before_note (self, printer):
934 printer.dump (self.before_note)
935 # print something after the note to which an event is attached, e.g. resetting
936 def print_after_note (self, printer):
938 printer.dump (self.after_note)
941 class SpanEvent (Event):
943 Event.__init__ (self)
944 self.span_direction = 0 # start/stop
945 self.line_type = 'solid'
946 self.span_type = 0 # e.g. cres/decrescendo, ottava up/down
947 self.size = 0 # size of e.g. ocrave shift
948 def wait_for_note (self):
950 def get_properties(self):
951 return "'span-direction %d" % self.span_direction
952 def set_span_type (self, type):
953 self.span_type = type
955 class SlurEvent (SpanEvent):
956 def print_before_note (self, printer):
957 command = {'dotted': '\\slurDotted',
958 'dashed' : '\\slurDashed'}.get (self.line_type, '')
959 if command and self.span_direction == -1:
960 printer.dump (command)
961 def print_after_note (self, printer):
962 # reset non-solid slur types!
963 command = {'dotted': '\\slurSolid',
964 'dashed' : '\\slurSolid'}.get (self.line_type, '')
965 if command and self.span_direction == -1:
966 printer.dump (command)
967 def ly_expression (self):
968 return {-1: '(', 1:')'}.get (self.span_direction, '')
970 class BeamEvent (SpanEvent):
971 def ly_expression (self):
972 return {-1: '[', 1:']'}.get (self.span_direction, '')
974 class PedalEvent (SpanEvent):
975 def ly_expression (self):
976 return {-1: '\\sustainOn',
977 0:'\\sustainOff\\sustainOn',
978 1:'\\sustainOff'}.get (self.span_direction, '')
980 class TextSpannerEvent (SpanEvent):
981 def ly_expression (self):
982 return {-1: '\\startTextSpan',
983 1:'\\stopTextSpan'}.get (self.span_direction, '')
985 class BracketSpannerEvent (SpanEvent):
986 # Ligature brackets use prefix-notation!!!
987 def print_before_note (self, printer):
988 if self.span_direction == -1:
990 # the the bracket after the last note
991 def print_after_note (self, printer):
992 if self.span_direction == 1:
994 # we're printing everything in print_(before|after)_note...
995 def ly_expression (self):
999 class OctaveShiftEvent (SpanEvent):
1000 def wait_for_note (self):
1002 def set_span_type (self, type):
1003 self.span_type = {'up': 1, 'down': -1}.get (type, 0)
1004 def ly_octave_shift_indicator (self):
1005 # convert 8/15 to lilypond indicators (+-1/+-2)
1007 value = {8: 1, 15: 2}[self.size]
1009 warning (_ ("Invalid octave shift size found: %s. Using no shift.") % self.size)
1011 # negative values go up!
1012 value *= -1*self.span_type
1014 def ly_expression (self):
1015 dir = self.ly_octave_shift_indicator ()
1018 value = '\ottava #%s' % dir
1021 1: '\ottava #0'}.get (self.span_direction, '')
1023 class TrillSpanEvent (SpanEvent):
1024 def ly_expression (self):
1025 return {-1: '\\startTrillSpan',
1026 0: '', # no need to write out anything for type='continue'
1027 1:'\\stopTrillSpan'}.get (self.span_direction, '')
1029 class GlissandoEvent (SpanEvent):
1030 def print_before_note (self, printer):
1031 if self.span_direction == -1:
1033 "dashed" : "dashed-line",
1034 "dotted" : "dotted-line",
1036 }. get (self.line_type, None)
1038 printer.dump ("\once \override Glissando #'style = #'%s" % style)
1039 def ly_expression (self):
1040 return {-1: '\\glissando',
1041 1:''}.get (self.span_direction, '')
1043 class ArpeggioEvent(Event):
1044 def __init__ (self):
1045 Event.__init__ (self)
1047 self.non_arpeggiate = False
1048 def wait_for_note (self):
1050 def print_before_note (self, printer):
1051 if self.non_arpeggiate:
1052 printer.dump ("\\arpeggioBracket")
1054 dir = { -1: "\\arpeggioArrowDown", 1: "\\arpeggioArrowUp" }.get (self.direction, '')
1057 def print_after_note (self, printer):
1058 if self.non_arpeggiate or self.direction:
1059 printer.dump ("\\arpeggioNormal")
1060 def ly_expression (self):
1061 return ('\\arpeggio')
1064 class TieEvent(Event):
1065 def ly_expression (self):
1069 class HairpinEvent (SpanEvent):
1070 def set_span_type (self, type):
1071 self.span_type = {'crescendo' : 1, 'decrescendo' : -1, 'diminuendo' : -1 }.get (type, 0)
1072 def hairpin_to_ly (self):
1073 if self.span_direction == 1:
1076 return {1: '\<', -1: '\>'}.get (self.span_type, '')
1078 def ly_expression (self):
1079 return self.hairpin_to_ly ()
1081 def print_ly (self, printer):
1082 val = self.hairpin_to_ly ()
1088 class DynamicsEvent (Event):
1089 def __init__ (self):
1090 Event.__init__ (self)
1092 def wait_for_note (self):
1094 def ly_expression (self):
1096 return '\%s' % self.type
1100 def print_ly (self, printer):
1102 printer.dump ("\\%s" % self.type)
1104 class MarkEvent (Event):
1105 def __init__ (self, text="\\default"):
1106 Event.__init__ (self)
1108 def wait_for_note (self):
1110 def ly_contents (self):
1112 return '%s' % self.mark
1115 def ly_expression (self):
1116 return '\\mark %s' % self.ly_contents ()
1118 class MusicGlyphMarkEvent (MarkEvent):
1119 def ly_contents (self):
1121 return '\\markup { \\musicglyph #"scripts.%s" }' % self.mark
1126 class TextEvent (Event):
1127 def __init__ (self):
1128 Event.__init__ (self)
1130 self.force_direction = None
1132 def wait_for_note (self):
1135 def direction_mod (self):
1136 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1138 def ly_expression (self):
1139 base_string = '%s\"%s\"'
1141 base_string = '%s\markup{ ' + self.markup + ' {%s} }'
1142 return base_string % (self.direction_mod (), self.text)
1144 class ArticulationEvent (Event):
1145 def __init__ (self):
1146 Event.__init__ (self)
1148 self.force_direction = None
1149 def wait_for_note (self):
1152 def direction_mod (self):
1153 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '')
1155 def ly_expression (self):
1156 return '%s\\%s' % (self.direction_mod (), self.type)
1158 class ShortArticulationEvent (ArticulationEvent):
1159 def direction_mod (self):
1161 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1162 def ly_expression (self):
1164 return '%s%s' % (self.direction_mod (), self.type)
1168 class NoDirectionArticulationEvent (ArticulationEvent):
1169 def ly_expression (self):
1171 return '\\%s' % self.type
1175 class MarkupEvent (ShortArticulationEvent):
1176 def __init__ (self):
1177 ArticulationEvent.__init__ (self)
1178 self.contents = None
1179 def ly_expression (self):
1181 return "%s\\markup { %s }" % (self.direction_mod (), self.contents)
1185 class FretEvent (MarkupEvent):
1186 def __init__ (self):
1187 MarkupEvent.__init__ (self)
1188 self.force_direction = 1
1193 def ly_expression (self):
1195 if self.strings <> 6:
1196 val += "w:%s;" % self.strings
1198 val += "h:%s;" % self.frets
1199 if self.barre and len (self.barre) >= 3:
1200 val += "c:%s-%s-%s;" % (self.barre[0], self.barre[1], self.barre[2])
1201 have_fingering = False
1202 for i in self.elements:
1204 val += "%s-%s" % (i[0], i[1])
1206 have_fingering = True
1212 return "%s\\markup { \\fret-diagram #\"%s\" }" % (self.direction_mod (), val)
1217 class FunctionWrapperEvent (Event):
1218 def __init__ (self, function_name = None):
1219 Event.__init__ (self)
1220 self.function_name = function_name
1221 def pre_note_ly (self, is_chord_element):
1222 if self.function_name:
1223 return "\\%s" % self.function_name
1226 def pre_chord_ly (self):
1228 def ly_expression (self):
1229 if self.function_name:
1230 return "\\%s" % self.function_name
1234 class ParenthesizeEvent (FunctionWrapperEvent):
1235 def __init__ (self):
1236 FunctionWrapperEvent.__init__ (self, "parenthesize")
1238 class NotestyleEvent (Event):
1239 def __init__ (self):
1240 Event.__init__ (self)
1243 def pre_chord_ly (self):
1245 return "\\once \\override NoteHead #'style = #%s" % self.style
1248 def pre_note_ly (self, is_chord_element):
1249 if self.style and is_chord_element:
1250 return "\\tweak #'style #%s" % self.style
1253 def ly_expression (self):
1254 return self.pre_chord_ly ()
1258 def __init__ (self):
1262 return self.ly_expression()
1263 def ly_expression (self):
1264 return pitch_generating_function (self)
1266 class ChordModification:
1267 def __init__ (self):
1271 def ly_expression (self):
1273 val = {1: ".", -1: "^" }.get (self.type, "")
1274 val += "%s" % self.step
1275 val += {1: "+", -1: "-"}.get (self.alteration, "")
1280 class ChordNameEvent (Event):
1281 def __init__ (self):
1282 Event.__init__ (self)
1285 self.duration = None
1286 self.modifications = []
1288 def add_modification (self, mod):
1289 self.modifications.append (mod)
1290 def ly_expression (self):
1293 value = self.root.ly_expression ()
1295 value += self.duration.ly_expression ()
1299 # First print all additions/changes, and only afterwards all subtractions
1300 for m in self.modifications:
1302 value += m.ly_expression ()
1303 for m in self.modifications:
1305 value += m.ly_expression ()
1307 value += "/+%s" % self.bass.ly_expression ()
1311 class TremoloEvent (ArticulationEvent):
1312 def __init__ (self):
1313 Event.__init__ (self)
1316 def ly_expression (self):
1318 if self.bars and self.bars > 0:
1319 str += ':%s' % (2 ** (2 + string.atoi (self.bars)))
1322 class BendEvent (ArticulationEvent):
1323 def __init__ (self):
1324 Event.__init__ (self)
1326 def ly_expression (self):
1327 if self.alter != None:
1328 return "-\\bendAfter #%s" % self.alter
1332 class RhythmicEvent(Event):
1333 def __init__ (self):
1334 Event.__init__ (self)
1335 self.duration = Duration()
1336 self.associated_events = []
1338 def add_associated_event (self, ev):
1340 self.associated_events.append (ev)
1342 def pre_chord_ly (self):
1343 return [ev.pre_chord_ly () for ev in self.associated_events]
1345 def pre_note_ly (self, is_chord_element):
1346 return [ev.pre_note_ly (is_chord_element) for ev in self.associated_events]
1348 def ly_expression_pre_note (self, is_chord_element):
1349 res = string.join (self.pre_note_ly (is_chord_element), ' ')
1354 def get_length (self):
1355 return self.duration.get_length()
1357 def get_properties (self):
1358 return ("'duration %s"
1359 % self.duration.lisp_expression ())
1361 class RestEvent (RhythmicEvent):
1362 def __init__ (self):
1363 RhythmicEvent.__init__ (self)
1366 def ly_expression (self):
1367 res = self.ly_expression_pre_note (False)
1369 return res + "%s%s\\rest" % (self.pitch.ly_expression (), self.duration.ly_expression ())
1371 return 'r%s' % self.duration.ly_expression ()
1373 def print_ly (self, printer):
1374 for ev in self.associated_events:
1375 ev.print_ly (printer)
1377 self.pitch.print_ly (printer)
1378 self.duration.print_ly (printer)
1382 self.duration.print_ly (printer)
1384 class SkipEvent (RhythmicEvent):
1385 def ly_expression (self):
1386 return 's%s' % self.duration.ly_expression ()
1388 class NoteEvent(RhythmicEvent):
1389 def __init__ (self):
1390 RhythmicEvent.__init__ (self)
1392 self.drum_type = None
1393 self.cautionary = False
1394 self.forced_accidental = False
1396 def get_properties (self):
1397 str = RhythmicEvent.get_properties (self)
1400 str += self.pitch.lisp_expression ()
1401 elif self.drum_type:
1402 str += "'drum-type '%s" % self.drum_type
1406 def pitch_mods (self):
1409 excl_question += '?'
1410 if self.forced_accidental:
1411 excl_question += '!'
1413 return excl_question
1415 def ly_expression (self):
1416 # obtain all stuff that needs to be printed before the note:
1417 res = self.ly_expression_pre_note (True)
1419 return res + '%s%s%s' % (self.pitch.ly_expression (),
1421 self.duration.ly_expression ())
1422 elif self.drum_type:
1423 return res + '%s%s' (self.drum_type,
1424 self.duration.ly_expression ())
1426 def chord_element_ly (self):
1427 # obtain all stuff that needs to be printed before the note:
1428 res = self.ly_expression_pre_note (True)
1430 return res + '%s%s' % (self.pitch.ly_expression (),
1432 elif self.drum_type:
1433 return res + '%s%s' (self.drum_type)
1436 def print_ly (self, printer):
1437 for ev in self.associated_events:
1438 ev.print_ly (printer)
1440 self.pitch.print_ly (printer)
1441 printer (self.pitch_mods ())
1443 printer (self.drum_type)
1445 self.duration.print_ly (printer)
1447 class KeySignatureChange (Music):
1448 def __init__ (self):
1449 Music.__init__ (self)
1452 self.non_standard_alterations = None
1454 def format_non_standard_alteration (self, a):
1455 alter_dict = { -2: ",DOUBLE-FLAT",
1456 -1.5: ",THREE-Q-FLAT",
1462 1.5: ",THREE-Q-SHARP",
1465 accidental = alter_dict[a[1]]
1467 warning (_ ("Unable to convert alteration %s to a lilypond expression") % a[1])
1470 return "( %s . %s )" % (a[0], accidental)
1472 return "(( %s . %s ) . %s )" % (a[2], a[0], accidental)
1476 def ly_expression (self):
1478 return '\\key %s \\%s' % (self.tonic.ly_step_expression (),
1480 elif self.non_standard_alterations:
1481 alterations = [self.format_non_standard_alteration (a) for
1482 a in self.non_standard_alterations]
1483 return "\\set Staff.keySignature = #`(%s)" % string.join (alterations, " ")
1487 class TimeSignatureChange (Music):
1488 def __init__ (self):
1489 Music.__init__ (self)
1490 self.fractions = [4,4]
1492 def format_fraction (self, frac):
1493 if isinstance (frac, list):
1494 l = [self.format_fraction (f) for f in frac]
1495 return "(" + string.join (l, " ") + ")"
1499 def ly_expression (self):
1501 # Print out the style if we have ome, but the '() should only be
1502 # forced for 2/2 or 4/4, since in all other cases we'll get numeric
1503 # signatures anyway despite the default 'C signature style!
1504 is_common_signature = self.fractions in ([2,2], [4,4], [4,2])
1506 if self.style == "common":
1507 st = "\\defaultTimeSignature"
1508 elif (self.style != "'()"):
1509 st = "\\once \\override Staff.TimeSignature #'style = #%s " % self.style
1510 elif (self.style != "'()") or is_common_signature:
1511 st = "\\numericTimeSignature"
1513 # Easy case: self.fractions = [n,d] => normal \time n/d call:
1514 if len (self.fractions) == 2 and isinstance (self.fractions[0], int):
1515 return st + '\\time %d/%d ' % tuple (self.fractions)
1516 elif self.fractions:
1517 return st + "\\compoundMeter #'%s" % self.format_fraction (self.fractions)
1521 class ClefChange (Music):
1522 def __init__ (self):
1523 Music.__init__ (self)
1528 def octave_modifier (self):
1529 return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self.octave, '')
1530 def clef_name (self):
1531 return {('G', 2): "treble",
1533 ('C', 1): "soprano",
1534 ('C', 2): "mezzosoprano",
1537 ('C', 5): "baritone",
1538 ('F', 3): "varbaritone",
1540 ('F', 5): "subbass",
1541 ("percussion", 2): "percussion",
1542 # Workaround: MuseScore uses PERC instead of percussion
1543 ("PERC", 2): "percussion",
1544 ("TAB", 5): "tab"}.get ((self.type, self.position), None)
1545 def ly_expression (self):
1546 return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ())
1549 "G": ("clefs.G", -2, -6),
1550 "C": ("clefs.C", 0, 0),
1551 "F": ("clefs.F", 2, 6),
1554 def lisp_expression (self):
1556 (glyph, pos, c0) = self.clef_dict[self.type]
1560 (make-music 'SequentialMusic
1563 (make-property-set 'clefGlyph "%s") 'Staff)
1565 (make-property-set 'clefPosition %d) 'Staff)
1567 (make-property-set 'middleCPosition %d) 'Staff)))
1568 """ % (glyph, pos, c0)
1571 class Transposition (Music):
1572 def __init__ (self):
1573 Music.__init__ (self)
1575 def ly_expression (self):
1576 self.pitch._force_absolute_pitch = True
1577 return '\\transposition %s' % self.pitch.ly_expression ()
1579 class StaffChange (Music):
1580 def __init__ (self, staff):
1581 Music.__init__ (self)
1583 def ly_expression (self):
1585 return "\\change Staff=\"%s\"" % self.staff
1590 class TempoMark (Music):
1591 def __init__ (self):
1592 Music.__init__ (self)
1593 self.baseduration = None
1594 self.newduration = None
1596 self.parentheses = False
1597 def set_base_duration (self, dur):
1598 self.baseduration = dur
1599 def set_new_duration (self, dur):
1600 self.newduration = dur
1601 def set_beats_per_minute (self, beats):
1603 def set_parentheses (self, parentheses):
1604 self.parentheses = parentheses
1605 def wait_for_note (self):
1607 def duration_to_markup (self, dur):
1609 # Generate the markup to print the note, use scheme mode for
1610 # ly_expression to get longa and not \longa (which causes an error)
1611 return "\\general-align #Y #DOWN \\smaller \\note #\"%s\" #UP" % dur.ly_expression(None, True)
1614 def tempo_markup_template (self):
1615 return "\\mark\\markup { \\fontsize #-2 \\line { %s } }"
1616 def ly_expression (self):
1618 if not self.baseduration:
1621 if self.parentheses:
1622 res += "\\tempo \"\" %s=%s" % (self.baseduration.ly_expression(), self.beats)
1624 res += "\\tempo %s=%s" % (self.baseduration.ly_expression(), self.beats)
1625 elif self.newduration:
1626 dm = self.duration_to_markup (self.baseduration)
1627 ndm = self.duration_to_markup (self.newduration)
1628 if self.parentheses:
1629 contents = "\"(\" %s = %s \")\"" % (dm, ndm)
1631 contents = " %s = %s " % (dm, ndm)
1632 res += self.tempo_markup_template() % contents
1637 class FiguredBassNote (Music):
1638 def __init__ (self):
1639 Music.__init__ (self)
1643 def set_prefix (self, prefix):
1644 self.prefix = prefix
1645 def set_suffix (self, suffix):
1646 self.prefix = suffix
1647 def set_number (self, number):
1648 self.number = number
1649 def ly_expression (self):
1662 class FiguredBassEvent (NestedMusic):
1663 def __init__ (self):
1664 NestedMusic.__init__ (self)
1665 self.duration = None
1666 self.real_duration = 0
1667 self.parentheses = False
1669 def set_duration (self, dur):
1671 def set_parentheses (self, par):
1672 self.parentheses = par
1673 def set_real_duration (self, dur):
1674 self.real_duration = dur
1676 def print_ly (self, printer):
1677 figured_bass_events = [e for e in self.elements if
1678 isinstance (e, FiguredBassNote)]
1679 if figured_bass_events:
1681 for x in figured_bass_events:
1682 notes.append (x.ly_expression ())
1683 contents = string.join (notes)
1684 if self.parentheses:
1685 contents = '[%s]' % contents
1686 printer ('<%s>' % contents)
1687 self.duration.print_ly (printer)
1690 class MultiMeasureRest(Music):
1692 def lisp_expression (self):
1695 'MultiMeasureRestMusicGroup
1697 (list (make-music (quote BarCheck))
1702 'MultiMeasureRestEvent
1705 (make-music (quote BarCheck))))
1706 """ % self.duration.lisp_expression ()
1708 def ly_expression (self):
1709 return 'R%s' % self.duration.ly_expression ()
1712 class Break (Music):
1713 def __init__ (self, tp="break"):
1714 Music.__init__ (self)
1716 def print_ly (self, printer):
1718 printer.dump ("\\%s" % self.type)
1721 def __init__ (self, command = "StaffGroup"):
1722 self.stafftype = command
1724 self.instrument_name = None
1725 self.short_instrument_name = None
1729 self.is_group = True
1730 # part_information is a list with entries of the form
1731 # [staffid, voicelist]
1732 # where voicelist is a list with entries of the form
1733 # [voiceid1, [lyricsid11, lyricsid12,...] ]
1734 self.part_information = None
1736 def append_staff (self, staff):
1737 self.children.append (staff)
1739 def set_part_information (self, part_name, staves_info):
1740 if part_name == self.id:
1741 self.part_information = staves_info
1743 for c in self.children:
1744 c.set_part_information (part_name, staves_info)
1746 def print_ly_contents (self, printer):
1747 for c in self.children:
1749 c.print_ly (printer)
1750 def print_ly_overrides (self, printer):
1752 needs_with |= self.spanbar == "no"
1753 needs_with |= self.instrument_name != None
1754 needs_with |= self.short_instrument_name != None
1755 needs_with |= (self.symbol != None) and (self.symbol != "bracket")
1757 printer.dump ("\\with {")
1758 if self.instrument_name or self.short_instrument_name:
1759 printer.dump ("\\consists \"Instrument_name_engraver\"")
1760 if self.spanbar == "no":
1761 printer.dump ("\\override SpanBar #'transparent = ##t")
1762 brack = {"brace": "SystemStartBrace",
1764 "line": "SystemStartSquare"}.get (self.symbol, None)
1766 printer.dump ("systemStartDelimiter = #'%s" % brack)
1769 def print_ly (self, printer):
1771 printer.dump ("\\new %s" % self.stafftype)
1772 self.print_ly_overrides (printer)
1775 if self.stafftype and self.instrument_name:
1776 printer.dump ("\\set %s.instrumentName = %s" % (self.stafftype,
1777 escape_instrument_string (self.instrument_name)))
1779 if self.stafftype and self.short_instrument_name:
1780 printer.dump ("\\set %s.shortInstrumentName = %s" % (self.stafftype,
1781 escape_instrument_string (self.short_instrument_name)))
1783 self.print_ly_contents (printer)
1789 class Staff (StaffGroup):
1790 def __init__ (self, command = "Staff"):
1791 StaffGroup.__init__ (self, command)
1792 self.is_group = False
1794 self.voice_command = "Voice"
1795 self.substafftype = None
1797 def print_ly_overrides (self, printer):
1800 def print_ly_contents (self, printer):
1801 if not self.id or not self.part_information:
1803 sub_staff_type = self.substafftype
1804 if not sub_staff_type:
1805 sub_staff_type = self.stafftype
1807 for [staff_id, voices] in self.part_information:
1808 # Chord names need to come before the staff itself!
1809 for [v, lyrics, figuredbass, chordnames] in voices:
1811 printer ('\context ChordNames = "%s" \\%s' % (chordnames, chordnames))
1813 # now comes the real staff definition:
1815 printer ('\\context %s = "%s" << ' % (sub_staff_type, staff_id))
1817 printer ('\\context %s << ' % sub_staff_type)
1820 nr_voices = len (voices)
1821 for [v, lyrics, figuredbass, chordnames] in voices:
1823 voice_count_text = ''
1825 voice_count_text = {1: ' \\voiceOne', 2: ' \\voiceTwo',
1826 3: ' \\voiceThree'}.get (n, ' \\voiceFour')
1827 printer ('\\context %s = "%s" {%s \\%s }' % (self.voice_command, v, voice_count_text, v))
1831 printer ('\\new Lyrics \\lyricsto "%s" \\%s' % (v,l))
1834 printer ('\context FiguredBass = "%s" \\%s' % (figuredbass, figuredbass))
1837 def print_ly (self, printer):
1838 if self.part_information and len (self.part_information) > 1:
1839 self.stafftype = "PianoStaff"
1840 self.substafftype = "Staff"
1841 StaffGroup.print_ly (self, printer)
1843 class TabStaff (Staff):
1844 def __init__ (self, command = "TabStaff"):
1845 Staff.__init__ (self, command)
1846 self.string_tunings = []
1847 self.tablature_format = None
1848 self.voice_command = "TabVoice"
1849 def print_ly_overrides (self, printer):
1850 if self.string_tunings or self.tablature_format:
1851 printer.dump ("\\with {")
1852 if self.string_tunings:
1853 printer.dump ("stringTunings = #'(")
1854 for i in self.string_tunings:
1855 printer.dump ("%s" % i.semitones ())
1857 if self.tablature_format:
1858 printer.dump ("tablatureFormat = #%s" % self.tablature_format)
1862 class DrumStaff (Staff):
1863 def __init__ (self, command = "DrumStaff"):
1864 Staff.__init__ (self, command)
1865 self.drum_style_table = None
1866 self.voice_command = "DrumVoice"
1867 def print_ly_overrides (self, printer):
1868 if self.drum_style_table:
1869 printer.dump ("\with {")
1870 printer.dump ("drumStyleTable = #%s" % self.drum_style_table)
1873 class RhythmicStaff (Staff):
1874 def __init__ (self, command = "RhythmicStaff"):
1875 Staff.__init__ (self, command)
1878 def __init__ (self):
1879 self.contents = None
1880 self.create_midi = False
1882 def set_contents (self, contents):
1883 self.contents = contents
1885 def set_part_information (self, part_id, staves_info):
1887 self.contents.set_part_information (part_id, staves_info)
1889 def print_ly (self, printer):
1890 printer.dump ("\\score {");
1893 self.contents.print_ly (printer);
1894 printer.dump ("\\layout {}");
1896 if not self.create_midi:
1897 printer.dump ("% To create MIDI output, uncomment the following line:");
1899 printer.dump ("% ");
1900 printer.dump ("\\midi {}");
1908 bflat.alteration = -1
1918 print bflat.semitones()
1919 print bflat.transposed (fifth), bflat.transposed (fifth).transposed (fifth)
1920 print bflat.transposed (fifth).transposed (fifth).transposed (fifth)
1922 print bflat.semitones(), 'down'
1923 print bflat.transposed (down)
1924 print bflat.transposed (down).transposed (down)
1925 print bflat.transposed (down).transposed (down).transposed (down)
1929 def test_printer ():
1937 m = SequentialMusic()
1938 m.append (make_note ())
1939 m.append (make_note ())
1940 m.append (make_note ())
1943 t = TimeScaledMusic ()
1949 m = SequentialMusic ()
1950 m.append (make_tup ())
1951 m.append (make_tup ())
1952 m.append (make_tup ())
1954 printer = Output_printer()
1955 m.print_ly (printer)
1959 m = SequentialMusic()
1963 n.duration.duration_log = l
1965 evc.insert_around (None, n, 0)
1966 m.insert_around (None, evc, 0)
1970 n.duration.duration_log = l
1972 evc.insert_around (None, n, 0)
1973 m.insert_around (None, evc, 0)
1977 n.duration.duration_log = l
1979 evc.insert_around (None, n, 0)
1980 m.insert_around (None, evc, 0)
1984 m.insert_around (None, evc, 0)
1989 tonic.alteration = -2
1990 n = KeySignatureChange()
1991 n.tonic=tonic.copy()
1992 n.scale = [0, 0, -2, 0, 0,-2,-2]
1994 evc.insert_around (None, n, 0)
1995 m.insert_around (None, evc, 0)
2000 if __name__ == '__main__':
2006 expr.set_start (Rational (0))
2007 print expr.ly_expression()
2008 start = Rational (0,4)
2009 stop = Rational (4,2)
2010 def sub(x, start=start, stop=stop):
2011 ok = x.start >= start and x.start +x.get_length() <= stop
2014 print expr.lisp_sub_expression(sub)