diff --git a/ShareX.HelpersLib/Helpers/FileHelpers.cs b/ShareX.HelpersLib/Helpers/FileHelpers.cs index 59f9c6db5..c93f57bb3 100644 --- a/ShareX.HelpersLib/Helpers/FileHelpers.cs +++ b/ShareX.HelpersLib/Helpers/FileHelpers.cs @@ -131,6 +131,21 @@ public static string ChangeFileNameExtension(string fileName, string extension) return fileName; } + public static string AppendTextToFileName(string filePath, string text) + { + if (!string.IsNullOrEmpty(filePath)) + { + int pos = filePath.LastIndexOf('.'); + + if (pos >= 0) + { + return filePath.Substring(0, pos) + text + filePath.Substring(pos); + } + } + + return filePath + text; + } + public static string AppendExtension(string filePath, string extension) { return filePath.TrimEnd('.') + '.' + extension.TrimStart('.'); diff --git a/ShareX.MediaLib/FFmpegCLIManager.cs b/ShareX.MediaLib/FFmpegCLIManager.cs index 4dc7daf4e..6796e335f 100644 --- a/ShareX.MediaLib/FFmpegCLIManager.cs +++ b/ShareX.MediaLib/FFmpegCLIManager.cs @@ -291,7 +291,7 @@ public void ConcatenateVideos(string[] inputFiles, string outputFile, bool autoD { foreach (string inputFile in inputFiles) { - if (!inputFile.Equals(outputFile, StringComparison.OrdinalIgnoreCase) && File.Exists(inputFile)) + if (File.Exists(inputFile)) { File.Delete(inputFile); } diff --git a/ShareX.ScreenCaptureLib/Enums.cs b/ShareX.ScreenCaptureLib/Enums.cs index 710295771..01aeeccfd 100644 --- a/ShareX.ScreenCaptureLib/Enums.cs +++ b/ShareX.ScreenCaptureLib/Enums.cs @@ -339,6 +339,6 @@ public enum BorderStyle // Localized public enum ScreenRecordState { - Waiting, BeforeStart, AfterStart, AfterRecordingStart, Encoding + Waiting, BeforeStart, AfterStart, AfterRecordingStart, RecordingEnd, Encoding } } \ No newline at end of file diff --git a/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.Designer.cs b/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.Designer.cs index b198514cf..766cb6326 100644 --- a/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.Designer.cs +++ b/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.Designer.cs @@ -26,6 +26,7 @@ private void InitializeComponent() this.tsmiStart = new System.Windows.Forms.ToolStripMenuItem(); this.tsmiAbort = new System.Windows.Forms.ToolStripMenuItem(); this.niTray = new System.Windows.Forms.NotifyIcon(this.components); + this.btnPause = new ShareX.HelpersLib.NoFocusBorderButton(); this.pInfo.SuspendLayout(); this.cmsMain.SuspendLayout(); this.SuspendLayout(); @@ -54,6 +55,7 @@ private void InitializeComponent() // pInfo // resources.ApplyResources(this.pInfo, "pInfo"); + this.pInfo.Controls.Add(this.btnPause); this.pInfo.Controls.Add(this.btnAbort); this.pInfo.Controls.Add(this.btnStart); this.pInfo.Controls.Add(this.lblTimer); @@ -87,6 +89,12 @@ private void InitializeComponent() resources.ApplyResources(this.niTray, "niTray"); this.niTray.MouseClick += new System.Windows.Forms.MouseEventHandler(this.btnStart_MouseClick); // + // btnPause + // + resources.ApplyResources(this.btnPause, "btnPause"); + this.btnPause.Name = "btnPause"; + this.btnPause.MouseClick += new System.Windows.Forms.MouseEventHandler(this.btnPause_MouseClick); + // // ScreenRecordForm // resources.ApplyResources(this, "$this"); @@ -116,5 +124,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem tsmiStart; private System.Windows.Forms.ToolStripMenuItem tsmiAbort; private System.Windows.Forms.NotifyIcon niTray; + private HelpersLib.NoFocusBorderButton btnPause; } } \ No newline at end of file diff --git a/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.cs b/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.cs index 570ee9e54..40f3e57ec 100644 --- a/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.cs +++ b/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.cs @@ -44,6 +44,7 @@ public partial class ScreenRecordForm : Form public Stopwatch Timer { get; private set; } public ManualResetEvent RecordResetEvent { get; set; } public bool IsStopRequested { get; private set; } + public bool IsPauseRequested { get; private set; } public bool IsAbortRequested { get; private set; } public bool ActivateWindow { get; set; } = true; @@ -171,6 +172,13 @@ public void StartRecordingTimer() UpdateTimer(); } + public void StopRecordingTimer() + { + Timer.Stop(); + timerRefresh.Stop(); + UpdateTimer(); + } + private void UpdateTimer() { if (!IsDisposed) @@ -216,6 +224,14 @@ private void btnStart_MouseClick(object sender, MouseEventArgs e) } } + private void btnPause_MouseClick(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + StartStopRecording(true); + } + } + private void btnAbort_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) @@ -228,12 +244,18 @@ private void btnAbort_MouseClick(object sender, MouseEventArgs e) } } - public void StartStopRecording() + public void StartStopRecording(bool isPause = false) { if (IsWorking) { IsStopRequested = true; + if (isPause) + { + RecordResetEvent.Reset(); + IsPauseRequested = true; + } + if (!IsRecording) { IsAbortRequested = true; @@ -274,6 +296,7 @@ public void ChangeState(ScreenRecordState state) break; case ScreenRecordState.AfterStart: IsWorking = true; + IsPauseRequested = false; string trayTextAfterStart = "ShareX - " + Resources.ScreenRecordForm_StartRecording_Click_tray_icon_to_stop_recording_; niTray.Text = trayTextAfterStart.Truncate(63); niTray.Icon = Resources.control_record.ToIcon(); @@ -284,6 +307,11 @@ public void ChangeState(ScreenRecordState state) IsRecording = true; StartRecordingTimer(); break; + case ScreenRecordState.RecordingEnd: + IsWorking = false; + IsRecording = false; + StopRecordingTimer(); + break; case ScreenRecordState.Encoding: Hide(); string trayTextAfterStop = "ShareX - " + Resources.ScreenRecordForm_StartRecording_Encoding___; diff --git a/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.resx b/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.resx index db39e7c6c..c5d8d4d8f 100644 --- a/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.resx +++ b/ShareX.ScreenCaptureLib/Forms/ScreenRecordForm.resx @@ -151,19 +151,19 @@ pInfo - 1 + 2 Arial, 12pt - 190, 0 + 285, 0 0, 0, 0, 0 - 90, 36 + 92, 36 2 @@ -184,7 +184,7 @@ pInfo - 2 + 3 17, 17 @@ -196,7 +196,7 @@ Arial, 12pt - 95, 0 + 190, 0 0, 0, 0, 0 @@ -220,7 +220,7 @@ pInfo - 0 + 1 True @@ -228,11 +228,47 @@ GrowAndShrink + + Flat + + + Arial, 12pt + + + NoControl + + + 95, 0 + + + 0, 0, 0, 0 + + + 96, 36 + + + 3 + + + Pause + + + btnPause + + + ShareX.HelpersLib.NoFocusBorderButton, ShareX.HelpersLib, Version=14.1.2.0, Culture=neutral, PublicKeyToken=null + + + pInfo + + + 0 + 8, 8 - 280, 36 + 377, 36 0 diff --git a/ShareX/ScreenRecordManager.cs b/ShareX/ScreenRecordManager.cs index acf93bcb7..626c7ac67 100644 --- a/ShareX/ScreenRecordManager.cs +++ b/ShareX/ScreenRecordManager.cs @@ -24,6 +24,7 @@ You should have received a copy of the GNU General Public License #endregion License Information (GPL v3) using ShareX.HelpersLib; +using ShareX.MediaLib; using ShareX.Properties; using ShareX.ScreenCaptureLib; using System; @@ -167,6 +168,8 @@ private static void StartRecording(ScreenRecordOutput outputType, TaskSettings t IsRecording = true; string path = ""; + string concatPath = ""; + string tempPath = ""; bool abortRequested = false; float duration = taskSettings.CaptureSettings.ScreenRecordFixedDuration ? taskSettings.CaptureSettings.ScreenRecordDuration : 0; @@ -202,61 +205,88 @@ private static void StartRecording(ScreenRecordOutput outputType, TaskSettings t { abortRequested = true; } - - if (!abortRequested) + else { - recordForm.ChangeState(ScreenRecordState.BeforeStart); - - if (taskSettings.CaptureSettings.ScreenRecordAutoStart) - { - int delay = (int)(taskSettings.CaptureSettings.ScreenRecordStartDelay * 1000); - - if (delay > 0) - { - recordForm.InvokeSafe(() => recordForm.StartCountdown(delay)); - - recordForm.RecordResetEvent.WaitOne(delay); - } - } - else - { - recordForm.RecordResetEvent.WaitOne(); - } - - if (recordForm.IsAbortRequested) - { - abortRequested = true; - } + concatPath = FileHelpers.AppendTextToFileName(path, "-concat"); + FileHelpers.DeleteFile(concatPath); + tempPath = FileHelpers.AppendTextToFileName(path, "-temp"); + FileHelpers.DeleteFile(tempPath); + } + do + { if (!abortRequested) { - ScreenRecordingOptions options = new ScreenRecordingOptions() + recordForm.ChangeState(ScreenRecordState.BeforeStart); + + if (recordForm.IsPauseRequested || !taskSettings.CaptureSettings.ScreenRecordAutoStart) { - IsRecording = true, - IsLossless = taskSettings.CaptureSettings.ScreenRecordTwoPassEncoding, - FFmpeg = taskSettings.CaptureSettings.FFmpegOptions, - FPS = fps, - Duration = duration, - OutputPath = path, - CaptureArea = captureRectangle, - DrawCursor = taskSettings.CaptureSettings.ScreenRecordShowCursor - }; + recordForm.RecordResetEvent.WaitOne(); + } + else + { + int delay = (int)(taskSettings.CaptureSettings.ScreenRecordStartDelay * 1000); - Screenshot screenshot = TaskHelpers.GetScreenshot(taskSettings); - screenshot.CaptureCursor = taskSettings.CaptureSettings.ScreenRecordShowCursor; + if (delay > 0) + { + recordForm.InvokeSafe(() => recordForm.StartCountdown(delay)); - screenRecorder = new ScreenRecorder(ScreenRecordOutput.FFmpeg, options, screenshot, captureRectangle); - screenRecorder.RecordingStarted += ScreenRecorder_RecordingStarted; - screenRecorder.EncodingProgressChanged += ScreenRecorder_EncodingProgressChanged; - recordForm.ChangeState(ScreenRecordState.AfterStart); - screenRecorder.StartRecording(); + recordForm.RecordResetEvent.WaitOne(delay); + } + } if (recordForm.IsAbortRequested) { abortRequested = true; } + + if (recordForm.IsPauseRequested && File.Exists(path)) + { + FileHelpers.RenameFile(path, concatPath); + } + + if (!abortRequested) + { + ScreenRecordingOptions options = new ScreenRecordingOptions() + { + IsRecording = true, + IsLossless = taskSettings.CaptureSettings.ScreenRecordTwoPassEncoding, + FFmpeg = taskSettings.CaptureSettings.FFmpegOptions, + FPS = fps, + Duration = duration, + OutputPath = path, + CaptureArea = captureRectangle, + DrawCursor = taskSettings.CaptureSettings.ScreenRecordShowCursor + }; + + Screenshot screenshot = TaskHelpers.GetScreenshot(taskSettings); + screenshot.CaptureCursor = taskSettings.CaptureSettings.ScreenRecordShowCursor; + + screenRecorder = new ScreenRecorder(ScreenRecordOutput.FFmpeg, options, screenshot, captureRectangle); + screenRecorder.RecordingStarted += ScreenRecorder_RecordingStarted; + screenRecorder.EncodingProgressChanged += ScreenRecorder_EncodingProgressChanged; + recordForm.ChangeState(ScreenRecordState.AfterStart); + screenRecorder.StartRecording(); + recordForm.ChangeState(ScreenRecordState.RecordingEnd); + + if (recordForm.IsAbortRequested) + { + abortRequested = true; + } + } + + if (File.Exists(concatPath)) + { + using (FFmpegCLIManager ffmpeg = new FFmpegCLIManager(taskSettings.CaptureSettings.FFmpegOptions.FFmpegPath)) + { + ffmpeg.ShowError = true; + ffmpeg.ConcatenateVideos(new string[] { concatPath, path }, tempPath, true); + FileHelpers.RenameFile(tempPath, path); + } + } } } + while (recordForm.IsPauseRequested); } catch (Exception e) {