import { LyricWord } from "../../VoiceData/Lyrics/LyricsWord" ; import { VoiceEntry } from "../../VoiceData/VoiceEntry" ; import { IXmlElement } from "../../../Common/FileIO/Xml" ; import { LyricsEntry } from "../../VoiceData/Lyrics/LyricsEntry" ; import { ITextTranslation } from "../../Interfaces/ITextTranslation" ; import { MusicSheet } from "../../MusicSheet" ; export class LyricsReader { private openLyricWords : { [ _ ] : LyricWord ; } = { } ; private currentLyricWord : LyricWord ; private musicSheet : MusicSheet ; constructor ( musicSheet ) { this . musicSheet = musicSheet ; } param { IXmlElement [ ] } lyricNodeList param { VoiceEntry } currentVoiceEntry public addLyricEntry ( lyricNodeList , currentVoiceEntry ) { if ( lyricNodeList ) { const lyricNodeListArr = lyricNodeList ; for ( let idx = 0 , len = lyricNodeListArr . length ; idx < len ; ++ idx ) { const lyricNode = lyricNodeListArr [ idx ] ; try { let syllabic = "single" ; if ( lyricNode . element ( "text" ) ) { let textNode = lyricNode . element ( "text" ) ; if ( lyricNode . element ( "syllabic" ) ) { syllabic = lyricNode . element ( "syllabic" ) . value ; } if ( textNode ) { let text = "" ; const textAndElisionNodes = lyricNode . elements ( ) ; for ( const node of textAndElisionNodes ) { if ( node . name === "text" || node . name === "elision" ) { text += node . value ; } } text = text . replace ( "  " , " " ) ; if ( lyricNode . element ( "elision" ) !== undefined && text === "-" ) { const lyricNodeChildren = lyricNode . elements ( ) ; let elisionIndex = 0 ; for ( let i = 0 ; i < lyricNodeChildren . length ; i ++ ) { const child = lyricNodeChildren [ i ] ; if ( child . name === "elision" ) { elisionIndex = i ; break ; } } let nextText = undefined ; let nextSyllabic = undefined ; if ( elisionIndex > 0 ) { for ( let i = elisionIndex ; i < lyricNodeChildren . length ; i ++ ) { const child = lyricNodeChildren [ i ] ; if ( child . name === "text" ) { nextText = child ; } if ( child . name === "syllabic" ) { nextSyllabic = child ; } } } if ( nextText !== undefined && nextSyllabic ) { textNode = nextText ; syllabic = "middle" ; } } let currentLyricVerseNumber = 1 ; let errorNumberParse1 = false ; if ( lyricNode . attributes ( ) !== undefined && lyricNode . attribute ( "number" ) ) { try { currentLyricVerseNumber = parseInt ( lyricNode . attribute ( "number" ) . value , 10 ) ; } catch ( err ) { errorNumberParse1 = true ; } errorNumberParse1 = errorNumberParse1 || isNaN ( currentLyricVerseNumber ) ; if ( errorNumberParse1 ) { try { const result = lyricNode . attribute ( "number" ) . value . toLowerCase ( ) . split ( "verse" ) ; if ( result . length > 1 ) { currentLyricVerseNumber = parseInt ( result [ 1 ] , 10 ) ; } } catch ( err ) { const errorMsg = ITextTranslation . translateText ( "ReaderErrorMessages/LyricVerseNumberError" , "Invalid lyric verse number" ) ; this . musicSheet . SheetErrors . pushMeasureError ( errorMsg ) ; continue ; } } } let lyricsEntry = undefined ; if ( syllabic === "single" || syllabic === "end" ) { if ( this . openLyricWords [ currentLyricVerseNumber ] ) { this . currentLyricWord = this . openLyricWords [ currentLyricVerseNumber ] ; const syllableNumber = this . currentLyricWord . Syllables . length ; lyricsEntry = new LyricsEntry ( text , currentLyricVerseNumber , this . currentLyricWord , currentVoiceEntry , syllableNumber ) ; this . currentLyricWord . Syllables . push ( lyricsEntry ) ; delete this . openLyricWords [ currentLyricVerseNumber ] ; this . currentLyricWord = undefined ; } else { lyricsEntry = new LyricsEntry ( text , currentLyricVerseNumber , undefined , currentVoiceEntry ) ; } lyricsEntry . extend = lyricNode . element ( "extend" ) !== undefined ; } else if ( syllabic === "begin" ) { if ( this . openLyricWords [ currentLyricVerseNumber ] ) { delete this . openLyricWords [ currentLyricVerseNumber ] ; this . currentLyricWord = undefined ; } this . currentLyricWord = new LyricWord ( ) ; this . openLyricWords [ currentLyricVerseNumber ] = this . currentLyricWord ; lyricsEntry = new LyricsEntry ( text , currentLyricVerseNumber , this . currentLyricWord , currentVoiceEntry , 0 ) ; this . currentLyricWord . Syllables . push ( lyricsEntry ) ; } else if ( syllabic === "middle" ) { if ( this . openLyricWords [ currentLyricVerseNumber ] ) { this . currentLyricWord = this . openLyricWords [ currentLyricVerseNumber ] ; const syllableNumber = this . currentLyricWord . Syllables . length ; lyricsEntry = new LyricsEntry ( text , currentLyricVerseNumber , this . currentLyricWord , currentVoiceEntry , syllableNumber ) ; this . currentLyricWord . Syllables . push ( lyricsEntry ) ; } else { lyricsEntry = new LyricsEntry ( text , currentLyricVerseNumber , undefined , currentVoiceEntry ) ; } } if ( lyricsEntry ) { if ( ! currentVoiceEntry . LyricsEntries [ currentLyricVerseNumber ] ) { currentVoiceEntry . LyricsEntries . setValue ( currentLyricVerseNumber , lyricsEntry ) ; if ( currentVoiceEntry . ParentSourceStaffEntry ?. VerticalContainerParent ?. ParentMeasure ) { currentVoiceEntry . ParentSourceStaffEntry . VerticalContainerParent . ParentMeasure . hasLyrics = true ; } } if ( ! currentVoiceEntry . ParentVoice . Parent . LyricVersesNumbers [ currentLyricVerseNumber ] ) { currentVoiceEntry . ParentVoice . Parent . LyricVersesNumbers . push ( currentLyricVerseNumber ) ; } } } } } catch ( err ) { const errorMsg = ITextTranslation . translateText ( "ReaderErrorMessages/LyricError" , "Error while reading lyric entry." ) ; this . musicSheet . SheetErrors . pushMeasureError ( errorMsg ) ; continue ; } } currentVoiceEntry . ParentVoice . Parent . LyricVersesNumbers = currentVoiceEntry . ParentVoice . Parent . LyricVersesNumbers . filter ( ( lvn , index , self ) => self . indexOf ( lvn ) === index ) ; } } }