1 # -*- coding: utf-8 -*-
13 from rational import Rational
15 # Store previously converted pitch for \relative conversion as a global state variable
17 relative_pitches = False
19 ly_dur = None # stores lilypond durations
21 def escape_instrument_string (input_string):
22 retstring = string.replace (input_string, "\"", "\\\"")
23 if re.match ('.*[\r\n]+.*', retstring):
24 rx = re.compile (r'[\n\r]+')
25 strings = rx.split (retstring)
26 retstring = "\\markup { \\center-column { "
28 retstring += "\\line {\"" + s + "\"} "
31 retstring = "\"" + retstring + "\""
34 class Output_stack_element:
36 self.factor = Rational (1)
38 o = Output_stack_element()
39 o.factor = self.factor
42 class Output_printer(object):
44 A class that takes care of formatting (eg.: indenting) a
45 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, version):
61 self.print_verbatim ('\\version "' + version + '"')
64 def get_indent (self):
65 return self._nesting * self._indent
68 last = self._output_state_stack[-1]
69 self._output_state_stack.append (last.copy())
71 def add_factor (self, factor):
73 self._output_state_stack[-1].factor *= factor
76 del self._output_state_stack[-1]
77 if not self._output_state_stack:
80 def duration_factor (self):
81 return self._output_state_stack[-1].factor
83 def print_verbatim (self, str):
86 def unformatted_output (self, str):
87 # don't indent on \< and indent only once on <<
88 self._nesting += (str.count ('<')
89 - str.count ('\<') - str.count ('<<')
91 self._nesting -= (str.count ('>') - str.count ('\>') - str.count ('>>')
92 - str.count ('->') - str.count ('_>')
95 self.print_verbatim (str)
97 def print_duration_string (self, str):
98 if self._last_duration == str:
101 self.unformatted_output (str)
103 # def print_note_color (self, object, rgb=None):
105 # str = ("\\once\\override %s #'color = #(rgb-color %s # %s %s)" % (object, rgb[0], rgb[1], rgb[2]))
107 # str = "\\revert %s #'color" % object
112 def add_word (self, str):
113 if (len (str) + 1 + len (self._line) > self._line_len):
115 self._skipspace = True
117 if not self._skipspace:
119 self.unformatted_output (str)
120 self._skipspace = False
123 self._file.write (self._line + '\n')
124 self._line = ' ' * self._indent * self._nesting
125 self._skipspace = True
127 def skipspace (self):
128 self._skipspace = True
130 def __call__(self, arg):
133 def dump (self, str):
135 self._skipspace = False
136 self.unformatted_output (str)
138 # Avoid splitting quoted strings (e.g. "1. Wie") when indenting.
139 words = utilities.split_string_and_preserve_doublequoted_substrings(str)
151 self.duration_log = 0
153 self.factor = Rational(1)
155 def lisp_expression(self):
156 return '(ly:make-duration %d %d %d %d)' % (self.duration_log,
158 self.factor.numerator(),
159 self.factor.denominator())
161 def ly_expression(self, factor=None, scheme_mode=False):
162 global ly_dur # stores lilypond durations
166 if self.duration_log < 0:
168 longer_dict = {-1: "breve", -2: "longa"}
170 longer_dict = {-1: "\\breve", -2: "\\longa"}
171 dur_str = longer_dict.get(self.duration_log, "1")
173 dur_str = '%d' % (1 << self.duration_log)
174 dur_str += '.' * self.dots
176 if factor <> Rational(1, 1):
177 if factor.denominator() <> 1:
178 dur_str += '*%d/%d' % (factor.numerator(), factor.denominator())
180 dur_str += '*%d' % factor.numerator()
182 if dur_str.isdigit():
183 ly_dur = int(dur_str)
184 # TODO: We need to deal with dotted notes and scaled durations
185 # otherwise ly_dur won't work in combination with tremolos.
188 def print_ly(self, outputter):
189 dur_str = self.ly_expression(self.factor / outputter.duration_factor())
190 outputter.print_duration_string(dur_str)
193 return self.ly_expression()
198 d.duration_log = self.duration_log
199 d.factor = self.factor
202 def get_length(self):
203 dot_fact = Rational((1 << (1 + self.dots)) - 1,
206 log = abs(self.duration_log)
208 if self.duration_log < 0:
211 base = Rational(1, dur)
213 return base * dot_fact * self.factor
215 def set_create_midi(option):
217 Implement the midi command line option '-m' and '--midi'.
218 If True, add midi-block to .ly file (see L{musicexp.Score.print_ly}).
220 @param option: Indicates whether the midi-block has to be added or not.
221 @type option: boolean
226 def get_create_midi ():
228 Return, if exists the state of the midi-option.
230 @return: The state of the midi-option.
238 # implement the command line option '--transpose'
239 def set_transpose(option):
240 global transpose_option
241 transpose_option = option
243 def get_transpose(optType):
245 if(optType == "string"):
246 return '\\transpose c %s' % transpose_option
247 elif(optType == "integer"):
248 p = generic_tone_to_pitch(transpose_option)
251 if(optType == "string"):
253 elif(optType == "integer"):
256 # implement the command line option '--tab-clef'
257 def set_tab_clef(option):
258 global tab_clef_option
259 tab_clef_option = option
263 return ("tab", tab_clef_option)[tab_clef_option == "tab" or tab_clef_option == "moderntab"]
267 # definitions of the command line option '--string-numbers'
268 def set_string_numbers(option):
269 global string_numbers_option
270 string_numbers_option = option
272 def get_string_numbers():
274 return ("t", string_numbers_option)[string_numbers_option == "t" or string_numbers_option == "f"]
278 def generic_tone_to_pitch (tone):
289 tone_ = tone.strip().lower()
290 p.octave = tone_.count("'") - tone_.count(",")
291 tone_ = tone_.replace(",","").replace("'","")
292 p.step = ((ord (tone_[0]) - ord ('a') + 5) % 7)
293 p.alteration = accidentals_dict.get(tone_[1:], 0)
296 # Implement the different note names for the various languages
297 def pitch_generic (pitch, notenames, accidentals):
298 str = notenames[pitch.step]
299 halftones = int (pitch.alteration)
301 str += accidentals[0] * (-halftones)
302 elif pitch.alteration > 0:
303 str += accidentals[3] * (halftones)
304 # Handle remaining fraction to pitch.alteration (for microtones)
305 if (halftones != pitch.alteration):
306 if None in accidentals[1:3]:
307 ly.warning (_ ("Language does not support microtones contained in the piece"))
310 str += {-0.5: accidentals[1], 0.5: accidentals[2]}[pitch.alteration - halftones]
312 ly.warning (_ ("Language does not support microtones contained in the piece"))
315 def pitch_general (pitch):
316 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['es', 'eh', 'ih', 'is'])
317 return str.replace ('aes', 'as').replace ('ees', 'es')
319 def pitch_nederlands (pitch):
320 return pitch_general (pitch)
322 def pitch_english (pitch):
323 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'b'], ['f', 'qf', 'qs', 's'])
324 return str.replace ('aes', 'as').replace ('ees', 'es')
326 def pitch_deutsch (pitch):
327 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['es', 'eh', 'ih', 'is'])
328 return str.replace ('hes', 'b').replace ('aes', 'as').replace ('ees', 'es')
330 def pitch_norsk (pitch):
331 return pitch_deutsch (pitch)
333 def pitch_svenska (pitch):
334 str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', None, None, 'iss'])
335 return str.replace ('hess', 'b').replace ('aes', 'as').replace ('ees', 'es')
337 def pitch_italiano (pitch):
338 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', 'sb', 'sd', 'd'])
341 def pitch_catalan (pitch):
342 return pitch_italiano (pitch)
344 def pitch_espanol (pitch):
345 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 's'])
348 def pitch_vlaams (pitch):
349 str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 'k'])
352 def set_pitch_language (language):
353 global pitch_generating_function
355 "nederlands": pitch_nederlands,
356 "english": pitch_english,
357 "deutsch": pitch_deutsch,
358 "norsk": pitch_norsk,
359 "svenska": pitch_svenska,
360 "italiano": pitch_italiano,
361 "catalan": pitch_catalan,
362 "espanol": pitch_espanol,
363 "vlaams": pitch_vlaams}
364 pitch_generating_function = function_dict.get (language, pitch_general)
366 # global variable to hold the formatting function.
367 pitch_generating_function = pitch_general
374 self._force_absolute_pitch = False
377 return self.ly_expression()
379 def transposed (self, interval):
381 c.alteration += interval.alteration
382 c.step += interval.step
383 c.octave += interval.octave
386 target_st = self.semitones() + interval.semitones()
387 c.alteration += target_st - c.semitones()
394 c.octave += c.step / 7
397 def lisp_expression (self):
398 return '(ly:make-pitch %d %d %d)' % (self.octave,
404 p.alteration = self.alteration
406 p.octave = self.octave
407 p._force_absolute_pitch = self._force_absolute_pitch
411 return self.step + self.octave * 7
413 def semitones (self):
414 return self.octave * 12 + [0, 2, 4, 5, 7, 9, 11][self.step] + self.alteration
416 def normalize_alteration (c):
417 if(c.alteration < 0 and [True, False, False, True, False, False, False][c.step]):
420 elif(c.alteration > 0 and [False, False, True, False, False, False, True][c.step]):
425 def add_semitones (self, number):
426 semi = number + self.alteration
430 sign = (1,-1)[semi < 0]
431 prev = self.semitones()
432 while abs((prev + semi) - self.semitones ()) > 1:
435 self.alteration += (prev + semi) - self.semitones ()
436 self.normalize_alteration ()
438 def ly_step_expression (self):
439 return pitch_generating_function (self)
441 def absolute_pitch (self):
443 return "'" * (self.octave + 1)
444 elif self.octave < -1:
445 return "," * (-self.octave - 1)
449 def relative_pitch (self):
450 global previous_pitch
451 if not previous_pitch:
452 previous_pitch = self
453 return self.absolute_pitch ()
454 previous_pitch_steps = previous_pitch.octave * 7 + previous_pitch.step
455 this_pitch_steps = self.octave * 7 + self.step
456 pitch_diff = (this_pitch_steps - previous_pitch_steps)
457 previous_pitch = self
459 return "'" * ((pitch_diff + 3) / 7)
460 elif pitch_diff < -3:
461 return "," * ((-pitch_diff + 3) / 7)
465 def ly_expression (self):
466 str = self.ly_step_expression ()
467 if relative_pitches and not self._force_absolute_pitch:
468 str += self.relative_pitch ()
470 str += self.absolute_pitch ()
473 def print_ly (self, outputter):
474 outputter (self.ly_expression())
479 self.start = Rational (0)
481 self.identifier = None
483 def get_length(self):
486 def get_properties (self):
489 def has_children (self):
492 def get_index (self):
494 return self.parent.elements.index (self)
498 return self.__class__.__name__
500 def lisp_expression (self):
503 props = self.get_properties ()
505 return "(make-music '%s %s)" % (name, props)
507 def set_start (self, start):
510 def find_first (self, predicate):
515 def print_comment (self, printer, text=None):
526 lines = string.split (text, '\n')
529 printer.unformatted_output ('% ' + l)
533 def print_with_identifier (self, printer):
535 printer ("\\%s" % self.identifier)
537 self.print_ly (printer)
539 def print_ly (self, printer):
540 printer (self.ly_expression ())
542 class MusicWrapper (Music):
546 def print_ly (self, func):
547 self.element.print_ly (func)
549 class ModeChangingMusicWrapper (MusicWrapper):
551 MusicWrapper.__init__ (self)
552 self.mode = 'notemode'
554 def print_ly (self, func):
555 func ('\\%s' % self.mode)
556 MusicWrapper.print_ly (self, func)
558 class RelativeMusic (MusicWrapper):
560 MusicWrapper.__init__ (self)
561 self.basepitch = None
563 def print_ly (self, func):
564 global previous_pitch
565 global relative_pitches
566 prev_relative_pitches = relative_pitches
567 relative_pitches = True
568 previous_pitch = self.basepitch
569 if not previous_pitch:
570 previous_pitch = Pitch ()
571 func ('\\relative %s%s' % (pitch_generating_function (previous_pitch),
572 previous_pitch.absolute_pitch ()))
573 MusicWrapper.print_ly (self, func)
574 relative_pitches = prev_relative_pitches
576 class TimeScaledMusic (MusicWrapper):
578 MusicWrapper.__init__ (self)
581 self.display_number = "actual" # valid values "actual" | "both" | None
582 # Display the basic note length for the tuplet:
583 self.display_type = None # value values "actual" | "both" | None
584 self.display_bracket = "bracket" # valid values "bracket" | "curved" | None
585 self.actual_type = None # The actually played unit of the scaling
586 self.normal_type = None # The basic unit of the scaling
587 self.display_numerator = None
588 self.display_denominator = None
590 def print_ly (self, func):
591 if self.display_bracket == None:
592 func ("\\once \\override TupletBracket #'stencil = ##f")
594 elif self.display_bracket == "curved":
595 ly.warning (_ ("Tuplet brackets of curved shape are not correctly implemented"))
596 func ("\\once \\override TupletBracket #'stencil = #ly:slur::print")
599 base_number_function = {None: "#f",
600 "actual": "tuplet-number::calc-denominator-text",
601 "both": "tuplet-number::calc-fraction-text"}.get (self.display_number, None)
602 # If we have non-standard numerator/denominator, use our custom function
603 if self.display_number == "actual" and self.display_denominator:
604 base_number_function = "(tuplet-number::non-default-tuplet-denominator-text %s)" % self.display_denominator
605 elif self.display_number == "both" and (self.display_denominator or self.display_numerator):
606 if self.display_numerator:
607 num = self.display_numerator
610 if self.display_denominator:
611 den = self.display_denominator
614 base_number_function = "(tuplet-number::non-default-tuplet-fraction-text %s %s)" % (den, num)
617 if self.display_type == "actual" and self.normal_type:
618 # Obtain the note duration in scheme-mode, i.e. \longa as \\longa
619 base_duration = self.normal_type.ly_expression (None, True)
620 func ("\\once \\override TupletNumber #'text = #(tuplet-number::append-note-wrapper %s \"%s\")" %
621 (base_number_function, base_duration))
623 elif self.display_type == "both": # TODO: Implement this using actual_type and normal_type!
624 if self.display_number == None:
625 func ("\\once \\override TupletNumber #'stencil = ##f")
627 elif self.display_number == "both":
628 den_duration = self.normal_type.ly_expression (None, True)
629 # If we don't have an actual type set, use the normal duration!
631 num_duration = self.actual_type.ly_expression (None, True)
633 num_duration = den_duration
634 if (self.display_denominator or self.display_numerator):
635 func ("\\once \\override TupletNumber #'text = #(tuplet-number::non-default-fraction-with-notes %s \"%s\" %s \"%s\")" %
636 (self.display_denominator, den_duration,
637 self.display_numerator, num_duration))
640 func ("\\once \\override TupletNumber #'text = #(tuplet-number::fraction-with-notes \"%s\" \"%s\")" %
641 (den_duration, num_duration))
644 if self.display_number == None:
645 func ("\\once \\override TupletNumber #'stencil = ##f")
647 elif self.display_number == "both":
648 func ("\\once \\override TupletNumber #'text = #%s" % base_number_function)
651 func ('\\times %d/%d ' %
652 (self.numerator, self.denominator))
653 func.add_factor (Rational (self.numerator, self.denominator))
654 MusicWrapper.print_ly (self, func)
657 class NestedMusic(Music):
659 Music.__init__ (self)
662 def append (self, what):
664 self.elements.append (what)
666 def has_children (self):
669 def insert_around (self, succ, elt, dir):
670 assert elt.parent == None
671 assert succ == None or succ in self.elements
676 idx = self.elements.index (succ)
683 idx = len (self.elements)
685 self.elements.insert (idx, elt)
688 def get_properties (self):
689 return ("'elements (list %s)"
690 % string.join (map (lambda x: x.lisp_expression(),
693 def get_subset_properties (self, predicate):
694 return ("'elements (list %s)"
695 % string.join (map (lambda x: x.lisp_expression(),
696 filter (predicate, self.elements))))
697 def get_neighbor (self, music, dir):
698 assert music.parent == self
699 idx = self.elements.index (music)
701 idx = min (idx, len (self.elements) - 1)
704 return self.elements[idx]
706 def delete_element (self, element):
707 assert element in self.elements
709 self.elements.remove (element)
710 element.parent = None
712 def set_start (self, start):
714 for e in self.elements:
717 def find_first (self, predicate):
718 r = Music.find_first (self, predicate)
722 for e in self.elements:
723 r = e.find_first (predicate)
728 class SequentialMusic (NestedMusic):
729 def get_last_event_chord (self):
731 at = len(self.elements) - 1
733 not isinstance (self.elements[at], ChordEvent) and
734 not isinstance (self.elements[at], BarLine)):
737 if (at >= 0 and isinstance (self.elements[at], ChordEvent)):
738 value = self.elements[at]
741 def print_ly (self, printer, newline=True):
744 self.print_comment (printer)
748 for e in self.elements:
755 def lisp_sub_expression (self, pred):
759 props = self.get_subset_properties (pred)
761 return "(make-music '%s %s)" % (name, props)
763 def set_start (self, start):
764 for e in self.elements:
766 start += e.get_length()
770 self.repeat_type = "volta"
771 self.repeat_count = 2
774 def set_music (self, music):
775 if isinstance (music, Music):
777 elif isinstance (music, list):
778 self.music = SequentialMusic ()
779 self.music.elements = music
781 ly.warning (_ ("unable to set the music %(music)s for the repeat %(repeat)s") % \
782 {'music':music, 'repeat':self})
783 def add_ending (self, music):
784 self.endings.append (music)
785 def print_ly (self, printer):
786 printer.dump ('\\repeat %s %s' % (self.repeat_type, self.repeat_count))
788 self.music.print_ly (printer)
790 ly.warning (_ ("encountered repeat without body"))
793 printer.dump ('\\alternative {')
794 for e in self.endings:
801 self.lyrics_syllables = []
803 def print_ly (self, printer):
804 printer.dump (self.ly_expression ())
809 def ly_expression (self):
810 lstr = "\lyricmode {\set ignoreMelismata = ##t"
811 for l in self.lyrics_syllables:
819 self.header_fields = {}
821 def set_field (self, field, value):
822 self.header_fields[field] = value
824 def format_header_strings(self, key, value, printer):
825 printer.dump(key + ' = ')
827 # If a header item contains a line break, it is segmented. The
828 # substrings are formatted with the help of \markup, using
831 value = value.replace('"', '')
832 printer.dump(r'\markup \column {')
833 substrings = value.split('\n')
836 printer.dump(r'\line { "' + s + '"}')
843 def print_ly(self, printer):
844 printer.dump("\header {")
846 for (k, v) in self.header_fields.items():
848 self.format_header_strings(k, v, printer)
857 self.global_staff_size = -1
860 self.page_height = -1
863 self.bottom_margin = -1
864 self.left_margin = -1
865 self.right_margin = -1
866 self.system_left_margin = -1
867 self.system_right_margin = -1
868 self.system_distance = -1
869 self.top_system_distance = -1
871 self.short_indent = 0
872 self.instrument_names = []
874 def print_length_field (self, printer, field, value):
876 printer.dump ("%s = %s\\cm" % (field, value))
879 def get_longest_instrument_name(self):
881 for name in self.instrument_names:
882 lines = name.split('\n')
884 if len(line) > len(result):
888 def print_ly (self, printer):
889 if self.global_staff_size > 0:
890 printer.dump ('#(set-global-staff-size %s)' % self.global_staff_size)
892 printer.dump ('\\paper {')
894 printer.dump ("markup-system-spacing #'padding = #2")
896 self.print_length_field (printer, "paper-width", self.page_width)
897 self.print_length_field (printer, "paper-height", self.page_height)
898 self.print_length_field (printer, "top-margin", self.top_margin)
899 self.print_length_field (printer, "bottom-margin", self.bottom_margin)
900 self.print_length_field (printer, "left-margin", self.left_margin)
901 # TODO: maybe set line-width instead of right-margin?
902 self.print_length_field (printer, "right-margin", self.right_margin)
903 # TODO: What's the corresponding setting for system_left_margin and
904 # system_right_margin in LilyPond?
905 self.print_length_field (printer, "between-system-space", self.system_distance)
906 self.print_length_field (printer, "page-top-space", self.top_system_distance)
907 # TODO: Compute the indentation with the instrument name lengths
910 char_per_cm = (len(self.get_longest_instrument_name()) * 13) / self.page_width
911 if (self.indent != 0):
912 self.print_length_field (printer, "indent", self.indent/char_per_cm)
913 if (self.short_indent != 0):
914 self.print_length_field (printer, "short-indent", self.short_indent/char_per_cm)
921 self.context_dict = {}
922 def add_context (self, context):
923 if not self.context_dict.has_key (context):
924 self.context_dict[context] = []
925 def set_context_item (self, context, item):
926 self.add_context (context)
927 if not item in self.context_dict[context]:
928 self.context_dict[context].append (item)
929 def print_ly (self, printer):
930 if self.context_dict.items ():
931 printer.dump ('\\layout {')
933 for (context, defs) in self.context_dict.items ():
934 printer.dump ('\\context { \\%s' % context)
945 class ChordEvent (NestedMusic):
947 NestedMusic.__init__ (self)
948 self.after_grace_elements = None
949 self.grace_elements = None
950 self.grace_type = None
951 def append_grace (self, element):
953 if not self.grace_elements:
954 self.grace_elements = SequentialMusic ()
955 self.grace_elements.append (element)
956 def append_after_grace (self, element):
958 if not self.after_grace_elements:
959 self.after_grace_elements = SequentialMusic ()
960 self.after_grace_elements.append (element)
962 def has_elements (self):
963 return [e for e in self.elements if
964 isinstance (e, NoteEvent) or isinstance (e, RestEvent)] != []
967 def get_length (self):
969 for e in self.elements:
970 l = max(l, e.get_length())
973 def get_duration (self):
974 note_events = [e for e in self.elements if
975 isinstance (e, NoteEvent) or isinstance (e, RestEvent)]
977 return note_events[0].duration
981 def print_ly (self, printer):
982 note_events = [e for e in self.elements if
983 isinstance (e, NoteEvent)]
985 rest_events = [e for e in self.elements if
986 isinstance (e, RhythmicEvent)
987 and not isinstance (e, NoteEvent)]
989 other_events = [e for e in self.elements if
990 not isinstance (e, RhythmicEvent)]
992 if self.after_grace_elements:
993 printer ('\\afterGrace {')
995 if self.grace_elements and self.elements:
997 printer ('\\%s' % self.grace_type)
1000 # don't print newlines after the { and } braces
1001 self.grace_elements.print_ly (printer, False)
1002 elif self.grace_elements: # no self.elements!
1003 ly.warning (_ ("Grace note with no following music: %s") % self.grace_elements)
1005 printer ('\\%s' % self.grace_type)
1008 self.grace_elements.print_ly (printer, False)
1011 # Print all overrides and other settings needed by the
1012 # articulations/ornaments before the note
1014 for e in other_events:
1015 e.print_before_note (printer)
1018 rest_events[0].print_ly (printer)
1019 elif len (note_events) == 1:
1020 note_events[0].print_ly (printer)
1022 global previous_pitch
1026 for x in note_events:
1027 if(x.associated_events):
1028 for aev in x.associated_events:
1029 if (isinstance(aev, StemEvent) and aev.value):
1031 pitches.append (x.chord_element_ly ())
1033 basepitch = previous_pitch
1035 printer (stem.ly_expression ())
1036 printer ('<%s>' % string.join (pitches))
1037 previous_pitch = basepitch
1038 duration = self.get_duration ()
1040 duration.print_ly (printer)
1044 for e in other_events:
1045 e.print_ly (printer)
1047 for e in other_events:
1048 e.print_after_note (printer)
1050 if self.after_grace_elements:
1052 self.after_grace_elements.print_ly (printer, False)
1054 self.print_comment (printer)
1056 class Partial (Music):
1057 def __init__ (self):
1058 Music.__init__ (self)
1060 def print_ly (self, printer):
1062 printer.dump ("\\partial %s" % self.partial.ly_expression ())
1064 class BarLine (Music):
1065 def __init__ (self):
1066 Music.__init__ (self)
1070 def print_ly (self, printer):
1071 bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': "dashed",
1072 'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
1073 'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
1074 'short': "'", 'none': "" }.get (self.type, None)
1075 if bar_symbol <> None:
1076 printer.dump ('\\bar "%s"' % bar_symbol)
1080 if self.bar_number > 0 and (self.bar_number % 10) == 0:
1081 printer.dump ("\\barNumberCheck #%d " % self.bar_number)
1082 elif self.bar_number > 0:
1083 printer.print_verbatim (' %% %d' % self.bar_number)
1086 def ly_expression (self):
1090 def __init__ (self):
1091 # strings to print before the note to which an event is attached.
1092 # Ignored for notes etc.
1093 self.before_note = None
1094 self.after_note = None
1095 # print something before the note to which an event is attached, e.g. overrides
1096 def print_before_note (self, printer):
1097 if self.before_note:
1098 printer.dump (self.before_note)
1099 # print something after the note to which an event is attached, e.g. resetting
1100 def print_after_note (self, printer):
1102 printer.dump (self.after_note)
1105 class SpanEvent (Event):
1106 def __init__ (self):
1107 Event.__init__ (self)
1108 self.span_direction = 0 # start/stop
1109 self.line_type = 'solid'
1110 self.span_type = 0 # e.g. cres/decrescendo, ottava up/down
1111 self.size = 0 # size of e.g. octave shift
1112 def wait_for_note (self):
1114 def get_properties(self):
1115 return "'span-direction %d" % self.span_direction
1116 def set_span_type (self, type):
1117 self.span_type = type
1119 class SlurEvent (SpanEvent):
1120 def print_before_note (self, printer):
1121 command = {'dotted': '\\slurDotted',
1122 'dashed' : '\\slurDashed'}.get (self.line_type, '')
1123 if command and self.span_direction == -1:
1124 printer.dump (command)
1125 def print_after_note (self, printer):
1126 # reset non-solid slur types!
1127 command = {'dotted': '\\slurSolid',
1128 'dashed' : '\\slurSolid'}.get (self.line_type, '')
1129 if command and self.span_direction == -1:
1130 printer.dump (command)
1131 def ly_expression (self):
1132 return {-1: '(', 1:')'}.get (self.span_direction, '')
1134 class BeamEvent (SpanEvent):
1135 def ly_expression (self):
1136 return {-1: '[', 1:']'}.get (self.span_direction, '')
1138 class PedalEvent (SpanEvent):
1139 def ly_expression (self):
1140 return {-1: '\\sustainOn',
1141 0:'\\sustainOff\\sustainOn',
1142 1:'\\sustainOff'}.get (self.span_direction, '')
1144 class TextSpannerEvent (SpanEvent):
1145 def print_before_note (self, printer):
1146 if hasattr(self, 'style') and self.style=="wave":
1147 printer.dump("\once \override TextSpanner #'style = #'trill")
1149 x = {-1:'\\textSpannerDown', 0:'\\textSpannerNeutral', 1: '\\textSpannerUp'}.get(self.force_direction, '')
1154 def print_after_note (self, printer):
1157 def ly_expression (self):
1159 if hasattr(self, 'style') and self.style=="ignore":
1161 # if self.style=="wave":
1162 if whatOrnament == "wave":
1163 return {-1: '\\startTextSpan',
1164 1:'\\stopTextSpan'}.get (self.span_direction, '')
1166 if hasattr(self, 'style') and self.style=="stop" and whatOrnament != "trill": return ""
1167 return {-1: '\\startTrillSpan',
1168 1:'\\stopTrillSpan'}.get (self.span_direction, '')
1170 class BracketSpannerEvent (SpanEvent):
1171 # Ligature brackets use prefix-notation!!!
1172 def print_before_note (self, printer):
1173 if self.span_direction == -1:
1174 if self.force_direction == 1:
1175 printer.dump("\once \override LigatureBracket #' direction = #UP")
1176 elif self.force_direction == -1:
1177 printer.dump("\once \override LigatureBracket #' direction = #DOWN")
1179 # the bracket after the last note
1180 def print_after_note (self, printer):
1181 if self.span_direction == 1:
1183 # we're printing everything in print_(before|after)_note...
1184 def ly_expression (self):
1188 class OctaveShiftEvent (SpanEvent):
1189 def wait_for_note (self):
1191 def set_span_type (self, type):
1192 self.span_type = {'up': 1, 'down':-1}.get (type, 0)
1193 def ly_octave_shift_indicator (self):
1194 # convert 8/15 to lilypond indicators (+-1/+-2)
1196 value = {8: 1, 15: 2}[self.size]
1198 ly.warning (_ ("Invalid octave shift size found: %s. Using no shift.") % self.size)
1200 # negative values go up!
1201 value *= -1 * self.span_type
1203 def ly_expression (self):
1204 dir = self.ly_octave_shift_indicator ()
1207 value = '\ottava #%s' % dir
1210 1: '\ottava #0'}.get (self.span_direction, '')
1212 class TrillSpanEvent (SpanEvent):
1213 def ly_expression (self):
1214 return {-1: '\\startTrillSpan',
1215 0: '', # no need to write out anything for type='continue'
1216 1:'\\stopTrillSpan'}.get (self.span_direction, '')
1218 class GlissandoEvent (SpanEvent):
1219 def print_before_note (self, printer):
1220 if self.span_direction == -1:
1222 "dashed" : "dashed-line",
1223 "dotted" : "dotted-line",
1225 }. get (self.line_type, None)
1227 printer.dump ("\\once \\override Glissando #'style = #'%s" % style)
1228 def ly_expression (self):
1229 return {-1: '\\glissando',
1230 1:''}.get (self.span_direction, '')
1232 class ArpeggioEvent(Event):
1233 def __init__ (self):
1234 Event.__init__ (self)
1236 self.non_arpeggiate = False
1237 def wait_for_note (self):
1239 def print_before_note (self, printer):
1240 if self.non_arpeggiate:
1241 printer.dump ("\\arpeggioBracket")
1243 dir = { -1: "\\arpeggioArrowDown", 1: "\\arpeggioArrowUp" }.get (self.direction, '')
1246 def print_after_note (self, printer):
1247 if self.non_arpeggiate or self.direction:
1248 printer.dump ("\\arpeggioNormal")
1249 def ly_expression (self):
1250 return ('\\arpeggio')
1253 class TieEvent(Event):
1254 def ly_expression (self):
1258 class HairpinEvent (SpanEvent):
1259 def set_span_type (self, type):
1260 self.span_type = {'crescendo' : 1, 'decrescendo' :-1, 'diminuendo' :-1 }.get (type, 0)
1261 def hairpin_to_ly (self):
1262 if self.span_direction == 1:
1265 return {1: '\<', -1: '\>'}.get (self.span_type, '')
1267 def direction_mod (self):
1268 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1270 def ly_expression (self):
1271 return self.hairpin_to_ly ()
1273 def print_ly (self, printer):
1274 val = self.hairpin_to_ly ()
1276 # printer.dump (val)
1277 printer.dump ('%s%s' % (self.direction_mod (), val))
1281 class DynamicsEvent (Event):
1282 def __init__ (self):
1283 Event.__init__ (self)
1285 self.force_direction = 0
1286 def wait_for_note (self):
1288 def ly_expression (self):
1290 return '\%s' % self.type
1294 def direction_mod (self):
1295 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1297 def print_ly (self, printer):
1299 printer.dump ('%s\\%s' % (self.direction_mod (), self.type))
1301 class MarkEvent (Event):
1302 def __init__ (self, text="\\default"):
1303 Event.__init__ (self)
1305 def wait_for_note (self):
1307 def ly_contents (self):
1309 return '%s' % self.mark
1312 def ly_expression (self):
1313 return '\\mark %s' % self.ly_contents ()
1315 class MusicGlyphMarkEvent (MarkEvent):
1316 def ly_contents (self):
1318 return '\\markup { \\musicglyph #"scripts.%s" }' % self.mark
1323 class TextEvent (Event):
1324 def __init__ (self):
1325 Event.__init__ (self)
1327 self.force_direction = None
1329 def wait_for_note (self):
1330 """ This is problematic: the lilypond-markup ^"text"
1331 requires wait_for_note to be true. Otherwise the
1332 compilation will fail. So we are forced to set return to True.
1333 But in some cases this might lead to a wrong placement of the text.
1334 In case of words like Allegro the text should be put in a '\tempo'-command.
1335 In this case we don't want to wait for the next note.
1336 In some other cases the text is supposed to be used in a '\mark\markup' construct.
1337 We would not want to wait for the next note either.
1338 There might be other problematic situations.
1339 In the long run we should differentiate between various contexts in MusicXML, e.g.
1340 the following markup should be interpreted as '\tempo "Allegretto"':
1341 <direction placement="above">
1343 <words>Allegretto</words>
1345 <sound tempo="120"/>
1347 In the mean time arising problems have to be corrected manually after the conversion.
1351 def direction_mod (self):
1352 """ 1: placement="above"; -1: placement="below"; 0: no placement attribute.
1353 see musicxml_direction_to_indicator in musicxml2ly_conversion.py """
1354 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1356 def ly_expression (self):
1357 base_string = '%s\"%s\"'
1359 base_string = '%s\markup{ ' + self.markup + ' {%s} }'
1360 return base_string % (self.direction_mod (), self.text)
1362 class ArticulationEvent (Event):
1363 def __init__ (self):
1364 Event.__init__ (self)
1366 self.force_direction = None
1367 def wait_for_note (self):
1370 def direction_mod (self):
1371 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '')
1373 def ly_expression (self):
1374 return '%s\\%s' % (self.direction_mod (), self.type)
1376 class ShortArticulationEvent (ArticulationEvent):
1377 def direction_mod (self):
1379 return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
1380 def ly_expression (self):
1382 return '%s%s' % (self.direction_mod (), self.type)
1386 class NoDirectionArticulationEvent (ArticulationEvent):
1388 def is_breathing_sign(self):
1389 return self.type == 'breathe'
1391 def print_after_note(self, printer):
1392 # The breathing sign should, according to current LilyPond
1393 # praxis, be treated as an independent musical
1394 # event. Consequently, it should be printed _after_ the note
1395 # to which it is attached.
1396 if self.is_breathing_sign():
1397 printer.dump(r'\breathe')
1399 def ly_expression (self):
1400 if self.type and not self.is_breathing_sign():
1401 return '\\%s' % self.type
1405 class MarkupEvent (ShortArticulationEvent):
1406 def __init__ (self):
1407 ArticulationEvent.__init__ (self)
1408 self.contents = None
1409 def ly_expression (self):
1411 return "%s\\markup { %s }" % (self.direction_mod (), self.contents)
1415 class FretEvent (MarkupEvent):
1416 def __init__ (self):
1417 MarkupEvent.__init__ (self)
1418 self.force_direction = 1
1423 def ly_expression (self):
1425 if self.strings <> 6:
1426 val += "w:%s;" % self.strings
1428 val += "h:%s;" % self.frets
1429 if self.barre and len (self.barre) >= 3:
1430 val += "c:%s-%s-%s;" % (self.barre[0], self.barre[1], self.barre[2]+get_transpose("integer"))
1431 have_fingering = False
1432 for i in self.elements:
1434 val += "%s-%s" % (i[0], i[1]+(get_transpose("integer"),'')[isinstance(i[1],str)])
1436 have_fingering = True
1442 return "%s\\markup { \\fret-diagram #\"%s\" }" % (self.direction_mod (), val)
1446 class FretBoardNote (Music):
1447 def __init__ (self):
1448 Music.__init__ (self)
1451 self.fingering = None
1452 def ly_expression (self):
1453 str = self.pitch.ly_expression()
1455 str += "-%s" % self.fingering
1457 str += "\%s" % self.string
1460 class FretBoardEvent (NestedMusic):
1461 def __init__ (self):
1462 NestedMusic.__init__ (self)
1463 self.duration = None
1464 def print_ly (self, printer):
1465 fretboard_notes = [n for n in self.elements if isinstance (n, FretBoardNote)]
1468 for n in fretboard_notes:
1469 notes.append (n.ly_expression ())
1470 contents = string.join (notes)
1471 printer ('<%s>%s' % (contents,self.duration))
1473 class FunctionWrapperEvent (Event):
1474 def __init__ (self, function_name=None):
1475 Event.__init__ (self)
1476 self.function_name = function_name
1477 def pre_note_ly (self, is_chord_element):
1478 if self.function_name:
1479 return "\\%s" % self.function_name
1482 def pre_chord_ly (self):
1484 def ly_expression (self):
1485 if self.function_name:
1486 return "\\%s" % self.function_name
1490 class ParenthesizeEvent (FunctionWrapperEvent):
1491 def __init__ (self):
1492 FunctionWrapperEvent.__init__ (self, "parenthesize")
1494 class StemEvent (Event):
1496 A class to take care of stem values (up, down, double, none)
1498 def __init__ (self):
1499 Event.__init__ (self)
1501 def pre_chord_ly (self):
1503 return "\\%s" % self.value
1506 def pre_note_ly (self, is_chord_element):
1508 def ly_expression (self):
1509 return self.pre_chord_ly ()
1511 class NotestyleEvent (Event): #class changed by DaLa: additional attribute color
1512 def __init__ (self):
1513 Event.__init__ (self)
1517 def pre_chord_ly (self):
1520 return_string += " \\once \\override NoteHead #'style = #%s" % self.style
1522 return_string += " \\once \\override NoteHead #'color = #(rgb-color %s %s %s)" % (self.color[0], self.color[1], self.color[2])
1523 return return_string
1524 def pre_note_ly (self, is_chord_element):
1525 if self.style and is_chord_element:
1526 return "\\tweak #'style #%s" % self.style
1529 def ly_expression (self):
1530 return self.pre_chord_ly ()
1532 class StemstyleEvent (Event): #class added by DaLa
1533 def __init__ (self):
1534 Event.__init__ (self)
1536 def pre_chord_ly (self):
1538 return "\\once \\override Stem #'color = #(rgb-color %s %s %s)" % (self.color[0], self.color[1], self.color[2])
1541 def pre_note_ly (self, is_chord_element):
1543 def ly_expression (self):
1544 return self.pre_chord_ly ()
1548 def __init__ (self):
1552 return self.ly_expression()
1553 def ly_expression (self):
1554 return pitch_generating_function (self)
1556 class ChordModification:
1557 def __init__ (self):
1561 def ly_expression (self):
1563 val = {1: ".", -1: "^" }.get (self.type, "")
1564 val += "%s" % self.step
1565 val += {1: "+", -1: "-"}.get (self.alteration, "")
1570 class ChordNameEvent (Event):
1571 def __init__ (self):
1572 Event.__init__ (self)
1575 self.duration = None
1576 self.modifications = []
1578 def add_modification (self, mod):
1579 self.modifications.append (mod)
1580 def ly_expression (self):
1584 value = self.root.ly_expression ()
1586 value += self.duration.ly_expression ()
1588 value = self.kind.format(value)
1589 # First print all additions/changes, and only afterwards all subtractions
1590 for m in self.modifications:
1592 value += m.ly_expression ()
1593 for m in self.modifications:
1595 value += m.ly_expression ()
1597 value += "/+%s" % self.bass.ly_expression ()
1601 class TremoloEvent(ArticulationEvent):
1603 Event.__init__(self)
1606 def ly_expression(self):
1608 if self.strokes and int(self.strokes) > 0:
1609 # ly_dur is a global variable defined in class Duration
1610 # ly_dur stores the value of the reciprocal values of notes
1611 # ly_dur is used here to check the current note duration
1612 # if the duration is smaller than 8, e.g.
1613 # quarter, half and whole notes,
1614 # `:(2 ** (2 + number of tremolo strokes))'
1615 # should be appended to the pitch and duration, e.g.
1616 # 1 stroke: `c4:8' or `c2:8' or `c1:8'
1617 # 2 strokes: `c4:16' or `c2:16' or `c1:16'
1619 # else (if ly_dur is equal to or greater than 8):
1620 # we need to make sure that the tremolo value that is to
1621 # be appended to the pitch and duration is twice the
1622 # duration (if there is only one tremolo stroke.
1623 # Each additional stroke doubles the tremolo value, e.g.:
1624 # 1 stroke: `c8:16', `c16:32', `c32:64', ...
1625 # 2 strokes: `c8:32', `c16:64', `c32:128', ...
1628 ly_str += ':%s' % (2 ** (2 + int(self.strokes)))
1630 ly_str += ':%s' % (2 ** int((math.log(ly_dur, 2)) + int(self.strokes)))
1633 class BendEvent (ArticulationEvent):
1634 def __init__ (self):
1635 Event.__init__ (self)
1637 def ly_expression (self):
1638 if self.alter != None:
1639 return "-\\bendAfter #%s" % self.alter
1643 class RhythmicEvent(Event):
1644 def __init__ (self):
1645 Event.__init__ (self)
1646 self.duration = Duration()
1647 self.associated_events = []
1649 def add_associated_event (self, ev):
1651 self.associated_events.append (ev)
1653 def pre_chord_ly (self):
1654 return [ev.pre_chord_ly () for ev in self.associated_events]
1656 def pre_note_ly (self, is_chord_element):
1657 return [ev.pre_note_ly (is_chord_element) for ev in self.associated_events]
1659 def ly_expression_pre_note (self, is_chord_element):
1660 res = string.join (self.pre_note_ly (is_chord_element), ' ')
1665 def get_length (self):
1666 return self.duration.get_length()
1668 def get_properties (self):
1669 return ("'duration %s"
1670 % self.duration.lisp_expression ())
1672 class RestEvent (RhythmicEvent):
1673 def __init__ (self):
1674 RhythmicEvent.__init__ (self)
1677 def ly_expression (self):
1678 res = self.ly_expression_pre_note (False)
1680 return res + "%s%s\\rest" % (self.pitch.ly_expression (), self.duration.ly_expression ())
1682 return 'r%s' % self.duration.ly_expression ()
1684 def print_ly (self, printer):
1685 for ev in self.associated_events:
1686 ev.print_ly (printer)
1687 # if hasattr(self, 'color'):
1688 # printer.print_note_color("NoteHead", self.color)
1689 # printer.print_note_color("Stem", self.color)
1690 # printer.print_note_color("Beam", self.color)
1692 self.pitch.print_ly (printer)
1693 self.duration.print_ly (printer)
1697 self.duration.print_ly (printer)
1699 class SkipEvent (RhythmicEvent):
1700 def ly_expression (self):
1701 return 's%s' % self.duration.ly_expression ()
1703 class NoteEvent(RhythmicEvent):
1704 def __init__ (self):
1705 RhythmicEvent.__init__ (self)
1707 self.drum_type = None
1708 self.cautionary = False
1709 self.forced_accidental = False
1711 def get_properties (self):
1712 str = RhythmicEvent.get_properties (self)
1715 str += self.pitch.lisp_expression ()
1716 elif self.drum_type:
1717 str += "'drum-type '%s" % self.drum_type
1721 def pitch_mods (self):
1724 excl_question += '?'
1725 if self.forced_accidental:
1726 excl_question += '!'
1728 return excl_question
1730 def ly_expression (self):
1731 # obtain all stuff that needs to be printed before the note:
1732 res = self.ly_expression_pre_note (True)
1734 return res + '%s%s%s' % (self.pitch.ly_expression (),
1736 self.duration.ly_expression ())
1737 elif self.drum_type:
1738 return res + '%s%s' (self.drum_type,
1739 self.duration.ly_expression ())
1741 def chord_element_ly (self):
1742 # obtain all stuff that needs to be printed before the note:
1743 res = self.ly_expression_pre_note (True)
1745 return res + '%s%s' % (self.pitch.ly_expression (),
1747 elif self.drum_type:
1748 return res + '%s%s' (self.drum_type)
1751 def print_ly (self, printer):
1752 for ev in self.associated_events:
1753 ev.print_ly (printer)
1754 if hasattr(self, 'color'):
1755 printer.print_note_color("NoteHead", self.color)
1756 printer.print_note_color("Stem", self.color)
1757 printer.print_note_color("Beam", self.color)
1760 self.pitch.print_ly (printer)
1761 printer (self.pitch_mods ())
1763 printer (self.drum_type)
1765 self.duration.print_ly (printer)
1767 # if hasattr(self, 'color'):
1768 # printer.print_note_color("NoteHead")
1769 # printer.print_note_color("Stem")
1770 # printer.print_note_color("Beam")
1772 class KeySignatureChange (Music):
1773 def __init__ (self):
1774 Music.__init__ (self)
1777 self.non_standard_alterations = None
1779 def format_non_standard_alteration (self, a):
1780 alter_dict = { -2: ",DOUBLE-FLAT",
1781 - 1.5: ",THREE-Q-FLAT",
1783 - 0.5: ",SEMI-FLAT",
1787 1.5: ",THREE-Q-SHARP",
1790 accidental = alter_dict[a[1]]
1792 ly.warning (_ ("Unable to convert alteration %s to a lilypond expression") % a[1])
1795 return "( %s . %s )" % (a[0], accidental)
1797 return "(( %s . %s ) . %s )" % (a[2], a[0], accidental)
1801 def ly_expression (self):
1803 return '\\key %s \\%s' % (self.tonic.ly_step_expression (),
1805 elif self.non_standard_alterations:
1806 alterations = [self.format_non_standard_alteration (a) for
1807 a in self.non_standard_alterations]
1808 return "\\set Staff.keyAlterations = #`(%s)" % string.join (alterations, " ")
1812 class ShiftDurations (MusicWrapper):
1813 def __init__ (self):
1814 MusicWrapper.__init__ (self)
1817 def set_shift_durations_parameters(self, timeSigChange):
1818 self.params = timeSigChange.get_shift_durations_parameters()
1820 def print_ly (self, func):
1821 func (' \\shiftDurations #%d #%d ' % tuple(self.params))
1822 MusicWrapper.print_ly (self, func)
1824 class TimeSignatureChange (Music):
1825 def __init__ (self):
1826 Music.__init__ (self)
1827 self.fractions = [4, 4]
1829 # Used for the --time-signature option of musicxml2ly
1830 self.originalFractions = [4, 4]
1832 def get_fractions_ratio (self):
1834 Calculate the ratio between the original time fraction and the new one.
1835 Used for the "--time-signature" option.
1837 @return: The ratio between the two time fractions.
1840 return (float(self.originalFractions[0])/self.originalFractions[1])*(float(self.fractions[1])/self.fractions[0])
1842 def get_shift_durations_parameters (self):
1843 dur = math.ceil(math.log(self.get_fractions_ratio(),2))
1844 dots = (1/self.get_fractions_ratio())/(math.pow(2,-dur))
1845 dots = int(math.log(2-dots,0.5))
1848 def format_fraction (self, frac):
1849 if isinstance (frac, list):
1850 l = [self.format_fraction (f) for f in frac]
1851 return "(" + string.join (l, " ") + ")"
1855 def ly_expression (self):
1857 # Print out the style if we have ome, but the '() should only be
1858 # forced for 2/2 or 4/4, since in all other cases we'll get numeric
1859 # signatures anyway despite the default 'C signature style!
1860 is_common_signature = self.fractions in ([2, 2], [4, 4], [4, 2])
1862 if self.style == "common":
1863 st = "\\defaultTimeSignature"
1864 elif (self.style != "'()"):
1865 st = "\\once \\override Staff.TimeSignature #'style = #%s " % self.style
1866 elif (self.style != "'()") or is_common_signature:
1867 st = "\\numericTimeSignature"
1869 # Easy case: self.fractions = [n,d] => normal \time n/d call:
1870 if len (self.fractions) == 2 and isinstance (self.fractions[0], int):
1871 return st + '\\time %d/%d ' % tuple (self.fractions)
1872 elif self.fractions:
1873 return st + "\\compoundMeter #'%s" % self.format_fraction (self.fractions)
1877 class ClefChange (Music):
1878 def __init__ (self):
1879 Music.__init__ (self)
1884 def octave_modifier (self):
1885 return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self.octave, '')
1887 def clef_name (self):
1888 return {('G', 2): "treble",
1890 ('C', 1): "soprano",
1891 ('C', 2): "mezzosoprano",
1894 ('C', 5): "baritone",
1895 ('F', 3): "varbaritone",
1897 ('F', 5): "subbass",
1898 ("percussion", 2): "percussion",
1899 # Workaround: MuseScore uses PERC instead of percussion
1900 ("PERC", 2): "percussion",
1901 ("TAB", 5): get_tab_clef ()}.get ((self.type, self.position), None)
1903 def ly_expression (self):
1904 return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ())
1907 "G": ("clefs.G", -2, -6),
1908 "C": ("clefs.C", 0, 0),
1909 "F": ("clefs.F", 2, 6),
1912 def lisp_expression (self):
1914 (glyph, pos, c0) = self.clef_dict[self.type]
1918 (make-music 'SequentialMusic
1921 (make-property-set 'clefGlyph "%s") 'Staff)
1923 (make-property-set 'clefPosition %d) 'Staff)
1925 (make-property-set 'middleCPosition %d) 'Staff)))
1926 """ % (glyph, pos, c0)
1929 class Transposition (Music):
1930 def __init__ (self):
1931 Music.__init__ (self)
1933 def ly_expression (self):
1934 self.pitch._force_absolute_pitch = True
1935 return '\\transposition %s' % self.pitch.ly_expression ()
1937 class StaffChange (Music):
1938 def __init__ (self, staff):
1939 Music.__init__ (self)
1941 def ly_expression (self):
1943 return "\\change Staff=\"%s\"" % self.staff
1947 class SetEvent (Music):
1948 def __init__ (self, contextprop, value):
1949 Music.__init__ (self)
1950 self.context_prop = contextprop
1952 def ly_expression (self):
1954 return "\\set %s = %s" % (self.context_prop, self.value)
1958 class StaffLinesEvent (Music):
1959 def __init__ (self, lines):
1960 Music.__init__ (self)
1962 def ly_expression (self):
1963 if (self.lines > 0):
1964 return "\\stopStaff \\override Staff.StaffSymbol #'line-count = #%s \\startStaff" % self.lines
1966 return "\\stopStaff \\revert Staff.StaffSymbol #'line-count \\startStaff"
1968 class TempoMark (Music):
1969 def __init__ (self):
1970 Music.__init__ (self)
1971 self.baseduration = None
1972 self.newduration = None
1974 self.parentheses = False
1975 def set_base_duration (self, dur):
1976 self.baseduration = dur
1977 def set_new_duration (self, dur):
1978 self.newduration = dur
1979 def set_beats_per_minute (self, beats):
1981 def set_parentheses (self, parentheses):
1982 self.parentheses = parentheses
1983 def wait_for_note (self):
1985 def duration_to_markup (self, dur):
1987 # Generate the markup to print the note, use scheme mode for
1988 # ly_expression to get longa and not \longa (which causes an error)
1989 return "\\general-align #Y #DOWN \\smaller \\note #\"%s\" #UP" % dur.ly_expression(None, True)
1992 def tempo_markup_template (self):
1993 return "\\mark\\markup { \\fontsize #-2 \\line { %s } }"
1994 def ly_expression (self):
1996 if not self.baseduration:
1999 if self.parentheses:
2000 res += "\\tempo \"\" %s=%s" % (self.baseduration.ly_expression(), self.beats)
2002 res += "\\tempo %s=%s" % (self.baseduration.ly_expression(), self.beats)
2003 elif self.newduration:
2004 dm = self.duration_to_markup (self.baseduration)
2005 ndm = self.duration_to_markup (self.newduration)
2006 if self.parentheses:
2007 contents = "\"(\" %s = %s \")\"" % (dm, ndm)
2009 contents = " %s = %s " % (dm, ndm)
2010 res += self.tempo_markup_template() % contents
2015 class FiguredBassNote (Music):
2016 def __init__ (self):
2017 Music.__init__ (self)
2021 def set_prefix (self, prefix):
2022 self.prefix = prefix
2023 def set_suffix (self, suffix):
2024 self.prefix = suffix
2025 def set_number (self, number):
2026 self.number = number
2027 def ly_expression (self):
2040 class FiguredBassEvent (NestedMusic):
2041 def __init__ (self):
2042 NestedMusic.__init__ (self)
2043 self.duration = None
2044 self.real_duration = 0
2045 self.parentheses = False
2047 def set_duration (self, dur):
2049 def set_parentheses (self, par):
2050 self.parentheses = par
2051 def set_real_duration (self, dur):
2052 self.real_duration = dur
2054 def print_ly (self, printer):
2055 figured_bass_events = [e for e in self.elements if
2056 isinstance (e, FiguredBassNote)]
2057 if figured_bass_events:
2059 for x in figured_bass_events:
2060 notes.append (x.ly_expression ())
2061 contents = string.join (notes)
2062 if self.parentheses:
2063 contents = '[%s]' % contents
2064 printer ('<%s>' % contents)
2065 self.duration.print_ly (printer)
2068 class MultiMeasureRest(Music):
2070 def lisp_expression (self):
2073 'MultiMeasureRestMusicGroup
2075 (list (make-music (quote BarCheck))
2080 'MultiMeasureRestEvent
2083 (make-music (quote BarCheck))))
2084 """ % self.duration.lisp_expression ()
2086 def ly_expression (self):
2087 return 'R%s' % self.duration.ly_expression ()
2090 class Break (Music):
2091 def __init__ (self, tp="break"):
2092 Music.__init__ (self)
2094 def print_ly (self, printer):
2096 printer.dump ("\\%s" % self.type)
2099 def __init__ (self, command="StaffGroup"):
2100 self.stafftype = command
2102 self.instrument_name = None
2104 self.short_instrument_name = None
2108 self.is_group = True
2109 self.context_modifications = []
2110 # part_information is a list with entries of the form
2111 # [staffid, voicelist]
2112 # where voicelist is a list with entries of the form
2113 # [voiceid1, [lyricsid11, lyricsid12,...] ]
2114 self.part_information = None
2116 def append_staff (self, staff):
2117 self.children.append (staff)
2119 def set_part_information (self, part_name, staves_info):
2120 if part_name == self.id:
2121 self.part_information = staves_info
2123 for c in self.children:
2124 c.set_part_information (part_name, staves_info)
2126 def add_context_modification (self, modification):
2127 self.context_modifications.append (modification)
2129 def print_ly_contents (self, printer):
2130 for c in self.children:
2132 c.print_ly (printer)
2133 #Intention: I want to put the content of new StaffGroup in angled brackets (<< >>)
2134 #printer.dump ("test")# test is printed twice at the end of a staffgroup with two staves.
2135 #printer ("test") # test is printed twice at the end of a staffgroup with two staves.
2137 def needs_with (self):
2139 needs_with |= self.spanbar == "no"
2140 needs_with |= self.instrument_name != None
2141 needs_with |= self.short_instrument_name != None
2142 needs_with |= (self.symbol != None) and (self.symbol != "bracket")
2145 def print_ly_context_mods (self, printer):
2146 if self.instrument_name or self.short_instrument_name:
2147 printer.dump ("\\consists \"Instrument_name_engraver\"")
2148 if self.spanbar == "no":
2149 printer.dump ("\\override SpanBar #'transparent = ##t")
2150 brack = {"brace": "SystemStartBrace",
2152 "line": "SystemStartSquare"}.get (self.symbol, None)
2154 printer.dump ("systemStartDelimiter = #'%s" % brack)
2156 def print_ly_overrides (self, printer):
2157 needs_with = self.needs_with () | (len (self.context_modifications) > 0);
2159 printer.dump ("\\with {")
2160 self.print_ly_context_mods (printer)
2161 for m in self.context_modifications:
2163 printer.dump ("} <<")
2165 #print a single << after StaffGroup only when the with-block is not needed.
2166 #This doesn't work. << is printed before and after StaffGroup!
2168 # printer.dump (" <<")
2169 #prints loads off << before and after StaffGroup and before \set Staff.instrumentName
2170 #elif not needs_with:
2171 # printer.dump (" <<")
2173 def print_chords(self, printer):
2175 for [staff_id, voices] in self.part_information:
2176 for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
2178 printer ('\context ChordNames = "%s" {%s \\%s}' % (chordnames, get_transpose ("string"), chordnames))
2183 def print_fretboards(self, printer):
2185 for [staff_id, voices] in self.part_information:
2186 for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
2188 printer ('\context FretBoards = "%s" {%s \\%s}' % (fretboards, get_transpose ("string"), fretboards))
2193 def print_ly (self, printer):
2194 #prints two << before a StaffGroup, one after a StaffGroup and one before each \new Staff
2197 self.print_chords(printer)
2198 self.print_fretboards(printer)
2200 printer.dump ("\\new %s" % self.stafftype)
2203 # if there is a width-block << should not be printed after StaffGroup but after the width-block
2204 # this seems to work. It prints \new StaffGroup \with{} <<:
2205 # if self.stafftype == "StaffGroup" and self.print_ly_overrides:
2206 #prints a new line before each new staff type, e.g. before \new StaffGroup and \new Staff...
2208 # printer.dump("\\new %s" % self.stafftype)
2209 #self.print_ly_overrides (printer)
2210 #prints a << and a new line after each new staff type.
2211 # printer.dump ("<<")
2213 # print a << after all other staff types:
2214 # can't use "else:" because then we get a '\new None' staff type in LilyPond...
2215 # elif self.stafftype == "StaffGroup":
2216 # printer.dump ("\\new %s" % self.stafftype)
2217 # printer.dump ("<<")
2218 # printer.newline ()
2219 # << should be printed directly after StaffGroups without a with-block:
2220 # this doesn't work:
2221 # elif self.stafftype == "StaffGroup" and not self.print_ly_overrides:
2222 # printer.dump ("<<")
2223 # printer.newline ()
2225 # elif self.stafftype == "StaffGroup" and self.stafftype == "Staff":
2226 # printer.dump ("<<")
2227 # printer.newline ()
2228 # this prints \new Staff << for every staff in the score:
2229 # elif self.stafftype:
2230 # printer.dump ("\\new %s" % self.stafftype)
2231 # printer.dump ("<<")
2232 # printer.newline ()
2233 self.print_ly_overrides (printer)
2234 #printer.dump ("<<")
2236 if self.stafftype and self.instrument_name:
2237 printer.dump ("\\set %s.instrumentName = %s" % (self.stafftype,
2238 escape_instrument_string (self.instrument_name)))
2240 if self.stafftype and self.short_instrument_name:
2241 printer.dump ("\\set %s.shortInstrumentName = %s" % (self.stafftype,
2242 escape_instrument_string (self.short_instrument_name)))
2246 r'\set {stafftype}.midiInstrument = #"{sound}"'.format(
2247 stafftype=self.stafftype, sound=self.sound))
2248 self.print_ly_contents (printer)
2250 # This is a crude hack: In scores with staff groups the closing angled brackets are not printed.
2251 # That's why I added the following two lines. I couldn't find a proper solution. This won't work with scores several staff groups!!!
2252 if self.stafftype == "StaffGroup":
2254 #printer.dump (">>")
2255 #printer.dump (">>")
2257 #printer.dump ("test") #test is printed 4 times in a staffgroup with two staves: once at the end of each staff and twice at the end of the staffgroup. That's not what we want!
2258 #printer.dump ("test") NameError: name 'printer' is not defined
2261 # def print_staffgroup_closing_brackets (self, printer): #test see class Staff / Score.
2262 # printer.dump ("test")
2265 class Staff (StaffGroup):
2266 def __init__ (self, command="Staff"):
2267 StaffGroup.__init__ (self, command)
2268 self.is_group = False
2270 self.voice_command = "Voice"
2271 self.substafftype = None
2274 def needs_with (self):
2277 def print_ly_context_mods (self, printer):
2278 #printer.dump ("test") #does nothing.
2281 def print_ly_contents (self, printer):
2282 if not self.id or not self.part_information:
2284 sub_staff_type = self.substafftype
2285 if not sub_staff_type:
2286 sub_staff_type = self.stafftype
2287 #printer.dump ("test") #prints test in each staff after the definitions of the instrument name and before the definition of the contexts.
2290 for [staff_id, voices] in self.part_information:
2291 # now comes the real staff definition:
2293 printer ('\\context %s = "%s" << ' % (sub_staff_type, staff_id))
2295 printer ('\\context %s << ' % sub_staff_type)
2297 printer.dump("\mergeDifferentlyDottedOn\mergeDifferentlyHeadedOn")
2300 nr_voices = len (voices)
2301 for [v, lyrics, figuredbass, chordnames, fretboards] in voices:
2303 voice_count_text = ''
2306 The next line contains a bug: The voices might not appear in numerical order! Some voices might be missing e.g. if the xml file contains only voice one, three and four, this would result in: \voiceOne, \voiceTwo and \voiceThree. This causes wrong stem directions and collisions.
2308 voice_count_text = {1: ' \\voiceOne', 2: ' \\voiceTwo', 3: ' \\voiceThree'}.get (n, ' \\voiceFour')
2309 printer ('\\context %s = "%s" {%s %s \\%s }' % (self.voice_command, v, get_transpose ("string"), voice_count_text, v))
2313 printer ('\\new Lyrics \\lyricsto "%s" { \\set stanza = "%s." \\%s }' % (v, lyrics_id, l))
2317 printer ('\context FiguredBass = "%s" \\%s' % (figuredbass, figuredbass))
2319 #printer.dump ("test") #prints test after each definition of a context.
2321 #printer.dump ("test") #prints test after each definition of a context.
2323 def print_ly (self, printer):
2324 if self.part_information and len (self.part_information) > 1:
2325 self.stafftype = "PianoStaff"
2326 self.substafftype = "Staff"
2327 #printer.dump ('test')
2328 StaffGroup.print_ly (self, printer)
2329 #StaffGroup.print_staffgroup_closing_brackets (self, printer) prints test after each definition of a staff
2331 #printer.dump ("test") #prints test after each definition of a context.
2333 #StaffGroup.print_staffgroup_closing_brackets(self, printer) #prints test after each definition of a staff.
2334 #printer.dump ("test")# NameError: name 'printer' is not defined
2335 #StaffGroup.print_staffgroup_closing_brackets() #TypeError: unbound method print_staffgroup_closing_brackets() must be called with StaffGroup instance as first argument (got nothing instead)
2338 class TabStaff (Staff):
2339 def __init__ (self, command="TabStaff"):
2340 Staff.__init__ (self, command)
2341 self.string_tunings = []
2342 self.tablature_format = None
2343 self.voice_command = "TabVoice"
2344 def print_ly_overrides (self, printer):
2345 if self.string_tunings or self.tablature_format:
2346 printer.dump ("\\with {")
2347 if self.string_tunings:
2348 printer.dump ("stringTunings = #`(")
2349 for i in self.string_tunings:
2350 printer.dump (",%s" % i.lisp_expression ())
2352 if self.tablature_format:
2353 printer.dump ("tablatureFormat = #%s" % self.tablature_format)
2357 class DrumStaff (Staff):
2358 def __init__ (self, command="DrumStaff"):
2359 Staff.__init__ (self, command)
2360 self.drum_style_table = None
2361 self.voice_command = "DrumVoice"
2362 def print_ly_overrides (self, printer):
2363 if self.drum_style_table:
2364 printer.dump ("\with {")
2365 printer.dump ("drumStyleTable = #%s" % self.drum_style_table)
2368 class RhythmicStaff (Staff):
2369 def __init__ (self, command="RhythmicStaff"):
2370 Staff.__init__ (self, command)
2373 #def print_staffgroup_closing_brackets (self, printer): #test see class Score / class Staff
2374 # printer.dump ("test")
2377 def __init__ (self):
2379 Constructs a new Score object.
2381 self.contents = None
2382 self.create_midi = False
2384 def set_contents (self, contents):
2385 self.contents = contents
2387 def set_part_information (self, part_id, staves_info):
2389 self.contents.set_part_information (part_id, staves_info)
2391 def set_tempo (self, tempo):
2393 Set the tempo attribute of the Score.
2394 This attribute can be used in L{print_ly} for the midi output (see L{musicxml.Sound}).
2396 @param tempo: The value of the tempo, in beats per minute.
2401 # def print_staffgroup_closing_brackets (self, printer): #test see class Score / class Staff
2402 # printer.dump ("test")
2404 def print_ly (self, printer):
2406 Print the content of the score to the printer, in lilypond format.
2408 @param printer: A printer given to display correctly the output.
2409 @type printer: L{Output_printer<musicexp.Output_printer>}
2411 self.create_midi = get_create_midi()
2412 printer.dump("\\score {")
2418 self.contents.print_ly(printer)
2419 #printer.dump ("test") prints test once before the >> of the score block, independent of the existence of a staffgroup.
2420 #if StaffGroup == False: # True or False: nothing happens.
2421 # printer.dump ('>>')
2424 #StaffGroup.print_staffgroup_closing_brackets(self, printer) #TypeError: unbound method print_staffgroup_closing_brackets() must be called with StaffGroup instance as first argument (got Score instance instead)
2425 #print_staffgroup_closing_brackets(self, printer) #NameError: global name 'print_staffgroup_closing_brackets' is not defined. prints test once before the >> of the score block, independent of the existence of a staffgroup.
2426 printer.dump ("\\layout {}")
2428 # If the --midi option was not passed to musicxml2ly, that comments the "midi" line
2429 if self.create_midi:
2432 printer.dump("\\score {")
2434 printer.dump("\\unfoldRepeats \\articulate {")
2436 self.contents.print_ly(printer)
2440 printer.dump ("% To create MIDI output, uncomment the following line:")
2443 printer.dump ("\\midi {\\tempo 4 = "+self.tempo+" }")
2450 bflat.alteration = -1
2460 print bflat.semitones()
2461 print bflat.transposed (fifth), bflat.transposed (fifth).transposed (fifth)
2462 print bflat.transposed (fifth).transposed (fifth).transposed (fifth)
2464 print bflat.semitones(), 'down'
2465 print bflat.transposed (down)
2466 print bflat.transposed (down).transposed (down)
2467 print bflat.transposed (down).transposed (down).transposed (down)
2471 def test_printer ():
2479 m = SequentialMusic()
2480 m.append (make_note ())
2481 m.append (make_note ())
2482 m.append (make_note ())
2485 t = TimeScaledMusic ()
2491 m = SequentialMusic ()
2492 m.append (make_tup ())
2493 m.append (make_tup ())
2494 m.append (make_tup ())
2496 printer = Output_printer()
2497 m.print_ly (printer)
2501 m = SequentialMusic()
2505 n.duration.duration_log = l
2507 evc.insert_around (None, n, 0)
2508 m.insert_around (None, evc, 0)
2512 n.duration.duration_log = l
2514 evc.insert_around (None, n, 0)
2515 m.insert_around (None, evc, 0)
2519 n.duration.duration_log = l
2521 evc.insert_around (None, n, 0)
2522 m.insert_around (None, evc, 0)
2526 m.insert_around (None, evc, 0)
2531 tonic.alteration = -2
2532 n = KeySignatureChange()
2533 n.tonic = tonic.copy()
2534 n.scale = [0, 0, -2, 0, 0, -2, -2]
2536 evc.insert_around (None, n, 0)
2537 m.insert_around (None, evc, 0)
2542 if __name__ == '__main__':
2548 expr.set_start (Rational (0))
2549 print expr.ly_expression()
2550 start = Rational (0, 4)
2551 stop = Rational (4, 2)
2552 def sub(x, start=start, stop=stop):
2553 ok = x.start >= start and x.start + x.get_length() <= stop
2556 print expr.lisp_sub_expression(sub)