1 ;------------------------------------------------------------------;
2 ; opus_libre -- 80-buildskel.scm ;
4 ; (c) 2008-2010 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 ;------------------------------------------------------------------;
21 (define (assoc-name alist name)
22 "If NAME begins with a lower case letter, then
23 try to find a matching entry in ALIST."
24 (let ((res (assoc-ref alist name)))
25 (if (not (string=? "" name))
26 (if (char-lower-case? (car (string->list name)))
27 (if (string? res) res name) name) name)))
29 (define (include-music name)
30 "Turn NAME into a music expression if one exists."
31 (let ((mus (ly:parser-lookup parser (string->symbol name))))
33 (begin (ly:debug-message "Loading music from ~a..." name)
35 (begin (ly:debug-message "Variable ~a doesn't exist." name)
36 (make-music 'Music 'void #t)))))
38 (define (make-this-text name suffix)
39 "Associate NAME with SUFFIX, and check if a suitable
41 (let ((mark (ly:parser-lookup parser
43 (string-append name suffix)))))
44 (if (markup? mark) mark
46 (ly:debug-message "No text found in ~a~a" name suffix)
47 (if (ly:get-option 'use-variable-names)
48 (regexp-substitute/global #f "[A-Z]" name 'pre " "0 'post)
52 ;; "If NAME matches a defined music expression, then
53 ;; create a Voice for it. If a matching timeline can be
54 ;; found, try and squash it as well."
55 (define-music-function (parser location name) (string?)
56 (let* ((current-name (string-append current-part name))
57 (music (ly:parser-lookup parser (string->symbol current-name)))
58 (part-timeline (ly:parser-lookup parser
60 (string-append current-part lang:timeline-suffix))))
61 (instr-timeline (ly:parser-lookup parser
63 (string-append current-name lang:timeline-suffix)))))
64 (ly:debug-message "Loading music from ~a..." current-name)
69 $(if (ly:music? instr-timeline)
71 (if (ly:music? part-timeline)
75 (begin (ly:debug-message "Variable ~a doesn't exist." current-name)
76 (make-music 'Music 'void #t))))))
79 ;; "If NAME matches an existing music expression, then
80 ;; create a Dynamics context for it. If NAME includes
81 ;; several names separated with spaces, then look for
82 ;; music expressions matching each available names."
83 (define-music-function (parser location name) (string?)
84 (let ((str-list (if (string-any #\sp name)
85 (string-split name #\sp)
89 (let* ((m (ly:parser-lookup parser
95 #{\context Dynamics = $name
99 (if (not (null? ret-list))
100 (make-simultaneous-music ret-list)
101 (make-music 'Music 'void #t)))))
104 ;; "If NAME matches a defined music expression, then
105 ;; create a Staff for it. Then find and include any
106 ;; instrumentName or Lyrics expression that could match
107 ;; this staff (using appropriate suffixes)."
108 (define-music-function (parser location name) (string?)
109 (let* ((name (assoc-name lang:instruments name))
110 (current-name (string-append current-part name))
111 (music (ly:parser-lookup parser (string->symbol current-name)))
112 (instr (make-this-text name lang:instr-suffix))
113 (short-instr (make-this-text name lang:short-instr-suffix))
114 (lyrics (ly:parser-lookup parser
116 (string-append current-name lang:lyrics-suffix)))))
117 (if (ly:music? music)
120 instrumentName = $instr
121 shortInstrumentName = $short-instr
124 $(if (ly:music? lyrics)
125 #{ \new Lyrics \lyricsto $name $lyrics #})
127 (begin (ly:debug-message "Variable ~a doesn't exist." current-name)
128 (make-music 'Music 'void #t))))))
131 ;; "From the given NAME, try and find as many Lyrics
132 ;; expressions as possible, using the lyrics suffix and
133 ;; (unless 'only-suffixed-varnames is set) numbers as
134 ;; suffixes: in case there would be multiple verses, etc.
135 ;; Create Lyrics contexts accordingly."
136 (define-music-function (parser location name) (string?)
137 (let* ((name (assoc-name lang:instruments name))
138 (current-name (string-append current-part name)))
140 $(let* ((musiclist (list #{ {} #}))
141 (numlist (if (ly:get-option 'only-suffixed-varnames)
143 (cons "" lang:numbers))))
145 (let* ((lyr-name (string-append current-name lang:lyrics-suffix
146 (string-capitalize x)))
147 (lyrics (ly:parser-lookup parser (string->symbol lyr-name))))
148 (if (ly:music? lyrics)
149 (append! musiclist (list
150 #{ \new Lyrics \lyricsto $name $lyrics #})))))
152 (make-simultaneous-music musiclist))
155 (define newGrandStaff
156 ;; "From the given NAME, try and find as many instrument
157 ;; parts as possible, by appending numbers as suffixes. Then
158 ;; create a GrandStaff containing staves for e.g.
159 ;; \fluteOne, \fluteTwo, \fluteThree etc. as needed."
160 (define-music-function (parser location name) (string?)
162 $(let* ((name (assoc-name lang:instruments name))
163 (musiclist (list #{ {} #}))
164 (numlist (if (ly:get-option 'only-suffixed-varnames)
166 (cons "" lang:numbers))))
168 (let ((staff-name (string-append current-part name (string-capitalize x))))
169 (append! musiclist (list
170 #{ \newStaff $staff-name #}))))
172 (make-simultaneous-music musiclist))
175 (define newPianoStaff ;; TODO: include lyrics?
176 ;; "Create a PianoStaff with two staves named after
177 ;; the appropriate upper-hand/lower-hand localized definitions,
178 ;; that are also used in the variables as suffixes (e.g.
179 ;; \PianoRh, \PianoLh). This also allows for localized
180 ;; Staff-\changing shorthands. If a suitable Dynamics
181 ;; expression is found, it will also be included accordingly;
182 ;; else if automatic-piano-dynamics is set, a Dynamics context
183 ;; will be created using dynamics from either staff (or both)."
184 (define-music-function (parser location name) (string?)
185 (let* ((name (assoc-name lang:instruments name))
186 (upper (string-append name (string-capitalize lang:upper-hand)))
187 (lower (string-append name (string-capitalize lang:lower-hand)))
188 (dynamics (string-append current-part name lang:dynamics-suffix))
189 (dynvar (ly:parser-lookup parser (string->symbol dynamics)))
190 (instr (make-this-text name lang:instr-suffix))
191 (short-instr (make-this-text name lang:short-instr-suffix)))
192 ;; requires removeDynamics, defined in libmusic.scm
193 ;; (which should have been loaded by now, since macros need it).
194 #{ \new PianoStaff \with {
195 instrumentName = $instr
196 shortInstrumentName = $short-instr
198 \new Staff = $lang:upper-hand
199 \removeDynamics \newVoice $upper
200 \newDynamics $(if (ly:music? dynvar)
202 (string-append upper " " lower))
203 \new Staff = $lang:lower-hand
204 \removeDynamics \newVoice $lower