// Methods -------------------------------------------------------------
        public List<SubtitleItem> ParseStream(Stream subStream, Encoding encoding)
        {
            // seek the beginning of the stream
            subStream.Position = 0;
            var reader = new StreamReader(subStream, encoding, true);

            var firstLine = reader.ReadLine();
            if (firstLine == FirstLine)
            {
                var line = reader.ReadLine();
                var lineNumber = 2;
                while (line != null && lineNumber <= MaxLineNumberForItems && !IsTimestampLine(line))
                {
                    line = reader.ReadLine();
                    lineNumber++;
                }

                if (line != null && lineNumber <= MaxLineNumberForItems && IsTimestampLine(line))
                {
                    // we parse all the lines
                    var items = new List<SubtitleItem>();

                    var timeCodeLine = line;
                    var textLine = reader.ReadLine();
                    var separatorLine = reader.ReadLine();

                    while (IsTimestampLine(timeCodeLine) && !string.IsNullOrEmpty(textLine))
                    {
                        // parse current line
                        var timeCodes = ParseTimecodeLine(timeCodeLine);
                        var lines = new List<string>(textLine.Split(_lineSeparator, StringSplitOptions.RemoveEmptyEntries));
                        var item = new SubtitleItem()
                            {
                                StartTime = timeCodes.Item1,
                                EndTime = timeCodes.Item2,
                                Lines = lines
                            };
                        items.Add(item);

                        // read next lines
                        timeCodeLine = reader.ReadLine();
                        textLine = reader.ReadLine();
                        separatorLine = reader.ReadLine();
                    }

                    return items;
                }
                else
                {
                    var message = string.Format("Couldn't find the first timestamp line in the current sub file. " +
                                                "Last line read: '{0}', line number #{1}", line, lineNumber);
                    throw new ArgumentException(message);
                }
            }
            else
            {
                throw new ArgumentException("Wrong subtitles format for the SubViewerSubParser");
            }
        }
示例#2
0
        // Methods ------------------------------------------------------------------
        public List<SubtitleItem> ParseStream(Stream ssaStream, Encoding encoding)
        {
            // test if stream if readable and seekable (just a check, should be good)
            if (!ssaStream.CanRead || !ssaStream.CanSeek)
            {
                var message = string.Format("Stream must be seekable and readable in a subtitles parser. " +
                                   "Operation interrupted; isSeekable: {0} - isReadable: {1}",
                                   ssaStream.CanSeek, ssaStream.CanSeek);
                throw new ArgumentException(message);
            }

            // seek the beginning of the stream
            ssaStream.Position = 0;

            var reader = new StreamReader(ssaStream, encoding, true);

            var line = reader.ReadLine();
            if (line == FirstLine)
            {
                var lineNumber = 1;
                // read the line until the [Events] section
                while (line != null && line != EventLine && lineNumber <= MaxLineNumberForEventSection)
                {
                    line = reader.ReadLine();
                    lineNumber++;
                }

                if (line != null && lineNumber <= MaxLineNumberForEventSection)
                {
                    // we are at the event section
                    var headerLine = reader.ReadLine();
                    if (!string.IsNullOrEmpty(headerLine))
                    {
                        var columnHeaders = headerLine.Split(Separator).Select(head => head.Trim()).ToList();

                        var startIndexColumn = columnHeaders.IndexOf(StartColumn);
                        var endIndexColumn = columnHeaders.IndexOf(EndColumn);
                        var textIndexColumn = columnHeaders.IndexOf(TextColumn);

                        if (startIndexColumn > 0 && endIndexColumn > 0 && textIndexColumn > 0)
                        {
                            var items = new List<SubtitleItem>();

                            line = reader.ReadLine();
                            while (line != null)
                            {
                                var columns = line.Split(Separator);
                                var startText = columns[startIndexColumn];
                                var endText = columns[endIndexColumn];
                                var textLine = columns[textIndexColumn];

                                var start = ParseSsaTimecode(startText);
                                var end = ParseSsaTimecode(endText);

                                // TODO: split text line?
                                var item = new SubtitleItem()
                                    {
                                        StartTime = start,
                                        EndTime = end,
                                        Lines = new List<string>() {textLine}
                                    };
                                items.Add(item);

                                line = reader.ReadLine();
                            }

                            return items;
                        }
                        else
                        {
                            var message = string.Format("Couldn't find all the necessary columns " +
                                                        "headers ({0}, {1}, {2}) in header line {3}",
                                                        StartColumn, EndColumn, TextColumn, headerLine);
                            throw new ArgumentException(message);
                        }
                    }
                    else
                    {
                        var message = string.Format("The header line after the line '{0}' was null -> " +
                                                    "no need to continue parsing", line);
                        throw new ArgumentException(message);
                    }
                }
                else
                {
                    var message = string.Format("We reached line '{0}' with line number #{1} without finding to " +
                                                "Event section ({2})", line, lineNumber, EventLine);
                    throw new ArgumentException(message);
                }
            }
            else
            {
                var message = string.Format("First subtitle line '{0}' was different from the one expected " +
                                            "for a SSA file ({1}). We stop the parsing here.", line, FirstLine);
                throw new ArgumentException(message);
            }
        }
        /// <summary>
        /// Parses one line of the .sub file
        /// 
        /// ex:
        /// {0}{180}PIRATES OF THE CARIBBEAN|English subtitlez by tHe.b0dY
        /// </summary>
        /// <param name="line">The .sub file line</param>
        /// <param name="frameRate">The frame rate with which the .sub file was created</param>
        /// <returns>The corresponding SubtitleItem</returns>
        private SubtitleItem ParseLine(string line, float frameRate)
        {
            const string regex = @"^[{\[](\d+)[}\]][{\[](\d+)[}\]](.*)";
            var match = Regex.Match(line, regex);
            if (match.Success && match.Groups.Count > 2)
            {
                var startFrame = match.Groups[1].Value;
                var start = (int)(1000 * double.Parse(startFrame) / frameRate);
                var endTime = match.Groups[2].Value;
                var end = (int)(1000 * double.Parse(endTime) / frameRate);
                var text = match.Groups[match.Groups.Count - 1].Value;
                var lines = text.Split(_lineSeparators);
                var nonEmptyLines = lines.Where(l => !string.IsNullOrEmpty(l)).ToList();
                var item = new SubtitleItem
                    {
                        Lines = nonEmptyLines,
                        StartTime = start,
                        EndTime = end
                    };

                return item;
            }
            else
            {
                var message = string.Format("The subtitle file line {0} is " +
                                            "not in the .sub format. We stop the process.", line);
                Console.WriteLine(message);
                throw new InvalidDataException(message);
            }
        }