X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=sidebyside;f=lily%2Fpart-combine-iterator.cc;h=f742d75a734f8f3bccc061e7482277f4218e9f32;hb=3c805354bda3080080f085b2ff7ef1df26b0a168;hp=0b17fd3f48f86f0a50a84aac3151d19f8a31cb98;hpb=40ce03239ae5e7d7056508c2dea7d368a7cd9bf4;p=lilypond.git diff --git a/lily/part-combine-iterator.cc b/lily/part-combine-iterator.cc index 0b17fd3f48..f742d75a73 100644 --- a/lily/part-combine-iterator.cc +++ b/lily/part-combine-iterator.cc @@ -1,116 +1,94 @@ -/* - new-part-combine-music-iterator.cc -- implement Part_combine_iterator +/* + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter - - (c) 2004 Han-Wen Nienhuys + Copyright (C) 2004--2015 Han-Wen Nienhuys + + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ #include "context.hh" -#include "event.hh" -#include "music-sequence.hh" +#include "dispatcher.hh" #include "lily-guile.hh" -#include "warn.hh" +#include "music.hh" #include "music-iterator.hh" -#include "interpretation-context-handle.hh" +#include "music-sequence.hh" +#include "warn.hh" +#include "lily-imports.hh" class Part_combine_iterator : public Music_iterator { public: Part_combine_iterator (); - DECLARE_SCHEME_CALLBACK (constructor, ()); + DECLARE_SCHEME_CALLBACK (constructor, ()); protected: - virtual void derived_substitute (Context *f, Context *t) ; + 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 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_; - Moment start_moment_; - - 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); + static const size_t NUM_PARTS = 2; + Music_iterator *iterators_[NUM_PARTS]; + + Stream_event *mmrest_event_; + + bool is_active_outlet (const Context *c) const; + void kill_mmrest (Context *c); }; +const size_t Part_combine_iterator::NUM_PARTS; -Part_combine_iterator::Part_combine_iterator () +void +Part_combine_iterator::do_quit () { - first_iter_ = 0; - second_iter_ = 0; - split_list_ = SCM_EOL; - state_ = APART; - playing_state_ = APART; + for (size_t i = 0; i < NUM_PARTS; i++) + if (iterators_[i]) + iterators_[i]->quit (); } -void -Part_combine_iterator::derived_mark () const +Part_combine_iterator::Part_combine_iterator () { - if (first_iter_) - scm_gc_mark (first_iter_->self_scm ()); - if (second_iter_) - scm_gc_mark (second_iter_->self_scm ()); + mmrest_event_ = 0; + + for (size_t i = 0; i < NUM_PARTS; i++) + iterators_[i] = 0; } void -Part_combine_iterator::derived_substitute (Context *f, - Context *t) +Part_combine_iterator::derived_mark () const { - if (first_iter_) - first_iter_->substitute_outlet (f,t); - if (second_iter_) - second_iter_->substitute_outlet (f,t); + for (size_t i = 0; i < NUM_PARTS; i++) + if (iterators_[i]) + scm_gc_mark (iterators_[i]->self_scm ()); + + if (mmrest_event_) + scm_gc_mark (mmrest_event_->self_scm ()); } void -Part_combine_iterator::do_quit () +Part_combine_iterator::derived_substitute (Context *f, + Context *t) { - 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); + // (Explain why just iterators_[0].) + if (iterators_[0]) + iterators_[0]->substitute_outlet (f, t); } Moment @@ -118,314 +96,83 @@ 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 (); + for (size_t i = 0; i < NUM_PARTS; i++) + if (iterators_[i]->ok ()) + p = min (p, iterators_[i]->pending_moment ()); + return p; } bool Part_combine_iterator::ok () const { - return first_iter_->ok () || second_iter_->ok (); -} + for (size_t i = 0; i < NUM_PARTS; i++) + if (iterators_[i]->ok ()) + return true; -void -Part_combine_iterator::chords_together () -{ - if (state_ == TOGETHER) - return; - else - { - playing_state_ = TOGETHER; - state_ = TOGETHER; - - substitute_both (shared_.get_outlet (), shared_.get_outlet ()); - } + return false; } - -void -Part_combine_iterator::kill_mmrest (Context * tg) +bool Part_combine_iterator::is_active_outlet (const Context *c) const { - static Music * mmrest; - if (!mmrest) - { - mmrest = make_music_by_name (ly_symbol2scm ("MultiMeasureRestEvent")); - mmrest->set_property ("duration", SCM_EOL); - } - - tg->try_music (mmrest); -} + for (size_t i = 0; i < NUM_PARTS; i++) + if (iterators_[i] && (iterators_[i]->get_outlet () == c)) + return true; -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; - } + return false; } void -Part_combine_iterator::substitute_both (Context * to1, - Context * to2) +Part_combine_iterator::kill_mmrest (Context *c) { - 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++) + if (!mmrest_event_) { - Context * t = hs[j]->get_outlet (); - if (t != to1 && t != to2) - kill_mmrest (t); + mmrest_event_ = new Stream_event + (Lily::ly_make_event_class (ly_symbol2scm ("multi-measure-rest-event"))); + mmrest_event_->set_property ("duration", SCM_EOL); + mmrest_event_->unprotect (); } -} - -void -Part_combine_iterator::unisono (bool silent) -{ - Status newstate = (silent) ? UNISILENCE : UNISONO; - - if (newstate == state_) - return; - else - { - /* - If we're coming from SOLO2 state, we might have kill mmrests - in the 1st voice, so in that case, we use the second voice - as a basis for events. - */ - Context *c1 = (state_ == SOLO2) ? null_.get_outlet() : shared_.get_outlet(); - Context *c2 = (state_ == SOLO2) ? shared_.get_outlet() : null_.get_outlet(); - - substitute_both (c1, c2); - - - kill_mmrest ((state_ == SOLO2) - ? one_.get_outlet () : 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")); - - (state_ == SOLO2 ? second_iter_ : first_iter_) - ->try_music_in_children (event); - playing_state_ = UNISONO; - } - state_ = newstate; - } + c->event_source ()->broadcast (mmrest_event_); } void -Part_combine_iterator::solo2 () +Part_combine_iterator::construct_children () { - 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; - } - } + SCM lst = get_music ()->get_property ("elements"); + iterators_[0] = unsmob (get_iterator (unsmob (scm_car (lst)))); + iterators_[1] = unsmob (get_iterator (unsmob (scm_cadr (lst)))); } void -Part_combine_iterator::apart (bool silent) +Part_combine_iterator::process (Moment m) { - if (!silent) - playing_state_ = APART; - - if (state_ == APART) - return; - else + Context *prev_active_outlets[NUM_PARTS]; + bool any_outlet_changed = false; + for (size_t i = 0; i < NUM_PARTS; i++) { - state_ = APART; - substitute_both (one_.get_outlet (), two_.get_outlet ()); - } -} - - -void -Part_combine_iterator::construct_children () -{ - start_moment_ = get_outlet ()->now_mom (); - split_list_ = get_music ()->get_property ("split-list"); - SCM lst = get_music ()->get_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); + prev_active_outlets[i] = iterators_[i]->get_outlet (); - Context *solo_tr - = get_outlet ()->find_create_context (ly_symbol2scm ("Voice"), - "solo",props); + if (iterators_[i]->ok ()) + iterators_[i]->process (m); - 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 (ly_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 (ly_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"), scm_int2num (1)); - - execute_pushpop_property (two, sym, - ly_symbol2scm ("direction"), scm_int2num (-1)); + if (prev_active_outlets[i] != iterators_[i]->get_outlet ()) + any_outlet_changed = true; } -} - -void -Part_combine_iterator::process (Moment m) -{ - Moment now = get_outlet ()->now_mom (); - Moment *splitm = 0; - - for (; ly_c_pair_p (split_list_); split_list_ = ly_cdr (split_list_)) + if (any_outlet_changed) { - splitm = unsmob_moment (ly_caar (split_list_)); - if (splitm && *splitm + start_moment_ > now) - break ; - - SCM tag = ly_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 (scm_is_symbol (tag)) - { - String s = "Unknown split directive: " - + (scm_is_symbol (tag) ? ly_symbol2string (tag) : String ("not a symbol")); - programming_error (s); - } + // Kill multi-measure rests in outlets that were previously active and + // are no longer active. + for (size_t i = 0; i < NUM_PARTS; i++) + { + Context *c = prev_active_outlets[i]; + if (c && !is_active_outlet (c)) + kill_mmrest (c); + } } - - 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);