Hi,
2018-04-02 6:32 GMT+02:00 brob2684 <[email protected]>:
> Hi Harm,
>
> I hadn't really thought about no key signature as being an issue, but I can
> certainly see how it can cause confusion.
>
> I think you are correct in suggesting "no key signature present" would be
> the appropriate output, although I'll admit I'm unlikely to ever come across
> such a case in my use of lilypond.
Well, even your first musical example has no (initial) KeySignature ;)
>>> melody = \relative c'' {
>>> \time 4/4
>>> c1 \key d \major d \key e \major e \key f \major f
>>> }
For the arbitrary reuse of a variable, this variable needs to be
defined at toplevel.
It's possible to update such a toplevel-variable by using an engraver,
though if you clear that variable in the engraver the value(s)/entries
are only available _in_ the score where the engraver works.
For multiple scores in the same file this means: if you don't clear it
then the values will accumulate (or override themselves).
Additionally the engraver updates it too late to have direct access to
the new values for other toplevel-markups.
So I decided to let the key-sig-names accumulate in a toplevel-list,
numbering them. Also, I wrote a markup-command where you need to
select the correct entry by using a number. A markup-command is
processed late enough.
Code attached, note the comments.
HTH,
Harm
\version "2.19.81"
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% After:
%%%%
%%%% http://lsr.di.unimi.it/LSR/Item?id=856
%%%% see also lists.gnu.org/archive/html/lilypond-user/2013-12/msg00828.html
%%%% by Paul Morris
%% tonic-num: number of the tonic note 0-6, C=0, B=6
%% acc-type: the accidental sign type, 1/2=sharp, -1/2=flat
%% acc-count: the number and type of accidentals in the key signature
%% values are: -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
%% (negative = flats, positive = sharps)
%% tonic-acc: #f if the tonic note is not sharp or flat, otherwise a pair
%% maj-num: number of the tonic note 0-6, if the key sig were major
%% mode-num: number of the mode 0-6
%% txt-size: size of key name text
%% mult: for correct resizing when the staff is resized
%% This list will be filled by the engraver and
%% 'replace-key-sig-name'-markup-command accesses it
#(define key-signature-list '())
#(define update-key-signature-list
;; Update `key-signature-list' by a pair containing a number and `entry'
;; The numbers increase.
(lambda (entry)
(set! key-signature-list
(cons
(cons (1+ (length key-signature-list)) entry)
key-signature-list))))
#(define (initial-moment? ctx)
"Is current-moment the @code{ZERO-MOMENT} or before?"
(not
(ly:moment<?
ZERO-MOMENT
(ly:context-current-moment ctx))))
#(define Store_initial_key_engraver
;; This engraver stores initial key-signatures in `key-signature-list'.
;; If no key-signature is present some text will be taken.
;; Because `key-signature-list' is a toplevel-definition all initial
;; key-signatures of all scores of a file will get an entry there.
;; To distuingish them they are numbered.
(lambda (context)
(let ((initial-key #f))
(make-engraver
;; If no initial key-signature is present let `initial-key' unchanged.
;; An entry in `key-signature-list' will then be done during th
;; `finalize'-step.
;; Otherwise `key-signature-list' will be updated in `acknowledgers'.
(listeners
((key-change-event engraver ev)
(if (initial-moment? context)
(set! initial-key #t))))
(acknowledgers
((key-signature-interface engraver grob source-engraver)
;; If key cancellation then do nothing (TODO needed?).
;; If we are at the very beginning, update `key-signature-list'
(if (and (initial-moment? context)
(not (eq? 'KeyCancellation (grob::name grob))))
(let* ((tonic-pitch (ly:context-property context 'tonic))
(tonic-num (ly:pitch-notename tonic-pitch))
(acc-list (ly:grob-property grob 'alteration-alist))
(acc-type (if (null? acc-list)
0
(cdr (list-ref acc-list 0))))
(acc-count (* (length acc-list) (if (< acc-type 0) -1 1)))
(maj-num
(case acc-count
((0) 0)
((1) 4) ((2) 1) ((3) 5) ((4) 2) ((5) 6) ((6) 3) ((7) 0)
((-1) 3) ((-2) 6) ((-3) 2) ((-4) 5) ((-5) 1) ((-6) 4)
((-7) 0)))
(mode-num (modulo (- tonic-num maj-num) 7))
;; Select the tonic-name
(key-letter (case tonic-num
((0) "C" ) ((1) "D" ) ((2) "E" ) ((3) "F" )
((4) "G" ) ((5) "A" ) ((6) "B" )))
(mult (magstep (ly:grob-property grob 'font-size 0.0)))
;; format accidentals for text
(txt-sharp
#{
\markup {
\translate #(cons (* mult -0.3) (* mult 0.8))
\magnify #(* mult 0.9)
\sharp
}
#})
(txt-flat
#{
\markup {
\translate #(cons (* mult -0.2) (* mult 0.4))
\magnify #(* mult 0.9)
\flat
}
#})
;; select the final accidental
(tonic-acc (if (pair? (assq tonic-num acc-list))
(if (= acc-type 0.5) txt-sharp txt-flat)
""))
;; select the scale-name
(key-mode (case mode-num
((0) "Major") ((1) "Dorian") ((2) "Phrygian")
((3) "Lydian") ((4) "Mixolydian") ((5) "Minor")
((6) "Locrian"))))
(update-key-signature-list
(list key-letter tonic-acc key-mode))))))
;; If not initial KeySignature is set, do an entry here.
((finalize engraver)
(if (not initial-key)
(update-key-signature-list (list "no")))
(set! initial-key #f))))))
%% We need to go for a markup-command, `key-signature-list' is updated too late
%% to acces it more directly.
#(define-markup-command (replace-key-sig-name layout props which arg)
(index? markup?)
#:category font
"
Replaces \"key-signature-name\" in @var{arg} by an entry from
@code{key-signature-list}, the relevant entry needs to be specified by
@var{which}"
(interpret-markup
layout
props
(if (string=? (markup->string arg) "key-signature-name")
(make-line-markup (assoc-get which key-signature-list (list "??")))
arg)))
\layout {
\context {
\Staff
\consists \Store_initial_key_engraver
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLES
%%%%%%%%%%%%%%%%%%%%%%%%%
txt =
\markuplist {
Some text later that states that the above piece starts in key-signature-name
key
}
lazySpacer =
\markup \column { \vspace #1 \draw-hline }
\new Staff \relative f'' {
\key cis \minor
c1 d
\key b \minor
a1
}
\markup \replace-key-sig-name #1 \txt
\lazySpacer
\new Staff \relative f'' {
\key gis \minor
c1 d
\key d \major
a1
}
\markup \replace-key-sig-name #2 \txt
\lazySpacer
\new Staff \relative f'' {
c1 d
a1
}
\markup \replace-key-sig-name #3 \txt
\lazySpacer
\new Staff \relative f'' {
\key c \major
c1 d
a1
}
\markup \replace-key-sig-name #4 \txt
\lazySpacer
\new Staff \relative f'' {
\key as \major
c1 d
\key d \major
a1
}
\markup \replace-key-sig-name #5 \txt
\lazySpacer
_______________________________________________
lilypond-user mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/lilypond-user