From: Reinhold Kainhofer Date: Fri, 8 Feb 2008 19:26:38 +0000 (+0100) Subject: MusicXML: Implement rehearsal marks and some more spanners X-Git-Tag: release/2.11.40-1~3^2~20^2~7^2~1 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=6ff000344cd3abfb8be088945913df7de5da01a7;p=lilypond.git MusicXML: Implement rehearsal marks and some more spanners -) Implement dashes (\startTextSpan and \stopTextSpan) and bracket (although I'll still need to add the bracket engraver, since I use \startGroup and \stopGroup, which does not automatically print the bracket) -) Pedal change is now implemented as \sustainUp\sustainDown -) Add MarkEvent and MusicGlyphMarkEvent to convert rehearsal marks and segno/coda markups. Rehearsal marks can also be boxed (default) or circled -) Revamp the way directions are converted. Now they also use a dict like the notations, where one can give a general conversion function, or a finished class --- diff --git a/python/musicexp.py b/python/musicexp.py index 07e4f5d792..7aa45b1a99 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -794,12 +794,24 @@ class BeamEvent (SpanEvent): class PedalEvent (SpanEvent): def ly_expression (self): return {-1: '\\sustainDown', + 0:'\\sustainUp\\sustainDown', 1:'\\sustainUp'}.get (self.span_direction, '') +class TextSpannerEvent (SpanEvent): + def ly_expression (self): + return {-1: '\\startTextSpan', + 1:'\\stopTextSpan'}.get (self.span_direction, '') + +class BracketSpannerEvent (SpanEvent): + def ly_expression (self): + return {-1: '\\startGroup', + 1:'\\stopGroup'}.get (self.span_direction, '') + + # type==-1 means octave up, type==-2 means octave down class OctaveShiftEvent (SpanEvent): def wait_for_note (self): - return False; + return False def set_span_type (self, type): self.span_type = {'up': 1, 'down': -1}.get (type, 0) def ly_octave_shift_indicator (self): @@ -839,7 +851,7 @@ class ArpeggioEvent(Event): Event.__init__ (self) self.direction = 0 def wait_for_note (self): - return True; + return True def ly_expression (self): # TODO: Use self.direction for up/down arpeggios return ('\\arpeggio') @@ -873,17 +885,37 @@ class DynamicsEvent (Event): def __init__ (self): self.type = None def wait_for_note (self): - return True; + return True def ly_expression (self): if self.type: return '\%s' % self.type else: - return; + return def print_ly (self, printer): if self.type: printer.dump ("\\%s" % self.type) +class MarkEvent (Event): + def __init__ (self, text="\\default"): + self.mark = text + def wait_for_note (self): + return False + def ly_contents (self): + if self.mark: + return '%s' % self.mark + else: + return "\"ERROR\"" + def ly_expression (self): + return '\\mark %s' % self.ly_contents () + +class MusicGlyphMarkEvent (MarkEvent): + def ly_contents (self): + if self.mark: + return '\\markup { \\musicglyph #"scripts.%s" }' % self.mark + else: + return '' + class TextEvent (Event): def __init__ (self): @@ -907,7 +939,7 @@ class ArticulationEvent (Event): self.type = None self.force_direction = None def wait_for_note (self): - return True; + return True def direction_mod (self): return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '') diff --git a/python/musicxml.py b/python/musicxml.py index 3074ee5b41..53fc9ffb54 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -751,6 +751,12 @@ class Wedge (Music_xml_spanner): class Tuplet (Music_xml_spanner): pass +class Bracket (Music_xml_spanner): + pass + +class Dashes (Music_xml_spanner): + pass + class Slur (Music_xml_spanner): def get_type (self): return self.type @@ -867,7 +873,9 @@ class_dict = { 'bar-style': BarStyle, 'beam' : Beam, 'bend' : Bend, + 'bracket' : Bracket, 'chord': Chord, + 'dashes' : Dashes, 'dot': Dot, 'direction': Direction, 'direction-type': DirType, diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index cf0318434a..ebad1a51d5 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -705,12 +705,14 @@ def musicxml_barline_to_lily (barline): return retval.values () spanner_event_dict = { - 'slur' : musicexp.SlurEvent, 'beam' : musicexp.BeamEvent, + 'dashes' : musicexp.TextSpannerEvent, + 'bracket' : musicexp.BracketSpannerEvent, 'glissando' : musicexp.GlissandoEvent, + 'octave-shift' : musicexp.OctaveShiftEvent, 'pedal' : musicexp.PedalEvent, + 'slur' : musicexp.SlurEvent, 'wavy-line' : musicexp.TrillSpanEvent, - 'octave-shift' : musicexp.OctaveShiftEvent, 'wedge' : musicexp.HairpinEvent } spanner_type_dict = { @@ -720,6 +722,7 @@ spanner_type_dict = { 'decreschendo': -1, 'diminuendo': -1, 'continue': 0, + 'change': 0, 'up': -1, 'down': -1, 'stop': 1, @@ -1023,16 +1026,76 @@ def musicxml_words_to_lily_event (words): return event -direction_spanners = [ 'octave-shift', 'pedal', 'wedge' ] + +def musicxml_rehearsal_to_ly_mark (mxl_event): + text = mxl_event.get_text () + if not text: + return + # default is boxed rehearsal marks! + encl = "box" + if hasattr (mxl_event, 'enclosure'): + encl = {"none": None, "square": "box", "circle": "circle" }.get (mxl_event.enclosure, None) + if encl: + text = "\\%s { %s }" % (encl, text) + ev = musicexp.MarkEvent ("\\markup { %s }" % text) + return ev + + +# translate directions into Events, possible values: +# -) string (MarkEvent with that command) +# -) function (function(mxl_event) needs to return a full Event-derived object +# -) (class, name) (like string, only that a different class than MarkEvent is used) +directions_dict = { +# 'accordion-registration' : musicxml_accordion_to_ly, + 'coda' : (musicexp.MusicGlyphMarkEvent, "coda"), +# 'damp' : ??? +# 'damp-all' : ??? +# 'eyeglasses': ?????? +# 'harp-pedals' : +# 'image' : +# 'metronome' : + 'rehearsal' : musicxml_rehearsal_to_ly_mark, +# 'scordatura' : + 'segno' : (musicexp.MusicGlyphMarkEvent, "segno"), + 'words' : musicxml_words_to_lily_event, +} +directions_spanners = [ 'octave-shift', 'pedal', 'wedge', 'dashes', 'bracket' ] def musicxml_direction_to_lily (n): # TODO: Handle the element! res = [] + # placement applies to all children! + dir = None + if hasattr (n, 'placement') and options.convert_directions: + dir = musicxml_direction_to_indicator (n.placement) dirtype_children = [] + # TODO: The direction-type is used for grouping (e.g. dynamics with text), + # so we can't simply flatten them out! for dt in n.get_typed_children (musicxml.DirType): dirtype_children += dt.get_all_children () for entry in dirtype_children: + # backets, dashes, octave shifts. pedal marks, hairpins etc. are spanners: + if entry.get_name() in directions_spanners: + event = musicxml_spanner_to_lily_event (entry) + if event: + res.append (event) + continue + + # now treat all the "simple" ones, that can be translated using the dict + ev = None + tmp_tp = directions_dict.get (entry.get_name (), None) + if isinstance (tmp_tp, str): # string means MarkEvent + ev = musicexp.MarkEvent (tmp_tp) + elif isinstance (tmp_tp, tuple): # tuple means (EventClass, "text") + ev = tmp_tp[0] (tmp_tp[1]) + elif tmp_tp: + ev = tmp_tp (entry) + if ev: + # TODO: set the correct direction! Unfortunately, \mark in ly does + # not seem to support directions! + res.append (ev) + continue if entry.get_name () == "dynamics": for dynentry in entry.get_all_children (): @@ -1040,18 +1103,6 @@ def musicxml_direction_to_lily (n): if ev: res.append (ev) - if entry.get_name () == "words": - ev = musicxml_words_to_lily_event (entry) - if ev: - res.append (ev) - - # octave shifts. pedal marks, hairpins etc. are spanners: - if entry.get_name() in direction_spanners: - event = musicxml_spanner_to_lily_event (entry) - if event: - res.append (event) - - return res def musicxml_frame_to_lily_event (frame):