From bd23c6b42eaf1e6689d8672676fa3b85c2b77d5f Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Mon, 2 Feb 2004 15:31:08 +0000 Subject: [PATCH] * scm/define-music-types.scm (music-descriptions): add Solo{One,Two}Event and UnisonoEvent * lily/new-part-combine-iterator.cc (unisono): add state_ variable, signal changes with part-combine-event. * input/regression/new-part-combine-text.ly: new file. * lily/part-combine-engraver.cc: new file. --- ChangeLog | 15 +++ input/regression/new-part-combine-text.ly | 18 ++++ input/regression/new-part-combine.ly | 4 - lily/new-part-combine-iterator.cc | 106 +++++++++++++++------ lily/part-combine-engraver.cc | 110 +++++++++++++++++++++ ly/engraver-init.ly | 1 + scm/define-grobs.scm | 17 +++- scm/define-music-properties.scm | 8 +- scm/define-music-types.scm | 22 ++++- scm/music-functions.scm | 111 +++++++++++++++------- 10 files changed, 345 insertions(+), 67 deletions(-) create mode 100644 input/regression/new-part-combine-text.ly create mode 100644 lily/part-combine-engraver.cc diff --git a/ChangeLog b/ChangeLog index 9091adb42e..610e235f3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,24 @@ +2004-02-02 Han-Wen Nienhuys + + * scm/define-music-types.scm (music-descriptions): add + Solo{One,Two}Event and UnisonoEvent + + * lily/new-part-combine-iterator.cc (unisono): add state_ + variable, signal changes with part-combine-event. + + * input/regression/new-part-combine-text.ly: new file. + + * lily/part-combine-engraver.cc: new file. + 2004-02-02 Jan Nieuwenhuizen * scripts/filter-lilypond-book.py: Handle snippet options. 2004-02-02 Han-Wen Nienhuys + * scm/music-functions.scm (determine-split-list): detect solo1/2 + and unisono. + * lily/new-lyric-combine-music-iterator.cc (construct_children): revert fix, document why. diff --git a/input/regression/new-part-combine-text.ly b/input/regression/new-part-combine-text.ly new file mode 100644 index 0000000000..89a65309b3 --- /dev/null +++ b/input/regression/new-part-combine-text.ly @@ -0,0 +1,18 @@ + +\header { + texidoc ="The new part combiner: + +Detect a2, solo1, solo2 and print texts accordingly. +" + + + } + + +vone = \notes \relative a' { R1 a4 r4 r r a a a a } +vtwo = \notes \relative a' { R1 f4 f4 f4 f f f a a } + +\score { + \newpartcombine \vone \vtwo +} + diff --git a/input/regression/new-part-combine.ly b/input/regression/new-part-combine.ly index e83d6bdde3..dfc3cb5d87 100644 --- a/input/regression/new-part-combine.ly +++ b/input/regression/new-part-combine.ly @@ -10,10 +10,6 @@ Apart for: " } -theMusic = \context Staff \notes { c4 d8-. } - - - vone = \notes \relative a' { g2 g g g4 g f' c c( c) c c c ~ c c2. c4 c } diff --git a/lily/new-part-combine-iterator.cc b/lily/new-part-combine-iterator.cc index ecb4534c17..c98761aa9d 100644 --- a/lily/new-part-combine-iterator.cc +++ b/lily/new-part-combine-iterator.cc @@ -43,6 +43,12 @@ private: bool is_shared_ ; SCM split_list_; + enum { + APART, TOGETHER, + SOLO1, SOLO2, + UNISONO, + } state_; + Interpretation_context_handle one_; Interpretation_context_handle two_; Interpretation_context_handle null_; @@ -62,6 +68,7 @@ New_pc_iterator::New_pc_iterator () first_iter_ = 0; second_iter_ = 0; split_list_ = SCM_EOL; + state_ = APART; } void @@ -137,59 +144,102 @@ New_pc_iterator::ok () const void New_pc_iterator::chords_together () { - first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ()); - first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ()); - second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ()); - second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ()); + if (state_ == TOGETHER) + return; + else + { + state_ = TOGETHER; + first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ()); + first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ()); + second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ()); + second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ()); + } } void New_pc_iterator::solo1 () { - first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ()); - first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ()); + if (state_ == SOLO1) + return; + else + { + state_ = SOLO1; + first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ()); + first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ()); - second_iter_->substitute_outlet (two_.report_to (), null_.report_to ()); - second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ()); -} + second_iter_->substitute_outlet (two_.report_to (), null_.report_to ()); + second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ()); + + static Music* event; + if (!event) + event = make_music_by_name (ly_symbol2scm ("SoloOneEvent")); + first_iter_-> try_music_in_children (event); + } +} void New_pc_iterator::unisono () { - /* - like solo1, but should set a2 string. - */ - first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ()); - first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ()); - - second_iter_->substitute_outlet (two_.report_to (), null_.report_to ()); - second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ()); -} + if (state_ == UNISONO) + return; + else + { + state_ = UNISONO; + + first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ()); + first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ()); + + second_iter_->substitute_outlet (two_.report_to (), null_.report_to ()); + second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ()); + static Music* event; + if (!event) + event = make_music_by_name (ly_symbol2scm ("UnisonoEvent")); + + first_iter_-> try_music_in_children (event); + } +} + void New_pc_iterator::solo2 () { - second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ()); - second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ()); + if (state_ == SOLO2) + return; + else + { + state_ = SOLO2; + second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ()); + second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ()); - first_iter_->substitute_outlet (one_.report_to (), null_.report_to ()); - first_iter_->substitute_outlet (shared_.report_to (), null_.report_to ()); -} + first_iter_->substitute_outlet (one_.report_to (), null_.report_to ()); + first_iter_->substitute_outlet (shared_.report_to (), null_.report_to ()); + static Music* event; + if (!event) + event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent")); + + second_iter_-> try_music_in_children (event); + } +} void New_pc_iterator::apart () { - first_iter_->substitute_outlet (null_.report_to (), one_.report_to ()); - first_iter_->substitute_outlet (shared_.report_to (), one_.report_to ()); + if (state_ == APART) + return; + else + { + state_ = APART; + + first_iter_->substitute_outlet (null_.report_to (), one_.report_to ()); + first_iter_->substitute_outlet (shared_.report_to (), one_.report_to ()); - second_iter_->substitute_outlet (null_.report_to (), two_.report_to ()); - second_iter_->substitute_outlet (shared_.report_to (), two_.report_to ()); + second_iter_->substitute_outlet (null_.report_to (), two_.report_to ()); + second_iter_->substitute_outlet (shared_.report_to (), two_.report_to ()); } } - void New_pc_iterator::construct_children () { diff --git a/lily/part-combine-engraver.cc b/lily/part-combine-engraver.cc new file mode 100644 index 0000000000..1952395857 --- /dev/null +++ b/lily/part-combine-engraver.cc @@ -0,0 +1,110 @@ +/* + part-combine-engraver.cc -- implement PC-engraver + + source file of the GNU LilyPond music typesetter + + (c) 2000--2003 Jan Nieuwenhuizen + + Han-Wen Nienhuys + +*/ + +#include "engraver.hh" +#include "item.hh" +#include "text-item.hh" +#include "note-head.hh" +#include "stem.hh" +#include "side-position-interface.hh" +#include "multi-measure-rest.hh" + +class Part_combine_engraver : public Engraver +{ + TRANSLATOR_DECLARATIONS(Part_combine_engraver); + +protected: + virtual void acknowledge_grob (Grob_info); + virtual void process_music (); + virtual void stop_translation_timestep (); + virtual bool try_music (Music *); +private: + Item *text_; + Music *event_; +}; + +bool +Part_combine_engraver::try_music (Music*m) +{ + event_ = m; + return true; +} + +Part_combine_engraver::Part_combine_engraver () +{ + text_ = 0; + event_ =0; +} + +void +Part_combine_engraver::process_music () +{ + if (event_ + && to_boolean (get_property ("soloADue"))) + { + SCM what = event_->get_mus_property ("part-combine-status"); + SCM text = SCM_EOL; + if (what == ly_symbol2scm ("solo1")) + text = get_property ("soloText"); + else if (what== ly_symbol2scm ("solo2")) + text = get_property ("soloIIText"); + else if (what == ly_symbol2scm ("unisono")) + text = get_property ("aDueText"); + + if (Text_item::markup_p (text)) + { + text_ = make_item ("CombineTextScript"); + text_->set_grob_property ("text", text); + announce_grob (text_, event_->self_scm ()); + } + } +} + +void +Part_combine_engraver::acknowledge_grob (Grob_info i) +{ + if (text_) + { + if (Note_head::has_interface (i.grob_)) + { + Grob*t = text_; + Side_position_interface::add_support (t, i.grob_); + if (Side_position_interface::get_axis (t) == X_AXIS + && !t->get_parent (Y_AXIS)) + t->set_parent (i.grob_, Y_AXIS); + } + if (Stem::has_interface (i.grob_)) + { + Side_position_interface::add_support (text_, i.grob_); + } + } +} + +void +Part_combine_engraver::stop_translation_timestep () +{ + if (text_) + { + typeset_grob (text_); + text_ = 0; + } + event_ = 0; +} + +ENTER_DESCRIPTION(Part_combine_engraver, +/* descr */ "Part combine engraver for orchestral scores: " + "Print markings a2, Solo, Solo II, and unisono ", +/* creats*/ "CombineTextScript", +/* accepts */ "part-combine-event", +/* acks */ "multi-measure-rest-interface " +"slur-interface stem-interface note-head-interface" +,/* reads */ "soloADue", +/* write */ ""); diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 193dd3ea47..b664bd8578 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -173,6 +173,7 @@ \consists "Percent_repeat_engraver" \consists "Slash_repeat_engraver" \consists "Melisma_engraver" + \consists "Part_combine_engraver" %{ Must come before text_engraver, but after note_column engraver. diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index a3da4407dc..435adc0378 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -1082,7 +1082,22 @@ (font-family . roman) (meta . ((interfaces . (text-script-interface text-interface side-position-interface font-interface item-interface )))) )) - + (CombineTextScript + . ( + (molecule-callback . ,Text_item::brew_molecule) + (no-spacing-rods . #t) + (Y-offset-callbacks . (,Side_position_interface::aligned_side)) + (X-offset-callbacks . (,Self_alignment_interface::aligned_on_self)) + (direction . 1) + (padding . 0.5) + (staff-padding . 0.5) + (script-priority . 200) + ;; todo: add X self alignment? + (baseline-skip . 2) + (font-family . roman) + (font-series . bold) + (meta . ((interfaces . (text-script-interface text-interface side-position-interface font-interface item-interface )))) + )) (TextSpanner . ( (molecule-callback . ,Text_spanner::brew_molecule) diff --git a/scm/define-music-properties.scm b/scm/define-music-properties.scm index 6731047090..a118419f74 100644 --- a/scm/define-music-properties.scm +++ b/scm/define-music-properties.scm @@ -79,7 +79,10 @@ For chord inversions, this is negative.") "Do these operations for instantiating the context.") (music-property-description 'predicate procedure? "the predicate of a \\outputproperty") (music-property-description 'type symbol? "The type of this music object. Determines iteration in some cases.") -(music-property-description 'types list? "The types of this music object. Determines iteration in some cases.") +(music-property-description 'types list? "The types of this music +object; determines by what engraver this music expression is +processed.") + (music-property-description 'repeat-count integer? "do a @code{\repeat} how ofen?") (music-property-description 'span-direction ly:dir? "Does this start or stop a spanner?") (music-property-description 'split-list list? "splitting moments for part combiner.") @@ -94,6 +97,9 @@ starting grace notes.") (music-property-description 'value scheme? "Assignment value for a translation property") (music-property-description 'what symbol? "What to change for auto-change. FIXME, naming") +(music-property-description 'part-combine-status symbol? + "Change to what kind of state? Options are +solo1, solo2 and unisono") (music-property-description 'figure string? "a `figure' (which may be a string) for figured bass") diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm index 58ff4e0121..c845f602cb 100644 --- a/scm/define-music-types.scm +++ b/scm/define-music-types.scm @@ -139,7 +139,7 @@ c8-[ c c-] c8") (CrescendoEvent . ( - (description . "Begins or ends a crescendo. Syntax: @var{note}\\cr + (description . "Begins or ends a crescendo. Syntax: @var{note}\\cr ... @var{note}\\rc (you can also use \\<, \\!, \\cresc, and \\endcresc. See the user manual for details.).") @@ -405,6 +405,26 @@ to group start-mmrest, skip, stop-mmrest sequence. Syntax @code{R2.*5} for 5 mea (iterator-ctor . ,Sequential_music_iterator::constructor) (types . (general-music sequential-music)) )) + + (SoloOneEvent + . ( + (description . "Print Solo.1") + (internal-class-name . "Event") + (part-combine-status . solo1) + (types . (general-music event part-combine-event)) + )) + (SoloTwoEvent + . ( + (description . "Print Solo.2") + (internal-class-name . "Event") + (part-combine-status . solo2) + (types . (general-music event part-combine-event)) + )) + (UnisonoEvent + . ((description . "Print a2") + (internal-class-name . "Event") + (part-combine-status . unisono) + (types . (general-music event part-combine-event)))) (SimultaneousMusic . ( diff --git a/scm/music-functions.scm b/scm/music-functions.scm index 081163c8af..9100c8907e 100644 --- a/scm/music-functions.scm +++ b/scm/music-functions.scm @@ -844,6 +844,10 @@ Rest can contain a list of beat groupings (cdr (vector-ref v i))) (define chord-threshold 8) + (define (get-note-evs v i) + (define (f? x) + (equal? (ly:get-mus-property x 'name) 'NoteEvent)) + (filter f? (map car (what v i)))) (define result (list->vector @@ -907,11 +911,7 @@ Rest can contain a list of beat groupings (helper analyse-tie-end active evs) evs) evs) active (length notes1) 1) (put 'apart)) ((> (length notes2) 1) (put 'apart)) + ((not (= (length notes1) (length notes2))) + (put 'apart)) ((and (= (length durs1) 1) (= (length durs2) 1) @@ -988,36 +990,81 @@ Rest can contain a list of beat groupings (put 'apart)) (else - (if - (and (= (length pitches1) 1) (= (length pitches2) 1) - (< chord-threshold (ly:pitch-steps - (ly:pitch-diff (car pitches1) (car pitches2))))) - (put 'apart) - - - ;; copy previous split state from spanner state - (begin - (map (lambda (key-idx) - (let* - ((idx (cdr key-idx)) - (prev (what result idx)) - ) - (if (symbol? prev) - (put prev)) - )) (append active1 active2)) - (if (and (null? new-active1) (null? new-active2)) - (put 'chords ri))) - - ))) ) + (if (and (= (length pitches1) (length pitches2))) + (if + (and (pair? pitches1) (pair? pitches2) + (< chord-threshold (ly:pitch-steps + (ly:pitch-diff (car pitches1) (car pitches2))))) + (put 'apart) + + + ;; copy previous split state from spanner state + (begin + (map (lambda (key-idx) + (let* + ((idx (cdr key-idx)) + (prev (what result idx)) + ) + (if (symbol? prev) + (put prev)) + )) (append active1 active2)) + (if (and (null? new-active1) (null? new-active2)) + (put 'chords ri)))) + + )))) + ;; active states different: - (put 'apart) ) - (analyse-time-step (1+ i1) (1+ i2) (1+ ri) new-active1 new-active2)) - ))))) + (put 'apart)) + (analyse-time-step (1+ i1) (1+ i2) (1+ ri) new-active1 new-active2))) + )))) ;; - - + (define (analyse-solo12 i1 i2 ri) + (cond + ((= ri (vector-length result)) '()) + ((= i1 (vector-length ev1)) '()) + ((= i2 (vector-length ev2)) '()) + (else + (let* + ( + (m1 (when ev1 i1)) + (m2 (when ev2 i2)) + (notes1 (get-note-evs ev1 i1)) + (durs1 (sort (map (lambda (x) (ly:get-mus-property x 'duration)) notes1) ly:durationlist result)) -- 2.39.2