Skip to main content

music21_rs/
mei.rs

1//! MEI: music21's `mei.base`, which reads a score encoded by the Music
2//! Encoding Initiative's schema.
3//!
4//! An MEI score is measures, each holding a `<staff>` for every part and in
5//! it a `<layer>` for every voice; `<scoreDef>` and `<staffDef>` say the
6//! meter, key, clef and instrument. Slurs, ties, beams and tuplets may be
7//! written on the notes or apart from them, naming the notes they join by
8//! their `xml:id`.
9
10use std::collections::HashMap;
11
12use crate::articulations::{Articulation, ArticulationKind};
13use crate::bar::{Barline, BarlineType, RepeatDirection};
14use crate::chord::Chord;
15use crate::clef::{Clef, ClefKind};
16use crate::defaults::{FloatType, IntegerType};
17use crate::duration::{Duration, DurationType, Tuplet, TupletType};
18use crate::error::{Error, Result};
19use crate::expressions::{Expression, Ornament, OrnamentKind};
20use crate::instrument::{Instrument, SearchLanguage};
21use crate::interval::Interval;
22use crate::key::{Key, KeySignature};
23use crate::makenotation::op_frac;
24use crate::metadata::Metadata;
25use crate::meter::TimeSignature;
26use crate::notation::{BeamType, Lyric, Syllabic, Tie, TieType};
27use crate::note::Note;
28use crate::pitch::{Accidental, Pitch, PitchOptions};
29use crate::rest::Rest;
30use crate::spanner::{Spanner, SpannerKind};
31use crate::stream::{Stream, StreamElement, StreamEvent, StreamKind};
32use crate::xml::Xml;
33
34fn mei_error(message: impl Into<String>) -> Error {
35    Error::Mei(message.into())
36}
37
38/// A tag with any namespace prefix taken off.
39fn local(tag: &str) -> &str {
40    tag.rsplit(':').next().unwrap_or(tag)
41}
42
43fn children<'a>(element: &'a Xml, tag: &'a str) -> impl Iterator<Item = &'a Xml> {
44    element
45        .children
46        .iter()
47        .filter(move |child| local(&child.tag) == tag)
48}
49
50fn child<'a>(element: &'a Xml, tag: &str) -> Option<&'a Xml> {
51    element
52        .children
53        .iter()
54        .find(|child| local(&child.tag) == tag)
55}
56
57/// Every element under this one of a tag, in document order.
58fn descendants<'a>(element: &'a Xml, tag: &str, out: &mut Vec<&'a Xml>) {
59    for held in &element.children {
60        if local(&held.tag) == tag {
61            out.push(held);
62        }
63        descendants(held, tag, out);
64    }
65}
66
67fn without_hash(id: &str) -> &str {
68    id.strip_prefix('#').unwrap_or(id)
69}
70
71/// A tuplet a `<tupletSpan>` runs from one note to another, waiting for
72/// the layer to say which notes lie between.
73#[derive(Clone, Debug)]
74struct Search {
75    end: &'static str,
76    number: u32,
77    base: u32,
78}
79
80/// A thing a layer holds: an element, and what is known of it that the
81/// element itself cannot say.
82#[derive(Clone, Debug)]
83struct Thing {
84    element: StreamElement,
85    /// The number slurs know it by.
86    uid: usize,
87    search: Option<Search>,
88    /// A measure rest with no length of its own.
89    whole_measure: bool,
90}
91
92/// What a `<staffDef>` says: music21's dictionary of instrument, meter, key
93/// and clef, in that order.
94#[derive(Clone, Debug, Default)]
95struct StaffDef {
96    instrument: Option<Instrument>,
97    meter: Option<TimeSignature>,
98    key: Option<Key>,
99    clef: Option<Clef>,
100}
101
102impl StaffDef {
103    fn elements(&self) -> Vec<StreamElement> {
104        let mut out: Vec<StreamElement> = Vec::new();
105        if let Some(instrument) = &self.instrument {
106            out.push(instrument.clone().into());
107        }
108        if let Some(meter) = &self.meter {
109            out.push(meter.clone().into());
110        }
111        if let Some(key) = &self.key {
112            out.push(StreamElement::Key(key.clone()));
113        }
114        if let Some(clef) = &self.clef {
115            out.push(clef.clone().into());
116        }
117        out
118    }
119}
120
121/// A measure of one staff while it is put together.
122#[derive(Clone, Debug)]
123struct Measure {
124    number: IntegerType,
125    /// Each voice with its name and what it holds.
126    voices: Vec<(String, Vec<Thing>)>,
127    /// What stands at the start outside any voice, in the order inserted.
128    own: Vec<StreamElement>,
129    left: Option<Barline>,
130    right: Option<Barline>,
131    /// The length a measure rest fixed it at.
132    length: Option<FloatType>,
133}
134
135/// What a part holds in order: an instrument before its measures, then the
136/// measures.
137#[derive(Clone, Debug)]
138enum Held {
139    Instrument(Box<Instrument>),
140    Measure(Box<Measure>),
141}
142
143/// music21's `MeiToM21Converter`: the document, and what the elements that
144/// stand apart from the notes say of each note by its id.
145struct Reader {
146    /// For each `xml:id`, the attributes to be put on the element.
147    extra: HashMap<String, Vec<(&'static str, String)>>,
148    /// The slurs, each with the name it is known by and the notes it joins.
149    slurs: Vec<(String, Vec<usize>)>,
150    next_uid: usize,
151    next_slur: usize,
152}
153
154const DURATIONS: [(&str, FloatType); 14] = [
155    ("long", 16.0),
156    ("breve", 8.0),
157    ("1", 4.0),
158    ("2", 2.0),
159    ("4", 1.0),
160    ("8", 0.5),
161    ("16", 0.25),
162    ("32", 0.125),
163    ("64", 0.0625),
164    ("128", 0.03125),
165    ("256", 0.015625),
166    ("512", 0.0078125),
167    ("1024", 0.00390625),
168    ("2048", 0.001953125),
169];
170
171/// The length a `<mRest>` with no `dur` is given until its measure says
172/// how long it is.
173const NO_DURATION: FloatType = 0.00390625;
174
175fn accidental_of(attribute: Option<&str>) -> Result<Option<&'static str>> {
176    let Some(attribute) = attribute else {
177        return Ok(None);
178    };
179    Ok(Some(match attribute {
180        "s" | "ns" => "#",
181        "f" | "nf" => "-",
182        "ss" | "x" => "##",
183        "ff" => "--",
184        "xs" | "ts" => "###",
185        "tf" => "---",
186        "n" => "n",
187        "su" => "#~",
188        "sd" | "nu" => "~",
189        "fu" | "nd" => "`",
190        "fd" => "-`",
191        other => {
192            return Err(mei_error(format!(
193                "Unexpected value for \"accid\" attribute: {other}"
194            )));
195        }
196    }))
197}
198
199fn gestural_accidental_of(attribute: &str) -> Result<&'static str> {
200    Ok(match attribute {
201        "s" => "#",
202        "f" => "-",
203        "ss" => "##",
204        "ff" => "--",
205        "n" => "n",
206        "su" => "#~",
207        "sd" => "~",
208        "fu" => "`",
209        "fd" => "-`",
210        other => {
211            return Err(mei_error(format!(
212                "Unexpected value for \"accid.ges\" attribute: {other}"
213            )));
214        }
215    })
216}
217
218fn length_of(attribute: Option<&str>) -> Result<FloatType> {
219    let Some(attribute) = attribute else {
220        return Ok(NO_DURATION);
221    };
222    DURATIONS
223        .iter()
224        .find(|(name, _)| *name == attribute)
225        .map(|(_, length)| *length)
226        .ok_or_else(|| {
227            mei_error(format!(
228                "Unexpected value for \"dur\" attribute: {attribute}"
229            ))
230        })
231}
232
233/// music21's `makeDuration`: a length, then its dots.
234fn duration_of(base: FloatType, dots: u32) -> Result<Duration> {
235    let plain = Duration::new(base)?;
236    Ok(match plain.type_and_dots() {
237        Some((kind, _)) => Duration::from_type_with_dots(kind, dots),
238        None => plain,
239    })
240}
241
242fn dots_of(element: &Xml) -> Result<u32> {
243    match element.get("dots") {
244        None => Ok(0),
245        Some(dots) => dots
246            .parse()
247            .map_err(|_| mei_error(format!("the dots {dots:?} are no number"))),
248    }
249}
250
251/// music21's `_makeArticList`: the marks an `artic` attribute names.
252fn articulations_of(attribute: &str) -> Result<Vec<Articulation>> {
253    let mut marks = Vec::new();
254    for name in attribute.split(' ') {
255        let classes: &[&str] = match name {
256            "marc-stacc" => &["StrongAccent", "Staccato"],
257            "ten-stacc" => &["Tenuto", "Staccato"],
258            "acc" => &["Accent"],
259            "stacc" => &["Staccato"],
260            "ten" => &["Tenuto"],
261            "stacciss" => &["Staccatissimo"],
262            "marc" => &["StrongAccent"],
263            "spicc" => &["Spiccato"],
264            "doit" => &["Doit"],
265            "plop" => &["Plop"],
266            "fall" => &["Falloff"],
267            "dnbow" => &["DownBow"],
268            "upbow" => &["UpBow"],
269            "harm" => &["Harmonic"],
270            "snap" => &["SnapPizzicato"],
271            "stop" => &["Stopped"],
272            "open" => &["OpenString"],
273            "dbltongue" => &["DoubleTongue"],
274            "toe" => &["OrganToe"],
275            "trpltongue" => &["TripleTongue"],
276            "heel" => &["OrganHeel"],
277            "tap" | "lhpizz" | "dot" | "stroke" | "rip" | "bend" | "flip" | "smear"
278            | "fingernail" | "damp" | "dampall" => &["Articulation"],
279            other => {
280                return Err(mei_error(format!(
281                    "Unexpected value for \"artic\" attribute: {other}"
282                )));
283            }
284        };
285        for class in classes {
286            let kind = ArticulationKind::from_class_name(class)
287                .ok_or_else(|| mei_error(format!("no articulation called {class}")))?;
288            marks.push(Articulation::of_kind(kind));
289        }
290    }
291    Ok(marks)
292}
293
294/// music21's `_barlineFromAttr`: a barline, or the two a repeat both ways
295/// is, the one closing a measure and the one opening the next.
296fn barline_of(attribute: &str) -> Result<(Barline, Option<Barline>)> {
297    Ok(match attribute {
298        "rptboth" => (
299            Barline::repeat(RepeatDirection::End, Some(2)),
300            Some(Barline::repeat(RepeatDirection::Start, None)),
301        ),
302        "rptend" => (Barline::repeat(RepeatDirection::End, Some(2)), None),
303        other if other.starts_with("rpt") => (Barline::repeat(RepeatDirection::Start, None), None),
304        other => {
305            let kind = match other {
306                "dashed" => BarlineType::Dashed,
307                "dotted" => BarlineType::Dotted,
308                "dbl" => BarlineType::Double,
309                "end" => BarlineType::Final,
310                "invis" => BarlineType::None,
311                "single" => BarlineType::Regular,
312                other => {
313                    return Err(mei_error(format!(
314                        "Unexpected value for \"right\" attribute: {other}"
315                    )));
316                }
317            };
318            (Barline::new(kind), None)
319        }
320    })
321}
322
323fn tie_of(attribute: &str) -> Tie {
324    let has = |mark: char| attribute.contains(mark);
325    Tie::new(if has('m') || (has('t') && has('i')) {
326        TieType::Continue
327    } else if has('i') {
328        TieType::Start
329    } else {
330        TieType::Stop
331    })
332}
333
334fn meter_of(element: &Xml) -> Result<TimeSignature> {
335    TimeSignature::from_ratio_string(&format!(
336        "{}/{}",
337        element.get("meter.count").unwrap_or("None"),
338        element.get("meter.unit").unwrap_or("None")
339    ))
340}
341
342/// music21's `_keySigFromAttrs`: a key named by its tonic, or by how many
343/// sharps or flats it is written with.
344fn key_of(element: &Xml) -> Result<Key> {
345    if let Some(step) = element.get("key.pname") {
346        let tonic = format!(
347            "{step}{}",
348            accidental_of(element.get("key.accid"))?.unwrap_or("")
349        );
350        return Key::from_tonic_mode(
351            &tonic,
352            element.get("key.mode").filter(|mode| !mode.is_empty()),
353        );
354    }
355    let signature = element.get("key.sig").unwrap_or("0");
356    let count = || -> Result<IntegerType> {
357        signature[..1]
358            .parse()
359            .map_err(|_| mei_error(format!("the key signature {signature:?} has no number")))
360    };
361    let sharps = if signature.starts_with('0') {
362        0
363    } else if signature.ends_with('s') {
364        count()?
365    } else {
366        -count()?
367    };
368    Ok(KeySignature::new(sharps).as_key(element.get("key.mode").unwrap_or("major")))
369}
370
371/// music21's `_transpositionFromAttrs`: the interval an instrument sounds
372/// away from where it is written.
373fn transposition_of(element: &Xml) -> Result<Interval> {
374    let read = |name: &str| -> Result<IntegerType> {
375        match element.get(name) {
376            None => Ok(0),
377            Some(text) => text
378                .parse()
379                .map_err(|_| mei_error(format!("{name} is no number: {text:?}"))),
380        }
381    };
382    let mut diatonic = read("trans.diat")?;
383    let semitones = read("trans.semi")?;
384    // A transposition of more than an octave written with its steps inside
385    // one has the octaves put back.
386    if (semitones - diatonic).abs() > 5 * (semitones.abs() / 12 + 1) {
387        if semitones < 0 {
388            diatonic -= 7 * (semitones.abs() / 12);
389        } else if semitones > 0 {
390            diatonic += 7 * (semitones.abs() / 12);
391        }
392    }
393    diatonic += diatonic.signum();
394    Interval::from_generic_and_chromatic(diatonic, semitones)
395}
396
397fn clef_of(
398    shape: Option<&str>,
399    line: Option<&str>,
400    displaced: Option<&str>,
401    place: Option<&str>,
402) -> Result<Clef> {
403    match shape {
404        Some("perc") => Ok(Clef::of_kind(ClefKind::PercussionClef)),
405        Some("TAB") => Ok(Clef::of_kind(ClefKind::TabClef)),
406        _ => {
407            let octaves = match displaced {
408                None => 0,
409                Some("8") => 1,
410                Some("15") => 2,
411                Some("22") => 3,
412                Some(other) => {
413                    return Err(mei_error(format!("a clef displaced by {other}")));
414                }
415            };
416            let shift = if place == Some("below") {
417                -octaves
418            } else {
419                octaves
420            };
421            let (Some(shape), Some(line)) = (shape, line) else {
422                return Err(mei_error("a clef with no shape or no line"));
423            };
424            Clef::from_string(&format!("{shape}{line}"), shift)
425        }
426    }
427}
428
429fn clef_element(element: &Xml) -> Result<Clef> {
430    clef_of(
431        element.get("shape"),
432        element.get("line"),
433        element.get("dis"),
434        element.get("dis.place"),
435    )
436}
437
438/// Whether a length is written with a flag, and so may be beamed.
439fn is_beamable(duration: &Duration) -> Option<DurationType> {
440    match duration.components().as_slice() {
441        [(kind, _)] if kind.quarter_length() < 1.0 => Some(*kind),
442        _ => None,
443    }
444}
445
446fn with_duration(element: &mut StreamElement, change: impl FnOnce(&mut Duration)) {
447    let Some(mut duration) = element.duration().cloned() else {
448        return;
449    };
450    change(&mut duration);
451    match element {
452        StreamElement::Note(note) => note.set_duration(duration),
453        StreamElement::Chord(chord) => chord.set_duration(duration),
454        StreamElement::Rest(rest) => rest.set_duration(duration),
455        _ => {}
456    }
457}
458
459fn is_sounding(element: &StreamElement) -> bool {
460    matches!(
461        element,
462        StreamElement::Note(_) | StreamElement::Chord(_) | StreamElement::Rest(_)
463    )
464}
465
466fn mark_first_tuplet(element: &mut StreamElement, kind: TupletType) {
467    with_duration(element, |duration| {
468        let mut tuplets = duration.tuplets();
469        if let Some(first) = tuplets.first_mut() {
470            first.set_tuplet_type(Some(kind));
471        }
472        duration.set_tuplets(tuplets);
473    });
474}
475
476/// music21's `scaleToTuplet` for a tuplet whose numbers are known: so many
477/// notes in the time of so many, of the value the note is written in.
478fn scale_to_tuplet(element: &mut StreamElement, number: u32, base: u32) {
479    if !is_sounding(element) {
480        return;
481    }
482    with_duration(element, |duration| {
483        let kind = match duration.components().as_slice() {
484            [(kind, _)] => *kind,
485            _ => DurationType::Quarter,
486        };
487        duration.append_tuplet(Tuplet::new(number, base, kind, 0));
488    });
489}
490
491/// music21's `beamTogether`: the first thing that can carry a beam starts
492/// it, those after carry it on, and the last ends it.
493fn beam_together(things: &mut [Thing]) -> Result<()> {
494    let mut last: Option<usize> = None;
495    for (index, thing) in things.iter_mut().enumerate() {
496        let (beams, duration) = match &thing.element {
497            StreamElement::Note(note) => (note.beams().clone(), note.duration().cloned()),
498            StreamElement::Chord(chord) => (chord.beams().clone(), chord.duration().cloned()),
499            _ => continue,
500        };
501        let Some(kind) = duration.as_ref().and_then(is_beamable) else {
502            continue;
503        };
504        if !beams.is_empty() {
505            continue;
506        }
507        let mut filled = beams;
508        filled.fill(
509            kind,
510            Some(if last.is_none() {
511                BeamType::Start
512            } else {
513                BeamType::Continue
514            }),
515        )?;
516        match &mut thing.element {
517            StreamElement::Note(note) => note.set_beams(filled),
518            StreamElement::Chord(chord) => chord.set_beams(filled),
519            _ => {}
520        }
521        last = Some(index);
522    }
523    // Where nothing was beamed music21 reaches for the last thing of all.
524    let closing = last.or(things.len().checked_sub(1));
525    if let Some(thing) = closing.and_then(|index| things.get_mut(index)) {
526        match &mut thing.element {
527            StreamElement::Note(note) => {
528                let mut beams = note.beams().clone();
529                beams.set_all(BeamType::Stop, None);
530                note.set_beams(beams);
531            }
532            StreamElement::Chord(chord) => {
533                let mut beams = chord.beams().clone();
534                beams.set_all(BeamType::Stop, None);
535                chord.set_beams(beams);
536            }
537            _ => {}
538        }
539    }
540    Ok(())
541}
542
543impl Reader {
544    /// An attribute as music21 reads it once the spanning elements have
545    /// written theirs onto the notes: what the element says, then what was
546    /// said of it.
547    fn attribute(&self, element: &Xml, name: &str) -> Option<String> {
548        let added = element
549            .get("xml:id")
550            .and_then(|id| self.extra.get(id))
551            .and_then(|extra| {
552                extra
553                    .iter()
554                    .find(|(held, _)| *held == name)
555                    .map(|(_, value)| value.clone())
556            });
557        match (element.get(name), added) {
558            (Some(own), Some(added)) => Some(format!("{own}{added}")),
559            (Some(own), None) => Some(own.to_string()),
560            (None, added) => added,
561        }
562    }
563
564    fn set(&mut self, id: &str, name: &'static str, value: String) {
565        let extra = self.extra.entry(without_hash(id).to_string()).or_default();
566        match extra.iter_mut().find(|(held, _)| *held == name) {
567            Some((_, held)) => *held = value,
568            None => extra.push((name, value)),
569        }
570    }
571
572    /// music21's `_ppSlurs`, `_ppTies`, `_ppBeams` and `_ppTuplets`: what
573    /// the spanning elements of the score say, written against the ids of
574    /// the notes they name.
575    fn preprocess(&mut self, score: &Xml) {
576        let mut found = Vec::new();
577        descendants(score, "slur", &mut found);
578        for slur in std::mem::take(&mut found) {
579            if let (Some(start), Some(end)) = (slur.get("startid"), slur.get("endid")) {
580                let name = format!("slur-{}", self.next_slur);
581                self.next_slur += 1;
582                self.slurs.push((name.clone(), Vec::new()));
583                self.set(start, "m21SlurStart", name.clone());
584                self.set(end, "m21SlurEnd", name);
585            }
586        }
587        descendants(score, "tie", &mut found);
588        for tie in std::mem::take(&mut found) {
589            if let (Some(start), Some(end)) = (tie.get("startid"), tie.get("endid")) {
590                self.set(start, "tie", "i".to_string());
591                self.set(end, "tie", "t".to_string());
592            }
593        }
594        descendants(score, "beamSpan", &mut found);
595        for beam in std::mem::take(&mut found) {
596            let (Some(start), Some(end)) = (beam.get("startid"), beam.get("endid")) else {
597                continue;
598            };
599            self.set(start, "m21Beam", "start".to_string());
600            self.set(end, "m21Beam", "stop".to_string());
601            for id in beam.get("plist").unwrap_or("").split(' ') {
602                let id = without_hash(id);
603                let has = self
604                    .extra
605                    .get(id)
606                    .is_some_and(|extra| extra.iter().any(|(name, _)| *name == "m21Beam"));
607                if !has {
608                    self.set(id, "m21Beam", "continue".to_string());
609                }
610            }
611        }
612        descendants(score, "tupletSpan", &mut found);
613        for tuplet in found {
614            let number = tuplet.get("num").unwrap_or("None").to_string();
615            let base = tuplet.get("numbase").unwrap_or("None").to_string();
616            if let Some(list) = tuplet.get("plist") {
617                for id in list.split(' ') {
618                    if !without_hash(id).is_empty() {
619                        self.set(id, "m21TupletNum", number.clone());
620                        self.set(id, "m21TupletNumbase", base.clone());
621                    }
622                }
623            } else if let (Some(start), Some(end)) = (tuplet.get("startid"), tuplet.get("endid")) {
624                for (id, which) in [(start, "start"), (end, "end")] {
625                    self.set(id, "m21TupletSearch", which.to_string());
626                    self.set(id, "m21TupletNum", number.clone());
627                    self.set(id, "m21TupletNumbase", base.clone());
628                }
629            }
630        }
631    }
632
633    fn uid(&mut self) -> usize {
634        self.next_uid += 1;
635        self.next_uid - 1
636    }
637
638    /// music21's `addSlurs`: the slurs an element starts or ends.
639    fn add_slurs(&mut self, element: &Xml, uid: usize) -> Result<()> {
640        let join = |slurs: &mut Vec<(String, Vec<usize>)>, name: &str| {
641            if let Some((_, held)) = slurs.iter_mut().find(|(held, _)| held == name) {
642                held.push(uid);
643            }
644        };
645        if let Some(name) = self.attribute(element, "m21SlurStart") {
646            join(&mut self.slurs, &name);
647        }
648        if let Some(name) = self.attribute(element, "m21SlurEnd") {
649            join(&mut self.slurs, &name);
650        }
651        if let Some(slurs) = element.get("slur") {
652            for slur in slurs.split(' ') {
653                let chars: Vec<char> = slur.chars().collect();
654                let [number, kind] = chars.as_slice() else {
655                    return Err(mei_error(format!("cannot read the slur {slur:?}")));
656                };
657                let name = number.to_string();
658                match kind {
659                    'i' => self.slurs.push((name, vec![uid])),
660                    't' => join(&mut self.slurs, &name),
661                    _ => {}
662                }
663            }
664        }
665        Ok(())
666    }
667
668    /// What the tuplet numbers written against an element do to it:
669    /// music21's `scaleToTuplet`.
670    fn tuplet(&self, element: &Xml, thing: &mut Thing) -> Result<()> {
671        let Some(number) = self.attribute(element, "m21TupletNum") else {
672            return Ok(());
673        };
674        let base = self
675            .attribute(element, "m21TupletNumbase")
676            .unwrap_or_default();
677        let read = |text: &str| -> Result<u32> {
678            text.parse()
679                .map_err(|_| mei_error(format!("a tuplet of {text:?} notes")))
680        };
681        let (number, base) = (read(&number)?, read(&base)?);
682        match self.attribute(element, "m21TupletSearch").as_deref() {
683            Some(end) => {
684                thing.search = Some(Search {
685                    end: if end.contains("start") {
686                        "start"
687                    } else {
688                        "end"
689                    },
690                    number,
691                    base,
692                });
693            }
694            None => {
695                scale_to_tuplet(&mut thing.element, number, base);
696                if let Some(written) = element.get("tuplet") {
697                    if written.starts_with('i') {
698                        mark_first_tuplet(&mut thing.element, TupletType::Start);
699                    } else if written.starts_with('t') {
700                        mark_first_tuplet(&mut thing.element, TupletType::Stop);
701                    }
702                }
703            }
704        }
705        Ok(())
706    }
707
708    /// music21's `noteFromElement`. The second answer is the number slurs
709    /// know the note by.
710    fn note(&mut self, element: &Xml) -> Result<(Note, usize)> {
711        let name = element.get("pname").unwrap_or("");
712        let mut pitch = if name.is_empty() {
713            Pitch::from_name("C4")?
714        } else {
715            let step = name
716                .chars()
717                .next()
718                .map(|c| c.to_ascii_uppercase())
719                .ok_or_else(|| mei_error("a note with no name"))?;
720            let mut options = PitchOptions::new().step(step);
721            if let Some(octave) = element.get("oct").filter(|octave| !octave.is_empty()) {
722                options = options.octave(
723                    octave
724                        .parse()
725                        .map_err(|_| mei_error(format!("the octave {octave:?} is no number")))?,
726                );
727            }
728            options.build()?
729        };
730        if let Some(accidental) = accidental_of(element.get("accid"))? {
731            pitch.set_written_accidental(Some(Accidental::new(accidental)?));
732        }
733        let length = length_of(element.get("dur"))?;
734        let mut note =
735            Note::from_pitch(pitch).with_duration(duration_of(length, dots_of(element)?)?);
736
737        let mut dot_elements = 0;
738        for held in &element.children {
739            match local(&held.tag) {
740                "dot" => dot_elements += 1,
741                "artic" => {
742                    if let Some(marks) = held.get("artic") {
743                        note.articulations_mut().extend(articulations_of(marks)?);
744                    }
745                }
746                "accid" => {
747                    let accidental = match held.get("accid.ges") {
748                        Some(gestural) => Some(gestural_accidental_of(gestural)?),
749                        None => accidental_of(held.get("accid"))?,
750                    };
751                    if let Some(accidental) = accidental {
752                        let mut pitch = note.pitch().clone();
753                        pitch.set_written_accidental(Some(Accidental::new(accidental)?));
754                        note.set_pitch(pitch);
755                    }
756                }
757                "syl" => *note.lyrics_mut() = vec![syllable_of(held)?],
758                _ => {}
759            }
760        }
761        if let Some(gestural) = element.get("accid.ges") {
762            let mut pitch = note.pitch().clone();
763            pitch.set_written_accidental(Some(Accidental::new(gestural_accidental_of(gestural)?)?));
764            note.set_pitch(pitch);
765        }
766        let uid = self.uid();
767        self.add_slurs(element, uid)?;
768        if let Some(id) = element.get("xml:id") {
769            note.set_id(Some(id.to_string()));
770        }
771        if let Some(marks) = element.get("artic") {
772            note.articulations_mut().extend(articulations_of(marks)?);
773        }
774        if let Some(tie) = self.attribute(element, "tie") {
775            note.set_tie(Some(tie_of(&tie)));
776        }
777        if dot_elements > 0 {
778            note.set_duration(duration_of(length, dot_elements)?);
779        }
780        if element.get("grace").is_some() {
781            let grace = note
782                .duration()
783                .map(Duration::grace_duration)
784                .unwrap_or_default();
785            note.set_duration(grace);
786        }
787        if let Some(beam) = self.attribute(element, "m21Beam")
788            && let Some(kind) = note.duration().and_then(is_beamable)
789        {
790            let mut beams = note.beams().clone();
791            beams.fill(kind, Some(beam_type_of(&beam)?))?;
792            note.set_beams(beams);
793        }
794        let verses: Vec<&Xml> = children(element, "verse").collect();
795        if !verses.is_empty() {
796            let mut lyrics = Vec::new();
797            for (index, verse) in verses.iter().enumerate() {
798                let number = match verse.get("n") {
799                    Some(number) => number.parse::<IntegerType>().ok(),
800                    None => Some(index as IntegerType + 1),
801                };
802                for syllable in children(verse, "syl") {
803                    let mut lyric = syllable_of(syllable)?;
804                    if let Some(number) = number {
805                        lyric.set_number(number);
806                    }
807                    lyrics.push(lyric);
808                }
809            }
810            *note.lyrics_mut() = lyrics;
811        }
812        Ok((note, uid))
813    }
814
815    fn note_thing(&mut self, element: &Xml) -> Result<Thing> {
816        let (note, uid) = self.note(element)?;
817        let mut thing = Thing {
818            element: note.into(),
819            uid,
820            search: None,
821            whole_measure: false,
822        };
823        self.tuplet(element, &mut thing)?;
824        Ok(thing)
825    }
826
827    /// music21's `chordFromElement`.
828    fn chord(&mut self, element: &Xml) -> Result<Thing> {
829        let mut notes = Vec::new();
830        for held in children(element, "note") {
831            // A note of a chord takes its own tuplet, as music21 gives it.
832            let thing = self.note_thing(held)?;
833            if let StreamElement::Note(note) = thing.element {
834                notes.push(note);
835            }
836        }
837        let mut chord = Chord::new(notes)?.with_duration(duration_of(
838            length_of(element.get("dur"))?,
839            dots_of(element)?,
840        )?);
841        for held in children(element, "artic") {
842            if let Some(marks) = held.get("artic") {
843                chord.articulations_mut().extend(articulations_of(marks)?);
844            }
845        }
846        let uid = self.uid();
847        self.add_slurs(element, uid)?;
848        if let Some(marks) = element.get("artic") {
849            chord.articulations_mut().extend(articulations_of(marks)?);
850        }
851        if let Some(tie) = self.attribute(element, "tie") {
852            chord.set_tie(Some(tie_of(&tie)));
853        }
854        if element.get("grace").is_some() {
855            let grace = chord
856                .duration()
857                .map(Duration::grace_duration)
858                .unwrap_or_default();
859            chord.set_duration(grace);
860        }
861        if let Some(beam) = self.attribute(element, "m21Beam")
862            && let Some(kind) = chord.duration().and_then(is_beamable)
863        {
864            let mut beams = chord.beams().clone();
865            beams.fill(kind, Some(beam_type_of(&beam)?))?;
866            chord.set_beams(beams);
867        }
868        let mut thing = Thing {
869            element: chord.into(),
870            uid,
871            search: None,
872            whole_measure: false,
873        };
874        self.tuplet(element, &mut thing)?;
875        Ok(thing)
876    }
877
878    /// music21's `restFromElement` and `spaceFromElement`: a rest, hidden
879    /// where it is only space.
880    fn rest(&mut self, element: &Xml, hidden: bool, whole_measure: bool) -> Result<Thing> {
881        let mut rest = Rest::new(duration_of(
882            length_of(element.get("dur"))?,
883            dots_of(element)?,
884        )?);
885        rest.set_hidden(hidden);
886        let mut thing = Thing {
887            element: rest.into(),
888            uid: self.uid(),
889            search: None,
890            whole_measure: whole_measure && element.get("dur").is_none(),
891        };
892        self.tuplet(element, &mut thing)?;
893        Ok(thing)
894    }
895
896    /// What a layer, a beam or a tuplet holds, in order.
897    fn contents(&mut self, element: &Xml, in_layer: bool) -> Result<Vec<Thing>> {
898        let mut things = Vec::new();
899        for held in &element.children {
900            match local(&held.tag) {
901                "clef" => things.push(Thing {
902                    element: clef_element(held)?.into(),
903                    uid: self.uid(),
904                    search: None,
905                    whole_measure: false,
906                }),
907                "chord" => things.push(self.chord(held)?),
908                "note" => things.push(self.note_thing(held)?),
909                "rest" => things.push(self.rest(held, false, false)?),
910                "mRest" if in_layer => things.push(self.rest(held, false, true)?),
911                "space" => things.push(self.rest(held, true, false)?),
912                "mSpace" if in_layer => things.push(self.rest(held, true, true)?),
913                "beam" => {
914                    let mut beamed = self.contents(held, false)?;
915                    beam_together(&mut beamed)?;
916                    things.extend(beamed);
917                }
918                "tuplet" => things.extend(self.tuplet_element(held)?),
919                "bTrem" => things.extend(self.tremolo(held)?),
920                // A barline inside a layer is checked and then has nowhere
921                // to stand.
922                "barLine" => {
923                    let _ = barline_of(held.get("rend").unwrap_or("single"))?;
924                }
925                _ => {}
926            }
927        }
928        Ok(things)
929    }
930
931    /// music21's `tupletFromElement`.
932    fn tuplet_element(&mut self, element: &Xml) -> Result<Vec<Thing>> {
933        let (Some(number), Some(base)) = (element.get("num"), element.get("numbase")) else {
934            return Err(mei_error(
935                "Both @num and @numbase attributes are required on <tuplet> tags.",
936            ));
937        };
938        let read = |text: &str| -> Result<u32> {
939            text.parse()
940                .map_err(|_| mei_error(format!("a tuplet of {text:?} notes")))
941        };
942        let (number, base) = (read(number)?, read(base)?);
943        let mut members = self.contents(element, false)?;
944        for member in &mut members {
945            scale_to_tuplet(&mut member.element, number, base);
946        }
947        let sounding: Vec<usize> = (0..members.len())
948            .filter(|index| is_sounding(&members[*index].element))
949            .collect();
950        let first = *sounding
951            .first()
952            .ok_or_else(|| mei_error("a tuplet with no notes in it"))?;
953        mark_first_tuplet(&mut members[first].element, TupletType::Start);
954        let last = sounding.last().copied().filter(|last| *last != first);
955        mark_first_tuplet(
956            &mut members[last.unwrap_or(first)].element,
957            TupletType::Stop,
958        );
959        beam_together(&mut members)?;
960        Ok(members)
961    }
962
963    /// music21's `bTremFromElement`: notes played as repeated strokes.
964    fn tremolo(&mut self, element: &Xml) -> Result<Vec<Thing>> {
965        let mut things = Vec::new();
966        for held in &element.children {
967            match local(&held.tag) {
968                "chord" => things.push(self.chord(held)?),
969                "note" => things.push(self.note_thing(held)?),
970                _ => {}
971            }
972        }
973        let marks = match element.get("unitdur") {
974            Some("8") => Some(1),
975            Some("16") => Some(2),
976            Some("32") => Some(3),
977            Some("64") => Some(4),
978            Some("128") => Some(5),
979            Some("256") => Some(6),
980            Some("512") => Some(7),
981            Some("1024") => Some(8),
982            _ => None,
983        };
984        if let Some(marks) = marks {
985            for thing in &mut things {
986                let mut tremolo = Ornament::of_kind(OrnamentKind::Tremolo);
987                tremolo.set_number_of_marks(marks)?;
988                let expression = Expression::from(tremolo);
989                match &mut thing.element {
990                    StreamElement::Note(note) => note.expressions_mut().push(expression),
991                    StreamElement::Chord(chord) => chord.expressions_mut().push(expression),
992                    _ => {}
993                }
994            }
995        }
996        Ok(things)
997    }
998
999    /// music21's `layerFromElement`, with `_guessTuplets`: the notes between
1000    /// the two a tuplet span names are in the tuplet too.
1001    fn layer(&mut self, element: &Xml) -> Result<Vec<Thing>> {
1002        let mut things = self.contents(element, true)?;
1003        let mut active: Option<(u32, u32)> = None;
1004        for thing in &mut things {
1005            if !is_sounding(&thing.element) {
1006                continue;
1007            }
1008            let search = thing.search.take();
1009            if let Some(search) = &search
1010                && search.end == "start"
1011            {
1012                active = Some((search.number, search.base));
1013            }
1014            if let Some((number, base)) = active {
1015                scale_to_tuplet(&mut thing.element, number, base);
1016                if search.is_some_and(|search| search.end == "end") {
1017                    mark_first_tuplet(&mut thing.element, TupletType::Stop);
1018                    active = None;
1019                }
1020            }
1021        }
1022        Ok(things)
1023    }
1024
1025    /// music21's `staffDefFromElement`.
1026    fn staff_def(&mut self, element: &Xml) -> Result<StaffDef> {
1027        let instrument = match child(element, "instrDef") {
1028            Some(definition) => Some(match definition.get("midi.instrnum") {
1029                Some(number) => Instrument::from_midi_program(number.parse().map_err(|_| {
1030                    mei_error(format!("the MIDI program {number:?} is no number"))
1031                })?)?,
1032                None => {
1033                    let name = definition.get("midi.instrname");
1034                    name.and_then(|name| Instrument::from_name(name, SearchLanguage::All).ok())
1035                        .unwrap_or_else(|| {
1036                            let mut generic = Instrument::new();
1037                            generic.set_part_name(Some(name.unwrap_or("").to_string()));
1038                            generic
1039                        })
1040                }
1041            }),
1042            None => {
1043                Instrument::from_name(element.get("label").unwrap_or(""), SearchLanguage::All).ok()
1044            }
1045        };
1046        let mut found = StaffDef {
1047            instrument,
1048            ..StaffDef::default()
1049        };
1050        if let Some(instrument) = &mut found.instrument {
1051            instrument.set_part_name(element.get("label").map(str::to_string));
1052            instrument.set_part_abbreviation(element.get("label.abbr").map(str::to_string));
1053            instrument.set_part_id(element.get("n").map(str::to_string));
1054        }
1055        if element.get("trans.semi").is_some() {
1056            found
1057                .instrument
1058                .get_or_insert_with(Instrument::new)
1059                .set_transposition(Some(transposition_of(element)?));
1060        }
1061        if element.get("meter.count").is_some() {
1062            found.meter = Some(meter_of(element)?);
1063        }
1064        if element.get("key.pname").is_some() || element.get("key.sig").is_some() {
1065            found.key = Some(key_of(element)?);
1066        }
1067        if element.get("clef.shape").is_some() {
1068            found.clef = Some(clef_of(
1069                element.get("clef.shape"),
1070                element.get("clef.line"),
1071                element.get("clef.dis"),
1072                element.get("clef.dis.place"),
1073            )?);
1074        }
1075        for held in children(element, "clef") {
1076            found.clef = Some(clef_element(held)?);
1077        }
1078        Ok(found)
1079    }
1080
1081    /// music21's `measureFromElement`: a measure of every part.
1082    fn measure(
1083        &mut self,
1084        element: &Xml,
1085        backup: IntegerType,
1086        parts: &[String],
1087        meter: Option<&TimeSignature>,
1088    ) -> Result<(HashMap<String, Measure>, Option<Barline>)> {
1089        let number = match element.get("n") {
1090            Some(number) => number
1091                .parse()
1092                .map_err(|_| mei_error(format!("the measure number {number:?} is no number")))?,
1093            None => backup,
1094        };
1095        let mut staves: HashMap<String, Measure> = HashMap::new();
1096        let mut waiting: Vec<(String, StaffDef)> = Vec::new();
1097        let mut longest: Option<FloatType> = None;
1098        for held in &element.children {
1099            match local(&held.tag) {
1100                "staff" => {
1101                    let mut voices = Vec::new();
1102                    for (count, layer) in children(held, "layer").enumerate() {
1103                        voices.push(((count + 1).to_string(), self.layer(layer)?));
1104                    }
1105                    let length = voices
1106                        .iter()
1107                        .map(|(_, things)| {
1108                            things
1109                                .iter()
1110                                .map(|thing| thing.element.quarter_length())
1111                                .sum::<FloatType>()
1112                        })
1113                        .fold(0.0, FloatType::max);
1114                    longest = Some(longest.map_or(length, |held| held.max(length)));
1115                    staves.insert(
1116                        held.get("n").unwrap_or("").to_string(),
1117                        Measure {
1118                            number,
1119                            voices,
1120                            own: Vec::new(),
1121                            left: None,
1122                            right: None,
1123                            length: None,
1124                        },
1125                    );
1126                }
1127                "staffDef" => {
1128                    if let Some(name) = held.get("n") {
1129                        waiting.push((name.to_string(), self.staff_def(held)?));
1130                    }
1131                }
1132                _ => {}
1133            }
1134        }
1135        for (name, definition) in waiting {
1136            let measure = staves.get_mut(&name).ok_or_else(|| {
1137                mei_error(format!("a <staffDef> for staff {name}, which is not here"))
1138            })?;
1139            measure.own.extend(definition.elements());
1140        }
1141        // A part with nothing written for this measure rests through it.
1142        for name in parts {
1143            if !staves.contains_key(name) {
1144                let length = longest.ok_or_else(|| mei_error("a measure with no staff in it"))?;
1145                staves.insert(
1146                    name.clone(),
1147                    Measure {
1148                        number,
1149                        voices: vec![(
1150                            "1".to_string(),
1151                            vec![Thing {
1152                                element: Rest::new(Duration::new(length)?).into(),
1153                                uid: self.uid(),
1154                                search: None,
1155                                whole_measure: true,
1156                            }],
1157                        )],
1158                        own: Vec::new(),
1159                        left: None,
1160                        right: None,
1161                        length: None,
1162                    },
1163                );
1164            }
1165        }
1166        // A measure rest lasts as long as the longest staff, or the bar
1167        // where no staff says.
1168        let target = match (longest, meter) {
1169            (Some(longest), Some(meter))
1170                if longest == NO_DURATION && longest != meter.bar_quarter_length() =>
1171            {
1172                Some(meter.bar_quarter_length())
1173            }
1174            (longest, _) => longest,
1175        };
1176        if let Some(target) = target {
1177            for measure in staves.values_mut() {
1178                for (_, things) in &mut measure.voices {
1179                    for thing in things {
1180                        if std::mem::take(&mut thing.whole_measure) {
1181                            let duration = Duration::new(target)?;
1182                            with_duration(&mut thing.element, |held| *held = duration);
1183                            measure.length = Some(target);
1184                        }
1185                    }
1186                }
1187            }
1188        }
1189        let mut next_left = None;
1190        if let Some(left) = element.get("left") {
1191            let (first, second) = barline_of(left)?;
1192            let barline = second.unwrap_or(first);
1193            for measure in staves.values_mut() {
1194                measure.left = Some(barline.clone());
1195            }
1196        }
1197        if let Some(right) = element.get("right") {
1198            let (barline, next) = barline_of(right)?;
1199            next_left = next;
1200            for measure in staves.values_mut() {
1201                measure.right = Some(barline.clone());
1202            }
1203        }
1204        Ok((staves, next_left))
1205    }
1206
1207    /// music21's `sectionScoreCore`: what a `<score>` or a `<section>`
1208    /// holds, part by part.
1209    fn section(
1210        &mut self,
1211        element: &Xml,
1212        parts: &[String],
1213        state: &mut SectionState,
1214    ) -> Result<HashMap<String, Vec<Held>>> {
1215        let in_section = local(&element.tag) == "section";
1216        let mut parsed: HashMap<String, Vec<Held>> = parts
1217            .iter()
1218            .map(|name| (name.clone(), Vec::new()))
1219            .collect();
1220        let mut next: HashMap<String, Vec<StreamElement>> = parts
1221            .iter()
1222            .map(|name| (name.clone(), Vec::new()))
1223            .collect();
1224        for held in &element.children {
1225            match local(&held.tag) {
1226                "measure" if in_section => {
1227                    state.backup += 1;
1228                    let (mut staves, next_left) =
1229                        self.measure(held, state.backup, parts, state.meter.as_ref())?;
1230                    for name in parts {
1231                        let measure = staves
1232                            .get_mut(name)
1233                            .ok_or_else(|| mei_error(format!("no staff {name} in a measure")))?;
1234                        measure
1235                            .own
1236                            .extend(std::mem::take(next.entry(name.clone()).or_default()));
1237                        if let Some(left) = &state.next_left {
1238                            measure.left = Some(left.clone());
1239                        }
1240                        if let Some(measure) = staves.remove(name) {
1241                            parsed
1242                                .entry(name.clone())
1243                                .or_default()
1244                                .push(Held::Measure(Box::new(measure)));
1245                        }
1246                    }
1247                    state.next_left = next_left;
1248                }
1249                "scoreDef" => {
1250                    let mut everywhere: Vec<StreamElement> = Vec::new();
1251                    if held.get("meter.count").is_some() {
1252                        let meter = meter_of(held)?;
1253                        state.meter = Some(meter.clone());
1254                        everywhere.push(meter.into());
1255                    }
1256                    if held.get("key.pname").is_some() || held.get("key.sig").is_some() {
1257                        everywhere.push(StreamElement::Key(key_of(held)?));
1258                    }
1259                    let mut definitions: Vec<&Xml> = Vec::new();
1260                    for group in children(held, "staffGrp") {
1261                        descendants_in_groups(group, &mut definitions);
1262                    }
1263                    let mut own: HashMap<String, StaffDef> = HashMap::new();
1264                    for definition in definitions {
1265                        own.insert(
1266                            definition.get("n").unwrap_or("").to_string(),
1267                            self.staff_def(definition)?,
1268                        );
1269                    }
1270                    for name in parts {
1271                        let waiting = next.entry(name.clone()).or_default();
1272                        waiting.extend(everywhere.iter().cloned());
1273                        if let Some(definition) = own.get(name) {
1274                            waiting.extend(definition.elements());
1275                        }
1276                    }
1277                }
1278                "staffDef" => {
1279                    if let Some(name) = held.get("n") {
1280                        let definition = self.staff_def(held)?;
1281                        if let Some(meter) = &definition.meter {
1282                            state.meter = Some(meter.clone());
1283                        }
1284                        next.get_mut(name)
1285                            .ok_or_else(|| mei_error(format!("a <staffDef> for no part: {name}")))?
1286                            .extend(definition.elements());
1287                    }
1288                }
1289                "section" => {
1290                    let inner = self.section(held, parts, state)?;
1291                    for name in parts {
1292                        let mut list = inner.get(name).cloned().unwrap_or_default();
1293                        let mut waiting = std::mem::take(next.entry(name.clone()).or_default());
1294                        if !waiting.is_empty() {
1295                            // The instrument stands before the measures, and
1296                            // the rest at the start of the first of them.
1297                            if let Some(at) = waiting
1298                                .iter()
1299                                .position(|thing| matches!(thing, StreamElement::Instrument(_)))
1300                                && let StreamElement::Instrument(instrument) = waiting.remove(at)
1301                            {
1302                                list.insert(0, Held::Instrument(instrument));
1303                            }
1304                            if let Some(Held::Measure(first)) = list
1305                                .iter_mut()
1306                                .find(|thing| matches!(thing, Held::Measure(_)))
1307                            {
1308                                first.own.extend(waiting);
1309                            }
1310                        }
1311                        parsed.entry(name.clone()).or_default().extend(list);
1312                    }
1313                }
1314                _ => {}
1315            }
1316        }
1317        Ok(parsed)
1318    }
1319}
1320
1321/// What carries from one section to the next: the meter in force, the
1322/// barline the next measure opens with, and the measure count.
1323#[derive(Default)]
1324struct SectionState {
1325    meter: Option<TimeSignature>,
1326    next_left: Option<Barline>,
1327    backup: IntegerType,
1328}
1329
1330/// The `<staffDef>`s of a group and of the groups inside it.
1331fn descendants_in_groups<'a>(group: &'a Xml, out: &mut Vec<&'a Xml>) {
1332    for held in &group.children {
1333        match local(&held.tag) {
1334            "staffDef" => out.push(held),
1335            "staffGrp" => descendants_in_groups(held, out),
1336            _ => {}
1337        }
1338    }
1339}
1340
1341fn beam_type_of(text: &str) -> Result<BeamType> {
1342    match text {
1343        "start" => Ok(BeamType::Start),
1344        "continue" => Ok(BeamType::Continue),
1345        "stop" => Ok(BeamType::Stop),
1346        other => Err(mei_error(format!("a beam that does {other:?}"))),
1347    }
1348}
1349
1350/// music21's `sylFromElement`: a syllable, with the hyphen its place in the
1351/// word gives it.
1352fn syllable_of(element: &Xml) -> Result<Lyric> {
1353    let text = element
1354        .text()
1355        .ok_or_else(|| mei_error("a <syl> with no text"))?;
1356    let joiner = match element.get("con") {
1357        Some("s") => " ",
1358        Some("d") | None => "-",
1359        Some("t") => "~",
1360        Some("u") => "_",
1361        Some(other) => {
1362            return Err(mei_error(format!("a syllable joined by {other:?}")));
1363        }
1364    };
1365    let (text, syllabic) = match element.get("wordpos") {
1366        Some("i") => (format!("{text}{joiner}"), Some(Syllabic::Begin)),
1367        Some("m") => (format!("{joiner}{text}{joiner}"), Some(Syllabic::Middle)),
1368        Some("t") => (format!("{joiner}{text}"), Some(Syllabic::End)),
1369        None => (text.to_string(), None),
1370        Some(other) => {
1371            return Err(mei_error(format!("a syllable placed at {other:?}")));
1372        }
1373    };
1374    Ok(match syllabic {
1375        Some(syllabic) => {
1376            let mut lyric = Lyric::new(text);
1377            lyric.set_syllabic(syllabic);
1378            lyric
1379        }
1380        None => Lyric::from_raw_text(&text),
1381    })
1382}
1383
1384/// music21's `makeMetadata`: the title, composer and date of the first
1385/// `<work>`.
1386fn metadata_of(root: &Xml) -> Metadata {
1387    let mut metadata = Metadata::new();
1388    let mut works = Vec::new();
1389    descendants(root, "work", &mut works);
1390    let Some(work) = works.first() else {
1391        return metadata;
1392    };
1393    let statement = child(work, "titleStmt");
1394    let mut title: Option<String> = None;
1395    let mut subtitle: Option<String> = None;
1396    for held in statement
1397        .into_iter()
1398        .flat_map(|held| children(held, "title"))
1399    {
1400        let text = held.text().map(str::to_string);
1401        if held.get("type") == Some("subtitle") {
1402            subtitle = text;
1403        } else if title.is_none() {
1404            title = text;
1405        }
1406    }
1407    if let Some(subtitle) = subtitle.filter(|subtitle| !subtitle.is_empty()) {
1408        title = Some(format!(
1409            "{} ({subtitle})",
1410            title.as_deref().unwrap_or("None")
1411        ));
1412    }
1413    if let Some(title) = title {
1414        metadata.add_text("title", title);
1415    }
1416    if let Some(tempo) = child(work, "tempo") {
1417        metadata.add_text("movementName", tempo.text().unwrap_or("None"));
1418    }
1419    let mut composers: Vec<String> = Vec::new();
1420    if let Some(statement) = statement {
1421        for responsibility in children(statement, "respStmt") {
1422            for person in children(responsibility, "persName") {
1423                if person.get("role") == Some("composer")
1424                    && let Some(text) = person.text().filter(|text| !text.is_empty())
1425                {
1426                    composers.push(text.to_string());
1427                }
1428            }
1429        }
1430        for composer in children(statement, "composer") {
1431            let text = composer
1432                .text()
1433                .filter(|text| !text.is_empty())
1434                .or_else(|| child(composer, "persName").and_then(Xml::text));
1435            if let Some(text) = text.filter(|text| !text.is_empty()) {
1436                composers.push(text.to_string());
1437            }
1438        }
1439    }
1440    for composer in composers {
1441        metadata.add_contributor("composer", composer);
1442    }
1443    let date = child(work, "history")
1444        .and_then(|history| child(history, "creation"))
1445        .and_then(|creation| child(creation, "date"));
1446    if let Some(date) = date {
1447        let written = date
1448            .get("isodate")
1449            .filter(|text| !text.is_empty())
1450            .or(date.text().filter(|text| !text.is_empty()));
1451        // A date as music21 writes one: year, month and day, with two
1452        // hyphens for what is not said.
1453        let said = |written: &str| -> Option<String> {
1454            let parts: Vec<&str> = written.split(['-', '/']).collect();
1455            if parts.len() > 3 {
1456                return None;
1457            }
1458            let mut fields = Vec::new();
1459            for (index, part) in parts.iter().enumerate() {
1460                let number: u32 = part.parse().ok()?;
1461                fields.push(if index == 0 {
1462                    format!("{number:04}")
1463                } else {
1464                    format!("{number:02}")
1465                });
1466            }
1467            fields.resize(3, "--".to_string());
1468            Some(fields.join("/"))
1469        };
1470        if let Some(written) = written {
1471            if let Some(date) = said(written) {
1472                metadata.add_text("dateCreated", date);
1473            }
1474        } else {
1475            let start = date.get("notbefore").or(date.get("startdate"));
1476            let end = date.get("notafter").or(date.get("enddate"));
1477            if let (Some(start), Some(end)) = (start, end)
1478                && let (Some(start), Some(end)) = (said(start), said(end))
1479            {
1480                metadata.add_text("dateCreated", format!("{start} to {end}"));
1481            }
1482        }
1483    }
1484    metadata
1485}
1486
1487/// Reads an MEI document into a score: music21's `converter.parse` of one.
1488///
1489/// Every `<staffDef>` number is a part. A measure holds a voice for each
1490/// `<layer>`; a part with no staff in a measure rests through it, and a
1491/// measure rest lasts what the longest staff of its measure lasts. Beams,
1492/// tuplets, ties and slurs are read where they are written on the notes and
1493/// where they stand apart and name the notes by `xml:id`.
1494///
1495/// The text is the document's own, already decoded: the library opens no
1496/// file. A barline written inside a layer is passed over.
1497///
1498/// ```
1499/// use music21_rs::mei::from_mei;
1500///
1501/// let score = from_mei(
1502///     r#"<mei xmlns="http://www.music-encoding.org/ns/mei"><music><score>
1503///     <scoreDef meter.count="2" meter.unit="4">
1504///       <staffGrp><staffDef n="1" clef.shape="G" clef.line="2"/></staffGrp>
1505///     </scoreDef>
1506///     <section><measure n="1"><staff n="1"><layer n="1">
1507///       <note pname="c" oct="4" dur="4"/><note pname="e" oct="4" dur="4" accid="f"/>
1508///     </layer></staff></measure></section>
1509///     </score></music></mei>"#,
1510/// )?;
1511/// let names: Vec<String> = score.parts()[0]
1512///     .pitches()
1513///     .iter()
1514///     .map(|pitch| pitch.name_with_octave())
1515///     .collect();
1516/// assert_eq!(names, ["C4", "Eb4"]);
1517/// # Ok::<(), music21_rs::Error>(())
1518/// ```
1519pub fn from_mei(document: &str) -> Result<Stream> {
1520    let root = Xml::parse(document).map_err(|_| mei_error("MEI document is not valid XML."))?;
1521    if local(&root.tag) != "mei" {
1522        return Err(mei_error(format!(
1523            "Root element should be <mei> in the MEI namespace, not <{}>.",
1524            root.tag
1525        )));
1526    }
1527    let score = child(&root, "music")
1528        .and_then(|music| {
1529            let mut found = Vec::new();
1530            descendants(music, "score", &mut found);
1531            found.first().copied()
1532        })
1533        .ok_or_else(|| mei_error("an MEI document with no <score> in its <music>"))?;
1534
1535    let mut reader = Reader {
1536        extra: HashMap::new(),
1537        slurs: Vec::new(),
1538        next_uid: 0,
1539        next_slur: 0,
1540    };
1541    reader.preprocess(score);
1542
1543    // music21's `allPartsPresent`: every staff number, in the order met.
1544    let mut definitions = Vec::new();
1545    descendants(score, "staffDef", &mut definitions);
1546    let mut parts: Vec<String> = Vec::new();
1547    for definition in definitions {
1548        let name = definition.get("n").unwrap_or("").to_string();
1549        if !parts.contains(&name) {
1550            parts.push(name);
1551        }
1552    }
1553    if parts.is_empty() {
1554        return Err(mei_error(
1555            "There appear to be no <staffDef> tags in this score.",
1556        ));
1557    }
1558
1559    let mut state = SectionState::default();
1560    let parsed = reader.section(score, &parts, &mut state)?;
1561
1562    // The parts, and the place among the score's leaves of every note a
1563    // slur may name.
1564    let mut events = Vec::new();
1565    let mut uids: Vec<Option<usize>> = Vec::new();
1566    for name in &parts {
1567        let mut held = Vec::new();
1568        let mut offset = 0.0;
1569        for thing in parsed.get(name).cloned().unwrap_or_default() {
1570            match thing {
1571                Held::Instrument(instrument) => {
1572                    uids.push(None);
1573                    held.push(StreamEvent::new(offset, *instrument));
1574                }
1575                Held::Measure(measure) => {
1576                    // What stands at the start sorts by its class, ahead of
1577                    // the voices.
1578                    let mut own: Vec<StreamEvent> = measure
1579                        .own
1580                        .into_iter()
1581                        .map(|element| StreamEvent::new(0.0, element))
1582                        .collect();
1583                    own.sort_by_key(|event| event.element().class_sort_order());
1584                    uids.extend(own.iter().map(|_| None));
1585                    let mut length: FloatType = 0.0;
1586                    for (id, things) in measure.voices {
1587                        let mut at = 0.0;
1588                        let mut inner = Vec::new();
1589                        for thing in things {
1590                            uids.push(Some(thing.uid));
1591                            let lasts = thing.element.quarter_length();
1592                            inner.push(StreamEvent::new(at, thing.element));
1593                            at = op_frac(at + lasts);
1594                        }
1595                        length = length.max(at);
1596                        let mut voice = Stream::with_kind(StreamKind::Voice).with_events(inner);
1597                        voice.set_id(Some(id));
1598                        own.push(StreamEvent::new(0.0, voice));
1599                    }
1600                    let mut stream = Stream::with_kind(StreamKind::Measure).with_events(own);
1601                    stream.set_number(measure.number);
1602                    stream.set_left_barline(measure.left);
1603                    stream.set_right_barline(measure.right);
1604                    held.push(StreamEvent::new(offset, stream));
1605                    offset = op_frac(offset + measure.length.unwrap_or(length));
1606                }
1607            }
1608        }
1609        let mut part = Stream::with_kind(StreamKind::Part).with_events(held);
1610        // music21 says an MEI part is at written pitch.
1611        part.set_at_sounding_pitch(Some(false));
1612        events.push(StreamEvent::new(0.0, part));
1613    }
1614    let mut made = Stream::with_kind(StreamKind::Score).with_events(events);
1615    made.set_metadata(Some(metadata_of(&root)));
1616    for (_, joined) in reader.slurs {
1617        let positions: Vec<Option<usize>> = joined
1618            .iter()
1619            .map(|uid| uids.iter().position(|held| *held == Some(*uid)))
1620            .collect();
1621        made.add_spanner(Spanner::with_unplaced(SpannerKind::Slur, positions));
1622    }
1623    Ok(made)
1624}
1625
1626#[cfg(test)]
1627mod tests {
1628    use super::*;
1629
1630    fn document(body: &str) -> String {
1631        format!(
1632            r#"<mei xmlns="http://www.music-encoding.org/ns/mei"><music><score>
1633            <scoreDef meter.count="4" meter.unit="4"><staffGrp>
1634            <staffDef n="1" clef.shape="G" clef.line="2"/>
1635            <staffDef n="2" clef.shape="F" clef.line="4"/>
1636            </staffGrp></scoreDef><section>{body}</section></score></music></mei>"#
1637        )
1638    }
1639
1640    #[test]
1641    fn a_staff_with_nothing_written_rests_through_the_measure() {
1642        let score = from_mei(&document(
1643            r#"<measure n="1"><staff n="1"><layer n="1">
1644            <note pname="c" oct="4" dur="2"/><note pname="d" oct="4" dur="2"/>
1645            </layer></staff></measure>"#,
1646        ))
1647        .unwrap();
1648        let parts = score.parts();
1649        assert_eq!(parts.len(), 2);
1650        let rests: Vec<FloatType> = parts[1]
1651            .recurse()
1652            .into_iter()
1653            .filter(|(_, element)| matches!(element, StreamElement::Rest(_)))
1654            .map(|(_, element)| element.quarter_length())
1655            .collect();
1656        assert_eq!(rests, [4.0]);
1657    }
1658
1659    #[test]
1660    fn a_beam_runs_from_its_first_note_to_its_last() {
1661        let score = from_mei(&document(
1662            r#"<measure n="1"><staff n="1"><layer n="1"><beam>
1663            <note pname="c" oct="4" dur="8"/><note pname="d" oct="4" dur="8"/>
1664            <note pname="e" oct="4" dur="8"/></beam></layer></staff>
1665            <staff n="2"><layer n="1"><mRest/></layer></staff></measure>"#,
1666        ))
1667        .unwrap();
1668        let beams: Vec<Option<BeamType>> = score.parts()[0]
1669            .recurse()
1670            .into_iter()
1671            .filter_map(|(_, element)| match element {
1672                StreamElement::Note(note) => {
1673                    Some(note.beams().by_number(1).and_then(|beam| beam.beam_type()))
1674                }
1675                _ => None,
1676            })
1677            .collect();
1678        assert_eq!(
1679            beams,
1680            [
1681                Some(BeamType::Start),
1682                Some(BeamType::Continue),
1683                Some(BeamType::Stop)
1684            ]
1685        );
1686    }
1687
1688    #[test]
1689    fn a_tuplet_scales_its_notes_and_brackets_them() {
1690        let score = from_mei(&document(
1691            r#"<measure n="1"><staff n="1"><layer n="1"><tuplet num="3" numbase="2">
1692            <note pname="c" oct="4" dur="4"/><note pname="d" oct="4" dur="4"/>
1693            <note pname="e" oct="4" dur="4"/></tuplet></layer></staff></measure>"#,
1694        ))
1695        .unwrap();
1696        let lengths: Vec<FloatType> = score.parts()[0]
1697            .notes()
1698            .into_iter()
1699            .map(|(_, element)| element.quarter_length())
1700            .collect();
1701        assert_eq!(lengths.len(), 3);
1702        assert!(
1703            lengths
1704                .iter()
1705                .all(|length| (length - 2.0 / 3.0).abs() < 1e-9)
1706        );
1707    }
1708
1709    #[test]
1710    fn a_tie_written_apart_names_its_notes() {
1711        let score = from_mei(&document(
1712            r##"<measure n="1"><staff n="1"><layer n="1">
1713            <note xml:id="a" pname="c" oct="4" dur="2"/><note xml:id="b" pname="c" oct="4" dur="2"/>
1714            </layer></staff><tie startid="#a" endid="#b"/></measure>"##,
1715        ))
1716        .unwrap();
1717        let ties: Vec<Option<TieType>> = score.parts()[0]
1718            .notes()
1719            .into_iter()
1720            .filter_map(|(_, element)| match element {
1721                StreamElement::Note(note) => Some(note.tie().map(Tie::tie_type)),
1722                _ => None,
1723            })
1724            .collect();
1725        assert_eq!(ties, [Some(TieType::Start), Some(TieType::Stop)]);
1726    }
1727
1728    #[test]
1729    fn what_is_no_mei_is_refused() {
1730        assert!(from_mei("<score-partwise/>").is_err());
1731        assert!(from_mei("not xml at all").is_err());
1732    }
1733}