]> git.donarmstrong.com Git - lilypond.git/blobdiff - python/musicxml.py
MusicXML: A grace note at the beginning shall not set staff for the voice
[lilypond.git] / python / musicxml.py
index 6234459187c71c7556e7f1e3cf6ae3537c2556f8..9788d9745dd9fda26d898660bb13af0634bd168e 100644 (file)
@@ -2,10 +2,11 @@ import new
 import string
 from rational import *
 import re
+import sys
 
 def escape_ly_output_string (input_string):
     return_string = input_string
-    needs_quotes = not re.match ("^[a-zA-ZäöüÜÄÖßñ]*$", return_string);
+    needs_quotes = not re.match (u"^[a-zA-ZäöüÜÄÖßñ]*$", return_string);
     if needs_quotes:
         return_string = "\"" + string.replace (return_string, "\"", "\\\"") + "\""
     return return_string
@@ -41,11 +42,11 @@ class Xml_node:
        return ''.join ([c.get_text () for c in self._children])
 
     def message (self, msg):
-        print msg
+        sys.stderr.write (msg+'\n')
 
         p = self
         while p:
-            print '  In: <%s %s>' % (p._name, ' '.join (['%s=%s' % item for item in p._attribute_dict.items()]))
+            sys.stderr.write ('  In: <%s %s>\n' % (p._name, ' '.join (['%s=%s' % item for item in p._attribute_dict.items()])))
             p = p.get_parent ()
         
     def get_typed_children (self, klass):
@@ -81,7 +82,7 @@ class Xml_node:
     def get_unique_typed_child (self, klass):
        cn = self.get_typed_children(klass)
        if len (cn) <> 1:
-           print self.__dict__ 
+           sys.stderr.write (self.__dict__ + '\n')
            raise 'Child is not unique for', (klass, 'found', cn)
 
        return cn[0]
@@ -121,8 +122,7 @@ class Identification (Xml_node):
         for i in creators:
             if hasattr (i, 'type') and i.type == type:
                 return i.get_text ()
-            else:
-                return ''
+        return None
 
     def get_composer (self):
         c = self.get_creator ('composer')
@@ -133,13 +133,17 @@ class Identification (Xml_node):
         for i in creators:
             if not hasattr (i, 'type'):
                 return i.get_text ()
-        return c
+        return None
     def get_arranger (self):
         return self.get_creator ('arranger')
     def get_editor (self):
         return self.get_creator ('editor')
     def get_poet (self):
-        return self.get_creator ('poet')
+        v = self.get_creator ('lyricist')
+        if v:
+            return v
+        v = self.get_creator ('poet')
+        return v
     
     def get_encoding_information (self, type):
         enc = self.get_named_children ('encoding')
@@ -148,7 +152,7 @@ class Identification (Xml_node):
             if children:
                 return children[0].get_text ()
         else:
-            return ''
+            return None
       
     def get_encoding_software (self):
         return self.get_encoding_information ('software')
@@ -225,13 +229,15 @@ class Attributes (Measure_element):
 
         try:
             mxl = self.get_named_attribute ('time')
-            
-            beats = mxl.get_maybe_exist_named_child ('beats')
-            type = mxl.get_maybe_exist_named_child ('beat-type')
-            return (int (beats.get_text ()),
-                    int (type.get_text ()))
+            if mxl:
+                beats = mxl.get_maybe_exist_named_child ('beats')
+                type = mxl.get_maybe_exist_named_child ('beat-type')
+                return (int (beats.get_text ()),
+                        int (type.get_text ()))
+            else:
+                return (4, 4)
         except KeyError:
-            print 'error: requested time signature, but time sig unknown'
+            sys.stderr.write ('error: requested time signature, but time sig unknown\n')
             return (4, 4)
 
     # returns clef information in the form ("cleftype", position, octave-shift)
@@ -320,8 +326,13 @@ class Part_list (Music_xml_node):
         if instrument_name:
             return instrument_name
         else:
-            print "Opps, couldn't find instrument for ID=", id
+            sys.stderr.write ("Opps, couldn't find instrument for ID=%s\n" % id)
             return "Grand Piano"
+
+class Part_group (Music_xml_node):
+    pass
+class Score_part (Music_xml_node):
+    pass
         
 class Measure (Music_xml_node):
     def get_notes (self):
@@ -381,7 +392,7 @@ class Musicxml_voice:
            and e.get_maybe_exist_typed_child (Staff)):
            name = e.get_maybe_exist_typed_child (Staff).get_text ()
 
-           if not self._start_staff:
+           if not self._start_staff and not e.get_maybe_exist_typed_child (Grace):
                self._start_staff = name
            self._staves[name] = True
 
@@ -477,6 +488,16 @@ class Part (Music_xml_node):
                     last_measure_position = measure_position
                     now += dur
                     measure_position += dur
+                elif dur < Rational (0):
+                    # backup element, reset measure position
+                    now += dur
+                    measure_position += dur
+                    if measure_position < 0:
+                        # backup went beyond the measure start => reset to 0
+                        now -= measure_position
+                        measure_position = 0
+                    last_moment = now
+                    last_measure_position = measure_position
                 if n._name == 'note':
                     instrument = n.get_maybe_exist_named_child ('instrument')
                     if instrument:
@@ -612,12 +633,28 @@ class Chord (Music_xml_node):
 class Dot (Music_xml_node):
     pass
 
+# Rests in MusicXML are <note> blocks with a <rest> inside. This class is only
+# for the inner <rest> element, not the whole rest block.
 class Rest (Music_xml_node):
     def __init__ (self):
         Music_xml_node.__init__ (self)
         self._is_whole_measure = False
     def is_whole_measure (self):
         return self._is_whole_measure
+    def get_step (self):
+        ch = self.get_maybe_exist_typed_child (get_class (u'display-step'))
+        if ch:
+            step = ch.get_text ().strip ()
+            return step
+        else:
+            return None
+    def get_octave (self):
+        ch = self.get_maybe_exist_typed_child (get_class (u'display-octave'))
+        if ch:
+            step = ch.get_text ().strip ()
+            return int (step)
+        else:
+            return None
 
 class Type (Music_xml_node):
     pass
@@ -665,10 +702,12 @@ class_dict = {
        'note': Note,
         'octave-shift': Octave_shift,
        'part': Part,
+    'part-group': Part_group,
        'part-list': Part_list,
         'pedal': Pedal,
        'pitch': Pitch,
        'rest': Rest,
+    'score-part': Score_part,
        'slur': Slur,
        'staff': Staff,
         'syllabic': Syllabic,