Merge pull request #7105 from Flitskikker/feature/beautify-timecodes-2023

Add "Beautify time codes" feature
This commit is contained in:
Nikolaj Olsson 2023-07-16 12:08:00 -04:00 committed by GitHub
commit ff3f40ba48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 6854 additions and 354 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

View File

@ -99,6 +99,7 @@
<ShortcutX>Shortcut: {0}</ShortcutX>
<ExampleX>Example: {0}</ExampleX>
<Reset>Reset</Reset>
<Error>Error</Error>
<Warning>Warning</Warning>
<UseLargerFontForThisWindow>Use larger font for this window</UseLargerFontForThisWindow>
</General>
@ -171,9 +172,12 @@ Note: Do check free disk space.</WaveFileMalformed>
<Fixed>Fixed</Fixed>
<Milliseconds>Milliseconds</Milliseconds>
<ExtendOnly>Extend only</ExtendOnly>
<EnforceDurationLimits>Enforce minimum and maximum duration</EnforceDurationLimits>
<CheckShotChanges>Don't extend past shot changes</CheckShotChanges>
</AdjustDisplayDuration>
<ApplyDurationLimits>
<Title>Apply duration limits</Title>
<CheckShotChanges>Don't extend past shot changes</CheckShotChanges>
<FixesAvailable>Fixes available: {0}</FixesAvailable>
<UnableToFix>Unable to fix: {0}</UnableToFix>
</ApplyDurationLimits>
@ -362,6 +366,94 @@ Read more info (web)?</WhisperNotFound>
<MkvLanguageStyleEmpty>No language code</MkvLanguageStyleEmpty>
<SearchFolderScanVideo>Also scan video files in "Search folder" (slow)</SearchFolderScanVideo>
</BatchConvert>
<BeautifyTimeCodes>
<Title>Beautify time codes</Title>
<GroupTimeCodes>Time codes</GroupTimeCodes>
<AlignTimeCodes>Align time codes to frame time codes</AlignTimeCodes>
<ExtractExactTimeCodes>Use ffprobe to extract exact frame time codes</ExtractExactTimeCodes>
<ExtractTimeCodes>Extract time codes</ExtractTimeCodes>
<CancelTimeCodes>Cancel</CancelTimeCodes>
<GroupShotChanges>Shot changes</GroupShotChanges>
<SnapToShotChanges>Snap cues to shot changes</SnapToShotChanges>
<ImportShotChanges>Generate / import shot changes...</ImportShotChanges>
<EditProfile>Edit profile...</EditProfile>
<NoTimeCodesLoaded>No time codes loaded</NoTimeCodesLoaded>
<XTimeCodesLoaded>{0} time codes loaded</XTimeCodesLoaded>
<NoTimeCodesLoadedError>You've selected to extract exact frame time codes, but there are no time codes loaded.
Please click "{0}" to extract the time codes first, or disable this option.</NoTimeCodesLoadedError>
<NoShotChangesLoaded>No shot changes loaded</NoShotChangesLoaded>
<XShotChangesLoaded>{0} shot changes loaded</XShotChangesLoaded>
<NoShotChangesLoadedError>You've selected to snap cues to shot changes, but there are no shot changes loaded.
Please click "{0}" to generate or import shot changes first, or disable this option.</NoShotChangesLoadedError>
</BeautifyTimeCodes>
<BeautifyTimeCodesProfile>
<Title>Edit profile</Title>
<LoadPreset>Load preset...</LoadPreset>
<PresetDefault>Default</PresetDefault>
<PresetNetflix>Netflix</PresetNetflix>
<PresetSDI>SDI</PresetSDI>
<CreateSimple>Simple mode...</CreateSimple>
<General>General</General>
<Gap>Gap:</Gap>
<GapSuffix>frames (will overwrite custom settings)</GapSuffix>
<InCues>In cues</InCues>
<SubtitlePreviewText>Subtitle text.</SubtitlePreviewText>
<Zones>Zones:</Zones>
<OutCues>Out cues</OutCues>
<ConnectedSubtitles>Connected subtitles</ConnectedSubtitles>
<InCueClosest>In cue is closest</InCueClosest>
<OutCueClosest>Out cue is closest</OutCueClosest>
<TreadAsConnected>Treat as connected if gap is smaller than:</TreadAsConnected>
<Milliseconds>ms</Milliseconds>
<Chaining>Chaining</Chaining>
<InCueOnShot>In cue on shot change</InCueOnShot>
<OutCueOnShot>Out cue on shot change</OutCueOnShot>
<MaxGap>Max. gap:</MaxGap>
<ShotChangeBehavior>If there is a shot change in between:</ShotChangeBehavior>
<DontChain>Don't chain</DontChain>
<ExtendCrossingShotChange>Extend, crossing shot change</ExtendCrossingShotChange>
<ExtendUntilShotChange>Extend until shot change</ExtendUntilShotChange>
<ResetWarning>This will reset your current profile and replace all values with those of the selected preset. This cannot be undone.
Do you want to continue?</ResetWarning>
<CreateSimpleTitle>Create simple</CreateSimpleTitle>
<CreateSimpleInstruction>Enter these basic rules, and the current profile will be updated accordingly.</CreateSimpleInstruction>
<CreateSimpleGapInstruction>The minimum amount of space between subtitles.</CreateSimpleGapInstruction>
<CreateSimpleInCues>In cues should be:</CreateSimpleInCues>
<CreateSimpleInCues0Frames>On the shot change</CreateSimpleInCues0Frames>
<CreateSimpleInCues1Frames>1 frame after the shot change</CreateSimpleInCues1Frames>
<CreateSimpleInCues2Frames>2 frames after the shot change</CreateSimpleInCues2Frames>
<CreateSimpleInCues3Frames>3 frames after the shot change</CreateSimpleInCues3Frames>
<CreateSimpleOutCues>Out cues should be:</CreateSimpleOutCues>
<CreateSimpleOutCues0Frames>On the shot change</CreateSimpleOutCues0Frames>
<CreateSimpleOutCues1Frames>1 frame before the shot change</CreateSimpleOutCues1Frames>
<CreateSimpleOutCues2Frames>2 frames before the shot change</CreateSimpleOutCues2Frames>
<CreateSimpleOutCues3Frames>3 frames before the shot change</CreateSimpleOutCues3Frames>
<CreateSimpleOutCuesGap>Minimum gap before the shot change</CreateSimpleOutCuesGap>
<CreateSimpleSnapClosestCue>For connected subtitles, snap the in or out cue to a shot change based on which one is closer</CreateSimpleSnapClosestCue>
<CreateSimpleMaxOffset>Max. offset:</CreateSimpleMaxOffset>
<CreateSimpleMaxOffsetInstruction>Cues within this distance from shot changes will be snapped to the shot change.</CreateSimpleMaxOffsetInstruction>
<CreateSimpleSafeZone>Safe zone:</CreateSimpleSafeZone>
<CreateSimpleSafeZoneInstruction>Cues within this distance from shot changes will be moved away from the shot change.</CreateSimpleSafeZoneInstruction>
<CreateSimpleChainingGap>Max. chaining gap:</CreateSimpleChainingGap>
<CreateSimpleChainingGapInstruction>If the space between two subtitles is smaller than this amount, the subtitles will be connected.</CreateSimpleChainingGapInstruction>
<CreateSimpleChainingGapAfterShotChanges>After an out cue on a shot change, the gap may be smaller</CreateSimpleChainingGapAfterShotChanges>
<CreateSimpleChainingToolTip>Chaining subtitles is recommended to ensure a consistent "rhythm" in the "flashing" of the subtitles.
This offers a more relaxed viewing experience.
After chaining, subtitles are either connected (i.e. a subtitle disappears and a new subtitle appears immediately after a slight pause) or not.
This gives the viewer some sense on when they can shift their focus back to the screen.
The length of the chaining gap can be a bit smaller right after a subtitle disappears on a shot change, because the changing shot "resets" the image in a way.
We leverage the intrinsic rhythm of the image.</CreateSimpleChainingToolTip>
<CreateSimpleLoadNetflixRules>Load Netflix rules</CreateSimpleLoadNetflixRules>
<Frames>frames</Frames>
<Maximum>Max.</Maximum>
<GapInMsFormat>{0} ms @ {1} FPS</GapInMsFormat>
<OffsetSafeZoneError>The safe zone should be larger than the max. offset.</OffsetSafeZoneError>
</BeautifyTimeCodesProfile>
<BinEdit>
<ImportImage>Import image...</ImportImage>
<ExportImage>Export image...</ExportImage>
@ -1274,6 +1366,7 @@ To use an API key, go to "Options -&gt; Settings -&gt; Tools" to enter your Goog
<Duration>Duration</Duration>
<ListErrors>List errors...</ListErrors>
<NetflixQualityCheck>Netflix quality check...</NetflixQualityCheck>
<BeautifyTimeCodes>Beautify time codes...</BeautifyTimeCodes>
<TextAlphabetically>Text - alphabetically</TextAlphabetically>
<TextSingleLineMaximumLength>Text - single line max. length</TextSingleLineMaximumLength>
<TextTotalLength>Text - total length</TextTotalLength>
@ -1369,6 +1462,7 @@ To use an API key, go to "Options -&gt; Settings -&gt; Tools" to enter your Goog
<VisualSync>Visual sync</VisualSync>
<SpellCheck>Spell check</SpellCheck>
<NetflixQualityCheck>Netflix quality check</NetflixQualityCheck>
<BeautifyTimeCodes>Beautify time codes</BeautifyTimeCodes>
<Settings>Settings</Settings>
<Help>Help</Help>
<ShowHideWaveform>Show/hide waveform</ShowHideWaveform>
@ -1600,6 +1694,8 @@ Would you like to start from the top of the document and continue search and rep
<CommonErrorsFixed>Common errors fixed</CommonErrorsFixed>
<BeforeRenumbering>Before renumbering</BeforeRenumbering>
<RenumberedStartingFromX>Renumbered starting from: {0}</RenumberedStartingFromX>
<BeforeBeautifyTimeCodes>Before beautifying time codes</BeforeBeautifyTimeCodes>
<BeautifiedTimeCodes>Time codes beautified</BeautifiedTimeCodes>
<BeforeRemovalOfTextingForHearingImpaired>Before removal of texting for hearing impaired</BeforeRemovalOfTextingForHearingImpaired>
<TextingForHearingImpairedRemovedOneLine>Texting for hearing impaired removed: One line</TextingForHearingImpairedRemovedOneLine>
<TextingForHearingImpairedRemovedXLines>Texting for hearing impaired removed: {0} lines</TextingForHearingImpairedRemovedXLines>
@ -2173,6 +2269,7 @@ can edit in same subtitle file (collaboration)</Information>
<BurnIn>Burn in</BurnIn>
<SpellCheck>Spell check</SpellCheck>
<NetflixQualityCheck>Netflix quality check</NetflixQualityCheck>
<BeautifyTimeCodes>Beautify time codes</BeautifyTimeCodes>
<SettingsName>Settings</SettingsName>
<ToggleBookmarks>Toggle bookmarks</ToggleBookmarks>
<ToggleBookmarksWithComment>Toggle bookmarks - add comment</ToggleBookmarksWithComment>
@ -2293,6 +2390,7 @@ can edit in same subtitle file (collaboration)</Information>
<WaveformListViewFocusMouseEnter>Also set list view focus on mouse enter in list view</WaveformListViewFocusMouseEnter>
<WaveformSingleClickSelect>Single click to select subtitles</WaveformSingleClickSelect>
<WaveformSnapToShotChanges>Snap to shot changes (hold Shift to override)</WaveformSnapToShotChanges>
<WaveformEditShotChangesProfile>Edit profile...</WaveformEditShotChangesProfile>
<WaveformAutoGen>Auto generate waveform when opening video</WaveformAutoGen>
<WaveformBorderHitMs1>Border marker hit must be within</WaveformBorderHitMs1>
<WaveformBorderHitMs2>milliseconds</WaveformBorderHitMs2>
@ -2448,15 +2546,13 @@ can edit in same subtitle file (collaboration)</Information>
<AdjustSetEndAndOffsetTheRest>Set end, offset the rest</AdjustSetEndAndOffsetTheRest>
<AdjustSetEndAndOffsetTheRestAndGoToNext>Set end, offset the rest and go to next</AdjustSetEndAndOffsetTheRestAndGoToNext>
<AdjustSnapStartToNextShotChange>Snap selected lines start to next shot change</AdjustSnapStartToNextShotChange>
<AdjustSnapStartToNextShotChangeWithGap>Snap selected lines start to next shot change with min. gap</AdjustSnapStartToNextShotChangeWithGap>
<AdjustSnapEndToPreviousShotChange>Snap selected lines end to previous shot change</AdjustSnapEndToPreviousShotChange>
<AdjustSnapEndToPreviousShotChangeWithGap>Snap selected lines end to previous shot change with min. gap</AdjustSnapEndToPreviousShotChangeWithGap>
<AdjustExtendToNextShotChange>Extend selected lines to next shot change (or next subtitle)</AdjustExtendToNextShotChange>
<AdjustExtendToNextShotChangeWithGap>Extend selected lines to next shot change with min. gap (or next subtitle)</AdjustExtendToNextShotChangeWithGap>
<AdjustExtendToPreviousShotChange>Extend selected lines to previous shot change (or previous subtitle)</AdjustExtendToPreviousShotChange>
<AdjustExtendToPreviousShotChangeWithGap>Extend selected lines to previous shot change with min. gap (or previous subtitle)</AdjustExtendToPreviousShotChangeWithGap>
<AdjustExtendToNextSubtitle>Extend selected lines to next subtitle</AdjustExtendToNextSubtitle>
<AdjustExtendToPreviousSubtitle>Extend selected lines to previous subtitle</AdjustExtendToPreviousSubtitle>
<AdjustExtendToNextSubtitleMinusChainingGap>Extend selected lines to next subtitle with chaining gap</AdjustExtendToNextSubtitleMinusChainingGap>
<AdjustExtendToPreviousSubtitleMinusChainingGap>Extend selected lines to previous subtitle with chaining gap</AdjustExtendToPreviousSubtitleMinusChainingGap>
<AdjustExtendCurrentSubtitle>Extend current line to next subtitle or max duration</AdjustExtendCurrentSubtitle>
<AdjustExtendPreviousLineEndToCurrentStart>Extend previous line's end to current's start</AdjustExtendPreviousLineEndToCurrentStart>
<AdjustExtendNextLineStartToCurrentEnd>Extend next line's start to current's end</AdjustExtendNextLineStartToCurrentEnd>

View File

@ -0,0 +1,146 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Nikse.SubtitleEdit.Core.Common;
using System.Collections.Generic;
namespace Test.Logic
{
[TestClass]
public class BeautifyTimeCodesTest
{
[TestMethod]
public void TestIsInCueOnShotChange1()
{
Configuration.Settings.General.CurrentFrameRate = 25;
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap = 1;
var shotChangesSeconds = new List<double>() { 1, 10, 20 };
var paragraph = new Paragraph("Test.", 1000, 3000);
var result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 1040, 3000); // 1 frame after
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 1080, 3000); // 2 frames after
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(false, result);
paragraph = new Paragraph("Test.", 960, 3000); // 1 frame before
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(false, result);
paragraph = new Paragraph("Test.", 920, 3000); // 2 frames before
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(false, result);
}
[TestMethod]
public void TestIsInCueOnShotChange2()
{
Configuration.Settings.General.CurrentFrameRate = 25;
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap = 0;
var shotChangesSeconds = new List<double>() { 1, 10, 20 };
var paragraph = new Paragraph("Test.", 1000, 3000);
var result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 1001, 3000);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 1010, 3000);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 1025, 3000);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(false, result);
paragraph = new Paragraph("Test.", 999, 3000);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 990, 3000);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 975, 3000);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.StartTime, true);
Assert.AreEqual(false, result);
}
[TestMethod]
public void TestIsOutCueOnShotChange1()
{
Configuration.Settings.General.CurrentFrameRate = 25;
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap = 2;
var shotChangesSeconds = new List<double>() { 1, 10, 20 };
var paragraph = new Paragraph("Test.", 8000, 10000);
var result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 8000, 9960); // 1 frame before
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 8000, 9920); // 2 frames before
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 8000, 9880); // 3 frames before
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(false, result);
paragraph = new Paragraph("Test.", 8000, 10040); // 1 frame after
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(false, result);
}
[TestMethod]
public void TestIsOutCueOnShotChange2()
{
Configuration.Settings.General.CurrentFrameRate = 25;
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap = 2;
var shotChangesSeconds = new List<double>() { 1, 10, 20 };
var paragraph = new Paragraph("Test.", 8000, 10000);
var result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 8000, 10001);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 8000, 10010);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 8000, 10030);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(false, result);
paragraph = new Paragraph("Test.", 8000, 9999);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 8000, 9950);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 8000, 9915);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(true, result);
paragraph = new Paragraph("Test.", 8000, 9890);
result = ShotChangeHelper.IsCueOnShotChange(shotChangesSeconds, paragraph.EndTime, false);
Assert.AreEqual(false, result);
}
}
}

View File

@ -69,6 +69,7 @@
<Compile Include="Dictionaries\StringWithoutSpaceSplitToWordsTest.cs" />
<Compile Include="GoogleCloudVision\GoogleCloudVisionJsonToLinesTest.cs" />
<Compile Include="LanguageFiles\LanguageFileTest.cs" />
<Compile Include="Logic\BeautifyTimeCodesTest.cs" />
<Compile Include="Logic\ConvertColorsToDialogTest.cs" />
<Compile Include="Core\LanguageAutoDetectLanguagesTest.cs" />
<Compile Include="Logic\NetflixHelperTest.cs" />

View File

@ -22,6 +22,7 @@ namespace Nikse.SubtitleEdit.Core.Common
public static readonly string DictionariesDirectory = DataDirectory + "Dictionaries" + Path.DirectorySeparatorChar;
public static readonly string SpectrogramsDirectory = DataDirectory + "Spectrograms" + Path.DirectorySeparatorChar;
public static readonly string ShotChangesDirectory = DataDirectory + "ShotChanges" + Path.DirectorySeparatorChar;
public static readonly string TimeCodesDirectory = DataDirectory + "TimeCodes" + Path.DirectorySeparatorChar;
public static readonly string AutoBackupDirectory = DataDirectory + "AutoBackup" + Path.DirectorySeparatorChar;
public static readonly string VobSubCompareDirectory = DataDirectory + "VobSub" + Path.DirectorySeparatorChar;
public static readonly string TesseractDirectory = DataDirectory + "Tesseract531" + Path.DirectorySeparatorChar;

View File

@ -342,6 +342,8 @@ namespace Nikse.SubtitleEdit.Core.Common
public int AdjustDurationPercent { get; set; }
public string AdjustDurationLast { get; set; }
public bool AdjustDurationExtendOnly { get; set; }
public bool AdjustDurationExtendEnforceDurationLimits { get; set; }
public bool AdjustDurationExtendCheckShotChanges { get; set; }
public bool ChangeSpeedAllowOverlap { get; set; }
public bool AutoBreakCommaBreakEarly { get; set; }
public bool AutoBreakDashEarly { get; set; }
@ -350,6 +352,7 @@ namespace Nikse.SubtitleEdit.Core.Common
public bool AutoBreakPreferBottomHeavy { get; set; }
public double AutoBreakPreferBottomPercent { get; set; }
public bool ApplyMinimumDurationLimit { get; set; }
public bool ApplyMinimumDurationLimitCheckShotChanges { get; set; }
public bool ApplyMaximumDurationLimit { get; set; }
public int MergeShortLinesMaxGap { get; set; }
public int MergeShortLinesMaxChars { get; set; }
@ -580,6 +583,8 @@ namespace Nikse.SubtitleEdit.Core.Common
AdjustDurationSeconds = 0.1m;
AdjustDurationPercent = 120;
AdjustDurationExtendOnly = true;
AdjustDurationExtendEnforceDurationLimits = true;
AdjustDurationExtendCheckShotChanges = true;
AutoBreakCommaBreakEarly = false;
AutoBreakDashEarly = true;
AutoBreakLineEndingEarly = false;
@ -587,6 +592,7 @@ namespace Nikse.SubtitleEdit.Core.Common
AutoBreakPreferBottomHeavy = true;
AutoBreakPreferBottomPercent = 5;
ApplyMinimumDurationLimit = true;
ApplyMinimumDurationLimitCheckShotChanges = true;
ApplyMaximumDurationLimit = true;
MergeShortLinesMaxGap = 250;
MergeShortLinesMaxChars = 55;
@ -1269,6 +1275,7 @@ $HorzAlign = Center
public bool ShowToolbarBurnIn { get; set; }
public bool ShowToolbarSpellCheck { get; set; }
public bool ShowToolbarNetflixGlyphCheck { get; set; }
public bool ShowToolbarBeautifyTimeCodes { get; set; }
public bool ShowToolbarSettings { get; set; }
public bool ShowToolbarHelp { get; set; }
@ -1493,6 +1500,7 @@ $HorzAlign = Center
ShowToolbarVisualSync = true;
ShowToolbarSpellCheck = true;
ShowToolbarNetflixGlyphCheck = true;
ShowToolbarBeautifyTimeCodes = true;
ShowToolbarSettings = false;
ShowToolbarHelp = true;
ShowToolbarToggleSourceView = true;
@ -2536,15 +2544,13 @@ $HorzAlign = Center
public string MoveEndOneFrameBackKeepGapNext { get; set; }
public string MoveEndOneFrameForwardKeepGapNext { get; set; }
public string MainAdjustSnapStartToNextShotChange { get; set; }
public string MainAdjustSnapStartToNextShotChangeWithGap { get; set; }
public string MainAdjustSnapEndToPreviousShotChange { get; set; }
public string MainAdjustSnapEndToPreviousShotChangeWithGap { get; set; }
public string MainAdjustExtendToNextShotChange { get; set; }
public string MainAdjustExtendToNextShotChangeWithGap { get; set; }
public string MainAdjustExtendToPreviousShotChange { get; set; }
public string MainAdjustExtendToPreviousShotChangeWithGap { get; set; }
public string MainAdjustExtendToNextSubtitle { get; set; }
public string MainAdjustExtendToPreviousSubtitle { get; set; }
public string MainAdjustExtendToNextSubtitleMinusChainingGap { get; set; }
public string MainAdjustExtendToPreviousSubtitleMinusChainingGap { get; set; }
public string MainAdjustExtendCurrentSubtitle { get; set; }
public string MainAdjustExtendPreviousLineEndToCurrentStart { get; set; }
public string MainAdjustExtendNextLineStartToCurrentEnd { get; set; }
@ -2675,6 +2681,8 @@ $HorzAlign = Center
MainTranslateAuto = "Control+Shift+G";
MainAdjustExtendToNextSubtitle = "Control+Shift+E";
MainAdjustExtendToPreviousSubtitle = "Alt+Shift+E";
MainAdjustExtendToNextSubtitleMinusChainingGap = "Control+Shift+W";
MainAdjustExtendToPreviousSubtitleMinusChainingGap = "Alt+Shift+W";
WaveformVerticalZoom = "Shift+Add";
WaveformVerticalZoomOut = "Shift+Subtract";
WaveformAddTextHere = "Return";
@ -2786,6 +2794,206 @@ $HorzAlign = Center
}
}
public class BeautifyTimeCodesSettings
{
public bool AlignTimeCodes { get; set; }
public bool ExtractExactTimeCodes { get; set; }
public bool SnapToShotChanges { get; set; }
public BeautifyTimeCodesProfile Profile { get; set; }
public BeautifyTimeCodesSettings()
{
AlignTimeCodes = true;
ExtractExactTimeCodes = false;
SnapToShotChanges = true;
Profile = new BeautifyTimeCodesProfile();
}
public class BeautifyTimeCodesProfile
{
// General
public int Gap { get; set; }
// In cues
public int InCuesGap { get; set; }
public int InCuesLeftGreenZone { get; set; }
public int InCuesLeftRedZone { get; set; }
public int InCuesRightRedZone { get; set; }
public int InCuesRightGreenZone { get; set; }
// Out cues
public int OutCuesGap { get; set; }
public int OutCuesLeftGreenZone { get; set; }
public int OutCuesLeftRedZone { get; set; }
public int OutCuesRightRedZone { get; set; }
public int OutCuesRightGreenZone { get; set; }
// Connected subtitles
public int ConnectedSubtitlesInCueClosestLeftGap { get; set; }
public int ConnectedSubtitlesInCueClosestRightGap { get; set; }
public int ConnectedSubtitlesOutCueClosestLeftGap { get; set; }
public int ConnectedSubtitlesOutCueClosestRightGap { get; set; }
public int ConnectedSubtitlesLeftGreenZone { get; set; }
public int ConnectedSubtitlesLeftRedZone { get; set; }
public int ConnectedSubtitlesRightRedZone { get; set; }
public int ConnectedSubtitlesRightGreenZone { get; set; }
public int ConnectedSubtitlesTreatConnected { get; set; }
// Chaining
public bool ChainingGeneralUseZones { get; set; }
public int ChainingGeneralMaxGap { get; set; }
public int ChainingGeneralLeftGreenZone { get; set; }
public int ChainingGeneralLeftRedZone { get; set; }
public ChainingGeneralShotChangeBehaviorEnum ChainingGeneralShotChangeBehavior { get; set; }
public bool ChainingInCueOnShotUseZones { get; set; }
public int ChainingInCueOnShotMaxGap { get; set; }
public int ChainingInCueOnShotLeftGreenZone { get; set; }
public int ChainingInCueOnShotLeftRedZone { get; set; }
public bool ChainingOutCueOnShotUseZones { get; set; }
public int ChainingOutCueOnShotMaxGap { get; set; }
public int ChainingOutCueOnShotRightRedZone { get; set; }
public int ChainingOutCueOnShotRightGreenZone { get; set; }
public enum Preset : int
{
Default = 0,
Netflix = 1,
SDI = 2,
}
public enum ChainingGeneralShotChangeBehaviorEnum : int
{
DontChain = 0,
ExtendCrossingShotChange = 1,
ExtendUntilShotChange = 2
}
public BeautifyTimeCodesProfile(Preset preset = Preset.Default)
{
switch (preset)
{
case Preset.Netflix:
Gap = 2;
InCuesGap = 0;
InCuesLeftGreenZone = 12;
InCuesLeftRedZone = 7;
InCuesRightRedZone = 7;
InCuesRightGreenZone = 12;
OutCuesGap = 2;
OutCuesLeftGreenZone = 12;
OutCuesLeftRedZone = 7;
OutCuesRightRedZone = 7;
OutCuesRightGreenZone = 12;
ConnectedSubtitlesInCueClosestLeftGap = 2;
ConnectedSubtitlesInCueClosestRightGap = 0;
ConnectedSubtitlesOutCueClosestLeftGap = 2;
ConnectedSubtitlesOutCueClosestRightGap = 0;
ConnectedSubtitlesLeftGreenZone = 12;
ConnectedSubtitlesLeftRedZone = 7;
ConnectedSubtitlesRightRedZone = 7;
ConnectedSubtitlesRightGreenZone = 12;
ConnectedSubtitlesTreatConnected = 180;
ChainingGeneralUseZones = false;
ChainingGeneralMaxGap = 500;
ChainingGeneralLeftGreenZone = 12;
ChainingGeneralLeftRedZone = 11;
ChainingGeneralShotChangeBehavior = ChainingGeneralShotChangeBehaviorEnum.ExtendUntilShotChange;
ChainingInCueOnShotUseZones = false;
ChainingInCueOnShotMaxGap = 500;
ChainingInCueOnShotLeftGreenZone = 12;
ChainingInCueOnShotLeftRedZone = 11;
ChainingOutCueOnShotUseZones = false;
ChainingOutCueOnShotMaxGap = 500;
ChainingOutCueOnShotRightRedZone = 11;
ChainingOutCueOnShotRightGreenZone = 12;
break;
case Preset.SDI:
Gap = 4;
InCuesGap = 2;
InCuesLeftGreenZone = 12;
InCuesLeftRedZone = 7;
InCuesRightRedZone = 7;
InCuesRightGreenZone = 12;
OutCuesGap = 2;
OutCuesLeftGreenZone = 12;
OutCuesLeftRedZone = 7;
OutCuesRightRedZone = 7;
OutCuesRightGreenZone = 12;
ConnectedSubtitlesInCueClosestLeftGap = 2;
ConnectedSubtitlesInCueClosestRightGap = 2;
ConnectedSubtitlesOutCueClosestLeftGap = 2;
ConnectedSubtitlesOutCueClosestRightGap = 2;
ConnectedSubtitlesLeftGreenZone = 12;
ConnectedSubtitlesLeftRedZone = 7;
ConnectedSubtitlesRightRedZone = 7;
ConnectedSubtitlesRightGreenZone = 12;
ConnectedSubtitlesTreatConnected = 240;
ChainingGeneralUseZones = false;
ChainingGeneralMaxGap = 1000;
ChainingGeneralLeftGreenZone = 25;
ChainingGeneralLeftRedZone = 24;
ChainingGeneralShotChangeBehavior = ChainingGeneralShotChangeBehaviorEnum.ExtendCrossingShotChange;
ChainingInCueOnShotUseZones = false;
ChainingInCueOnShotMaxGap = 1000;
ChainingInCueOnShotLeftGreenZone = 25;
ChainingInCueOnShotLeftRedZone = 24;
ChainingOutCueOnShotUseZones = false;
ChainingOutCueOnShotMaxGap = 1000;
ChainingOutCueOnShotRightRedZone = 24;
ChainingOutCueOnShotRightGreenZone = 25;
break;
default:
Gap = 3;
InCuesGap = 0;
InCuesLeftGreenZone = 3;
InCuesLeftRedZone = 3;
InCuesRightRedZone = 5;
InCuesRightGreenZone = 5;
OutCuesGap = 0;
OutCuesLeftGreenZone = 10;
OutCuesLeftRedZone = 10;
OutCuesRightRedZone = 3;
OutCuesRightGreenZone = 12;
ConnectedSubtitlesInCueClosestLeftGap = 3;
ConnectedSubtitlesInCueClosestRightGap = 0;
ConnectedSubtitlesOutCueClosestLeftGap = 0;
ConnectedSubtitlesOutCueClosestRightGap = 3;
ConnectedSubtitlesLeftGreenZone = 3;
ConnectedSubtitlesLeftRedZone = 3;
ConnectedSubtitlesRightRedZone = 3;
ConnectedSubtitlesRightGreenZone = 3;
ConnectedSubtitlesTreatConnected = 180;
ChainingGeneralUseZones = false;
ChainingGeneralMaxGap = 1000;
ChainingGeneralLeftGreenZone = 25;
ChainingGeneralLeftRedZone = 24;
ChainingGeneralShotChangeBehavior = ChainingGeneralShotChangeBehaviorEnum.ExtendUntilShotChange;
ChainingInCueOnShotUseZones = false;
ChainingInCueOnShotMaxGap = 1000;
ChainingInCueOnShotLeftGreenZone = 25;
ChainingInCueOnShotLeftRedZone = 24;
ChainingOutCueOnShotUseZones = false;
ChainingOutCueOnShotMaxGap = 500;
ChainingOutCueOnShotRightRedZone = 11;
ChainingOutCueOnShotRightGreenZone = 12;
break;
}
}
}
}
public class CompareSettings
{
public bool ShowOnlyDifferences { get; set; }
@ -2820,6 +3028,7 @@ $HorzAlign = Center
public RemoveTextForHearingImpairedSettings RemoveTextForHearingImpaired { get; set; }
public SubtitleBeaming SubtitleBeaming { get; set; }
public List<MultipleSearchAndReplaceGroup> MultipleSearchAndReplaceGroups { get; set; }
public BeautifyTimeCodesSettings BeautifyTimeCodes { get; set; }
public void Reset()
{
@ -2839,6 +3048,7 @@ $HorzAlign = Center
RemoveTextForHearingImpaired = new RemoveTextForHearingImpairedSettings();
SubtitleBeaming = new SubtitleBeaming();
Compare = new CompareSettings();
BeautifyTimeCodes = new BeautifyTimeCodesSettings();
}
private Settings()
@ -3289,6 +3499,12 @@ $HorzAlign = Center
settings.General.ShowToolbarNetflixGlyphCheck = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = node.SelectSingleNode("ShowToolbarBeautifyTimeCodes");
if (subNode != null)
{
settings.General.ShowToolbarBeautifyTimeCodes = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = node.SelectSingleNode("ShowToolbarSettings");
if (subNode != null)
{
@ -5902,6 +6118,18 @@ $HorzAlign = Center
settings.Tools.AdjustDurationExtendOnly = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = node.SelectSingleNode("AdjustDurationExtendEnforceDurationLimits");
if (subNode != null)
{
settings.Tools.AdjustDurationExtendEnforceDurationLimits = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = node.SelectSingleNode("AdjustDurationExtendCheckShotChanges");
if (subNode != null)
{
settings.Tools.AdjustDurationExtendCheckShotChanges = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = node.SelectSingleNode("ChangeSpeedAllowOverlap");
if (subNode != null)
{
@ -5950,6 +6178,12 @@ $HorzAlign = Center
settings.Tools.ApplyMinimumDurationLimit = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = node.SelectSingleNode("ApplyMinimumDurationLimitCheckShotChanges");
if (subNode != null)
{
settings.Tools.ApplyMinimumDurationLimitCheckShotChanges = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = node.SelectSingleNode("ApplyMaximumDurationLimit");
if (subNode != null)
{
@ -8088,6 +8322,231 @@ $HorzAlign = Center
}
}
// Beautify time codes
node = doc.DocumentElement.SelectSingleNode("BeautifyTimeCodes");
if (node != null)
{
subNode = node.SelectSingleNode("AlignTimeCodes");
if (subNode != null)
{
settings.BeautifyTimeCodes.AlignTimeCodes = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = node.SelectSingleNode("ExtractExactTimeCodes");
if (subNode != null)
{
settings.BeautifyTimeCodes.ExtractExactTimeCodes = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = node.SelectSingleNode("SnapToShotChanges");
if (subNode != null)
{
settings.BeautifyTimeCodes.SnapToShotChanges = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
var profileNode = node.SelectSingleNode("Profile");
if (profileNode != null)
{
subNode = profileNode.SelectSingleNode("Gap");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.Gap = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("InCuesGap");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.InCuesGap = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("InCuesLeftGreenZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.InCuesLeftGreenZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("InCuesLeftRedZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.InCuesLeftRedZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("InCuesRightRedZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.InCuesRightRedZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("InCuesRightGreenZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.InCuesRightGreenZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("OutCuesGap");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.OutCuesGap = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("OutCuesLeftGreenZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.OutCuesLeftGreenZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("OutCuesLeftRedZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.OutCuesLeftRedZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("OutCuesRightRedZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.OutCuesRightRedZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("OutCuesRightGreenZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.OutCuesRightGreenZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ConnectedSubtitlesInCueClosestLeftGap");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestLeftGap = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ConnectedSubtitlesInCueClosestRightGap");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestRightGap = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ConnectedSubtitlesOutCueClosestLeftGap");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestLeftGap = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ConnectedSubtitlesOutCueClosestRightGap");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestRightGap = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ConnectedSubtitlesLeftGreenZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftGreenZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ConnectedSubtitlesLeftRedZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftRedZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ConnectedSubtitlesRightRedZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightRedZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ConnectedSubtitlesRightGreenZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightGreenZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ConnectedSubtitlesTreatConnected");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesTreatConnected = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingGeneralUseZones");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingGeneralUseZones = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingGeneralMaxGap");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingGeneralLeftGreenZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingGeneralLeftRedZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftRedZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingGeneralShotChangeBehavior");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior = (BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum)Enum.Parse(typeof(BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum), subNode.InnerText);
}
subNode = profileNode.SelectSingleNode("ChainingInCueOnShotUseZones");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotUseZones = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingInCueOnShotMaxGap");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingInCueOnShotLeftGreenZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftGreenZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingInCueOnShotLeftRedZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftRedZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingOutCueOnShotUseZones");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotUseZones = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingOutCueOnShotMaxGap");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingOutCueOnShotRightRedZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightRedZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
subNode = profileNode.SelectSingleNode("ChainingOutCueOnShotRightGreenZone");
if (subNode != null)
{
settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
}
}
}
if (profileCount == 0)
{
settings.General.CurrentProfile = "Default";
@ -9845,48 +10304,24 @@ $HorzAlign = Center
shortcuts.MainAdjustSnapStartToNextShotChange = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustSnapStartToNextShotChangeWithGap");
if (subNode != null)
{
shortcuts.MainAdjustSnapStartToNextShotChangeWithGap = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustSnapEndToPreviousShotChange");
if (subNode != null)
{
shortcuts.MainAdjustSnapEndToPreviousShotChange = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustSnapEndToPreviousShotChangeWithGap");
if (subNode != null)
{
shortcuts.MainAdjustSnapEndToPreviousShotChangeWithGap = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustExtendToNextShotChange");
if (subNode != null)
{
shortcuts.MainAdjustExtendToNextShotChange = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustExtendToNextShotChangeWithGap");
if (subNode != null)
{
shortcuts.MainAdjustExtendToNextShotChangeWithGap = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustExtendToPreviousShotChange");
if (subNode != null)
{
shortcuts.MainAdjustExtendToPreviousShotChange = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustExtendToPreviousShotChangeWithGap");
if (subNode != null)
{
shortcuts.MainAdjustExtendToPreviousShotChangeWithGap = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustExtendToNextSubtitle");
if (subNode != null)
{
@ -9899,6 +10334,18 @@ $HorzAlign = Center
shortcuts.MainAdjustExtendToPreviousSubtitle = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustExtendToNextSubtitleMinusChainingGap");
if (subNode != null)
{
shortcuts.MainAdjustExtendToNextSubtitleMinusChainingGap = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustExtendToPreviousSubtitleMinusChainingGap");
if (subNode != null)
{
shortcuts.MainAdjustExtendToPreviousSubtitleMinusChainingGap = subNode.InnerText;
}
subNode = node.SelectSingleNode("MainAdjustExtendCurrentSubtitle");
if (subNode != null)
{
@ -10319,6 +10766,7 @@ $HorzAlign = Center
textWriter.WriteElementString("ShowToolbarBurnIn", settings.General.ShowToolbarBurnIn.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ShowToolbarSpellCheck", settings.General.ShowToolbarSpellCheck.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ShowToolbarNetflixGlyphCheck", settings.General.ShowToolbarNetflixGlyphCheck.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ShowToolbarBeautifyTimeCodes", settings.General.ShowToolbarBeautifyTimeCodes.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ShowToolbarSettings", settings.General.ShowToolbarSettings.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ShowToolbarHelp", settings.General.ShowToolbarHelp.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ShowFrameRate", settings.General.ShowFrameRate.ToString(CultureInfo.InvariantCulture));
@ -10763,6 +11211,8 @@ $HorzAlign = Center
textWriter.WriteElementString("AdjustDurationPercent", settings.Tools.AdjustDurationPercent.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("AdjustDurationLast", settings.Tools.AdjustDurationLast);
textWriter.WriteElementString("AdjustDurationExtendOnly", settings.Tools.AdjustDurationExtendOnly.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("AdjustDurationExtendEnforceDurationLimits", settings.Tools.AdjustDurationExtendEnforceDurationLimits.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("AdjustDurationExtendCheckShotChanges", settings.Tools.AdjustDurationExtendCheckShotChanges.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChangeSpeedAllowOverlap", settings.Tools.ChangeSpeedAllowOverlap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("AutoBreakCommaBreakEarly", settings.Tools.AutoBreakCommaBreakEarly.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("AutoBreakDashEarly", settings.Tools.AutoBreakDashEarly.ToString(CultureInfo.InvariantCulture));
@ -10771,6 +11221,7 @@ $HorzAlign = Center
textWriter.WriteElementString("AutoBreakPreferBottomHeavy", settings.Tools.AutoBreakPreferBottomHeavy.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("AutoBreakPreferBottomPercent", settings.Tools.AutoBreakPreferBottomPercent.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ApplyMinimumDurationLimit", settings.Tools.ApplyMinimumDurationLimit.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ApplyMinimumDurationLimitCheckShotChanges", settings.Tools.ApplyMinimumDurationLimitCheckShotChanges.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ApplyMaximumDurationLimit", settings.Tools.ApplyMaximumDurationLimit.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("MergeShortLinesMaxGap", settings.Tools.MergeShortLinesMaxGap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("MergeShortLinesMaxChars", settings.Tools.MergeShortLinesMaxChars.ToString(CultureInfo.InvariantCulture));
@ -11211,6 +11662,47 @@ $HorzAlign = Center
textWriter.WriteElementString("BorderWidth", settings.SubtitleBeaming.BorderWidth.ToString(CultureInfo.InvariantCulture));
textWriter.WriteEndElement();
textWriter.WriteStartElement("BeautifyTimeCodes", string.Empty);
textWriter.WriteElementString("AlignTimeCodes", settings.BeautifyTimeCodes.AlignTimeCodes.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ExtractExactTimeCodes", settings.BeautifyTimeCodes.ExtractExactTimeCodes.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("SnapToShotChanges", settings.BeautifyTimeCodes.SnapToShotChanges.ToString(CultureInfo.InvariantCulture));
textWriter.WriteStartElement("Profile", string.Empty);
textWriter.WriteElementString("Gap", settings.BeautifyTimeCodes.Profile.Gap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("InCuesGap", settings.BeautifyTimeCodes.Profile.InCuesGap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("InCuesLeftGreenZone", settings.BeautifyTimeCodes.Profile.InCuesLeftGreenZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("InCuesLeftRedZone", settings.BeautifyTimeCodes.Profile.InCuesLeftRedZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("InCuesRightRedZone", settings.BeautifyTimeCodes.Profile.InCuesRightRedZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("InCuesRightGreenZone", settings.BeautifyTimeCodes.Profile.InCuesRightGreenZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("OutCuesGap", settings.BeautifyTimeCodes.Profile.OutCuesGap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("OutCuesLeftGreenZone", settings.BeautifyTimeCodes.Profile.OutCuesLeftGreenZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("OutCuesLeftRedZone", settings.BeautifyTimeCodes.Profile.OutCuesLeftRedZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("OutCuesRightRedZone", settings.BeautifyTimeCodes.Profile.OutCuesRightRedZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("OutCuesRightGreenZone", settings.BeautifyTimeCodes.Profile.OutCuesRightGreenZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ConnectedSubtitlesInCueClosestLeftGap", settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestLeftGap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ConnectedSubtitlesInCueClosestRightGap", settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestRightGap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ConnectedSubtitlesOutCueClosestLeftGap", settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestLeftGap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ConnectedSubtitlesOutCueClosestRightGap", settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestRightGap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ConnectedSubtitlesLeftGreenZone", settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftGreenZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ConnectedSubtitlesLeftRedZone", settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftRedZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ConnectedSubtitlesRightRedZone", settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightRedZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ConnectedSubtitlesRightGreenZone", settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightGreenZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ConnectedSubtitlesTreatConnected", settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesTreatConnected.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingGeneralUseZones", settings.BeautifyTimeCodes.Profile.ChainingGeneralUseZones.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingGeneralMaxGap", settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingGeneralLeftGreenZone", settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingGeneralLeftRedZone", settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftRedZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingGeneralShotChangeBehavior", settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior.ToString());
textWriter.WriteElementString("ChainingInCueOnShotUseZones", settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotUseZones.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingInCueOnShotMaxGap", settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingInCueOnShotLeftGreenZone", settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftGreenZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingInCueOnShotLeftRedZone", settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftRedZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingOutCueOnShotUseZones", settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotUseZones.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingOutCueOnShotMaxGap", settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingOutCueOnShotRightRedZone", settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightRedZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ChainingOutCueOnShotRightGreenZone", settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone.ToString(CultureInfo.InvariantCulture));
textWriter.WriteEndElement();
textWriter.WriteEndElement();
textWriter.WriteEndElement();
textWriter.WriteEndDocument();
@ -11592,15 +12084,13 @@ $HorzAlign = Center
textWriter.WriteElementString("MoveEndOneFrameBackKeepGapNext", shortcuts.MoveEndOneFrameBackKeepGapNext);
textWriter.WriteElementString("MoveEndOneFrameForwardKeepGapNext", shortcuts.MoveEndOneFrameForwardKeepGapNext);
textWriter.WriteElementString("MainAdjustSnapStartToNextShotChange", shortcuts.MainAdjustSnapStartToNextShotChange);
textWriter.WriteElementString("MainAdjustSnapStartToNextShotChangeWithGap", shortcuts.MainAdjustSnapStartToNextShotChangeWithGap);
textWriter.WriteElementString("MainAdjustSnapEndToPreviousShotChange", shortcuts.MainAdjustSnapEndToPreviousShotChange);
textWriter.WriteElementString("MainAdjustSnapEndToPreviousShotChangeWithGap", shortcuts.MainAdjustSnapEndToPreviousShotChangeWithGap);
textWriter.WriteElementString("MainAdjustExtendToNextShotChange", shortcuts.MainAdjustExtendToNextShotChange);
textWriter.WriteElementString("MainAdjustExtendToNextShotChangeWithGap", shortcuts.MainAdjustExtendToNextShotChangeWithGap);
textWriter.WriteElementString("MainAdjustExtendToPreviousShotChange", shortcuts.MainAdjustExtendToPreviousShotChange);
textWriter.WriteElementString("MainAdjustExtendToPreviousShotChangeWithGap", shortcuts.MainAdjustExtendToPreviousShotChangeWithGap);
textWriter.WriteElementString("MainAdjustExtendToNextSubtitle", shortcuts.MainAdjustExtendToNextSubtitle);
textWriter.WriteElementString("MainAdjustExtendToPreviousSubtitle", shortcuts.MainAdjustExtendToPreviousSubtitle);
textWriter.WriteElementString("MainAdjustExtendToNextSubtitleMinusChainingGap", shortcuts.MainAdjustExtendToNextSubtitleMinusChainingGap);
textWriter.WriteElementString("MainAdjustExtendToPreviousSubtitleMinusChainingGap", shortcuts.MainAdjustExtendToPreviousSubtitleMinusChainingGap);
textWriter.WriteElementString("MainAdjustExtendCurrentSubtitle", shortcuts.MainAdjustExtendCurrentSubtitle);
textWriter.WriteElementString("MainAdjustExtendPreviousLineEndToCurrentStart", shortcuts.MainAdjustExtendPreviousLineEndToCurrentStart);
textWriter.WriteElementString("MainAdjustExtendNextLineStartToCurrentEnd", shortcuts.MainAdjustExtendNextLineStartToCurrentEnd);

View File

@ -1,7 +1,11 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Nikse.SubtitleEdit.Core.Forms;
using Nikse.SubtitleEdit.Core.SubtitleFormats;
namespace Nikse.SubtitleEdit.Core.Common
{
@ -79,5 +83,89 @@ namespace Nikse.SubtitleEdit.Core.Common
File.Delete(shotChangesFileName);
}
}
// Util functions
public static double? GetPreviousShotChangeInMs(List<double> shotChanges, TimeCode currentTime)
{
try
{
return shotChanges.Last(x => SubtitleFormat.MillisecondsToFrames(x * 1000) <= SubtitleFormat.MillisecondsToFrames(currentTime.TotalMilliseconds));
}
catch (InvalidOperationException)
{
return null;
}
}
public static double? GetPreviousShotChangePlusGapInMs(List<double> shotChanges, TimeCode currentTime)
{
var previousShotChangeInMs = GetPreviousShotChangeInMs(shotChanges, currentTime);
if (previousShotChangeInMs != null)
{
return previousShotChangeInMs + TimeCodesBeautifierUtils.GetInCuesGapMs();
}
return null;
}
public static double? GetNextShotChangeInMs(List<double> shotChanges, TimeCode currentTime)
{
try
{
return shotChanges.First(x => SubtitleFormat.MillisecondsToFrames(x * 1000) >= SubtitleFormat.MillisecondsToFrames(currentTime.TotalMilliseconds));
}
catch (InvalidOperationException)
{
return null;
}
}
public static double? GetNextShotChangeMinusGapInMs(List<double> shotChanges, TimeCode currentTime)
{
var nextShotChangeInMs = GetNextShotChangeInMs(shotChanges, currentTime);
if (nextShotChangeInMs != null)
{
return nextShotChangeInMs - TimeCodesBeautifierUtils.GetOutCuesGapMs();
}
return null;
}
public static double? GetClosestShotChange(List<double> shotChanges, TimeCode currentTime)
{
try
{
return shotChanges.Aggregate((x, y) => Math.Abs(x - currentTime.TotalSeconds) < Math.Abs(y - currentTime.TotalSeconds) ? x : y);
}
catch (InvalidOperationException)
{
return null;
}
}
public static bool IsCueOnShotChange(List<double> shotChanges, TimeCode currentTime, bool isInCue)
{
var closestShotChange = GetClosestShotChange(shotChanges, currentTime);
if (closestShotChange != null)
{
var currentFrame = SubtitleFormat.MillisecondsToFrames(currentTime.TotalMilliseconds);
var closestShotChangeFrame = SubtitleFormat.MillisecondsToFrames(closestShotChange.Value * 1000);
if (isInCue)
{
return currentFrame >= closestShotChangeFrame && currentFrame <= closestShotChangeFrame + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap;
}
else
{
return currentFrame <= closestShotChangeFrame && currentFrame >= closestShotChangeFrame - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
}
}
else
{
return false;
}
}
}
}

View File

@ -377,7 +377,7 @@ namespace Nikse.SubtitleEdit.Core.Common
}
}
public void AdjustDisplayTimeUsingPercent(double percent, List<int> selectedIndexes)
public void AdjustDisplayTimeUsingPercent(double percent, List<int> selectedIndexes, List<double> shotChanges = null, bool enforceDurationLimits = true)
{
for (int i = 0; i < Paragraphs.Count; i++)
{
@ -391,11 +391,43 @@ namespace Nikse.SubtitleEdit.Core.Common
double newEndMilliseconds = Paragraphs[i].EndTime.TotalMilliseconds;
newEndMilliseconds = Paragraphs[i].StartTime.TotalMilliseconds + (((newEndMilliseconds - Paragraphs[i].StartTime.TotalMilliseconds) * percent) / 100.0);
// fix too short duration
if (enforceDurationLimits)
{
var minDur = Math.Max(Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds, 100);
if (Paragraphs[i].StartTime.TotalMilliseconds + minDur > newEndMilliseconds)
{
newEndMilliseconds = Paragraphs[i].StartTime.TotalMilliseconds + minDur;
}
}
// handle overlap with next
if (newEndMilliseconds > nextStartMilliseconds)
{
newEndMilliseconds = nextStartMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
}
// handle shot change if supplied -- keep earliest time
if (shotChanges != null)
{
double nextShotChangeMilliseconds = ShotChangeHelper.GetNextShotChangeMinusGapInMs(shotChanges, Paragraphs[i].EndTime) ?? double.MaxValue;
if (newEndMilliseconds > nextShotChangeMilliseconds)
{
newEndMilliseconds = nextShotChangeMilliseconds;
}
}
// max duration
if (enforceDurationLimits)
{
var dur = newEndMilliseconds - Paragraphs[i].StartTime.TotalMilliseconds;
if (dur > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds)
{
newEndMilliseconds = Paragraphs[i].StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds;
}
}
if (percent > 100 && newEndMilliseconds > Paragraphs[i].EndTime.TotalMilliseconds || percent < 100)
{
Paragraphs[i].EndTime.TotalMilliseconds = newEndMilliseconds;
@ -404,7 +436,7 @@ namespace Nikse.SubtitleEdit.Core.Common
}
}
public void AdjustDisplayTimeUsingSeconds(double seconds, List<int> selectedIndexes)
public void AdjustDisplayTimeUsingSeconds(double seconds, List<int> selectedIndexes, List<double> shotChanges = null, bool enforceDurationLimits = true)
{
if (Math.Abs(seconds) < 0.001)
{
@ -416,19 +448,19 @@ namespace Nikse.SubtitleEdit.Core.Common
{
foreach (var idx in selectedIndexes)
{
AdjustDisplayTimeUsingMilliseconds(idx, adjustMs);
AdjustDisplayTimeUsingMilliseconds(idx, adjustMs, shotChanges, enforceDurationLimits);
}
}
else
{
for (int idx = 0; idx < Paragraphs.Count; idx++)
{
AdjustDisplayTimeUsingMilliseconds(idx, adjustMs);
AdjustDisplayTimeUsingMilliseconds(idx, adjustMs, shotChanges, enforceDurationLimits);
}
}
}
private void AdjustDisplayTimeUsingMilliseconds(int idx, double ms)
private void AdjustDisplayTimeUsingMilliseconds(int idx, double ms, List<double> shotChanges = null, bool enforceDurationLimits = true)
{
var p = Paragraphs[idx];
var nextStartTimeInMs = double.MaxValue;
@ -439,10 +471,13 @@ namespace Nikse.SubtitleEdit.Core.Common
var newEndTimeInMs = p.EndTime.TotalMilliseconds + ms;
// fix too short duration
var minDur = Math.Max(Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds, 100);
if (p.StartTime.TotalMilliseconds + minDur > newEndTimeInMs)
if (enforceDurationLimits)
{
newEndTimeInMs = p.StartTime.TotalMilliseconds + minDur;
var minDur = Math.Max(Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds, 100);
if (p.StartTime.TotalMilliseconds + minDur > newEndTimeInMs)
{
newEndTimeInMs = p.StartTime.TotalMilliseconds + minDur;
}
}
// handle overlap with next
@ -451,11 +486,20 @@ namespace Nikse.SubtitleEdit.Core.Common
newEndTimeInMs = nextStartTimeInMs - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
}
// max duration
var dur = newEndTimeInMs - p.StartTime.TotalMilliseconds;
if (dur > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds)
// handle shot change if supplied -- keep earliest time
if (shotChanges != null)
{
newEndTimeInMs = p.StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds;
newEndTimeInMs = Math.Min(newEndTimeInMs, ShotChangeHelper.GetNextShotChangeMinusGapInMs(shotChanges, p.EndTime) ?? double.MaxValue);
}
// max duration
if (enforceDurationLimits)
{
var dur = newEndTimeInMs - p.StartTime.TotalMilliseconds;
if (dur > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds)
{
newEndTimeInMs = p.StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds;
}
}
if (ms > 0 && newEndTimeInMs < p.EndTime.TotalMilliseconds || ms < 0 && newEndTimeInMs > p.EndTime.TotalMilliseconds)
@ -466,25 +510,25 @@ namespace Nikse.SubtitleEdit.Core.Common
p.EndTime.TotalMilliseconds = newEndTimeInMs;
}
public void RecalculateDisplayTimes(double maxCharPerSec, List<int> selectedIndexes, double optimalCharPerSec, bool extendOnly = false)
public void RecalculateDisplayTimes(double maxCharPerSec, List<int> selectedIndexes, double optimalCharPerSec, bool extendOnly = false, List<double> shotChanges = null, bool enforceDurationLimits = true)
{
if (selectedIndexes != null)
{
foreach (var index in selectedIndexes)
{
RecalculateDisplayTime(maxCharPerSec, index, optimalCharPerSec, extendOnly);
RecalculateDisplayTime(maxCharPerSec, index, optimalCharPerSec, extendOnly, false, shotChanges, enforceDurationLimits);
}
}
else
{
for (int i = 0; i < Paragraphs.Count; i++)
{
RecalculateDisplayTime(maxCharPerSec, i, optimalCharPerSec, extendOnly);
RecalculateDisplayTime(maxCharPerSec, i, optimalCharPerSec, extendOnly, false, shotChanges, enforceDurationLimits);
}
}
}
public void RecalculateDisplayTime(double maxCharactersPerSecond, int index, double optimalCharactersPerSeconds, bool extendOnly = false, bool onlyOptimal = false)
public void RecalculateDisplayTime(double maxCharactersPerSecond, int index, double optimalCharactersPerSeconds, bool extendOnly = false, bool onlyOptimal = false, List<double> shotChanges = null, bool enforceDurationLimits = true)
{
var p = GetParagraphOrDefault(index);
if (p == null)
@ -494,7 +538,7 @@ namespace Nikse.SubtitleEdit.Core.Common
var originalEndTime = p.EndTime.TotalMilliseconds;
var duration = Utilities.GetOptimalDisplayMilliseconds(p.Text, optimalCharactersPerSeconds, onlyOptimal);
var duration = Utilities.GetOptimalDisplayMilliseconds(p.Text, optimalCharactersPerSeconds, onlyOptimal, enforceDurationLimits);
p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + duration;
while (Utilities.GetCharactersPerSecond(p) > maxCharactersPerSecond)
{
@ -508,17 +552,30 @@ namespace Nikse.SubtitleEdit.Core.Common
}
var next = GetParagraphOrDefault(index + 1);
if (next != null && p.StartTime.TotalMilliseconds + duration + Configuration.Settings.General.MinimumMillisecondsBetweenLines > next.StartTime.TotalMilliseconds)
var wantedEndMs = p.EndTime.TotalMilliseconds;
var bestEndMs = double.MaxValue;
// First check for next subtitle
if (next != null)
{
p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
if (p.DurationTotalMilliseconds <= 0)
{
p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + 1;
}
bestEndMs = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
}
// Then check for next shot change (if option is checked, and if any are supplied) -- keeping earliest time
if (shotChanges != null)
{
bestEndMs = Math.Min(bestEndMs, ShotChangeHelper.GetNextShotChangeMinusGapInMs(shotChanges, new TimeCode(originalEndTime)) ?? double.MaxValue);
}
p.EndTime.TotalMilliseconds = wantedEndMs <= bestEndMs ? wantedEndMs : bestEndMs;
if (p.DurationTotalMilliseconds <= 0)
{
p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + 1;
}
}
public void SetFixedDuration(List<int> selectedIndexes, double fixedDurationMilliseconds)
public void SetFixedDuration(List<int> selectedIndexes, double fixedDurationMilliseconds, List<double> shotChanges = null)
{
for (int i = 0; i < Paragraphs.Count; i++)
{
@ -530,16 +587,27 @@ namespace Nikse.SubtitleEdit.Core.Common
continue;
}
p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + fixedDurationMilliseconds;
var next = GetParagraphOrDefault(i + 1);
if (next != null && p.StartTime.TotalMilliseconds + fixedDurationMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines > next.StartTime.TotalMilliseconds)
var wantedEndMs = p.StartTime.TotalMilliseconds + fixedDurationMilliseconds;
var bestEndMs = double.MaxValue;
// First check for next subtitle
if (next != null)
{
p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
if (p.DurationTotalMilliseconds <= 0)
{
p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + 1;
}
bestEndMs = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
}
// Then check for next shot change (if option is checked, and if any are supplied) -- keeping earliest time
if (shotChanges != null)
{
bestEndMs = Math.Min(bestEndMs, ShotChangeHelper.GetNextShotChangeMinusGapInMs(shotChanges, p.EndTime) ?? double.MaxValue);
}
p.EndTime.TotalMilliseconds = wantedEndMs <= bestEndMs ? wantedEndMs : bestEndMs;
if (p.DurationTotalMilliseconds <= 0)
{
p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + 1;
}
}
}

View File

@ -0,0 +1,82 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
namespace Nikse.SubtitleEdit.Core.Common
{
public static class TimeCodesFileHelper
{
private static string GetTimeCodesFileName(string videoFileName)
{
var dir = Configuration.TimeCodesDirectory.TrimEnd(Path.DirectorySeparatorChar);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
var newFileName = MovieHasher.GenerateHash(videoFileName) + ".timecodes";
newFileName = Path.Combine(dir, newFileName);
return newFileName;
}
/// <summary>
/// Load time codes from file
/// </summary>
/// <param name="videoFileName">Video file name</param>
/// <returns>List of time codes in seconds</returns>
public static List<double> FromDisk(string videoFileName)
{
var list = new List<double>();
if (string.IsNullOrEmpty(videoFileName))
{
return list;
}
var timeCodesFileName = GetTimeCodesFileName(videoFileName);
if (!File.Exists(timeCodesFileName))
{
return list;
}
foreach (var line in File.ReadLines(timeCodesFileName))
{
if (!string.IsNullOrWhiteSpace(line))
{
list.Add(double.Parse(line, CultureInfo.InvariantCulture));
}
}
return list;
}
/// <summary>
/// Saves time codes
/// </summary>
/// <param name="videoFileName">Video file name</param>
/// <param name="list">List of time codes in seconds</param>
public static void SaveTimeCodes(string videoFileName, List<double> list)
{
var sb = new StringBuilder();
foreach (var d in list)
{
sb.AppendLine(d.ToString(CultureInfo.InvariantCulture));
}
File.WriteAllText(GetTimeCodesFileName(videoFileName), sb.ToString().Trim());
}
/// <summary>
/// Delete time codes file associated with video file
/// </summary>
/// <param name="videoFileName">Video file name</param>
public static void DeleteTimeCodes(string videoFileName)
{
var timeCodesFileName = GetTimeCodesFileName(videoFileName);
if (File.Exists(timeCodesFileName))
{
File.Delete(timeCodesFileName);
}
}
}
}

View File

@ -869,7 +869,7 @@ namespace Nikse.SubtitleEdit.Core.Common
return GetOptimalDisplayMilliseconds(text, Configuration.Settings.General.SubtitleOptimalCharactersPerSeconds);
}
public static double GetOptimalDisplayMilliseconds(string text, double optimalCharactersPerSecond, bool onlyOptimal = false)
public static double GetOptimalDisplayMilliseconds(string text, double optimalCharactersPerSecond, bool onlyOptimal = false, bool enforceDurationLimits = true)
{
if (optimalCharactersPerSecond < 2 || optimalCharactersPerSecond > 100)
{
@ -894,12 +894,12 @@ namespace Nikse.SubtitleEdit.Core.Common
}
}
if (duration < Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds)
if (enforceDurationLimits && duration < Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds)
{
duration = Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds;
}
if (duration > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds)
if (enforceDurationLimits && duration > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds)
{
duration = Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds;
}

View File

@ -0,0 +1,878 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Nikse.SubtitleEdit.Core.Common;
using Nikse.SubtitleEdit.Core.SubtitleFormats;
namespace Nikse.SubtitleEdit.Core.Forms
{
public class TimeCodesBeautifier
{
private readonly Subtitle _subtitle;
private readonly double _frameRate;
private readonly List<double> _timeCodes;
private readonly List<int> _shotChangesFrames;
public ProgressChangedDelegate ProgressChanged { get; set; }
public TimeCodesBeautifier(Subtitle subtitle, double frameRate, List<double> timeCodes, List<double> shotChanges)
{
_subtitle = subtitle;
_frameRate = frameRate;
_timeCodes = timeCodes;
// Convert shot changes to frame numbers
_shotChangesFrames = shotChanges.Select(d => SubtitleFormat.MillisecondsToFrames(d * 1000, _frameRate)).ToList();
}
public void Beautify()
{
var amountOfPasses = 2;
var skipNextInCue = false;
for (int pass = 0; pass < amountOfPasses; pass++)
{
for (int p = 0; p < _subtitle.Paragraphs.Count; p++)
{
// Gather relevant paragraphs
var paragraph = _subtitle.Paragraphs.ElementAtOrDefault(p);
var previousParagraph = _subtitle.Paragraphs.ElementAtOrDefault(p - 1);
var nextParagraph = _subtitle.Paragraphs.ElementAtOrDefault(p + 1);
var result = false;
// === In cue ===
// Check if the in cue should be processed
if (!skipNextInCue)
{
// Check if we have connected subtitles
result = FixConnectedSubtitles(previousParagraph, paragraph);
// If not, check if we have chainable subtitles
if (!result)
{
result = FixChainableSubtitles(previousParagraph, paragraph);
}
// If not, then we have a free in cue
if (!result)
{
FixInCue(p);
}
}
else
{
// Reset flag for next iteration
skipNextInCue = false;
}
// === Out cue ===
// Check if we have connected subtitles
result = FixConnectedSubtitles(paragraph, nextParagraph);
if (result)
{
// Yes, this means the next subtitle's in cue is now also processed. Skipping in next iteration
skipNextInCue = true;
}
else
{
// If not, then we have a free out cue
FixOutCue(p);
}
// Report progress
var progress = ((pass + 1) / (double)amountOfPasses) * (p / (double)_subtitle.Paragraphs.Count);
ProgressChanged.Invoke(progress);
}
}
}
private bool FixConnectedSubtitles(Paragraph leftParagraph = null, Paragraph rightParagraph = null)
{
if (leftParagraph == null || rightParagraph == null)
{
return false;
}
var distance = rightParagraph.StartTime.TotalMilliseconds - leftParagraph.EndTime.TotalMilliseconds;
var subtitlesAreConnected = distance < Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesTreatConnected;
if (subtitlesAreConnected)
{
var newLeftOutCueFrame = SubtitleFormat.MillisecondsToFrames(leftParagraph.EndTime.TotalMilliseconds, _frameRate);
var newRightInCueFrame = SubtitleFormat.MillisecondsToFrames(rightParagraph.StartTime.TotalMilliseconds, _frameRate);
// Check if we should do something with shot changes
if (_shotChangesFrames.Count > 0)
{
// Find best cues for left out cue and right in cue
var bestLeftOutCueFrameInfo = FindConnectedSubtitlesBestCueFrame(newLeftOutCueFrame);
var bestRightInCueFrameInfo = FindConnectedSubtitlesBestCueFrame(newRightInCueFrame);
// Check result
if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRedZone && bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRedZone)
{
// Both are in red zones! We will use the closest shot change to align the cues around
if (Math.Abs(newLeftOutCueFrame - bestLeftOutCueFrameInfo.cueFrame) <= Math.Abs(newRightInCueFrame - bestRightInCueFrameInfo.cueFrame))
{
var fixInfo = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, bestLeftOutCueFrameInfo.cueFrame);
newLeftOutCueFrame = fixInfo.newLeftOutCueFrame;
newRightInCueFrame = fixInfo.newRightInCueFrame;
}
else
{
var fixInfo = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, bestRightInCueFrameInfo.cueFrame);
newLeftOutCueFrame = fixInfo.newLeftOutCueFrame;
newRightInCueFrame = fixInfo.newRightInCueFrame;
}
}
else if ((bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone || bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone) &&
(bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone || bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone))
{
// Both are in green zones! Check cases...
if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone && bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone)
{
// Both cues want to go backward. Most likely both are in the same shot change's green zone
// For now, assume that, and put the right in cue on the edge of the green zone, and push the previous subtitle backward
newRightInCueFrame = bestRightInCueFrameInfo.cueFrame;
newLeftOutCueFrame = newRightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
else if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone && bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone)
{
// Cues want to be pulled apart. Highly unlikely. There is probably a shot change in the middle of them and no red zone set
// For now, try get the first shot change in between and align the cues around that, ignoring the zones
var firstShotChangeInBetween = GetFirstShotChangeFrameInBetween(newLeftOutCueFrame, newRightInCueFrame);
if (firstShotChangeInBetween != null)
{
var fixInfo = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, firstShotChangeInBetween.Value);
newLeftOutCueFrame = fixInfo.newLeftOutCueFrame;
newRightInCueFrame = fixInfo.newRightInCueFrame;
}
else
{
// No shot change found... Then just chain them then as fallback
newLeftOutCueFrame = newRightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
}
else if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone && bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone)
{
// Cues want to be pushed together. The connect subtitles are most likely between two shot changes that are close together
// For now, check which shot change is closer and align the cues around that, ignoring the zones
var previousShotChange = new List<int> { -1 }.Concat(_shotChangesFrames).Last(x => x <= newLeftOutCueFrame); // will return -1 if none found
var nextShotChange = _shotChangesFrames.Concat(new List<int> { int.MaxValue }).First(x => x >= newRightInCueFrame); // will return maxValue if none found
if (previousShotChange >= 0 && nextShotChange != int.MaxValue)
{
if (Math.Abs(previousShotChange - newLeftOutCueFrame) <= Math.Abs(nextShotChange - newRightInCueFrame))
{
var fixInfo = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, previousShotChange);
newLeftOutCueFrame = fixInfo.newLeftOutCueFrame;
newRightInCueFrame = fixInfo.newRightInCueFrame;
}
else
{
var fixInfo = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, nextShotChange);
newLeftOutCueFrame = fixInfo.newLeftOutCueFrame;
newRightInCueFrame = fixInfo.newRightInCueFrame;
}
}
else
{
// No shot changes found on either sides... Then just chain them as fallback
newLeftOutCueFrame = newRightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
}
else if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone && bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone)
{
// Both cues want to go forward. Most likely both are in the same shot change's green zone
// For now, assume that, and put the left out cue on the edge of the green zone, and push the next subtitle forward
newLeftOutCueFrame = bestLeftOutCueFrameInfo.cueFrame;
newRightInCueFrame = newLeftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
}
else if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRedZone) // Other cases... Red zone snapping has priority
{
var fixInfo = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, bestLeftOutCueFrameInfo.cueFrame);
newLeftOutCueFrame = fixInfo.newLeftOutCueFrame;
newRightInCueFrame = fixInfo.newRightInCueFrame;
}
else if (bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRedZone)
{
var fixInfo = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, bestRightInCueFrameInfo.cueFrame);
newLeftOutCueFrame = fixInfo.newLeftOutCueFrame;
newRightInCueFrame = fixInfo.newRightInCueFrame;
}
else if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone)
{
throw new InvalidOperationException("The left out cue cannot be snapped to the left side of a green zone while the right in cue is unaffected at the same time.");
}
else if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone)
{
// Put the left out cue on the edge of the green zone, and push the next subtitle forward
newLeftOutCueFrame = bestLeftOutCueFrameInfo.cueFrame;
newRightInCueFrame = newLeftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
else if (bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone)
{
// Put the right in cue on the edge of the green zone, and push the previous subtitle backward
newRightInCueFrame = bestRightInCueFrameInfo.cueFrame;
newLeftOutCueFrame = newRightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
else if (bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone)
{
throw new InvalidOperationException("The right in cue cannot be snapped to the right side of a green zone while the left out cue is unaffected at the same time.");
}
else
{
// Fallback when no shot changes were apparently found: just chain them
newLeftOutCueFrame = newRightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
}
else
{
// Just chain them
newLeftOutCueFrame = newRightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
// Align and update cues
AlignAndSetCue(leftParagraph, false, newLeftOutCueFrame);
AlignAndSetCue(rightParagraph, true, newRightInCueFrame);
}
else
{
return false;
}
return true;
}
private (int cueFrame, FindBestCueResult result) FindConnectedSubtitlesBestCueFrame(int cueFrame)
{
var previousShotChange = new List<int> { -1 }.Concat(_shotChangesFrames).Last(x => x <= cueFrame); // will return -1 if none found
var nextShotChange = _shotChangesFrames.Concat(new List<int> { int.MaxValue }).First(x => x >= cueFrame); // will return maxValue if none found
// If both not found, return self
if (previousShotChange < 0 && nextShotChange == int.MaxValue)
{
return (cueFrame, FindBestCueResult.NoShotChangeFound);
}
// Do logic
var previousShotChangeWithGreenZone = previousShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightGreenZone;
var nextShotChangeWithGreenZone = nextShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftGreenZone;
var isInPreviousShotChangeGreenZone = cueFrame < previousShotChangeWithGreenZone && cueFrame > (previousShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightRedZone);
var isInPreviousShotChangeRedZone = cueFrame <= (previousShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightRedZone) && cueFrame >= previousShotChange;
var isInNextShotChangeGreenZone = cueFrame > nextShotChangeWithGreenZone && cueFrame < (nextShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftRedZone);
var isInNextShotChangeRedZone = cueFrame >= (nextShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftRedZone) && cueFrame <= nextShotChange;
if (isInPreviousShotChangeRedZone && isInNextShotChangeRedZone)
{
// We are in both red zones! Snap to closest shot change
if (Math.Abs(cueFrame - previousShotChange) <= Math.Abs(cueFrame - nextShotChange))
{
return (previousShotChange, FindBestCueResult.SnappedToRedZone);
}
else
{
return (nextShotChange, FindBestCueResult.SnappedToRedZone);
}
}
else if (isInPreviousShotChangeGreenZone && isInNextShotChangeGreenZone)
{
// We are in both green zones! Take one with least "violation"
if (Math.Abs(previousShotChangeWithGreenZone - nextShotChange) > Math.Abs(nextShotChangeWithGreenZone - previousShotChange))
{
return (previousShotChangeWithGreenZone, FindBestCueResult.SnappedToRightGreenZone);
}
else
{
return (nextShotChangeWithGreenZone, FindBestCueResult.SnappedToLeftGreenZone);
}
}
else
{
if (isInPreviousShotChangeRedZone)
{
// Snap to previous shot change
return (previousShotChange, FindBestCueResult.SnappedToRedZone);
}
else if (isInNextShotChangeRedZone)
{
// Snap to next shot change
return (nextShotChange, FindBestCueResult.SnappedToRedZone);
}
else if (isInPreviousShotChangeGreenZone)
{
// Enforce green zone from previous shot change, but shouldn't exceed next shot change
return (Math.Min(previousShotChangeWithGreenZone, nextShotChange), FindBestCueResult.SnappedToRightGreenZone);
}
else if (isInNextShotChangeGreenZone)
{
// Enforce green zone from next shot change, but shouldn't exceed previous shot change
return (Math.Max(nextShotChangeWithGreenZone, previousShotChange), FindBestCueResult.SnappedToLeftGreenZone);
}
}
return (cueFrame, FindBestCueResult.NoShotChangeFound);
}
private enum FindBestCueResult
{
NoShotChangeFound,
SnappedToRedZone,
SnappedToRightGreenZone,
SnappedToLeftGreenZone
}
private (int newLeftOutCueFrame, int newRightInCueFrame) GetFixedConnectedSubtitlesCueFrames(Paragraph leftParagraph, Paragraph rightParagraph, int shotChangeFrame)
{
// Check which cue is closest (use milliseconds to check original unaligned positions)
var shotChangeMs = SubtitleFormat.FramesToMilliseconds(shotChangeFrame, _frameRate);
if (Math.Abs(leftParagraph.EndTime.TotalMilliseconds - shotChangeMs) < Math.Abs(rightParagraph.StartTime.TotalMilliseconds - shotChangeMs))
{
// Left subtitle's out cue is closest
var newLeftOutCueFrame = shotChangeFrame - Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestLeftGap;
var newRightInCueFrame = shotChangeFrame + Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestRightGap;
return (newLeftOutCueFrame, newRightInCueFrame);
}
else
{
// Right subtitle's in cue is closest (priority if same)
var newLeftOutCueFrame = shotChangeFrame - Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestLeftGap;
var newRightInCueFrame = shotChangeFrame + Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestRightGap;
return (newLeftOutCueFrame, newRightInCueFrame);
}
}
private bool FixChainableSubtitles(Paragraph leftParagraph = null, Paragraph rightParagraph = null)
{
if (leftParagraph == null || rightParagraph == null)
{
return false;
}
var newLeftOutCueFrame = SubtitleFormat.MillisecondsToFrames(leftParagraph.EndTime.TotalMilliseconds, _frameRate);
var newRightInCueFrame = SubtitleFormat.MillisecondsToFrames(rightParagraph.StartTime.TotalMilliseconds, _frameRate);
var shouldFixConnectedSubtitles = false;
// Check if we should do something with shot changes
if (_shotChangesFrames.Count > 0)
{
// Find best cues for left out cue and right in cue
var bestLeftOutCueFrameInfo = FindBestCueFrame(newLeftOutCueFrame, false);
var bestLeftOutCueFrame = bestLeftOutCueFrameInfo.cueFrame;
var bestRightInCueFrameInfo = FindBestCueFrame(newRightInCueFrame, true);
var bestRightInCueFrame = bestRightInCueFrameInfo.cueFrame;
// Check cases
var isLeftOutCueOnShotChange = IsCueOnShotChange(bestLeftOutCueFrame, false);
var isRightInCueOnShotChange = IsCueOnShotChange(bestRightInCueFrame, true);
if (isRightInCueOnShotChange)
{
// The right in cue is on a shot change
// Try to chain the subtitles
var fixedLeftOutCueFrame = GetFixedChainableSubtitlesLeftOutCueFrameInCueOnShot(bestLeftOutCueFrame, bestRightInCueFrame);
if (fixedLeftOutCueFrame != null)
{
newLeftOutCueFrame = fixedLeftOutCueFrame.Value;
newRightInCueFrame = bestRightInCueFrame;
// Make sure the newly connected subtitles get fixed
shouldFixConnectedSubtitles = true;
}
else
{
// Chaining wasn't needed
return false;
}
}
else if (isLeftOutCueOnShotChange)
{
// The left out cue in on a shot change
// Try to chain the subtitles
var fixedRightInCueFrame = GetFixedChainableSubtitlesRightInCueFrameOutCueOnShot(bestLeftOutCueFrame, bestRightInCueFrame);
if (fixedRightInCueFrame != null)
{
newLeftOutCueFrame = bestLeftOutCueFrame;
newRightInCueFrame = fixedRightInCueFrame.Value;
// Make sure the newly connected subtitles get fixed
shouldFixConnectedSubtitles = true;
}
else
{
// Chaining wasn't needed
return false;
}
}
else
{
// The cues are not on shot changes
// Try to chain the subtitles already, maybe chaining is not needed
var fixedLeftOutCueFrame = GetFixedChainableSubtitlesLeftOutCueFrameGeneral(bestLeftOutCueFrame, bestRightInCueFrame);
if (fixedLeftOutCueFrame != null)
{
// Check if there are any shot changes in between them
var firstShotChangeInBetween = GetFirstShotChangeFrameInBetween(bestLeftOutCueFrame, bestRightInCueFrame);
if (firstShotChangeInBetween != null)
{
// There are shot changes in between. Check behaviors
switch (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior)
{
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum.DontChain:
// Don't do anything
return false;
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum.ExtendCrossingShotChange:
// Apply the chaining
newLeftOutCueFrame = fixedLeftOutCueFrame.Value;
newRightInCueFrame = bestRightInCueFrame;
// Make sure the newly connected subtitles get fixed
shouldFixConnectedSubtitles = true;
break;
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum.ExtendUntilShotChange:
// Put the left out cue on the shot change, minus gap
newLeftOutCueFrame = firstShotChangeInBetween.Value - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
newRightInCueFrame = bestRightInCueFrame;
break;
}
}
else
{
// Apply the chaining
newLeftOutCueFrame = fixedLeftOutCueFrame.Value;
newRightInCueFrame = bestRightInCueFrame;
}
}
else
{
// Chaining not needed
return false;
}
}
}
else
{
// No, so we will be using the "General" settings
// Try to chain the subtitles (we can pass the original paragraphs because we haven't moved the cues)
var fixedLeftOutCueFrame = GetFixedChainableSubtitlesLeftOutCueFrameGeneral(newLeftOutCueFrame, newRightInCueFrame, leftParagraph, rightParagraph);
if (fixedLeftOutCueFrame != null)
{
newLeftOutCueFrame = fixedLeftOutCueFrame.Value;
}
else
{
// Chaining wasn't needed
return false;
}
}
// Align and update cues
AlignAndSetCue(leftParagraph, false, newLeftOutCueFrame);
AlignAndSetCue(rightParagraph, true, newRightInCueFrame);
// Update connected subtitles if requested
if (shouldFixConnectedSubtitles)
{
FixConnectedSubtitles(leftParagraph, rightParagraph);
}
return true;
}
private int? GetFixedChainableSubtitlesLeftOutCueFrameGeneral(int leftOutCueFrame, int rightInCueFrame, Paragraph leftParagraph = null, Paragraph rightParagraph = null)
{
// Check if zones are being used
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralUseZones)
{
var rightInCueWithGreenZone = rightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone;
var isInGreenZone = leftOutCueFrame > rightInCueWithGreenZone && leftOutCueFrame < (rightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftRedZone);
var isInRedZone = leftOutCueFrame >= (rightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftRedZone) && leftOutCueFrame <= rightInCueFrame;
if (isInRedZone)
{
// Chain them
return rightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
else if (isInGreenZone)
{
// Enforce green zone
return rightInCueWithGreenZone;
}
else
{
// Chaining not needed
return null;
}
}
else
{
// No, so just check the distance in milliseconds (use original milliseconds if passed)
double distance;
if (leftParagraph != null && rightParagraph != null)
{
distance = rightParagraph.StartTime.TotalMilliseconds - leftParagraph.EndTime.TotalMilliseconds;
}
else
{
distance = SubtitleFormat.FramesToMilliseconds(rightInCueFrame, _frameRate) - SubtitleFormat.FramesToMilliseconds(leftOutCueFrame, _frameRate);
}
if (distance < Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap)
{
// Chain them
return rightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
else
{
// Chaining not needed
return null;
}
}
}
private int? GetFixedChainableSubtitlesLeftOutCueFrameInCueOnShot(int leftOutCueFrame, int rightInCueFrame)
{
// Check if zones are being used
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotUseZones)
{
var rightInCueWithGreenZone = rightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftGreenZone;
var isInGreenZone = leftOutCueFrame > rightInCueWithGreenZone && leftOutCueFrame < (rightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftRedZone);
var isInRedZone = leftOutCueFrame >= (rightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftRedZone) && leftOutCueFrame <= rightInCueFrame;
if (isInRedZone)
{
// Chain them
return rightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
else if (isInGreenZone)
{
// Enforce green zone
return rightInCueWithGreenZone;
}
else
{
// Chaining not needed
return null;
}
}
else
{
// No, so just check the distance in milliseconds
var distance = SubtitleFormat.FramesToMilliseconds(rightInCueFrame, _frameRate) - SubtitleFormat.FramesToMilliseconds(leftOutCueFrame, _frameRate);
if (distance < Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap)
{
// Chain them
return rightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
else
{
// Chaining not needed
return null;
}
}
}
private int? GetFixedChainableSubtitlesRightInCueFrameOutCueOnShot(int leftOutCueFrame, int rightInCueFrame)
{
// Check if zones are being used
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotUseZones)
{
var leftOutCueWithGreenZone = leftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone;
var isInGreenZone = rightInCueFrame < leftOutCueWithGreenZone && rightInCueFrame > (leftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightRedZone);
var isInRedZone = rightInCueFrame <= (leftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftRedZone) && rightInCueFrame >= leftOutCueFrame;
if (isInRedZone)
{
// Chain them
return leftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
else if (isInGreenZone)
{
// Enforce green zone
return leftOutCueWithGreenZone;
}
else
{
// Chaining not needed
return null;
}
}
else
{
// No, so just check the distance in milliseconds
var distance = SubtitleFormat.FramesToMilliseconds(rightInCueFrame, _frameRate) - SubtitleFormat.FramesToMilliseconds(leftOutCueFrame, _frameRate);
if (distance < Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap)
{
// Chain them
return leftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
}
else
{
// Chaining not needed
return null;
}
}
}
private void FixInCue(int index)
{
FixCue(index, true);
}
private void FixOutCue(int index)
{
FixCue(index, false);
}
private void FixCue(int index, bool isInCue)
{
var paragraph = _subtitle.Paragraphs[index];
var newCueFrame = SubtitleFormat.MillisecondsToFrames(isInCue ? paragraph.StartTime.TotalMilliseconds : paragraph.EndTime.TotalMilliseconds, _frameRate);
// Check if we should do something with shot changes
if (_shotChangesFrames.Count > 0)
{
var bestCueFrameInfo = FindBestCueFrame(newCueFrame, isInCue);
var bestCueFrame = bestCueFrameInfo.cueFrame;
// Check if adjacent subtitle is not in the way
if (isInCue)
{
var previousParagraph = _subtitle.Paragraphs.ElementAtOrDefault(index - 1);
if (previousParagraph != null)
{
var previousOutCueFrame = SubtitleFormat.MillisecondsToFrames(previousParagraph.EndTime.TotalMilliseconds, _frameRate);
newCueFrame = Math.Max(bestCueFrame, previousOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.Gap);
}
else
{
newCueFrame = bestCueFrame;
}
}
else
{
var nextParagraph = _subtitle.Paragraphs.ElementAtOrDefault(index + 1);
if (nextParagraph != null)
{
var nextInCueFrame = SubtitleFormat.MillisecondsToFrames(nextParagraph.StartTime.TotalMilliseconds, _frameRate);
newCueFrame = Math.Min(bestCueFrame, nextInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap);
}
else
{
newCueFrame = bestCueFrame;
}
}
}
// Align and update cue
AlignAndSetCue(paragraph, isInCue, newCueFrame);
}
private (int cueFrame, FindBestCueResult result) FindBestCueFrame(int cueFrame, bool isInCue)
{
var previousShotChange = new List<int> { -1 }.Concat(_shotChangesFrames).Last(x => x <= cueFrame); // will return -1 if none found
var nextShotChange = _shotChangesFrames.Concat(new List<int> { int.MaxValue }).First(x => x >= cueFrame); // will return maxValue if none found
// If both not found, return self
if (previousShotChange < 0 && nextShotChange == int.MaxValue)
{
return (cueFrame, FindBestCueResult.NoShotChangeFound);
}
// Do logic
int previousShotChangeWithGreenZone;
int nextShotChangeWithGreenZone;
bool isInPreviousShotChangeGreenZone;
bool isInPreviousShotChangeRedZone;
bool isInNextShotChangeGreenZone;
bool isInNextShotChangeRedZone;
int previousShotChangeWithGap;
int nextShotChangeWithGap;
if (isInCue)
{
previousShotChangeWithGreenZone = previousShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesRightGreenZone;
nextShotChangeWithGreenZone = nextShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.InCuesLeftGreenZone;
isInPreviousShotChangeGreenZone = cueFrame < previousShotChangeWithGreenZone && cueFrame > (previousShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesRightRedZone);
isInPreviousShotChangeRedZone = cueFrame <= (previousShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesRightRedZone) && cueFrame >= previousShotChange;
isInNextShotChangeGreenZone = cueFrame > nextShotChangeWithGreenZone && cueFrame < (nextShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.InCuesLeftRedZone);
isInNextShotChangeRedZone = cueFrame >= (nextShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.InCuesLeftRedZone) && cueFrame <= nextShotChange;
previousShotChangeWithGap = previousShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap;
nextShotChangeWithGap = nextShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap;
}
else
{
previousShotChangeWithGreenZone = previousShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesRightGreenZone;
nextShotChangeWithGreenZone = nextShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesLeftGreenZone;
isInPreviousShotChangeGreenZone = cueFrame < previousShotChangeWithGreenZone && cueFrame > (previousShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesRightRedZone);
isInPreviousShotChangeRedZone = cueFrame <= (previousShotChange + Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesRightRedZone) && cueFrame >= previousShotChange;
isInNextShotChangeGreenZone = cueFrame > nextShotChangeWithGreenZone && cueFrame < (nextShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesLeftRedZone);
isInNextShotChangeRedZone = cueFrame >= (nextShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesLeftRedZone) && cueFrame <= nextShotChange;
previousShotChangeWithGap = previousShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
nextShotChangeWithGap = nextShotChange - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
}
if (isInPreviousShotChangeRedZone && isInNextShotChangeRedZone)
{
// We are in both red zones! Snap to closest shot change
if (Math.Abs(cueFrame - previousShotChange) <= Math.Abs(cueFrame - nextShotChange))
{
return (previousShotChangeWithGap, FindBestCueResult.SnappedToRedZone);
}
else
{
return (nextShotChangeWithGap, FindBestCueResult.SnappedToRedZone);
}
}
else if (isInPreviousShotChangeGreenZone && isInNextShotChangeGreenZone)
{
// We are in both green zones! Take one with least "violation"
if (Math.Abs(previousShotChangeWithGreenZone - nextShotChange) > Math.Abs(nextShotChangeWithGreenZone - previousShotChange))
{
return (previousShotChangeWithGreenZone, FindBestCueResult.SnappedToRightGreenZone);
}
else
{
return (nextShotChangeWithGreenZone, FindBestCueResult.SnappedToLeftGreenZone);
}
}
else
{
// Other cases... Red zone snapping has priority
if (isInPreviousShotChangeRedZone)
{
// Snap to previous shot change
return (previousShotChangeWithGap, FindBestCueResult.SnappedToRedZone);
}
else if (isInNextShotChangeRedZone)
{
// Snap to next shot change
return (nextShotChangeWithGap, FindBestCueResult.SnappedToRedZone);
}
else if (isInPreviousShotChangeGreenZone)
{
// Enforce green zone from previous shot change, but shouldn't exceed next shot change
return (Math.Min(previousShotChangeWithGreenZone, nextShotChange), FindBestCueResult.SnappedToRightGreenZone);
}
else if (isInNextShotChangeGreenZone)
{
// Enforce green zone from next shot change, but shouldn't exceed previous shot change
return (Math.Max(nextShotChangeWithGreenZone, previousShotChange), FindBestCueResult.SnappedToLeftGreenZone);
}
}
return (cueFrame, FindBestCueResult.NoShotChangeFound);
}
private void AlignAndSetCue(Paragraph paragraph, bool isInCue, int newFrame)
{
double newTime = SubtitleFormat.FramesToMilliseconds(newFrame, _frameRate);
// Check if we have extracted exact time codes
if (_timeCodes.Count > 0)
{
newTime = _timeCodes.Aggregate((x, y) => Math.Abs(x - newTime) < Math.Abs(y - newTime) ? x : y);
}
// Finally, update time
if (isInCue)
{
paragraph.StartTime.TotalMilliseconds = newTime;
}
else
{
paragraph.EndTime.TotalMilliseconds = newTime;
}
// Duration cannot be negative
if (paragraph.DurationTotalMilliseconds < 0)
{
paragraph.EndTime.TotalMilliseconds = paragraph.StartTime.TotalMilliseconds;
}
}
// Helpers
private int? GetFirstShotChangeFrameInBetween(int leftCueFrame, int rightCueFrame)
{
try
{
return _shotChangesFrames.First(x => x >= leftCueFrame && x <= rightCueFrame);
}
catch (InvalidOperationException)
{
return null;
}
}
private int? GetClosestShotChangeFrame(int cueFrame)
{
try
{
return _shotChangesFrames.Aggregate((x, y) => Math.Abs(x - cueFrame) < Math.Abs(y - cueFrame) ? x : y);
}
catch (InvalidOperationException)
{
return null;
}
}
private bool IsCueOnShotChange(int cueFrame, bool isInCue)
{
var closestShotChangeFrame = GetClosestShotChangeFrame(cueFrame);
if (closestShotChangeFrame != null)
{
if (isInCue)
{
return cueFrame >= closestShotChangeFrame.Value && cueFrame <= closestShotChangeFrame.Value + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap;
}
else
{
return cueFrame <= closestShotChangeFrame.Value && cueFrame >= closestShotChangeFrame.Value - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
}
}
else
{
return false;
}
}
// Delegates
public delegate void ProgressChangedDelegate(double progress);
}
public static class TimeCodesBeautifierUtils
{
public static double GetFrameDurationMs(double? frameRate = null)
{
return TimeCode.BaseUnit / (frameRate ?? Configuration.Settings.General.CurrentFrameRate);
}
public static double GetInCuesGapMs(double? frameRate = null)
{
return GetFrameDurationMs(frameRate) * Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap;
}
public static double GetOutCuesGapMs(double? frameRate = null)
{
return GetFrameDurationMs(frameRate) * Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
}
}
}

View File

@ -473,7 +473,12 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
public static int FramesToMilliseconds(double frames)
{
return (int)Math.Round(frames * (TimeCode.BaseUnit / GetFrameForCalculation(Configuration.Settings.General.CurrentFrameRate)), MidpointRounding.AwayFromZero);
return FramesToMilliseconds(frames, Configuration.Settings.General.CurrentFrameRate);
}
public static int FramesToMilliseconds(double frames, double frameRate)
{
return (int)Math.Round(frames * (TimeCode.BaseUnit / GetFrameForCalculation(frameRate)), MidpointRounding.AwayFromZero);
}
public static int FramesToMillisecondsMax999(double frames)

View File

@ -10,6 +10,7 @@ using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Forms;
using Nikse.SubtitleEdit.Core.Forms;
namespace Nikse.SubtitleEdit.Controls
{
@ -129,7 +130,7 @@ namespace Nikse.SubtitleEdit.Controls
public const double ZoomMaximum = 2.5;
private double _zoomFactor = 1.0; // 1.0=no zoom
public const int ShotChangeSnapPixels = 8;
public int ShotChangeSnapPixels = 8;
public double ZoomFactor
{
@ -150,6 +151,7 @@ namespace Nikse.SubtitleEdit.Controls
if (Math.Abs(_zoomFactor - value) > 0.01)
{
_zoomFactor = value;
UpdateSnappingDistance();
Invalidate();
}
}
@ -391,6 +393,8 @@ namespace Nikse.SubtitleEdit.Controls
ShowSpectrogram = true;
ShowWaveform = true;
InsertAtVideoPositionShortcut = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainWaveformInsertAtCurrentPosition);
UpdateSnappingDistance();
}
protected override bool IsInputKey(Keys keyData)
@ -1730,8 +1734,8 @@ namespace Nikse.SubtitleEdit.Controls
{
var nearestShotChange = _shotChanges.Count > 0 ? _shotChanges.Aggregate((x, y) => Math.Abs((x * 1000) - milliseconds) < Math.Abs((y * 1000) - milliseconds) ? x : y) : -9999;
if (Math.Abs(e.X - SecondsToXPosition(nearestShotChange - _startPositionSeconds)) < ShotChangeSnapPixels)
{
_mouseDownParagraph.StartTime.TotalMilliseconds = nearestShotChange * 1000;
{
_mouseDownParagraph.StartTime.TotalMilliseconds = (nearestShotChange * 1000) + TimeCodesBeautifierUtils.GetInCuesGapMs();
}
}
@ -1749,7 +1753,7 @@ namespace Nikse.SubtitleEdit.Controls
var nearestShotChange = _shotChanges.Count > 0 ? _shotChanges.Aggregate((x, y) => Math.Abs((x * 1000) - milliseconds) < Math.Abs((y * 1000) - milliseconds) ? x : y) : -9999;
if (Math.Abs(e.X - SecondsToXPosition(nearestShotChange - _startPositionSeconds)) < ShotChangeSnapPixels)
{
NewSelectionParagraph.StartTime.TotalMilliseconds = nearestShotChange * 1000;
NewSelectionParagraph.StartTime.TotalMilliseconds = (nearestShotChange * 1000) + TimeCodesBeautifierUtils.GetInCuesGapMs();
}
}
@ -1788,7 +1792,7 @@ namespace Nikse.SubtitleEdit.Controls
var nearestShotChange = _shotChanges.Count > 0 ? _shotChanges.Aggregate((x, y) => Math.Abs((x * 1000) - milliseconds) < Math.Abs((y * 1000) - milliseconds) ? x : y) : -9999;
if (Math.Abs(e.X - SecondsToXPosition(nearestShotChange - _startPositionSeconds)) < ShotChangeSnapPixels)
{
_mouseDownParagraph.EndTime.TotalMilliseconds = nearestShotChange * 1000;
_mouseDownParagraph.EndTime.TotalMilliseconds = (nearestShotChange * 1000) - TimeCodesBeautifierUtils.GetOutCuesGapMs();
}
}
@ -1806,7 +1810,7 @@ namespace Nikse.SubtitleEdit.Controls
var nearestShotChange = _shotChanges.Count > 0 ? _shotChanges.Aggregate((x, y) => Math.Abs((x * 1000) - milliseconds) < Math.Abs((y * 1000) - milliseconds) ? x : y) : -9999;
if (Math.Abs(e.X - SecondsToXPosition(nearestShotChange - _startPositionSeconds)) < ShotChangeSnapPixels)
{
NewSelectionParagraph.EndTime.TotalMilliseconds = nearestShotChange * 1000;
NewSelectionParagraph.EndTime.TotalMilliseconds = (nearestShotChange * 1000) - TimeCodesBeautifierUtils.GetOutCuesGapMs();
}
}
@ -1839,13 +1843,15 @@ namespace Nikse.SubtitleEdit.Controls
if (Math.Abs(SecondsToXPosition(_mouseDownParagraph.StartTime.TotalSeconds - _startPositionSeconds) - SecondsToXPosition(nearestShotChangeInFront - _startPositionSeconds)) < ShotChangeSnapPixels)
{
_mouseDownParagraph.StartTime.TotalMilliseconds = nearestShotChangeInFront * 1000;
_mouseDownParagraph.EndTime.TotalMilliseconds = (nearestShotChangeInFront * 1000) + durationMilliseconds;
var nearestShotChangeInFrontMs = (nearestShotChangeInFront * 1000) + TimeCodesBeautifierUtils.GetInCuesGapMs();
_mouseDownParagraph.StartTime.TotalMilliseconds = nearestShotChangeInFrontMs;
_mouseDownParagraph.EndTime.TotalMilliseconds = nearestShotChangeInFrontMs + durationMilliseconds;
}
else if (Math.Abs(SecondsToXPosition(_mouseDownParagraph.EndTime.TotalSeconds - _startPositionSeconds) - SecondsToXPosition(nearestShotChangeInBack - _startPositionSeconds)) < ShotChangeSnapPixels)
{
_mouseDownParagraph.EndTime.TotalMilliseconds = nearestShotChangeInBack * 1000;
_mouseDownParagraph.StartTime.TotalMilliseconds = (nearestShotChangeInBack * 1000) - durationMilliseconds;
var nearestShotChangeInBackMs = (nearestShotChangeInBack * 1000) - TimeCodesBeautifierUtils.GetOutCuesGapMs();
_mouseDownParagraph.EndTime.TotalMilliseconds = nearestShotChangeInBackMs;
_mouseDownParagraph.StartTime.TotalMilliseconds = nearestShotChangeInBackMs - durationMilliseconds;
}
}
@ -1901,12 +1907,12 @@ namespace Nikse.SubtitleEdit.Controls
if (Math.Abs(SecondsToXPosition(NewSelectionParagraph.StartTime.TotalSeconds - _startPositionSeconds) - SecondsToXPosition(nearestShotChangeInFront - _startPositionSeconds)) < ShotChangeSnapPixels)
{
NewSelectionParagraph.StartTime.TotalMilliseconds = nearestShotChangeInFront * 1000;
NewSelectionParagraph.StartTime.TotalMilliseconds = (nearestShotChangeInFront * 1000) + TimeCodesBeautifierUtils.GetInCuesGapMs();
Invalidate();
}
if (Math.Abs(SecondsToXPosition(NewSelectionParagraph.EndTime.TotalSeconds - _startPositionSeconds) - SecondsToXPosition(nearestShotChangeInBack - _startPositionSeconds)) < ShotChangeSnapPixels)
{
NewSelectionParagraph.EndTime.TotalMilliseconds = nearestShotChangeInBack * 1000;
NewSelectionParagraph.EndTime.TotalMilliseconds = (nearestShotChangeInBack * 1000) - TimeCodesBeautifierUtils.GetOutCuesGapMs();
Invalidate();
}
}
@ -2718,5 +2724,21 @@ namespace Nikse.SubtitleEdit.Controls
return -1;
}
private void UpdateSnappingDistance()
{
if (_wavePeaks != null)
{
var largestGapInFrames = Math.Max(Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap, Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap);
var pixelsPerFrame = (_wavePeaks.SampleRate * _zoomFactor) / Configuration.Settings.General.CurrentFrameRate;
var snappingDistance = (int) Math.Round(pixelsPerFrame * Math.Max(1, largestGapInFrames));
ShotChangeSnapPixels = Math.Max(8, snappingDistance);
}
else
{
ShotChangeSnapPixels = 8;
}
}
}
}

View File

@ -0,0 +1,151 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using Nikse.SubtitleEdit.Core.Common;
using Nikse.SubtitleEdit.Logic;
namespace Nikse.SubtitleEdit.Controls
{
public sealed class CuesPreviewView : Panel
{
private float _frameRate = 25f;
private string _previewText = "Subtitle text.";
private bool _showShotChange = true;
private int _leftGap = 0;
private int _leftRedZone = 7;
private int _leftGreenZone = 12;
private int _rightGap = 0;
private int _rightRedZone = 7;
private int _rightGreenZone = 12;
public float FrameRate
{
get => _frameRate;
set { _frameRate = value; Invalidate(); }
}
public string PreviewText
{
get => _previewText;
set { _previewText = value; Invalidate(); }
}
public bool ShowShotChange
{
get => _showShotChange;
set { _showShotChange = value; Invalidate(); }
}
public int LeftGap
{
get => _leftGap;
set { _leftGap = value; Invalidate(); }
}
public int LeftRedZone
{
get => _leftRedZone;
set { _leftRedZone = value; Invalidate(); }
}
public int LeftGreenZone
{
get => _leftGreenZone;
set { _leftGreenZone = value; Invalidate(); }
}
public int RightGap
{
get => _rightGap;
set { _rightGap = value; Invalidate(); }
}
public int RightRedZone
{
get => _rightRedZone;
set { _rightRedZone = value; Invalidate(); }
}
public int RightGreenZone
{
get => _rightGreenZone;
set { _rightGreenZone = value; Invalidate(); }
}
public CuesPreviewView()
{
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (var brush = new SolidBrush(Color.White))
{
float width = this.Size.Width;
float height = this.Size.Height;
// Background
brush.Color = Color.Gray;
e.Graphics.FillRectangle(brush, 0, 0, width, height);
// Green zones
brush.Color = Color.Green;
e.Graphics.FillRectangle(brush, (width / 2) - FramesToPixels(this.LeftGreenZone), 0, FramesToPixels(this.LeftGreenZone), height);
e.Graphics.FillRectangle(brush, width / 2, 0, FramesToPixels(this.RightGreenZone), height);
// Red zone
brush.Color = Color.Firebrick;
e.Graphics.FillRectangle(brush, (width / 2) - FramesToPixels(this.LeftRedZone), 0, FramesToPixels(this.LeftRedZone), height);
e.Graphics.FillRectangle(brush, width / 2, 0, FramesToPixels(this.RightRedZone), height);
// Subtitle
brush.Color = Color.FromArgb(153, 0, 0, 0);
e.Graphics.FillRectangle(brush, 0, 0, (width / 2) - FramesToPixels(this.LeftGap), height);
e.Graphics.FillRectangle(brush, (width / 2) + FramesToPixels(this.RightGap), 0, (width / 2) - FramesToPixels(this.RightGap), height);
brush.Color = Color.White;
if (this.LeftGap <= 12)
{
e.Graphics.DrawString(GetSubtitleLabel(1000, GetLeftOutCue()), UiUtil.GetDefaultFont(), brush, new RectangleF(5, 5, (width / 2) - FramesToPixels(this.LeftGap) - 10, height - 10));
}
if (this.RightGap <= 12)
{
e.Graphics.DrawString(GetSubtitleLabel(GetRightInCue(), 5000), UiUtil.GetDefaultFont(), brush, new RectangleF((width / 2) + FramesToPixels(this.RightGap) + 5, 5, (width / 2) - FramesToPixels(this.RightGap) - 10, height - 10));
}
// Shot change
if (this.ShowShotChange)
{
brush.Color = Color.PaleGreen;
e.Graphics.FillRectangle(brush, (width / 2) - (1.5f), 0, 3f, height);
}
}
}
private float FramesToPixels(float frames)
{
return (Size.Width / (this.FrameRate * 3)) * frames;
}
private double GetLeftOutCue()
{
return 3000 - (this.LeftGap * (1000 / this.FrameRate));
}
private double GetRightInCue()
{
return 3000 + (this.RightGap * (1000 / this.FrameRate));
}
private string GetSubtitleLabel(double start, double end)
{
var timeCodeStart = new TimeCode(start);
var timeCodeEnd = new TimeCode(end);
return timeCodeStart.ToString() + " --> " + timeCodeEnd.ToString() + Environment.NewLine + this.PreviewText;
}
}
}

View File

@ -48,6 +48,8 @@
this.labelMillisecondsFixed = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.checkBoxExtendOnly = new System.Windows.Forms.CheckBox();
this.checkBoxCheckShotChanges = new System.Windows.Forms.CheckBox();
this.checkBoxEnforceDurationLimits = new System.Windows.Forms.CheckBox();
this.groupBoxAdjustVia.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownMaxCharsSec)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownSeconds)).BeginInit();
@ -119,8 +121,10 @@
//
// labelNote
//
this.labelNote.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.labelNote.AutoSize = true;
this.labelNote.Location = new System.Drawing.Point(10, 211);
this.labelNote.ForeColor = System.Drawing.SystemColors.ControlDarkDark;
this.labelNote.Location = new System.Drawing.Point(10, 275);
this.labelNote.Name = "labelNote";
this.labelNote.Size = new System.Drawing.Size(279, 13);
this.labelNote.TabIndex = 7;
@ -149,7 +153,7 @@
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonCancel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.buttonCancel.Location = new System.Drawing.Point(537, 231);
this.buttonCancel.Location = new System.Drawing.Point(537, 270);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 21;
@ -160,7 +164,7 @@
//
this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonOK.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.buttonOK.Location = new System.Drawing.Point(456, 231);
this.buttonOK.Location = new System.Drawing.Point(456, 270);
this.buttonOK.Name = "buttonOK";
this.buttonOK.Size = new System.Drawing.Size(75, 23);
this.buttonOK.TabIndex = 20;
@ -330,11 +334,35 @@
this.checkBoxExtendOnly.Text = "Extend only";
this.checkBoxExtendOnly.UseVisualStyleBackColor = true;
//
// checkBoxCheckShotChanges
//
this.checkBoxCheckShotChanges.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.checkBoxCheckShotChanges.AutoSize = true;
this.checkBoxCheckShotChanges.Location = new System.Drawing.Point(12, 247);
this.checkBoxCheckShotChanges.Name = "checkBoxCheckShotChanges";
this.checkBoxCheckShotChanges.Size = new System.Drawing.Size(122, 17);
this.checkBoxCheckShotChanges.TabIndex = 19;
this.checkBoxCheckShotChanges.Text = "Check shot changes";
this.checkBoxCheckShotChanges.UseVisualStyleBackColor = true;
//
// checkBoxEnforceDurationLimits
//
this.checkBoxEnforceDurationLimits.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.checkBoxEnforceDurationLimits.AutoSize = true;
this.checkBoxEnforceDurationLimits.Location = new System.Drawing.Point(12, 224);
this.checkBoxEnforceDurationLimits.Name = "checkBoxEnforceDurationLimits";
this.checkBoxEnforceDurationLimits.Size = new System.Drawing.Size(217, 17);
this.checkBoxEnforceDurationLimits.TabIndex = 18;
this.checkBoxEnforceDurationLimits.Text = "Enforce minimum and maximum duration";
this.checkBoxEnforceDurationLimits.UseVisualStyleBackColor = true;
//
// AdjustDisplayDuration
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(624, 268);
this.ClientSize = new System.Drawing.Size(624, 307);
this.Controls.Add(this.checkBoxEnforceDurationLimits);
this.Controls.Add(this.checkBoxCheckShotChanges);
this.Controls.Add(this.checkBoxExtendOnly);
this.Controls.Add(this.label1);
this.Controls.Add(this.numericUpDownFixedMilliseconds);
@ -395,5 +423,7 @@
private System.Windows.Forms.Label labelMillisecondsFixed;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.CheckBox checkBoxExtendOnly;
private System.Windows.Forms.CheckBox checkBoxCheckShotChanges;
private System.Windows.Forms.CheckBox checkBoxEnforceDurationLimits;
}
}

View File

@ -45,6 +45,10 @@ namespace Nikse.SubtitleEdit.Forms
public bool ExtendOnly => checkBoxExtendOnly.Checked;
public bool EnforceDurationLimits => checkBoxEnforceDurationLimits.Checked;
public bool CheckShotChanges => checkBoxCheckShotChanges.Checked;
public AdjustDisplayDuration(bool recalcActive = true)
{
UiUtil.PreInitialize(this);
@ -71,6 +75,8 @@ namespace Nikse.SubtitleEdit.Forms
numericUpDownMaxCharsSec.Value = (decimal)Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds;
checkBoxExtendOnly.Checked = Configuration.Settings.Tools.AdjustDurationExtendOnly;
checkBoxEnforceDurationLimits.Checked = Configuration.Settings.Tools.AdjustDurationExtendEnforceDurationLimits;
checkBoxCheckShotChanges.Checked = Configuration.Settings.Tools.AdjustDurationExtendCheckShotChanges;
LanguageStructure.AdjustDisplayDuration language = LanguageSettings.Current.AdjustDisplayDuration;
Text = language.Title;
@ -86,6 +92,8 @@ namespace Nikse.SubtitleEdit.Forms
radioButtonFixed.Text = language.Fixed;
labelMillisecondsFixed.Text = language.Milliseconds;
checkBoxExtendOnly.Text = language.ExtendOnly;
checkBoxEnforceDurationLimits.Text = language.EnforceDurationLimits;
checkBoxCheckShotChanges.Text = language.CheckShotChanges;
buttonOK.Text = LanguageSettings.Current.General.Ok;
buttonCancel.Text = LanguageSettings.Current.General.Cancel;
FixLargeFonts();
@ -161,6 +169,8 @@ namespace Nikse.SubtitleEdit.Forms
Configuration.Settings.Tools.AdjustDurationSeconds = numericUpDownSeconds.Value;
Configuration.Settings.Tools.AdjustDurationPercent = (int)numericUpDownPercent.Value;
Configuration.Settings.Tools.AdjustDurationExtendOnly = checkBoxExtendOnly.Checked;
Configuration.Settings.Tools.AdjustDurationExtendEnforceDurationLimits = checkBoxEnforceDurationLimits.Checked;
Configuration.Settings.Tools.AdjustDurationExtendCheckShotChanges = checkBoxCheckShotChanges.Checked;
if (radioButtonSeconds.Checked)
{

View File

@ -40,23 +40,24 @@
this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.toolStripMenuItemSelectAll = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItemInverseSelection = new System.Windows.Forms.ToolStripMenuItem();
this.groupBoxUnfixable = new System.Windows.Forms.GroupBox();
this.subtitleListView1 = new Nikse.SubtitleEdit.Controls.SubtitleListView();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.checkBoxMinDuration = new System.Windows.Forms.CheckBox();
this.checkBoxMaxDuration = new System.Windows.Forms.CheckBox();
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.toolStripMenuItemSelectAll = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItemInverseSelection = new System.Windows.Forms.ToolStripMenuItem();
this.checkBoxCheckShotChanges = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownDurationMax)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownDurationMin)).BeginInit();
this.groupBoxFixesAvailable.SuspendLayout();
this.contextMenuStrip1.SuspendLayout();
this.groupBoxUnfixable.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
this.contextMenuStrip1.SuspendLayout();
this.SuspendLayout();
//
// numericUpDownDurationMax
@ -74,7 +75,7 @@
0});
this.numericUpDownDurationMax.Name = "numericUpDownDurationMax";
this.numericUpDownDurationMax.Size = new System.Drawing.Size(56, 20);
this.numericUpDownDurationMax.TabIndex = 4;
this.numericUpDownDurationMax.TabIndex = 5;
this.numericUpDownDurationMax.Value = new decimal(new int[] {
50000,
0,
@ -149,8 +150,8 @@
this.groupBoxFixesAvailable.Dock = System.Windows.Forms.DockStyle.Fill;
this.groupBoxFixesAvailable.Location = new System.Drawing.Point(0, 0);
this.groupBoxFixesAvailable.Name = "groupBoxFixesAvailable";
this.groupBoxFixesAvailable.Size = new System.Drawing.Size(931, 302);
this.groupBoxFixesAvailable.TabIndex = 5;
this.groupBoxFixesAvailable.Size = new System.Drawing.Size(931, 292);
this.groupBoxFixesAvailable.TabIndex = 6;
this.groupBoxFixesAvailable.TabStop = false;
this.groupBoxFixesAvailable.Text = "Fixes available: {0}";
//
@ -170,7 +171,7 @@
this.listViewFixes.HideSelection = false;
this.listViewFixes.Location = new System.Drawing.Point(6, 23);
this.listViewFixes.Name = "listViewFixes";
this.listViewFixes.Size = new System.Drawing.Size(919, 273);
this.listViewFixes.Size = new System.Drawing.Size(919, 262);
this.listViewFixes.TabIndex = 6;
this.listViewFixes.UseCompatibleStateImageBehavior = false;
this.listViewFixes.View = System.Windows.Forms.View.Details;
@ -196,13 +197,35 @@
this.columnHeader8.Text = "After";
this.columnHeader8.Width = 390;
//
// contextMenuStrip1
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItemSelectAll,
this.toolStripMenuItemInverseSelection});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(162, 48);
//
// toolStripMenuItemSelectAll
//
this.toolStripMenuItemSelectAll.Name = "toolStripMenuItemSelectAll";
this.toolStripMenuItemSelectAll.Size = new System.Drawing.Size(161, 22);
this.toolStripMenuItemSelectAll.Text = "Select all";
this.toolStripMenuItemSelectAll.Click += new System.EventHandler(this.toolStripMenuItemSelectAll_Click);
//
// toolStripMenuItemInverseSelection
//
this.toolStripMenuItemInverseSelection.Name = "toolStripMenuItemInverseSelection";
this.toolStripMenuItemInverseSelection.Size = new System.Drawing.Size(161, 22);
this.toolStripMenuItemInverseSelection.Text = "Inverse selection";
this.toolStripMenuItemInverseSelection.Click += new System.EventHandler(this.toolStripMenuItemInverseSelection_Click);
//
// groupBoxUnfixable
//
this.groupBoxUnfixable.Controls.Add(this.subtitleListView1);
this.groupBoxUnfixable.Dock = System.Windows.Forms.DockStyle.Fill;
this.groupBoxUnfixable.Location = new System.Drawing.Point(0, 0);
this.groupBoxUnfixable.Name = "groupBoxUnfixable";
this.groupBoxUnfixable.Size = new System.Drawing.Size(931, 154);
this.groupBoxUnfixable.Size = new System.Drawing.Size(931, 164);
this.groupBoxUnfixable.TabIndex = 51;
this.groupBoxUnfixable.TabStop = false;
this.groupBoxUnfixable.Text = "Unable to fix min duration: {0}";
@ -222,7 +245,7 @@
this.subtitleListView1.Location = new System.Drawing.Point(6, 19);
this.subtitleListView1.Name = "subtitleListView1";
this.subtitleListView1.OwnerDraw = true;
this.subtitleListView1.Size = new System.Drawing.Size(919, 129);
this.subtitleListView1.Size = new System.Drawing.Size(919, 124);
this.subtitleListView1.SubtitleFontBold = false;
this.subtitleListView1.SubtitleFontName = "Tahoma";
this.subtitleListView1.SubtitleFontSize = 8;
@ -250,7 +273,7 @@
this.splitContainer1.Panel2.Controls.Add(this.groupBoxUnfixable);
this.splitContainer1.Panel2MinSize = 100;
this.splitContainer1.Size = new System.Drawing.Size(931, 460);
this.splitContainer1.SplitterDistance = 302;
this.splitContainer1.SplitterDistance = 292;
this.splitContainer1.TabIndex = 54;
this.splitContainer1.TabStop = false;
//
@ -271,38 +294,28 @@
this.checkBoxMaxDuration.Location = new System.Drawing.Point(16, 39);
this.checkBoxMaxDuration.Name = "checkBoxMaxDuration";
this.checkBoxMaxDuration.Size = new System.Drawing.Size(152, 17);
this.checkBoxMaxDuration.TabIndex = 3;
this.checkBoxMaxDuration.TabIndex = 4;
this.checkBoxMaxDuration.Text = "Max. duration, milliseconds";
this.checkBoxMaxDuration.UseVisualStyleBackColor = true;
this.checkBoxMaxDuration.CheckedChanged += new System.EventHandler(this.checkBoxMaxDuration_CheckedChanged);
//
// contextMenuStrip1
// checkBoxCheckShotChanges
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItemSelectAll,
this.toolStripMenuItemInverseSelection});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(181, 70);
//
// toolStripMenuItemSelectAll
//
this.toolStripMenuItemSelectAll.Name = "toolStripMenuItemSelectAll";
this.toolStripMenuItemSelectAll.Size = new System.Drawing.Size(180, 22);
this.toolStripMenuItemSelectAll.Text = "Select all";
this.toolStripMenuItemSelectAll.Click += new System.EventHandler(this.toolStripMenuItemSelectAll_Click);
//
// toolStripMenuItemInverseSelection
//
this.toolStripMenuItemInverseSelection.Name = "toolStripMenuItemInverseSelection";
this.toolStripMenuItemInverseSelection.Size = new System.Drawing.Size(180, 22);
this.toolStripMenuItemInverseSelection.Text = "Inverse selection";
this.toolStripMenuItemInverseSelection.Click += new System.EventHandler(this.toolStripMenuItemInverseSelection_Click);
this.checkBoxCheckShotChanges.AutoSize = true;
this.checkBoxCheckShotChanges.Location = new System.Drawing.Point(269, 13);
this.checkBoxCheckShotChanges.Name = "checkBoxCheckShotChanges";
this.checkBoxCheckShotChanges.Size = new System.Drawing.Size(124, 17);
this.checkBoxCheckShotChanges.TabIndex = 3;
this.checkBoxCheckShotChanges.Text = "Check shot changes";
this.checkBoxCheckShotChanges.UseVisualStyleBackColor = true;
this.checkBoxCheckShotChanges.CheckedChanged += new System.EventHandler(this.checkBoxCheckShotChanges_CheckedChanged);
//
// ApplyDurationLimits
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(961, 571);
this.Controls.Add(this.checkBoxCheckShotChanges);
this.Controls.Add(this.checkBoxMaxDuration);
this.Controls.Add(this.checkBoxMinDuration);
this.Controls.Add(this.splitContainer1);
@ -320,18 +333,18 @@
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Apply duration limits";
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ApplyDurationLimits_KeyDown);
this.ResizeEnd += new System.EventHandler(this.ApplyDurationLimits_ResizeEnd);
this.Shown += new System.EventHandler(this.ApplyDurationLimits_Shown);
this.ResizeEnd += new System.EventHandler(this.ApplyDurationLimits_ResizeEnd);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ApplyDurationLimits_KeyDown);
((System.ComponentModel.ISupportInitialize)(this.numericUpDownDurationMax)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownDurationMin)).EndInit();
this.groupBoxFixesAvailable.ResumeLayout(false);
this.contextMenuStrip1.ResumeLayout(false);
this.groupBoxUnfixable.ResumeLayout(false);
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
this.splitContainer1.ResumeLayout(false);
this.contextMenuStrip1.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
@ -357,5 +370,6 @@
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemSelectAll;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemInverseSelection;
private System.Windows.Forms.CheckBox checkBoxCheckShotChanges;
}
}

View File

@ -1,7 +1,9 @@
using Nikse.SubtitleEdit.Core.Common;
using Nikse.SubtitleEdit.Logic;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace Nikse.SubtitleEdit.Forms
@ -16,6 +18,7 @@ namespace Nikse.SubtitleEdit.Forms
private readonly Timer _refreshTimer = new Timer();
private readonly Color _warningColor = Color.FromArgb(255, 253, 145);
private Subtitle _unfixables = new Subtitle();
private List<double> _shotChanges = new List<double>();
public ApplyDurationLimits()
{
@ -25,8 +28,10 @@ namespace Nikse.SubtitleEdit.Forms
Text = LanguageSettings.Current.ApplyDurationLimits.Title;
checkBoxMinDuration.Text = LanguageSettings.Current.Settings.DurationMinimumMilliseconds;
checkBoxMaxDuration.Text = LanguageSettings.Current.Settings.DurationMaximumMilliseconds;
checkBoxCheckShotChanges.Text = LanguageSettings.Current.ApplyDurationLimits.CheckShotChanges;
checkBoxMinDuration.Checked = Configuration.Settings.Tools.ApplyMinimumDurationLimit;
checkBoxMaxDuration.Checked = Configuration.Settings.Tools.ApplyMaximumDurationLimit;
checkBoxCheckShotChanges.Checked = Configuration.Settings.Tools.ApplyMinimumDurationLimitCheckShotChanges;
labelNote.Text = LanguageSettings.Current.AdjustDisplayDuration.Note;
numericUpDownDurationMin.Value = Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds;
numericUpDownDurationMax.Value = Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds;
@ -48,6 +53,8 @@ namespace Nikse.SubtitleEdit.Forms
numericUpDownDurationMin.Left = Math.Max(numericUpDownDurationMin.Left, numericUpDownDurationMax.Left);
numericUpDownDurationMax.Left = Math.Max(numericUpDownDurationMin.Left, numericUpDownDurationMax.Left);
}
checkBoxCheckShotChanges.Left = numericUpDownDurationMin.Left + numericUpDownDurationMin.Width + 16;
FixLargeFonts();
_refreshTimer.Interval = 400;
_refreshTimer.Tick += RefreshTimerTick;
@ -70,9 +77,20 @@ namespace Nikse.SubtitleEdit.Forms
UiUtil.FixLargeFonts(this, buttonOK);
}
public void Initialize(Subtitle subtitle)
public void Initialize(Subtitle subtitle, List<double> shotChanges = null)
{
_subtitle = subtitle;
if (shotChanges != null)
{
_shotChanges = shotChanges;
checkBoxCheckShotChanges.Enabled = true;
}
else
{
checkBoxCheckShotChanges.Enabled = false;
}
GeneratePreview();
}
@ -150,16 +168,29 @@ namespace Nikse.SubtitleEdit.Forms
{
var next = _working.GetParagraphOrDefault(i + 1);
var wantedEndMs = p.StartTime.TotalMilliseconds + minDisplayTime;
if (next == null || wantedEndMs < next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines)
var bestEndMs = double.MaxValue;
// First check for next subtitle
if (next != null)
{
bestEndMs = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
}
// Then check for next shot change (if option is checked, and if any are supplied) -- keeping earliest time
if (checkBoxCheckShotChanges.Checked && _shotChanges.Count > 0)
{
bestEndMs = Math.Min(bestEndMs, ShotChangeHelper.GetNextShotChangeMinusGapInMs(_shotChanges, p.EndTime) ?? double.MaxValue);
}
if (wantedEndMs <= bestEndMs)
{
AddFix(p, wantedEndMs, DefaultBackColor);
}
else
{
var nextBestEndMs = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
if (nextBestEndMs > p.EndTime.TotalMilliseconds)
if (bestEndMs > p.EndTime.TotalMilliseconds)
{
AddFix(p, nextBestEndMs, _warningColor);
AddFix(p, bestEndMs, _warningColor);
_unfixables.Paragraphs.Add(new Paragraph(p) { Extra = "Warning" });
}
else
@ -228,6 +259,7 @@ namespace Nikse.SubtitleEdit.Forms
{
Configuration.Settings.Tools.ApplyMinimumDurationLimit = checkBoxMinDuration.Checked;
Configuration.Settings.Tools.ApplyMaximumDurationLimit = checkBoxMaxDuration.Checked;
Configuration.Settings.Tools.ApplyMinimumDurationLimitCheckShotChanges = checkBoxCheckShotChanges.Checked;
_onlyListFixes = false;
_working = new Subtitle(_subtitle);
@ -322,5 +354,10 @@ namespace Nikse.SubtitleEdit.Forms
item.Checked = !item.Checked;
}
}
private void checkBoxCheckShotChanges_CheckedChanged(object sender, EventArgs e)
{
GeneratePreview();
}
}
}
}

View File

@ -172,6 +172,7 @@ namespace Nikse.SubtitleEdit.Forms
this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.labelStatus = new System.Windows.Forms.Label();
this.labelError = new System.Windows.Forms.Label();
this.checkBoxEnforceDurationLimits = new System.Windows.Forms.CheckBox();
this.groupBoxConvertOptions.SuspendLayout();
this.contextMenuStripOptions.SuspendLayout();
this.groupBoxChangeCasing.SuspendLayout();
@ -237,10 +238,10 @@ namespace Nikse.SubtitleEdit.Forms
//
this.groupBoxConvertOptions.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBoxConvertOptions.Controls.Add(this.groupBoxAdjustDuration);
this.groupBoxConvertOptions.Controls.Add(this.listViewConvertOptions);
this.groupBoxConvertOptions.Controls.Add(this.groupBoxChangeCasing);
this.groupBoxConvertOptions.Controls.Add(this.groupBoxMergeShortLines);
this.groupBoxConvertOptions.Controls.Add(this.groupBoxAdjustDuration);
this.groupBoxConvertOptions.Controls.Add(this.buttonConvertOptionsSettings);
this.groupBoxConvertOptions.Controls.Add(this.groupBoxAssaChangeRes);
this.groupBoxConvertOptions.Controls.Add(this.groupBoxSortBy);
@ -502,6 +503,7 @@ namespace Nikse.SubtitleEdit.Forms
//
// groupBoxAdjustDuration
//
this.groupBoxAdjustDuration.Controls.Add(this.checkBoxEnforceDurationLimits);
this.groupBoxAdjustDuration.Controls.Add(this.comboBoxAdjustDurationVia);
this.groupBoxAdjustDuration.Controls.Add(this.labelAdjustDurationVia);
this.groupBoxAdjustDuration.Controls.Add(this.panelAdjustDurationFixed);
@ -1706,7 +1708,7 @@ namespace Nikse.SubtitleEdit.Forms
this.toolStripMenuItemOcrEngine,
this.alsoScanVideoFilesInSearchFolderslowToolStripMenuItem});
this.contextMenuStripFiles.Name = "contextMenuStripStyles";
this.contextMenuStripFiles.Size = new System.Drawing.Size(400, 192);
this.contextMenuStripFiles.Size = new System.Drawing.Size(400, 170);
this.contextMenuStripFiles.Opening += new System.ComponentModel.CancelEventHandler(this.ContextMenuStripFilesOpening);
//
// addFilesToolStripMenuItem
@ -1801,6 +1803,16 @@ namespace Nikse.SubtitleEdit.Forms
this.labelError.TabIndex = 10;
this.labelError.Text = "labelError";
//
// checkBoxEnforceDurationLimits
//
this.checkBoxEnforceDurationLimits.AutoSize = true;
this.checkBoxEnforceDurationLimits.Location = new System.Drawing.Point(10, 222);
this.checkBoxEnforceDurationLimits.Name = "checkBoxEnforceDurationLimits";
this.checkBoxEnforceDurationLimits.Size = new System.Drawing.Size(214, 17);
this.checkBoxEnforceDurationLimits.TabIndex = 17;
this.checkBoxEnforceDurationLimits.Text = "Enforce minimum and maximum duration";
this.checkBoxEnforceDurationLimits.UseVisualStyleBackColor = true;
//
// BatchConvert
//
this.AllowDrop = true;
@ -2023,5 +2035,6 @@ namespace Nikse.SubtitleEdit.Forms
private System.Windows.Forms.RadioButton radioButtonProperCase;
private System.Windows.Forms.CheckBox checkBoxProperCaseOnlyUpper;
private System.Windows.Forms.ToolStripMenuItem alsoScanVideoFilesInSearchFolderslowToolStripMenuItem;
private System.Windows.Forms.CheckBox checkBoxEnforceDurationLimits;
}
}

View File

@ -378,12 +378,14 @@ namespace Nikse.SubtitleEdit.Forms
numericUpDownOptimalCharsSec.Value = (decimal)Configuration.Settings.General.SubtitleOptimalCharactersPerSeconds;
numericUpDownMaxCharsSec.Value = (decimal)Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds;
checkBoxExtendOnly.Checked = Configuration.Settings.Tools.AdjustDurationExtendOnly;
checkBoxEnforceDurationLimits.Checked = Configuration.Settings.Tools.AdjustDurationExtendEnforceDurationLimits;
labelOptimalCharsSec.Text = LanguageSettings.Current.Settings.OptimalCharactersPerSecond;
labelMaxCharsPerSecond.Text = LanguageSettings.Current.Settings.MaximumCharactersPerSecond;
labelAddSeconds.Text = LanguageSettings.Current.AdjustDisplayDuration.AddSeconds;
labelMillisecondsFixed.Text = LanguageSettings.Current.AdjustDisplayDuration.Milliseconds;
checkBoxExtendOnly.Text = LanguageSettings.Current.AdjustDisplayDuration.ExtendOnly;
checkBoxEnforceDurationLimits.Text = LanguageSettings.Current.AdjustDisplayDuration.EnforceDurationLimits;
labelAdjustViaPercent.Text = LanguageSettings.Current.AdjustDisplayDuration.SetAsPercent;
labelTargetRes.Text = LanguageSettings.Current.AssaResolutionChanger.TargetVideoRes;
@ -1982,14 +1984,15 @@ namespace Nikse.SubtitleEdit.Forms
if (IsActionEnabled(CommandLineConverter.BatchAction.AdjustDisplayDuration))
{
// TODO shot changes
var adjustmentType = comboBoxAdjustDurationVia.Text;
if (adjustmentType == LanguageSettings.Current.AdjustDisplayDuration.Percent)
{
sub.AdjustDisplayTimeUsingPercent((double)numericUpDownAdjustViaPercent.Value, null);
sub.AdjustDisplayTimeUsingPercent((double)numericUpDownAdjustViaPercent.Value, null, null, checkBoxEnforceDurationLimits.Checked);
}
else if (adjustmentType == LanguageSettings.Current.AdjustDisplayDuration.Recalculate)
{
sub.RecalculateDisplayTimes((double)numericUpDownMaxCharsSec.Value, null, (double)numericUpDownOptimalCharsSec.Value, checkBoxExtendOnly.Checked);
sub.RecalculateDisplayTimes((double)numericUpDownMaxCharsSec.Value, null, (double)numericUpDownOptimalCharsSec.Value, checkBoxExtendOnly.Checked, null, checkBoxEnforceDurationLimits.Checked);
}
else if (adjustmentType == LanguageSettings.Current.AdjustDisplayDuration.Fixed)
{
@ -1997,7 +2000,7 @@ namespace Nikse.SubtitleEdit.Forms
}
else
{
sub.AdjustDisplayTimeUsingSeconds((double)numericUpDownSeconds.Value, null);
sub.AdjustDisplayTimeUsingSeconds((double)numericUpDownSeconds.Value, null, null, checkBoxEnforceDurationLimits.Checked);
}
}
@ -3718,6 +3721,8 @@ namespace Nikse.SubtitleEdit.Forms
panel.Visible = true;
panel.Left = 2;
panel.Top = labelAdjustDurationVia.Top + labelAdjustDurationVia.Height + 9;
checkBoxEnforceDurationLimits.Visible = panel != panelAdjustDurationFixed;
}
private void addFilesToolStripMenuItem_Click(object sender, EventArgs e)

View File

@ -0,0 +1,323 @@

namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
{
partial class BeautifyTimeCodes
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.buttonOK = new System.Windows.Forms.Button();
this.buttonCancel = new System.Windows.Forms.Button();
this.groupBoxTimeCodes = new System.Windows.Forms.GroupBox();
this.checkBoxAlignTimeCodes = new System.Windows.Forms.CheckBox();
this.panelTimeCodes = new System.Windows.Forms.Panel();
this.checkBoxExtractExactTimeCodes = new System.Windows.Forms.CheckBox();
this.panelExtractTimeCodes = new System.Windows.Forms.Panel();
this.buttonCancelTimeCodes = new System.Windows.Forms.Button();
this.labelExtractTimeCodesProgress = new System.Windows.Forms.Label();
this.progressBarExtractTimeCodes = new System.Windows.Forms.ProgressBar();
this.buttonExtractTimeCodes = new System.Windows.Forms.Button();
this.labelTimeCodesStatus = new System.Windows.Forms.Label();
this.groupBoxShotChanges = new System.Windows.Forms.GroupBox();
this.checkBoxSnapToShotChanges = new System.Windows.Forms.CheckBox();
this.panelShotChanges = new System.Windows.Forms.Panel();
this.buttonImportShotChanges = new System.Windows.Forms.Button();
this.labelShotChangesStatus = new System.Windows.Forms.Label();
this.buttonEditProfile = new System.Windows.Forms.Button();
this.progressBar = new System.Windows.Forms.ProgressBar();
this.groupBoxTimeCodes.SuspendLayout();
this.panelTimeCodes.SuspendLayout();
this.panelExtractTimeCodes.SuspendLayout();
this.groupBoxShotChanges.SuspendLayout();
this.panelShotChanges.SuspendLayout();
this.SuspendLayout();
//
// buttonOK
//
this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonOK.Location = new System.Drawing.Point(415, 350);
this.buttonOK.Name = "buttonOK";
this.buttonOK.Size = new System.Drawing.Size(75, 23);
this.buttonOK.TabIndex = 30;
this.buttonOK.Text = "OK";
this.buttonOK.UseVisualStyleBackColor = true;
this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
//
// buttonCancel
//
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonCancel.Location = new System.Drawing.Point(496, 350);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 31;
this.buttonCancel.Text = "Cancel";
this.buttonCancel.UseVisualStyleBackColor = true;
//
// groupBoxTimeCodes
//
this.groupBoxTimeCodes.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBoxTimeCodes.Controls.Add(this.checkBoxAlignTimeCodes);
this.groupBoxTimeCodes.Controls.Add(this.panelTimeCodes);
this.groupBoxTimeCodes.Location = new System.Drawing.Point(12, 12);
this.groupBoxTimeCodes.Name = "groupBoxTimeCodes";
this.groupBoxTimeCodes.Size = new System.Drawing.Size(558, 152);
this.groupBoxTimeCodes.TabIndex = 1;
this.groupBoxTimeCodes.TabStop = false;
this.groupBoxTimeCodes.Text = "Time codes";
//
// checkBoxAlignTimeCodes
//
this.checkBoxAlignTimeCodes.AutoSize = true;
this.checkBoxAlignTimeCodes.Checked = true;
this.checkBoxAlignTimeCodes.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBoxAlignTimeCodes.Enabled = false;
this.checkBoxAlignTimeCodes.Location = new System.Drawing.Point(10, 22);
this.checkBoxAlignTimeCodes.Name = "checkBoxAlignTimeCodes";
this.checkBoxAlignTimeCodes.Size = new System.Drawing.Size(224, 19);
this.checkBoxAlignTimeCodes.TabIndex = 2;
this.checkBoxAlignTimeCodes.Text = "Align time codes to frame time codes";
this.checkBoxAlignTimeCodes.UseVisualStyleBackColor = true;
this.checkBoxAlignTimeCodes.CheckedChanged += new System.EventHandler(this.checkBoxAlignTimeCodes_CheckedChanged);
//
// panelTimeCodes
//
this.panelTimeCodes.Controls.Add(this.checkBoxExtractExactTimeCodes);
this.panelTimeCodes.Controls.Add(this.panelExtractTimeCodes);
this.panelTimeCodes.Location = new System.Drawing.Point(6, 41);
this.panelTimeCodes.Name = "panelTimeCodes";
this.panelTimeCodes.Size = new System.Drawing.Size(546, 105);
this.panelTimeCodes.TabIndex = 2;
//
// checkBoxExtractExactTimeCodes
//
this.checkBoxExtractExactTimeCodes.AutoSize = true;
this.checkBoxExtractExactTimeCodes.Checked = true;
this.checkBoxExtractExactTimeCodes.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBoxExtractExactTimeCodes.Location = new System.Drawing.Point(4, 2);
this.checkBoxExtractExactTimeCodes.Name = "checkBoxExtractExactTimeCodes";
this.checkBoxExtractExactTimeCodes.Size = new System.Drawing.Size(266, 19);
this.checkBoxExtractExactTimeCodes.TabIndex = 3;
this.checkBoxExtractExactTimeCodes.Text = "Use ffprobe to extract exact frame time codes";
this.checkBoxExtractExactTimeCodes.UseVisualStyleBackColor = true;
this.checkBoxExtractExactTimeCodes.CheckedChanged += new System.EventHandler(this.checkBoxExtractExactTimeCodes_CheckedChanged);
//
// panelExtractTimeCodes
//
this.panelExtractTimeCodes.Controls.Add(this.buttonCancelTimeCodes);
this.panelExtractTimeCodes.Controls.Add(this.labelExtractTimeCodesProgress);
this.panelExtractTimeCodes.Controls.Add(this.progressBarExtractTimeCodes);
this.panelExtractTimeCodes.Controls.Add(this.buttonExtractTimeCodes);
this.panelExtractTimeCodes.Controls.Add(this.labelTimeCodesStatus);
this.panelExtractTimeCodes.Location = new System.Drawing.Point(0, 27);
this.panelExtractTimeCodes.Name = "panelExtractTimeCodes";
this.panelExtractTimeCodes.Size = new System.Drawing.Size(546, 78);
this.panelExtractTimeCodes.TabIndex = 2;
//
// buttonCancelTimeCodes
//
this.buttonCancelTimeCodes.Location = new System.Drawing.Point(23, 18);
this.buttonCancelTimeCodes.Name = "buttonCancelTimeCodes";
this.buttonCancelTimeCodes.Size = new System.Drawing.Size(149, 23);
this.buttonCancelTimeCodes.TabIndex = 5;
this.buttonCancelTimeCodes.Text = "Cancel";
this.buttonCancelTimeCodes.UseVisualStyleBackColor = true;
this.buttonCancelTimeCodes.Visible = false;
this.buttonCancelTimeCodes.Click += new System.EventHandler(this.buttonCancelTimeCodes_Click);
//
// labelExtractTimeCodesProgress
//
this.labelExtractTimeCodesProgress.AutoSize = true;
this.labelExtractTimeCodesProgress.ForeColor = System.Drawing.SystemColors.ControlDarkDark;
this.labelExtractTimeCodesProgress.Location = new System.Drawing.Point(178, 22);
this.labelExtractTimeCodesProgress.Name = "labelExtractTimeCodesProgress";
this.labelExtractTimeCodesProgress.Size = new System.Drawing.Size(102, 15);
this.labelExtractTimeCodesProgress.TabIndex = 3;
this.labelExtractTimeCodesProgress.Text = "00:00:00 / 00:00:00";
//
// progressBarExtractTimeCodes
//
this.progressBarExtractTimeCodes.Location = new System.Drawing.Point(24, 47);
this.progressBarExtractTimeCodes.Name = "progressBarExtractTimeCodes";
this.progressBarExtractTimeCodes.Size = new System.Drawing.Size(516, 23);
this.progressBarExtractTimeCodes.TabIndex = 4;
//
// buttonExtractTimeCodes
//
this.buttonExtractTimeCodes.Location = new System.Drawing.Point(23, 18);
this.buttonExtractTimeCodes.Name = "buttonExtractTimeCodes";
this.buttonExtractTimeCodes.Size = new System.Drawing.Size(149, 23);
this.buttonExtractTimeCodes.TabIndex = 4;
this.buttonExtractTimeCodes.Text = "Extract time codes";
this.buttonExtractTimeCodes.UseVisualStyleBackColor = true;
this.buttonExtractTimeCodes.Click += new System.EventHandler(this.buttonExtractTimeCodes_Click);
//
// labelTimeCodesStatus
//
this.labelTimeCodesStatus.AutoSize = true;
this.labelTimeCodesStatus.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.labelTimeCodesStatus.Location = new System.Drawing.Point(20, 0);
this.labelTimeCodesStatus.Name = "labelTimeCodesStatus";
this.labelTimeCodesStatus.Size = new System.Drawing.Size(132, 15);
this.labelTimeCodesStatus.TabIndex = 1;
this.labelTimeCodesStatus.Text = "123 time codes loaded";
//
// groupBoxShotChanges
//
this.groupBoxShotChanges.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBoxShotChanges.Controls.Add(this.checkBoxSnapToShotChanges);
this.groupBoxShotChanges.Controls.Add(this.panelShotChanges);
this.groupBoxShotChanges.Location = new System.Drawing.Point(12, 170);
this.groupBoxShotChanges.Name = "groupBoxShotChanges";
this.groupBoxShotChanges.Size = new System.Drawing.Size(558, 101);
this.groupBoxShotChanges.TabIndex = 10;
this.groupBoxShotChanges.TabStop = false;
this.groupBoxShotChanges.Text = "Shot changes";
//
// checkBoxSnapToShotChanges
//
this.checkBoxSnapToShotChanges.AutoSize = true;
this.checkBoxSnapToShotChanges.Checked = true;
this.checkBoxSnapToShotChanges.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBoxSnapToShotChanges.Location = new System.Drawing.Point(10, 22);
this.checkBoxSnapToShotChanges.Name = "checkBoxSnapToShotChanges";
this.checkBoxSnapToShotChanges.Size = new System.Drawing.Size(166, 19);
this.checkBoxSnapToShotChanges.TabIndex = 11;
this.checkBoxSnapToShotChanges.Text = "Snap cues to shot changes";
this.checkBoxSnapToShotChanges.UseVisualStyleBackColor = true;
this.checkBoxSnapToShotChanges.CheckedChanged += new System.EventHandler(this.checkBoxSnapToShotChanges_CheckedChanged);
//
// panelShotChanges
//
this.panelShotChanges.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.panelShotChanges.Controls.Add(this.buttonImportShotChanges);
this.panelShotChanges.Controls.Add(this.labelShotChangesStatus);
this.panelShotChanges.Location = new System.Drawing.Point(6, 47);
this.panelShotChanges.Name = "panelShotChanges";
this.panelShotChanges.Size = new System.Drawing.Size(546, 48);
this.panelShotChanges.TabIndex = 2;
//
// buttonImportShotChanges
//
this.buttonImportShotChanges.Location = new System.Drawing.Point(23, 18);
this.buttonImportShotChanges.Name = "buttonImportShotChanges";
this.buttonImportShotChanges.Size = new System.Drawing.Size(221, 23);
this.buttonImportShotChanges.TabIndex = 12;
this.buttonImportShotChanges.Text = "Generate / import shot changes...";
this.buttonImportShotChanges.UseVisualStyleBackColor = true;
this.buttonImportShotChanges.Click += new System.EventHandler(this.buttonImportShotChanges_Click);
//
// labelShotChangesStatus
//
this.labelShotChangesStatus.AutoSize = true;
this.labelShotChangesStatus.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.labelShotChangesStatus.Location = new System.Drawing.Point(20, 0);
this.labelShotChangesStatus.Name = "labelShotChangesStatus";
this.labelShotChangesStatus.Size = new System.Drawing.Size(143, 15);
this.labelShotChangesStatus.TabIndex = 1;
this.labelShotChangesStatus.Text = "123 shot changes loaded";
//
// buttonEditProfile
//
this.buttonEditProfile.Location = new System.Drawing.Point(11, 279);
this.buttonEditProfile.Name = "buttonEditProfile";
this.buttonEditProfile.Size = new System.Drawing.Size(178, 28);
this.buttonEditProfile.TabIndex = 20;
this.buttonEditProfile.Text = "Edit profile...";
this.buttonEditProfile.UseVisualStyleBackColor = true;
this.buttonEditProfile.Click += new System.EventHandler(this.buttonEditProfile_Click);
//
// progressBar
//
this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.progressBar.Location = new System.Drawing.Point(12, 316);
this.progressBar.Name = "progressBar";
this.progressBar.Size = new System.Drawing.Size(558, 23);
this.progressBar.TabIndex = 21;
//
// BeautifyTimeCodes
//
this.AcceptButton = this.buttonOK;
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.buttonCancel;
this.ClientSize = new System.Drawing.Size(582, 385);
this.Controls.Add(this.progressBar);
this.Controls.Add(this.groupBoxShotChanges);
this.Controls.Add(this.buttonEditProfile);
this.Controls.Add(this.groupBoxTimeCodes);
this.Controls.Add(this.buttonCancel);
this.Controls.Add(this.buttonOK);
this.DoubleBuffered = true;
this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "BeautifyTimeCodes";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "BeautifyTimeCodes";
this.groupBoxTimeCodes.ResumeLayout(false);
this.groupBoxTimeCodes.PerformLayout();
this.panelTimeCodes.ResumeLayout(false);
this.panelTimeCodes.PerformLayout();
this.panelExtractTimeCodes.ResumeLayout(false);
this.panelExtractTimeCodes.PerformLayout();
this.groupBoxShotChanges.ResumeLayout(false);
this.groupBoxShotChanges.PerformLayout();
this.panelShotChanges.ResumeLayout(false);
this.panelShotChanges.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button buttonOK;
private System.Windows.Forms.Button buttonCancel;
private System.Windows.Forms.GroupBox groupBoxTimeCodes;
private System.Windows.Forms.CheckBox checkBoxAlignTimeCodes;
private System.Windows.Forms.GroupBox groupBoxShotChanges;
private System.Windows.Forms.CheckBox checkBoxSnapToShotChanges;
private System.Windows.Forms.Panel panelTimeCodes;
private System.Windows.Forms.CheckBox checkBoxExtractExactTimeCodes;
private System.Windows.Forms.Panel panelExtractTimeCodes;
private System.Windows.Forms.Label labelExtractTimeCodesProgress;
private System.Windows.Forms.ProgressBar progressBarExtractTimeCodes;
private System.Windows.Forms.Button buttonExtractTimeCodes;
private System.Windows.Forms.Label labelTimeCodesStatus;
private System.Windows.Forms.Panel panelShotChanges;
private System.Windows.Forms.Button buttonImportShotChanges;
private System.Windows.Forms.Label labelShotChangesStatus;
private System.Windows.Forms.Button buttonEditProfile;
private System.Windows.Forms.Button buttonCancelTimeCodes;
private System.Windows.Forms.ProgressBar progressBar;
}
}

View File

@ -0,0 +1,319 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Nikse.SubtitleEdit.Core.Common;
using Nikse.SubtitleEdit.Core.Forms;
using Nikse.SubtitleEdit.Forms.ShotChanges;
using Nikse.SubtitleEdit.Logic;
namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
{
public partial class BeautifyTimeCodes : Form
{
private readonly Subtitle _subtitle;
private readonly VideoInfo _videoInfo;
private readonly double _frameRate;
private readonly double _duration;
private readonly string _videoFileName;
private List<double> _timeCodes = new List<double>();
private List<double> _shotChanges = new List<double>();
public List<double> ShotChangesInSeconds = new List<double>(); // For storing imported/generated shot changes that will be returned to the main form
public Subtitle FixedSubtitle { get; private set; }
private bool _abortTimeCodes;
private TimeCodesGenerator _timeCodesGenerator;
public BeautifyTimeCodes(Subtitle subtitle, VideoInfo videoInfo, string videoFileName, List<double> shotChanges)
{
UiUtil.PreInitialize(this);
InitializeComponent();
UiUtil.FixFonts(this);
if (videoInfo != null && videoInfo.FramesPerSecond > 1)
{
_frameRate = videoInfo.FramesPerSecond;
}
else
{
_frameRate = Configuration.Settings.General.CurrentFrameRate;
}
if (videoInfo != null && videoInfo.TotalMilliseconds > 0)
{
_duration = videoInfo.TotalMilliseconds;
}
_videoInfo = videoInfo;
_videoFileName = videoFileName;
_subtitle = subtitle;
var language = LanguageSettings.Current.BeautifyTimeCodes;
var settings = Configuration.Settings.BeautifyTimeCodes;
Text = language.Title;
groupBoxTimeCodes.Text = language.GroupTimeCodes;
groupBoxShotChanges.Text = language.GroupShotChanges;
checkBoxAlignTimeCodes.Text = language.AlignTimeCodes;
checkBoxExtractExactTimeCodes.Text = language.ExtractExactTimeCodes;
buttonExtractTimeCodes.Text = language.ExtractTimeCodes;
buttonCancelTimeCodes.Text = language.CancelTimeCodes;
checkBoxSnapToShotChanges.Text = language.SnapToShotChanges;
buttonImportShotChanges.Text = language.ImportShotChanges;
buttonEditProfile.Text = language.EditProfile;
labelExtractTimeCodesProgress.Text = "";
buttonOK.Text = LanguageSettings.Current.General.Ok;
buttonCancel.Text = LanguageSettings.Current.General.Cancel;
UiUtil.FixLargeFonts(this, buttonOK);
labelTimeCodesStatus.Font = new Font(labelTimeCodesStatus.Font, FontStyle.Bold);
labelShotChangesStatus.Font = new Font(labelShotChangesStatus.Font, FontStyle.Bold);
checkBoxAlignTimeCodes.Checked = settings.AlignTimeCodes;
checkBoxExtractExactTimeCodes.Checked = settings.ExtractExactTimeCodes;
checkBoxSnapToShotChanges.Checked = settings.SnapToShotChanges;
// Check if video is loaded
if (_videoFileName != null)
{
// Load time codes
this._timeCodes = TimeCodesFileHelper.FromDisk(videoFileName);
this._shotChanges = shotChanges;
// Check if ffprobe is available
var ffProbePath = Path.GetDirectoryName(Configuration.Settings.General.FFmpegLocation) + Path.DirectorySeparatorChar + "ffprobe" + Path.GetExtension(Configuration.Settings.General.FFmpegLocation);
var isffProbeAvailable = !string.IsNullOrEmpty(ffProbePath) && File.Exists(ffProbePath);
if (!isffProbeAvailable)
{
checkBoxExtractExactTimeCodes.Enabled = false;
checkBoxExtractExactTimeCodes.Checked = false;
}
}
else
{
checkBoxExtractExactTimeCodes.Enabled = false;
checkBoxExtractExactTimeCodes.Checked = false;
groupBoxShotChanges.Enabled = false;
checkBoxSnapToShotChanges.Enabled = false;
checkBoxSnapToShotChanges.Checked = false;
}
RefreshControls();
}
private void RefreshControls()
{
panelTimeCodes.Enabled = checkBoxAlignTimeCodes.Checked;
panelExtractTimeCodes.Enabled = checkBoxExtractExactTimeCodes.Checked;
panelShotChanges.Enabled = checkBoxSnapToShotChanges.Checked;
if (_timeCodes.Count > 0)
{
labelTimeCodesStatus.Text = string.Format(LanguageSettings.Current.BeautifyTimeCodes.XTimeCodesLoaded, _timeCodes.Count);
buttonExtractTimeCodes.Enabled = false;
progressBarExtractTimeCodes.Enabled = false;
}
else
{
labelTimeCodesStatus.Text = LanguageSettings.Current.BeautifyTimeCodes.NoTimeCodesLoaded;
buttonExtractTimeCodes.Enabled = true;
progressBarExtractTimeCodes.Enabled = true;
progressBarExtractTimeCodes.Value = 0;
}
if (_shotChanges.Count > 0)
{
labelShotChangesStatus.Text = string.Format(LanguageSettings.Current.BeautifyTimeCodes.XShotChangesLoaded, _shotChanges.Count);
buttonImportShotChanges.Enabled = false;
}
else
{
labelShotChangesStatus.Text = LanguageSettings.Current.BeautifyTimeCodes.NoShotChangesLoaded;
buttonImportShotChanges.Enabled = true;
}
}
private void buttonExtractTimeCodes_Click(object sender, EventArgs e)
{
_timeCodesGenerator = new TimeCodesGenerator();
_abortTimeCodes = false;
checkBoxSnapToShotChanges.Enabled = false;
panelShotChanges.Enabled = false;
labelTimeCodesStatus.Enabled = false;
checkBoxExtractExactTimeCodes.Enabled = false;
buttonExtractTimeCodes.Enabled = false;
buttonCancelTimeCodes.Visible = true;
progressBarExtractTimeCodes.Style = ProgressBarStyle.Marquee;
labelExtractTimeCodesProgress.Visible = true;
Cursor = Cursors.WaitCursor;
buttonOK.Enabled = false;
buttonCancel.Enabled = false;
bool success = false;
using (var process = _timeCodesGenerator.GetProcess(_videoFileName))
{
while (!process.HasExited)
{
Application.DoEvents();
System.Threading.Thread.Sleep(100);
UpdateTimeCodeProgress();
if (_abortTimeCodes)
{
process.Kill();
break;
}
}
if (!_abortTimeCodes)
{
success = process.ExitCode == 0;
}
}
UpdateTimeCodeProgress();
checkBoxSnapToShotChanges.Enabled = true;
panelShotChanges.Enabled = true;
labelTimeCodesStatus.Enabled = true;
checkBoxExtractExactTimeCodes.Enabled = true;
buttonExtractTimeCodes.Enabled = true;
buttonCancelTimeCodes.Visible = false;
Cursor = Cursors.Default;
buttonOK.Enabled = true;
buttonCancel.Enabled = true;
progressBarExtractTimeCodes.Style = ProgressBarStyle.Blocks;
progressBarExtractTimeCodes.Value = 0;
labelExtractTimeCodesProgress.Visible = false;
if (!_abortTimeCodes && success)
{
_timeCodes = _timeCodesGenerator.GetTimeCodes();
TimeCodesFileHelper.SaveTimeCodes(_videoFileName, _timeCodes);
}
RefreshControls();
}
private void UpdateTimeCodeProgress()
{
if (_duration > 0 && _timeCodesGenerator.LastSeconds > 0)
{
if (progressBarExtractTimeCodes.Style != ProgressBarStyle.Blocks)
{
progressBarExtractTimeCodes.Style = ProgressBarStyle.Blocks;
progressBarExtractTimeCodes.Maximum = Convert.ToInt32(_duration);
}
progressBarExtractTimeCodes.Value = Convert.ToInt32(_timeCodesGenerator.LastSeconds);
labelExtractTimeCodesProgress.Text = FormatSeconds(_timeCodesGenerator.LastSeconds) + @" / " + FormatSeconds(_duration);
}
}
private string FormatSeconds(double seconds)
{
TimeSpan t = TimeSpan.FromSeconds(seconds);
return t.ToString(@"hh\:mm\:ss");
}
private void buttonEditProfile_Click(object sender, EventArgs e)
{
using (var form = new BeautifyTimeCodesProfile(_frameRate))
{
form.ShowDialog(this);
}
}
private void buttonImportShotChanges_Click(object sender, EventArgs e)
{
using (var form = new ImportShotChanges(_videoInfo, _videoFileName))
{
if (form.ShowDialog(this) == DialogResult.OK)
{
this._shotChanges = form.ShotChangesInSeconds;
this.ShotChangesInSeconds = form.ShotChangesInSeconds;
ShotChangeHelper.SaveShotChanges(_videoFileName, form.ShotChangesInSeconds);
RefreshControls();
}
}
}
private void buttonOK_Click(object sender, EventArgs e)
{
// Validation
if (checkBoxExtractExactTimeCodes.Checked && _timeCodes.Count == 0) // we check the extract checkbox here, otherwise it should just calculate the time codes based on frame rate
{
MessageBox.Show(this, string.Format(LanguageSettings.Current.BeautifyTimeCodes.NoTimeCodesLoadedError, LanguageSettings.Current.BeautifyTimeCodes.ExtractTimeCodes), LanguageSettings.Current.General.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
DialogResult = DialogResult.None;
return;
}
if (checkBoxSnapToShotChanges.Checked && _shotChanges.Count == 0)
{
MessageBox.Show(this, string.Format(LanguageSettings.Current.BeautifyTimeCodes.NoShotChangesLoadedError, LanguageSettings.Current.BeautifyTimeCodes.ImportShotChanges), LanguageSettings.Current.General.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
DialogResult = DialogResult.None;
return;
}
// Prepare
groupBoxTimeCodes.Enabled = false;
groupBoxShotChanges.Enabled = false;
buttonOK.Enabled = false;
// Actual processing
FixedSubtitle = new Subtitle(_subtitle);
TimeCodesBeautifier timeCodesBeautifier = new TimeCodesBeautifier(
FixedSubtitle,
_frameRate,
checkBoxExtractExactTimeCodes.Checked ? _timeCodes : new List<double>(), // ditto
checkBoxSnapToShotChanges.Checked ? _shotChanges : new List<double>()
);
timeCodesBeautifier.ProgressChanged += delegate(double progress)
{
progressBar.Value = Convert.ToInt32(progress * 100);
Application.DoEvents();
};
timeCodesBeautifier.Beautify();
// Save settings
Configuration.Settings.BeautifyTimeCodes.AlignTimeCodes = checkBoxAlignTimeCodes.Checked;
if (checkBoxExtractExactTimeCodes.Enabled)
{
Configuration.Settings.BeautifyTimeCodes.ExtractExactTimeCodes = checkBoxExtractExactTimeCodes.Checked;
}
if (checkBoxSnapToShotChanges.Enabled)
{
Configuration.Settings.BeautifyTimeCodes.SnapToShotChanges = checkBoxSnapToShotChanges.Checked;
}
DialogResult = DialogResult.OK;
}
private void checkBoxAlignTimeCodes_CheckedChanged(object sender, EventArgs e)
{
RefreshControls();
}
private void checkBoxExtractExactTimeCodes_CheckedChanged(object sender, EventArgs e)
{
RefreshControls();
}
private void checkBoxSnapToShotChanges_CheckedChanged(object sender, EventArgs e)
{
RefreshControls();
}
private void buttonCancelTimeCodes_Click(object sender, EventArgs e)
{
_abortTimeCodes = true;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
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
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<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
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
mimetype set.
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
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
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
: 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
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,350 @@
using System;
using System.Windows.Forms;
using Nikse.SubtitleEdit.Core.Common;
using Nikse.SubtitleEdit.Logic;
namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
{
public partial class BeautifyTimeCodesProfile : Form
{
private readonly double _frameRate;
public BeautifyTimeCodesProfile(double frameRate)
{
_frameRate = frameRate;
UiUtil.PreInitialize(this);
InitializeComponent();
UiUtil.FixFonts(this);
if (frameRate > 0)
{
cuesPreviewViewInCues.FrameRate = (float)frameRate;
cuesPreviewViewOutCues.FrameRate = (float)frameRate;
cuesPreviewViewConnectedSubtitlesInCueClosest.FrameRate = (float)frameRate;
cuesPreviewViewConnectedSubtitlesOutCueClosest.FrameRate = (float)frameRate;
cuesPreviewViewChainingGeneral.FrameRate = (float)frameRate;
cuesPreviewViewChainingInCueOnShot.FrameRate = (float)frameRate;
cuesPreviewViewChainingOutCueOnShot.FrameRate = (float)frameRate;
}
var language = LanguageSettings.Current.BeautifyTimeCodesProfile;
Text = language.Title;
buttonCreateSimple.Text = language.CreateSimple;
toolStripMenuItemLoadPreset.Text = language.LoadPreset;
groupBoxGeneral.Text = language.General;
labelGap.Text = language.Gap;
labelGapSuffix.Text = language.GapSuffix;
groupBoxInCues.Text = language.InCues;
labelInCuesGap.Text = language.Gap;
labelInCuesZones.Text = language.Zones;
groupBoxOutCues.Text = language.OutCues;
labelOutCuesGap.Text = language.Gap;
labelOutCuesZones.Text = language.Zones;
groupBoxConnectedSubtitles.Text = language.ConnectedSubtitles;
tabPageConnectedSubtitlesInCueClosest.Text = language.InCueClosest;
labelConnectedSubtitlesInCueClosestGaps.Text = language.Gap;
tabPageConnectedSubtitlesOutCueClosest.Text = language.OutCueClosest;
labelConnectedSubtitlesOutCueClosestGaps.Text = language.Gap;
labelConnectedSubtitlesZones.Text = language.Zones;
labelConnectedSubtitlesTreatConnected.Text = language.TreadAsConnected;
labelConnectedSubtitlesTreatConnectedSuffix.Text = language.Milliseconds;
groupBoxChaining.Text = language.Chaining;
tabPageChainingGeneral.Text = language.General;
radioButtonChainingGeneralMaxGap.Text = language.MaxGap;
labelChainingGeneralMaxGapSuffix.Text = language.Milliseconds;
radioButtonChainingGeneralZones.Text = language.Zones;
labelChainingGeneralShotChangeBehavior.Text = language.ShotChangeBehavior;
comboBoxChainingGeneralShotChangeBehavior.Items.Clear();
comboBoxChainingGeneralShotChangeBehavior.Items.Add(language.DontChain);
comboBoxChainingGeneralShotChangeBehavior.Items.Add(language.ExtendCrossingShotChange);
comboBoxChainingGeneralShotChangeBehavior.Items.Add(language.ExtendUntilShotChange);
radioButtonChainingInCueOnShotMaxGap.Text = language.MaxGap;
labelChainingInCueOnShotMaxGapSuffix.Text = language.Milliseconds;
radioButtonChainingInCueOnShotZones.Text = language.Zones;
radioButtonChainingOutCueOnShotMaxGap.Text = language.MaxGap;
labelChainingOutCueOnShotMaxGapSuffix.Text = language.Milliseconds;
radioButtonChainingOutCueOnShotZones.Text = language.Zones;
cuesPreviewViewInCues.PreviewText = language.SubtitlePreviewText;
cuesPreviewViewOutCues.PreviewText = language.SubtitlePreviewText;
cuesPreviewViewConnectedSubtitlesInCueClosest.PreviewText = language.SubtitlePreviewText;
cuesPreviewViewConnectedSubtitlesOutCueClosest.PreviewText = language.SubtitlePreviewText;
cuesPreviewViewChainingGeneral.PreviewText = language.SubtitlePreviewText;
cuesPreviewViewChainingInCueOnShot.PreviewText = language.SubtitlePreviewText;
cuesPreviewViewChainingOutCueOnShot.PreviewText = language.SubtitlePreviewText;
numericUpDownGap.Left = labelGap.Left + labelGap.Width + 12;
labelGapSuffix.Left = numericUpDownGap.Left + numericUpDownGap.Width + 6;
numericUpDownConnectedSubtitlesTreatConnected.Left = Math.Max(labelConnectedSubtitlesTreatConnected.Left + labelConnectedSubtitlesTreatConnected.Width + 6, numericUpDownConnectedSubtitlesTreatConnected.Left);
labelConnectedSubtitlesTreatConnectedSuffix.Left = numericUpDownConnectedSubtitlesTreatConnected.Left + numericUpDownConnectedSubtitlesTreatConnected.Width + 6;
var comboBoxRight = comboBoxChainingGeneralShotChangeBehavior.Right;
comboBoxChainingGeneralShotChangeBehavior.Left = Math.Max(labelChainingGeneralShotChangeBehavior.Left + labelChainingGeneralShotChangeBehavior.Width + 6, comboBoxChainingGeneralShotChangeBehavior.Left);
comboBoxChainingGeneralShotChangeBehavior.Width = comboBoxRight - comboBoxChainingGeneralShotChangeBehavior.Left;
foreach (BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.Preset preset in Enum.GetValues(typeof(BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.Preset)))
{
var toolStripMenuItem = new ToolStripMenuItem(UiUtil.GetBeautifyTimeCodesProfilePresetName(preset));
toolStripMenuItem.Click += (sender, args) =>
{
ResetSettings(preset);
};
toolStripMenuItemLoadPreset.DropDownItems.Add(toolStripMenuItem);
}
buttonOK.Text = LanguageSettings.Current.General.Ok;
buttonCancel.Text = LanguageSettings.Current.General.Cancel;
UiUtil.FixLargeFonts(this, buttonOK);
LoadSettings();
}
private void LoadSettings()
{
var settings = Configuration.Settings.BeautifyTimeCodes.Profile;
numericUpDownGap.Value = settings.Gap;
numericUpDownInCuesGap.Value = settings.InCuesGap;
numericUpDownInCuesLeftRedZone.Value = settings.InCuesLeftRedZone;
numericUpDownInCuesRightRedZone.Value = settings.InCuesRightRedZone;
numericUpDownInCuesLeftGreenZone.Value = settings.InCuesLeftGreenZone;
numericUpDownInCuesRightGreenZone.Value = settings.InCuesRightGreenZone;
numericUpDownOutCuesGap.Value = settings.OutCuesGap;
numericUpDownOutCuesLeftRedZone.Value = settings.OutCuesLeftRedZone;
numericUpDownOutCuesRightRedZone.Value = settings.OutCuesRightRedZone;
numericUpDownOutCuesLeftGreenZone.Value = settings.OutCuesLeftGreenZone;
numericUpDownOutCuesRightGreenZone.Value = settings.OutCuesRightGreenZone;
numericUpDownConnectedSubtitlesInCueClosestLeftGap.Value = settings.ConnectedSubtitlesInCueClosestLeftGap;
numericUpDownConnectedSubtitlesInCueClosestRightGap.Value = settings.ConnectedSubtitlesInCueClosestRightGap;
numericUpDownConnectedSubtitlesOutCueClosestLeftGap.Value = settings.ConnectedSubtitlesOutCueClosestLeftGap;
numericUpDownConnectedSubtitlesOutCueClosestRightGap.Value = settings.ConnectedSubtitlesOutCueClosestRightGap;
numericUpDownConnectedSubtitlesLeftRedZone.Value = settings.ConnectedSubtitlesLeftRedZone;
numericUpDownConnectedSubtitlesRightRedZone.Value = settings.ConnectedSubtitlesRightRedZone;
numericUpDownConnectedSubtitlesLeftGreenZone.Value = settings.ConnectedSubtitlesLeftGreenZone;
numericUpDownConnectedSubtitlesRightGreenZone.Value = settings.ConnectedSubtitlesRightGreenZone;
numericUpDownConnectedSubtitlesTreatConnected.Value = settings.ConnectedSubtitlesTreatConnected;
radioButtonChainingGeneralZones.Checked = settings.ChainingGeneralUseZones;
radioButtonChainingGeneralMaxGap.Checked = !settings.ChainingGeneralUseZones;
numericUpDownChainingGeneralMaxGap.Value = settings.ChainingGeneralMaxGap;
numericUpDownChainingGeneralLeftRedZone.Value = settings.ChainingGeneralLeftRedZone;
numericUpDownChainingGeneralLeftGreenZone.Value = settings.ChainingGeneralLeftGreenZone;
comboBoxChainingGeneralShotChangeBehavior.SelectedIndex = (int)settings.ChainingGeneralShotChangeBehavior;
radioButtonChainingInCueOnShotZones.Checked = settings.ChainingInCueOnShotUseZones;
radioButtonChainingInCueOnShotMaxGap.Checked = !settings.ChainingInCueOnShotUseZones;
numericUpDownChainingInCueOnShotMaxGap.Value = settings.ChainingInCueOnShotMaxGap;
numericUpDownChainingInCueOnShotLeftRedZone.Value = settings.ChainingInCueOnShotLeftRedZone;
numericUpDownChainingInCueOnShotLeftGreenZone.Value = settings.ChainingInCueOnShotLeftGreenZone;
radioButtonChainingOutCueOnShotZones.Checked = settings.ChainingOutCueOnShotUseZones;
radioButtonChainingOutCueOnShotMaxGap.Checked = !settings.ChainingOutCueOnShotUseZones;
numericUpDownChainingOutCueOnShotMaxGap.Value = settings.ChainingOutCueOnShotMaxGap;
numericUpDownChainingOutCueOnShotRightRedZone.Value = settings.ChainingOutCueOnShotRightRedZone;
numericUpDownChainingOutCueOnShotRightGreenZone.Value = settings.ChainingOutCueOnShotRightGreenZone;
RefreshControls();
}
private void RefreshControls()
{
// Radio button toggling
numericUpDownChainingGeneralMaxGap.Enabled = radioButtonChainingGeneralMaxGap.Checked;
labelChainingGeneralMaxGapSuffix.Enabled = radioButtonChainingGeneralMaxGap.Checked;
numericUpDownChainingGeneralLeftGreenZone.Enabled = radioButtonChainingGeneralZones.Checked;
numericUpDownChainingGeneralLeftRedZone.Enabled = radioButtonChainingGeneralZones.Checked;
numericUpDownChainingInCueOnShotMaxGap.Enabled = radioButtonChainingInCueOnShotMaxGap.Checked;
labelChainingInCueOnShotMaxGapSuffix.Enabled = radioButtonChainingInCueOnShotMaxGap.Checked;
numericUpDownChainingInCueOnShotLeftGreenZone.Enabled = radioButtonChainingInCueOnShotZones.Checked;
numericUpDownChainingInCueOnShotLeftRedZone.Enabled = radioButtonChainingInCueOnShotZones.Checked;
numericUpDownChainingOutCueOnShotMaxGap.Enabled = radioButtonChainingOutCueOnShotMaxGap.Checked;
labelChainingOutCueOnShotMaxGapSuffix.Enabled = radioButtonChainingOutCueOnShotMaxGap.Checked;
numericUpDownChainingOutCueOnShotRightRedZone.Enabled = radioButtonChainingOutCueOnShotZones.Checked;
numericUpDownChainingOutCueOnShotRightGreenZone.Enabled = radioButtonChainingOutCueOnShotZones.Checked;
// Connected subtitles page toggling
cuesPreviewViewConnectedSubtitlesInCueClosest.Visible = tabControlConnectedSubtitles.SelectedIndex == 0;
cuesPreviewViewConnectedSubtitlesOutCueClosest.Visible = tabControlConnectedSubtitles.SelectedIndex == 1;
// Chaining page toggling
cuesPreviewViewChainingGeneral.Visible = tabControlChaining.SelectedIndex == 0;
cuesPreviewViewChainingInCueOnShot.Visible = tabControlChaining.SelectedIndex == 1;
cuesPreviewViewChainingOutCueOnShot.Visible = tabControlChaining.SelectedIndex == 2;
// Update cue previews
cuesPreviewViewInCues.RightGap = Convert.ToInt32(numericUpDownInCuesGap.Value);
cuesPreviewViewInCues.LeftGreenZone = Convert.ToInt32(numericUpDownInCuesLeftGreenZone.Value);
cuesPreviewViewInCues.LeftRedZone = Convert.ToInt32(numericUpDownInCuesLeftRedZone.Value);
cuesPreviewViewInCues.RightRedZone = Convert.ToInt32(numericUpDownInCuesRightRedZone.Value);
cuesPreviewViewInCues.RightGreenZone = Convert.ToInt32(numericUpDownInCuesRightGreenZone.Value);
cuesPreviewViewOutCues.LeftGap = Convert.ToInt32(numericUpDownOutCuesGap.Value);
cuesPreviewViewOutCues.LeftGreenZone = Convert.ToInt32(numericUpDownOutCuesLeftGreenZone.Value);
cuesPreviewViewOutCues.LeftRedZone = Convert.ToInt32(numericUpDownOutCuesLeftRedZone.Value);
cuesPreviewViewOutCues.RightRedZone = Convert.ToInt32(numericUpDownOutCuesRightRedZone.Value);
cuesPreviewViewOutCues.RightGreenZone = Convert.ToInt32(numericUpDownOutCuesRightGreenZone.Value);
cuesPreviewViewConnectedSubtitlesInCueClosest.LeftGap = Convert.ToInt32(numericUpDownConnectedSubtitlesInCueClosestLeftGap.Value);
cuesPreviewViewConnectedSubtitlesInCueClosest.RightGap = Convert.ToInt32(numericUpDownConnectedSubtitlesInCueClosestRightGap.Value);
cuesPreviewViewConnectedSubtitlesInCueClosest.LeftGreenZone = Convert.ToInt32(numericUpDownConnectedSubtitlesLeftGreenZone.Value);
cuesPreviewViewConnectedSubtitlesInCueClosest.LeftRedZone = Convert.ToInt32(numericUpDownConnectedSubtitlesLeftRedZone.Value);
cuesPreviewViewConnectedSubtitlesInCueClosest.RightRedZone = Convert.ToInt32(numericUpDownConnectedSubtitlesRightRedZone.Value);
cuesPreviewViewConnectedSubtitlesInCueClosest.RightGreenZone = Convert.ToInt32(numericUpDownConnectedSubtitlesRightGreenZone.Value);
cuesPreviewViewConnectedSubtitlesOutCueClosest.LeftGap = Convert.ToInt32(numericUpDownConnectedSubtitlesOutCueClosestLeftGap.Value);
cuesPreviewViewConnectedSubtitlesOutCueClosest.RightGap = Convert.ToInt32(numericUpDownConnectedSubtitlesOutCueClosestRightGap.Value);
cuesPreviewViewConnectedSubtitlesOutCueClosest.LeftGreenZone = Convert.ToInt32(numericUpDownConnectedSubtitlesLeftGreenZone.Value);
cuesPreviewViewConnectedSubtitlesOutCueClosest.LeftRedZone = Convert.ToInt32(numericUpDownConnectedSubtitlesLeftRedZone.Value);
cuesPreviewViewConnectedSubtitlesOutCueClosest.RightRedZone = Convert.ToInt32(numericUpDownConnectedSubtitlesRightRedZone.Value);
cuesPreviewViewConnectedSubtitlesOutCueClosest.RightGreenZone = Convert.ToInt32(numericUpDownConnectedSubtitlesRightGreenZone.Value);
cuesPreviewViewChainingGeneral.LeftGreenZone = Convert.ToInt32(numericUpDownChainingGeneralLeftGreenZone.Value);
cuesPreviewViewChainingGeneral.LeftRedZone = Convert.ToInt32(numericUpDownChainingGeneralLeftRedZone.Value);
cuesPreviewViewChainingInCueOnShot.RightGap = Convert.ToInt32(numericUpDownInCuesGap.Value);
cuesPreviewViewChainingInCueOnShot.LeftGreenZone = Convert.ToInt32(numericUpDownChainingInCueOnShotLeftGreenZone.Value);
cuesPreviewViewChainingInCueOnShot.LeftRedZone = Convert.ToInt32(numericUpDownChainingInCueOnShotLeftRedZone.Value);
cuesPreviewViewChainingOutCueOnShot.LeftGap = Convert.ToInt32(numericUpDownOutCuesGap.Value);
cuesPreviewViewChainingOutCueOnShot.RightRedZone = Convert.ToInt32(numericUpDownChainingOutCueOnShotRightRedZone.Value);
cuesPreviewViewChainingOutCueOnShot.RightGreenZone = Convert.ToInt32(numericUpDownChainingOutCueOnShotRightGreenZone.Value);
}
private void buttonOK_Click(object sender, EventArgs e)
{
// Save settings
Configuration.Settings.BeautifyTimeCodes.Profile.Gap = Convert.ToInt32(numericUpDownGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap = Convert.ToInt32(numericUpDownInCuesGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesLeftGreenZone = Convert.ToInt32(numericUpDownInCuesLeftGreenZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesLeftRedZone = Convert.ToInt32(numericUpDownInCuesLeftRedZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesRightRedZone = Convert.ToInt32(numericUpDownInCuesRightRedZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesRightGreenZone = Convert.ToInt32(numericUpDownInCuesRightGreenZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap = Convert.ToInt32(numericUpDownOutCuesGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesLeftGreenZone = Convert.ToInt32(numericUpDownOutCuesLeftGreenZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesLeftRedZone = Convert.ToInt32(numericUpDownOutCuesLeftRedZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesRightRedZone = Convert.ToInt32(numericUpDownOutCuesRightRedZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesRightGreenZone = Convert.ToInt32(numericUpDownOutCuesRightGreenZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestLeftGap = Convert.ToInt32(numericUpDownConnectedSubtitlesInCueClosestLeftGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestRightGap = Convert.ToInt32(numericUpDownConnectedSubtitlesInCueClosestRightGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestLeftGap = Convert.ToInt32(numericUpDownConnectedSubtitlesOutCueClosestLeftGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestRightGap = Convert.ToInt32(numericUpDownConnectedSubtitlesOutCueClosestRightGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftGreenZone = Convert.ToInt32(numericUpDownConnectedSubtitlesLeftGreenZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftRedZone = Convert.ToInt32(numericUpDownConnectedSubtitlesLeftRedZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightRedZone = Convert.ToInt32(numericUpDownConnectedSubtitlesRightRedZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightGreenZone = Convert.ToInt32(numericUpDownConnectedSubtitlesRightGreenZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesTreatConnected = Convert.ToInt32(numericUpDownConnectedSubtitlesTreatConnected.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralUseZones = radioButtonChainingGeneralZones.Checked;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap = Convert.ToInt32(numericUpDownChainingGeneralMaxGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone = Convert.ToInt32(numericUpDownChainingGeneralLeftGreenZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftRedZone = Convert.ToInt32(numericUpDownChainingGeneralLeftRedZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior = (BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum)comboBoxChainingGeneralShotChangeBehavior.SelectedIndex;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotUseZones = radioButtonChainingInCueOnShotZones.Checked;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap = Convert.ToInt32(numericUpDownChainingInCueOnShotMaxGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftGreenZone = Convert.ToInt32(numericUpDownChainingInCueOnShotLeftGreenZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftRedZone = Convert.ToInt32(numericUpDownChainingInCueOnShotLeftRedZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotUseZones = radioButtonChainingOutCueOnShotZones.Checked;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap = Convert.ToInt32(numericUpDownChainingOutCueOnShotMaxGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightRedZone = Convert.ToInt32(numericUpDownChainingOutCueOnShotRightRedZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone = Convert.ToInt32(numericUpDownChainingOutCueOnShotRightGreenZone.Value);
DialogResult = DialogResult.OK;
}
private void ResetSettings(BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.Preset preset)
{
if (MessageBox.Show(this, LanguageSettings.Current.BeautifyTimeCodesProfile.ResetWarning, LanguageSettings.Current.General.Warning, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
Configuration.Settings.BeautifyTimeCodes.Profile = new BeautifyTimeCodesSettings.BeautifyTimeCodesProfile(preset);
LoadSettings();
}
}
private void radioButtonChaining_CheckedChanged(object sender, EventArgs e)
{
RefreshControls();
}
private void tabControlChaining_SelectedIndexChanged(object sender, EventArgs e)
{
RefreshControls();
}
private void numericUpDown_ValueChanged(object sender, EventArgs e)
{
ValidateZones();
RefreshControls();
}
private void tabControlConnectedSubtitles_SelectedIndexChanged(object sender, EventArgs e)
{
RefreshControls();
}
private void numericUpDownGap_ValueChanged(object sender, EventArgs e)
{
if (numericUpDownOutCuesGap.Value > 0)
{
numericUpDownOutCuesGap.Value = numericUpDownGap.Value;
}
if (numericUpDownConnectedSubtitlesInCueClosestLeftGap.Value > 0 && numericUpDownConnectedSubtitlesInCueClosestRightGap.Value == 0)
{
numericUpDownConnectedSubtitlesInCueClosestLeftGap.Value = numericUpDownGap.Value;
}
if (numericUpDownConnectedSubtitlesInCueClosestLeftGap.Value == 0 && numericUpDownConnectedSubtitlesInCueClosestRightGap.Value > 0)
{
numericUpDownConnectedSubtitlesInCueClosestRightGap.Value = numericUpDownGap.Value;
}
if (numericUpDownConnectedSubtitlesOutCueClosestRightGap.Value > 0 && numericUpDownConnectedSubtitlesOutCueClosestLeftGap.Value == 0)
{
numericUpDownConnectedSubtitlesOutCueClosestRightGap.Value = numericUpDownGap.Value;
}
if (numericUpDownConnectedSubtitlesOutCueClosestRightGap.Value == 0 && numericUpDownConnectedSubtitlesOutCueClosestLeftGap.Value > 0)
{
numericUpDownConnectedSubtitlesOutCueClosestLeftGap.Value = numericUpDownGap.Value;
}
}
private void ValidateZones()
{
numericUpDownInCuesLeftGreenZone.Minimum = numericUpDownInCuesLeftRedZone.Value;
numericUpDownInCuesRightGreenZone.Minimum = numericUpDownInCuesRightRedZone.Value;
numericUpDownOutCuesLeftGreenZone.Minimum = numericUpDownOutCuesLeftRedZone.Value;
numericUpDownOutCuesRightGreenZone.Minimum = numericUpDownOutCuesRightRedZone.Value;
numericUpDownConnectedSubtitlesLeftGreenZone.Minimum = numericUpDownConnectedSubtitlesLeftRedZone.Value;
numericUpDownConnectedSubtitlesRightGreenZone.Minimum = numericUpDownConnectedSubtitlesRightRedZone.Value;
numericUpDownChainingGeneralLeftGreenZone.Minimum = numericUpDownChainingGeneralLeftRedZone.Value;
numericUpDownChainingInCueOnShotLeftGreenZone.Minimum = numericUpDownChainingInCueOnShotLeftRedZone.Value;
numericUpDownChainingOutCueOnShotRightGreenZone.Minimum = numericUpDownChainingOutCueOnShotRightRedZone.Value;
}
private void buttonCreateSimple_Click(object sender, EventArgs e)
{
using (var form = new BeautifyTimeCodesProfileSimple(_frameRate))
{
if (form.ShowDialog() == DialogResult.OK)
{
LoadSettings();
}
}
}
}
}

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
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
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<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
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
mimetype set.
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
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
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
: 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
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,552 @@
namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
{
partial class BeautifyTimeCodesProfileSimple
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BeautifyTimeCodesProfileSimple));
this.buttonCancel = new System.Windows.Forms.Button();
this.buttonOK = new System.Windows.Forms.Button();
this.labelInstructions = new System.Windows.Forms.Label();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.checkBoxSnapClosestCue = new System.Windows.Forms.CheckBox();
this.pictureBoxChainingInfo = new System.Windows.Forms.PictureBox();
this.labelChainingGapAfterShotChangesPrefix = new System.Windows.Forms.Label();
this.numericUpDownChainingGapAfterShotChanges = new System.Windows.Forms.NumericUpDown();
this.labelChainingGapAfterShotChangesSuffix = new System.Windows.Forms.Label();
this.checkBoxChainingGapAfterShotChanges = new System.Windows.Forms.CheckBox();
this.numericUpDownChainingGap = new System.Windows.Forms.NumericUpDown();
this.labelChainingGapInstruction = new System.Windows.Forms.Label();
this.labelChainingGapSuffix = new System.Windows.Forms.Label();
this.labelChainingGap = new System.Windows.Forms.Label();
this.labelOffsetInstruction = new System.Windows.Forms.Label();
this.labelOffsetSuffix = new System.Windows.Forms.Label();
this.numericUpDownOffset = new System.Windows.Forms.NumericUpDown();
this.labelOffset = new System.Windows.Forms.Label();
this.labelSafeZoneInstruction = new System.Windows.Forms.Label();
this.labelSafeZoneSuffix = new System.Windows.Forms.Label();
this.numericUpDownSafeZone = new System.Windows.Forms.NumericUpDown();
this.comboBoxOutCues = new System.Windows.Forms.ComboBox();
this.comboBoxInCues = new System.Windows.Forms.ComboBox();
this.labelOutCues = new System.Windows.Forms.Label();
this.labelInCues = new System.Windows.Forms.Label();
this.labelSafeZone = new System.Windows.Forms.Label();
this.labelGapInstruction = new System.Windows.Forms.Label();
this.labelGapHint = new System.Windows.Forms.Label();
this.labelGapSuffix = new System.Windows.Forms.Label();
this.numericUpDownGap = new System.Windows.Forms.NumericUpDown();
this.labelGap = new System.Windows.Forms.Label();
this.toolTipChaining = new System.Windows.Forms.ToolTip(this.components);
this.buttonLoadNetflixRules = new System.Windows.Forms.Button();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxChainingInfo)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownChainingGapAfterShotChanges)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownChainingGap)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownOffset)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownSafeZone)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownGap)).BeginInit();
this.SuspendLayout();
//
// buttonCancel
//
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonCancel.Location = new System.Drawing.Point(463, 527);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 101;
this.buttonCancel.Text = "Cancel";
this.buttonCancel.UseVisualStyleBackColor = true;
//
// buttonOK
//
this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK;
this.buttonOK.Location = new System.Drawing.Point(382, 527);
this.buttonOK.Name = "buttonOK";
this.buttonOK.Size = new System.Drawing.Size(75, 23);
this.buttonOK.TabIndex = 100;
this.buttonOK.Text = "OK";
this.buttonOK.UseVisualStyleBackColor = true;
this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
//
// labelInstructions
//
this.labelInstructions.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.labelInstructions.AutoSize = true;
this.labelInstructions.Location = new System.Drawing.Point(9, 9);
this.labelInstructions.Name = "labelInstructions";
this.labelInstructions.Size = new System.Drawing.Size(399, 15);
this.labelInstructions.TabIndex = 1;
this.labelInstructions.Text = "Enter these basic rules, and the current profile will be updated accordingly.";
//
// groupBox1
//
this.groupBox1.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.groupBox1.Controls.Add(this.checkBoxSnapClosestCue);
this.groupBox1.Controls.Add(this.pictureBoxChainingInfo);
this.groupBox1.Controls.Add(this.labelChainingGapAfterShotChangesPrefix);
this.groupBox1.Controls.Add(this.numericUpDownChainingGapAfterShotChanges);
this.groupBox1.Controls.Add(this.labelChainingGapAfterShotChangesSuffix);
this.groupBox1.Controls.Add(this.checkBoxChainingGapAfterShotChanges);
this.groupBox1.Controls.Add(this.numericUpDownChainingGap);
this.groupBox1.Controls.Add(this.labelChainingGapInstruction);
this.groupBox1.Controls.Add(this.labelChainingGapSuffix);
this.groupBox1.Controls.Add(this.labelChainingGap);
this.groupBox1.Controls.Add(this.labelOffsetInstruction);
this.groupBox1.Controls.Add(this.labelOffsetSuffix);
this.groupBox1.Controls.Add(this.numericUpDownOffset);
this.groupBox1.Controls.Add(this.labelOffset);
this.groupBox1.Controls.Add(this.labelSafeZoneInstruction);
this.groupBox1.Controls.Add(this.labelSafeZoneSuffix);
this.groupBox1.Controls.Add(this.numericUpDownSafeZone);
this.groupBox1.Controls.Add(this.comboBoxOutCues);
this.groupBox1.Controls.Add(this.comboBoxInCues);
this.groupBox1.Controls.Add(this.labelOutCues);
this.groupBox1.Controls.Add(this.labelInCues);
this.groupBox1.Controls.Add(this.labelSafeZone);
this.groupBox1.Controls.Add(this.labelGapInstruction);
this.groupBox1.Controls.Add(this.labelGapHint);
this.groupBox1.Controls.Add(this.labelGapSuffix);
this.groupBox1.Controls.Add(this.numericUpDownGap);
this.groupBox1.Controls.Add(this.labelGap);
this.groupBox1.Location = new System.Drawing.Point(12, 27);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(525, 490);
this.groupBox1.TabIndex = 2;
this.groupBox1.TabStop = false;
//
// checkBoxSnapClosestCue
//
this.checkBoxSnapClosestCue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.checkBoxSnapClosestCue.Checked = true;
this.checkBoxSnapClosestCue.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBoxSnapClosestCue.Location = new System.Drawing.Point(134, 157);
this.checkBoxSnapClosestCue.Name = "checkBoxSnapClosestCue";
this.checkBoxSnapClosestCue.Size = new System.Drawing.Size(377, 35);
this.checkBoxSnapClosestCue.TabIndex = 10;
this.checkBoxSnapClosestCue.Text = "For connected subtitles, snap the in or out cue to the shot change based on which" +
" one is closer";
this.checkBoxSnapClosestCue.UseVisualStyleBackColor = true;
//
// pictureBoxChainingInfo
//
this.pictureBoxChainingInfo.Image = ((System.Drawing.Image)(resources.GetObject("pictureBoxChainingInfo.Image")));
this.pictureBoxChainingInfo.Location = new System.Drawing.Point(15, 381);
this.pictureBoxChainingInfo.Name = "pictureBoxChainingInfo";
this.pictureBoxChainingInfo.Size = new System.Drawing.Size(16, 16);
this.pictureBoxChainingInfo.TabIndex = 31;
this.pictureBoxChainingInfo.TabStop = false;
//
// labelChainingGapAfterShotChangesPrefix
//
this.labelChainingGapAfterShotChangesPrefix.AutoSize = true;
this.labelChainingGapAfterShotChangesPrefix.Location = new System.Drawing.Point(150, 447);
this.labelChainingGapAfterShotChangesPrefix.Name = "labelChainingGapAfterShotChangesPrefix";
this.labelChainingGapAfterShotChangesPrefix.Size = new System.Drawing.Size(33, 15);
this.labelChainingGapAfterShotChangesPrefix.TabIndex = 24;
this.labelChainingGapAfterShotChangesPrefix.Text = "Max.";
//
// numericUpDownChainingGapAfterShotChanges
//
this.numericUpDownChainingGapAfterShotChanges.Location = new System.Drawing.Point(193, 444);
this.numericUpDownChainingGapAfterShotChanges.Maximum = new decimal(new int[] {
2000,
0,
0,
0});
this.numericUpDownChainingGapAfterShotChanges.Name = "numericUpDownChainingGapAfterShotChanges";
this.numericUpDownChainingGapAfterShotChanges.Size = new System.Drawing.Size(52, 23);
this.numericUpDownChainingGapAfterShotChanges.TabIndex = 25;
this.numericUpDownChainingGapAfterShotChanges.Value = new decimal(new int[] {
500,
0,
0,
0});
//
// labelChainingGapAfterShotChangesSuffix
//
this.labelChainingGapAfterShotChangesSuffix.AutoSize = true;
this.labelChainingGapAfterShotChangesSuffix.Location = new System.Drawing.Point(251, 447);
this.labelChainingGapAfterShotChangesSuffix.Name = "labelChainingGapAfterShotChangesSuffix";
this.labelChainingGapAfterShotChangesSuffix.Size = new System.Drawing.Size(23, 15);
this.labelChainingGapAfterShotChangesSuffix.TabIndex = 26;
this.labelChainingGapAfterShotChangesSuffix.Text = "ms";
//
// checkBoxChainingGapAfterShotChanges
//
this.checkBoxChainingGapAfterShotChanges.AutoSize = true;
this.checkBoxChainingGapAfterShotChanges.Checked = true;
this.checkBoxChainingGapAfterShotChanges.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBoxChainingGapAfterShotChanges.Location = new System.Drawing.Point(134, 422);
this.checkBoxChainingGapAfterShotChanges.Name = "checkBoxChainingGapAfterShotChanges";
this.checkBoxChainingGapAfterShotChanges.Size = new System.Drawing.Size(334, 19);
this.checkBoxChainingGapAfterShotChanges.TabIndex = 23;
this.checkBoxChainingGapAfterShotChanges.Text = "After an out cue on a shot change, the gap may be smaller";
this.checkBoxChainingGapAfterShotChanges.UseVisualStyleBackColor = true;
this.checkBoxChainingGapAfterShotChanges.CheckedChanged += new System.EventHandler(this.checkBoxChainingGapAfterShotChanges_CheckedChanged);
//
// numericUpDownChainingGap
//
this.numericUpDownChainingGap.Location = new System.Drawing.Point(134, 352);
this.numericUpDownChainingGap.Maximum = new decimal(new int[] {
2000,
0,
0,
0});
this.numericUpDownChainingGap.Name = "numericUpDownChainingGap";
this.numericUpDownChainingGap.Size = new System.Drawing.Size(52, 23);
this.numericUpDownChainingGap.TabIndex = 20;
this.numericUpDownChainingGap.Value = new decimal(new int[] {
1000,
0,
0,
0});
//
// labelChainingGapInstruction
//
this.labelChainingGapInstruction.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.labelChainingGapInstruction.ForeColor = System.Drawing.SystemColors.GrayText;
this.labelChainingGapInstruction.Location = new System.Drawing.Point(131, 381);
this.labelChainingGapInstruction.Name = "labelChainingGapInstruction";
this.labelChainingGapInstruction.Size = new System.Drawing.Size(380, 30);
this.labelChainingGapInstruction.TabIndex = 22;
this.labelChainingGapInstruction.Text = "If the space between two subtitles is smaller than this amount, the subtitles wil" +
"l be connected.";
//
// labelChainingGapSuffix
//
this.labelChainingGapSuffix.AutoSize = true;
this.labelChainingGapSuffix.Location = new System.Drawing.Point(192, 355);
this.labelChainingGapSuffix.Name = "labelChainingGapSuffix";
this.labelChainingGapSuffix.Size = new System.Drawing.Size(23, 15);
this.labelChainingGapSuffix.TabIndex = 21;
this.labelChainingGapSuffix.Text = "ms";
//
// labelChainingGap
//
this.labelChainingGap.AutoSize = true;
this.labelChainingGap.Location = new System.Drawing.Point(12, 355);
this.labelChainingGap.Name = "labelChainingGap";
this.labelChainingGap.Size = new System.Drawing.Size(108, 15);
this.labelChainingGap.TabIndex = 19;
this.labelChainingGap.Text = "Max. chaining gap:";
//
// labelOffsetInstruction
//
this.labelOffsetInstruction.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.labelOffsetInstruction.ForeColor = System.Drawing.SystemColors.GrayText;
this.labelOffsetInstruction.Location = new System.Drawing.Point(131, 237);
this.labelOffsetInstruction.Name = "labelOffsetInstruction";
this.labelOffsetInstruction.Size = new System.Drawing.Size(380, 30);
this.labelOffsetInstruction.TabIndex = 14;
this.labelOffsetInstruction.Text = "Cues within this distance from shot changes will be considered as being on the sh" +
"ot change.";
//
// labelOffsetSuffix
//
this.labelOffsetSuffix.AutoSize = true;
this.labelOffsetSuffix.Location = new System.Drawing.Point(192, 211);
this.labelOffsetSuffix.Name = "labelOffsetSuffix";
this.labelOffsetSuffix.Size = new System.Drawing.Size(43, 15);
this.labelOffsetSuffix.TabIndex = 13;
this.labelOffsetSuffix.Text = "frames";
//
// numericUpDownOffset
//
this.numericUpDownOffset.Location = new System.Drawing.Point(134, 208);
this.numericUpDownOffset.Maximum = new decimal(new int[] {
50,
0,
0,
0});
this.numericUpDownOffset.Name = "numericUpDownOffset";
this.numericUpDownOffset.Size = new System.Drawing.Size(52, 23);
this.numericUpDownOffset.TabIndex = 12;
this.numericUpDownOffset.Value = new decimal(new int[] {
3,
0,
0,
0});
//
// labelOffset
//
this.labelOffset.AutoSize = true;
this.labelOffset.Location = new System.Drawing.Point(12, 211);
this.labelOffset.Name = "labelOffset";
this.labelOffset.Size = new System.Drawing.Size(69, 15);
this.labelOffset.TabIndex = 11;
this.labelOffset.Text = "Max. offset:";
//
// labelSafeZoneInstruction
//
this.labelSafeZoneInstruction.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.labelSafeZoneInstruction.ForeColor = System.Drawing.SystemColors.GrayText;
this.labelSafeZoneInstruction.Location = new System.Drawing.Point(131, 309);
this.labelSafeZoneInstruction.Name = "labelSafeZoneInstruction";
this.labelSafeZoneInstruction.Size = new System.Drawing.Size(380, 30);
this.labelSafeZoneInstruction.TabIndex = 18;
this.labelSafeZoneInstruction.Text = "The amount of frames around shot changes where no cues are allowed.";
//
// labelSafeZoneSuffix
//
this.labelSafeZoneSuffix.AutoSize = true;
this.labelSafeZoneSuffix.Location = new System.Drawing.Point(192, 283);
this.labelSafeZoneSuffix.Name = "labelSafeZoneSuffix";
this.labelSafeZoneSuffix.Size = new System.Drawing.Size(43, 15);
this.labelSafeZoneSuffix.TabIndex = 17;
this.labelSafeZoneSuffix.Text = "frames";
//
// numericUpDownSafeZone
//
this.numericUpDownSafeZone.Location = new System.Drawing.Point(134, 280);
this.numericUpDownSafeZone.Maximum = new decimal(new int[] {
50,
0,
0,
0});
this.numericUpDownSafeZone.Name = "numericUpDownSafeZone";
this.numericUpDownSafeZone.Size = new System.Drawing.Size(52, 23);
this.numericUpDownSafeZone.TabIndex = 16;
this.numericUpDownSafeZone.Value = new decimal(new int[] {
6,
0,
0,
0});
//
// comboBoxOutCues
//
this.comboBoxOutCues.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.comboBoxOutCues.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxOutCues.FormattingEnabled = true;
this.comboBoxOutCues.Items.AddRange(new object[] {
"On the shot change",
"1 frame before the shot change",
"2 frames before the shot change",
"3 frames before the shot change",
"The same amount of frames as the gap before the shot change"});
this.comboBoxOutCues.Location = new System.Drawing.Point(134, 118);
this.comboBoxOutCues.Name = "comboBoxOutCues";
this.comboBoxOutCues.Size = new System.Drawing.Size(377, 23);
this.comboBoxOutCues.TabIndex = 9;
this.comboBoxOutCues.SelectedIndexChanged += new System.EventHandler(this.comboBoxInCues_SelectedIndexChanged);
//
// comboBoxInCues
//
this.comboBoxInCues.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.comboBoxInCues.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxInCues.FormattingEnabled = true;
this.comboBoxInCues.Items.AddRange(new object[] {
"On the shot change",
"1 frame after the shot change",
"2 frames after the shot change",
"3 frames after the shot change"});
this.comboBoxInCues.Location = new System.Drawing.Point(134, 79);
this.comboBoxInCues.Name = "comboBoxInCues";
this.comboBoxInCues.Size = new System.Drawing.Size(377, 23);
this.comboBoxInCues.TabIndex = 7;
this.comboBoxInCues.SelectedIndexChanged += new System.EventHandler(this.comboBoxInCues_SelectedIndexChanged);
//
// labelOutCues
//
this.labelOutCues.AutoSize = true;
this.labelOutCues.Location = new System.Drawing.Point(12, 121);
this.labelOutCues.Name = "labelOutCues";
this.labelOutCues.Size = new System.Drawing.Size(112, 15);
this.labelOutCues.TabIndex = 8;
this.labelOutCues.Text = "Out cues should be:";
//
// labelInCues
//
this.labelInCues.AutoSize = true;
this.labelInCues.Location = new System.Drawing.Point(12, 82);
this.labelInCues.Name = "labelInCues";
this.labelInCues.Size = new System.Drawing.Size(102, 15);
this.labelInCues.TabIndex = 6;
this.labelInCues.Text = "In cues should be:";
//
// labelSafeZone
//
this.labelSafeZone.AutoSize = true;
this.labelSafeZone.Location = new System.Drawing.Point(12, 283);
this.labelSafeZone.Name = "labelSafeZone";
this.labelSafeZone.Size = new System.Drawing.Size(60, 15);
this.labelSafeZone.TabIndex = 15;
this.labelSafeZone.Text = "Safe zone:";
//
// labelGapInstruction
//
this.labelGapInstruction.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.labelGapInstruction.ForeColor = System.Drawing.SystemColors.GrayText;
this.labelGapInstruction.Location = new System.Drawing.Point(131, 51);
this.labelGapInstruction.Name = "labelGapInstruction";
this.labelGapInstruction.Size = new System.Drawing.Size(380, 15);
this.labelGapInstruction.TabIndex = 5;
this.labelGapInstruction.Text = "The minimum amount of space between subtitles.";
//
// labelGapHint
//
this.labelGapHint.AutoSize = true;
this.labelGapHint.ForeColor = System.Drawing.SystemColors.ButtonShadow;
this.labelGapHint.Location = new System.Drawing.Point(250, 25);
this.labelGapHint.Name = "labelGapHint";
this.labelGapHint.Size = new System.Drawing.Size(95, 15);
this.labelGapHint.TabIndex = 4;
this.labelGapHint.Text = "120 ms @ 25 FPS";
//
// labelGapSuffix
//
this.labelGapSuffix.AutoSize = true;
this.labelGapSuffix.Location = new System.Drawing.Point(192, 25);
this.labelGapSuffix.Name = "labelGapSuffix";
this.labelGapSuffix.Size = new System.Drawing.Size(43, 15);
this.labelGapSuffix.TabIndex = 3;
this.labelGapSuffix.Text = "frames";
//
// numericUpDownGap
//
this.numericUpDownGap.Location = new System.Drawing.Point(134, 22);
this.numericUpDownGap.Maximum = new decimal(new int[] {
10,
0,
0,
0});
this.numericUpDownGap.Name = "numericUpDownGap";
this.numericUpDownGap.Size = new System.Drawing.Size(52, 23);
this.numericUpDownGap.TabIndex = 2;
this.numericUpDownGap.Value = new decimal(new int[] {
3,
0,
0,
0});
this.numericUpDownGap.ValueChanged += new System.EventHandler(this.numericUpDownGap_ValueChanged);
//
// labelGap
//
this.labelGap.AutoSize = true;
this.labelGap.Location = new System.Drawing.Point(12, 25);
this.labelGap.Name = "labelGap";
this.labelGap.Size = new System.Drawing.Size(31, 15);
this.labelGap.TabIndex = 1;
this.labelGap.Text = "Gap:";
//
// toolTipChaining
//
this.toolTipChaining.IsBalloon = true;
this.toolTipChaining.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info;
//
// buttonLoadNetflixRules
//
this.buttonLoadNetflixRules.Location = new System.Drawing.Point(11, 527);
this.buttonLoadNetflixRules.Name = "buttonLoadNetflixRules";
this.buttonLoadNetflixRules.Size = new System.Drawing.Size(169, 23);
this.buttonLoadNetflixRules.TabIndex = 102;
this.buttonLoadNetflixRules.Text = "Load Netflix rules";
this.buttonLoadNetflixRules.UseVisualStyleBackColor = true;
this.buttonLoadNetflixRules.Click += new System.EventHandler(this.buttonLoadNetflixRules_Click);
//
// BeautifyTimeCodesProfileSimple
//
this.AcceptButton = this.buttonOK;
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.buttonCancel;
this.ClientSize = new System.Drawing.Size(549, 562);
this.Controls.Add(this.buttonLoadNetflixRules);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.labelInstructions);
this.Controls.Add(this.buttonCancel);
this.Controls.Add(this.buttonOK);
this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "BeautifyTimeCodesProfileSimple";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "BeautifyTimeCodesProfileSimple";
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxChainingInfo)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownChainingGapAfterShotChanges)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownChainingGap)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownOffset)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownSafeZone)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownGap)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button buttonCancel;
private System.Windows.Forms.Button buttonOK;
private System.Windows.Forms.Label labelInstructions;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Label labelGap;
private System.Windows.Forms.NumericUpDown numericUpDownGap;
private System.Windows.Forms.Label labelGapHint;
private System.Windows.Forms.Label labelGapSuffix;
private System.Windows.Forms.Label labelGapInstruction;
private System.Windows.Forms.ComboBox comboBoxOutCues;
private System.Windows.Forms.ComboBox comboBoxInCues;
private System.Windows.Forms.Label labelOutCues;
private System.Windows.Forms.Label labelInCues;
private System.Windows.Forms.Label labelSafeZone;
private System.Windows.Forms.Label labelOffsetInstruction;
private System.Windows.Forms.Label labelOffsetSuffix;
private System.Windows.Forms.NumericUpDown numericUpDownOffset;
private System.Windows.Forms.Label labelOffset;
private System.Windows.Forms.Label labelSafeZoneInstruction;
private System.Windows.Forms.Label labelSafeZoneSuffix;
private System.Windows.Forms.NumericUpDown numericUpDownSafeZone;
private System.Windows.Forms.Label labelChainingGapInstruction;
private System.Windows.Forms.Label labelChainingGapSuffix;
private System.Windows.Forms.Label labelChainingGap;
private System.Windows.Forms.NumericUpDown numericUpDownChainingGap;
private System.Windows.Forms.CheckBox checkBoxChainingGapAfterShotChanges;
private System.Windows.Forms.NumericUpDown numericUpDownChainingGapAfterShotChanges;
private System.Windows.Forms.Label labelChainingGapAfterShotChangesSuffix;
private System.Windows.Forms.Label labelChainingGapAfterShotChangesPrefix;
private System.Windows.Forms.PictureBox pictureBoxChainingInfo;
private System.Windows.Forms.ToolTip toolTipChaining;
private System.Windows.Forms.CheckBox checkBoxSnapClosestCue;
private System.Windows.Forms.Button buttonLoadNetflixRules;
}
}

View File

@ -0,0 +1,184 @@
using Nikse.SubtitleEdit.Core.Common;
using Nikse.SubtitleEdit.Logic;
using System;
using System.Windows.Forms;
using Nikse.SubtitleEdit.Core.Forms;
using Nikse.SubtitleEdit.Core.SubtitleFormats;
namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
{
public partial class BeautifyTimeCodesProfileSimple : Form
{
private readonly double _frameRate;
public BeautifyTimeCodesProfileSimple(double frameRate)
{
_frameRate = frameRate;
UiUtil.PreInitialize(this);
InitializeComponent();
UiUtil.FixFonts(this);
var language = LanguageSettings.Current.BeautifyTimeCodesProfile;
Text = language.CreateSimpleTitle;
labelInstructions.Text = language.CreateSimpleInstruction;
labelGap.Text = language.Gap;
labelGapSuffix.Text = language.Frames;
labelGapInstruction.Text = language.CreateSimpleGapInstruction;
labelInCues.Text = language.CreateSimpleInCues;
comboBoxInCues.Items.Clear();
comboBoxInCues.Items.Add(language.CreateSimpleInCues0Frames);
comboBoxInCues.Items.Add(language.CreateSimpleInCues1Frames);
comboBoxInCues.Items.Add(language.CreateSimpleInCues2Frames);
comboBoxInCues.Items.Add(language.CreateSimpleInCues3Frames);
comboBoxInCues.SelectedIndex = 0;
labelOutCues.Text = language.CreateSimpleOutCues;
comboBoxOutCues.Items.Clear();
comboBoxOutCues.Items.Add(language.CreateSimpleOutCues0Frames);
comboBoxOutCues.Items.Add(language.CreateSimpleOutCues1Frames);
comboBoxOutCues.Items.Add(language.CreateSimpleOutCues2Frames);
comboBoxOutCues.Items.Add(language.CreateSimpleOutCues3Frames);
comboBoxOutCues.Items.Add(language.CreateSimpleOutCuesGap);
comboBoxOutCues.SelectedIndex = 0;
checkBoxSnapClosestCue.Text = language.CreateSimpleSnapClosestCue;
checkBoxSnapClosestCue.Checked = true;
labelOffset.Text = language.CreateSimpleMaxOffset;
labelOffsetSuffix.Text = language.Frames;
labelOffsetInstruction.Text = language.CreateSimpleMaxOffsetInstruction;
labelSafeZone.Text = language.CreateSimpleSafeZone;
labelSafeZoneSuffix.Text = language.Frames;
labelSafeZoneInstruction.Text = language.CreateSimpleSafeZoneInstruction;
labelChainingGap.Text = language.CreateSimpleChainingGap;
labelChainingGapSuffix.Text = language.Milliseconds;
labelChainingGapInstruction.Text = language.CreateSimpleChainingGapInstruction;
checkBoxChainingGapAfterShotChanges.Text = language.CreateSimpleChainingGapAfterShotChanges;
labelChainingGapAfterShotChangesPrefix.Text = language.Maximum;
labelChainingGapAfterShotChangesSuffix.Text = language.Milliseconds;
toolTipChaining.SetToolTip(pictureBoxChainingInfo, language.CreateSimpleChainingToolTip);
buttonLoadNetflixRules.Text = language.CreateSimpleLoadNetflixRules;
buttonOK.Text = LanguageSettings.Current.General.Ok;
buttonCancel.Text = LanguageSettings.Current.General.Cancel;
UiUtil.FixLargeFonts(this, buttonOK);
RefreshControls();
}
private void RefreshControls()
{
numericUpDownGap_ValueChanged(numericUpDownGap, EventArgs.Empty);
checkBoxChainingGapAfterShotChanges_CheckedChanged(checkBoxChainingGapAfterShotChanges, EventArgs.Empty);
comboBoxInCues_SelectedIndexChanged(comboBoxInCues, EventArgs.Empty);
}
private void buttonOK_Click(object sender, EventArgs e)
{
// Validation
if (numericUpDownSafeZone.Value < numericUpDownOffset.Value)
{
MessageBox.Show(this, LanguageSettings.Current.BeautifyTimeCodesProfile.OffsetSafeZoneError, LanguageSettings.Current.General.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
DialogResult = DialogResult.None;
return;
}
// Save settings
var gap = Convert.ToInt32(numericUpDownGap.Value);
var inCuesGap = comboBoxInCues.SelectedIndex;
var outCuesGap = comboBoxOutCues.SelectedIndex;
if (comboBoxOutCues.SelectedIndex == comboBoxOutCues.Items.Count - 1)
{
outCuesGap = gap;
}
var redZone = Convert.ToInt32(numericUpDownOffset.Value);
var greenZone = Convert.ToInt32(numericUpDownSafeZone.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.Gap = Convert.ToInt32(numericUpDownGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap = inCuesGap;
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesLeftGreenZone = greenZone;
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesLeftRedZone = redZone;
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesRightRedZone = redZone;
Configuration.Settings.BeautifyTimeCodes.Profile.InCuesRightGreenZone = greenZone;
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap = outCuesGap;
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesLeftGreenZone = greenZone;
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesLeftRedZone = redZone;
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesRightRedZone = redZone;
Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesRightGreenZone = greenZone;
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestLeftGap = Math.Max(gap, outCuesGap);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestRightGap = inCuesGap;
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestLeftGap = checkBoxSnapClosestCue.Checked ? inCuesGap : Math.Max(gap, outCuesGap);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestRightGap = checkBoxSnapClosestCue.Checked ? Math.Max(gap, outCuesGap) : inCuesGap;
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftGreenZone = greenZone;
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftRedZone = redZone;
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightRedZone = redZone;
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightGreenZone = greenZone;
var treadConnectedMs = Math.Round(SubtitleFormat.FramesToMilliseconds(gap, _frameRate) * 1.5);
Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesTreatConnected = Convert.ToInt32(treadConnectedMs);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralUseZones = false;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap = Convert.ToInt32(numericUpDownChainingGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone = GetChainingZoneFrames(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftRedZone = GetChainingZoneFrames(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap) - 1;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior = BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum.ExtendUntilShotChange;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotUseZones = false;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap = Convert.ToInt32(numericUpDownChainingGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftGreenZone = GetChainingZoneFrames(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftRedZone = GetChainingZoneFrames(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap) - 1;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotUseZones = false;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap = checkBoxChainingGapAfterShotChanges.Checked ? Convert.ToInt32(numericUpDownChainingGapAfterShotChanges.Value) : Convert.ToInt32(numericUpDownChainingGap.Value);
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightRedZone = GetChainingZoneFrames(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap) - 1;
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone = GetChainingZoneFrames(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap);
DialogResult = DialogResult.OK;
}
private int GetChainingZoneFrames(double valueMs)
{
var frameDurationMs = TimeCodesBeautifierUtils.GetFrameDurationMs(_frameRate);
return Convert.ToInt32(Math.Floor(valueMs / frameDurationMs));
}
private void numericUpDownGap_ValueChanged(object sender, EventArgs e)
{
int gapFrames = Convert.ToInt32(numericUpDownGap.Value);
double gapMs = SubtitleFormat.FramesToMilliseconds(gapFrames, _frameRate);
labelGapHint.Text = string.Format(LanguageSettings.Current.BeautifyTimeCodesProfile.GapInMsFormat, Math.Round(gapMs), Math.Round(_frameRate, 3));
}
private void checkBoxChainingGapAfterShotChanges_CheckedChanged(object sender, EventArgs e)
{
labelChainingGapAfterShotChangesPrefix.Enabled = checkBoxChainingGapAfterShotChanges.Checked;
numericUpDownChainingGapAfterShotChanges.Enabled = checkBoxChainingGapAfterShotChanges.Checked;
labelChainingGapAfterShotChangesSuffix.Enabled = checkBoxChainingGapAfterShotChanges.Checked;
}
private void comboBoxInCues_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBoxInCues.SelectedIndex != 0 || comboBoxOutCues.SelectedIndex != 0)
{
checkBoxSnapClosestCue.Checked = false;
}
}
private void buttonLoadNetflixRules_Click(object sender, EventArgs e)
{
numericUpDownGap.Value = 2;
comboBoxInCues.SelectedIndex = 0;
comboBoxOutCues.SelectedIndex = 2;
checkBoxSnapClosestCue.Checked = false;
numericUpDownOffset.Value = 7;
numericUpDownSafeZone.Value = 12;
numericUpDownChainingGap.Value = 500;
checkBoxChainingGapAfterShotChanges.Checked = false;
RefreshControls();
}
}
}

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
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
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<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
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
mimetype set.
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
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
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
: 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
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="pictureBoxChainingInfo.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAANVJREFUOE+l
k1EOgjAQRPuLpwHPRc8DwmXUUwg3kQ/1TVk1oSsS3eTFZmdmaYuEZdV1XcYYG7jA1Rjoq1eaLS8MBYYD
3ODugUeaPIXF5rLw8Wn8Bv4Tv+8hNDQ1M5ocPI1Ml0QWJbjbTgbK05SBSgN0OZlhI42mD4vmZnj4oB3o
NbkGO4F7BEF2kvjfAG3DE4Xl1waMEj9eouXXBrTaQQW/vsZ9MrDoPFMSKU8j05ucDAUN/T0zowfeM7jf
Qw+rHxP0sLNYXoi6kxZGQpOhdQvzmV8VwgNvzMGlpptvoQAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="toolTipChaining.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -68,6 +68,7 @@ namespace Nikse.SubtitleEdit.Forms
this.toolStripButtonAssAttachments = new System.Windows.Forms.ToolStripButton();
this.toolStripButtonAssaDraw = new System.Windows.Forms.ToolStripButton();
this.toolStripButtonNetflixQualityCheck = new System.Windows.Forms.ToolStripButton();
this.toolStripButtonBeautifyTimeCodes = new System.Windows.Forms.ToolStripButton();
this.toolStripButtonSettings = new System.Windows.Forms.ToolStripButton();
this.toolStripSeparatorHelp = new System.Windows.Forms.ToolStripSeparator();
this.toolStripButtonHelp = new System.Windows.Forms.ToolStripButton();
@ -207,6 +208,8 @@ namespace Nikse.SubtitleEdit.Forms
this.descendingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.listErrorsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.netflixQualityCheckToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator27 = new System.Windows.Forms.ToolStripSeparator();
this.toolStripMenuItemBeautifyTimeCodes = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator22 = new System.Windows.Forms.ToolStripSeparator();
this.toolStripMenuItemMakeEmptyFromCurrent = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItemBatchConvert = new System.Windows.Forms.ToolStripMenuItem();
@ -694,6 +697,7 @@ namespace Nikse.SubtitleEdit.Forms
this.toolStripButtonAssAttachments,
this.toolStripButtonAssaDraw,
this.toolStripButtonNetflixQualityCheck,
this.toolStripButtonBeautifyTimeCodes,
this.toolStripButtonSettings,
this.toolStripSeparatorHelp,
this.toolStripButtonHelp,
@ -938,6 +942,17 @@ namespace Nikse.SubtitleEdit.Forms
this.toolStripButtonNetflixQualityCheck.Text = "Netflix quality check";
this.toolStripButtonNetflixQualityCheck.Click += new System.EventHandler(this.toolStripButtonNetflixGlyphCheck_Click);
//
// toolStripButtonBeautifyTimeCodes
//
this.toolStripButtonBeautifyTimeCodes.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.toolStripButtonBeautifyTimeCodes.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButtonBeautifyTimeCodes.Image")));
this.toolStripButtonBeautifyTimeCodes.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
this.toolStripButtonBeautifyTimeCodes.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripButtonBeautifyTimeCodes.Name = "toolStripButtonBeautifyTimeCodes";
this.toolStripButtonBeautifyTimeCodes.Size = new System.Drawing.Size(36, 37);
this.toolStripButtonBeautifyTimeCodes.Text = "Beautify time codes...";
this.toolStripButtonBeautifyTimeCodes.Click += new System.EventHandler(this.toolStripButtonBeautifyTimeCodes_Click);
//
// toolStripButtonSettings
//
this.toolStripButtonSettings.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
@ -1826,6 +1841,8 @@ namespace Nikse.SubtitleEdit.Forms
this.toolStripMenuItemSortBy,
this.listErrorsToolStripMenuItem,
this.netflixQualityCheckToolStripMenuItem,
this.toolStripSeparator27,
this.toolStripMenuItemBeautifyTimeCodes,
this.toolStripSeparator22,
this.toolStripMenuItemMakeEmptyFromCurrent,
this.toolStripMenuItemBatchConvert,
@ -2088,6 +2105,18 @@ namespace Nikse.SubtitleEdit.Forms
this.netflixQualityCheckToolStripMenuItem.Text = "Netflix quality check";
this.netflixQualityCheckToolStripMenuItem.Click += new System.EventHandler(this.netflixGlyphCheckToolStripMenuItem_Click);
//
// toolStripSeparator27
//
this.toolStripSeparator27.Name = "toolStripSeparator27";
this.toolStripSeparator27.Size = new System.Drawing.Size(335, 6);
//
// toolStripMenuItemBeautifyTimeCodes
//
this.toolStripMenuItemBeautifyTimeCodes.Name = "toolStripMenuItemBeautifyTimeCodes";
this.toolStripMenuItemBeautifyTimeCodes.Size = new System.Drawing.Size(338, 22);
this.toolStripMenuItemBeautifyTimeCodes.Text = "Beautify time codes...";
this.toolStripMenuItemBeautifyTimeCodes.Click += new System.EventHandler(this.toolStripMenuItemBeautifyTimeCodes_Click);
//
// toolStripSeparator22
//
this.toolStripSeparator22.Name = "toolStripSeparator22";
@ -6217,8 +6246,11 @@ namespace Nikse.SubtitleEdit.Forms
private System.Windows.Forms.ToolStripButton toolStripButtonAssStyleManager;
private System.Windows.Forms.ToolStripButton toolStripButtonAssProperties;
private System.Windows.Forms.ToolStripButton toolStripButtonAssAttachments;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemBeautifyTimeCodes;
private System.Windows.Forms.ToolStripButton toolStripButtonBeautifyTimeCodes;
private System.Windows.Forms.ToolStripMenuItem mergeSentencesToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator26;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator27;
private System.Windows.Forms.ToolStripMenuItem breaksplitLongLinesToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemSelectedLines;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemAutoBreakLines;

View File

@ -1727,6 +1727,8 @@ namespace Nikse.SubtitleEdit.Forms
listErrorsToolStripMenuItem.Text = _language.Menu.Tools.ListErrors;
netflixQualityCheckToolStripMenuItem.Text = _language.Menu.Tools.NetflixQualityCheck;
toolStripButtonNetflixQualityCheck.Text = _language.Menu.Tools.NetflixQualityCheck;
toolStripMenuItemBeautifyTimeCodes.Text = _language.Menu.Tools.BeautifyTimeCodes;
toolStripButtonBeautifyTimeCodes.Text = _language.Menu.Tools.BeautifyTimeCodes;
sortNumberToolStripMenuItem.Text = _language.Menu.Tools.Number;
sortStartTimeToolStripMenuItem.Text = _language.Menu.Tools.StartTime;
@ -5537,7 +5539,8 @@ namespace Nikse.SubtitleEdit.Forms
{
settings.Initialize(Icon, toolStripButtonFileNew.Image, toolStripButtonFileOpen.Image, toolStripButtonSave.Image, toolStripButtonSaveAs.Image, toolStripButtonFind.Image,
toolStripButtonReplace.Image, toolStripButtonFixCommonErrors.Image, toolStripButtonRemoveTextForHi.Image, toolStripButtonVisualSync.Image, toolStripButtonBurnIn.Image,
toolStripButtonSpellCheck.Image, toolStripButtonNetflixQualityCheck.Image, toolStripButtonSettings.Image, toolStripButtonHelp.Image, toolStripButtonSourceView.Image);
toolStripButtonSpellCheck.Image, toolStripButtonNetflixQualityCheck.Image, toolStripButtonBeautifyTimeCodes.Image, toolStripButtonSettings.Image, toolStripButtonHelp.Image,
toolStripButtonSourceView.Image);
if (settings.ShowDialog(this) == DialogResult.Cancel)
{
@ -6018,6 +6021,7 @@ namespace Nikse.SubtitleEdit.Forms
TryLoadIcon(toolStripButtonBurnIn, "BurnIn");
TryLoadIcon(toolStripButtonSpellCheck, "SpellCheck");
TryLoadIcon(toolStripButtonNetflixQualityCheck, "Netflix");
TryLoadIcon(toolStripButtonBeautifyTimeCodes, "BeautifyTimeCodes");
TryLoadIcon(toolStripButtonAssStyleManager, "AssaStyle");
TryLoadIcon(toolStripButtonAssProperties, "AssaProperties");
TryLoadIcon(toolStripButtonAssAttachments, "AssaAttachments");
@ -6053,6 +6057,7 @@ namespace Nikse.SubtitleEdit.Forms
toolStripButtonBurnIn.Visible = gs.ShowToolbarBurnIn;
toolStripButtonSpellCheck.Visible = gs.ShowToolbarSpellCheck;
toolStripButtonNetflixQualityCheck.Visible = gs.ShowToolbarNetflixGlyphCheck;
toolStripButtonBeautifyTimeCodes.Visible = gs.ShowToolbarBeautifyTimeCodes;
toolStripButtonSettings.Visible = gs.ShowToolbarSettings;
toolStripButtonHelp.Visible = gs.ShowToolbarHelp;
toolStripButtonSourceView.Visible = gs.ShowToolbarToggleSourceView;
@ -6068,7 +6073,7 @@ namespace Nikse.SubtitleEdit.Forms
toolStrip1.Visible = gs.ShowToolbarNew || gs.ShowToolbarOpen || gs.ShowToolbarSave || gs.ShowToolbarSaveAs || gs.ShowToolbarFind || gs.ShowToolbarReplace ||
gs.ShowToolbarFixCommonErrors || gs.ShowToolbarVisualSync || gs.ShowToolbarSpellCheck || gs.ShowToolbarNetflixGlyphCheck ||
gs.ShowToolbarSettings || gs.ShowToolbarHelp;
gs.ShowToolbarBeautifyTimeCodes || gs.ShowToolbarSettings || gs.ShowToolbarHelp;
UpdateToolbarButtonsToCurrentFormat(GetCurrentSubtitleFormat());
}
@ -7556,27 +7561,29 @@ namespace Nikse.SubtitleEdit.Forms
if (adjustDisplayTime.ShowDialog(this) == DialogResult.OK)
{
MakeHistoryForUndo(_language.BeforeDisplayTimeAdjustment);
List<double> shotChanges = adjustDisplayTime.CheckShotChanges ? audioVisualizer.ShotChanges : new List<double>();
if (adjustDisplayTime.AdjustUsingPercent)
{
double percent = double.Parse(adjustDisplayTime.AdjustValue);
_subtitle.AdjustDisplayTimeUsingPercent(percent, selectedIndices);
_subtitle.AdjustDisplayTimeUsingPercent(percent, selectedIndices, shotChanges, adjustDisplayTime.EnforceDurationLimits);
ShowStatus(string.Format(_language.DisplayTimesAdjustedX, double.Parse(adjustDisplayTime.AdjustValue, CultureInfo.InvariantCulture) + "%"));
}
else if (adjustDisplayTime.AdjustUsingSeconds)
{
double seconds = double.Parse(adjustDisplayTime.AdjustValue, CultureInfo.InvariantCulture);
_subtitle.AdjustDisplayTimeUsingSeconds(seconds, selectedIndices);
_subtitle.AdjustDisplayTimeUsingSeconds(seconds, selectedIndices, shotChanges, adjustDisplayTime.EnforceDurationLimits);
ShowStatus(string.Format(_language.DisplayTimesAdjustedX, double.Parse(adjustDisplayTime.AdjustValue, CultureInfo.InvariantCulture)));
}
else if (adjustDisplayTime.AdjustUsingRecalc)
{
double maxCharSeconds = (double)(adjustDisplayTime.MaxCharactersPerSecond);
_subtitle.RecalculateDisplayTimes(maxCharSeconds, selectedIndices, (double)adjustDisplayTime.OptimalCharactersPerSecond, adjustDisplayTime.ExtendOnly);
_subtitle.RecalculateDisplayTimes(maxCharSeconds, selectedIndices, (double)adjustDisplayTime.OptimalCharactersPerSecond, adjustDisplayTime.ExtendOnly, shotChanges, adjustDisplayTime.EnforceDurationLimits);
ShowStatus(string.Format(_language.DisplayTimesAdjustedX, adjustDisplayTime.AdjustValue));
}
else
{ // fixed duration
_subtitle.SetFixedDuration(selectedIndices, adjustDisplayTime.FixedMilliseconds);
_subtitle.SetFixedDuration(selectedIndices, adjustDisplayTime.FixedMilliseconds, shotChanges);
ShowStatus(string.Format(_language.DisplayTimesAdjustedX, adjustDisplayTime.FixedMilliseconds));
}
@ -18043,6 +18050,16 @@ namespace Nikse.SubtitleEdit.Forms
ExtendSelectedLinesToPreviousLine();
e.SuppressKeyPress = true;
}
else if (_shortcuts.MainAdjustExtendToNextSubtitleMinusChainingGap == e.KeyData)
{
ExtendSelectedLinesToNextLine(true);
e.SuppressKeyPress = true;
}
else if (_shortcuts.MainAdjustExtendToPreviousSubtitleMinusChainingGap == e.KeyData)
{
ExtendSelectedLinesToPreviousLine(true);
e.SuppressKeyPress = true;
}
else if (_shortcuts.MainAdjustExtendPreviousLineEndToCurrentStart == e.KeyData)
{
ExtendPreviousEndToCurrentStart();
@ -18058,41 +18075,21 @@ namespace Nikse.SubtitleEdit.Forms
SnapSelectedLinesStartToNextShotChange();
e.SuppressKeyPress = true;
}
else if (_shortcuts.MainAdjustSnapStartToNextShotChangeWithGap == e.KeyData)
{
SnapSelectedLinesStartToNextShotChange(true);
e.SuppressKeyPress = true;
}
else if (_shortcuts.MainAdjustSnapEndToPreviousShotChange == e.KeyData)
{
SnapSelectedLinesEndToPreviousShotChange();
e.SuppressKeyPress = true;
}
else if (_shortcuts.MainAdjustSnapEndToPreviousShotChangeWithGap == e.KeyData)
{
SnapSelectedLinesEndToPreviousShotChange(true);
e.SuppressKeyPress = true;
}
else if (_shortcuts.MainAdjustExtendToNextShotChange == e.KeyData)
{
ExtendSelectedLinesToNextShotChange();
e.SuppressKeyPress = true;
}
else if (_shortcuts.MainAdjustExtendToNextShotChangeWithGap == e.KeyData)
{
ExtendSelectedLinesToNextShotChange(true);
e.SuppressKeyPress = true;
}
else if (_shortcuts.MainAdjustExtendToPreviousShotChange == e.KeyData)
{
ExtendSelectedLinesToPreviousShotChange();
e.SuppressKeyPress = true;
}
else if (_shortcuts.MainAdjustExtendToPreviousShotChangeWithGap == e.KeyData)
{
ExtendSelectedLinesToPreviousShotChange(true);
e.SuppressKeyPress = true;
}
else if (e.KeyData == _shortcuts.MainListViewGoToNextError)
{
GoToNextSyntaxError();
@ -18646,8 +18643,34 @@ namespace Nikse.SubtitleEdit.Forms
}
}
private void ExtendSelectedLinesToNextLine()
private void ExtendSelectedLinesToNextLine(bool minusChainingGap = false)
{
double GetNextStartTimeMinusChainingGap(Paragraph next)
{
if (ShotChangeHelper.IsCueOnShotChange(audioVisualizer.ShotChanges, next.StartTime, true))
{
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotUseZones)
{
return next.StartTime.TotalMilliseconds - SubtitleFormat.FramesToMilliseconds(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftGreenZone);
}
else
{
return next.StartTime.TotalMilliseconds - Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap;
}
}
else
{
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralUseZones)
{
return next.StartTime.TotalMilliseconds - SubtitleFormat.FramesToMilliseconds(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone);
}
else
{
return next.StartTime.TotalMilliseconds - Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap;
}
}
}
var historyAdded = false;
foreach (ListViewItem selectedItem in SubtitleListview1.SelectedItems)
{
@ -18658,11 +18681,23 @@ namespace Nikse.SubtitleEdit.Forms
{
if (!historyAdded)
{
MakeHistoryForUndo(string.Format(_language.BeforeX, LanguageSettings.Current.Settings.AdjustExtendToNextSubtitle));
MakeHistoryForUndo(string.Format(_language.BeforeX, minusChainingGap ? LanguageSettings.Current.Settings.AdjustExtendToNextSubtitleMinusChainingGap : LanguageSettings.Current.Settings.AdjustExtendToNextSubtitle));
historyAdded = true;
}
p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - MinGapBetweenLines;
if (minusChainingGap)
{
p.EndTime.TotalMilliseconds = GetNextStartTimeMinusChainingGap(next);
}
else
{
p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - MinGapBetweenLines;
}
if (p.DurationTotalMilliseconds < 0)
{
p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds;
}
}
if (IsOriginalEditable)
@ -18675,11 +18710,23 @@ namespace Nikse.SubtitleEdit.Forms
{
if (!historyAdded)
{
MakeHistoryForUndo(string.Format(_language.BeforeX, LanguageSettings.Current.Settings.AdjustExtendToNextSubtitle));
MakeHistoryForUndo(string.Format(_language.BeforeX, minusChainingGap ? LanguageSettings.Current.Settings.AdjustExtendToNextSubtitleMinusChainingGap : LanguageSettings.Current.Settings.AdjustExtendToNextSubtitle));
historyAdded = true;
}
original.EndTime.TotalMilliseconds = originalNext.StartTime.TotalMilliseconds - MinGapBetweenLines;
if (minusChainingGap)
{
original.EndTime.TotalMilliseconds = GetNextStartTimeMinusChainingGap(originalNext);
}
else
{
original.EndTime.TotalMilliseconds = originalNext.StartTime.TotalMilliseconds - MinGapBetweenLines;
}
if (original.DurationTotalMilliseconds < 0)
{
original.EndTime.TotalMilliseconds = original.StartTime.TotalMilliseconds;
}
}
}
}
@ -18688,8 +18735,34 @@ namespace Nikse.SubtitleEdit.Forms
}
}
private void ExtendSelectedLinesToPreviousLine()
private void ExtendSelectedLinesToPreviousLine(bool minusChainingGap = false)
{
double GetPreviousEndTimePlusChainingGap(Paragraph previous)
{
if (ShotChangeHelper.IsCueOnShotChange(audioVisualizer.ShotChanges, previous.EndTime, false))
{
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotUseZones)
{
return previous.EndTime.TotalMilliseconds + SubtitleFormat.FramesToMilliseconds(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone);
}
else
{
return previous.EndTime.TotalMilliseconds + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap;
}
}
else
{
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralUseZones)
{
return previous.EndTime.TotalMilliseconds + SubtitleFormat.FramesToMilliseconds(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone);
}
else
{
return previous.EndTime.TotalMilliseconds + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap;
}
}
}
var historyAdded = false;
foreach (ListViewItem selectedItem in SubtitleListview1.SelectedItems)
{
@ -18708,22 +18781,46 @@ namespace Nikse.SubtitleEdit.Forms
{
if (!historyAdded)
{
MakeHistoryForUndo(string.Format(_language.BeforeX, LanguageSettings.Current.Settings.AdjustExtendToPreviousSubtitle));
MakeHistoryForUndo(string.Format(_language.BeforeX, minusChainingGap ? LanguageSettings.Current.Settings.AdjustExtendToPreviousSubtitleMinusChainingGap : LanguageSettings.Current.Settings.AdjustExtendToPreviousSubtitle));
historyAdded = true;
}
original.StartTime.TotalMilliseconds = originalPrevious.EndTime.TotalMilliseconds + MinGapBetweenLines;
if (minusChainingGap)
{
original.StartTime.TotalMilliseconds = GetPreviousEndTimePlusChainingGap(originalPrevious);
}
else
{
original.StartTime.TotalMilliseconds = originalPrevious.EndTime.TotalMilliseconds + MinGapBetweenLines;
}
if (original.DurationTotalMilliseconds < 0)
{
original.StartTime.TotalMilliseconds = original.EndTime.TotalMilliseconds;
}
}
}
}
if (!historyAdded)
{
MakeHistoryForUndo(string.Format(_language.BeforeX, LanguageSettings.Current.Settings.AdjustExtendToPreviousSubtitle));
MakeHistoryForUndo(string.Format(_language.BeforeX, minusChainingGap ? LanguageSettings.Current.Settings.AdjustExtendToPreviousSubtitleMinusChainingGap : LanguageSettings.Current.Settings.AdjustExtendToPreviousSubtitle));
historyAdded = true;
}
p.StartTime.TotalMilliseconds = previous.EndTime.TotalMilliseconds + MinGapBetweenLines;
if (minusChainingGap)
{
p.StartTime.TotalMilliseconds = GetPreviousEndTimePlusChainingGap(previous);
}
else
{
p.StartTime.TotalMilliseconds = previous.EndTime.TotalMilliseconds + MinGapBetweenLines;
}
if (p.DurationTotalMilliseconds < 0)
{
p.StartTime.TotalMilliseconds = p.EndTime.TotalMilliseconds;
}
}
RefreshSelectedParagraphs();
@ -18796,17 +18893,17 @@ namespace Nikse.SubtitleEdit.Forms
}
}
private void SnapSelectedLinesStartToNextShotChange(bool withGap = false)
private void SnapSelectedLinesStartToNextShotChange()
{
var historyAdded = false;
foreach (ListViewItem selectedItem in SubtitleListview1.SelectedItems)
{
var idx = selectedItem.Index;
var p = _subtitle.Paragraphs[idx];
List<double> nextShotChanges = audioVisualizer.ShotChanges.Count > 0 ? audioVisualizer.ShotChanges.Where(x => x > p.StartTime.TotalSeconds + 0.01).ToList() : new List<double>();
if (nextShotChanges.Count > 0)
var nextShotChange = ShotChangeHelper.GetNextShotChangeInMs(audioVisualizer.ShotChanges, p.StartTime);
if (nextShotChange != null)
{
double nearestShotChange = nextShotChanges.Aggregate((x, y) => Math.Abs(x - p.StartTime.TotalSeconds) < Math.Abs(y - p.StartTime.TotalSeconds) ? x : y);
var newStartTime = nextShotChange.Value + TimeCodesBeautifierUtils.GetInCuesGapMs();
if (IsOriginalEditable)
{
@ -18818,21 +18915,10 @@ namespace Nikse.SubtitleEdit.Forms
MakeHistoryForUndo(string.Format(_language.BeforeX, LanguageSettings.Current.Settings.AdjustSnapStartToNextShotChange));
historyAdded = true;
}
if (!withGap)
if (newStartTime < p.EndTime.TotalMilliseconds)
{
if (nearestShotChange * 1000 < p.EndTime.TotalMilliseconds)
{
original.StartTime.TotalMilliseconds = nearestShotChange * 1000;
}
}
else
{
if (nearestShotChange * 1000 + MinGapBetweenLines < p.EndTime.TotalMilliseconds)
{
original.StartTime.TotalMilliseconds = nearestShotChange * 1000 + MinGapBetweenLines;
}
original.StartTime.TotalMilliseconds = newStartTime;
}
}
}
@ -18843,19 +18929,9 @@ namespace Nikse.SubtitleEdit.Forms
historyAdded = true;
}
if (!withGap)
if (newStartTime < p.EndTime.TotalMilliseconds)
{
if (nearestShotChange * 1000 < p.EndTime.TotalMilliseconds)
{
p.StartTime.TotalMilliseconds = nearestShotChange * 1000;
}
}
else
{
if (nearestShotChange * 1000 + MinGapBetweenLines < p.EndTime.TotalMilliseconds)
{
p.StartTime.TotalMilliseconds = nearestShotChange * 1000 + MinGapBetweenLines;
}
p.StartTime.TotalMilliseconds = newStartTime;
}
}
@ -18863,37 +18939,27 @@ namespace Nikse.SubtitleEdit.Forms
}
}
private void SnapSelectedLinesEndToPreviousShotChange(bool withGap = false)
private void SnapSelectedLinesEndToPreviousShotChange()
{
var historyAdded = false;
foreach (ListViewItem selectedItem in SubtitleListview1.SelectedItems)
{
var idx = selectedItem.Index;
var p = _subtitle.Paragraphs[idx];
List<double> previousShotChanges = audioVisualizer.ShotChanges.Count > 0 ? audioVisualizer.ShotChanges.Where(x => x < p.EndTime.TotalSeconds + 0.01).ToList() : new List<double>();
if (previousShotChanges.Count > 0)
var previousShotChange = ShotChangeHelper.GetPreviousShotChangeInMs(audioVisualizer.ShotChanges, p.EndTime);
if (previousShotChange != null)
{
double nearestShotChange = previousShotChanges.Aggregate((x, y) => Math.Abs(x - p.EndTime.TotalSeconds) < Math.Abs(y - p.EndTime.TotalSeconds) ? x : y);
var newEndTime = previousShotChange.Value - TimeCodesBeautifierUtils.GetOutCuesGapMs();
if (!historyAdded)
{
MakeHistoryForUndo(string.Format(_language.BeforeX, LanguageSettings.Current.Settings.AdjustSnapEndToPreviousShotChange));
historyAdded = true;
}
if (!withGap)
if (newEndTime > p.StartTime.TotalMilliseconds)
{
if (nearestShotChange * 1000 > p.StartTime.TotalMilliseconds)
{
p.EndTime.TotalMilliseconds = nearestShotChange * 1000;
}
}
else
{
if (nearestShotChange * 1000 - MinGapBetweenLines > p.StartTime.TotalMilliseconds)
{
p.EndTime.TotalMilliseconds = nearestShotChange * 1000 - MinGapBetweenLines;
}
p.EndTime.TotalMilliseconds = newEndTime;
}
if (IsOriginalEditable)
@ -18907,20 +18973,9 @@ namespace Nikse.SubtitleEdit.Forms
historyAdded = true;
}
if (!withGap)
if (newEndTime > p.StartTime.TotalMilliseconds)
{
if (nearestShotChange * 1000 > p.StartTime.TotalMilliseconds)
{
original.EndTime.TotalMilliseconds = nearestShotChange * 1000;
}
}
else
{
if (nearestShotChange * 1000 - MinGapBetweenLines > p.StartTime.TotalMilliseconds)
{
original.EndTime.TotalMilliseconds = nearestShotChange * 1000 - MinGapBetweenLines;
}
original.EndTime.TotalMilliseconds = newEndTime;
}
}
}
@ -18930,18 +18985,17 @@ namespace Nikse.SubtitleEdit.Forms
}
}
private void ExtendSelectedLinesToNextShotChange(bool withGap = false)
private void ExtendSelectedLinesToNextShotChange()
{
var historyAdded = false;
foreach (ListViewItem selectedItem in SubtitleListview1.SelectedItems)
{
var idx = selectedItem.Index;
var p = _subtitle.Paragraphs[idx];
List<double> nextShotChanges = audioVisualizer.ShotChanges.Count > 0 ? audioVisualizer.ShotChanges.Where(x => x > p.EndTime.TotalSeconds + 0.01).ToList() : new List<double>();
if (nextShotChanges.Count > 0)
if (audioVisualizer.ShotChanges.Count > 0)
{
var next = _subtitle.GetParagraphOrDefault(idx + 1);
double nearestShotChange = nextShotChanges.Aggregate((x, y) => Math.Abs(x - p.EndTime.TotalSeconds) < Math.Abs(y - p.EndTime.TotalSeconds) ? x : y);
double nearestShotChangeWithGap = ShotChangeHelper.GetNextShotChangeMinusGapInMs(audioVisualizer.ShotChanges, p.EndTime) ?? double.MaxValue;
double nearestStartTimeWithGap = next != null ? next.StartTime.TotalMilliseconds - MinGapBetweenLines : Double.MaxValue;
if (!historyAdded)
@ -18950,13 +19004,10 @@ namespace Nikse.SubtitleEdit.Forms
historyAdded = true;
}
if (!withGap)
var newEndTime = Math.Min(nearestShotChangeWithGap, nearestStartTimeWithGap);
if (newEndTime <= _videoInfo.TotalMilliseconds)
{
p.EndTime.TotalMilliseconds = Math.Min(nearestShotChange * 1000, nearestStartTimeWithGap);
}
else
{
p.EndTime.TotalMilliseconds = Math.Min(nearestShotChange * 1000 - MinGapBetweenLines, nearestStartTimeWithGap);
p.EndTime.TotalMilliseconds = newEndTime;
}
if (IsOriginalEditable)
@ -18973,14 +19024,10 @@ namespace Nikse.SubtitleEdit.Forms
historyAdded = true;
}
if (!withGap)
var originalNewEndTime = Math.Min(nearestShotChangeWithGap, nearestStartTimeWithGap);
if (originalNewEndTime <= _videoInfo.TotalMilliseconds)
{
original.EndTime.TotalMilliseconds = Math.Min(nearestShotChange * 1000, nearestOriginalStartTimeWithGap);
}
else
{
original.EndTime.TotalMilliseconds = Math.Min(nearestShotChange * 1000 - MinGapBetweenLines, nearestStartTimeWithGap);
original.EndTime.TotalMilliseconds = originalNewEndTime;
}
}
}
@ -18997,11 +19044,10 @@ namespace Nikse.SubtitleEdit.Forms
{
var idx = selectedItem.Index;
var p = _subtitle.Paragraphs[idx];
List<double> previousShotChanges = audioVisualizer.ShotChanges.Count > 0 ? audioVisualizer.ShotChanges.Where(x => x < p.StartTime.TotalSeconds - 0.01).ToList() : new List<double>();
if (previousShotChanges.Count > 0)
if (audioVisualizer.ShotChanges.Count > 0)
{
var previous = _subtitle.GetParagraphOrDefault(idx - 1);
double nearestShotChange = previousShotChanges.Aggregate((x, y) => Math.Abs(x - p.StartTime.TotalSeconds) < Math.Abs(y - p.StartTime.TotalSeconds) ? x : y);
double nearestShotChangeWithGap = ShotChangeHelper.GetPreviousShotChangePlusGapInMs(audioVisualizer.ShotChanges, p.StartTime) ?? double.MinValue;
double nearestEndTimeWithGap = previous != null ? previous.EndTime.TotalMilliseconds + MinGapBetweenLines : -9999;
if (IsOriginalEditable)
@ -19018,13 +19064,10 @@ namespace Nikse.SubtitleEdit.Forms
historyAdded = true;
}
if (!withGap)
var originalNewStartTime = Math.Max(nearestShotChangeWithGap, nearestOriginalEndTimeWithGap);
if (originalNewStartTime >= 0)
{
original.StartTime.TotalMilliseconds = Math.Max(nearestShotChange * 1000, nearestOriginalEndTimeWithGap);
}
else
{
original.StartTime.TotalMilliseconds = Math.Max(nearestShotChange * 1000 + MinGapBetweenLines, nearestOriginalEndTimeWithGap);
original.StartTime.TotalMilliseconds = originalNewStartTime;
}
}
}
@ -19035,13 +19078,10 @@ namespace Nikse.SubtitleEdit.Forms
historyAdded = true;
}
if (!withGap)
var newStartTime = Math.Max(nearestShotChangeWithGap, nearestEndTimeWithGap);
if (newStartTime >= 0)
{
p.StartTime.TotalMilliseconds = Math.Max(nearestShotChange * 1000, nearestEndTimeWithGap);
}
else
{
p.StartTime.TotalMilliseconds = Math.Max(nearestShotChange * 1000 + MinGapBetweenLines, nearestEndTimeWithGap);
p.StartTime.TotalMilliseconds = newStartTime;
}
}
@ -30608,11 +30648,11 @@ namespace Nikse.SubtitleEdit.Forms
selectedLines.Paragraphs.Add(_subtitle.Paragraphs[index]);
}
applyDurationLimits.Initialize(selectedLines);
applyDurationLimits.Initialize(selectedLines, audioVisualizer.ShotChanges);
}
else
{
applyDurationLimits.Initialize(_subtitle);
applyDurationLimits.Initialize(_subtitle, audioVisualizer.ShotChanges);
}
if (applyDurationLimits.ShowDialog(this) == DialogResult.OK)
@ -34437,6 +34477,48 @@ namespace Nikse.SubtitleEdit.Forms
}
}
private void toolStripMenuItemBeautifyTimeCodes_Click(object sender, EventArgs e)
{
if (!IsSubtitleLoaded)
{
DisplaySubtitleNotLoadedMessage();
return;
}
using (var form = new BeautifyTimeCodes.BeautifyTimeCodes(_subtitle, _videoInfo, _videoFileName, audioVisualizer.ShotChanges))
{
var result = form.ShowDialog(this);
if (form.ShotChangesInSeconds.Count > 0)
{
audioVisualizer.ShotChanges = form.ShotChangesInSeconds;
}
if (result == DialogResult.OK)
{
int index = FirstSelectedIndex;
if (index < 0)
{
index = 0;
}
MakeHistoryForUndo(_language.BeforeBeautifyTimeCodes);
SaveSubtitleListviewIndices();
_subtitle.Paragraphs.Clear();
_subtitle.Paragraphs.AddRange(form.FixedSubtitle.Paragraphs);
SubtitleListview1.Fill(_subtitle, _subtitleOriginal);
SubtitleListview1.SelectIndexAndEnsureVisible(index, true);
RestoreSubtitleListviewIndices();
}
}
}
private void toolStripButtonBeautifyTimeCodes_Click(object sender, EventArgs e)
{
toolStripMenuItemBeautifyTimeCodes_Click(sender, e);
}
public bool ProcessCmdKeyFromChildForm(ref Message msg, Keys keyData)
{
Message messageCopy = msg;

View File

@ -604,6 +604,18 @@
q/o3FSCEl3FCbkOuAKg2F2MqAPoFjOQz2Ib8AZh3ssnFbxXgE3ThMWxD7gAo+Ms2pwKga3CfPDLAglHc
qxeKzbrurNZ0e6lq2FNV3bkpl0ntGv6ZVcNZWYM/LR917+sGL+7tQFcaXPylARj7BzrmrMNw48QGAAAA
AElFTkSuQmCC
</value>
</data>
<data name="toolStripButtonBeautifyTimeCodes.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE7SURBVFhH7ZfNbYNQEISpweJiH1IAHUQ04pOrcgHpKj0k
l5x9efGsPGhYr2GDcSxCDp94vIXZj39RNU1TQNu+2jLLvq7LYbctp8/3UlVVmrrelLevF8PmGLg4AYB9
1ivwd+4BNJ4CmlMAoVnYvJPgESFUj3CM6Ax0RzXAwwUsVBp6tLlty8A5BSxYmkb1bjsGZgU+3DgjoPOe
KwGEEtYUrWFJgavgrICGebSx3+Z4vgRgSMDPRZhAhiGBMHhuAc+YQJZ/gecL4PGLGmS5W8Df3Z7oEVQg
kL3jI3ovIh/OGtGaXgIv8BOh8FU8JoCx/xb0QmV9SAa1m9+CSEDnI4FoyXGE1RnsBcaIvoZspuuci7A6
A+cSiOiaXca6/isCymwCAPusV+Dpl2CxAvg36M2h8RTQnAL+5yPPpnwDqGxABPG+k6gAAAAASUVORK5C
YII=
</value>
</data>
<data name="toolStripButtonSourceView.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@ -849,6 +861,55 @@
<metadata name="contextMenuStripEmpty.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 95</value>
</metadata>
<metadata name="imageListPlayRate.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 56</value>
</metadata>
<data name="imageListPlayRate.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAD2
CAAAAk1TRnQBSQFMAgEBAgEAAbwBLgG8AS4BEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm
AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM
AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA
ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz
AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ
AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM
AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA
AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA
AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ
AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/
AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA
AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm
ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ
Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz
AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA
AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM
AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM
ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM
Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA
AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM
AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ
AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz
AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm
AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw
AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/xEAEHUwABB1MAAQdSQA
AewB9AQAAewB9AQABHUB7AV1AewFdSQAAewBDwHyAwAB7AEPAfIDAAR1AewBDwR1AewBDwR1JAAB7AFJ
AQ8B8gIAAewBSQEPAfICAAR1AewBSQEPA3UB7AFJAQ8DdSAAAewBEQFDARUBFAFyAUkBDwEHAesBFAFy
AUkBDwHyAQAB7AERAUMBFQEUAXIBSQEPAQcB6wEUAXIBSQEPAnUgAAHtAQgBeARyAUkBDwRyAUkBDwHy
Ae0BCAF4BHIBSQEPBHIBSQEPAXUgAAGSAQgDmAJ4AnIBbQGYAngCcgFtAZIBCAOYAngCcgFtAZgCeAJy
AW0gAAEcAcIECAJ4AewBmQIIAngB7AHzARwBwgQIAngB7AGZAggCeAHsAXUgAAGYARwBkgHtAewBCAGY
AewB8AHvAewBCAGYAewB8wEAAZgBHAGSAe0B7AEIAZgB7AHwAe8B7AEIAZgB7AJ1JAAB7QEIAewB8wIA
Ae0BCAHsAfMCAAR1Ae0BCAHsA3UB7QEIAewDdSQAAZIB7AHzAwABkgHsAfMDAAR1AZIB7AR1AZIB7AR1
JAABHAH0BAABHAH0BAAEdQEcBXUBHAV1MAAQdTAAEHUgAAFCAU0BPgcAAT4DAAEoAwABQAMAARADAAEB
AQABAQUAAYAXAAP/AQAC/wYAAv8GAAL/BgAB8wHPBgAB8QHHBgAB8AHDBwABAR8AAQEGAAHwAcMGAAHx
AccGAAHzAc8GAAL/BgAC/wYACw==
</value>
</data>
<metadata name="timerTextUndo.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>339, 89</value>
</metadata>

View File

@ -1127,7 +1127,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
// checkBoxSeHandlesTextMerge
//
this.checkBoxSeHandlesTextMerge.AutoSize = true;
this.checkBoxSeHandlesTextMerge.Location = new System.Drawing.Point(7, 105);
this.checkBoxSeHandlesTextMerge.Location = new System.Drawing.Point(9, 104);
this.checkBoxSeHandlesTextMerge.Name = "checkBoxSeHandlesTextMerge";
this.checkBoxSeHandlesTextMerge.Size = new System.Drawing.Size(134, 17);
this.checkBoxSeHandlesTextMerge.TabIndex = 5;

View File

@ -233,6 +233,7 @@
this.buttonWaveformsFolderEmpty = new System.Windows.Forms.Button();
this.labelWaveformsFolderInfo = new System.Windows.Forms.Label();
this.groupBoxWaveformAppearence = new System.Windows.Forms.GroupBox();
this.buttonEditShotChangesProfile = new System.Windows.Forms.Button();
this.checkBoxWaveformAutoGen = new System.Windows.Forms.CheckBox();
this.panelWaveformCursorColor = new System.Windows.Forms.Panel();
this.buttonWaveformCursorColor = new System.Windows.Forms.Button();
@ -337,6 +338,9 @@
this.labelTBBurnIn = new System.Windows.Forms.Label();
this.pictureBoxBurnIn = new System.Windows.Forms.PictureBox();
this.checkBoxTBBurnIn = new System.Windows.Forms.CheckBox();
this.labelTBBeautifyTimeCodes = new System.Windows.Forms.Label();
this.pictureBoxBeautifyTimeCodes = new System.Windows.Forms.PictureBox();
this.checkBoxBeautifyTimeCodes = new System.Windows.Forms.CheckBox();
this.labelTBNetflixQualityCheck = new System.Windows.Forms.Label();
this.pictureBoxNetflixQualityCheck = new System.Windows.Forms.PictureBox();
this.checkBoxNetflixQualityCheck = new System.Windows.Forms.CheckBox();
@ -505,6 +509,7 @@
((System.ComponentModel.ISupportInitialize)(this.pictureBoxAssStyleManager)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxSourceView)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxBurnIn)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxBeautifyTimeCodes)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxNetflixQualityCheck)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxRemoveTextForHi)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxFixCommonErrors)).BeginInit();
@ -3053,6 +3058,7 @@
//
this.groupBoxWaveformAppearence.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBoxWaveformAppearence.Controls.Add(this.buttonEditShotChangesProfile);
this.groupBoxWaveformAppearence.Controls.Add(this.checkBoxWaveformAutoGen);
this.groupBoxWaveformAppearence.Controls.Add(this.panelWaveformCursorColor);
this.groupBoxWaveformAppearence.Controls.Add(this.buttonWaveformCursorColor);
@ -3089,13 +3095,23 @@
this.groupBoxWaveformAppearence.TabStop = false;
this.groupBoxWaveformAppearence.Text = "Waveform appearance";
//
// buttonEditShotChangesProfile
//
this.buttonEditShotChangesProfile.Location = new System.Drawing.Point(524, 157);
this.buttonEditShotChangesProfile.Name = "buttonEditShotChangesProfile";
this.buttonEditShotChangesProfile.Size = new System.Drawing.Size(136, 23);
this.buttonEditShotChangesProfile.TabIndex = 27;
this.buttonEditShotChangesProfile.Text = "Edit profile...";
this.buttonEditShotChangesProfile.UseVisualStyleBackColor = true;
this.buttonEditShotChangesProfile.Click += new System.EventHandler(this.buttonEditShotChangesProfile_Click);
//
// checkBoxWaveformAutoGen
//
this.checkBoxWaveformAutoGen.AutoSize = true;
this.checkBoxWaveformAutoGen.Location = new System.Drawing.Point(262, 186);
this.checkBoxWaveformAutoGen.Location = new System.Drawing.Point(262, 185);
this.checkBoxWaveformAutoGen.Name = "checkBoxWaveformAutoGen";
this.checkBoxWaveformAutoGen.Size = new System.Drawing.Size(220, 17);
this.checkBoxWaveformAutoGen.TabIndex = 27;
this.checkBoxWaveformAutoGen.TabIndex = 28;
this.checkBoxWaveformAutoGen.Text = "Auto gen waveform when opening video";
this.checkBoxWaveformAutoGen.UseVisualStyleBackColor = true;
//
@ -3174,7 +3190,7 @@
this.labelWaveformTextSize.Location = new System.Drawing.Point(259, 220);
this.labelWaveformTextSize.Name = "labelWaveformTextSize";
this.labelWaveformTextSize.Size = new System.Drawing.Size(73, 13);
this.labelWaveformTextSize.TabIndex = 27;
this.labelWaveformTextSize.TabIndex = 29;
this.labelWaveformTextSize.Text = "Text font size";
//
// checkBoxWaveformTextBold
@ -3183,7 +3199,7 @@
this.checkBoxWaveformTextBold.Location = new System.Drawing.Point(463, 221);
this.checkBoxWaveformTextBold.Name = "checkBoxWaveformTextBold";
this.checkBoxWaveformTextBold.Size = new System.Drawing.Size(46, 17);
this.checkBoxWaveformTextBold.TabIndex = 29;
this.checkBoxWaveformTextBold.TabIndex = 31;
this.checkBoxWaveformTextBold.Text = "Bold";
this.checkBoxWaveformTextBold.UseVisualStyleBackColor = true;
//
@ -3209,7 +3225,7 @@
this.comboBoxWaveformTextSize.Location = new System.Drawing.Point(336, 217);
this.comboBoxWaveformTextSize.Name = "comboBoxWaveformTextSize";
this.comboBoxWaveformTextSize.Size = new System.Drawing.Size(121, 21);
this.comboBoxWaveformTextSize.TabIndex = 28;
this.comboBoxWaveformTextSize.TabIndex = 30;
//
// checkBoxListViewMouseEnterFocus
//
@ -3238,7 +3254,7 @@
this.labelWaveformBorderHitMs2.Location = new System.Drawing.Point(454, 250);
this.labelWaveformBorderHitMs2.Name = "labelWaveformBorderHitMs2";
this.labelWaveformBorderHitMs2.Size = new System.Drawing.Size(62, 13);
this.labelWaveformBorderHitMs2.TabIndex = 32;
this.labelWaveformBorderHitMs2.TabIndex = 34;
this.labelWaveformBorderHitMs2.Text = "milliseconds";
//
// numericUpDownWaveformBorderHitMs
@ -3251,7 +3267,7 @@
0});
this.numericUpDownWaveformBorderHitMs.Name = "numericUpDownWaveformBorderHitMs";
this.numericUpDownWaveformBorderHitMs.Size = new System.Drawing.Size(44, 21);
this.numericUpDownWaveformBorderHitMs.TabIndex = 31;
this.numericUpDownWaveformBorderHitMs.TabIndex = 33;
this.numericUpDownWaveformBorderHitMs.Value = new decimal(new int[] {
18,
0,
@ -3264,7 +3280,7 @@
this.labelWaveformBorderHitMs1.Location = new System.Drawing.Point(259, 250);
this.labelWaveformBorderHitMs1.Name = "labelWaveformBorderHitMs1";
this.labelWaveformBorderHitMs1.Size = new System.Drawing.Size(127, 13);
this.labelWaveformBorderHitMs1.TabIndex = 30;
this.labelWaveformBorderHitMs1.TabIndex = 32;
this.labelWaveformBorderHitMs1.Text = "Marker hit must be within";
//
// checkBoxAllowOverlap
@ -4080,6 +4096,9 @@
this.groupBoxShowToolBarButtons.Controls.Add(this.labelTBBurnIn);
this.groupBoxShowToolBarButtons.Controls.Add(this.pictureBoxBurnIn);
this.groupBoxShowToolBarButtons.Controls.Add(this.checkBoxTBBurnIn);
this.groupBoxShowToolBarButtons.Controls.Add(this.labelTBBeautifyTimeCodes);
this.groupBoxShowToolBarButtons.Controls.Add(this.pictureBoxBeautifyTimeCodes);
this.groupBoxShowToolBarButtons.Controls.Add(this.checkBoxBeautifyTimeCodes);
this.groupBoxShowToolBarButtons.Controls.Add(this.labelTBNetflixQualityCheck);
this.groupBoxShowToolBarButtons.Controls.Add(this.pictureBoxNetflixQualityCheck);
this.groupBoxShowToolBarButtons.Controls.Add(this.checkBoxNetflixQualityCheck);
@ -4209,7 +4228,7 @@
// labelToggleSourceView
//
this.labelToggleSourceView.AutoSize = true;
this.labelToggleSourceView.Location = new System.Drawing.Point(11, 253);
this.labelToggleSourceView.Location = new System.Drawing.Point(9, 256);
this.labelToggleSourceView.Name = "labelToggleSourceView";
this.labelToggleSourceView.Size = new System.Drawing.Size(99, 13);
this.labelToggleSourceView.TabIndex = 48;
@ -4217,7 +4236,7 @@
//
// pictureBoxSourceView
//
this.pictureBoxSourceView.Location = new System.Drawing.Point(24, 272);
this.pictureBoxSourceView.Location = new System.Drawing.Point(22, 275);
this.pictureBoxSourceView.Name = "pictureBoxSourceView";
this.pictureBoxSourceView.Size = new System.Drawing.Size(32, 32);
this.pictureBoxSourceView.TabIndex = 47;
@ -4226,7 +4245,7 @@
// checkBoxTBToggleSourceView
//
this.checkBoxTBToggleSourceView.AutoSize = true;
this.checkBoxTBToggleSourceView.Location = new System.Drawing.Point(27, 311);
this.checkBoxTBToggleSourceView.Location = new System.Drawing.Point(25, 314);
this.checkBoxTBToggleSourceView.Name = "checkBoxTBToggleSourceView";
this.checkBoxTBToggleSourceView.Size = new System.Drawing.Size(55, 17);
this.checkBoxTBToggleSourceView.TabIndex = 46;
@ -4260,6 +4279,33 @@
this.checkBoxTBBurnIn.Text = "Visible";
this.checkBoxTBBurnIn.UseVisualStyleBackColor = true;
//
// labelTBBeautifyTimeCodes
//
this.labelTBBeautifyTimeCodes.AutoSize = true;
this.labelTBBeautifyTimeCodes.Location = new System.Drawing.Point(765, 143);
this.labelTBBeautifyTimeCodes.Name = "labelTBBeautifyTimeCodes";
this.labelTBBeautifyTimeCodes.Size = new System.Drawing.Size(101, 13);
this.labelTBBeautifyTimeCodes.TabIndex = 45;
this.labelTBBeautifyTimeCodes.Text = "Beautify time codes";
//
// pictureBoxBeautifyTimeCodes
//
this.pictureBoxBeautifyTimeCodes.Location = new System.Drawing.Point(776, 160);
this.pictureBoxBeautifyTimeCodes.Name = "pictureBoxBeautifyTimeCodes";
this.pictureBoxBeautifyTimeCodes.Size = new System.Drawing.Size(32, 32);
this.pictureBoxBeautifyTimeCodes.TabIndex = 44;
this.pictureBoxBeautifyTimeCodes.TabStop = false;
//
// checkBoxBeautifyTimeCodes
//
this.checkBoxBeautifyTimeCodes.AutoSize = true;
this.checkBoxBeautifyTimeCodes.Location = new System.Drawing.Point(779, 198);
this.checkBoxBeautifyTimeCodes.Name = "checkBoxBeautifyTimeCodes";
this.checkBoxBeautifyTimeCodes.Size = new System.Drawing.Size(55, 17);
this.checkBoxBeautifyTimeCodes.TabIndex = 43;
this.checkBoxBeautifyTimeCodes.Text = "Visible";
this.checkBoxBeautifyTimeCodes.UseVisualStyleBackColor = true;
//
// labelTBNetflixQualityCheck
//
this.labelTBNetflixQualityCheck.AutoSize = true;
@ -5475,6 +5521,7 @@
((System.ComponentModel.ISupportInitialize)(this.pictureBoxAssStyleManager)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxSourceView)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxBurnIn)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxBeautifyTimeCodes)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxNetflixQualityCheck)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxRemoveTextForHi)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxFixCommonErrors)).EndInit();
@ -5872,6 +5919,9 @@
private System.Windows.Forms.CheckBox checkBoxLiveSpellCheck;
private System.Windows.Forms.CheckBox checkBoxDarkThemeShowListViewGridLines;
private System.Windows.Forms.GroupBox groupBoxFontInUI;
private System.Windows.Forms.Label labelTBBeautifyTimeCodes;
private System.Windows.Forms.PictureBox pictureBoxBeautifyTimeCodes;
private System.Windows.Forms.CheckBox checkBoxBeautifyTimeCodes;
private System.Windows.Forms.GroupBox groupBoxToolsMisc;
private System.Windows.Forms.ComboBox comboBoxBDOpensIn;
private System.Windows.Forms.Label labelBDOpensIn;
@ -5920,6 +5970,7 @@
private System.Windows.Forms.Button buttonMpvOutlineColor;
private System.Windows.Forms.Panel panelMpvPrimaryColor;
private System.Windows.Forms.Button buttonMpvPrimaryColor;
private System.Windows.Forms.Button buttonEditShotChangesProfile;
private System.Windows.Forms.PictureBox pictureBoxAssStyleManager;
private System.Windows.Forms.PictureBox pictureBoxAssAttachments;
private System.Windows.Forms.PictureBox pictureBoxAssProperties;

View File

@ -4,6 +4,7 @@ using Nikse.SubtitleEdit.Core.SubtitleFormats;
using Nikse.SubtitleEdit.Core.Translate.Service;
using Nikse.SubtitleEdit.Logic;
using Nikse.SubtitleEdit.Logic.VideoPlayers;
using Nikse.SubtitleEdit.Forms.BeautifyTimeCodes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -144,6 +145,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
checkBoxSettings.Checked = gs.ShowToolbarSettings;
checkBoxSpellCheck.Checked = gs.ShowToolbarSpellCheck;
checkBoxNetflixQualityCheck.Checked = gs.ShowToolbarNetflixGlyphCheck;
checkBoxBeautifyTimeCodes.Checked = gs.ShowToolbarBeautifyTimeCodes;
checkBoxHelp.Checked = gs.ShowToolbarHelp;
comboBoxFrameRate.Items.Clear();
@ -399,6 +401,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
labelTBBurnIn.Text = language.BurnIn;
labelTBSpellCheck.Text = language.SpellCheck;
labelTBNetflixQualityCheck.Text = language.NetflixQualityCheck;
labelTBBeautifyTimeCodes.Text = language.BeautifyTimeCodes;
labelToggleSourceView.Text = language.ToggleView;
labelTBSettings.Text = language.SettingsName;
labelTBHelp.Text = language.Help;
@ -415,6 +418,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
checkBoxTBBurnIn.Text = LanguageSettings.Current.General.Visible;
checkBoxSpellCheck.Text = LanguageSettings.Current.General.Visible;
checkBoxNetflixQualityCheck.Text = LanguageSettings.Current.General.Visible;
checkBoxBeautifyTimeCodes.Text = LanguageSettings.Current.General.Visible;
checkBoxSettings.Text = LanguageSettings.Current.General.Visible;
checkBoxHelp.Text = LanguageSettings.Current.General.Visible;
checkBoxTBToggleSourceView.Text = LanguageSettings.Current.General.Visible;
@ -469,6 +473,9 @@ namespace Nikse.SubtitleEdit.Forms.Options
pictureBoxNetflixQualityCheck.Left = labelTBNetflixQualityCheck.Left;
checkBoxNetflixQualityCheck.Left = labelTBNetflixQualityCheck.Left;
labelTBBeautifyTimeCodes.Left = Math.Max(labelTBNetflixQualityCheck.Right, checkBoxNetflixQualityCheck.Right) + 18;
pictureBoxBeautifyTimeCodes.Left = labelTBBeautifyTimeCodes.Left;
checkBoxBeautifyTimeCodes.Left = labelTBBeautifyTimeCodes.Left;
groupBoxMiscellaneous.Text = language.General;
groupBoxToolsMisc.Text = language.Miscellaneous;
@ -685,6 +692,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
checkBoxListViewMouseEnterFocus.Text = language.WaveformListViewFocusMouseEnter;
checkBoxWaveformSingleClickSelect.Text = language.WaveformSingleClickSelect;
checkBoxWaveformSnapToShotChanges.Text = language.WaveformSnapToShotChanges;
buttonEditShotChangesProfile.Text = language.WaveformEditShotChangesProfile;
checkBoxWaveformAutoGen.Text = language.WaveformAutoGen;
labelWaveformBorderHitMs1.Text = language.WaveformBorderHitMs1;
labelWaveformBorderHitMs2.Text = language.WaveformBorderHitMs2;
@ -1071,6 +1079,8 @@ namespace Nikse.SubtitleEdit.Forms.Options
numericUpDownWaveformBorderHitMs.Value = Configuration.Settings.VideoControls.WaveformBorderHitMs;
}
buttonEditShotChangesProfile.Left = checkBoxWaveformSnapToShotChanges.Left + checkBoxWaveformSnapToShotChanges.Width + 16;
checkBoxUseFFmpeg.Checked = gs.UseFFmpegForWaveExtraction;
checkBoxFfmpegUseCenterChannel.Checked = gs.FFmpegUseCenterChannelOnly;
textBoxFFmpegPath.Text = gs.FFmpegLocation;
@ -1713,15 +1723,13 @@ namespace Nikse.SubtitleEdit.Forms.Options
AddNode(createAndAdjustNode, language.RecalculateDurationOfCurrentSubtitleByOptimalReadingSpeed, nameof(Configuration.Settings.Shortcuts.GeneralAutoCalcCurrentDurationByOptimalReadingSpeed));
AddNode(createAndAdjustNode, language.RecalculateDurationOfCurrentSubtitleByMinReadingSpeed, nameof(Configuration.Settings.Shortcuts.GeneralAutoCalcCurrentDurationByMinReadingSpeed));
AddNode(createAndAdjustNode, language.AdjustSnapStartToNextShotChange, nameof(Configuration.Settings.Shortcuts.MainAdjustSnapStartToNextShotChange));
AddNode(createAndAdjustNode, language.AdjustSnapStartToNextShotChangeWithGap, nameof(Configuration.Settings.Shortcuts.MainAdjustSnapStartToNextShotChangeWithGap));
AddNode(createAndAdjustNode, language.AdjustSnapEndToPreviousShotChange, nameof(Configuration.Settings.Shortcuts.MainAdjustSnapEndToPreviousShotChange));
AddNode(createAndAdjustNode, language.AdjustSnapEndToPreviousShotChangeWithGap, nameof(Configuration.Settings.Shortcuts.MainAdjustSnapEndToPreviousShotChangeWithGap));
AddNode(createAndAdjustNode, language.AdjustExtendToNextShotChange, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendToNextShotChange));
AddNode(createAndAdjustNode, language.AdjustExtendToNextShotChangeWithGap, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendToNextShotChangeWithGap));
AddNode(createAndAdjustNode, language.AdjustExtendToPreviousShotChange, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendToPreviousShotChange));
AddNode(createAndAdjustNode, language.AdjustExtendToPreviousShotChangeWithGap, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendToPreviousShotChangeWithGap));
AddNode(createAndAdjustNode, language.AdjustExtendToNextSubtitle, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendToNextSubtitle));
AddNode(createAndAdjustNode, language.AdjustExtendToPreviousSubtitle, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendToPreviousSubtitle));
AddNode(createAndAdjustNode, language.AdjustExtendToNextSubtitleMinusChainingGap, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendToNextSubtitleMinusChainingGap));
AddNode(createAndAdjustNode, language.AdjustExtendToPreviousSubtitleMinusChainingGap, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendToPreviousSubtitleMinusChainingGap));
AddNode(createAndAdjustNode, language.AdjustExtendCurrentSubtitle, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendCurrentSubtitle));
AddNode(createAndAdjustNode, language.AdjustExtendPreviousLineEndToCurrentStart, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendPreviousLineEndToCurrentStart));
AddNode(createAndAdjustNode, language.AdjustExtendNextLineStartToCurrentEnd, nameof(Configuration.Settings.Shortcuts.MainAdjustExtendNextLineStartToCurrentEnd));
@ -1887,7 +1895,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
}
public void Initialize(Icon icon, Image newFile, Image openFile, Image saveFile, Image saveFileAs, Image find, Image replace, Image fixCommonErrors, Image removeTextForHi,
Image visualSync, Image burnIn, Image spellCheck, Image netflixGlyphCheck, Image settings, Image help, Image toggleSourceView)
Image visualSync, Image burnIn, Image spellCheck, Image netflixGlyphCheck, Image beautifyTimeCodes, Image settings, Image help, Image toggleSourceView)
{
Icon = (Icon)icon.Clone();
pictureBoxFileNew.Image = (Image)newFile.Clone();
@ -1906,6 +1914,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
pictureBoxBurnIn.Image = (Image)burnIn.Clone();
pictureBoxSpellCheck.Image = (Image)spellCheck.Clone();
pictureBoxNetflixQualityCheck.Image = (Image)netflixGlyphCheck.Clone();
pictureBoxBeautifyTimeCodes.Image = (Image)beautifyTimeCodes.Clone();
pictureBoxSettings.Image = (Image)settings.Clone();
pictureBoxHelp.Image = (Image)help.Clone();
}
@ -1927,6 +1936,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
gs.ShowToolbarSettings = checkBoxSettings.Checked;
gs.ShowToolbarSpellCheck = checkBoxSpellCheck.Checked;
gs.ShowToolbarNetflixGlyphCheck = checkBoxNetflixQualityCheck.Checked;
gs.ShowToolbarBeautifyTimeCodes = checkBoxBeautifyTimeCodes.Checked;
gs.ShowToolbarHelp = checkBoxHelp.Checked;
gs.ShowFrameRate = checkBoxShowFrameRate.Checked;
@ -3672,6 +3682,14 @@ namespace Nikse.SubtitleEdit.Forms.Options
}
}
private void buttonEditShotChangesProfile_Click(object sender, EventArgs e)
{
using (var form = new BeautifyTimeCodesProfile(0))
{
form.ShowDialog(this);
}
}
private void comboBoxToolbarIconTheme_SelectedIndexChanged(object sender, EventArgs e)
{
if (_loading)
@ -3695,6 +3713,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
TryLoadIcon(pictureBoxBurnIn, "BurnIn");
TryLoadIcon(pictureBoxSpellCheck, "SpellCheck");
TryLoadIcon(pictureBoxNetflixQualityCheck, "Netflix");
TryLoadIcon(pictureBoxBeautifyTimeCodes, "BeautifyTimeCodes");
TryLoadIcon(pictureBoxAssStyleManager, "AssaStyle");
TryLoadIcon(pictureBoxAssProperties, "AssaProperties");
TryLoadIcon(pictureBoxAssAttachments, "AssaAttachments");

View File

@ -126,7 +126,7 @@
this.checkBoxGapSuffixAddForComma.Location = new System.Drawing.Point(53, 243);
this.checkBoxGapSuffixAddForComma.Name = "checkBoxGapSuffixAddForComma";
this.checkBoxGapSuffixAddForComma.Size = new System.Drawing.Size(186, 17);
this.checkBoxGapSuffixAddForComma.TabIndex = 11;
this.checkBoxGapSuffixAddForComma.TabIndex = 14;
this.checkBoxGapSuffixAddForComma.Text = "Add suffix when ends with comma";
this.checkBoxGapSuffixAddForComma.UseVisualStyleBackColor = true;
this.checkBoxGapSuffixAddForComma.CheckedChanged += new System.EventHandler(this.RefreshControls);
@ -148,7 +148,7 @@
this.checkBoxGapPrefixAddSpace.Location = new System.Drawing.Point(53, 345);
this.checkBoxGapPrefixAddSpace.Name = "checkBoxGapPrefixAddSpace";
this.checkBoxGapPrefixAddSpace.Size = new System.Drawing.Size(77, 17);
this.checkBoxGapPrefixAddSpace.TabIndex = 15;
this.checkBoxGapPrefixAddSpace.TabIndex = 19;
this.checkBoxGapPrefixAddSpace.Text = "Add space";
this.checkBoxGapPrefixAddSpace.UseVisualStyleBackColor = true;
this.checkBoxGapPrefixAddSpace.CheckedChanged += new System.EventHandler(this.RefreshControls);
@ -159,7 +159,7 @@
this.labelGapPrefix.Location = new System.Drawing.Point(11, 319);
this.labelGapPrefix.Name = "labelGapPrefix";
this.labelGapPrefix.Size = new System.Drawing.Size(36, 13);
this.labelGapPrefix.TabIndex = 53;
this.labelGapPrefix.TabIndex = 17;
this.labelGapPrefix.Text = "Prefix:";
//
// comboBoxGapPrefix
@ -176,7 +176,7 @@
this.comboBoxGapPrefix.Location = new System.Drawing.Point(53, 316);
this.comboBoxGapPrefix.Name = "comboBoxGapPrefix";
this.comboBoxGapPrefix.Size = new System.Drawing.Size(93, 22);
this.comboBoxGapPrefix.TabIndex = 14;
this.comboBoxGapPrefix.TabIndex = 18;
this.comboBoxGapPrefix.SelectedIndexChanged += new System.EventHandler(this.RefreshControls);
this.comboBoxGapPrefix.TextChanged += new System.EventHandler(this.RefreshControls);
//
@ -186,7 +186,7 @@
this.checkBoxGapSuffixRemoveComma.Location = new System.Drawing.Point(53, 289);
this.checkBoxGapSuffixRemoveComma.Name = "checkBoxGapSuffixRemoveComma";
this.checkBoxGapSuffixRemoveComma.Size = new System.Drawing.Size(103, 17);
this.checkBoxGapSuffixRemoveComma.TabIndex = 13;
this.checkBoxGapSuffixRemoveComma.TabIndex = 16;
this.checkBoxGapSuffixRemoveComma.Text = "Remove comma";
this.checkBoxGapSuffixRemoveComma.UseVisualStyleBackColor = true;
this.checkBoxGapSuffixRemoveComma.CheckedChanged += new System.EventHandler(this.RefreshControls);
@ -197,7 +197,7 @@
this.checkBoxGapSuffixAddSpace.Location = new System.Drawing.Point(53, 266);
this.checkBoxGapSuffixAddSpace.Name = "checkBoxGapSuffixAddSpace";
this.checkBoxGapSuffixAddSpace.Size = new System.Drawing.Size(77, 17);
this.checkBoxGapSuffixAddSpace.TabIndex = 12;
this.checkBoxGapSuffixAddSpace.TabIndex = 15;
this.checkBoxGapSuffixAddSpace.Text = "Add space";
this.checkBoxGapSuffixAddSpace.UseVisualStyleBackColor = true;
this.checkBoxGapSuffixAddSpace.CheckedChanged += new System.EventHandler(this.RefreshControls);
@ -208,7 +208,7 @@
this.labelGapSuffix.Location = new System.Drawing.Point(11, 218);
this.labelGapSuffix.Name = "labelGapSuffix";
this.labelGapSuffix.Size = new System.Drawing.Size(36, 13);
this.labelGapSuffix.TabIndex = 49;
this.labelGapSuffix.TabIndex = 12;
this.labelGapSuffix.Text = "Suffix:";
//
// comboBoxGapSuffix
@ -225,7 +225,7 @@
this.comboBoxGapSuffix.Location = new System.Drawing.Point(53, 215);
this.comboBoxGapSuffix.Name = "comboBoxGapSuffix";
this.comboBoxGapSuffix.Size = new System.Drawing.Size(93, 22);
this.comboBoxGapSuffix.TabIndex = 10;
this.comboBoxGapSuffix.TabIndex = 13;
this.comboBoxGapSuffix.SelectedIndexChanged += new System.EventHandler(this.RefreshControls);
this.comboBoxGapSuffix.TextChanged += new System.EventHandler(this.RefreshControls);
//
@ -235,7 +235,7 @@
this.labelMs.Location = new System.Drawing.Point(289, 186);
this.labelMs.Name = "labelMs";
this.labelMs.Size = new System.Drawing.Size(20, 13);
this.labelMs.TabIndex = 47;
this.labelMs.TabIndex = 11;
this.labelMs.Text = "ms";
//
// numericUpDownDifferentStyleGapMs
@ -248,7 +248,7 @@
0});
this.numericUpDownDifferentStyleGapMs.Name = "numericUpDownDifferentStyleGapMs";
this.numericUpDownDifferentStyleGapMs.Size = new System.Drawing.Size(56, 20);
this.numericUpDownDifferentStyleGapMs.TabIndex = 9;
this.numericUpDownDifferentStyleGapMs.TabIndex = 10;
this.numericUpDownDifferentStyleGapMs.Value = new decimal(new int[] {
300,
0,
@ -261,7 +261,7 @@
this.checkBoxDifferentStyleGap.Location = new System.Drawing.Point(14, 185);
this.checkBoxDifferentStyleGap.Name = "checkBoxDifferentStyleGap";
this.checkBoxDifferentStyleGap.Size = new System.Drawing.Size(207, 17);
this.checkBoxDifferentStyleGap.TabIndex = 8;
this.checkBoxDifferentStyleGap.TabIndex = 9;
this.checkBoxDifferentStyleGap.Text = "Use different style for gaps longer than";
this.checkBoxDifferentStyleGap.UseVisualStyleBackColor = true;
this.checkBoxDifferentStyleGap.CheckedChanged += new System.EventHandler(this.checkBoxDifferentStyleGap_CheckedChanged);
@ -272,7 +272,7 @@
this.checkBoxPrefixAddSpace.Location = new System.Drawing.Point(53, 150);
this.checkBoxPrefixAddSpace.Name = "checkBoxPrefixAddSpace";
this.checkBoxPrefixAddSpace.Size = new System.Drawing.Size(77, 17);
this.checkBoxPrefixAddSpace.TabIndex = 7;
this.checkBoxPrefixAddSpace.TabIndex = 8;
this.checkBoxPrefixAddSpace.Text = "Add space";
this.checkBoxPrefixAddSpace.UseVisualStyleBackColor = true;
this.checkBoxPrefixAddSpace.CheckedChanged += new System.EventHandler(this.RefreshControls);
@ -283,7 +283,7 @@
this.labelPrefix.Location = new System.Drawing.Point(11, 124);
this.labelPrefix.Name = "labelPrefix";
this.labelPrefix.Size = new System.Drawing.Size(36, 13);
this.labelPrefix.TabIndex = 24;
this.labelPrefix.TabIndex = 6;
this.labelPrefix.Text = "Prefix:";
//
// comboBoxPrefix
@ -300,7 +300,7 @@
this.comboBoxPrefix.Location = new System.Drawing.Point(53, 121);
this.comboBoxPrefix.Name = "comboBoxPrefix";
this.comboBoxPrefix.Size = new System.Drawing.Size(93, 22);
this.comboBoxPrefix.TabIndex = 6;
this.comboBoxPrefix.TabIndex = 7;
this.comboBoxPrefix.SelectedIndexChanged += new System.EventHandler(this.RefreshControls);
this.comboBoxPrefix.TextChanged += new System.EventHandler(this.RefreshControls);
//
@ -332,7 +332,7 @@
this.labelSuffix.Location = new System.Drawing.Point(11, 22);
this.labelSuffix.Name = "labelSuffix";
this.labelSuffix.Size = new System.Drawing.Size(36, 13);
this.labelSuffix.TabIndex = 20;
this.labelSuffix.TabIndex = 1;
this.labelSuffix.Text = "Suffix:";
//
// comboBoxSuffix
@ -376,7 +376,7 @@
this.labelPreviewPause.Location = new System.Drawing.Point(23, 209);
this.labelPreviewPause.Name = "labelPreviewPause";
this.labelPreviewPause.Size = new System.Drawing.Size(65, 13);
this.labelPreviewPause.TabIndex = 54;
this.labelPreviewPause.TabIndex = 27;
this.labelPreviewPause.Text = "(long pause)";
//
// labelPreviewLine4
@ -386,7 +386,7 @@
this.labelPreviewLine4.Location = new System.Drawing.Point(23, 249);
this.labelPreviewLine4.Name = "labelPreviewLine4";
this.labelPreviewLine4.Size = new System.Drawing.Size(256, 34);
this.labelPreviewLine4.TabIndex = 27;
this.labelPreviewLine4.TabIndex = 28;
this.labelPreviewLine4.Text = "mauris mollis consectetur nibh,\r\nnec congue est viverra quis.";
//
// labelPreviewLine3

View File

@ -50,7 +50,7 @@
this.buttonCancel.Location = new System.Drawing.Point(416, 232);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 10;
this.buttonCancel.TabIndex = 21;
this.buttonCancel.Text = "C&ancel";
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
@ -62,7 +62,7 @@
this.buttonOK.Location = new System.Drawing.Point(335, 232);
this.buttonOK.Name = "buttonOK";
this.buttonOK.Size = new System.Drawing.Size(75, 23);
this.buttonOK.TabIndex = 9;
this.buttonOK.TabIndex = 20;
this.buttonOK.Text = "&OK";
this.buttonOK.UseVisualStyleBackColor = true;
this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
@ -123,7 +123,7 @@
this.labelContinuationPause.Location = new System.Drawing.Point(9, 140);
this.labelContinuationPause.Name = "labelContinuationPause";
this.labelContinuationPause.Size = new System.Drawing.Size(86, 13);
this.labelContinuationPause.TabIndex = 11;
this.labelContinuationPause.TabIndex = 6;
this.labelContinuationPause.Text = "Pause threshold:";
//
// numericUpDownContinuationPause
@ -136,7 +136,7 @@
0});
this.numericUpDownContinuationPause.Name = "numericUpDownContinuationPause";
this.numericUpDownContinuationPause.Size = new System.Drawing.Size(56, 20);
this.numericUpDownContinuationPause.TabIndex = 6;
this.numericUpDownContinuationPause.TabIndex = 7;
this.numericUpDownContinuationPause.Value = new decimal(new int[] {
300,
0,
@ -149,7 +149,7 @@
this.labelMs.Location = new System.Drawing.Point(163, 140);
this.labelMs.Name = "labelMs";
this.labelMs.Size = new System.Drawing.Size(20, 13);
this.labelMs.TabIndex = 13;
this.labelMs.TabIndex = 8;
this.labelMs.Text = "ms";
//
// buttonEditCustomStyle
@ -157,7 +157,7 @@
this.buttonEditCustomStyle.Location = new System.Drawing.Point(12, 177);
this.buttonEditCustomStyle.Name = "buttonEditCustomStyle";
this.buttonEditCustomStyle.Size = new System.Drawing.Size(240, 27);
this.buttonEditCustomStyle.TabIndex = 7;
this.buttonEditCustomStyle.TabIndex = 9;
this.buttonEditCustomStyle.Text = "Edit custom continuation style...";
this.buttonEditCustomStyle.UseVisualStyleBackColor = true;
this.buttonEditCustomStyle.Click += new System.EventHandler(this.buttonEditCustomStyle_Click);

View File

@ -49,7 +49,7 @@
this.buttonCancel.Location = new System.Drawing.Point(368, 91);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 8;
this.buttonCancel.TabIndex = 11;
this.buttonCancel.Text = "C&ancel";
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
@ -61,7 +61,7 @@
this.buttonOK.Location = new System.Drawing.Point(287, 91);
this.buttonOK.Name = "buttonOK";
this.buttonOK.Size = new System.Drawing.Size(75, 23);
this.buttonOK.TabIndex = 7;
this.buttonOK.TabIndex = 10;
this.buttonOK.Text = "&OK";
this.buttonOK.UseVisualStyleBackColor = true;
this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
@ -72,7 +72,7 @@
this.labelMaximumLineWidth.Location = new System.Drawing.Point(12, 14);
this.labelMaximumLineWidth.Name = "labelMaximumLineWidth";
this.labelMaximumLineWidth.Size = new System.Drawing.Size(101, 13);
this.labelMaximumLineWidth.TabIndex = 208;
this.labelMaximumLineWidth.TabIndex = 1;
this.labelMaximumLineWidth.Text = "Maximum line width:";
//
// numericUpDownMaxLineWidth
@ -85,7 +85,7 @@
0});
this.numericUpDownMaxLineWidth.Name = "numericUpDownMaxLineWidth";
this.numericUpDownMaxLineWidth.Size = new System.Drawing.Size(56, 20);
this.numericUpDownMaxLineWidth.TabIndex = 1;
this.numericUpDownMaxLineWidth.TabIndex = 2;
this.numericUpDownMaxLineWidth.Value = new decimal(new int[] {
576,
0,
@ -98,7 +98,7 @@
this.labelPixelsSuffix.Location = new System.Drawing.Point(181, 14);
this.labelPixelsSuffix.Name = "labelPixelsSuffix";
this.labelPixelsSuffix.Size = new System.Drawing.Size(33, 13);
this.labelPixelsSuffix.TabIndex = 210;
this.labelPixelsSuffix.TabIndex = 3;
this.labelPixelsSuffix.Text = "pixels";
//
// comboBoxMeasureFontName
@ -111,7 +111,7 @@
this.comboBoxMeasureFontName.Location = new System.Drawing.Point(119, 38);
this.comboBoxMeasureFontName.Name = "comboBoxMeasureFontName";
this.comboBoxMeasureFontName.Size = new System.Drawing.Size(199, 21);
this.comboBoxMeasureFontName.TabIndex = 2;
this.comboBoxMeasureFontName.TabIndex = 5;
//
// labelMeasureFont
//
@ -119,7 +119,7 @@
this.labelMeasureFont.Location = new System.Drawing.Point(12, 41);
this.labelMeasureFont.Name = "labelMeasureFont";
this.labelMeasureFont.Size = new System.Drawing.Size(72, 13);
this.labelMeasureFont.TabIndex = 213;
this.labelMeasureFont.TabIndex = 4;
this.labelMeasureFont.Text = "Measure font:";
//
// checkBoxMeasureFontBold
@ -129,7 +129,7 @@
this.checkBoxMeasureFontBold.Location = new System.Drawing.Point(386, 40);
this.checkBoxMeasureFontBold.Name = "checkBoxMeasureFontBold";
this.checkBoxMeasureFontBold.Size = new System.Drawing.Size(47, 17);
this.checkBoxMeasureFontBold.TabIndex = 4;
this.checkBoxMeasureFontBold.TabIndex = 7;
this.checkBoxMeasureFontBold.Text = "Bold";
this.checkBoxMeasureFontBold.UseVisualStyleBackColor = true;
//
@ -149,7 +149,7 @@
0});
this.numericUpDownMeasureFontSize.Name = "numericUpDownMeasureFontSize";
this.numericUpDownMeasureFontSize.Size = new System.Drawing.Size(56, 20);
this.numericUpDownMeasureFontSize.TabIndex = 3;
this.numericUpDownMeasureFontSize.TabIndex = 6;
this.numericUpDownMeasureFontSize.Value = new decimal(new int[] {
24,
0,

View File

@ -48,6 +48,7 @@
this.textBoxGenerate = new System.Windows.Forms.TextBox();
this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.labelProgress = new System.Windows.Forms.Label();
this.groupBoxImportText.SuspendLayout();
this.groupBoxTimeCodes.SuspendLayout();
this.groupBoxGenerateShotChanges.SuspendLayout();
@ -203,7 +204,7 @@
this.groupBoxGenerateShotChanges.Controls.Add(this.textBoxGenerate);
this.groupBoxGenerateShotChanges.Location = new System.Drawing.Point(12, 12);
this.groupBoxGenerateShotChanges.Name = "groupBoxGenerateShotChanges";
this.groupBoxGenerateShotChanges.Size = new System.Drawing.Size(349, 413);
this.groupBoxGenerateShotChanges.Size = new System.Drawing.Size(349, 412);
this.groupBoxGenerateShotChanges.TabIndex = 0;
this.groupBoxGenerateShotChanges.TabStop = false;
this.groupBoxGenerateShotChanges.Text = "Generate shot changes";
@ -212,7 +213,7 @@
//
this.labelThresholdDescription.AutoSize = true;
this.labelThresholdDescription.ForeColor = System.Drawing.SystemColors.ControlDarkDark;
this.labelThresholdDescription.Location = new System.Drawing.Point(6, 387);
this.labelThresholdDescription.Location = new System.Drawing.Point(120, 385);
this.labelThresholdDescription.Name = "labelThresholdDescription";
this.labelThresholdDescription.Size = new System.Drawing.Size(186, 13);
this.labelThresholdDescription.TabIndex = 5;
@ -226,17 +227,17 @@
0,
0,
131072});
this.numericUpDownThreshold.Location = new System.Drawing.Point(66, 364);
this.numericUpDownThreshold.Location = new System.Drawing.Point(66, 383);
this.numericUpDownThreshold.Maximum = new decimal(new int[] {
9,
95,
0,
0,
65536});
131072});
this.numericUpDownThreshold.Minimum = new decimal(new int[] {
1,
5,
0,
0,
65536});
131072});
this.numericUpDownThreshold.Name = "numericUpDownThreshold";
this.numericUpDownThreshold.Size = new System.Drawing.Size(48, 20);
this.numericUpDownThreshold.TabIndex = 4;
@ -249,7 +250,7 @@
// labelFfmpegThreshold
//
this.labelFfmpegThreshold.AutoSize = true;
this.labelFfmpegThreshold.Location = new System.Drawing.Point(6, 366);
this.labelFfmpegThreshold.Location = new System.Drawing.Point(6, 385);
this.labelFfmpegThreshold.Name = "labelFfmpegThreshold";
this.labelFfmpegThreshold.Size = new System.Drawing.Size(54, 13);
this.labelFfmpegThreshold.TabIndex = 3;
@ -270,7 +271,7 @@
//
this.buttonImportWithFfmpeg.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.buttonImportWithFfmpeg.Location = new System.Drawing.Point(6, 330);
this.buttonImportWithFfmpeg.Location = new System.Drawing.Point(6, 351);
this.buttonImportWithFfmpeg.Name = "buttonImportWithFfmpeg";
this.buttonImportWithFfmpeg.Size = new System.Drawing.Size(337, 23);
this.buttonImportWithFfmpeg.TabIndex = 2;
@ -290,7 +291,7 @@
this.textBoxGenerate.Name = "textBoxGenerate";
this.textBoxGenerate.ReadOnly = true;
this.textBoxGenerate.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.textBoxGenerate.Size = new System.Drawing.Size(337, 276);
this.textBoxGenerate.Size = new System.Drawing.Size(337, 297);
this.textBoxGenerate.TabIndex = 1;
//
// progressBar1
@ -299,7 +300,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.progressBar1.Location = new System.Drawing.Point(12, 433);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(528, 23);
this.progressBar1.Size = new System.Drawing.Size(407, 23);
this.progressBar1.TabIndex = 2;
this.progressBar1.Visible = false;
//
@ -307,11 +308,23 @@
//
this.openFileDialog1.FileName = "openFileDialog1";
//
// labelProgress
//
this.labelProgress.AutoSize = true;
this.labelProgress.ForeColor = System.Drawing.SystemColors.ControlDarkDark;
this.labelProgress.Location = new System.Drawing.Point(425, 438);
this.labelProgress.Name = "labelProgress";
this.labelProgress.Size = new System.Drawing.Size(102, 13);
this.labelProgress.TabIndex = 5;
this.labelProgress.Text = "00:00:00 / 00:00:00";
this.labelProgress.Visible = false;
//
// ImportShotChanges
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(738, 468);
this.Controls.Add(this.labelProgress);
this.Controls.Add(this.buttonCancel);
this.Controls.Add(this.progressBar1);
this.Controls.Add(this.buttonOK);
@ -336,6 +349,7 @@
this.groupBoxGenerateShotChanges.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownThreshold)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
@ -361,5 +375,6 @@
private System.Windows.Forms.NumericUpDown numericUpDownThreshold;
private System.Windows.Forms.Label labelFfmpegThreshold;
private System.Windows.Forms.TextBox textBoxLog;
private System.Windows.Forms.Label labelProgress;
}
}

View File

@ -16,6 +16,7 @@ namespace Nikse.SubtitleEdit.Forms.ShotChanges
{
public List<double> ShotChangesInSeconds = new List<double>();
private readonly double _frameRate = 25;
private readonly double _duration = 0;
private readonly string _videoFileName;
private bool _abort;
private bool _pause;
@ -31,6 +32,10 @@ namespace Nikse.SubtitleEdit.Forms.ShotChanges
{
_frameRate = videoInfo.FramesPerSecond;
}
if (videoInfo != null && videoInfo.TotalMilliseconds > 0)
{
_duration = videoInfo.TotalMilliseconds;
}
_videoFileName = videoFileName;
@ -338,6 +343,7 @@ namespace Nikse.SubtitleEdit.Forms.ShotChanges
buttonOK.Enabled = false;
progressBar1.Visible = true;
progressBar1.Style = ProgressBarStyle.Marquee;
labelProgress.Visible = true;
buttonImportWithFfmpeg.Enabled = false;
numericUpDownThreshold.Enabled = false;
Cursor = Cursors.WaitCursor;
@ -380,11 +386,29 @@ namespace Nikse.SubtitleEdit.Forms.ShotChanges
private void UpdateImportTextBox()
{
if (_duration > 0 && _shotChangesGenerator.LastSeconds > 0)
{
if (progressBar1.Style != ProgressBarStyle.Blocks)
{
progressBar1.Style = ProgressBarStyle.Blocks;
progressBar1.Maximum = Convert.ToInt32(_duration / 1000);
}
progressBar1.Value = Convert.ToInt32(_shotChangesGenerator.LastSeconds);
labelProgress.Text = FormatSeconds(_shotChangesGenerator.LastSeconds) + @" / " + FormatSeconds(_duration / 1000);
}
textBoxGenerate.Text = _shotChangesGenerator.GetTimeCodesString();
textBoxGenerate.SelectionStart = textBoxGenerate.Text.Length;
textBoxGenerate.ScrollToCaret();
}
private string FormatSeconds(double seconds)
{
TimeSpan t = TimeSpan.FromSeconds(seconds);
return t.ToString(@"hh\:mm\:ss");
}
private void ImportShotChanges_Shown(object sender, EventArgs e)
{
Activate();

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

BIN
src/ui/Icons/Info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

View File

@ -28,6 +28,8 @@ namespace Nikse.SubtitleEdit.Logic
public LanguageStructure.AssaSetPosition AssaSetPosition;
public LanguageStructure.AutoBreakUnbreakLines AutoBreakUnbreakLines;
public LanguageStructure.BatchConvert BatchConvert;
public LanguageStructure.BeautifyTimeCodes BeautifyTimeCodes;
public LanguageStructure.BeautifyTimeCodesProfile BeautifyTimeCodesProfile;
public LanguageStructure.BinEdit BinEdit;
public LanguageStructure.Bookmarks Bookmarks;
public LanguageStructure.ChangeCasing ChangeCasing;
@ -232,6 +234,7 @@ namespace Nikse.SubtitleEdit.Logic
ShortcutX = "Shortcut: {0}",
ExampleX = "Example: {0}",
Reset = "Reset",
Error = "Error",
Warning = "Warning",
UseLargerFontForThisWindow = "Use larger font for this window",
};
@ -318,11 +321,14 @@ namespace Nikse.SubtitleEdit.Logic
Fixed = "Fixed",
Milliseconds = "Milliseconds",
ExtendOnly = "Extend only",
EnforceDurationLimits = "Enforce minimum and maximum duration",
CheckShotChanges = "Don't extend past shot changes",
};
ApplyDurationLimits = new LanguageStructure.ApplyDurationLimits
{
Title = "Apply duration limits",
CheckShotChanges = "Don't extend past shot changes",
FixesAvailable = "Fixes available: {0}",
UnableToFix = "Unable to fix: {0}",
};
@ -530,6 +536,112 @@ namespace Nikse.SubtitleEdit.Logic
SearchFolderScanVideo = "Also scan video files in \"Search folder\" (slow)",
};
BeautifyTimeCodes = new LanguageStructure.BeautifyTimeCodes
{
Title = "Beautify time codes",
GroupTimeCodes = "Time codes",
AlignTimeCodes = "Align time codes to frame time codes",
ExtractExactTimeCodes = "Use ffprobe to extract exact frame time codes",
ExtractTimeCodes = "Extract time codes",
CancelTimeCodes = "Cancel",
GroupShotChanges = "Shot changes",
SnapToShotChanges = "Snap cues to shot changes",
ImportShotChanges = "Generate / import shot changes...",
EditProfile = "Edit profile...",
NoTimeCodesLoaded = "No time codes loaded",
XTimeCodesLoaded = "{0} time codes loaded",
NoTimeCodesLoadedError =
"You've selected to extract exact frame time codes, but there are no time codes loaded." +
Environment.NewLine + Environment.NewLine +
"Please click \"{0}\" to extract the time codes first, or disable this option.",
NoShotChangesLoaded = "No shot changes loaded",
XShotChangesLoaded = "{0} shot changes loaded",
NoShotChangesLoadedError =
"You've selected to snap cues to shot changes, but there are no shot changes loaded." +
Environment.NewLine + Environment.NewLine +
"Please click \"{0}\" to generate or import shot changes first, or disable this option.",
};
BeautifyTimeCodesProfile = new LanguageStructure.BeautifyTimeCodesProfile
{
Title = "Edit profile",
LoadPreset = "Load preset...",
PresetDefault = "Default",
PresetNetflix = "Netflix",
PresetSDI = "SDI",
CreateSimple = "Simple mode...",
General = "General",
Gap = "Gap:",
GapSuffix = "frames (will overwrite custom settings)",
InCues = "In cues",
SubtitlePreviewText = "Subtitle text.",
Zones = "Zones:",
OutCues = "Out cues",
ConnectedSubtitles = "Connected subtitles",
InCueClosest = "In cue is closest",
OutCueClosest = "Out cue is closest",
TreadAsConnected = "Treat as connected if gap is smaller than:",
Milliseconds = "ms",
Chaining = "Chaining",
InCueOnShot = "In cue on shot change",
OutCueOnShot = "Out cue on shot change",
MaxGap = "Max. gap:",
ShotChangeBehavior = "If there is a shot change in between:",
DontChain = "Don't chain",
ExtendCrossingShotChange = "Extend, crossing shot change",
ExtendUntilShotChange = "Extend until shot change",
ResetWarning =
"This will reset your current profile and replace all values with those of the selected preset. This cannot be undone." +
Environment.NewLine +
Environment.NewLine +
"Do you want to continue?",
CreateSimpleTitle = "Create simple",
CreateSimpleInstruction =
"Enter these basic rules, and the current profile will be updated accordingly.",
CreateSimpleGapInstruction = "The minimum amount of space between subtitles.",
CreateSimpleInCues = "In cues should be:",
CreateSimpleInCues0Frames = "On the shot change",
CreateSimpleInCues1Frames = "1 frame after the shot change",
CreateSimpleInCues2Frames = "2 frames after the shot change",
CreateSimpleInCues3Frames = "3 frames after the shot change",
CreateSimpleOutCues = "Out cues should be:",
CreateSimpleOutCues0Frames = "On the shot change",
CreateSimpleOutCues1Frames = "1 frame before the shot change",
CreateSimpleOutCues2Frames = "2 frames before the shot change",
CreateSimpleOutCues3Frames = "3 frames before the shot change",
CreateSimpleOutCuesGap = "Minimum gap before the shot change",
CreateSimpleSnapClosestCue =
"For connected subtitles, snap the in or out cue to a shot change based on which one is closer",
CreateSimpleMaxOffset = "Max. offset:",
CreateSimpleMaxOffsetInstruction =
"Cues within this distance from shot changes will be snapped to the shot change.",
CreateSimpleSafeZone = "Safe zone:",
CreateSimpleSafeZoneInstruction = "Cues within this distance from shot changes will be moved away from the shot change.",
CreateSimpleChainingGap = "Max. chaining gap:",
CreateSimpleChainingGapInstruction =
"If the space between two subtitles is smaller than this amount, the subtitles will be connected.",
CreateSimpleChainingGapAfterShotChanges = "After an out cue on a shot change, the gap may be smaller",
CreateSimpleChainingToolTip =
"Chaining subtitles is recommended to ensure a consistent \"rhythm\" in the \"flashing\" of the subtitles." +
Environment.NewLine +
"This offers a more relaxed viewing experience." +
Environment.NewLine +
Environment.NewLine +
"After chaining, subtitles are either connected (i.e. a subtitle disappears and a new subtitle appears immediately after a slight pause) or not." +
Environment.NewLine +
"This gives the viewer some sense on when they can shift their focus back to the screen." +
Environment.NewLine +
Environment.NewLine +
"The length of the chaining gap can be a bit smaller right after a subtitle disappears on a shot change, because the changing shot \"resets\" the image in a way." +
Environment.NewLine +
"We leverage the intrinsic rhythm of the image.",
CreateSimpleLoadNetflixRules = "Load Netflix rules",
Frames = "frames",
Maximum = "Max.",
GapInMsFormat = "{0} ms @ {1} FPS",
OffsetSafeZoneError = "The safe zone should be larger than the max. offset.",
};
BinEdit = new LanguageStructure.BinEdit
{
ImportImage = "Import image...",
@ -1502,6 +1614,8 @@ namespace Nikse.SubtitleEdit.Logic
CommonErrorsFixed = "Common errors fixed",
BeforeRenumbering = "Before renumbering",
RenumberedStartingFromX = "Renumbered starting from: {0}",
BeforeBeautifyTimeCodes = "Before beautifying time codes",
BeautifiedTimeCodes = "Time codes beautified",
BeforeRemovalOfTextingForHearingImpaired = "Before removal of texting for hearing impaired",
TextingForHearingImpairedRemovedOneLine = "Texting for hearing impaired removed: One line",
TextingForHearingImpairedRemovedXLines = "Texting for hearing impaired removed: {0} lines",
@ -1817,6 +1931,7 @@ namespace Nikse.SubtitleEdit.Logic
SplitLongLines = "Break/split long lines...",
MinimumDisplayTimeBetweenParagraphs = "Apply minimum gap between subtitles...",
NetflixQualityCheck = "Netflix quality check...",
BeautifyTimeCodes = "Beautify time codes...",
SortBy = "Sort by",
Number = "Number",
StartTime = "Start time",
@ -1934,6 +2049,7 @@ namespace Nikse.SubtitleEdit.Logic
VisualSync = "Visual sync",
SpellCheck = "Spell check",
NetflixQualityCheck = "Netflix quality check",
BeautifyTimeCodes = "Beautify time codes",
Settings = "Settings",
Help = "Help",
ShowHideWaveform = "Show/hide waveform",
@ -2512,6 +2628,7 @@ can edit in same subtitle file (collaboration)",
BurnIn = "Burn in",
SpellCheck = "Spell check",
NetflixQualityCheck = "Netflix quality check",
BeautifyTimeCodes = "Beautify time codes",
SettingsName = "Settings",
ToggleBookmarks = "Toggle bookmarks",
ToggleBookmarksWithComment = "Toggle bookmarks - add comment",
@ -2632,6 +2749,7 @@ can edit in same subtitle file (collaboration)",
WaveformListViewFocusMouseEnter = "Also set list view focus on mouse enter in list view",
WaveformSingleClickSelect = "Single click to select subtitles",
WaveformSnapToShotChanges = "Snap to shot changes (hold Shift to override)",
WaveformEditShotChangesProfile = "Edit profile...",
WaveformAutoGen = "Auto generate waveform when opening video",
WaveformBorderHitMs1 = "Border marker hit must be within",
WaveformBorderHitMs2 = "milliseconds",
@ -2785,15 +2903,13 @@ can edit in same subtitle file (collaboration)",
AdjustSetEndAndOffsetTheRest = "Set end, offset the rest",
AdjustSetEndAndOffsetTheRestAndGoToNext = "Set end, offset the rest and go to next",
AdjustSnapStartToNextShotChange = "Snap selected lines start to next shot change",
AdjustSnapStartToNextShotChangeWithGap = "Snap selected lines start to next shot change with min. gap",
AdjustSnapEndToPreviousShotChange = "Snap selected lines end to previous shot change",
AdjustSnapEndToPreviousShotChangeWithGap = "Snap selected lines end to previous shot change with min. gap",
AdjustExtendToNextShotChange = "Extend selected lines to next shot change (or next subtitle)",
AdjustExtendToNextShotChangeWithGap = "Extend selected lines to next shot change with min. gap (or next subtitle)",
AdjustExtendToPreviousShotChange = "Extend selected lines to previous shot change (or previous subtitle)",
AdjustExtendToPreviousShotChangeWithGap = "Extend selected lines to previous shot change with min. gap (or previous subtitle)",
AdjustExtendToNextSubtitle = "Extend selected lines to next subtitle",
AdjustExtendToPreviousSubtitle = "Extend selected lines to previous subtitle",
AdjustExtendToNextSubtitleMinusChainingGap = "Extend selected lines to next subtitle with chaining gap",
AdjustExtendToPreviousSubtitleMinusChainingGap = "Extend selected lines to previous subtitle with chaining gap",
AdjustExtendCurrentSubtitle = "Extend current line to next subtitle or max duration",
AdjustExtendPreviousLineEndToCurrentStart = "Extend previous line's end to current's start",
AdjustExtendNextLineStartToCurrentEnd = "Extend next line's start to current's end",

View File

@ -352,6 +352,9 @@ namespace Nikse.SubtitleEdit.Logic
case "General/Reset":
language.General.Reset = reader.Value;
break;
case "General/Error":
language.General.Error = reader.Value;
break;
case "General/Warning":
language.General.Warning = reader.Value;
break;
@ -472,9 +475,18 @@ namespace Nikse.SubtitleEdit.Logic
case "AdjustDisplayDuration/ExtendOnly":
language.AdjustDisplayDuration.ExtendOnly = reader.Value;
break;
case "AdjustDisplayDuration/EnforceDurationLimits":
language.AdjustDisplayDuration.EnforceDurationLimits = reader.Value;
break;
case "AdjustDisplayDuration/CheckShotChanges":
language.AdjustDisplayDuration.CheckShotChanges = reader.Value;
break;
case "ApplyDurationLimits/Title":
language.ApplyDurationLimits.Title = reader.Value;
break;
case "ApplyDurationLimits/CheckShotChanges":
language.ApplyDurationLimits.CheckShotChanges = reader.Value;
break;
case "ApplyDurationLimits/FixesAvailable":
language.ApplyDurationLimits.FixesAvailable = reader.Value;
break;
@ -970,6 +982,219 @@ namespace Nikse.SubtitleEdit.Logic
case "BatchConvert/SearchFolderScanVideo":
language.BatchConvert.SearchFolderScanVideo = reader.Value;
break;
case "BeautifyTimeCodes/Title":
language.BeautifyTimeCodes.Title = reader.Value;
break;
case "BeautifyTimeCodes/GroupTimeCodes":
language.BeautifyTimeCodes.GroupTimeCodes = reader.Value;
break;
case "BeautifyTimeCodes/AlignTimeCodes":
language.BeautifyTimeCodes.AlignTimeCodes = reader.Value;
break;
case "BeautifyTimeCodes/ExtractExactTimeCodes":
language.BeautifyTimeCodes.ExtractExactTimeCodes = reader.Value;
break;
case "BeautifyTimeCodes/ExtractTimeCodes":
language.BeautifyTimeCodes.ExtractTimeCodes = reader.Value;
break;
case "BeautifyTimeCodes/CancelTimeCodes":
language.BeautifyTimeCodes.CancelTimeCodes = reader.Value;
break;
case "BeautifyTimeCodes/GroupShotChanges":
language.BeautifyTimeCodes.GroupShotChanges = reader.Value;
break;
case "BeautifyTimeCodes/SnapToShotChanges":
language.BeautifyTimeCodes.SnapToShotChanges = reader.Value;
break;
case "BeautifyTimeCodes/ImportShotChanges":
language.BeautifyTimeCodes.ImportShotChanges = reader.Value;
break;
case "BeautifyTimeCodes/EditProfile":
language.BeautifyTimeCodes.EditProfile = reader.Value;
break;
case "BeautifyTimeCodes/NoTimeCodesLoaded":
language.BeautifyTimeCodes.NoTimeCodesLoaded = reader.Value;
break;
case "BeautifyTimeCodes/XTimeCodesLoaded":
language.BeautifyTimeCodes.XTimeCodesLoaded = reader.Value;
break;
case "BeautifyTimeCodes/NoTimeCodesLoadedError":
language.BeautifyTimeCodes.NoTimeCodesLoadedError = reader.Value;
break;
case "BeautifyTimeCodes/NoShotChangesLoaded":
language.BeautifyTimeCodes.NoShotChangesLoaded = reader.Value;
break;
case "BeautifyTimeCodes/XShotChangesLoaded":
language.BeautifyTimeCodes.XShotChangesLoaded = reader.Value;
break;
case "BeautifyTimeCodes/NoShotChangesLoadedError":
language.BeautifyTimeCodes.NoShotChangesLoadedError = reader.Value;
break;
case "BeautifyTimeCodesProfile/Title":
language.BeautifyTimeCodesProfile.Title = reader.Value;
break;
case "BeautifyTimeCodesProfile/LoadPreset":
language.BeautifyTimeCodesProfile.LoadPreset = reader.Value;
break;
case "BeautifyTimeCodesProfile/PresetDefault":
language.BeautifyTimeCodesProfile.PresetDefault = reader.Value;
break;
case "BeautifyTimeCodesProfile/PresetNetflix":
language.BeautifyTimeCodesProfile.PresetNetflix = reader.Value;
break;
case "BeautifyTimeCodesProfile/PresetSDI":
language.BeautifyTimeCodesProfile.PresetSDI = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimple":
language.BeautifyTimeCodesProfile.CreateSimple = reader.Value;
break;
case "BeautifyTimeCodesProfile/General":
language.BeautifyTimeCodesProfile.General = reader.Value;
break;
case "BeautifyTimeCodesProfile/Gap":
language.BeautifyTimeCodesProfile.Gap = reader.Value;
break;
case "BeautifyTimeCodesProfile/GapSuffix":
language.BeautifyTimeCodesProfile.GapSuffix = reader.Value;
break;
case "BeautifyTimeCodesProfile/InCues":
language.BeautifyTimeCodesProfile.InCues = reader.Value;
break;
case "BeautifyTimeCodesProfile/SubtitlePreviewText":
language.BeautifyTimeCodesProfile.SubtitlePreviewText = reader.Value;
break;
case "BeautifyTimeCodesProfile/Zones":
language.BeautifyTimeCodesProfile.Zones = reader.Value;
break;
case "BeautifyTimeCodesProfile/OutCues":
language.BeautifyTimeCodesProfile.OutCues = reader.Value;
break;
case "BeautifyTimeCodesProfile/ConnectedSubtitles":
language.BeautifyTimeCodesProfile.ConnectedSubtitles = reader.Value;
break;
case "BeautifyTimeCodesProfile/InCueClosest":
language.BeautifyTimeCodesProfile.InCueClosest = reader.Value;
break;
case "BeautifyTimeCodesProfile/OutCueClosest":
language.BeautifyTimeCodesProfile.OutCueClosest = reader.Value;
break;
case "BeautifyTimeCodesProfile/TreadAsConnected":
language.BeautifyTimeCodesProfile.TreadAsConnected = reader.Value;
break;
case "BeautifyTimeCodesProfile/Milliseconds":
language.BeautifyTimeCodesProfile.Milliseconds = reader.Value;
break;
case "BeautifyTimeCodesProfile/Chaining":
language.BeautifyTimeCodesProfile.Chaining = reader.Value;
break;
case "BeautifyTimeCodesProfile/InCueOnShot":
language.BeautifyTimeCodesProfile.InCueOnShot = reader.Value;
break;
case "BeautifyTimeCodesProfile/OutCueOnShot":
language.BeautifyTimeCodesProfile.OutCueOnShot = reader.Value;
break;
case "BeautifyTimeCodesProfile/MaxGap":
language.BeautifyTimeCodesProfile.MaxGap = reader.Value;
break;
case "BeautifyTimeCodesProfile/ShotChangeBehavior":
language.BeautifyTimeCodesProfile.ShotChangeBehavior = reader.Value;
break;
case "BeautifyTimeCodesProfile/DontChain":
language.BeautifyTimeCodesProfile.DontChain = reader.Value;
break;
case "BeautifyTimeCodesProfile/ExtendCrossingShotChange":
language.BeautifyTimeCodesProfile.ExtendCrossingShotChange = reader.Value;
break;
case "BeautifyTimeCodesProfile/ExtendUntilShotChange":
language.BeautifyTimeCodesProfile.ExtendUntilShotChange = reader.Value;
break;
case "BeautifyTimeCodesProfile/ResetWarning":
language.BeautifyTimeCodesProfile.ResetWarning = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleTitle":
language.BeautifyTimeCodesProfile.CreateSimpleTitle = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleInstruction":
language.BeautifyTimeCodesProfile.CreateSimpleInstruction = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleGapInstruction":
language.BeautifyTimeCodesProfile.CreateSimpleGapInstruction = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleInCues":
language.BeautifyTimeCodesProfile.CreateSimpleInCues = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleInCues0Frames":
language.BeautifyTimeCodesProfile.CreateSimpleInCues0Frames = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleInCues1Frames":
language.BeautifyTimeCodesProfile.CreateSimpleInCues1Frames = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleInCues2Frames":
language.BeautifyTimeCodesProfile.CreateSimpleInCues2Frames = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleInCues3Frames":
language.BeautifyTimeCodesProfile.CreateSimpleInCues3Frames = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleOutCues":
language.BeautifyTimeCodesProfile.CreateSimpleOutCues = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleOutCues0Frames":
language.BeautifyTimeCodesProfile.CreateSimpleOutCues0Frames = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleOutCues1Frames":
language.BeautifyTimeCodesProfile.CreateSimpleOutCues1Frames = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleOutCues2Frames":
language.BeautifyTimeCodesProfile.CreateSimpleOutCues2Frames = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleOutCues3Frames":
language.BeautifyTimeCodesProfile.CreateSimpleOutCues3Frames = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleOutCuesGap":
language.BeautifyTimeCodesProfile.CreateSimpleOutCuesGap = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleSnapClosestCue":
language.BeautifyTimeCodesProfile.CreateSimpleSnapClosestCue = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleMaxOffset":
language.BeautifyTimeCodesProfile.CreateSimpleMaxOffset = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleMaxOffsetInstruction":
language.BeautifyTimeCodesProfile.CreateSimpleMaxOffsetInstruction = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleSafeZone":
language.BeautifyTimeCodesProfile.CreateSimpleSafeZone = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleSafeZoneInstruction":
language.BeautifyTimeCodesProfile.CreateSimpleSafeZoneInstruction = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleChainingGap":
language.BeautifyTimeCodesProfile.CreateSimpleChainingGap = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleChainingGapInstruction":
language.BeautifyTimeCodesProfile.CreateSimpleChainingGapInstruction = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleChainingGapAfterShotChanges":
language.BeautifyTimeCodesProfile.CreateSimpleChainingGapAfterShotChanges = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleChainingToolTip":
language.BeautifyTimeCodesProfile.CreateSimpleChainingToolTip = reader.Value;
break;
case "BeautifyTimeCodesProfile/CreateSimpleLoadNetflixRules":
language.BeautifyTimeCodesProfile.CreateSimpleLoadNetflixRules = reader.Value;
break;
case "BeautifyTimeCodesProfile/Frames":
language.BeautifyTimeCodesProfile.Frames = reader.Value;
break;
case "BeautifyTimeCodesProfile/Maximum":
language.BeautifyTimeCodesProfile.Maximum = reader.Value;
break;
case "BeautifyTimeCodesProfile/GapInMsFormat":
language.BeautifyTimeCodesProfile.GapInMsFormat = reader.Value;
break;
case "BeautifyTimeCodesProfile/OffsetSafeZoneError":
language.BeautifyTimeCodesProfile.OffsetSafeZoneError = reader.Value;
break;
case "BinEdit/ImportImage":
language.BinEdit.ImportImage = reader.Value;
break;
@ -3334,6 +3559,12 @@ namespace Nikse.SubtitleEdit.Logic
case "Main/RenumberedStartingFromX":
language.Main.RenumberedStartingFromX = reader.Value;
break;
case "Main/BeforeBeautifyTimeCodes":
language.Main.BeforeBeautifyTimeCodes = reader.Value;
break;
case "Main/BeautifiedTimeCodes":
language.Main.BeautifiedTimeCodes = reader.Value;
break;
case "Main/BeforeRemovalOfTextingForHearingImpaired":
language.Main.BeforeRemovalOfTextingForHearingImpaired = reader.Value;
break;
@ -4246,6 +4477,9 @@ namespace Nikse.SubtitleEdit.Logic
case "Main/Menu/Tools/NetflixQualityCheck":
language.Main.Menu.Tools.NetflixQualityCheck = reader.Value;
break;
case "Main/Menu/Tools/BeautifyTimeCodes":
language.Main.Menu.Tools.BeautifyTimeCodes = reader.Value;
break;
case "Main/Menu/Tools/TextAlphabetically":
language.Main.Menu.Tools.TextAlphabetically = reader.Value;
break;
@ -4483,6 +4717,9 @@ namespace Nikse.SubtitleEdit.Logic
case "Main/Menu/ToolBar/NetflixQualityCheck":
language.Main.Menu.ToolBar.NetflixQualityCheck = reader.Value;
break;
case "Main/Menu/ToolBar/BeautifyTimeCodes":
language.Main.Menu.ToolBar.BeautifyTimeCodes = reader.Value;
break;
case "Main/Menu/ToolBar/Settings":
language.Main.Menu.ToolBar.Settings = reader.Value;
break;
@ -5860,6 +6097,9 @@ namespace Nikse.SubtitleEdit.Logic
case "Settings/NetflixQualityCheck":
language.Settings.NetflixQualityCheck = reader.Value;
break;
case "Settings/BeautifyTimeCodes":
language.Settings.BeautifyTimeCodes = reader.Value;
break;
case "Settings/SettingsName":
language.Settings.SettingsName = reader.Value;
break;
@ -6220,6 +6460,9 @@ namespace Nikse.SubtitleEdit.Logic
case "Settings/WaveformSnapToShotChanges":
language.Settings.WaveformSnapToShotChanges = reader.Value;
break;
case "Settings/WaveformEditShotChangesProfile":
language.Settings.WaveformEditShotChangesProfile = reader.Value;
break;
case "Settings/WaveformAutoGen":
language.Settings.WaveformAutoGen = reader.Value;
break;
@ -6685,33 +6928,27 @@ namespace Nikse.SubtitleEdit.Logic
case "Settings/AdjustSnapStartToNextShotChange":
language.Settings.AdjustSnapStartToNextShotChange = reader.Value;
break;
case "Settings/AdjustSnapStartToNextShotChangeWithGap":
language.Settings.AdjustSnapStartToNextShotChangeWithGap = reader.Value;
break;
case "Settings/AdjustSnapEndToPreviousShotChange":
language.Settings.AdjustSnapEndToPreviousShotChange = reader.Value;
break;
case "Settings/AdjustSnapEndToPreviousShotChangeWithGap":
language.Settings.AdjustSnapEndToPreviousShotChangeWithGap = reader.Value;
break;
case "Settings/AdjustExtendToNextShotChange":
language.Settings.AdjustExtendToNextShotChange = reader.Value;
break;
case "Settings/AdjustExtendToNextShotChangeWithGap":
language.Settings.AdjustExtendToNextShotChangeWithGap = reader.Value;
break;
case "Settings/AdjustExtendToPreviousShotChange":
language.Settings.AdjustExtendToPreviousShotChange = reader.Value;
break;
case "Settings/AdjustExtendToPreviousShotChangeWithGap":
language.Settings.AdjustExtendToPreviousShotChangeWithGap = reader.Value;
break;
case "Settings/AdjustExtendToNextSubtitle":
language.Settings.AdjustExtendToNextSubtitle = reader.Value;
break;
case "Settings/AdjustExtendToPreviousSubtitle":
language.Settings.AdjustExtendToPreviousSubtitle = reader.Value;
break;
case "Settings/AdjustExtendToNextSubtitleMinusChainingGap":
language.Settings.AdjustExtendToNextSubtitleMinusChainingGap = reader.Value;
break;
case "Settings/AdjustExtendToPreviousSubtitleMinusChainingGap":
language.Settings.AdjustExtendToPreviousSubtitleMinusChainingGap = reader.Value;
break;
case "Settings/AdjustExtendCurrentSubtitle":
language.Settings.AdjustExtendCurrentSubtitle = reader.Value;
break;

View File

@ -105,6 +105,7 @@ namespace Nikse.SubtitleEdit.Logic
public string ShortcutX { get; set; }
public string ExampleX { get; set; }
public string Reset { get; set; }
public string Error { get; set; }
public string Warning { get; set; }
public string UseLargerFontForThisWindow { get; set; }
}
@ -173,11 +174,14 @@ namespace Nikse.SubtitleEdit.Logic
public string Fixed { get; set; }
public string Milliseconds { get; set; }
public string ExtendOnly { get; set; }
public string EnforceDurationLimits { get; set; }
public string CheckShotChanges { get; set; }
}
public class ApplyDurationLimits
{
public string Title { get; set; }
public string CheckShotChanges { get; set; }
public string FixesAvailable { get; set; }
public string UnableToFix { get; set; }
}
@ -385,6 +389,85 @@ namespace Nikse.SubtitleEdit.Logic
public string SearchFolderScanVideo { get; set; }
}
public class BeautifyTimeCodes
{
public string Title { get; set; }
public string GroupTimeCodes { get; set; }
public string AlignTimeCodes { get; set; }
public string ExtractExactTimeCodes { get; set; }
public string ExtractTimeCodes { get; set; }
public string CancelTimeCodes { get; set; }
public string GroupShotChanges { get; set; }
public string SnapToShotChanges { get; set; }
public string ImportShotChanges { get; set; }
public string EditProfile { get; set; }
public string NoTimeCodesLoaded { get; set; }
public string XTimeCodesLoaded { get; set; }
public string NoTimeCodesLoadedError { get; set; }
public string NoShotChangesLoaded { get; set; }
public string XShotChangesLoaded { get; set; }
public string NoShotChangesLoadedError { get; set; }
}
public class BeautifyTimeCodesProfile
{
public string Title { get; set; }
public string LoadPreset { get; set; }
public string PresetDefault { get; set; }
public string PresetNetflix { get; set; }
public string PresetSDI { get; set; }
public string CreateSimple { get; set; }
public string General { get; set; }
public string Gap { get; set; }
public string GapSuffix { get; set; }
public string InCues { get; set; }
public string SubtitlePreviewText { get; set; }
public string Zones { get; set; }
public string OutCues { get; set; }
public string ConnectedSubtitles { get; set; }
public string InCueClosest { get; set; }
public string OutCueClosest { get; set; }
public string TreadAsConnected { get; set; }
public string Milliseconds { get; set; }
public string Chaining { get; set; }
public string InCueOnShot { get; set; }
public string OutCueOnShot { get; set; }
public string MaxGap { get; set; }
public string ShotChangeBehavior { get; set; }
public string DontChain { get; set; }
public string ExtendCrossingShotChange { get; set; }
public string ExtendUntilShotChange { get; set; }
public string ResetWarning { get; set; }
public string CreateSimpleTitle { get; set; }
public string CreateSimpleInstruction { get; set; }
public string CreateSimpleGapInstruction { get; set; }
public string CreateSimpleInCues { get; set; }
public string CreateSimpleInCues0Frames { get; set; }
public string CreateSimpleInCues1Frames { get; set; }
public string CreateSimpleInCues2Frames { get; set; }
public string CreateSimpleInCues3Frames { get; set; }
public string CreateSimpleOutCues { get; set; }
public string CreateSimpleOutCues0Frames { get; set; }
public string CreateSimpleOutCues1Frames { get; set; }
public string CreateSimpleOutCues2Frames { get; set; }
public string CreateSimpleOutCues3Frames { get; set; }
public string CreateSimpleOutCuesGap { get; set; }
public string CreateSimpleSnapClosestCue { get; set; }
public string CreateSimpleMaxOffset { get; set; }
public string CreateSimpleMaxOffsetInstruction { get; set; }
public string CreateSimpleSafeZone { get; set; }
public string CreateSimpleSafeZoneInstruction { get; set; }
public string CreateSimpleChainingGap { get; set; }
public string CreateSimpleChainingGapInstruction { get; set; }
public string CreateSimpleChainingGapAfterShotChanges { get; set; }
public string CreateSimpleChainingToolTip { get; set; }
public string CreateSimpleLoadNetflixRules { get; set; }
public string Frames { get; set; }
public string Maximum { get; set; }
public string GapInMsFormat { get; set; }
public string OffsetSafeZoneError { get; set; }
}
public class BinEdit
{
public string ImportImage { get; set; }
@ -1355,6 +1438,8 @@ namespace Nikse.SubtitleEdit.Logic
public string CommonErrorsFixed { get; set; }
public string BeforeRenumbering { get; set; }
public string RenumberedStartingFromX { get; set; }
public string BeforeBeautifyTimeCodes { get; set; }
public string BeautifiedTimeCodes { get; set; }
public string BeforeRemovalOfTextingForHearingImpaired { get; set; }
public string TextingForHearingImpairedRemovedOneLine { get; set; }
public string TextingForHearingImpairedRemovedXLines { get; set; }
@ -1670,6 +1755,7 @@ namespace Nikse.SubtitleEdit.Logic
public string Duration { get; set; }
public string ListErrors { get; set; }
public string NetflixQualityCheck { get; set; }
public string BeautifyTimeCodes { get; set; }
public string TextAlphabetically { get; set; }
public string TextSingleLineMaximumLength { get; set; }
public string TextTotalLength { get; set; }
@ -1776,6 +1862,7 @@ namespace Nikse.SubtitleEdit.Logic
public string VisualSync { get; set; }
public string SpellCheck { get; set; }
public string NetflixQualityCheck { get; set; }
public string BeautifyTimeCodes { get; set; }
public string Settings { get; set; }
public string Help { get; set; }
public string ShowHideWaveform { get; set; }
@ -2355,6 +2442,7 @@ namespace Nikse.SubtitleEdit.Logic
public string BurnIn { get; set; }
public string SpellCheck { get; set; }
public string NetflixQualityCheck { get; set; }
public string BeautifyTimeCodes { get; set; }
public string SettingsName { get; set; }
public string ToggleBookmarks { get; set; }
public string ToggleBookmarksWithComment { get; set; }
@ -2478,6 +2566,7 @@ namespace Nikse.SubtitleEdit.Logic
public string WaveformListViewFocusMouseEnter { get; set; }
public string WaveformSingleClickSelect { get; set; }
public string WaveformSnapToShotChanges { get; set; }
public string WaveformEditShotChangesProfile { get; set; }
public string WaveformAutoGen { get; set; }
public string WaveformBorderHitMs1 { get; set; }
public string WaveformBorderHitMs2 { get; set; }
@ -2635,15 +2724,13 @@ namespace Nikse.SubtitleEdit.Logic
public string AdjustSetEndAndOffsetTheRest { get; set; }
public string AdjustSetEndAndOffsetTheRestAndGoToNext { get; set; }
public string AdjustSnapStartToNextShotChange { get; set; }
public string AdjustSnapStartToNextShotChangeWithGap { get; set; }
public string AdjustSnapEndToPreviousShotChange { get; set; }
public string AdjustSnapEndToPreviousShotChangeWithGap { get; set; }
public string AdjustExtendToNextShotChange { get; set; }
public string AdjustExtendToNextShotChangeWithGap { get; set; }
public string AdjustExtendToPreviousShotChange { get; set; }
public string AdjustExtendToPreviousShotChangeWithGap { get; set; }
public string AdjustExtendToNextSubtitle { get; set; }
public string AdjustExtendToPreviousSubtitle { get; set; }
public string AdjustExtendToNextSubtitleMinusChainingGap { get; set; }
public string AdjustExtendToPreviousSubtitleMinusChainingGap { get; set; }
public string AdjustExtendCurrentSubtitle { get; set; }
public string AdjustExtendPreviousLineEndToCurrentStart { get; set; }
public string AdjustExtendNextLineStartToCurrentEnd { get; set; }

View File

@ -159,15 +159,13 @@ namespace Nikse.SubtitleEdit.Logic
public Keys MainAdjustMoveEndOneFrameBackKeepGapNext { get; set; }
public Keys MainAdjustMoveEndOneFrameForwardKeepGapNext { get; set; }
public Keys MainAdjustSnapStartToNextShotChange { get; set; }
public Keys MainAdjustSnapStartToNextShotChangeWithGap { get; set; }
public Keys MainAdjustSnapEndToPreviousShotChange { get; set; }
public Keys MainAdjustSnapEndToPreviousShotChangeWithGap { get; set; }
public Keys MainAdjustExtendToNextShotChange { get; set; }
public Keys MainAdjustExtendToNextShotChangeWithGap { get; set; }
public Keys MainAdjustExtendToPreviousShotChange { get; set; }
public Keys MainAdjustExtendToPreviousShotChangeWithGap { get; set; }
public Keys MainAdjustExtendToNextSubtitle { get; set; }
public Keys MainAdjustExtendToPreviousSubtitle { get; set; }
public Keys MainAdjustExtendToNextSubtitleMinusChainingGap { get; set; }
public Keys MainAdjustExtendToPreviousSubtitleMinusChainingGap { get; set; }
public Keys MainAdjustExtendCurrentSubtitle { get; set; }
public Keys MainAdjustExtendPreviousLineEndToCurrentStart { get; set; }
public Keys MainAdjustExtendNextLineStartToCurrentEnd { get; set; }
@ -437,15 +435,13 @@ namespace Nikse.SubtitleEdit.Logic
MainAdjustMoveEndOneFrameBackKeepGapNext = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MoveEndOneFrameBackKeepGapNext);
MainAdjustMoveEndOneFrameForwardKeepGapNext = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MoveEndOneFrameForwardKeepGapNext);
MainAdjustSnapStartToNextShotChange = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSnapStartToNextShotChange);
MainAdjustSnapStartToNextShotChangeWithGap = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSnapStartToNextShotChangeWithGap);
MainAdjustSnapEndToPreviousShotChange = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSnapEndToPreviousShotChange);
MainAdjustSnapEndToPreviousShotChangeWithGap = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSnapEndToPreviousShotChangeWithGap);
MainAdjustExtendToNextShotChange = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendToNextShotChange);
MainAdjustExtendToNextShotChangeWithGap = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendToNextShotChangeWithGap);
MainAdjustExtendToPreviousShotChange = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendToPreviousShotChange);
MainAdjustExtendToPreviousShotChangeWithGap = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendToPreviousShotChangeWithGap);
MainAdjustExtendToNextSubtitle = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendToNextSubtitle);
MainAdjustExtendToPreviousSubtitle = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendToPreviousSubtitle);
MainAdjustExtendToNextSubtitleMinusChainingGap = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendToNextSubtitleMinusChainingGap);
MainAdjustExtendToPreviousSubtitleMinusChainingGap = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendToPreviousSubtitleMinusChainingGap);
MainAdjustExtendCurrentSubtitle = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendCurrentSubtitle);
MainAdjustExtendPreviousLineEndToCurrentStart = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendPreviousLineEndToCurrentStart);
MainAdjustExtendNextLineStartToCurrentEnd = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustExtendNextLineStartToCurrentEnd);

View File

@ -51,7 +51,7 @@ namespace Nikse.SubtitleEdit.Logic
StartInfo =
{
FileName = ffmpegLocation,
Arguments = $"-i \"{videoFileName}\" -vf \"select=gt(scene\\," + threshold.ToString(CultureInfo.InvariantCulture) + "),showinfo\" -vsync vfr -f null -",
Arguments = $"-i \"{videoFileName}\" -vf \"select=gt(scene\\," + threshold.ToString(CultureInfo.InvariantCulture) + "),showinfo\" -threads 0 -vsync vfr -f null -",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,

View File

@ -0,0 +1,90 @@
using Nikse.SubtitleEdit.Core.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace Nikse.SubtitleEdit.Logic
{
public class TimeCodesGenerator
{
private List<double> _timeCodes;
public List<double> GetTimeCodes()
{
lock (TimeCodesLock)
{
return _timeCodes;
}
}
private static readonly object TimeCodesLock = new object();
public double LastSeconds { get; private set; }
private string line;
public TimeCodesGenerator()
{
_timeCodes = new List<double>();
}
public Process GetProcess(string videoFileName)
{
lock (TimeCodesLock)
{
_timeCodes = new List<double>();
}
var ffProbePath = Path.GetDirectoryName(Configuration.Settings.General.FFmpegLocation) + Path.DirectorySeparatorChar + "ffprobe" + Path.GetExtension(Configuration.Settings.General.FFmpegLocation);
if (!Configuration.IsRunningOnWindows && (string.IsNullOrEmpty(ffProbePath) || !File.Exists(ffProbePath)))
{
ffProbePath = "ffprobe";
}
var process = new Process
{
StartInfo =
{
FileName = ffProbePath,
Arguments = $"-select_streams v -show_frames -show_entries frame=pkt_dts_time -of csv -threads 0 \"{videoFileName}\"",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
}
};
process.OutputDataReceived += OutputHandler;
process.ErrorDataReceived += OutputHandler;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
return process;
}
private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
line = outLine.Data;
if (string.IsNullOrWhiteSpace(line))
{
return;
}
if (line.StartsWith("frame,") && !line.Contains("N/A"))
{
string timeString = line.Replace("frame,", "").Trim();
if (timeString.Contains("side_data")) timeString = timeString.Substring(0, timeString.IndexOf("side_data", StringComparison.Ordinal));
var timeCode = timeString.Replace(",", ".").Replace("٫", ".").Replace("⠨", ".");
if (double.TryParse(timeCode, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var seconds))
{
lock (TimeCodesLock)
{
_timeCodes.Add(seconds);
}
LastSeconds = seconds;
}
}
}
}
}

View File

@ -1386,6 +1386,21 @@ namespace Nikse.SubtitleEdit.Logic
}
}
public static string GetBeautifyTimeCodesProfilePresetName(BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.Preset preset)
{
switch (preset)
{
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.Preset.Default:
return LanguageSettings.Current.BeautifyTimeCodesProfile.PresetDefault;
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.Preset.Netflix:
return LanguageSettings.Current.BeautifyTimeCodesProfile.PresetNetflix;
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.Preset.SDI:
return LanguageSettings.Current.BeautifyTimeCodesProfile.PresetSDI;
default:
return preset.ToString();
}
}
public static string DecimalSeparator => CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
public static Control FindFocusedControl(Control control)

View File

@ -106,6 +106,9 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Controls\CuesPreviewView.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Controls\NikseTimeUpDown.cs">
<SubType>Component</SubType>
</Compile>
@ -280,6 +283,24 @@
<Compile Include="Forms\BatchConvertTsSettings.Designer.cs">
<DependentUpon>BatchConvertTsSettings.cs</DependentUpon>
</Compile>
<Compile Include="Forms\BeautifyTimeCodes\BeautifyTimeCodes.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\BeautifyTimeCodes\BeautifyTimeCodes.Designer.cs">
<DependentUpon>BeautifyTimeCodes.cs</DependentUpon>
</Compile>
<Compile Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesProfile.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesProfile.Designer.cs">
<DependentUpon>BeautifyTimeCodesProfile.cs</DependentUpon>
</Compile>
<Compile Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesProfileSimple.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesProfileSimple.Designer.cs">
<DependentUpon>BeautifyTimeCodesProfileSimple.cs</DependentUpon>
</Compile>
<Compile Include="Forms\BinaryEdit\BinEdit.cs">
<SubType>Form</SubType>
</Compile>
@ -1518,6 +1539,7 @@
<Compile Include="Logic\TaskbarList.cs" />
<Compile Include="Logic\TextDesigner.cs" />
<Compile Include="Logic\TextWidth.cs" />
<Compile Include="Logic\TimeCodesGenerator.cs" />
<Compile Include="Logic\UiEbuSaveHelper.cs" />
<Compile Include="Logic\UiGetPacEncoding.cs" />
<Compile Include="Logic\UiGetYouTubeAnnotationStyles.cs" />
@ -1634,6 +1656,15 @@
<EmbeddedResource Include="Forms\BatchConvertTsSettings.resx">
<DependentUpon>BatchConvertTsSettings.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\BeautifyTimeCodes\BeautifyTimeCodes.resx">
<DependentUpon>BeautifyTimeCodes.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesProfile.resx">
<DependentUpon>BeautifyTimeCodesProfile.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesProfileSimple.resx">
<DependentUpon>BeautifyTimeCodesProfileSimple.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\BinaryEdit\BinEdit.resx">
<DependentUpon>BinEdit.cs</DependentUpon>
</EmbeddedResource>
@ -2262,6 +2293,7 @@
<None Include="Resources\color-picker-small2.png" />
<None Include="Resources\rec32.png" />
<None Include="Resources\Help32.png" />
<Content Include="Icons\BeautifyTimeCodes.png" />
<Content Include="SE2.ico" />
<None Include="Resources\SE.ico" />
<None Include="Hunspellx64.dll">