1pub mod builder;
4pub mod writer;
5
6#[derive(Clone, Debug, PartialEq)]
7pub struct TuneBook {
8 pub comments: Vec<IgnoredLine>,
9 pub header: Option<FileHeader>,
10 pub tunes: Vec<Tune>,
11}
12impl TuneBook {
13 pub fn new(
14 comments: Vec<IgnoredLine>,
15 header: Option<FileHeader>,
16 tunes: Vec<Tune>,
17 ) -> TuneBook {
18 TuneBook {
19 comments,
20 header,
21 tunes,
22 }
23 }
24}
25
26#[derive(Clone, Debug, Eq, PartialEq)]
27pub struct FileHeader {
28 pub lines: Vec<HeaderLine>,
29}
30impl FileHeader {
31 pub fn new(lines: Vec<HeaderLine>) -> FileHeader {
32 FileHeader { lines }
33 }
34}
35
36#[derive(Clone, Debug, PartialEq)]
37pub struct Tune {
38 pub header: TuneHeader,
39 pub body: Option<TuneBody>,
40}
41impl Tune {
42 pub fn new(header: TuneHeader, body: Option<TuneBody>) -> Tune {
43 Tune { header, body }
44 }
45}
46
47#[derive(Clone, Debug, Eq, PartialEq)]
48pub struct TuneHeader {
49 pub lines: Vec<HeaderLine>,
50}
51impl TuneHeader {
52 pub fn new(lines: Vec<HeaderLine>) -> TuneHeader {
53 TuneHeader { lines }
54 }
55}
56
57#[derive(Clone, Debug, Eq, PartialEq)]
58pub enum IgnoredLine {
59 Comment(Comment),
60 EmptyLine,
61}
62
63#[derive(Clone, Debug, Eq, PartialEq)]
64pub enum HeaderLine {
65 Field(InfoField, Option<Comment>),
66 Comment(Comment),
67}
68
69#[derive(Clone, Debug, Eq, PartialEq)]
70pub struct InfoField(pub char, pub String);
71impl InfoField {
72 pub fn new(c: char, s: String) -> InfoField {
73 InfoField(c, s)
74 }
75}
76
77#[derive(Clone, Debug, PartialEq)]
78pub struct TuneBody {
79 pub lines: Vec<TuneLine>,
80}
81impl TuneBody {
82 pub fn new(lines: Vec<TuneLine>) -> TuneBody {
83 TuneBody { lines }
84 }
85}
86
87#[derive(Clone, Debug, PartialEq)]
88pub enum TuneLine {
89 Comment(Comment),
90 Music(MusicLine),
91 Symbol(SymbolLine),
92 Lyric(LyricLine),
93}
94
95#[derive(Clone, Debug, PartialEq)]
96pub struct MusicLine {
97 pub symbols: Vec<MusicSymbol>,
98}
99impl MusicLine {
100 pub fn new(symbols: Vec<MusicSymbol>) -> MusicLine {
101 MusicLine { symbols }
102 }
103}
104
105#[derive(Clone, Debug, Eq, PartialEq)]
106pub struct SymbolLine {
107 pub symbols: Vec<SymbolLineSymbol>,
108}
109impl SymbolLine {
110 pub fn new(symbols: Vec<SymbolLineSymbol>) -> SymbolLine {
111 SymbolLine { symbols }
112 }
113}
114
115#[derive(Clone, Debug, PartialEq)]
116pub struct LyricLine {
117 pub symbols: Vec<LyricSymbol>,
118}
119impl LyricLine {
120 pub fn new(symbols: Vec<LyricSymbol>) -> LyricLine {
121 LyricLine { symbols }
122 }
123}
124
125#[derive(Clone, Debug, PartialEq)]
126pub enum MusicSymbol {
127 Note {
128 accidental: Option<Accidental>,
129 note: Note,
130 octave: i8,
131 length: Option<Length>,
132 tie: Option<Tie>,
133 },
134 Chord {
135 notes: Vec<MusicSymbol>,
136 length: Option<Length>,
137 tie: Option<Tie>,
138 },
139 GraceNotes {
140 acciaccatura: Option<()>,
141 notes: Vec<MusicSymbol>,
142 },
143 Tuplet {
146 p: u32,
147 q: Option<u32>,
148 r: Option<u32>,
149 },
150 BrokenRhythm {
151 rhythm: String,
152 before: Vec<MusicSymbol>,
153 after: Vec<MusicSymbol>,
154 },
155 Decoration(Decoration),
156 Annotation(Annotation),
157 Bar(String, Option<String>),
158 Beam(String),
159 Slur(Slur),
160 Comment(Comment),
161 Rest(Rest),
162 Spacer,
163 Ending(String),
164 InlineField(InfoField, bool),
165 Space(String),
166 Reserved(String),
167}
168
169impl MusicSymbol {
170 pub fn new_note(
171 accidental: Option<Accidental>,
172 note: Note,
173 octave: i8,
174 length: Option<Length>,
175 tie: Option<Tie>,
176 ) -> MusicSymbol {
177 MusicSymbol::Note {
178 accidental,
179 note,
180 octave,
181 length,
182 tie,
183 }
184 }
185
186 pub fn new_tuplet(p: u32, q: Option<u32>, r: Option<u32>) -> MusicSymbol {
187 assert!(p > 1 && p < 10);
188 assert_ne!(r, Some(0));
189
190 MusicSymbol::Tuplet { p, q, r }
191 }
192}
193
194#[derive(Clone, Debug, Eq, PartialEq)]
195pub enum SymbolLineSymbol {
196 Annotation(Annotation),
197 Decoration(Decoration),
198 SymbolAlignment(SymbolAlignment),
199 Space(String),
200}
201
202#[derive(Clone, Debug, Eq, PartialEq)]
203pub enum LyricSymbol {
204 Syllable(String),
205 SymbolAlignment(SymbolAlignment),
206 Space(String),
207}
208
209#[derive(Copy, Clone, Debug, Eq, PartialEq)]
210pub enum SymbolAlignment {
211 Break,
213 Extend,
215 Skip,
217 Space,
219 Hyphen,
221 Bar,
223}
224
225#[derive(Clone, Debug, Eq, PartialEq)]
226pub struct Annotation {
227 placement: Option<Placement>,
228 text: String,
229}
230
231impl Annotation {
232 pub fn new(placement: Option<Placement>, text: String) -> Annotation {
233 Annotation { placement, text }
234 }
235}
236
237#[derive(Copy, Clone, Debug, Eq, PartialEq)]
239pub enum Placement {
240 Above,
241 Below,
242 Left,
243 Right,
244 Auto,
245}
246
247#[derive(Copy, Clone, Debug, Eq, PartialEq)]
249pub enum Tie {
250 Solid,
252 Dotted,
254}
255
256#[derive(Copy, Clone, Debug, Eq, PartialEq)]
257pub enum Slur {
258 Begin,
259 BeginDotted,
260 End,
261}
262
263#[derive(Copy, Clone, Debug, Eq, PartialEq)]
264pub enum Note {
265 C,
266 D,
267 E,
268 F,
269 G,
270 A,
271 B,
272}
273
274impl From<Note> for char {
275 fn from(note: Note) -> Self {
276 match note {
277 Note::C => 'C',
278 Note::D => 'D',
279 Note::E => 'E',
280 Note::F => 'F',
281 Note::G => 'G',
282 Note::A => 'A',
283 Note::B => 'B',
284 }
285 }
286}
287
288#[derive(Clone, Debug, Eq, PartialEq)]
289pub enum Decoration {
290 Staccato,
291 Roll,
292 Fermata,
293 Accent,
294 LowerMordent,
295 Coda,
296 UpperMordent,
297 Segno,
298 Trill,
299 UpBow,
300 DownBow,
301 Unresolved(String),
302}
303
304#[derive(Copy, Clone, Debug, Eq, PartialEq)]
305pub enum Accidental {
306 Natural,
307 Sharp,
308 Flat,
309 DoubleSharp,
310 DoubleFlat,
311}
312
313#[derive(Copy, Clone, Debug, PartialEq)]
314pub enum Rest {
315 Note(Option<Length>),
316 Measure(Option<Length>),
317 NoteHidden(Option<Length>),
318 MeasureHidden(Option<Length>),
319}
320
321#[derive(Copy, Clone, Debug, PartialEq)]
322pub struct Length(f32);
323
324impl Length {
325 pub fn new(length: f32) -> Length {
326 Length(length)
327 }
328}
329
330#[derive(Clone, Debug, Eq, PartialEq)]
331pub enum Comment {
332 Comment(String),
333 CommentLine(String, String),
334 StylesheetDirective(String),
335}