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