]> git.donarmstrong.com Git - lilypond.git/blob - scm/define-music-callbacks.scm
Add '-dcrop' option to ps and svg backends
[lilypond.git] / scm / define-music-callbacks.scm
1 ;;;; This file is part of LilyPond, the GNU music typesetter.
2 ;;;;
3 ;;;; Copyright (C) 1998--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
4 ;;;;                 Jan Nieuwenhuizen <janneke@gnu.org>
5 ;;;;                 Neil Puttock <n.puttock@gmail.com>
6 ;;;;                 Carl Sorensen <c_sorensen@byu.edu>
7 ;;;;
8 ;;;; LilyPond is free software: you can redistribute it and/or modify
9 ;;;; it under the terms of the GNU General Public License as published by
10 ;;;; the Free Software Foundation, either version 3 of the License, or
11 ;;;; (at your option) any later version.
12 ;;;;
13 ;;;; LilyPond is distributed in the hope that it will be useful,
14 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;;;; GNU General Public License for more details.
17 ;;;;
18 ;;;; You should have received a copy of the GNU General Public License
19 ;;;; along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
20
21 ;; TODO: should link back into user manual.
22
23 (define (mm-rest-child-list music)
24   "Generate events for multimeasure rests,
25 to be used by the sequential-iterator"
26   (ly:set-origin! (list (make-music 'BarCheck)
27                         (make-music 'MultiMeasureRestEvent
28                                     (ly:music-deep-copy music))
29                         (make-music 'BarCheck))
30                   music))
31
32 (define (make-unfolded-set music)
33   (let ((n (ly:music-property music 'repeat-count))
34         (alts (ly:music-property music 'elements))
35         (body (ly:music-property music 'element)))
36     (cond ((<= n 0) '())
37           ((null? alts) (make-list n body))
38           (else
39            (concatenate
40             (zip (make-list n body)
41                  (append! (make-list (max 0 (- n (length alts)))
42                                      (car alts))
43                           alts)))))))
44
45 (define (make-volta-set music)
46   (let* ((alts (ly:music-property music 'elements))
47          (lalts (length alts))
48          (times (ly:music-property music 'repeat-count)))
49     (map (lambda (x y)
50            (make-music
51             'SequentialMusic
52             'elements
53             ;; set properties for proper bar numbering
54             (append
55              (list (make-music 'AlternativeEvent
56                                'alternative-dir (if (= y 0)
57                                                     -1
58                                                     0)
59                                'alternative-increment
60                                (if (= 0 y)
61                                    (1+ (- times
62                                           lalts))
63                                    1)))
64              (list x)
65              (if (= y (1- lalts))
66                  (list (make-music 'AlternativeEvent
67                                    'alternative-dir 1
68                                    'alternative-increment 0))
69                  '()))))
70          alts
71          (iota lalts))))
72
73 (define (make-ottava-set music)
74   "Set context properties for an ottava bracket."
75   (let ((octavation (ly:music-property music 'ottava-number)))
76
77     (list (context-spec-music
78            (make-apply-context
79             (lambda (context)
80               (let ((offset (* -7 octavation))
81                     (string (assoc-get octavation '((2 . "15ma")
82                                                     (1 . "8va")
83                                                     (0 . #f)
84                                                     (-1 . "8vb")
85                                                     (-2 . "15mb")))))
86                 (set! (ly:context-property context 'middleCOffset) offset)
87                 (set! (ly:context-property context 'ottavation) string)
88                 (ly:set-middle-C! context))))
89            'Staff))))
90
91 (define (make-time-signature-set music)
92   "Set context properties for a time signature."
93   (let* ((num (ly:music-property music 'numerator))
94          (den (ly:music-property music 'denominator))
95          (structure (ly:music-property music 'beat-structure))
96          (fraction (cons num den)))
97     (list (descend-to-context
98            (context-spec-music
99             (make-apply-context
100              (lambda (context)
101                (let* ((time-signature-settings
102                        (ly:context-property context 'timeSignatureSettings))
103                       (my-base-length
104                        (base-length fraction time-signature-settings))
105                       (my-beat-structure
106                        (if (null? structure)
107                            (beat-structure my-base-length
108                                            fraction
109                                            time-signature-settings)
110                            structure))
111                       (beaming-exception
112                        (beam-exceptions fraction time-signature-settings))
113                       (new-measure-length (ly:make-moment num den)))
114                  (ly:context-set-property!
115                   context 'timeSignatureFraction fraction)
116                  (ly:context-set-property!
117                   context 'baseMoment (ly:make-moment my-base-length))
118                  (ly:context-set-property!
119                   context 'beatStructure my-beat-structure)
120                  (ly:context-set-property!
121                   context 'beamExceptions beaming-exception)
122                  (ly:context-set-property!
123                   context 'measureLength new-measure-length))))
124             'Timing)
125            'Score)
126           ;; (make-music 'TimeSignatureEvent music) would always
127           ;; create a Bottom context.  So instead, we just send the
128           ;; event to whatever context may be currently active.  If
129           ;; that is not contained within an existing context with
130           ;; TimeSignatureEngraver at the time \time is iterated, it
131           ;; will drop through the floor which mostly means that
132           ;; point&click and tweaks are not available for any time
133           ;; signatures engraved due to the Timing property changes
134           ;; but without a \time of its own.  This is more a
135           ;; "notification" rather than an "event" (which is always
136           ;; sent to Bottom) but we don't currently have iterators for
137           ;; that.
138           (make-apply-context
139            (lambda (context)
140              (ly:broadcast (ly:context-event-source context)
141                            (ly:make-stream-event
142                             (ly:make-event-class 'time-signature-event)
143                             (ly:music-mutable-properties music))))))))
144
145 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
146 ;; Some MIDI callbacks -- is this a good place for them?
147
148 (define-public (breathe::midi-length len context)
149   ;;Shorten by half, or by up to a second, but always by a power of 2
150   (let* ((desired (min (ly:moment-main (seconds->moment 1 context))
151                        (* (ly:moment-main len) 1/2)))
152          (scale (inexact->exact (ceiling (/ (log desired) (log 1/2)))))
153          (breath (ly:make-moment (expt 1/2 scale))))
154     (ly:moment-sub (ly:make-moment (ly:moment-main len)) breath)))