1 ;------------------------------------------------------------------;
2 ; opus_libre -- 80-buildskel.scm ;
4 ; (c) 2008-2011 Valentin Villenave <valentin@villenave.net> ;
6 ; opus_libre is a free framework for GNU LilyPond: you may ;
7 ; redistribute it and/or modify it under the terms of the GNU ;
8 ; General Public License as published by the Free Software ;
9 ; Foundation, either version 3 of the License, or (at your option) ;
10 ; any later version. ;
11 ; This program is distributed WITHOUT ANY WARRANTY; without ;
12 ; even the implied warranty of MERCHANTABILITY or FITNESS FOR A ;
13 ; PARTICULAR PURPOSE. You should have received a copy of the GNU ;
14 ; General Public License along with this program (typically in the ;
15 ; share/doc/ directory). If not, see http://www.gnu.org/licenses/ ;
17 ;------------------------------------------------------------------;
20 (scm-load "libdynamics.scm")
21 (scm-load "libtext.scm")
23 (define *has-timeline* (make-parameter #f))
25 (define (assoc-name alist name)
26 "If NAME begins with a lower case letter, then
27 try to find a matching entry in ALIST."
28 (let ((res (assoc-ref alist name)))
29 (if (not (string=? "" name))
30 (if (char-lower-case? (car (string->list name)))
31 (if (string? res) res name) name) name)))
33 (define (include-music name)
34 "Turn NAME into a music expression if one exists."
35 (let ((mus (ly:parser-lookup parser (string->symbol name))))
37 (begin (ly:debug-message "Loading music from ~a..." name)
39 (begin (ly:debug-message "Variable ~a doesn't exist." name)
40 (make-music 'Music 'void #t)))))
42 (define (make-this-text name suffix)
43 "Associate NAME with SUFFIX, and check if a suitable
45 (let ((mark (ly:parser-lookup parser
47 (string-append name suffix)))))
48 (if (markup? mark) mark
50 (ly:debug-message "No text found in ~a~a" name suffix)
51 (if (ly:get-option 'use-variable-names)
52 (regexp-substitute/global #f "[A-Z]" name 'pre " "0 'post)
53 (make-null-markup))))))
55 (define (make-this-layout name suffix)
56 "Associate NAME with SUFFIX, and check if a local \\layout{} block
57 exists with that name. If so, parse it."
58 (let* ((fullname (string-append name (string-capitalize suffix)))
59 (def (ly:parser-lookup parser (string->symbol fullname))))
60 (if (ly:output-def? def)
61 (begin (ly:debug-message "Using layout definition from variable ~a" fullname)
63 (begin (ly:debug-message "No layout definitions stored in ~a" fullname)
67 ;; "If NAME matches a defined music expression, then
68 ;; create a Voice for it. If a matching timeline can be
69 ;; found, try and squash it as well."
70 (define-music-function (parser location name) (string?)
71 (let* ((current-name (string-append (*current-part*) name))
72 (music (ly:parser-lookup parser (string->symbol current-name)))
73 (global-timeline (if (not (*has-timeline*))
74 (ly:parser-lookup parser
76 (string-append (*current-part*) lang:timeline-suffix)))
78 (local-timeline (ly:parser-lookup parser
80 (string-append current-name lang:timeline-suffix)))))
81 (ly:debug-message "Loading music from ~a..." current-name)
86 $(if (ly:music? local-timeline)
88 (if (ly:music? global-timeline)
89 (begin (*has-timeline* #t) global-timeline)))
92 (begin (ly:debug-message "Variable ~a doesn't exist." current-name)
93 (make-music 'Music 'void #t))))))
96 ;; "If NAME matches an existing music expression, then
97 ;; create a Dynamics context for it. If NAME includes
98 ;; several names separated with spaces, then look for
99 ;; music expressions matching each available names."
100 (define-music-function (parser location name) (string?)
101 (let ((str-list (if (string-any #\sp name)
102 (string-split name #\sp)
106 (let* ((m (ly:parser-lookup parser
107 (string->symbol x))))
112 #{\context PianoDynamics = $name
116 (if (not-null? ret-list)
117 (make-simultaneous-music ret-list)
118 (make-music 'Music 'void #t)))))
121 ;; "If NAME matches a defined music expression, then
122 ;; create a Staff for it. Then find and include any
123 ;; instrumentName or Lyrics expression that could match
124 ;; this staff (using appropriate suffixes)."
125 (define-music-function (parser location name) (string?)
126 (let* ((name (assoc-name lang:instruments name))
127 (current-name (string-append (*current-part*) name))
128 (music (ly:parser-lookup parser (string->symbol current-name)))
129 (instr (make-this-text name lang:instr-suffix))
130 (short-instr (make-this-text name lang:short-instr-suffix)))
131 (if (ly:music? music)
133 \new Staff = $name \with {
134 instrumentName = $instr
135 shortInstrumentName = $short-instr
140 (begin (ly:debug-message "Variable ~a doesn't exist." current-name)
141 (make-music 'Music 'void #t))))))
144 ;; "From the given NAME, try and find as many Lyrics
145 ;; expressions as possible, using the lyrics suffix and
146 ;; (unless 'only-suffixed-varnames is set) numbers as
147 ;; suffixes: in case there would be multiple verses, etc.
148 ;; Create Lyrics contexts accordingly."
149 (define-music-function (parser location name) (string?)
150 (let* ((name (assoc-name lang:instruments name))
151 (current-name (string-append (*current-part*) name)))
153 $(let* ((musiclist (list #{ {} #}))
154 (numlist (if (ly:get-option 'only-suffixed-varnames)
156 (cons "" lang:numbers))))
158 (let* ((lyr-name (string-append current-name lang:lyrics-suffix
159 (string-capitalize x)))
160 (lyrics (ly:parser-lookup parser (string->symbol lyr-name))))
161 (if (ly:music? lyrics)
162 (append! musiclist (list
163 #{ \new Lyrics \lyricsto $name $lyrics #})))))
165 (make-simultaneous-music musiclist))
168 (define newGrandStaff
169 ;; "From the given NAME, try and find as many instrument
170 ;; parts as possible, by appending numbers as suffixes. Then
171 ;; create a GrandStaff containing staves for e.g.
172 ;; \fluteOne, \fluteTwo, \fluteThree etc. as needed."
173 (define-music-function (parser location name) (string?)
175 $(let* ((name (assoc-name lang:instruments name))
176 (musiclist (list #{ {} #}))
177 (numlist (if (ly:get-option 'only-suffixed-varnames)
179 (cons "" lang:numbers))))
181 (let ((staff-name (string-append (*current-part*) name (string-capitalize x))))
182 (append! musiclist (list
183 #{ \newStaff $staff-name #}))))
185 (make-simultaneous-music musiclist))
188 (define newPianoStaff ;; TODO: include lyrics?
189 ;; "Create a PianoStaff with two staves named after
190 ;; the appropriate upper-hand/lower-hand localized definitions,
191 ;; that are also used in the variables as suffixes (e.g.
192 ;; \PianoRh, \PianoLh). This also allows for localized
193 ;; Staff-\changing shorthands. If a suitable Dynamics
194 ;; expression is found, it will also be included accordingly;
195 ;; else if automatic-piano-dynamics is set, a Dynamics context
196 ;; will be created using dynamics from either staff (or both)."
197 (define-music-function (parser location name) (string?)
198 (let* ((name (assoc-name lang:instruments name))
199 (upper (string-append name (string-capitalize lang:upper-hand)))
200 (lower (string-append name (string-capitalize lang:lower-hand)))
201 (dynamics (string-append (*current-part*) name lang:dynamics-suffix))
202 (dynvar (ly:parser-lookup parser (string->symbol dynamics)))
203 (instr (make-this-text name lang:instr-suffix))
204 (short-instr (make-this-text name lang:short-instr-suffix)))
205 ;; requires removeDynamics, defined in libdynamics.scm
206 #{ \new PianoStaff \with {
207 instrumentName = $instr
208 shortInstrumentName = $short-instr
210 \new Staff = $lang:upper-hand
211 \removeDynamics \newVoice $upper
212 \newDynamics $(if (ly:music? dynvar)
215 (*current-part*) upper
217 (*current-part*) lower))
218 \new Staff = $lang:lower-hand
219 \removeDynamics \newVoice $lower
222 (define newChordNames
223 ;; "If NAME matches a defined music expression, then
224 ;; create a Voice for it. If a matching timeline can be
225 ;; found, try and squash it as well."
226 (define-music-function (parser location name) (string?)
227 (let* ((current-name (string-append (*current-part*) name))
228 (music (ly:parser-lookup parser (string->symbol current-name))))
229 (ly:debug-message "Loading music from ~a..." current-name)
230 (if (ly:music? music)
231 #{ \new ChordNames = $name $music #}
232 (begin (ly:debug-message "Variable ~a doesn't exist." current-name)
233 (make-music 'Music 'void #t))))))