X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=ly%2Fmusic-functions-init.ly;h=59c452065c3a03cc33fda0e489908c5f15faff69;hb=252ec5e71b5e121734a9c9897245137cb07e4a1f;hp=e0b36696bab23c20eefaede5e1c1e634baa87faa;hpb=264022bd6ebfed3220c0272d2c4a1c8ef9db4028;p=lilypond.git diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly index e0b36696ba..59c452065c 100644 --- a/ly/music-functions-init.ly +++ b/ly/music-functions-init.ly @@ -2,7 +2,7 @@ %%%% This file is part of LilyPond, the GNU music typesetter. %%%% -%%%% Copyright (C) 2003--2011 Han-Wen Nienhuys +%%%% Copyright (C) 2003--2012 Han-Wen Nienhuys %%%% Jan Nieuwenhuizen %%%% %%%% LilyPond is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ %%%% You should have received a copy of the GNU General Public License %%%% along with LilyPond. If not, see . -\version "2.14.0" +\version "2.15.18" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -38,13 +38,13 @@ acciaccatura = %% keep these two together "instrument-definitions" = #'() addInstrumentDefinition = -#(define-scheme-function +#(define-void-function (parser location name lst) (string? list?) (_i "Create instrument @var{name} with properties @var{list}.") (set! instrument-definitions (acons name lst instrument-definitions))) addQuote = -#(define-scheme-function (parser location name music) (string? ly:music?) +#(define-void-function (parser location name music) (string? ly:music?) (_i "Define @var{music} as a quotable music expression named @var{name}") (add-quotable parser name music)) @@ -86,19 +86,17 @@ markups), or inside a score.") 'break-permission 'allow)))) appendToTag = -#(define-music-function (parser location tag music more) +#(define-music-function (parser location tag more music) (symbol? ly:music? ly:music?) (_i "Append @var{more} to the @code{elements} of all music expressions in @var{music} that are tagged with @var{tag}.") - (music-map-copy (lambda (m) - (if (memq tag (ly:music-property m 'tags)) - (begin - (set! m (music-clone m)) - (set! (ly:music-property m 'elements) - (append (ly:music-property m 'elements) - (list more))))) - m) - music)) + (music-map (lambda (m) + (if (memq tag (ly:music-property m 'tags)) + (set! (ly:music-property m 'elements) + (append (ly:music-property m 'elements) + (list more)))) + m) + music)) applyContext = #(define-music-function (parser location proc) (procedure?) @@ -126,23 +124,13 @@ appoggiatura = assertBeamQuant = #(define-music-function (parser location l r) (pair? pair?) (_i "Testing function: check whether the beam quants @var{l} and @var{r} are correct") - (make-grob-property-override 'Beam 'positions - (ly:make-simple-closure - (ly:make-simple-closure - (append - (list chain-grob-member-functions `(,cons 0 0)) - (check-quant-callbacks l r)))))) + (make-grob-property-override 'Beam 'positions (check-quant-callbacks l r))) % for regression testing purposes. assertBeamSlope = #(define-music-function (parser location comp) (procedure?) (_i "Testing function: check whether the slope of the beam is the same as @code{comp}") - (make-grob-property-override 'Beam 'positions - (ly:make-simple-closure - (ly:make-simple-closure - (append - (list chain-grob-member-functions `(,cons 0 0)) - (check-slope-callbacks comp)))))) + (make-grob-property-override 'Beam 'positions (check-slope-callbacks comp))) autochange = #(define-music-function (parser location music) (ly:music?) @@ -196,12 +184,12 @@ bendAfter = 'delta-step delta)) bookOutputName = -#(define-scheme-function (parser location newfilename) (string?) +#(define-void-function (parser location newfilename) (string?) (_i "Direct output for the current book block to @var{newfilename}.") (set! book-filename newfilename)) bookOutputSuffix = -#(define-scheme-function (parser location newsuffix) (string?) +#(define-void-function (parser location newsuffix) (string?) (_i "Set the output filename suffix for the current book block to @var{newsuffix}.") (set! book-output-suffix newsuffix)) @@ -239,7 +227,7 @@ as @code{\\compoundMeter #'((3 2 8))} or shorter (ly:moment-main-denominator mlen)))) #{ \once \override Staff.TimeSignature #'stencil = #(lambda (grob) - (grob-interpret-markup grob (format-compound-time $args))) + (grob-interpret-markup grob (format-compound-time args))) \set Timing.timeSignatureFraction = $timesig \set Timing.baseMoment = $beat \set Timing.beatStructure = $beatGrouping @@ -305,13 +293,11 @@ endSpanners = #(define-music-function (parser location music) (ly:music?) (_i "Terminate the next spanner prematurely after exactly one note without the need of a specific end spanner.") - (if (eq? (ly:music-property music 'name) 'EventChord) - (let* ((elts (ly:music-property music 'elements)) - (start-span-evs (filter (lambda (ev) - (and (music-has-type ev 'span-event) - (equal? (ly:music-property ev 'span-direction) - START))) - elts)) + (if (memq (ly:music-property music 'name) '(EventChord NoteEvent)) + (let* ((start-span-evs (filter (lambda (ev) + (equal? (ly:music-property ev 'span-direction) + START)) + (extract-typed-music music 'span-event))) (stop-span-evs (map (lambda (m) (let ((c (music-clone m))) @@ -325,7 +311,9 @@ without the need of a specific end spanner.") end-ev-chord)))) total) - (ly:input-message location (_ "argument endSpanners is not an EventChord: ~a" music)))) + (begin + (ly:input-message location (_ "argument endSpanners is not an EventChord: ~a") music) + music))) @@ -335,83 +323,51 @@ featherDurations= (let ((orig-duration (ly:music-length argument)) (multiplier (ly:make-moment 1 1))) - (music-map + (for-each (lambda (mus) - (if (and (eq? (ly:music-property mus 'name) 'EventChord) - (< 0 (ly:moment-main-denominator (ly:music-length mus)))) + (if (< 0 (ly:moment-main-denominator (ly:music-length mus))) (begin (ly:music-compress mus multiplier) - (set! multiplier (ly:moment-mul factor multiplier)))) - mus) - argument) - + (set! multiplier (ly:moment-mul factor multiplier))))) + (extract-named-music argument '(EventChord NoteEvent RestEvent SkipEvent))) (ly:music-compress argument (ly:moment-div orig-duration (ly:music-length argument))) argument)) -footnoteGrob = -#(define-music-function (parser location grob-name offset text footnote) - (symbol? number-pair? markup? markup?) - (_i "Attach @var{text} to @var{grob-name} at offset @var{offset}, -with @var{text} referring to @var{footnote} (use like @code{\\once})") - (make-music 'FootnoteEvent - 'automatically-numbered #f - 'symbol grob-name - 'X-offset (car offset) - 'Y-offset (cdr offset) - 'text text - 'footnote-text footnote)) - -autoFootnoteGrob = -#(define-music-function (parser location grob-name offset footnote) - (symbol? number-pair? markup?) - (_i "Footnote @var{grob-name} with the text in @var{footnote} -allowing for the footnote to be automatically numbered such that -the number appears at @var{offset}. Note that, for this to take effect, -auto-numbering must be turned on in the paper block. Otherwise, no -number will appear. Use like @code{\\once})") - (make-music 'FootnoteEvent - 'automatically-numbered #t - 'symbol grob-name - 'X-offset (car offset) - 'Y-offset (cdr offset) - 'text (make-null-markup) - 'footnote-text footnote)) - - footnote = -#(define-music-function (parser location offset text footnote) - (number-pair? markup? markup?) - (_i "Attach @var{text} at @var{offset} with @var{text} referring -to @var{footnote} (use like @code{\\tweak})") - (make-music 'FootnoteEvent - 'automatically-numbered #f - 'X-offset (car offset) - 'Y-offset (cdr offset) - 'text text - 'footnote-text footnote)) - -autoFootnote = -#(define-music-function (parser location offset footnote) - (number-pair? markup?) - (_i "Footnote the item after which this comes with the text in -@var{footnote} allowing for the footnote to be automatically numbered -such that the number appears at @var{offset}. Note that, for this to -take effect, auto-numbering must be turned on in the paper block. -Otherwise, no number will appear. Use like @code{\\tweak})") - (make-music 'FootnoteEvent - 'automatically-numbered #t - 'X-offset (car offset) - 'Y-offset (cdr offset) - 'text (make-null-markup) - 'footnote-text footnote)) +#(define-music-function (parser location text offset grob-name footnote) + ((markup?) number-pair? (symbol? '()) markup?) + (_i "Attach @var{text} at @var{offset} with @var{text} referring to +@var{footnote}. If @var{text} is given as @code{\\default}, use +autonumbering instead. Note that, for this to take effect, +auto-numbering must be turned on in the paper block. Otherwise, no +number will appear. Footnotes are applied like articulations. If a +symbol @var{grob-name} is specified, all grobs of that kind at the +current time step are affected.") + (make-music + 'FootnoteEvent + 'X-offset (car offset) + 'Y-offset (cdr offset) + 'automatically-numbered (not text) + 'text (or text (make-null-markup)) + 'footnote-text footnote + 'symbol grob-name)) grace = #(def-grace-function startGraceMusic stopGraceMusic (_i "Insert @var{music} as grace notes.")) +grobdescriptions = +#(define-scheme-function (parser location descriptions) (list?) + (_i "Create a context modification from @var{descriptions}, a list +in the format of @code{all-grob-descriptions}.") + (ly:make-context-mod + (map (lambda (p) + (list 'assign (car p) (list (cdr p)))) + descriptions))) + harmonicByFret = #(define-music-function (parser location fret music) (number? ly:music?) (_i "Convert @var{music} into harmonics; the resulting notes resemble harmonics played on a fretted instrument by touching the strings above @var{fret}.") @@ -420,7 +376,7 @@ harmonics played on a fretted instrument by touching the strings above @var{fret (make-sequential-music (list #{ - \override TabNoteHead #'stencil = #(tab-note-head::print-custom-fret-label $fret) + \override TabNoteHead #'stencil = #(tab-note-head::print-custom-fret-label fret) #} (make-harmonic (calc-harmonic-pitch pitch music)) @@ -437,7 +393,7 @@ given through @var{ratio}.") (make-sequential-music (list #{ - \override TabNoteHead #'stencil = #(tab-note-head::print-custom-fret-label $fret) + \override TabNoteHead #'stencil = #(tab-note-head::print-custom-fret-label fret) #} (make-harmonic (calc-harmonic-pitch pitch music)) @@ -479,6 +435,23 @@ keepWithTag = res))) music)) +key = +#(define-music-function (parser location tonic pitch-alist) + ((ly:pitch? '()) (list? '())) + (_i "Set key to @var{tonic} and scale @var{pitch-alist}. +If both are null, just generate @code{KeyChangeEvent}.") + (cond ((null? tonic) (make-music 'KeyChangeEvent)) + ((null? pitch-alist) + (ly:parser-error parser (_ "second argument must be pitch list") + location) + (make-music 'SequentialMusic 'void #t)) + (else + (ly:music-transpose + (make-music 'KeyChangeEvent + 'tonic (ly:make-pitch 0 0 0) + 'pitch-alist pitch-alist) + tonic)))) + killCues = #(define-music-function (parser location music) (ly:music?) (_i "Remove cue notes from @var{music}.") @@ -503,18 +476,18 @@ label = language = -#(define-scheme-function (parser location language) (string?) +#(define-void-function (parser location language) (string?) (_i "Set note names for language @var{language}.") (note-names-language parser language)) languageSaveAndChange = -#(define-scheme-function (parser location language) (string?) +#(define-void-function (parser location language) (string?) (_i "Store the previous pitchnames alist, and set a new one.") (set! previous-pitchnames pitchnames) (note-names-language parser language)) languageRestore = -#(define-scheme-function (parser location) () +#(define-void-function (parser location) () (_i "Restore a previously-saved pitchnames alist.") (if previous-pitchnames (begin @@ -553,6 +526,22 @@ inversion = transpose from @var{around} to @var{to}.") (music-invert around to music)) +mark = +#(define-music-function + (parser location label) ((scheme? '())) + "Make the music for the \\mark command." + (let* ((set (and (integer? label) + (context-spec-music (make-property-set 'rehearsalMark label) + 'Score))) + (ev (make-music 'MarkEvent + 'origin location))) + + (if set + (make-sequential-music (list set ev)) + (begin + (set! (ly:music-property ev 'label) label) + ev)))) + musicMap = #(define-music-function (parser location proc mus) (procedure? ly:music?) (_i "Apply @var{proc} to @var{mus} and all of the music it contains.") @@ -588,6 +577,18 @@ octaveCheck = (make-music 'RelativeOctaveCheck 'pitch pitch)) +once = +#(define-music-function (parser location music) (ly:music?) + (_i "Set @code{once} to @code{#t} on all layout instruction events in @var{music}.") + (music-map + (lambda (m) + (cond ((music-is-of-type? m 'layout-instruction-event) + (set! (ly:music-property m 'once) #t)) + ((ly:duration? (ly:music-property m 'duration)) + (ly:music-warning m (_ "Cannot apply \\once to timed music")))) + m) + music)) + ottava = #(define-music-function (parser location octave) (integer?) (_i "Set the octavation.") @@ -668,7 +669,7 @@ pageTurn = 'break-permission 'force)))) parallelMusic = -#(define-scheme-function (parser location voice-ids music) (list? ly:music?) +#(define-void-function (parser location voice-ids music) (list? ly:music?) (_i "Define parallel music sequences, separated by '|' (bar check signs), and assign them to the identifiers provided in @var{voice-ids}. @@ -719,10 +720,16 @@ Example: (and (not (null? origins)) (car origins))))))) ;; ;; first, split the music and fill in voices - (for-each (lambda (m) - (push-music m) - (if (bar-check? m) (change-voice))) - (ly:music-property music 'elements)) + ;; 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) @@ -778,7 +785,21 @@ partcombine = (_i "Take the music in @var{part1} and @var{part2} and typeset so that they share a staff.") (make-part-combine-music parser - (list part1 part2))) + (list part1 part2) #f)) + +partcombineUp = +#(define-music-function (parser location part1 part2) (ly:music? ly:music?) + (_i "Take the music in @var{part1} and @var{part2} and typeset so +that they share a staff with stems directed upward.") + (make-part-combine-music parser + (list part1 part2) UP)) + +partcombineDown = +#(define-music-function (parser location part1 part2) (ly:music? ly:music?) + (_i "Take the music in @var{part1} and @var{part2} and typeset so +that they share a staff with stems directed downward.") + (make-part-combine-music parser + (list part1 part2) DOWN)) partcombineForce = #(define-music-function (location parser type once) (symbol-or-boolean? boolean?) @@ -820,13 +841,9 @@ pitchedTrill = (_i "Print a trill with @var{main-note} as the main note of the trill and print @var{secondary-note} as a stemless note head in parentheses.") (let* ((get-notes (lambda (ev-chord) - (filter - (lambda (m) (eq? 'NoteEvent (ly:music-property m 'name))) - (ly:music-property ev-chord 'elements)))) + (extract-named-music ev-chord 'NoteEvent))) (sec-note-events (get-notes secondary-note)) - (trill-events (filter (lambda (m) (music-has-type m 'trill-span-event)) - (ly:music-property main-note 'elements)))) - + (trill-events (extract-named-music main-note 'TrillSpanEvent))) (if (pair? sec-note-events) (begin (let* ((trill-pitch (ly:music-property (car sec-note-events) 'pitch)) @@ -846,18 +863,16 @@ print @var{secondary-note} as a stemless note head in parentheses.") main-note)) pushToTag = -#(define-music-function (parser location tag music more) +#(define-music-function (parser location tag more music) (symbol? ly:music? ly:music?) (_i "Add @var{more} to the front of @code{elements} of all music expressions in @var{music} that are tagged with @var{tag}.") - (music-map-copy (lambda (m) - (if (memq tag (ly:music-property m 'tags)) - (begin - (set! m (music-clone m)) - (set! (ly:music-property m 'elements) - (cons more (ly:music-property m 'elements))))) - m) - music)) + (music-map (lambda (m) + (if (memq tag (ly:music-property m 'tags)) + (set! (ly:music-property m 'elements) + (cons more (ly:music-property m 'elements)))) + m) + music)) quoteDuring = #(define-music-function (parser location what main-music) (string? ly:music?) @@ -869,6 +884,14 @@ usually contains spacers or multi-measure rests.") 'element main-music 'quoted-music-name what)) +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) + (make-music 'RelativeOctaveMusic + 'element music)) + removeWithTag = #(define-music-function (parser location tag music) (symbol? ly:music?) (_i "Remove elements of @var{music} that are tagged with @var{tag}.") @@ -914,15 +937,54 @@ rightHandFinger = scaleDurations = #(define-music-function (parser location fraction music) - (number-pair? ly:music?) + (fraction? ly:music?) (_i "Multiply the duration of events in @var{music} by @var{fraction}.") (ly:music-compress music (ly:make-moment (car fraction) (cdr fraction)))) +settingsFrom = +#(define-scheme-function (parser location ctx music) + ((symbol?) ly:music?) + (_i "Take the layout instruction events from @var{music}, optionally +restricted to those applying to context type @var{ctx}, and return +a context modification duplicating their effect.") + (let ((mods (ly:make-context-mod))) + (define (musicop m) + (if (music-is-of-type? m 'layout-instruction-event) + (ly:add-context-mod + mods + (case (ly:music-property m 'name) + ((PropertySet) + (list 'assign + (ly:music-property m 'symbol) + (ly:music-property m 'value))) + ((PropertyUnset) + (list 'unset + (ly:music-property m 'symbol))) + ((OverrideProperty) + (list 'push + (ly:music-property m 'symbol) + (ly:music-property m 'grob-property-path) + (ly:music-property m 'grob-value))) + ((RevertProperty) + (list 'pop + (ly:music-property m 'symbol) + (ly:music-property m 'grob-property-path))))) + (case (ly:music-property m 'name) + ((SequentialMusic SimultaneousMusic) + (for-each musicop (ly:music-property m 'elements))) + ((ContextSpeccedMusic) + (if (or (not ctx) + (eq? ctx (ly:music-property m 'context-type))) + (musicop (ly:music-property m 'element))))))) + (musicop music) + mods)) + shiftDurations = #(define-music-function (parser location dur dots arg) (integer? integer? ly:music?) - (_i "Scale @var{arg} up by a factor of 2^@var{dur}*(2-(1/2)^@var{dots}).") + (_i "Change the duration of @var{arg} by adding @var{dur} to the +@code{durlog} of @var{arg} and @var{dots} to the @code{dots} of @var{arg}.") (music-map (lambda (x) @@ -947,7 +1009,7 @@ the `parameters' assoc list.") #{ \overrideProperty #"Score.NonMusicalPaperColumn" #'line-break-system-details - #$(list (cons 'alignment-extra-space (cdr (assoc 'system-stretch parameters))) + #(list (cons 'alignment-extra-space (cdr (assoc 'system-stretch parameters))) (cons 'system-Y-extent (cdr (assoc 'system-Y-extent parameters)))) #}) @@ -976,6 +1038,25 @@ tag = (ly:music-property arg 'tags))) arg) +time = +#(define-music-function (parser location beat-structure fraction) + ((number-list? '()) fraction?) + (_i "Set @var{fraction} as time signature, with optional +number list @var{beat-structure} before it.") + (make-music 'TimeSignatureMusic + 'numerator (car fraction) + 'denominator (cdr fraction) + 'beat-structure beat-structure)) + +times = +#(define-music-function (parser location fraction music) + (fraction? ly:music?) + (_i "Scale @var{music} in time by @var{fraction}.") + (make-music 'TimeScaledMusic + 'element (ly:music-compress music (ly:make-moment (car fraction) (cdr fraction))) + 'numerator (car fraction) + 'denominator (cdr fraction))) + transpose = #(define-music-function (parser location from to music) @@ -1037,7 +1118,11 @@ unfoldRepeats = as @code{\\repeat unfold}.") (unfold-repeats music)) - +void = +#(define-void-function (parser location arg) (scheme?) + (_i "Accept a scheme argument, return a void expression. +Use this if you want to have a scheme expression evaluated +because of its side-effects, but its value ignored.")) withMusicProperty = #(define-music-function (parser location sym val music)