From: David Kastrup Date: Sun, 15 Jun 2014 23:01:57 +0000 (+0200) Subject: Issue 4056: Let \partial in mid-piece work via a finalization hook X-Git-Tag: release/2.19.12-1~10^2~2 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=37d4a68caf4bca4ed931aa884b0b3dfe17688d69;p=lilypond.git Issue 4056: Let \partial in mid-piece work via a finalization hook That allows all other processing to complete before measurePosition is adjusted. In particular, this avoids problems when multiple parallel contexts invoke \partial and/or bar checks. --- diff --git a/lily/partial-iterator.cc b/lily/partial-iterator.cc index 13223297f5..7233910209 100644 --- a/lily/partial-iterator.cc +++ b/lily/partial-iterator.cc @@ -18,6 +18,7 @@ */ #include "context.hh" +#include "global-context.hh" #include "input.hh" #include "international.hh" #include "moment.hh" @@ -28,6 +29,7 @@ class Partial_iterator : public Simple_music_iterator { public: DECLARE_SCHEME_CALLBACK (constructor, ()); + DECLARE_SCHEME_CALLBACK (finalization, (SCM, SCM)); protected: virtual void process (Moment); }; @@ -38,33 +40,41 @@ Partial_iterator::process (Moment m) if (Duration * dur = Duration::unsmob (get_music ()->get_property ("duration"))) { - // Partial_iterator is an iterator rather than an engraver, so - // the active context it is getting called in does not depend on - // which context definition the engraver might be defined. - // - // Using where_defined to find the context where measurePosition - // should be overwritten does not actually work since the - // Timing_translator does not set measurePosition when - // initializing. - - Context *timing = Context::unsmob (scm_call_2 (ly_lily_module_constant ("ly:context-find"), - get_outlet ()->self_scm (), - ly_symbol2scm ("Timing"))); - - if (!timing) - programming_error ("missing Timing in \\partial"); + Moment length = Moment (dur->get_length ()); + if (get_outlet ()->now_mom () > 0) + { + Global_context *tg = get_outlet ()->get_global_context (); + tg->add_finalization (scm_list_3 (finalization_proc, + get_outlet ()->self_scm (), + length.smobbed_copy ())); + } else { - Moment mp = robust_scm2moment (timing->get_property ("measurePosition"), - Rational (0)); + // Partial_iterator is an iterator rather than an engraver, + // so the active context it is getting called in does not + // depend on which context definition the engraver might be + // defined. + // + // Using where_defined to find the context where + // measurePosition should be overwritten does not actually + // work since the Timing_translator does not set + // measurePosition when initializing. - if (get_outlet ()->now_mom () > 0) - mp.main_part_ = measure_length (timing); + Context *timing = Context::unsmob + (scm_call_2 (ly_lily_module_constant ("ly:context-find"), + get_outlet ()->self_scm (), + ly_symbol2scm ("Timing"))); + if (!timing) + programming_error ("missing Timing in \\partial"); else - mp.main_part_ = 0; - - Moment length = Moment (dur->get_length ()); - timing->set_property ("measurePosition", (mp - length).smobbed_copy ()); + { + Moment mp = robust_scm2moment + (timing->get_property ("measurePosition"), + Rational (0)); + mp.main_part_ = 0; + timing->set_property + ("measurePosition", (mp - length).smobbed_copy ()); + } } } else @@ -74,3 +84,25 @@ Partial_iterator::process (Moment m) } IMPLEMENT_CTOR_CALLBACK (Partial_iterator); + +MAKE_SCHEME_CALLBACK (Partial_iterator, finalization, 2); +SCM +Partial_iterator::finalization (SCM ctx, SCM length) +{ + LY_ASSERT_SMOB (Context, ctx, 1); + LY_ASSERT_SMOB (Moment, length, 2); + Context *timing = Context::unsmob + (scm_call_2 (ly_lily_module_constant ("ly:context-find"), + ctx, + ly_symbol2scm ("Timing"))); + if (!timing) { + programming_error ("missing Timing in \\partial"); + return SCM_UNSPECIFIED; + } + Moment mp = robust_scm2moment (timing->get_property ("measurePosition"), + Rational (0)); + mp.main_part_ = measure_length (timing); + timing->set_property ("measurePosition", + (mp - *Moment::unsmob (length)).smobbed_copy ()); + return SCM_UNSPECIFIED; +}