9 from rational
import Rational
11 # Store previously converted pitch for \relative conversion as a global state variable
13 relative_pitches
= False
16 ly
.stderr_write ((_ ("warning: %s") % str) + "\n")
19 def escape_instrument_string (input_string
):
20 retstring
= string
.replace (input_string
, "\"", "\\\"")
21 if re
.match ('.*[\r\n]+.*', retstring
):
22 rx
= re
.compile (r
'[\n\r]+')
23 strings
= rx
.split (retstring
)
24 retstring
= "\\markup { \\column { "
26 retstring
+= "\\line {\"" + s
+ "\"} "
29 retstring
= "\"" + retstring
+ "\""
32 class Output_stack_element
:
34 self
.factor
= Rational (1)
36 o
= Output_stack_element()
37 o
.factor
= self
.factor
42 """A class that takes care of formatting (eg.: indenting) a
43 Music expression as a .ly file.
51 self
._file
= sys
.stdout
53 self
._output
_state
_stack
= [Output_stack_element()]
54 self
._skipspace
= False
55 self
._last
_duration
= None
57 def set_file (self
, file):
60 def dump_version (self
):
62 self
.print_verbatim ('\\version "@TOPLEVEL_VERSION@"')
65 def get_indent (self
):
66 return self
._nesting
* self
._indent
69 last
= self
._output
_state
_stack
[-1]
70 self
._output
_state
_stack
.append (last
.copy())
72 def add_factor (self
, factor
):
74 self
._output
_state
_stack
[-1].factor
*= factor
77 del self
._output
_state
_stack
[-1]
78 if not self
._output
_state
_stack
:
81 def duration_factor (self
):
82 return self
._output
_state
_stack
[-1].factor
84 def print_verbatim (self
, str):
87 def unformatted_output (self
, str):
88 # don't indent on \< and indent only once on <<
89 self
._nesting
+= ( str.count ('<')
90 - str.count ('\<') - str.count ('<<')
92 self
._nesting
-= ( str.count ('>') - str.count ('\>') - str.count ('>>')
93 - str.count ('->') - str.count ('_>')
96 self
.print_verbatim (str)
98 def print_duration_string (self
, str):
99 if self
._last
_duration
== str:
102 self
.unformatted_output (str)
104 def add_word (self
, str):
105 if (len (str) + 1 + len (self
._line
) > self
._line
_len
):
107 self
._skipspace
= True
109 if not self
._skipspace
:
111 self
.unformatted_output (str)
112 self
._skipspace
= False
115 self
._file
.write (self
._line
+ '\n')
116 self
._line
= ' ' * self
._indent
* self
._nesting
117 self
._skipspace
= True
119 def skipspace (self
):
120 self
._skipspace
= True
122 def __call__(self
, arg
):
125 def dump (self
, str):
127 self
._skipspace
= False
128 self
.unformatted_output (str)
130 words
= string
.split (str)
143 self
.duration_log
= 0
145 self
.factor
= Rational (1)
147 def lisp_expression (self
):
148 return '(ly:make-duration %d %d %d %d)' % (self
.duration_log
,
150 self
.factor
.numerator (),
151 self
.factor
.denominator ())
154 def ly_expression (self
, factor
= None, scheme_mode
= False):
158 if self
.duration_log
< 0:
160 longer_dict
= {-1: "breve", -2: "longa"}
162 longer_dict
= {-1: "\\breve", -2: "\\longa"}
163 str = longer_dict
.get (self
.duration_log
, "1")
165 str = '%d' % (1 << self
.duration_log
)
168 if factor
<> Rational (1,1):
169 if factor
.denominator () <> 1:
170 str += '*%d/%d' % (factor
.numerator (), factor
.denominator ())
172 str += '*%d' % factor
.numerator ()
176 def print_ly (self
, outputter
):
177 str = self
.ly_expression (self
.factor
/ outputter
.duration_factor ())
178 outputter
.print_duration_string (str)
181 return self
.ly_expression()
186 d
.duration_log
= self
.duration_log
187 d
.factor
= self
.factor
190 def get_length (self
):
191 dot_fact
= Rational( (1 << (1 + self
.dots
))-1,
194 log
= abs (self
.duration_log
)
196 if self
.duration_log
< 0:
197 base
= Rational (dur
)
199 base
= Rational (1, dur
)
201 return base
* dot_fact
* self
.factor
204 # Implement the different note names for the various languages
205 def pitch_generic (pitch
, notenames
, accidentals
):
206 str = notenames
[pitch
.step
]
207 halftones
= int (pitch
.alteration
)
209 str += accidentals
[0] * (-halftones
)
210 elif pitch
.alteration
> 0:
211 str += accidentals
[3] * (halftones
)
212 # Handle remaining fraction to pitch.alteration (for microtones)
213 if (halftones
!= pitch
.alteration
):
214 if None in accidentals
[1:3]:
215 warning (_ ("Language does not support microtones contained in the piece"))
218 str += {-0.5: accidentals
[1], 0.5: accidentals
[2]}[pitch
.alteration
-halftones
]
220 warning (_ ("Language does not support microtones contained in the piece"))
223 def pitch_general (pitch
):
224 str = pitch_generic (pitch
, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['es', 'eh', 'ih', 'is'])
225 return str.replace ('aes', 'as').replace ('ees', 'es')
227 def pitch_nederlands (pitch
):
228 return pitch_general (pitch
)
230 def pitch_english (pitch
):
231 str = pitch_generic (pitch
, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['f', 'qf', 'qs', 's'])
232 return str.replace ('aes', 'as').replace ('ees', 'es')
234 def pitch_deutsch (pitch
):
235 str = pitch_generic (pitch
, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['es', 'eh', 'ih', 'is'])
236 return str.replace ('hes', 'b').replace ('aes', 'as').replace ('ees', 'es')
238 def pitch_norsk (pitch
):
239 return pitch_deutsch (pitch
)
241 def pitch_svenska (pitch
):
242 str = pitch_generic (pitch
, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', None, None, 'iss'])
243 return str.replace ('hess', 'b').replace ('aes', 'as').replace ('ees', 'es')
245 def pitch_italiano (pitch
):
246 str = pitch_generic (pitch
, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', 'sb', 'sd', 'd'])
249 def pitch_catalan (pitch
):
250 return pitch_italiano (pitch
)
252 def pitch_espanol (pitch
):
253 str = pitch_generic (pitch
, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 's'])
256 def pitch_vlaams (pitch
):
257 str = pitch_generic (pitch
, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 'k'])
260 def set_pitch_language (language
):
261 global pitch_generating_function
263 "nederlands": pitch_nederlands
,
264 "english": pitch_english
,
265 "deutsch": pitch_deutsch
,
266 "norsk": pitch_norsk
,
267 "svenska": pitch_svenska
,
268 "italiano": pitch_italiano
,
269 "catalan": pitch_catalan
,
270 "espanol": pitch_espanol
,
271 "vlaams": pitch_vlaams
}
272 pitch_generating_function
= function_dict
.get (language
, pitch_general
)
274 # global variable to hold the formatting function.
275 pitch_generating_function
= pitch_general
283 self
._force
_absolute
_pitch
= False
286 return self
.ly_expression()
288 def transposed (self
, interval
):
290 c
.alteration
+= interval
.alteration
291 c
.step
+= interval
.step
292 c
.octave
+= interval
.octave
295 target_st
= self
.semitones() + interval
.semitones()
296 c
.alteration
+= target_st
- c
.semitones()
303 c
.octave
+= c
.step
/ 7
306 def lisp_expression (self
):
307 return '(ly:make-pitch %d %d %d)' % (self
.octave
,
313 p
.alteration
= self
.alteration
315 p
.octave
= self
.octave
319 return self
.step
+ self
.octave
*7
321 def semitones (self
):
322 return self
.octave
* 12 + [0,2,4,5,7,9,11][self
.step
] + self
.alteration
324 def ly_step_expression (self
):
325 return pitch_generating_function (self
)
327 def absolute_pitch (self
):
329 return "'" * (self
.octave
+ 1)
330 elif self
.octave
< -1:
331 return "," * (-self
.octave
- 1)
335 def relative_pitch (self
):
336 global previous_pitch
337 if not previous_pitch
:
338 previous_pitch
= self
339 return self
.absolute_pitch ()
340 previous_pitch_steps
= previous_pitch
.octave
* 7 + previous_pitch
.step
341 this_pitch_steps
= self
.octave
* 7 + self
.step
342 pitch_diff
= (this_pitch_steps
- previous_pitch_steps
)
343 previous_pitch
= self
345 return "'" * ((pitch_diff
+ 3) / 7)
346 elif pitch_diff
< -3:
347 return "," * ((-pitch_diff
+ 3) / 7)
351 def ly_expression (self
):
352 str = self
.ly_step_expression ()
353 if relative_pitches
and not self
._force
_absolute
_pitch
:
354 str += self
.relative_pitch ()
356 str += self
.absolute_pitch ()
360 def print_ly (self
, outputter
):
361 outputter (self
.ly_expression())
366 self
.start
= Rational (0)
368 self
.identifier
= None
370 def get_length(self
):
373 def get_properties (self
):
376 def has_children (self
):
379 def get_index (self
):
381 return self
.parent
.elements
.index (self
)
385 return self
.__class
__.__name
__
387 def lisp_expression (self
):
390 props
= self
.get_properties ()
392 return "(make-music '%s %s)" % (name
, props
)
394 def set_start (self
, start
):
397 def find_first (self
, predicate
):
402 def print_comment (self
, printer
, text
= None):
413 lines
= string
.split (text
, '\n')
416 printer
.unformatted_output ('% ' + l
)
420 def print_with_identifier (self
, printer
):
422 printer ("\\%s" % self
.identifier
)
424 self
.print_ly (printer
)
426 def print_ly (self
, printer
):
427 printer (self
.ly_expression ())
429 class MusicWrapper (Music
):
433 def print_ly (self
, func
):
434 self
.element
.print_ly (func
)
436 class ModeChangingMusicWrapper (MusicWrapper
):
438 MusicWrapper
.__init
__ (self
)
439 self
.mode
= 'notemode'
441 def print_ly (self
, func
):
442 func ('\\%s' % self
.mode
)
443 MusicWrapper
.print_ly (self
, func
)
445 class RelativeMusic (MusicWrapper
):
447 MusicWrapper
.__init
__ (self
)
448 self
.basepitch
= None
450 def print_ly (self
, func
):
451 global previous_pitch
452 global relative_pitches
453 prev_relative_pitches
= relative_pitches
454 relative_pitches
= True
455 previous_pitch
= self
.basepitch
456 if not previous_pitch
:
457 previous_pitch
= Pitch ()
458 func ('\\relative %s%s' % (pitch_generating_function (previous_pitch
),
459 previous_pitch
.absolute_pitch ()))
460 MusicWrapper
.print_ly (self
, func
)
461 relative_pitches
= prev_relative_pitches
463 class TimeScaledMusic (MusicWrapper
):
465 MusicWrapper
.__init
__ (self
)
468 self
.display_number
= "actual" # valid values "actual" | "both" | None
469 # Display the basic note length for the tuplet:
470 self
.display_type
= None # value values "actual" | "both" | None
471 self
.display_bracket
= "bracket" # valid values "bracket" | "curved" | None
472 self
.actual_type
= None # The actually played unit of the scaling
473 self
.normal_type
= None # The basic unit of the scaling
474 self
.display_numerator
= None
475 self
.display_denominator
= None
477 def print_ly (self
, func
):
478 if self
.display_bracket
== None:
479 func ("\\once \\override TupletBracket #'stencil = ##f")
481 elif self
.display_bracket
== "curved":
482 warning (_ ("Tuplet brackets of curved shape are not correctly implemented"))
483 func ("\\once \\override TupletBracket #'stencil = #ly:slur::print")
486 base_number_function
= {None: "#f",
487 "actual": "tuplet-number::calc-denominator-text",
488 "both": "tuplet-number::calc-fraction-text"}.get (self
.display_number
, None)
489 # If we have non-standard numerator/denominator, use our custom function
490 if self
.display_number
== "actual" and self
.display_denominator
:
491 base_number_function
= "(tuplet-number::non-default-tuplet-denominator-text %s)" % self
.display_denominator
492 elif self
.display_number
== "both" and (self
.display_denominator
or self
.display_numerator
):
493 if self
.display_numerator
:
494 num
= self
.display_numerator
497 if self
.display_denominator
:
498 den
= self
.display_denominator
501 base_number_function
= "(tuplet-number::non-default-tuplet-fraction-text %s %s)" % (den
, num
)
504 if self
.display_type
== "actual" and self
.normal_type
:
505 # Obtain the note duration in scheme-mode, i.e. \longa as \\longa
506 base_duration
= self
.normal_type
.ly_expression (None, True)
507 func ("\\once \\override TupletNumber #'text = #(tuplet-number::append-note-wrapper %s \"%s\")" %
508 (base_number_function
, base_duration
))
510 elif self
.display_type
== "both": # TODO: Implement this using actual_type and normal_type!
511 warning (_ ("Tuplet brackets displaying both note durations are not implemented, using default"))
512 if self
.display_number
== None:
513 func ("\\once \\override TupletNumber #'stencil = ##f")
515 elif self
.display_number
== "both":
516 func ("\\once \\override TupletNumber #'text = #%s" % base_number_function
)
519 if self
.display_number
== None:
520 func ("\\once \\override TupletNumber #'stencil = ##f")
522 elif self
.display_number
== "both":
523 func ("\\once \\override TupletNumber #'text = #%s" % base_number_function
)
526 func ('\\times %d/%d ' %
527 (self
.numerator
, self
.denominator
))
528 func
.add_factor (Rational (self
.numerator
, self
.denominator
))
529 MusicWrapper
.print_ly (self
, func
)
532 class NestedMusic(Music
):
534 Music
.__init
__ (self
)
537 def append (self
, what
):
539 self
.elements
.append (what
)
541 def has_children (self
):
544 def insert_around (self
, succ
, elt
, dir):
545 assert elt
.parent
== None
546 assert succ
== None or succ
in self
.elements
551 idx
= self
.elements
.index (succ
)
558 idx
= len (self
.elements
)
560 self
.elements
.insert (idx
, elt
)
563 def get_properties (self
):
564 return ("'elements (list %s)"
565 % string
.join (map (lambda x
: x
.lisp_expression(),
568 def get_subset_properties (self
, predicate
):
569 return ("'elements (list %s)"
570 % string
.join (map (lambda x
: x
.lisp_expression(),
571 filter ( predicate
, self
.elements
))))
572 def get_neighbor (self
, music
, dir):
573 assert music
.parent
== self
574 idx
= self
.elements
.index (music
)
576 idx
= min (idx
, len (self
.elements
) -1)
579 return self
.elements
[idx
]
581 def delete_element (self
, element
):
582 assert element
in self
.elements
584 self
.elements
.remove (element
)
585 element
.parent
= None
587 def set_start (self
, start
):
589 for e
in self
.elements
:
592 def find_first (self
, predicate
):
593 r
= Music
.find_first (self
, predicate
)
597 for e
in self
.elements
:
598 r
= e
.find_first (predicate
)
603 class SequentialMusic (NestedMusic
):
604 def get_last_event_chord (self
):
606 at
= len( self
.elements
) - 1
608 not isinstance (self
.elements
[at
], ChordEvent
) and
609 not isinstance (self
.elements
[at
], BarLine
)):
612 if (at
>= 0 and isinstance (self
.elements
[at
], ChordEvent
)):
613 value
= self
.elements
[at
]
616 def print_ly (self
, printer
, newline
= True):
619 self
.print_comment (printer
)
623 for e
in self
.elements
:
630 def lisp_sub_expression (self
, pred
):
634 props
= self
.get_subset_properties (pred
)
636 return "(make-music '%s %s)" % (name
, props
)
638 def set_start (self
, start
):
639 for e
in self
.elements
:
641 start
+= e
.get_length()
645 self
.repeat_type
= "volta"
646 self
.repeat_count
= 2
649 def set_music (self
, music
):
650 if isinstance (music
, Music
):
652 elif isinstance (music
, list):
653 self
.music
= SequentialMusic ()
654 self
.music
.elements
= music
656 warning (_ ("unable to set the music %(music)s for the repeat %(repeat)s") % \
657 {'music':music
, 'repeat':self
})
658 def add_ending (self
, music
):
659 self
.endings
.append (music
)
660 def print_ly (self
, printer
):
661 printer
.dump ('\\repeat %s %s' % (self
.repeat_type
, self
.repeat_count
))
663 self
.music
.print_ly (printer
)
665 warning (_ ("encountered repeat without body"))
668 printer
.dump ('\\alternative {')
669 for e
in self
.endings
:
676 self
.lyrics_syllables
= []
678 def print_ly (self
, printer
):
679 printer
.dump ("\lyricmode {")
680 for l
in self
.lyrics_syllables
:
681 printer
.dump ( "%s " % l
)
684 def ly_expression (self
):
685 lstr
= "\lyricmode {\n "
686 for l
in self
.lyrics_syllables
:
694 self
.header_fields
= {}
695 def set_field (self
, field
, value
):
696 self
.header_fields
[field
] = value
698 def print_ly (self
, printer
):
699 printer
.dump ("\header {")
701 for (k
,v
) in self
.header_fields
.items ():
703 printer
.dump ('%s = %s' % (k
,v
))
712 self
.global_staff_size
= -1
715 self
.page_height
= -1
718 self
.bottom_margin
= -1
719 self
.left_margin
= -1
720 self
.right_margin
= -1
721 self
.system_left_margin
= -1
722 self
.system_right_margin
= -1
723 self
.system_distance
= -1
724 self
.top_system_distance
= -1
726 def print_length_field (self
, printer
, field
, value
):
728 printer
.dump ("%s = %s\\cm" % (field
, value
))
730 def print_ly (self
, printer
):
731 if self
.global_staff_size
> 0:
732 printer
.dump ('#(set-global-staff-size %s)' % self
.global_staff_size
)
734 printer
.dump ('\\paper {')
736 self
.print_length_field (printer
, "paper-width", self
.page_width
)
737 self
.print_length_field (printer
, "paper-height", self
.page_height
)
738 self
.print_length_field (printer
, "top-margin", self
.top_margin
)
739 self
.print_length_field (printer
, "botton-margin", self
.bottom_margin
)
740 self
.print_length_field (printer
, "left-margin", self
.left_margin
)
741 # TODO: maybe set line-width instead of right-margin?
742 self
.print_length_field (printer
, "right-margin", self
.right_margin
)
743 # TODO: What's the corresponding setting for system_left_margin and
744 # system_right_margin in Lilypond?
745 self
.print_length_field (printer
, "between-system-space", self
.system_distance
)
746 self
.print_length_field (printer
, "page-top-space", self
.top_system_distance
)
753 self
.context_dict
= {}
754 def add_context (self
, context
):
755 if not self
.context_dict
.has_key (context
):
756 self
.context_dict
[context
] = []
757 def set_context_item (self
, context
, item
):
758 self
.add_context (context
)
759 if not item
in self
.context_dict
[context
]:
760 self
.context_dict
[context
].append (item
)
761 def print_ly (self
, printer
):
762 if self
.context_dict
.items ():
763 printer
.dump ('\\layout {')
765 for (context
, defs
) in self
.context_dict
.items ():
766 printer
.dump ('\\context { \\%s' % context
)
777 class ChordEvent (NestedMusic
):
779 NestedMusic
.__init
__ (self
)
780 self
.after_grace_elements
= None
781 self
.grace_elements
= None
782 self
.grace_type
= None
783 def append_grace (self
, element
):
785 if not self
.grace_elements
:
786 self
.grace_elements
= SequentialMusic ()
787 self
.grace_elements
.append (element
)
788 def append_after_grace (self
, element
):
790 if not self
.after_grace_elements
:
791 self
.after_grace_elements
= SequentialMusic ()
792 self
.after_grace_elements
.append (element
)
794 def has_elements (self
):
795 return [e
for e
in self
.elements
if
796 isinstance (e
, NoteEvent
) or isinstance (e
, RestEvent
)] != []
799 def get_length (self
):
801 for e
in self
.elements
:
802 l
= max(l
, e
.get_length())
805 def get_duration (self
):
806 note_events
= [e
for e
in self
.elements
if
807 isinstance (e
, NoteEvent
) or isinstance (e
, RestEvent
)]
809 return note_events
[0].duration
813 def print_ly (self
, printer
):
814 note_events
= [e
for e
in self
.elements
if
815 isinstance (e
, NoteEvent
)]
817 rest_events
= [e
for e
in self
.elements
if
818 isinstance (e
, RhythmicEvent
)
819 and not isinstance (e
, NoteEvent
)]
821 other_events
= [e
for e
in self
.elements
if
822 not isinstance (e
, RhythmicEvent
)]
824 if self
.after_grace_elements
:
825 printer ('\\afterGrace {')
827 if self
.grace_elements
and self
.elements
:
829 printer ('\\%s' % self
.grace_type
)
832 # don't print newlines after the { and } braces
833 self
.grace_elements
.print_ly (printer
, False)
834 elif self
.grace_elements
: # no self.elements!
835 warning (_ ("Grace note with no following music: %s") % self
.grace_elements
)
837 printer ('\\%s' % self
.grace_type
)
840 self
.grace_elements
.print_ly (printer
, False)
843 # Print all overrides and other settings needed by the
844 # articulations/ornaments before the note
845 for e
in other_events
:
846 e
.print_before_note (printer
)
849 rest_events
[0].print_ly (printer
)
850 elif len (note_events
) == 1:
851 note_events
[0].print_ly (printer
)
853 global previous_pitch
856 for x
in note_events
:
857 pitches
.append (x
.chord_element_ly ())
859 basepitch
= previous_pitch
860 printer ('<%s>' % string
.join (pitches
))
861 previous_pitch
= basepitch
862 duration
= self
.get_duration ()
864 duration
.print_ly (printer
)
868 for e
in other_events
:
871 for e
in other_events
:
872 e
.print_after_note (printer
)
874 if self
.after_grace_elements
:
876 self
.after_grace_elements
.print_ly (printer
, False)
878 self
.print_comment (printer
)
880 class Partial (Music
):
882 Music
.__init
__ (self
)
884 def print_ly (self
, printer
):
886 printer
.dump ("\\partial %s" % self
.partial
.ly_expression ())
888 class BarLine (Music
):
890 Music
.__init
__ (self
)
894 def print_ly (self
, printer
):
895 bar_symbol
= { 'regular': "|", 'dotted': ":", 'dashed': ":",
896 'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
897 'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
898 'short': "'", 'none': "" }.get (self
.type, None)
899 if bar_symbol
<> None:
900 printer
.dump ('\\bar "%s"' % bar_symbol
)
904 if self
.bar_number
> 0 and (self
.bar_number
% 10) == 0:
905 printer
.dump ("\\barNumberCheck #%d " % self
.bar_number
)
906 elif self
.bar_number
> 0:
907 printer
.print_verbatim (' %% %d' % self
.bar_number
)
910 def ly_expression (self
):
915 # strings to print before the note to which an event is attached.
916 # Ignored for notes etc.
917 self
.before_note
= None
918 self
.after_note
= None
919 # print something before the note to which an event is attached, e.g. overrides
920 def print_before_note (self
, printer
):
922 printer
.dump (self
.before_note
)
923 # print something after the note to which an event is attached, e.g. resetting
924 def print_after_note (self
, printer
):
926 printer
.dump (self
.after_note
)
929 class SpanEvent (Event
):
931 Event
.__init
__ (self
)
932 self
.span_direction
= 0 # start/stop
933 self
.line_type
= 'solid'
934 self
.span_type
= 0 # e.g. cres/decrescendo, ottava up/down
935 self
.size
= 0 # size of e.g. ocrave shift
936 def wait_for_note (self
):
938 def get_properties(self
):
939 return "'span-direction %d" % self
.span_direction
940 def set_span_type (self
, type):
941 self
.span_type
= type
943 class SlurEvent (SpanEvent
):
944 def print_before_note (self
, printer
):
945 command
= {'dotted': '\\slurDotted',
946 'dashed' : '\\slurDashed'}.get (self
.line_type
, '')
947 if command
and self
.span_direction
== -1:
948 printer
.dump (command
)
949 def print_after_note (self
, printer
):
950 # reset non-solid slur types!
951 command
= {'dotted': '\\slurSolid',
952 'dashed' : '\\slurSolid'}.get (self
.line_type
, '')
953 if command
and self
.span_direction
== -1:
954 printer
.dump (command
)
955 def ly_expression (self
):
956 return {-1: '(', 1:')'}.get (self
.span_direction
, '')
958 class BeamEvent (SpanEvent
):
959 def ly_expression (self
):
960 return {-1: '[', 1:']'}.get (self
.span_direction
, '')
962 class PedalEvent (SpanEvent
):
963 def ly_expression (self
):
964 return {-1: '\\sustainOn',
965 0:'\\sustainOff\\sustainOn',
966 1:'\\sustainOff'}.get (self
.span_direction
, '')
968 class TextSpannerEvent (SpanEvent
):
969 def ly_expression (self
):
970 return {-1: '\\startTextSpan',
971 1:'\\stopTextSpan'}.get (self
.span_direction
, '')
973 class BracketSpannerEvent (SpanEvent
):
974 # Ligature brackets use prefix-notation!!!
975 def print_before_note (self
, printer
):
976 if self
.span_direction
== -1:
978 # the the bracket after the last note
979 def print_after_note (self
, printer
):
980 if self
.span_direction
== 1:
982 # we're printing everything in print_(before|after)_note...
983 def ly_expression (self
):
987 class OctaveShiftEvent (SpanEvent
):
988 def wait_for_note (self
):
990 def set_span_type (self
, type):
991 self
.span_type
= {'up': 1, 'down': -1}.get (type, 0)
992 def ly_octave_shift_indicator (self
):
993 # convert 8/15 to lilypond indicators (+-1/+-2)
994 value
= {8: 1, 15: 2}.get (self
.size
, 0)
995 # negative values go up!
996 value
*= -1*self
.span_type
998 def ly_expression (self
):
999 dir = self
.ly_octave_shift_indicator ()
1002 value
= '\ottava #%s' % dir
1005 1: '\ottava #0'}.get (self
.span_direction
, '')
1007 class TrillSpanEvent (SpanEvent
):
1008 def ly_expression (self
):
1009 return {-1: '\\startTrillSpan',
1010 0: '', # no need to write out anything for type='continue'
1011 1:'\\stopTrillSpan'}.get (self
.span_direction
, '')
1013 class GlissandoEvent (SpanEvent
):
1014 def print_before_note (self
, printer
):
1015 if self
.span_direction
== -1:
1017 "dashed" : "dashed-line",
1018 "dotted" : "dotted-line",
1020 }. get (self
.line_type
, None)
1022 printer
.dump ("\once \override Glissando #'style = #'%s" % style
)
1023 def ly_expression (self
):
1024 return {-1: '\\glissando',
1025 1:''}.get (self
.span_direction
, '')
1027 class ArpeggioEvent(Event
):
1028 def __init__ (self
):
1029 Event
.__init
__ (self
)
1031 self
.non_arpeggiate
= False
1032 def wait_for_note (self
):
1034 def print_before_note (self
, printer
):
1035 if self
.non_arpeggiate
:
1036 printer
.dump ("\\arpeggioBracket")
1038 dir = { -1: "\\arpeggioArrowDown", 1: "\\arpeggioArrowUp" }.get (self
.direction
, '')
1041 def print_after_note (self
, printer
):
1042 if self
.non_arpeggiate
or self
.direction
:
1043 printer
.dump ("\\arpeggioNormal")
1044 def ly_expression (self
):
1045 return ('\\arpeggio')
1048 class TieEvent(Event
):
1049 def ly_expression (self
):
1053 class HairpinEvent (SpanEvent
):
1054 def set_span_type (self
, type):
1055 self
.span_type
= {'crescendo' : 1, 'decrescendo' : -1, 'diminuendo' : -1 }.get (type, 0)
1056 def hairpin_to_ly (self
):
1057 if self
.span_direction
== 1:
1060 return {1: '\<', -1: '\>'}.get (self
.span_type
, '')
1062 def ly_expression (self
):
1063 return self
.hairpin_to_ly ()
1065 def print_ly (self
, printer
):
1066 val
= self
.hairpin_to_ly ()
1072 class DynamicsEvent (Event
):
1073 def __init__ (self
):
1074 Event
.__init
__ (self
)
1076 def wait_for_note (self
):
1078 def ly_expression (self
):
1080 return '\%s' % self
.type
1084 def print_ly (self
, printer
):
1086 printer
.dump ("\\%s" % self
.type)
1088 class MarkEvent (Event
):
1089 def __init__ (self
, text
="\\default"):
1090 Event
.__init
__ (self
)
1092 def wait_for_note (self
):
1094 def ly_contents (self
):
1096 return '%s' % self
.mark
1099 def ly_expression (self
):
1100 return '\\mark %s' % self
.ly_contents ()
1102 class MusicGlyphMarkEvent (MarkEvent
):
1103 def ly_contents (self
):
1105 return '\\markup { \\musicglyph #"scripts.%s" }' % self
.mark
1110 class TextEvent (Event
):
1111 def __init__ (self
):
1112 Event
.__init
__ (self
)
1114 self
.force_direction
= None
1116 def wait_for_note (self
):
1119 def direction_mod (self
):
1120 return { 1: '^', -1: '_', 0: '-' }.get (self
.force_direction
, '-')
1122 def ly_expression (self
):
1123 base_string
= '%s\"%s\"'
1125 base_string
= '%s\markup{ ' + self
.markup
+ ' {%s} }'
1126 return base_string
% (self
.direction_mod (), self
.text
)
1128 class ArticulationEvent (Event
):
1129 def __init__ (self
):
1130 Event
.__init
__ (self
)
1132 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 return '%s\\%s' % (self
.direction_mod (), self
.type)
1142 class ShortArticulationEvent (ArticulationEvent
):
1143 def direction_mod (self
):
1145 return { 1: '^', -1: '_', 0: '-' }.get (self
.force_direction
, '-')
1146 def ly_expression (self
):
1148 return '%s%s' % (self
.direction_mod (), self
.type)
1152 class NoDirectionArticulationEvent (ArticulationEvent
):
1153 def ly_expression (self
):
1155 return '\\%s' % self
.type
1159 class MarkupEvent (ShortArticulationEvent
):
1160 def __init__ (self
):
1161 ArticulationEvent
.__init
__ (self
)
1162 self
.contents
= None
1163 def ly_expression (self
):
1165 return "%s\\markup { %s }" % (self
.direction_mod (), self
.contents
)
1169 class FretEvent (MarkupEvent
):
1170 def __init__ (self
):
1171 MarkupEvent
.__init
__ (self
)
1172 self
.force_direction
= 1
1177 def ly_expression (self
):
1179 if self
.strings
<> 6:
1180 val
+= "w:%s;" % self
.strings
1182 val
+= "h:%s;" % self
.frets
1183 if self
.barre
and len (self
.barre
) >= 3:
1184 val
+= "c:%s-%s-%s;" % (self
.barre
[0], self
.barre
[1], self
.barre
[2])
1185 have_fingering
= False
1186 for i
in self
.elements
:
1188 val
+= "%s-%s" % (i
[0], i
[1])
1190 have_fingering
= True
1196 return "%s\\markup { \\fret-diagram #\"%s\" }" % (self
.direction_mod (), val
)
1201 class FunctionWrapperEvent (Event
):
1202 def __init__ (self
, function_name
= None):
1203 Event
.__init
__ (self
)
1204 self
.function_name
= function_name
1205 def pre_note_ly (self
, is_chord_element
):
1206 if self
.function_name
:
1207 return "\\%s" % self
.function_name
1210 def pre_chord_ly (self
):
1212 def ly_expression (self
):
1213 if self
.function_name
:
1214 return "\\%s" % self
.function_name
1218 class ParenthesizeEvent (FunctionWrapperEvent
):
1219 def __init__ (self
):
1220 FunctionWrapperEvent
.__init
__ (self
, "parenthesize")
1222 class NotestyleEvent (Event
):
1223 def __init__ (self
):
1224 Event
.__init
__ (self
)
1227 def pre_chord_ly (self
):
1229 return "\\once \\override NoteHead #'style = #%s" % self
.style
1232 def pre_note_ly (self
, is_chord_element
):
1233 if self
.style
and is_chord_element
:
1234 return "\\tweak #'style #%s" % self
.style
1237 def ly_expression (self
):
1238 return self
.pre_chord_ly ()
1242 def __init__ (self
):
1246 return self
.ly_expression()
1247 def ly_expression (self
):
1248 return pitch_generating_function (self
)
1250 class ChordModification
:
1251 def __init__ (self
):
1255 def ly_expression (self
):
1257 val
= {1: ".", -1: "^" }.get (self
.type, "")
1258 val
+= "%s" % self
.step
1259 val
+= {1: "+", -1: "-"}.get (self
.alteration
, "")
1264 class ChordNameEvent (Event
):
1265 def __init__ (self
):
1266 Event
.__init
__ (self
)
1269 self
.duration
= None
1270 self
.modifications
= []
1272 def add_modification (self
, mod
):
1273 self
.modifications
.append (mod
)
1274 def ly_expression (self
):
1277 value
= self
.root
.ly_expression ()
1279 value
+= self
.duration
.ly_expression ()
1283 # First print all additions/changes, and only afterwards all subtractions
1284 for m
in self
.modifications
:
1286 value
+= m
.ly_expression ()
1287 for m
in self
.modifications
:
1289 value
+= m
.ly_expression ()
1291 value
+= "/+%s" % self
.bass
.ly_expression ()
1295 class TremoloEvent (ArticulationEvent
):
1296 def __init__ (self
):
1297 Event
.__init
__ (self
)
1300 def ly_expression (self
):
1302 if self
.bars
and self
.bars
> 0:
1303 str += ':%s' % (2 ** (2 + string
.atoi (self
.bars
)))
1306 class BendEvent (ArticulationEvent
):
1307 def __init__ (self
):
1308 Event
.__init
__ (self
)
1310 def ly_expression (self
):
1311 if self
.alter
!= None:
1312 return "-\\bendAfter #%s" % self
.alter
1316 class RhythmicEvent(Event
):
1317 def __init__ (self
):
1318 Event
.__init
__ (self
)
1319 self
.duration
= Duration()
1320 self
.associated_events
= []
1322 def add_associated_event (self
, ev
):
1324 self
.associated_events
.append (ev
)
1326 def pre_chord_ly (self
):
1327 return [ev
.pre_chord_ly () for ev
in self
.associated_events
]
1329 def pre_note_ly (self
, is_chord_element
):
1330 return [ev
.pre_note_ly (is_chord_element
) for ev
in self
.associated_events
]
1332 def ly_expression_pre_note (self
, is_chord_element
):
1333 res
= string
.join (self
.pre_note_ly (is_chord_element
), ' ')
1338 def get_length (self
):
1339 return self
.duration
.get_length()
1341 def get_properties (self
):
1342 return ("'duration %s"
1343 % self
.duration
.lisp_expression ())
1345 class RestEvent (RhythmicEvent
):
1346 def __init__ (self
):
1347 RhythmicEvent
.__init
__ (self
)
1350 def ly_expression (self
):
1351 res
= self
.ly_expression_pre_note (False)
1353 return res
+ "%s%s\\rest" % (self
.pitch
.ly_expression (), self
.duration
.ly_expression ())
1355 return 'r%s' % self
.duration
.ly_expression ()
1357 def print_ly (self
, printer
):
1358 for ev
in self
.associated_events
:
1359 ev
.print_ly (printer
)
1361 self
.pitch
.print_ly (printer
)
1362 self
.duration
.print_ly (printer
)
1366 self
.duration
.print_ly (printer
)
1368 class SkipEvent (RhythmicEvent
):
1369 def ly_expression (self
):
1370 return 's%s' % self
.duration
.ly_expression ()
1372 class NoteEvent(RhythmicEvent
):
1373 def __init__ (self
):
1374 RhythmicEvent
.__init
__ (self
)
1376 self
.drum_type
= None
1377 self
.cautionary
= False
1378 self
.forced_accidental
= False
1380 def get_properties (self
):
1381 str = RhythmicEvent
.get_properties (self
)
1384 str += self
.pitch
.lisp_expression ()
1385 elif self
.drum_type
:
1386 str += "'drum-type '%s" % self
.drum_type
1390 def pitch_mods (self
):
1393 excl_question
+= '?'
1394 if self
.forced_accidental
:
1395 excl_question
+= '!'
1397 return excl_question
1399 def ly_expression (self
):
1400 # obtain all stuff that needs to be printed before the note:
1401 res
= self
.ly_expression_pre_note (True)
1403 return res
+ '%s%s%s' % (self
.pitch
.ly_expression (),
1405 self
.duration
.ly_expression ())
1406 elif self
.drum_type
:
1407 return res
+ '%s%s' (self
.drum_type
,
1408 self
.duration
.ly_expression ())
1410 def chord_element_ly (self
):
1411 # obtain all stuff that needs to be printed before the note:
1412 res
= self
.ly_expression_pre_note (True)
1414 return res
+ '%s%s' % (self
.pitch
.ly_expression (),
1416 elif self
.drum_type
:
1417 return res
+ '%s%s' (self
.drum_type
)
1420 def print_ly (self
, printer
):
1421 for ev
in self
.associated_events
:
1422 ev
.print_ly (printer
)
1424 self
.pitch
.print_ly (printer
)
1425 printer (self
.pitch_mods ())
1427 printer (self
.drum_type
)
1429 self
.duration
.print_ly (printer
)
1431 class KeySignatureChange (Music
):
1432 def __init__ (self
):
1433 Music
.__init
__ (self
)
1436 self
.non_standard_alterations
= None
1438 def format_non_standard_alteration (self
, a
):
1439 alter_dict
= { -2: ",DOUBLE-FLAT",
1440 -1.5: ",THREE-Q-FLAT",
1446 1.5: ",THREE-Q-SHARP",
1449 accidental
= alter_dict
[a
[1]]
1451 warning (_ ("Unable to convert alteration %s to a lilypond expression") % a
[1])
1454 return "( %s . %s )" % (a
[0], accidental
)
1456 return "(( %s . %s ) . %s )" % (a
[2], a
[0], accidental
)
1460 def ly_expression (self
):
1462 return '\\key %s \\%s' % (self
.tonic
.ly_step_expression (),
1464 elif self
.non_standard_alterations
:
1465 alterations
= [self
.format_non_standard_alteration (a
) for
1466 a
in self
.non_standard_alterations
]
1467 # TODO: Check if the alterations should really be given in reverse
1468 # order of if that's just a bug in Lilypond. If it's a bug,
1469 # fix it and remove the following call, otherwise add a
1470 # proper comment here!
1471 alterations
.reverse ()
1472 return "\\set Staff.keySignature = #`(%s)" % string
.join (alterations
, " ")
1476 class TimeSignatureChange (Music
):
1477 def __init__ (self
):
1478 Music
.__init
__ (self
)
1479 self
.fractions
= [4,4]
1481 def ly_expression (self
):
1483 # Print out the style if we have ome, but the '() should only be
1484 # forced for 2/2 or 4/4, since in all other cases we'll get numeric
1485 # signatures anyway despite the default 'C signature style!
1486 is_common_signature
= self
.fractions
in ([2,2], [4,4], [4,2])
1488 if self
.style
== "common":
1489 st
= "\\defaultTimeSignature"
1490 elif (self
.style
!= "'()"):
1491 st
= "\\once \\override Staff.TimeSignature #'style = #%s " % self
.style
1492 if (self
.style
!= "'()") or is_common_signature
:
1493 st
= "\\numericTimeSignature"
1495 # Easy case: self.fractions = [n,d] => normal \time n/d call:
1496 if len (self
.fractions
) == 2 and isinstance (self
.fractions
[0], int):
1497 return st
+ '\\time %d/%d ' % tuple (self
.fractions
)
1498 elif self
.fractions
and not isinstance (self
.fractions
[0], list):
1499 # TODO: Implement non-standard time-signatures
1502 # TODO: Implement non-standard time-signatures
1505 class ClefChange (Music
):
1506 def __init__ (self
):
1507 Music
.__init
__ (self
)
1512 def octave_modifier (self
):
1513 return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self
.octave
, '')
1514 def clef_name (self
):
1515 return {('G', 2): "treble",
1517 ('C', 1): "soprano",
1518 ('C', 2): "mezzosoprano",
1521 ('C', 5): "baritone",
1522 ('F', 3): "varbaritone",
1524 ('F', 5): "subbass",
1525 ("percussion", 2): "percussion",
1526 ("TAB", 5): "tab"}.get ((self
.type, self
.position
), None)
1527 def ly_expression (self
):
1528 return '\\clef "%s%s"' % (self
.clef_name (), self
.octave_modifier ())
1531 "G": ("clefs.G", -2, -6),
1532 "C": ("clefs.C", 0, 0),
1533 "F": ("clefs.F", 2, 6),
1536 def lisp_expression (self
):
1538 (glyph
, pos
, c0
) = self
.clef_dict
[self
.type]
1542 (make-music 'SequentialMusic
1545 (make-property-set 'clefGlyph "%s") 'Staff)
1547 (make-property-set 'clefPosition %d) 'Staff)
1549 (make-property-set 'middleCPosition %d) 'Staff)))
1550 """ % (glyph
, pos
, c0
)
1553 class Transposition (Music
):
1554 def __init__ (self
):
1555 Music
.__init
__ (self
)
1557 def ly_expression (self
):
1558 self
.pitch
._force
_absolute
_pitch
= True
1559 return '\\transposition %s' % self
.pitch
.ly_expression ()
1561 class StaffChange (Music
):
1562 def __init__ (self
, staff
):
1563 Music
.__init
__ (self
)
1565 def ly_expression (self
):
1567 return "\\change Staff=\"%s\"" % self
.staff
1572 class TempoMark (Music
):
1573 def __init__ (self
):
1574 Music
.__init
__ (self
)
1575 self
.baseduration
= None
1576 self
.newduration
= None
1578 self
.parentheses
= False
1579 def set_base_duration (self
, dur
):
1580 self
.baseduration
= dur
1581 def set_new_duration (self
, dur
):
1582 self
.newduration
= dur
1583 def set_beats_per_minute (self
, beats
):
1585 def set_parentheses (self
, parentheses
):
1586 self
.parentheses
= parentheses
1587 def wait_for_note (self
):
1589 def duration_to_markup (self
, dur
):
1591 # Generate the markup to print the note, use scheme mode for
1592 # ly_expression to get longa and not \longa (which causes an error)
1593 return "\\general-align #Y #DOWN \\smaller \\note #\"%s\" #UP" % dur
.ly_expression(None, True)
1596 def tempo_markup_template (self
):
1597 return "\\mark\\markup { \\fontsize #-2 \\line { %s } }"
1598 def ly_expression (self
):
1600 if not self
.baseduration
:
1603 if self
.parentheses
:
1604 res
+= "\\tempo \"\" %s=%s" % (self
.baseduration
.ly_expression(), self
.beats
)
1606 res
+= "\\tempo %s=%s" % (self
.baseduration
.ly_expression(), self
.beats
)
1607 elif self
.newduration
:
1608 dm
= self
.duration_to_markup (self
.baseduration
)
1609 ndm
= self
.duration_to_markup (self
.newduration
)
1610 if self
.parentheses
:
1611 contents
= "\"(\" %s = %s \")\"" % (dm
, ndm
)
1613 contents
= " %s = %s " % (dm
, ndm
)
1614 res
+= self
.tempo_markup_template() % contents
1619 class FiguredBassNote (Music
):
1620 def __init__ (self
):
1621 Music
.__init
__ (self
)
1625 def set_prefix (self
, prefix
):
1626 self
.prefix
= prefix
1627 def set_suffix (self
, suffix
):
1628 self
.prefix
= suffix
1629 def set_number (self
, number
):
1630 self
.number
= number
1631 def ly_expression (self
):
1644 class FiguredBassEvent (NestedMusic
):
1645 def __init__ (self
):
1646 NestedMusic
.__init
__ (self
)
1647 self
.duration
= None
1648 self
.real_duration
= 0
1649 self
.parentheses
= False
1651 def set_duration (self
, dur
):
1653 def set_parentheses (self
, par
):
1654 self
.parentheses
= par
1655 def set_real_duration (self
, dur
):
1656 self
.real_duration
= dur
1658 def print_ly (self
, printer
):
1659 figured_bass_events
= [e
for e
in self
.elements
if
1660 isinstance (e
, FiguredBassNote
)]
1661 if figured_bass_events
:
1663 for x
in figured_bass_events
:
1664 notes
.append (x
.ly_expression ())
1665 contents
= string
.join (notes
)
1666 if self
.parentheses
:
1667 contents
= '[%s]' % contents
1668 printer ('<%s>' % contents
)
1669 self
.duration
.print_ly (printer
)
1672 class MultiMeasureRest(Music
):
1674 def lisp_expression (self
):
1677 'MultiMeasureRestMusicGroup
1679 (list (make-music (quote BarCheck))
1684 'MultiMeasureRestEvent
1687 (make-music (quote BarCheck))))
1688 """ % self
.duration
.lisp_expression ()
1690 def ly_expression (self
):
1691 return 'R%s' % self
.duration
.ly_expression ()
1695 def __init__ (self
, command
= "StaffGroup"):
1696 self
.stafftype
= command
1698 self
.instrument_name
= None
1699 self
.short_instrument_name
= None
1703 self
.is_group
= True
1704 # part_information is a list with entries of the form
1705 # [staffid, voicelist]
1706 # where voicelist is a list with entries of the form
1707 # [voiceid1, [lyricsid11, lyricsid12,...] ]
1708 self
.part_information
= None
1710 def append_staff (self
, staff
):
1711 self
.children
.append (staff
)
1713 def set_part_information (self
, part_name
, staves_info
):
1714 if part_name
== self
.id:
1715 self
.part_information
= staves_info
1717 for c
in self
.children
:
1718 c
.set_part_information (part_name
, staves_info
)
1720 def print_ly_contents (self
, printer
):
1721 for c
in self
.children
:
1723 c
.print_ly (printer
)
1724 def print_ly_overrides (self
, printer
):
1726 needs_with |
= self
.spanbar
== "no"
1727 needs_with |
= self
.instrument_name
!= None
1728 needs_with |
= self
.short_instrument_name
!= None
1729 needs_with |
= (self
.symbol
!= None) and (self
.symbol
!= "bracket")
1731 printer
.dump ("\\with {")
1732 if self
.instrument_name
or self
.short_instrument_name
:
1733 printer
.dump ("\\consists \"Instrument_name_engraver\"")
1734 if self
.spanbar
== "no":
1735 printer
.dump ("\\override SpanBar #'transparent = ##t")
1736 brack
= {"brace": "SystemStartBrace",
1738 "line": "SystemStartSquare"}.get (self
.symbol
, None)
1740 printer
.dump ("systemStartDelimiter = #'%s" % brack
)
1743 def print_ly (self
, printer
):
1745 printer
.dump ("\\new %s" % self
.stafftype
)
1746 self
.print_ly_overrides (printer
)
1749 if self
.stafftype
and self
.instrument_name
:
1750 printer
.dump ("\\set %s.instrumentName = %s" % (self
.stafftype
,
1751 escape_instrument_string (self
.instrument_name
)))
1753 if self
.stafftype
and self
.short_instrument_name
:
1754 printer
.dump ("\\set %s.shortInstrumentName = %s" % (self
.stafftype
,
1755 escape_instrument_string (self
.short_instrument_name
)))
1757 self
.print_ly_contents (printer
)
1763 class Staff (StaffGroup
):
1764 def __init__ (self
, command
= "Staff"):
1765 StaffGroup
.__init
__ (self
, command
)
1766 self
.is_group
= False
1768 self
.voice_command
= "Voice"
1769 self
.substafftype
= None
1771 def print_ly_overrides (self
, printer
):
1774 def print_ly_contents (self
, printer
):
1775 if not self
.id or not self
.part_information
:
1777 sub_staff_type
= self
.substafftype
1778 if not sub_staff_type
:
1779 sub_staff_type
= self
.stafftype
1781 for [staff_id
, voices
] in self
.part_information
:
1782 # Chord names need to come before the staff itself!
1783 for [v
, lyrics
, figuredbass
, chordnames
] in voices
:
1785 printer ('\context ChordNames = "%s" \\%s' % (chordnames
, chordnames
))
1787 # now comes the real staff definition:
1789 printer ('\\context %s = "%s" << ' % (sub_staff_type
, staff_id
))
1791 printer ('\\context %s << ' % sub_staff_type
)
1794 nr_voices
= len (voices
)
1795 for [v
, lyrics
, figuredbass
, chordnames
] in voices
:
1797 voice_count_text
= ''
1799 voice_count_text
= {1: ' \\voiceOne', 2: ' \\voiceTwo',
1800 3: ' \\voiceThree'}.get (n
, ' \\voiceFour')
1801 printer ('\\context %s = "%s" {%s \\%s }' % (self
.voice_command
, v
, voice_count_text
, v
))
1805 printer ('\\new Lyrics \\lyricsto "%s" \\%s' % (v
,l
))
1808 printer ('\context FiguredBass = "%s" \\%s' % (figuredbass
, figuredbass
))
1811 def print_ly (self
, printer
):
1812 if self
.part_information
and len (self
.part_information
) > 1:
1813 self
.stafftype
= "PianoStaff"
1814 self
.substafftype
= "Staff"
1815 StaffGroup
.print_ly (self
, printer
)
1817 class TabStaff (Staff
):
1818 def __init__ (self
, command
= "TabStaff"):
1819 Staff
.__init
__ (self
, command
)
1820 self
.string_tunings
= []
1821 self
.tablature_format
= None
1822 self
.voice_command
= "TabVoice"
1823 def print_ly_overrides (self
, printer
):
1824 if self
.string_tunings
or self
.tablature_format
:
1825 printer
.dump ("\\with {")
1826 if self
.string_tunings
:
1827 printer
.dump ("stringTunings = #'(")
1828 for i
in self
.string_tunings
:
1829 printer
.dump ("%s" % i
.semitones ())
1831 if self
.tablature_format
:
1832 printer
.dump ("tablatureFormat = #%s" % self
.tablature_format
)
1836 class DrumStaff (Staff
):
1837 def __init__ (self
, command
= "DrumStaff"):
1838 Staff
.__init
__ (self
, command
)
1839 self
.drum_style_table
= None
1840 self
.voice_command
= "DrumVoice"
1841 def print_ly_overrides (self
, printer
):
1842 if self
.drum_style_table
:
1843 printer
.dump ("\with {")
1844 printer
.dump ("drumStyleTable = #%s" % self
.drum_style_table
)
1847 class RhythmicStaff (Staff
):
1848 def __init__ (self
, command
= "RhythmicStaff"):
1849 Staff
.__init
__ (self
, command
)
1852 def __init__ (self
):
1853 self
.contents
= None
1854 self
.create_midi
= False
1856 def set_contents (self
, contents
):
1857 self
.contents
= contents
1859 def set_part_information (self
, part_id
, staves_info
):
1861 self
.contents
.set_part_information (part_id
, staves_info
)
1863 def print_ly (self
, printer
):
1864 printer
.dump ("\\score {");
1867 self
.contents
.print_ly (printer
);
1868 printer
.dump ("\\layout {}");
1870 if not self
.create_midi
:
1871 printer
.dump ("% To create MIDI output, uncomment the following line:");
1873 printer
.dump ("% ");
1874 printer
.dump ("\\midi {}");
1882 bflat
.alteration
= -1
1892 print bflat
.semitones()
1893 print bflat
.transposed (fifth
), bflat
.transposed (fifth
).transposed (fifth
)
1894 print bflat
.transposed (fifth
).transposed (fifth
).transposed (fifth
)
1896 print bflat
.semitones(), 'down'
1897 print bflat
.transposed (down
)
1898 print bflat
.transposed (down
).transposed (down
)
1899 print bflat
.transposed (down
).transposed (down
).transposed (down
)
1903 def test_printer ():
1911 m
= SequentialMusic()
1912 m
.append (make_note ())
1913 m
.append (make_note ())
1914 m
.append (make_note ())
1917 t
= TimeScaledMusic ()
1923 m
= SequentialMusic ()
1924 m
.append (make_tup ())
1925 m
.append (make_tup ())
1926 m
.append (make_tup ())
1928 printer
= Output_printer()
1929 m
.print_ly (printer
)
1933 m
= SequentialMusic()
1937 n
.duration
.duration_log
= l
1939 evc
.insert_around (None, n
, 0)
1940 m
.insert_around (None, evc
, 0)
1944 n
.duration
.duration_log
= l
1946 evc
.insert_around (None, n
, 0)
1947 m
.insert_around (None, evc
, 0)
1951 n
.duration
.duration_log
= l
1953 evc
.insert_around (None, n
, 0)
1954 m
.insert_around (None, evc
, 0)
1958 m
.insert_around (None, evc
, 0)
1963 tonic
.alteration
= -2
1964 n
= KeySignatureChange()
1965 n
.tonic
=tonic
.copy()
1966 n
.scale
= [0, 0, -2, 0, 0,-2,-2]
1968 evc
.insert_around (None, n
, 0)
1969 m
.insert_around (None, evc
, 0)
1974 if __name__
== '__main__':
1980 expr
.set_start (Rational (0))
1981 print expr
.ly_expression()
1982 start
= Rational (0,4)
1983 stop
= Rational (4,2)
1984 def sub(x
, start
=start
, stop
=stop
):
1985 ok
= x
.start
>= start
and x
.start
+x
.get_length() <= stop
1988 print expr
.lisp_sub_expression(sub
)