mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-23 19:52:48 +01:00
194 lines
6.9 KiB
C#
194 lines
6.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|
{
|
|
public class AvidStl : SubtitleFormat
|
|
{
|
|
private const int TextLength = 112;
|
|
|
|
private static Paragraph ReadSubtitleBlock(byte[] buffer, int index)
|
|
{
|
|
index += 5;
|
|
var p = new Paragraph { StartTime = ReadTimeCode(buffer, ref index), EndTime = ReadTimeCode(buffer, ref index) };
|
|
index += 3;
|
|
for (int i = index; i < index + TextLength; i++)
|
|
{
|
|
if (buffer[i] == 0x8f || buffer[i] == 0)
|
|
{
|
|
buffer[i] = 32;
|
|
}
|
|
else if (buffer[i] == 0x8a)
|
|
{
|
|
buffer[i] = 0xa;
|
|
}
|
|
}
|
|
p.Text = Encoding.GetEncoding(1252).GetString(buffer, index, TextLength).Trim();
|
|
p.Text = p.Text.Replace("\n", Environment.NewLine);
|
|
return p;
|
|
}
|
|
|
|
private static TimeCode ReadTimeCode(byte[] buffer, ref int index)
|
|
{
|
|
int hours = buffer[index];
|
|
int minutes = buffer[index + 1];
|
|
int seconds = buffer[index + 2];
|
|
int milliseconds = FramesToMillisecondsMax999(buffer[index + 3]);
|
|
index += 4;
|
|
return new TimeCode(hours, minutes, seconds, milliseconds);
|
|
}
|
|
|
|
public static void WriteSubtitleBlock(FileStream fs, Paragraph p, int number)
|
|
{
|
|
fs.WriteByte(0);
|
|
fs.WriteByte((byte)(number % 256)); // number - low byte
|
|
fs.WriteByte((byte)(number / 256)); // number - high byte
|
|
fs.WriteByte(0xff);
|
|
fs.WriteByte(0);
|
|
WriteTimeCode(fs, p.StartTime);
|
|
WriteTimeCode(fs, p.EndTime);
|
|
fs.WriteByte(1);
|
|
fs.WriteByte(2);
|
|
fs.WriteByte(0);
|
|
var buffer = Encoding.GetEncoding(1252).GetBytes(p.Text.Replace(Environment.NewLine, "Š"));
|
|
if (buffer.Length <= 128)
|
|
{
|
|
fs.Write(buffer, 0, buffer.Length);
|
|
for (int i = buffer.Length; i < TextLength; i++)
|
|
{
|
|
fs.WriteByte(0x8f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < TextLength; i++)
|
|
{
|
|
fs.WriteByte(buffer[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void WriteTimeCode(FileStream fs, TimeCode tc)
|
|
{
|
|
fs.WriteByte((byte)(tc.Hours));
|
|
fs.WriteByte((byte)(tc.Minutes));
|
|
fs.WriteByte((byte)(tc.Seconds));
|
|
fs.WriteByte((byte)(MillisecondsToFramesMaxFrameRate(tc.Milliseconds)));
|
|
}
|
|
|
|
public override string Extension => ".stl";
|
|
|
|
public const string NameOfFormat = "Avid STL";
|
|
|
|
public override string Name => NameOfFormat;
|
|
|
|
public static void Save(string fileName, Subtitle subtitle)
|
|
{
|
|
using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
|
|
{
|
|
byte[] buffer = { 0x38, 0x35, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x30, 0x30, 0x30, 0x39 };
|
|
fs.Write(buffer, 0, buffer.Length);
|
|
for (int i = 0; i < 0xde; i++)
|
|
{
|
|
fs.WriteByte(0);
|
|
}
|
|
|
|
string numberOfLines = subtitle.Paragraphs.Count.ToString("D5");
|
|
|
|
buffer = Encoding.ASCII.GetBytes(numberOfLines + numberOfLines + "001");
|
|
fs.Write(buffer, 0, buffer.Length);
|
|
for (int i = 0; i < 0x15; i++)
|
|
{
|
|
fs.WriteByte(0);
|
|
}
|
|
|
|
buffer = Encoding.ASCII.GetBytes("11");
|
|
fs.Write(buffer, 0, buffer.Length);
|
|
while (fs.Length < 1024)
|
|
{
|
|
fs.WriteByte(0);
|
|
}
|
|
|
|
int subtitleNumber = 0;
|
|
foreach (Paragraph p in subtitle.Paragraphs)
|
|
{
|
|
WriteSubtitleBlock(fs, p, subtitleNumber);
|
|
subtitleNumber++;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override bool IsMine(List<string> lines, string fileName)
|
|
{
|
|
if (!string.IsNullOrEmpty(fileName) && File.Exists(fileName))
|
|
{
|
|
try
|
|
{
|
|
var fi = new FileInfo(fileName);
|
|
if (fi.Length > 1150 && fi.Length < 1024000) // not too small or too big
|
|
{
|
|
byte[] buffer = FileUtil.ReadAllBytesShared(fileName);
|
|
if (buffer[0] == 0x38 &&
|
|
buffer[1] == 0x35 &&
|
|
buffer[2] == 0x30 &&
|
|
buffer[1024] == 0 &&
|
|
buffer[1025] == 0 &&
|
|
buffer[1026] == 0 &&
|
|
buffer[1027] == 0xff)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (fileName.EndsWith(".stl", StringComparison.OrdinalIgnoreCase) &&
|
|
buffer.Length > 1283 &&
|
|
buffer[1024] == 0 &&
|
|
buffer[1025] == 1 &&
|
|
buffer[1026] == 0 &&
|
|
buffer[1027] == 0xff &&
|
|
buffer[1152] == 0 &&
|
|
buffer[1153] == 2 &&
|
|
buffer[1154] == 0 &&
|
|
buffer[1155] == 0xff &&
|
|
buffer[1280] == 0 &&
|
|
buffer[1281] == 3 &&
|
|
buffer[1282] == 0 &&
|
|
buffer[1283] == 0xff)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public override string ToText(Subtitle subtitle, string title)
|
|
{
|
|
return "Not supported!";
|
|
}
|
|
|
|
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
|
|
{
|
|
subtitle.Paragraphs.Clear();
|
|
subtitle.Header = null;
|
|
byte[] buffer = FileUtil.ReadAllBytesShared(fileName);
|
|
|
|
int index = 1024;
|
|
while (index <= buffer.Length - 128)
|
|
{
|
|
Paragraph p = ReadSubtitleBlock(buffer, index);
|
|
subtitle.Paragraphs.Add(p);
|
|
index += 128;
|
|
}
|
|
subtitle.Renumber();
|
|
}
|
|
|
|
}
|
|
}
|