]> git.donarmstrong.com Git - lilypond.git/blobdiff - python/musicexp.py
Update documentation targets
[lilypond.git] / python / musicexp.py
index a2d405973bcea05008e0da791c638021b1ae9f45..61598f28e51e7c58258cc5532c163ce84e45bcb3 100644 (file)
@@ -43,7 +43,6 @@ class Output_printer:
     Music expression as a .ly file.
     
     """
-    ## TODO: support for \relative.
     
     def __init__ (self):
         self._line = ''
@@ -205,11 +204,20 @@ class Duration:
 # Implement the different note names for the various languages
 def pitch_generic (pitch, notenames, accidentals):
     str = notenames[pitch.step]
-    # TODO: Handle microtones!
-    if pitch.alteration < 0:
-        str += accidentals[0] * (-pitch.alteration)
+    halftones = int (pitch.alteration)
+    if halftones < 0:
+        str += accidentals[0] * (-halftones)
     elif pitch.alteration > 0:
-        str += accidentals[3] * (pitch.alteration)
+        str += accidentals[3] * (halftones)
+    # Handle remaining fraction to pitch.alteration (for microtones)
+    if (halftones != pitch.alteration):
+        if None in accidentals[1:3]:
+            warning (_ ("Language does not support microtones contained in the piece"))
+        else:
+            try:
+                str += {-0.5: accidentals[1], 0.5: accidentals[2]}[pitch.alteration-halftones]
+            except KeyError:
+                warning (_ ("Language does not support microtones contained in the piece"))
     return str
 
 def pitch_general (pitch):
@@ -231,7 +239,7 @@ def pitch_norsk (pitch):
     return pitch_deutsch (pitch)
 
 def pitch_svenska (pitch):
-    str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', '', '', 'iss'])
+    str = pitch_generic (pitch, ['c', 'd', 'e', 'f', 'g', 'a', 'h'], ['ess', None, None, 'iss'])
     return str.replace ('hess', 'b').replace ('aes', 'as').replace ('ees', 'es')
 
 def pitch_italiano (pitch):
@@ -242,11 +250,11 @@ def pitch_catalan (pitch):
     return pitch_italiano (pitch)
 
 def pitch_espanol (pitch):
-    str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', '', '', 's'])
+    str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 's'])
     return str
 
 def pitch_vlaams (pitch):
-    str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', '', '', 'k'])
+    str = pitch_generic (pitch, ['do', 're', 'mi', 'fa', 'sol', 'la', 'si'], ['b', None, None, 'k'])
     return str
 
 def set_pitch_language (language):
@@ -500,13 +508,25 @@ class TimeScaledMusic (MusicWrapper):
                 (base_number_function, base_duration))
             func.newline ()
         elif self.display_type == "both": # TODO: Implement this using actual_type and normal_type!
-            warning (_ ("Tuplet brackets displaying both note durations are not implemented, using default"))
             if self.display_number == None:
                 func ("\\once \\override TupletNumber #'stencil = ##f")
                 func.newline ()
             elif self.display_number == "both":
-                func ("\\once \\override TupletNumber #'text = #%s" % base_number_function)
-                func.newline ()
+                den_duration = self.normal_type.ly_expression (None, True)
+                # If we don't have an actual type set, use the normal duration!
+                if self.actual_type:
+                    num_duration = self.actual_type.ly_expression (None, True)
+                else:
+                    num_duration = den_duration
+                if (self.display_denominator or self.display_numerator):
+                    func ("\\once \\override TupletNumber #'text = #(tuplet-number::non-default-fraction-with-notes %s \"%s\" %s \"%s\")" % 
+                                (self.display_denominator, den_duration,
+                                 self.display_numerator, num_duration))
+                    func.newline ()
+                else:
+                    func ("\\once \\override TupletNumber #'text = #(tuplet-number::fraction-with-notes \"%s\" \"%s\")" % 
+                                (den_duration, num_duration))
+                    func.newline ()
         else:
             if self.display_number == None:
                 func ("\\once \\override TupletNumber #'stencil = ##f")
@@ -884,10 +904,10 @@ class BarLine (Music):
         self.type = None
         
     def print_ly (self, printer):
-        bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': ":",
+        bar_symbol = { 'regular': "|", 'dotted': ":", 'dashed': "dashed",
                        'heavy': "|", 'light-light': "||", 'light-heavy': "|.",
                        'heavy-light': ".|", 'heavy-heavy': ".|.", 'tick': "'",
-                       'short': "'", 'none': "" }.get (self.type, None)
+                       'short': "'|", 'none': "" }.get (self.type, None)
         if bar_symbol <> None:
             printer.dump ('\\bar "%s"' % bar_symbol)
         else:
@@ -983,7 +1003,11 @@ class OctaveShiftEvent (SpanEvent):
         self.span_type = {'up': 1, 'down': -1}.get (type, 0)
     def ly_octave_shift_indicator (self):
         # convert 8/15 to lilypond indicators (+-1/+-2)
-        value = {8: 1, 15: 2}.get (self.size, 0)
+        try:
+            value = {8: 1, 15: 2}[self.size]
+        except KeyError:
+            warning (_ ("Invalid octave shift size found: %s. Using no shift.") % self.size)
+            value = 0
         # negative values go up!
         value *= -1*self.span_type
         return value
@@ -1298,9 +1322,9 @@ class TremoloEvent (ArticulationEvent):
 class BendEvent (ArticulationEvent):
     def __init__ (self):
         Event.__init__ (self)
-        self.alter = 0
+        self.alter = None
     def ly_expression (self):
-        if self.alter:
+        if self.alter != None:
             return "-\\bendAfter #%s" % self.alter
         else:
             return ''
@@ -1428,15 +1452,24 @@ class KeySignatureChange (Music):
         self.non_standard_alterations = None
 
     def format_non_standard_alteration (self, a):
-        alter_dict = { -2: ",DOUBLE-FLAT",
-                       -1: ",FLAT",
-                        0: ",NATURAL",
-                        1: ",SHARP",
-                        2: ",DOUBLE-SHARP"}
+        alter_dict = { -2:   ",DOUBLE-FLAT",
+                       -1.5: ",THREE-Q-FLAT",
+                       -1:   ",FLAT",
+                       -0.5: ",SEMI-FLAT",
+                        0:   ",NATURAL",
+                        0.5: ",SEMI-SHARP",
+                        1:   ",SHARP",
+                        1.5: ",THREE-Q-SHARP",
+                        2:   ",DOUBLE-SHARP"}
+        try:
+            accidental = alter_dict[a[1]]
+        except KeyError:
+            warning (_ ("Unable to convert alteration %s to a lilypond expression") % a[1])
+            return ''
         if len (a) == 2:
-            return "( %s . %s )" % (a[0], alter_dict.get (a[1], a[1]))
+            return "( %s . %s )" % (a[0], accidental)
         elif len (a) == 3:
-            return "(( %s . %s ) . %s )" % (a[2], a[0], alter_dict.get (a[1], a[1]))
+            return "(( %s . %s ) . %s )" % (a[2], a[0], accidental)
         else:
             return ''
 
@@ -1447,12 +1480,6 @@ class KeySignatureChange (Music):
         elif self.non_standard_alterations:
             alterations = [self.format_non_standard_alteration (a) for
                                         a in self.non_standard_alterations]
-            # TODO: Check if the alterations should really be given in reverse
-            #       order of if that's just a bug in Lilypond. If it's a bug,
-            #       fix it and remove the following call, otherwise add a
-            #       proper comment here!
-            alterations.reverse ()
-            print "Non-Standard alterations printed out: %s" % alterations
             return "\\set Staff.keySignature = #`(%s)" % string.join (alterations, " ")
         else:
             return ''
@@ -1462,6 +1489,13 @@ class TimeSignatureChange (Music):
         Music.__init__ (self)
         self.fractions = [4,4]
         self.style = None
+    def format_fraction (self, frac):
+        if isinstance (frac, list):
+            l = [self.format_fraction (f) for f in frac]
+            return "(" + string.join (l, " ") + ")"
+        else:
+            return "%s" % frac
+
     def ly_expression (self):
         st = ''
         # Print out the style if we have ome, but the '() should only be 
@@ -1469,17 +1503,19 @@ class TimeSignatureChange (Music):
         # signatures anyway despite the default 'C signature style!
         is_common_signature = self.fractions in ([2,2], [4,4], [4,2])
         if self.style:
-            if (self.style != "'()") or is_common_signature:
+            if self.style == "common":
+                st = "\\defaultTimeSignature"
+            elif (self.style != "'()"):
                 st = "\\once \\override Staff.TimeSignature #'style = #%s " % self.style
+            elif (self.style != "'()") or is_common_signature:
+                st = "\\numericTimeSignature"
 
         # Easy case: self.fractions = [n,d] => normal \time n/d call:
         if len (self.fractions) == 2 and isinstance (self.fractions[0], int):
             return st + '\\time %d/%d ' % tuple (self.fractions)
-        elif self.fractions and not isinstance (self.fractions[0], list):
-            # TODO: Implement non-standard time-signatures
-            return st + ''
+        elif self.fractions:
+            return st + "\\compoundMeter #'%s" % self.format_fraction (self.fractions)
         else:
-            # TODO: Implement non-standard time-signatures
             return st + ''
     
 class ClefChange (Music):
@@ -1671,6 +1707,14 @@ class MultiMeasureRest(Music):
         return 'R%s' % self.duration.ly_expression ()
 
 
+class Break (Music):
+    def __init__ (self, tp="break"):
+        Music.__init__ (self)
+        self.type = tp
+    def print_ly (self, printer):
+        if self.type:
+            printer.dump ("\\%s" % self.type)
+
 class StaffGroup:
     def __init__ (self, command = "StaffGroup"):
         self.stafftype = command