]> git.donarmstrong.com Git - lilypond.git/commitdiff
MusicXML: Fix graces to allow beams, chords, etc.
authorReinhold Kainhofer <reinhold@kainhofer.com>
Fri, 21 Sep 2007 07:40:11 +0000 (09:40 +0200)
committerReinhold Kainhofer <reinhold@kainhofer.com>
Wed, 3 Oct 2007 16:40:08 +0000 (18:40 +0200)
Instead of keeping an array of grace elements for each chord,
rather use a full SequentialMusic object that holds EventChords
(so we can insert beams, real grace chords, etc.). For this we also
need a method in the SequentialMusic class to get the last chord.
Depending on the slash attribute of the <grace> element, we now
use acciaccatura rather than grace for slashed grace notes.

Signed-off-by: Reinhold Kainhofer <reinhold@kainhofer.com>
python/musicexp.py
scripts/musicxml2ly.py

index 45a2e6d4c8ed832297cb191afabe578ac82e81e6..9c6e2341f3b01073aba34b146f61fd322b90b985 100644 (file)
@@ -393,17 +393,31 @@ class NestedMusic(Music):
         return None
         
 class SequentialMusic (NestedMusic):
-    def print_ly (self, printer):
+    def get_last_event_chord (self):
+        value = None
+        at = len( self.elements ) - 1
+        while (at >= 0 and
+               not isinstance (self.elements[at], EventChord) and
+               not isinstance (self.elements[at], BarCheck)):
+            at -= 1
+
+        if (at >= 0 and isinstance (self.elements[at], EventChord)):
+            value = self.elements[at]
+        return value
+
+    def print_ly (self, printer, newline = True):
         printer ('{')
         if self.comment:
             self.print_comment (printer)
 
-        printer.newline()
+        if newline:
+            printer.newline()
         for e in self.elements:
             e.print_ly (printer)
 
         printer ('}')
-        printer.newline()
+        if newline:
+            printer.newline()
             
     def lisp_sub_expression (self, pred):
         name = self.name()
@@ -459,9 +473,12 @@ class Header:
 class EventChord (NestedMusic):
     def __init__ (self):
         NestedMusic.__init__ (self)
-        self.grace_elements = []
+        self.grace_elements = None
+        self.grace_type = None
     def append_grace (self, element):
         if element:
+            if not self.grace_elements:
+                self.grace_elements = SequentialMusic ()
             self.grace_elements.append (element)
 
     def get_length (self):
@@ -482,10 +499,12 @@ class EventChord (NestedMusic):
                 not isinstance (e, RhythmicEvent)]
 
         if self.grace_elements and self.elements:
-            printer ('\grace {')
-            for g in self.grace_elements:
-                g.print_ly (printer)
-            printer ('}')
+            if self.grace_type:
+                printer ('\\%s' % self.grace_type)
+            else:
+                printer ('\\grace')
+            # don't print newlines after the { and } braces
+            self.grace_elements.print_ly (printer, False)
 
         if rest_events:
             rest_events[0].print_ly (printer)
index 985ffa45c9a808fdfb0e3db4c67b9da9c833864d..9502e16bc602ce5441333e5e15d923695ba0ba1c 100644 (file)
@@ -683,15 +683,32 @@ def musicxml_voice_to_lily_voice (voice):
         if not ev_chord: 
             ev_chord = musicexp.EventChord()
             voice_builder.add_music (ev_chord, n._duration)
-        # When a note/chord has grace notes (duration==0), the duration of the 
-        # event chord is not yet known, but the event chord was already added
-        # with duration 0. The following correct this when we hit the real note!
-        if voice_builder.current_duration () == 0 and n._duration > 0:
-            voice_builder.set_duration (n._duration)
-        if n.get_maybe_exist_typed_child (musicxml.Grace):
-            ev_chord.append_grace (main_event)
+
+        grace = n.get_maybe_exist_typed_child (musicxml.Grace)
+        if grace:
+            grace_chord = None
+            if n.get_maybe_exist_typed_child (musicxml.Chord) and ev_chord.grace_elements:
+                grace_chord = ev_chord.grace_elements.get_last_event_chord ()
+            if not grace_chord:
+                grace_chord = musicexp.EventChord ()
+                ev_chord.append_grace (grace_chord)
+            if hasattr (grace, 'slash'):
+                # TODO: use grace_type = "appoggiatura" for slurred grace notes
+                if grace.slash == "yes":
+                    ev_chord.grace_type = "acciaccatura"
+                elif grace.slash == "no":
+                    ev_chord.grace_type = "grace"
+            # now that we have inserted the chord into the grace music, insert
+            # everything into that chord instead of the ev_chord
+            ev_chord = grace_chord
+            ev_chord.append (main_event)
         else:
             ev_chord.append (main_event)
+            # When a note/chord has grace notes (duration==0), the duration of the
+            # event chord is not yet known, but the event chord was already added
+            # with duration 0. The following correct this when we hit the real note!
+            if voice_builder.current_duration () == 0 and n._duration > 0:
+                voice_builder.set_duration (n._duration)
         
         notations = n.get_maybe_exist_typed_child (musicxml.Notations)
         tuplet_event = None