]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix 1214: Don't crash with \relative c' \new Voice {...}
authorReinhold Kainhofer <reinhold@kainhofer.com>
Wed, 3 Aug 2011 19:19:28 +0000 (21:19 +0200)
committerReinhold Kainhofer <reinhold@kainhofer.com>
Sat, 13 Aug 2011 10:37:08 +0000 (12:37 +0200)
Also add better warnings if the quoted music is empty
or cannot be found.

Also works if a complete voice (or a more complex structure) is
quoted, i.e. when one uses
   \addQuote "quote" \new Voice {...}
   \addQuote "quote" \relative c' \new Voice {...}

As a positive (unintended) side-effect, quoting music
with parallel sections, i.e. containing << { ...} \\ { ...} >>
now also quote those notes.

Documentation/notation/staff.itely
input/regression/quote-during-subvoice.ly
scm/music-functions.scm
scm/part-combiner.scm

index b4e471f7b09233c22d62a24c6ffe5cfc72346e7f..2ac12942588040d1c86c482b8be26963a7f7ef95 100644 (file)
@@ -1173,9 +1173,9 @@ Installed Files:
 
 @knownissues
 Only the contents of the first @code{Voice} occurring in an
-@code{\addQuote} command will be considered for quotation, so the music
-expression must not contain @code{\new} and @code{\context Voice}
-statements which would switch to a different Voice.  Quoting grace notes
+@code{\addQuote} command will be considered for quotation, so if the music
+expression contains @code{\new} or @code{\context Voice}
+statements, their contents will not be quoted.  Quoting grace notes
 is unsupported and may cause LilyPond to crash whereas quoting nested
 triplets may result in poor notation.
 
index 00ba9f22d11bee69b01f7d34a96f3150311bd32e..6b39f07a27fd39bc5e0fde3e14f29eab5bca2e3c 100644 (file)
@@ -1,21 +1,68 @@
-\version "2.15.6"
+\version "2.15.9"
 
 \header {
   texidoc = "@code{\\quoteDuring} and @code{\\cueDuring} shall properly quote
-voices that create a sub-voice. The sub-voice will not be quoted, though.
+voices that create a sub-voice.  The sub-voice will not be quoted, though.
+Exceptions are sections of parallel music @code{<< @{...@} \\ @{...@} >>},
+which will be quoted.
 "
 }
 
-
+% Simple case, normal sub-voice
 quoteMe = \relative c' {
   c4 c
   \new Voice {
     c4 c
   }
 }
-\addQuote quoteMe \quoteMe
+\addQuote "quoteMe" \quoteMe
+% Also works if wrapped with \new Voice
+\addQuote "quoteMeA" \new Voice \quoteMe
+
+% Also works with voice directly inside relative
+quoteMeI = \relative c' \new Voice {
+  c4 c4
+}
+\addQuote "quoteMeI" \quoteMeI
+
+% Quoting music with some parallel sections (identical rhythm)
+quoteMeII = \relative c' {
+  c4 c
+  << { d4 e4 } \\ { c4 b4 } >>
+  c4
+}
+\addQuote "quoteMeII" \quoteMeII
 
-\relative c'' {
-  c4 \cueDuring #"quoteMe" #DOWN { r4 } % <- show a cue note from quoteMe
-  c4 \cueDuring #"quoteMe" #DOWN { r4 } % <- no cue note due to sub-voice
+% Quoting music with some parallel sections (different rhythm)
+quoteMeIII = \relative c' {
+  c4 c
+  << { d4 e4 } \\ { c4. b8 } >>
+  c4
 }
+\addQuote "quoteMeIII" \quoteMeIII
+
+
+
+
+<<
+  \new Staff \relative c'' {
+    c4 \cueDuring #"quoteMe" #DOWN { r4 }
+    c4 \cueDuring #"quoteMe" #DOWN { r4 } % <- no cue note due to sub-voice
+  }
+  \new Staff \relative c'' {
+    c4 \cueDuring #"quoteMeA" #DOWN { r4 }
+    c4 \cueDuring #"quoteMeA" #DOWN { r4 } % <- no cue note due to sub-voice
+  }
+  \new Staff \relative c'' {
+    c4 \cueDuring #"quoteMeI" #DOWN { r4 }
+    c4
+  }
+  \new Staff \relative c'' {
+    c4 \cueDuring #"quoteMeII" #DOWN { r4 }
+    c4 \cueDuring #"quoteMeII" #DOWN { r4 } % <- quoted parallel notes
+  }
+  \new Staff \relative c'' {
+    c4 \cueDuring #"quoteMeIII" #DOWN { r4 }
+    c4 \cueDuring #"quoteMeIII" #DOWN { r4 } % <- quoted parallel notes
+  }
+>>
index c31360019912c04285896b5c1e3a19381d5f8736..3394ed1b3b78c3489de22ceef025be00b76dedc1 100644 (file)
@@ -842,7 +842,7 @@ Syntax:
              (set! (ly:music-property music 'quoted-events) quoted-vector)
              (set! (ly:music-property music 'iterator-ctor)
                    ly:quote-iterator::constructor))
-           (ly:warning (_ "cannot find quoted music: `~S'") quoted-name)))
+           (ly:music-message music (ly:format (_ "cannot find quoted music: `~S'") quoted-name))))
     music))
 
 
index 54f9ea4a57aeefe4a3389c6a779e85cc06d78c1d..8c779a91ee19944affc53ee95d8848e5f1582724 100644 (file)
@@ -571,18 +571,27 @@ the mark when there are no spanners active.
 
 (define-public (add-quotable parser name mus)
   (let* ((tab (eval 'musicQuotes (current-module)))
-         ;; If a Voice is passed, use its contents:
-         (contents (if (equal? (ly:music-property mus 'name) 'ContextSpeccedMusic)
-                       (ly:music-property mus 'element)
-                       mus))
          (voicename (get-next-unique-voice-name))
-         ;; recording-group-emulate returns an assoc list, so hand it a
-         ;; proper unique context name and extract that key:
-         (context-list (recording-group-emulate (context-spec-music contents 'Voice voicename)
-                                                (ly:parser-lookup parser 'partCombineListener)))
-         (quote-contents (if (assoc voicename context-list)
-                             (assoc-get voicename context-list)
-                             '())))
-
-    (if quote-contents
-        (hash-set! tab name (list->vector (reverse! quote-contents '()))))))
+         ;; recording-group-emulate returns an assoc list (reversed!), so
+         ;; hand it a proper unique context name and extract that key:
+         (ctx-spec (context-spec-music mus 'Voice voicename))
+         (listener (ly:parser-lookup parser 'partCombineListener))
+         (context-list (reverse (recording-group-emulate ctx-spec listener)))
+         (raw-voice (assoc voicename context-list))
+         (quote-contents (if (pair? raw-voice) (cdr raw-voice) '())))
+
+    ;; If the context-specced quoted music does not contain anything, try to
+    ;; use the first child, i.e. the next in context-list after voicename
+    ;; That's the case e.g. for \addQuote "x" \relative c \new Voice {...}
+    (if (null? quote-contents)
+        (let find-non-empty ((current-tail (member raw-voice context-list)))
+          ;; if voice has contents, use them, otherwise check next ctx
+          (cond ((null? current-tail) #f)
+                ((and (pair? (car current-tail))
+                      (pair? (cdar current-tail)))
+                 (set! quote-contents (cdar current-tail)))
+                (else (find-non-empty (cdr current-tail))))))
+
+    (if (not (null? quote-contents))
+        (hash-set! tab name (list->vector (reverse! quote-contents '())))
+        (ly:music-message mus (ly:format (_ "quoted music `~a' is empty") name)))))