]> git.donarmstrong.com Git - lilypond.git/commitdiff
MusicXML: convert score information into the \header{..} construct in lilypond.
authorReinhold Kainhofer <reinhold@kainhofer.com>
Fri, 24 Aug 2007 22:23:52 +0000 (00:23 +0200)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Sat, 1 Sep 2007 03:07:33 +0000 (00:07 -0300)
Also fix problem that \breathe does not accept any direction modifyer
Convert some more ornaments

python/musicxml.py
scripts/musicxml2ly.py

index f7b962dba8ff929d8df54b83232faf38e7dade7a..2056805aeee13accd26da2173f1404c5019b18b5 100644 (file)
@@ -82,6 +82,74 @@ class Music_xml_node (Xml_node):
        self.duration = Rational (0)
        self.start = Rational (0)
 
+class Work (Xml_node):
+    def get_work_information (self, tag):
+        wt = self.get_maybe_exist_named_child (tag)
+        if wt:
+            return wt.get_text ()
+        else:
+            return self.get_text ()
+      
+    def get_work_title (self):
+        return self.get_work_information ('work-title')
+    def get_work_number (self):
+        return self.get_work_information ('work-number')
+    def get_opus (self):
+        return self.get_work_information ('opus')
+
+class Identification (Xml_node):
+    def get_rights (self):
+        rights = self.get_maybe_exist_named_child ('rights')
+        if rights:
+            return rights.get_text ()
+        else:
+            return ''
+
+    def get_creator (self, type):
+        creators = self.get_named_children ('creator')
+        # return the first creator tag that has type 'editor'
+        for i in creators:
+            if hasattr (i, 'type') and i.type == type:
+                return i.get_text ()
+            else:
+                return ''
+
+    def get_composer (self):
+        c = self.get_creator ('composer')
+        if c:
+            return c
+        creators = self.get_named_children ('creator')
+        # return the first creator tag that has no type at all
+        for i in creators:
+            if not hasattr (i, 'type'):
+                return i.get_text ()
+        return c
+    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')
+    
+    def get_encoding_information (self, type):
+        enc = self.get_named_children ('encoding')
+        if enc:
+            children = enc[0].get_named_children (type)
+            if children:
+                return children[0].get_text ()
+        else:
+            return ''
+      
+    def get_encoding_software (self):
+        return self.get_encoding_information ('software')
+    def get_encoding_date (self):
+        return self.get_encoding_information ('encoding-date')
+    def get_encoding_person (self):
+        return self.get_encoding_information ('encoder')
+    def get_encoding_description (self):
+        return self.get_encoding_information ('encoding-description')
+      
+
 
 class Duration (Music_xml_node):
     def get_length (self):
@@ -483,6 +551,14 @@ class DirType (Music_xml_node):
 class Wedge (Music_xml_node):
     pass
 
+class Creator (Music_xml_node):
+    pass
+class Rights (Music_xml_node):
+    pass
+class Encoding (Music_xml_node):
+    pass
+class WorkTitle (Music_xml_node):
+    pass
 
 ## need this, not all classes are instantiated
 ## for every input file.
@@ -522,7 +598,15 @@ class_dict = {
         'direction': Direction,
         'direction-type': DirType,
         'dynamics': Dynamics,
-        'wedge': Wedge
+        'wedge': Wedge,
+        
+        'identification': Identification,
+        'creator': Creator,
+        'rights': Rights,
+        'encoding': Encoding,
+        'work': Work,
+        'work-title': WorkTitle
+        
 }
 
 def name2class_name (name):
index 9e48b1f53ebfc2b936862c5c95042e40df3457a0..45ffbb8c88e497d4c482dc6143e0d85067bea066 100644 (file)
@@ -24,6 +24,59 @@ def progress (str):
     sys.stderr.flush ()
     
 
+# score information is contained in the <work>, <identification> or <movement-title> tags
+# extract those into a hash, indexed by proper lilypond header attributes
+def extract_score_information (tree):
+    score_information = {}
+    work = tree.get_maybe_exist_named_child ('work')
+    if work:
+        if work.get_work_title ():
+            score_information['title'] = work.get_work_title ()
+        if work.get_work_number ():
+            score_information['worknumber'] = work.get_work_number ()
+        if work.get_opus ():
+            score_information['opus'] = work.get_opus ()
+    else:
+        movement_title = tree.get_maybe_exist_named_child ('movement-title')
+        if movement_title:
+            score_information['title'] = movement_title.get_text ()
+    
+    identifications = tree.get_named_children ('identification')
+    for ids in identifications:
+        if ids.get_rights ():
+            score_information['copyright'] = ids.get_rights ()
+        if ids.get_composer ():
+            score_information['composer'] = ids.get_composer ()
+        if ids.get_arranger ():
+            score_information['arranger'] = ids.get_arranger ()
+        if ids.get_editor ():
+            score_information['editor'] = ids.get_editor ()
+        if ids.get_poet ():
+            score_information['poet'] = ids.get_poet ()
+            
+        if ids.get_encoding_software ():
+            score_information['tagline'] = ids.get_encoding_software ()
+            score_information['encodingsoftware'] = ids.get_encoding_software ()
+        if ids.get_encoding_date ():
+            score_information['encodingdate'] = ids.get_encoding_date ()
+        if ids.get_encoding_person ():
+            score_information['encoder'] = ids.get_encoding_person ()
+        if ids.get_encoding_description ():
+            score_information['encodingdescription'] = ids.get_encoding_description ()
+
+    return score_information
+
+def print_ly_information (printer, score_information):
+    printer.dump ('\header {')
+    printer.newline ()
+    for k in score_information.keys ():
+        printer.dump ('%s = "%s"' % (k, score_information[k]))
+        printer.newline ()
+    printer.dump ('}')
+    printer.newline ()
+    printer.newline ()
+    
+
 def musicxml_duration_to_lily (mxl_note):
     d = musicexp.Duration ()
     if mxl_note.get_maybe_exist_typed_child (musicxml.Type):
@@ -198,12 +251,12 @@ articulations_dict = {
     #"shake": "?", 
     #"wavy-line": "?", 
     "mordent": "mordent",
-    #"inverted-mordent": "?", 
+    "inverted-mordent": "downmordent", 
     #"schleifer": "?" 
     ##### TECHNICALS
     "up-bow": "upbow", 
     "down-bow": "downbow", 
-    #"harmonic": "", 
+    "harmonic": "flageolet", 
     #"open-string": "", 
     #"thumb-position": "", 
     #"fingering": "", 
@@ -253,7 +306,8 @@ def musicxml_articulation_to_lily_event(mxl_event):
         dir = musicxml_direction_to_indicator (mxl_event.type)
     if hasattr (mxl_event, 'placement'):
         dir = musicxml_direction_to_indicator (mxl_event.placement)
-    if dir:
+    # \breathe cannot have any direction modifyer (^, _, -)!
+    if dir and tp != "breathe":
         ev.force_direction = dir
     return ev
 
@@ -799,6 +853,8 @@ def convert (filename, options):
         mxl_pl = tree.get_maybe_exist_typed_child (musicxml.Part_list)
         part_list = mxl_pl.get_named_children ("score-part")
         
+    # score information is contained in the <work>, <identification> or <movement-title> tags
+    score_information = extract_score_information (tree)
     parts = tree.get_typed_children (musicxml.Part)
     voices = get_all_voices (parts)
 
@@ -815,6 +871,7 @@ def convert (filename, options):
     printer.set_file (open (defs_ly_name, 'w'))
 
     print_ly_preamble (printer, filename)
+    print_ly_information (printer, score_information)
     print_voice_definitions (printer, part_list, voices)
     
     printer.close ()