X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=python%2Fmusicxml.py;h=76e33ceb7b6792b5acb3615cfe50ae3a4d920730;hb=51062dd7ec2e2cce5000b4c1e56173b1f0b4ee16;hp=1ababbc7d5ba5dbee466f0deda33f5a57e1cd601;hpb=ffd4b1434da640477729308ca47c121d12f008e5;p=lilypond.git diff --git a/python/musicxml.py b/python/musicxml.py index 1ababbc7d5..76e33ceb7b 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -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,