diff --git a/src/Forms/Main.cs b/src/Forms/Main.cs index 9b4f34fb5..fa0d4db0f 100644 --- a/src/Forms/Main.cs +++ b/src/Forms/Main.cs @@ -12438,25 +12438,24 @@ namespace Nikse.SubtitleEdit.Forms private void ShowSubtitleTimerTick(object sender, EventArgs e) { ShowSubtitleTimer.Stop(); - if (mediaPlayer != null) + int oldIndex = FirstSelectedIndex; + int index = ShowSubtitle(); + if (index != -1 && checkBoxSyncListViewWithVideoWhilePlaying.Checked && oldIndex != index) { - int index = ShowSubtitle(); - if (index != -1 && checkBoxSyncListViewWithVideoWhilePlaying.Checked) + if ((DateTime.Now.Ticks - _lastTextKeyDownTicks) > 10000 * 700) // only if last typed char was entered > 700 milliseconds { - if ((DateTime.Now.Ticks - _lastTextKeyDownTicks) > 10000 * 700) // only if last typed char was entered > 700 milliseconds + if (_endSeconds <= 0 || !checkBoxAutoRepeatOn.Checked) { - if (_endSeconds <= 0 || !checkBoxAutoRepeatOn.Checked) + if (!timerAutoDuration.Enabled && !mediaPlayer.IsPaused) { - if (!timerAutoDuration.Enabled && !mediaPlayer.IsPaused) - { - SubtitleListview1.BeginUpdate(); - SubtitleListview1.SelectIndexAndEnsureVisible(index, true); - SubtitleListview1.EndUpdate(); - } + SubtitleListview1.BeginUpdate(); + SubtitleListview1.SelectIndexAndEnsureVisible(index, true); + SubtitleListview1.EndUpdate(); } } } } + if (_changeSubtitleToString != SerializeSubtitle(_subtitle)) { if (!Text.EndsWith("*")) @@ -13444,7 +13443,7 @@ namespace Nikse.SubtitleEdit.Forms toolStripMenuItemSubStationAlpha.Visible = false; } - if (format.GetType() == typeof(DCSubtitle) || format.GetType() == typeof(DCinemaSmpte)) + if (format.GetType() == typeof(DCSubtitle) || format.GetType() == typeof(DCinemaSmpte2010)) { toolStripMenuItemDCinemaProperties.Visible = true; } diff --git a/src/Logic/SubtitleFormats/DCinemaSmpte.cs b/src/Logic/SubtitleFormats/DCinemaSmpte2007.cs similarity index 95% rename from src/Logic/SubtitleFormats/DCinemaSmpte.cs rename to src/Logic/SubtitleFormats/DCinemaSmpte2007.cs index 4b00b902d..c94e5ceaa 100644 --- a/src/Logic/SubtitleFormats/DCinemaSmpte.cs +++ b/src/Logic/SubtitleFormats/DCinemaSmpte2007.cs @@ -1,16 +1,17 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Text; using System.Xml; using System.Xml.Schema; namespace Nikse.SubtitleEdit.Logic.SubtitleFormats { - public class DCinemaSmpte : SubtitleFormat + public class DCinemaSmpte2007 : SubtitleFormat { // - // + // // urn:uuid:7be835a3-cfb4-43d0-bb4b-f0b4c95e962e // 2001, A Space Odissey // This is a subtitle file @@ -31,6 +32,8 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats private double frameRate = 24; + public int Version { get; set; } + public override string Extension { get { return ".xml"; } @@ -38,7 +41,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats public override string Name { - get { return "D-Cinema SMPTE"; } + get { return "D-Cinema SMPTE 2007"; } } public override bool IsTimeBased @@ -51,6 +54,10 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats var sb = new StringBuilder(); lines.ForEach(line => sb.AppendLine(line)); string xmlAsString = sb.ToString().Trim(); + + if (xmlAsString.Contains("http://www.smpte-ra.org/schemas/428-7/2010/DCST")) + return false; + if (xmlAsString.Contains("= 0) @@ -443,7 +449,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats } string result = ToUtf8XmlString(xml).Replace("encoding=\"utf-8\"", "encoding=\"UTF-8\"").Replace(" xmlns:dcst=\"dcst\"", string.Empty); - string res = "Nikse.SubtitleEdit.Resources.SMPTE-428-7-2007-DCST.xsd"; + string res = "Nikse.SubtitleEdit.Resources.SMPTE-428-7-2007-DCST.xsd.gz"; System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly(); Stream strm = asm.GetManifestResourceStream(res); if (strm != null) @@ -451,17 +457,22 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats try { var xmld = new XmlDocument(); - xmld.LoadXml(result); - var xr = XmlReader.Create(strm); - xmld.Schemas.Add(null, xr); - xmld.Validate(ValidationCallBack); - xr.Close(); - strm.Close(); + var rdr = new StreamReader(strm); + using (var zip = new GZipStream(rdr.BaseStream, CompressionMode.Decompress)) + { + xmld.LoadXml(result); + var xr = XmlReader.Create(zip); + xmld.Schemas.Add(null, xr); + xmld.Validate(ValidationCallBack); + xr.Close(); + strm.Close(); + } + rdr.Close(); } catch (Exception exception) { if (!BatchMode) - System.Windows.Forms.MessageBox.Show("SMPTE-428-7-2007-DCST.xsd:" + exception.Message); + System.Windows.Forms.MessageBox.Show("SMPTE-428-7-2007-DCST.xsd: " + exception.Message); } } return result; diff --git a/src/Logic/SubtitleFormats/DCinemaSmpte2010.cs b/src/Logic/SubtitleFormats/DCinemaSmpte2010.cs new file mode 100644 index 000000000..c7c0666b8 --- /dev/null +++ b/src/Logic/SubtitleFormats/DCinemaSmpte2010.cs @@ -0,0 +1,778 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Text; +using System.Xml; +using System.Xml.Schema; + +namespace Nikse.SubtitleEdit.Logic.SubtitleFormats +{ + public class DCinemaSmpte2010 : SubtitleFormat + { + // + // + // urn:uuid:7be835a3-cfb4-43d0-bb4b-f0b4c95e962e + // 2001, A Space Odissey + // This is a subtitle file + // 2012-06-26T12:33:59.000-00:00 + // 1 + // fr + // 25 1 + // 25 + // 00:00:00:00 + // urn:uuid:3dec6dc0-39d0-498d-97d0-928d2eb78391 + // + // + // Hallo + // + // + + private double frameRate = 24; + + public int Version { get; set; } + + public override string Extension + { + get { return ".xml"; } + } + + public override string Name + { + get { return "D-Cinema SMPTE 2010"; } + } + + public override bool IsTimeBased + { + get { return true; } + } + + public override bool IsMine(List lines, string fileName) + { + var sb = new StringBuilder(); + lines.ForEach(line => sb.AppendLine(line)); + string xmlAsString = sb.ToString().Trim(); + + if (xmlAsString.Contains("http://www.smpte-ra.org/schemas/428-7/2007/DCST")) + return false; + + if (xmlAsString.Contains("= 0) + return subtitles != null && subtitles.Count > 0; + return false; + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine(ex.Message); + return false; + } + } + else + { + return false; + } + } + + private static string RemoveSubStationAlphaFormatting(string s) + { + int indexOfBegin = s.IndexOf("{", StringComparison.Ordinal); + while (indexOfBegin >= 0 && s.IndexOf("}", StringComparison.Ordinal) > indexOfBegin) + { + int indexOfEnd = s.IndexOf("}", StringComparison.Ordinal); + s = s.Remove(indexOfBegin, (indexOfEnd - indexOfBegin) + 1); + indexOfBegin = s.IndexOf("{", StringComparison.Ordinal); + } + return s; + } + + public override string ToText(Subtitle subtitle, string title) + { + var ss = Configuration.Settings.SubtitleSettings; + + if (!string.IsNullOrEmpty(ss.CurrentDCinemaEditRate)) + { + string[] temp = ss.CurrentDCinemaEditRate.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + double d1, d2; + if (temp.Length == 2 && double.TryParse(temp[0], out d1) && double.TryParse(temp[1], out d2)) + frameRate = d1 / d2; + } + + string xmlStructure = + "" + Environment.NewLine + + " urn:uuid:7be835a3-cfb4-43d0-bb4b-f0b4c95e962e" + Environment.NewLine + + " " + Environment.NewLine + + " This is a subtitle file" + Environment.NewLine + + " 2012-06-26T12:33:59.000-00:00" + Environment.NewLine + + " 1" + Environment.NewLine + + " en" + Environment.NewLine + + " 25 1" + Environment.NewLine + + " 25" + Environment.NewLine + + " 00:00:00:00 " + Environment.NewLine + + " urn:uuid:3dec6dc0-39d0-498d-97d0-928d2eb78391" + Environment.NewLine + + " " + Environment.NewLine + + " " + Environment.NewLine + + " " + Environment.NewLine + + " " + Environment.NewLine + + ""; + + var xml = new XmlDocument(); + xml.LoadXml(xmlStructure); + xml.PreserveWhitespace = true; + var nsmgr = new XmlNamespaceManager(xml.NameTable); + nsmgr.AddNamespace("dcst", xml.DocumentElement.NamespaceURI); + + if (string.IsNullOrEmpty(ss.CurrentDCinemaMovieTitle)) + ss.CurrentDCinemaMovieTitle = title; + + if (ss.CurrentDCinemaFontSize == 0 || string.IsNullOrEmpty(ss.CurrentDCinemaFontEffect)) + Configuration.Settings.SubtitleSettings.InitializeDCinameSettings(true); + + xml.DocumentElement.SelectSingleNode("dcst:ContentTitleText", nsmgr).InnerText = ss.CurrentDCinemaMovieTitle; + xml.DocumentElement.SelectSingleNode("dcst:Id", nsmgr).InnerText = ss.CurrentDCinemaSubtitleId; + xml.DocumentElement.SelectSingleNode("dcst:ReelNumber", nsmgr).InnerText = ss.CurrentDCinemaReelNumber; + xml.DocumentElement.SelectSingleNode("dcst:IssueDate", nsmgr).InnerText = ss.CurrentDCinemaIssueDate; + if (string.IsNullOrEmpty(ss.CurrentDCinemaLanguage)) + ss.CurrentDCinemaLanguage = "en"; + xml.DocumentElement.SelectSingleNode("dcst:Language", nsmgr).InnerText = ss.CurrentDCinemaLanguage; + if (ss.CurrentDCinemaEditRate == null && ss.CurrentDCinemaTimeCodeRate == null) + { + if (Configuration.Settings.General.CurrentFrameRate == 24) + { + ss.CurrentDCinemaEditRate = "24 1"; + ss.CurrentDCinemaTimeCodeRate = "24"; + } + else + { + ss.CurrentDCinemaEditRate = "25 1"; + ss.CurrentDCinemaTimeCodeRate = "25"; + } + } + xml.DocumentElement.SelectSingleNode("dcst:EditRate", nsmgr).InnerText = ss.CurrentDCinemaEditRate; + xml.DocumentElement.SelectSingleNode("dcst:TimeCodeRate", nsmgr).InnerText = ss.CurrentDCinemaTimeCodeRate; + if (string.IsNullOrEmpty(ss.CurrentDCinemaStartTime)) + ss.CurrentDCinemaStartTime = "00:00:00:00"; + xml.DocumentElement.SelectSingleNode("dcst:StartTime", nsmgr).InnerText = ss.CurrentDCinemaStartTime; + xml.DocumentElement.SelectSingleNode("dcst:LoadFont", nsmgr).InnerText = ss.CurrentDCinemaFontUri; + int fontSize = ss.CurrentDCinemaFontSize; + string loadedFontId = "Font1"; + if (!string.IsNullOrEmpty(ss.CurrentDCinemaFontId)) + loadedFontId = ss.CurrentDCinemaFontId; + xml.DocumentElement.SelectSingleNode("dcst:LoadFont", nsmgr).Attributes["ID"].Value = loadedFontId; + xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr).Attributes["Size"].Value = fontSize.ToString(); + xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr).Attributes["Color"].Value = "FF" + Utilities.ColorToHex(ss.CurrentDCinemaFontColor).TrimStart('#').ToUpper(); + xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr).Attributes["ID"].Value = loadedFontId; + xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr).Attributes["Effect"].Value = ss.CurrentDCinemaFontEffect; + xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr).Attributes["EffectColor"].Value = "FF" + Utilities.ColorToHex(ss.CurrentDCinemaFontEffectColor).TrimStart('#').ToUpper(); + + XmlNode mainListFont = xml.DocumentElement.SelectSingleNode("dcst:SubtitleList/dcst:Font", nsmgr); + int no = 0; + foreach (Paragraph p in subtitle.Paragraphs) + { + if (p.Text != null) + { + XmlNode subNode = xml.CreateElement("dcst:Subtitle", "dcst"); + + XmlAttribute id = xml.CreateAttribute("SpotNumber"); + id.InnerText = (no + 1).ToString(); + subNode.Attributes.Append(id); + + XmlAttribute fadeUpTime = xml.CreateAttribute("FadeUpTime"); + fadeUpTime.InnerText = "00:00:00:00"; //Configuration.Settings.SubtitleSettings.DCinemaFadeUpDownTime.ToString(); + subNode.Attributes.Append(fadeUpTime); + + XmlAttribute fadeDownTime = xml.CreateAttribute("FadeDownTime"); + fadeDownTime.InnerText = "00:00:00:00"; //Configuration.Settings.SubtitleSettings.DCinemaFadeUpDownTime.ToString(); + subNode.Attributes.Append(fadeDownTime); + + XmlAttribute start = xml.CreateAttribute("TimeIn"); + start.InnerText = ConvertToTimeString(p.StartTime); + subNode.Attributes.Append(start); + + XmlAttribute end = xml.CreateAttribute("TimeOut"); + end.InnerText = ConvertToTimeString(p.EndTime); + subNode.Attributes.Append(end); + + + bool alignLeft = p.Text.StartsWith("{\\a1}") || p.Text.StartsWith("{\\a5}") || p.Text.StartsWith("{\\a9}") || // sub station alpha + p.Text.StartsWith("{\\an1}") || p.Text.StartsWith("{\\an4}") || p.Text.StartsWith("{\\an7}"); // advanced sub station alpha + + bool alignRight = p.Text.StartsWith("{\\a3}") || p.Text.StartsWith("{\\a7}") || p.Text.StartsWith("{\\a11}") || // sub station alpha + p.Text.StartsWith("{\\an3}") || p.Text.StartsWith("{\\an6}") || p.Text.StartsWith("{\\an9}"); // advanced sub station alpha + + bool alignVTop = p.Text.StartsWith("{\\a5}") || p.Text.StartsWith("{\\a6}") || p.Text.StartsWith("{\\a7}") || // sub station alpha + p.Text.StartsWith("{\\an7}") || p.Text.StartsWith("{\\an8}") || p.Text.StartsWith("{\\an9}"); // advanced sub station alpha + + bool alignVCenter = p.Text.StartsWith("{\\a9}") || p.Text.StartsWith("{\\a10}") || p.Text.StartsWith("{\\a11}") || // sub station alpha + p.Text.StartsWith("{\\an4}") || p.Text.StartsWith("{\\an5}") || p.Text.StartsWith("{\\an6}"); // advanced sub station alpha + + // remove styles for display text (except italic) + string text = RemoveSubStationAlphaFormatting(p.Text); + + + string[] lines = text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + int vPos = 1 + lines.Length * 7; + int vPosFactor = (int)Math.Round(fontSize / 7.4); + if (alignVTop) + { + vPos = Configuration.Settings.SubtitleSettings.DCinemaBottomMargin; // Bottom margin is normally 8 + } + else if (alignVCenter) + { + vPos = (int)Math.Round((lines.Length * vPosFactor * -1) / 2.0); + } + else + { + vPos = (lines.Length * vPosFactor) - vPosFactor + Configuration.Settings.SubtitleSettings.DCinemaBottomMargin; // Bottom margin is normally 8 + } + + bool isItalic = false; + int fontNo = 0; + System.Collections.Generic.Stack fontColors = new Stack(); + foreach (string line in lines) + { + XmlNode textNode = xml.CreateElement("dcst:Text", "dcst"); + + XmlAttribute vPosition = xml.CreateAttribute("Vposition"); + vPosition.InnerText = vPos.ToString(); + textNode.Attributes.Append(vPosition); + + XmlAttribute vAlign = xml.CreateAttribute("Valign"); + if (alignVTop) + vAlign.InnerText = "top"; + else if (alignVCenter) + vAlign.InnerText = "center"; + else + vAlign.InnerText = "bottom"; + textNode.Attributes.Append(vAlign); textNode.Attributes.Append(vAlign); + + XmlAttribute hAlign = xml.CreateAttribute("Halign"); + if (alignLeft) + hAlign.InnerText = "left"; + else if (alignRight) + hAlign.InnerText = "right"; + else + hAlign.InnerText = "center"; + textNode.Attributes.Append(hAlign); + + XmlAttribute direction = xml.CreateAttribute("Direction"); + direction.InnerText = "ltr"; + textNode.Attributes.Append(direction); + + int i = 0; + var txt = new StringBuilder(); + var html = new StringBuilder(); + XmlNode nodeTemp = xml.CreateElement("temp"); + while (i < line.Length) + { + if (!isItalic && line.Substring(i).StartsWith("")) + { + if (txt.Length > 0) + { + nodeTemp.InnerText = txt.ToString(); + html.Append(nodeTemp.InnerXml); + txt = new StringBuilder(); + } + isItalic = true; + i += 2; + } + else if (isItalic && line.Substring(i).StartsWith("")) + { + if (txt.Length > 0) + { + XmlNode fontNode = xml.CreateElement("dcst:Font", "dcst"); + + XmlAttribute italic = xml.CreateAttribute("Italic"); + italic.InnerText = "yes"; + fontNode.Attributes.Append(italic); + + if (line.Length > i + 5 && line.Substring(i+4).StartsWith("")) + { + XmlAttribute fontColor = xml.CreateAttribute("Color"); + fontColor.InnerText = fontColors.Pop(); + fontNode.Attributes.Append(fontColor); + fontNo--; + i += 7; + } + + fontNode.InnerText = Utilities.RemoveHtmlTags(txt.ToString()); + html.Append(fontNode.OuterXml); + txt = new StringBuilder(); + } + isItalic = false; + i += 3; + } + else if (line.Substring(i).StartsWith("")) + { + int endOfFont = line.IndexOf(">", i); + if (txt.Length > 0) + { + nodeTemp.InnerText = txt.ToString(); + html.Append(nodeTemp.InnerXml); + txt = new StringBuilder(); + } + string c = line.Substring(i + 12, endOfFont - (i + 12)); + c = c.Trim('"').Trim('\'').Trim(); + if (c.StartsWith("#")) + c = c.TrimStart('#').ToUpper().PadLeft(8, 'F'); + fontColors.Push(c); + fontNo++; + i += endOfFont - i; + } + else if (fontNo > 0 && line.Substring(i).StartsWith("")) + { + if (txt.Length > 0) + { + XmlNode fontNode = xml.CreateElement("dcst:Font", "dcst"); + + XmlAttribute fontColor = xml.CreateAttribute("Color"); + fontColor.InnerText = fontColors.Pop(); + fontNode.Attributes.Append(fontColor); + + if (line.Length > i + 9 && line.Substring(i + 7).StartsWith("")) + { + XmlAttribute italic = xml.CreateAttribute("Italic"); + italic.InnerText = "yes"; + fontNode.Attributes.Append(italic); + isItalic = false; + i += 4; + } + + fontNode.InnerText = Utilities.RemoveHtmlTags(txt.ToString()); + html.Append(fontNode.OuterXml); + txt = new StringBuilder(); + } + fontNo--; + i += 6; + } + else + { + txt.Append(line.Substring(i, 1)); + } + i++; + } + + if (fontNo > 0) + { + if (txt.Length > 0) + { + XmlNode fontNode = xml.CreateElement("dcst:Font", "dcst"); + + XmlAttribute fontColor = xml.CreateAttribute("Color"); + fontColor.InnerText = fontColors.Peek(); + fontNode.Attributes.Append(fontColor); + + if (isItalic) + { + XmlAttribute italic = xml.CreateAttribute("Italic"); + italic.InnerText = "yes"; + fontNode.Attributes.Append(italic); + } + + fontNode.InnerText = Utilities.RemoveHtmlTags(txt.ToString()); + html.Append(fontNode.OuterXml); + } + else if (html.Length > 0 && html.ToString().StartsWith("" + html.ToString().Replace("dcst:Font", "Font") + ""); + XmlNode fontNode = xml.CreateElement("dcst:Font"); + fontNode.InnerXml = temp.DocumentElement.SelectSingleNode("Font").InnerXml; + foreach (XmlAttribute a in temp.DocumentElement.SelectSingleNode("Font").Attributes) + { + XmlAttribute newA = xml.CreateAttribute(a.Name); + newA.InnerText = a.InnerText; + fontNode.Attributes.Append(newA); + } + + XmlAttribute fontColor = xml.CreateAttribute("Color"); + fontColor.InnerText = fontColors.Peek(); + fontNode.Attributes.Append(fontColor); + + html = new StringBuilder(); + html.Append(fontNode.OuterXml); + } + } + else if (isItalic) + { + if (txt.Length > 0) + { + XmlNode fontNode = xml.CreateElement("dcst:Font", "dcst"); + + XmlAttribute italic = xml.CreateAttribute("Italic"); + italic.InnerText = "yes"; + fontNode.Attributes.Append(italic); + + fontNode.InnerText = Utilities.RemoveHtmlTags(line); + html.Append(fontNode.OuterXml); + } + } + else + { + if (txt.Length > 0) + { + nodeTemp.InnerText = txt.ToString(); + html.Append(nodeTemp.InnerXml); + } + } + textNode.InnerXml = html.ToString(); + + subNode.AppendChild(textNode); + vPos -= vPosFactor; + } + if (subNode.InnerXml.Length == 0) + { // Empty text is just one space + XmlNode textNode = xml.CreateElement("dcst:Text", "dcst"); + textNode.InnerXml = " "; + subNode.AppendChild(textNode); + + XmlAttribute vPosition = xml.CreateAttribute("Vposition"); + vPosition.InnerText = vPos.ToString(); + textNode.Attributes.Append(vPosition); + + XmlAttribute vAlign = xml.CreateAttribute("Valign"); + vAlign.InnerText = "bottom"; + textNode.Attributes.Append(vAlign); + } + mainListFont.AppendChild(subNode); + no++; + } + } + string result = ToUtf8XmlString(xml).Replace("encoding=\"utf-8\"", "encoding=\"UTF-8\"").Replace(" xmlns:dcst=\"dcst\"", string.Empty); + + string res = "Nikse.SubtitleEdit.Resources.SMPTE-428-7-2010-DCST.xsd.gz"; + System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly(); + Stream strm = asm.GetManifestResourceStream(res); + if (strm != null) + { + try + { + var xmld = new XmlDocument(); + var rdr = new StreamReader(strm); + using (var zip = new GZipStream(rdr.BaseStream, CompressionMode.Decompress)) + { + xmld.LoadXml(result); + var xr = XmlReader.Create(zip); + xmld.Schemas.Add(null, xr); + xmld.Validate(ValidationCallBack); + xr.Close(); + strm.Close(); + } + rdr.Close(); + } + catch (Exception exception) + { + if (!BatchMode) + System.Windows.Forms.MessageBox.Show("SMPTE-428-7-2010-DCST.xsd: " + exception.Message); + } + } + return result; + } + + + private void ValidationCallBack(object sender, ValidationEventArgs e) + { + throw new Exception(e.Message); + } + + + public override void LoadSubtitle(Subtitle subtitle, List lines, string fileName) + { + _errorCount = 0; + + var sb = new StringBuilder(); + lines.ForEach(line => sb.AppendLine(line)); + var xml = new XmlDocument(); + xml.LoadXml(sb.ToString().Replace(" 0 && lastVPosition.Length > 0) + pText.AppendLine(); + lastVPosition = vPosition; + } + } + bool alignLeft = false; + bool alignRight = false; + bool alignVTop = false; + bool alignVCenter = false; + if (innerNode.Attributes["Halign"] != null) + { + string hAlign = innerNode.Attributes["Halign"].InnerText; + if (hAlign == "left") + alignLeft = true; + else if (hAlign == "right") + alignRight = true; + } + if (innerNode.Attributes["Valign"] != null) + { + string hAlign = innerNode.Attributes["Valign"].InnerText; + if (hAlign == "top") + alignVTop = true; + else if (hAlign == "center") + alignVCenter = true; + } + if (alignLeft || alignRight || alignVCenter || alignVTop) + { + if (!pText.ToString().StartsWith("{\\an")) + { + string pre = string.Empty; + if (alignVTop) + { + if (alignLeft) + pre = "{\\an7}"; + else if (alignRight) + pre = "{\\an9}"; + else + pre = "{\\an8}"; + } + else if (alignVCenter) + { + if (alignLeft) + pre = "{\\an4}"; + else if (alignRight) + pre = "{\\an6}"; + else + pre = "{\\an5}"; + } + else + { + if (alignLeft) + pre = "{\\an1}"; + else if (alignRight) + pre = "{\\an3}"; + } + string temp = pre + pText.ToString(); + pText = new StringBuilder(); + pText.Append(temp); + } + } + + if (innerNode.ChildNodes.Count == 0) + { + pText.Append(innerNode.InnerText); + } + else + { + foreach (XmlNode innerInnerNode in innerNode) + { + if (innerInnerNode.Name == "Font" && innerInnerNode.Attributes["Italic"] != null && + innerInnerNode.Attributes["Italic"].InnerText.ToLower() == "yes") + { + if (innerInnerNode.Attributes["Color"] != null) + pText.Append("" + innerInnerNode.InnerText + ""); + else + pText.Append("" + innerInnerNode.InnerText + ""); + } + else if (innerInnerNode.Name == "Font" && innerInnerNode.Attributes["Color"] != null) + { + if (innerInnerNode.Attributes["Italic"] != null && innerInnerNode.Attributes["Italic"].InnerText.ToLower() == "yes") + pText.Append("" + innerInnerNode.InnerText + ""); + else + pText.Append("" + innerInnerNode.InnerText + ""); + } + else + { + pText.Append(innerInnerNode.InnerText); + } + } + } + break; + default: + pText.Append(innerNode.InnerText); + break; + } + } + string start = node.Attributes["TimeIn"].InnerText; + string end = node.Attributes["TimeOut"].InnerText; + + if (node.ParentNode.Name == "Font" && node.ParentNode.Attributes["Italic"] != null && node.ParentNode.Attributes["Italic"].InnerText.ToLower() == "yes" && + !pText.ToString().Contains("")) + { + string text = pText.ToString(); + if (text.StartsWith("{\\an") && text.Length > 6) + text = text.Insert(6, "") + ""; + else + text = "" + text + ""; + pText = new StringBuilder(text); + } + + subtitle.Paragraphs.Add(new Paragraph(GetTimeCode(start), GetTimeCode(end), pText.ToString())); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine(ex.Message); + _errorCount++; + } + } + + if (subtitle.Paragraphs.Count > 0) + subtitle.Header = xml.OuterXml; // save id/language/font for later use + + subtitle.Renumber(1); + } + + private string GetColorStringForDCinema(string p) + { + string s = p.ToUpper().Trim(); + if (s.Replace("#", string.Empty). + Replace("0", string.Empty). + Replace("1", string.Empty). + Replace("2", string.Empty). + Replace("3", string.Empty). + Replace("4", string.Empty). + Replace("5", string.Empty). + Replace("6", string.Empty). + Replace("7", string.Empty). + Replace("8", string.Empty). + Replace("9", string.Empty). + Replace("A", string.Empty). + Replace("B", string.Empty). + Replace("C", string.Empty). + Replace("D", string.Empty). + Replace("E", string.Empty). + Replace("F", string.Empty).Length == 0) + { + return s.TrimStart('#'); + } + else + { + return p; + } + } + + private string GetColorStringFromDCinema(string p) + { + string s = p.ToLower().Trim(); + if (s.Replace("#", string.Empty). + Replace("0", string.Empty). + Replace("1", string.Empty). + Replace("2", string.Empty). + Replace("3", string.Empty). + Replace("4", string.Empty). + Replace("5", string.Empty). + Replace("6", string.Empty). + Replace("7", string.Empty). + Replace("8", string.Empty). + Replace("9", string.Empty). + Replace("a", string.Empty). + Replace("b", string.Empty). + Replace("c", string.Empty). + Replace("d", string.Empty). + Replace("e", string.Empty). + Replace("f", string.Empty).Length == 0) + { + if (s.StartsWith("#")) + return s; + else + return "#" + s; + } + else + { + return p; + } + } + + private TimeCode GetTimeCode(string s) + { + string[] parts = s.Split(new char[] { ':', '.', ',' }); + + int milliseconds = (int)System.Math.Round(int.Parse(parts[3]) * (1000.0 / frameRate)); + if (milliseconds > 999) + milliseconds = 999; + + var ts = new TimeSpan(0, int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), milliseconds); + return new TimeCode(ts); + } + + private string ConvertToTimeString(TimeCode time) + { + int frames = (int)System.Math.Round(time.Milliseconds / (1000.0 / frameRate)); + return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", time.Hours, time.Minutes, time.Seconds, frames); + } + + } +} \ No newline at end of file diff --git a/src/Logic/SubtitleFormats/SubtitleFormat.cs b/src/Logic/SubtitleFormats/SubtitleFormat.cs index 3c53c3dde..764ae13fb 100644 --- a/src/Logic/SubtitleFormats/SubtitleFormat.cs +++ b/src/Logic/SubtitleFormats/SubtitleFormat.cs @@ -43,7 +43,8 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats new Csv(), new Csv2(), new DCSubtitle(), - new DCinemaSmpte(), + new DCinemaSmpte2010(), + new DCinemaSmpte2007(), new DigiBeta(), new DvdStudioPro(), new DvdStudioProSpace(), diff --git a/src/Logic/Utilities.cs b/src/Logic/Utilities.cs index 1b49339c2..977c3555e 100644 --- a/src/Logic/Utilities.cs +++ b/src/Logic/Utilities.cs @@ -1,4 +1,8 @@ -using System; +using Nikse.SubtitleEdit.Controls; +using Nikse.SubtitleEdit.Forms; +using Nikse.SubtitleEdit.Logic.SubtitleFormats; +using Nikse.SubtitleEdit.Logic.VideoPlayers; +using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; @@ -9,10 +13,6 @@ using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; using System.Xml; -using Nikse.SubtitleEdit.Controls; -using Nikse.SubtitleEdit.Forms; -using Nikse.SubtitleEdit.Logic.SubtitleFormats; -using Nikse.SubtitleEdit.Logic.VideoPlayers; namespace Nikse.SubtitleEdit.Logic { @@ -209,6 +209,27 @@ namespace Nikse.SubtitleEdit.Logic } } + public static int GetSubtitleIndex(List paragraphs, VideoPlayerContainer videoPlayerContainer) + { + if (videoPlayerContainer.VideoPlayer != null) + { + double positionInMilliseconds = (videoPlayerContainer.VideoPlayer.CurrentPosition * 1000.0) + 5; + for (int i = 0; i < paragraphs.Count; i++) + { + var p = paragraphs[i]; + if (p.StartTime.TotalMilliseconds <= positionInMilliseconds && p.EndTime.TotalMilliseconds > positionInMilliseconds) + { + bool isInfo = p == paragraphs[0] && (p.StartTime.TotalMilliseconds == 0 && p.Duration.TotalMilliseconds == 0 || p.StartTime.TotalMilliseconds == Pac.PacNullTime.TotalMilliseconds); + if (!isInfo) + return i; + } + } + if (!string.IsNullOrEmpty(videoPlayerContainer.SubtitleText)) + videoPlayerContainer.SetSubtitleText(string.Empty, null); + } + return -1; + } + public static int ShowSubtitle(List paragraphs, VideoPlayerContainer videoPlayerContainer) { if (videoPlayerContainer.VideoPlayer != null) @@ -221,19 +242,14 @@ namespace Nikse.SubtitleEdit.Logic p.EndTime.TotalMilliseconds > positionInMilliseconds) { string text = p.Text.Replace("|", Environment.NewLine); - bool isInfo = p == paragraphs[0] && ((p.StartTime.TotalMilliseconds == 0 && p.Duration.TotalMilliseconds == 0) || p.StartTime.TotalMilliseconds == Pac.PacNullTime.TotalMilliseconds); + bool isInfo = p == paragraphs[0] && (p.StartTime.TotalMilliseconds == 0 && p.Duration.TotalMilliseconds == 0 || p.StartTime.TotalMilliseconds == Pac.PacNullTime.TotalMilliseconds); if (!isInfo) { if (videoPlayerContainer.LastParagraph != p) - { videoPlayerContainer.SetSubtitleText(text, p); - return i; - } else if (videoPlayerContainer.SubtitleText != text) - { videoPlayerContainer.SetSubtitleText(text, p); - } - return -1; + return i; } } } @@ -249,8 +265,9 @@ namespace Nikse.SubtitleEdit.Logic if (videoPlayerContainer.VideoPlayer != null) { double positionInMilliseconds = (videoPlayerContainer.VideoPlayer.CurrentPosition * 1000.0) + 15; - foreach (Paragraph p in paragraphs) + for (int i = 0; i < paragraphs.Count; i++) { + var p = paragraphs[i]; if (p.StartTime.TotalMilliseconds <= positionInMilliseconds && p.EndTime.TotalMilliseconds > positionInMilliseconds) { @@ -264,18 +281,12 @@ namespace Nikse.SubtitleEdit.Logic if (!isInfo) { if (videoPlayerContainer.LastParagraph != p) - { videoPlayerContainer.SetSubtitleText(text, p); - return index; - } else if (videoPlayerContainer.SubtitleText != text) - { videoPlayerContainer.SetSubtitleText(text, p); - } - return -1; + return i; } } - index++; } } if (!string.IsNullOrEmpty(videoPlayerContainer.SubtitleText)) diff --git a/src/Resources/SMPTE-428-7-2007-DCST.xsd.gz b/src/Resources/SMPTE-428-7-2007-DCST.xsd.gz new file mode 100644 index 000000000..825f218ef Binary files /dev/null and b/src/Resources/SMPTE-428-7-2007-DCST.xsd.gz differ diff --git a/src/Resources/SMPTE-428-7-2010-DCST.xsd b/src/Resources/SMPTE-428-7-2010-DCST.xsd new file mode 100644 index 000000000..af8962d0a --- /dev/null +++ b/src/Resources/SMPTE-428-7-2010-DCST.xsd @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Resources/SMPTE-428-7-2010-DCST.xsd.gz b/src/Resources/SMPTE-428-7-2010-DCST.xsd.gz new file mode 100644 index 000000000..a1f5f957a Binary files /dev/null and b/src/Resources/SMPTE-428-7-2010-DCST.xsd.gz differ diff --git a/src/SubtitleEdit.csproj b/src/SubtitleEdit.csproj index bcdd7e6ef..a0744fc53 100644 --- a/src/SubtitleEdit.csproj +++ b/src/SubtitleEdit.csproj @@ -861,6 +861,7 @@ + @@ -892,7 +893,7 @@ - + @@ -1465,9 +1466,14 @@ - + Designer - + + + + Designer + + Reference.map diff --git a/src/Test/SubtitleFormatsTest.cs b/src/Test/SubtitleFormatsTest.cs index 7b74ecb05..ed3a3c9fe 100644 --- a/src/Test/SubtitleFormatsTest.cs +++ b/src/Test/SubtitleFormatsTest.cs @@ -375,7 +375,7 @@ Dialogue: Marked=0,0:00:01.00,0:00:03.00,Default,NTP,0000,0000,0000,!Effect," + [DeploymentItem("SubtitleEdit.exe")] public void DcinemaSmpteItalic() { - var target = new DCinemaSmpte(); + var target = new DCinemaSmpte2010(); var subtitle = new Subtitle(); subtitle.Paragraphs.Add(new Paragraph("Italic", 1000, 5000)); string text = target.ToText(subtitle, "title"); @@ -386,7 +386,7 @@ Dialogue: Marked=0,0:00:01.00,0:00:03.00,Default,NTP,0000,0000,0000,!Effect," + [DeploymentItem("SubtitleEdit.exe")] public void DcinemaSmpteColorAndItalic() { - var target = new DCinemaSmpte(); + var target = new DCinemaSmpte2010(); var subtitle = new Subtitle(); subtitle.Paragraphs.Add(new Paragraph("Red", 1000, 5000)); string text = target.ToText(subtitle, "title");