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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
use super::{
Attributes, Backup, Barline, Bookmark, Direction, FiguredBass, Forward, Grouping, Harmony, Link, Listening, Note,
Part, Print, Sound,
};
use crate::datatypes::{Id, MeasureText, Tenths, Token, YesNo};
use alloc::{string::String, vec::Vec};
use musicxml_internal::*;
use musicxml_macros::*;
/// Attributes pertaining to the [Measure] element.
#[derive(Debug, PartialEq, Eq, AttributeDeserialize, AttributeSerialize)]
pub struct MeasureAttributes {
/// The attribute that identifies the measure. Going from partwise to timewise, measures are grouped via this attribute.
/// In partwise files, it should be the same for measures in different parts that share the same left barline.
///
/// While often numeric, it does not have to be. Non-numeric values are typically used together with the `implicit` or
/// `non_controlling` attributes being set to "yes". For a pickup measure, the `number` attribute is typically set to "0"
/// and the `implicit` attribute is typically set to "yes".
pub number: Token,
/// Specifies an ID that is unique to the entire document.
pub id: Option<Id>,
/// Set to "yes" for measures where the measure number should never appear, such as pickup measures and the last half
/// of mid-measure repeats. The value is "no" if not specified.
pub implicit: Option<YesNo>,
/// Intended for use in multimetric music like the Don Giovanni minuet. If set to "yes", the left barline in this measure
/// does not coincide with the left barline of measures in other parts. The value is "no" if not specified.
pub non_controlling: Option<YesNo>,
/// If measure numbers are not unique within a part, this can cause problems for conversions between partwise and
/// timewise formats. The `text` attribute allows specification of displayed measure numbers that are different than what
/// is used in the `number` attribute. This attribute is ignored for measures where the `implicit` attribute is set to "yes".
/// Further details about measure numbering can be specified using the [MeasureNumbering][super::MeasureNumbering] element.
pub text: Option<MeasureText>,
/// Used to size and scale an image. The image should be scaled independently in X and Y if both `height` and `width` are specified.
/// If only `width` is specified, the image should be scaled proportionally to fit in the specified X dimension.
pub width: Option<Tenths>,
}
/// The [MeasureElement] specifies all possible elements available for use in a [Measure] element.
#[derive(Debug, PartialEq, Eq, ElementDeserialize, ElementSerialize)]
pub enum MeasureElement {
/// The [Part] element is a container for musical data that is part of a score.
Part(Part),
/// The [Note] element includes the basic musical data such as pitch, duration, and instrument.
Note(Note),
/// The [Backup] element is used to indicate that the music following it is a repetition of music that already appeared earlier in the score.
Backup(Backup),
/// The [Forward] element is used to indicate that the music following it is not a repetition of music that already appeared earlier in the score.
Forward(Forward),
/// The [Direction] element is a musical indication that is not necessarily attached to a specific note.
Direction(Direction),
/// The [Attributes] element contains all the musical information that is not pitch-related.
Attributes(Attributes),
/// The [Harmony] element is used to represent harmony symbols.
Harmony(Harmony),
/// The [FiguredBass] element is used to specify figured bass symbols.
#[rename("figured-bass")]
FiguredBass(FiguredBass),
/// The [Print] element contains score layout information.
Print(Print),
/// The [Sound] element contains MIDI instrument information.
Sound(Sound),
/// The [Listening] element specifies the MIDI device that should be used for playback.
Listening(Listening),
/// The [Barline] element is used to set barline information.
Barline(Barline),
/// The [Grouping] element is used to indicate editorial information about how to group parts of a score.
Grouping(Grouping),
/// The [Link] element is used to establish a link to a URL.
Link(Link),
/// The [Bookmark] element is used to establish a bookmark for the current score location.
Bookmark(Bookmark),
}
/// The [Measure] element includes the basic musical data such as [Notes][super::Note] within a document.
#[derive(Debug, PartialEq, Eq, ElementDeserialize, ElementSerialize)]
pub struct Measure {
/// Element-specific attributes
pub attributes: MeasureAttributes,
/// Element-specific content
pub content: Vec<MeasureElement>,
}
#[cfg(test)]
mod measure_tests {
use super::*;
use crate::elements::*;
use crate::parser::parse_from_xml_str;
#[test]
fn deserialize_valid() {
let result = parse_from_xml_str::<Measure>(
"<measure number=\"2\">
<note default-x=\"148.50\" dynamics=\"2.22\" time-only=\"1,2,3\" default-y=\"-35.00\">
<pitch>
<step>F</step>
<octave>4</octave>
</pitch>
<duration>6</duration>
<voice>1</voice>
<type>eighth</type>
<stem>up</stem>
<staff>1</staff>
<beam number=\"1\">continue</beam>
<notations>
<articulations>
<staccato/>
</articulations>
</notations>
</note>
</measure>",
);
assert!(result.is_ok());
assert_eq!(
result.unwrap(),
Measure {
attributes: MeasureAttributes {
number: Token(String::from("2")),
id: None,
implicit: None,
non_controlling: None,
text: None,
width: None,
},
content: vec![MeasureElement::Note(Note {
attributes: NoteAttributes {
default_x: Some(Tenths(148.50)),
dynamics: Some(crate::datatypes::NonNegativeDecimal(2.22)),
time_only: Some(crate::datatypes::TimeOnly(vec![1, 2, 3])),
default_y: Some(Tenths(-35.00)),
..Default::default()
},
content: NoteContents {
info: NoteType::Normal(NormalInfo {
chord: None,
audible: AudibleType::Pitch(Pitch {
attributes: (),
content: PitchContents {
step: Step {
attributes: (),
content: crate::datatypes::Step::F
},
alter: None,
octave: Octave {
attributes: (),
content: crate::datatypes::Octave(4)
},
}
}),
duration: Duration {
attributes: (),
content: crate::datatypes::PositiveDivisions(6)
},
tie: vec![],
}),
instrument: vec![],
footnote: None,
level: None,
voice: Some(Voice {
attributes: (),
content: String::from("1")
}),
r#type: Some(Type {
attributes: TypeAttributes::default(),
content: crate::datatypes::NoteTypeValue::Eighth
}),
dot: vec![],
accidental: None,
time_modification: None,
stem: Some(Stem {
attributes: StemAttributes::default(),
content: crate::datatypes::StemValue::Up
}),
notehead: None,
notehead_text: None,
staff: Some(Staff {
attributes: (),
content: crate::datatypes::PositiveInteger(1)
}),
beam: vec![Beam {
attributes: BeamAttributes {
number: Some(crate::datatypes::BeamLevel(1)),
..Default::default()
},
content: crate::datatypes::BeamValue::Continue,
}],
notations: vec![Notations {
attributes: NotationsAttributes::default(),
content: NotationsContents {
footnote: None,
level: None,
notations: vec![NotationContentTypes::Articulations(Articulations {
attributes: ArticulationsAttributes::default(),
content: vec![ArticulationsType::Staccato(Staccato {
attributes: StaccatoAttributes::default(),
content: ()
})],
})]
}
}],
lyric: vec![],
play: None,
listen: None,
},
})]
}
);
}
}