X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=ly%2Fmusic-functions-init.ly;h=80c3020ac04b7a2574ad72b85e59cad45edffaac;hb=b1d802ef08915cd1d87f7dfb5ff45beeabf6e9fb;hp=90cae893c674cf27b5678749a63d8ac9f5462661;hpb=a42aaa559b71ce5776795fa11a7e1df9110d85b7;p=lilypond.git diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly index 90cae893c6..80c3020ac0 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 @@ -186,13 +186,13 @@ bendAfter = bookOutputName = #(define-void-function (parser location newfilename) (string?) (_i "Direct output for the current book block to @var{newfilename}.") - (set! book-filename newfilename)) + (set! (paper-variable parser #f 'output-filename) newfilename)) bookOutputSuffix = #(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)) + (set! (paper-variable parser #f 'output-suffix) newsuffix)) %% \breathe is defined as a music function rather than an event identifier to %% ensure it gets useful input location information: as an event identifier, @@ -273,23 +273,18 @@ in a CueVoice oriented by @var{dir}.") displayLilyMusic = -#(define-music-function (parser location port music) ((port?) ly:music?) +#(define-music-function (parser location music) (ly:music?) (_i "Display the LilyPond input representation of @var{music} -to @var{port}, defaulting to the console.") - (if (not port) - (set! port (current-output-port))) - (newline port) - (display-lily-music music parser port) +to the console.") + (newline) + (display-lily-music music parser) music) displayMusic = -#(define-music-function (parser location port music) ((port?) ly:music?) - (_i "Display the internal representation of @var{music} to -@var{port}, default to the console.") - (if (not port) - (set! port (current-output-port))) - (newline port) - (display-scheme-music music port) +#(define-music-function (parser location music) (ly:music?) + (_i "Display the internal representation of @var{music} to the console.") + (newline) + (display-scheme-music music) music) @@ -298,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))) @@ -319,10 +312,15 @@ without the need of a specific end spanner.") total) (begin - (ly:input-message location (_ "argument endSpanners is not an EventChord: ~a" music)) + (ly:input-message location (_ "argument endSpanners is not an EventChord: ~a") music) music))) - +eventChords = +#(define-music-function (parser location music) (ly:music?) + (_i "Compatibility function wrapping @code{EventChord} around +isolated rhythmic events occuring since version 2.15.28, after +expanding repeat chords @samp{q}.") + (event-chord-wrap! music parser)) featherDurations= #(define-music-function (parser location factor argument) (ly:moment? ly:music?) @@ -330,78 +328,37 @@ 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 @@ -417,37 +374,43 @@ in the format of @code{all-grob-descriptions}.") 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}.") - (let* ((fret (number->string fret)) - (pitch (fret->pitch fret))) - (make-sequential-music - (list - #{ - \override TabNoteHead #'stencil = #(tab-note-head::print-custom-fret-label fret) - #} - (make-harmonic - (calc-harmonic-pitch pitch music)) - #{ - \revert TabNoteHead #'stencil - #})))) + (_i "Convert @var{music} into mixed harmonics; the resulting notes resemble +harmonics played on a fretted instrument by touching the strings at @var{fret}.") + #{ + \set harmonicDots = ##t + \override TabNoteHead #'stencil = #(tab-note-head::print-custom-fret-label (number->string fret)) + \override NoteHead #'Y-extent = #(ly:make-unpure-pure-container ly:grob::stencil-height + (lambda (grob start end) + (ly:grob::stencil-height grob))) + \override NoteHead #'stencil = #(lambda (grob) (ly:grob-set-property! grob 'style 'harmonic-mixed) + (ly:note-head::print grob)) + $(make-harmonic + (calc-harmonic-pitch (fret->pitch (number->string fret)) music)) + \unset harmonicDots + \revert TabNoteHead #'stencil + \revert NoteHead #'Y-extent + \revert NoteHead #'stencil + #}) harmonicByRatio = #(define-music-function (parser location ratio 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 the point + (_i "Convert @var{music} into mixed harmonics; the resulting notes resemble +harmonics played on a fretted instrument by touching the strings at the point given through @var{ratio}.") - (let ((pitch (ratio->pitch ratio)) - (fret (ratio->fret ratio))) - (make-sequential-music - (list - #{ - \override TabNoteHead #'stencil = #(tab-note-head::print-custom-fret-label fret) - #} - (make-harmonic - (calc-harmonic-pitch pitch music)) - #{ - \revert TabNoteHead #'stencil - #})))) + #{ + \set harmonicDots = ##t + \override TabNoteHead #'stencil = #(tab-note-head::print-custom-fret-label (ratio->fret ratio)) + \override NoteHead #'Y-extent = #(ly:make-unpure-pure-container ly:grob::stencil-height + (lambda (grob start end) + (ly:grob::stencil-height grob))) + \override NoteHead #'stencil = #(lambda (grob) (ly:grob-set-property! grob 'style 'harmonic-mixed) + (ly:note-head::print grob)) + $(make-harmonic + (calc-harmonic-pitch (ratio->pitch ratio) music)) + \unset harmonicDots + \revert TabNoteHead #'stencil + \revert NoteHead #'Y-extent + \revert NoteHead #'stencil + #}) instrumentSwitch = #(define-music-function @@ -740,7 +703,9 @@ Example: ") (let* ((voices (apply circular-list (make-list (length voice-ids) (list)))) (current-voices voices) - (current-sequence (list))) + (current-sequence (list)) + (original music) + (wrapper #f)) ;; ;; utilities (define (push-music m) @@ -766,12 +731,28 @@ Example: (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 - (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) @@ -800,9 +781,12 @@ Example: ;; bind voice identifiers to the voices (for-each (lambda (voice-id voice) (ly:parser-define! parser voice-id - (make-music 'SequentialMusic - 'origin location - 'elements voice))) + (let ((v (ly:music-deep-copy original))) + (set! (ly:music-property + (car (extract-named-music + v 'SequentialMusic)) + 'elements) voice) + v))) voice-ids voices))) parenthesize = @@ -883,13 +867,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)) @@ -1008,21 +988,27 @@ a context modification duplicating their effect.") (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))) + (cons* 'push + (ly:music-property m 'symbol) + (ly:music-property m 'grob-value) + (ly:music-property m 'grob-property-path))) ((RevertProperty) - (list 'pop - (ly:music-property m 'symbol) - (ly:music-property m 'grob-property-path))))) + (cons* '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))) + ((ApplyContext) + (ly:add-context-mod mods + (list 'apply + (ly:music-property m 'procedure)))) ((ContextSpeccedMusic) (if (or (not ctx) (eq? ctx (ly:music-property m 'context-type))) - (musicop (ly:music-property m 'element))))))) + (musicop (ly:music-property m 'element)))) + (else + (let ((callback (ly:music-property m 'elements-callback))) + (if (procedure? callback) + (for-each musicop (callback m)))))))) (musicop music) mods)) @@ -1065,14 +1051,6 @@ styledNoteHeads = (_i "Set @var{heads} in @var{music} to @var{style}.") (style-note-heads heads style music)) - - -tabChordRepetition = -#(define-music-function (parser location) () - (_i "Include the string information in a chord repetition.") - (ly:parser-set-repetition-function parser tab-repeat-chord) - (make-music 'SequentialMusic 'void #t)) - tag = #(define-music-function (parser location tag arg) (symbol? ly:music?)