|
From: | Urs Liska |
Subject: | Re: Passing \tweak-s to engravers |
Date: | Thu, 14 Jun 2018 15:01:59 +0200 |
User-agent: | Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0 |
Am 14.06.2018 um 13:32 schrieb David
Kastrup:
Urs Liska <address@hidden> writes:I have been banging my head against the wall for quite some time now, but finally I'm at least at a point where I can ask a question here. I am programmatically attaching a custom grob property to some music and want to later act upon that in an engraver."later" is the key. To do something "later" than something else, that something else has to happen _earlier_. That makes sense, but I didn't have a chance to realize this was an issue. I am exclusively working in a music-function, which is of course way earlier than an engraver's acknowledger. When I tried to switch the attachment process from \once \override to \tweak the engraver suddenly didn't recognize the property anymore.It did. _After_ you looked. OK, now I see that. First I thought I got it wrong with where the property was attached in the music _expression_, but now I've realized the following behaviour: When an engraver is consisted to a Voice or Staff or similar context only properties created through overrides are visible to the acknowledger while tweaks seem to be hidden. However, if I consist the engraver to Score also tweaks are recognized. The following MWE shows this behaviour with a common grob property, but it's the same with my custom grob property. For my use case in scholarLY it's neither an option to switch back to \once \override (because also \tweak-able post-events have to be supported) nor to consist the engraver to Score (because I need to know from which context the annotations come). So what do I have to do to make a Voice/Staff-consisted engraver aware of \tweak-s and not only of \override-s? And why is that behaviour as it is? %%% \version "2.19.80" testEngr = #(lambda (context) (make-engraver (acknowledgers ((note-head-interface engraver grob source-engraver) (ly:message "Notehead color: ~a" (ly:grob-property grob 'color)) )))) \layout { \context { % uncomment *one* of the following two lines \Staff %\Score \consists #testEngr } } \relative { \once \override NoteHead.color = #red c' \tweak color #red c' } %%%>From the Engraver tutorial in the Contributor's Guide (Acknowledging grobs): Acknowledge functions are called in the order engravers are ‘\consist’-ed (the only exception is if you set ‘must-be-last’ to ‘#t’). There will always be a call to ‘process-acknowledged ()’ whenever grobs have been created, and _reading_ stuff from grobs should be delayed until then since other acknowledgers might _write_ stuff into a grob even after your acknowledger has been called. So the basic workflow is to use the various acknowledgers to _record_ the grobs you are interested in and _write_ stuff into them (or do read/write stuff that more or less is accumulative and/or really unrelated to other engravers), and then use the ‘process-acknowledged ()’ hook for processing (including _reading_) the grobs you had recorded. You can create new grobs in ‘process-acknowledged ()’. That will lead to a new cycle of ‘acknowledger ()’ calls followed by a new cycle of ‘process-acknowledged ()’ calls. Note that tweaks are applied by the acknowledger in the Tweak_engraver. OK, this seems to be the culprit. Do I get this right that the tweaks are applied to a grob only *after* my grob acknowledger sees the grob? Then it is relevant that ... I repeat my advice to read the Engraver tutorial. Really. In this case, the central paragraph I quoted is very, very relevant. ... I did read that but it didn't help me. Nowhere did *I* write into grobs or even created new ones, so I couldn't actually know these paragraphs are relevant to my case. This is just another point for the case I'm often making that much of our documentation on that level is too complicated insofar as you're only getting to the point of understanding it when you don't really need it anymore. However, I've now changed the example to record the note-heads (as per an example in scm/music-functions.scm): \version "2.19.80" testEngr = #(lambda (context) (let ((note-heads '())) (make-engraver (acknowledgers ((note-head-interface engraver grob source-engraver) (set! note-heads (cons grob note-heads)) )) ((process-acknowledged translator) (for-each (lambda (nh) (ly:message "NoteHead color: ~a" (ly:grob-property nh 'color))) note-heads)) ))) \layout { \context { % uncomment *one* of the following two lines \Voice %\Staff %\Score \consists #testEngr } } \relative { %\once \override NoteHead.color = #red c' \tweak color #blue c' } => Interpreting music... NoteHead color: () NoteHead color: () NoteHead color: (0.0 0.0 1.0) NoteHead color: (0.0 0.0 1.0)This shows that process-acknowledged is called four times and the color information is only available at a certain time. Depending on where the engraver is consistet this "certain time" differs. I get better and reliable results when looking for the property in (stop-translation-timestep), which should be OK since I'm not in any way dealing with the grobs themselves at that point. I'll fetch the data from the custom property, need to determine the ly:moment and then store the information away in some Scheme variables (for use in finalize). However, since this will acknowledge grob-interface this means that I'll have to record and process *all* grobs in my score then? In the earlier approach (with \once \override) I could just check for the presence of the custom property and simply skip any grob that doesn't have one. Still surprsising all this ... Best Urs |
[Prev in Thread] | Current Thread | [Next in Thread] |