]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix #372.
authorNeil Puttock <n.puttock@gmail.com>
Sat, 25 Sep 2010 23:43:29 +0000 (00:43 +0100)
committerNeil Puttock <n.puttock@gmail.com>
Sun, 26 Sep 2010 00:04:22 +0000 (01:04 +0100)
Thanks to Carl for providing the inspiration for this patch.

* input/regression/auto-beam-partial-grace.ly:

  new regtest

* input/regression/display-lily-tests.ly:

  remove TODO for scaled duration \partial test

* lily/partial-iterator.cc (new file):

  use a simple music iterator to calculate the correct measurePosition
  setting, and warn for \partial used after the start of a score

* scm/define-music-display-methods.scm:

  simplify display method for partial: since the new music object `PartialSet'
  carries the original duration from the parser, extra code for converting
  moments to durations is no longer required

* scm/define-music-properties.scm (all-music-properties):

  add property for \partial, partial-duration

* scm/define-music-types.scm (music-descriptions):

  add PartialSet

* scm/ly-syntax-constructors.scm (partial):

  change constructor to allow 'origin to be set directly (used by iterator
  to signal warning message)

  use PartialSet

input/regression/auto-beam-partial-grace.ly [new file with mode: 0644]
input/regression/display-lily-tests.ly
lily/partial-iterator.cc [new file with mode: 0644]
scm/define-music-display-methods.scm
scm/define-music-properties.scm
scm/define-music-types.scm
scm/ly-syntax-constructors.scm

diff --git a/input/regression/auto-beam-partial-grace.ly b/input/regression/auto-beam-partial-grace.ly
new file mode 100644 (file)
index 0000000..f80c49e
--- /dev/null
@@ -0,0 +1,13 @@
+\version "2.13.35"
+
+\header {
+  texidoc = "Grace notes at the start of a partial measure do not
+break autobeaming."
+}
+
+\relative c' {
+  \partial 4
+  \grace e16
+  d8 d
+  c8 c c c c c c c
+}
index 1d8d0097a9e8ec592eaa700b8604a65a2b794829..426b61771bee5e5c35010b73a1611dd6fb422741 100644 (file)
@@ -223,7 +223,7 @@ stderr of this run."
 %% \partial
 \test "" ##[ \partial 2 #]
 \test "" ##[ \partial 8. #]
-\test #"TODO? exotic durations in \\partial" ##[ \partial 4*2/3 #]
+\test "" ##[ \partial 4*2/3 #]
 
 %% \partcombine
 \test "" ##[ \partcombine { c e }
diff --git a/lily/partial-iterator.cc b/lily/partial-iterator.cc
new file mode 100644 (file)
index 0000000..2e38056
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+  This file is part of LilyPond, the GNU music typesetter.
+
+  Copyright (C) 2010 Neil Puttock <n.puttock@gmail.com>
+
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "context.hh"
+#include "input.hh"
+#include "international.hh"
+#include "moment.hh"
+#include "music.hh"
+#include "simple-music-iterator.hh"
+
+class Partial_iterator : public Simple_music_iterator
+{
+public:
+  DECLARE_SCHEME_CALLBACK (constructor, ());
+ protected:
+  virtual void process (Moment);
+};
+
+void
+Partial_iterator::process (Moment m)
+{
+  if (Duration *dur
+      = unsmob_duration (get_music ()->get_property ("partial-duration")))
+    {
+      Context *ctx = get_outlet ();
+      Moment now = ctx->now_mom ();
+      if (now.main_part_ > Rational (0))
+       get_music ()->origin ()->
+         warning (_ ("trying to use \\partial after the start of a piece"));
+      Moment length = Moment (dur->get_length ());
+      now = Moment (0, now.grace_part_);
+      ctx->set_property ("measurePosition", (now - length).smobbed_copy ());
+    }
+  else
+    programming_error ("invalid duration in \\partial");
+
+  Simple_music_iterator::process (m);
+}
+
+IMPLEMENT_CTOR_CALLBACK (Partial_iterator);
index 03df67ab82a71efc5697b41115870e0c6f22780b..3b896a245017f6aa463fcb8d412b0dcd495aa617 100644 (file)
@@ -1013,29 +1013,6 @@ Otherwise, return #f."
      (format #f "\\bar \"~a\"~a" ?bar-type (new-line->lily-string))))
 
 ;;; \partial
-(define (duration->moment ly-duration)
-  (let ((log2   (ly:duration-log ly-duration))
-       (dots    (ly:duration-dot-count ly-duration))
-       (num+den (ly:duration-factor ly-duration)))
-    (let* ((m (expt 2 (- log2)))
-          (factor (/ (car num+den) (cdr num+den))))
-      (/ (do ((i 0 (1+ i))
-             (delta (/ m 2) (/ delta 2)))
-            ((= i dots) m)
-          (set! m (+ m delta)))
-        factor))))
-
-(define moment-duration-alist (map (lambda (duration)
-                                    (cons (duration->moment duration)
-                                          duration))
-                                  (append-map (lambda (log2)
-                                                (map (lambda (dots)
-                                                       (ly:make-duration log2 dots 1 1))
-                                                     (list 0 1 2 3)))
-                                              (list 0 1 2 3 4))))
-
-(define (moment->duration moment)
-  (assoc-get (- moment) moment-duration-alist))
 
 (define-extra-display-method ContextSpeccedMusic (expr parser)
   "If `expr' is a partial measure, return \"\\partial ...\".
@@ -1046,13 +1023,12 @@ Otherwise, return #f."
                                    'ContextSpeccedMusic
                                    context-type 'Timing
                                    element (music
-                                            'PropertySet
-                                            value ?moment
-                                            symbol 'measurePosition))))
-     (let ((duration (moment->duration (/ (ly:moment-main-numerator ?moment)
-                                         (ly:moment-main-denominator ?moment)))))
-       (and duration (format #f "\\partial ~a" (duration->lily-string duration
-                                                #:force-duration #t))))))
+                                            'PartialSet
+                                            partial-duration ?duration))))
+
+                   (and ?duration
+                        (format #f "\\partial ~a"
+                                (duration->lily-string ?duration #:force-duration #t)))))
 
 ;;;
 ;;;
index ebd48794ba1162441695fa696dc17804d53fbe2f..d7b602afe72f2b852f01a2659a1b81e5536c291d 100644 (file)
@@ -126,6 +126,8 @@ top-level, a page marker object is instanciated instead of a score.")
      (page-turn-permission ,symbol? "When the music is at top-level,
 whether to allow, forbid or force a page turn.")
      (parenthesize ,boolean? "Enclose resulting objects in parentheses?")
+     (partial-duration ,ly:duration? "The length of a partial measure as a
+duration.")
      (part-combine-status ,symbol? "Change to what kind of state?
 Options are @code{solo1}, @code{solo2} and @code{unisono}.")
      (pitch ,ly:pitch? "The pitch of this note.")
index 7f4525e0013b7a3f42017c5e0d01bd81b1fc2763..4b446d72b7143a0df64bd4f4c1d1fbae3551cc3c 100644 (file)
@@ -349,6 +349,12 @@ Syntax: @code{\\override} [ @var{context} @code{.} ]
        (types . (general-music break-event page-turn-event event))
        ))
 
+    (PartialSet
+     . ((description . "Create an anacrusis or upbeat (partial measure).")
+       (iterator-ctor . ,ly:partial-iterator::constructor)
+       (types . (general-music partial-set))
+       ))
+
     (PartCombineMusic
      . ((description . "Combine two parts on a staff, either merged or
 as separate voices.")
index decc5153616f5d87c5b92df9584fc09abf161223..82aee84d0a7190b1a9c0cdcec230f933d00d483b 100644 (file)
@@ -248,12 +248,14 @@ into a @code{MultiMeasureTextEvent}."
          (set! (ly:music-property ev 'label) label)
          ch))))
 
-(define-ly-syntax-simple (partial dur)
+(define-ly-syntax (partial parser location dur)
   "Make a partial measure."
-  (let ((mom (ly:moment-sub ZERO-MOMENT (ly:duration-length dur))))
 
-    ;; We use `descend-to-context' here instead of `context-spec-music' to
-    ;; ensure \partial still works if the Timing_translator is moved
+  ;; We use `descend-to-context' here instead of `context-spec-music' to
+  ;; ensure \partial still works if the Timing_translator is moved
     (descend-to-context
-     (context-spec-music (make-property-set 'measurePosition mom) 'Timing)
-     'Score)))
+     (context-spec-music (make-music 'PartialSet
+                                    'origin location
+                                    'partial-duration dur)
+                        'Timing)
+     'Score))