]> git.donarmstrong.com Git - lilypond.git/commitdiff
MusicXML: Convert all clefs, escape " in header fields, code simplification
authorReinhold Kainhofer <reinhold@kainhofer.com>
Sun, 2 Sep 2007 23:03:53 +0000 (01:03 +0200)
committerReinhold Kainhofer <reinhold@kainhofer.com>
Thu, 6 Sep 2007 14:15:13 +0000 (16:15 +0200)
-) Extend the ClefChange class to convert all different clefs (G,C,F,
   percussion,tab) to the corresponding lilypond clef names. MusicXML
   also allows a "None" key, which lilypond does not :-(
-) In the header fields and the lyrics, escape all quotes by \". Only
   wrap the whole string in quotes if it is necessary (string contains
   numbers, spaces, quotes, or starts with a period or comma). This makes
   it much easier to edit the lyrics later on.
-) Several coding style issued pointed out by Han-Wen

Signed-off-by: Reinhold Kainhofer <reinhold@kainhofer.com>
python/musicexp.py
python/musicxml.py
scripts/musicxml2ly.py

index 79fcf95ec76384f5465a2c6e3b57ac31169eb623..0163939b9041aa300b485d3e9e2db406daa67ba7 100644 (file)
@@ -5,6 +5,7 @@ import re
 
 from rational import Rational
 
+
 class Output_stack_element:
     def __init__ (self):
         self.factor = Rational (1)
@@ -763,10 +764,27 @@ class ClefChange (Music):
     def __init__ (self):
         Music.__init__ (self)
         self.type = 'G'
-        
-    
+        self.position = 2
+        self.octave = 0
+
+    def octave_modifier (self):
+        return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self.octave, '')
+    def clef_name (self):
+        return {('G', 2): "treble",
+                ('G', 1): "french",
+                ('C', 1): "soprano",
+                ('C', 2): "mezzosoprano",
+                ('C', 3): "alto",
+                ('C', 4): "tenor",
+                ('C', 5): "baritone",
+                ('F', 3): "varbaritone",
+                ('F', 4): "bass",
+                ('F', 5): "subbass",
+                ("percussion", 2): "percussion",
+                ("TAB", 5): "tab"}.get ((self.type, self.position), None)
     def ly_expression (self):
-        return '\\clef "%s"' % self.type
+        return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ())
+
     clef_dict = {
         "G": ("clefs.G", -2, -6),
         "C": ("clefs.C", 0, 0),
@@ -774,7 +792,10 @@ class ClefChange (Music):
         }
     
     def lisp_expression (self):
-        (glyph, pos, c0) = self.clef_dict.get (self.type)
+        try:
+            (glyph, pos, c0) = self.clef_dict[self.type]
+        except KeyError:
+            return ""
         clefsetting = """
         (make-music 'SequentialMusic
         'elements (list
index fe8dd60537d59ea42bd384ed5eb1df1ffead08f5..a24cb53caae4ceea7038891438c8816b7d3cf8dc 100644 (file)
@@ -1,6 +1,16 @@
 import new
 import string
 from rational import *
+import re
+
+def escape_ly_output_string (input_string):
+    return_string = input_string
+    needs_quotes = re.search ("[0-9\" ]", return_string) or re.search ("^[,.]", return_string);
+    return_string = string.replace (return_string, "\"", "\\\"")
+    if needs_quotes:
+        return_string = "\"" + return_string + "\""
+    return return_string
+
 
 class Xml_node:
     def __init__ (self):
@@ -108,7 +118,7 @@ class Identification (Xml_node):
 
     def get_creator (self, type):
         creators = self.get_named_children ('creator')
-        # return the first creator tag that has type 'editor'
+        # return the first creator tag that has the particular type
         for i in creators:
             if hasattr (i, 'type') and i.type == type:
                 return i.get_text ()
@@ -223,14 +233,22 @@ class Attributes (Measure_element):
             print 'error: requested time signature, but time sig unknown'
             return (4, 4)
 
-    def get_clef_sign (self):
+    # returns clef information in the form ("cleftype", position, octave-shift)
+    def get_clef_information (self):
+        clefinfo = ['G', 2, 0]
         mxl = self.get_named_attribute ('clef')
+        if not mxl:
+            return clefinfo
         sign = mxl.get_maybe_exist_named_child ('sign')
         if sign:
-            return sign.get_text ()
-        else:
-            print 'clef requested, but unknow'
-            return 'G'
+            clefinfo[0] = sign.get_text()
+        line = mxl.get_maybe_exist_named_child ('line')
+        if line:
+            clefinfo[1] = string.atoi (line.get_text ())
+        octave = mxl.get_maybe_exist_named_child ('clef-octave-change')
+        if octave:
+            clefinfo[2] = string.atoi (octave.get_text ())
+        return clefinfo
 
     def get_key_signature (self):
         "return (fifths, mode) tuple"
@@ -336,11 +354,11 @@ class Lyric (Music_xml_node):
         elif text == "_" and continued:
             return "__"
         elif continued and text:
-            return "\"" + text + "\" --"
+            return escape_ly_output_string (text) + " --"
         elif continued:
             return "--"
         elif text:
-            return "\"" + text + "\""
+            return escape_ly_output_string (text)
         else:
             return ""
 
index 12d4747bf9dc01f8c3cf82cf785a9bd9dfcae012..478bf83de4162a7c64fbca96750244755817685d 100644 (file)
@@ -28,49 +28,42 @@ def progress (str):
 # extract those into a hash, indexed by proper lilypond header attributes
 def extract_score_information (tree):
     score_information = {}
+    def set_if_exists (field, value):
+        if value:
+            score_information[field] = value
+
     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 ()
+        set_if_exists ('title', work.get_work_title ())
+        set_if_exists ('worknumber', work.get_work_number ())
+        set_if_exists ('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 ()
+            set_if_exists ('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 ()
+        set_if_exists ('copyright', ids.get_rights ())
+        set_if_exists ('composer', ids.get_composer ())
+        set_if_exists ('arranger', ids.get_arranger ())
+        set_if_exists ('editor', ids.get_editor ())
+        set_if_exists ('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 ()
+        set_if_exists ('tagline', ids.get_encoding_software ())
+        set_if_exists ('encodingsoftware', ids.get_encoding_software ())
+        set_if_exists ('encodingdate', ids.get_encoding_date ())
+        set_if_exists ('encoder', ids.get_encoding_person ())
+        set_if_exists ('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]))
+    for (k, text) in score_information.items ():
+        printer.dump ('%s = %s' % (k, musicxml.escape_ly_output_string (text)))
         printer.newline ()
     printer.dump ('}')
     printer.newline ()
@@ -135,7 +128,7 @@ def group_tuplets (music_list, events):
 
 def musicxml_clef_to_lily (attributes):
     change = musicexp.ClefChange ()
-    change.type = attributes.get_clef_sign ()
+    (change.type, change.position, change.octave) = attributes.get_clef_information ()
     return change
     
 def musicxml_time_to_lily (attributes):
@@ -356,7 +349,7 @@ 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)
-    # \breathe cannot have any direction modifyer (^, _, -)!
+    # \breathe cannot have any direction modifier (^, _, -)!
     if dir and tp != "breathe":
         ev.force_direction = dir
     return ev