1 # -*- coding: utf-8 -*-
10 from rational
import Rational
12 # Store previously converted pitch for \relative conversion as a global state variable
14 relative_pitches
= False
17 ly
.stderr_write ((_ ("warning: %s") % str) + "\n")
20 def escape_instrument_string (input_string
):
21 retstring
= string
.replace (input_string
, "\"", "\\\"")
22 if re
.match ('.*[\r\n]+.*', retstring
):
23 rx
= re
.compile (r
'[\n\r]+')
24 strings
= rx
.split (retstring
)
25 retstring
= "\\markup { \\column { "
27 retstring
+= "\\line {\"" + s
+ "\"} "
30 retstring
= "\"" + retstring
+ "\""
33 class Output_stack_element
:
35 self
.factor
= Rational (1)
37 o
= Output_stack_element()
38 o
.factor
= self
.factor
43 """A class that takes care of formatting (eg.: indenting) a
44 Music expression as a .ly file.
52 self
._file
= sys
.stdout
54 self
._output
_state
_stack
= [Output_stack_element()]
55 self
._skipspace
= False
56 self
._last
_duration
= None
58 def set_file (self
, file):
61 def dump_version (self
):
63 self
.print_verbatim ('\\version "@TOPLEVEL_VERSION@"')
66 def get_indent (self
):
67 return self
._nesting
* self
._indent
70 last
= self
._output
_state
_stack
[-1]
71 self
._output
_state
_stack
.append (last
.copy())
73 def add_factor (self
, factor
):
75 self
._output
_state
_stack
[-1].factor
*= factor
78 del self
._output
_state
_stack
[-1]
79 if not self
._output
_state
_stack
:
82 def duration_factor (self
):
83 return self
._output
_state
_stack
[-1].factor
85 def print_verbatim (self
, str):
88 def unformatted_output (self
, str):
89 # don't indent on \< and indent only once on <<
90 self
._nesting
+= ( str.count ('<')
91 - str.count ('\<') - str.count ('<<')
93 self
._nesting
-= ( str.count ('>') - str.count ('\>') - str.count ('>>')
94 - str.count ('->') - str.count ('_>')
97 self
.print_verbatim (str)
99 def print_duration_string (self
, str):
100 if self
._last
_duration
== str:
103 self
.unformatted_output (str)
105 def add_word (self
, str):
106 if (len (str) + 1 + len (self
._line
) > self
._line
_len
):
108 self
._skipspace
= True
110 if not self
._skipspace
:
112 self
.unformatted_output (str)
113 self
._skipspace
= False
116 self
._file
.write (self
._line
+ '\n')
117 self
._line
= ' ' * self
._indent
* self
._nesting
118 self
._skipspace
= True
120 def skipspace (self
):
121 self
._skipspace
= True
123 def __call__(self
, arg
):
126 def dump (self
, str):
128 self
._skipspace
= False
129 self
.unformatted_output (str)
131 words
= string
.split (str)
144 self
.duration_log
= 0
146 self
.factor
= Rational (1)
148 def lisp_expression (self
):
149 return '(ly:make-duration %d %d %d %d)' % (self
.duration_log
,
151 self
.factor
.numerator (),
152 self
.factor
.denominator ())
155 def ly_expression (self
, factor
= None, scheme_mode
= False):
159 if self
.duration_log
< 0:
161 longer_dict
= {-1: "breve", -2: "longa"}
163 longer_dict
= {-1: "\\breve", -2: "\\longa"}
164 str = longer_dict
.get (self
.duration_log
, "1")
166 str = '%d' % (1 << self
.duration_log
)
169 if factor
<> Rational (1,1):
170 if factor
.denominator () <> 1:
171 str += '*%d/%d' % (factor
.numerator (), factor
.denominator ())
173 str += '*%d' % factor
.numerator ()
177 def print_ly (self
, outputter
):
178 str = self
.ly_expression (self
.factor
/ outputter
.duration_factor ())
179 outputter
.print_duration_string (str)
182 return self
.ly_expression()
187 d
.duration_log
= self
.duration_log
188 d
.factor
= self
.factor
191 def get_length (self
):
192 dot_fact
= Rational( (1 << (1 + self
.dots
))-1,
195 log
= abs (self
.duration_log
)
197 if self
.duration_log
< 0:
198 base
= Rational (dur
)
200 base
= Rational (1, dur
)
202 return base
* dot_fact
* self
.factor
205 # Implement the different note names for the various languages
206 def pitch_generic (pitch
, notenames
, accidentals
):
207 str = notenames
[pitch
.step
]
208 halftones
= int (pitch
.alteration
)
210 str += accidentals
[0] * (-halftones
)
211 elif pitch
.alteration
> 0:
212 str += accidentals
[3] * (halftones
)
213 # Handle remaining fraction to pitch.alteration (for microtones)
214 if (halftones
!= pitch
.alteration
):
215 if None in accidentals
[1:3]:
216 warning (_ ("Language does not support microtones contained in the piece"))
219 str += {-0.5: accidentals
[1], 0.5: accidentals
[2]}[pitch
.alteration
-halftones
]
221 warning (_ ("Language does not support microtones contained in the piece"))
224 def pitch_general (pitch
):
225 str = pitch_generic (pitch
, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['es', 'eh', 'ih', 'is'])
226 return str.replace ('aes', 'as').replace ('ees', 'es')
228 def pitch_nederlands (pitch
):
229 return pitch_general (pitch
)
231 def pitch_english (pitch
):
232 str = pitch_generic (pitch
, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['f', 'qf', 'qs', 's'])
233 return str.replace ('aes', 'as').replace ('ees', 'es')
235 def pitch_deutsch (pitch
):
236 str = pitch_generic (pitch
, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['es', 'eh', 'ih', 'is'])
237 return str.replace ('hes', 'b').replace ('aes', 'as').replace ('ees', 'es')
239 def pitch_norsk (pitch
):
240 return pitch_deutsch (pitch
)
242 def pitch_svenska (pitch
):
243 str = pitch_generic (pitch
, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', None, None, 'iss'])
244 return str.replace ('hess', 'b').replace ('aes', 'as').replace ('ees', 'es')
246 def pitch_italiano (pitch
):
247 str = pitch_generic (pitch
, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', 'sb', 'sd', 'd'])
250 def pitch_catalan (pitch
):
251 return pitch_italiano (pitch
)
253 def pitch_espanol (pitch
):
254 str = pitch_generic (pitch
, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 's'])
257 def pitch_vlaams (pitch
):
258 str = pitch_generic (pitch
, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 'k'])
261 def set_pitch_language (language
):
262 global pitch_generating_function
264 "nederlands": pitch_nederlands
,
265 "english": pitch_english
,
266 "deutsch": pitch_deutsch
,
267 "norsk": pitch_norsk
,
268 "svenska": pitch_svenska
,
269 "italiano": pitch_italiano
,
270 "catalan": pitch_catalan
,
271 "espanol": pitch_espanol
,
272 "vlaams": pitch_vlaams
}
273 pitch_generating_function
= function_dict
.get (language
, pitch_general
)
275 # global variable to hold the formatting function.
276 pitch_generating_function
= pitch_general
284 self
._force
_absolute
_pitch
= False
287 return self
.ly_expression()
289 def transposed (self
, interval
):
291 c
.alteration
+= interval
.alteration
292 c
.step
+= interval
.step
293 c
.octave
+= interval
.octave
296 target_st
= self
.semitones() + interval
.semitones()
297 c
.alteration
+= target_st
- c
.semitones()
304 c
.octave
+= c
.step
/ 7
307 def lisp_expression (self
):
308 return '(ly:make-pitch %d %d %d)' % (self
.octave
,
314 p
.alteration
= self
.alteration
316 p
.octave
= self
.octave
320 return self
.step
+ self
.octave
*7
322 def semitones (self
):
323 return self
.octave
* 12 + [0,2,4,5,7,9,11][self
.step
] + self
.alteration
325 def ly_step_expression (self
):
326 return pitch_generating_function (self
)
328 def absolute_pitch (self
):
330 return "'" * (self
.octave
+ 1)
331 elif self
.octave
< -1:
332 return "," * (-self
.octave
- 1)
336 def relative_pitch (self
):
337 global previous_pitch
338 if not previous_pitch
:
339 previous_pitch
= self
340 return self
.absolute_pitch ()
341 previous_pitch_steps
= previous_pitch
.octave
* 7 + previous_pitch
.step
342 this_pitch_steps
= self
.octave
* 7 + self
.step
343 pitch_diff
= (this_pitch_steps
- previous_pitch_steps
)
344 previous_pitch
= self
346 return "'" * ((pitch_diff
+ 3) / 7)
347 elif pitch_diff
< -3:
348 return "," * ((-pitch_diff
+ 3) / 7)
352 def ly_expression (self
):
353 str = self
.ly_step_expression ()
354 if relative_pitches
and not self
._force
_absolute
_pitch
:
355 str += self
.relative_pitch ()
357 str += self
.absolute_pitch ()
361 def print_ly (self
, outputter
):
362 outputter (self
.ly_expression())
367 self
.start
= Rational (0)
369 self
.identifier
= None
371 def get_length(self
):
374 def get_properties (self
):
377 def has_children (self
):
380 def get_index (self
):
382 return self
.parent
.elements
.index (self
)
386 return self
.__class
__.__name
__
388 def lisp_expression (self
):
391 props
= self
.get_properties ()
393 return "(make-music '%s %s)" % (name
, props
)
395 def set_start (self
, start
):
398 def find_first (self
, predicate
):
403 def print_comment (self
, printer
, text
= None):
414 lines
= string
.split (text
, '\n')
417 printer
.unformatted_output ('% ' + l
)
421 def print_with_identifier (self
, printer
):
423 printer ("\\%s" % self
.identifier
)
425 self
.print_ly (printer
)
427 def print_ly (self
, printer
):
428 printer (self
.ly_expression ())
430 class MusicWrapper (Music
):
434 def print_ly (self
, func
):
435 self
.element
.print_ly (func
)
437 class ModeChangingMusicWrapper (MusicWrapper
):
439 MusicWrapper
.__init
__ (self
)
440 self
.mode
= 'notemode'
442 def print_ly (self
, func
):
443 func ('\\%s' % self
.mode
)
444 MusicWrapper
.print_ly (self
, func
)
446 class RelativeMusic (MusicWrapper
):
448 MusicWrapper
.__init
__ (self
)
449 self
.basepitch
= None
451 def print_ly (self
, func
):
452 global previous_pitch
453 global relative_pitches
454 prev_relative_pitches
= relative_pitches
455 relative_pitches
= True
456 previous_pitch
= self
.basepitch
457 if not previous_pitch
:
458 previous_pitch
= Pitch ()
459 func ('\\relative %s%s' % (pitch_generating_function (previous_pitch
),
460 previous_pitch
.absolute_pitch ()))
461 MusicWrapper
.print_ly (self
, func
)
462 relative_pitches
= prev_relative_pitches
464 class TimeScaledMusic (MusicWrapper
):
466 MusicWrapper
.__init
__ (self
)
469 self
.display_number
= "actual" # valid values "actual" | "both" | None
470 # Display the basic note length for the tuplet:
471 self
.display_type
= None # value values "actual" | "both" | None
472 self
.display_bracket
= "bracket" # valid values "bracket" | "curved" | None
473 self
.actual_type
= None # The actually played unit of the scaling
474 self
.normal_type
= None # The basic unit of the scaling
475 self
.display_numerator
= None
476 self
.display_denominator
= None
478 def print_ly (self
, func
):
479 if self
.display_bracket
== None:
480 func ("\\once \\override TupletBracket #'stencil = ##f")
482 elif self
.display_bracket
== "curved":
483 warning (_ ("Tuplet brackets of curved shape are not correctly implemented"))
484 func ("\\once \\override TupletBracket #'stencil = #ly:slur::print")
487 base_number_function
= {None: "#f",
488 "actual": "tuplet-number::calc-denominator-text",
489 "both": "tuplet-number::calc-fraction-text"}.get (self
.display_number
, None)
490 # If we have non-standard numerator/denominator, use our custom function
491 if self
.display_number
== "actual" and self
.display_denominator
:
492 base_number_function
= "(tuplet-number::non-default-tuplet-denominator-text %s)" % self
.display_denominator
493 elif self
.display_number
== "both" and (self
.display_denominator
or self
.display_numerator
):
494 if self
.display_numerator
:
495 num
= self
.display_numerator
498 if self
.display_denominator
:
499 den
= self
.display_denominator
502 base_number_function
= "(tuplet-number::non-default-tuplet-fraction-text %s %s)" % (den
, num
)
505 if self
.display_type
== "actual" and self
.normal_type
:
506 # Obtain the note duration in scheme-mode, i.e. \longa as \\longa
507 base_duration
= self
.normal_type
.ly_expression (None, True)
508 func ("\\once \\override TupletNumber #'text = #(tuplet-number::append-note-wrapper %s \"%s\")" %
509 (base_number_function
, base_duration
))
511 elif self
.display_type
== "both": # TODO: Implement this using actual_type and normal_type!
512 if self
.display_number
== None:
513 func ("\\once \\override TupletNumber #'stencil = ##f")
515 elif self
.display_number
== "both":
516 den_duration
= self
.normal_type
.ly_expression (None, True)
517 # If we don't have an actual type set, use the normal duration!
519 num_duration
= self
.actual_type
.ly_expression (None, True)
521 num_duration
= den_duration
522 if (self
.display_denominator
or self
.display_numerator
):
523 func ("\\once \\override TupletNumber #'text = #(tuplet-number::non-default-fraction-with-notes %s \"%s\" %s \"%s\")" %
524 (self
.display_denominator
, den_duration
,
525 self
.display_numerator
, num_duration
))
528 func ("\\once \\override TupletNumber #'text = #(tuplet-number::fraction-with-notes \"%s\" \"%s\")" %
529 (den_duration
, num_duration
))
532 if self
.display_number
== None:
533 func ("\\once \\override TupletNumber #'stencil = ##f")
535 elif self
.display_number
== "both":
536 func ("\\once \\override TupletNumber #'text = #%s" % base_number_function
)
539 func ('\\times %d/%d ' %
540 (self
.numerator
, self
.denominator
))
541 func
.add_factor (Rational (self
.numerator
, self
.denominator
))
542 MusicWrapper
.print_ly (self
, func
)
545 class NestedMusic(Music
):
547 Music
.__init
__ (self
)
550 def append (self
, what
):
552 self
.elements
.append (what
)
554 def has_children (self
):
557 def insert_around (self
, succ
, elt
, dir):
558 assert elt
.parent
== None
559 assert succ
== None or succ
in self
.elements
564 idx
= self
.elements
.index (succ
)
571 idx
= len (self
.elements
)
573 self
.elements
.insert (idx
, elt
)
576 def get_properties (self
):
577 return ("'elements (list %s)"
578 % string
.join (map (lambda x
: x
.lisp_expression(),
581 def get_subset_properties (self
, predicate
):
582 return ("'elements (list %s)"
583 % string
.join (map (lambda x
: x
.lisp_expression(),
584 filter ( predicate
, self
.elements
))))
585 def get_neighbor (self
, music
, dir):
586 assert music
.parent
== self
587 idx
= self
.elements
.index (music
)
589 idx
= min (idx
, len (self
.elements
) -1)
592 return self
.elements
[idx
]
594 def delete_element (self
, element
):
595 assert element
in self
.elements
597 self
.elements
.remove (element
)
598 element
.parent
= None
600 def set_start (self
, start
):
602 for e
in self
.elements
:
605 def find_first (self
, predicate
):
606 r
= Music
.find_first (self
, predicate
)
610 for e
in self
.elements
:
611 r
= e
.find_first (predicate
)
616 class SequentialMusic (NestedMusic
):
617 def get_last_event_chord (self
):
619 at
= len( self
.elements
) - 1
621 not isinstance (self
.elements
[at
], ChordEvent
) and
622 not isinstance (self
.elements
[at
], BarLine
)):
625 if (at
>= 0 and isinstance (self
.elements
[at
], ChordEvent
)):
626 value
= self
.elements
[at
]
629 def print_ly (self
, printer
, newline
= True):
632 self
.print_comment (printer
)
636 for e
in self
.elements
:
643 def lisp_sub_expression (self
, pred
):
647 props
= self
.get_subset_properties (pred
)
649 return "(make-music '%s %s)" % (name
, props
)
651 def set_start (self
, start
):
652 for e
in self
.elements
:
654 start
+= e
.get_length()
658 self
.repeat_type
= "volta"
659 self
.repeat_count
= 2
662 def set_music (self
, music
):
663 if isinstance (music
, Music
):
665 elif isinstance (music
, list):
666 self
.music
= SequentialMusic ()
667 self
.music
.elements
= music
669 warning (_ ("unable to set the music %(music)s for the repeat %(repeat)s") % \
670 {'music':music
, 'repeat':self
})
671 def add_ending (self
, music
):
672 self
.endings
.append (music
)
673 def print_ly (self
, printer
):
674 printer
.dump ('\\repeat %s %s' % (self
.repeat_type
, self
.repeat_count
))
676 self
.music
.print_ly (printer
)
678 warning (_ ("encountered repeat without body"))
681 printer
.dump ('\\alternative {')
682 for e
in self
.endings
:
689 self
.lyrics_syllables
= []
691 def print_ly (self
, printer
):
692 printer
.dump ("\lyricmode {")
693 for l
in self
.lyrics_syllables
:
694 printer
.dump ( "%s " % l
)
697 def ly_expression (self
):
698 lstr
= "\lyricmode {\n "
699 for l
in self
.lyrics_syllables
:
707 self
.header_fields
= {}
708 def set_field (self
, field
, value
):
709 self
.header_fields
[field
] = value
711 def print_ly (self
, printer
):
712 printer
.dump ("\header {")
714 for (k
,v
) in self
.header_fields
.items ():
716 printer
.dump ('%s = %s' % (k
,v
))
725 self
.global_staff_size
= -1
728 self
.page_height
= -1
731 self
.bottom_margin
= -1
732 self
.left_margin
= -1
733 self
.right_margin
= -1
734 self
.system_left_margin
= -1
735 self
.system_right_margin
= -1
736 self
.system_distance
= -1
737 self
.top_system_distance
= -1
739 def print_length_field (self
, printer
, field
, value
):
741 printer
.dump ("%s = %s\\cm" % (field
, value
))
743 def print_ly (self
, printer
):
744 if self
.global_staff_size
> 0:
745 printer
.dump ('#(set-global-staff-size %s)' % self
.global_staff_size
)
747 printer
.dump ('\\paper {')
749 self
.print_length_field (printer
, "paper-width", self
.page_width
)
750 self
.print_length_field (printer
, "paper-height", self
.page_height
)
751 self
.print_length_field (printer
, "top-margin", self
.top_margin
)
752 self
.print_length_field (printer
, "botton-margin", self
.bottom_margin
)
753 self
.print_length_field (printer
, "left-margin", self
.left_margin
)
754 # TODO: maybe set line-width instead of right-margin?
755 self
.print_length_field (printer
, "right-margin", self
.right_margin
)
756 # TODO: What's the corresponding setting for system_left_margin and
757 # system_right_margin in LilyPond?
758 self
.print_length_field (printer
, "between-system-space", self
.system_distance
)
759 self
.print_length_field (printer
, "page-top-space", self
.top_system_distance
)
766 self
.context_dict
= {}
767 def add_context (self
, context
):
768 if not self
.context_dict
.has_key (context
):
769 self
.context_dict
[context
] = []
770 def set_context_item (self
, context
, item
):
771 self
.add_context (context
)
772 if not item
in self
.context_dict
[context
]:
773 self
.context_dict
[context
].append (item
)
774 def print_ly (self
, printer
):
775 if self
.context_dict
.items ():
776 printer
.dump ('\\layout {')
778 for (context
, defs
) in self
.context_dict
.items ():
779 printer
.dump ('\\context { \\%s' % context
)
790 class ChordEvent (NestedMusic
):
792 NestedMusic
.__init
__ (self
)
793 self
.after_grace_elements
= None
794 self
.grace_elements
= None
795 self
.grace_type
= None
796 def append_grace (self
, element
):
798 if not self
.grace_elements
:
799 self
.grace_elements
= SequentialMusic ()
800 self
.grace_elements
.append (element
)
801 def append_after_grace (self
, element
):
803 if not self
.after_grace_elements
:
804 self
.after_grace_elements
= SequentialMusic ()
805 self
.after_grace_elements
.append (element
)
807 def has_elements (self
):
808 return [e
for e
in self
.elements
if
809 isinstance (e
, NoteEvent
) or isinstance (e
, RestEvent
)] != []
812 def get_length (self
):
814 for e
in self
.elements
:
815 l
= max(l
, e
.get_length())
818 def get_duration (self
):
819 note_events
= [e
for e
in self
.elements
if
820 isinstance (e
, NoteEvent
) or isinstance (e
, RestEvent
)]
822 return note_events
[0].duration
826 def print_ly (self
, printer
):
827 note_events
= [e
for e
in self
.elements
if
828 isinstance (e
, NoteEvent
)]
830 rest_events
= [e
for e
in self
.elements
if
831 isinstance (e
, RhythmicEvent
)
832 and not isinstance (e
, NoteEvent
)]
834 other_events
= [e
for e
in self
.elements
if
835 not isinstance (e
, RhythmicEvent
)]
837 if self
.after_grace_elements
:
838 printer ('\\afterGrace {')
840 if self
.grace_elements
and self
.elements
:
842 printer ('\\%s' % self
.grace_type
)
845 # don't print newlines after the { and } braces
846 self
.grace_elements
.print_ly (printer
, False)
847 elif self
.grace_elements
: # no self.elements!
848 warning (_ ("Grace note with no following music: %s") % self
.grace_elements
)
850 printer ('\\%s' % self
.grace_type
)
853 self
.grace_elements
.print_ly (printer
, False)
856 # Print all overrides and other settings needed by the
857 # articulations/ornaments before the note
858 for e
in other_events
:
859 e
.print_before_note (printer
)
862 rest_events
[0].print_ly (printer
)
863 elif len (note_events
) == 1:
864 note_events
[0].print_ly (printer
)
866 global previous_pitch
869 for x
in note_events
:
870 pitches
.append (x
.chord_element_ly ())
872 basepitch
= previous_pitch
873 printer ('<%s>' % string
.join (pitches
))
874 previous_pitch
= basepitch
875 duration
= self
.get_duration ()
877 duration
.print_ly (printer
)
881 for e
in other_events
:
884 for e
in other_events
:
885 e
.print_after_note (printer
)
887 if self
.after_grace_elements
:
889 self
.after_grace_elements
.print_ly (printer
, False)
891 self
.print_comment (printer
)
893 class Partial (Music
):
895 Music
.__init
__ (self
)
897 def print_ly (self
, printer
):
899 printer
.dump ("\\partial %s" % self
.partial
.ly_expression ())
901 class BarLine (Music
):
903 Music
.__init
__ (self
)
907 def print_ly (self
, printer
):
908 bar_symbol
= { 'regular': "|", 'dotted': ":", 'dashed': "dashed",
909 'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
910 'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
911 'short': "'", 'none': "" }.get (self
.type, None)
912 if bar_symbol
<> None:
913 printer
.dump ('\\bar "%s"' % bar_symbol
)
917 if self
.bar_number
> 0 and (self
.bar_number
% 10) == 0:
918 printer
.dump ("\\barNumberCheck #%d " % self
.bar_number
)
919 elif self
.bar_number
> 0:
920 printer
.print_verbatim (' %% %d' % self
.bar_number
)
923 def ly_expression (self
):
928 # strings to print before the note to which an event is attached.
929 # Ignored for notes etc.
930 self
.before_note
= None
931 self
.after_note
= None
932 # print something before the note to which an event is attached, e.g. overrides
933 def print_before_note (self
, printer
):
935 printer
.dump (self
.before_note
)
936 # print something after the note to which an event is attached, e.g. resetting
937 def print_after_note (self
, printer
):
939 printer
.dump (self
.after_note
)
942 class SpanEvent (Event
):
944 Event
.__init
__ (self
)
945 self
.span_direction
= 0 # start/stop
946 self
.line_type
= 'solid'
947 self
.span_type
= 0 # e.g. cres/decrescendo, ottava up/down
948 self
.size
= 0 # size of e.g. ocrave shift
949 def wait_for_note (self
):
951 def get_properties(self
):
952 return "'span-direction %d" % self
.span_direction
953 def set_span_type (self
, type):
954 self
.span_type
= type
956 class SlurEvent (SpanEvent
):
957 def print_before_note (self
, printer
):
958 command
= {'dotted': '\\slurDotted',
959 'dashed' : '\\slurDashed'}.get (self
.line_type
, '')
960 if command
and self
.span_direction
== -1:
961 printer
.dump (command
)
962 def print_after_note (self
, printer
):
963 # reset non-solid slur types!
964 command
= {'dotted': '\\slurSolid',
965 'dashed' : '\\slurSolid'}.get (self
.line_type
, '')
966 if command
and self
.span_direction
== -1:
967 printer
.dump (command
)
968 def ly_expression (self
):
969 return {-1: '(', 1:')'}.get (self
.span_direction
, '')
971 class BeamEvent (SpanEvent
):
972 def ly_expression (self
):
973 return {-1: '[', 1:']'}.get (self
.span_direction
, '')
975 class PedalEvent (SpanEvent
):
976 def ly_expression (self
):
977 return {-1: '\\sustainOn',
978 0:'\\sustainOff\\sustainOn',
979 1:'\\sustainOff'}.get (self
.span_direction
, '')
981 class TextSpannerEvent (SpanEvent
):
982 def ly_expression (self
):
983 return {-1: '\\startTextSpan',
984 1:'\\stopTextSpan'}.get (self
.span_direction
, '')
986 class BracketSpannerEvent (SpanEvent
):
987 # Ligature brackets use prefix-notation!!!
988 def print_before_note (self
, printer
):
989 if self
.span_direction
== -1:
991 # the bracket after the last note
992 def print_after_note (self
, printer
):
993 if self
.span_direction
== 1:
995 # we're printing everything in print_(before|after)_note...
996 def ly_expression (self
):
1000 class OctaveShiftEvent (SpanEvent
):
1001 def wait_for_note (self
):
1003 def set_span_type (self
, type):
1004 self
.span_type
= {'up': 1, 'down': -1}.get (type, 0)
1005 def ly_octave_shift_indicator (self
):
1006 # convert 8/15 to lilypond indicators (+-1/+-2)
1008 value
= {8: 1, 15: 2}[self
.size
]
1010 warning (_ ("Invalid octave shift size found: %s. Using no shift.") % self
.size
)
1012 # negative values go up!
1013 value
*= -1*self
.span_type
1015 def ly_expression (self
):
1016 dir = self
.ly_octave_shift_indicator ()
1019 value
= '\ottava #%s' % dir
1022 1: '\ottava #0'}.get (self
.span_direction
, '')
1024 class TrillSpanEvent (SpanEvent
):
1025 def ly_expression (self
):
1026 return {-1: '\\startTrillSpan',
1027 0: '', # no need to write out anything for type='continue'
1028 1:'\\stopTrillSpan'}.get (self
.span_direction
, '')
1030 class GlissandoEvent (SpanEvent
):
1031 def print_before_note (self
, printer
):
1032 if self
.span_direction
== -1:
1034 "dashed" : "dashed-line",
1035 "dotted" : "dotted-line",
1037 }. get (self
.line_type
, None)
1039 printer
.dump ("\\once \\override Glissando #'style = #'%s" % style
)
1040 def ly_expression (self
):
1041 return {-1: '\\glissando',
1042 1:''}.get (self
.span_direction
, '')
1044 class ArpeggioEvent(Event
):
1045 def __init__ (self
):
1046 Event
.__init
__ (self
)
1048 self
.non_arpeggiate
= False
1049 def wait_for_note (self
):
1051 def print_before_note (self
, printer
):
1052 if self
.non_arpeggiate
:
1053 printer
.dump ("\\arpeggioBracket")
1055 dir = { -1: "\\arpeggioArrowDown", 1: "\\arpeggioArrowUp" }.get (self
.direction
, '')
1058 def print_after_note (self
, printer
):
1059 if self
.non_arpeggiate
or self
.direction
:
1060 printer
.dump ("\\arpeggioNormal")
1061 def ly_expression (self
):
1062 return ('\\arpeggio')
1065 class TieEvent(Event
):
1066 def ly_expression (self
):
1070 class HairpinEvent (SpanEvent
):
1071 def set_span_type (self
, type):
1072 self
.span_type
= {'crescendo' : 1, 'decrescendo' : -1, 'diminuendo' : -1 }.get (type, 0)
1073 def hairpin_to_ly (self
):
1074 if self
.span_direction
== 1:
1077 return {1: '\<', -1: '\>'}.get (self
.span_type
, '')
1079 def ly_expression (self
):
1080 return self
.hairpin_to_ly ()
1082 def print_ly (self
, printer
):
1083 val
= self
.hairpin_to_ly ()
1089 class DynamicsEvent (Event
):
1090 def __init__ (self
):
1091 Event
.__init
__ (self
)
1093 def wait_for_note (self
):
1095 def ly_expression (self
):
1097 return '\%s' % self
.type
1101 def print_ly (self
, printer
):
1103 printer
.dump ("\\%s" % self
.type)
1105 class MarkEvent (Event
):
1106 def __init__ (self
, text
="\\default"):
1107 Event
.__init
__ (self
)
1109 def wait_for_note (self
):
1111 def ly_contents (self
):
1113 return '%s' % self
.mark
1116 def ly_expression (self
):
1117 return '\\mark %s' % self
.ly_contents ()
1119 class MusicGlyphMarkEvent (MarkEvent
):
1120 def ly_contents (self
):
1122 return '\\markup { \\musicglyph #"scripts.%s" }' % self
.mark
1127 class TextEvent (Event
):
1128 def __init__ (self
):
1129 Event
.__init
__ (self
)
1131 self
.force_direction
= None
1133 def wait_for_note (self
):
1136 def direction_mod (self
):
1137 return { 1: '^', -1: '_', 0: '-' }.get (self
.force_direction
, '-')
1139 def ly_expression (self
):
1140 base_string
= '%s\"%s\"'
1142 base_string
= '%s\markup{ ' + self
.markup
+ ' {%s} }'
1143 return base_string
% (self
.direction_mod (), self
.text
)
1145 class ArticulationEvent (Event
):
1146 def __init__ (self
):
1147 Event
.__init
__ (self
)
1149 self
.force_direction
= None
1150 def wait_for_note (self
):
1153 def direction_mod (self
):
1154 return { 1: '^', -1: '_', 0: '-' }.get (self
.force_direction
, '')
1156 def ly_expression (self
):
1157 return '%s\\%s' % (self
.direction_mod (), self
.type)
1159 class ShortArticulationEvent (ArticulationEvent
):
1160 def direction_mod (self
):
1162 return { 1: '^', -1: '_', 0: '-' }.get (self
.force_direction
, '-')
1163 def ly_expression (self
):
1165 return '%s%s' % (self
.direction_mod (), self
.type)
1169 class NoDirectionArticulationEvent (ArticulationEvent
):
1170 def ly_expression (self
):
1172 return '\\%s' % self
.type
1176 class MarkupEvent (ShortArticulationEvent
):
1177 def __init__ (self
):
1178 ArticulationEvent
.__init
__ (self
)
1179 self
.contents
= None
1180 def ly_expression (self
):
1182 return "%s\\markup { %s }" % (self
.direction_mod (), self
.contents
)
1186 class FretEvent (MarkupEvent
):
1187 def __init__ (self
):
1188 MarkupEvent
.__init
__ (self
)
1189 self
.force_direction
= 1
1194 def ly_expression (self
):
1196 if self
.strings
<> 6:
1197 val
+= "w:%s;" % self
.strings
1199 val
+= "h:%s;" % self
.frets
1200 if self
.barre
and len (self
.barre
) >= 3:
1201 val
+= "c:%s-%s-%s;" % (self
.barre
[0], self
.barre
[1], self
.barre
[2])
1202 have_fingering
= False
1203 for i
in self
.elements
:
1205 val
+= "%s-%s" % (i
[0], i
[1])
1207 have_fingering
= True
1213 return "%s\\markup { \\fret-diagram #\"%s\" }" % (self
.direction_mod (), val
)
1218 class FunctionWrapperEvent (Event
):
1219 def __init__ (self
, function_name
= None):
1220 Event
.__init
__ (self
)
1221 self
.function_name
= function_name
1222 def pre_note_ly (self
, is_chord_element
):
1223 if self
.function_name
:
1224 return "\\%s" % self
.function_name
1227 def pre_chord_ly (self
):
1229 def ly_expression (self
):
1230 if self
.function_name
:
1231 return "\\%s" % self
.function_name
1235 class ParenthesizeEvent (FunctionWrapperEvent
):
1236 def __init__ (self
):
1237 FunctionWrapperEvent
.__init
__ (self
, "parenthesize")
1239 class NotestyleEvent (Event
):
1240 def __init__ (self
):
1241 Event
.__init
__ (self
)
1244 def pre_chord_ly (self
):
1246 return "\\once \\override NoteHead #'style = #%s" % self
.style
1249 def pre_note_ly (self
, is_chord_element
):
1250 if self
.style
and is_chord_element
:
1251 return "\\tweak #'style #%s" % self
.style
1254 def ly_expression (self
):
1255 return self
.pre_chord_ly ()
1259 def __init__ (self
):
1263 return self
.ly_expression()
1264 def ly_expression (self
):
1265 return pitch_generating_function (self
)
1267 class ChordModification
:
1268 def __init__ (self
):
1272 def ly_expression (self
):
1274 val
= {1: ".", -1: "^" }.get (self
.type, "")
1275 val
+= "%s" % self
.step
1276 val
+= {1: "+", -1: "-"}.get (self
.alteration
, "")
1281 class ChordNameEvent (Event
):
1282 def __init__ (self
):
1283 Event
.__init
__ (self
)
1286 self
.duration
= None
1287 self
.modifications
= []
1289 def add_modification (self
, mod
):
1290 self
.modifications
.append (mod
)
1291 def ly_expression (self
):
1294 value
= self
.root
.ly_expression ()
1296 value
+= self
.duration
.ly_expression ()
1300 # First print all additions/changes, and only afterwards all subtractions
1301 for m
in self
.modifications
:
1303 value
+= m
.ly_expression ()
1304 for m
in self
.modifications
:
1306 value
+= m
.ly_expression ()
1308 value
+= "/+%s" % self
.bass
.ly_expression ()
1312 class TremoloEvent (ArticulationEvent
):
1313 def __init__ (self
):
1314 Event
.__init
__ (self
)
1317 def ly_expression (self
):
1319 if self
.bars
and self
.bars
> 0:
1320 str += ':%s' % (2 ** (2 + string
.atoi (self
.bars
)))
1323 class BendEvent (ArticulationEvent
):
1324 def __init__ (self
):
1325 Event
.__init
__ (self
)
1327 def ly_expression (self
):
1328 if self
.alter
!= None:
1329 return "-\\bendAfter #%s" % self
.alter
1333 class RhythmicEvent(Event
):
1334 def __init__ (self
):
1335 Event
.__init
__ (self
)
1336 self
.duration
= Duration()
1337 self
.associated_events
= []
1339 def add_associated_event (self
, ev
):
1341 self
.associated_events
.append (ev
)
1343 def pre_chord_ly (self
):
1344 return [ev
.pre_chord_ly () for ev
in self
.associated_events
]
1346 def pre_note_ly (self
, is_chord_element
):
1347 return [ev
.pre_note_ly (is_chord_element
) for ev
in self
.associated_events
]
1349 def ly_expression_pre_note (self
, is_chord_element
):
1350 res
= string
.join (self
.pre_note_ly (is_chord_element
), ' ')
1355 def get_length (self
):
1356 return self
.duration
.get_length()
1358 def get_properties (self
):
1359 return ("'duration %s"
1360 % self
.duration
.lisp_expression ())
1362 class RestEvent (RhythmicEvent
):
1363 def __init__ (self
):
1364 RhythmicEvent
.__init
__ (self
)
1367 def ly_expression (self
):
1368 res
= self
.ly_expression_pre_note (False)
1370 return res
+ "%s%s\\rest" % (self
.pitch
.ly_expression (), self
.duration
.ly_expression ())
1372 return 'r%s' % self
.duration
.ly_expression ()
1374 def print_ly (self
, printer
):
1375 for ev
in self
.associated_events
:
1376 ev
.print_ly (printer
)
1378 self
.pitch
.print_ly (printer
)
1379 self
.duration
.print_ly (printer
)
1383 self
.duration
.print_ly (printer
)
1385 class SkipEvent (RhythmicEvent
):
1386 def ly_expression (self
):
1387 return 's%s' % self
.duration
.ly_expression ()
1389 class NoteEvent(RhythmicEvent
):
1390 def __init__ (self
):
1391 RhythmicEvent
.__init
__ (self
)
1393 self
.drum_type
= None
1394 self
.cautionary
= False
1395 self
.forced_accidental
= False
1397 def get_properties (self
):
1398 str = RhythmicEvent
.get_properties (self
)
1401 str += self
.pitch
.lisp_expression ()
1402 elif self
.drum_type
:
1403 str += "'drum-type '%s" % self
.drum_type
1407 def pitch_mods (self
):
1410 excl_question
+= '?'
1411 if self
.forced_accidental
:
1412 excl_question
+= '!'
1414 return excl_question
1416 def ly_expression (self
):
1417 # obtain all stuff that needs to be printed before the note:
1418 res
= self
.ly_expression_pre_note (True)
1420 return res
+ '%s%s%s' % (self
.pitch
.ly_expression (),
1422 self
.duration
.ly_expression ())
1423 elif self
.drum_type
:
1424 return res
+ '%s%s' (self
.drum_type
,
1425 self
.duration
.ly_expression ())
1427 def chord_element_ly (self
):
1428 # obtain all stuff that needs to be printed before the note:
1429 res
= self
.ly_expression_pre_note (True)
1431 return res
+ '%s%s' % (self
.pitch
.ly_expression (),
1433 elif self
.drum_type
:
1434 return res
+ '%s%s' (self
.drum_type
)
1437 def print_ly (self
, printer
):
1438 for ev
in self
.associated_events
:
1439 ev
.print_ly (printer
)
1441 self
.pitch
.print_ly (printer
)
1442 printer (self
.pitch_mods ())
1444 printer (self
.drum_type
)
1446 self
.duration
.print_ly (printer
)
1448 class KeySignatureChange (Music
):
1449 def __init__ (self
):
1450 Music
.__init
__ (self
)
1453 self
.non_standard_alterations
= None
1455 def format_non_standard_alteration (self
, a
):
1456 alter_dict
= { -2: ",DOUBLE-FLAT",
1457 -1.5: ",THREE-Q-FLAT",
1463 1.5: ",THREE-Q-SHARP",
1466 accidental
= alter_dict
[a
[1]]
1468 warning (_ ("Unable to convert alteration %s to a lilypond expression") % a
[1])
1471 return "( %s . %s )" % (a
[0], accidental
)
1473 return "(( %s . %s ) . %s )" % (a
[2], a
[0], accidental
)
1477 def ly_expression (self
):
1479 return '\\key %s \\%s' % (self
.tonic
.ly_step_expression (),
1481 elif self
.non_standard_alterations
:
1482 alterations
= [self
.format_non_standard_alteration (a
) for
1483 a
in self
.non_standard_alterations
]
1484 return "\\set Staff.keySignature = #`(%s)" % string
.join (alterations
, " ")
1488 class TimeSignatureChange (Music
):
1489 def __init__ (self
):
1490 Music
.__init
__ (self
)
1491 self
.fractions
= [4,4]
1493 def format_fraction (self
, frac
):
1494 if isinstance (frac
, list):
1495 l
= [self
.format_fraction (f
) for f
in frac
]
1496 return "(" + string
.join (l
, " ") + ")"
1500 def ly_expression (self
):
1502 # Print out the style if we have ome, but the '() should only be
1503 # forced for 2/2 or 4/4, since in all other cases we'll get numeric
1504 # signatures anyway despite the default 'C signature style!
1505 is_common_signature
= self
.fractions
in ([2,2], [4,4], [4,2])
1507 if self
.style
== "common":
1508 st
= "\\defaultTimeSignature"
1509 elif (self
.style
!= "'()"):
1510 st
= "\\once \\override Staff.TimeSignature #'style = #%s " % self
.style
1511 elif (self
.style
!= "'()") or is_common_signature
:
1512 st
= "\\numericTimeSignature"
1514 # Easy case: self.fractions = [n,d] => normal \time n/d call:
1515 if len (self
.fractions
) == 2 and isinstance (self
.fractions
[0], int):
1516 return st
+ '\\time %d/%d ' % tuple (self
.fractions
)
1517 elif self
.fractions
:
1518 return st
+ "\\compoundMeter #'%s" % self
.format_fraction (self
.fractions
)
1522 class ClefChange (Music
):
1523 def __init__ (self
):
1524 Music
.__init
__ (self
)
1529 def octave_modifier (self
):
1530 return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self
.octave
, '')
1531 def clef_name (self
):
1532 return {('G', 2): "treble",
1534 ('C', 1): "soprano",
1535 ('C', 2): "mezzosoprano",
1538 ('C', 5): "baritone",
1539 ('F', 3): "varbaritone",
1541 ('F', 5): "subbass",
1542 ("percussion", 2): "percussion",
1543 # Workaround: MuseScore uses PERC instead of percussion
1544 ("PERC", 2): "percussion",
1545 ("TAB", 5): "tab"}.get ((self
.type, self
.position
), None)
1546 def ly_expression (self
):
1547 return '\\clef "%s%s"' % (self
.clef_name (), self
.octave_modifier ())
1550 "G": ("clefs.G", -2, -6),
1551 "C": ("clefs.C", 0, 0),
1552 "F": ("clefs.F", 2, 6),
1555 def lisp_expression (self
):
1557 (glyph
, pos
, c0
) = self
.clef_dict
[self
.type]
1561 (make-music 'SequentialMusic
1564 (make-property-set 'clefGlyph "%s") 'Staff)
1566 (make-property-set 'clefPosition %d) 'Staff)
1568 (make-property-set 'middleCPosition %d) 'Staff)))
1569 """ % (glyph
, pos
, c0
)
1572 class Transposition (Music
):
1573 def __init__ (self
):
1574 Music
.__init
__ (self
)
1576 def ly_expression (self
):
1577 self
.pitch
._force
_absolute
_pitch
= True
1578 return '\\transposition %s' % self
.pitch
.ly_expression ()
1580 class StaffChange (Music
):
1581 def __init__ (self
, staff
):
1582 Music
.__init
__ (self
)
1584 def ly_expression (self
):
1586 return "\\change Staff=\"%s\"" % self
.staff
1590 class SetEvent (Music
):
1591 def __init__ (self
, contextprop
, value
):
1592 Music
.__init
__ (self
)
1593 self
.context_prop
= contextprop
1595 def ly_expression (self
):
1597 return "\\set %s = %s" % (self
.context_prop
, self
.value
)
1601 class StaffLinesEvent (Music
):
1602 def __init__ (self
, lines
):
1603 Music
.__init
__ (self
)
1605 def ly_expression (self
):
1606 if (self
.lines
> 0):
1607 return "\\stopStaff \\override Staff.StaffSymbol #'line-count = #%s \\startStaff" % self
.lines
1609 return "\\stopStaff \\revert Staff.StaffSymbol #'line-count \\startStaff"
1611 class TempoMark (Music
):
1612 def __init__ (self
):
1613 Music
.__init
__ (self
)
1614 self
.baseduration
= None
1615 self
.newduration
= None
1617 self
.parentheses
= False
1618 def set_base_duration (self
, dur
):
1619 self
.baseduration
= dur
1620 def set_new_duration (self
, dur
):
1621 self
.newduration
= dur
1622 def set_beats_per_minute (self
, beats
):
1624 def set_parentheses (self
, parentheses
):
1625 self
.parentheses
= parentheses
1626 def wait_for_note (self
):
1628 def duration_to_markup (self
, dur
):
1630 # Generate the markup to print the note, use scheme mode for
1631 # ly_expression to get longa and not \longa (which causes an error)
1632 return "\\general-align #Y #DOWN \\smaller \\note #\"%s\" #UP" % dur
.ly_expression(None, True)
1635 def tempo_markup_template (self
):
1636 return "\\mark\\markup { \\fontsize #-2 \\line { %s } }"
1637 def ly_expression (self
):
1639 if not self
.baseduration
:
1642 if self
.parentheses
:
1643 res
+= "\\tempo \"\" %s=%s" % (self
.baseduration
.ly_expression(), self
.beats
)
1645 res
+= "\\tempo %s=%s" % (self
.baseduration
.ly_expression(), self
.beats
)
1646 elif self
.newduration
:
1647 dm
= self
.duration_to_markup (self
.baseduration
)
1648 ndm
= self
.duration_to_markup (self
.newduration
)
1649 if self
.parentheses
:
1650 contents
= "\"(\" %s = %s \")\"" % (dm
, ndm
)
1652 contents
= " %s = %s " % (dm
, ndm
)
1653 res
+= self
.tempo_markup_template() % contents
1658 class FiguredBassNote (Music
):
1659 def __init__ (self
):
1660 Music
.__init
__ (self
)
1664 def set_prefix (self
, prefix
):
1665 self
.prefix
= prefix
1666 def set_suffix (self
, suffix
):
1667 self
.prefix
= suffix
1668 def set_number (self
, number
):
1669 self
.number
= number
1670 def ly_expression (self
):
1683 class FiguredBassEvent (NestedMusic
):
1684 def __init__ (self
):
1685 NestedMusic
.__init
__ (self
)
1686 self
.duration
= None
1687 self
.real_duration
= 0
1688 self
.parentheses
= False
1690 def set_duration (self
, dur
):
1692 def set_parentheses (self
, par
):
1693 self
.parentheses
= par
1694 def set_real_duration (self
, dur
):
1695 self
.real_duration
= dur
1697 def print_ly (self
, printer
):
1698 figured_bass_events
= [e
for e
in self
.elements
if
1699 isinstance (e
, FiguredBassNote
)]
1700 if figured_bass_events
:
1702 for x
in figured_bass_events
:
1703 notes
.append (x
.ly_expression ())
1704 contents
= string
.join (notes
)
1705 if self
.parentheses
:
1706 contents
= '[%s]' % contents
1707 printer ('<%s>' % contents
)
1708 self
.duration
.print_ly (printer
)
1711 class MultiMeasureRest(Music
):
1713 def lisp_expression (self
):
1716 'MultiMeasureRestMusicGroup
1718 (list (make-music (quote BarCheck))
1723 'MultiMeasureRestEvent
1726 (make-music (quote BarCheck))))
1727 """ % self
.duration
.lisp_expression ()
1729 def ly_expression (self
):
1730 return 'R%s' % self
.duration
.ly_expression ()
1733 class Break (Music
):
1734 def __init__ (self
, tp
="break"):
1735 Music
.__init
__ (self
)
1737 def print_ly (self
, printer
):
1739 printer
.dump ("\\%s" % self
.type)
1742 def __init__ (self
, command
= "StaffGroup"):
1743 self
.stafftype
= command
1745 self
.instrument_name
= None
1746 self
.short_instrument_name
= None
1750 self
.is_group
= True
1751 self
.context_modifications
= []
1752 # part_information is a list with entries of the form
1753 # [staffid, voicelist]
1754 # where voicelist is a list with entries of the form
1755 # [voiceid1, [lyricsid11, lyricsid12,...] ]
1756 self
.part_information
= None
1758 def append_staff (self
, staff
):
1759 self
.children
.append (staff
)
1761 def set_part_information (self
, part_name
, staves_info
):
1762 if part_name
== self
.id:
1763 self
.part_information
= staves_info
1765 for c
in self
.children
:
1766 c
.set_part_information (part_name
, staves_info
)
1768 def add_context_modification (self
, modification
):
1769 self
.context_modifications
.append (modification
)
1771 def print_ly_contents (self
, printer
):
1772 for c
in self
.children
:
1774 c
.print_ly (printer
)
1775 def needs_with (self
):
1777 needs_with |
= self
.spanbar
== "no"
1778 needs_with |
= self
.instrument_name
!= None
1779 needs_with |
= self
.short_instrument_name
!= None
1780 needs_with |
= (self
.symbol
!= None) and (self
.symbol
!= "bracket")
1782 def print_ly_context_mods (self
, printer
):
1783 if self
.instrument_name
or self
.short_instrument_name
:
1784 printer
.dump ("\\consists \"Instrument_name_engraver\"")
1785 if self
.spanbar
== "no":
1786 printer
.dump ("\\override SpanBar #'transparent = ##t")
1787 brack
= {"brace": "SystemStartBrace",
1789 "line": "SystemStartSquare"}.get (self
.symbol
, None)
1791 printer
.dump ("systemStartDelimiter = #'%s" % brack
)
1793 def print_ly_overrides (self
, printer
):
1794 needs_with
= self
.needs_with () |
(len (self
.context_modifications
) > 0);
1796 printer
.dump ("\\with {")
1797 self
.print_ly_context_mods (printer
)
1798 for m
in self
.context_modifications
:
1802 def print_ly (self
, printer
):
1804 printer
.dump ("\\new %s" % self
.stafftype
)
1805 self
.print_ly_overrides (printer
)
1808 if self
.stafftype
and self
.instrument_name
:
1809 printer
.dump ("\\set %s.instrumentName = %s" % (self
.stafftype
,
1810 escape_instrument_string (self
.instrument_name
)))
1812 if self
.stafftype
and self
.short_instrument_name
:
1813 printer
.dump ("\\set %s.shortInstrumentName = %s" % (self
.stafftype
,
1814 escape_instrument_string (self
.short_instrument_name
)))
1816 self
.print_ly_contents (printer
)
1822 class Staff (StaffGroup
):
1823 def __init__ (self
, command
= "Staff"):
1824 StaffGroup
.__init
__ (self
, command
)
1825 self
.is_group
= False
1827 self
.voice_command
= "Voice"
1828 self
.substafftype
= None
1830 def needs_with (self
):
1832 def print_ly_context_mods (self
, printer
):
1835 def print_ly_contents (self
, printer
):
1836 if not self
.id or not self
.part_information
:
1838 sub_staff_type
= self
.substafftype
1839 if not sub_staff_type
:
1840 sub_staff_type
= self
.stafftype
1842 for [staff_id
, voices
] in self
.part_information
:
1843 # Chord names need to come before the staff itself!
1844 for [v
, lyrics
, figuredbass
, chordnames
] in voices
:
1846 printer ('\context ChordNames = "%s" \\%s' % (chordnames
, chordnames
))
1848 # now comes the real staff definition:
1850 printer ('\\context %s = "%s" << ' % (sub_staff_type
, staff_id
))
1852 printer ('\\context %s << ' % sub_staff_type
)
1855 nr_voices
= len (voices
)
1856 for [v
, lyrics
, figuredbass
, chordnames
] in voices
:
1858 voice_count_text
= ''
1860 voice_count_text
= {1: ' \\voiceOne', 2: ' \\voiceTwo',
1861 3: ' \\voiceThree'}.get (n
, ' \\voiceFour')
1862 printer ('\\context %s = "%s" {%s \\%s }' % (self
.voice_command
, v
, voice_count_text
, v
))
1866 printer ('\\new Lyrics \\lyricsto "%s" \\%s' % (v
,l
))
1869 printer ('\context FiguredBass = "%s" \\%s' % (figuredbass
, figuredbass
))
1872 def print_ly (self
, printer
):
1873 if self
.part_information
and len (self
.part_information
) > 1:
1874 self
.stafftype
= "PianoStaff"
1875 self
.substafftype
= "Staff"
1876 StaffGroup
.print_ly (self
, printer
)
1878 class TabStaff (Staff
):
1879 def __init__ (self
, command
= "TabStaff"):
1880 Staff
.__init
__ (self
, command
)
1881 self
.string_tunings
= []
1882 self
.tablature_format
= None
1883 self
.voice_command
= "TabVoice"
1884 def print_ly_overrides (self
, printer
):
1885 if self
.string_tunings
or self
.tablature_format
:
1886 printer
.dump ("\\with {")
1887 if self
.string_tunings
:
1888 printer
.dump ("stringTunings = #'(")
1889 for i
in self
.string_tunings
:
1890 printer
.dump ("%s" % i
.semitones ())
1892 if self
.tablature_format
:
1893 printer
.dump ("tablatureFormat = #%s" % self
.tablature_format
)
1897 class DrumStaff (Staff
):
1898 def __init__ (self
, command
= "DrumStaff"):
1899 Staff
.__init
__ (self
, command
)
1900 self
.drum_style_table
= None
1901 self
.voice_command
= "DrumVoice"
1902 def print_ly_overrides (self
, printer
):
1903 if self
.drum_style_table
:
1904 printer
.dump ("\with {")
1905 printer
.dump ("drumStyleTable = #%s" % self
.drum_style_table
)
1908 class RhythmicStaff (Staff
):
1909 def __init__ (self
, command
= "RhythmicStaff"):
1910 Staff
.__init
__ (self
, command
)
1913 def __init__ (self
):
1914 self
.contents
= None
1915 self
.create_midi
= False
1917 def set_contents (self
, contents
):
1918 self
.contents
= contents
1920 def set_part_information (self
, part_id
, staves_info
):
1922 self
.contents
.set_part_information (part_id
, staves_info
)
1924 def print_ly (self
, printer
):
1925 printer
.dump ("\\score {");
1928 self
.contents
.print_ly (printer
);
1929 printer
.dump ("\\layout {}");
1931 if not self
.create_midi
:
1932 printer
.dump ("% To create MIDI output, uncomment the following line:");
1934 printer
.dump ("% ");
1935 printer
.dump ("\\midi {}");
1943 bflat
.alteration
= -1
1953 print bflat
.semitones()
1954 print bflat
.transposed (fifth
), bflat
.transposed (fifth
).transposed (fifth
)
1955 print bflat
.transposed (fifth
).transposed (fifth
).transposed (fifth
)
1957 print bflat
.semitones(), 'down'
1958 print bflat
.transposed (down
)
1959 print bflat
.transposed (down
).transposed (down
)
1960 print bflat
.transposed (down
).transposed (down
).transposed (down
)
1964 def test_printer ():
1972 m
= SequentialMusic()
1973 m
.append (make_note ())
1974 m
.append (make_note ())
1975 m
.append (make_note ())
1978 t
= TimeScaledMusic ()
1984 m
= SequentialMusic ()
1985 m
.append (make_tup ())
1986 m
.append (make_tup ())
1987 m
.append (make_tup ())
1989 printer
= Output_printer()
1990 m
.print_ly (printer
)
1994 m
= SequentialMusic()
1998 n
.duration
.duration_log
= l
2000 evc
.insert_around (None, n
, 0)
2001 m
.insert_around (None, evc
, 0)
2005 n
.duration
.duration_log
= l
2007 evc
.insert_around (None, n
, 0)
2008 m
.insert_around (None, evc
, 0)
2012 n
.duration
.duration_log
= l
2014 evc
.insert_around (None, n
, 0)
2015 m
.insert_around (None, evc
, 0)
2019 m
.insert_around (None, evc
, 0)
2024 tonic
.alteration
= -2
2025 n
= KeySignatureChange()
2026 n
.tonic
=tonic
.copy()
2027 n
.scale
= [0, 0, -2, 0, 0,-2,-2]
2029 evc
.insert_around (None, n
, 0)
2030 m
.insert_around (None, evc
, 0)
2035 if __name__
== '__main__':
2041 expr
.set_start (Rational (0))
2042 print expr
.ly_expression()
2043 start
= Rational (0,4)
2044 stop
= Rational (4,2)
2045 def sub(x
, start
=start
, stop
=stop
):
2046 ok
= x
.start
>= start
and x
.start
+x
.get_length() <= stop
2049 print expr
.lisp_sub_expression(sub
)