From: hanwen Date: Sat, 21 Feb 2004 01:05:31 +0000 (+0000) Subject: * lily/sequential-iterator.cc (process): only process if moment >= 0. X-Git-Tag: release/2.1.27~22 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=388393d4de6c93d12da5d1c84cb112126fa80c84;p=lilypond.git * lily/sequential-iterator.cc (process): only process if moment >= 0. * lily/parser.yy (command_element): \quote DURATION NAME: support cue notes. * lily/quote-iterator.cc (class Quote_iterator): new file. --- diff --git a/ChangeLog b/ChangeLog index b8e7a5c27b..7d32442c92 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2004-02-21 Han-Wen Nienhuys + + * lily/sequential-iterator.cc (process): only process if moment >= 0. + + * lily/parser.yy (command_element): \quote DURATION NAME: support + cue notes. + + * lily/quote-iterator.cc (class Quote_iterator): new file. + 2004-02-20 Han-Wen Nienhuys * lily/auto-beam-engraver.cc (try_music): accept and process diff --git a/lily/my-lily-lexer.cc b/lily/my-lily-lexer.cc index f412d4d2ba..cceb376a6f 100644 --- a/lily/my-lily-lexer.cc +++ b/lily/my-lily-lexer.cc @@ -67,6 +67,7 @@ static Keyword_ent the_key_tab[]={ {"paper", PAPER}, {"partcombine", PARTCOMBINE}, {"partial", PARTIAL}, + {"quote", QUOTE}, {"relative", RELATIVE}, {"remove", REMOVE}, {"repeat", REPEAT}, diff --git a/lily/new-part-combine-iterator.cc b/lily/new-part-combine-iterator.cc deleted file mode 100644 index 79e3e7c889..0000000000 --- a/lily/new-part-combine-iterator.cc +++ /dev/null @@ -1,418 +0,0 @@ -/* - new-part-combine-music-iterator.cc -- implement New_pc_iterator - - source file of the GNU LilyPond music typesetter - - (c) 2004 Han-Wen Nienhuys -*/ - -#include "context.hh" -#include "event.hh" -#include "music-sequence.hh" -#include "lily-guile.hh" -#include "warn.hh" -#include "music-iterator.hh" -#include "interpretation-context-handle.hh" - -class New_pc_iterator : public Music_iterator -{ -public: - New_pc_iterator (); - - DECLARE_SCHEME_CALLBACK(constructor, ()); -protected: - virtual void derived_substitute (Context *f, Context *t) ; - virtual void derived_mark () const; - New_pc_iterator (New_pc_iterator const &); - - virtual void construct_children (); - virtual Moment pending_moment () const; - virtual void do_quit(); - virtual void process (Moment); - - virtual Music_iterator *try_music_in_children (Music *) const; - - virtual bool ok () const; - -private: - Music_iterator * first_iter_; - Music_iterator * second_iter_; - - SCM split_list_; - - enum Status { - APART, TOGETHER, - SOLO1, SOLO2, - UNISONO, UNISILENCE, - }; - Status state_; - Status playing_state_; - - /* - TODO: this is getting of hand... - */ - Interpretation_context_handle one_; - Interpretation_context_handle two_; - Interpretation_context_handle null_; - Interpretation_context_handle shared_; - Interpretation_context_handle solo_; - - void substitute_both (Context * to1, - Context * to2); - - void kill_mmrest (Context *); - void chords_together (); - void solo1 (); - void solo2 (); - void apart (bool silent); - void unisono (bool silent); -}; - - -New_pc_iterator::New_pc_iterator () -{ - first_iter_ = 0; - second_iter_ = 0; - split_list_ = SCM_EOL; - state_ = APART; - playing_state_ = APART; -} - -void -New_pc_iterator::derived_mark () const -{ - if (first_iter_) - scm_gc_mark (first_iter_->self_scm()); - if (second_iter_) - scm_gc_mark(second_iter_->self_scm()); -} - -void -New_pc_iterator::derived_substitute (Context *f, - Context *t) -{ - if (first_iter_) - first_iter_->substitute_outlet (f,t); - if (second_iter_) - second_iter_->substitute_outlet (f,t); -} - -void -New_pc_iterator::do_quit () -{ - if (first_iter_) - first_iter_->quit(); - if (second_iter_) - second_iter_->quit(); - - null_.set_translator (0); - one_ .set_translator (0); - two_.set_translator (0); - shared_.set_translator (0); - solo_.set_translator (0); -} - -Moment -New_pc_iterator::pending_moment () const -{ - Moment p; - p.set_infinite (1); - if (first_iter_->ok ()) - p = p pending_moment (); - - if (second_iter_->ok ()) - p = p pending_moment (); - return p; -} - -bool -New_pc_iterator::ok () const -{ - return first_iter_->ok () || second_iter_->ok (); -} - -void -New_pc_iterator::chords_together () -{ - if (state_ == TOGETHER) - return; - else - { - playing_state_ = TOGETHER; - state_ = TOGETHER; - - substitute_both (shared_.get_outlet (), shared_.get_outlet()); - } -} - - -void -New_pc_iterator::kill_mmrest (Context * tg) -{ - static Music * mmrest; - if (!mmrest) - { - mmrest = make_music_by_name (ly_symbol2scm ("MultiMeasureRestEvent")); - mmrest->set_mus_property ("duration", SCM_EOL); - } - - tg->try_music (mmrest); -} - -void -New_pc_iterator::solo1 () -{ - if (state_ == SOLO1) - return; - else - { - state_ = SOLO1; - substitute_both (solo_.get_outlet (), - null_.get_outlet ()); - - kill_mmrest (two_.get_outlet ()); - kill_mmrest (shared_.get_outlet ()); - - if (playing_state_ != SOLO1) - { - static Music* event; - if (!event) - event = make_music_by_name (ly_symbol2scm ("SoloOneEvent")); - - first_iter_-> try_music_in_children (event); - } - playing_state_ = SOLO1; - } -} - -void -New_pc_iterator::substitute_both (Context * to1, - Context * to2) -{ - Context *tos[] = {to1,to2}; - Music_iterator *mis[] = {first_iter_, second_iter_}; - Interpretation_context_handle *hs[] = { - &null_, - &one_, &two_, - &shared_, &solo_, - 0 - }; - - for (int i = 0; i < 2 ; i++) - { - for (int j = 0; hs[j]; j++) - if (hs[j]->get_outlet () != tos[i]) - mis[i]->substitute_outlet (hs[j]->get_outlet (), tos[i]); - } - - for (int j = 0; hs[j]; j++) - { - Context * t = hs[j]->get_outlet (); - if (t != to1 && t != to2) - kill_mmrest (t); - } -} - - -void -New_pc_iterator::unisono (bool silent) -{ - Status newstate = (silent) ? UNISILENCE : UNISONO; - - if (newstate == state_) - return; - else - { - substitute_both (shared_.get_outlet (), null_.get_outlet ()); - - kill_mmrest (two_.get_outlet ()); - kill_mmrest (shared_.get_outlet ()); - - if (playing_state_ != UNISONO - && newstate == UNISONO) - { - static Music* event; - if (!event) - event = make_music_by_name (ly_symbol2scm ("UnisonoEvent")); - - first_iter_-> try_music_in_children (event); - playing_state_ = UNISONO; - } - state_ = newstate; - } -} - -void -New_pc_iterator::solo2 () -{ - if (state_ == SOLO2) - return; - else - { - state_ = SOLO2; - - substitute_both (null_.get_outlet (), solo_.get_outlet ()); - - if (playing_state_ != SOLO2) - { - static Music* event; - if (!event) - event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent")); - - second_iter_-> try_music_in_children (event); - playing_state_ = SOLO2; - } - } -} - -void -New_pc_iterator::apart (bool silent) -{ - if (!silent) - playing_state_ = APART; - - if (state_ == APART) - return; - else - { - state_ = APART; - substitute_both (one_.get_outlet (), two_.get_outlet ()); - } -} - - -void -New_pc_iterator::construct_children () -{ - split_list_ = get_music ()->get_mus_property ("split-list"); - SCM lst = get_music ()->get_mus_property ("elements"); - - SCM props = scm_list_n (/* - used to have tweaks here. - */ - - SCM_UNDEFINED); - - Context *tr - = get_outlet ()->find_create_context (ly_symbol2scm ("Voice"), - "shared",props); - - shared_.set_translator (tr); - - /* - If we don't, we get a new staff for every Voice. - */ - set_translator (tr); - - Context *solo_tr - = get_outlet ()->find_create_context (ly_symbol2scm ("Voice"), - "solo",props); - - solo_ .set_translator (solo_tr); - - Context *null - = get_outlet ()->find_create_context (ly_symbol2scm ("Devnull"), - "", SCM_EOL); - - if (!null) - programming_error ("No Devnull found?"); - - null_.set_translator (null); - - Context *one = tr->find_create_context (ly_symbol2scm ("Voice"), - "one", props); - - one_.set_translator (one); - - set_translator (one); - first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst)))); - - - Context *two = tr->find_create_context (ly_symbol2scm ("Voice"), - "two", props); - two_.set_translator (two); - set_translator (two); - second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst)))); - - - set_translator (tr); - - - char const * syms[] = { - "Stem", - "DynamicLineSpanner", - "Tie", - "Dots", - "Rest", - "Slur", - "TextScript", - "Script", - 0 - }; - - for (char const**p = syms; *p; p++) - { - SCM sym = ly_symbol2scm (*p); - execute_pushpop_property (one, sym, - ly_symbol2scm ("direction"), gh_int2scm (1)); - - execute_pushpop_property (two, sym, - ly_symbol2scm ("direction"), gh_int2scm (-1)); - } - -} - -void -New_pc_iterator::process (Moment m) -{ - Moment now = get_outlet ()->now_mom (); - Moment *splitm = 0; - - for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_)) - { - splitm = unsmob_moment (gh_caar (split_list_)); - if (*splitm > now) - break ; - - SCM tag = gh_cdar (split_list_); - - if (tag == ly_symbol2scm ("chords")) - chords_together (); - else if (tag == ly_symbol2scm ("apart") - || tag == ly_symbol2scm ("apart-silence") - || tag == ly_symbol2scm ("apart-spanner")) - apart (tag == ly_symbol2scm ("apart-silence")); - else if (tag == ly_symbol2scm ("unisono")) - unisono (false); - else if (tag == ly_symbol2scm ("unisilence")) - unisono (true); - else if (tag == ly_symbol2scm ("solo1")) - solo1 (); - else if (tag == ly_symbol2scm ("solo2")) - solo2 (); - else if (gh_symbol_p (tag)) - { - String s = "Unknown split directive: " - + (gh_symbol_p (tag) ? ly_symbol2string (tag) : String ("not a symbol")); - programming_error (s); - } - } - - if (first_iter_->ok ()) - first_iter_->process (m); - - if (second_iter_->ok ()) - second_iter_->process (m); -} - -Music_iterator* -New_pc_iterator::try_music_in_children (Music *m) const -{ - Music_iterator * i = first_iter_->try_music (m); - if (i) - return i; - else - return second_iter_->try_music (m); -} - -IMPLEMENT_CTOR_CALLBACK (New_pc_iterator); diff --git a/lily/parser.yy b/lily/parser.yy index f4998c7c6b..566af26bb6 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -283,6 +283,7 @@ yylex (YYSTYPE *s, void * v) %token PAPER %token PARTCOMBINE %token PARTIAL +%token QUOTE %token RELATIVE %token REMOVE %token REPEAT @@ -1347,6 +1348,13 @@ command_element: $$ = skip; } + | QUOTE duration_length STRING { + Music * quote = MY_MAKE_MUSIC("QuoteMusic"); + quote->set_mus_property ("duration", $2); + quote->set_mus_property ("quoted-name", $3); + quote->set_spot (THIS->here_input ()); + $$ = quote; + } | OCTAVE { THIS->push_spot (); } pitch { Music *l = MY_MAKE_MUSIC("RelativeOctaveCheck"); diff --git a/lily/part-combine-iterator.cc b/lily/part-combine-iterator.cc new file mode 100644 index 0000000000..600de9611e --- /dev/null +++ b/lily/part-combine-iterator.cc @@ -0,0 +1,418 @@ +/* + new-part-combine-music-iterator.cc -- implement Part_combine_iterator + + source file of the GNU LilyPond music typesetter + + (c) 2004 Han-Wen Nienhuys +*/ + +#include "context.hh" +#include "event.hh" +#include "music-sequence.hh" +#include "lily-guile.hh" +#include "warn.hh" +#include "music-iterator.hh" +#include "interpretation-context-handle.hh" + +class Part_combine_iterator : public Music_iterator +{ +public: + Part_combine_iterator (); + + DECLARE_SCHEME_CALLBACK(constructor, ()); +protected: + virtual void derived_substitute (Context *f, Context *t) ; + virtual void derived_mark () const; + Part_combine_iterator (Part_combine_iterator const &); + + virtual void construct_children (); + virtual Moment pending_moment () const; + virtual void do_quit(); + virtual void process (Moment); + + virtual Music_iterator *try_music_in_children (Music *) const; + + virtual bool ok () const; + +private: + Music_iterator * first_iter_; + Music_iterator * second_iter_; + + SCM split_list_; + + enum Status { + APART, TOGETHER, + SOLO1, SOLO2, + UNISONO, UNISILENCE, + }; + Status state_; + Status playing_state_; + + /* + TODO: this is getting of hand... + */ + Interpretation_context_handle one_; + Interpretation_context_handle two_; + Interpretation_context_handle null_; + Interpretation_context_handle shared_; + Interpretation_context_handle solo_; + + void substitute_both (Context * to1, + Context * to2); + + void kill_mmrest (Context *); + void chords_together (); + void solo1 (); + void solo2 (); + void apart (bool silent); + void unisono (bool silent); +}; + + +Part_combine_iterator::Part_combine_iterator () +{ + first_iter_ = 0; + second_iter_ = 0; + split_list_ = SCM_EOL; + state_ = APART; + playing_state_ = APART; +} + +void +Part_combine_iterator::derived_mark () const +{ + if (first_iter_) + scm_gc_mark (first_iter_->self_scm()); + if (second_iter_) + scm_gc_mark(second_iter_->self_scm()); +} + +void +Part_combine_iterator::derived_substitute (Context *f, + Context *t) +{ + if (first_iter_) + first_iter_->substitute_outlet (f,t); + if (second_iter_) + second_iter_->substitute_outlet (f,t); +} + +void +Part_combine_iterator::do_quit () +{ + if (first_iter_) + first_iter_->quit(); + if (second_iter_) + second_iter_->quit(); + + null_.set_translator (0); + one_ .set_translator (0); + two_.set_translator (0); + shared_.set_translator (0); + solo_.set_translator (0); +} + +Moment +Part_combine_iterator::pending_moment () const +{ + Moment p; + p.set_infinite (1); + if (first_iter_->ok ()) + p = p pending_moment (); + + if (second_iter_->ok ()) + p = p pending_moment (); + return p; +} + +bool +Part_combine_iterator::ok () const +{ + return first_iter_->ok () || second_iter_->ok (); +} + +void +Part_combine_iterator::chords_together () +{ + if (state_ == TOGETHER) + return; + else + { + playing_state_ = TOGETHER; + state_ = TOGETHER; + + substitute_both (shared_.get_outlet (), shared_.get_outlet()); + } +} + + +void +Part_combine_iterator::kill_mmrest (Context * tg) +{ + static Music * mmrest; + if (!mmrest) + { + mmrest = make_music_by_name (ly_symbol2scm ("MultiMeasureRestEvent")); + mmrest->set_mus_property ("duration", SCM_EOL); + } + + tg->try_music (mmrest); +} + +void +Part_combine_iterator::solo1 () +{ + if (state_ == SOLO1) + return; + else + { + state_ = SOLO1; + substitute_both (solo_.get_outlet (), + null_.get_outlet ()); + + kill_mmrest (two_.get_outlet ()); + kill_mmrest (shared_.get_outlet ()); + + if (playing_state_ != SOLO1) + { + static Music* event; + if (!event) + event = make_music_by_name (ly_symbol2scm ("SoloOneEvent")); + + first_iter_-> try_music_in_children (event); + } + playing_state_ = SOLO1; + } +} + +void +Part_combine_iterator::substitute_both (Context * to1, + Context * to2) +{ + Context *tos[] = {to1,to2}; + Music_iterator *mis[] = {first_iter_, second_iter_}; + Interpretation_context_handle *hs[] = { + &null_, + &one_, &two_, + &shared_, &solo_, + 0 + }; + + for (int i = 0; i < 2 ; i++) + { + for (int j = 0; hs[j]; j++) + if (hs[j]->get_outlet () != tos[i]) + mis[i]->substitute_outlet (hs[j]->get_outlet (), tos[i]); + } + + for (int j = 0; hs[j]; j++) + { + Context * t = hs[j]->get_outlet (); + if (t != to1 && t != to2) + kill_mmrest (t); + } +} + + +void +Part_combine_iterator::unisono (bool silent) +{ + Status newstate = (silent) ? UNISILENCE : UNISONO; + + if (newstate == state_) + return; + else + { + substitute_both (shared_.get_outlet (), null_.get_outlet ()); + + kill_mmrest (two_.get_outlet ()); + kill_mmrest (shared_.get_outlet ()); + + if (playing_state_ != UNISONO + && newstate == UNISONO) + { + static Music* event; + if (!event) + event = make_music_by_name (ly_symbol2scm ("UnisonoEvent")); + + first_iter_-> try_music_in_children (event); + playing_state_ = UNISONO; + } + state_ = newstate; + } +} + +void +Part_combine_iterator::solo2 () +{ + if (state_ == SOLO2) + return; + else + { + state_ = SOLO2; + + substitute_both (null_.get_outlet (), solo_.get_outlet ()); + + if (playing_state_ != SOLO2) + { + static Music* event; + if (!event) + event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent")); + + second_iter_-> try_music_in_children (event); + playing_state_ = SOLO2; + } + } +} + +void +Part_combine_iterator::apart (bool silent) +{ + if (!silent) + playing_state_ = APART; + + if (state_ == APART) + return; + else + { + state_ = APART; + substitute_both (one_.get_outlet (), two_.get_outlet ()); + } +} + + +void +Part_combine_iterator::construct_children () +{ + split_list_ = get_music ()->get_mus_property ("split-list"); + SCM lst = get_music ()->get_mus_property ("elements"); + + SCM props = scm_list_n (/* + used to have tweaks here. + */ + + SCM_UNDEFINED); + + Context *tr + = get_outlet ()->find_create_context (ly_symbol2scm ("Voice"), + "shared",props); + + shared_.set_translator (tr); + + /* + If we don't, we get a new staff for every Voice. + */ + set_translator (tr); + + Context *solo_tr + = get_outlet ()->find_create_context (ly_symbol2scm ("Voice"), + "solo",props); + + solo_ .set_translator (solo_tr); + + Context *null + = get_outlet ()->find_create_context (ly_symbol2scm ("Devnull"), + "", SCM_EOL); + + if (!null) + programming_error ("No Devnull found?"); + + null_.set_translator (null); + + Context *one = tr->find_create_context (ly_symbol2scm ("Voice"), + "one", props); + + one_.set_translator (one); + + set_translator (one); + first_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_car (lst)))); + + + Context *two = tr->find_create_context (ly_symbol2scm ("Voice"), + "two", props); + two_.set_translator (two); + set_translator (two); + second_iter_ = unsmob_iterator (get_iterator (unsmob_music (gh_cadr (lst)))); + + + set_translator (tr); + + + char const * syms[] = { + "Stem", + "DynamicLineSpanner", + "Tie", + "Dots", + "Rest", + "Slur", + "TextScript", + "Script", + 0 + }; + + for (char const**p = syms; *p; p++) + { + SCM sym = ly_symbol2scm (*p); + execute_pushpop_property (one, sym, + ly_symbol2scm ("direction"), gh_int2scm (1)); + + execute_pushpop_property (two, sym, + ly_symbol2scm ("direction"), gh_int2scm (-1)); + } + +} + +void +Part_combine_iterator::process (Moment m) +{ + Moment now = get_outlet ()->now_mom (); + Moment *splitm = 0; + + for (; gh_pair_p (split_list_); split_list_ = gh_cdr (split_list_)) + { + splitm = unsmob_moment (gh_caar (split_list_)); + if (*splitm > now) + break ; + + SCM tag = gh_cdar (split_list_); + + if (tag == ly_symbol2scm ("chords")) + chords_together (); + else if (tag == ly_symbol2scm ("apart") + || tag == ly_symbol2scm ("apart-silence") + || tag == ly_symbol2scm ("apart-spanner")) + apart (tag == ly_symbol2scm ("apart-silence")); + else if (tag == ly_symbol2scm ("unisono")) + unisono (false); + else if (tag == ly_symbol2scm ("unisilence")) + unisono (true); + else if (tag == ly_symbol2scm ("solo1")) + solo1 (); + else if (tag == ly_symbol2scm ("solo2")) + solo2 (); + else if (gh_symbol_p (tag)) + { + String s = "Unknown split directive: " + + (gh_symbol_p (tag) ? ly_symbol2string (tag) : String ("not a symbol")); + programming_error (s); + } + } + + if (first_iter_->ok ()) + first_iter_->process (m); + + if (second_iter_->ok ()) + second_iter_->process (m); +} + +Music_iterator* +Part_combine_iterator::try_music_in_children (Music *m) const +{ + Music_iterator * i = first_iter_->try_music (m); + if (i) + return i; + else + return second_iter_->try_music (m); +} + +IMPLEMENT_CTOR_CALLBACK (Part_combine_iterator); diff --git a/lily/quote-iterator.cc b/lily/quote-iterator.cc new file mode 100644 index 0000000000..ed26decf3f --- /dev/null +++ b/lily/quote-iterator.cc @@ -0,0 +1,173 @@ +/* + quote-iterator.cc -- implement Quote_iterator + + source file of the GNU LilyPond music typesetter + + (c) 2004 Han-Wen Nienhuys + +*/ + +#include "context.hh" +#include "event.hh" +#include "music-sequence.hh" +#include "lily-guile.hh" +#include "music-iterator.hh" +#include "music.hh" +#include "input.hh" +#include "warn.hh" + + +class Quote_iterator : public Music_iterator +{ +public: + Quote_iterator (); + + Moment start_moment_; + SCM event_vector_; + int event_idx_; + int end_idx_ ; + + DECLARE_SCHEME_CALLBACK(constructor, ()); + +protected: + virtual void construct_children (); + virtual Moment pending_moment () const; + virtual void process (Moment); + virtual bool ok () const; +}; + +Quote_iterator::Quote_iterator () +{ + event_vector_ = SCM_EOL; + event_idx_ = 0; + end_idx_ = 0; +} + +bool +moment_less (SCM a, SCM b) +{ + return *unsmob_moment (a) < *unsmob_moment (b); +} + + +int +binsearch_scm_vector (SCM vec, SCM key, bool (*is_less)(SCM a,SCM b)) +{ + int lo; + int hi; + lo = 0; + hi = SCM_VECTOR_LENGTH (vec); + + /* binary search */ + do + { + int cmp = (lo + hi) / 2; + + SCM when = gh_car (SCM_VECTOR_REF(vec, cmp)); + bool result = (*is_less) (key, when); + if (result) + hi = cmp; + else + lo = cmp; + } + while (hi - lo > 1); + + return lo; +} + + +void +Quote_iterator::construct_children () +{ + SCM tab = get_outlet()->get_property ("quotes"); + if (scm_hash_table_p (tab) != SCM_BOOL_T) + { + get_music ()->origin ()->warning ("Context property `quotes' unset; cannot process quote."); + return ; + } + + SCM name = get_music ()->get_mus_property ("quoted-name"); + SCM dur = get_music ()->get_mus_property ("duration"); + + if (!unsmob_duration (dur)) + return ; + + set_translator (get_outlet ()->get_default_interpreter ()); + + Moment now = get_outlet ()->now_mom (); + Moment stop = now + unsmob_duration (dur)->get_length (); + + start_moment_ = now; + + event_vector_ = scm_hash_ref (tab, name, SCM_BOOL_F); + + if (scm_vector_p (event_vector_) == SCM_BOOL_T) + { + event_idx_ = binsearch_scm_vector (event_vector_, now.smobbed_copy (), &moment_less); + end_idx_ = binsearch_scm_vector (event_vector_, stop.smobbed_copy (), &moment_less); + } + else + get_music ()->origin ()->warning ("Can't find requested source"); +} + + +bool +Quote_iterator::ok () const +{ + return (event_idx_ < end_idx_); +} + + +Moment +Quote_iterator::pending_moment () const +{ + SCM entry = SCM_VECTOR_REF (event_vector_, event_idx_); + return *unsmob_moment (gh_car (entry)) - start_moment_; +} + + +void +Quote_iterator::process (Moment m) +{ + SCM entry = SCM_EOL; + + m += start_moment_; + while (event_idx_ < end_idx_) + { + entry = SCM_VECTOR_REF (event_vector_, event_idx_); + + Moment em = *unsmob_moment (gh_car (entry)); + + if (em > m) + return ; + + if (em == m) + break ; + + event_idx_++; + } + + if (!gh_pair_p (entry)) + return; + + for (SCM s = gh_cdr (entry); gh_pair_p (s); s = gh_cdr (s)) + { + SCM ev_acc = gh_car (s); + + + Music * mus = unsmob_music (gh_car (ev_acc)); + if (mus) + { + bool b = get_outlet ()->try_music (mus); + + if (!b) + mus->origin ()->warning (_f ("In quotation: junking event %s", mus->name())); + } + else + programming_error ("need music in quote."); + } + + event_idx_ ++; +} + +IMPLEMENT_CTOR_CALLBACK (Quote_iterator); diff --git a/lily/sequential-iterator.cc b/lily/sequential-iterator.cc index c63d812ccb..b7d733aa25 100644 --- a/lily/sequential-iterator.cc +++ b/lily/sequential-iterator.cc @@ -246,8 +246,12 @@ Sequential_iterator::process (Moment until) iter_->process (iter_->music_get_length ()); } else - iter_->process (until - here_mom_ + iter_->music_start_mom ()); - + { + Moment w = until - here_mom_ + iter_->music_start_mom (); + if (w >= Moment (0)) + iter_->process (w); + } + /* if the iter is still OK, there must be events left that have diff --git a/ly/declarations-init.ly b/ly/declarations-init.ly index 9405e8985c..ba75cb154e 100644 --- a/ly/declarations-init.ly +++ b/ly/declarations-init.ly @@ -130,5 +130,4 @@ partCombineListener = \paper { % reset default duration unusedEntry = \notes { c4 } -% music = "\melodic\relative c" - +#(define musicQuotes (make-hash-table)) diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm index 23389f9cbf..22c2b77848 100644 --- a/scm/define-context-properties.scm +++ b/scm/define-context-properties.scm @@ -437,6 +437,7 @@ signature change.") Script_engraver for typesetting note-super/subscripts. See @file{scm/script.scm} for more information ") + (quotes ,hash-table? "Hash table, mapping names to music-event vectors.") (stavesFound ,grob-list? "list of all staff-symbols found.") (tieMelismaBusy ,boolean? "Signal whether a tie is present.") ) diff --git a/scm/define-music-properties.scm b/scm/define-music-properties.scm index 0c70e7a78e..f033680d3b 100644 --- a/scm/define-music-properties.scm +++ b/scm/define-music-properties.scm @@ -81,6 +81,7 @@ For chord inversions, this is negative.") (property-operations ,list? "Do these operations for instantiating the context.") (predicate ,procedure? "the predicate of a \\outputproperty") + (quoted-name ,string? "The name of the voice to be quoted") (type ,symbol? "The type of this music object. Determines iteration in some cases.") (types ,list? "The types of this music object; determines by what engraver this music expression is diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm index 5d7bb57b29..5cd4e91f45 100644 --- a/scm/define-music-types.scm +++ b/scm/define-music-types.scm @@ -321,9 +321,8 @@ as separate voices.") (internal-class-name . "Simultaneous_music") (types . (general-music part-combine-music)) - (iterator-ctor . ,New_pc_iterator::constructor) + (iterator-ctor . ,Part_combine_iterator::constructor) )) - (PhrasingSlurEvent . ( (description . "Start or end phrasing slur. Syntax NOTE \\( and \\) NOTE") @@ -362,6 +361,14 @@ goes down).") (types . (general-music pes-or-flexa-event event)) )) + (QuoteMusic + . ( + (description . "Quote preprocessed snippets of music. ") + (internal-class-name . "Event") ;; so we get Event::get_length (). + (iterator-ctor . ,Quote_iterator::constructor) + (types . (general-music)) + )) + (RelativeOctaveCheck . ((description . "Check if a pitch is in the correct octave.") (internal-class-name . "Relative_octave_check") diff --git a/scm/part-combiner.scm b/scm/part-combiner.scm index 297153fef4..16f5e0f5aa 100644 --- a/scm/part-combiner.scm +++ b/scm/part-combiner.scm @@ -625,3 +625,18 @@ the mark when there are no spanners active." )) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define-public (add-quotable name mus) + (set! noticed '()) + (let* + ((tab (eval 'musicQuotes (current-module) )) + (context (ly:run-translator (context-spec-music mus 'Voice) + part-combine-listener)) + (evs (last-pair noticed)) + ) + + (if (pair? evs) + (hash-set! tab name + (list->vector (reverse! (car evs) '())))) + ))