From bbd36fb0cb6b2d8249cbe628470c736747c330d0 Mon Sep 17 00:00:00 2001 From: Valentin Villenave Date: Tue, 30 Nov 2010 21:24:40 +0100 Subject: [PATCH] Add support for tempo ranges This commit - extends the parser to accept the following syntax: \tempo numA ~ numB - changes the 'tempoUnitCount property to accept either a number or a pair (in which case tempoWholesPerMinutes will be set by averaging the two numbers) - adapts the format-metronome-markup translation function to print the tempo range properly - adds a metronome-range.ly regtest - adds relevant display-lily methods, and updates this regtest as well. --- input/regression/display-lily-tests.ly | 3 +++ input/regression/metronome-range.ly | 15 ++++++++++++++ lily/metronome-engraver.cc | 2 +- lily/parser.yy | 23 ++++++++++++++------- scm/c++.scm | 3 +++ scm/define-context-properties.scm | 2 +- scm/define-music-display-methods.scm | 12 +++++++++-- scm/lily.scm | 1 + scm/ly-syntax-constructors.scm | 28 +++++++++++++++----------- scm/song.scm | 6 +++++- scm/translation-functions.scm | 17 ++++++++++++++-- 11 files changed, 86 insertions(+), 26 deletions(-) create mode 100644 input/regression/metronome-range.ly diff --git a/input/regression/display-lily-tests.ly b/input/regression/display-lily-tests.ly index 426b61771b..c28ebf7e3b 100644 --- a/input/regression/display-lily-tests.ly +++ b/input/regression/display-lily-tests.ly @@ -164,6 +164,9 @@ stderr of this run." \test "" ##[ \mark \default #] % MarkEvent \test "" ##[ \mark "Allegro" #] \test "" ##[ \tempo 4 = 120 #] % MetronomeChangeEvent +\test "" ##[ \tempo 4 = 108 ~ 116 #] +\test "" ##[ \tempo "Allegro" 4 = 132 #] +\test "" ##[ \tempo "Andante" #] %% key, time, clef, bar \test "" ##[ \key \default #] % KeyChangeEvent diff --git a/input/regression/metronome-range.ly b/input/regression/metronome-range.ly new file mode 100644 index 0000000000..e5456ab529 --- /dev/null +++ b/input/regression/metronome-range.ly @@ -0,0 +1,15 @@ +\version "2.13.41" + +\header { + texidoc = " +Tempo ranges are supported. By default, numbers are +printed with an en-dash character, separated by thin-spaces. +" +} + +\relative c'' { + \tempo 4 = 66 ~ 72 + c1 c + \set Score.tempoUnitCount = #(cons 124 132) + c1 c +} diff --git a/lily/metronome-engraver.cc b/lily/metronome-engraver.cc index d55455f23d..0a41fc97ab 100644 --- a/lily/metronome-engraver.cc +++ b/lily/metronome-engraver.cc @@ -160,7 +160,7 @@ Metronome_mark_engraver::process_music () SCM duration = get_property ("tempoUnitDuration"); SCM text = get_property ("tempoText"); - if ( ( (unsmob_duration (duration) && scm_is_number (count)) + if ( ( (unsmob_duration (duration) && scm_is_true (count)) || Text_interface::is_markup (text) ) && !(ly_is_equal (count, last_count_) && ly_is_equal (duration, last_duration_) diff --git a/lily/parser.yy b/lily/parser.yy index 38e3e93b10..94dacc5d3e 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -437,6 +437,7 @@ If we give names, Bison complains. %type step_number %type step_numbers %type string +%type tempo_range %type score_block %type score_body @@ -906,14 +907,14 @@ output_def_body: ; tempo_event: - TEMPO steno_duration '=' bare_unsigned { - $$ = MAKE_SYNTAX ("tempo", @$, SCM_BOOL_F, $2, scm_from_int ($4)); + TEMPO steno_duration '=' tempo_range { + $$ = MAKE_SYNTAX ("tempo", @$, SCM_BOOL_F, $2, $4); } - | TEMPO string steno_duration '=' bare_unsigned { - $$ = MAKE_SYNTAX ("tempo", @$, make_simple_markup($2), $3, scm_from_int ($5)); + | TEMPO string steno_duration '=' tempo_range { + $$ = MAKE_SYNTAX ("tempo", @$, make_simple_markup($2), $3, $5); } - | TEMPO full_markup steno_duration '=' bare_unsigned { - $$ = MAKE_SYNTAX ("tempo", @$, $2, $3, scm_from_int ($5)); + | TEMPO full_markup steno_duration '=' tempo_range { + $$ = MAKE_SYNTAX ("tempo", @$, $2, $3, $5); } | TEMPO string { $$ = MAKE_SYNTAX ("tempoText", @$, make_simple_markup($2) ); @@ -2289,6 +2290,15 @@ step_number: } ; +tempo_range: + bare_unsigned { + $$ = scm_from_int ($1); + } + | bare_unsigned '~' bare_unsigned { + $$ = scm_cons (scm_from_int ($1), scm_from_int ($3)); + } + ; + /* UTILITIES @@ -2360,7 +2370,6 @@ unsigned_number: } ; - exclamations: { $$ = 0; } | exclamations '!' { $$ ++; } diff --git a/scm/c++.scm b/scm/c++.scm index 7f28900917..204f813d47 100644 --- a/scm/c++.scm +++ b/scm/c++.scm @@ -47,6 +47,9 @@ (define-public (string-or-pair? x) (or (string? x) (pair? x))) +(define-public (number-or-pair? x) + (or (number? x) (pair? x))) + (define-public (cheap-list? x) (or (pair? x) (null? x))) diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm index 8a22e2d36a..f758c04ca1 100644 --- a/scm/define-context-properties.scm +++ b/scm/define-context-properties.scm @@ -461,7 +461,7 @@ staff position of a tablature note head. Called with two arguments: the context and the string.") (tempoHideNote ,boolean? "Hide the note=count in tempo marks.") (tempoText ,markup? "Text for tempo marks.") - (tempoUnitCount ,number? "Count for specifying tempo.") + (tempoUnitCount ,number-or-pair? "Count for specifying tempo.") (tempoUnitDuration ,ly:duration? "Unit for specifying tempo.") (tempoWholesPerMinute ,ly:moment? "The tempo in whole notes per minute.") diff --git a/scm/define-music-display-methods.scm b/scm/define-music-display-methods.scm index 3b896a2450..515fc92d38 100644 --- a/scm/define-music-display-methods.scm +++ b/scm/define-music-display-methods.scm @@ -934,7 +934,11 @@ Otherwise, return #f." (format #f "\\tempo ~a ~a = ~a" (scheme-expr->lily-string ?unit-text) (duration->lily-string ?unit-duration #:force-duration #t) - ?unit-count)) + (if (number-pair? ?unit-count) + (format #f "~a ~~ ~a" + (car ?unit-count) + (cdr ?unit-count)) + ?unit-count))) (with-music-match (expr (music 'ContextSpeccedMusic element (music 'SequentialMusic elements ((music 'PropertyUnset @@ -949,7 +953,11 @@ Otherwise, return #f." symbol 'tempoUnitCount))))) (format #f "\\tempo ~a = ~a" (duration->lily-string ?unit-duration #:force-duration #t) - ?unit-count)) + (if (number-pair? ?unit-count) + (format #f "~a ~~ ~a" + (car ?unit-count) + (cdr ?unit-count)) + ?unit-count))) (with-music-match (expr (music 'ContextSpeccedMusic element (music 'SequentialMusic elements ((music 'PropertySet diff --git a/scm/lily.scm b/scm/lily.scm index 0a7e4d0d13..d4a0b23846 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -502,6 +502,7 @@ LilyPond safe mode. The syntax is the same as `define*-public'." (,markup-list? . "markup list") (,moment-pair? . "pair of moment objects") (,number-or-grob? . "number or grob") + (,number-or-pair? . "number or pair") (,number-or-string? . "number or string") (,number-pair? . "pair of numbers") (,rhythmic-location? . "rhythmic location") diff --git a/scm/ly-syntax-constructors.scm b/scm/ly-syntax-constructors.scm index 92276e745f..c34f5c9dd1 100644 --- a/scm/ly-syntax-constructors.scm +++ b/scm/ly-syntax-constructors.scm @@ -90,19 +90,23 @@ 'element (ly:music-transpose music pitch))) (define-ly-syntax-simple (tempo text duration tempo) - (let ((props (list - (make-property-set 'tempoWholesPerMinute - (ly:moment-mul (ly:make-moment tempo 1) - (ly:duration-length duration))) - (make-property-set 'tempoUnitDuration duration) - (make-property-set 'tempoUnitCount tempo)))) - (set! props (cons - (if text (make-property-set 'tempoText text) - (make-property-unset 'tempoText)) - props)) + (let* ((range-tempo? (pair? tempo)) + (tempo-count (if range-tempo? + (round (/ (+ (car tempo) (cdr tempo)) 2)) + tempo)) + (props (list + (make-property-set 'tempoWholesPerMinute + (ly:moment-mul (ly:make-moment tempo-count 1) + (ly:duration-length duration))) + (make-property-set 'tempoUnitDuration duration) + (make-property-set 'tempoUnitCount tempo)))) + (set! props (cons + (if text (make-property-set 'tempoText text) + (make-property-unset 'tempoText)) + props)) (context-spec-music - (make-sequential-music props) - 'Score))) + (make-sequential-music props) + 'Score))) (define-ly-syntax-simple (tempoText text) (context-spec-music diff --git a/scm/song.scm b/scm/song.scm index 410b3c89df..88b4423702 100644 --- a/scm/song.scm +++ b/scm/song.scm @@ -151,7 +151,11 @@ (duration->number (ly:music-property tempo-spec 'tempo-unit)))) ((music-name? tempo-spec 'SequentialMusic) (* (property-value - (find-child tempo-spec (lambda (elt) (music-property? elt 'tempoUnitCount)))) + (find-child tempo-spec (lambda (elt) + (let ((tempo (music-property? elt 'tempoUnitCount))) + (if (pair? tempo) + (round (/ (+ (car tempo) (cdr tempo)) 2)) + tempo))))) (duration->number (property-value (find-child tempo-spec (lambda (elt) (music-property? elt 'tempoUnitDuration))))))) diff --git a/scm/translation-functions.scm b/scm/translation-functions.scm index 62a408ce96..67653bc49a 100644 --- a/scm/translation-functions.scm +++ b/scm/translation-functions.scm @@ -31,14 +31,27 @@ (ly:duration-dot-count dur) 1)) #f)) - (note-markup (if (and (not hide-note) (number? count) (> count 0) ) + (count-markup (cond ((number? count) + (if (> count 0) + (make-simple-markup (number->string count)) + #f)) + ((pair? count) + (make-concat-markup + (list + (make-simple-markup (number->string (car count))) + (make-simple-markup " ") + (make-simple-markup "–") + (make-simple-markup " ") + (make-simple-markup (number->string (cdr count)))))) + (else #f))) + (note-markup (if (and (not hide-note) count-markup) (make-concat-markup (list (make-general-align-markup Y DOWN note-mark) (make-simple-markup " ") (make-simple-markup "=") (make-simple-markup " ") - (make-simple-markup (number->string count)))) + count-markup)) #f)) (text-markup (if (not (null? text)) (make-bold-markup text) -- 2.39.2