Added German language file - thx JW 301 :)

Also some cleanup + some shortcuts (+ some testing of TS files)


git-svn-id: https://subtitleedit.googlecode.com/svn/trunk@716 99eadd0c-20b8-1223-b5c4-2a2b2df33de2
This commit is contained in:
niksedk 2011-10-13 20:26:18 +00:00
parent bfc04f7a70
commit 68397dbd57
16 changed files with 2437 additions and 88 deletions

View File

@ -128,6 +128,8 @@ namespace Nikse.SubtitleEdit.Controls
public bool Locked { get; set; }
public double VerticalZoomPercent { get; set; }
public double EndPositionSeconds
{
get
@ -198,6 +200,7 @@ namespace Nikse.SubtitleEdit.Controls
AllowNewSelection = true;
ShowSpectrogram = true;
ShowWaveform = true;
VerticalZoomPercent = 1.0;
}
public void NearestSubtitles(Subtitle subtitle, double currentVideoPositionSeconds, int subtitleIndex)
@ -316,6 +319,9 @@ namespace Nikse.SubtitleEdit.Controls
}
int imageHeight = Height;
int maxHeight = (int)(Math.Max(Math.Abs(_wavePeaks.DataMinValue), Math.Abs(_wavePeaks.DataMaxValue)) + 0.5);
maxHeight = (int)(maxHeight * VerticalZoomPercent);
if (maxHeight < 0)
maxHeight = 1000;
Pen pen = new System.Drawing.Pen(Color);
DrawBackground(graphics);

View File

@ -123,6 +123,8 @@ namespace Nikse.SubtitleEdit.Forms
public void Initialize(Subtitle subtitle)
{
_autoDetectGoogleLanguage = Utilities.AutoDetectGoogleLanguage(subtitle);
if (_autoDetectGoogleLanguage.ToLower() == "zh")
_autoDetectGoogleLanguage = "zh-CHS"; // Note that "zh-CHS" (Simplified Chinese) and "zh-CHT" (Traditional Chinese) are neutral cultures
CultureInfo ci = CultureInfo.GetCultureInfo(_autoDetectGoogleLanguage);
string threeLetterISOLanguageName = ci.ThreeLetterISOLanguageName;

View File

@ -157,8 +157,8 @@
this.pointSyncViaOtherSubtitleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItemChangeFrameRate2 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItemAutoTranslate = new System.Windows.Forms.ToolStripMenuItem();
this.translatepoweredByMicrosoftToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.translateByGoogleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.translatepoweredByMicrosoftToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.translateFromSwedishToDanishToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@ -1505,13 +1505,6 @@
this.toolStripMenuItemAutoTranslate.Size = new System.Drawing.Size(97, 20);
this.toolStripMenuItemAutoTranslate.Text = "Auto-translate";
//
// translatepoweredByMicrosoftToolStripMenuItem
//
this.translatepoweredByMicrosoftToolStripMenuItem.Name = "translatepoweredByMicrosoftToolStripMenuItem";
this.translatepoweredByMicrosoftToolStripMenuItem.Size = new System.Drawing.Size(414, 22);
this.translatepoweredByMicrosoftToolStripMenuItem.Text = "Translate (powered by Microsoft)...";
this.translatepoweredByMicrosoftToolStripMenuItem.Click += new System.EventHandler(this.translatepoweredByMicrosoftToolStripMenuItem_Click);
//
// translateByGoogleToolStripMenuItem
//
this.translateByGoogleToolStripMenuItem.Name = "translateByGoogleToolStripMenuItem";
@ -1521,6 +1514,13 @@
this.translateByGoogleToolStripMenuItem.Text = "Translate (powered by Google)...";
this.translateByGoogleToolStripMenuItem.Click += new System.EventHandler(this.TranslateByGoogleToolStripMenuItemClick);
//
// translatepoweredByMicrosoftToolStripMenuItem
//
this.translatepoweredByMicrosoftToolStripMenuItem.Name = "translatepoweredByMicrosoftToolStripMenuItem";
this.translatepoweredByMicrosoftToolStripMenuItem.Size = new System.Drawing.Size(414, 22);
this.translatepoweredByMicrosoftToolStripMenuItem.Text = "Translate (powered by Microsoft)...";
this.translatepoweredByMicrosoftToolStripMenuItem.Click += new System.EventHandler(this.translatepoweredByMicrosoftToolStripMenuItem_Click);
//
// translateFromSwedishToDanishToolStripMenuItem
//
this.translateFromSwedishToDanishToolStripMenuItem.Name = "translateFromSwedishToDanishToolStripMenuItem";

View File

@ -91,6 +91,10 @@ namespace Nikse.SubtitleEdit.Forms
Keys _mainAdjustSetStartAndOffsetTheRest = Keys.None;
Keys _mainAdjustSetEndAndGotoNext = Keys.None;
Keys _mainAdjustInsertViaEndAutoStartAndGoToNext = Keys.None;
Keys _mainInsertAfter = Keys.None;
Keys _mainInsertBefore = Keys.None;
Keys _mainListViewToggleDashes = Keys.None;
Keys _waveformVerticalZoom = Keys.None;
bool _videoLoadedGoToSubPosAndPause = false;
bool _makeHistory = true;
string _cutText = string.Empty;
@ -1434,11 +1438,11 @@ namespace Nikse.SubtitleEdit.Forms
var fi = new FileInfo(fileName);
if (Path.GetExtension(fileName).ToLower() == ".ts" && fi.Length > 10000)
{
//ImportSubtitleFromTransportStream();
//return;
}
//if (Path.GetExtension(fileName).ToLower() == ".ts" && fi.Length > 10000 && IsTransportStream(fileName)) //TODO: Also check mpg, mpeg - and file header!
//{
// ImportSubtitleFromTransportStream();
// return;
//}
if ((Path.GetExtension(fileName).ToLower() == ".mp4" || Path.GetExtension(fileName).ToLower() == ".m4v" || Path.GetExtension(fileName).ToLower() == ".3gp")
&& fi.Length > 10000)
@ -1699,26 +1703,37 @@ namespace Nikse.SubtitleEdit.Forms
}
}
private bool IsTransportStream(string fileName)
{
try
{
var buffer = new byte[1];
var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read) { Position = 0 };
fs.Read(buffer, 0, buffer.Length);
fs.Close();
return buffer[0] == 0x47; // 47hex (71 dec) == TS sync byte
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
return false;
}
}
private void SetUndockedWindowsTitle()
{
string title = Configuration.Settings.Language.General.NoVideoLoaded;
if (!string.IsNullOrEmpty(_videoFileName))
title = Path.GetFileNameWithoutExtension(_videoFileName);
try //TODO: Remove in 3.2 final
{
if (_videoControlsUnDocked != null && !_videoControlsUnDocked.IsDisposed)
_videoControlsUnDocked.Text = string.Format(Configuration.Settings.Language.General.ControlsWindowTitle, title);
if (_videoControlsUnDocked != null && !_videoControlsUnDocked.IsDisposed)
_videoControlsUnDocked.Text = string.Format(Configuration.Settings.Language.General.ControlsWindowTitle, title);
if (_videoPlayerUnDocked != null && !_videoPlayerUnDocked.IsDisposed)
_videoPlayerUnDocked.Text = string.Format(Configuration.Settings.Language.General.VideoWindowTitle, title);
if (_videoPlayerUnDocked != null && !_videoPlayerUnDocked.IsDisposed)
_videoPlayerUnDocked.Text = string.Format(Configuration.Settings.Language.General.VideoWindowTitle, title);
if (_waveFormUnDocked != null && !_waveFormUnDocked.IsDisposed)
_waveFormUnDocked.Text = string.Format(Configuration.Settings.Language.General.AudioWindowTitle, title);
}
catch
{
}
if (_waveFormUnDocked != null && !_waveFormUnDocked.IsDisposed)
_waveFormUnDocked.Text = string.Format(Configuration.Settings.Language.General.AudioWindowTitle, title);
}
private void ImportAndOcrBdnXml(string fileName, BdnXml bdnXml, List<string> list)
@ -5818,16 +5833,69 @@ namespace Nikse.SubtitleEdit.Forms
}
}
private void ImportSubtitleFromTransportStream()
private bool ImportSubtitleFromTransportStream()
{
//TransportStreamParser tsParser = new TransportStreamParser();
//tsParser.ParseTsFile(openFileDialog1.FileName);
var tsParser = new Nikse.SubtitleEdit.Logic.TransportStream.TransportStreamParser();
tsParser.ParseTsFile(openFileDialog1.FileName);
//var vobSubOcr = new VobSubOcr();
//vobSubOcr.Initialize(tsParser.MergeVobSubPacks(), null, Configuration.Settings.VobSubOcr, null);
//if (vobSubOcr.ShowDialog(this) == DialogResult.OK)
//{
//}
if (tsParser.SubtitlePacketIds.Count == 0)
{
MessageBox.Show(_language.NoSubtitlesFound);
return false;
}
var log = new StringBuilder();
List<BluRaySupPicture> subtitles = new List<BluRaySupPicture>();
var pesList = tsParser.GetSubtitlePesPackets(tsParser.SubtitlePacketIds[0]);
foreach (var sp in pesList)
{
if (sp.DataBuffer != null)
{
MemoryStream ms = new MemoryStream(sp.DataBuffer);
var list = BluRaySupParser.ParseBluRaySup(ms, log, true);
foreach (var sup in list)
{
//sup.StartTime = p.StartMilliseconds;
//sup.EndTime = p.EndMilliseconds;
subtitles.Add(sup);
// fix overlapping
//if (subtitles.Count > 1 && sub[subtitles.Count - 2].EndMilliseconds > sub[subtitles.Count - 1].StartMilliseconds)
// subtitles[subtitles.Count - 2].EndTime = subtitles[subtitles.Count - 1].StartTime - 1;
}
ms.Close();
}
}
var formSubOcr = new VobSubOcr();
formSubOcr.Initialize(subtitles, Configuration.Settings.VobSubOcr);
if (formSubOcr.ShowDialog(this) == DialogResult.OK)
{
MakeHistoryForUndo(_language.BeforeImportingDvdSubtitle);
_subtitle.Paragraphs.Clear();
SetCurrentFormat(new SubRip().FriendlyName);
_subtitle.WasLoadedWithFrameNumbers = false;
_subtitle.CalculateFrameNumbersFromTimeCodes(CurrentFrameRate);
foreach (Paragraph p in formSubOcr.SubtitleFromOcr.Paragraphs)
{
_subtitle.Paragraphs.Add(p);
}
ShowSource();
SubtitleListview1.Fill(_subtitle, _subtitleAlternate);
_change = true;
_subtitleListViewIndex = -1;
SubtitleListview1.FirstVisibleIndex = -1;
SubtitleListview1.SelectIndexAndEnsureVisible(0);
_fileName = string.Empty;
Text = Title;
Configuration.Settings.Save();
return true;
}
return false;
}
private bool ImportSubtitleFromMp4(string fileName)
@ -6437,18 +6505,28 @@ namespace Nikse.SubtitleEdit.Forms
bool inListView = tabControlSubtitle.SelectedIndex == TabControlListView;
if (e.Modifiers == Keys.Alt && e.KeyCode == Keys.Insert && inListView)
if (audioVisualizer != null && audioVisualizer.Visible)
{
InsertAfter();
e.SuppressKeyPress = true;
textBoxListViewText.Focus();
if (e.KeyData == _waveformVerticalZoom)
{
if (audioVisualizer.VerticalZoomPercent > 0.2)
audioVisualizer.VerticalZoomPercent -= 0.1;
else
audioVisualizer.VerticalZoomPercent = 1;
e.SuppressKeyPress = true;
}
}
else if (e.Modifiers == (Keys.Shift | Keys.Control) && e.KeyCode == Keys.Insert && inListView)
else if (_mainInsertBefore == e.KeyData && inListView)
{
InsertBefore();
e.SuppressKeyPress = true;
textBoxListViewText.Focus();
}
else if (_mainListViewToggleDashes == e.KeyData && inListView)
{
ToggleDashes();
e.SuppressKeyPress = true;
}
else if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Z)
{
ShowHistoryforUndoToolStripMenuItemClick(null, null);
@ -6871,6 +6949,74 @@ namespace Nikse.SubtitleEdit.Forms
// put new entries above tabs
}
private void ToggleDashes()
{
int index = FirstSelectedIndex;
if (index >= 0)
{
bool hasStartDash = false;
var p = _subtitle.Paragraphs[index];
string[] lines = p.Text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
if (line.Trim().StartsWith("-") || line.Trim().StartsWith("<i>-") || line.Trim().StartsWith("<i> -"))
hasStartDash = true;
}
if (hasStartDash)
RemoveDashes();
else
AddDashes();
}
}
private void AddDashes()
{
foreach (int index in SubtitleListview1.SelectedIndices)
{
var p = _subtitle.Paragraphs[index];
string[] lines = p.Text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
var sb = new StringBuilder();
foreach (string line in lines)
{
if (line.Trim().StartsWith("-") || line.Trim().StartsWith("<i>-") || line.Trim().StartsWith("<i> -"))
sb.AppendLine(line);
else if (line.Trim().StartsWith("<i>") && line.Trim().Length > 3)
sb.AppendLine("<i>-" + line.Substring(3));
else
sb.AppendLine("- " + line);
}
string text = sb.ToString().Trim(); ;
_subtitle.Paragraphs[index].Text = text;
SubtitleListview1.SetText(index, text);
if (index == _subtitleListViewIndex)
textBoxListViewText.Text = text;
}
}
private void RemoveDashes()
{
foreach (int index in SubtitleListview1.SelectedIndices)
{
var p = _subtitle.Paragraphs[index];
string[] lines = p.Text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
var sb = new StringBuilder();
foreach (string line in lines)
{
if (line.Trim().StartsWith("-"))
sb.AppendLine(line.TrimStart().TrimStart('-').TrimStart());
else if (line.Trim().StartsWith("<i>-") || line.Trim().StartsWith("<i> -"))
sb.AppendLine("<i>" + line.TrimStart().Substring(3).TrimStart().TrimStart('-').TrimStart());
else
sb.AppendLine(line);
}
string text = sb.ToString().Trim(); ;
_subtitle.Paragraphs[index].Text = text;
SubtitleListview1.SetText(index, text);
if (index == _subtitleListViewIndex)
textBoxListViewText.Text = text;
}
}
private void SetTitle()
{
Text = Title;
@ -6981,12 +7127,12 @@ namespace Nikse.SubtitleEdit.Forms
{
ToolStripMenuItemDeleteClick(null, null);
}
else if (e.Modifiers == Keys.Shift && e.KeyCode == Keys.Insert)
else if (e.KeyData == _mainInsertBefore)
{
InsertBefore();
e.SuppressKeyPress = true;
}
else if (e.KeyCode == Keys.Insert)
else if (e.KeyData == _mainInsertAfter)
{
InsertAfter();
e.SuppressKeyPress = true;
@ -8992,10 +9138,14 @@ namespace Nikse.SubtitleEdit.Forms
toolStripMenuItemAdjustAllTimes.ShortcutKeys = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainSynchronizationAdjustTimes);
italicToolStripMenuItem.ShortcutKeys = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainListViewItalic);
_mainListViewToggleDashes = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainListViewToggleDashes);
italicToolStripMenuItem1.ShortcutKeys = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainTextBoxItalic);
_mainAdjustSetStartAndOffsetTheRest = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSetStartAndOffsetTheRest);
_mainAdjustSetEndAndGotoNext = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSetEndAndGotoNext);
_mainAdjustInsertViaEndAutoStartAndGoToNext = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainAdjustViaEndAutoStartAndGoToNext);
_mainInsertAfter = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainInsertAfter);
_mainInsertBefore = Utilities.GetKeys(Configuration.Settings.Shortcuts.MainInsertBefore);
_waveformVerticalZoom = Utilities.GetKeys(Configuration.Settings.Shortcuts.WaveformVerticalZoom);
}
private void LoadPlugins()

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@ -681,7 +681,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAD2
CAAAAk1TRnQBSQFMAgEBAgEAAYgBCwGIAQsBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
CAAAAk1TRnQBSQFMAgEBAgEAAagBCwGoAQsBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA

View File

@ -51,7 +51,6 @@ namespace Nikse.SubtitleEdit.Forms
labelMaxCharacters.Text = Configuration.Settings.Language.MergedShortLines.MaximumCharacters;
labelMaxMillisecondsBetweenLines.Text = Configuration.Settings.Language.MergedShortLines.MaximumMillisecondsBetween;
checkBoxOnlyContinuationLines.Visible = !string.IsNullOrEmpty(Configuration.Settings.Language.MergedShortLines.OnlyMergeContinuationLines); //TODO: Remove in se 3.2
checkBoxOnlyContinuationLines.Text = Configuration.Settings.Language.MergedShortLines.OnlyMergeContinuationLines;
listViewFixes.Columns[0].Text = Configuration.Settings.Language.General.Apply;

View File

@ -423,10 +423,6 @@ namespace Nikse.SubtitleEdit.Forms
comboBoxSpectrogramAppearance.SelectedIndex = 1;
//<MainFileNew>Control+N</MainFileNew>
//<MainFileOpen>Control+O</MainFileOpen>
//<MainFileSave>Control+S</MainFileSave>
//<MainFileSaveAs>Control+Shift+S</MainFileSaveAs>
TreeNode fileNode = new TreeNode(Configuration.Settings.Language.Main.Menu.File.Title);
fileNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.File.New + GetShortcutText(Configuration.Settings.Shortcuts.MainFileNew));
fileNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.File.Open + GetShortcutText(Configuration.Settings.Shortcuts.MainFileOpen));
@ -435,10 +431,6 @@ namespace Nikse.SubtitleEdit.Forms
fileNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.File.Export + " -> " + Configuration.Settings.Language.Main.Menu.File.ExportEbu + GetShortcutText(Configuration.Settings.Shortcuts.MainFileExportEbu));
treeViewShortcuts.Nodes.Add(fileNode);
//<MainEditFind>Control+F</MainEditFind>
//<MainEditFindNext>F3</MainEditFindNext>
//<MainEditReplace>Control+H</MainEditReplace>
//<MainEditGoToLineNumber>Control+G</MainEditGoToLineNumber>
TreeNode editNode = new TreeNode(Configuration.Settings.Language.Main.Menu.Edit.Title);
editNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.Edit.Find + GetShortcutText(Configuration.Settings.Shortcuts.MainEditFind));
editNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.Edit.FindNext + GetShortcutText(Configuration.Settings.Shortcuts.MainEditFindNext));
@ -450,23 +442,22 @@ namespace Nikse.SubtitleEdit.Forms
toolsNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.Tools.FixCommonErrors + GetShortcutText(Configuration.Settings.Shortcuts.MainToolsFixCommonErrors));
treeViewShortcuts.Nodes.Add(toolsNode);
//<MainVideoShowHideVideo>Control+Q</MainVideoShowHideVideo>
TreeNode videoNode = new TreeNode(Configuration.Settings.Language.Main.Menu.Video.Title);
videoNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.Video.ShowHideVideo + GetShortcutText(Configuration.Settings.Shortcuts.MainVideoShowHideVideo));
videoNode.Nodes.Add(Configuration.Settings.Language.Settings.ToggleDockUndockOfVideoControls + GetShortcutText(Configuration.Settings.Shortcuts.MainVideoToggleVideoControls));
treeViewShortcuts.Nodes.Add(videoNode);
//<MainSynchronizationAdjustTimes>Control+Shift+A</MainSynchronizationAdjustTimes>
TreeNode SyncNode = new TreeNode(Configuration.Settings.Language.Main.Menu.Synchronization.Title);
SyncNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.Synchronization.AdjustAllTimes + GetShortcutText(Configuration.Settings.Shortcuts.MainSynchronizationAdjustTimes));
treeViewShortcuts.Nodes.Add(SyncNode);
//<MainListViewItalic>Control+G</MainListViewItalic>
TreeNode ListViewNode = new TreeNode(Configuration.Settings.Language.Main.Controls.ListView);
ListViewNode.Nodes.Add(Configuration.Settings.Language.General.Italic + GetShortcutText(Configuration.Settings.Shortcuts.MainListViewItalic));
ListViewNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.ContextMenu.InsertAfter + GetShortcutText(Configuration.Settings.Shortcuts.MainInsertAfter));
ListViewNode.Nodes.Add(Configuration.Settings.Language.Main.Menu.ContextMenu.InsertBefore + GetShortcutText(Configuration.Settings.Shortcuts.MainInsertBefore));
ListViewNode.Nodes.Add("Toggle dashes" + GetShortcutText(Configuration.Settings.Shortcuts.MainListViewToggleDashes));
treeViewShortcuts.Nodes.Add(ListViewNode);
//<MainTextBoxItalic>Control+I</MainTextBoxItalic>
TreeNode TextBoxNode = new TreeNode(Configuration.Settings.Language.Settings.TextBox);
TextBoxNode.Nodes.Add(Configuration.Settings.Language.General.Italic + GetShortcutText(Configuration.Settings.Shortcuts.MainTextBoxItalic));
treeViewShortcuts.Nodes.Add(TextBoxNode);
@ -477,6 +468,11 @@ namespace Nikse.SubtitleEdit.Forms
adjustNode.Nodes.Add(Configuration.Settings.Language.Settings.AdjustViaEndAutoStartAndGoToNext + GetShortcutText(Configuration.Settings.Shortcuts.MainAdjustViaEndAutoStartAndGoToNext));
treeViewShortcuts.Nodes.Add(adjustNode);
TreeNode audioVisualizerNode = new TreeNode(Configuration.Settings.Language.Settings.WaveformAndSpectrogram);
audioVisualizerNode.Nodes.Add("Vertical zoom" + GetShortcutText(Configuration.Settings.Shortcuts.WaveformVerticalZoom));
treeViewShortcuts.Nodes.Add(audioVisualizerNode);
foreach (TreeNode node in treeViewShortcuts.Nodes)
{
node.Text = node.Text.Replace("&", string.Empty);
@ -886,6 +882,12 @@ namespace Nikse.SubtitleEdit.Forms
string text = node.Text.Substring(0, node.Text.IndexOf("[")).Trim();
if (text == Configuration.Settings.Language.General.Italic.Replace("&", string.Empty))
Configuration.Settings.Shortcuts.MainListViewItalic = GetShortcut(node.Text);
else if (text == Configuration.Settings.Language.Main.Menu.ContextMenu.InsertAfter.Replace("&", string.Empty))
Configuration.Settings.Shortcuts.MainInsertAfter = GetShortcut(node.Text);
else if (text == Configuration.Settings.Language.Main.Menu.ContextMenu.InsertBefore.Replace("&", string.Empty))
Configuration.Settings.Shortcuts.MainInsertBefore = GetShortcut(node.Text);
else if (text == ("Toggle dashes").Replace("&", string.Empty))
Configuration.Settings.Shortcuts.MainListViewToggleDashes = GetShortcut(node.Text);
}
}
@ -915,6 +917,17 @@ namespace Nikse.SubtitleEdit.Forms
}
}
//Audio-visualizer
foreach (TreeNode node in treeViewShortcuts.Nodes[8].Nodes)
{
if (node.Text.Contains("["))
{
string text = node.Text.Substring(0, node.Text.IndexOf("[")).Trim();
if (text == ("Vertical zoom").Replace("&", string.Empty))
Configuration.Settings.Shortcuts.WaveformVerticalZoom = GetShortcut(node.Text);
}
}
Configuration.Settings.Save();
}

View File

@ -29,7 +29,6 @@ namespace Nikse.SubtitleEdit.Forms
public WaveFormUnDocked()
{
// TODO: Complete member initialization
}
private void WaveFormUnDocked_FormClosing(object sender, FormClosingEventArgs e)

1283
src/Languages/de-DE.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -427,10 +427,14 @@ namespace Nikse.SubtitleEdit.Logic
public string MainVideoToggleVideoControls { get; set; }
public string MainSynchronizationAdjustTimes { get; set; }
public string MainListViewItalic { get; set; }
public string MainListViewToggleDashes { get; set; }
public string MainTextBoxItalic { get; set; }
public string MainAdjustSetStartAndOffsetTheRest { get; set; }
public string MainAdjustSetEndAndGotoNext { get; set; }
public string MainAdjustViaEndAutoStartAndGoToNext { get; set; }
public string MainInsertAfter { get; set; }
public string MainInsertBefore { get; set; }
public string WaveformVerticalZoom { get; set; }
public Shortcuts()
{
@ -451,6 +455,9 @@ namespace Nikse.SubtitleEdit.Logic
MainAdjustSetStartAndOffsetTheRest = "Control+Space";
MainAdjustSetEndAndGotoNext = "Shift+Space";
MainAdjustViaEndAutoStartAndGoToNext = "Shift+End";
MainInsertAfter = "Alt+Ins";
MainInsertBefore = "Control+Shift+Ins";
WaveformVerticalZoom = string.Empty;
}
}
@ -530,10 +537,8 @@ namespace Nikse.SubtitleEdit.Logic
public void Save()
{
//slow
//Serialize(Configuration.BaseDirectory + "Settings.xml", this);
//this is too slow: Serialize(Configuration.BaseDirectory + "Settings.xml", this);
//Fast - TODO: Fix in release
CustomSerialize(Configuration.SettingsFileName, this);
}
@ -553,11 +558,9 @@ namespace Nikse.SubtitleEdit.Logic
{
try
{
//TODO: Fix in release
settings = CustomDeserialize(settingsFileName); // 15 msecs
//too slow... :(
//settings = Deserialize(Configuration.BaseDirectory + "Settings.xml"); // 688 msecs
//too slow... :( - settings = Deserialize(Configuration.BaseDirectory + "Settings.xml"); // 688 msecs
}
catch
{
@ -1138,6 +1141,9 @@ namespace Nikse.SubtitleEdit.Logic
subNode = node.SelectSingleNode("MainListViewItalic");
if (subNode != null)
settings.Shortcuts.MainListViewItalic = subNode.InnerText;
subNode = node.SelectSingleNode("MainListViewToggleDashes");
if (subNode != null)
settings.Shortcuts.MainListViewToggleDashes = subNode.InnerText;
subNode = node.SelectSingleNode("MainTextBoxItalic");
if (subNode != null)
settings.Shortcuts.MainTextBoxItalic = subNode.InnerText;
@ -1150,6 +1156,15 @@ namespace Nikse.SubtitleEdit.Logic
subNode = node.SelectSingleNode("MainAdjustViaEndAutoStartAndGoToNext");
if (subNode != null)
settings.Shortcuts.MainAdjustViaEndAutoStartAndGoToNext = subNode.InnerText;
subNode = node.SelectSingleNode("MainInsertAfter");
if (subNode != null)
settings.Shortcuts.MainInsertAfter = subNode.InnerText;
subNode = node.SelectSingleNode("MainInsertBefore");
if (subNode != null)
settings.Shortcuts.MainInsertBefore = subNode.InnerText;
subNode = node.SelectSingleNode("WaveformVerticalZoom");
if (subNode != null)
settings.Shortcuts.WaveformVerticalZoom = subNode.InnerText;
}
settings.RemoveTextForHearingImpaired = new RemoveTextForHearingImpairedSettings();
@ -1410,10 +1425,14 @@ namespace Nikse.SubtitleEdit.Logic
textWriter.WriteElementString("MainVideoToggleVideoControls", settings.Shortcuts.MainVideoToggleVideoControls);
textWriter.WriteElementString("MainSynchronizationAdjustTimes", settings.Shortcuts.MainSynchronizationAdjustTimes);
textWriter.WriteElementString("MainListViewItalic", settings.Shortcuts.MainListViewItalic);
textWriter.WriteElementString("MainListViewToggleDashes", settings.Shortcuts.MainListViewToggleDashes);
textWriter.WriteElementString("MainTextBoxItalic", settings.Shortcuts.MainTextBoxItalic);
textWriter.WriteElementString("MainAdjustSetStartAndOffsetTheRest", settings.Shortcuts.MainAdjustSetStartAndOffsetTheRest);
textWriter.WriteElementString("MainAdjustSetEndAndGotoNext", settings.Shortcuts.MainAdjustSetEndAndGotoNext);
textWriter.WriteElementString("MainAdjustViaEndAutoStartAndGoToNext", settings.Shortcuts.MainAdjustViaEndAutoStartAndGoToNext);
textWriter.WriteElementString("MainInsertAfter", settings.Shortcuts.MainInsertAfter);
textWriter.WriteElementString("MainInsertBefore", settings.Shortcuts.MainInsertBefore);
textWriter.WriteElementString("WaveformVerticalZoom", settings.Shortcuts.WaveformVerticalZoom);
textWriter.WriteEndElement();
textWriter.WriteStartElement("RemoveTextForHearingImpaired", "");

View File

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Nikse.SubtitleEdit.Logic.TransportStream
{
public class AdaptationField
{
/// <summary>
/// Number of bytes in the adaptation field immediately following the Length
/// </summary>
public int Length { get; set; }
public bool DiscontinuityIndicator { get; set; }
public bool RandomAccessIndicator { get; set; }
public bool ElementaryStreamPriorityIndicator { get; set; }
/// <summary>
/// '1' indicates that the adaptation field contains a PCR field coded in two parts
/// </summary>
public bool PcrFlag { get; set; }
/// <summary>
/// '1' indicates that the adaptation field contains an OPCR field coded in two parts
/// </summary>
public bool OpcrFlag { get; set; }
/// <summary>
/// '1' indicates that a splice countdown field shall be present in the associated adaptation field
/// </summary>
public bool SplicingPointFlag { get; set; }
/// <summary>
/// 1' indicates that the adaptation field contains one or more private data bytes
/// </summary>
public bool TransportPrivateDataFlag { get; set; }
/// <summary>
/// '1' indicates the presence of an adaptation field extension
/// </summary>
public bool AdaptationFieldExtensionFlag { get; set; }
public int ProgramClockReferenceBase { get; set; }
public int ProgramClockReferenceExtension { get; set; }
public int OriginalProgramClockReferenceBase { get; set; }
public int OriginalProgramClockReferenceExtension { get; set; }
public int SpliceCountdown { get; set; }
public int TransportPrivateDataLength { get; set; }
public byte[] TransportPrivateData { get; set; }
public int AdaptationFieldExtensionLength { get; set; }
public AdaptationField(byte[] packetBuffer)
{
Length = packetBuffer[4];
DiscontinuityIndicator = 1 == packetBuffer[5] >> 7;
RandomAccessIndicator = 1 == (packetBuffer[5] & 64); // and with 01000000 to get second byte
ElementaryStreamPriorityIndicator = 1 == (packetBuffer[5] & 32); // and with 00100000 to get third byte
PcrFlag = 1 == (packetBuffer[5] & 16); // and with 00010000 to get fourth byte
OpcrFlag = 1 == (packetBuffer[5] & 8); // and with 00001000 to get fifth byte
SplicingPointFlag = 1 == (packetBuffer[5] & 4); // and with 00000100 to get sixth byte
TransportPrivateDataFlag = 1 == (packetBuffer[5] & 2); // and with 00000100 to get seventh byte
AdaptationFieldExtensionFlag = 1 == (packetBuffer[5] & 1); // and with 00000010 to get 8th byte
int index = 6;
if (PcrFlag)
{
ProgramClockReferenceBase = (packetBuffer[index] * 256 + packetBuffer[index + 1]) << 1;
ProgramClockReferenceBase += packetBuffer[index + 2] >> 7;
ProgramClockReferenceExtension = (packetBuffer[index + 2] & Helper.B00000001) * 256 + packetBuffer[index + 3];
index += 4;
}
if (OpcrFlag)
{
OriginalProgramClockReferenceBase = (packetBuffer[index] * 256 + packetBuffer[index + 1]) << 1;
OriginalProgramClockReferenceBase += packetBuffer[index + 2] >> 7;
OriginalProgramClockReferenceExtension = (packetBuffer[index + 2] & Helper.B00000001) * 256 + packetBuffer[index + 3];
index += 4;
}
if (SplicingPointFlag)
{
SpliceCountdown = packetBuffer[index];
index++;
}
if (TransportPrivateDataFlag)
{
TransportPrivateDataLength = packetBuffer[index];
index++;
TransportPrivateData = new byte[TransportPrivateDataLength];
Buffer.BlockCopy(packetBuffer, index, TransportPrivateData, 0, TransportPrivateDataLength);
index += TransportPrivateDataLength;
}
if (AdaptationFieldExtensionFlag)
{
AdaptationFieldExtensionLength = packetBuffer[index];
}
}
}
}

View File

@ -0,0 +1,329 @@
using System;
using System.Text;
namespace Nikse.SubtitleEdit.Logic.TransportStream
{
public static class Helper
{
#region Binary constants
public const int B00000000 = 0;
public const int B00000001 = 1;
public const int B00000010 = 2;
public const int B00000011 = 3;
public const int B00000100 = 4;
public const int B00000101 = 5;
public const int B00000110 = 6;
public const int B00000111 = 7;
public const int B00001000 = 8;
public const int B00001001 = 9;
public const int B00001010 = 10;
public const int B00001011 = 11;
public const int B00001100 = 12;
public const int B00001101 = 13;
public const int B00001110 = 14;
public const int B00001111 = 15;
public const int B00010000 = 16;
public const int B00010001 = 17;
public const int B00010010 = 18;
public const int B00010011 = 19;
public const int B00010100 = 20;
public const int B00010101 = 21;
public const int B00010110 = 22;
public const int B00010111 = 23;
public const int B00011000 = 24;
public const int B00011001 = 25;
public const int B00011010 = 26;
public const int B00011011 = 27;
public const int B00011100 = 28;
public const int B00011101 = 29;
public const int B00011110 = 30;
public const int B00011111 = 31;
public const int B00100000 = 32;
public const int B00100001 = 33;
public const int B00100010 = 34;
public const int B00100011 = 35;
public const int B00100100 = 36;
public const int B00100101 = 37;
public const int B00100110 = 38;
public const int B00100111 = 39;
public const int B00101000 = 40;
public const int B00101001 = 41;
public const int B00101010 = 42;
public const int B00101011 = 43;
public const int B00101100 = 44;
public const int B00101101 = 45;
public const int B00101110 = 46;
public const int B00101111 = 47;
public const int B00110000 = 48;
public const int B00110001 = 49;
public const int B00110010 = 50;
public const int B00110011 = 51;
public const int B00110100 = 52;
public const int B00110101 = 53;
public const int B00110110 = 54;
public const int B00110111 = 55;
public const int B00111000 = 56;
public const int B00111001 = 57;
public const int B00111010 = 58;
public const int B00111011 = 59;
public const int B00111100 = 60;
public const int B00111101 = 61;
public const int B00111110 = 62;
public const int B00111111 = 63;
public const int B01000000 = 64;
public const int B01000001 = 65;
public const int B01000010 = 66;
public const int B01000011 = 67;
public const int B01000100 = 68;
public const int B01000101 = 69;
public const int B01000110 = 70;
public const int B01000111 = 71;
public const int B01001000 = 72;
public const int B01001001 = 73;
public const int B01001010 = 74;
public const int B01001011 = 75;
public const int B01001100 = 76;
public const int B01001101 = 77;
public const int B01001110 = 78;
public const int B01001111 = 79;
public const int B01010000 = 80;
public const int B01010001 = 81;
public const int B01010010 = 82;
public const int B01010011 = 83;
public const int B01010100 = 84;
public const int B01010101 = 85;
public const int B01010110 = 86;
public const int B01010111 = 87;
public const int B01011000 = 88;
public const int B01011001 = 89;
public const int B01011010 = 90;
public const int B01011011 = 91;
public const int B01011100 = 92;
public const int B01011101 = 93;
public const int B01011110 = 94;
public const int B01011111 = 95;
public const int B01100000 = 96;
public const int B01100001 = 97;
public const int B01100010 = 98;
public const int B01100011 = 99;
public const int B01100100 = 100;
public const int B01100101 = 101;
public const int B01100110 = 102;
public const int B01100111 = 103;
public const int B01101000 = 104;
public const int B01101001 = 105;
public const int B01101010 = 106;
public const int B01101011 = 107;
public const int B01101100 = 108;
public const int B01101101 = 109;
public const int B01101110 = 110;
public const int B01101111 = 111;
public const int B01110000 = 112;
public const int B01110001 = 113;
public const int B01110010 = 114;
public const int B01110011 = 115;
public const int B01110100 = 116;
public const int B01110101 = 117;
public const int B01110110 = 118;
public const int B01110111 = 119;
public const int B01111000 = 120;
public const int B01111001 = 121;
public const int B01111010 = 122;
public const int B01111011 = 123;
public const int B01111100 = 124;
public const int B01111101 = 125;
public const int B01111110 = 126;
public const int B01111111 = 127;
public const int B10000000 = 128;
public const int B10000001 = 129;
public const int B10000010 = 130;
public const int B10000011 = 131;
public const int B10000100 = 132;
public const int B10000101 = 133;
public const int B10000110 = 134;
public const int B10000111 = 135;
public const int B10001000 = 136;
public const int B10001001 = 137;
public const int B10001010 = 138;
public const int B10001011 = 139;
public const int B10001100 = 140;
public const int B10001101 = 141;
public const int B10001110 = 142;
public const int B10001111 = 143;
public const int B10010000 = 144;
public const int B10010001 = 145;
public const int B10010010 = 146;
public const int B10010011 = 147;
public const int B10010100 = 148;
public const int B10010101 = 149;
public const int B10010110 = 150;
public const int B10010111 = 151;
public const int B10011000 = 152;
public const int B10011001 = 153;
public const int B10011010 = 154;
public const int B10011011 = 155;
public const int B10011100 = 156;
public const int B10011101 = 157;
public const int B10011110 = 158;
public const int B10011111 = 159;
public const int B10100000 = 160;
public const int B10100001 = 161;
public const int B10100010 = 162;
public const int B10100011 = 163;
public const int B10100100 = 164;
public const int B10100101 = 165;
public const int B10100110 = 166;
public const int B10100111 = 167;
public const int B10101000 = 168;
public const int B10101001 = 169;
public const int B10101010 = 170;
public const int B10101011 = 171;
public const int B10101100 = 172;
public const int B10101101 = 173;
public const int B10101110 = 174;
public const int B10101111 = 175;
public const int B10110000 = 176;
public const int B10110001 = 177;
public const int B10110010 = 178;
public const int B10110011 = 179;
public const int B10110100 = 180;
public const int B10110101 = 181;
public const int B10110110 = 182;
public const int B10110111 = 183;
public const int B10111000 = 184;
public const int B10111001 = 185;
public const int B10111010 = 186;
public const int B10111011 = 187;
public const int B10111100 = 188;
public const int B10111101 = 189;
public const int B10111110 = 190;
public const int B10111111 = 191;
public const int B11000000 = 192;
public const int B11000001 = 193;
public const int B11000010 = 194;
public const int B11000011 = 195;
public const int B11000100 = 196;
public const int B11000101 = 197;
public const int B11000110 = 198;
public const int B11000111 = 199;
public const int B11001000 = 200;
public const int B11001001 = 201;
public const int B11001010 = 202;
public const int B11001011 = 203;
public const int B11001100 = 204;
public const int B11001101 = 205;
public const int B11001110 = 206;
public const int B11001111 = 207;
public const int B11010000 = 208;
public const int B11010001 = 209;
public const int B11010010 = 210;
public const int B11010011 = 211;
public const int B11010100 = 212;
public const int B11010101 = 213;
public const int B11010110 = 214;
public const int B11010111 = 215;
public const int B11011000 = 216;
public const int B11011001 = 217;
public const int B11011010 = 218;
public const int B11011011 = 219;
public const int B11011100 = 220;
public const int B11011101 = 221;
public const int B11011110 = 222;
public const int B11011111 = 223;
public const int B11100000 = 224;
public const int B11100001 = 225;
public const int B11100010 = 226;
public const int B11100011 = 227;
public const int B11100100 = 228;
public const int B11100101 = 229;
public const int B11100110 = 230;
public const int B11100111 = 231;
public const int B11101000 = 232;
public const int B11101001 = 233;
public const int B11101010 = 234;
public const int B11101011 = 235;
public const int B11101100 = 236;
public const int B11101101 = 237;
public const int B11101110 = 238;
public const int B11101111 = 239;
public const int B11110000 = 240;
public const int B11110001 = 241;
public const int B11110010 = 242;
public const int B11110011 = 243;
public const int B11110100 = 244;
public const int B11110101 = 245;
public const int B11110110 = 246;
public const int B11110111 = 247;
public const int B11111000 = 248;
public const int B11111001 = 249;
public const int B11111010 = 250;
public const int B11111011 = 251;
public const int B11111100 = 252;
public const int B11111101 = 253;
public const int B11111110 = 254;
public const int B11111111 = 255;
#endregion
public static string IntToHex(UInt64 value, int digits)
{
return value.ToString("X").PadLeft(digits, '0');
}
public static string IntToHex(int value, int digits)
{
return value.ToString("X").PadLeft(digits, '0');
}
public static string IntToBin(long value, int digits)
{
return Convert.ToString(value, 2).PadLeft(digits, '0');
}
public static UInt32 GetEndian(byte[] buffer, int index, int count)
{
UInt32 result = 0;
for (int i = 0; i < count; i++)
result = (result << 8) + buffer[index + i];
return result;
}
public static int GetLittleEndian32(byte[] buffer, int index)
{
return ((int)buffer[index + 3] << 24 | (int)buffer[index + 2] << 16 | (int)buffer[index + 1] << 8 | (int)buffer[index + 0]);
}
//private int Swap4Bytes(byte[] b)
//{
// return ((int)b[3] << 24 | (int)b[2] << 16 | (int)b[1] << 8 | (int)b[0]);
//}
/// <summary>
/// Get two bytes word stored in endian order
/// </summary>
/// <param name="buffer">Byte array</param>
/// <param name="index">Index in byte array</param>
/// <returns>Word as int</returns>
public static int GetEndianWord(byte[] buffer, int index)
{
if (index +1 < buffer.Length)
return (buffer[index] << 8) + buffer[index+1];
return 0;
}
public static string GetBinaryString(byte[] buffer, int index, int count)
{
var sb = new StringBuilder();
for (int i=0; i < count; i++)
sb.Append(Convert.ToString(buffer[index + i], 2).PadLeft(8, '0'));
return sb.ToString();
}
public static UInt64 GetUInt32FromBinaryString(string binaryValue)
{
return Convert.ToUInt32(binaryValue, 2);
}
}
}

View File

@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Nikse.SubtitleEdit.Logic.TransportStream
{
/// <summary>
/// MPEG transport stream packet
/// </summary>
public class Packet
{
/// <summary>
/// ID byte of TS Packet
/// </summary>
public const byte SynchronizationByte = 0x47; // 74 decimal, or 01000111 binary
/// <summary>
/// Null packets can ensure that the stream maintains a constant bitrate. Null packets is to be ignored
/// </summary>
public const int NullPacketId = 0x1FFF;
/// <summary>
/// Program Association Table: lists all programs available in the transport stream.
/// </summary>
public const int ProgramAssociationTablePacketId = 0;
/// <summary>
///
/// </summary>
public const int ConditionalAccessTablePacketId = 1;
/// <summary>
///
/// </summary>
public const int TransportStreamDescriptionTablePacketId = 2;
/// <summary>
/// Set by demodulator if can't correct errors in the stream, to tell the demultiplexer that the packet has an uncorrectable error
/// </summary>
public bool TransportErrorIndicator { get; set; }
/// <summary>
/// Start of PES data or PSI
/// </summary>
public bool PayloadUnitStartIndicator { get; set; }
/// <summary>
/// Higher priority than other packets with the same PID
/// </summary>
public bool TransportPriority { get; set; }
public int PacketId { get; set; }
/// <summary>
/// 1 = Reserved for future use, 10 = Scrambled with even key, 11 = Scrambled with odd key
/// </summary>
public int ScramblingControl { get; set; }
/// <summary>
/// 1 = no adaptation fields (payload only), 10 = adaptation field only, 11 = adaptation field and payload
/// </summary>
public int AdaptationFieldControl { get; set; }
/// <summary>
/// Incremented only when a payload is present (AdaptationFieldExist = 10 or 11). Starts at 0.
/// </summary>
public int ContinuityCounter { get; set; }
public int AdaptionFieldLength { get; set; }
public AdaptationField AdaptationField { get; private set; }
public bool IsNullPacket { get { return PacketId == NullPacketId; } }
public bool IsProgramAssociationTable { get { return PacketId == ProgramAssociationTablePacketId; } }
public byte[] Payload { get; private set; }
public bool IsPrivateStream1
{
get
{
if (Payload == null || Payload.Length < 4)
return false;
return Payload[0] == 0 &&
Payload[1] == 0 &&
Payload[2] == 1 &&
Payload[3] == 0xbd; // 0xbd == 189 - MPEG-2 Private stream 1 (non MPEG audio, subpictures)
}
}
public ProgramAssociationTable ProgramAssociationTable { get; private set; }
public Packet(byte[] packetBuffer)
{
TransportErrorIndicator = 1 == packetBuffer[1] >> 7; // Set by demodulator if can't correct errors in the stream, to tell the demultiplexer that the packet has an uncorrectable error
PayloadUnitStartIndicator = 1 == ((packetBuffer[1] & 64) >> 6); // and with 01000000 to get second byte - 1 means start of PES data or PSI otherwise zero
TransportPriority = 1 == ((packetBuffer[1] & 32) >> 5); // and with 00100000 to get third byte - 1 means higher priority than other packets with the same PID
PacketId = (packetBuffer[1] & 31) * 256 + packetBuffer[2];// and with 00011111 to get last 5 bytes
ScramblingControl = packetBuffer[3] >> 6; // '00' = Not scrambled. The following per DVB spec:[12] '01' = Reserved for future use, '10' = Scrambled with even key, '11' = Scrambled with odd key
AdaptationFieldControl = (packetBuffer[3] & 48) >> 4; // and with 00110000, 01 = no adaptation fields (payload only), 10 = adaptation field only, 11 = adaptation field and payload
ContinuityCounter = packetBuffer[3] & 15;
AdaptionFieldLength = AdaptationFieldControl > 1 ? (0xFF & packetBuffer[4]) + 1 : 0;
if (AdaptationFieldControl == Helper.B00000010 || AdaptationFieldControl == Helper.B00000011)
AdaptationField = new AdaptationField(packetBuffer);
if (AdaptationFieldControl == Helper.B00000001 || AdaptationFieldControl == Helper.B00000011) // Payload exists - binary '01' || '11'
{
int payloadStart = 4;
if (AdaptationField != null)
payloadStart += (1 + AdaptationField.Length);
if (PacketId == ProgramAssociationTablePacketId) // PAT = Program Association Table: lists all programs available in the transport stream.
{
ProgramAssociationTable = new ProgramAssociationTable(packetBuffer, payloadStart+1); // TODO: what index?
}
//if (PayloadUnitStartIndicator)
// payloadStart += packetBuffer[payloadStart];
// Save payload
Payload = new byte[packetBuffer.Length - payloadStart];
Buffer.BlockCopy(packetBuffer, payloadStart, Payload, 0, Payload.Length);
}
}
}
}

View File

@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Nikse.SubtitleEdit.Logic.TransportStream
{
/// <summary>
/// http://www.mpucoder.com/DVD/pes-hdr.html
/// </summary>
public class PacketizedElementaryStream
{
public const int HeaderLength = 6;
public const int Mpeg2HeaderLength = 14;
public readonly UInt32 StartCode;
public readonly int StreamId;
public readonly int Length;
public readonly int ScramblingControl;
public readonly int Priority;
public readonly int DataAlignmentIndicator;
public readonly int Copyright;
public readonly int OriginalOrCopy;
public readonly int PresentationTimeStampDecodeTimeStampFlags;
public readonly int ElementaryStreamClockReferenceFlag;
public readonly int EsRateFlag;
public readonly int DsmTrickModeFlag;
public readonly int AdditionalCopyInfoFlag;
public readonly int CrcFlag;
public readonly int ExtensionFlag;
public readonly int HeaderDataLength;
public readonly UInt64? PresentationTimeStamp;
public readonly UInt64? DecodeTimeStamp;
public readonly int? SubPictureStreamId;
public readonly byte[] DataBuffer;
public PacketizedElementaryStream(byte[] buffer, int index)
{
StartCode = Helper.GetEndian(buffer, index + 0, 3);
StreamId = buffer[index + 3];
Length = Helper.GetEndianWord(buffer, index + 4);
ScramblingControl = (buffer[index + 6] >> 4) & Helper.B00000011;
Priority = buffer[index + 6] & Helper.B00001000;
DataAlignmentIndicator = buffer[index + 6] & Helper.B00000100;
Copyright = buffer[index + 6] & Helper.B00000010;
OriginalOrCopy = buffer[index + 6] & Helper.B00000001;
PresentationTimeStampDecodeTimeStampFlags = buffer[index + 7] >> 6;
ElementaryStreamClockReferenceFlag = buffer[index + 7] & Helper.B00100000;
EsRateFlag = buffer[index + 7] & Helper.B00010000;
DsmTrickModeFlag = buffer[index + 7] & Helper.B00001000;
AdditionalCopyInfoFlag = buffer[index + 7] & Helper.B00000100;
CrcFlag = buffer[index + 7] & Helper.B00001000;
ExtensionFlag = buffer[index + 7] & Helper.B00000010;
HeaderDataLength = buffer[index + 8];
if (StreamId == 0xBD) // 10111101 binary = 189 decimal = 0xBD hex -> private_stream_1
{
int id = buffer[index + 9 + HeaderDataLength];
if (id >= 0x20 && id <= 0x40) // x3f 0r x40 ?
SubPictureStreamId = id;
}
int tempIndex = index + 9;
if (PresentationTimeStampDecodeTimeStampFlags == Helper.B00000010 ||
PresentationTimeStampDecodeTimeStampFlags == Helper.B00000011)
{
string bString = Helper.GetBinaryString(buffer, tempIndex, 5);
bString = bString.Substring(4, 3) + bString.Substring(8, 15) + bString.Substring(24, 15);
PresentationTimeStamp = Convert.ToUInt64(bString, 2);
tempIndex += 5;
}
if (PresentationTimeStampDecodeTimeStampFlags == Helper.B00000011)
{
string bString = Helper.GetBinaryString(buffer, tempIndex, 5);
bString = bString.Substring(4, 3) + bString.Substring(8, 15) + bString.Substring(24, 15);
DecodeTimeStamp = Convert.ToUInt64(bString, 2);
}
int dataIndex = index + HeaderDataLength + 24 - Mpeg2HeaderLength;
int dataSize = Length - (4 + HeaderDataLength);
if (dataSize < 0 || (dataSize + dataIndex > buffer.Length)) // to fix bad subs...
{
dataSize = buffer.Length - dataIndex;
if (dataSize < 0)
return;
}
DataBuffer = new byte[dataSize+1];
//Buffer.BlockCopy(buffer, dataIndex, DataBuffer, 0, dataSize);
Buffer.BlockCopy(buffer, dataIndex - 1, DataBuffer, 0, DataBuffer.Length); // why subtract one from dataIndex ?????
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Nikse.SubtitleEdit.Logic.TransportStream
{
public class ProgramAssociationTable
{
public int TableId { get; set; }
public int SectionLength { get; set; }
public int TransportStreamId { get; set; }
public int VersionNumber { get; set; }
public int CurrentNextIndicator { get; set; }
public int SectionNumber { get; set; }
public int LastSectionNumber { get; set; }
public List<int> ProgramNumbers { get; set; }
public List<int> ProgramIds { get; set; }
public ProgramAssociationTable(byte[] packetBuffer, int index)
{
TableId = packetBuffer[index];
SectionLength = (packetBuffer[index + 1] & Helper.B00000011) * 256 + packetBuffer[index + 2];
TransportStreamId = packetBuffer[index + 3] * 256 + packetBuffer[index + 4];
VersionNumber = (packetBuffer[index + 5] & Helper.B00111110) >> 1;
CurrentNextIndicator = packetBuffer[index + 5] & 1;
SectionNumber = packetBuffer[index + 6];
LastSectionNumber = packetBuffer[index + 7];
ProgramNumbers = new List<int>();
ProgramIds = new List<int>();
index = index + 8;
for (int i = 0; i < (SectionLength - 5) / 8; i++)
{
int programNumber = packetBuffer[index] * 256 + packetBuffer[index + 1];
int programId = (packetBuffer[index + 2] & Helper.B00011111) * 256 + packetBuffer[index + 3];
ProgramNumbers.Add(programNumber);
ProgramIds.Add(programId);
index += 8;
}
}
}
}

View File

@ -0,0 +1,168 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
namespace Nikse.SubtitleEdit.Logic.TransportStream
{
/// <summary>
/// MPEG transport stream parser
/// </summary>
public class TransportStreamParser
{
public int NumberOfNullPackets { get; private set; }
public long TotalNumberOfPackets { get; private set; }
public long TotalNumberOfPrivateStream1 { get; private set; }
public long TotalNumberOfPrivateStream1Continuation0 { get; private set; }
public List<int> SubtitlePacketIds { get; private set; }
public List<Packet> SubtitlePackets { get; private set; }
public void ParseTsFile(string fileName)
{
var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
ParseTsFile(fs);
fs.Close();
}
/// <summary>
/// Can be used with e.g. MemoryStream or FileStream
/// </summary>
/// <param name="ms">Input stream</param>
public void ParseTsFile(Stream ms)
{
NumberOfNullPackets = 0;
TotalNumberOfPackets = 0;
TotalNumberOfPrivateStream1 = 0;
TotalNumberOfPrivateStream1Continuation0 = 0;
SubtitlePacketIds = new List<int>();
SubtitlePackets = new List<Packet>();
ms.Position = 0;
int packetLength = DeterminePacketLength(ms);
var packetBuffer = new byte[packetLength];
long position = 0;
while (position < ms.Length)
{
ms.Seek(position, SeekOrigin.Begin);
ms.Read(packetBuffer, 0, packetLength);
byte syncByte = packetBuffer[0];
if (syncByte == Packet.SynchronizationByte)
{
Packet packet = new Packet(packetBuffer);
if (packet.IsNullPacket)
{
NumberOfNullPackets++;
}
else if (packet.IsProgramAssociationTable)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("PacketNo: " + TotalNumberOfPackets + 1);
sb.AppendLine("PacketId: " + packet.PacketId);
sb.AppendLine();
sb.AppendLine("TransportErrorIndicator: " + packet.TransportErrorIndicator);
sb.AppendLine("PayloadUnitStartIndicator: " + packet.PayloadUnitStartIndicator);
sb.AppendLine("TransportPriority: " + packet.TransportPriority);
sb.AppendLine("ScramblingControl: " + packet.ScramblingControl);
sb.AppendLine("AdaptationFieldExist: " + packet.AdaptationFieldControl);
sb.AppendLine("ContinuityCounter: " + packet.ContinuityCounter);
sb.AppendLine();
if (packet.AdaptationField != null)
{
sb.AppendLine("AdaptationFieldLength: " + packet.AdaptationField.Length);
sb.AppendLine("DiscontinuityIndicator: " + packet.AdaptationField.DiscontinuityIndicator);
sb.AppendLine("RandomAccessIndicator: " + packet.AdaptationField.RandomAccessIndicator);
sb.AppendLine("ElementaryStreamPriorityIndicator: " + packet.AdaptationField.ElementaryStreamPriorityIndicator);
sb.AppendLine("PcrFlag: " + packet.AdaptationField.PcrFlag);
sb.AppendLine("OpcrFlag: " + packet.AdaptationField.OpcrFlag);
sb.AppendLine("SplicingPointFlag: " + packet.AdaptationField.SplicingPointFlag);
sb.AppendLine("TransportPrivateDataFlag: " + packet.AdaptationField.TransportPrivateDataFlag);
sb.AppendLine("AdaptationFieldExtensionFlag: " + packet.AdaptationField.AdaptationFieldExtensionFlag);
sb.AppendLine();
}
sb.AppendLine("TableId: " + packet.ProgramAssociationTable.TableId);
sb.AppendLine("SectionLength: " + packet.ProgramAssociationTable.SectionLength);
sb.AppendLine("TransportStreamId: " + packet.ProgramAssociationTable.TransportStreamId);
sb.AppendLine("VersionNumber: " + packet.ProgramAssociationTable.VersionNumber);
sb.AppendLine("CurrentNextIndicator: " + packet.ProgramAssociationTable.CurrentNextIndicator);
sb.AppendLine("SectionNumber: " + packet.ProgramAssociationTable.SectionNumber);
sb.AppendLine("LastSectionNumber: " + packet.ProgramAssociationTable.LastSectionNumber);
// MessageBox.Show(sb.ToString());
}
else if (packet.IsPrivateStream1 || SubtitlePacketIds.Contains(packet.PacketId))
{
TotalNumberOfPrivateStream1++;
SubtitlePackets.Add(packet);
if (!SubtitlePacketIds.Contains(packet.PacketId))
{
SubtitlePacketIds.Add(packet.PacketId);
// MessageBox.Show("Subtitle packet id=" + packet.PacketId);
}
if (packet.ContinuityCounter == 0)
{
TotalNumberOfPrivateStream1Continuation0++;
int pes_extensionlength = 0xFF & packetBuffer[12 + packet.AdaptionFieldLength];
int pes_offset = 13 + packet.AdaptionFieldLength + pes_extensionlength;
bool isTeletext = (pes_extensionlength == 0x24 && (0xFF & packetBuffer[pes_offset])>>4 == 1);
// workaround uk freesat teletext
if (!isTeletext)
isTeletext = (pes_extensionlength == 0x24 && (0xFF & packetBuffer[pes_offset]) == 0x99);
//if (isTeletext)
// MessageBox.Show(TotalNumberOfPackets.ToString() + ": Teletext!");
//if (!isTeletext)
// pes_subID = ((0xFF & ts_packet[pes_offset]) == 0x20 && (0xFF & ts_packet[pes_offset + 1]) == 0 && (0xFF & ts_packet[pes_offset + 2]) == 0xF) ? 0x20 : 0;
}
}
TotalNumberOfPackets++;
position += packetLength;
}
else
{
position++;
break;
}
}
//MessageBox.Show("Done parsing " + Environment.NewLine +
// Environment.NewLine +
// "#Packets: " + TotalNumberOfPackets.ToString() + Environment.NewLine +
// "#Null packets: " + NumberOfNullPackets.ToString() + Environment.NewLine +
// "#Private stream 1's: " + TotalNumberOfPrivateStream1.ToString() + Environment.NewLine +
// "#Private stream 1's with continuation=0: " + TotalNumberOfPrivateStream1Continuation0.ToString());
}
public List<PacketizedElementaryStream> GetSubtitlePesPackets(int packetId)
{
var list = new List<PacketizedElementaryStream>();
var buffer = new byte[20000];
int index =0;
foreach (Packet packet in SubtitlePackets)
{
if (packet.ContinuityCounter == 0)
{
if (index > 0)
{
var pes = new PacketizedElementaryStream(buffer, 0);
list.Add(pes);
}
index = 0;
}
Buffer.BlockCopy(packet.Payload, 0, buffer, index, packet.Payload.Length);
index += packet.Payload.Length;
}
return list;
}
private int DeterminePacketLength(Stream ms)
{
return 188;
}
}
}