]> git.donarmstrong.com Git - lilypond.git/blobdiff - python/musicxml.py
Doc: NR 4.1.2: Nitpicks.
[lilypond.git] / python / musicxml.py
index 1ababbc7d5ba5dbee466f0deda33f5a57e1cd601..76e33ceb7b6792b5acb3615cfe50ae3a4d920730 100644 (file)
@@ -15,7 +15,7 @@ def error (str):
 
 def escape_ly_output_string (input_string):
     return_string = input_string
-    needs_quotes = not re.match (u"^[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
@@ -35,6 +35,13 @@ def musicxml_duration_to_log (dur):
              'longa': -2,
              'long': -2}.get (dur, 0)
 
+def interpret_alter_element (alter_elm):
+    alter = 0
+    if alter_elm:
+        val = eval(alter_elm.get_text ())
+        if type (val) in (int, float):
+            alter = val
+    return alter
 
 
 class Xml_node:
@@ -252,10 +259,7 @@ class Pitch (Music_xml_node):
 
     def get_alteration (self):
        ch = self.get_maybe_exist_typed_child (get_class (u'alter'))
-       alter = 0
-       if ch:
-           alter = int (ch.get_text ().strip ())
-       return alter
+       return interpret_alter_element (ch)
 
 class Unpitched (Music_xml_node):
     def get_step (self):
@@ -323,8 +327,8 @@ class Attributes (Measure_element):
 
     def get_measure_length (self):
         sig = self.get_time_signature ()
-        if len (sig) == 0:
-            return 0
+        if not sig or len (sig) == 0:
+            return 1
         if isinstance (sig[0], list):
             # Complex compound time signature
             l = 0
@@ -346,7 +350,7 @@ class Attributes (Measure_element):
         try:
             mxl = self.get_named_attribute ('time')
             if not mxl:
-                return (4, 4)
+                return None
 
             if mxl.get_maybe_exist_named_child ('senza-misura'):
                 # TODO: Handle pieces without a time signature!
@@ -363,17 +367,13 @@ class Attributes (Measure_element):
                         current_sig.append (int (i.get_text ()))
                         signature.append (current_sig)
                         current_sig = []
-                if len (signature) == 1 and isinstance (signature[0], list):
+                if isinstance (signature[0], list) and len (signature) == 1:
                     signature = signature[0]
-                if len (signature) ==0:
-                    error (_ ("requested time signature, but time sig is unknown"))
-                    return (4, 4)
                 self._time_signature_cache = signature
                 return signature
-        except KeyError:
-            error (_ ("requested time signature, but time sig is unknown"))
+        except (KeyError, ValueError):
+            self.message (_ ("Unable to interpret time signature! Falling back to 4/4."))
             return (4, 4)
-        #except 
 
     # returns clef information in the form ("cleftype", position, octave-shift)
     def get_clef_information (self):
@@ -393,22 +393,54 @@ class Attributes (Measure_element):
         return clefinfo
 
     def get_key_signature (self):
-        "return (fifths, mode) tuple"
+        "return (fifths, mode) tuple if the key signatures is given as "
+        "major/minor in the Circle of fifths. Otherwise return an alterations"
+        "list of the form [[step,alter<,octave>], [step,alter<,octave>], ...], "
+        "where the octave values are optional."
 
         key = self.get_named_attribute ('key')
-        mode_node = key.get_maybe_exist_named_child ('mode')
-        mode = None
-        if mode_node:
-            mode = mode_node.get_text ()
-        if not mode or mode == '':
-            mode = 'major'
-
-        fifths = int (key.get_maybe_exist_named_child ('fifths').get_text ())
-        return (fifths, mode)
-        
+        if not key:
+            return None
+        fifths_elm = key.get_maybe_exist_named_child ('fifths')
+        if fifths_elm:
+            mode_node = key.get_maybe_exist_named_child ('mode')
+            mode = None
+            if mode_node:
+                mode = mode_node.get_text ()
+            if not mode or mode == '':
+                mode = 'major'
+            fifths = int (fifths_elm.get_text ())
+            # TODO: Shall we try to convert the key-octave and the cancel, too?
+            return (fifths, mode)
+        else:
+            alterations = []
+            current_step = 0
+            for i in key.get_all_children ():
+                if isinstance (i, KeyStep):
+                    current_step = int (i.get_text ())
+                elif isinstance (i, KeyAlter):
+                    alterations.append ([current_step, interpret_alter_element (i)])
+                elif isinstance (i, KeyOctave):
+                    nr = -1
+                    if hasattr (i, 'number'):
+                        nr = int (i.number)
+                    if (nr > 0) and (nr <= len (alterations)):
+                        # MusicXML Octave 4 is middle C -> shift to 0
+                        alterations[nr-1].append (int (i.get_text ())-4)
+                    else:
+                        i.message (_ ("Key alteration octave given for a "
+                            "non-existing alteration nr. %s, available numbers: %s!") % (nr, len(alterations)))
+            return alterations
+
     def get_transposition (self):
         return self.get_named_attribute ('transpose')
-        
+
+class KeyAlter (Music_xml_node):
+    pass
+class KeyStep (Music_xml_node):
+    pass
+class KeyOctave (Music_xml_node):
+    pass
 
 
 class Barline (Measure_element):
@@ -507,6 +539,8 @@ class Syllabic (Music_xml_node):
         return (text == "begin") or (text == "middle")
 class Elision (Music_xml_node):
     pass
+class Extend (Music_xml_node):
+    pass
 class Text (Music_xml_node):
     pass
 
@@ -794,7 +828,7 @@ class Part (Music_xml_node):
            if not (isinstance (n, Note) or isinstance (n, Attributes) or
                     isinstance (n, Direction) or isinstance (n, Partial) or
                     isinstance (n, Barline) or isinstance (n, Harmony) or
-                    isinstance (n, FiguredBass) ):
+                    isinstance (n, FiguredBass) or isinstance (n, Print)):
                continue
 
            if isinstance (n, Attributes) and not start_attr:
@@ -810,7 +844,7 @@ class Part (Music_xml_node):
                             voices[v].add_element (staff_attributes)
                 continue
 
-            if isinstance (n, Partial) or isinstance (n, Barline):
+            if isinstance (n, Partial) or isinstance (n, Barline) or isinstance (n, Print):
                 for v in voices.keys ():
                     voices[v].add_element (n)
                 continue
@@ -963,7 +997,10 @@ class Beam (Music_xml_spanner):
     def get_type (self):
        return self.get_text ()
     def is_primary (self):
-        return self.number == "1"
+        if hasattr (self, 'number'):
+            return self.number == "1"
+        else:
+            return True
 
 class Wavy_line (Music_xml_spanner):
     pass
@@ -1029,10 +1066,7 @@ class DirType (Music_xml_node):
 class Bend (Music_xml_node):
     def bend_alter (self):
         alter = self.get_maybe_exist_named_child ('bend-alter')
-        if alter:
-            return alter.get_text()
-        else:
-            return 0
+        return interpret_alter_element (alter)
 
 class Words (Music_xml_node):
     pass
@@ -1050,10 +1084,7 @@ class ChordPitch (Music_xml_node):
         return ch.get_text ().strip ()
     def get_alteration (self):
         ch = self.get_maybe_exist_typed_child (get_class (self.alter_class_name ()))
-        alter = 0
-        if ch:
-            alter = int (ch.get_text ().strip ())
-        return alter
+        return interpret_alter_element (ch)
 
 class Root (ChordPitch):
     pass
@@ -1076,10 +1107,7 @@ class ChordModification (Music_xml_node):
         return value
     def get_alter (self):
         ch = self.get_maybe_exist_typed_child (get_class (u'degree-alter'))
-        value = 0
-        if ch:
-            value = int (ch.get_text ().strip ())
-        return value
+        return interpret_alter_element (ch)
 
 
 class Frame (Music_xml_node):
@@ -1122,6 +1150,9 @@ class BeatUnitDot (Music_xml_node):
 class PerMinute (Music_xml_node):
     pass
 
+class Print (Music_xml_node):
+    pass
+
 
 
 ## need this, not all classes are instantiated
@@ -1150,6 +1181,7 @@ class_dict = {
         'direction-type': DirType,
        'duration': Duration,
         'elision': Elision,
+        'extend': Extend,
         'frame': Frame,
         'frame-note': Frame_Note,
         'figured-bass': FiguredBass,
@@ -1157,6 +1189,9 @@ class_dict = {
        'grace': Grace,
         'harmony': Harmony,
         'identification': Identification,
+        'key-alter': KeyAlter,
+        'key-octave': KeyOctave,
+        'key-step': KeyStep,
         'lyric': Lyric,
        'measure': Measure,
        'notations': Notations,
@@ -1168,6 +1203,7 @@ class_dict = {
         'pedal': Pedal,
         'per-minute': PerMinute,
        'pitch': Pitch,
+        'print': Print,
        'rest': Rest,
         'root': Root,
         'score-part': Score_part,