Hi Holleyanne,
please always try to provide a complete (minimal) example which is ready
to try it out.
It is more likely then that somebody will respond to your question.
An adapted version of your snippet is attached.
First few remarks for providing optional arguments.
In a simple (lambda) statement, as you tried, this is not possible. A
common approach
then is to provide an argument list and extract what you need.
Like:
colorNoteheads-c =
#(lambda (args)
(let ((color-outline? (car args))
(line-width (second args))
[...]
You can check the length of the argument list and see, if (or how many)
optional
arguments are given.
Another possibility is to use the built-in (define-scheme-function),
which also has
the possibility to do simple type checks.
See:
http://lilypond.org/doc/v2.18/Documentation/extending/scheme-function-definitions.html
The problem with optional arguments is, that the last argument cannot be
optional.
(Reasons are described in
http://lilypond.org/doc/v2.18/Documentation/extending/scheme-function-usage.html)
Thus I changed the order of arguments:
coloredNoteheads-c =
#(define-scheme-function (tonic-pitch line-width tonic-color part-color
color-outline?)
(ly:pitch? number? color? (color? black) boolean?)
It is of course possible to pass a tonic pitch to this function as an
argument.
Using context properties with this kind of callback function is not
possible, IMHO, since
you cannot afterwards determine the context a grob was created in.
Anyway I think a better solution for what you want to achieve would be a
scheme engraver.
That way you could access context properties, acknowledge NoteHead grobs
and modify the stencil
as you like.
To be honest, I think that the underlying snippet with all its hardcoded
paths is not the best way to color note heads with black outline,
because it will break for every change in the note head shape and so on.
I would propose a different solution, shown here as callback function:
%
\version "2.18.2"
\relative c' { c4 d e f }
color-notehead =
#(define-scheme-function (parser location color-outline color-fill
border-width)
(color? color? number?)
(lambda (grob)
(let* ((stencil-orig (ly:note-head::print grob))
(scale-factors (cons (- 1 border-width)
(- 1 border-width
(grob-interpret-markup grob
#{
\markup \halign #LEFT \overlay {
\with-color $color-outline \halign #CENTER \stencil
$stencil-orig
\with-color $color-fill \halign #CENTER \scale
$scale-factors \stencil $stencil-orig
}
#}
\layout {
\context {
\Staff
\override NoteHead.stencil = \color-notehead #black #red #0.3
}
}
Cheers,
Michael
Am 16.12.2019 um 22:38 schrieb Holleyanne McDaniel:
Hi - I've been working to adapt Colored Noteheads/Outlines
(http://lsr.di.unimi.it/LSR/Item?id=890) to highlight tonic notes, and
also be able to color a given voice. I've adjusted the variables to
let me specify tonic-color and part-color when I call the function,
and I've narrowed the note comparison to look only at the tonic value.
(my edited function included below)
There are two things I'm still struggling with. First, I'm currently
having to include/call a separate function for every single key. (If I
include them all in a library file, the parser maxes out its memory
and fails.) In a previous solution that only colored tonic noteheads,
I used a tonic variable from the EZ numbers engraver, allowing it to
adapt to key changes on the fly:
(tonic-pitch (ly:context-property context 'tonic))
(tonic-name (ly:pitch-notename tonic-pitch))
Is there a way to use these variables in my current function? If not,
can I specify the key through a variable when I call it? Every form of
sending pitch, string, etc. that I've tried has broken the function.
And secondly, I know I'm probably missing something obvious because
I've made it work in similar settings, but how do I get part-color to
be an optional variable with a default in the lambda context? Every
version of (predicate? (predicate? default)) type of definitions I've
tried also errors out.
coloredNoteheads-c = %% < rename per key
#(lambda (color-outline line-width tonic-color part-color)
;; @var{color-outline} is a boolean for whether
;; the outline is colored (#t) or the note head (#f).
;; @var{line-width} is a number, the width of
;; the outline, 7 is a good default.
;; @var{tonic-color} is a color, the key note's
;; color or outline.
;; @var{part-color} is a color, used if you want a particular
;; voice's notes highlighted. If not, set to black.
(lambda (grob)
(let* ((fsz (ly:grob-property grob 'font-size 0.0))
(mult (magstep fsz))
(stl empty-stencil)
(dur-log (ly:grob-property grob 'duration-log))
(pch (ly:event-property (event-cause