lilypond-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: triggering translation from engraver


From: David Kastrup
Subject: Re: triggering translation from engraver
Date: Wed, 23 Aug 2017 18:33:15 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.50 (gnu/linux)

David Kastrup <address@hidden> writes:

> David Kastrup <address@hidden> writes:
>
>> Jan-Peter Voigt <address@hidden> writes:
>>
>>> Do you have another idea how to do that?
>>
>> Timing is established by iterators and they work on music expressions,
>> not events.  So you need to have an iterator in the race from the start.
>> Few iterators have variable length.  The sequential iterator can have an
>> elements-callback delivering music expressions.  Those can have a
>> structure and/or length determined at callback time.
>>
>> Kicking this into orderly operation does not seem like it would be
>> reasonably workable.
>>
>> Iterators are not user-definable at the moment.  Either a general
>> facility or a more specific "wait-iterator" would seem warranted.
>
> You might want to use \lyricsto to add your private control context to
> the Score context.  When switching off everything that can track
> melismata, you might get woken up once per event regardless of how long
> your actual expressions are.
>
> But it might make more sense to work on actual infrastructure for this
> rather than fudging around with existing facilities not intended for it.

As an example: I've created a \waitFor music function that does
something similar to what you want.  It was just quite useless in the
original state since it waited for a particular expression, and you
cannot use it to wait for \mark "B" when the mark has been generated
with \mark \default .

It turns out, looking at it, that the C++ code already does something
more useful, namely taking the "procedure" callback for evaluating a
triggering condition.  While the LilyPond code does not yet match the
C++ code: so I probably gave up for some reason after noticing that this
still wasn't what I could be using.

So this definitely needs fleshing out into something more useful.  But
it illustrates the kind of iterator you likely want to be using: I seem
to remember that I was able to make the original version (before fudging
the procedure callback into the C++ code) do something.

>From eda3025f4aebd5b400a40de3fe72bf4e58baf363 Mon Sep 17 00:00:00 2001
From: David Kastrup <address@hidden>
Date: Fri, 17 Jul 2015 17:23:17 +0200
Subject: [PATCH] Create a wait music function.

---
 lily/wait-iterator.cc      | 112 +++++++++++++++++++++++++++++++++++++++++++++
 ly/music-functions-init.ly |  11 +++++
 scm/define-music-types.scm |   6 +++
 3 files changed, 129 insertions(+)
 create mode 100644 lily/wait-iterator.cc

diff --git a/lily/wait-iterator.cc b/lily/wait-iterator.cc
new file mode 100644
index 0000000000..939ba34c9b
--- /dev/null
+++ b/lily/wait-iterator.cc
@@ -0,0 +1,112 @@
+/*
+  This file is part of LilyPond, the GNU music typesetter.
+
+  Copyright (C) 2016 David Kastrup <address@hidden>
+
+  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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "lily-guile.hh"
+#include "context.hh"
+#include "input.hh"
+#include "international.hh"
+#include "moment.hh"
+#include "music.hh"
+#include "music-iterator.hh"
+
+class Wait_iterator : public Music_wrapper_iterator
+{
+  bool triggered_;
+  SCM procedure_;
+protected:
+  virtual void derived_mark () const;
+  virtual Moment pending_moment () const;
+  virtual void process (Moment);
+  virtual bool ok () const;
+  virtual bool run_always () const;
+public:
+  Wait_iterator ();
+  DECLARE_SCHEME_CALLBACK (constructor, ());
+  virtual void construct_children ();
+};
+
+Wait_iterator::Wait_iterator ()
+  : triggered_ (false), procedure_ (SCM_UNDEFINED)
+{
+}
+
+void
+Wait_iterator::derived_mark () const
+{
+  scm_gc_mark (procedure_);
+}
+
+Moment
+Wait_iterator::pending_moment () const
+{
+  if (triggered_)
+    return Moment (0);
+  Moment m;
+  m.set_infinite (1);
+  return m;
+}
+
+bool
+Wait_iterator::run_always () const
+{
+  return triggered
+    || !Music_wrapper_iterator::ok ()
+    || Music_wrapper_iterator::run_always ();
+}
+  
+void
+Wait_iterator::process (Moment m)
+{
+  if (triggered_)
+    return;
+  if (scm_is_true (scm_call_1 (procedure_, get_outlet ()->self_scm ())))
+    {
+      triggered_ = true;
+      return;
+    }
+  if (!Music_wrapper_iterator::ok ())
+    {
+      Music_wrapper_iterator::construct_children ();
+      if (!Music_wrapper_iterator::ok ())
+        return;
+    }
+  Music_wrapper_iterator::process (m);
+}
+
+bool
+Wait_iterator::ok () const
+{
+  return !triggered_;
+}
+
+void
+Wait_iterator::construct_children ()
+{
+  procedure_ = get_music ()->get_property ("procedure");
+  if (!ly_is_procedure (procedure_))
+    {
+      get_music ()->origin ()->warning (_ ("Bad procedure"));
+      triggered_ = true;
+      return;
+    }
+
+  Music_iterator::construct_children ();
+}
+
+IMPLEMENT_CTOR_CALLBACK (Wait_iterator)
diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly
index d41da5b5b6..e87196957b 100644
--- a/ly/music-functions-init.ly
+++ b/ly/music-functions-init.ly
@@ -2014,6 +2014,17 @@ void =
 Use this if you want to have a scheme expression evaluated
 because of its side-effects, but its value ignored."))
 
+waitFor =
+#(define-music-function (music) (ly:music?)
+   (_i "Wait for the occurence of the given @var{music} in the
+current context.  Use it, for example, as
address@hidden
+\\context Score \\waitFor \\mark "A"
address@hidden example
+")
+   (make-music 'WaitMusic
+               'element music))
+
 withMusicProperty =
 #(define-music-function (sym val music)
    (symbol? scheme? ly:music?)
diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm
index 348bcd0e87..61689a3701 100644
--- a/scm/define-music-types.scm
+++ b/scm/define-music-types.scm
@@ -753,6 +753,12 @@ Syntax: @code{\\\\}")
         (length-callback . ,ly:repeated-music::volta-music-length)
         (types . (repeated-music volta-repeated-music))
         ))
+
+    (WaitMusic
+     . ((description . "Waits for the given event.")
+        (iterator-ctor . ,ly:wait-iterator::constructor)
+        (types . (wait-music))
+        ))
     ))
 
 (set! music-descriptions
-- 
2.11.0

-- 
David Kastrup

reply via email to

[Prev in Thread] Current Thread [Next in Thread]