From: Reinhold Kainhofer <reinhold@kainhofer.com>
Date: Fri, 30 Jan 2009 23:06:57 +0000 (+0100)
Subject: Implement non-standard tuplet numbers
X-Git-Tag: release/2.13.1-1~82
X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=e83d4d449bbb7d775b4ef1058b963fa236ba1048;p=lilypond.git

Implement non-standard tuplet numbers

-) Add function for different fraction than the actual tuplet fraction
-) Add wrapper function that appends a note with given duration after
   the standard tuplet text (denominator or fraction)
-) Add function to print tuplet text with both fraction values with a
   note duration attached
-) Add snippet to be included in the Docs
-) Add regtests for all these cases
-) Remove definitions from musicxml2ly and make it use these new functions
---

diff --git a/Documentation/topdocs/NEWS.tely b/Documentation/topdocs/NEWS.tely
index ae899645c2..99089a1782 100644
--- a/Documentation/topdocs/NEWS.tely
+++ b/Documentation/topdocs/NEWS.tely
@@ -70,6 +70,30 @@ A snap-pizzicato (also known as Bartok-pizzicato) articulation was added:
 }
 @end lilypond
 
+@item
+Tuplet number formatting functions are now available to print other fractions and to add notes to the number or fraction:
+@lilypond[quote]
+\relative c'' {
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-tuplet-denominator-text 7)
+  \times 2/3  { c4. c4. c4. c4. } % begin verbatim
+
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-tuplet-fraction-text 12 7)
+  \times 2/3  { c4. c4. c4. c4. }
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper (tuplet-number::non-default-tuplet-fraction-text 12 7) "8")
+  \times 2/3  { c4. c4. c4. c4. }
+
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper tuplet-number::calc-denominator-text "4")
+  \times 2/3  { c8 c8 c8 c8 c8 c8 }
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper tuplet-number::calc-fraction-text "4")
+  \times 2/3  { c8 c8 c8 c8 c8 c8 }
+
+  \once \override TupletNumber #'text = #(tuplet-number::fraction-with-notes "4." "8")
+  \times 2/3  { c4. c4. c4. c4. }
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-fraction-with-notes 12 "8" 4 "4")
+  \times 2/3  { c4. c4. c4. c4. }
+}
+@end lilypond
+
 @item
 FretBoards now have a chordChanges property to keep repeated FretBoard objects
 from being typeset.
diff --git a/Documentation/user/rhythms.itely b/Documentation/user/rhythms.itely
index 00b5786b54..7c5b450db6 100644
--- a/Documentation/user/rhythms.itely
+++ b/Documentation/user/rhythms.itely
@@ -246,6 +246,9 @@ see @ref{Scaling durations}.
 @lilypondfile[verbatim,lilyquote,ragged-right,texidoc,doctitle]
 {changing-the-tuplet-number.ly}
 
+@lilypondfile[verbatim,lilyquote,ragged-right,texidoc,doctitle]
+{non-default-tuplet-numbers.ly}
+
 @lilypondfile[verbatim,lilyquote,ragged-right,texidoc,doctitle]
 {permitting-line-breaks-within-beamed-tuplets.ly}
 
diff --git a/input/lsr/non-default-tuplet-numbers.ly b/input/lsr/non-default-tuplet-numbers.ly
new file mode 100644
index 0000000000..f3574a45ab
--- /dev/null
+++ b/input/lsr/non-default-tuplet-numbers.ly
@@ -0,0 +1,35 @@
+%% Do not edit this file; it is auto-generated from input/new
+%% This file is in the public domain.
+\version "2.12.3"
+
+\header {
+  lsrtags = "rhythms"
+
+  texidoc = "
+LilyPond also provides formatting functions to print tuplet numbers different
+than the actual fraction, as well as to append a note value to the tuplet 
+number or tuplet fraction.
+"
+  doctitle = "Non-default tuplet numbers"
+} % begin verbatim
+
+
+\relative c'' {
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-tuplet-denominator-text 7)
+  \times 2/3  { c4. c4. c4. c4. } % begin verbatim
+
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-tuplet-fraction-text 12 7)
+  \times 2/3  { c4. c4. c4. c4. }
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper (tuplet-number::non-default-tuplet-fraction-text 12 7) "8")
+  \times 2/3  { c4. c4. c4. c4. }
+
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper tuplet-number::calc-denominator-text "4")
+  \times 2/3  { c8 c8 c8 c8 c8 c8 }
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper tuplet-number::calc-fraction-text "4")
+  \times 2/3  { c8 c8 c8 c8 c8 c8 }
+
+  \once \override TupletNumber #'text = #(tuplet-number::fraction-with-notes "4." "8")
+  \times 2/3  { c4. c4. c4. c4. }
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-fraction-with-notes 12 "8" 4 "4")
+  \times 2/3  { c4. c4. c4. c4. }
+}
diff --git a/input/lsr/rhythms.snippet-list b/input/lsr/rhythms.snippet-list
index 03efe3e1f3..e6e4922d33 100644
--- a/input/lsr/rhythms.snippet-list
+++ b/input/lsr/rhythms.snippet-list
@@ -28,6 +28,7 @@ manually-controlling-beam-positions.ly
 merging-multi-measure-rests-in-a-polyphonic-part.ly
 modifying-tuplet-bracket-length.ly
 multi--measure-rest-markup.ly
+non-default-tuplet-numbers.ly
 permitting-line-breaks-within-beamed-tuplets.ly
 positioning-multi--measure-rests.ly
 printing-metronome-and-rehearsal-marks-below-the-staff.ly
diff --git a/input/new/non-default-tuplet-numbers.ly b/input/new/non-default-tuplet-numbers.ly
new file mode 100644
index 0000000000..ec4c0cc924
--- /dev/null
+++ b/input/new/non-default-tuplet-numbers.ly
@@ -0,0 +1,32 @@
+\version "2.12.3"
+
+\header {
+  lsrtags = "rhythms"
+
+  texidoc = "
+LilyPond also provides formatting functions to print tuplet numbers different
+than the actual fraction, as well as to append a note value to the tuplet 
+number or tuplet fraction.
+"
+  doctitle = "Non-default tuplet numbers"
+} % begin verbatim
+
+
+\relative c'' {
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-tuplet-denominator-text 7)
+  \times 2/3  { c4. c4. c4. c4. }
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-tuplet-fraction-text 12 7)
+  \times 2/3  { c4. c4. c4. c4. }
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper (tuplet-number::non-default-tuplet-fraction-text 12 7) "8")
+  \times 2/3  { c4. c4. c4. c4. }
+
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper tuplet-number::calc-denominator-text "4")
+  \times 2/3  { c8 c8 c8 c8 c8 c8 }
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper tuplet-number::calc-fraction-text "4")
+  \times 2/3  { c8 c8 c8 c8 c8 c8 }
+
+  \once \override TupletNumber #'text = #(tuplet-number::fraction-with-notes "4." "8")
+  \times 2/3  { c4. c4. c4. c4. }
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-fraction-with-notes 12 "8" 4 "4")
+  \times 2/3  { c4. c4. c4. c4. }
+}
diff --git a/input/regression/musicxml/23c-Tuplet-Display-NonStandard.xml b/input/regression/musicxml/23c-Tuplet-Display-NonStandard.xml
index 984292ff38..c0949e4c43 100644
--- a/input/regression/musicxml/23c-Tuplet-Display-NonStandard.xml
+++ b/input/regression/musicxml/23c-Tuplet-Display-NonStandard.xml
@@ -568,10 +568,12 @@
           <tuplet bracket="yes" show-number="both" show-type="both" number="1" type="start">
             <tuplet-actual>
               <tuplet-number>7</tuplet-number>
+              <tuplet-type>eighth</tuplet-type>
               <tuplet-dot/>
             </tuplet-actual>
             <tuplet-normal>
               <tuplet-number>5</tuplet-number>
+              <tuplet-type>breve</tuplet-type>
             </tuplet-normal>
           </tuplet>
         </notations>
diff --git a/input/regression/tuplet-text-different-numbers.ly b/input/regression/tuplet-text-different-numbers.ly
new file mode 100644
index 0000000000..8464c22742
--- /dev/null
+++ b/input/regression/tuplet-text-different-numbers.ly
@@ -0,0 +1,15 @@
+\version "2.12.3"
+\header{
+  texidoc="Non-standard tuplet texts: Printing other tuplet fractions than the ones actually assigned."
+}
+\layout { ragged-right= ##t }
+
+
+\context Voice \relative c'' {
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-tuplet-denominator-text 7)
+  \times 2/3  { c4. c4. c4. c4. }
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-tuplet-fraction-text 12 7)
+  \times 2/3  { c4. c4. c4. c4. }
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper (tuplet-number::non-default-tuplet-fraction-text 12 7) "8")
+  \times 2/3  { c4. c4. c4. c4. }
+}
diff --git a/input/regression/tuplet-text-fraction-with-notes.ly b/input/regression/tuplet-text-fraction-with-notes.ly
new file mode 100644
index 0000000000..d35dcc220c
--- /dev/null
+++ b/input/regression/tuplet-text-fraction-with-notes.ly
@@ -0,0 +1,12 @@
+\version "2.12.3"
+\header{
+  texidoc="Non-standard tuplet texts: Printing a tuplet fraction with note durations assigned to both the denominator and the numerator."
+}
+
+
+\context Voice \relative c'' {
+  \once \override TupletNumber #'text = #(tuplet-number::fraction-with-notes "4." "8")
+  \times 2/3  { c4. c4. c4. c4. }
+  \once \override TupletNumber #'text = #(tuplet-number::non-default-fraction-with-notes 12 "8" 4 "4")
+  \times 2/3  { c4. c4. c4. c4. }
+}
diff --git a/input/regression/tuplet-text-note-appended.ly b/input/regression/tuplet-text-note-appended.ly
new file mode 100644
index 0000000000..645b66d28a
--- /dev/null
+++ b/input/regression/tuplet-text-note-appended.ly
@@ -0,0 +1,13 @@
+\version "2.12.3"
+\header{
+  texidoc="Non-standard tuplet texts: Appending a note value to the normal text and to the fraction text."
+}
+\layout { ragged-right= ##t }
+
+
+\context Voice \relative c'' {
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper tuplet-number::calc-denominator-text "4")
+  \times 2/3  { c8 c8 c8 c8 c8 c8 }
+  \once \override TupletNumber #'text = #(tuplet-number::append-note-wrapper tuplet-number::calc-fraction-text "4")
+  \times 2/3  { c8 c8 c8 c8 c8 c8 }
+}
diff --git a/python/musicexp.py b/python/musicexp.py
index 1a3fea70fe..0e8b212c85 100644
--- a/python/musicexp.py
+++ b/python/musicexp.py
@@ -508,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")
diff --git a/scm/output-lib.scm b/scm/output-lib.scm
index 53a5773d0f..fdd5253115 100644
--- a/scm/output-lib.scm
+++ b/scm/output-lib.scm
@@ -300,6 +300,53 @@ centered, X==1 is at the right, X == -1 is at the left."
 	    (ly:event-property ev 'denominator)
 	    (ly:event-property ev 'numerator))))
 
+
+; a formatter function, which is simply a wrapper around an existing 
+; tuplet formatter function. It takes the value returned by the given
+; function and appends a note of given length. 
+(define-public ((tuplet-number::append-note-wrapper function note) grob)
+  (let* ((txt (if function (function grob) #f)))
+    (if txt 
+      (markup txt #:fontsize -5 #:note note UP)
+      (markup #:fontsize -5 #:note note UP))))
+
+; Print a tuplet denominator with a different number than the one derived from 
+; the actual tuplet fraction
+(define-public ((tuplet-number::non-default-tuplet-denominator-text denominator) grob)
+(number->string (if denominator 
+                    denominator 
+                    (ly:event-property (event-cause grob) 'denominator))))
+
+; Print a tuplet fraction with different numbers than the ones derived from 
+; the actual tuplet fraction
+(define-public ((tuplet-number::non-default-tuplet-fraction-text denominator numerator) grob)
+  (let* ((ev (event-cause grob))
+         (den (if denominator denominator (ly:event-property ev 'denominator)))
+         (num (if numerator numerator (ly:event-property ev 'numerator))))
+     (format "~a:~a" den num)))
+
+; Print a tuplet fraction with note durations appended to the numerator and the 
+; denominator
+(define-public ((tuplet-number::fraction-with-notes denominatornote numeratornote) grob)
+  (let* ((ev (event-cause grob))
+         (denominator (ly:event-property ev 'denominator))
+         (numerator (ly:event-property ev 'numerator)))
+    ((tuplet-number::non-default-fraction-with-notes denominator denominatornote numerator numeratornote) grob)))
+
+; Print a tuplet fraction with note durations appended to the numerator and the 
+; denominator
+(define-public ((tuplet-number::non-default-fraction-with-notes denominator denominatornote numerator numeratornote) grob)
+  (let* ((ev (event-cause grob))
+         (den (if denominator denominator (ly:event-property ev 'denominator)))
+         (num (if numerator numerator (ly:event-property ev 'numerator))))
+     (make-concat-markup (list 
+          (make-simple-markup (format "~a" den)) 
+          (markup #:fontsize -5 #:note denominatornote UP)
+          (make-simple-markup " : ")
+          (make-simple-markup (format "~a" num)) 
+          (markup #:fontsize -5 #:note numeratornote UP)))))
+
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Color
 
diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py
index 831873bf86..b8e11f7233 100644
--- a/scripts/musicxml2ly.py
+++ b/scripts/musicxml2ly.py
@@ -743,7 +743,7 @@ def musicxml_tuplet_to_lily (tuplet_elt, time_modification):
     actual_type = tuplet_elt.get_actual_type ()
     if actual_type:
         actual_note = musicexp.Duration ()
-        (actual_note.duration_log, actual_note.dots) = normal_type
+        (actual_note.duration_log, actual_note.dots) = actual_type
         tsm.actual_type = actual_note
 
     # Obtain non-default nrs of notes from the tuplet object!
@@ -761,14 +761,8 @@ def musicxml_tuplet_to_lily (tuplet_elt, time_modification):
     display_values = {"none": None, "actual": "actual", "both": "both"}
     if hasattr (tuplet_elt, "show-number"):
         tsm.display_number = display_values.get (getattr (tuplet_elt, "show-number"), "actual")
-    if tsm.display_number == "actual" and tsm.display_denominator:
-        needed_additional_definitions.append ("tuplet-non-default-denominator")
-    elif tsm.display_number == "both" and (tsm.display_numerator or tsm.display_denominator):
-        needed_additional_definitions.append ("tuplet-non-default-fraction")
 
     if hasattr (tuplet_elt, "show-type"):
-        if getattr (tuplet_elt, "show-type") == "actual":
-            needed_additional_definitions.append ("tuplet-note-wrapper")
         tsm.display_type = display_values.get (getattr (tuplet_elt, "show-type"), None)
 
     return tsm