From: Reinhold Kainhofer Date: Wed, 3 Aug 2011 19:19:28 +0000 (+0200) Subject: Fix 1214: Don't crash with \relative c' \new Voice {...} X-Git-Tag: release/2.15.9-1~10^2~14^2 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=1b11dc0cb1bec0e353773aac6b8afba9030f88c4;p=lilypond.git Fix 1214: Don't crash with \relative c' \new Voice {...} 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. --- diff --git a/Documentation/notation/staff.itely b/Documentation/notation/staff.itely index b4e471f7b0..2ac1294258 100644 --- a/Documentation/notation/staff.itely +++ b/Documentation/notation/staff.itely @@ -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. diff --git a/input/regression/quote-during-subvoice.ly b/input/regression/quote-during-subvoice.ly index 00ba9f22d1..6b39f07a27 100644 --- a/input/regression/quote-during-subvoice.ly +++ b/input/regression/quote-during-subvoice.ly @@ -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 + } +>> diff --git a/scm/music-functions.scm b/scm/music-functions.scm index c313600199..3394ed1b3b 100644 --- a/scm/music-functions.scm +++ b/scm/music-functions.scm @@ -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)) diff --git a/scm/part-combiner.scm b/scm/part-combiner.scm index 54f9ea4a57..8c779a91ee 100644 --- a/scm/part-combiner.scm +++ b/scm/part-combiner.scm @@ -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)))))