]> git.donarmstrong.com Git - lilypond.git/blobdiff - python/musicexp.py
MusicXML: Correctly convert nested staff/part groups
[lilypond.git] / python / musicexp.py
index 8ae3105cada6d35d1efeba95378124861b1dc5cb..050ae66c03daed3ebeaa162d38ae673e53ffe505 100644 (file)
@@ -148,7 +148,10 @@ class Duration:
         str = '%d%s' % (1 << self.duration_log, '.'*self.dots)
 
         if factor <> Rational (1,1):
-            str += '*%d/%d' % (factor.numerator (), factor.denominator ())
+            if factor.denominator () <> 1:
+                str += '*%d/%d' % (factor.numerator (), factor.denominator ())
+            else:
+                str += '*%d' % factor.numerator ()
 
         return str
     
@@ -413,7 +416,7 @@ class SequentialMusic (NestedMusic):
         at = len( self.elements ) - 1
         while (at >= 0 and
                not isinstance (self.elements[at], EventChord) and
-               not isinstance (self.elements[at], BarCheck)):
+               not isinstance (self.elements[at], BarLine)):
             at -= 1
 
         if (at >= 0 and isinstance (self.elements[at], EventChord)):
@@ -447,6 +450,36 @@ class SequentialMusic (NestedMusic):
             e.set_start (start)
             start += e.get_length()
 
+class RepeatedMusic:
+    def __init__ (self):
+        self.repeat_type = "volta"
+        self.repeat_count = 2
+        self.endings = []
+        self.music = None
+    def set_music (self, music):
+        if isinstance (music, Music):
+            self.music = music
+        elif isinstance (music, list):
+            self.music = SequentialMusic ()
+            self.music.elements = music
+        else:
+            sys.stderr.write ("WARNING: Unable to set the music %s for the repeat %s" % (music, self))
+    def add_ending (self, music):
+        self.endings.append (music)
+    def print_ly (self, printer):
+        printer.dump ('\\repeat %s %s' % (self.repeat_type, self.repeat_count))
+        if self.music:
+            self.music.print_ly (printer)
+        else:
+            sys.stderr.write ("WARNING: Encountered repeat without body\n")
+            printer.dump ('{}')
+        if self.endings:
+            printer.dump ('\\alternative {')
+            for e in self.endings:
+                e.print_ly (printer)
+            printer.dump ('}')
+
+
 class Lyrics:
     def __init__ (self):
         self.lyrics_syllables = []
@@ -537,21 +570,35 @@ class EventChord (NestedMusic):
 
         self.print_comment (printer)
             
+class Partial (Music):
+    def __init__ (self):
+        Music.__init__ (self)
+        self.partial = None
+    def print_ly (self, printer):
+        if self.partial:
+            printer.dump ("\\partial %s" % self.partial.ly_expression ())
 
-class BarCheck (Music):
+class BarLine (Music):
     def __init__ (self):
         Music.__init__ (self)
         self.bar_number = 0
+        self.type = None
         
     def print_ly (self, printer):
+        bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': ":",
+                       'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
+                       'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
+                       'short': "'", 'none': "" }.get (self.type, None)
+        if bar_symbol <> None:
+            printer.dump ('\\bar "%s"' % bar_symbol)
+        else:
+            printer.dump ("|")
+
         if self.bar_number > 0 and (self.bar_number % 10) == 0:
-            printer.dump ("|  \\barNumberCheck #%d " % self.bar_number)
-            printer.newline ()
+            printer.dump ("\\barNumberCheck #%d " % self.bar_number)
         else:
-            printer.dump ("| ")
             printer.print_verbatim (' %% %d' % self.bar_number)
-            printer.newline ()
+        printer.newline ()
 
     def ly_expression (self):
         return " | "
@@ -693,10 +740,29 @@ class DynamicsEvent (Event):
             printer.dump ("-\\markup{ \\dynamic %s }" % self.type)
 
 
+class TextEvent (Event):
+    def __init__ (self):
+        self.Text = None
+        self.force_direction = None
+        self.markup = ''
+    def wait_for_note (self):
+        return True
+
+    def direction_mod (self):
+        return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
+
+    def ly_expression (self):
+        base_string = '%s\"%s\"'
+        if self.markup:
+            base_string = '%s\markup{ ' + self.markup + ' {%s} }'
+        return base_string % (self.direction_mod (), self.text)
+
 class ArticulationEvent (Event):
     def __init__ (self):
         self.type = None
         self.force_direction = None
+    def wait_for_note (self):
+        return True;
 
     def direction_mod (self):
         return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '')
@@ -722,6 +788,39 @@ class MarkupEvent (ShortArticulationEvent):
     def ly_expression (self):
         if self.contents:
             return "%s\\markup { %s }" % (self.direction_mod (), self.contents)
+        else:
+            return ''
+
+class FretEvent (MarkupEvent):
+    def __init__ (self):
+        MarkupEvent.__init__ (self)
+        self.force_direction = 1
+        self.strings = 6
+        self.frets = 4
+        self.barre = None
+        self.elements = []
+    def ly_expression (self):
+        val = ""
+        if self.strings <> 6:
+            val += "w:%s;" % self.strings
+        if self.frets <> 4:
+            val += "h:%s;" % self.frets
+        if self.barre and len (self.barre) >= 3:
+            val += "c:%s-%s-%s;" % (self.barre[0], self.barre[1], self.barre[2])
+        have_fingering = False
+        for i in self.elements:
+            if len (i) > 1:
+                val += "%s-%s" % (i[0], i[1])
+            if len (i) > 2:
+                have_fingering = True
+                val += "-%s" % i[2]
+            val += ";"
+        if have_fingering:
+            val = "f:1;" + val
+        if val:
+            return "%s\\markup { \\fret-diagram #\"%s\" }" % (self.direction_mod (), val)
+        else:
+            return ''
 
 class TremoloEvent (ArticulationEvent):
     def __init__ (self):
@@ -898,6 +997,17 @@ class ClefChange (Music):
         return clefsetting
 
 
+class StaffChange (Music):
+    def __init__ (self, staff):
+        Music.__init__ (self)
+        self.staff = staff
+    def ly_expression (self):
+        if self.staff:
+            return "\\change Staff=\"%s\"" % self.staff
+        else:
+            return ''
+
+
 class MultiMeasureRest(Music):
 
     def lisp_expression (self):
@@ -929,21 +1039,22 @@ class StaffGroup:
         self.symbol = None
         self.spanbar = None
         self.children = []
+        self.is_group = True
         # part_information is a list with entries of the form
         #     [staffid, voicelist]
         # where voicelist is a list with entries of the form
         #     [voiceid1, [lyricsid11, lyricsid12,...] ]
         self.part_information = None
 
-    def appendStaff (self, staff):
+    def append_staff (self, staff):
         self.children.append (staff)
 
-    def setPartInformation (self, part_name, staves_info):
+    def set_part_information (self, part_name, staves_info):
         if part_name == self.id:
             self.part_information = staves_info
         else:
             for c in self.children:
-                c.setPartInformation (part_name, staves_info)
+                c.set_part_information (part_name, staves_info)
 
     def print_ly_contents (self, printer):
         for c in self.children:
@@ -963,7 +1074,7 @@ class StaffGroup:
                 printer.dump ("\\override SpanBar #'transparent = ##t")
             brack = {"brace": "SystemStartBrace",
                      "none": "f",
-                     "line": "SystemStartBar"}.get (self.symbol, None)
+                     "line": "SystemStartSquare"}.get (self.symbol, None)
             if brack:
                 printer.dump ("systemStartDelimiter = #'%s" % brack)
             printer.dump ("}")
@@ -979,7 +1090,7 @@ class StaffGroup:
                     escape_instrument_string (self.instrument_name)))
             printer.newline ()
         if self.stafftype and self.short_instrument_name:
-            printer.dump ("\\set %s.shortInstrumentName = %s\n" % (self.stafftype, 
+            printer.dump ("\\set %s.shortInstrumentName = %s" % (self.stafftype,
                     escape_instrument_string (self.short_instrument_name)))
             printer.newline ()
         self.print_ly_contents (printer)
@@ -991,6 +1102,7 @@ class StaffGroup:
 class Staff (StaffGroup):
     def __init__ (self):
         StaffGroup.__init__ (self, "Staff")
+        self.is_group = False
         self.part = None
 
     def print_ly_overrides (self, printer):