public override string ToText(Subtitle subtitle, string title)
        {
            string xmlStructure =
                "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + Environment.NewLine +
                "<fcpxml version=\"1.8\">" + Environment.NewLine +
                "   <resources>" + Environment.NewLine +
                "       <format height=\"[HEIGHT]\" width=\"[WIDTH]\" frameDuration=\"" + FinalCutProXml15.GetFrameDuration() + "\" id=\"r1\"/>" + Environment.NewLine +
                "       <effect id=\"r2\" uid=\".../Titles.localized/Bumper:Opener.localized/Basic Title.localized/Basic Title.moti\" name=\"Basic Title\"/>" + Environment.NewLine +
                "   </resources>" + Environment.NewLine +
                "   <library location=\"\">" + Environment.NewLine +
                "       <event name=\"Title\">" + Environment.NewLine +
                "           <project name=\"SUBTITLES\">" + Environment.NewLine +
                "               <sequence duration=\"[SEQUENCE_DURATION]s\" format=\"r1\" tcStart=\"0s\" tcFormat=\"" + FinalCutProXml15.GetNdfDf() + "\" audioLayout=\"stereo\" audioRate=\"48k\">" + Environment.NewLine +
                "                   <spine>" + Environment.NewLine +
                "                      <gap name=\"Gap\" offset=\"0s\" duration=\"[SEQUENCE_DURATION]s\" start=\"[FIRST_START]\">" + Environment.NewLine +
                "                      </gap>" + Environment.NewLine +
                "                    </spine>" + Environment.NewLine +
                "                </sequence>" + Environment.NewLine +
                "            </project>" + Environment.NewLine +
                "        </event>" + Environment.NewLine +
                "    </library>" + Environment.NewLine +
                "</fcpxml>";

            var xml = new XmlDocument();
            var sequenceDuration = 10;

            if (subtitle.Paragraphs.Count > 0)
            {
                sequenceDuration = (int)Math.Round(subtitle.Paragraphs[subtitle.Paragraphs.Count - 1].EndTime.TotalSeconds);
            }

            var firstStart = "0s";

            if (subtitle.Paragraphs.Count > 0)
            {
                FinalCutProXml15.GetFrameTime(subtitle.Paragraphs[0].StartTime);
            }

            xml.LoadXml(xmlStructure
                        .Replace("[WIDTH]", DefaultStyle.Width.ToString(CultureInfo.InvariantCulture))
                        .Replace("[HEIGHT]", DefaultStyle.Height.ToString(CultureInfo.InvariantCulture))
                        .Replace("[SEQUENCE_DURATIONSEQUENCE_DURATION]", sequenceDuration.ToString(CultureInfo.InvariantCulture))
                        .Replace("[FIRST_START]", firstStart)
                        );
            XmlNode gapNode = xml.DocumentElement.SelectSingleNode("//project/sequence/spine/gap");

            foreach (var p in subtitle.Paragraphs)
            {
                var     text  = HtmlUtil.RemoveHtmlTags(p.Text, true);
                XmlNode video = xml.CreateElement("video");
                MakeTitleNodeWithText(video, text);
                XmlNode generatorNode = video.SelectSingleNode("title");
                generatorNode.Attributes["offset"].Value   = FinalCutProXml15.GetFrameTime(p.StartTime);
                generatorNode.Attributes["duration"].Value = FinalCutProXml15.GetFrameTime(p.Duration);
                generatorNode.Attributes["start"].Value    = FinalCutProXml15.GetFrameTime(p.StartTime);
                generatorNode.Attributes["name"].Value     = text;
                gapNode.AppendChild(generatorNode);
            }
            return(ToUtf8XmlString(xml));
        }
        public override void LoadSubtitle(Subtitle subtitle, List <string> lines, string fileName)
        {
            _errorCount = 0;
            FrameRate   = Configuration.Settings.General.CurrentFrameRate;
            var sb = new StringBuilder();

            lines.ForEach(line => sb.AppendLine(line));
            var x   = sb.ToString();
            var xml = new XmlDocument();

            try
            {
                xml.LoadXml(x.Trim());

                if (subtitle.Paragraphs.Count == 0)
                {
                    var textNodes = xml.SelectNodes("//title/text");
                    if (textNodes.Count > 0)
                    {
                        return;
                    }

                    textNodes = xml.SelectNodes("//title");
                    foreach (XmlNode node in textNodes)
                    {
                        try
                        {
                            if (node.Attributes?["name"] == null ||
                                node.Attributes?["offset"] == null ||
                                node.Attributes?["duration"] == null)
                            {
                                continue;
                            }

                            var text = node.Attributes["name"].InnerText.Replace("\r\r", "\r");
                            var p    = new Paragraph {
                                Text = text.Trim()
                            };
                            if (node.ParentNode.InnerXml.Contains("bold=\"1\""))
                            {
                                p.Text = "<b>" + p.Text + "</b>";
                            }

                            if (node.ParentNode.InnerXml.Contains("italic=\"1\""))
                            {
                                p.Text = "<i>" + p.Text + "</i>";
                            }

                            p.StartTime = FinalCutProXml15.DecodeTime(node.Attributes["offset"]);
                            p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + FinalCutProXml15.DecodeTime(node.Attributes["duration"]).TotalMilliseconds;
                            var add = true;
                            if (subtitle.Paragraphs.Count > 0)
                            {
                                var prev = subtitle.Paragraphs[subtitle.Paragraphs.Count - 1];
                                if (prev.Text == p.Text && prev.StartTime.TotalMilliseconds == p.StartTime.TotalMilliseconds)
                                {
                                    add = false;
                                }
                            }
                            if (add)
                            {
                                subtitle.Paragraphs.Add(p);
                            }
                        }
                        catch
                        {
                            _errorCount++;
                        }
                    }
                }
                subtitle.Renumber();
            }
            catch
            {
                _errorCount = 1;
            }
        }
        public override string ToText(Subtitle subtitle, string title)
        {
            if (Configuration.Settings.General.CurrentFrameRate > 26)
            {
                FrameRate = 30;
            }
            else
            {
                FrameRate = 25;
            }

            string xmlStructure =
                "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" + Environment.NewLine +
                "<!DOCTYPE fcpxml>" + Environment.NewLine +
                Environment.NewLine +
                "<fcpxml version=\"1.4\">" + Environment.NewLine +
                "   <resources>" + Environment.NewLine +
                "       <format height=\"1080\" width=\"1440\" frameDuration=\"" + FinalCutProXml15.GetFrameDuration() + "\" id=\"r1\"/>" + Environment.NewLine +
                "       <effect id=\"r2\" uid=\".../Titles.localized/Bumper:Opener.localized/Basic Title.localized/Basic Title.moti\" name=\"Basic Title\"/>" + Environment.NewLine +
                "   </resources>" + Environment.NewLine +
                "   <library location=\"\">" + Environment.NewLine +
                "       <event name=\"Title\" uid=\"15A02C43-1B7A-4CF8-8007-5C266E77A91E\">" + Environment.NewLine +
                "           <project name=\"SUBTITLES\" uid=\"E04A4539-1369-47C8-AC44-F459A96AC90F\">" + Environment.NewLine +
                "               <sequence duration=\"929s\" format=\"r1\" tcStart=\"0s\" tcFormat=\"" + FinalCutProXml15.GetNdfDf() + "\" audioLayout=\"stereo\" audioRate=\"48k\">" + Environment.NewLine +
                "                   <spine>" + Environment.NewLine +
                "                       <gap name=\"Gap\" offset=\"0s\" duration=\"929s\" start=\"3600s\">" + Environment.NewLine +
                "                       </gap>" + Environment.NewLine +
                "                    </spine>" + Environment.NewLine +
                "                </sequence>" + Environment.NewLine +
                "            </project>" + Environment.NewLine +
                "        </event>" + Environment.NewLine +
                "    </library>" + Environment.NewLine +
                "</fcpxml>";

            string xmlClipStructure =
                "<title name=\"Basic Title: [TITLEID]\" lane=\"1\" offset=\"8665300/2400s\" ref=\"r2\" duration=\"13400/2400s\" start=\"3600s\">" + Environment.NewLine +
                "    <param name=\"Position\" key=\"9999/999166631/999166633/1/100/101\" value=\"-1.67499 -470.934\"/>" + Environment.NewLine +
                "    <text>" + Environment.NewLine +
                "        <text-style ref=\"ts[NUMBER]\">THE NOISEMAKER</text-style>" + Environment.NewLine +
                "    </text>" + Environment.NewLine +
                "    <text-style-def id=\"ts[NUMBER]\">" + Environment.NewLine +
                "        <text-style font=\"Lucida Grande\" fontSize=\"36\" fontFace=\"Regular\" fontColor=\"0.793266 0.793391 0.793221 1\" baseline=\"29\" shadowColor=\"0 0 0 1\" shadowOffset=\"5 315\" alignment=\"center\"/>" + Environment.NewLine +
                "    </text-style-def>" + Environment.NewLine +
                "</title>";

            var xml = new XmlDocument();

            xml.LoadXml(xmlStructure);
            XmlNode videoNode = xml.DocumentElement.SelectSingleNode("//project/sequence/spine/gap");
            int     number    = 1;

            foreach (Paragraph p in subtitle.Paragraphs)
            {
                XmlNode video        = xml.CreateElement("video");
                var     trimmedTitle = new StringBuilder();
                foreach (var ch in HtmlUtil.RemoveHtmlTags(p.Text, true))
                {
                    if ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".Contains(ch.ToString(CultureInfo.InvariantCulture)))
                    {
                        trimmedTitle.Append(ch.ToString(CultureInfo.InvariantCulture));
                    }
                }
                string temp = xmlClipStructure.Replace("[NUMBER]", number.ToString(CultureInfo.InvariantCulture)).Replace("[TITLEID]", trimmedTitle.ToString());
                video.InnerXml = temp;

                XmlNode generatorNode = video.SelectSingleNode("title");
                if (IsNearleWholeNumber(p.StartTime.TotalSeconds))
                {
                    generatorNode.Attributes["offset"].Value = Convert.ToInt64(p.StartTime.TotalSeconds) + "s";
                }
                else
                {
                    generatorNode.Attributes["offset"].Value = FinalCutProXml15.GetFrameTime(p.StartTime);
                }

                if (IsNearleWholeNumber(p.Duration.TotalSeconds))
                {
                    generatorNode.Attributes["duration"].Value = Convert.ToInt64(p.Duration.TotalSeconds) + "s";
                }
                else
                {
                    generatorNode.Attributes["duration"].Value = FinalCutProXml15.GetFrameTime(p.Duration);
                }

                if (IsNearleWholeNumber(p.StartTime.TotalSeconds))
                {
                    generatorNode.Attributes["start"].Value = Convert.ToInt64(p.StartTime.TotalSeconds) + "s";
                }
                else
                {
                    generatorNode.Attributes["start"].Value = FinalCutProXml15.GetFrameTime(p.StartTime);
                }

                XmlNode param = video.SelectSingleNode("title/text/text-style");
                param.InnerText = HtmlUtil.RemoveHtmlTags(p.Text);

                videoNode.AppendChild(generatorNode);
                number++;
            }

            string xmlAsText = ToUtf8XmlString(xml);

            xmlAsText = xmlAsText.Replace("fcpxml[]", "fcpxml");
            xmlAsText = xmlAsText.Replace("fcpxml []", "fcpxml");
            return(xmlAsText);
        }