private IEnumerable <TimeSpan> RunSequence(IEnumerable <GloCommand> seq)
        {
            foreach (GloCommand cmd in seq)
            {
                if (cmd is GloLoop)
                {
                    GloLoop loop = (GloLoop)cmd;
                    for (int i = 0; i < loop.Repetitions; i++)
                    {
                        foreach (var elem in RunSequence(loop.Commands))
                        {
                            yield return(elem);
                        }
                    }
                }

                else if (cmd is GloDelayCommand)
                {
                    yield return(((GloDelayCommand)cmd).Delay);
                }

                else if (cmd is GloRampCommand)
                {
                    GloRampCommand ramp     = (GloRampCommand)cmd;
                    GloColor       startCol = currentColor;


                    ColorAnimation animation = new ColorAnimation();
                    animation.To       = c2c(ramp.TargetColor);
                    animation.Duration = new Duration(ramp.Duration);
                    colorPanel.Background.BeginAnimation(SolidColorBrush.ColorProperty, animation);

                    currentColor = ramp.TargetColor;

                    /*double duration = ramp.Duration.TotalMilliseconds;
                     * for (double t = 0; t < duration; t += 10)
                     * {
                     *  CurrentColor = GloColor.Blend(startCol, ((GloRampCommand)cmd).TargetColor, t / duration);
                     *  yield return TimeSpan.FromMilliseconds(10);
                     * }*/
                    yield return(ramp.Duration);
                }

                else if (cmd is GloColorCommand)
                {
                    colorPanel.Background.SetCurrentValue(SolidColorBrush.ColorProperty, c2c(((GloColorCommand)cmd).Color));
                    //CurrentColor = ((GloColorCommand)cmd).Color;
                    yield return(TimeSpan.Zero);
                }

                else
                {
                    MessageBox.Show("Unknown command: " + cmd.GetType().Name);
                }
            }
        }
        public static GloProgram LoadFromFile(string file)
        {
            Stack <GloCommandContainer> openContainers = new Stack <GloCommandContainer>();

            openContainers.Push(new GloCommandContainer("PROGRAM"));
            bool seal = false;

            int lineNum = 0;

            foreach (string line in File.ReadAllLines(file, Encoding.UTF8))
            {
                lineNum++;

                int    commentIndex = line.IndexOf(';');
                string commandLine  = (commentIndex >= 0 ? line.Substring(0, commentIndex) : line).Trim();
                if (commandLine == "")
                {
                    continue;
                }

                string[] tokens = commandLine.Split(',');
                string   cmd    = tokens[0];

                switch (cmd)
                {
                case "L":
                    openContainers.Push(new GloLoop(GetIntArg(tokens, 1)));
                    break;

                case "E":
                    if (!(openContainers.Peek() is GloLoop))
                    {
                        throw new FileFormatException("no open loop to close");
                    }

                    GloLoop finishedLoop = (GloLoop)openContainers.Pop();
                    openContainers.Peek().Commands.Add(finishedLoop);
                    break;

                case "D":
                    openContainers.Peek().Commands.Add(new GloDelayCommand(GetTimeArg(tokens, 1)));
                    break;

                case "C":
                    openContainers.Peek().Commands.Add(new GloColorCommand(GetColorArg(tokens, 1)));
                    break;

                case "RAMP":
                    openContainers.Peek().Commands.Add(new GloRampCommand(GetColorArg(tokens, 1), GetTimeArg(tokens, 4)));
                    break;

                case "END":
                    seal = true;
                    break;
                }
            }

            if (openContainers.Count > 1)
            {
                throw new FileFormatException("program ended with unclosed section: " + openContainers.Peek().GetType().Name);
            }
            if (!seal)
            {
                throw new FileFormatException("program was not terminated with END");
            }

            return(new GloProgram(openContainers.Pop()));
        }