Hello Richard,

usually for this I’d simply use grace notes to create a timestep separation 
between two clefs:

{
  \clef bass
  \once\hideNotes\grace c64
  \once\override Staff.Clef.X-extent = #'(1.5 . 2)
  \clef treble
  1
}

But then it would actually be quite easy to have this done properly by an 
engraver (without any hacks). See the appended file for such an engraver that 
will enable showing an initial clef change.

Also the change clef will use the cue-clef break alignment, so using that you 
can actually adjust order (such as placing the change clef before key or time 
sigs) simply by using the break-align-order.

It would in fact be quite simple to extend the clef engraver to do this 
natively, simply by setting some context property. Maybe then using an 
initial-change-clef break alignment and a slightly adapted glyph name 
calculation that takes this into account (currently the small clef glyph needs 
to be set in the engraver, as Lilypond does not use change clefs at the begin 
of the line).

Cheers,
Valentin

Am Samstag, 8. Juni 2024, 19:05:26 MESZ schrieb Richard Shann:
> On Sat, 2024-06-08 at 08:09 -0700, Knute Snortum wrote:
> > On Sat, Jun 8, 2024 at 7:03 AM Richard Shann
> > 
> > <rich...@rshann.plus.com> wrote:
> > > I think it's not uncommon for two clefs to appear side by side at
> > > the
> > > start of a piece (e.g. when a piano piece starts with both staves
> > > in
> > > bass clef so as to alert the pianist that the upper staff is not in
> > > treble clef).
> > > How is this done in LilyPond?
> > 
> > It can be done with some Scheme magic.  I'm assuming you want both a
> > treble and bass clef initial and then immediately change to another
> > clef?  Someone wrote this (attached) for me (I really need to put the
> > author in the code so I can give credit where due.)  All you do is
> > include it in your LilyPond source and write \trebleToBass or
> > \bassToTreble and you have what you want.
> 
> Perfect!  Thank you so much!
> 
> Richard

%%% This engraver records the initial clef properties (e.g. what is set by \with { \clef ... })
%%% If in the first timestep these changed, engrave the original clef, and change formatting and break
%%% alignment of the actual clef to mimic a clef change clef. Duplicates some procedure from clef engraver
%%% and could easily be integrated.
#(define (initial-clef-change-engraver context)
   (let ((initial-clef-properties #f) (cclef #f))
     ; macro for checking if any clef property has changed
     (define (clef-changed)
       (>
        (length initial-clef-properties)
        (length
         (filter
          (lambda (x) (equal? (cdr x) (ly:context-property context (car x))))
          initial-clef-properties))))
     (make-engraver
      ; Record initials propertis
      ((initialize engraver)
       (set!
        initial-clef-properties
        `((clefGlyph . ,(ly:context-property context 'clefGlyph))
          (clefPosition  . ,(ly:context-property context 'clefPosition))
          (clefTransposition  . ,(ly:context-property context 'clefTransposition)))))
      ; Record the actual clef to adjust. Use detals.muted to not acknowledge clef created by this engraver.
      (acknowledgers
       ((clef-interface engraver grob source-engraver)
        (if (not (assoc-get 'muted (ly:grob-property grob 'details) #f))
            (set! cclef grob))))
      ; Create a clef if necessary
      ((process-music engraver)
       (if (and initial-clef-properties (clef-changed))
           (let ((clef (ly:engraver-make-grob engraver 'Clef '())))
             (ly:grob-set-property! clef 'staff-position (assoc-get 'clefPosition initial-clef-properties))
             (ly:grob-set-property! clef 'glyph (assoc-get 'clefGlyph initial-clef-properties))
             (ly:grob-set-nested-property! clef '(details muted) #t)
             (if ((lambda (x) (and (number? x) (not (= 0 x))))
                  (assoc-get 'clefTransposition initial-clef-properties 0))
                 (let ((mod (ly:engraver-make-grob engraver 'ClefModifier '()))
                       (formatter (ly:context-property context 'clefTranspositionFormatter))
                       (style (ly:context-property context 'clefTranspositionStyle))
                       (dir (sign (assoc-get 'clefTransposition initial-clef-properties 0)))
                       (abs_trans (1+ (abs (assoc-get 'clefTransposition initial-clef-properties 0)))))
                   (if (procedure? formatter)
                       (ly:grob-set-property! mod 'text (formatter (number->string abs_trans) style)))
                   (ly:grob-set-object! mod 'side-support-elements (ly:grob-list->grob-array (list clef)))
                   (ly:grob-set-parent! mod X clef)
                   (ly:grob-set-parent! mod Y clef)
                   (ly:grob-set-property! mod 'direction dir))))))
      ; Adjust the actual clef
      ((process-acknowledged engraver)
       (if (and cclef initial-clef-properties (clef-changed))
           (begin
            (ly:grob-set-property! cclef 'non-default #t)
            (ly:grob-set-property! cclef 'break-align-symbol 'cue-clef)
            (if (not (eq? #t (ly:grob-property cclef 'full-size-change)))
                (ly:grob-set-property! cclef 'glyph-name
                                       (format #f "~a_change" (ly:grob-property cclef 'glyph)))))))
      ; Unset parameters
      ((stop-translation-timestep engraver)
       (set! initial-clef-properties #f)
       (set! clef #f)))))

\layout {
  \context {
    \Staff
    \consists #initial-clef-change-engraver
    \clef "bass^15"
  }
}

{
  \clef "treble_8"
  1 1
  \clef bass
  1
}

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to