X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fsimultaneous-music-iterator.cc;h=e892776b61a39e6f4814eb350500ab706a45c4ee;hb=5d84bfad4626892bcffd05adcced53c8a2329047;hp=ad093ec93b8aab77257e7357c238df80ed3178b4;hpb=5758fa63add68276fd012fac73a240f40332a320;p=lilypond.git diff --git a/lily/simultaneous-music-iterator.cc b/lily/simultaneous-music-iterator.cc index ad093ec93b..e892776b61 100644 --- a/lily/simultaneous-music-iterator.cc +++ b/lily/simultaneous-music-iterator.cc @@ -1,25 +1,34 @@ /* - Simultaneous_music-iterator.cc -- implement Simultaneous_music_iterator + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 1997--2015 Han-Wen Nienhuys - (c) 1997--2004 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 "simultaneous-music-iterator.hh" +#include "music.hh" #include "context.hh" #include "warn.hh" -#include "simultaneous-music-iterator.hh" -#include "music-list.hh" #include "context-def.hh" - Simultaneous_music_iterator::Simultaneous_music_iterator () { create_separate_contexts_ = false; children_list_ = SCM_EOL; } - void Simultaneous_music_iterator::derived_mark () const { @@ -27,10 +36,10 @@ Simultaneous_music_iterator::derived_mark () const } void -Simultaneous_music_iterator::derived_substitute (Context *f,Context *t) +Simultaneous_music_iterator::derived_substitute (Context *f, Context *t) { for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s)) - unsmob_iterator (scm_car (s))-> substitute_outlet (f,t); + unsmob (scm_car (s))->substitute_outlet (f, t); } void @@ -41,59 +50,79 @@ Simultaneous_music_iterator::construct_children () SCM i = get_music ()->get_property ("elements"); children_list_ = SCM_EOL; - SCM * tail = &children_list_; + SCM *tail = &children_list_; for (; scm_is_pair (i); i = scm_cdr (i), j++) { - Music *mus = unsmob_music (scm_car (i)); + Music *mus = unsmob (scm_car (i)); SCM scm_iter = get_static_get_iterator (mus); - Music_iterator * mi = unsmob_iterator (scm_iter); + Music_iterator *mi = unsmob (scm_iter); /* if create_separate_contexts_ is set, create a new context with the - number number as name */ + number number as name */ - SCM name = ly_symbol2scm (get_outlet ()->context_name ().to_str0 ()); - Context * t = (j && create_separate_contexts_) - ? get_outlet ()->find_create_context (name, to_string (j), SCM_EOL) - : get_outlet (); + SCM name = ly_symbol2scm (get_outlet ()->context_name ().c_str ()); + Context *c = (j && create_separate_contexts_) + ? get_outlet ()->find_create_context (name, ::to_string (j), SCM_EOL) + : get_outlet (); - if (!t) - t = get_outlet (); + if (!c) + c = get_outlet (); - mi->init_translator (mus, t); + mi->init_context (mus, c); mi->construct_children (); - if (mi->ok ()) - { - *tail = scm_cons (scm_iter, *tail); - tail = SCM_CDRLOC (*tail); - } + if (mi->ok ()) + { + *tail = scm_cons (scm_iter, *tail); + tail = SCM_CDRLOC (*tail); + } else - mi->set_context (0); + mi->quit (); } } +// If we have some iterators with definite next moment and no of them +// remain after processing, we take the iterators with indefinite next +// moment along. That makes sure that no Lyric_combine_music_iterator +// will outstay its welcome (issue 2010). + void Simultaneous_music_iterator::process (Moment until) { - SCM *proc = &children_list_; + SCM *proc = &children_list_; + bool finite = !pending_moment ().main_part_.is_infinity (); while (scm_is_pair (*proc)) { - Music_iterator * i = unsmob_iterator (scm_car (*proc)); - if (i->run_always () - || i->pending_moment () == until) - { - i->process (until); - } + Music_iterator *i = unsmob (scm_car (*proc)); + if (i->run_always () || i->pending_moment () == until) + i->process (until); if (!i->ok ()) - { - i->quit (); - *proc = scm_cdr (*proc); - } + { + i->quit (); + *proc = scm_cdr (*proc); + } else - { - proc = SCM_CDRLOC (*proc); - } + { + proc = SCM_CDRLOC (*proc); + } + } + // If there were definite-ended iterators and all of them died, take + // the rest of the iterators along with them. They have + // likely lost their reference iterators. Basing this on the actual + // music contexts is not reliable since something like + // \new Voice = blah { + // << \context Voice = blah { c4 d } + // \addlyrics { oh no } + // >> e f + // } + // cannot wait for the death of context blah before ending the + // simultaneous iterator. + if (finite && pending_moment ().main_part_.is_infinity ()) + { + for (SCM p = children_list_; scm_is_pair (p); p = scm_cdr (p)) + unsmob (scm_car (p))->quit (); + children_list_ = SCM_EOL; } } @@ -102,29 +131,26 @@ Simultaneous_music_iterator::pending_moment () const { Moment next; next.set_infinite (1); - + for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s)) { - Music_iterator * it = unsmob_iterator (scm_car (s)); - next = next pending_moment (); + Music_iterator *it = unsmob (scm_car (s)); + next = min (next, it->pending_moment ()); } - + return next; } bool Simultaneous_music_iterator::ok () const { - bool run_always_ok = false; for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s)) { - Music_iterator * it = unsmob_iterator (scm_car (s)); - if (!it->run_always ()) - return true; - else - run_always_ok = run_always_ok || it->ok (); + Music_iterator *it = unsmob (scm_car (s)); + if (it->ok ()) + return true; } - return run_always_ok; + return false; } bool @@ -132,27 +158,18 @@ Simultaneous_music_iterator::run_always () const { for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s)) { - Music_iterator * it = unsmob_iterator (scm_car (s)); + Music_iterator *it = unsmob (scm_car (s)); if (it->run_always ()) - return true; + return true; } return false; } -Music_iterator* -Simultaneous_music_iterator::try_music_in_children (Music *m) const -{ - Music_iterator * b=0; - for (SCM s = children_list_; !b && scm_is_pair (s); s = scm_cdr (s)) - b =unsmob_iterator (scm_car (s))->try_music (m); - return b; -} - void Simultaneous_music_iterator::do_quit () { for (SCM s = children_list_; scm_is_pair (s); s = scm_cdr (s)) - unsmob_iterator (scm_car (s))->quit (); + unsmob (scm_car (s))->quit (); } IMPLEMENT_CTOR_CALLBACK (Simultaneous_music_iterator);