lilypond-user
[Top][All Lists]
Advanced

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

Re: vertical shift of trill


From: Jean Abou Samra
Subject: Re: vertical shift of trill
Date: Sat, 6 Aug 2022 20:58:27 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.12.0

Le 06/08/2022 à 20:24, Thomas Morley a écrit :
Am Sa., 6. Aug. 2022 um 17:15 Uhr schrieb Jean Abou Samra <jean@abou-samra.fr>:
Le 06/08/2022 à 16:45, Werner LEMBERG a écrit :
That said, there's a much simpler way.  [...]
Your solution is ingenious.  However, how on earth are we mere mortals
able to find that?

Read the source, Luke :-)
roflmao



Well, reading the source is what I do at any rate.
That doesn't mean I'm happy that you need to read
the source to learn how to extend LilyPond -- and that
is the primary reason why I wrote
https://extending-lilypond.readthedocs.io
so reading the source is no longer necessary before you reach
a level far higher than before -- but as a matter of fact,
I think it's fair to say that many things are not currently
accessible without reading the source.

I'm able to understand C++ reasonably, so I can't comment
on what is accessible or not by reading the Scheme parts
of the source only.



Seriously, there is no way around that in this case -- as in many cases
when it comes to Scheme coding, because the task is essentially to meddle
with LilyPond internals.

Obviously, I don't claim that this is something every user is supposed to
be able to do.
Some remarks:
(1) `meta'
     \override TrillSpanner.meta.object-callbacks.side-support-elements = ...
I'd never thought overriding `meta' is possible at all.
Afaict, there is no example anywhere.



Nothing prevents it. The only quirk is that modifications you
make this way may not work in a \tweak, because whereas \override
sets the properties that the object gets at the point of its
creation, \tweak modifies properties after the object has been
created. object-callbacks, for example, is read at grob creation
time, so modifying it afterwards has no effect.



Overriding other meta-subproperties like `class'may result in
surprises, not tested, though.

(2) `object-callbacks'
Some years ago I tried to manipulate `object-callbacks' for a certain
use case. I don't remember exactly, apart from: It was a fiasko.
I never tried this again...

Furthermore:
$ git grep object-callbacks
lily/grob.cc:      SCM object_cbs = scm_assq (ly_symbol2scm
("object-callbacks"), meta);
lily/note-column.cc:  via object-callbacks. --JeanAS
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((normal-stems . ,ly:beam::calc-normal-stems)))
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((footnotes-before-line-breaking .
,ly:system::footnotes-before-line-breaking)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
scm/define-grobs.scm:                 (object-callbacks . ((Y-common .
,ly:axis-group-interface::calc-y-common)
scm/define-grobs.scm:                 (object-callbacks . (
scm/define-grobs.scm:                 (object-callbacks .
((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)

Above seems like object-callbacks is close to always related to
unpure/pure thingies.
As a user one would have to be very bold to use it for something
different relying on the few exceptions.
And cc-code is locked from the user.


object-callbacks is much simpler than how you seem to view it.
You surely know that you can do

  \override Stem.thickness = #2

but also

  \override Stem.thickness = #(lambda (grob) ...)

and in the latter case, the procedure (called a "callback")
allows to compute the property on the first time it is
looked up. With "grob object properties", it's the same,
you can do

(ly:grob-set-object!
 my-grob
 'property
 another-grob)

or

(ly:grob-set-object!
 my-grob
 'property
 (lambda (my-grob-will-be-passed-for-this-parameter)
   ...))


There is no interface for setting "grob object properties" in a
way similar to \override because plain LilyPond (non-Scheme) code
doesn't manipulate grobs directly -- if you were to do
\overrideObject NoteHead.stem = ..., how would you get the stem
grob? You have to be in an engraver for that. Similarly, there
are no non-callback defaults for "grob object properties" in
define-grobs.scm, again grobs just don't exist at that
point. But it does make sense to give a default if it's a callback,
and that's what meta.object-callbacks does. When it creates
a grob, LilyPond does this (grob.cc):

  SCM meta = get_property (this, "meta");
  if (scm_is_pair (meta))
    {
      [...]
      SCM object_cbs = scm_assq (ly_symbol2scm ("object-callbacks"), meta);
      if (scm_is_pair (object_cbs))
        {
          for (SCM s = scm_cdr (object_cbs); scm_is_pair (s); s = scm_cdr (s))
            set_object (this, scm_caar (s), scm_cdar (s));
        }
    }

which is the C++ equivalent for

(let ((meta (ly:grob-property grob-under-creation 'meta)))
  (if (pair? meta)
      (let ((object-callbacks (assq 'object-callbacks meta)))
        (if (pair? object-callbacks)
            (for-each
              (lambda (property-callback-pair)
                (ly:grob-set-object! grob-under-creation
                                     (car property-callback-pair)
                                     (cdr property-callback-pair)))
              (cdr object-callbacks))))))


In summary, \override Grob.meta.object-callbacks.object-property = #(lambda (grob) ...)
is an equivalent of \override Grob.property = #(lambda (grob) ...)
but for properties of the "object" kind.


(3) same for `side-support-elements':
$ git grep side-support-elements
Documentation/misc/CHANGES-1.3:of checking side-support-elements. This
fixes a problem with stacked
lily/bar-number-engraver.cc:      set_object (text_, "side-support-elements",
lily/dot-column.cc:  extract_grob_set (me, "side-support-elements", support);
lily/jump-engraver.cc:          set_object (text, "side-support-elements",
lily/mark-engraver.cc:      set_object (text_, "side-support-elements",
lily/metronome-engraver.cc:      set_object (text_, "side-support-elements",
lily/side-position-interface.cc:
Pointer_group_interface::add_unordered_grob (me, ly_symbol2scm
("side-support-elements"), e);
lily/side-position-interface.cc:  extract_grob_set (me,
"side-support-elements", proto_support);
lily/side-position-interface.cc:  extract_grob_set (me,
"side-support-elements", elts);
lily/side-position-interface.cc:  // TODO: if there is a grob that
never has side-support-elements
lily/side-position-interface.cc:  Grob_array *ga = unsmob<Grob_array>
(get_object (me, "side-support-elements"));
lily/side-position-interface.cc:side-support-elements
lily/span-arpeggio-engraver.cc:          extract_grob_set
(arpeggios_[j], "side-support-elements", sses);
lily/span-arpeggio-engraver.cc:
Pointer_group_interface::add_grob (span_arpeggio_, ly_symbol2scm
("side-support-elements"),
scm/define-grob-properties.scm:     (side-support-elements
,ly:grob-array? "The side support, an array of
scm/output-lib.scm:       (ly:grob-array->list (ly:grob-object g
'side-support-elements))))

I.e. apart from doc-strings for IR, no code-example, which would be
the most important, imho.
Thus I think it was close to impossible to find.
Reminds me as David K posted about <> being valid syntax.



I understand, but don't have a solution to that problem given
the number of properties.

I do try to contribute new functionality in Scheme rather than
C++ so it is more accessible both for people trying to improve
it and for people trying to use it as an example.


That said, I recently used `side-support-elements' for a custom
coding, setting and reading it.
https://lilypondforum.de/index.php/topic,1082.msg5858.html#msg5858
I learned how to do it by observing the behaviour of 'scripts and
their `side-support-elements' in ScriptRow.
I.e. not by reading the source-code, but by playing around with it.
This is tedious, time-consuming and not always successful.

Nevertheless, many, many thanks for your coding-example.
I may even be able to simplify the linked code.


Glad to have helped.

Best,
Jean




reply via email to

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