\version "2.19.15"
bassVerseA = \relative c { g1 1 1 1 c 1 g 1 d' c g d' }
bassBridge = \relative c { d1 1 1 1 }
bassVerseB = \relative c { c1 1 1 1 }
bassVerseC = \relative c { g1\fermata }
\layout {
\context {
\Score
\override RehearsalMark.self-alignment-X = #LEFT
}
}
\score {
{
\clef bass
\mark "3X"
\repeat volta 3 { \bassVerseA }
\mark "Bridge"
\bassBridge \break
\mark "3X"
\repeat volta 3 { \bassVerseA }
\mark "Verse B"
\bassVerseB \break
\mark "3X"
\repeat volta 3 { \bassVerseA }
\mark "Verse C"
\bassVerseC
}
\header {
piece = "Clear"
}
}
% If you are concerned about the length of the chart,
% here are two other approaches.
% If \bassVerseA is the kind of lick that you expect someone to memorize quickly,
% you could save space and write a modified multi-measure rest
% and write instructions to repeat the first section.
#(define (white-under grob) (grob-interpret-markup grob
(markup #:vcenter #:whiteout #:pad-x 1 (ly:grob-property grob 'text))))
inlineMMRN = {
\once \override MultiMeasureRest.layer = #-2
\once \override MultiMeasureRestNumber.layer = #-1
\once \override MultiMeasureRestNumber.Y-offset = #0
\once \override MultiMeasureRestNumber.stencil = #white-under
}
\score {
{
\clef bass
\compressFullBarRests
\override MultiMeasureRest #'minimum-length = #20
\mark \markup { \box "Verse A" "3X" }
\repeat volta 3 { \bassVerseA }
\mark \markup { \box "Bridge" }
\bassBridge \break
\mark \markup { \box "Verse A" "3X" }
\repeat volta 3 { \inlineMMRN R1*12 }
\mark \markup { \box "Verse B" }
\bassVerseB \break
\mark \markup { \box "Verse A" "3X" }
\repeat volta 3 { \inlineMMRN R1*12 }
\mark \markup { \box "Verse C" }
\bassVerseC
}
\header {
piece = "Concise but incomplete"
}
}
% To use standard notation with a small footprint you can use two codas.
% This requires some fiddling with layout of simultaneous marks
% These next functions come from
http://lsr.di.unimi.it/LSR/Snippet?id=977#(define-public (string-or-markup-or-boolean? e)
(or (string? e) (markup? e) (boolean? e)))
#(define (music-property-description symbol type? description)
(if (not (equal? #f (object-property symbol 'music-doc)))
(ly:error (_ "symbol ~S redefined") symbol))
(set-object-property! symbol 'music-type? type?)
(set-object-property! symbol 'music-doc description)
symbol)
#(for-each
(lambda (x)
(apply music-property-description x))
`((left-label
,string-or-markup-or-boolean?
"set the left part of a RehearsalMark")
(right-label
,string-or-markup-or-boolean?
"set the right part of a RehearsalMark")
))
#(define (double-rehearsalmark-stencil grob)
(let*
((grobs-event (ly:grob-property grob 'cause '()))
(left-label (ly:event-property grobs-event 'left-label))
(right-label (ly:event-property grobs-event 'right-label))
(gap (ly:grob-property grob 'gap 1.4)))
(if (not (or (null? left-label) (null? right-label)))
(case (ly:item-break-dir grob)
((-1)
(if (boolean? left-label) empty-stencil
(grob-interpret-markup grob
(make-right-align-markup left-label))))
((1)
(if (boolean? right-label) empty-stencil
(grob-interpret-markup grob
(make-left-align-markup right-label))))
(else
(if (boolean? left-label)
(grob-interpret-markup grob
(if left-label
(make-center-align-markup right-label)
(make-left-align-markup right-label)))
(if (boolean? right-label)
(grob-interpret-markup grob
(if right-label
(make-center-align-markup left-label)
(make-right-align-markup left-label)))
(ly:stencil-add
(ly:stencil-translate
(grob-interpret-markup grob
(make-right-align-markup left-label))
(cons (* -0.5 gap) 0.0))
(ly:stencil-translate
(grob-interpret-markup grob
(make-left-align-markup right-label))
(cons (* 0.5 gap) 0.0)))))))
(begin
(ly:warning "\"doubleMark stencil\" did not find \"doubleMark texts\".")
(ly:warning "fallback to using \"ly:text-interface::print\".")
(ly:text-interface::print grob)))))
doubleMark =
#(define-music-function
(parser location left-string right-string)
(string-or-markup-or-boolean? string-or-markup-or-boolean?)
(if (and (boolean? left-string) (boolean? right-string))
(ly:warning "~a \\doubleMark - at least one string or markup required" location))
(make-music 'SequentialMusic
'elements (list
(make-music 'ContextSpeccedMusic
'context-type 'Score
'element
(make-music 'OverrideProperty
'symbol 'RehearsalMark
'grob-value double-rehearsalmark-stencil
'grob-property-path (list 'stencil)
'pop-first #t
'once #t))
(make-music 'ContextSpeccedMusic
'context-type 'Score
'element
(make-music 'OverrideProperty
'symbol 'RehearsalMark
'grob-value #f
'grob-property-path (list 'self-alignment-X)
'pop-first #t
'once #t))
(make-music 'ContextSpeccedMusic
'context-type 'Score
'element
(make-music 'OverrideProperty
'symbol 'RehearsalMark
'grob-value `#(,(not (boolean? left-string))
#t
,(not (boolean? right-string)))
'grob-property-path (list 'break-visibility)
'pop-first #t
'once #t))
(make-music 'MarkEvent
'label #f
'left-label (if (string? left-string)
(make-simple-markup left-string)
left-string)
'right-label (if (string? right-string)
(make-simple-markup right-string)
right-string)
'origin location))))
set-mark-y-dir =
#(define-music-function (parser location ls)(list?)
"
Sets 'direction of RehearsalMark. Depending on their break-dir.
address@hidden is supposed to be an alist with entries like
(<break-dir of the item> . <Y-direction>)
A full list is not needed. An empty list is possible, too, will default to all
items UP.
Example:
`( (,left . ,DOWN) (,center . ,DOWN) (,right . ,UP) )
Ofcourse this is the same as:
'((-1 . -1)(0 . -1)(1 . 1))
"
#{
\override Score.RehearsalMark.before-line-breaking =
#(lambda (grob)
(let* ((get-break-dir (ly:item-break-dir grob))
(left-y-dir (or (assoc-get left ls) 1))
(right-y-dir (or (assoc-get right ls) 1))
(center-y-dir (or (assoc-get center ls) 1)))
(ly:grob-set-property! grob 'direction
(case get-break-dir
((-1) left-y-dir)
((1) right-y-dir)
((0) center-y-dir)
;; better be paranoiac
(else 1)))))
#})
% And now back to our example.
toCodaOne = \markup \tiny { \musicglyph #"scripts.coda" }
toCodaTwo = \markup \tiny { \musicglyph #"scripts.coda" \musicglyph #"scripts.coda" }
dcOne = \markup \teeny { \lower #0.5 "D.C. al " \musicglyph #"scripts.coda" }
dcTwo = \markup \teeny { \lower #0.5 "D.C. al " \musicglyph #"scripts.coda" \musicglyph #"scripts.coda" }
\score {
{
\clef bass
\mark "3X"
\repeat volta 3 {
\bassVerseA
% I'm not happy with the alignment of this mark,
% it would work better centered over the barline.
% but the following override isn't working like I'd expect.
\once \override RehearsalMark.self-alignment-X = #CENTER
\mark \markup { \center-column { \toCodaOne \toCodaTwo } "Bridge" }
}
\bassBridge \break
\set-mark-y-dir #`( (,left . ,DOWN) (,center . ,DOWN) (,right . ,UP) )
\doubleMark
\markup \teeny \center-column { \dcOne "with repeats" }
\markup { \musicglyph #"scripts.coda" "Verse B" } \bar "||"
\bassVerseB
\set-mark-y-dir #`( (,left . ,DOWN) (,center . ,DOWN) (,right . ,UP) )
\doubleMark
\markup \teeny \center-column { \dcTwo "with repeats" }
\markup { \musicglyph #"scripts.coda" \musicglyph #"scripts.coda" "Verse C" } \bar "||" \break
\bassVerseC
}
\header {
piece = "Concise and complete"
}
}