using System; using System.Collections.Generic; using System.Net; using System.Text; namespace Nikse.SubtitleEdit.Core.SubtitleFormats { /// /// http://wam.inrialpes.fr/timesheets/annotations/video.html /// public class SmilTimesheetData : SubtitleFormat { public override string Extension { get { return ".html"; } } public override string Name { get { return "SMIL Timesheet"; } } public override bool IsTimeBased { get { return true; } } public override bool IsMine(List lines, string fileName) { var sb = new StringBuilder(); foreach (string l in lines) sb.AppendLine(l); if (!sb.ToString().Contains(" data-begin")) return false; var subtitle = new Subtitle(); LoadSubtitle(subtitle, lines, fileName); return subtitle.Paragraphs.Count > _errorCount; } public override string ToText(Subtitle subtitle, string title) { string header = @" " + Environment.NewLine + "\t" + Environment.NewLine + "\tSMIL Timesheet" + @" " + Environment.NewLine + "\t
" + Environment.NewLine + "\t\t" + Environment.NewLine; const string paragraphWriteFormatOpen = "\t\t

\r\n{1}\r\n

"; const string paragraphWriteFormat = "\t\t

\r\n{2}\r\n

"; int count = 1; var sb = new StringBuilder(); sb.AppendLine(header.Replace("_TITLE_", title)); foreach (Paragraph p in subtitle.Paragraphs) { Paragraph next = subtitle.GetParagraphOrDefault(count); string text = p.Text; if (next != null && Math.Abs(next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds) < 100) sb.AppendLine(string.Format(paragraphWriteFormatOpen, EncodeTime(p.StartTime), text)); else sb.AppendLine(string.Format(paragraphWriteFormat, EncodeTime(p.StartTime), EncodeTime(p.EndTime), text)); count++; } sb.AppendLine("\t
"); sb.AppendLine(""); sb.AppendLine(""); return sb.ToString().Trim(); } private static string EncodeTime(TimeCode time) { //3:15:22 if (time.Hours > 0) return string.Format("{0:00}:{1:00}:{2:00}.{3:00}", time.Hours, time.Minutes, time.Seconds, time.Milliseconds / 10); if (time.Minutes > 9) return string.Format("{0:00}:{1:00}.{2:00}", time.Minutes, time.Seconds, time.Milliseconds / 10); return string.Format("{0}:{1:00}.{2:00}", time.Minutes, time.Seconds, time.Milliseconds / 10); } private static TimeCode DecodeTimeCode(string[] s) { if (s.Length == 3) return new TimeCode(0, int.Parse(s[0]), int.Parse(s[1]), int.Parse(s[2]) * 10); return new TimeCode(int.Parse(s[0]), int.Parse(s[1]), int.Parse(s[2]), int.Parse(s[3]) * 10); } public override void LoadSubtitle(Subtitle subtitle, List lines, string fileName) { _errorCount = 0; var sb = new StringBuilder(); foreach (string l in lines) sb.AppendLine(l); string allInput = sb.ToString(); string allInputLower = allInput.ToLower(); const string syncTag = "

= 0) { var syncEndPos = allInputLower.IndexOf("

", index, StringComparison.Ordinal); if (syncEndPos > 0) { string s = allInput.Substring(syncStartPos + 2, syncEndPos - syncStartPos - 2); int indexOfBegin = s.IndexOf(" data-begin=", StringComparison.Ordinal); int indexOfAttributesEnd = s.IndexOf('>'); if (indexOfBegin >= 0 && indexOfAttributesEnd > indexOfBegin) { string text = s.Substring(indexOfAttributesEnd + 1).Trim(); text = text.Replace("
", Environment.NewLine); text = text.Replace("
", Environment.NewLine); text = text.Replace("
", Environment.NewLine); text = text.Replace("\t", " "); while (text.Contains(" ")) text = text.Replace(" ", " "); while (text.Contains(Environment.NewLine + " ")) text = text.Replace(Environment.NewLine + " ", Environment.NewLine); while (text.Contains(Environment.NewLine + Environment.NewLine)) text = text.Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine); string begin = s.Substring(indexOfBegin + " data-begin=".Length); tcBegin.Clear(); for (int i = 0; i <= 10; i++) { if (begin.Length > i && @"0123456789:.".Contains(begin[i])) { tcBegin.Append(begin[i]); } } tcEnd.Clear(); var indexOfEnd = s.IndexOf(" data-end=", StringComparison.Ordinal); if (indexOfEnd >= 0) { string end = s.Substring(indexOfEnd + " data-end=".Length); for (int i = 0; i <= 10; i++) { if (end.Length > i && @"0123456789:.".Contains(end[i])) { tcEnd.Append(end[i]); } } } var arr = tcBegin.ToString().Split(splitChars, StringSplitOptions.RemoveEmptyEntries); if (arr.Length == 3 || arr.Length == 4) { var p = new Paragraph(); p.Text = text; try { p.StartTime = DecodeTimeCode(arr); if (tcEnd.Length > 0) { arr = tcEnd.ToString().Split(splitChars, StringSplitOptions.RemoveEmptyEntries); p.EndTime = DecodeTimeCode(arr); } subtitle.Paragraphs.Add(p); } catch { _errorCount++; } } } } if (syncEndPos <= 0) { syncStartPos = -1; } else { syncStartPos = allInputLower.IndexOf(syncTag, syncEndPos, StringComparison.Ordinal); index = syncStartPos + syncTag.Length; } } index = 1; foreach (Paragraph paragraph in subtitle.Paragraphs) { Paragraph next = subtitle.GetParagraphOrDefault(index); if (next != null) { paragraph.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - 1; } else if (paragraph.EndTime.TotalMilliseconds < 50) { paragraph.EndTime.TotalMilliseconds = paragraph.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(paragraph.Text); } if (paragraph.Duration.TotalMilliseconds > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds) { paragraph.EndTime.TotalMilliseconds = paragraph.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(paragraph.Text); } index++; } foreach (Paragraph p2 in subtitle.Paragraphs) p2.Text = WebUtility.HtmlDecode(p2.Text); subtitle.Renumber(); } } }