Am 12.08.2016 um 15:48 schrieb Kieren MacMillan:
My expectation (and desires) would be that it would say “a2” (or whatever the 
aDueText is) in m1.
Instead, it says “solo” (or whatever the soloText is).

Am I misusing either the quote mechanism or the partcombine mechanism? Or is 
this expected behaviour, and if so, is there a mechanism to automatically 
handle such a circumstance such that it accurately indicates who is playing m1?

I think the problem is that \quoteDuring sets only a QuoteMusic event instead of copying music. This is also why quotes are not transitive, i. e. if B quotes A and C quotes B *at the same time* the music of A doesn’t appear in C.

I made a hacky workaround that redefines addQuote and defines a new function \replaceQuotes that replaces QuoteMusic events by actual music. This has some limitations though: You have to use \addQuote on every instrument, even if it isn’t quoted. And the name of the quote changes the name of the variable; see lines 168 to 171 of the attached file. (The file alignTo.ily mentioned at line 172ff. is another hack of mine which you don’t need.) And you have to call \replaceQuotes by hand. Probably there are some other bugs/limitations but maybe it helps ;)

Of course it would be nice if LilyPond allowed quotes that really copy the quoted music to the quoting instrument.

%%%%%%%% this is how to use the solution

\version "2.19.46"
\include "transitiveReplace.ily"

hornI = {
  c'4 4 4 4
  d'4 4 4 4
}
\addQuote "hornI" \hornI

hornII = \displayMusic {
  \quoteDuring "hornI" s1
  b4 4 4 4
}
\addQuote "hornII" \hornII

\replaceQuotes

\score {
  \new Staff \partcombine \hornI \hornII
}
\version "2.19.25"

% TODO: rename malte-length and malte-abs-time?
% TODO: rename replace-all-in-all?

% adds property 'malte-length to all music
add-length =
#(define-music-function (music) (ly:music?)
   (music-map
    (lambda (m)
      (ly:music-set-property! m 'malte-length (ly:music-length m))
      m)
    music))

% adds property 'malte-abs-time (time since beginning) to all music
add-abs-time =
#(define-music-function (music) (ly:music?)
   (let loop ((cur-time (ly:make-moment 0))
              (music music))
     (ly:music-set-property! music 'malte-abs-time cur-time)
     (cond
      ((music-is-of-type? music 'music-wrapper-music)
       (loop cur-time (ly:music-property music 'element))
       music)
      ((music-is-of-type? music 'simultaneous-music)
       (map
        (lambda (element)
          (loop cur-time element))
        (ly:music-property music 'elements))
       music)
      ((music-is-of-type? music 'sequential-music)
       (map
        (lambda (element)
          (loop cur-time element)
          (set! cur-time (ly:moment-add cur-time (ly:music-property element 
'malte-length))))
        (ly:music-property music 'elements))
       music)
      (else
       music))))

% extracts music between begin-moment (inclusive) and end-moment (exclusive),
% correctly extracting only parts of quotes (but not yet other wrappers like 
tuplets)
extract-music-between =
#(define-music-function (begin-moment end-moment original-music) (ly:moment? 
ly:moment? ly:music?)
   (let ((music (ly:music-deep-copy original-music))) ; TODO: deep-copy 
necessary?
     (let loop ((music music))
       (cond
        ((eq? (ly:music-property music 'name) 'QuoteMusic)
         (let* ((quote-begin (ly:music-property music 'malte-abs-time))
                (quote-end (ly:moment-add quote-begin (ly:music-property music 
'malte-length)))
                (shortened? #f))
           (if (ly:moment<? quote-begin begin-moment)
               (begin
                (set! quote-begin begin-moment)
                (set! shortened? #t)))
           (if (ly:moment<? end-moment quote-end)
               (begin
                (set! quote-end end-moment)
                (set! shortened? #t)))
           (if shortened?
               (let ((newdur (ly:moment-sub quote-end quote-begin)))
                 (ly:music-set-property! music 'element
                   (make-music 'SkipEvent
                     'duration (make-duration-of-length newdur)))
                 (ly:music-set-property! music 'malte-abs-time quote-begin)
                 (ly:music-set-property! music 'malte-length newdur)))
           music))
        ((music-is-of-type? music 'music-wrapper-music) ; wrapper except 
QuoteMusic
          (loop (ly:music-property music 'element))
          (ly:music-set-property! music 'malte-length (ly:music-length music))
          (ly:music-set-property! music 'malte-abs-time
            (ly:music-property (ly:music-property music 'element) 
'malte-abs-time))
          music)
        ((music-is-of-type? music 'simultaneous-music) ; TODO: shorten?
          (map loop
            (ly:music-property music 'elements))
          music)
        ((music-is-of-type? music 'sequential-music)
         (ly:music-set-property! music 'elements
           (drop-while (lambda (element)
                         (and
                          (ly:moment<? (ly:music-property element 
'malte-abs-time) begin-moment)
                          (not (and
                                ;(eq? (ly:music-property element 'name) 
'QuoteMusic)
                                (ly:moment<? begin-moment (ly:moment-add
                                                           (ly:music-property 
element 'malte-abs-time)
                                                           (ly:music-property 
element 'malte-length)))))))
             (take-while (lambda (element)
                           (ly:moment<? (ly:music-property element 
'malte-abs-time) end-moment))
               (ly:music-property music 'elements))))
         (let ((elements (ly:music-property music 'elements)))
           (map loop elements)
           (ly:music-set-property! music 'malte-abs-time
             (ly:music-property (car elements) 'malte-abs-time)))
         (ly:music-set-property! music 'malte-length (ly:music-length music))
         music)
        (else ; TODO?
          music)))))

% replaces \quoteDuring #name by extracted music from original-quoted
replace-one-in-one =
#(define-music-function (name original-quoted original-quoting) (string? 
ly:music? ly:music?)
   (let ((quoting (ly:music-deep-copy original-quoting)) ; TODO: deep-copy 
necessary?
          (quoted (ly:music-deep-copy original-quoted))) ; TODO: deep-copy 
necessary?
     (music-map
      (lambda (m)
        (if (and
             (eq? (ly:music-property m 'name) 'QuoteMusic)
             (equal? (ly:music-property m 'quoted-music-name) name))
            (ly:music-transpose ; TODO: don’t transpose if quoted-transposition 
is c'?
              (extract-music-between
               (ly:music-property m 'malte-abs-time)
               (ly:moment-add
                (ly:music-property m 'malte-abs-time)
                (ly:music-property m 'malte-length))
               quoted)
              (ly:music-property m 'quoted-transposition (ly:make-pitch 0 0 
0))) ; default: c'
            m))
      quoting)))

% (string? . ly:music?)
#(define (quote-list-entry? entry)
   (and
    (pair? entry)
    (string? (car entry))
    (ly:music? (cdr entry))))

% list of (string? . ly:music?)
#(define (quote-list? thelist)
   (and
    (list? thelist)
    (every quote-list-entry? thelist)))

% list of string?
#(define (string-list? thelist)
   (and
    (list? thelist)
    (every string? thelist)))

replace-all-in-all-helper =
#(define-syntax-function quote-list? (names everything) (string-list? 
quote-list?)
   (if (null? names)
       everything
       (replace-all-in-all-helper (cdr names)
         (map
          (lambda (element)
            (cons
             (car element)
             (replace-one-in-one (car names) (assoc-ref everything (car names)) 
(cdr element))))
          everything))))

% replaces all occurences of \quoteDuring #name by real music
replace-all-in-all =
#(define-syntax-function ly:music-list? (everything) (quote-list?)
   (map cdr (replace-all-in-all-helper (map car everything) everything)))

% global alist containing (name . music) pairs, to be filled by new \addQuote
#(define quotes-alist '())

% doesn’t use (add-quotable …) but only serves my purpose
addQuote =
#(define-void-function (name music) (string? ly:music?)
   (set! quotes-alist
         (cons
          (cons name (add-abs-time (add-length music)))
          quotes-alist)))

% This (re)defines music variables. The user has to take care of possible
% variable name changes. For example, if something like
%   \addQuote "bsn" \bassoon
% is used, the new variable bsn contains the replaced quotes, not bassoon.
% Another side effect (when using alignTo.ily): If you have something like
%   \addQuote "bassoon" \alignTo \global \bassoon
% you now have to use
%   << \global \bassoon >>
% instead of
%   \useAndAlignTo \global \bassoon
% because bassoon is now already aligned (and \bassoon instead of
% \alignTo \bassoon).

replaceQuotes =
#(define-void-function () ()
   (let ((replaced-quotes-list (replace-all-in-all quotes-alist)))
     (for-each
      (lambda (element-qal element-rql)
        (ly:parser-define! (string->symbol (car element-qal)) element-rql))
      quotes-alist
      replaced-quotes-list)))
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to