File size: 7,135 Bytes
f65fe85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
;;;; This file is part of LilyPond, the GNU music typesetter.
;;;;
;;;; Copyright (C) 1998--2020 Han-Wen Nienhuys <[email protected]>
;;;;                 Jan Nieuwenhuizen <[email protected]>
;;;;                 Neil Puttock <[email protected]>
;;;;                 Carl Sorensen <[email protected]>
;;;;
;;;; LilyPond is free software: you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by
;;;; the Free Software Foundation, either version 3 of the License, or
;;;; (at your option) any later version.
;;;;
;;;; LilyPond is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.

;; TODO: should link back into user manual.

(define (mm-rest-child-list music)
  "Generate events for multimeasure rests,
to be used by the sequential-iterator"
  (ly:set-origin! (list (make-music 'BarCheck)
                        (make-music 'MultiMeasureRestEvent
                                    (ly:music-deep-copy music))
                        (make-music 'BarCheck))
                  music))

(define (make-unfolded-set music)
  (let ((n (ly:music-property music 'repeat-count))
        (alts (ly:music-property music 'elements))
        (body (ly:music-property music 'element)))
    (cond ((<= n 0) '())
          ((null? alts) (make-list n body))
          (else
           (concatenate
            (zip (make-list n body)
                 (append! (make-list (max 0 (- n (length alts)))
                                     (car alts))
                          alts)))))))

(define (make-volta-set music)
  (let* ((alts (ly:music-property music 'elements))
         (lalts (length alts))
         (times (ly:music-property music 'repeat-count)))
    (map (lambda (x y)
           (make-music
            'SequentialMusic
            'elements
            ;; set properties for proper bar numbering
            (append
             (list (make-music 'AlternativeEvent
                               'alternative-dir (if (= y 0)
                                                    -1
                                                    0)
                               'alternative-increment
                               (if (= 0 y)
                                   (1+ (- times
                                          lalts))
                                   1)))
             (list x)
             (if (= y (1- lalts))
                 (list (make-music 'AlternativeEvent
                                   'alternative-dir 1
                                   'alternative-increment 0))
                 '()))))
         alts
         (iota lalts))))

(define (make-ottava-set music)
  "Set context properties for an ottava bracket."
  (let ((octavation (ly:music-property music 'ottava-number)))

    (list (context-spec-music
           (make-apply-context
            (lambda (context)
              (let* ((offset (* -7 octavation))
                     (markups (ly:context-property context 'ottavationMarkups))
                     (ottavation-markup (assoc-get octavation markups)))
                (set! (ly:context-property context 'middleCOffset) offset)
                (set! (ly:context-property context 'ottavation) ottavation-markup)
                (if (and (not (zero? octavation))
                         (not (markup? ottavation-markup)))
                    (ly:warning "Could not find ottavation markup for ~a octaves up." octavation))
                (ly:set-middle-C! context))))
           'Staff))))

(define (make-time-signature-set music)
  "Set context properties for a time signature."
  (let* ((num (ly:music-property music 'numerator))
         (den (ly:music-property music 'denominator))
         (structure (ly:music-property music 'beat-structure))
         (fraction (cons num den)))
    (list (context-spec-music
           (make-apply-context
            (lambda (context)
              (let* ((time-signature-settings
                      (ly:context-property context 'timeSignatureSettings))
                     (my-base-length
                      (base-length fraction time-signature-settings))
                     (my-beat-structure
                      (if (null? structure)
                          (beat-structure my-base-length
                                          fraction
                                          time-signature-settings)
                          structure))
                     (beaming-exception
                      (beam-exceptions fraction time-signature-settings))
                     (new-measure-length (ly:make-moment num den)))
                (ly:context-set-property!
                 context 'timeSignatureFraction fraction)
                (ly:context-set-property!
                 context 'baseMoment (ly:make-moment my-base-length))
                (ly:context-set-property!
                 context 'beatStructure my-beat-structure)
                (ly:context-set-property!
                 context 'beamExceptions beaming-exception)
                (ly:context-set-property!
                 context 'measureLength new-measure-length))))
           'Timing)
          ;; (make-music 'TimeSignatureEvent music) would always
          ;; create a Bottom context.  So instead, we just send the
          ;; event to whatever context may be currently active.  If
          ;; that is not contained within an existing context with
          ;; TimeSignatureEngraver at the time \time is iterated, it
          ;; will drop through the floor which mostly means that
          ;; point&click and tweaks are not available for any time
          ;; signatures engraved due to the Timing property changes
          ;; but without a \time of its own.  This is more a
          ;; "notification" rather than an "event" (which is always
          ;; sent to Bottom) but we don't currently have iterators for
          ;; that.
          (descend-to-context
           (make-apply-context
            (lambda (context)
              (ly:broadcast (ly:context-event-source context)
                            (ly:make-stream-event
                             (ly:make-event-class 'time-signature-event)
                             (ly:music-mutable-properties music)))))
           'Score))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Some MIDI callbacks -- is this a good place for them?

(define-public (breathe::midi-length len context)
  ;;Shorten by half, or by up to a second, but always by a power of 2
  (let* ((desired (min (ly:moment-main (seconds->moment 1 context))
                       (* (ly:moment-main len) 1/2)))
         (scale (inexact->exact (ceiling (/ (log desired) (log 1/2)))))
         (breath (ly:make-moment (expt 1/2 scale))))
    (ly:moment-sub (ly:make-moment (ly:moment-main len)) breath)))