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)); } } }
/* Public methods */ /// <summary>Creates new empty <see cref="Subtitles" />.</summary> /// <returns>The newly created subtitles.</returns> public Subtitles New() { SubtitleCollection collection = new SubtitleCollection(); SubtitleProperties properties = new SubtitleProperties(); return(new Subtitles(collection, properties)); }
/* Private members */ /// <summary>Splits a subtitle in two halves. The subtitle passed as parameter is turned into the first half and the second half is returned.</summary> /// <param name="subtitle">The subtitle to split</param> /// <param name="subtitleProperties">The subtitle properties</param> /// <param name="timeBetweenSubtitles">Time between the 2 subtitles, in milliseconds</param> private Subtitle Split(Subtitle subtitle, SubtitleProperties subtitleProperties, int timeBetweenSubtitles) { Subtitle subtitle2 = subtitle.Clone(subtitleProperties); /* Change timings */ int originalStart = (int)subtitle.Times.Start.TotalMilliseconds; int originalEnd = (int)subtitle.Times.End.TotalMilliseconds; if ((originalEnd - originalStart) <= timeBetweenSubtitles) { /* Not possible to have the predefined time between subtitle, subtitle 2 will start at subtitle's end time */ int originalMiddle = (originalStart + originalEnd) / 2; TimeSpan newSubtitleEnd = TimeSpan.FromMilliseconds(originalMiddle); subtitle.Times.End = newSubtitleEnd; subtitle2.Times.Start = newSubtitleEnd; } else { int newSubtitleEnd = (originalStart + originalEnd - timeBetweenSubtitles) / 2; int subtitle2Start = newSubtitleEnd + timeBetweenSubtitles; subtitle.Times.End = TimeSpan.FromMilliseconds(newSubtitleEnd); subtitle2.Times.Start = TimeSpan.FromMilliseconds(subtitle2Start); } /* Change subtitle text */ string[] textLines = subtitle.Text.GetLines(); if (textLines.Length == 1) { subtitle2.Text.Clear(); } else if (textLines.Length > 1) { string[] textLinesHalf1 = null; string[] textLinesHalf2 = null; SplitArray(textLines, ref textLinesHalf1, ref textLinesHalf2); subtitle.Text.Set(textLinesHalf1); subtitle2.Text.Set(textLinesHalf2); } /* Change translation text */ if (subtitle.HasTranslation) { string[] translationLines = subtitle.Translation.GetLines(); if (translationLines.Length == 1) { subtitle2.Translation.Clear(); } else if (translationLines.Length > 1) { string[] translationLinesHalf1 = null; string[] translationLinesHalf2 = null; SplitArray(translationLines, ref translationLinesHalf1, ref translationLinesHalf2); subtitle.Translation.Set(translationLinesHalf1); subtitle2.Translation.Set(translationLinesHalf2); } } return(subtitle2); }
internal override string GetDynamicSubtitleOut(SubtitleProperties properties) { bool isFrameRatePAL = IsFrameRatePAL(properties.CurrentFrameRate); char sep = GetTimingSeparator(isFrameRatePAL); string suf = GetFrameRateSuffix(isFrameRatePAL); return("<<SubtitleNumber>> <<StartHours>>" + sep + "<<StartMinutes>>" + sep + "<<StartSeconds>>" + sep + "<<StartMillisecondsAsFrames" + suf + ">> <<EndHours>>" + sep + "<<EndMinutes>>" + sep + "<<EndSeconds>>" + sep + "<<EndMillisecondsAsFrames" + suf + ">> <<Text>>"); }
internal override string HeadersToString(SubtitleProperties subtitleProperties, FileProperties fileProperties) { Headers headers = subtitleProperties.Headers; return("# <HEAD>\n" + "# FRAME RATE=" + headers.FrameRate + "\n" + "# CREATOR=" + headers.Author + "\n" + "# VIDEO SOURCE=" + headers.Source + "\n" + "# DATE=" + headers.Date + "\n" + "# </HEAD>\n#\n"); }
internal override string HeadersToString(SubtitleProperties subtitleProperties, FileProperties fileProperties) { Headers headers = subtitleProperties.Headers; return("[TITLE]\n" + headers.Title + "\n" + "[AUTHOR]\n" + headers.Author + "\n" + "[SOURCE]\n" + headers.Source + "\n" + "[PRG]\n" + headers.Program + "\n" + "[FILEPATH]\n" + headers.FilePath + "\n" + "[DELAY]\n" + headers.Delay + "\n" + "[CD TRACK]\n" + headers.CDTrack + "\n"); }
internal override string HeadersToString(SubtitleProperties subtitleProperties, FileProperties fileProperties) { Headers headers = subtitleProperties.Headers; string format = (fileProperties.TimingMode == TimingMode.Times ? "TIME" : subtitleProperties.CurrentFrameRate.ToString()); return("TITLE=" + headers.Title + "\n" + "FILE=" + headers.MPSubFileProperties + "\n" + "AUTHOR=" + headers.Author + "\n" + "TYPE=" + headers.MPSubMediaType + "\n" + "FORMAT=" + format + "\n" + "NOTE=" + headers.Comment + "\n\n"); }
internal override string HeadersToString(SubtitleProperties subtitleProperties, FileProperties fileProperties) { Headers headers = subtitleProperties.Headers; return("[ti: " + headers.Title + "]\n" + "[au:" + headers.Author + "]\n" + "[ar:" + headers.Artist + "]\n" + "[al:" + headers.Album + "]\n" + "[by:" + headers.FileCreator + "]\n" + "[ve:" + headers.Version + "]\n" + "[re:" + headers.Program + "]\n"); }
/// <summary>Updates the subtitles' frames using the specified frame rate as the one they had when they were opened.</summary> /// <param name="frameRate">The original subtitles' frame rate.</param> /// <remarks>This results on having the subtitles with the frames they would have if they had been opened with this frame rate. /// The original frame rate is sometimes refered to as the input frame rate.</remarks> public void ChangeOriginal(float frameRate) { SubtitleProperties properties = subtitles.Properties; float originalFrameRate = properties.OriginalFrameRate; float currentFrameRate = properties.CurrentFrameRate; if (originalFrameRate != frameRate) { float conversionFrameRate = currentFrameRate * originalFrameRate / frameRate; subtitles.UpdateFramesFromTimes(conversionFrameRate); subtitles.UpdateTimesFromFrames(currentFrameRate); properties.SetOriginalFrameRate(frameRate); } }
internal override string HeadersToString(SubtitleProperties subtitleProperties, FileProperties fileProperties) { Headers headers = subtitleProperties.Headers; return("[INFORMATION]\n" + "[TITLE]" + headers.Title + "\n" + "[AUTHOR]" + headers.Author + "\n" + "[SOURCE]" + headers.Source + "\n" + "[PRG]" + headers.Program + "\n" + "[FILEPATH]" + headers.FilePath + "\n" + "[DELAY]" + headers.Delay + "\n" + "[CD TRACK]" + headers.CDTrack + "\n" + "[COMMENT]" + headers.Comment + "\n" + "[END INFORMATION]\n" + "[SUBTITLE]\n" + "[COLF]" + headers.SubViewer2FontColor + ",[STYLE]" + headers.SubViewer2FontStyle + ",[SIZE]" + headers.SubViewer2FontSize + ",[FONT]" + headers.SubViewer2FontName + "\n"); }
private Subtitles ParsedSubtitlesPlain(string path, Encoding fileEncoding, string text, bool withCharacterNames, TimingMode timingMode, string lineSeparator) { SubtitleCollection collection = null; PlainTextParser plainParser = new PlainTextParser(withCharacterNames, lineSeparator); ParsingProperties parsingProperties = plainParser.Parse(text, timingMode, fileEncoding, out collection); SubtitleProperties subtitleProperties = new SubtitleProperties(parsingProperties); collection.SetPropertiesForAll(subtitleProperties); Subtitles subtitles = new Subtitles(collection, subtitleProperties); CompleteTimingsAfterParsing(subtitles, parsingProperties); fileProperties = new FileProperties(path, fileEncoding, parsingProperties.TimingMode); Logger.Info("[SubtitleFactory] Opened {0} with encoding {1}", path, fileEncoding); return(subtitles); }
internal override string HeadersToString(SubtitleProperties subtitleProperties, FileProperties fileProperties) { Headers headers = subtitleProperties.Headers; return("[Script Info]\n" + Header("Title:", headers.Title, "<untitled>") + Header("Original Script:", headers.SubStationAlphaOriginalScript, "<unknown>") + "Script Type: " + ScriptType + "\n" + Header("Original Translation:", headers.SubStationAlphaOriginalTranslation) + Header("Original Editing:", headers.SubStationAlphaOriginalEditing) + Header("Original Timing:", headers.SubStationAlphaOriginalTiming) + Header("Original Script Checking:", headers.SubStationAlphaOriginalScriptChecking) + Header("Script Updated By:", headers.SubStationAlphaScriptUpdatedBy) + Header("Collisions:", headers.SubStationAlphaCollisions) + Header("PlayResX:", headers.SubStationAlphaPlayResX) + Header("PlayResY:", headers.SubStationAlphaPlayResY) + Header("PlayDepth:", headers.SubStationAlphaPlayDepth) + Header("Timer:", headers.SubStationAlphaTimer) + "\n" + StyleSection); }
internal string Build(SubtitleCollection collection, SubtitleProperties subtitleProperties, FileProperties fileProperties) { this.subtitleProperties = subtitleProperties; StringBuilder output = new StringBuilder(); if (format.HasHeaders) { output.Append(format.HeadersToString(subtitleProperties, fileProperties)); } if (format.HasBodyBegin) { output.Append(format.BodyBeginOut); } string subtitleExpression = GetSubtitleExpression(format, subtitleProperties, fileProperties); Regex fieldExpression = new Regex(@"<<(?<Field>\w+)(,(?<Width>\d+))?>>"); MatchEvaluator matchEvaluator = new MatchEvaluator(this.FieldEvaluator); foreach (Subtitle currentSubtitle in collection) { subtitle = currentSubtitle; string outputSubtitle = fieldExpression.Replace(subtitleExpression, matchEvaluator); output.Append(outputSubtitle); output.Append("\n"); subtitleNumber++; previousSubtitle = subtitle; } if (format.HasBodyEnd) { output.Append(format.BodyEndOut); } subtitle = null; previousSubtitle = null; subtitleNumber = 1; ConvertNewlines(output, fileProperties); return(output.ToString()); }
/* Private members */ private Subtitles ParsedSubtitles(string path, Encoding fileEncoding, SubtitleFormat format, float inputFrameRate, string text) { SubtitleCollection collection = null; SubtitleParser subtitleParser = new SubtitleParser(includeIncompleteSubtitles); ParsingProperties parsingProperties = subtitleParser.Parse(text, format, inputFrameRate, out collection, out incompleteSubtitles); SubtitleProperties subtitleProperties = new SubtitleProperties(parsingProperties); collection.SetPropertiesForAll(subtitleProperties); Subtitles subtitles = new Subtitles(collection, subtitleProperties); CompleteTimingsAfterParsing(subtitles, parsingProperties); fileProperties = new FileProperties(path, fileEncoding, format.Type, parsingProperties.TimingMode); Logger.Info("[SubtitleFactory] Opened \"{0}\" with encoding \"{1}\", format \"{2}\", timing mode \"{3}\" and frame rate \"{4}\" (input frame rate was \"{5}\")", path, fileEncoding, format.Name, parsingProperties.TimingMode, subtitleProperties.CurrentFrameRate, inputFrameRate); return(subtitles); }
internal virtual string HeadersToString(SubtitleProperties subtitleProperties, FileProperties fileProperties) { return(String.Empty); }
internal virtual string GetDynamicSubtitleOut(SubtitleProperties properties) { return(null); }
/* Private members */ /// <summary>Splits a single subtitle into multiple subtitles - one for each subtitle line.</summary> /// <param name="subtitle">The subtitle to split</param> /// <param name="subtitleProperties">The subtitle properties</param> /// <param name="timeBetweenSubtitles">Time between the 2 subtitles, in milliseconds</param> private Subtitle[] Split(Subtitle subtitle, SubtitleProperties subtitleProperties, int timeBetweenSubtitles) { //Get text lines ArrayList textLines = GetTextLines(subtitle); if (textLines == null) { return(null); } //Get translation lines ArrayList translationLines = GetAlignedTranslationLines(subtitle, textLines); //Prepare times. There must be at least int originalStart = (int)subtitle.Times.Start.TotalMilliseconds; int originalEnd = (int)subtitle.Times.End.TotalMilliseconds; int originalDuration = originalEnd - originalStart; int newDuration = CalculateSubtitleDuration(originalDuration, timeBetweenSubtitles, textLines.Count); if (newDuration < timeBetweenSubtitles) { timeBetweenSubtitles = 0; //If each subtitle would have a duration shorter than timeBetweenSubtitles itself, we don't use it newDuration = CalculateSubtitleDuration(originalDuration, timeBetweenSubtitles, textLines.Count); } /* Create a new Subtitle for each line by cloning the original one and setting appropriate text and times. * Note: textLines can have a single line (which means the other original lines were empty). In this case, * the subtitle will still be changed as a form of "cleanup" where the empty lines are removed. */ ArrayList result = new ArrayList(); for (int i = 0; i < textLines.Count; i++) { Subtitle newSubtitle = subtitle.Clone(subtitleProperties); //Set text newSubtitle.Text.Set(textLines[i] as String); //Set translation if (subtitle.HasTranslation) { if (i < translationLines.Count) { newSubtitle.Translation.Set(translationLines[i] as String); } else { newSubtitle.Translation.Clear(); } } int start = originalStart + i * (newDuration + timeBetweenSubtitles); newSubtitle.Times.Start = TimeSpan.FromMilliseconds(start); newSubtitle.Times.End = TimeSpan.FromMilliseconds(start + newDuration); result.Add(newSubtitle); } return((Subtitle[])result.ToArray(typeof(Subtitle))); }