private void Read(Stream input, Encoding encoding)
        {
            BinaryReader reader      = new BinaryReader(input, encoding, true);
            short        magicNumber = reader.ReadInt16();
            byte         lineCount   = reader.ReadByte();

            SubtitlePriority = reader.ReadByte();
            // TODO: Check if this is string length and (encoded) byte count.
            short stringLength1 = reader.ReadInt16();
            short stringLength2 = reader.ReadInt16();
            // TODO: Analyze what these values are used for
            short unknown3 = reader.ReadInt16();
            short flags    = reader.ReadInt16();

            SubpTiming[] timings = new SubpTiming[lineCount];
            for (int i = 0; i < lineCount; i++)
            {
                timings[i] = SubpTiming.ReadSubpTiming(input);
            }

            byte[] data      = reader.ReadBytes(stringLength1);
            string subtitles = encoding.GetString(data).TrimEnd('\0');


            // TODO: Check if $ can be escaped somehow
            // TODO: Check if Split('$').Count == lineCount
            string[] lines = subtitles.Split('$');
            for (int i = 0; i < lineCount; i++)
            {
                Lines.Add(new SubpLine(lines.Length > i ? lines[i] : "", timings[i]));
            }
        }
        public void Write(Stream outputStream, Encoding encoding)
        {
            BinaryWriter writer = new BinaryWriter(outputStream, encoding, true);

            writer.Write(MagicNumber);
            writer.Write((byte)Lines.Count);
            writer.Write(SubtitlePriority);

            string subtitles = GetJoinedSubtitleLines() + '\0';

            byte[] encodedData = encoding.GetBytes(subtitles);

            writer.Write(Convert.ToInt16(encodedData.Length));
            writer.Write(Convert.ToInt16(encodedData.Length + AdditionalLength));
            writer.Write(CharacterId);
            writer.Write(Flags);

            foreach (var line in Lines)
            {
                SubpTiming timing = line.Timing ?? SubpTiming.Null;
                timing.Write(outputStream);
            }

            writer.Write(encodedData);
        }
        public static SubpTiming ReadSubpTiming(Stream input)
        {
            SubpTiming subpTiming = new SubpTiming();

            subpTiming.Read(input);
            return(subpTiming);
        }
        private void Read(Stream input, Encoding encoding)
        {
            BinaryReader reader = new BinaryReader(input, encoding, true);
            short magicNumber = reader.ReadInt16();
            byte lineCount = reader.ReadByte();
            SubtitlePriority = reader.ReadByte();
            // TODO: Check if this is string length and (encoded) byte count.
            short stringLength1 = reader.ReadInt16();
            short stringLength2 = reader.ReadInt16();
            // TODO: Analyze what these values are used for
            short unknown3 = reader.ReadInt16();
            short flags = reader.ReadInt16();

            SubpTiming[] timings = new SubpTiming[lineCount];
            for (int i = 0; i < lineCount; i++)
            {
                timings[i] = SubpTiming.ReadSubpTiming(input);
            }

            byte[] data = reader.ReadBytes(stringLength1);
            string subtitles = encoding.GetString(data).TrimEnd('\0');


            // TODO: Check if $ can be escaped somehow
            // TODO: Check if Split('$').Count == lineCount
            string[] lines = subtitles.Split('$');
            for (int i = 0; i < lineCount; i++)
            {
                Lines.Add(new SubpLine(lines.Length > i ? lines[i] : "", timings[i]));
            }
        }
        private void Read(Stream input, Encoding encoding)
        {
            BinaryReader reader      = new BinaryReader(input, encoding, true);
            short        magicNumber = reader.ReadInt16();
            byte         timingCount = reader.ReadByte();

            SubtitlePriority = reader.ReadByte();
            // TODO: Check if this is string length and (encoded) byte count.
            short stringLength1 = reader.ReadInt16();
            short stringLength2 = reader.ReadInt16();

            // TODO: Analyze what these values are used for
            AdditionalLength = Convert.ToInt16(stringLength2 - stringLength1);
            CharacterId      = reader.ReadInt16();
            Flags            = reader.ReadInt16();

            SubpTiming[] timings = new SubpTiming[timingCount];
            for (int i = 0; i < timingCount; i++)
            {
                timings[i] = SubpTiming.ReadSubpTiming(input);
            }

            byte[] data      = reader.ReadBytes(stringLength1);
            string subtitles = encoding.GetString(data).TrimEnd('\0');

            // TODO: Check if the '$' literal can be escaped somehow
            // TODO: Check if Split('$').Count == lineCount
            string[] lines = subtitles.Split('$');
            for (int i = 0; i < timingCount; i++)
            {
                Lines.Add(new SubpLine(lines.Length > i ? lines[i] : "", timings[i]));
            }

            if (lines.Length > timingCount)
            {
                // More lines than timings => Append without timing
                for (int i = timingCount; i < lines.Length; i++)
                {
                    Lines.Add(new SubpLine(lines[i], null));
                }
            }
        }
 public SubpLine(string text, SubpTiming timing)
 {
     Text   = text;
     Timing = timing;
 }
 public static SubpTiming ReadSubpTiming(Stream input)
 {
     SubpTiming subpTiming = new SubpTiming();
     subpTiming.Read(input);
     return subpTiming;
 }
 public SubpLine(string text, SubpTiming timing)
 {
     Text = text;
     Timing = timing;
 }