]> git.donarmstrong.com Git - lilypond.git/blobdiff - scripts/musicxml2ly.py
Merge branch 'master' into lilypond/translation
[lilypond.git] / scripts / musicxml2ly.py
index 33c0aca03925e8830ff73a6178b18c259aaabae1..ba7be37a65f025d71dd24164803af20af35aab52 100644 (file)
@@ -308,6 +308,7 @@ def extract_score_information (tree):
         # Case 1: "Sibelius 5.1" with the "Dolet 3.4 for Sibelius" plugin
         #         is missing all beam ends => ignore all beaming information
         ignore_beaming_software = {
+            "Dolet 4 for Sibelius, Beta 2": "Dolet 4 for Sibelius, Beta 2",
             "Dolet 3.5 for Sibelius": "Dolet 3.5 for Sibelius",
             "Dolet 3.4 for Sibelius": "Dolet 3.4 for Sibelius",
             "Dolet 3.3 for Sibelius": "Dolet 3.3 for Sibelius",
@@ -930,6 +931,30 @@ def musicxml_attributes_to_lily (attrs):
                 elts.append (ev)
     
     return elts
+    
+def musicxml_print_to_lily (el):
+    # TODO: Implement other print attributes
+    #  <!ELEMENT print (page-layout?, system-layout?, staff-layout*,
+    #          measure-layout?, measure-numbering?, part-name-display?, 
+    #          part-abbreviation-display?)>
+    #  <!ATTLIST print
+    #      staff-spacing %tenths; #IMPLIED
+    #      new-system %yes-no; #IMPLIED
+    #      new-page %yes-no-number; #IMPLIED
+    #      blank-page NMTOKEN #IMPLIED
+    #      page-number CDATA #IMPLIED 
+    #  >
+    elts = []
+    if (hasattr (el, "new-system") and conversion_settings.convert_page_layout):
+        val = getattr (el, "new-system")
+        if (val == "yes"):
+            elts.append (musicexp.Break ("break"))
+    if (hasattr (el, "new-page") and conversion_settings.convert_page_layout):
+        val = getattr (el, "new-page")
+        if (val == "yes"):
+            elts.append (musicexp.Break ("pageBreak"))
+    return elts
+
 
 class Marker (musicexp.Music):
     def __init__ (self):
@@ -1313,7 +1338,7 @@ def musicxml_words_to_lily_event (words):
     # TODO: How should I best convert the font-family attribute?
 
     # TODO: How can I represent the underline, overline and line-through
-    #       attributes in Lilypond? Values of these attributes indicate
+    #       attributes in LilyPond? Values of these attributes indicate
     #       the number of lines
 
     return event
@@ -1685,7 +1710,7 @@ def musicxml_harmony_to_lily_chordname (n):
             ev.bass = musicxml_chordpitch_to_lily (bass)
         inversion = n.get_maybe_exist_named_child ('inversion')
         if inversion:
-            # TODO: Lilypond does not support inversions, does it?
+            # TODO: LilyPond does not support inversions, does it?
 
             # Mail from Carl Sorensen on lilypond-devel, June 11, 2008:
             # 4. LilyPond supports the first inversion in the form of added 
@@ -2083,6 +2108,7 @@ def musicxml_voice_to_lily_voice (voice):
     voice_builder.set_measure_length (current_measure_length)
 
     for n in voice._elements:
+        tie_started = False
         if n.get_name () == 'forward':
             continue
         staff = n.get_maybe_exist_named_child ('staff')
@@ -2126,6 +2152,12 @@ def musicxml_voice_to_lily_voice (voice):
                     chordnames_builder.add_barline (a, False)
             continue
 
+
+        if isinstance (n, musicxml.Print):
+            for a in musicxml_print_to_lily (n):
+                voice_builder.add_command (a, False)
+            continue
+
         # Continue any multimeasure-rests before trying to add bar checks!
         # Don't handle new MM rests yet, because for them we want bar checks!
         rest = n.get_maybe_exist_typed_child (musicxml.Rest)
@@ -2319,6 +2351,7 @@ def musicxml_voice_to_lily_voice (voice):
                 if mxl_tie and mxl_tie.type == 'start':
                     ev_chord.append (musicexp.TieEvent ())
                     is_tied = True
+                    tie_started = True
                 else:
                     is_tied = False
 
@@ -2414,7 +2447,13 @@ def musicxml_voice_to_lily_voice (voice):
                 if not lnr in note_lyrics_processed:
                     lyrics[lnr].append ("\skip4")
 
-    ## force trailing mm rests to be written out.   
+        # Assume that a <tie> element only lasts for one note.
+        # This might not be correct MusicXML interpretation, but works for
+        # most cases and fixes broken files, which have the end tag missing
+        if is_tied and not tie_started:
+            is_tied = False
+
+    ## force trailing mm rests to be written out.
     voice_builder.add_music (musicexp.ChordEvent (), Rational (0))
     
     ly_voice = group_tuplets (voice_builder.elements, tuplet_events)
@@ -2520,7 +2559,17 @@ def voices_in_part (part):
 
 def voices_in_part_in_parts (parts):
     """return a Part -> Name -> Voice dictionary"""
-    return dict([(p.id, voices_in_part (p)) for p in parts])
+    # don't crash if p doesn't have an id (that's invalid MusicXML,
+    # but such files are out in the wild!
+    dictionary = {}
+    for p in parts:
+        voices = voices_in_part (p)
+        if (hasattr (p, "id")):
+             dictionary[p.id] = voices
+        else:
+             # TODO: extract correct part id from other sources
+             dictionary[None] = voices
+    return dictionary;
 
 
 def get_all_voices (parts):
@@ -2616,6 +2665,12 @@ information.""") % 'lilypond')
                   dest = "convert_rest_positions",
                   help = _ ("do not convert exact vertical positions of rests"))
 
+    p.add_option ('--npl', '--no-page-layout', 
+                  action = "store_false",
+                  default = True,
+                  dest = "convert_page_layout",
+                  help = _ ("do not convert the exact page layout and breaks"))
+
     p.add_option ('--no-beaming', 
                   action = "store_false",
                   default = True,
@@ -2852,7 +2907,7 @@ def convert (filename, options):
     print_ly_additional_definitions (printer, filename)
     if score_information:
         score_information.print_ly (printer)
-    if paper_information:
+    if paper_information and conversion_settings.convert_page_layout:
         paper_information.print_ly (printer)
     if layout_information:
         layout_information.print_ly (printer)
@@ -2891,6 +2946,7 @@ def main ():
         needed_additional_definitions.append (options.language)
         additional_definitions[options.language] = "\\include \"%s.ly\"\n" % options.language
     conversion_settings.ignore_beaming = not options.convert_beaming
+    conversion_settings.convert_page_layout = options.convert_page_layout
 
     # Allow the user to leave out the .xml or xml on the filename
     basefilename = args[0].decode('utf-8')