]> git.donarmstrong.com Git - lilypond.git/blob - ly/music-functions-init.ly
* lily/relocate.cc (prefix_relocation): allow "current"
[lilypond.git] / ly / music-functions-init.ly
1 % -*-Scheme-*-
2
3 \version "2.7.32"
4
5 %% need SRFI-1 filter 
6
7 #(use-modules (srfi srfi-1))  
8
9
10 tweak = #(def-music-function (parser location sym val arg)
11            (symbol? scheme? ly:music?)
12
13            "Add @code{sym . val} to the @code{tweaks} property of @var{arg}."
14
15            
16            (set!
17             (ly:music-property arg 'tweaks)
18             (acons sym val
19                    (ly:music-property arg 'tweaks)))
20            arg)
21
22 tag = #(def-music-function (parser location tag arg)
23    (symbol? ly:music?)
24
25    "Add @var{tag} to the @code{tags} property of @var{arg}."
26
27    (set!
28     (ly:music-property arg 'tags)
29     (cons tag
30           (ly:music-property arg 'tags)))
31    arg)
32
33 clef =
34 #(def-music-function (parser location type)
35    (string?)
36    
37    "Set the current clef."
38
39    (make-clef-set type))
40
41 bar =
42 #(def-music-function (parser location type)
43    (string?)
44    (context-spec-music
45     (make-property-set 'whichBar type)
46     'Timing))
47
48 applyMusic =
49 #(def-music-function (parser location func music) (procedure? ly:music?)
50                (func music))
51
52 oldaddlyrics =
53 #(def-music-function (parser location music lyrics) (ly:music? ly:music?)
54
55               (make-music 'OldLyricCombineMusic 
56                           'origin location
57                           'elements (list music lyrics)))
58
59 grace =
60 #(def-grace-function startGraceMusic stopGraceMusic)
61
62 acciaccatura =
63 #(def-grace-function startAcciaccaturaMusic stopAcciaccaturaMusic)
64 appoggiatura =
65 #(def-grace-function startAppoggiaturaMusic stopAppoggiaturaMusic)
66
67 partcombine =
68 #(def-music-function (parser location part1 part2) (ly:music? ly:music?)
69                 (make-part-combine-music (list part1 part2)))
70
71 autochange =
72 #(def-music-function (parser location music) (ly:music?)
73                (make-autochange-music music))
74
75 applyContext =
76 #(def-music-function (parser location proc) (procedure?)
77                  (make-music 'ApplyContext 
78                    'origin location
79                    'procedure proc))
80
81 musicMap =
82 #(def-music-function (parser location proc mus) (procedure? ly:music?)
83              (music-map proc mus))
84
85 displayMusic =
86 #(def-music-function (parser location music) (ly:music?)
87                  (display-scheme-music music)
88                  music)
89
90 %% FIXME: guile-1.7 required?
91 %#(use-modules (scm display-lily))invalid module name for use-syntax ((srfi srfi-39))
92
93 #(use-modules (scm display-lily))
94 #(display-lily-init parser)
95 displayLilyMusic =
96 #(def-music-function (parser location music) (ly:music?)
97    (display-lily-music music)
98    music)
99
100 applyOutput =
101 #(def-music-function (parser location proc) (procedure?)
102                 (make-music 'ApplyOutputEvent 
103                   'origin location
104                   'procedure proc))
105
106 overrideProperty =
107 #(def-music-function (parser location name property value)
108    (string? symbol? scheme?)
109
110
111    "Set @var{property} to @var{value} in all grobs named @var{name}.
112 The @var{name} argument is a string of the form @code{\"Context.GrobName\"}
113 or @code{\"GrobName\"}"
114
115    (let*
116        ((name-components (string-split name #\.))
117         (context-name 'Bottom)
118         (grob-name #f))
119
120      (if (> 2 (length name-components))
121          (set! grob-name (string->symbol (car name-components)))
122          (begin
123            (set! grob-name (string->symbol (list-ref name-components 1)))
124            (set! context-name (string->symbol (list-ref name-components 0)))))
125
126      (context-spec-music
127       (make-music 'ApplyOutputEvent
128                   'origin location
129                   'procedure
130                   (lambda (grob orig-context context)
131                     (if (equal?
132                          (cdr (assoc 'name (ly:grob-property grob 'meta)))
133                          grob-name)
134                         (set! (ly:grob-property grob property) value)
135                         )))
136
137       context-name)))
138
139 breathe =
140 #(def-music-function (parser location) ()
141             (make-music 'EventChord 
142               'origin location
143               'elements (list (make-music 'BreathingSignEvent))))
144
145
146 unfoldRepeats =
147 #(def-music-function (parser location music) (ly:music?)
148                   (unfold-repeats music))
149
150 compressMusic =
151 #(def-music-function
152                   (parser location fraction music) (number-pair? ly:music?)
153                   (ly:music-compress music (ly:make-moment (car fraction) (cdr fraction))))
154
155 makeClusters =
156 #(def-music-function
157                 (parser location arg) (ly:music?)
158                 (music-map note-to-cluster arg))
159
160
161 removeWithTag = 
162 #(def-music-function
163   (parser location tag music) (symbol? ly:music?)
164   (music-filter
165    (lambda (m)
166     (let* ((tags (ly:music-property m 'tags))
167            (res (memq tag tags)))
168      (not res)))
169  music))
170               
171 keepWithTag =
172 #(def-music-function
173   (parser location tag music) (symbol? ly:music?)
174   (music-filter
175    (lambda (m)
176     (let* ((tags (ly:music-property m 'tags))
177            (res (memq tag tags)))
178      (or
179       (eq? tags '())
180       res)))
181    music))
182
183
184 %% Todo:
185 %% doing
186 %% def-music-function in a .scm causes crash.
187
188 cueDuring = 
189 #(def-music-function
190   (parser location what dir main-music)
191   (string? ly:dir? ly:music?)
192   (make-music 'QuoteMusic
193               'element main-music 
194               'quoted-context-type 'Voice
195               'quoted-context-id "cue"
196               'quoted-music-name what
197               'quoted-voice-direction dir
198               'origin location))
199
200
201 quoteDuring = #
202 (def-music-function
203   (parser location what main-music)
204   (string? ly:music?)
205   (make-music 'QuoteMusic
206               'element main-music
207               'quoted-music-name what
208               'origin location))
209
210
211
212 pitchedTrill =
213 #(def-music-function
214    (parser location main-note secondary-note)
215    (ly:music? ly:music?)
216    (let*
217        ((get-notes (lambda (ev-chord)
218                      (filter
219                       (lambda (m) (eq? 'NoteEvent (ly:music-property m 'name)))
220                       (ly:music-property ev-chord 'elements))))
221         (sec-note-events (get-notes secondary-note))
222         (trill-events (filter (lambda (m) (memq 'trill-span-event (ly:music-property m 'types)))
223                               (ly:music-property main-note 'elements)))
224
225         (trill-pitch
226          (if (pair? sec-note-events)
227              (ly:music-property (car sec-note-events) 'pitch)
228              )))
229      
230      (if (ly:pitch? trill-pitch)
231          (for-each (lambda (m) (ly:music-set-property! m 'pitch trill-pitch))
232                    trill-events)
233          (begin
234            (ly:warning (_ "Second argument of \\pitchedTrill should be single note: "))
235            (display sec-note-events)))
236
237      main-note))
238
239 killCues =
240 #(def-music-function
241    (parser location music)
242    (ly:music?)
243    (music-map
244     (lambda (mus)
245       (if (string? (ly:music-property mus 'quoted-music-name))
246           (ly:music-property mus 'element)
247           mus)) music))
248    
249
250 afterGraceFraction =
251 #(cons 6 8)
252
253 afterGrace =
254 #(def-music-function
255   (parser location main grace)
256   (ly:music? ly:music?)
257
258   (let*
259       ((main-length (ly:music-length main))
260        (fraction  (ly:parser-lookup parser 'afterGraceFraction)))
261     
262     (make-simultaneous-music
263      (list
264       main
265       (make-sequential-music
266        (list
267
268         (make-music 'SkipMusic
269                     'duration (ly:make-duration
270                                0 0
271                                (* (ly:moment-main-numerator main-length)
272                                   (car fraction))
273                                (* (ly:moment-main-denominator main-length)
274                                   (cdr fraction)) ))
275         (make-music 'GraceMusic
276                     'element grace)))))))
277
278
279 barNumberCheck =
280 #(def-music-function (parser location n) (integer?)
281    (make-music 'ApplyContext 
282                'origin location
283                'procedure 
284                (lambda (c)
285                  (let*
286                      ((cbn (ly:context-property c 'currentBarNumber)))
287                    (if (not (= cbn n))
288                        (ly:input-message location "Barcheck failed got ~a expect ~a"
289                                          cbn n))))))
290
291
292
293 % for regression testing purposes.
294 assertBeamQuant =
295 #(def-music-function (parser location l r) (pair? pair?)
296   (make-grob-property-override 'Beam 'positions
297    (ly:make-simple-closure
298     (ly:make-simple-closure
299      (append
300       (list chain-grob-member-functions `(,cons 0 0))
301       (check-quant-callbacks l r))))))
302     
303 % for regression testing purposes.
304 assertBeamSlope =
305 #(def-music-function (parser location comp) (procedure?)
306   (make-grob-property-override 'Beam 'positions
307    (ly:make-simple-closure
308     (ly:make-simple-closure
309      (append
310       (list chain-grob-member-functions `(,cons 0 0))
311       (check-slope-callbacks comp))))))
312
313
314 parallelMusic =
315 #(def-music-function (parser location voice-ids music) (list? ly:music?)
316   "Define parallel music sequences, separated by '|' (bar check signs),
317 and assign them to the identifiers provided in @var{voice-ids}.
318
319 @var{voice-ids}: a list of music identifiers (symbols containing only letters)
320
321 @var{music}: a music sequence, containing BarChecks as limiting expressions.
322
323 Example:
324   \\parallelMusic #'(A B C) {
325     c c | d d | e e |
326     d d | e e | f f |
327   }
328 <==>
329   A = { c c | d d | }
330   B = { d d | e e | }
331   C = { e e | f f | }
332 "
333   (let* ((voices (apply circular-list (make-list (length voice-ids) (list))))
334          (current-voices voices)
335          (current-sequence (list)))
336     ;;
337     ;; utilities
338     (define (push-music m)
339       "Push the music expression into the current sequence"
340       (set! current-sequence (cons m current-sequence)))
341     (define (change-voice)
342       "Stores the previously built sequence into the current voice and
343        change to the following voice."
344       (list-set! current-voices 0 (cons (make-music 'SequentialMusic 
345                                          'elements (reverse! current-sequence))
346                                         (car current-voices)))
347       (set! current-sequence (list))
348       (set! current-voices (cdr current-voices)))
349     (define (bar-check? m)
350       "Checks whether m is a bar check."
351       (eq? (ly:music-property m 'name) 'BarCheck))
352     (define (music-origin music)
353       "Recursively search an origin location stored in music."
354       (cond ((null? music) #f)
355             ((not (null? (ly:music-property music 'origin)))
356              (ly:music-property music 'origin))
357             (else (or (music-origin (ly:music-property music 'element))
358                       (let ((origins (remove not (map music-origin 
359                                                       (ly:music-property music 'elements)))))
360                         (and (not (null? origins)) (car origins)))))))
361     ;;
362     ;; first, split the music and fill in voices
363     (map-in-order (lambda (m)
364                     (push-music m)
365                     (if (bar-check? m) (change-voice)))
366                   (ly:music-property music 'elements))
367     (if (not (null? current-sequence)) (change-voice))
368     ;; un-circularize `voices' and reorder the voices
369     (set! voices (map-in-order (lambda (dummy seqs)
370                                  (reverse! seqs))
371                                voice-ids voices))
372     ;;
373     ;; set origin location of each sequence in each voice
374     ;; for better type error tracking
375     (for-each (lambda (voice)
376                 (for-each (lambda (seq)
377                             (set! (ly:music-property seq 'origin)
378                                   (or (music-origin seq) location)))
379                           voice))
380               voices)
381     ;;
382     ;; check sequence length
383     (apply for-each (lambda (. seqs)
384                       (let ((moment-reference (ly:music-length (car seqs))))
385                         (for-each (lambda (seq moment)
386                                     (if (not (equal? moment moment-reference))
387                                         (ly:music-message seq 
388                                          "Bars in parallel music don't have the same length")))
389                           seqs (map-in-order ly:music-length seqs))))
390            voices)
391    ;;
392    ;; bind voice identifiers to the voices
393    (map (lambda (voice-id voice)
394           (ly:parser-define! parser voice-id 
395                              (make-music 'SequentialMusic 
396                                'origin location
397                                'elements voice)))
398         voice-ids voices))
399  ;; Return an empty sequence. this function is actually a "void" function.
400  (make-music 'SequentialMusic 'void #t))
401
402
403
404
405 %% this is a stub. Write your own to suit the spacing tweak output.
406 spacingTweaks =
407 #(def-music-function (parser location parameters) (list?)
408    (make-music 'SequentialMusic 'void #t))
409
410 octave =
411 #(def-music-function (parser location pitch-note) (ly:music?)
412    "octave check"
413
414    (make-music 'RelativeOctaveCheck
415                'origin location
416                'pitch (pitch-of-note pitch-note) 
417                ))
418
419 addquote =
420 #(def-music-function (parser location name music) (string? ly:music?)
421    "Add a piece of music to be quoted "
422    (add-quotable name music)
423    (make-music 'SequentialMusic 'void #t))
424
425    
426 parenthesize =
427 #(def-music-function (parser loc arg) (ly:music?)
428    "Tag @var{arg} to be parenthesized."
429
430    (set! (ly:music-property arg 'parenthesize) #t)
431    arg)