package com.xenoage.zong.musicxml.types;
import com.xenoage.utils.annotations.MaybeNull;
import com.xenoage.utils.xml.XmlReader;
import com.xenoage.utils.xml.XmlWriter;
import com.xenoage.zong.musicxml.types.attributes.MxlPrintStyle;
import com.xenoage.zong.musicxml.types.choice.MxlDirectionTypeContent;
import com.xenoage.zong.musicxml.types.enums.MxlNoteTypeValue;
import com.xenoage.zong.musicxml.types.util.MxlPrintStyleContent;
import com.xenoage.zong.musicxml.util.IncompleteMusicXML;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import static com.xenoage.utils.Parser.parseIntegerNull;
/**
* MusicXML metronome.
*
* Currently only the first type (e.g. "♩. = 160")
* of metronome marks is supported. The right part must
* be a number.
* The "♩ = ♩" form is also not supported yet.
* All other metronome elements are ignored.
*
* @author Andreas Wenger
*/
@IncompleteMusicXML(missing = "metronome-note,metronome-relation,parentheses")
@AllArgsConstructor @Getter @Setter
public final class MxlMetronome
implements MxlDirectionTypeContent, MxlPrintStyleContent {
public static final String elemName = "metronome";
private MxlNoteTypeValue beatUnit;
private int dotsCount;
private int perMinute;
private MxlPrintStyle printStyle;
@Override public MxlDirectionTypeContentType getDirectionTypeContentType() {
return MxlDirectionTypeContentType.Metronome;
}
/**
* Returns null, if the given element contains an unsupported metronome type.
*/
@MaybeNull public static MxlMetronome read(XmlReader reader) {
//attributes
MxlPrintStyle printStyle = MxlPrintStyle.read(reader);
//elements
String sBeatUnit = null;
int dotsCount = 0;
Integer perMinute = null;
while (reader.openNextChildElement()) {
String n = reader.getElementName();
switch (n) {
case "beat-unit":
sBeatUnit = reader.getText();
break;
case "beat-unit-dot":
dotsCount++;
break;
case "per-minute":
perMinute = parseIntegerNull(reader.getText());
break;
}
reader.closeElement();
}
if (sBeatUnit != null && perMinute != null) {
MxlNoteTypeValue beatUnit = MxlNoteTypeValue.read(sBeatUnit);
return new MxlMetronome(beatUnit, dotsCount, perMinute, printStyle);
}
else {
return null;
}
}
@Override public void write(XmlWriter writer) {
writer.writeElementStart(elemName);
printStyle.write(writer);
writer.writeElementText("beat-unit", beatUnit.write());
for (int i = 0; i < dotsCount; i++)
writer.writeElementEmpty("beat-unit-dot");
writer.writeElementText("per-minute", perMinute);
writer.writeElementEnd();
}
}