summaryrefslogtreecommitdiff
path: root/Documentation/snippets/generating-whole-scores-also-book-parts-in-scheme-without-using-the-parser.ly
blob: 1c216d3ed7c475ce0301f2c74a5d6b55f4d18a14 (about) (plain)
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
%% DO NOT EDIT this file manually; it is automatically
%% generated from LSR http://lsr.dsi.unimi.it
%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
%% and then run scripts/auxiliar/makelsr.py
%%
%% This file is in the public domain.
\version "2.14.2"

\header {
  lsrtags = "automatic-notation, scheme-language, really-cool"

%% Translation of GIT committish: 57f9346bb030f49336a858fcbf1519366fe56454
  texidocfr = "
Une partition LilyPond, de manière interne, n'est rien d'autre qu'une
expression Scheme générée par l'analyseur syntaxique de lilypond.  Il
est donc possible, à l'aide de Scheme, de générer automatiquement une
partition sans fichier source.  Une expression musicale en Scheme sera
transformée en partition par un appel à
@code{(scorify-music music parser)}.  Ceci aura pour effet de générer
un objet @code{score} auquel sera appliqué un bloc @code{layout}
comportant la fonction

@example
(let* ((layout (ly:output-def-clone $defaultlayout)))
   ; modification de la mise en forme, puis assignation :
   (ly:score-add-output-def! score layout)
  )
@end example

Il suffit alors de transmettre ce @code{score} à lilypond pour qu'il le
grave.  Les trois fonctions -- @code{(add-score parser score)},
@code{(add-text parser text)} et @code{(add-music parser music)} --
définies dans le code ci-dessous permettent de transmettre à lilypond,
aux fins de les graver, une partition complète, un @emph{markup} ou
simplement de la musique.

Cet exemple permet aussi de graver les pièces contenues dans un bloc
@code{\\book@{@dots{}@}} ainsi que des partitions de niveau supérieur.
Chaque partition destinée à être gravée est alors ajoutée à la liste des
partitions de niveau supérieur ; le @code{toplevel-book-handler} --
fonction Scheme appelée pour traiter un @emph{book} dès que le bloc
@code{\\book@{@dots{}@}} est clôturé -- s'adapte pour prendre en charge
tous les @code{score} jusque là collectés dans l'ouvrage.

"
  doctitlefr = "Génération en Scheme de partitions complètes (y compris des parties d'ouvrage) sans utiliser l'analyseur"

  texidoc = "
A lilypond score internally is just a Scheme expression, generated by
the lilypond parser. Using scheme, one can also automatically generate
a score without an input file. If you have the music expression in
scheme, a score can be generated by simply calling (scorify-music music
parser) on your music. This will generate a score object, for which you
can then set a custom layout block with (let* ((layout
(ly:output-def-clone $defaultlayout)))
   ; modify the layout here, then assign it:
   (ly:score-add-output-def! score layout)
  )


Finally, all you have to do it to pass this score to lilypond for
typesetting. This snippet defines functions @code{(add-score parser
score)}, @code{(add-text parser text)} and @code{(add-music parser
music)} to pass a complete score, some markup or some music to lilypond
for typesetting.

This snippet also works for typesetting scores inside a @code{\\book
@{...@}} block, as well as top-level scores. To achieve this, each
score schedulled for typesetting is appended to the list of toplevel
scores and the toplevel-book-handler (which is a scheme function called
to process a book once a @code{\\book@{..@}} block is closed) is
modified to inser all collected scores so far to the book.

"
  doctitle = "Generating whole scores (also book parts) in scheme without using the parser"
} % begin verbatim

#(define-public (add-score parser score)
   (ly:parser-define! parser 'toplevel-scores
                      (cons score (ly:parser-lookup parser 'toplevel-scores))))

#(define-public (add-text parser text)
  (add-score parser (list text)))

#(define-public (add-music parser music)
  (collect-music-aux (lambda (score)
		       (add-score parser score))
                     parser
		     music))

#(define-public (toplevel-book-handler parser book)
   (map (lambda (score)
          (ly:book-add-score! book score))
        (reverse! (ly:parser-lookup parser 'toplevel-scores)))
   (ly:parser-define! parser 'toplevel-scores (list))
   (print-book-with-defaults parser book))

#(define-public (book-score-handler book score)
   (add-score parser score))

#(define-public (book-text-handler book text)
   (add-text parser text))

#(define-public (book-music-handler parser book music)
   (add-music parser music))

%%%


%% Just some example score to show how to use these functions:
#(define add-one-note-score #f)
#(let ((pitch 0))
  (set! add-one-note-score
        (lambda (parser)
          (let* ((music (make-music 'EventChord
                          'elements (list (make-music 'NoteEvent
                                            'duration (ly:make-duration 2 0 1 1)
                                            'pitch (ly:make-pitch 0 pitch 0)))))
                 (score (scorify-music music parser))
                 (layout (ly:output-def-clone $defaultlayout))
                 (note-name (case pitch
                              ((0) "do")
                              ((1) "ré")
                              ((2) "mi")
                              ((3) "fa")
                              ((4) "sol")
                              ((5) "la")
                              ((6) "si")
                              (else "huh")))
                 (title (markup #:large #:line ("Score with a" note-name))))
            (ly:score-add-output-def! score layout)
            (add-text parser title)
            (add-score parser score))
            (set! pitch (modulo (1+ pitch) 7)))))

oneNoteScore =
#(define-music-function (parser location) ()
   (add-one-note-score parser)
   (make-music 'Music 'void #t))

%%%

\book {
  \oneNoteScore
}


\book {
  \oneNoteScore
  \oneNoteScore
}

% Top-level scores are also handled correctly
\oneNoteScore
\oneNoteScore