X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fpart-combine-iterator.cc;h=4d1baec7568b3d24939dac9c7bdac59b5467ad00;hb=3740ac23c9e222602cec4ddc6c38b58504f17673;hp=8841fb826b82c83064b2670eca674f87b19ff174;hpb=f9214bac21e9926dc3248416f58190c98c4167a9;p=lilypond.git diff --git a/lily/part-combine-iterator.cc b/lily/part-combine-iterator.cc index 8841fb826b..4d1baec756 100644 --- a/lily/part-combine-iterator.cc +++ b/lily/part-combine-iterator.cc @@ -1,9 +1,20 @@ /* - 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 + Copyright (C) 2004--2015 Han-Wen Nienhuys - (c) 2004--2007 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" @@ -14,15 +25,15 @@ #include "music-sequence.hh" #include "warn.hh" -typedef enum Outlet_type - { - CONTEXT_ONE, CONTEXT_TWO, - CONTEXT_SHARED, CONTEXT_SOLO, - CONTEXT_NULL, NUM_OUTLETS - }; +enum Outlet_type +{ + CONTEXT_ONE, CONTEXT_TWO, + CONTEXT_SHARED, CONTEXT_SOLO, + CONTEXT_NULL, NUM_OUTLETS +}; -static const char *outlet_names_[NUM_OUTLETS] = - {"one", "two", "shared", "solo", "null"}; +static const char *outlet_names_[NUM_OUTLETS] + = {"one", "two", "shared", "solo", "null"}; class Part_combine_iterator : public Music_iterator { @@ -46,44 +57,52 @@ private: DECLARE_LISTENER (set_busy); bool busy_; bool notice_busy_; - + bool try_process (Music_iterator *i, Moment m); - + Music_iterator *first_iter_; Music_iterator *second_iter_; Moment start_moment_; SCM split_list_; - Stream_event *unisono_event_; + Stream_event *unisono_event_; Stream_event *solo_one_event_; Stream_event *solo_two_event_; - Stream_event *mmrest_event_; - + Stream_event *mmrest_event_; + enum Status - { - APART, - TOGETHER, - SOLO1, - SOLO2, - UNISONO, - UNISILENCE, - }; + { + APART, + TOGETHER, + SOLO, + UNISONO, + UNISILENCE, + }; Status state_; - Status playing_state_; - /* - Should be SOLO1 or SOLO2 - */ - Status last_playing_; + // For states in which it matters, this is the relevant part, + // e.g. 1 for Solo I, 2 for Solo II. + int chosen_part_; + + // States for generating partcombine text. + enum PlayingState + { + PLAYING_OTHER, + PLAYING_UNISONO, + PLAYING_SOLO1, + PLAYING_SOLO2, + } playing_state_; + + int last_playing_; /* - TODO: this is getting of hand... + TODO: this is getting off hand... */ Context_handle handles_[NUM_OUTLETS]; void substitute_both (Outlet_type to1, - Outlet_type to2); + Outlet_type to2); /* parameter is really Outlet_type */ void kill_mmrest (int in); @@ -91,7 +110,7 @@ private: void solo1 (); void solo2 (); void apart (bool silent); - void unisono (bool silent); + void unisono (bool silent, int newpart); }; void @@ -105,9 +124,9 @@ Part_combine_iterator::do_quit () // Add listeners to all contexts except Devnull. for (int i = 0; i < NUM_OUTLETS; i++) { - Context *c = handles_[i].get_outlet (); + Context *c = handles_[i].get_context (); if (c->is_alias (ly_symbol2scm ("Voice"))) - c->event_source ()->remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("music-event")); + c->event_source ()->remove_listener (GET_LISTENER (set_busy), ly_symbol2scm ("music-event")); handles_[i].set_context (0); } } @@ -117,13 +136,18 @@ Part_combine_iterator::Part_combine_iterator () mmrest_event_ = 0; unisono_event_ = 0; solo_two_event_ = 0; - solo_one_event_= 0; + solo_one_event_ = 0; first_iter_ = 0; second_iter_ = 0; split_list_ = SCM_EOL; state_ = APART; - playing_state_ = APART; + chosen_part_ = 1; + playing_state_ = PLAYING_OTHER; + last_playing_ = 0; + + busy_ = false; + notice_busy_ = false; } void @@ -133,22 +157,19 @@ Part_combine_iterator::derived_mark () const scm_gc_mark (first_iter_->self_scm ()); if (second_iter_) scm_gc_mark (second_iter_->self_scm ()); - - Stream_event *ptrs[] = { - unisono_event_, - mmrest_event_, - solo_two_event_, - solo_one_event_, - 0 - }; - for (int i = 0; ptrs[i]; i++) - if (ptrs[i]) - scm_gc_mark (ptrs[i]->self_scm ()); + if (unisono_event_) + scm_gc_mark (unisono_event_->self_scm ()); + if (mmrest_event_) + scm_gc_mark (mmrest_event_->self_scm ()); + if (solo_one_event_) + scm_gc_mark (solo_one_event_->self_scm ()); + if (solo_two_event_) + scm_gc_mark (solo_two_event_->self_scm ()); } void Part_combine_iterator::derived_substitute (Context *f, - Context *t) + Context *t) { if (first_iter_) first_iter_->substitute_outlet (f, t); @@ -174,144 +195,147 @@ Part_combine_iterator::ok () const } void -Part_combine_iterator::chords_together () +Part_combine_iterator::substitute_both (Outlet_type to1, + Outlet_type to2) { - if (state_ == TOGETHER) - return; - else + Outlet_type tos[] = {to1, to2}; + + Music_iterator *mis[] = {first_iter_, second_iter_}; + + for (int i = 0; i < 2; i++) { - playing_state_ = TOGETHER; - state_ = TOGETHER; + for (int j = 0; j < NUM_OUTLETS; j++) + if (j != tos[i]) + mis[i]->substitute_outlet (handles_[j].get_context (), handles_[tos[i]].get_context ()); + } - substitute_both (CONTEXT_SHARED, CONTEXT_SHARED); + for (int j = 0; j < NUM_OUTLETS; j++) + { + if (j != to1 && j != to2) + kill_mmrest (j); } } void Part_combine_iterator::kill_mmrest (int in) { - + if (!mmrest_event_) { - mmrest_event_ = new Stream_event (ly_symbol2scm ("multi-measure-rest-event")); + mmrest_event_ = new Stream_event + (scm_call_1 (ly_lily_module_constant ("ly:make-event-class"), + ly_symbol2scm ("multi-measure-rest-event"))); mmrest_event_->set_property ("duration", SCM_EOL); mmrest_event_->unprotect (); } - handles_[in].get_outlet ()->event_source ()->broadcast (mmrest_event_); + handles_[in].get_context ()->event_source ()->broadcast (mmrest_event_); } void -Part_combine_iterator::solo1 () +Part_combine_iterator::unisono (bool silent, int newpart) { - if (state_ == SOLO1) + Status newstate = (silent) ? UNISILENCE : UNISONO; + + if ((newstate == state_) and (newpart == chosen_part_)) return; else { - state_ = SOLO1; - substitute_both (CONTEXT_SOLO, CONTEXT_NULL); - - kill_mmrest (CONTEXT_TWO); + Outlet_type c1 = (newpart == 2) ? CONTEXT_NULL : CONTEXT_SHARED; + Outlet_type c2 = (newpart == 2) ? CONTEXT_SHARED : CONTEXT_NULL; + substitute_both (c1, c2); + kill_mmrest ((newpart == 2) ? CONTEXT_ONE : CONTEXT_TWO); kill_mmrest (CONTEXT_SHARED); - if (playing_state_ != SOLO1) - { - if (!solo_one_event_) - { - solo_one_event_ = new Stream_event (ly_symbol2scm ("solo-one-event")); - solo_one_event_->unprotect (); - } - - first_iter_->get_outlet ()->event_source ()->broadcast (solo_one_event_); - } - playing_state_ = SOLO1; + if (playing_state_ != PLAYING_UNISONO + && newstate == UNISONO) + { + if (!unisono_event_) + { + unisono_event_ = new Stream_event + (scm_call_1 (ly_lily_module_constant ("ly:make-event-class"), + ly_symbol2scm ("unisono-event"))); + unisono_event_->unprotect (); + } + + Context *out = (newpart == 2 ? second_iter_ : first_iter_) + ->get_outlet (); + out->event_source ()->broadcast (unisono_event_); + playing_state_ = PLAYING_UNISONO; + } + state_ = newstate; + chosen_part_ = newpart; } } void -Part_combine_iterator::substitute_both (Outlet_type to1, - Outlet_type to2) +Part_combine_iterator::solo1 () { - Outlet_type tos[] = {to1, to2}; - - Music_iterator *mis[] = {first_iter_, second_iter_}; - - for (int i = 0; i < 2; i++) + if ((state_ == SOLO) && (chosen_part_ == 1)) + return; + else { - for (int j = 0; j < NUM_OUTLETS; j++) - if (j != tos[i]) - mis[i]->substitute_outlet (handles_[j].get_outlet (), handles_[tos[i]].get_outlet ()); - } + state_ = SOLO; + chosen_part_ = 1; + substitute_both (CONTEXT_SOLO, CONTEXT_NULL); - for (int j = 0; j < NUM_OUTLETS; j++) - { - if (j != to1 && j != to2) - kill_mmrest (j); + kill_mmrest (CONTEXT_TWO); + kill_mmrest (CONTEXT_SHARED); + + if (playing_state_ != PLAYING_SOLO1) + { + if (!solo_one_event_) + { + solo_one_event_ = new Stream_event + (scm_call_1 (ly_lily_module_constant ("ly:make-event-class"), + ly_symbol2scm ("solo-one-event"))); + solo_one_event_->unprotect (); + } + + first_iter_->get_outlet ()->event_source ()->broadcast (solo_one_event_); + } + playing_state_ = PLAYING_SOLO1; } } void -Part_combine_iterator::unisono (bool silent) +Part_combine_iterator::solo2 () { - Status newstate = (silent) ? UNISILENCE : UNISONO; - - if (newstate == state_) + if ((state_ == SOLO) and (chosen_part_ == 2)) 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. - */ - Outlet_type c1 = (last_playing_ == SOLO2) ? CONTEXT_NULL : CONTEXT_SHARED; - Outlet_type c2 = (last_playing_ == SOLO2) ? CONTEXT_SHARED : CONTEXT_NULL; - substitute_both (c1, c2); - kill_mmrest ((last_playing_ == SOLO2) - ? CONTEXT_ONE : CONTEXT_TWO); - kill_mmrest (CONTEXT_SHARED); + state_ = SOLO; + chosen_part_ = 2; + substitute_both (CONTEXT_NULL, CONTEXT_SOLO); - if (playing_state_ != UNISONO - && newstate == UNISONO) - { - if (!unisono_event_) - { - unisono_event_ = new Stream_event (ly_symbol2scm ("unisono-event")); - unisono_event_->unprotect (); - } - - - Context *out = (last_playing_ == SOLO2 ? second_iter_ : first_iter_) - ->get_outlet (); - out->event_source ()->broadcast (unisono_event_); - playing_state_ = UNISONO; - } - state_ = newstate; + if (playing_state_ != PLAYING_SOLO2) + { + if (!solo_two_event_) + { + solo_two_event_ = new Stream_event + (scm_call_1 (ly_lily_module_constant ("ly:make-event-class"), + ly_symbol2scm ("solo-two-event"))); + solo_two_event_->unprotect (); + } + + second_iter_->get_outlet ()->event_source ()->broadcast (solo_two_event_); + playing_state_ = PLAYING_SOLO2; + } } } void -Part_combine_iterator::solo2 () +Part_combine_iterator::chords_together () { - if (state_ == SOLO2) + if (state_ == TOGETHER) return; else { - state_ = SOLO2; - - substitute_both (CONTEXT_NULL, CONTEXT_SOLO); + playing_state_ = PLAYING_OTHER; + state_ = TOGETHER; - if (playing_state_ != SOLO2) - { - if (!solo_two_event_) - { - solo_two_event_ = new Stream_event (ly_symbol2scm ("solo-two-event")); - solo_two_event_->unprotect (); - } - - second_iter_->get_outlet ()->event_source ()->broadcast (solo_two_event_); - playing_state_ = SOLO2; - } + substitute_both (CONTEXT_SHARED, CONTEXT_SHARED); } } @@ -319,7 +343,7 @@ void Part_combine_iterator::apart (bool silent) { if (!silent) - playing_state_ = APART; + playing_state_ = PLAYING_OTHER; if (state_ == APART) return; @@ -345,39 +369,18 @@ Part_combine_iterator::construct_children () c = c->find_create_context (type, outlet_names_[i], SCM_EOL); handles_[i].set_context (c); if (c->is_alias (ly_symbol2scm ("Voice"))) - c->event_source ()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("music-event")); + c->event_source ()->add_listener (GET_LISTENER (set_busy), ly_symbol2scm ("music-event")); } SCM lst = get_music ()->get_property ("elements"); - Context *one = handles_[CONTEXT_ONE].get_outlet (); + Context *one = handles_[CONTEXT_ONE].get_context (); set_context (one); - first_iter_ = unsmob_iterator (get_iterator (unsmob_music (scm_car (lst)))); - Context *two = handles_[CONTEXT_TWO].get_outlet (); + first_iter_ = Music_iterator::unsmob (get_iterator (Music::unsmob (scm_car (lst)))); + Context *two = handles_[CONTEXT_TWO].get_context (); set_context (two); - second_iter_ = unsmob_iterator (get_iterator (unsmob_music (scm_cadr (lst)))); - - 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_from_int (1)); - - execute_pushpop_property (two, sym, - ly_symbol2scm ("direction"), scm_from_int (-1)); - } + second_iter_ = Music_iterator::unsmob (get_iterator (Music::unsmob (scm_cadr (lst)))); + Context *shared = handles_[CONTEXT_SHARED].get_context (); + set_context (shared); } IMPLEMENT_LISTENER (Part_combine_iterator, set_busy); @@ -387,7 +390,7 @@ Part_combine_iterator::set_busy (SCM se) if (!notice_busy_) return; - Stream_event *e = unsmob_stream_event (se); + Stream_event *e = Stream_event::unsmob (se); if (e->in_event_class ("note-event") || e->in_event_class ("cluster-note-event")) busy_ = true; @@ -404,7 +407,7 @@ Part_combine_iterator::try_process (Music_iterator *i, Moment m) notice_busy_ = true; i->process (m); - + notice_busy_ = false; return busy_; } @@ -422,44 +425,55 @@ Part_combine_iterator::process (Moment m) for (; scm_is_pair (split_list_); split_list_ = scm_cdr (split_list_)) { - splitm = unsmob_moment (scm_caar (split_list_)); + splitm = Moment::unsmob (scm_caar (split_list_)); if (splitm && *splitm + start_moment_ > now) - break; + break; SCM tag = scm_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 (); + if (scm_is_eq (tag, ly_symbol2scm ("chords"))) + chords_together (); + else if (scm_is_eq (tag, ly_symbol2scm ("apart")) + || scm_is_eq (tag, ly_symbol2scm ("apart-silence")) + || scm_is_eq (tag, ly_symbol2scm ("apart-spanner"))) + apart (scm_is_eq (tag, ly_symbol2scm ("apart-silence"))); + else if (scm_is_eq (tag, ly_symbol2scm ("unisono"))) + { + // Continue to use the most recently used part because we might have + // killed mmrests in the other part. + unisono (false, (last_playing_ == 2) ? 2 : 1); + } + else if (scm_is_eq (tag, ly_symbol2scm ("unisilence"))) + { + // as for unisono + unisono (true, (last_playing_ == 2) ? 2 : 1); + } + else if (scm_is_eq (tag, ly_symbol2scm ("silence1"))) + unisono (true, 1); + else if (scm_is_eq (tag, ly_symbol2scm ("silence2"))) + unisono (true, 2); + else if (scm_is_eq (tag, ly_symbol2scm ("solo1"))) + solo1 (); + else if (scm_is_eq (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); - } + { + string s = "Unknown split directive: " + + (scm_is_symbol (tag) ? ly_symbol2string (tag) : string ("not a symbol")); + programming_error (s); + } } if (first_iter_->ok ()) { if (try_process (first_iter_, m)) - last_playing_ = SOLO1; + last_playing_ = 1; } if (second_iter_->ok ()) { if (try_process (second_iter_, m)) - last_playing_ = SOLO2; + last_playing_ = 2; } }