package com.xenoage.zong.io.musicxml.in.readers;
import static com.xenoage.utils.collections.CollectionUtils.alist;
import static com.xenoage.utils.iterators.It.it;
import static com.xenoage.zong.core.text.UnformattedText.ut;
import java.util.List;
import lombok.RequiredArgsConstructor;
import com.xenoage.utils.Parser;
import com.xenoage.zong.commands.core.music.lyric.LyricAdd;
import com.xenoage.zong.core.music.chord.Chord;
import com.xenoage.zong.core.music.lyric.Lyric;
import com.xenoage.zong.core.music.lyric.SyllableType;
import com.xenoage.zong.musicxml.types.MxlLyric;
import com.xenoage.zong.musicxml.types.MxlNote;
import com.xenoage.zong.musicxml.types.MxlSyllabicText;
import com.xenoage.zong.musicxml.types.choice.MxlLyricContent.MxlLyricContentType;
/**
* Reads {@link Lyric}s from {@link MxlLyric} elements of {@link MxlNote}s.
*
* @author Andreas Wenger
*/
@RequiredArgsConstructor
public class LyricReader {
private final List<MxlNote> mxlNotes;
public void readToChord(Chord chord) {
List<Lyric> lyrics = readLyrics();
for (Lyric lyric : lyrics)
new LyricAdd(lyric, chord).execute();
}
private List<Lyric> readLyrics() {
//not supported yet: in MusicXML also rests can have lyrics. see measure 36 in Echigo-Jishi
List<Lyric> ret = alist();
for (MxlNote mxlNote : mxlNotes) {
for (MxlLyric mxlLyric : it(mxlNote.getLyrics())) {
int verse = readVerse(mxlLyric);
MxlLyricContentType mxlLCType = mxlLyric.getContent().getLyricContentType();
if (mxlLCType == MxlLyricContentType.SyllabicText) {
MxlSyllabicText mxlSyllabicText = (MxlSyllabicText) mxlLyric.getContent();
SyllableType syllableType = readSyllableType(mxlLyric);
//the next element must be the text element
ret.add(new Lyric(ut(mxlSyllabicText.getText().getValue()), syllableType, verse));
}
else if (mxlLCType == MxlLyricContentType.Extend) {
//extend - TODO: extension to next chord!
ret.add(Lyric.lyricExtend(verse));
}
}
}
return ret;
}
private int readVerse(MxlLyric mxlLyric) {
//not supported yet: number which are not integer and
//name instead of or additional to the number attribute (see MusicXML Test 61g)
String number = mxlLyric.getNumber();
if (number != null) {
Integer i = Parser.parseIntegerNull(number);
if (i != null)
return i - 1;
}
return 0;
}
private SyllableType readSyllableType(MxlLyric mxlLyric) {
MxlSyllabicText mxlSyllabicText = (MxlSyllabicText) mxlLyric.getContent();
//a syllable
switch (mxlSyllabicText.getSyllabic()) {
case Single:
return SyllableType.Single;
case Begin:
return SyllableType.Begin;
case Middle:
return SyllableType.Middle;
case End:
return SyllableType.End;
}
return null;
}
}