From 2ab7e4b0b257cf89dcda08a2d17a672f9a7a39de Mon Sep 17 00:00:00 2001 From: niksedk Date: Mon, 16 Dec 2013 18:36:23 +0000 Subject: [PATCH] Split up D-cinema smtp to 2007 and 2010 versions - thx Knut :) git-svn-id: https://subtitleedit.googlecode.com/svn/trunk@2308 99eadd0c-20b8-1223-b5c4-2a2b2df33de2 --- src/Forms/Main.cs | 23 +- .../{DCinemaSmpte.cs => DCinemaSmpte2007.cs} | 35 +- src/Logic/SubtitleFormats/DCinemaSmpte2010.cs | 778 ++++++++++++++++++ src/Logic/SubtitleFormats/SubtitleFormat.cs | 3 +- src/Logic/Utilities.cs | 51 +- src/Resources/SMPTE-428-7-2007-DCST.xsd.gz | Bin 0 -> 1528 bytes src/Resources/SMPTE-428-7-2010-DCST.xsd | 334 ++++++++ src/Resources/SMPTE-428-7-2010-DCST.xsd.gz | Bin 0 -> 1629 bytes src/SubtitleEdit.csproj | 12 +- src/Test/SubtitleFormatsTest.cs | 4 +- 10 files changed, 1190 insertions(+), 50 deletions(-) rename src/Logic/SubtitleFormats/{DCinemaSmpte.cs => DCinemaSmpte2007.cs} (95%) create mode 100644 src/Logic/SubtitleFormats/DCinemaSmpte2010.cs create mode 100644 src/Resources/SMPTE-428-7-2007-DCST.xsd.gz create mode 100644 src/Resources/SMPTE-428-7-2010-DCST.xsd create mode 100644 src/Resources/SMPTE-428-7-2010-DCST.xsd.gz 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 0000000000000000000000000000000000000000..825f218efd68b2845a83e516a81c9a480b32ed2e GIT binary patch literal 1528 zcmVciwFo3a7I!B08>p+R7EW`GB_ACBA`=6P0Oojp)YitO0?^6u?$ z!R$JchzR6+l0cS{0B$iG#E<}!7hEKLn2)${0-mHX%++8i zq)Mwum&6%-&w&N79NDD7Ags(g9uNAiS5JP`p@2hakvBvFKfsutApP&?gd5PC*eCKSwkH6Q4rreV+Ir))-TsQAw|0z$8QerbX?ao+k0%wlHmm->Xr= zGiYIUKHbeUA2fSntv}*8I#g??)(z8HwR-8O(V}45>m4p?3$ND~QmaC0z?N?Z35lvp zzZfamtbt(k_nTidg#W^Y^1(;T<13Jg;&u@SIW16@j4eh17@ITw;d zfddr~+9Z9*MNMLyaf-LB-NSwoJR<9v>3=`Ry zSkP!H^@gXSxE7?E!T6yB)PnP}LFERhyW682LO>G|Z-hCaY`}sz&*&8(7M3{G~pG(P;#^jQxhsXKOKMlCmRdIbcWGn-!FR@pFRrgY9eGG*?5Hywb z>&Cc1%uNet4-K2+;!Iux(kxFwG^F$uon=M!)znwA9>Q0X2?Rz685{;c28}@Rxd@x$ zHzgsT?H$5_Bry$45FP@+Yseab!uZ|+8M6>XOc~r^vclvu&}jNsq$;1sq3boyY5NbK z{x-X^a~^Y1q2C6@Da>C|M#QxSWDG2lQ-tR9KzaFpwQfj%7?Q*3$!%=3orc@>HFhu~ zm^bKP3M#FG(T}gHhwN<*v#?9Tkf|K{7%xL||GL7Y25d}2b-z~OT8!A(-nh{vEuw~SF8#1)yKVge60N>fvTx&CZsE5N&+WJDb_DHPA^SF{(H3a$xP1B-eM{Sd z8@J#4$MDX#HsaE!0s=EGu{?xtscD+!A{jUHDrwxt?y5lJHF~8;uZu*akr3}mbkv%F z9MeoXR6;UZJqO?{GV~jD-PQ^6=)mYw&{#Z>w;GFtnz3dVLAtcS9>i)Xzjiw(--qq2{UohBW(cCGc=9u3Mx%23u>opPl(VB*R zm~a7_mgWP{_F2f5KTr>^6%(0g_0g7qtmmVKQ&I!i*hm+4?`0uBOePt~mZA^!?4|t+ zfo0oo&jRK4z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 0000000000000000000000000000000000000000..a1f5f957a40640633faa6b70b7c64c3b36541cb5 GIT binary patch literal 1629 zcmV-j2BP^NiwFn|9tKSU08>p+R7EW`GB_`eA&EAdZsDGs&4Ihpt;mSvN(*^ z7Gj>|DJ)f~u~HYVWLMG>J{Q1ZI4e4@6QiWo^zrd%7)B2Hhn!*gHBn7YV2O2Y2|^V* zE!<~}BSFg9cKslu>}4DmqMX3K)7nVN0)_-Z8!9D|@^eBna4IUiUKH6B#D-?hB}MuL zMhsyNqD4QR5jHQ#e6t&=E^2P&Q9|)GL8zhfx&n(-v+LAWV}8gJP!=46a+w$-5m?%( z_dpvid(dVyLn`x>oR(U3b28>RBoqD#SWAn~I7uFJrU*ioTBTr9Ua$m`aII-Mi>cAB zK~>!un@z20cUe}b=od_hT;WLA>GA84Zlo^0jt`oa!;J}$WgVM`L7@!sd^MYToW@MF z*=)VTk)y|Dr8QJjq3|>Et}yhBN^FB*yx=qj&qVkdJvZ(dqC0IUB3QFwMahgVA-NNx zD4-^6i=RR3&~Wgh8i4ANiNV&-ipl1;A6Q%5A==iB$k7iU7j4p6l=KnPK~JMsv1><~ z+XJ+IewWx8I6u+- z;no`U9z--$-nLkbbB-nz@h%#+8MFM4m}B9tOoDj@NidRgE>Y&|9k9OurQ!WyN= z+>oEJb_TscK>3j;0vK1*J}@JxtT^q=D*X9`E0cIiQaWcp4=70V9wY{aAi^yPjv;8R zQh=gYjHW+^ap$@yup$FNDupj3EnwYn)Kor&88(*|biTmzawOAv+imS(n;HYG5AapK z%pI8b4*_=qG0jMNKHeE+BNnHHq+dWo(!0{{ZvikPOH15HcZ=Vfe}%A9j>xm-^2qbw z1NeW!dhv6t`S#|@yI81n#=Tao6P{YS-2C)-M2Av_vpcyz*E|SJTE=a;pI>B;;B&D$n%Z`vd1=$Q7 z#ybJ#m?a=m%HTgX7B+98%-;T#U^eAx5=PC#UN>$v+-s}%kf&VK6!wF20m}!J5pilG zngW~SLPK<|!vOw|4{}VuI%3DQqdkUdANe1u)AwZ#G2Tx;7Si%>O=y!Tn&DJ8h>`OQ zgv7QJ_-*=k_7hlolC@I8PS)%*zWOyqixWSS5?14}4#k|;RK@hPrlkrTS_Vz1sZ}Lj zy{AtEFLEn1xqHaby0KD4rZxK{Y`?>f4i*k;zu4w*!+)^RL4av|kl}~YzaMP37xeD~ zJHhA8-%2*?V8VSU(G8gY$>zjoNCm`hd{XR)Y^tS(!3xucG{b2_?&1N1pLgxoPbUIZ zVUmCi!+L(Sq`9TCpl&udDU}#dglw{Y2g2FhnSpJ~Lys!0Z7A7>%((Skh=1H#(i*pq zVp=dKh#=PU`@Y{h`cVG4^9>02<$vMl>%8Kv(q{yw!@34*VC5y4<7#AiPy1R zn+iK=cEse%*Tblhjro(VjzT_4DkC ze$9-&oXsR)OWU14TWbHFW3~He5FpGp#dU|7f&O)MtqoQ5|`%?%dzTN!Z+x)!N z=JU$Y_nmVL{S>(YC$#74Ws&~>59QYngXqO_H8B7H(Z(VW literal 0 HcmV?d00001 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");