From: Han-Wen Nienhuys Date: Sat, 17 May 2003 13:27:00 +0000 (+0000) Subject: * input/regression/markup-note.ly: new file X-Git-Tag: release/1.7.20~48 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=de19d3787ab5ba1d4bd951176eaa03b2b4ceee95;p=lilypond.git * input/regression/markup-note.ly: new file * input/regression/metronome-marking.ly: new file * lily/metronome-engraver.cc: new file. Print \tempo markings. * scm/new-markup.scm (note-markup): make a note glyph, useful for metronome marks. --- diff --git a/ChangeLog b/ChangeLog index 4209da2636..7d56f42436 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2003-05-17 Han-Wen Nienhuys + + * input/regression/markup-note.ly: new file + + * input/regression/metronome-marking.ly: new file + + * lily/metronome-engraver.cc: new file. Print \tempo markings. + + * scm/new-markup.scm (note-markup): make a note glyph, useful for + metronome marks. + 2003-05-17 Jan Nieuwenhuizen * Documentation/user/GNUmakefile: Compatibility fix for new diff --git a/Documentation/user/refman.itely b/Documentation/user/refman.itely index e2d7547df9..861874b0a4 100644 --- a/Documentation/user/refman.itely +++ b/Documentation/user/refman.itely @@ -402,13 +402,10 @@ by replacing the @internalsref{Note_heads_engraver} by the @end example For example, - -@ignore -@example[relative 0] +@example \time 2/4 c2. c8 d4 e f g a b c8 c2 b4 a g16 f4 e d c8. c2 @end example -@end ignore @lilypond[noindent] \score{ diff --git a/input/regression/markup-note.ly b/input/regression/markup-note.ly new file mode 100644 index 0000000000..8f342f7ad5 --- /dev/null +++ b/input/regression/markup-note.ly @@ -0,0 +1,43 @@ +\header { + + texidoc = "The note markup function is used to make metronome + markings. It works for a variety of flag dot and duration settings." +} +\version "1.7.18" + +\score { \notes { c4^\markup { + \note #0 #0 #1 + \note #1 #0 #1 + \note #2 #0 #1 + \note #3 #0 #1 + \note #4 #0 #1 + \note #5 #0 #1 + \note #6 #0 #1 + + \note #0 #0 #-1 + \note #1 #0 #-1 + \note #2 #0 #-1 + \note #3 #0 #-1 + \note #4 #0 #-1 + \note #5 #0 #-1 + \note #6 #0 #-1 + + \note #0 #1 #-1 + \note #1 #1 #-1 + \note #2 #1 #-1 + \note #3 #1 #-1 + \note #4 #1 #-1 + \note #5 #1 #-1 + \note #6 #1 #-1 + + \note #0 #1 #1 + \note #1 #1 #1 + \note #2 #1 #1 + \note #3 #1 #1 + \note #4 #1 #1 + \note #5 #1 #1 + \note #6 #1 #1 + +} + +} } diff --git a/input/regression/metronome-marking.ly b/input/regression/metronome-marking.ly new file mode 100644 index 0000000000..1743b6483e --- /dev/null +++ b/input/regression/metronome-marking.ly @@ -0,0 +1,17 @@ + +\header { + + texidoc = "@code{\tempo} directives are printed as metronome markings. + +THe marking is left aligned with the time signature, if there is one. +" + + } + +\version "1.7.18" + +\score { \notes \relative c'' { \tempo \breve = 100 c1 c1 \tempo 8.. = 50 c1 } +\paper { raggedright = ##t } + + } + diff --git a/lily/lexer.ll b/lily/lexer.ll index 332257ff80..7fc5828206 100644 --- a/lily/lexer.ll +++ b/lily/lexer.ll @@ -468,7 +468,10 @@ HYPHEN -- return MARKUP_HEAD_SCM0_MARKUP1; else if (tag == ly_symbol2scm ("scheme0-scheme1-markup2")) return MARKUP_HEAD_SCM0_SCM1_MARKUP2; + else if (tag == ly_symbol2scm ("scheme0-scheme1-scheme2")) + return MARKUP_HEAD_SCM0_SCM1_SCM2; else { + programming_error ("No parser tag defined for this signature. Abort"); ly_display_scm (s); assert(false); } diff --git a/lily/metronome-engraver.cc b/lily/metronome-engraver.cc new file mode 100644 index 0000000000..32d15cafe8 --- /dev/null +++ b/lily/metronome-engraver.cc @@ -0,0 +1,121 @@ +/* + mark-engraver.cc -- implement Metronome_mark_engraver + + source file of the GNU LilyPond music typesetter + + (c) 1998--2003 Jan Nieuwenhuizen +*/ + +#include + +#include "bar-line.hh" +#include "time-signature.hh" +#include "engraver.hh" +#include "engraver-group-engraver.hh" +#include "item.hh" + +/** + put stuff over or next to bars. Examples: bar numbers, marginal notes, + rehearsal marks. + */ +class Metronome_mark_engraver : public Engraver +{ +public: + TRANSLATOR_DECLARATIONS(Metronome_mark_engraver); +protected: + Item* text_; + Grob * bar_line_; + +protected: + virtual void stop_translation_timestep (); + virtual void acknowledge_grob (Grob_info); + void create_items (Music*); + virtual bool try_music (Music *req); + virtual void start_translation_timestep (); + virtual void process_music (); + +private: + Music * mark_req_; +}; + +Metronome_mark_engraver::Metronome_mark_engraver () +{ + text_ =0; + mark_req_ = 0; +} + +void +Metronome_mark_engraver::acknowledge_grob (Grob_info inf) +{ + if (Bar_line::has_interface (inf.grob_)) + { + bar_line_ = inf.grob_; + } + else if (text_ && Time_signature::has_interface (inf.grob_)) + { + text_->set_parent (inf.grob_, X_AXIS); + } +} + +void +Metronome_mark_engraver::stop_translation_timestep () +{ + if (text_) + { + if (bar_line_ && !text_->get_parent (X_AXIS)) + text_->set_parent (bar_line_, X_AXIS); + + text_->set_grob_property ("side-support-elements" , get_property ("stavesFound")); + typeset_grob (text_); + text_ =0; + } +} + + +void +Metronome_mark_engraver::create_items (Music *rq) +{ + if (text_) + return; + + SCM s = get_property ("MetronomeMark"); + text_ = new Item (s); + + announce_grob(text_, rq->self_scm()); +} + +void +Metronome_mark_engraver::start_translation_timestep () +{ + mark_req_ = 0; +} + +bool +Metronome_mark_engraver::try_music (Music* r) +{ + mark_req_ = r; + return true; +} + +void +Metronome_mark_engraver::process_music () +{ + if (mark_req_) + { + create_items (mark_req_); + + SCM proc = get_property ("metronomeMarkFormatter"); + SCM result= scm_call_2 (proc, mark_req_->self_scm (), + daddy_trans_->self_scm()); + + text_->set_grob_property ("text", result); + } +} + +ENTER_DESCRIPTION(Metronome_mark_engraver, +/* descr */ "Engrave metro nome marking. This delegates the real work to the function in the metronomeMarkFormatter property", +/* creats*/ "MetronomeMark", +/* accepts */ "metronome-change-event", +/* acks */ "time-signature-interface bar-line-interface", +/* reads */ "stavesFound metronomeMarkFormatter", +/* write */ ""); diff --git a/lily/parser.yy b/lily/parser.yy index e9025b65c2..09ace3518a 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -308,6 +308,7 @@ yylex (YYSTYPE *s, void * v) %token MARKUP_HEAD_SCM0 %token MARKUP_HEAD_SCM0_MARKUP1 %token MARKUP_HEAD_SCM0_SCM1 +%token MARKUP_HEAD_SCM0_SCM1_SCM2 %token MARKUP_HEAD_SCM0_SCM1_MARKUP2 %token MARKUP_IDENTIFIER MARKUP_HEAD_LIST0 @@ -707,7 +708,7 @@ music_output_def_body: tempo_event: TEMPO steno_duration '=' bare_unsigned { - $$ = MY_MAKE_MUSIC("TempoEvent"); + $$ = MY_MAKE_MUSIC("MetronomeChangeEvent"); $$->set_mus_property ("tempo-unit", $2); $$->set_mus_property ("metronome-count", gh_int2scm ( $4)); } @@ -2179,7 +2180,11 @@ full_markup: THIS->lexer_->pop_state (); } ; - + + +/* +This should be done more dynamically if possible. +*/ markup: STRING { $$ = make_simple_markup ($1); @@ -2205,6 +2210,9 @@ markup: | MARKUP_HEAD_SCM0_SCM1_MARKUP2 embedded_scm embedded_scm markup { $$ = scm_list_n ($1, $2, $3, $4, SCM_UNDEFINED); } + | MARKUP_HEAD_SCM0_SCM1_SCM2 embedded_scm embedded_scm embedded_scm { + $$ = scm_list_n ($1, $2, $3, $4, SCM_UNDEFINED); + } | MARKUP_IDENTIFIER { $$ = $1; } diff --git a/lily/tempo-performer.cc b/lily/tempo-performer.cc index b963d593e8..c699aea225 100644 --- a/lily/tempo-performer.cc +++ b/lily/tempo-performer.cc @@ -81,5 +81,5 @@ Tempo_performer::try_music (Music* req) ENTER_DESCRIPTION (Tempo_performer, "","", - "tempo-event", + "metronome-change-event", "","","" ); diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 1c85c4c44b..7151edd13e 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -350,6 +350,7 @@ ScoreContext = \translator { \consists "Output_property_engraver" \consists "System_start_delimiter_engraver" \consists "Mark_engraver" + \consists "Metronome_mark_engraver" \consists "Break_align_engraver" \consists "Spacing_engraver" \consists "Vertical_align_engraver" @@ -452,7 +453,7 @@ ScoreContext = \translator { %% bassFigureFormatFunction = #make-bass-figure-markup - + metronomeMarkFormatter = #make-metronome-markup \grobdescriptions #all-grob-descriptions } diff --git a/scm/grob-description.scm b/scm/grob-description.scm index eb9fd179e1..18a53ca200 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -502,11 +502,11 @@ (RehearsalMark . ( - (molecule-callback . ,Text_item::brew_molecule) + (molecule-callback . ,brew-new-markup-molecule) (X-offset-callbacks . (,Self_alignment_interface::aligned_on_self)) (Y-offset-callbacks . (,Side_position_interface::aligned_side)) (self-alignment-X . 0) - + (break-align-symbol . time-signature) (direction . 1) (breakable . #t) (font-family . roman) @@ -515,7 +515,17 @@ (padding . 0.8) (meta . ((interfaces . (text-interface side-position-interface font-interface mark-interface self-alignment-interface item-interface )))) )) - + (MetronomeMark + . ( + (molecule-callback . ,brew-new-markup-molecule) + (Y-offset-callbacks . (,Side_position_interface::aligned_side)) + (direction . 1) + (breakable . #t) + (font-family . roman) + (break-visibility . ,end-of-line-invisible) + (padding . 0.8) + (meta . ((interfaces . (text-interface side-position-interface font-interface metronome-mark-interface item-interface)))) + )) (MeasureGrouping . ( (Y-offset-callbacks . (,Side_position_interface::out_of_staff diff --git a/scm/interface-description.scm b/scm/interface-description.scm index 300785f770..25370f169a 100644 --- a/scm/interface-description.scm +++ b/scm/interface-description.scm @@ -49,6 +49,12 @@ are interesting enough to maintain a hara-kiri staff." '( )) +(ly:add-interface + 'metronome-mark-interface + "a rehearsal mark" + '( + )) + ;;; todo: this is not typesetting info. Move to interpretation. (ly:add-interface 'tablature-interface diff --git a/scm/lily.scm b/scm/lily.scm index 26df1eef06..0c5cda7036 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -226,6 +226,21 @@ L1 is copied, L2 not. ) +(define-public (range x y) + "Produce a list of integers starting at Y with X elements." + (if (<= x 0) + '() + (cons y (range (- x 1) (+ y 1))) + + ) + ) + +(define-public (interval-length x) + "Length of the number-pair X, when an interval" + (max 0 (- (cdr x) (car x))) + ) + + (define (other-axis a) (remainder (+ a 1) 2)) diff --git a/scm/music-functions.scm b/scm/music-functions.scm index 4129d94be0..5ca516c5bc 100644 --- a/scm/music-functions.scm +++ b/scm/music-functions.scm @@ -10,6 +10,25 @@ (number->string (ly:get-mus-property mus 'denominator)) )) +;; metronome marks +(define-public (make-metronome-markup event context) + (let* + ((dur (ly:get-mus-property event 'tempo-unit)) + (count (ly:get-mus-property event 'metronome-count)) + (note-mark (make-note-markup (ly:duration-log dur) + (ly:duration-dot-count dur) + 1) + ) + ) + + (make-line-markup + (list + note-mark + (make-simple-markup "=") + (make-simple-markup (number->string count)) + + )))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define-public (music-map function music) diff --git a/scm/music-types.scm b/scm/music-types.scm index 6f97df349e..e44981c176 100644 --- a/scm/music-types.scm +++ b/scm/music-types.scm @@ -538,11 +538,11 @@ For example, transposed music.") (types . (general-music string-number-event event)) )) - (TempoEvent + (MetronomeChangeEvent . ( (description . "Change tempo setting (in beats per minute).") (internal-class-name . "Event") - (types . (general-music tempo-event event)) + (types . (general-music metronome-change-event tempo-event event)) )) (TextScriptEvent diff --git a/scm/new-markup.scm b/scm/new-markup.scm index 1c3020c45b..248047def9 100644 --- a/scm/new-markup.scm +++ b/scm/new-markup.scm @@ -201,26 +201,77 @@ for the reader. (let* ( (log (car rest)) - (dots (cadr rest)) + (dot-count (cadr rest)) (dir (caddr rest)) - (font (ly:get-font grob props)) + (font (ly:get-font grob (cons '((font-family . music)) props))) + (stemlen (max 3 (- log 1))) (headgl - (ly:find-glyph-by-name font (string-append "noteheads-" (number->string log)))) - (flaggl (if (> log 2) - (ly:find-glyph-by-name - font - (string-append "flags-" (number->string log) - (if (dir > 0) "u" "d"))) #f)) - (stemth 0.13) - (stemgl (ly:round-filled-box (cons - (cons 0.0 stemth) - (cons 0.0 (+ 3.0 0.75))))) - ) + (ly:find-glyph-by-name font (string-append "noteheads-" (number->string (min log 2))))) + (stemth 0.13) + (stemy (* dir stemlen)) + (attachx (if (> dir 0) (- (cdr (ly:molecule-get-extent headgl X)) stemth) + 0)) + (attachy (* dir 0.28)) + (stemgl (if (> log 0) + (ly:round-filled-box (cons + (cons attachx (+ attachx stemth)) + (cons (min stemy attachy) + (max stemy attachy))) + (/ stemth 3) + ) #f)) + (dot (ly:find-glyph-by-name font "dots-dot")) + (dotwid (interval-length (ly:molecule-get-extent dot X))) + (dots (if (> dot-count 0) + (reduce + (lambda (x y) + (ly:molecule-add x y)) + (map (lambda (x) + (ly:molecule-translate-axis + dot (* (+ 1 (* 2 x)) dotwid) X) ) + (range dot-count 1))) + #f + )) + + (flaggl (if (> log 2) + (ly:molecule-translate + (ly:find-glyph-by-name + font + (string-append "flags-" + (if (> dir 0) "u" "d") + (number->string log) + )) + (cons (+ attachx (/ stemth 2)) stemy)) + + #f))) + + (if flaggl + (set! stemgl (ly:molecule-add flaggl stemgl))) + (if (ly:molecule? stemgl) + (set! stemgl (ly:molecule-add stemgl headgl)) + (set! stemgl headgl) + ) + + (if (ly:molecule? dots) + (set! stemgl + (ly:molecule-add + (ly:molecule-translate-axis + dots + (+ + (if (and (> dir 0) (> log 2)) + (* 1.5 dotwid) 0) + ;; huh ? why not necessary? + ;(cdr (ly:molecule-get-extent headgl X)) + dotwid + ) + X) + stemgl + ) + )) - #f - )) + stemgl + )) (define-public (normal-size-super-markup grob props . rest) (ly:molecule-translate-axis (interpret-markup diff --git a/scm/translator-property-description.scm b/scm/translator-property-description.scm index 94b7cb445c..ce325a021e 100644 --- a/scm/translator-property-description.scm +++ b/scm/translator-property-description.scm @@ -297,6 +297,9 @@ the start of the music. whether a melisma is active. This can be used to signal melismas on top of those automatically detected. ") (translator-property-description 'melismaEngraverBusy boolean? "See melismaBusy. This is set automatically.") +(translator-property-description 'metronomeMarkFormatter procedure? + "How to produce a metronome markup. +Called with 2 arguments, event and context.") (translator-property-description 'midiInstrument string? "Name of the MIDI instrument to use ") (translator-property-description 'midiMinimumVolume number? "[DOCUMENT-ME]") diff --git a/scripts/lilypond-book.py b/scripts/lilypond-book.py index 5d1b35d46c..981611d984 100644 --- a/scripts/lilypond-book.py +++ b/scripts/lilypond-book.py @@ -1345,6 +1345,8 @@ def write_deps (fn, target, chunks): read_files = [] def check_texidoc (chunks): + ## TODO: put file name in front of texidoc. + ## n = [] for c in chunks: if c[0] == 'lilypond':