/// <exception cref="UnknownSubtitleFormatException">Thrown if the subtitle format could not be detected.</exception> internal string Read (string path, Encoding encoding, out SubtitleFormat format) { /* Open file */ FileStream fileStream = FileInputOutput.OpenFileForReading(path); /* Read the text */ return TestEncoding(fileStream, encoding, out format); }
private string ClearComments (string text, SubtitleFormat format) { if (format.HasComments) { Regex regex = new Regex(format.Comments); string clearText = regex.Replace(text, String.Empty); return clearText; } else return text; }
/// <summary>Parses the specified text, using the specified format.</summary> /// <remarks>The created <see cref="SubtitleCollection" /> will have its <see cref="SubtitleProperties" /> property set to null. /// It is mandatory to use <see cref="SubtitleCollection.SetPropertiesForAll" /> after.</remarks> internal ParsingProperties Parse (string text, SubtitleFormat format, float inputFrameRate, out SubtitleCollection collection, out IncompleteSubtitleCollection incompleteSubtitles){ collection = new SubtitleCollection(); incompleteSubtitles = new IncompleteSubtitleCollection(); ParsingProperties properties = new ParsingProperties(); properties.InputFrameRate = inputFrameRate; Regex subtitleRegex = null; int bodyIndex = 0; text = ClearComments(text, format); /* Read the headers if available */ if (format.Mode == SubtitleMode.Both) { //Read headers to know if format is using Times or Frames bodyIndex = text.Length; int lastIndex = ReadHeaders(text, bodyIndex, format, properties); subtitleRegex = CreateSubtitleRegex(format, properties.TimingMode); /* Detect body index from matching the first subtitle or the end of headers */ bodyIndex = FindBodyIndex(text, format, subtitleRegex); if (lastIndex > bodyIndex) bodyIndex = lastIndex; } else { //End of headers is detected by start of subtitles' body properties.TimingMode = format.ModeAsTimingMode; subtitleRegex = CreateSubtitleRegex(format); bodyIndex = FindBodyIndex(text, format, subtitleRegex); ReadHeaders(text, bodyIndex, format, properties); } /* Get properties from the whole input, if available */ format.GlobalInputGetProperties(text, properties); int textLength = text.Length; /* Read the subtitles */ bodyIndex = ReadSubtitles(text, bodyIndex, textLength, subtitleRegex, format, properties, collection, incompleteSubtitles); /* Read the end text of the subtitles */ bodyIndex = ReadBodyEnd(text, bodyIndex, format, collection, incompleteSubtitles); /* Check if there's still text remaining */ if ((bodyIndex < textLength) && includeIncompleteSubtitles) AddIncompleteSubtitle(incompleteSubtitles, text.Substring(bodyIndex), collection.Count); return properties; }
/// <exception cref="EncodingNotSupportedException">Thrown if the encoding is not supported by the platform.</exception> /// <exception cref="UnknownSubtitleFormatException">Thrown if the subtitle format could not be detected.</exception> internal string Read (string path, out Encoding encoding, out SubtitleFormat format) { /* Open file */ FileStream fileStream = FileInputOutput.OpenFileForReading(path); return ReadSubtitleText(true, fileStream, out encoding, out format); }
/// <exception cref="UnknownSubtitleFormatException">Thrown if the subtitle format could not be detected.</exception> private string TestEncoding (FileStream fileStream, Encoding encoding, out SubtitleFormat format) { /* Get the text */ string text = TestEncoding(fileStream, encoding); /* Check the subtitle format */ format = GetSubtitleFormat(text); return text; }
/// <exception cref="EncodingNotSupportedException">Thrown if the encoding is not supported by the platform.</exception> /// <exception cref="UnknownSubtitleFormatException">Thrown if the subtitle format could not be detected.</exception> private string TestCodePage (FileStream fileStream, int codePage, out Encoding encoding, out SubtitleFormat format) { /* Check the encoding */ TestCodePageCommon(codePage, out encoding); return TestEncoding(fileStream, encoding, out format); }
private static bool TrySubtitleFormat (SubtitleFormat format, string subtitleText, int length) { Regex expression = new Regex(format.Format, RegexOptions.IgnoreCase); Match match = expression.Match(subtitleText, 0, length); return match.Success; }
private int ReadSubtitles (string text, int bodyIndex, int textLength, Regex subtitleRegex, SubtitleFormat format, ParsingProperties properties, SubtitleCollection collection, IncompleteSubtitleCollection incompleteSubtitles) { Subtitle previousSubtitle = null; /* Read the subtitles. BodyIndex points to the start of the subtitles, skipping its possible beginning text*/ while (bodyIndex < textLength) { Match match = subtitleRegex.Match(text, bodyIndex); if (match.Success) { Subtitle subtitle = ParseSubtitle(match, format, properties, previousSubtitle); collection.Add(subtitle); AddIncompleteSubtitleIfExists(text, match, bodyIndex, collection.Count, incompleteSubtitles); bodyIndex = match.Index + match.Length; previousSubtitle = subtitle; } else break; } return bodyIndex; }
private string GetSubtitleExpression (SubtitleFormat format, SubtitleProperties subtitleProperties, FileProperties fileProperties) { if (format.Mode == SubtitleMode.Both) { if (fileProperties.TimingMode == TimingMode.Times) return format.SubtitleOutTimesMode; else return format.SubtitleOutFramesMode; } else { if (format.SubtitleOut != null) return format.SubtitleOut; else return format.GetDynamicSubtitleOut(subtitleProperties); } }
private int FindBodyIndex (string text, SubtitleFormat format, Regex subtitleRegex) { if (format.HasHeaders || format.HasBodyBegin) { Match subtitleMatch = subtitleRegex.Match(text); if (subtitleMatch.Success) { return subtitleMatch.Index; } } return 0; }
private int ReadBodyEnd (string text, int bodyIndex, SubtitleFormat format, SubtitleCollection collection, IncompleteSubtitleCollection incompleteSubtitles) { Regex bodyEnd = new Regex(format.BodyEndIn + @"\s*", RegexOptions.IgnoreCase); Match bodyEndMatch = bodyEnd.Match(text, bodyIndex); if (bodyEndMatch.Success) { AddIncompleteSubtitleIfExists(text, bodyEndMatch, bodyIndex, collection.Count, incompleteSubtitles); bodyIndex = bodyEndMatch.Index + bodyEndMatch.Length; } return bodyIndex; }
private Style ParseStyle (Match match, SubtitleFormat subtitleFormat) { string styleText = String.Empty; if (ParseGroup(match, "Style", ref styleText)) return subtitleFormat.StringToStyle(styleText); else return new Style(); }
private SubtitleText ParseSubtitleText (Match match, SubtitleFormat subtitleFormat) { string text = String.Empty; if (ParseGroup(match, "Text", ref text)) return new SubtitleText(text, subtitleFormat.LineBreak, true); else return new SubtitleText(); }
private Subtitle ParseSubtitle (Match match, SubtitleFormat format, ParsingProperties properties, Subtitle previousSubtitle){ SubtitleText text = ParseSubtitleText(match, format); Style style = ParseStyle(match, format); Subtitle subtitle = new Subtitle(null, text, style); if (properties.TimingMode == TimingMode.Frames) { Frames previousFrames = (previousSubtitle == null ? null : previousSubtitle.Frames); ParseFrames(match, subtitle.Frames, previousFrames); } else { Times previousTimes = (previousSubtitle == null ? null : previousSubtitle.Times); ParseTimes(match, subtitle.Times, previousTimes, properties); } format.SubtitleInputPostProcess(subtitle); return subtitle; }
/* Private methods */ /// <summary>Checks the encoding of a file.</summary> /// <param name="isSubtitleFile">If it is a subtitle file or a plain text one.</param> /// <param name="fileStream">The stream for reading the file.</param> /// <param name="usedEncoding">The encoding supposedly used.</param> /// <param name="usedFormat">The subtitle format used.</param> /// <exception cref="EncodingNotSupportedException">Thrown if the encoding is not supported by the platform.</exception> /// <exception cref="UnknownSubtitleFormatException">Thrown if the subtitle format could not be detected.</exception> private string ReadSubtitleText (bool isSubtitleFile, FileStream fileStream, out Encoding usedEncoding, out SubtitleFormat usedFormat) { /* Init the out arguments */ usedEncoding = null; usedFormat = null; /* Detect code pages */ int[] codePages = FileInputOutput.DetectCodePages(fileStream); /* Check if no codepage was detected */ if (codePages.Length == 0) { VerboseConsole.WriteLine("No encoding was automatically detected. Using the fall-back encoding \"" + fallbackEncoding.WebName + "\""); string text; if (isSubtitleFile) text = TestEncoding(fileStream, fallbackEncoding, out usedFormat); else text = TestEncoding(fileStream, fallbackEncoding); usedEncoding = fallbackEncoding; return text; } /* The first code page represents the most probable encoding. If any problem occurs when trying to use * that code page, this problem is registered. The remaining code pages are then tried, and if none works, * the first occuring error is the one to be reported. */ Exception firstEncodingException = null; Exception firstSubtitleFormatException = null; int firstCodePage = codePages[0]; try { string text; if (isSubtitleFile) text = TestCodePage(fileStream, firstCodePage, out usedEncoding, out usedFormat); else text = TestCodePagePlain(fileStream, firstCodePage, out usedEncoding); return text; } catch (EncodingNotSupportedException e) { firstEncodingException = e; } catch (UnknownSubtitleFormatException e) { firstSubtitleFormatException = e; } /* Problems were found, going to try additional code pages */ for (int count = 1 ; count < codePages.Length ; count++) { try { int codePage = codePages[count]; string text; if (isSubtitleFile) text = TestCodePage(fileStream, codePage, out usedEncoding, out usedFormat); else text = TestCodePagePlain(fileStream, codePage, out usedEncoding); return text; } catch (Exception) { //Don't do anything, will try the next code page } } /* No code page worked, throwing the exceptions caught for the first (more probable) code page */ if (firstEncodingException != null) throw firstEncodingException; else throw firstSubtitleFormatException; }
private Regex CreateSubtitleRegex(SubtitleFormat format) { string subtitleInExpression = format.SubtitleIn + @"\s*"; //Ignore spaces between subtitles return new Regex(subtitleInExpression, RegexOptions.IgnoreCase); }
/* Internal members */ internal SubtitleTypeInfo (SubtitleFormat format) : this(format.Name, format.Type, format.Mode, format.Extensions) { }
// Used when a subtitle format suppports both times and frames private Regex CreateSubtitleRegex(SubtitleFormat format, TimingMode timingMode) { string subtitleInExpression; if (timingMode == TimingMode.Times) subtitleInExpression = format.SubtitleInTimesMode + @"\s*"; //Ignore spaces between subtitles else subtitleInExpression = format.SubtitleInFramesMode + @"\s*"; //Ignore spaces between subtitles return new Regex(subtitleInExpression, RegexOptions.IgnoreCase); }
internal SubtitleOutput (SubtitleFormat format, SubtitleTextType textType) { this.format = format; this.textType = textType; }
/// <returns>The index where subtitles start.</returns> private int ReadHeaders (string text, int bodyIndex, SubtitleFormat format, ParsingProperties properties) { if (!(format.HasHeaders && (bodyIndex > 0))) return 0; ParseHeaderDelegate headerParser = GetHeaderParser(format.Type); int lastIndex = 0; //the last index with header text string headerText = text.Substring(0, bodyIndex); foreach (string headerExpression in format.Headers) { Regex expression = new Regex(headerExpression, RegexOptions.IgnoreCase); Match match = expression.Match(headerText, 0, bodyIndex); if (match.Success) { /* Update the last index based on the header match */ int matchLastIndex = match.Index + match.Length; if (matchLastIndex > lastIndex) lastIndex = matchLastIndex; headerParser(match, properties); } } return lastIndex; }