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.
46 ## TODO: support for \relative.
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):
159 if self.duration_log < 0:
160 str = {-1: "\\breve", -2: "\\longa"}.get (self.duration_log, "1")
162 str = '%d' % (1 << self.duration_log)
165 if factor <> Rational (1,1):
166 if factor.denominator () <> 1:
167 str += '*%d/%d' % (factor.numerator (), factor.denominator ())
169 str += '*%d' % factor.numerator ()
173 def print_ly (self, outputter):
174 str = self.ly_expression (self.factor / outputter.duration_factor ())
175 outputter.print_duration_string (str)
178 return self.ly_expression()
183 d.duration_log = self.duration_log
184 d.factor = self.factor
187 def get_length (self):
188 dot_fact = Rational( (1 << (1 + self.dots))-1,
191 log = abs (self.duration_log)
193 if self.duration_log < 0:
194 base = Rational (dur)
196 base = Rational (1, dur)
198 return base * dot_fact * self.factor
201 # Implement the different note names for the various languages
202 def pitch_generic (pitch, notenames, accidentals):
203 str = notenames[pitch.step]
204 if pitch.alteration < 0:
205 str += accidentals[0] * (-pitch.alteration)
206 elif pitch.alteration > 0:
207 str += accidentals[3] * (pitch.alteration)
210 def pitch_general (pitch):
211 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['es', 'eh', 'ih', 'is'])
212 return str.replace ('aes', 'as').replace ('ees', 'es')
214 def pitch_nederlands (pitch):
215 return pitch_general (pitch)
217 def pitch_english (pitch):
218 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['f', 'qf', 'qs', 's'])
219 return str.replace ('aes', 'as').replace ('ees', 'es')
221 def pitch_deutsch (pitch):
222 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['es', 'eh', 'ih', 'is'])
223 return str.replace ('hes', 'b').replace ('aes', 'as').replace ('ees', 'es')
225 def pitch_norsk (pitch):
226 return pitch_deutsch (pitch)
228 def pitch_svenska (pitch):
229 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', '', '', 'iss'])
230 return str.replace ('hess', 'b').replace ('aes', 'as').replace ('ees', 'es')
232 def pitch_italiano (pitch):
233 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', 'sb', 'sd', 'd'])
236 def pitch_catalan (pitch):
237 return pitch_italiano (pitch)
239 def pitch_espanol (pitch):
240 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', '', '', 's'])
243 def pitch_vlaams (pitch):
244 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', '', '', 'k'])
247 def set_pitch_language (language):
248 global pitch_generating_function
250 "nederlands": pitch_nederlands,
251 "english": pitch_english,
252 "deutsch": pitch_deutsch,
253 "norsk": pitch_norsk,
254 "svenska": pitch_svenska,
255 "italiano": pitch_italiano,
256 "catalan": pitch_catalan,
257 "espanol": pitch_espanol,
258 "vlaams": pitch_vlaams}
259 pitch_generating_function = function_dict.get (language, pitch_general)
261 # global variable to hold the formatting function.
262 pitch_generating_function = pitch_general
272 return self.ly_expression()
274 def transposed (self, interval):
276 c.alteration += interval.alteration
277 c.step += interval.step
278 c.octave += interval.octave
281 target_st = self.semitones() + interval.semitones()
282 c.alteration += target_st - c.semitones()
289 c.octave += c.step / 7
292 def lisp_expression (self):
293 return '(ly:make-pitch %d %d %d)' % (self.octave,
299 p.alteration = self.alteration
301 p.octave = self.octave
305 return self.step + self.octave *7
307 def semitones (self):
308 return self.octave * 12 + [0,2,4,5,7,9,11][self.step] + self.alteration
310 def ly_step_expression (self):
311 return pitch_generating_function (self)
313 def absolute_pitch (self):
315 return "'" * (self.octave + 1)
316 elif self.octave < -1:
317 return "," * (-self.octave - 1)
321 def relative_pitch (self):
322 global previous_pitch
323 if not previous_pitch:
324 previous_pitch = self
325 return self.absolute_pitch ()
326 previous_pitch_steps = previous_pitch.octave * 7 + previous_pitch.step
327 this_pitch_steps = self.octave * 7 + self.step
328 pitch_diff = (this_pitch_steps - previous_pitch_steps)
329 previous_pitch = self
331 return "'" * ((pitch_diff + 3) / 7)
332 elif pitch_diff < -3:
333 return "," * ((-pitch_diff + 3) / 7)
337 def ly_expression (self):
338 str = self.ly_step_expression ()
340 str += self.relative_pitch ()
342 str += self.absolute_pitch ()
346 def print_ly (self, outputter):
347 outputter (self.ly_expression())
352 self.start = Rational (0)
354 self.identifier = None
356 def get_length(self):
359 def get_properties (self):
362 def has_children (self):
365 def get_index (self):
367 return self.parent.elements.index (self)
371 return self.__class__.__name__
373 def lisp_expression (self):
376 props = self.get_properties ()
378 return "(make-music '%s %s)" % (name, props)
380 def set_start (self, start):
383 def find_first (self, predicate):
388 def print_comment (self, printer, text = None):
399 lines = string.split (text, '\n')
402 printer.unformatted_output ('% ' + l)
406 def print_with_identifier (self, printer):
408 printer ("\\%s" % self.identifier)
410 self.print_ly (printer)
412 def print_ly (self, printer):
413 printer (self.ly_expression ())
415 class MusicWrapper (Music):
419 def print_ly (self, func):
420 self.element.print_ly (func)
422 class ModeChangingMusicWrapper (MusicWrapper):
424 MusicWrapper.__init__ (self)
425 self.mode = 'notemode'
427 def print_ly (self, func):
428 func ('\\%s' % self.mode)
429 MusicWrapper.print_ly (self, func)
431 class RelativeMusic (MusicWrapper):
433 MusicWrapper.__init__ (self)
434 self.basepitch = None
436 def print_ly (self, func):
437 global previous_pitch
438 global relative_pitches
439 prev_relative_pitches = relative_pitches
440 relative_pitches = True
441 previous_pitch = self.basepitch
442 if not previous_pitch:
443 previous_pitch = Pitch ()
444 func ('\\relative %s%s' % (pitch_generating_function (previous_pitch),
445 previous_pitch.absolute_pitch ()))
446 MusicWrapper.print_ly (self, func)
447 relative_pitches = prev_relative_pitches
449 class TimeScaledMusic (MusicWrapper):
450 def print_ly (self, func):
451 func ('\\times %d/%d ' %
452 (self.numerator, self.denominator))
453 func.add_factor (Rational (self.numerator, self.denominator))
454 MusicWrapper.print_ly (self, func)
457 class NestedMusic(Music):
459 Music.__init__ (self)
462 def append (self, what):
464 self.elements.append (what)
466 def has_children (self):
469 def insert_around (self, succ, elt, dir):
470 assert elt.parent == None
471 assert succ == None or succ in self.elements
476 idx = self.elements.index (succ)
483 idx = len (self.elements)
485 self.elements.insert (idx, elt)
488 def get_properties (self):
489 return ("'elements (list %s)"
490 % string.join (map (lambda x: x.lisp_expression(),
493 def get_subset_properties (self, predicate):
494 return ("'elements (list %s)"
495 % string.join (map (lambda x: x.lisp_expression(),
496 filter ( predicate, self.elements))))
497 def get_neighbor (self, music, dir):
498 assert music.parent == self
499 idx = self.elements.index (music)
501 idx = min (idx, len (self.elements) -1)
504 return self.elements[idx]
506 def delete_element (self, element):
507 assert element in self.elements
509 self.elements.remove (element)
510 element.parent = None
512 def set_start (self, start):
514 for e in self.elements:
517 def find_first (self, predicate):
518 r = Music.find_first (self, predicate)
522 for e in self.elements:
523 r = e.find_first (predicate)
528 class SequentialMusic (NestedMusic):
529 def get_last_event_chord (self):
531 at = len( self.elements ) - 1
533 not isinstance (self.elements[at], ChordEvent) and
534 not isinstance (self.elements[at], BarLine)):
537 if (at >= 0 and isinstance (self.elements[at], ChordEvent)):
538 value = self.elements[at]
541 def print_ly (self, printer, newline = True):
544 self.print_comment (printer)
548 for e in self.elements:
555 def lisp_sub_expression (self, pred):
559 props = self.get_subset_properties (pred)
561 return "(make-music '%s %s)" % (name, props)
563 def set_start (self, start):
564 for e in self.elements:
566 start += e.get_length()
570 self.repeat_type = "volta"
571 self.repeat_count = 2
574 def set_music (self, music):
575 if isinstance (music, Music):
577 elif isinstance (music, list):
578 self.music = SequentialMusic ()
579 self.music.elements = music
581 warning (_ ("unable to set the music %(music)s for the repeat %(repeat)s" % \
582 {'music':music, 'repeat':self}))
583 def add_ending (self, music):
584 self.endings.append (music)
585 def print_ly (self, printer):
586 printer.dump ('\\repeat %s %s' % (self.repeat_type, self.repeat_count))
588 self.music.print_ly (printer)
590 warning (_ ("encountered repeat without body"))
593 printer.dump ('\\alternative {')
594 for e in self.endings:
601 self.lyrics_syllables = []
603 def print_ly (self, printer):
604 printer.dump ("\lyricmode {")
605 for l in self.lyrics_syllables:
606 printer.dump ( "%s " % l )
609 def ly_expression (self):
610 lstr = "\lyricmode {\n "
611 for l in self.lyrics_syllables:
619 self.header_fields = {}
620 def set_field (self, field, value):
621 self.header_fields[field] = value
623 def print_ly (self, printer):
624 printer.dump ("\header {")
626 for (k,v) in self.header_fields.items ():
628 printer.dump ('%s = %s' % (k,v))
637 self.global_staff_size = -1
640 self.page_height = -1
643 self.bottom_margin = -1
644 self.left_margin = -1
645 self.right_margin = -1
646 self.system_left_margin = -1
647 self.system_right_margin = -1
648 self.system_distance = -1
649 self.top_system_distance = -1
651 def print_length_field (self, printer, field, value):
653 printer.dump ("%s = %s\\cm" % (field, value))
655 def print_ly (self, printer):
656 if self.global_staff_size > 0:
657 printer.dump ('#(set-global-staff-size %s)' % self.global_staff_size)
659 printer.dump ('\\paper {')
661 self.print_length_field (printer, "paper-width", self.page_width)
662 self.print_length_field (printer, "paper-height", self.page_height)
663 self.print_length_field (printer, "top-margin", self.top_margin)
664 self.print_length_field (printer, "botton-margin", self.bottom_margin)
665 self.print_length_field (printer, "left-margin", self.left_margin)
666 # TODO: maybe set line-width instead of right-margin?
667 self.print_length_field (printer, "right-margin", self.right_margin)
668 # TODO: What's the corresponding setting for system_left_margin and
669 # system_right_margin in Lilypond?
670 self.print_length_field (printer, "between-system-space", self.system_distance)
671 self.print_length_field (printer, "page-top-space", self.top_system_distance)
678 self.context_dict = {}
679 def add_context (self, context):
680 if not self.context_dict.has_key (context):
681 self.context_dict[context] = []
682 def set_context_item (self, context, item):
683 self.add_context (context)
684 if not item in self.context_dict[context]:
685 self.context_dict[context].append (item)
686 def print_ly (self, printer):
687 if self.context_dict.items ():
688 printer.dump ('\\layout {')
690 for (context, defs) in self.context_dict.items ():
691 printer.dump ('\\context { \\%s' % context)
702 class ChordEvent (NestedMusic):
704 NestedMusic.__init__ (self)
705 self.grace_elements = None
706 self.grace_type = None
707 def append_grace (self, element):
709 if not self.grace_elements:
710 self.grace_elements = SequentialMusic ()
711 self.grace_elements.append (element)
713 def get_length (self):
715 for e in self.elements:
716 l = max(l, e.get_length())
719 def print_ly (self, printer):
720 note_events = [e for e in self.elements if
721 isinstance (e, NoteEvent)]
723 rest_events = [e for e in self.elements if
724 isinstance (e, RhythmicEvent)
725 and not isinstance (e, NoteEvent)]
727 other_events = [e for e in self.elements if
728 not isinstance (e, RhythmicEvent)]
730 if self.grace_elements and self.elements:
732 printer ('\\%s' % self.grace_type)
735 # don't print newlines after the { and } braces
736 self.grace_elements.print_ly (printer, False)
737 # Print all overrides and other settings needed by the
738 # articulations/ornaments before the note
739 for e in other_events:
740 e.print_before_note (printer)
743 rest_events[0].print_ly (printer)
744 elif len (note_events) == 1:
745 note_events[0].print_ly (printer)
747 global previous_pitch
750 for x in note_events:
751 pitches.append (x.pitch.ly_expression ())
753 basepitch = previous_pitch
754 printer ('<%s>' % string.join (pitches))
755 previous_pitch = basepitch
756 note_events[0].duration.print_ly (printer)
760 for e in other_events:
763 for e in other_events:
764 e.print_after_note (printer)
766 self.print_comment (printer)
768 class Partial (Music):
770 Music.__init__ (self)
772 def print_ly (self, printer):
774 printer.dump ("\\partial %s" % self.partial.ly_expression ())
776 class BarLine (Music):
778 Music.__init__ (self)
782 def print_ly (self, printer):
783 bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': ":",
784 'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
785 'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
786 'short': "'", 'none': "" }.get (self.type, None)
787 if bar_symbol <> None:
788 printer.dump ('\\bar "%s"' % bar_symbol)
792 if self.bar_number > 0 and (self.bar_number % 10) == 0:
793 printer.dump ("\\barNumberCheck #%d " % self.bar_number)
795 printer.print_verbatim (' %% %d' % self.bar_number)
798 def ly_expression (self):
803 # strings to print before the note to which an event is attached.
804 # Ignored for notes etc.
805 self.before_note = None
806 self.after_note = None
807 # print something before the note to which an event is attached, e.g. overrides
808 def print_before_note (self, printer):
810 printer.dump (self.before_note)
811 # print something after the note to which an event is attached, e.g. resetting
812 def print_after_note (self, printer):
814 printer.dump (self.after_note)
817 class SpanEvent (Event):
819 Event.__init__ (self)
820 self.span_direction = 0 # start/stop
821 self.line_type = 'solid'
822 self.span_type = 0 # e.g. cres/decrescendo, ottava up/down
823 self.size = 0 # size of e.g. ocrave shift
824 def wait_for_note (self):
826 def get_properties(self):
827 return "'span-direction %d" % self.span_direction
828 def set_span_type (self, type):
829 self.span_type = type
831 class SlurEvent (SpanEvent):
832 def print_before_note (self, printer):
833 command = {'dotted': '\\slurDotted',
834 'dashed' : '\\slurDashed'}.get (self.line_type, '')
835 if command and self.span_direction == -1:
836 printer.dump (command)
837 def print_after_note (self, printer):
838 # reset non-solid slur types!
839 command = {'dotted': '\\slurSolid',
840 'dashed' : '\\slurSolid'}.get (self.line_type, '')
841 if command and self.span_direction == -1:
842 printer.dump (command)
843 def ly_expression (self):
844 return {-1: '(', 1:')'}.get (self.span_direction, '')
846 class BeamEvent (SpanEvent):
847 def ly_expression (self):
848 return {-1: '[', 1:']'}.get (self.span_direction, '')
850 class PedalEvent (SpanEvent):
851 def ly_expression (self):
852 return {-1: '\\sustainDown',
853 0:'\\sustainUp\\sustainDown',
854 1:'\\sustainUp'}.get (self.span_direction, '')
856 class TextSpannerEvent (SpanEvent):
857 def ly_expression (self):
858 return {-1: '\\startTextSpan',
859 1:'\\stopTextSpan'}.get (self.span_direction, '')
861 class BracketSpannerEvent (SpanEvent):
862 # Ligature brackets use prefix-notation!!!
863 def print_before_note (self, printer):
864 if self.span_direction == -1:
866 # the the bracket after the last note
867 def print_after_note (self, printer):
868 if self.span_direction == 1:
870 # we're printing everything in print_(before|after)_note...
871 def ly_expression (self):
875 class OctaveShiftEvent (SpanEvent):
876 def wait_for_note (self):
878 def set_span_type (self, type):
879 self.span_type = {'up': 1, 'down': -1}.get (type, 0)
880 def ly_octave_shift_indicator (self):
881 # convert 8/15 to lilypond indicators (+-1/+-2)
882 value = {8: 1, 15: 2}.get (self.size, 0)
883 # negative values go up!
884 value *= -1*self.span_type
886 def ly_expression (self):
887 dir = self.ly_octave_shift_indicator ()
890 value = '#(set-octavation %s)' % dir
893 1: '#(set-octavation 0)'}.get (self.span_direction, '')
895 class TrillSpanEvent (SpanEvent):
896 def ly_expression (self):
897 return {-1: '\\startTrillSpan',
898 0: '', # no need to write out anything for type='continue'
899 1:'\\stopTrillSpan'}.get (self.span_direction, '')
901 class GlissandoEvent (SpanEvent):
902 def print_before_note (self, printer):
903 if self.span_direction == -1:
905 "dashed" : "dashed-line",
906 "dotted" : "dotted-line",
908 }. get (self.line_type, None)
910 printer.dump ("\once \override Glissando #'style = #'%s" % style)
911 def ly_expression (self):
912 return {-1: '\\glissando',
913 1:''}.get (self.span_direction, '')
915 class ArpeggioEvent(Event):
917 Event.__init__ (self)
919 self.non_arpeggiate = False
920 def wait_for_note (self):
922 def print_before_note (self, printer):
923 if self.non_arpeggiate:
924 printer.dump ("\\arpeggioBracket")
926 dir = { -1: "\\arpeggioDown", 1: "\\arpeggioUp" }.get (self.direction, '')
929 def print_after_note (self, printer):
930 if self.non_arpeggiate or self.direction:
931 printer.dump ("\\arpeggioNeutral")
932 def ly_expression (self):
933 return ('\\arpeggio')
936 class TieEvent(Event):
937 def ly_expression (self):
941 class HairpinEvent (SpanEvent):
942 def set_span_type (self, type):
943 self.span_type = {'crescendo' : 1, 'decrescendo' : -1, 'diminuendo' : -1 }.get (type, 0)
944 def hairpin_to_ly (self):
945 if self.span_direction == 1:
948 return {1: '\<', -1: '\>'}.get (self.span_type, '')
950 def ly_expression (self):
951 return self.hairpin_to_ly ()
953 def print_ly (self, printer):
954 val = self.hairpin_to_ly ()
960 class DynamicsEvent (Event):
962 Event.__init__ (self)
964 def wait_for_note (self):
966 def ly_expression (self):
968 return '\%s' % self.type
972 def print_ly (self, printer):
974 printer.dump ("\\%s" % self.type)
976 class MarkEvent (Event):
977 def __init__ (self, text="\\default"):
978 Event.__init__ (self)
980 def wait_for_note (self):
982 def ly_contents (self):
984 return '%s' % self.mark
987 def ly_expression (self):
988 return '\\mark %s' % self.ly_contents ()
990 class MusicGlyphMarkEvent (MarkEvent):
991 def ly_contents (self):
993 return '\\markup { \\musicglyph #"scripts.%s" }' % self.mark
998 class TextEvent (Event):
1000 Event.__init__ (self)
1002 self.force_direction = None
1004 def wait_for_note (self):
1007 def direction_mod (self):
1008 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1010 def ly_expression (self):
1011 base_string = '%s\"%s\"'
1013 base_string = '%s\markup{ ' + self.markup + ' {%s} }'
1014 return base_string % (self.direction_mod (), self.text)
1016 class ArticulationEvent (Event):
1017 def __init__ (self):
1018 Event.__init__ (self)
1020 self.force_direction = None
1021 def wait_for_note (self):
1024 def direction_mod (self):
1025 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '')
1027 def ly_expression (self):
1028 return '%s\\%s' % (self.direction_mod (), self.type)
1030 class ShortArticulationEvent (ArticulationEvent):
1031 def direction_mod (self):
1033 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1034 def ly_expression (self):
1036 return '%s%s' % (self.direction_mod (), self.type)
1040 class NoDirectionArticulationEvent (ArticulationEvent):
1041 def ly_expression (self):
1043 return '\\%s' % self.type
1047 class MarkupEvent (ShortArticulationEvent):
1048 def __init__ (self):
1049 ArticulationEvent.__init__ (self)
1050 self.contents = None
1051 def ly_expression (self):
1053 return "%s\\markup { %s }" % (self.direction_mod (), self.contents)
1057 class FretEvent (MarkupEvent):
1058 def __init__ (self):
1059 MarkupEvent.__init__ (self)
1060 self.force_direction = 1
1065 def ly_expression (self):
1067 if self.strings <> 6:
1068 val += "w:%s;" % self.strings
1070 val += "h:%s;" % self.frets
1071 if self.barre and len (self.barre) >= 3:
1072 val += "c:%s-%s-%s;" % (self.barre[0], self.barre[1], self.barre[2])
1073 have_fingering = False
1074 for i in self.elements:
1076 val += "%s-%s" % (i[0], i[1])
1078 have_fingering = True
1084 return "%s\\markup { \\fret-diagram #\"%s\" }" % (self.direction_mod (), val)
1088 class TremoloEvent (ArticulationEvent):
1089 def __init__ (self):
1090 Event.__init__ (self)
1093 def ly_expression (self):
1095 if self.bars and self.bars > 0:
1096 str += ':%s' % (2 ** (2 + string.atoi (self.bars)))
1099 class BendEvent (ArticulationEvent):
1100 def __init__ (self):
1101 Event.__init__ (self)
1103 def ly_expression (self):
1105 return "-\\bendAfter #%s" % self.alter
1109 class RhythmicEvent(Event):
1110 def __init__ (self):
1111 Event.__init__ (self)
1112 self.duration = Duration()
1114 def get_length (self):
1115 return self.duration.get_length()
1117 def get_properties (self):
1118 return ("'duration %s"
1119 % self.duration.lisp_expression ())
1121 class RestEvent (RhythmicEvent):
1122 def __init__ (self):
1123 RhythmicEvent.__init__ (self)
1125 def ly_expression (self):
1127 return "%s%s\\rest" % (self.pitch.ly_expression (), self.duration.ly_expression ())
1129 return 'r%s' % self.duration.ly_expression ()
1131 def print_ly (self, printer):
1133 self.pitch.print_ly (printer)
1134 self.duration.print_ly (printer)
1138 self.duration.print_ly (printer)
1140 class SkipEvent (RhythmicEvent):
1141 def ly_expression (self):
1142 return 's%s' % self.duration.ly_expression ()
1144 class NoteEvent(RhythmicEvent):
1145 def __init__ (self):
1146 RhythmicEvent.__init__ (self)
1148 self.drum_type = None
1149 self.cautionary = False
1150 self.forced_accidental = False
1152 def get_properties (self):
1153 str = RhythmicEvent.get_properties (self)
1156 str += self.pitch.lisp_expression ()
1157 elif self.drum_type:
1158 str += "'drum-type '%s" % self.drum_type
1162 def pitch_mods (self):
1165 excl_question += '?'
1166 if self.forced_accidental:
1167 excl_question += '!'
1169 return excl_question
1171 def ly_expression (self):
1173 return '%s%s%s' % (self.pitch.ly_expression (),
1175 self.duration.ly_expression ())
1176 elif self.drum_type:
1177 return '%s%s' (self.drum_type,
1178 self.duration.ly_expression ())
1180 def print_ly (self, printer):
1182 self.pitch.print_ly (printer)
1183 printer (self.pitch_mods ())
1185 printer (self.drum_type)
1187 self.duration.print_ly (printer)
1189 class KeySignatureChange (Music):
1190 def __init__ (self):
1191 Music.__init__ (self)
1193 self.tonic = Pitch()
1196 def ly_expression (self):
1197 return '\\key %s \\%s' % (self.tonic.ly_step_expression (),
1200 def lisp_expression (self):
1201 pairs = ['(%d . %d)' % (i , self.scale[i]) for i in range (0,7)]
1202 scale_str = ("'(%s)" % string.join (pairs))
1204 return """ (make-music 'KeyChangeEvent
1205 'pitch-alist %s) """ % scale_str
1207 class TimeSignatureChange (Music):
1208 def __init__ (self):
1209 Music.__init__ (self)
1210 self.fraction = (4,4)
1211 def ly_expression (self):
1212 return '\\time %d/%d ' % self.fraction
1214 class ClefChange (Music):
1215 def __init__ (self):
1216 Music.__init__ (self)
1221 def octave_modifier (self):
1222 return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self.octave, '')
1223 def clef_name (self):
1224 return {('G', 2): "treble",
1226 ('C', 1): "soprano",
1227 ('C', 2): "mezzosoprano",
1230 ('C', 5): "baritone",
1231 ('F', 3): "varbaritone",
1233 ('F', 5): "subbass",
1234 ("percussion", 2): "percussion",
1235 ("TAB", 5): "tab"}.get ((self.type, self.position), None)
1236 def ly_expression (self):
1237 return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ())
1240 "G": ("clefs.G", -2, -6),
1241 "C": ("clefs.C", 0, 0),
1242 "F": ("clefs.F", 2, 6),
1245 def lisp_expression (self):
1247 (glyph, pos, c0) = self.clef_dict[self.type]
1251 (make-music 'SequentialMusic
1254 (make-property-set 'clefGlyph "%s") 'Staff)
1256 (make-property-set 'clefPosition %d) 'Staff)
1258 (make-property-set 'middleCPosition %d) 'Staff)))
1259 """ % (glyph, pos, c0)
1263 class StaffChange (Music):
1264 def __init__ (self, staff):
1265 Music.__init__ (self)
1267 def ly_expression (self):
1269 return "\\change Staff=\"%s\"" % self.staff
1274 class MultiMeasureRest(Music):
1276 def lisp_expression (self):
1279 'MultiMeasureRestMusicGroup
1281 (list (make-music (quote BarCheck))
1286 'MultiMeasureRestEvent
1289 (make-music (quote BarCheck))))
1290 """ % self.duration.lisp_expression ()
1292 def ly_expression (self):
1293 return 'R%s' % self.duration.ly_expression ()
1297 def __init__ (self, command = "StaffGroup"):
1298 self.stafftype = command
1300 self.instrument_name = None
1301 self.short_instrument_name = None
1305 self.is_group = True
1306 # part_information is a list with entries of the form
1307 # [staffid, voicelist]
1308 # where voicelist is a list with entries of the form
1309 # [voiceid1, [lyricsid11, lyricsid12,...] ]
1310 self.part_information = None
1312 def append_staff (self, staff):
1313 self.children.append (staff)
1315 def set_part_information (self, part_name, staves_info):
1316 if part_name == self.id:
1317 self.part_information = staves_info
1319 for c in self.children:
1320 c.set_part_information (part_name, staves_info)
1322 def print_ly_contents (self, printer):
1323 for c in self.children:
1325 c.print_ly (printer)
1326 def print_ly_overrides (self, printer):
1328 needs_with |= self.spanbar == "no"
1329 needs_with |= self.instrument_name != None
1330 needs_with |= self.short_instrument_name != None
1331 needs_with |= (self.symbol != None) and (self.symbol != "bracket")
1333 printer.dump ("\\with {")
1334 if self.instrument_name or self.short_instrument_name:
1335 printer.dump ("\\consists \"Instrument_name_engraver\"")
1336 if self.spanbar == "no":
1337 printer.dump ("\\override SpanBar #'transparent = ##t")
1338 brack = {"brace": "SystemStartBrace",
1340 "line": "SystemStartSquare"}.get (self.symbol, None)
1342 printer.dump ("systemStartDelimiter = #'%s" % brack)
1345 def print_ly (self, printer):
1347 printer.dump ("\\new %s" % self.stafftype)
1348 self.print_ly_overrides (printer)
1351 if self.stafftype and self.instrument_name:
1352 printer.dump ("\\set %s.instrumentName = %s" % (self.stafftype,
1353 escape_instrument_string (self.instrument_name)))
1355 if self.stafftype and self.short_instrument_name:
1356 printer.dump ("\\set %s.shortInstrumentName = %s" % (self.stafftype,
1357 escape_instrument_string (self.short_instrument_name)))
1359 self.print_ly_contents (printer)
1365 class Staff (StaffGroup):
1366 def __init__ (self, command = "Staff"):
1367 StaffGroup.__init__ (self, command)
1368 self.is_group = False
1370 self.voice_command = "Voice"
1371 self.substafftype = None
1373 def print_ly_overrides (self, printer):
1376 def print_ly_contents (self, printer):
1377 if not self.id or not self.part_information:
1379 sub_staff_type = self.substafftype
1380 if not sub_staff_type:
1381 sub_staff_type = self.stafftype
1383 for [staff_id, voices] in self.part_information:
1385 printer ('\\context %s = "%s" << ' % (sub_staff_type, staff_id))
1387 printer ('\\context %s << ' % sub_staff_type)
1390 nr_voices = len (voices)
1391 for [v, lyrics] in voices:
1393 voice_count_text = ''
1395 voice_count_text = {1: ' \\voiceOne', 2: ' \\voiceTwo',
1396 3: ' \\voiceThree'}.get (n, ' \\voiceFour')
1397 printer ('\\context %s = "%s" {%s \\%s }' % (self.voice_command, v, voice_count_text, v))
1401 printer ('\\new Lyrics \\lyricsto "%s" \\%s' % (v,l))
1405 def print_ly (self, printer):
1406 if self.part_information and len (self.part_information) > 1:
1407 self.stafftype = "PianoStaff"
1408 self.substafftype = "Staff"
1409 StaffGroup.print_ly (self, printer)
1411 class TabStaff (Staff):
1412 def __init__ (self, command = "TabStaff"):
1413 Staff.__init__ (self, command)
1414 self.string_tunings = []
1415 self.tablature_format = None
1416 self.voice_command = "TabVoice"
1417 def print_ly_overrides (self, printer):
1418 if self.string_tunings or self.tablature_format:
1419 printer.dump ("\\with {")
1420 if self.string_tunings:
1421 printer.dump ("stringTunings = #'(")
1422 for i in self.string_tunings:
1423 printer.dump ("%s" % i.semitones ())
1425 if self.tablature_format:
1426 printer.dump ("tablatureFormat = #%s" % self.tablature_format)
1430 class DrumStaff (Staff):
1431 def __init__ (self, command = "DrumStaff"):
1432 Staff.__init__ (self, command)
1433 self.drum_style_table = None
1434 self.voice_command = "DrumVoice"
1435 def print_ly_overrides (self, printer):
1436 if self.drum_style_table:
1437 printer.dump ("\with {")
1438 printer.dump ("drumStyleTable = #%s" % self.drum_style_table)
1441 class RhythmicStaff (Staff):
1442 def __init__ (self, command = "RhythmicStaff"):
1443 Staff.__init__ (self, command)
1448 bflat.alteration = -1
1458 print bflat.semitones()
1459 print bflat.transposed (fifth), bflat.transposed (fifth).transposed (fifth)
1460 print bflat.transposed (fifth).transposed (fifth).transposed (fifth)
1462 print bflat.semitones(), 'down'
1463 print bflat.transposed (down)
1464 print bflat.transposed (down).transposed (down)
1465 print bflat.transposed (down).transposed (down).transposed (down)
1469 def test_printer ():
1477 m = SequentialMusic()
1478 m.append (make_note ())
1479 m.append (make_note ())
1480 m.append (make_note ())
1483 t = TimeScaledMusic ()
1489 m = SequentialMusic ()
1490 m.append (make_tup ())
1491 m.append (make_tup ())
1492 m.append (make_tup ())
1494 printer = Output_printer()
1495 m.print_ly (printer)
1499 m = SequentialMusic()
1503 n.duration.duration_log = l
1505 evc.insert_around (None, n, 0)
1506 m.insert_around (None, evc, 0)
1510 n.duration.duration_log = l
1512 evc.insert_around (None, n, 0)
1513 m.insert_around (None, evc, 0)
1517 n.duration.duration_log = l
1519 evc.insert_around (None, n, 0)
1520 m.insert_around (None, evc, 0)
1524 m.insert_around (None, evc, 0)
1529 tonic.alteration = -2
1530 n = KeySignatureChange()
1531 n.tonic=tonic.copy()
1532 n.scale = [0, 0, -2, 0, 0,-2,-2]
1534 evc.insert_around (None, n, 0)
1535 m.insert_around (None, evc, 0)
1540 if __name__ == '__main__':
1546 expr.set_start (Rational (0))
1547 print expr.ly_expression()
1548 start = Rational (0,4)
1549 stop = Rational (4,2)
1550 def sub(x, start=start, stop=stop):
1551 ok = x.start >= start and x.start +x.get_length() <= stop
1554 print expr.lisp_sub_expression(sub)