lilypond-user
[Top][All Lists]
Advanced

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

Re: Automatically identify beats


From: Thomas Morley
Subject: Re: Automatically identify beats
Date: Mon, 8 Oct 2018 23:16:43 +0200

Am So., 7. Okt. 2018 um 22:28 Uhr schrieb David Kastrup <address@hidden>:
>
> Thomas Morley <address@hidden> writes:
>
> > Am So., 7. Okt. 2018 um 18:00 Uhr schrieb David Kastrup <address@hidden>:
> >>
> >> Thomas Morley <address@hidden> writes:
> >>
> >> > If you have too much time, you may have a look at ‘scheme-engraver.ly’
> >> > from
> >> > http://lilypond.org/doc/v2.13/input/regression/collated-files.html The
> >> > newer file uses the great 'make-engraver'-macro (by David Kastrup).
> >> > Otoh, this macro hides an engraver _is_ a list (which is obvious, if
> >> > you look in the older file).
> >>
> >> An engraver is not a list, just like it isn't a string like
> >> "Note_engraver".  That's just how you _specify_ an engraver.  If it's a
> >> list, the Scheme_engraver type will be used for actually instantiating
> >> an engraver (which is bound to a particular context), initialized using
> >> the list contents.
> >
> > Hi David,
> >
> > I don't understand the subtleties.
> > Could you elaborate a bit using the examples below.
> >
> > testI =
> >   #(list
> >     (cons 'initialize
> >      (lambda (trans)
> >        (write trans))))
> >
> > testII =
> >   #(lambda (ctx) testI)
> >
> > \layout {
> >   \context {
> >     \Voice
> >     \consists #testI
> >     \consists #testII
> >   }
> > }
> >
> > { R1 }
> >
> > testI is a list, testII a procedure using testI.
> > Both return #<Translator Scheme_engraver >, though.
>
> They don't "return" the Translator but rather cause it to be created
> when specified after \consists , like a Notehead_engraver instance is
> created when specifying the string "Notehead_engraver".
>
> Basically there is the _specification_, \consists looks up (or in your
> example creates) a suitable translator creator given a specification.
> This translator creator is called with a suitable context to actually
> create a translator instance when a context is instantiated, and that
> creator instance is what you see listed rather unspecifically as
> #<Translator Scheme_engraver > or #<Engraver Notehead_engraver> or
> whatever else (to get to see those, create a suitable Scheme engraver
> and look at the "source-engraver" argument of one of your grob
> acknowledgers).
>
> One of the more problematic bits in history was making a
> \consists/\removes pair work for ad-hoc defined engravers (rather than
> those registered under a name) since at the time of the \removes call,
> the translator creator did not carry information about its originating
> expression (particularly so if its list expression was the result of
> calling a lambda function) and creating a fresh translator creator from
> the same expression led to a different translator creator unsuitable for
> looking up the preexisting translator creator.
>
> --
> David Kastrup

Hi David,

thanks a lot for your explanations.

I try to repeat/summarize in my own words:

Defining some code like #(define my-code ...) will not create a
translator, before \consists has done its work in some context.

But with (for example)
\layout {
  \context {
    \Voice
    \consists #my-code
  }
}
an unnamed and unregistered translator is created. Assumed 'my-code'
is suitable, ofcourse.

Below some musing.
Don't read unless you're very interested ;)

So the two codings below will not create any engraver.

testI =
  #(list
    (cons 'initialize
      (lambda (engraver)
        (newline)
        (pretty-print (list 'from-initialize: (cons 'engraver engraver)))))
    (cons 'acknowledgers
      (list
        (cons 'note-head-interface
          (lambda (engraver grob source-engraver)
            (pretty-print
              (list
                'from-acknowledgers:
                (cons 'engraver engraver)
                (cons 'source-engraver source-engraver))))))))

testII =
  #(lambda (ctx) testI)


But as soon as I do:
\layout {
  \context {
    \Voice
    \consists #testI
    \consists #testII
  }
}

Two translators are created.
Which can be checked with some code you once tailored for me
http://lilypond.1069038.n5.nabble.com/catching-layout-content-tc213339.html
Ofcourse adjusted to fit here, thanks again for it.

#(define all-Voice-translators
  (assoc
    'Voice
    (map
      (lambda (x)
        (if (ly:context-def? (cdr x))
            (cons (car x) (ly:context-def-lookup (cdr x) 'consists))
            x))
      (sort
        (ly:module->alist (ly:output-def-scope $defaultlayout))
        (lambda (p q) (symbol<? (car p) (car q)))))))
#(newline)
#(format #t "\nAll Voice-translator:\n~y"
  (cdr all-Voice-translators))

Though:
#(pretty-print (ly:get-all-translators))
doesn't show them.

Is this expected?

%%%%%
%%%%%

Things are different for registered translators:
#(ly:register-translator
 testI 'testI
 '((grobs-created . ())
   (events-accepted . ())
   (properties-read . ())
   (properties-written . ())
   (description . "")))

#(ly:register-translator
 testII 'testII
 '((grobs-created . ())
   (events-accepted . ())
   (properties-read . ())
   (properties-written . ())
   (description . "")))

Now (ly:get-all-translators) sees them as:
testII:
 #<procedure #f (ctx)>
testI:
 ((initialize . #<procedure #f (engraver)>)
  (acknowledgers
    (note-head-interface
      .
      #<procedure #f (engraver grob source-engraver)>)))

Their names can be found with
#(format #t "\nAll translator-names:\n~y"
  (sort
    (map ly:translator-name (ly:get-all-translators))
    symbol<?))

So _registering_ them makes testI/II translators, \consists may look them up.


Many thanks,
  Harm



reply via email to

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