public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            ClefType typeOfClef = ClefType.GClef;
            int      line       = 1;

            element.IfElement("sign").HasValue(new Dictionary <string, ClefType> {
                { "G", ClefType.GClef },
                { "C", ClefType.CClef },
                { "F", ClefType.FClef },
                { "percussion", ClefType.Percussion }
            }).Then(v => typeOfClef = v);
            element.IfElement("line").HasValue <int>().Then(v => line = v).Otherwise(s =>
            {
                if (typeOfClef == ClefType.Percussion)
                {
                    line = 2;
                }
            });

            var clef = new Clef(typeOfClef, line);

            element.IfAttribute("number").HasValue <int>().Then(v => clef.Staff = staff.Part.Staves.ElementAt(v - 1));
            element.IfElement("clef-octave-change").HasValue <int>().Then(c => clef.OctaveChange = c);

            var correctStaff = clef.Staff ?? staff;

            correctStaff.Elements.Add(clef);
        }
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            int numberOfBeats       = 4;
            int beatType            = 4;
            TimeSignatureType sType = TimeSignatureType.Numbers;

            element.IfElement("beats").HasValue <int>().Then(v => numberOfBeats = v);
            element.IfElement("beat-type").HasValue <int>().Then(v => beatType  = v);
            element.IfAttribute("symbol").HasValue(new Dictionary <string, TimeSignatureType> {
                { "common", TimeSignatureType.Common },
                { "cut", TimeSignatureType.Cut }
            }).Then(s => sType = s);

            if (staff.Part != null && staff.Part.Staves.Any())  //If part contains many staves, add to all staves
            {
                foreach (var s in staff.Part.Staves)
                {
                    var t = new TimeSignature(sType, numberOfBeats, beatType);
                    s.Elements.Add(t);
                }
            }
            else
            {
                var t = new TimeSignature(sType, numberOfBeats, beatType);
                staff.Elements.Add(t);
            }
        }
Пример #3
0
 public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
 {
     foreach (XElement measureStyleAttribute in element.Elements())
     {
         if (measureStyleAttribute.Name == "multiple-rest")
         {
             state.SkipMeasures = Convert.ToInt32(measureStyleAttribute.Value) - 1;
         }
     }
 }
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            var directionTypeNode = element.Elements().FirstOrDefault(e => e.Name.LocalName == "direction-type");

            if (directionTypeNode == null)
            {
                return;
            }

            foreach (var directionDefinitionNode in directionTypeNode.Elements())
            {
                Direction dir = new Direction();
                dir.DefaultYPosition = 0;
                dir.Placement        = DirectionPlacementType.Above;

                directionDefinitionNode.IfAttribute("default-y").HasValue <int>().Then(v =>
                {
                    dir.DefaultYPosition = v;
                    dir.Placement        = DirectionPlacementType.Custom;
                });

                //Placement can suposedly be set both on direction-type node and it's subnodes:
                directionTypeNode.IfAttribute("placement")
                .HasValue <DirectionPlacementType>(d =>
                {
                    d.Add("above", DirectionPlacementType.Above);
                    d.Add("below", DirectionPlacementType.Below);
                    return(d);
                })
                .Then(v => dir.Placement = v);

                directionDefinitionNode.IfAttribute("placement")
                .HasValue <DirectionPlacementType>(d =>
                {
                    d.Add("above", DirectionPlacementType.Above);
                    d.Add("below", DirectionPlacementType.Below);
                    return(d);
                })
                .Then(v => dir.Placement = v);

                switch (directionDefinitionNode.Name.LocalName)
                {
                case "dynamics":
                    dir.Text = directionTypeNode.Elements().FirstOrDefault()?.Name.LocalName;
                    break;

                case "words":
                    dir.Text = directionTypeNode.Value;
                    break;
                }

                staff.Elements.Add(dir);
            }
        }
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            var b = new Barline();

            element.IfAttribute("location").HasValue("left")
            .Then(() => b.Location     = HorizontalPlacement.Left)
            .Otherwise(r => b.Location = HorizontalPlacement.Right);

            element.IfElement("bar-style").HasValue("light-heavy").Then(() => b.Style = BarlineStyle.LightHeavy);
            element.IfElement("bar-style").HasValue("none").Then(() => b.Style        = BarlineStyle.None);
            element.IfElement("bar-style").HasValue("dashed").Then(() => b.Style      = BarlineStyle.Dashed);
            var repeatAttribute = element.Elements().FirstOrDefault(e => e.Name == "repeat");
            var attribute       = repeatAttribute?.Attributes().FirstOrDefault(a => a.Name == "direction");

            bool add = false;

            if (attribute != null)
            {
                if (attribute.Value == "forward")
                {
                    b.RepeatSign = RepeatSignType.Forward;
                }
                else if (attribute.Value == "backward")
                {
                    b.RepeatSign = RepeatSignType.Backward;
                    state.BarlineAlreadyAdded = true;
                }
                add = true;
            }
            else if (b.Style != BarlineStyle.Regular)
            {
                state.BarlineAlreadyAdded = true;
                add = true;
            }

            if (add)
            {
                if (staff.Part?.Staves.Any() ?? false)  //If part contains many staves, add to all staves
                {
                    foreach (var s in staff.Part.Staves)
                    {
                        s.Elements.Add(b);
                    }
                }
                else
                {
                    staff.Elements.Add(b);
                }
            }
        }
Пример #6
0
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            var b = new Barline();

            element.IfAttribute("location").HasValue("left")
            .Then(() => b.Location      = HorizontalPlacement.Left)
            .Otherwise(() => b.Location = HorizontalPlacement.Right);

            element.IfElement("bar-style").HasValue("light-heavy").Then(() => b.Style = BarlineStyle.LightHeavy);

            foreach (XElement barlineAttribute in element.Elements())
            {
                if (barlineAttribute.Name == "repeat")
                {
                    var attribute = barlineAttribute.Attribute("direction");
                    if (attribute != null)
                    {
                        if (attribute.Value == "forward")
                        {
                            b.RepeatSign = RepeatSignType.Forward;
                        }
                        else if (attribute.Value == "backward")
                        {
                            b.RepeatSign = RepeatSignType.Backward;
                            state.BarlineAlreadyAdded = true;
                        }

                        //Usuń pojedynczą kreskę taktową, jeśli już taka została dodana:
                        //Barline existingBarline = staff.Elements.LastOrDefault() as Barline;
                        //if (existingBarline != null) staff.Elements.Remove(existingBarline);

                        if (staff.Part != null && staff.Part.Staves.Any())  //If part contains many staves, add to all staves
                        {
                            foreach (var s in staff.Part.Staves)
                            {
                                s.Elements.Add(b);
                            }
                        }
                        else
                        {
                            staff.Elements.Add(b);
                        }
                    }
                }
            }
        }
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            XElement elementNode = element.Parent;

            foreach (XElement directionTypeNode in element.Elements())
            {
                if (directionTypeNode.Name == "dynamics")
                {
                    DirectionPlacementType placement = DirectionPlacementType.Above;
                    int    defaultY  = 0;
                    string text      = "";
                    var    attribute = elementNode.Attribute(XName.Get("default-y"));
                    if (attribute != null)
                    {
                        defaultY  = Convert.ToInt32(attribute.Value);
                        placement = DirectionPlacementType.Custom;
                    }
                    attribute = elementNode.Attribute(XName.Get("placement"));
                    if (attribute != null && placement != DirectionPlacementType.Custom)
                    {
                        if (attribute.Value == "above")
                        {
                            placement = DirectionPlacementType.Above;
                        }
                        else if (attribute.Value == "below")
                        {
                            placement = DirectionPlacementType.Below;
                        }
                    }
                    foreach (XElement dynamicsType in directionTypeNode.Elements())
                    {
                        text = dynamicsType.Name.LocalName;
                    }
                    Direction dir = new Direction();
                    dir.DefaultY  = defaultY;
                    dir.Placement = placement;
                    dir.Text      = text;
                    staff.Elements.Add(dir);
                }
            }
        }
Пример #8
0
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            ClefType typeOfClef = ClefType.GClef;
            int      line       = 1;

            element.IfElement("sign").HasValue(new Dictionary <string, ClefType> {
                { "G", ClefType.GClef },
                { "C", ClefType.CClef },
                { "F", ClefType.FClef }
            }).Then(v => typeOfClef = v);
            element.IfElement("line").HasValue <int>().Then(v => line = v);

            var clef = new Clef(typeOfClef, line);

            element.IfAttribute("number").HasValue <int>().Then(v => clef.Staff = staff.Score.Staves.ElementAt(v - 1)); //TODO: Sprawdzić czy staff to numer liczony od góry strony czy numer w obrębie parta
            element.IfElement("clef-octave-change").HasValue <int>().Then(c => clef.OctaveChange = c);

            var correctStaff = clef.Staff ?? staff;

            correctStaff.Elements.Add(clef);
        }
Пример #9
0
 public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
 {
     foreach (XElement keyAttribute in element.Elements())
     {
         if (keyAttribute.Name == "fifths")
         {
             if (staff.Part != null && staff.Part.Staves.Any())  //If part contains many staves, add to all staves
             {
                 foreach (var s in staff.Part.Staves)
                 {
                     var key = new Key(Convert.ToInt16(keyAttribute.Value));
                     s.Elements.Add(key);
                 }
             }
             else
             {
                 var key = new Key(Convert.ToInt16(keyAttribute.Value));
                 staff.Elements.Add(key);
             }
         }
     }
 }
Пример #10
0
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            var elementList = element.Elements().ToList();

            //Element "staves" must be the first element:
            var stavesElement = elementList.FirstOrDefault(e => e.Name == "staves");

            if (stavesElement != null)
            {
                elementList.Remove(stavesElement);
                elementList.Insert(0, stavesElement);
            }

            var attributePriorities = new[] { "clef", "key", "time" }.ToList();

            foreach (XElement attribute in elementList.OrderBy(k => attributePriorities.IndexOf(k.Name.LocalName)))
            {
                MusicXmlParsingStrategy parsingStrategy = GetProperStrategy(attribute);
                if (parsingStrategy != null)
                {
                    parsingStrategy.ParseElement(state, staff, attribute);
                }
            }
        }
Пример #11
0
 public abstract void ParseElement(MusicXmlParserState state, Staff staff, XElement element);
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            var directionTypeNode = element.Elements().FirstOrDefault(e => e.Name.LocalName == "direction-type");

            if (directionTypeNode == null)
            {
                return;
            }
            DirectionPlaybackEffect playbackEffect = new DirectionPlaybackEffect();
            var soundNode = element.Elements().FirstOrDefault(e => e.Name.LocalName == "sound");

            if (soundNode != null)
            {
                soundNode.IfAttribute("tempo").HasValue <int>().Then(v => playbackEffect.Tempo    = new Tempo(RhythmicDuration.Quarter, v));
                soundNode.IfAttribute("fine").HasAnyValue().Then(v => playbackEffect.IsFine       = v == "yes");
                soundNode.IfAttribute("dalsegno").HasAnyValue().Then(v => playbackEffect.DalSegno = v);
            }

            foreach (var directionDefinitionNode in directionTypeNode.Elements())
            {
                Direction dir = new Direction();
                dir.PlaybackEffect   = playbackEffect;
                dir.DefaultYPosition = 0;
                dir.Placement        = DirectionPlacementType.Above;

                directionDefinitionNode.IfAttribute("default-y").HasValue <int>().Then(v =>
                {
                    dir.DefaultYPosition = v;
                    dir.Placement        = DirectionPlacementType.Custom;
                });

                //Placement can suposedly be set both on direction-type node and it's subnodes:
                directionTypeNode.IfAttribute("placement")
                .HasValue <DirectionPlacementType>(d =>
                {
                    d.Add("above", DirectionPlacementType.Above);
                    d.Add("below", DirectionPlacementType.Below);
                    return(d);
                })
                .Then(v => dir.Placement = v);

                directionDefinitionNode.IfAttribute("placement")
                .HasValue <DirectionPlacementType>(d =>
                {
                    d.Add("above", DirectionPlacementType.Above);
                    d.Add("below", DirectionPlacementType.Below);
                    return(d);
                })
                .Then(v => dir.Placement = v);

                switch (directionDefinitionNode.Name.LocalName)
                {
                case "dynamics":
                    dir.Text = directionTypeNode.Elements().FirstOrDefault()?.Name.LocalName;
                    break;

                case "words":
                    dir.Text = directionTypeNode.Value;
                    break;
                }

                staff.Elements.Add(dir);
            }
        }
Пример #13
0
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            var builder = new NoteOrRestBuilder(state);

            element.IfAttribute("default-x").HasValue <double>().Then(m => builder.DefaultX = m);
            element.IfAttribute("measure").HasValue("yes").Then(m => builder.FullMeasure    = true);
            element.IfAttribute("print-object").HasValue(new Dictionary <string, bool> {
                { "yes", true }, { "no", false }
            }).Then(m => builder.IsVisible = m);
            element.IfAttribute("size").HasValue(new Dictionary <string, NoteOrRestSize>
            {
                { "cue", NoteOrRestSize.Cue },
                { "full", NoteOrRestSize.Full },
                { "large", NoteOrRestSize.Large },
            }).Then(s => builder.Size = s);
            element.IfElement("staff").HasValue <int>().Then(m => builder.Staff = staff.Part.Staves.ElementAt(m - 1));
            element.IfElement("type").HasValue(new Dictionary <string, RhythmicDuration> {
                { "breve", RhythmicDuration.DoubleWhole },
                { "whole", RhythmicDuration.Whole },
                { "half", RhythmicDuration.Half },
                { "quarter", RhythmicDuration.Quarter },
                { "eighth", RhythmicDuration.Eighth },
                { "16th", RhythmicDuration.Sixteenth },
                { "32nd", RhythmicDuration.D32nd },
                { "64th", RhythmicDuration.D64th },
                { "128th", RhythmicDuration.D128th }
            }).Then(m => builder.BaseDuration = m);
            var typeElement = element.GetElement("type");

            if (typeElement != null)
            {
                typeElement.IfAttribute("size").HasValue(new Dictionary <string, NoteOrRestSize>
                {
                    { "cue", NoteOrRestSize.Cue },
                    { "full", NoteOrRestSize.Full },
                    { "large", NoteOrRestSize.Large },
                }).Then(s => builder.Size = s);   //"size" attribute apparently can be added to element "type" too
            }

            element.IfElement("voice").HasValue <int>().Then(m => builder.Voice = m);
            var graceElement = element.GetElement("grace");

            if (graceElement != null)
            {
                graceElement.IfAttribute("slash").HasValue("yes")
                .Then(v => builder.GraceNoteType      = GraceNoteType.Slashed)
                .Otherwise(v => builder.GraceNoteType = GraceNoteType.Simple);
            }
            element.IfElement("chord").Exists().Then(() => builder.IsChordElement             = true);
            element.IfElement("accidental").HasValue("natural").Then(() => builder.HasNatural = true);
            element.IfElement("rest").Exists().Then(() => builder.IsRest = true);
            element.ForEachDescendant("dot", f => f.Exists().Then(() => builder.NumberOfDots++));

            var pitchElement = element.IfElement("pitch").Exists().ThenReturnResult();

            pitchElement.IfElement("step").HasAnyValue().Then(v => builder.Step        = v);
            pitchElement.IfElement("octave").HasValue <int>().Then(v => builder.Octave = v);
            pitchElement.IfElement("alter").HasValue <int>().Then(v => builder.Alter   = v);

            var unpitchedElement = element.IfElement("unpitched").Exists().Then(x => builder.IsUnpitched = true).AndReturnResult();

            unpitchedElement.IfElement("display-step").HasAnyValue().Then(v => builder.Step        = v);
            unpitchedElement.IfElement("display-octave").HasValue <int>().Then(v => builder.Octave = v);
            unpitchedElement.IfElement("display-alter").HasValue <int>().Then(v => builder.Alter   = v);

            var tieElements = element.Elements().Where(e => e.Name == "tie");

            foreach (var tieElement in tieElements)
            {
                tieElement.IfAttribute("type").HasValue("start").Then(v =>
                {
                    if (builder.TieType == NoteTieType.Stop)
                    {
                        builder.TieType = NoteTieType.StopAndStartAnother;
                    }
                    else
                    {
                        builder.TieType = NoteTieType.Start;
                    }
                }).Otherwise(r => builder.TieType = NoteTieType.Stop);
            }

            element.IfElement("stem").HasValue("down")
            .Then(() => builder.StemDirection     = VerticalDirection.Down)
            .Otherwise(r => builder.StemDirection = VerticalDirection.Up);
            element.GetElement("stem").IfAttribute("default-y").HasValue <float>().Then(v =>
            {
                builder.StemDefaultY          = v;
                builder.CustomStemEndPosition = true;
            });

            element.ForEachDescendant("beam", h => h.HasValue(new Dictionary <string, NoteBeamType> {
                { "begin", NoteBeamType.Start },
                { "end", NoteBeamType.End },
                { "continue", NoteBeamType.Continue },
                { "forward hook", NoteBeamType.ForwardHook },
                { "backward hook", NoteBeamType.BackwardHook }
            }).Then(v => builder.BeamList.Add(v))
                                      .Otherwise(r => { if (r.ToLowerInvariant() != "single")
                                                        {
                                                            throw new ScoreException(builder, $"Unsupported beam type \"{r}\".");
                                                        }
                                                 }));

            var notationsNode = element.GetElement("notations");
            var tupletNode    = notationsNode.GetElement("tuplet");

            tupletNode.IfAttribute("type").HasValue(new Dictionary <string, TupletType> {
                { "start", TupletType.Start },
                { "stop", TupletType.Stop },
            }).Then(v => builder.Tuplet = v);
            tupletNode.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                { "above", VerticalPlacement.Above },
                { "below", VerticalPlacement.Below },
            }).Then(v => builder.TupletPlacement = v);

            notationsNode.IfElement("fermata").Exists().Then(() => builder.HasFermataSign = true);
            notationsNode.IfElement("sound").Exists().Then(e => e.IfAttribute("dynamics").HasValue <int>().Then(v => state.CurrentDynamics = v));

            notationsNode.IfHasElement("dynamics").Then(d =>
            {
                var dir = new Direction();
                d.IfAttribute("default-y").HasValue <int>().Then(v =>
                {
                    dir.DefaultYPosition = v;
                    dir.Placement        = DirectionPlacementType.Custom;
                });
                d.IfAttribute("placement").HasValue(new Dictionary <string, DirectionPlacementType>
                {
                    { "above", DirectionPlacementType.Above },
                    { "below", DirectionPlacementType.Below }
                }).Then(v =>
                {
                    if (dir.Placement != DirectionPlacementType.Custom)
                    {
                        dir.Placement = v;
                    }
                });
                foreach (XElement dynamicsType in d.Elements())
                {
                    dir.Text = dynamicsType.Name.LocalName;
                }
                staff.Elements.Add(dir);
            });

            notationsNode.IfHasElement("articulations").Then(d =>
            {
                d.IfElement("staccato").HasAnyValue().Then(() => builder.Articulation = ArticulationType.Staccato);
                d.IfElement("accent").HasAnyValue().Then(() => builder.Articulation   = ArticulationType.Accent);
                d.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                    { "above", VerticalPlacement.Above },
                    { "below", VerticalPlacement.Below },
                }).Then(v => builder.ArticulationPlacement = v);
            });

            var ornamentsNode = notationsNode.GetElement("ornaments");

            ornamentsNode.GetElement("trill-mark").IfAttribute("placement").HasValue(new Dictionary <string, NoteTrillMark> {
                { "above", NoteTrillMark.Above },
                { "below", NoteTrillMark.Below }
            }).Then(v => builder.TrillMark = v);
            ornamentsNode.IfElement("tremolo").HasValue <int>().Then(v => builder.TremoloLevel = v);

            var invMordentNode = ornamentsNode
                                 .IfElement("inverted-mordent")
                                 .Exists()
                                 .Then(e => builder.Mordent = new Mordent()
            {
                IsInverted = true
            })
                                 .AndReturnResult();

            invMordentNode.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                { "above", VerticalPlacement.Above },
                { "below", VerticalPlacement.Below }
            }).Then(v => builder.Mordent.Placement = v);
            invMordentNode.IfAttribute("default-x").HasValue <double>().Then(v => builder.Mordent.DefaultXPosition = v);
            invMordentNode.IfAttribute("default-y").HasValue <double>().Then(v => builder.Mordent.DefaultYPosition = v);

            foreach (var slurNode in notationsNode?.Elements().Where(e => e.Name == "slur") ?? new XElement[] { })
            {
                var slur = new Slur();
                builder.Slurs.Add(slur);
                slurNode.IfAttribute("number").HasValue <int>().Then(v => slur.Number = v);
                slurNode.IfAttribute("type").HasValue(new Dictionary <string, NoteSlurType> {
                    { "start", NoteSlurType.Start },
                    { "stop", NoteSlurType.Stop }
                }).Then(v => slur.Type = v);
                slurNode.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                    { "above", VerticalPlacement.Above },
                    { "below", VerticalPlacement.Below }
                }).Then(v => slur.Placement = v);
                slurNode.IfAttribute("default-x").HasValue <double>().Then(v => slur.DefaultXPosition = v);
                slurNode.IfAttribute("default-y").HasValue <double>().Then(v => slur.DefaultYPosition = v);
                slurNode.IfAttribute("bezier-x").HasValue <double>().Then(v => slur.BezierX           = v);
                slurNode.IfAttribute("bezier-y").HasValue <double>().Then(v => slur.BezierY           = v);
            }

            foreach (var lNode in element.Elements().Where(n => n.Name == "lyric"))
            {
                //There can be more than one lyrics in one <lyrics> tag. Add lyrics to list once syllable type and text is set.
                //Then reset these tags so the next <syllabic> tag starts another lyric.
                Lyrics          lyricsInstance    = new Lyrics();
                Lyrics.Syllable syllable          = new Lyrics.Syllable();
                bool            isSylabicSet      = false;
                bool            isTextSet         = false;
                var             defaultYattribute = lNode.Attributes().FirstOrDefault(a => a.Name == "default-y");
                if (defaultYattribute != null)
                {
                    lyricsInstance.DefaultYPosition = UsefulMath.TryParse(defaultYattribute.Value);
                }

                foreach (XElement lyricAttribute in lNode.Elements())
                {
                    if (lyricAttribute.Name == "syllabic")
                    {
                        if (lyricAttribute.Value == "begin")
                        {
                            syllable.Type = SyllableType.Begin;
                        }
                        else if (lyricAttribute.Value == "middle")
                        {
                            syllable.Type = SyllableType.Middle;
                        }
                        else if (lyricAttribute.Value == "end")
                        {
                            syllable.Type = SyllableType.End;
                        }
                        else if (lyricAttribute.Value == "single")
                        {
                            syllable.Type = SyllableType.Single;
                        }
                        isSylabicSet = true;
                    }
                    else if (lyricAttribute.Name == "text")
                    {
                        syllable.Text = lyricAttribute.Value;
                        isTextSet     = true;
                    }
                    else if (lyricAttribute.Name == "elision")
                    {
                        syllable.ElisionMark = lyricAttribute.Value;
                    }

                    if (isSylabicSet && isTextSet)
                    {
                        lyricsInstance.Syllables.Add(syllable);
                        syllable     = new Lyrics.Syllable();
                        isSylabicSet = false;
                        isTextSet    = false;
                    }
                }

                builder.Lyrics.Add(lyricsInstance);
            }

            if (builder.BeamList.Count == 0)
            {
                builder.BeamList.Add(NoteBeamType.Single);
            }

            var noteOrRest = builder.Build();

            var correctStaff = noteOrRest.Staff ?? staff;

            correctStaff.Elements.Add(noteOrRest);
        }
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            var builder = new NoteOrRestBuilder(state);

            element.IfAttribute("default-x").HasValue <double>().Then(m => builder.DefaultX = m);
            element.IfAttribute("measure").HasValue("yes").Then(m => builder.FullMeasure    = true);
            element.IfAttribute("print-object").HasValue(new Dictionary <string, bool> {
                { "yes", true }, { "no", false }
            }).Then(m => builder.IsVisible = m);
            element.IfAttribute("size").HasValue("cue").Then(() => builder.IsCueNote = true);
            element.IfElement("staff").HasValue <int>().Then(m => builder.Staff      = staff.Score.Staves.ElementAt(m - 1));       //TODO: Sprawdzić czy staff to numer liczony od góry strony czy numer w obrębie parta
            element.IfElement("type").HasValue(new Dictionary <string, RhythmicDuration> {
                { "whole", RhythmicDuration.Whole },
                { "half", RhythmicDuration.Half },
                { "quarter", RhythmicDuration.Quarter },
                { "eighth", RhythmicDuration.Eighth },
                { "16th", RhythmicDuration.Sixteenth },
                { "32nd", RhythmicDuration.D32nd },
                { "64th", RhythmicDuration.D64th },
                { "128th", RhythmicDuration.D128th }
            }).Then(m => builder.BaseDuration = m);

            element.IfElement("voice").HasValue <int>().Then(m => builder.Voice               = m);
            element.IfElement("grace").Exists().Then(() => builder.IsGraceNote                = true);
            element.IfElement("chord").Exists().Then(() => builder.IsChordElement             = true);
            element.IfElement("accidental").HasValue("natural").Then(() => builder.HasNatural = true);
            element.IfElement("rest").Exists().Then(() => builder.IsRest = true);
            element.ForEachDescendant("dot", f => f.Exists().Then(() => builder.NumberOfDots++));

            var pitchElement = element.IfElement("pitch").Exists().ThenReturnResult();

            pitchElement.IfElement("step").HasAnyValue().Then(v => builder.Step        = v);
            pitchElement.IfElement("octave").HasValue <int>().Then(v => builder.Octave = v);
            pitchElement.IfElement("alter").HasValue <int>().Then(v => builder.Alter   = v);

            var tieElements = element.Elements().Where(e => e.Name == "tie");

            foreach (var tieElement in tieElements)
            {
                tieElement.IfAttribute("type").HasValue("start").Then(v =>
                {
                    if (builder.TieType == NoteTieType.Stop)
                    {
                        builder.TieType = NoteTieType.StopAndStartAnother;
                    }
                    else
                    {
                        builder.TieType = NoteTieType.Start;
                    }
                }).Otherwise(() => builder.TieType = NoteTieType.Stop);
            }

            element.IfElement("stem").HasValue("down")
            .Then(() => builder.StemDirection      = VerticalDirection.Down)
            .Otherwise(() => builder.StemDirection = VerticalDirection.Up);
            element.GetElement("stem").IfAttribute("default-y").HasValue <float>().Then(v =>
            {
                builder.StemDefaultY          = v;
                builder.CustomStemEndPosition = true;
            });

            element.ForEachDescendant("beam", h => h.HasValue(new Dictionary <string, NoteBeamType> {
                { "begin", NoteBeamType.Start },
                { "end", NoteBeamType.End },
                { "continue", NoteBeamType.Continue },
                { "forward hook", NoteBeamType.ForwardHook },
                { "backward hook", NoteBeamType.BackwardHook }
            }).Then(v => builder.BeamList.Add(v)));

            var notationsNode = element.GetElement("notations");
            var tupletNode    = notationsNode.GetElement("tuplet");

            tupletNode.IfAttribute("type").HasValue(new Dictionary <string, TupletType> {
                { "start", TupletType.Start },
                { "stop", TupletType.Stop },
            }).Then(v => builder.Tuplet = v);
            tupletNode.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                { "above", VerticalPlacement.Above },
                { "below", VerticalPlacement.Below },
            }).Then(v => builder.TupletPlacement = v);

            notationsNode.IfElement("fermata").HasAnyValue().Then(() => builder.HasFermataSign = true);
            notationsNode.IfElement("sound").Exists().Then(e => e.IfAttribute("dynamics").HasValue <int>().Then(v => state.CurrentDynamics = v));

            notationsNode.IfHasElement("dynamics").Then(d =>
            {
                var dir = new Direction();
                d.IfAttribute("default-y").HasValue <int>().Then(v =>
                {
                    dir.DefaultYPosition = v;
                    dir.Placement        = DirectionPlacementType.Custom;
                });
                d.IfAttribute("placement").HasValue(new Dictionary <string, DirectionPlacementType>
                {
                    { "above", DirectionPlacementType.Above },
                    { "below", DirectionPlacementType.Below }
                }).Then(v =>
                {
                    if (dir.Placement != DirectionPlacementType.Custom)
                    {
                        dir.Placement = v;
                    }
                });
                foreach (XElement dynamicsType in d.Elements())
                {
                    dir.Text = dynamicsType.Name.LocalName;
                }
                staff.Elements.Add(dir);
            });

            notationsNode.IfHasElement("articulations").Then(d =>
            {
                d.IfElement("staccato").HasAnyValue().Then(() => builder.Articulation = ArticulationType.Staccato);
                d.IfElement("accent").HasAnyValue().Then(() => builder.Articulation   = ArticulationType.Accent);
                d.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                    { "above", VerticalPlacement.Above },
                    { "below", VerticalPlacement.Below },
                }).Then(v => builder.ArticulationPlacement = v);
            });

            var ornamentsNode = notationsNode.GetElement("ornaments");

            ornamentsNode.GetElement("trill-mark").IfAttribute("placement").HasValue(new Dictionary <string, NoteTrillMark> {
                { "above", NoteTrillMark.Above },
                { "below", NoteTrillMark.Below }
            }).Then(v => builder.TrillMark = v);
            ornamentsNode.IfElement("tremolo").HasValue <int>().Then(v => builder.TremoloLevel = v);

            var invMordentNode = ornamentsNode
                                 .IfElement("inverted-mordent")
                                 .Exists()
                                 .Then(e => builder.Mordent = new Mordent()
            {
                IsInverted = true
            })
                                 .AndReturnResult();

            invMordentNode.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                { "above", VerticalPlacement.Above },
                { "below", VerticalPlacement.Below }
            }).Then(v => builder.Mordent.Placement = v);
            invMordentNode.IfAttribute("default-x").HasValue <double>().Then(v => builder.Mordent.DefaultXPosition = v);
            invMordentNode.IfAttribute("default-y").HasValue <double>().Then(v => builder.Mordent.DefaultYPosition = v);

            var slurNode = notationsNode.IfElement("slur").Exists().Then(s => builder.Slur = new Slur()).AndReturnResult();
            var number   = slurNode.IfAttribute("number").HasValue <int>().Then(v => { }).AndReturnResult();

            if (number < 2)
            {
                slurNode.IfAttribute("type").HasValue(new Dictionary <string, NoteSlurType> {
                    { "start", NoteSlurType.Start },
                    { "stop", NoteSlurType.Stop }
                }).Then(v => builder.Slur.Type = v);
                slurNode.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                    { "above", VerticalPlacement.Above },
                    { "below", VerticalPlacement.Below }
                }).Then(v => builder.Slur.Placement = v);
            }

            foreach (var lNode in element.Elements().Where(n => n.Name == "lyric"))
            {
                Lyrics          lyricsInstance = new Lyrics();
                Lyrics.Syllable syllable       = new Lyrics.Syllable();
                bool            isSylabicSet   = false;
                bool            isTextSet      = false;
                lNode.IfAttribute("default-y").HasValue <double>().Then(v => lyricsInstance.DefaultYPosition = v);
                lNode.IfElement("syllabic").HasValue(new Dictionary <string, SyllableType> {
                    { "begin", SyllableType.Begin },
                    { "middle", SyllableType.Middle },
                    { "end", SyllableType.End },
                    { "single", SyllableType.Single }
                }).Then(v =>
                {
                    syllable.Type = v;
                    isSylabicSet  = true;
                });
                lNode.IfElement("text").HasAnyValue().Then(v =>
                {
                    syllable.Text = v;
                    isTextSet     = true;
                });
                lNode.IfElement("elision").HasAnyValue().Then(v => syllable.ElisionMark = v);

                if (isSylabicSet && isTextSet)
                {
                    lyricsInstance.Syllables.Add(syllable);
                    syllable     = new Lyrics.Syllable();
                    isSylabicSet = false;
                    isTextSet    = false;
                }
                builder.Lyrics.Add(lyricsInstance);
            }

            if (builder.BeamList.Count == 0)
            {
                builder.BeamList.Add(NoteBeamType.Single);
            }

            var noteOrRest = builder.Build();

            var correctStaff = noteOrRest.Staff ?? staff;

            correctStaff.Elements.Add(noteOrRest);
        }
 public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
 {
     element.IfAttribute("tempo").HasValue <int>().Then(v => state.CurrentTempo       = v);
     element.IfAttribute("dynamics").HasValue <int>().Then(v => state.CurrentDynamics = v);
 }