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 warning (_ ("Tuplet brackets displaying both note durations are not implemented, using default"))
512 if self
.display_number
== None:
513 func ("\\once \\override TupletNumber #'stencil = ##f")
515 elif self
.display_number
== "both":
516 func ("\\once \\override TupletNumber #'text = #%s" % base_number_function
)
519 if self
.display_number
== None:
520 func ("\\once \\override TupletNumber #'stencil = ##f")
522 elif self
.display_number
== "both":
523 func ("\\once \\override TupletNumber #'text = #%s" % base_number_function
)
526 func ('\\times %d/%d ' %
527 (self
.numerator
, self
.denominator
))
528 func
.add_factor (Rational (self
.numerator
, self
.denominator
))
529 MusicWrapper
.print_ly (self
, func
)
532 class NestedMusic(Music
):
534 Music
.__init
__ (self
)
537 def append (self
, what
):
539 self
.elements
.append (what
)
541 def has_children (self
):
544 def insert_around (self
, succ
, elt
, dir):
545 assert elt
.parent
== None
546 assert succ
== None or succ
in self
.elements
551 idx
= self
.elements
.index (succ
)
558 idx
= len (self
.elements
)
560 self
.elements
.insert (idx
, elt
)
563 def get_properties (self
):
564 return ("'elements (list %s)"
565 % string
.join (map (lambda x
: x
.lisp_expression(),
568 def get_subset_properties (self
, predicate
):
569 return ("'elements (list %s)"
570 % string
.join (map (lambda x
: x
.lisp_expression(),
571 filter ( predicate
, self
.elements
))))
572 def get_neighbor (self
, music
, dir):
573 assert music
.parent
== self
574 idx
= self
.elements
.index (music
)
576 idx
= min (idx
, len (self
.elements
) -1)
579 return self
.elements
[idx
]
581 def delete_element (self
, element
):
582 assert element
in self
.elements
584 self
.elements
.remove (element
)
585 element
.parent
= None
587 def set_start (self
, start
):
589 for e
in self
.elements
:
592 def find_first (self
, predicate
):
593 r
= Music
.find_first (self
, predicate
)
597 for e
in self
.elements
:
598 r
= e
.find_first (predicate
)
603 class SequentialMusic (NestedMusic
):
604 def get_last_event_chord (self
):
606 at
= len( self
.elements
) - 1
608 not isinstance (self
.elements
[at
], ChordEvent
) and
609 not isinstance (self
.elements
[at
], BarLine
)):
612 if (at
>= 0 and isinstance (self
.elements
[at
], ChordEvent
)):
613 value
= self
.elements
[at
]
616 def print_ly (self
, printer
, newline
= True):
619 self
.print_comment (printer
)
623 for e
in self
.elements
:
630 def lisp_sub_expression (self
, pred
):
634 props
= self
.get_subset_properties (pred
)
636 return "(make-music '%s %s)" % (name
, props
)
638 def set_start (self
, start
):
639 for e
in self
.elements
:
641 start
+= e
.get_length()
645 self
.repeat_type
= "volta"
646 self
.repeat_count
= 2
649 def set_music (self
, music
):
650 if isinstance (music
, Music
):
652 elif isinstance (music
, list):
653 self
.music
= SequentialMusic ()
654 self
.music
.elements
= music
656 warning (_ ("unable to set the music %(music)s for the repeat %(repeat)s") % \
657 {'music':music
, 'repeat':self
})
658 def add_ending (self
, music
):
659 self
.endings
.append (music
)
660 def print_ly (self
, printer
):
661 printer
.dump ('\\repeat %s %s' % (self
.repeat_type
, self
.repeat_count
))
663 self
.music
.print_ly (printer
)
665 warning (_ ("encountered repeat without body"))
668 printer
.dump ('\\alternative {')
669 for e
in self
.endings
:
676 self
.lyrics_syllables
= []
678 def print_ly (self
, printer
):
679 printer
.dump ("\lyricmode {")
680 for l
in self
.lyrics_syllables
:
681 printer
.dump ( "%s " % l
)
684 def ly_expression (self
):
685 lstr
= "\lyricmode {\n "
686 for l
in self
.lyrics_syllables
:
694 self
.header_fields
= {}
695 def set_field (self
, field
, value
):
696 self
.header_fields
[field
] = value
698 def print_ly (self
, printer
):
699 printer
.dump ("\header {")
701 for (k
,v
) in self
.header_fields
.items ():
703 printer
.dump ('%s = %s' % (k
,v
))
712 self
.global_staff_size
= -1
715 self
.page_height
= -1
718 self
.bottom_margin
= -1
719 self
.left_margin
= -1
720 self
.right_margin
= -1
721 self
.system_left_margin
= -1
722 self
.system_right_margin
= -1
723 self
.system_distance
= -1
724 self
.top_system_distance
= -1
726 def print_length_field (self
, printer
, field
, value
):
728 printer
.dump ("%s = %s\\cm" % (field
, value
))
730 def print_ly (self
, printer
):
731 if self
.global_staff_size
> 0:
732 printer
.dump ('#(set-global-staff-size %s)' % self
.global_staff_size
)
734 printer
.dump ('\\paper {')
736 self
.print_length_field (printer
, "paper-width", self
.page_width
)
737 self
.print_length_field (printer
, "paper-height", self
.page_height
)
738 self
.print_length_field (printer
, "top-margin", self
.top_margin
)
739 self
.print_length_field (printer
, "botton-margin", self
.bottom_margin
)
740 self
.print_length_field (printer
, "left-margin", self
.left_margin
)
741 # TODO: maybe set line-width instead of right-margin?
742 self
.print_length_field (printer
, "right-margin", self
.right_margin
)
743 # TODO: What's the corresponding setting for system_left_margin and
744 # system_right_margin in Lilypond?
745 self
.print_length_field (printer
, "between-system-space", self
.system_distance
)
746 self
.print_length_field (printer
, "page-top-space", self
.top_system_distance
)
753 self
.context_dict
= {}
754 def add_context (self
, context
):
755 if not self
.context_dict
.has_key (context
):
756 self
.context_dict
[context
] = []
757 def set_context_item (self
, context
, item
):
758 self
.add_context (context
)
759 if not item
in self
.context_dict
[context
]:
760 self
.context_dict
[context
].append (item
)
761 def print_ly (self
, printer
):
762 if self
.context_dict
.items ():
763 printer
.dump ('\\layout {')
765 for (context
, defs
) in self
.context_dict
.items ():
766 printer
.dump ('\\context { \\%s' % context
)
777 class ChordEvent (NestedMusic
):
779 NestedMusic
.__init
__ (self
)
780 self
.after_grace_elements
= None
781 self
.grace_elements
= None
782 self
.grace_type
= None
783 def append_grace (self
, element
):
785 if not self
.grace_elements
:
786 self
.grace_elements
= SequentialMusic ()
787 self
.grace_elements
.append (element
)
788 def append_after_grace (self
, element
):
790 if not self
.after_grace_elements
:
791 self
.after_grace_elements
= SequentialMusic ()
792 self
.after_grace_elements
.append (element
)
794 def has_elements (self
):
795 return [e
for e
in self
.elements
if
796 isinstance (e
, NoteEvent
) or isinstance (e
, RestEvent
)] != []
799 def get_length (self
):
801 for e
in self
.elements
:
802 l
= max(l
, e
.get_length())
805 def get_duration (self
):
806 note_events
= [e
for e
in self
.elements
if
807 isinstance (e
, NoteEvent
) or isinstance (e
, RestEvent
)]
809 return note_events
[0].duration
813 def print_ly (self
, printer
):
814 note_events
= [e
for e
in self
.elements
if
815 isinstance (e
, NoteEvent
)]
817 rest_events
= [e
for e
in self
.elements
if
818 isinstance (e
, RhythmicEvent
)
819 and not isinstance (e
, NoteEvent
)]
821 other_events
= [e
for e
in self
.elements
if
822 not isinstance (e
, RhythmicEvent
)]
824 if self
.after_grace_elements
:
825 printer ('\\afterGrace {')
827 if self
.grace_elements
and self
.elements
:
829 printer ('\\%s' % self
.grace_type
)
832 # don't print newlines after the { and } braces
833 self
.grace_elements
.print_ly (printer
, False)
834 elif self
.grace_elements
: # no self.elements!
835 warning (_ ("Grace note with no following music: %s") % self
.grace_elements
)
837 printer ('\\%s' % self
.grace_type
)
840 self
.grace_elements
.print_ly (printer
, False)
843 # Print all overrides and other settings needed by the
844 # articulations/ornaments before the note
845 for e
in other_events
:
846 e
.print_before_note (printer
)
849 rest_events
[0].print_ly (printer
)
850 elif len (note_events
) == 1:
851 note_events
[0].print_ly (printer
)
853 global previous_pitch
856 for x
in note_events
:
857 pitches
.append (x
.chord_element_ly ())
859 basepitch
= previous_pitch
860 printer ('<%s>' % string
.join (pitches
))
861 previous_pitch
= basepitch
862 duration
= self
.get_duration ()
864 duration
.print_ly (printer
)
868 for e
in other_events
:
871 for e
in other_events
:
872 e
.print_after_note (printer
)
874 if self
.after_grace_elements
:
876 self
.after_grace_elements
.print_ly (printer
, False)
878 self
.print_comment (printer
)
880 class Partial (Music
):
882 Music
.__init
__ (self
)
884 def print_ly (self
, printer
):
886 printer
.dump ("\\partial %s" % self
.partial
.ly_expression ())
888 class BarLine (Music
):
890 Music
.__init
__ (self
)
894 def print_ly (self
, printer
):
895 bar_symbol
= { 'regular': "|", 'dotted': ":", 'dashed': "dashed",
896 'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
897 'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
898 'short': "'|", 'none': "" }.get (self
.type, None)
899 if bar_symbol
<> None:
900 printer
.dump ('\\bar "%s"' % bar_symbol
)
904 if self
.bar_number
> 0 and (self
.bar_number
% 10) == 0:
905 printer
.dump ("\\barNumberCheck #%d " % self
.bar_number
)
906 elif self
.bar_number
> 0:
907 printer
.print_verbatim (' %% %d' % self
.bar_number
)
910 def ly_expression (self
):
915 # strings to print before the note to which an event is attached.
916 # Ignored for notes etc.
917 self
.before_note
= None
918 self
.after_note
= None
919 # print something before the note to which an event is attached, e.g. overrides
920 def print_before_note (self
, printer
):
922 printer
.dump (self
.before_note
)
923 # print something after the note to which an event is attached, e.g. resetting
924 def print_after_note (self
, printer
):
926 printer
.dump (self
.after_note
)
929 class SpanEvent (Event
):
931 Event
.__init
__ (self
)
932 self
.span_direction
= 0 # start/stop
933 self
.line_type
= 'solid'
934 self
.span_type
= 0 # e.g. cres/decrescendo, ottava up/down
935 self
.size
= 0 # size of e.g. ocrave shift
936 def wait_for_note (self
):
938 def get_properties(self
):
939 return "'span-direction %d" % self
.span_direction
940 def set_span_type (self
, type):
941 self
.span_type
= type
943 class SlurEvent (SpanEvent
):
944 def print_before_note (self
, printer
):
945 command
= {'dotted': '\\slurDotted',
946 'dashed' : '\\slurDashed'}.get (self
.line_type
, '')
947 if command
and self
.span_direction
== -1:
948 printer
.dump (command
)
949 def print_after_note (self
, printer
):
950 # reset non-solid slur types!
951 command
= {'dotted': '\\slurSolid',
952 'dashed' : '\\slurSolid'}.get (self
.line_type
, '')
953 if command
and self
.span_direction
== -1:
954 printer
.dump (command
)
955 def ly_expression (self
):
956 return {-1: '(', 1:')'}.get (self
.span_direction
, '')
958 class BeamEvent (SpanEvent
):
959 def ly_expression (self
):
960 return {-1: '[', 1:']'}.get (self
.span_direction
, '')
962 class PedalEvent (SpanEvent
):
963 def ly_expression (self
):
964 return {-1: '\\sustainOn',
965 0:'\\sustainOff\\sustainOn',
966 1:'\\sustainOff'}.get (self
.span_direction
, '')
968 class TextSpannerEvent (SpanEvent
):
969 def ly_expression (self
):
970 return {-1: '\\startTextSpan',
971 1:'\\stopTextSpan'}.get (self
.span_direction
, '')
973 class BracketSpannerEvent (SpanEvent
):
974 # Ligature brackets use prefix-notation!!!
975 def print_before_note (self
, printer
):
976 if self
.span_direction
== -1:
978 # the the bracket after the last note
979 def print_after_note (self
, printer
):
980 if self
.span_direction
== 1:
982 # we're printing everything in print_(before|after)_note...
983 def ly_expression (self
):
987 class OctaveShiftEvent (SpanEvent
):
988 def wait_for_note (self
):
990 def set_span_type (self
, type):
991 self
.span_type
= {'up': 1, 'down': -1}.get (type, 0)
992 def ly_octave_shift_indicator (self
):
993 # convert 8/15 to lilypond indicators (+-1/+-2)
995 value
= {8: 1, 15: 2}[self
.size
]
997 warning (_ ("Invalid octave shift size found: %s. Using no shift.") % self
.size
)
999 # negative values go up!
1000 value
*= -1*self
.span_type
1002 def ly_expression (self
):
1003 dir = self
.ly_octave_shift_indicator ()
1006 value
= '\ottava #%s' % dir
1009 1: '\ottava #0'}.get (self
.span_direction
, '')
1011 class TrillSpanEvent (SpanEvent
):
1012 def ly_expression (self
):
1013 return {-1: '\\startTrillSpan',
1014 0: '', # no need to write out anything for type='continue'
1015 1:'\\stopTrillSpan'}.get (self
.span_direction
, '')
1017 class GlissandoEvent (SpanEvent
):
1018 def print_before_note (self
, printer
):
1019 if self
.span_direction
== -1:
1021 "dashed" : "dashed-line",
1022 "dotted" : "dotted-line",
1024 }. get (self
.line_type
, None)
1026 printer
.dump ("\once \override Glissando #'style = #'%s" % style
)
1027 def ly_expression (self
):
1028 return {-1: '\\glissando',
1029 1:''}.get (self
.span_direction
, '')
1031 class ArpeggioEvent(Event
):
1032 def __init__ (self
):
1033 Event
.__init
__ (self
)
1035 self
.non_arpeggiate
= False
1036 def wait_for_note (self
):
1038 def print_before_note (self
, printer
):
1039 if self
.non_arpeggiate
:
1040 printer
.dump ("\\arpeggioBracket")
1042 dir = { -1: "\\arpeggioArrowDown", 1: "\\arpeggioArrowUp" }.get (self
.direction
, '')
1045 def print_after_note (self
, printer
):
1046 if self
.non_arpeggiate
or self
.direction
:
1047 printer
.dump ("\\arpeggioNormal")
1048 def ly_expression (self
):
1049 return ('\\arpeggio')
1052 class TieEvent(Event
):
1053 def ly_expression (self
):
1057 class HairpinEvent (SpanEvent
):
1058 def set_span_type (self
, type):
1059 self
.span_type
= {'crescendo' : 1, 'decrescendo' : -1, 'diminuendo' : -1 }.get (type, 0)
1060 def hairpin_to_ly (self
):
1061 if self
.span_direction
== 1:
1064 return {1: '\<', -1: '\>'}.get (self
.span_type
, '')
1066 def ly_expression (self
):
1067 return self
.hairpin_to_ly ()
1069 def print_ly (self
, printer
):
1070 val
= self
.hairpin_to_ly ()
1076 class DynamicsEvent (Event
):
1077 def __init__ (self
):
1078 Event
.__init
__ (self
)
1080 def wait_for_note (self
):
1082 def ly_expression (self
):
1084 return '\%s' % self
.type
1088 def print_ly (self
, printer
):
1090 printer
.dump ("\\%s" % self
.type)
1092 class MarkEvent (Event
):
1093 def __init__ (self
, text
="\\default"):
1094 Event
.__init
__ (self
)
1096 def wait_for_note (self
):
1098 def ly_contents (self
):
1100 return '%s' % self
.mark
1103 def ly_expression (self
):
1104 return '\\mark %s' % self
.ly_contents ()
1106 class MusicGlyphMarkEvent (MarkEvent
):
1107 def ly_contents (self
):
1109 return '\\markup { \\musicglyph #"scripts.%s" }' % self
.mark
1114 class TextEvent (Event
):
1115 def __init__ (self
):
1116 Event
.__init
__ (self
)
1118 self
.force_direction
= None
1120 def wait_for_note (self
):
1123 def direction_mod (self
):
1124 return { 1: '^', -1: '_', 0: '-' }.get (self
.force_direction
, '-')
1126 def ly_expression (self
):
1127 base_string
= '%s\"%s\"'
1129 base_string
= '%s\markup{ ' + self
.markup
+ ' {%s} }'
1130 return base_string
% (self
.direction_mod (), self
.text
)
1132 class ArticulationEvent (Event
):
1133 def __init__ (self
):
1134 Event
.__init
__ (self
)
1136 self
.force_direction
= None
1137 def wait_for_note (self
):
1140 def direction_mod (self
):
1141 return { 1: '^', -1: '_', 0: '-' }.get (self
.force_direction
, '')
1143 def ly_expression (self
):
1144 return '%s\\%s' % (self
.direction_mod (), self
.type)
1146 class ShortArticulationEvent (ArticulationEvent
):
1147 def direction_mod (self
):
1149 return { 1: '^', -1: '_', 0: '-' }.get (self
.force_direction
, '-')
1150 def ly_expression (self
):
1152 return '%s%s' % (self
.direction_mod (), self
.type)
1156 class NoDirectionArticulationEvent (ArticulationEvent
):
1157 def ly_expression (self
):
1159 return '\\%s' % self
.type
1163 class MarkupEvent (ShortArticulationEvent
):
1164 def __init__ (self
):
1165 ArticulationEvent
.__init
__ (self
)
1166 self
.contents
= None
1167 def ly_expression (self
):
1169 return "%s\\markup { %s }" % (self
.direction_mod (), self
.contents
)
1173 class FretEvent (MarkupEvent
):
1174 def __init__ (self
):
1175 MarkupEvent
.__init
__ (self
)
1176 self
.force_direction
= 1
1181 def ly_expression (self
):
1183 if self
.strings
<> 6:
1184 val
+= "w:%s;" % self
.strings
1186 val
+= "h:%s;" % self
.frets
1187 if self
.barre
and len (self
.barre
) >= 3:
1188 val
+= "c:%s-%s-%s;" % (self
.barre
[0], self
.barre
[1], self
.barre
[2])
1189 have_fingering
= False
1190 for i
in self
.elements
:
1192 val
+= "%s-%s" % (i
[0], i
[1])
1194 have_fingering
= True
1200 return "%s\\markup { \\fret-diagram #\"%s\" }" % (self
.direction_mod (), val
)
1205 class FunctionWrapperEvent (Event
):
1206 def __init__ (self
, function_name
= None):
1207 Event
.__init
__ (self
)
1208 self
.function_name
= function_name
1209 def pre_note_ly (self
, is_chord_element
):
1210 if self
.function_name
:
1211 return "\\%s" % self
.function_name
1214 def pre_chord_ly (self
):
1216 def ly_expression (self
):
1217 if self
.function_name
:
1218 return "\\%s" % self
.function_name
1222 class ParenthesizeEvent (FunctionWrapperEvent
):
1223 def __init__ (self
):
1224 FunctionWrapperEvent
.__init
__ (self
, "parenthesize")
1226 class NotestyleEvent (Event
):
1227 def __init__ (self
):
1228 Event
.__init
__ (self
)
1231 def pre_chord_ly (self
):
1233 return "\\once \\override NoteHead #'style = #%s" % self
.style
1236 def pre_note_ly (self
, is_chord_element
):
1237 if self
.style
and is_chord_element
:
1238 return "\\tweak #'style #%s" % self
.style
1241 def ly_expression (self
):
1242 return self
.pre_chord_ly ()
1246 def __init__ (self
):
1250 return self
.ly_expression()
1251 def ly_expression (self
):
1252 return pitch_generating_function (self
)
1254 class ChordModification
:
1255 def __init__ (self
):
1259 def ly_expression (self
):
1261 val
= {1: ".", -1: "^" }.get (self
.type, "")
1262 val
+= "%s" % self
.step
1263 val
+= {1: "+", -1: "-"}.get (self
.alteration
, "")
1268 class ChordNameEvent (Event
):
1269 def __init__ (self
):
1270 Event
.__init
__ (self
)
1273 self
.duration
= None
1274 self
.modifications
= []
1276 def add_modification (self
, mod
):
1277 self
.modifications
.append (mod
)
1278 def ly_expression (self
):
1281 value
= self
.root
.ly_expression ()
1283 value
+= self
.duration
.ly_expression ()
1287 # First print all additions/changes, and only afterwards all subtractions
1288 for m
in self
.modifications
:
1290 value
+= m
.ly_expression ()
1291 for m
in self
.modifications
:
1293 value
+= m
.ly_expression ()
1295 value
+= "/+%s" % self
.bass
.ly_expression ()
1299 class TremoloEvent (ArticulationEvent
):
1300 def __init__ (self
):
1301 Event
.__init
__ (self
)
1304 def ly_expression (self
):
1306 if self
.bars
and self
.bars
> 0:
1307 str += ':%s' % (2 ** (2 + string
.atoi (self
.bars
)))
1310 class BendEvent (ArticulationEvent
):
1311 def __init__ (self
):
1312 Event
.__init
__ (self
)
1314 def ly_expression (self
):
1315 if self
.alter
!= None:
1316 return "-\\bendAfter #%s" % self
.alter
1320 class RhythmicEvent(Event
):
1321 def __init__ (self
):
1322 Event
.__init
__ (self
)
1323 self
.duration
= Duration()
1324 self
.associated_events
= []
1326 def add_associated_event (self
, ev
):
1328 self
.associated_events
.append (ev
)
1330 def pre_chord_ly (self
):
1331 return [ev
.pre_chord_ly () for ev
in self
.associated_events
]
1333 def pre_note_ly (self
, is_chord_element
):
1334 return [ev
.pre_note_ly (is_chord_element
) for ev
in self
.associated_events
]
1336 def ly_expression_pre_note (self
, is_chord_element
):
1337 res
= string
.join (self
.pre_note_ly (is_chord_element
), ' ')
1342 def get_length (self
):
1343 return self
.duration
.get_length()
1345 def get_properties (self
):
1346 return ("'duration %s"
1347 % self
.duration
.lisp_expression ())
1349 class RestEvent (RhythmicEvent
):
1350 def __init__ (self
):
1351 RhythmicEvent
.__init
__ (self
)
1354 def ly_expression (self
):
1355 res
= self
.ly_expression_pre_note (False)
1357 return res
+ "%s%s\\rest" % (self
.pitch
.ly_expression (), self
.duration
.ly_expression ())
1359 return 'r%s' % self
.duration
.ly_expression ()
1361 def print_ly (self
, printer
):
1362 for ev
in self
.associated_events
:
1363 ev
.print_ly (printer
)
1365 self
.pitch
.print_ly (printer
)
1366 self
.duration
.print_ly (printer
)
1370 self
.duration
.print_ly (printer
)
1372 class SkipEvent (RhythmicEvent
):
1373 def ly_expression (self
):
1374 return 's%s' % self
.duration
.ly_expression ()
1376 class NoteEvent(RhythmicEvent
):
1377 def __init__ (self
):
1378 RhythmicEvent
.__init
__ (self
)
1380 self
.drum_type
= None
1381 self
.cautionary
= False
1382 self
.forced_accidental
= False
1384 def get_properties (self
):
1385 str = RhythmicEvent
.get_properties (self
)
1388 str += self
.pitch
.lisp_expression ()
1389 elif self
.drum_type
:
1390 str += "'drum-type '%s" % self
.drum_type
1394 def pitch_mods (self
):
1397 excl_question
+= '?'
1398 if self
.forced_accidental
:
1399 excl_question
+= '!'
1401 return excl_question
1403 def ly_expression (self
):
1404 # obtain all stuff that needs to be printed before the note:
1405 res
= self
.ly_expression_pre_note (True)
1407 return res
+ '%s%s%s' % (self
.pitch
.ly_expression (),
1409 self
.duration
.ly_expression ())
1410 elif self
.drum_type
:
1411 return res
+ '%s%s' (self
.drum_type
,
1412 self
.duration
.ly_expression ())
1414 def chord_element_ly (self
):
1415 # obtain all stuff that needs to be printed before the note:
1416 res
= self
.ly_expression_pre_note (True)
1418 return res
+ '%s%s' % (self
.pitch
.ly_expression (),
1420 elif self
.drum_type
:
1421 return res
+ '%s%s' (self
.drum_type
)
1424 def print_ly (self
, printer
):
1425 for ev
in self
.associated_events
:
1426 ev
.print_ly (printer
)
1428 self
.pitch
.print_ly (printer
)
1429 printer (self
.pitch_mods ())
1431 printer (self
.drum_type
)
1433 self
.duration
.print_ly (printer
)
1435 class KeySignatureChange (Music
):
1436 def __init__ (self
):
1437 Music
.__init
__ (self
)
1440 self
.non_standard_alterations
= None
1442 def format_non_standard_alteration (self
, a
):
1443 alter_dict
= { -2: ",DOUBLE-FLAT",
1444 -1.5: ",THREE-Q-FLAT",
1450 1.5: ",THREE-Q-SHARP",
1453 accidental
= alter_dict
[a
[1]]
1455 warning (_ ("Unable to convert alteration %s to a lilypond expression") % a
[1])
1458 return "( %s . %s )" % (a
[0], accidental
)
1460 return "(( %s . %s ) . %s )" % (a
[2], a
[0], accidental
)
1464 def ly_expression (self
):
1466 return '\\key %s \\%s' % (self
.tonic
.ly_step_expression (),
1468 elif self
.non_standard_alterations
:
1469 alterations
= [self
.format_non_standard_alteration (a
) for
1470 a
in self
.non_standard_alterations
]
1471 return "\\set Staff.keySignature = #`(%s)" % string
.join (alterations
, " ")
1475 class TimeSignatureChange (Music
):
1476 def __init__ (self
):
1477 Music
.__init
__ (self
)
1478 self
.fractions
= [4,4]
1480 def format_fraction (self
, frac
):
1481 if isinstance (frac
, list):
1482 l
= [self
.format_fraction (f
) for f
in frac
]
1483 return "(" + string
.join (l
, " ") + ")"
1487 def ly_expression (self
):
1489 # Print out the style if we have ome, but the '() should only be
1490 # forced for 2/2 or 4/4, since in all other cases we'll get numeric
1491 # signatures anyway despite the default 'C signature style!
1492 is_common_signature
= self
.fractions
in ([2,2], [4,4], [4,2])
1494 if self
.style
== "common":
1495 st
= "\\defaultTimeSignature"
1496 elif (self
.style
!= "'()"):
1497 st
= "\\once \\override Staff.TimeSignature #'style = #%s " % self
.style
1498 elif (self
.style
!= "'()") or is_common_signature
:
1499 st
= "\\numericTimeSignature"
1501 # Easy case: self.fractions = [n,d] => normal \time n/d call:
1502 if len (self
.fractions
) == 2 and isinstance (self
.fractions
[0], int):
1503 return st
+ '\\time %d/%d ' % tuple (self
.fractions
)
1504 elif self
.fractions
:
1505 return st
+ "\\compoundMeter #'%s" % self
.format_fraction (self
.fractions
)
1509 class ClefChange (Music
):
1510 def __init__ (self
):
1511 Music
.__init
__ (self
)
1516 def octave_modifier (self
):
1517 return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self
.octave
, '')
1518 def clef_name (self
):
1519 return {('G', 2): "treble",
1521 ('C', 1): "soprano",
1522 ('C', 2): "mezzosoprano",
1525 ('C', 5): "baritone",
1526 ('F', 3): "varbaritone",
1528 ('F', 5): "subbass",
1529 ("percussion", 2): "percussion",
1530 ("TAB", 5): "tab"}.get ((self
.type, self
.position
), None)
1531 def ly_expression (self
):
1532 return '\\clef "%s%s"' % (self
.clef_name (), self
.octave_modifier ())
1535 "G": ("clefs.G", -2, -6),
1536 "C": ("clefs.C", 0, 0),
1537 "F": ("clefs.F", 2, 6),
1540 def lisp_expression (self
):
1542 (glyph
, pos
, c0
) = self
.clef_dict
[self
.type]
1546 (make-music 'SequentialMusic
1549 (make-property-set 'clefGlyph "%s") 'Staff)
1551 (make-property-set 'clefPosition %d) 'Staff)
1553 (make-property-set 'middleCPosition %d) 'Staff)))
1554 """ % (glyph
, pos
, c0
)
1557 class Transposition (Music
):
1558 def __init__ (self
):
1559 Music
.__init
__ (self
)
1561 def ly_expression (self
):
1562 self
.pitch
._force
_absolute
_pitch
= True
1563 return '\\transposition %s' % self
.pitch
.ly_expression ()
1565 class StaffChange (Music
):
1566 def __init__ (self
, staff
):
1567 Music
.__init
__ (self
)
1569 def ly_expression (self
):
1571 return "\\change Staff=\"%s\"" % self
.staff
1576 class TempoMark (Music
):
1577 def __init__ (self
):
1578 Music
.__init
__ (self
)
1579 self
.baseduration
= None
1580 self
.newduration
= None
1582 self
.parentheses
= False
1583 def set_base_duration (self
, dur
):
1584 self
.baseduration
= dur
1585 def set_new_duration (self
, dur
):
1586 self
.newduration
= dur
1587 def set_beats_per_minute (self
, beats
):
1589 def set_parentheses (self
, parentheses
):
1590 self
.parentheses
= parentheses
1591 def wait_for_note (self
):
1593 def duration_to_markup (self
, dur
):
1595 # Generate the markup to print the note, use scheme mode for
1596 # ly_expression to get longa and not \longa (which causes an error)
1597 return "\\general-align #Y #DOWN \\smaller \\note #\"%s\" #UP" % dur
.ly_expression(None, True)
1600 def tempo_markup_template (self
):
1601 return "\\mark\\markup { \\fontsize #-2 \\line { %s } }"
1602 def ly_expression (self
):
1604 if not self
.baseduration
:
1607 if self
.parentheses
:
1608 res
+= "\\tempo \"\" %s=%s" % (self
.baseduration
.ly_expression(), self
.beats
)
1610 res
+= "\\tempo %s=%s" % (self
.baseduration
.ly_expression(), self
.beats
)
1611 elif self
.newduration
:
1612 dm
= self
.duration_to_markup (self
.baseduration
)
1613 ndm
= self
.duration_to_markup (self
.newduration
)
1614 if self
.parentheses
:
1615 contents
= "\"(\" %s = %s \")\"" % (dm
, ndm
)
1617 contents
= " %s = %s " % (dm
, ndm
)
1618 res
+= self
.tempo_markup_template() % contents
1623 class FiguredBassNote (Music
):
1624 def __init__ (self
):
1625 Music
.__init
__ (self
)
1629 def set_prefix (self
, prefix
):
1630 self
.prefix
= prefix
1631 def set_suffix (self
, suffix
):
1632 self
.prefix
= suffix
1633 def set_number (self
, number
):
1634 self
.number
= number
1635 def ly_expression (self
):
1648 class FiguredBassEvent (NestedMusic
):
1649 def __init__ (self
):
1650 NestedMusic
.__init
__ (self
)
1651 self
.duration
= None
1652 self
.real_duration
= 0
1653 self
.parentheses
= False
1655 def set_duration (self
, dur
):
1657 def set_parentheses (self
, par
):
1658 self
.parentheses
= par
1659 def set_real_duration (self
, dur
):
1660 self
.real_duration
= dur
1662 def print_ly (self
, printer
):
1663 figured_bass_events
= [e
for e
in self
.elements
if
1664 isinstance (e
, FiguredBassNote
)]
1665 if figured_bass_events
:
1667 for x
in figured_bass_events
:
1668 notes
.append (x
.ly_expression ())
1669 contents
= string
.join (notes
)
1670 if self
.parentheses
:
1671 contents
= '[%s]' % contents
1672 printer ('<%s>' % contents
)
1673 self
.duration
.print_ly (printer
)
1676 class MultiMeasureRest(Music
):
1678 def lisp_expression (self
):
1681 'MultiMeasureRestMusicGroup
1683 (list (make-music (quote BarCheck))
1688 'MultiMeasureRestEvent
1691 (make-music (quote BarCheck))))
1692 """ % self
.duration
.lisp_expression ()
1694 def ly_expression (self
):
1695 return 'R%s' % self
.duration
.ly_expression ()
1699 def __init__ (self
, command
= "StaffGroup"):
1700 self
.stafftype
= command
1702 self
.instrument_name
= None
1703 self
.short_instrument_name
= None
1707 self
.is_group
= True
1708 # part_information is a list with entries of the form
1709 # [staffid, voicelist]
1710 # where voicelist is a list with entries of the form
1711 # [voiceid1, [lyricsid11, lyricsid12,...] ]
1712 self
.part_information
= None
1714 def append_staff (self
, staff
):
1715 self
.children
.append (staff
)
1717 def set_part_information (self
, part_name
, staves_info
):
1718 if part_name
== self
.id:
1719 self
.part_information
= staves_info
1721 for c
in self
.children
:
1722 c
.set_part_information (part_name
, staves_info
)
1724 def print_ly_contents (self
, printer
):
1725 for c
in self
.children
:
1727 c
.print_ly (printer
)
1728 def print_ly_overrides (self
, printer
):
1730 needs_with |
= self
.spanbar
== "no"
1731 needs_with |
= self
.instrument_name
!= None
1732 needs_with |
= self
.short_instrument_name
!= None
1733 needs_with |
= (self
.symbol
!= None) and (self
.symbol
!= "bracket")
1735 printer
.dump ("\\with {")
1736 if self
.instrument_name
or self
.short_instrument_name
:
1737 printer
.dump ("\\consists \"Instrument_name_engraver\"")
1738 if self
.spanbar
== "no":
1739 printer
.dump ("\\override SpanBar #'transparent = ##t")
1740 brack
= {"brace": "SystemStartBrace",
1742 "line": "SystemStartSquare"}.get (self
.symbol
, None)
1744 printer
.dump ("systemStartDelimiter = #'%s" % brack
)
1747 def print_ly (self
, printer
):
1749 printer
.dump ("\\new %s" % self
.stafftype
)
1750 self
.print_ly_overrides (printer
)
1753 if self
.stafftype
and self
.instrument_name
:
1754 printer
.dump ("\\set %s.instrumentName = %s" % (self
.stafftype
,
1755 escape_instrument_string (self
.instrument_name
)))
1757 if self
.stafftype
and self
.short_instrument_name
:
1758 printer
.dump ("\\set %s.shortInstrumentName = %s" % (self
.stafftype
,
1759 escape_instrument_string (self
.short_instrument_name
)))
1761 self
.print_ly_contents (printer
)
1767 class Staff (StaffGroup
):
1768 def __init__ (self
, command
= "Staff"):
1769 StaffGroup
.__init
__ (self
, command
)
1770 self
.is_group
= False
1772 self
.voice_command
= "Voice"
1773 self
.substafftype
= None
1775 def print_ly_overrides (self
, printer
):
1778 def print_ly_contents (self
, printer
):
1779 if not self
.id or not self
.part_information
:
1781 sub_staff_type
= self
.substafftype
1782 if not sub_staff_type
:
1783 sub_staff_type
= self
.stafftype
1785 for [staff_id
, voices
] in self
.part_information
:
1786 # Chord names need to come before the staff itself!
1787 for [v
, lyrics
, figuredbass
, chordnames
] in voices
:
1789 printer ('\context ChordNames = "%s" \\%s' % (chordnames
, chordnames
))
1791 # now comes the real staff definition:
1793 printer ('\\context %s = "%s" << ' % (sub_staff_type
, staff_id
))
1795 printer ('\\context %s << ' % sub_staff_type
)
1798 nr_voices
= len (voices
)
1799 for [v
, lyrics
, figuredbass
, chordnames
] in voices
:
1801 voice_count_text
= ''
1803 voice_count_text
= {1: ' \\voiceOne', 2: ' \\voiceTwo',
1804 3: ' \\voiceThree'}.get (n
, ' \\voiceFour')
1805 printer ('\\context %s = "%s" {%s \\%s }' % (self
.voice_command
, v
, voice_count_text
, v
))
1809 printer ('\\new Lyrics \\lyricsto "%s" \\%s' % (v
,l
))
1812 printer ('\context FiguredBass = "%s" \\%s' % (figuredbass
, figuredbass
))
1815 def print_ly (self
, printer
):
1816 if self
.part_information
and len (self
.part_information
) > 1:
1817 self
.stafftype
= "PianoStaff"
1818 self
.substafftype
= "Staff"
1819 StaffGroup
.print_ly (self
, printer
)
1821 class TabStaff (Staff
):
1822 def __init__ (self
, command
= "TabStaff"):
1823 Staff
.__init
__ (self
, command
)
1824 self
.string_tunings
= []
1825 self
.tablature_format
= None
1826 self
.voice_command
= "TabVoice"
1827 def print_ly_overrides (self
, printer
):
1828 if self
.string_tunings
or self
.tablature_format
:
1829 printer
.dump ("\\with {")
1830 if self
.string_tunings
:
1831 printer
.dump ("stringTunings = #'(")
1832 for i
in self
.string_tunings
:
1833 printer
.dump ("%s" % i
.semitones ())
1835 if self
.tablature_format
:
1836 printer
.dump ("tablatureFormat = #%s" % self
.tablature_format
)
1840 class DrumStaff (Staff
):
1841 def __init__ (self
, command
= "DrumStaff"):
1842 Staff
.__init
__ (self
, command
)
1843 self
.drum_style_table
= None
1844 self
.voice_command
= "DrumVoice"
1845 def print_ly_overrides (self
, printer
):
1846 if self
.drum_style_table
:
1847 printer
.dump ("\with {")
1848 printer
.dump ("drumStyleTable = #%s" % self
.drum_style_table
)
1851 class RhythmicStaff (Staff
):
1852 def __init__ (self
, command
= "RhythmicStaff"):
1853 Staff
.__init
__ (self
, command
)
1856 def __init__ (self
):
1857 self
.contents
= None
1858 self
.create_midi
= False
1860 def set_contents (self
, contents
):
1861 self
.contents
= contents
1863 def set_part_information (self
, part_id
, staves_info
):
1865 self
.contents
.set_part_information (part_id
, staves_info
)
1867 def print_ly (self
, printer
):
1868 printer
.dump ("\\score {");
1871 self
.contents
.print_ly (printer
);
1872 printer
.dump ("\\layout {}");
1874 if not self
.create_midi
:
1875 printer
.dump ("% To create MIDI output, uncomment the following line:");
1877 printer
.dump ("% ");
1878 printer
.dump ("\\midi {}");
1886 bflat
.alteration
= -1
1896 print bflat
.semitones()
1897 print bflat
.transposed (fifth
), bflat
.transposed (fifth
).transposed (fifth
)
1898 print bflat
.transposed (fifth
).transposed (fifth
).transposed (fifth
)
1900 print bflat
.semitones(), 'down'
1901 print bflat
.transposed (down
)
1902 print bflat
.transposed (down
).transposed (down
)
1903 print bflat
.transposed (down
).transposed (down
).transposed (down
)
1907 def test_printer ():
1915 m
= SequentialMusic()
1916 m
.append (make_note ())
1917 m
.append (make_note ())
1918 m
.append (make_note ())
1921 t
= TimeScaledMusic ()
1927 m
= SequentialMusic ()
1928 m
.append (make_tup ())
1929 m
.append (make_tup ())
1930 m
.append (make_tup ())
1932 printer
= Output_printer()
1933 m
.print_ly (printer
)
1937 m
= SequentialMusic()
1941 n
.duration
.duration_log
= l
1943 evc
.insert_around (None, n
, 0)
1944 m
.insert_around (None, evc
, 0)
1948 n
.duration
.duration_log
= l
1950 evc
.insert_around (None, n
, 0)
1951 m
.insert_around (None, evc
, 0)
1955 n
.duration
.duration_log
= l
1957 evc
.insert_around (None, n
, 0)
1958 m
.insert_around (None, evc
, 0)
1962 m
.insert_around (None, evc
, 0)
1967 tonic
.alteration
= -2
1968 n
= KeySignatureChange()
1969 n
.tonic
=tonic
.copy()
1970 n
.scale
= [0, 0, -2, 0, 0,-2,-2]
1972 evc
.insert_around (None, n
, 0)
1973 m
.insert_around (None, evc
, 0)
1978 if __name__
== '__main__':
1984 expr
.set_start (Rational (0))
1985 print expr
.ly_expression()
1986 start
= Rational (0,4)
1987 stop
= Rational (4,2)
1988 def sub(x
, start
=start
, stop
=stop
):
1989 ok
= x
.start
>= start
and x
.start
+x
.get_length() <= stop
1992 print expr
.lisp_sub_expression(sub
)