From 28b03579e5129ba89e9b07d0170dee73202bf110 Mon Sep 17 00:00:00 2001 From: Nicolas Sceaux Date: Sun, 22 Jan 2006 17:48:54 +0000 Subject: [PATCH] * ly/music-functions-init.ly (parallelMusic): new music function for parallel music entry. * scm/define-music-properties.scm (all-music-properties): new 'void music property * scm/music-functions.scm (ly:music-message): make public, to be used in music function definitions * scm/lily-library.scm (collect-music-for-book): discard music when the 'void property is set. --- ChangeLog | 13 +++++ ly/music-functions-init.ly | 90 +++++++++++++++++++++++++++++++-- scm/define-music-properties.scm | 2 + scm/lily-library.scm | 5 +- scm/music-functions.scm | 2 +- 5 files changed, 107 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 25e13176e8..6e932bd105 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2006-01-22 Nicolas Sceaux + + * ly/music-functions-init.ly (parallelMusic): new music function for parallel + music entry. + + * scm/define-music-properties.scm (all-music-properties): new 'void music property + + * scm/music-functions.scm (ly:music-message): make public, to be + used in music function definitions + + * scm/lily-library.scm (collect-music-for-book): discard music + when the 'void property is set. + 2006-01-22 Han-Wen Nienhuys * lily/ttf.cc (LY_DEFINE): store name before destroying face. diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly index 3ace0c203b..8a8e24706d 100644 --- a/ly/music-functions-init.ly +++ b/ly/music-functions-init.ly @@ -310,6 +310,90 @@ assertBeamSlope = (list chain-grob-member-functions `(,cons 0 0)) (check-slope-callbacks comp)))))) - - - +parallelMusic = +#(def-music-function (parser location voice-ids music) (list? ly:music?) + "Define parallel music sequences, separated by '|' (bar check signs), +and assign them to the identifiers provided in @var{voice-ids}. + +@var{voice-ids}: a list of music identifiers (symbols containing only letters) + +@var{music}: a music sequence, containing BarChecks as limiting expressions. + +Example: + \\parallelMusic #'(A B C) { + c c | d d | e e | + d d | e e | f f | + } +<==> + A = { c c | d d | } + B = { d d | e e | } + C = { e e | f f | } +" + (let* ((voices (apply circular-list (make-list (length voice-ids) (list)))) + (current-voices voices) + (current-sequence (list))) + ;; + ;; utilities + (define (push-music m) + "Push the music expression into the current sequence" + (set! current-sequence (cons m current-sequence))) + (define (change-voice) + "Stores the previously built sequence into the current voice and + change to the following voice." + (list-set! current-voices 0 (cons (make-music 'SequentialMusic + 'elements (reverse! current-sequence)) + (car current-voices))) + (set! current-sequence (list)) + (set! current-voices (cdr current-voices))) + (define (bar-check? m) + "Checks whether m is a bar check." + (eq? (ly:music-property m 'name) 'BarCheck)) + (define (music-origin music) + "Recursively search an origin location stored in music." + (cond ((null? music) #f) + ((not (null? (ly:music-property music 'origin))) + (ly:music-property music 'origin)) + (else (or (music-origin (ly:music-property music 'element)) + (let ((origins (remove not (map music-origin + (ly:music-property music 'elements))))) + (and (not (null? origins)) (car origins))))))) + ;; + ;; first, split the music and fill in voices + (map-in-order (lambda (m) + (push-music m) + (if (bar-check? m) (change-voice))) + (ly:music-property music 'elements)) + (if (not (null? current-sequence)) (change-voice)) + ;; un-circularize `voices' and reorder the voices + (set! voices (map-in-order (lambda (dummy seqs) + (reverse! seqs)) + voice-ids voices)) + ;; + ;; set origin location of each sequence in each voice + ;; for better type error tracking + (for-each (lambda (voice) + (for-each (lambda (seq) + (set! (ly:music-property seq 'origin) + (or (music-origin seq) location))) + voice)) + voices) + ;; + ;; check sequence length + (apply for-each (lambda (. seqs) + (let ((moment-reference (ly:music-length (car seqs)))) + (for-each (lambda (seq moment) + (if (not (equal? moment moment-reference)) + (ly:music-message seq + "Bars in parallel music don't have the same length"))) + seqs (map-in-order ly:music-length seqs)))) + voices) + ;; + ;; bind voice identifiers to the voices + (map (lambda (voice-id voice) + (ly:parser-define! parser voice-id + (make-music 'SequentialMusic + 'origin location + 'elements voice))) + voice-ids voices)) + ;; Return an empty sequence. this function is actually a "void" function. + (make-music 'SequentialMusic 'void #t)) \ No newline at end of file diff --git a/scm/define-music-properties.scm b/scm/define-music-properties.scm index a9d2f39969..ebd8b9a0ff 100644 --- a/scm/define-music-properties.scm +++ b/scm/define-music-properties.scm @@ -108,6 +108,8 @@ e.g. @code{\\tag #'part ...} could tag a piece of music as only being active in engraver this music expression is processed.") (value ,scheme? "Assignment value for a translation property") + (void ,boolean? "If this property is #t, then the music expression is to be +discarded by the toplevel music handler.") (what ,symbol? "What to change for auto-change. FIXME, naming") (part-combine-status ,symbol? "Change to what kind of state? Options are diff --git a/scm/lily-library.scm b/scm/lily-library.scm index 5788f37a35..057d6f8807 100644 --- a/scm/lily-library.scm +++ b/scm/lily-library.scm @@ -75,7 +75,10 @@ (ly:make-score music)) (define-public (collect-music-for-book parser music) - (collect-scores-for-book parser (scorify-music music parser))) + ;; discard music if its 'void property is true. + (let ((void-music (ly:music-property music 'void))) + (if (or (null? void-music) (not void-music)) + (collect-scores-for-book parser (scorify-music music parser))))) (define-public (print-book-with-defaults parser book) diff --git a/scm/music-functions.scm b/scm/music-functions.scm index 0074d3a1f6..3650dd0e8b 100644 --- a/scm/music-functions.scm +++ b/scm/music-functions.scm @@ -603,7 +603,7 @@ SkipEvent. Useful for extracting parts from crowded scores" (equal? (ly:music-property x 'name) 'RequestChord)) elts))) -(define (ly:music-message music msg) +(define-public (ly:music-message music msg) (let ((ip (ly:music-property music 'origin))) (if (ly:input-location? ip) (ly:input-message ip msg) -- 2.39.5