6 from rational import Rational
9 def escape_instrument_string (input_string):
10 retstring = string.replace (input_string, "\"", "\\\"")
11 if re.match ('.*\n.*', retstring):
12 strings = retstring.split ('\r\n')
13 retstring = "\\markup { \\column { "
15 retstring += "\\line {\"" + s + "\"} "
18 retstring = "\"" + retstring + "\""
21 class Output_stack_element:
23 self.factor = Rational (1)
25 o = Output_stack_element()
26 o.factor = self.factor
31 """A class that takes care of formatting (eg.: indenting) a
32 Music expression as a .ly file.
35 ## TODO: support for \relative.
41 self._file = sys.stdout
43 self._output_state_stack = [Output_stack_element()]
44 self._skipspace = False
45 self._last_duration = None
47 def set_file (self, file):
50 def dump_version (self):
52 self.print_verbatim ('\\version "@TOPLEVEL_VERSION@"')
55 def get_indent (self):
56 return self._nesting * self._indent
59 last = self._output_state_stack[-1]
60 self._output_state_stack.append (last.copy())
62 def add_factor (self, factor):
64 self._output_state_stack[-1].factor *= factor
67 del self._output_state_stack[-1]
68 if not self._output_state_stack:
71 def duration_factor (self):
72 return self._output_state_stack[-1].factor
74 def print_verbatim (self, str):
77 def unformatted_output (self, str):
78 # don't indent on \< and indent only once on <<
79 self._nesting += ( str.count ('<')
80 - str.count ('\<') - str.count ('<<')
82 self._nesting -= ( str.count ('>') - str.count ('\>') - str.count ('>>')
83 - str.count ('->') - str.count ('_>')
86 self.print_verbatim (str)
88 def print_duration_string (self, str):
89 if self._last_duration == str:
92 self.unformatted_output (str)
94 def add_word (self, str):
95 if (len (str) + 1 + len (self._line) > self._line_len):
97 self._skipspace = True
99 if not self._skipspace:
101 self.unformatted_output (str)
102 self._skipspace = False
105 self._file.write (self._line + '\n')
106 self._line = ' ' * self._indent * self._nesting
107 self._skipspace = True
109 def skipspace (self):
110 self._skipspace = True
112 def __call__(self, arg):
115 def dump (self, str):
117 self._skipspace = False
118 self.unformatted_output (str)
120 words = string.split (str)
133 self.duration_log = 0
135 self.factor = Rational (1)
137 def lisp_expression (self):
138 return '(ly:make-duration %d %d %d %d)' % (self.duration_log,
140 self.factor.numerator (),
141 self.factor.denominator ())
144 def ly_expression (self, factor = None):
148 str = '%d%s' % (1 << self.duration_log, '.'*self.dots)
150 if factor <> Rational (1,1):
151 if factor.denominator () <> 1:
152 str += '*%d/%d' % (factor.numerator (), factor.denominator ())
154 str += '*%d' % factor.numerator ()
158 def print_ly (self, outputter):
159 str = self.ly_expression (self.factor / outputter.duration_factor ())
160 outputter.print_duration_string (str)
163 return self.ly_expression()
168 d.duration_log = self.duration_log
169 d.factor = self.factor
172 def get_length (self):
173 dot_fact = Rational( (1 << (1 + self.dots))-1,
176 log = abs (self.duration_log)
178 if self.duration_log < 0:
179 base = Rational (dur)
181 base = Rational (1, dur)
183 return base * dot_fact * self.factor
193 return self.ly_expression()
195 def transposed (self, interval):
197 c.alteration += interval.alteration
198 c.step += interval.step
199 c.octave += interval.octave
202 target_st = self.semitones() + interval.semitones()
203 c.alteration += target_st - c.semitones()
210 c.octave += c.step / 7
213 def lisp_expression (self):
214 return '(ly:make-pitch %d %d %d)' % (self.octave,
220 p.alteration = self.alteration
222 p.octave = self.octave
226 return self.step + self.octave *7
228 def semitones (self):
229 return self.octave * 12 + [0,2,4,5,7,9,11][self.step] + self.alteration
231 def ly_step_expression (self):
232 str = 'cdefgab'[self.step]
233 if self.alteration > 0:
234 str += 'is'* (self.alteration)
235 elif self.alteration < 0:
236 str += 'es'* (-self.alteration)
238 return str.replace ('aes', 'as').replace ('ees', 'es')
240 def ly_expression (self):
241 str = self.ly_step_expression ()
243 str += "'" * (self.octave + 1)
244 elif self.octave < -1:
245 str += "," * (-self.octave - 1)
249 def print_ly (self, outputter):
250 outputter (self.ly_expression())
255 self.start = Rational (0)
257 self.identifier = None
259 def get_length(self):
262 def get_properties (self):
265 def has_children (self):
268 def get_index (self):
270 return self.parent.elements.index (self)
274 return self.__class__.__name__
276 def lisp_expression (self):
279 props = self.get_properties ()
281 return "(make-music '%s %s)" % (name, props)
283 def set_start (self, start):
286 def find_first (self, predicate):
291 def print_comment (self, printer, text = None):
302 lines = string.split (text, '\n')
305 printer.unformatted_output ('% ' + l)
309 def print_with_identifier (self, printer):
311 printer ("\\%s" % self.identifier)
313 self.print_ly (printer)
315 def print_ly (self, printer):
316 printer (self.ly_expression ())
318 class MusicWrapper (Music):
322 def print_ly (self, func):
323 self.element.print_ly (func)
325 class ModeChangingMusicWrapper (MusicWrapper):
327 MusicWrapper.__init__ (self)
328 self.mode = 'notemode'
330 def print_ly (self, func):
331 func ('\\%s' % self.mode)
332 MusicWrapper.print_ly (self, func)
334 class TimeScaledMusic (MusicWrapper):
335 def print_ly (self, func):
336 func ('\\times %d/%d ' %
337 (self.numerator, self.denominator))
338 func.add_factor (Rational (self.numerator, self.denominator))
339 MusicWrapper.print_ly (self, func)
342 class NestedMusic(Music):
344 Music.__init__ (self)
347 def append (self, what):
349 self.elements.append (what)
351 def has_children (self):
354 def insert_around (self, succ, elt, dir):
355 assert elt.parent == None
356 assert succ == None or succ in self.elements
361 idx = self.elements.index (succ)
368 idx = len (self.elements)
370 self.elements.insert (idx, elt)
373 def get_properties (self):
374 return ("'elements (list %s)"
375 % string.join (map (lambda x: x.lisp_expression(),
378 def get_subset_properties (self, predicate):
379 return ("'elements (list %s)"
380 % string.join (map (lambda x: x.lisp_expression(),
381 filter ( predicate, self.elements))))
382 def get_neighbor (self, music, dir):
383 assert music.parent == self
384 idx = self.elements.index (music)
386 idx = min (idx, len (self.elements) -1)
389 return self.elements[idx]
391 def delete_element (self, element):
392 assert element in self.elements
394 self.elements.remove (element)
395 element.parent = None
397 def set_start (self, start):
399 for e in self.elements:
402 def find_first (self, predicate):
403 r = Music.find_first (self, predicate)
407 for e in self.elements:
408 r = e.find_first (predicate)
413 class SequentialMusic (NestedMusic):
414 def get_last_event_chord (self):
416 at = len( self.elements ) - 1
418 not isinstance (self.elements[at], EventChord) and
419 not isinstance (self.elements[at], BarLine)):
422 if (at >= 0 and isinstance (self.elements[at], EventChord)):
423 value = self.elements[at]
426 def print_ly (self, printer, newline = True):
429 self.print_comment (printer)
433 for e in self.elements:
440 def lisp_sub_expression (self, pred):
444 props = self.get_subset_properties (pred)
446 return "(make-music '%s %s)" % (name, props)
448 def set_start (self, start):
449 for e in self.elements:
451 start += e.get_length()
455 self.repeat_type = "volta"
456 self.repeat_count = 2
459 def set_music (self, music):
460 if isinstance (music, Music):
462 elif isinstance (music, list):
463 self.music = SequentialMusic ()
464 self.music.elements = music
466 sys.stderr.write ("WARNING: Unable to set the music %s for the repeat %s" % (music, self))
467 def add_ending (self, music):
468 self.endings.append (music)
469 def print_ly (self, printer):
470 printer.dump ('\\repeat %s %s' % (self.repeat_type, self.repeat_count))
472 self.music.print_ly (printer)
474 sys.stderr.write ("WARNING: Encountered repeat without body\n")
477 printer.dump ('\\alternative {')
478 for e in self.endings:
485 self.lyrics_syllables = []
487 def print_ly (self, printer):
488 printer.dump ("\lyricmode {")
489 for l in self.lyrics_syllables:
490 printer.dump ( "%s " % l )
493 def ly_expression (self):
494 lstr = "\lyricmode {\n "
495 for l in self.lyrics_syllables:
503 self.header_fields = {}
504 def set_field (self, field, value):
505 self.header_fields[field] = value
507 def print_ly (self, printer):
508 printer.dump ("\header {")
510 for (k,v) in self.header_fields.items ():
512 printer.dump ('%s = %s' % (k,v))
521 class EventChord (NestedMusic):
523 NestedMusic.__init__ (self)
524 self.grace_elements = None
525 self.grace_type = None
526 def append_grace (self, element):
528 if not self.grace_elements:
529 self.grace_elements = SequentialMusic ()
530 self.grace_elements.append (element)
532 def get_length (self):
534 for e in self.elements:
535 l = max(l, e.get_length())
538 def print_ly (self, printer):
539 note_events = [e for e in self.elements if
540 isinstance (e, NoteEvent)]
542 rest_events = [e for e in self.elements if
543 isinstance (e, RhythmicEvent)
544 and not isinstance (e, NoteEvent)]
546 other_events = [e for e in self.elements if
547 not isinstance (e, RhythmicEvent)]
549 if self.grace_elements and self.elements:
551 printer ('\\%s' % self.grace_type)
554 # don't print newlines after the { and } braces
555 self.grace_elements.print_ly (printer, False)
558 rest_events[0].print_ly (printer)
559 elif len (note_events) == 1:
560 note_events[0].print_ly (printer)
562 pitches = [x.pitch.ly_expression () for x in note_events]
563 printer ('<%s>' % string.join (pitches))
564 note_events[0].duration.print_ly (printer)
568 for e in other_events:
571 self.print_comment (printer)
573 class Partial (Music):
575 Music.__init__ (self)
577 def print_ly (self, printer):
579 printer.dump ("\\partial %s" % self.partial.ly_expression ())
581 class BarLine (Music):
583 Music.__init__ (self)
587 def print_ly (self, printer):
588 bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': ":",
589 'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
590 'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
591 'short': "'", 'none': "" }.get (self.type, None)
592 if bar_symbol <> None:
593 printer.dump ('\\bar "%s"' % bar_symbol)
597 if self.bar_number > 0 and (self.bar_number % 10) == 0:
598 printer.dump ("\\barNumberCheck #%d " % self.bar_number)
600 printer.print_verbatim (' %% %d' % self.bar_number)
603 def ly_expression (self):
609 class SpanEvent (Event):
611 Event.__init__ (self)
612 self.span_direction = 0 # start/stop
613 self.line_type = 'solid'
614 self.span_type = 0 # e.g. cres/decrescendo, ottava up/down
615 self.size = 0 # size of e.g. ocrave shift
616 def wait_for_note (self):
618 def get_properties(self):
619 return "'span-direction %d" % self.span_direction
620 def set_span_type (self, type):
621 self.span_type = type
623 class SlurEvent (SpanEvent):
624 def ly_expression (self):
627 # TODO: setting dashed/dotted line style does not work, because that
628 # command needs to be written before the note, not when the
629 # event is observed after the note!
630 #before = {'dotted': '\\slurDotted',
631 # 'dashed' : '\\slurDashed'}.get (self.line_type, '')
633 #after = '\\slurSolid'
635 return {-1: before + '(' + after,
636 1:')'}.get (self.span_direction, '')
638 class BeamEvent (SpanEvent):
639 def ly_expression (self):
641 1:']'}.get (self.span_direction, '')
643 class PedalEvent (SpanEvent):
644 def ly_expression (self):
645 return {-1: '\\sustainDown',
646 1:'\\sustainUp'}.get (self.span_direction, '')
648 # type==-1 means octave up, type==-2 means octave down
649 class OctaveShiftEvent (SpanEvent):
650 def wait_for_note (self):
652 def set_span_type (self, type):
653 self.span_type = {'up': 1, 'down': -1}.get (type, 0)
654 def ly_octave_shift_indicator (self):
655 # convert 8/15 to lilypond indicators (+-1/+-2)
656 value = {8: 1, 15: 2}.get (self.size, 0)
657 # negative values go up!
658 value *= -1*self.span_type
660 def ly_expression (self):
661 dir = self.ly_octave_shift_indicator ()
664 value = '#(set-octavation %s)' % dir
667 1: '#(set-octavation 0)'}.get (self.span_direction, '')
669 class TrillSpanEvent (SpanEvent):
670 def ly_expression (self):
671 return {-1: '\\startTrillSpan',
672 0: '', # no need to write out anything for type='continue'
673 1:'\\stopTrillSpan'}.get (self.span_direction, '')
675 class GlissandoEvent (SpanEvent):
676 def ly_expression (self):
678 # TODO: wavy-line glissandos don't work, becasue the style has to be
679 # set before the note, at the \glissando it's already too late!
680 #if self.line_type == 'wavy':
681 #style = "\once\override Glissando #'style = #'zigzag"
682 # In lilypond, glissando is NOT a spanner, unlike MusicXML.
683 return {-1: style + '\\glissando',
684 1:''}.get (self.span_direction, '')
686 class ArpeggioEvent(Event):
687 def wait_for_note (self):
689 def ly_expression (self):
690 return ('\\arpeggio')
693 class TieEvent(Event):
694 def ly_expression (self):
698 class HairpinEvent (SpanEvent):
699 def set_span_type (self, type):
700 self.span_type = {'crescendo' : 1, 'decrescendo' : -1, 'diminuendo' : -1 }.get (type, 0)
701 def hairpin_to_ly (self):
702 if self.span_direction == 1:
705 return {1: '\<', -1: '\>'}.get (self.span_type, '')
707 def ly_expression (self):
708 return self.hairpin_to_ly ()
710 def print_ly (self, printer):
711 val = self.hairpin_to_ly ()
717 class DynamicsEvent (Event):
720 self.available_commands = [ "ppppp", "pppp", "ppp", "pp", "p",
722 "f", "ff", "fff", "ffff",
723 "fp", "sf", "sff", "sp", "spp", "sfz", "rfz" ];
724 def wait_for_note (self):
726 def ly_expression (self):
727 if self.type == None:
729 elif self.type in self.available_commands:
730 return '\%s' % self.type
732 return '-\markup{ \dynamic %s }' % self.type
734 def print_ly (self, printer):
735 if self.type == None:
737 elif self.type in self.available_commands:
738 printer.dump ("\\%s" % self.type)
740 printer.dump ("-\\markup{ \\dynamic %s }" % self.type)
743 class TextEvent (Event):
746 self.force_direction = None
748 def wait_for_note (self):
751 def direction_mod (self):
752 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
754 def ly_expression (self):
755 base_string = '%s\"%s\"'
757 base_string = '%s\markup{ ' + self.markup + ' {%s} }'
758 return base_string % (self.direction_mod (), self.text)
760 class ArticulationEvent (Event):
763 self.force_direction = None
765 def direction_mod (self):
766 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '')
768 def ly_expression (self):
769 return '%s\\%s' % (self.direction_mod (), self.type)
771 class ShortArticulationEvent (ArticulationEvent):
772 def direction_mod (self):
774 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
775 def ly_expression (self):
776 return '%s%s' % (self.direction_mod (), self.type)
778 class NoDirectionArticulationEvent (ArticulationEvent):
779 def ly_expression (self):
780 return '\\%s' % self.type
782 class MarkupEvent (ShortArticulationEvent):
784 ArticulationEvent.__init__ (self)
786 def ly_expression (self):
788 return "%s\\markup { %s }" % (self.direction_mod (), self.contents)
790 class TremoloEvent (ArticulationEvent):
792 Event.__init__ (self)
795 def ly_expression (self):
797 if self.bars and self.bars > 0:
798 str += ':%s' % (2 ** (2 + string.atoi (self.bars)))
801 class BendEvent (ArticulationEvent):
803 Event.__init__ (self)
805 def ly_expression (self):
807 return "-\\bendAfter #%s" % self.alter
811 class RhythmicEvent(Event):
813 Event.__init__ (self)
814 self.duration = Duration()
816 def get_length (self):
817 return self.duration.get_length()
819 def get_properties (self):
820 return ("'duration %s"
821 % self.duration.lisp_expression ())
823 class RestEvent (RhythmicEvent):
825 RhythmicEvent.__init__ (self)
827 def ly_expression (self):
829 return "%s%s\\rest" % (self.pitch.ly_expression (), self.duration.ly_expression ())
831 return 'r%s' % self.duration.ly_expression ()
833 def print_ly (self, printer):
835 self.pitch.print_ly (printer)
836 self.duration.print_ly (printer)
840 self.duration.print_ly (printer)
842 class SkipEvent (RhythmicEvent):
843 def ly_expression (self):
844 return 's%s' % self.duration.ly_expression ()
846 class NoteEvent(RhythmicEvent):
848 RhythmicEvent.__init__ (self)
850 self.drum_type = None
851 self.cautionary = False
852 self.forced_accidental = False
854 def get_properties (self):
855 str = RhythmicEvent.get_properties (self)
858 str += self.pitch.lisp_expression ()
860 str += "'drum-type '%s" % self.drum_type
864 def pitch_mods (self):
868 if self.forced_accidental:
873 def ly_expression (self):
875 return '%s%s%s' % (self.pitch.ly_expression (),
877 self.duration.ly_expression ())
879 return '%s%s' (self.drum_type,
880 self.duration.ly_expression ())
882 def print_ly (self, printer):
884 self.pitch.print_ly (printer)
885 printer (self.pitch_mods ())
887 printer (self.drum_type)
889 self.duration.print_ly (printer)
891 class KeySignatureChange (Music):
893 Music.__init__ (self)
898 def ly_expression (self):
899 return '\\key %s \\%s' % (self.tonic.ly_step_expression (),
902 def lisp_expression (self):
903 pairs = ['(%d . %d)' % (i , self.scale[i]) for i in range (0,7)]
904 scale_str = ("'(%s)" % string.join (pairs))
906 return """ (make-music 'KeyChangeEvent
907 'pitch-alist %s) """ % scale_str
909 class TimeSignatureChange (Music):
911 Music.__init__ (self)
912 self.fraction = (4,4)
913 def ly_expression (self):
914 return '\\time %d/%d ' % self.fraction
916 class ClefChange (Music):
918 Music.__init__ (self)
923 def octave_modifier (self):
924 return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self.octave, '')
925 def clef_name (self):
926 return {('G', 2): "treble",
929 ('C', 2): "mezzosoprano",
932 ('C', 5): "baritone",
933 ('F', 3): "varbaritone",
936 ("percussion", 2): "percussion",
937 ("TAB", 5): "tab"}.get ((self.type, self.position), None)
938 def ly_expression (self):
939 return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ())
942 "G": ("clefs.G", -2, -6),
943 "C": ("clefs.C", 0, 0),
944 "F": ("clefs.F", 2, 6),
947 def lisp_expression (self):
949 (glyph, pos, c0) = self.clef_dict[self.type]
953 (make-music 'SequentialMusic
956 (make-property-set 'clefGlyph "%s") 'Staff)
958 (make-property-set 'clefPosition %d) 'Staff)
960 (make-property-set 'middleCPosition %d) 'Staff)))
961 """ % (glyph, pos, c0)
965 class MultiMeasureRest(Music):
967 def lisp_expression (self):
970 'MultiMeasureRestMusicGroup
972 (list (make-music (quote BarCheck))
977 'MultiMeasureRestEvent
980 (make-music (quote BarCheck))))
981 """ % self.duration.lisp_expression ()
983 def ly_expression (self):
984 return 'R%s' % self.duration.ly_expression ()
988 def __init__ (self, command = "StaffGroup"):
989 self.stafftype = command
991 self.instrument_name = None
992 self.short_instrument_name = None
996 # part_information is a list with entries of the form
997 # [staffid, voicelist]
998 # where voicelist is a list with entries of the form
999 # [voiceid1, [lyricsid11, lyricsid12,...] ]
1000 self.part_information = None
1002 def appendStaff (self, staff):
1003 self.children.append (staff)
1005 def setPartInformation (self, part_name, staves_info):
1006 if part_name == self.id:
1007 self.part_information = staves_info
1009 for c in self.children:
1010 c.setPartInformation (part_name, staves_info)
1012 def print_ly_contents (self, printer):
1013 for c in self.children:
1015 c.print_ly (printer)
1016 def print_ly_overrides (self, printer):
1018 needs_with |= self.spanbar == "no"
1019 needs_with |= self.instrument_name != None
1020 needs_with |= self.short_instrument_name != None
1021 needs_with |= (self.symbol != None) and (self.symbol != "bracket")
1023 printer.dump ("\\with {")
1024 if self.instrument_name or self.short_instrument_name:
1025 printer.dump ("\\consists \"Instrument_name_engraver\"")
1026 if self.spanbar == "no":
1027 printer.dump ("\\override SpanBar #'transparent = ##t")
1028 brack = {"brace": "SystemStartBrace",
1030 "line": "SystemStartBar"}.get (self.symbol, None)
1032 printer.dump ("systemStartDelimiter = #'%s" % brack)
1035 def print_ly (self, printer):
1037 printer.dump ("\\new %s" % self.stafftype)
1038 self.print_ly_overrides (printer)
1041 if self.stafftype and self.instrument_name:
1042 printer.dump ("\\set %s.instrumentName = %s" % (self.stafftype,
1043 escape_instrument_string (self.instrument_name)))
1045 if self.stafftype and self.short_instrument_name:
1046 printer.dump ("\\set %s.shortInstrumentName = %s\n" % (self.stafftype,
1047 escape_instrument_string (self.short_instrument_name)))
1049 self.print_ly_contents (printer)
1055 class Staff (StaffGroup):
1056 def __init__ (self):
1057 StaffGroup.__init__ (self, "Staff")
1060 def print_ly_overrides (self, printer):
1063 def print_ly_contents (self, printer):
1064 if not self.id or not self.part_information:
1067 for [staff_id, voices] in self.part_information:
1069 printer ('\\context Staff = "%s" << ' % staff_id)
1071 printer ('\\context Staff << ')
1074 nr_voices = len (voices)
1075 for [v, lyrics] in voices:
1077 voice_count_text = ''
1079 voice_count_text = {1: ' \\voiceOne', 2: ' \\voiceTwo',
1080 3: ' \\voiceThree'}.get (n, ' \\voiceFour')
1081 printer ('\\context Voice = "%s" {%s \\%s }' % (v,voice_count_text,v))
1085 printer ('\\new Lyrics \\lyricsto "%s" \\%s' % (v,l))
1089 def print_ly (self, printer):
1090 if self.part_information and len (self.part_information) > 1:
1091 self.stafftype = "PianoStaff"
1092 StaffGroup.print_ly (self, printer)
1097 bflat.alteration = -1
1107 print bflat.semitones()
1108 print bflat.transposed (fifth), bflat.transposed (fifth).transposed (fifth)
1109 print bflat.transposed (fifth).transposed (fifth).transposed (fifth)
1111 print bflat.semitones(), 'down'
1112 print bflat.transposed (down)
1113 print bflat.transposed (down).transposed (down)
1114 print bflat.transposed (down).transposed (down).transposed (down)
1118 def test_printer ():
1126 m = SequentialMusic()
1127 m.append (make_note ())
1128 m.append (make_note ())
1129 m.append (make_note ())
1132 t = TimeScaledMusic ()
1138 m = SequentialMusic ()
1139 m.append (make_tup ())
1140 m.append (make_tup ())
1141 m.append (make_tup ())
1143 printer = Output_printer()
1144 m.print_ly (printer)
1148 m = SequentialMusic()
1152 n.duration.duration_log = l
1154 evc.insert_around (None, n, 0)
1155 m.insert_around (None, evc, 0)
1159 n.duration.duration_log = l
1161 evc.insert_around (None, n, 0)
1162 m.insert_around (None, evc, 0)
1166 n.duration.duration_log = l
1168 evc.insert_around (None, n, 0)
1169 m.insert_around (None, evc, 0)
1173 m.insert_around (None, evc, 0)
1178 tonic.alteration = -2
1179 n = KeySignatureChange()
1180 n.tonic=tonic.copy()
1181 n.scale = [0, 0, -2, 0, 0,-2,-2]
1183 evc.insert_around (None, n, 0)
1184 m.insert_around (None, evc, 0)
1189 if __name__ == '__main__':
1195 expr.set_start (Rational (0))
1196 print expr.ly_expression()
1197 start = Rational (0,4)
1198 stop = Rational (4,2)
1199 def sub(x, start=start, stop=stop):
1200 ok = x.start >= start and x.start +x.get_length() <= stop
1203 print expr.lisp_sub_expression(sub)