1 %%% -*- Mode: scheme -*-
2 %%% clef.ily -- ancient and modern clef command
4 %%% Author: Nicolas Sceaux <nicolas.sceaux@free.fr>
9 %%% When true, use ancient clefs, instead of modern ones.
12 %%% When true, do not print incipit in modern style.
16 %%% \clef "ancient/modern"
18 %%% Overrides the \clef music command, with this extra feature: two
19 %%% clefs may be given as an argument to \clef, seperated by a
20 %%% slash. The first one is the ancient clef, the second the modern
21 %%% clef. The actually displayed clef depends on the value of the
22 %%% 'ancient-style option: if 'ancient-style option is #t, then the
23 %%% ancient clef is displayed; otherwise, the modern clef is
24 %%% displayed, preceeded by the ancient clef if at the beginning of a
26 %%% \clef "soprano/treble" is like:
27 %%% - \clef "soprano" when (ly:get-option 'ancient-style) is #t
28 %%% - \clef "treble" otherwise, but with an soprano clef in an incipit
29 %%% preceeding the first line.
31 %%% \oldKey pitch mode
32 %%% \newKey pitch mode
37 %%% This feature relies on LilyPond >=2.11.40
39 #(use-modules (ice-9 regex))
42 #(set-object-property! 'clef 'backend-type? ly:music?)
43 #(set-object-property! 'clef 'backend-doc "Incipit clef music")
44 #(set-object-property! 'key 'backend-type? ly:music?)
45 #(set-object-property! 'key 'backend-doc "Incipit key music")
48 #(define-music-function (parser location) ()
49 (if (or (eqv? #t (ly:get-option 'non-incipit))
50 (eqv? #t (ly:get-option 'ancient-style)))
53 \set Staff.vocalName = ""
54 \once \override Staff.InstrumentName #'self-alignment-X = #RIGHT
55 \once \override Staff.InstrumentName #'padding = #0
56 \once \override Staff.InstrumentName #'stencil =
58 (let ((clef (ly:grob-property grob 'clef))
59 (key (ly:grob-property grob 'key)))
60 (if (or (ly:music? clef) (ly:music? key))
61 (let* ((instrument-name (ly:grob-property grob 'long-text))
62 (layout (ly:output-def-clone (ly:grob-layout grob)))
63 (r1 (list (list 'remove "Time_signature_engraver")))
64 (r2 (if (ly:music? clef) r1 (cons (list 'remove "Clef_engraver") r1)))
65 (r3 (if (ly:music? key) r2 (cons (list 'remove "Key_engraver") r2)))
66 (m1 (list (make-music 'SkipMusic
67 'duration (ly:make-duration 3 0 1 1))))
68 (m2 (if (ly:music? key) (cons key m1) m1))
69 (m3 (if (ly:music? clef) (cons clef m2) m2))
72 'elements (cons (make-music
75 'property-operations (cons
76 (list 'push 'VerticalAxisGroup '(-2 . 2) 'Y-extent)
80 'symbol 'instrumentName
81 'value instrument-name))
83 (score (ly:make-score music))
84 (mm (ly:output-def-lookup layout 'mm))
85 (indent (ly:output-def-lookup layout 'indent))
86 (incipit-width (ly:output-def-lookup layout 'incipit-width))
87 (width (* (if (number? incipit-width) incipit-width 6)
89 (ly:output-def-set-variable! layout 'line-width indent)
90 (ly:output-def-set-variable! layout 'indent (- indent width))
91 (ly:output-def-set-variable! layout 'ragged-right #f)
92 (ly:score-add-output-def! score layout)
93 (set! (ly:grob-property grob 'long-text) (markup #:score score)))))
94 ;; hack. Why are Staff.InstrumentName overrides permanent,
95 ;; even with \once, and non re-overridable?
96 (let ((short-text (ly:grob-property grob 'text)))
97 (if (markup? short-text)
98 (set! (ly:grob-property grob 'text)
99 (markup #:null #:raise -4.5 #:concat (short-text #:hspace 0.5)))))
100 (system-start-text::print grob))
103 #(define french-clefs '((dessus french . treble)
104 (dessus2 soprano . treble)
105 (haute-contre soprano . treble)
106 (haute-contre2 mezzosoprano . treble)
107 (taille mezzosoprano . alto)
108 (taille2 alto . alto)
111 (vdessus treble . treble)
112 (vbas-dessus soprano . treble)
113 (vpetite-haute-contre mezzosoprano . treble)
114 (vhaute-contre alto . G_8)
115 (vtaille tenor . G_8)
116 (vbasse-taille varbaritone . bass)
120 (valto alto . treble)
123 #(define (make-ancient-or-modern-clef clef-name)
124 (let* ((match (string-match "^(.*)/(.*)$" clef-name))
125 (clefs (assoc (string->symbol clef-name) french-clefs))
126 (ancient-clef (cond (match (match:substring match 1))
127 (clefs (symbol->string (cadr clefs)))
129 (modern-clef (cond (match (match:substring match 2))
130 (clefs (symbol->string (cddr clefs)))
132 (cond ((eqv? #t (ly:get-option 'ancient-style))
134 (make-clef-set ancient-clef))
135 ((eqv? #t (ly:get-option 'non-incipit))
137 (make-clef-set modern-clef))
139 ;; modern clef + ancient clef in incipit
142 'elements (list (make-music
148 'grob-property-path '(clef)
149 'grob-value (make-clef-set ancient-clef)
151 'symbol 'InstrumentName))
152 (make-clef-set modern-clef)))))))
155 #(define-music-function (parser location clef-name) (string?)
156 (make-ancient-or-modern-clef clef-name))
159 #(define-music-function (parser location clef-name) (string?)
160 (make-music 'SequentialMusic
161 'elements (list (make-music 'ContextSpeccedMusic
163 'element (make-music 'PropertySet
166 (make-ancient-or-modern-clef clef-name))))
168 #(define (make-key-set note key-alist)
169 (let ((pitch (ly:music-property (car (ly:music-property
172 (make-music 'KeyChangeEvent
173 'pitch-alist (ly:transpose-key-alist key-alist pitch)
177 #(define-music-function (parser location note key-alist) (ly:music? list?)
178 (let ((key-set (make-key-set note key-alist)))
179 (if (eqv? #t (ly:get-option 'ancient-style))
181 (make-music 'ContextSpeccedMusic
183 'element (make-music 'OverrideProperty
185 'grob-property-path '(key)
188 'symbol 'InstrumentName)))))
191 #(define-music-function (parser location note key-alist) (ly:music? list?)
192 (if (eqv? #t (ly:get-option 'ancient-style))
194 (make-key-set note key-alist)))
197 #(define-music-function (parser location note key-alist) (ly:music? list?)
198 (let ((key-set (make-key-set note key-alist)))
199 (if (eqv? #t (ly:get-option 'ancient-style))
203 'elements (list key-set
210 'grob-property-path '(key)
213 'symbol 'InstrumentName)))))))