%%%% You should have received a copy of the GNU General Public License
%%%% along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
-\version "2.17.6"
+\version "2.17.11"
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% TODO: using define-music-function in a .scm causes crash.
+absolute =
+#(define-music-function (parser location music)
+ (ly:music?)
+ (_i "Make @var{music} absolute. This does not actually change the
+music itself but rather hides it from surrounding @code{\\relative}
+commands.")
+ (make-music 'RelativeOctaveMusic 'element music))
+
acciaccatura =
#(def-grace-function startAcciaccaturaMusic stopAcciaccaturaMusic
(_i "Create an acciaccatura from the following music expression"))
(symbol? number-pair? markup?)
(_i "Attach @var{text} to @var{grob-name} at offset @var{offset}
(use like @code{\\once})")
- (make-music 'AnnotateOutputEvent
- 'symbol grob-name
- 'X-offset (car offset)
- 'Y-offset (cdr offset)
- 'text text))
+ (make-event-chord
+ (list
+ (make-music 'AnnotateOutputEvent
+ 'symbol grob-name
+ 'X-offset (car offset)
+ 'Y-offset (cdr offset)
+ 'text text))))
balloonText =
-#(define-music-function (parser location offset text) (number-pair? markup?)
+#(define-event-function (parser location offset text) (number-pair? markup?)
(_i "Attach @var{text} at @var{offset} (use like @code{\\tweak})")
(make-music 'AnnotateOutputEvent
'X-offset (car offset)
#{
\once \override Staff.TimeSignature.stencil = #(lambda (grob)
(grob-interpret-markup grob (format-compound-time args)))
- \set Timing.timeSignatureFraction = $timesig
- \set Timing.baseMoment = $beat
- \set Timing.beatStructure = $beatGrouping
+ \set Timing.timeSignatureFraction = #timesig
+ \set Timing.baseMoment = #beat
+ \set Timing.beatStructure = #beatGrouping
\set Timing.beamExceptions = #'()
- \set Timing.measureLength = $mlen
+ \set Timing.measureLength = #mlen
#} ))
crossStaff =
#{
\temporary \override Stem.cross-staff = #cross-staff-connect
\temporary \override Flag.style = #'no-flag
- $notes
+ #notes
\revert Stem.cross-staff
\revert Flag.style
#})
(extract-typed-music music 'span-event)))
(stop-span-evs
(map (lambda (m)
- (let ((c (music-clone m)))
- (set! (ly:music-property c 'span-direction) STOP)
- c))
- start-span-evs))
+ (music-clone m 'span-direction STOP))
+ start-span-evs))
(end-ev-chord (make-music 'EventChord
'elements stop-span-evs))
(total (make-music 'SequentialMusic
argument))
+finger =
+#(define-event-function (parser location finger) (number-or-markup?)
+ (_i "Apply @var{finger} as a fingering indication.")
+
+ (make-music
+ 'FingeringEvent
+ (if (number? finger) 'digit 'text)
+ finger))
+
footnote =
#(define-music-function (parser location mark offset footnote item)
((markup?) number-pair? markup? symbol-list-or-music?)
#{
\set harmonicDots = ##t
\temporary \override TabNoteHead.stencil = #(tab-note-head::print-custom-fret-label (number->string fret))
- \temporary \override NoteHead.Y-extent = #(ly:make-unpure-pure-container ly:grob::stencil-height
- (lambda (grob start end)
- (ly:grob::stencil-height grob)))
+ \temporary \override NoteHead.Y-extent = #grob::always-Y-extent-from-stencil
\temporary \override NoteHead.stencil = #(lambda (grob) (ly:grob-set-property! grob 'style 'harmonic-mixed)
(ly:note-head::print grob))
- $(make-harmonic
+ #(make-harmonic
(calc-harmonic-pitch (fret->pitch (number->string fret)) music))
\unset harmonicDots
\revert TabNoteHead.stencil
(ly:grob::stencil-height grob)))
\temporary \override NoteHead.stencil = #(lambda (grob) (ly:grob-set-property! grob 'style 'harmonic-mixed)
(ly:note-head::print grob))
- $(make-harmonic
+ #(make-harmonic
(calc-harmonic-pitch (ratio->pitch ratio) music))
\unset harmonicDots
\revert TabNoteHead.stencil
specified by it. If @var{item} is a music expression, the result is
the same music expression with an appropriate tweak applied to it.")
(if (ly:music? item)
- #{ \tweak transparent ##t $item #}
- #{ \override $item #'transparent = ##t #}))
+ #{ \tweak transparent ##t #item #}
+ #{ \override #item . transparent = ##t #}))
inStaffSegno =
#(define-music-function (parser location) ()
specified by it. If @var{item} is a music expression, the result is
the same music expression with an appropriate tweak applied to it.")
(if (ly:music? item)
- #{ \tweak stencil ##f $item #}
- #{ \override $item #'stencil = ##f #}))
+ #{ \tweak stencil ##f #item #}
+ #{ \override #item . stencil = ##f #}))
once =
#(define-music-function (parser location music) (ly:music?)
(if (equal?
(cdr (assoc 'name (ly:grob-property grob 'meta)))
(second p))
- (if (null? (cdddr p))
- (ly:grob-set-property! grob (caddr p) value)
- (ly:grob-set-nested-property!
- grob (cddr p) value)))))
+ (ly:grob-set-nested-property!
+ grob (cddr p) value))))
(make-music 'Music))))
C = { e e | f f | }
@end verbatim
")
- (let* ((voices (apply circular-list (make-list (length voice-ids) (list))))
- (current-voices voices)
- (current-sequence (list))
- (original music)
- (wrapper #f))
- ;;
- ;; 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
+ (define (bar-check? m)
+ "Checks whether m is a bar check."
+ (eq? (ly:music-property m 'name) 'BarCheck))
+ (define (recurse-and-split music)
+ "This returns either a list of music split along barchecks, or
+@code{#f}."
+ (let ((elt (ly:music-property music 'element))
+ (elts (ly:music-property music 'elements)))
+ (cond ((ly:music? elt)
+ (let ((lst (recurse-and-split elt)))
+ (and lst
+ (map
+ (lambda (x)
+ (let ((res (music-clone music 'element x)))
+ (if (ly:input-location?
+ (ly:music-property x 'origin))
+ (set! (ly:music-property res 'origin)
+ (ly:music-property x 'origin)))
+ res))
+ lst))))
+ ((any bar-check? elts)
+ (let* ((voices (apply circular-list
+ (make-list (length voice-ids)
+ '())))
+ (current-voices voices)
+ (current-sequence '()))
+ ;;
+ ;; 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)))))))
- (while (music-is-of-type? music 'music-wrapper-music)
- (set! wrapper music)
- (set! music (ly:music-property wrapper 'element)))
- (if wrapper
- (set! (ly:music-property wrapper 'element)
- (make-music 'SequentialMusic
- 'origin location))
- (set! original
- (make-music 'SequentialMusic
- 'origin location)))
- ;;
- ;; first, split the music and fill in voices
- ;; We flatten direct layers of SequentialMusic since they are
- ;; pretty much impossible to avoid when writing music functions.
- (let rec ((music music))
- (for-each (lambda (m)
- (if (eq? (ly:music-property m 'name) 'SequentialMusic)
- (rec m)
- (begin
- (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* (#:rest seqs)
- (let ((moment-reference (ly:music-length (car seqs))))
- (for-each (lambda (seq moment)
- (if (not (equal? moment moment-reference))
- (ly:music-warning 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
- (for-each (lambda (voice-id voice)
- (ly:parser-define! parser voice-id
- (let ((v (ly:music-deep-copy original)))
- (set! (ly:music-property
- (car (extract-named-music
- v 'SequentialMusic))
- 'elements) voice)
- v)))
- voice-ids voices)))
+ (set-car! current-voices
+ (cons (reverse! current-sequence)
+ (car current-voices)))
+ (set! current-sequence '())
+ (set! current-voices (cdr current-voices)))
+ (for-each (lambda (m)
+ (let ((split? (recurse-and-split m)))
+ (if split?
+ (for-each
+ (lambda (m)
+ (push-music m)
+ (change-voice))
+ split?)
+ (begin
+ (push-music m)
+ (if (bar-check? m) (change-voice))))))
+ elts)
+ (if (pair? current-sequence) (change-voice))
+ ;; un-circularize `voices' and reorder the voices
+
+ (set! voices (map reverse!
+ (list-head voices (length voice-ids))))
+
+ ;; check sequence length
+ (apply for-each (lambda seqs
+ (define (seq-len seq)
+ (reduce ly:moment-add
+ (ly:make-moment 0)
+ (map ly:music-length seq)))
+ (let ((moment-reference (seq-len (car seqs))))
+ (for-each (lambda (seq)
+ (if (not (equal? (seq-len seq)
+ moment-reference))
+ (ly:music-warning
+ (if (pair? seq)
+ (last seq)
+ (caar seqs))
+ (_ "Bars in parallel music don't have the same length"))))
+ seqs)))
+ voices)
+ (map
+ (lambda (lst)
+ (set! lst (concatenate! lst))
+ (let ((res (music-clone music 'elements lst)))
+ (if (and (pair? lst)
+ (ly:input-location? (ly:music-property
+ (car lst)
+ 'origin)))
+ (set! (ly:music-property res 'origin)
+ (ly:music-property (car lst) 'origin)))
+ res))
+ voices)))
+ (else #f))))
+ (let ((voices (recurse-and-split music)))
+ (if voices
+ ;;
+ ;; bind voice identifiers to the voices
+ (for-each (lambda (voice-id voice)
+ (ly:parser-define! parser voice-id voice))
+ voice-ids voices)
+ (ly:music-warning music
+ (_ "ignoring parallel music without barchecks")))))
parenthesize =
#(define-music-function (parser loc arg) (ly:music?)
relative =
#(define-music-function (parser location pitch music)
- ((ly:pitch? (ly:make-pitch 0 0 0)) ly:music?)
- (_i "Make @var{music} relative to @var{pitch} (default @code{c'}).")
- (ly:make-music-relative! music pitch)
+ ((ly:pitch?) ly:music?)
+ (_i "Make @var{music} relative to @var{pitch}. If @var{pitch} is
+omitted, the first note in @var{music} is given in absolute pitch.")
+ ;; When \relative has no clear decision (can only happen with
+ ;; scales with an even number of steps), it goes down (see
+ ;; pitch.cc). The following formula puts out f for both the normal
+ ;; 7-step scale as well as for a "shortened" scale missing the
+ ;; final b. In either case, a first note of c will end up as c,
+ ;; namely pitch (-1, 0, 0).
+ (ly:make-music-relative! music
+ (or pitch
+ (ly:make-pitch
+ -1
+ (quotient
+ ;; size of current scale:
+ (ly:pitch-steps (ly:make-pitch 1 0))
+ 2))))
(make-music 'RelativeOctaveMusic
'element music))
(revert-time-signature-setting time-signature))
rightHandFinger =
-#(define-event-function (parser location finger) (number-or-string?)
+#(define-event-function (parser location finger) (number-or-markup?)
(_i "Apply @var{finger} as a fingering indication.")
(make-music
'StrokeFingerEvent
- 'origin location
- (if (string? finger) 'text 'digit)
+ (if (number? finger) 'digit 'text)
finger))
scaleDurations =
#(define-music-function (parser location overrides music)
(ly:music? ly:music?)
(_i "Convert @var{overrides} to tweaks and apply them to @var{music}.
-This does not convert @code{\\revert}, @code{\\set} or @code{\\unset}
-and ignores nested overrides.")
+This does not convert @code{\\revert}, @code{\\set} or @code{\\unset}.")
(set! (ly:music-property music 'tweaks)
(fold-some-music
(lambda (m) (eq? (ly:music-property m 'name)
((ly:music-property m 'grob-property #f) => list)
(else
(ly:music-property m 'grob-property-path)))))
- (if (pair? (cdr p))
- tweaks ;ignore nested properties
- (acons (cons (ly:music-property m 'symbol) ;grob name
- (car p)) ;grob property
- (ly:music-property m 'grob-value)
- tweaks))))
+ (acons (cons (ly:music-property m 'symbol) ;grob name
+ (if (pair? (cdr p))
+ p ;grob property path
+ (car p))) ;grob property
+ (ly:music-property m 'grob-value)
+ tweaks)))
(ly:music-property music 'tweaks)
overrides))
music)
'quoted-context-id "cue"
'quoted-music-name what
'quoted-voice-direction dir
+ ;; following is inverse of instrumentTransposition for
+ ;; historical reasons
'quoted-transposition pitch))
transposition =
(_i "Set instrument transposition")
(context-spec-music
- (make-property-set 'instrumentTransposition
- (ly:pitch-negate pitch))
+ (make-property-set 'instrumentTransposition pitch)
'Staff))
+tuplet =
+#(define-music-function (parser location ratio tuplet-span music)
+ (fraction? (ly:duration? '()) ly:music?)
+ (_i "Scale the given @var{music} to tuplets. @var{ratio} is a
+fraction that specifies how many notes are played in place of the
+nominal value: it will be @samp{3/2} for triplets, namely three notes
+being played in place of two. If the optional duration
+@var{tuplet-span} is specified, it is used instead of
+@code{tupletSpannerDuration} for grouping the tuplets.
+For example,
+@example
+\\tuplet 3/2 4 @{ c8 c c c c c @}
+@end example
+will result in two groups of three tuplets, each group lasting for a
+quarter note.")
+ (make-music 'TimeScaledMusic
+ 'element (ly:music-compress
+ music
+ (ly:make-moment (cdr ratio) (car ratio)))
+ 'numerator (cdr ratio)
+ 'denominator (car ratio)
+ 'duration tuplet-span))
+
+tupletSpan =
+#(define-music-function (parser location tuplet-span)
+ ((ly:duration?))
+ (_i "Set @code{tupletSpannerDuration}, the length into which
+@code{\\tuplet} without an explicit @samp{tuplet-span} argument of its
+own will group its tuplets, to the duration @var{tuplet-span}. To
+revert to the default of not subdividing the contents of a @code{\\tuplet}
+command without explicit @samp{tuplet-span}, use
+@example
+\\tupletSpan \\default
+@end example
+")
+ (if tuplet-span
+ #{ \set tupletSpannerDuration = #(ly:duration-length tuplet-span) #}
+ #{ \unset tupletSpannerDuration #}))
+
tweak =
#(define-music-function (parser location prop value item)
(symbol-list-or-symbol? scheme? symbol-list-or-music?)
As a special case, @var{item} may be a symbol list specifying a grob
path, in which case @code{\\once\\override} is called on it instead of
creating tweaked music. This is mainly useful when using
-@code{\\tweak} as as a component for building other functions.")
+@code{\\tweak} as as a component for building other functions.
+
+@var{prop} can contain additional elements in which case a nested
+property (inside of an alist) is tweaked.")
(if (ly:music? item)
(let ((p (check-grob-path prop parser location
#:start 1
#:default #t
- #:min 2
- #:max 2)))
+ #:min 2)))
(if p
(set! (ly:music-property item 'tweaks)
- (acons (if (eq? (car p) #t)
- (cadr p)
- (cons (car p) (cadr p)))
+ (acons (cond ((pair? (cddr p)) p)
+ ((symbol? (car p))
+ (cons (car p) (cadr p)))
+ (else (cadr p)))
value
(ly:music-property item 'tweaks))))
item)