X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fgrace-engraver.cc;h=4249a922a4addc0988973c757bf72d9d144048d7;hb=47db9a3883d726ca53e2133a3b2298f78dd6a32e;hp=5afe21e00275561886650dc9ae91e36cbb02d96e;hpb=7d737869f67f101dcc2c602a0fcccdfb7d0bd4a4;p=lilypond.git diff --git a/lily/grace-engraver.cc b/lily/grace-engraver.cc index 5afe21e002..4249a922a4 100644 --- a/lily/grace-engraver.cc +++ b/lily/grace-engraver.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2004--2014 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 @@ -19,21 +19,26 @@ #include "engraver.hh" #include "context.hh" +#include "dispatcher.hh" +#include "listener.hh" #include "warn.hh" #include "grob-properties.hh" +#include "stream-event.hh" +#include "translator.icc" class Grace_engraver : public Engraver { + Moment last_moment_; + SCM grace_settings_; void consider_change_grace_settings (); protected: - void start_translation_timestep (); virtual void derived_mark () const; - virtual void initialize (); + virtual void process_music (); + virtual void start_translation_timestep (); + virtual void finalize (); TRANSLATOR_DECLARATIONS (Grace_engraver); - Moment last_moment_; - SCM grace_settings_; -public: + DECLARE_LISTENER (grace_change); }; Grace_engraver::Grace_engraver () @@ -42,17 +47,52 @@ Grace_engraver::Grace_engraver () last_moment_ = Moment (Rational (-1, 1)); } +// The iterator should usually come before process_music +IMPLEMENT_LISTENER (Grace_engraver, grace_change); void -Grace_engraver::initialize () +Grace_engraver::grace_change (SCM) { consider_change_grace_settings (); } +// if we are in grace time already on initialization, it is unlikely +// that we'll receive a GraceChange event from the grace iterator yet, +// so we want to start into grace mode anyway. The downside is that +// this will get us confused when given something like +// +// \new Voice { \oneVoice \grace { c''8 8 } g'1 } +// +// where \grace executes its actions already before \oneVoice, causing +// different stem directions. + +void +Grace_engraver::start_translation_timestep () +{ + // Only on startup + if (last_moment_ == Rational (-1)) + consider_change_grace_settings (); +} + +// If the grace iterator has moved off to some other context, we might +// not get to see the ChangeContext event. In that case, we still +// want to change into or out of grace mode settings as appropriate + +void +Grace_engraver::process_music () +{ + // We may have lost connection to the iterator in which case we + // still need to call consider_change_grace_settings in particular + // in order to get out of grace mode again + if (last_moment_ != now_mom ()) + consider_change_grace_settings (); +} + void Grace_engraver::consider_change_grace_settings () { Moment now = now_mom (); - if (last_moment_.grace_part_ && !now.grace_part_) + + if (!now.grace_part_) { for (SCM s = grace_settings_; scm_is_pair (s); s = scm_cdr (s)) { @@ -63,10 +103,9 @@ Grace_engraver::consider_change_grace_settings () Grob_property_info (Context::unsmob (context), grob).matched_pop (cell); } - grace_settings_ = SCM_EOL; } - else if (!last_moment_.grace_part_ && now.grace_part_) + else if (!last_moment_.grace_part_) { SCM settings = get_property ("graceSettings"); @@ -97,25 +136,31 @@ Grace_engraver::consider_change_grace_settings () + ly_symbol2string (context_name)); } } - - last_moment_ = now_mom (); + if (last_moment_ == Rational (-1)) + { + Dispatcher *d = context ()->event_source (); + d->add_listener (GET_LISTENER (grace_change), ly_symbol2scm ("GraceChange")); + } + last_moment_ = now; } void -Grace_engraver::derived_mark () const +Grace_engraver::finalize () { - scm_gc_mark (grace_settings_); - Engraver::derived_mark (); + if (last_moment_ != Rational (-1)) + { + Dispatcher *d = context ()->event_source (); + d->remove_listener (GET_LISTENER (grace_change), ly_symbol2scm ("GraceChange")); + } } void -Grace_engraver::start_translation_timestep () +Grace_engraver::derived_mark () const { - consider_change_grace_settings (); + scm_gc_mark (grace_settings_); + Engraver::derived_mark (); } -#include "translator.icc" - ADD_TRANSLATOR (Grace_engraver, /* doc */ "Set font size and other properties for grace notes.",