From e864a61c53a13b5b53843dc702f6ba4e54a8fc6b Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 19 Jul 2006 12:02:22 +0000 Subject: [PATCH 1/1] *** empty log message *** --- ChangeLog | 27 ++ Documentation/topdocs/NEWS.tely | 12 + lily/breathing-sign-engraver.cc | 10 +- lily/fall-engraver.cc | 118 +++++++ lily/grob-scheme.cc | 28 ++ lily/parser.yy | 69 ++-- ly/engraver-init.ly | 1 + ly/music-functions-init.ly | 590 +++++++++++++++++--------------- scm/define-grobs.scm | 9 + scm/define-music-properties.scm | 31 +- scm/define-music-types.scm | 6 + scm/define-stencil-commands.scm | 7 +- scm/output-lib.scm | 35 ++ scm/output-ps.scm | 8 + 14 files changed, 617 insertions(+), 334 deletions(-) create mode 100644 lily/fall-engraver.cc diff --git a/ChangeLog b/ChangeLog index e86fe90bb7..8884f4bd9c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,33 @@ 2006-07-19 Han-Wen Nienhuys + * Documentation/topdocs/NEWS.tely (Top): doc new feature. + + * scm/output-ps.scm (path): define path. + + * scm/define-stencil-commands.scm + (ly:register-stencil-expression): add path. + + * scm/define-music-properties.scm (all-music-properties): add delta-pitch. + + * ly/engraver-init.ly: add Fall_engraver + + * lily/parser.yy (music_function_event): allow musicfunction + without music arg as music_function_event. + + * lily/grob-scheme.cc (LY_DEFINE): + ly:grob-robust-relative-extent. New function. + + * scm/define-grobs.scm (all-grob-descriptions): add BendAfter + + * scm/define-music-types.scm (music-descriptions): add BendAfterEvent. + + * scm/output-lib.scm (fall::print): new function + + * lily/fall-engraver.cc (stop_fall): new file. + + * ly/music-functions-init.ly: alphabetise. + * Documentation/user/GNUmakefile (OUT_PNG_IMAGES): pdf iso. eps as base. diff --git a/Documentation/topdocs/NEWS.tely b/Documentation/topdocs/NEWS.tely index 45d3c18e35..32d7949faf 100644 --- a/Documentation/topdocs/NEWS.tely +++ b/Documentation/topdocs/NEWS.tely @@ -65,6 +65,18 @@ which scares away people. * only show user-visible changes. @end ignore +@item +Falls and doits can be added to notes + +@lilypond[fragment,ragged-right,relative=2] + \override Score.SpacingSpanner #'shortest-duration-space = #3.0 + c4-\bendAfter #+5 + c4-\bendAfter #-3 +} +@end lilypond + +This feature was sponsored by Anthony Youngman and Paul Scott. + @item @code{lilypond-book} now includes support for PDF@TeX{}. diff --git a/lily/breathing-sign-engraver.cc b/lily/breathing-sign-engraver.cc index d659b64a90..d7a73bf6be 100644 --- a/lily/breathing-sign-engraver.cc +++ b/lily/breathing-sign-engraver.cc @@ -12,9 +12,8 @@ . Spacing is not yet completely pretty */ -#include "staff-symbol-referencer.hh" #include "breathing-sign.hh" -#include "engraver-group.hh" +#include "engraver.hh" #include "item.hh" class Breathing_sign_engraver : public Engraver @@ -24,7 +23,7 @@ public: protected: virtual bool try_music (Music *event); - void process_acknowledged (); + void process_music (); void stop_translation_timestep (); private: @@ -46,12 +45,11 @@ Breathing_sign_engraver::try_music (Music *r) } void -Breathing_sign_engraver::process_acknowledged () +Breathing_sign_engraver::process_music () { - if (breathing_sign_event_ && ! breathing_sign_) + if (breathing_sign_event_) { breathing_sign_ = make_item ("BreathingSign", breathing_sign_event_->self_scm ()); - breathing_sign_event_ = 0; } } diff --git a/lily/fall-engraver.cc b/lily/fall-engraver.cc new file mode 100644 index 0000000000..1b7cf93e81 --- /dev/null +++ b/lily/fall-engraver.cc @@ -0,0 +1,118 @@ +/* + fall-engraver.cc -- implement Fall_engraver + + (c) 2006 Han-Wen Nienhuys + + +*/ + +#include "engraver.hh" +#include "item.hh" +#include "spanner.hh" + +class Fall_engraver : public Engraver +{ +public: + TRANSLATOR_DECLARATIONS (Fall_engraver); + DECLARE_ACKNOWLEDGER (note_head); + +protected: + virtual bool try_music (Music *event); + void process_music (); + void stop_translation_timestep (); + void start_translation_timestep (); + void stop_fall (); + +private: + Moment stop_moment_; + Music *fall_event_; + Spanner *fall_; + Grob *note_head_; +}; + +void +Fall_engraver::stop_fall () +{ + bool bar = scm_is_string (get_property ("whichBar")); + + + fall_->set_bound (RIGHT, unsmob_grob ( + bar + ? get_property ("currentCommandColumn") + : get_property ("currentMusicalColumn"))); + fall_ = 0; + note_head_ = 0; + fall_event_ = 0; +} + +void +Fall_engraver::stop_translation_timestep () +{ + if (fall_ && !fall_->get_bound (LEFT)) + { + fall_->set_bound (LEFT, note_head_); + fall_->set_parent (note_head_, Y_AXIS); + } +} + +void +Fall_engraver::start_translation_timestep () +{ + if (fall_ && now_mom ().main_part_ >= stop_moment_.main_part_) + { + stop_fall (); + } +} + +void +Fall_engraver::acknowledge_note_head (Grob_info info) +{ + if (!fall_event_) + return; + + if (note_head_ && fall_) + { + stop_fall (); + } + + note_head_ = info.grob (); + stop_moment_ = now_mom () + info.music_cause ()->get_length (); +} + +Fall_engraver::Fall_engraver () +{ + fall_ = 0; + note_head_ = 0; + fall_event_ = 0; +} + +bool +Fall_engraver::try_music (Music *r) +{ + fall_event_ = r; + return true; +} + +void +Fall_engraver::process_music () +{ + if (fall_event_ && !fall_) + { + fall_ = make_spanner ("BendAfter", fall_event_->self_scm ()); + fall_->set_property ("delta-position", + scm_from_double (robust_scm2double (fall_event_->get_property ("delta-pitch"), 0) * 0.5)); + } +} + +#include "translator.icc" + + +ADD_ACKNOWLEDGER (Fall_engraver, note_head); + + +ADD_TRANSLATOR (Fall_engraver, + /* doc */ "Create fall spanners.", + /* create */ "BendAfter", + /* accept */ "bend-after-event", + /* read */ "", + /* write */ ""); diff --git a/lily/grob-scheme.cc b/lily/grob-scheme.cc index c8bdc2c828..bca86f5a76 100644 --- a/lily/grob-scheme.cc +++ b/lily/grob-scheme.cc @@ -156,6 +156,28 @@ LY_DEFINE (ly_get_extent, "ly:grob-extent", return ly_interval2scm (sc->extent (ref, a)); } +LY_DEFINE (ly_grob_robust_relative_extent, "ly:grob-robust-relative-extent", + 3, 0, 0, (SCM grob, SCM refp, SCM axis), + "Get the extent in @var{axis} direction of @var{grob} relative to " + "the grob @var{refp}, or (0,0) if empty") +{ + Grob *sc = unsmob_grob (grob); + Grob *ref = unsmob_grob (refp); + + SCM_ASSERT_TYPE (sc, grob, SCM_ARG1, __FUNCTION__, "grob"); + SCM_ASSERT_TYPE (ref, refp, SCM_ARG2, __FUNCTION__, "grob"); + SCM_ASSERT_TYPE (is_axis (axis), axis, SCM_ARG3, __FUNCTION__, "axis"); + + Axis a = Axis (scm_to_int (axis)); + + if (ref->common_refpoint (sc, a) != ref) + { + // ugh. should use other error message + SCM_ASSERT_TYPE (false, refp, SCM_ARG2, __FUNCTION__, "common refpoint"); + } + + return ly_interval2scm (robust_relative_extent (sc, ref, a)); +} LY_DEFINE (ly_grob_relative_coordinate, "ly:grob-relative-coordinate", 3, 0, 0, (SCM grob, SCM refp, SCM axis), @@ -309,6 +331,12 @@ LY_DEFINE (ly_grob_default_font, "ly:grob-default-font", return Font_interface::get_default_font (gr)->self_scm (); } + +/* + TODO: consider swapping order, so we can do + + (grob-common-refpoint a b c d e) + */ LY_DEFINE (ly_grob_common_refpoint, "ly:grob-common-refpoint", 3, 0, 0, (SCM grob, SCM other, SCM axis), "Find the common refpoint of @var{grob} and @var{other} for @var{axis}." diff --git a/lily/parser.yy b/lily/parser.yy index 5901962c86..04469f817b 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -366,6 +366,7 @@ If we give names, Bison complains. %type music_function_event %type music_function_chord_body %type music_function_musicless_prefix +%type music_function_musicless_function %type bass_figure %type figured_bass_modification %type br_bass_figure @@ -945,7 +946,7 @@ function_scm_argument: /* TODO: use code generation for this */ -generic_prefix_music_scm: +music_function_musicless_function: MUSIC_FUNCTION { $$ = scm_list_2 ($1, make_input (@$)); } @@ -955,21 +956,48 @@ generic_prefix_music_scm: | MUSIC_FUNCTION_MARKUP full_markup { $$ = scm_list_3 ($1, make_input (@$), $2); } - | music_function_musicless_prefix music { - $$ = ly_append2 ($1, scm_list_1 ($2)); - } | MUSIC_FUNCTION_SCM_SCM function_scm_argument function_scm_argument { $$ = scm_list_4 ($1, make_input (@$), $2, $3); } | MUSIC_FUNCTION_SCM_SCM_SCM function_scm_argument function_scm_argument function_scm_argument { $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4); } - | MUSIC_FUNCTION_MARKUP_MUSIC full_markup music { + | MUSIC_FUNCTION_MARKUP_MARKUP full_markup full_markup { $$ = scm_list_4 ($1, make_input (@$), $2, $3); } - | MUSIC_FUNCTION_MARKUP_MARKUP full_markup full_markup { + ; + +/* +TODO: use code generation for this +*/ +music_function_musicless_prefix: + MUSIC_FUNCTION_MUSIC { + $$ = scm_list_2 ($1, make_input (@$)); + } + | MUSIC_FUNCTION_SCM_MUSIC function_scm_argument { + $$ = scm_list_3 ($1, make_input (@$), $2); + } + | MUSIC_FUNCTION_SCM_SCM_MUSIC function_scm_argument function_scm_argument { $$ = scm_list_4 ($1, make_input (@$), $2, $3); } + | MUSIC_FUNCTION_SCM_SCM_SCM_MUSIC function_scm_argument function_scm_argument function_scm_argument { + $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4); + } + | MUSIC_FUNCTION_SCM_SCM_SCM_SCM_MUSIC function_scm_argument function_scm_argument function_scm_argument function_scm_argument { + $$ = scm_list_n ($1, make_input (@$), $2, $3, $4, $5, SCM_UNDEFINED); + } + | MUSIC_FUNCTION_MARKUP_MUSIC full_markup { + $$ = scm_list_3 ($1, make_input (@$), $2); + } + ; + +generic_prefix_music_scm: + music_function_musicless_function { + $$ = $1 + } + | music_function_musicless_prefix music { + $$ = ly_append2 ($1, scm_list_1 ($2)); + } | MUSIC_FUNCTION_MUSIC_MUSIC music music { $$ = scm_list_4 ($1, make_input (@$), $2, $3); } @@ -984,6 +1012,7 @@ generic_prefix_music_scm: } ; + optional_id: /**/ { $$ = SCM_EOL; } | '=' simple_string { @@ -1387,8 +1416,8 @@ chord_body_element: ; music_function_chord_body: - MUSIC_FUNCTION { - $$ = scm_list_2 ($1, make_input (@$)); + music_function_musicless_function { + $$ = $1; } | music_function_musicless_prefix chord_body_element { $$ = ly_append2 ($1, scm_list_1 ($2)); @@ -1399,29 +1428,11 @@ music_function_event: music_function_musicless_prefix post_event { $$ = ly_append2 ($1, scm_list_1 ($2)); } - ; - -/* -TODO: use code generation for this -*/ -music_function_musicless_prefix: - MUSIC_FUNCTION_MUSIC { - $$ = scm_list_2 ($1, make_input (@$)); - } - | MUSIC_FUNCTION_SCM_MUSIC function_scm_argument { - $$ = scm_list_3 ($1, make_input (@$), $2); - } - | MUSIC_FUNCTION_SCM_SCM_MUSIC function_scm_argument function_scm_argument { - $$ = scm_list_4 ($1, make_input (@$), $2, $3); - } - | MUSIC_FUNCTION_SCM_SCM_SCM_MUSIC function_scm_argument function_scm_argument function_scm_argument { - $$ = scm_list_5 ($1, make_input (@$), $2, $3, $4); - } - | MUSIC_FUNCTION_SCM_SCM_SCM_SCM_MUSIC function_scm_argument function_scm_argument function_scm_argument function_scm_argument { - $$ = scm_list_n ($1, make_input (@$), $2, $3, $4, $5, SCM_UNDEFINED); + | music_function_musicless_function { + $$ = $1; } ; - + command_element: command_event { diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index aa27cbdd7c..efc14e9a35 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -211,6 +211,7 @@ contained staves are not connected vertically." \consists "Text_engraver" \consists "Dynamic_engraver" \consists "Fingering_engraver" + \consists "Fall_engraver" \consists "Script_engraver" \consists "Script_column_engraver" diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly index 32b4d41bd0..4396a64c45 100644 --- a/ly/music-functions-init.ly +++ b/ly/music-functions-init.ly @@ -1,72 +1,94 @@ % -*-Scheme-*- -\version "2.7.39" +\version "2.9.12" %% need SRFI-1 filter #(use-modules (srfi srfi-1)) +%% FIXME: guile-1.7 required? +%#(use-modules (scm display-lily))invalid module name for use-syntax ((srfi srfi-39)) +#(use-modules (scm display-lily)) +#(display-lily-init parser) -tweak = #(define-music-function (parser location sym val arg) - (symbol? scheme? ly:music?) - "Add @code{sym . val} to the @code{tweaks} property of @var{arg}." +acciaccatura = +#(def-grace-function startAcciaccaturaMusic stopAcciaccaturaMusic) - - (set! - (ly:music-property arg 'tweaks) - (acons sym val - (ly:music-property arg 'tweaks))) - arg) -tag = #(define-music-function (parser location tag arg) - (symbol? ly:music?) +addquote = +#(define-music-function (parser location name music) (string? ly:music?) + "Add a piece of music to be quoted " + (add-quotable name music) + (make-music 'SequentialMusic 'void #t)) - "Add @var{tag} to the @code{tags} property of @var{arg}." - (set! - (ly:music-property arg 'tags) - (cons tag - (ly:music-property arg 'tags))) - arg) +afterGraceFraction = +#(cons 6 8) -clef = -#(define-music-function (parser location type) - (string?) - - "Set the current clef." +afterGrace = +#(define-music-function + (parser location main grace) + (ly:music? ly:music?) - (make-clef-set type)) + (let* + ((main-length (ly:music-length main)) + (fraction (ly:parser-lookup parser 'afterGraceFraction))) + + (make-simultaneous-music + (list + main + (make-sequential-music + (list -bar = -#(define-music-function (parser location type) - (string?) - (context-spec-music - (make-property-set 'whichBar type) - 'Timing)) + (make-music 'SkipMusic + 'duration (ly:make-duration + 0 0 + (* (ly:moment-main-numerator main-length) + (car fraction)) + (* (ly:moment-main-denominator main-length) + (cdr fraction)) )) + (make-music 'GraceMusic + 'element grace))))))) applyMusic = #(define-music-function (parser location func music) (procedure? ly:music?) (func music)) -oldaddlyrics = -#(define-music-function (parser location music lyrics) (ly:music? ly:music?) - - (make-music 'OldLyricCombineMusic - 'origin location - 'elements (list music lyrics))) -grace = -#(def-grace-function startGraceMusic stopGraceMusic) +applyOutput = +#(define-music-function (parser location ctx proc) (symbol? procedure?) + (make-music 'ApplyOutputEvent + 'origin location + 'procedure proc + 'context-type ctx)) -acciaccatura = -#(def-grace-function startAcciaccaturaMusic stopAcciaccaturaMusic) appoggiatura = #(def-grace-function startAppoggiaturaMusic stopAppoggiaturaMusic) -partcombine = -#(define-music-function (parser location part1 part2) (ly:music? ly:music?) - (make-part-combine-music (list part1 part2))) + + +% for regression testing purposes. +assertBeamQuant = +#(define-music-function (parser location l r) (pair? pair?) + (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)))))) + +% for regression testing purposes. +assertBeamSlope = +#(define-music-function (parser location comp) (procedure?) + (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)))))) + + autochange = #(define-music-function (parser location music) (ly:music?) @@ -78,40 +100,151 @@ applyContext = 'origin location 'procedure proc)) -shiftDurations = -#(define-music-function (parser location dur dots arg) (integer? integer? ly:music?) - "" +bar = +#(define-music-function (parser location type) + (string?) + (context-spec-music + (make-property-set 'whichBar type) + 'Timing)) + + +barNumberCheck = +#(define-music-function (parser location n) (integer?) + (make-music 'ApplyContext + 'origin location + 'procedure + (lambda (c) + (let* + ((cbn (ly:context-property c 'currentBarNumber))) + (if (not (= cbn n)) + (ly:input-message location "Barcheck failed got ~a expect ~a" + cbn n)))))) + +%% why a function? +breathe = +#(define-music-function (parser location) () + (make-music 'EventChord + 'origin location + 'elements (list (make-music 'BreathingSignEvent)))) + +bendAfter = +#(define-music-function (parser location delta) (integer?) + + (make-music 'BendAfterEvent + 'delta-pitch delta)) + +clef = +#(define-music-function (parser location type) + (string?) - (music-map - (lambda (x) - (shift-one-duration-log x dur dots)) arg)) + "Set the current clef." -musicMap = -#(define-music-function (parser location proc mus) (procedure? ly:music?) - (music-map proc mus)) + (make-clef-set type)) -displayMusic = -#(define-music-function (parser location music) (ly:music?) - (display-scheme-music music) - music) -%% FIXME: guile-1.7 required? -%#(use-modules (scm display-lily))invalid module name for use-syntax ((srfi srfi-39)) +compressMusic = +#(define-music-function + (parser location fraction music) (number-pair? ly:music?) + (ly:music-compress music (ly:make-moment (car fraction) (cdr fraction)))) + + +cueDuring = +#(define-music-function + (parser location what dir main-music) + (string? ly:dir? ly:music?) + (make-music 'QuoteMusic + 'element main-music + 'quoted-context-type 'Voice + 'quoted-context-id "cue" + 'quoted-music-name what + 'quoted-voice-direction dir + 'origin location)) + -#(use-modules (scm display-lily)) -#(display-lily-init parser) displayLilyMusic = #(define-music-function (parser location music) (ly:music?) (display-lily-music music) music) -applyOutput = -#(define-music-function (parser location ctx proc) (symbol? procedure?) - (make-music 'ApplyOutputEvent - 'origin location - 'procedure proc - 'context-type ctx)) +displayMusic = +#(define-music-function (parser location music) (ly:music?) + (display-scheme-music music) + music) + +featherDurations= +#(define-music-function (parser location factor argument) (ly:moment? ly:music?) + + "Rearrange durations in ARGUMENT so there is an +acceleration/deceleration. " + + (let* + ((orig-duration (ly:music-length argument)) + (multiplier (ly:make-moment 1 1))) + + (music-map + (lambda (mus) + (if (and (eq? (ly:music-property mus 'name) 'EventChord) + (< 0 (ly:moment-main-denominator (ly:music-length mus)))) + (begin + (ly:music-compress mus multiplier) + (set! multiplier (ly:moment-mul factor multiplier))) + ) + mus) + argument) + + (ly:music-compress + argument + (ly:moment-div orig-duration (ly:music-length argument))) + + argument)) + +grace = +#(def-grace-function startGraceMusic stopGraceMusic) + +keepWithTag = +#(define-music-function + (parser location tag music) (symbol? ly:music?) + (music-filter + (lambda (m) + (let* ((tags (ly:music-property m 'tags)) + (res (memq tag tags))) + (or + (eq? tags '()) + res))) + music)) + + + +killCues = +#(define-music-function + (parser location music) + (ly:music?) + (music-map + (lambda (mus) + (if (string? (ly:music-property mus 'quoted-music-name)) + (ly:music-property mus 'element) + mus)) music)) + + +makeClusters = +#(define-music-function + (parser location arg) (ly:music?) + (music-map note-to-cluster arg)) + +musicMap = +#(define-music-function (parser location proc mus) (procedure? ly:music?) + (music-map proc mus)) + + + +oldaddlyrics = +#(define-music-function (parser location music lyrics) (ly:music? ly:music?) + + (make-music 'OldLyricCombineMusic + 'origin location + 'elements (list music lyrics))) + overrideProperty = #(define-music-function (parser location name property value) @@ -140,102 +273,38 @@ or @code{\"GrobName\"}" (lambda (grob orig-context context) (if (equal? (cdr (assoc 'name (ly:grob-property grob 'meta))) - grob-name) - (set! (ly:grob-property grob property) value)))))) - -breathe = -#(define-music-function (parser location) () - (make-music 'EventChord - 'origin location - 'elements (list (make-music 'BreathingSignEvent)))) - - -unfoldRepeats = -#(define-music-function (parser location music) (ly:music?) - (unfold-repeats music)) - -compressMusic = -#(define-music-function - (parser location fraction music) (number-pair? ly:music?) - (ly:music-compress music (ly:make-moment (car fraction) (cdr fraction)))) - -makeClusters = -#(define-music-function - (parser location arg) (ly:music?) - (music-map note-to-cluster arg)) - - -removeWithTag = -#(define-music-function - (parser location tag music) (symbol? ly:music?) - (music-filter - (lambda (m) - (let* ((tags (ly:music-property m 'tags)) - (res (memq tag tags))) - (not res))) - music)) - -keepWithTag = -#(define-music-function - (parser location tag music) (symbol? ly:music?) - (music-filter - (lambda (m) - (let* ((tags (ly:music-property m 'tags)) - (res (memq tag tags))) - (or - (eq? tags '()) - res))) - music)) - - -%% Todo: -%% doing -%% define-music-function in a .scm causes crash. - -cueDuring = -#(define-music-function - (parser location what dir main-music) - (string? ly:dir? ly:music?) - (make-music 'QuoteMusic - 'element main-music - 'quoted-context-type 'Voice - 'quoted-context-id "cue" - 'quoted-music-name what - 'quoted-voice-direction dir - 'origin location)) - - -transposedCueDuring = # -(define-music-function - (parser location what dir pitch-note main-music) - (string? ly:dir? ly:music? ly:music?) + grob-name) + (set! (ly:grob-property grob property) value)))))) - "Insert notes from the part @var{what} into a voice called @code{cue}, -using the transposition defined by @var{pitch-note}. This happens -simultaneously with @var{main-music}, which is usually a rest. The -argument @var{dir} determines whether the cue notes should be notated -as a first or second voice." - (make-music 'QuoteMusic - 'element main-music - 'quoted-context-type 'Voice - 'quoted-context-id "cue" - 'quoted-music-name what - 'quoted-voice-direction dir - 'quoted-transposition (pitch-of-note pitch-note) - 'origin location)) +removeWithTag = +#(define-music-function + (parser location tag music) (symbol? ly:music?) + (music-filter + (lambda (m) + (let* ((tags (ly:music-property m 'tags)) + (res (memq tag tags))) + (not res))) + music)) +%% Todo: +%% doing +%% define-music-function in a .scm causes crash. -quoteDuring = # -(define-music-function - (parser location what main-music) - (string? ly:music?) - (make-music 'QuoteMusic - 'element main-music - 'quoted-music-name what - 'origin location)) +octave = +#(define-music-function (parser location pitch-note) (ly:music?) + "octave check" + + (make-music 'RelativeOctaveCheck + 'origin location + 'pitch (pitch-of-note pitch-note) + )) +partcombine = +#(define-music-function (parser location part1 part2) (ly:music? ly:music?) + (make-part-combine-music (list part1 part2))) + pitchedTrill = #(define-music-function (parser location main-note secondary-note) @@ -263,80 +332,17 @@ pitchedTrill = main-note)) -killCues = -#(define-music-function - (parser location music) - (ly:music?) - (music-map - (lambda (mus) - (if (string? (ly:music-property mus 'quoted-music-name)) - (ly:music-property mus 'element) - mus)) music)) - - -afterGraceFraction = -#(cons 6 8) - -afterGrace = -#(define-music-function - (parser location main grace) - (ly:music? ly:music?) - - (let* - ((main-length (ly:music-length main)) - (fraction (ly:parser-lookup parser 'afterGraceFraction))) - - (make-simultaneous-music - (list - main - (make-sequential-music - (list - - (make-music 'SkipMusic - 'duration (ly:make-duration - 0 0 - (* (ly:moment-main-numerator main-length) - (car fraction)) - (* (ly:moment-main-denominator main-length) - (cdr fraction)) )) - (make-music 'GraceMusic - 'element grace))))))) - -barNumberCheck = -#(define-music-function (parser location n) (integer?) - (make-music 'ApplyContext - 'origin location - 'procedure - (lambda (c) - (let* - ((cbn (ly:context-property c 'currentBarNumber))) - (if (not (= cbn n)) - (ly:input-message location "Barcheck failed got ~a expect ~a" - cbn n)))))) -% for regression testing purposes. -assertBeamQuant = -#(define-music-function (parser location l r) (pair? pair?) - (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)))))) - -% for regression testing purposes. -assertBeamSlope = -#(define-music-function (parser location comp) (procedure?) - (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)))))) + +parenthesize = +#(define-music-function (parser loc arg) (ly:music?) + "Tag @var{arg} to be parenthesized." + (set! (ly:music-property arg 'parenthesize) #t) + arg) parallelMusic = #(define-music-function (parser location voice-ids music) (list? ly:music?) @@ -428,63 +434,14 @@ Example: - -%% this is a stub. Write your own to suit the spacing tweak output. -spacingTweaks = -#(define-music-function (parser location parameters) (list?) - (make-music 'SequentialMusic 'void #t)) - -octave = -#(define-music-function (parser location pitch-note) (ly:music?) - "octave check" - - (make-music 'RelativeOctaveCheck - 'origin location - 'pitch (pitch-of-note pitch-note) - )) - -addquote = -#(define-music-function (parser location name music) (string? ly:music?) - "Add a piece of music to be quoted " - (add-quotable name music) - (make-music 'SequentialMusic 'void #t)) - - -parenthesize = -#(define-music-function (parser loc arg) (ly:music?) - "Tag @var{arg} to be parenthesized." - - (set! (ly:music-property arg 'parenthesize) #t) - arg) - - -featherDurations= -#(define-music-function (parser location factor argument) (ly:moment? ly:music?) - - "Rearrange durations in ARGUMENT so there is an -acceleration/deceleration. " - - (let* - ((orig-duration (ly:music-length argument)) - (multiplier (ly:make-moment 1 1))) - - (music-map - (lambda (mus) - (if (and (eq? (ly:music-property mus 'name) 'EventChord) - (< 0 (ly:moment-main-denominator (ly:music-length mus)))) - (begin - (ly:music-compress mus multiplier) - (set! multiplier (ly:moment-mul factor multiplier))) - ) - mus) - argument) - - (ly:music-compress - argument - (ly:moment-div orig-duration (ly:music-length argument))) - - argument)) - +quoteDuring = # +(define-music-function + (parser location what main-music) + (string? ly:music?) + (make-music 'QuoteMusic + 'element main-music + 'quoted-music-name what + 'origin location)) @@ -506,3 +463,72 @@ resetRelativeOctave = reference-note)) + + +shiftDurations = +#(define-music-function (parser location dur dots arg) (integer? integer? ly:music?) + "" + + + (music-map + (lambda (x) + (shift-one-duration-log x dur dots)) arg)) + + +%% this is a stub. Write your own to suit the spacing tweak output. +spacingTweaks = +#(define-music-function (parser location parameters) (list?) + (make-music 'SequentialMusic 'void #t)) + + +transposedCueDuring = # +(define-music-function + (parser location what dir pitch-note main-music) + (string? ly:dir? ly:music? ly:music?) + + "Insert notes from the part @var{what} into a voice called @code{cue}, +using the transposition defined by @var{pitch-note}. This happens +simultaneously with @var{main-music}, which is usually a rest. The +argument @var{dir} determines whether the cue notes should be notated +as a first or second voice." + + (make-music 'QuoteMusic + 'element main-music + 'quoted-context-type 'Voice + 'quoted-context-id "cue" + 'quoted-music-name what + 'quoted-voice-direction dir + 'quoted-transposition (pitch-of-note pitch-note) + 'origin location)) + + + + + +tweak = #(define-music-function (parser location sym val arg) + (symbol? scheme? ly:music?) + + "Add @code{sym . val} to the @code{tweaks} property of @var{arg}." + + + (set! + (ly:music-property arg 'tweaks) + (acons sym val + (ly:music-property arg 'tweaks))) + arg) + +tag = #(define-music-function (parser location tag arg) + (symbol? ly:music?) + + "Add @var{tag} to the @code{tags} property of @var{arg}." + + (set! + (ly:music-property arg 'tags) + (cons tag + (ly:music-property arg 'tags))) + arg) + + +unfoldRepeats = +#(define-music-function (parser location music) (ly:music?) + (unfold-repeats music)) diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index 9ac56f093c..6c91ae3159 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -314,6 +314,14 @@ (interfaces . (staff-symbol-referencer-interface beam-interface)))))) + (BendAfter + . ( + (stencil . ,fall::print) + (thickness . 2.0) + (meta . ((class . Spanner) + (interfaces . (spanner-interface + fall-interface)))))) + (BreakAlignment . ( (non-musical . #t) @@ -603,6 +611,7 @@ dynamic-text-spanner-interface spanner-interface)))))) + (Fingering . ( diff --git a/scm/define-music-properties.scm b/scm/define-music-properties.scm index 9bf878ed6a..5ee322a5ca 100644 --- a/scm/define-music-properties.scm +++ b/scm/define-music-properties.scm @@ -16,12 +16,8 @@ (map (lambda (x) (apply music-property-description x)) `( - (iterator-ctor ,procedure? "Function to construct music-event-iterator object for this Music") - (duration ,ly:duration? "Duration of this note/lyric.") - (metronome-count ,number? "How many beats in a minute?") - (span-type ,string? "What kind of spanner should be created? + (alteration ,number? "alteration for figured bass") -TODO: consider making type into symbol") (absolute-octave ,integer? "The absolute octave for a octave check note.") (articulations ,ly:music-list? @@ -32,6 +28,9 @@ TODO: consider making type into symbol ") (augmented ,boolean? "This figure is for an augmented figured bass (with +) sign.") (associated-context ,string? "Name of the Voice context associated with this \\newaddlyrics section") (bass ,boolean? "Set if this note is a bass note in a chord") + (bracket-start ,boolean? "start a bracket +here. TODO: use SpanEvents?") + (bracket-stop ,boolean? "stop a bracket here.") (break-penalty ,number? "Penalty for line break hint.") (break-permission ,symbol? "Whether to allow, forbid or force a line break.") (cautionary ,boolean? "If set, this alteration needs cautionary accidental") @@ -40,34 +39,43 @@ TODO: consider making type into symbol ") (compress-procedure ,procedure? "compress this music expression. Argument 1: the music, arg 2: factor") (context-id ,string? "name of context") (context-type ,symbol? "type of context") - (create-new ,boolean? "Create a fresh context.") + (create-new ,boolean? "Create a fresh context.") + (delta-pitch ,number? "How much should a fall change pitch?") (descend-only ,boolean? "If set, this @code{\\context} will only descend in the context tree.") (denominator ,integer? "denominator in a time signature") (digit ,integer? "digit for fingering") (diminished ,boolean? "This bass figure should be slashed.") (direction ,ly:dir? "Print this up or down?") (drum-type ,symbol? "Which percussion instrument to play this note on.") + (duration ,ly:duration? "Duration of this note/lyric.") (error-found ,boolean? "If true, a parsing error was found in this expression") (element ,ly:music? "The single child of a Music_wrapper music object, or the body of a repeat.") (elements ,ly:music-list? "A list of elements for sequential of simultaneous music, or the alternatives of repeated music. ") (elements-callback ,procedure? "Return a list of children, for use by a sequential iterator. Takes a single Music parameter") (expected-beam-count ,integer? "Expected number of non-tremolo beams in a tremolo repeat") + (figure ,integer? "a bass figure") (force-accidental ,boolean? "If set, a cautionary accidental should always be printed on this note") (grob-property ,symbol? "The symbol of the grob property to set. ") (grob-property-path ,list? "A list of symbols, locating a nested grob property, e.g. (beamed-lengths details). ") (grob-value ,scheme? "The value of the grob property to set") (input-tag ,scheme? "Arbitrary marker to relate input and output") (inversion ,boolean? "If set, this chord note is inverted.") + (iterator-ctor ,procedure? "Function to construct music-event-iterator object for this Music") + (label ,markup? "label of a mark.") (last-pitch ,ly:pitch? "The last pitch after relativization.") (length ,ly:moment? "The duration of this music") (length-callback ,procedure? "How to compute the duration of this music. This property can only be defined as initializer in @file{define-music-types.scm}.") + (metronome-count ,number? "How many beats in a minute?") (name ,symbol? "Name of this music object") (no-continuation ,boolean? "If set, disallow continuation lines") (numerator ,integer? "numerator of a time signature") (once ,boolean? "Apply this operation only during one time step?") (octavation ,integer? "This pitch was octavated by how many octaves? For chord inversions, this is negative.") (origin ,ly:input-location? "where was this piece of music defined?") + (part-combine-status ,symbol? + "Change to what kind of state? Options are +solo1, solo2 and unisono") (parenthesize ,boolean? "Enclose resulting objects in parentheses?") (pitch ,ly:pitch? "the pitch of this note") (pitch-alist ,list? "list of pitches jointly forming the scale of a key signature") @@ -90,6 +98,9 @@ for the grob made of this event.") (repeat-count ,integer? "do a @code{\repeat} how ofen?") (span-direction ,ly:dir? "Does this start or stop a spanner?") + (span-type ,string? "What kind of spanner should be created? + +TODO: consider making type into symbol") (split-list ,list? "splitting moments for part combiner.") (start-callback ,procedure? "Function to compute the negative length of starting grace notes. This property can only be defined as @@ -113,14 +124,6 @@ translation property") (void ,boolean? "If this property is #t, then the music expression is to be discarded by the toplevel music handler.") (what ,symbol? "What to change for auto-change. FIXME, naming") - (part-combine-status ,symbol? - "Change to what kind of state? Options are -solo1, solo2 and unisono") - (figure ,integer? "a bass figure") - (alteration ,number? "alteration for figured bass") - (bracket-start ,boolean? "start a bracket -here. TODO: use SpanEvents?") - (bracket-stop ,boolean? "stop a bracket here.") (untransposable ,boolean? "If set, this music is not transposed.") ))) diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm index 251de0488e..3043c8aa52 100644 --- a/scm/define-music-types.scm +++ b/scm/define-music-types.scm @@ -104,6 +104,11 @@ Syntax for manual control: c8-[ c c-] c8") (types . (general-music event beam-event span-event)) )) + + (BendAfterEvent + . ((description . "A drop/fall/doit jazz articulation") + (types . (general-music fall-event event)))) + (BreakEvent . ( (description . "Create a line break, Syntax: \\break or page break, Syntax: \\pagebreak.") @@ -189,6 +194,7 @@ Syntax: @var{note}\\cr (types . (general-music event-chord simultaneous-music)) )) + (FingerEvent . ( (description . "Specify what finger to use for this note.") diff --git a/scm/define-stencil-commands.scm b/scm/define-stencil-commands.scm index 7a9740c76e..9b0b9422d6 100644 --- a/scm/define-stencil-commands.scm +++ b/scm/define-stencil-commands.scm @@ -17,20 +17,21 @@ dashed-slur dot draw-line + embedded-ps glyph-string named-glyph + path polygon repeat-slash + resetcolor round-filled-box + setcolor text url-link utf-8-string white-dot white-text - embedded-ps zigzag-line - setcolor - resetcolor grob-cause no-origin diff --git a/scm/output-lib.scm b/scm/output-lib.scm index 950e552e2a..572fcaff43 100644 --- a/scm/output-lib.scm +++ b/scm/output-lib.scm @@ -340,3 +340,38 @@ centered, X==1 is at the right, X == -1 is at the left." value) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; falls + +(define-public (fall::print spanner) + (let* + ((delta (ly:grob-property spanner 'delta-position)) + (left-span (ly:spanner-bound spanner LEFT)) + (right-span (ly:spanner-bound spanner RIGHT)) + (thickness (* (ly:grob-property spanner 'thickness) + (ly:output-def-lookup (ly:grob-layout spanner) 'line-thickness))) + (padding (ly:grob-property spanner 'padding 0.5)) + (common (ly:grob-common-refpoint right-span + (ly:grob-common-refpoint spanner + left-span X) + X)) + (left-x (+ padding (interval-end (ly:grob-robust-relative-extent left-span common X)))) + (right-x (- (interval-start (ly:grob-robust-relative-extent right-span common X)) padding)) + (self-x (ly:grob-relative-coordinate spanner common X)) + (dx (- right-x left-x)) + (exp (list 'path thickness + `(quote + (,(- left-x self-x) 0 + rmoveto + ,(/ dx 3) + 0 + ,dx ,(* 0.66 delta) + ,dx ,delta + rcurveto)))) + ) + + (ly:make-stencil + exp + (cons 0 dx) + (cons (min 0 delta) + (max 0 delta))))) diff --git a/scm/output-ps.scm b/scm/output-ps.scm index 1beaef6361..f71bc3dfce 100644 --- a/scm/output-ps.scm +++ b/scm/output-ps.scm @@ -320,3 +320,11 @@ (str4 thick) (str4 dx) (str4 dy))) + +(define (path thickness exps) + (format + "1 setlinecap ~a setlinewidth\n~a stroke" + thickness + (string-join (map (lambda (x) (format "~a" x)) exps) + " "))) + -- 2.39.2