mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-25 20:52:44 +01:00
Working on subtitle formats
This commit is contained in:
parent
25bbcfa80b
commit
e04ef478c2
37
libse/ContainerFormats/Mp4/Boxes/Mdat.cs
Normal file
37
libse/ContainerFormats/Mp4/Boxes/Mdat.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Nikse.SubtitleEdit.Core.ContainerFormats.Mp4.Boxes
|
||||||
|
{
|
||||||
|
public class Mdat : Box
|
||||||
|
{
|
||||||
|
public List<string> Payloads { get; set; }
|
||||||
|
|
||||||
|
public Mdat(FileStream fs, ulong maximumLength)
|
||||||
|
{
|
||||||
|
Payloads = new List<string>();
|
||||||
|
while (fs.Position < (long)maximumLength)
|
||||||
|
{
|
||||||
|
if (!InitializeSizeAndName(fs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Name == "vtte")
|
||||||
|
Console.WriteLine("vtte");
|
||||||
|
else if (Name == "vttc")
|
||||||
|
{
|
||||||
|
Console.WriteLine("vttc");
|
||||||
|
var vttc = new Vttc(fs, Position);
|
||||||
|
if (vttc.Payload != null)
|
||||||
|
{
|
||||||
|
Payloads.Add(vttc.Payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Name == "payl")
|
||||||
|
Console.WriteLine("payl");
|
||||||
|
|
||||||
|
fs.Seek((long)Position, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
libse/ContainerFormats/Mp4/Boxes/Vttc.cs
Normal file
44
libse/ContainerFormats/Mp4/Boxes/Vttc.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Nikse.SubtitleEdit.Core.ContainerFormats.Mp4.Boxes
|
||||||
|
{
|
||||||
|
public class Vttc : Box
|
||||||
|
{
|
||||||
|
|
||||||
|
public string Payload { get; set; }
|
||||||
|
|
||||||
|
public Vttc(FileStream fs, ulong maximumLength)
|
||||||
|
{
|
||||||
|
long max = (long)maximumLength;
|
||||||
|
StringBuilder sb = null;
|
||||||
|
while (fs.Position < max)
|
||||||
|
{
|
||||||
|
if (!InitializeSizeAndName(fs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Name == "payl")
|
||||||
|
{
|
||||||
|
Console.WriteLine("payl");
|
||||||
|
var length = (int) (max - fs.Position);
|
||||||
|
if (length > 0 && length < 5000)
|
||||||
|
{
|
||||||
|
if (sb == null)
|
||||||
|
sb = new StringBuilder();
|
||||||
|
|
||||||
|
var buffer = new byte[length];
|
||||||
|
fs.Read(buffer, 0, length);
|
||||||
|
var s = Encoding.UTF8.GetString(buffer);
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.Seek((long)Position, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
if (sb != null)
|
||||||
|
Payload = sb.ToString().Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
179
libse/ContainerFormats/Mp4/CmafParser.cs
Normal file
179
libse/ContainerFormats/Mp4/CmafParser.cs
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
using Nikse.SubtitleEdit.Core.ContainerFormats.Mp4.Boxes;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Nikse.SubtitleEdit.Core.ContainerFormats.Mp4
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// http://wiki.multimedia.cx/index.php?title=QuickTime_container
|
||||||
|
/// </summary>
|
||||||
|
public class CmafParser : Box
|
||||||
|
{
|
||||||
|
public string FileName { get; private set; }
|
||||||
|
public Moov Moov { get; private set; }
|
||||||
|
public Subtitle Subtitle { get; private set; }
|
||||||
|
|
||||||
|
public List<Trak> GetSubtitleTracks()
|
||||||
|
{
|
||||||
|
var list = new List<Trak>();
|
||||||
|
if (Moov != null && Moov.Tracks != null)
|
||||||
|
{
|
||||||
|
foreach (var trak in Moov.Tracks)
|
||||||
|
{
|
||||||
|
if (trak.Mdia != null && (trak.Mdia.IsTextSubtitle || trak.Mdia.IsVobSubSubtitle || trak.Mdia.IsClosedCaption) && trak.Mdia.Minf != null && trak.Mdia.Minf.Stbl != null)
|
||||||
|
{
|
||||||
|
list.Add(trak);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Trak> GetAudioTracks()
|
||||||
|
{
|
||||||
|
var list = new List<Trak>();
|
||||||
|
if (Moov != null && Moov.Tracks != null)
|
||||||
|
{
|
||||||
|
foreach (var trak in Moov.Tracks)
|
||||||
|
{
|
||||||
|
if (trak.Mdia != null && trak.Mdia.IsAudio)
|
||||||
|
{
|
||||||
|
list.Add(trak);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Trak> GetVideoTracks()
|
||||||
|
{
|
||||||
|
var list = new List<Trak>();
|
||||||
|
if (Moov != null && Moov.Tracks != null)
|
||||||
|
{
|
||||||
|
foreach (var trak in Moov.Tracks)
|
||||||
|
{
|
||||||
|
if (trak.Mdia != null && trak.Mdia.IsVideo)
|
||||||
|
{
|
||||||
|
list.Add(trak);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeSpan Duration
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Moov != null && Moov.Mvhd != null && Moov.Mvhd.TimeScale > 0)
|
||||||
|
return TimeSpan.FromSeconds((double)Moov.Mvhd.Duration / Moov.Mvhd.TimeScale);
|
||||||
|
return new TimeSpan();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime CreationDate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Moov != null && Moov.Mvhd != null && Moov.Mvhd.TimeScale > 0)
|
||||||
|
return new DateTime(1904, 1, 1, 0, 0, 0, DateTimeKind.Utc).Add(TimeSpan.FromSeconds(Moov.Mvhd.CreationTime));
|
||||||
|
return DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resolution of first video track. If not present returns 0.0
|
||||||
|
/// </summary>
|
||||||
|
public System.Drawing.Point VideoResolution
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Moov != null && Moov.Tracks != null)
|
||||||
|
{
|
||||||
|
foreach (var trak in Moov.Tracks)
|
||||||
|
{
|
||||||
|
if (trak != null && trak.Mdia != null && trak.Tkhd != null)
|
||||||
|
{
|
||||||
|
if (trak.Mdia.IsVideo)
|
||||||
|
return new System.Drawing.Point((int)trak.Tkhd.Width, (int)trak.Tkhd.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new System.Drawing.Point(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CmafParser(string fileName)
|
||||||
|
{
|
||||||
|
FileName = fileName;
|
||||||
|
using (var fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
|
{
|
||||||
|
ParseCmaf(fs);
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CmafParser(FileStream fs)
|
||||||
|
{
|
||||||
|
FileName = null;
|
||||||
|
ParseCmaf(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseCmaf(FileStream fs)
|
||||||
|
{
|
||||||
|
Subtitle = new Subtitle();
|
||||||
|
int count = 0;
|
||||||
|
Position = 0;
|
||||||
|
fs.Seek(0, SeekOrigin.Begin);
|
||||||
|
bool moreBytes = true;
|
||||||
|
while (moreBytes)
|
||||||
|
{
|
||||||
|
moreBytes = InitializeSizeAndName(fs);
|
||||||
|
if (Size < 8)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Name == "moov" && Moov == null)
|
||||||
|
Moov = new Moov(fs, Position); // only scan first "moov" element
|
||||||
|
|
||||||
|
if (Name == "mdat")
|
||||||
|
{
|
||||||
|
var mdat = new Mdat(fs, Position);
|
||||||
|
if (mdat.Payloads.Count > 0)
|
||||||
|
{
|
||||||
|
Subtitle.Paragraphs.Add(new Paragraph(string.Join(Environment.NewLine, mdat.Payloads), 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
if (count > 10000)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (Position > (ulong)fs.Length)
|
||||||
|
break;
|
||||||
|
fs.Seek((long)Position, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal double FrameRate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// Formula: moov.mdia.stbl.stsz.samplecount / (moov.trak.tkhd.duration / moov.mvhd.timescale) - http://www.w3.org/2008/WebVideo/Annotations/drafts/ontology10/CR/test.php?table=containerMPEG4
|
||||||
|
if (Moov != null && Moov.Mvhd != null && Moov.Mvhd.TimeScale > 0)
|
||||||
|
{
|
||||||
|
var videoTracks = GetVideoTracks();
|
||||||
|
if (videoTracks.Count > 0 && videoTracks[0].Tkhd != null && videoTracks[0].Mdia != null && videoTracks[0].Mdia.Minf != null && videoTracks[0].Mdia.Minf.Stbl != null)
|
||||||
|
{
|
||||||
|
double duration = videoTracks[0].Tkhd.Duration;
|
||||||
|
double sampleCount = videoTracks[0].Mdia.Minf.Stbl.StszSampleCount;
|
||||||
|
return sampleCount / (duration / Moov.Mvhd.TimeScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -59,6 +59,8 @@
|
|||||||
<Compile Include="ContainerFormats\Matroska\MatroskaSubtitle.cs" />
|
<Compile Include="ContainerFormats\Matroska\MatroskaSubtitle.cs" />
|
||||||
<Compile Include="ContainerFormats\Matroska\MatroskaTrackInfo.cs" />
|
<Compile Include="ContainerFormats\Matroska\MatroskaTrackInfo.cs" />
|
||||||
<Compile Include="ContainerFormats\Mp4\Boxes\Box.cs" />
|
<Compile Include="ContainerFormats\Mp4\Boxes\Box.cs" />
|
||||||
|
<Compile Include="ContainerFormats\Mp4\Boxes\Vttc.cs" />
|
||||||
|
<Compile Include="ContainerFormats\Mp4\Boxes\Mdat.cs" />
|
||||||
<Compile Include="ContainerFormats\Mp4\Boxes\Mdhd.cs" />
|
<Compile Include="ContainerFormats\Mp4\Boxes\Mdhd.cs" />
|
||||||
<Compile Include="ContainerFormats\Mp4\Boxes\Mdia.cs" />
|
<Compile Include="ContainerFormats\Mp4\Boxes\Mdia.cs" />
|
||||||
<Compile Include="ContainerFormats\Mp4\Boxes\Minf.cs" />
|
<Compile Include="ContainerFormats\Mp4\Boxes\Minf.cs" />
|
||||||
@ -67,6 +69,7 @@
|
|||||||
<Compile Include="ContainerFormats\Mp4\Boxes\Stbl.cs" />
|
<Compile Include="ContainerFormats\Mp4\Boxes\Stbl.cs" />
|
||||||
<Compile Include="ContainerFormats\Mp4\Boxes\Tkhd.cs" />
|
<Compile Include="ContainerFormats\Mp4\Boxes\Tkhd.cs" />
|
||||||
<Compile Include="ContainerFormats\Mp4\Boxes\Trak.cs" />
|
<Compile Include="ContainerFormats\Mp4\Boxes\Trak.cs" />
|
||||||
|
<Compile Include="ContainerFormats\Mp4\CmafParser.cs" />
|
||||||
<Compile Include="ContainerFormats\Mp4\Mp4Parser.cs" />
|
<Compile Include="ContainerFormats\Mp4\Mp4Parser.cs" />
|
||||||
<Compile Include="ContainerFormats\RiffDecodeHeader.cs" />
|
<Compile Include="ContainerFormats\RiffDecodeHeader.cs" />
|
||||||
<Compile Include="ContainerFormats\RiffParser.cs" />
|
<Compile Include="ContainerFormats\RiffParser.cs" />
|
||||||
@ -216,6 +219,7 @@
|
|||||||
<Compile Include="Subtitle.cs" />
|
<Compile Include="Subtitle.cs" />
|
||||||
<Compile Include="SubtitleFormats\AribB36.cs" />
|
<Compile Include="SubtitleFormats\AribB36.cs" />
|
||||||
<Compile Include="SubtitleFormats\AribB24Decoder.cs" />
|
<Compile Include="SubtitleFormats\AribB24Decoder.cs" />
|
||||||
|
<Compile Include="SubtitleFormats\CmafImsc1.cs" />
|
||||||
<Compile Include="SubtitleFormats\Csv5.cs" />
|
<Compile Include="SubtitleFormats\Csv5.cs" />
|
||||||
<Compile Include="SubtitleFormats\JacoSub.cs" />
|
<Compile Include="SubtitleFormats\JacoSub.cs" />
|
||||||
<Compile Include="SubtitleFormats\JsonType11.cs" />
|
<Compile Include="SubtitleFormats\JsonType11.cs" />
|
||||||
|
45
libse/SubtitleFormats/CmafImsc1.cs
Normal file
45
libse/SubtitleFormats/CmafImsc1.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using Nikse.SubtitleEdit.Core.ContainerFormats.Mp4;
|
||||||
|
|
||||||
|
namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// CMFT - "Common Media application Format Text"
|
||||||
|
/// </summary>
|
||||||
|
public class CmafImsc1 : SubtitleFormat
|
||||||
|
{
|
||||||
|
|
||||||
|
public override string Extension => ".cmft";
|
||||||
|
|
||||||
|
public const string NameOfFormat = "CmafImsc1";
|
||||||
|
|
||||||
|
public override string Name => NameOfFormat;
|
||||||
|
|
||||||
|
public override bool IsTimeBased => true;
|
||||||
|
|
||||||
|
public override bool IsMine(List<string> lines, string fileName)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(fileName) && fileName.EndsWith(".cmft", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var parser = new CmafParser(fileName);
|
||||||
|
return parser.Subtitle.Paragraphs.Count > 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToText(Subtitle subtitle, string title)
|
||||||
|
{
|
||||||
|
return "Not implemented!";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
|
||||||
|
{
|
||||||
|
var parser = new CmafParser(fileName);
|
||||||
|
subtitle.Paragraphs.AddRange(parser.Subtitle.Paragraphs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ using System.Text.RegularExpressions;
|
|||||||
|
|
||||||
namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
||||||
{
|
{
|
||||||
public class PE2 : SubtitleFormat
|
public class Pe2 : SubtitleFormat
|
||||||
{
|
{
|
||||||
private static readonly Regex RegexTimeCode = new Regex(@"^\d\d:\d\d:\d\d:\d\d ", RegexOptions.Compiled);
|
private static readonly Regex RegexTimeCode = new Regex(@"^\d\d:\d\d:\d\d:\d\d ", RegexOptions.Compiled);
|
||||||
private static readonly Regex RegexTimeCodeEnd = new Regex(@"^\d\d:\d\d:\d\d:\d\d$", RegexOptions.Compiled);
|
private static readonly Regex RegexTimeCodeEnd = new Regex(@"^\d\d:\d\d:\d\d:\d\d$", RegexOptions.Compiled);
|
||||||
@ -17,20 +17,11 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||||||
TimeEndOrText,
|
TimeEndOrText,
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Extension
|
public override string Extension => ".txt";
|
||||||
{
|
|
||||||
get { return ".txt"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Name
|
public override string Name => "PE2";
|
||||||
{
|
|
||||||
get { return "PE2"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsTimeBased
|
public override bool IsTimeBased => true;
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsMine(List<string> lines, string fileName)
|
public override bool IsMine(List<string> lines, string fileName)
|
||||||
{
|
{
|
||||||
@ -38,8 +29,8 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||||||
foreach (string line in lines)
|
foreach (string line in lines)
|
||||||
sb.AppendLine(line);
|
sb.AppendLine(line);
|
||||||
string s = sb.ToString();
|
string s = sb.ToString();
|
||||||
if (s.Contains("[HEADER]") && s.Contains("[BODY]"))
|
if (!s.Contains("#PE2"))
|
||||||
return false; // UnknownSubtitle17
|
return false;
|
||||||
|
|
||||||
var subtitle = new Subtitle();
|
var subtitle = new Subtitle();
|
||||||
LoadSubtitle(subtitle, lines, fileName);
|
LoadSubtitle(subtitle, lines, fileName);
|
||||||
@ -71,8 +62,8 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||||||
|
|
||||||
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
|
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
|
||||||
{
|
{
|
||||||
var paragraph = new Paragraph();
|
Paragraph paragraph = null;
|
||||||
ExpectingLine expecting = ExpectingLine.TimeStart;
|
var expecting = ExpectingLine.TimeStart;
|
||||||
_errorCount = 0;
|
_errorCount = 0;
|
||||||
|
|
||||||
subtitle.Paragraphs.Clear();
|
subtitle.Paragraphs.Clear();
|
||||||
@ -86,39 +77,40 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tc = DecodeTimeCodeFramesFourParts(parts);
|
var tc = DecodeTimeCodeFramesFourParts(parts);
|
||||||
if (expecting == ExpectingLine.TimeStart)
|
if (paragraph != null)
|
||||||
{
|
{
|
||||||
paragraph = new Paragraph();
|
if (paragraph.EndTime.TotalMilliseconds < 0.001)
|
||||||
paragraph.StartTime = tc;
|
paragraph.EndTime.TotalMilliseconds = tc.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
|
||||||
expecting = ExpectingLine.Text;
|
subtitle.Paragraphs.Add(paragraph);
|
||||||
if (line.Length > 12)
|
|
||||||
paragraph.Text = line.Substring(12).Trim().Replace("//", Environment.NewLine);
|
|
||||||
}
|
}
|
||||||
|
paragraph = new Paragraph { StartTime = tc };
|
||||||
|
expecting = ExpectingLine.Text;
|
||||||
|
if (line.Length > 12)
|
||||||
|
paragraph.Text = line.Substring(12).Trim().Replace("//", Environment.NewLine);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_errorCount++;
|
_errorCount++;
|
||||||
expecting = ExpectingLine.TimeStart;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (RegexTimeCodeEnd.IsMatch(line))
|
else if (RegexTimeCodeEnd.IsMatch(line))
|
||||||
{
|
{
|
||||||
string[] parts = line.Substring(0, 11).Split(SplitCharColon, StringSplitOptions.RemoveEmptyEntries);
|
string[] parts = line.Substring(0, 11).Split(SplitCharColon, StringSplitOptions.RemoveEmptyEntries);
|
||||||
if (parts.Length == 4)
|
if (parts.Length == 4 && paragraph != null)
|
||||||
{
|
{
|
||||||
var tc = DecodeTimeCodeFramesFourParts(parts);
|
var tc = DecodeTimeCodeFramesFourParts(parts);
|
||||||
paragraph.EndTime = tc;
|
paragraph.EndTime = tc;
|
||||||
subtitle.Paragraphs.Add(paragraph);
|
subtitle.Paragraphs.Add(paragraph);
|
||||||
if (paragraph.StartTime.TotalMilliseconds < 0.001)
|
if (paragraph.StartTime.TotalMilliseconds < 0.001)
|
||||||
_errorCount++;
|
_errorCount++;
|
||||||
paragraph = new Paragraph();
|
paragraph = null;
|
||||||
expecting = ExpectingLine.TimeStart;
|
expecting = ExpectingLine.TimeStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (expecting == ExpectingLine.Text)
|
if (expecting == ExpectingLine.Text && paragraph != null)
|
||||||
{
|
{
|
||||||
if (line.Length > 0)
|
if (line.Length > 0)
|
||||||
{
|
{
|
||||||
@ -139,6 +131,10 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!string.IsNullOrEmpty(paragraph?.Text) && paragraph.EndTime.TotalMilliseconds < 0.001)
|
||||||
|
{
|
||||||
|
paragraph.EndTime.TotalMilliseconds = 3000;
|
||||||
|
}
|
||||||
subtitle.Renumber();
|
subtitle.Renumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||||||
new OpenDvt(),
|
new OpenDvt(),
|
||||||
new Oresme(),
|
new Oresme(),
|
||||||
new OresmeDocXDocument(),
|
new OresmeDocXDocument(),
|
||||||
new PE2(),
|
new Pe2(),
|
||||||
new PhoenixSubtitle(),
|
new PhoenixSubtitle(),
|
||||||
new PinnacleImpression(),
|
new PinnacleImpression(),
|
||||||
new PListCaption(),
|
new PListCaption(),
|
||||||
|
@ -6,27 +6,18 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||||||
{
|
{
|
||||||
public class UnknownSubtitle53 : SubtitleFormat
|
public class UnknownSubtitle53 : SubtitleFormat
|
||||||
{
|
{
|
||||||
|
|
||||||
private static readonly Regex RegexTimeCodes = new Regex(@"^\d\d\:\d\d\:\d\d\:\d\d .+", RegexOptions.Compiled);
|
private static readonly Regex RegexTimeCodes = new Regex(@"^\d\d\:\d\d\:\d\d\:\d\d .+", RegexOptions.Compiled);
|
||||||
|
private static readonly Regex RegexTimeCodesEnd = new Regex(@"^\d\d\:\d\d\:\d\d\:\d\d$", RegexOptions.Compiled);
|
||||||
|
|
||||||
public override string Extension
|
public override string Extension => ".txt";
|
||||||
{
|
|
||||||
get { return ".txt"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Name
|
public override string Name => "Unknown 53";
|
||||||
{
|
|
||||||
get { return "Unknown 53"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsTimeBased
|
public override bool IsTimeBased => true;
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsMine(List<string> lines, string fileName)
|
public override bool IsMine(List<string> lines, string fileName)
|
||||||
{
|
{
|
||||||
Subtitle subtitle = new Subtitle();
|
var subtitle = new Subtitle();
|
||||||
LoadSubtitle(subtitle, lines, fileName);
|
LoadSubtitle(subtitle, lines, fileName);
|
||||||
return subtitle.Paragraphs.Count > _errorCount;
|
return subtitle.Paragraphs.Count > _errorCount;
|
||||||
}
|
}
|
||||||
@ -50,7 +41,7 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||||||
|
|
||||||
private static string EncodeTimeCode(TimeCode timeCode)
|
private static string EncodeTimeCode(TimeCode timeCode)
|
||||||
{
|
{
|
||||||
return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", timeCode.Hours, timeCode.Minutes, timeCode.Seconds, MillisecondsToFramesMaxFrameRate(timeCode.Milliseconds));
|
return $"{timeCode.Hours:00}:{timeCode.Minutes:00}:{timeCode.Seconds:00}:{MillisecondsToFramesMaxFrameRate(timeCode.Milliseconds):00}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
|
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName)
|
||||||
@ -62,33 +53,34 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||||||
string s = line.Trim();
|
string s = line.Trim();
|
||||||
if (RegexTimeCodes.Match(s).Success)
|
if (RegexTimeCodes.Match(s).Success)
|
||||||
{
|
{
|
||||||
if (p != null && !string.IsNullOrEmpty(p.Text))
|
if (!string.IsNullOrEmpty(p?.Text))
|
||||||
subtitle.Paragraphs.Add(p);
|
subtitle.Paragraphs.Add(p);
|
||||||
p = new Paragraph();
|
p = new Paragraph();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string[] arr = s.Substring(0, 11).Split(':');
|
var arr = s.Substring(0, 11).Split(':');
|
||||||
if (arr.Length == 4)
|
p.StartTime = DecodeTimeCodeFramesFourParts(arr);
|
||||||
{
|
string text = s.Substring(11).Trim();
|
||||||
p.StartTime = DecodeTimeCodeFramesFourParts(arr);
|
p.Text = text;
|
||||||
string text = s.Substring(11).Trim();
|
if (text.Length > 1 && Utilities.IsInteger(text.Substring(0, 2)))
|
||||||
p.Text = text;
|
_errorCount++;
|
||||||
if (text.Length > 1 && Utilities.IsInteger(text.Substring(0, 2)))
|
|
||||||
_errorCount++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_errorCount++;
|
_errorCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (s.Length == 11 && RegexTimeCodesEnd.IsMatch(line) && p != null)
|
||||||
|
{
|
||||||
|
p.EndTime = DecodeTimeCodeFramesFourParts(s.Split(':'));
|
||||||
|
}
|
||||||
else if (s.Length > 0)
|
else if (s.Length > 0)
|
||||||
{
|
{
|
||||||
_errorCount++;
|
_errorCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p != null && !string.IsNullOrEmpty(p.Text))
|
if (!string.IsNullOrEmpty(p?.Text))
|
||||||
subtitle.Paragraphs.Add(p);
|
subtitle.Paragraphs.Add(p);
|
||||||
|
|
||||||
int index = 1;
|
int index = 1;
|
||||||
@ -97,11 +89,11 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
|
|||||||
paragraph.Text = paragraph.Text.Replace("\\M", "♪");
|
paragraph.Text = paragraph.Text.Replace("\\M", "♪");
|
||||||
|
|
||||||
Paragraph next = subtitle.GetParagraphOrDefault(index);
|
Paragraph next = subtitle.GetParagraphOrDefault(index);
|
||||||
if (next != null)
|
if (next != null && paragraph.EndTime.TotalMilliseconds < 0.01)
|
||||||
{
|
{
|
||||||
paragraph.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - 1;
|
paragraph.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - 1;
|
||||||
}
|
}
|
||||||
else
|
else if (next == null)
|
||||||
{
|
{
|
||||||
paragraph.EndTime.TotalMilliseconds = paragraph.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(paragraph.Text);
|
paragraph.EndTime.TotalMilliseconds = paragraph.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(paragraph.Text);
|
||||||
}
|
}
|
||||||
|
91
src/Forms/ImportText.Designer.cs
generated
91
src/Forms/ImportText.Designer.cs
generated
@ -34,6 +34,8 @@
|
|||||||
this.listViewInputFiles = new System.Windows.Forms.ListView();
|
this.listViewInputFiles = new System.Windows.Forms.ListView();
|
||||||
this.columnHeaderFName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
this.columnHeaderFName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||||
this.columnHeaderSize = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
this.columnHeaderSize = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||||
|
this.contextMenuStripListView = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||||
|
this.clearToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.checkBoxMultipleFiles = new System.Windows.Forms.CheckBox();
|
this.checkBoxMultipleFiles = new System.Windows.Forms.CheckBox();
|
||||||
this.textBoxText = new System.Windows.Forms.TextBox();
|
this.textBoxText = new System.Windows.Forms.TextBox();
|
||||||
this.groupBoxImportOptions = new System.Windows.Forms.GroupBox();
|
this.groupBoxImportOptions = new System.Windows.Forms.GroupBox();
|
||||||
@ -57,13 +59,12 @@
|
|||||||
this.radioButtonLineMode = new System.Windows.Forms.RadioButton();
|
this.radioButtonLineMode = new System.Windows.Forms.RadioButton();
|
||||||
this.checkBoxRemoveEmptyLines = new System.Windows.Forms.CheckBox();
|
this.checkBoxRemoveEmptyLines = new System.Windows.Forms.CheckBox();
|
||||||
this.groupBoxImportResult = new System.Windows.Forms.GroupBox();
|
this.groupBoxImportResult = new System.Windows.Forms.GroupBox();
|
||||||
|
this.SubtitleListview1 = new Nikse.SubtitleEdit.Controls.SubtitleListView();
|
||||||
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
|
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
|
||||||
this.buttonCancel = new System.Windows.Forms.Button();
|
this.buttonCancel = new System.Windows.Forms.Button();
|
||||||
this.buttonOK = new System.Windows.Forms.Button();
|
this.buttonOK = new System.Windows.Forms.Button();
|
||||||
this.contextMenuStripListView = new System.Windows.Forms.ContextMenuStrip(this.components);
|
|
||||||
this.clearToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.SubtitleListview1 = new Nikse.SubtitleEdit.Controls.SubtitleListView();
|
|
||||||
this.groupBoxImportText.SuspendLayout();
|
this.groupBoxImportText.SuspendLayout();
|
||||||
|
this.contextMenuStripListView.SuspendLayout();
|
||||||
this.groupBoxImportOptions.SuspendLayout();
|
this.groupBoxImportOptions.SuspendLayout();
|
||||||
this.groupBoxTimeCodes.SuspendLayout();
|
this.groupBoxTimeCodes.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDownGapBetweenLines)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDownGapBetweenLines)).BeginInit();
|
||||||
@ -71,7 +72,6 @@
|
|||||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDownDurationFixed)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.numericUpDownDurationFixed)).BeginInit();
|
||||||
this.groupBoxSplitting.SuspendLayout();
|
this.groupBoxSplitting.SuspendLayout();
|
||||||
this.groupBoxImportResult.SuspendLayout();
|
this.groupBoxImportResult.SuspendLayout();
|
||||||
this.contextMenuStripListView.SuspendLayout();
|
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// buttonOpenText
|
// buttonOpenText
|
||||||
@ -131,6 +131,20 @@
|
|||||||
this.columnHeaderSize.Text = "Size";
|
this.columnHeaderSize.Text = "Size";
|
||||||
this.columnHeaderSize.Width = 81;
|
this.columnHeaderSize.Width = 81;
|
||||||
//
|
//
|
||||||
|
// contextMenuStripListView
|
||||||
|
//
|
||||||
|
this.contextMenuStripListView.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||||
|
this.clearToolStripMenuItem});
|
||||||
|
this.contextMenuStripListView.Name = "contextMenuStripListView";
|
||||||
|
this.contextMenuStripListView.Size = new System.Drawing.Size(102, 26);
|
||||||
|
//
|
||||||
|
// clearToolStripMenuItem
|
||||||
|
//
|
||||||
|
this.clearToolStripMenuItem.Name = "clearToolStripMenuItem";
|
||||||
|
this.clearToolStripMenuItem.Size = new System.Drawing.Size(101, 22);
|
||||||
|
this.clearToolStripMenuItem.Text = "Clear";
|
||||||
|
this.clearToolStripMenuItem.Click += new System.EventHandler(this.clearToolStripMenuItem_Click);
|
||||||
|
//
|
||||||
// checkBoxMultipleFiles
|
// checkBoxMultipleFiles
|
||||||
//
|
//
|
||||||
this.checkBoxMultipleFiles.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
this.checkBoxMultipleFiles.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
@ -437,6 +451,32 @@
|
|||||||
this.groupBoxImportResult.TabStop = false;
|
this.groupBoxImportResult.TabStop = false;
|
||||||
this.groupBoxImportResult.Text = "Preview";
|
this.groupBoxImportResult.Text = "Preview";
|
||||||
//
|
//
|
||||||
|
// SubtitleListview1
|
||||||
|
//
|
||||||
|
this.SubtitleListview1.AllowColumnReorder = true;
|
||||||
|
this.SubtitleListview1.AllowDrop = true;
|
||||||
|
this.SubtitleListview1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.SubtitleListview1.FirstVisibleIndex = -1;
|
||||||
|
this.SubtitleListview1.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
|
this.SubtitleListview1.FullRowSelect = true;
|
||||||
|
this.SubtitleListview1.GridLines = true;
|
||||||
|
this.SubtitleListview1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
|
||||||
|
this.SubtitleListview1.HideSelection = false;
|
||||||
|
this.SubtitleListview1.Location = new System.Drawing.Point(6, 19);
|
||||||
|
this.SubtitleListview1.MultiSelect = false;
|
||||||
|
this.SubtitleListview1.Name = "SubtitleListview1";
|
||||||
|
this.SubtitleListview1.OwnerDraw = true;
|
||||||
|
this.SubtitleListview1.Size = new System.Drawing.Size(882, 204);
|
||||||
|
this.SubtitleListview1.SubtitleFontBold = false;
|
||||||
|
this.SubtitleListview1.SubtitleFontName = "Tahoma";
|
||||||
|
this.SubtitleListview1.SubtitleFontSize = 8;
|
||||||
|
this.SubtitleListview1.TabIndex = 0;
|
||||||
|
this.SubtitleListview1.UseCompatibleStateImageBehavior = false;
|
||||||
|
this.SubtitleListview1.UseSyntaxColoring = true;
|
||||||
|
this.SubtitleListview1.View = System.Windows.Forms.View.Details;
|
||||||
|
//
|
||||||
// openFileDialog1
|
// openFileDialog1
|
||||||
//
|
//
|
||||||
this.openFileDialog1.FileName = "openFileDialog1";
|
this.openFileDialog1.FileName = "openFileDialog1";
|
||||||
@ -465,46 +505,6 @@
|
|||||||
this.buttonOK.UseVisualStyleBackColor = true;
|
this.buttonOK.UseVisualStyleBackColor = true;
|
||||||
this.buttonOK.Click += new System.EventHandler(this.ButtonOkClick);
|
this.buttonOK.Click += new System.EventHandler(this.ButtonOkClick);
|
||||||
//
|
//
|
||||||
// contextMenuStripListView
|
|
||||||
//
|
|
||||||
this.contextMenuStripListView.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
|
||||||
this.clearToolStripMenuItem});
|
|
||||||
this.contextMenuStripListView.Name = "contextMenuStripListView";
|
|
||||||
this.contextMenuStripListView.Size = new System.Drawing.Size(102, 26);
|
|
||||||
//
|
|
||||||
// clearToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.clearToolStripMenuItem.Name = "clearToolStripMenuItem";
|
|
||||||
this.clearToolStripMenuItem.Size = new System.Drawing.Size(101, 22);
|
|
||||||
this.clearToolStripMenuItem.Text = "Clear";
|
|
||||||
this.clearToolStripMenuItem.Click += new System.EventHandler(this.clearToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// SubtitleListview1
|
|
||||||
//
|
|
||||||
this.SubtitleListview1.AllowColumnReorder = true;
|
|
||||||
this.SubtitleListview1.AllowDrop = true;
|
|
||||||
this.SubtitleListview1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
|
||||||
this.SubtitleListview1.FirstVisibleIndex = -1;
|
|
||||||
this.SubtitleListview1.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
|
||||||
this.SubtitleListview1.FullRowSelect = true;
|
|
||||||
this.SubtitleListview1.GridLines = true;
|
|
||||||
this.SubtitleListview1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
|
|
||||||
this.SubtitleListview1.HideSelection = false;
|
|
||||||
this.SubtitleListview1.Location = new System.Drawing.Point(6, 19);
|
|
||||||
this.SubtitleListview1.MultiSelect = false;
|
|
||||||
this.SubtitleListview1.Name = "SubtitleListview1";
|
|
||||||
this.SubtitleListview1.OwnerDraw = true;
|
|
||||||
this.SubtitleListview1.Size = new System.Drawing.Size(882, 204);
|
|
||||||
this.SubtitleListview1.SubtitleFontBold = false;
|
|
||||||
this.SubtitleListview1.SubtitleFontName = "Tahoma";
|
|
||||||
this.SubtitleListview1.SubtitleFontSize = 8;
|
|
||||||
this.SubtitleListview1.TabIndex = 0;
|
|
||||||
this.SubtitleListview1.UseCompatibleStateImageBehavior = false;
|
|
||||||
this.SubtitleListview1.UseSyntaxColoring = true;
|
|
||||||
this.SubtitleListview1.View = System.Windows.Forms.View.Details;
|
|
||||||
//
|
|
||||||
// ImportText
|
// ImportText
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
@ -524,9 +524,11 @@
|
|||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
this.Text = "Import text";
|
this.Text = "Import text";
|
||||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImportText_FormClosing);
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImportText_FormClosing);
|
||||||
|
this.Shown += new System.EventHandler(this.ImportText_Shown);
|
||||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ImportTextKeyDown);
|
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ImportTextKeyDown);
|
||||||
this.groupBoxImportText.ResumeLayout(false);
|
this.groupBoxImportText.ResumeLayout(false);
|
||||||
this.groupBoxImportText.PerformLayout();
|
this.groupBoxImportText.PerformLayout();
|
||||||
|
this.contextMenuStripListView.ResumeLayout(false);
|
||||||
this.groupBoxImportOptions.ResumeLayout(false);
|
this.groupBoxImportOptions.ResumeLayout(false);
|
||||||
this.groupBoxImportOptions.PerformLayout();
|
this.groupBoxImportOptions.PerformLayout();
|
||||||
this.groupBoxTimeCodes.ResumeLayout(false);
|
this.groupBoxTimeCodes.ResumeLayout(false);
|
||||||
@ -538,7 +540,6 @@
|
|||||||
this.groupBoxSplitting.ResumeLayout(false);
|
this.groupBoxSplitting.ResumeLayout(false);
|
||||||
this.groupBoxSplitting.PerformLayout();
|
this.groupBoxSplitting.PerformLayout();
|
||||||
this.groupBoxImportResult.ResumeLayout(false);
|
this.groupBoxImportResult.ResumeLayout(false);
|
||||||
this.contextMenuStripListView.ResumeLayout(false);
|
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2516,6 +2516,27 @@ namespace Nikse.SubtitleEdit.Forms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (format == null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var cmaf = new CmafImsc1();
|
||||||
|
if (cmaf.IsMine(null, fileName))
|
||||||
|
{
|
||||||
|
cmaf.LoadSubtitle(_subtitle, null, fileName);
|
||||||
|
SetCurrentFormat(Configuration.Settings.General.DefaultSubtitleFormat);
|
||||||
|
SetEncoding(Configuration.Settings.General.DefaultEncoding);
|
||||||
|
encoding = GetCurrentEncoding();
|
||||||
|
justConverted = true;
|
||||||
|
format = GetCurrentSubtitleFormat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (format == null || format.Name == Scenarist.NameOfFormat)
|
if (format == null || format.Name == Scenarist.NameOfFormat)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 14.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 14
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 14.0.23107.0
|
VisualStudioVersion = 15.0.26430.14
|
||||||
MinimumVisualStudioVersion = 14.0.23107.0
|
MinimumVisualStudioVersion = 14.0.23107.0
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SubtitleEdit", "SubtitleEdit.csproj", "{511A5B59-1C35-4719-8536-23B19AF9B21A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SubtitleEdit", "SubtitleEdit.csproj", "{511A5B59-1C35-4719-8536-23B19AF9B21A}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
Loading…
Reference in New Issue
Block a user