From 9a4cbe521a7be360da124af5910098310d3baede Mon Sep 17 00:00:00 2001 From: Bartek Motyl <29923773+bartekmotyl@users.noreply.github.com> Date: Thu, 19 Dec 2019 21:33:42 +0100 Subject: [PATCH 1/2] Lossless cut, custom ffmpeg arguments, next frame button --- .../FFmpegNET/FFmpegArgumentBuilder.cs | 28 +++ src/SimpleVideoCutter/MainForm.Designer.cs | 185 +++++++++++------- src/SimpleVideoCutter/MainForm.cs | 43 ++-- src/SimpleVideoCutter/MainForm.resx | 6 +- .../Properties/Resources.Designer.cs | 10 + .../Properties/Resources.resx | 49 ++--- ...e-icon-arrow-button-circle-right@32x32.png | Bin 0 -> 581 bytes .../Settings/FFmpegCutProfile.cs | 14 ++ .../SimpleVideoCutter.csproj | 3 + src/SimpleVideoCutter/TaskProcessor.cs | 82 ++++++-- src/SimpleVideoCutter/VideoCutterSettings.cs | 7 +- 11 files changed, 301 insertions(+), 126 deletions(-) create mode 100644 src/SimpleVideoCutter/FFmpegNET/FFmpegArgumentBuilder.cs create mode 100644 src/SimpleVideoCutter/Resources/streamline/streamline-icon-arrow-button-circle-right@32x32.png create mode 100644 src/SimpleVideoCutter/Settings/FFmpegCutProfile.cs diff --git a/src/SimpleVideoCutter/FFmpegNET/FFmpegArgumentBuilder.cs b/src/SimpleVideoCutter/FFmpegNET/FFmpegArgumentBuilder.cs new file mode 100644 index 0000000..7582350 --- /dev/null +++ b/src/SimpleVideoCutter/FFmpegNET/FFmpegArgumentBuilder.cs @@ -0,0 +1,28 @@ +using FFmpeg.NET; +using FFmpeg.NET.Enums; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SimpleVideoCutter.FFmpegNET +{ + internal class FFmpegArgumentBuilder + { + public static string BuildArgumentsCutOperation(string inputFileFullPath, string outputFileFullPath, + TimeSpan seek, TimeSpan duration, string customArguments) + { + var commandBuilder = new StringBuilder(); + + commandBuilder.AppendFormat(CultureInfo.InvariantCulture, " -ss {0} ", seek); + commandBuilder.AppendFormat(" -t {0} ", duration); + commandBuilder.AppendFormat(" -i \"{0}\" ", inputFileFullPath); + commandBuilder.AppendFormat(" {0}", customArguments); + + return commandBuilder.AppendFormat(" \"{0}\" ", outputFileFullPath).ToString(); + } + + } +} \ No newline at end of file diff --git a/src/SimpleVideoCutter/MainForm.Designer.cs b/src/SimpleVideoCutter/MainForm.Designer.cs index 89455a4..17e3d3e 100644 --- a/src/SimpleVideoCutter/MainForm.Designer.cs +++ b/src/SimpleVideoCutter/MainForm.Designer.cs @@ -31,6 +31,7 @@ private void InitializeComponent() this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.toolStripTasks = new System.Windows.Forms.ToolStrip(); + this.toolStripButtonTasksShow = new System.Windows.Forms.ToolStripButton(); this.videoViewHover = new LibVLCSharp.WinForms.VideoView(); this.vlcControl1 = new LibVLCSharp.WinForms.VideoView(); this.statusStrip = new System.Windows.Forms.StatusStrip(); @@ -45,14 +46,14 @@ private void InitializeComponent() this.videoCutterTimeline1 = new SimpleVideoCutter.VideoCutterTimeline(); this.panelTasks = new System.Windows.Forms.Panel(); this.listViewTasks = new System.Windows.Forms.ListView(); + this.columnStatus = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnFilename = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnDuration = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnOutputFile = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnError = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.labelTasks = new System.Windows.Forms.Label(); this.labelProgress = new System.Windows.Forms.Label(); this.toolStripSelection = new System.Windows.Forms.ToolStrip(); - this.toolStripTimeline = new System.Windows.Forms.ToolStrip(); - this.toolStripPlayback = new System.Windows.Forms.ToolStrip(); - this.toolStripFile = new System.Windows.Forms.ToolStrip(); this.toolStripButtonSelectionSetStart = new System.Windows.Forms.ToolStripButton(); this.toolStripButtonSelectionSetEnd = new System.Windows.Forms.ToolStripButton(); this.toolStripButtonSelectionPlay = new System.Windows.Forms.ToolStripButton(); @@ -60,12 +61,15 @@ private void InitializeComponent() this.toolStripButtonSelectionGoToStart = new System.Windows.Forms.ToolStripButton(); this.toolStripButtonSelectionGoToEnd = new System.Windows.Forms.ToolStripButton(); this.toolStripButtonSelectionEnqueue = new System.Windows.Forms.ToolStripButton(); + this.toolStripTimeline = new System.Windows.Forms.ToolStrip(); this.toolStripButtonTimelineZoomOut = new System.Windows.Forms.ToolStripButton(); this.toolStripButtonTimelineZoomAuto = new System.Windows.Forms.ToolStripButton(); this.toolStripButtonTimelineGoToCurrentPosition = new System.Windows.Forms.ToolStripButton(); - this.toolStripButtonTasksShow = new System.Windows.Forms.ToolStripButton(); + this.toolStripPlayback = new System.Windows.Forms.ToolStrip(); this.toolStripButtonPlabackPlayPause = new System.Windows.Forms.ToolStripButton(); this.toolStripButtonPlabackMute = new System.Windows.Forms.ToolStripButton(); + this.toolStripButtonPlabackNextFrame = new System.Windows.Forms.ToolStripButton(); + this.toolStripFile = new System.Windows.Forms.ToolStrip(); this.toolStripButtonFileOpen = new System.Windows.Forms.ToolStripButton(); this.toolStripButtonFilePrev = new System.Windows.Forms.ToolStripButton(); this.toolStripButtonFileNext = new System.Windows.Forms.ToolStripButton(); @@ -96,12 +100,24 @@ private void InitializeComponent() this.toolStripTasks.ImageScalingSize = new System.Drawing.Size(32, 32); this.toolStripTasks.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripButtonTasksShow}); - this.toolStripTasks.Location = new System.Drawing.Point(427, 0); + this.toolStripTasks.Location = new System.Drawing.Point(301, 0); this.toolStripTasks.Name = "toolStripTasks"; - this.toolStripTasks.Size = new System.Drawing.Size(112, 54); + this.toolStripTasks.Size = new System.Drawing.Size(81, 54); this.toolStripTasks.TabIndex = 5; this.toolStripTasks.Text = "Tasks"; // + // toolStripButtonTasksShow + // + this.toolStripButtonTasksShow.CheckOnClick = true; + this.toolStripButtonTasksShow.Image = global::SimpleVideoCutter.Properties.Resources.streamline_icon_task_list_clock_32x32; + this.toolStripButtonTasksShow.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripButtonTasksShow.Name = "toolStripButtonTasksShow"; + this.toolStripButtonTasksShow.Size = new System.Drawing.Size(69, 51); + this.toolStripButtonTasksShow.Text = "Show tasks"; + this.toolStripButtonTasksShow.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; + this.toolStripButtonTasksShow.ToolTipText = "Show tasks (T)"; + this.toolStripButtonTasksShow.CheckedChanged += new System.EventHandler(this.toolStripButtonShowTasks_CheckedChanged); + // // videoViewHover // this.videoViewHover.BackColor = System.Drawing.Color.Black; @@ -119,7 +135,7 @@ private void InitializeComponent() this.vlcControl1.Location = new System.Drawing.Point(0, 0); this.vlcControl1.MediaPlayer = null; this.vlcControl1.Name = "vlcControl1"; - this.vlcControl1.Size = new System.Drawing.Size(886, 521); + this.vlcControl1.Size = new System.Drawing.Size(986, 621); this.vlcControl1.TabIndex = 5; this.vlcControl1.Text = "videoView1"; this.vlcControl1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.vlcControl1_MouseClick); @@ -132,9 +148,9 @@ private void InitializeComponent() this.toolStripStatusLabelFileDate, this.toolStripStatusLabelIndex, this.toolStripStatusLabelSelection}); - this.statusStrip.Location = new System.Drawing.Point(0, 639); + this.statusStrip.Location = new System.Drawing.Point(0, 739); this.statusStrip.Name = "statusStrip"; - this.statusStrip.Size = new System.Drawing.Size(984, 22); + this.statusStrip.Size = new System.Drawing.Size(1084, 22); this.statusStrip.TabIndex = 7; this.statusStrip.Text = "statusStrip1"; // @@ -181,7 +197,7 @@ private void InitializeComponent() // toolStripContainer1.ContentPanel // this.toolStripContainer1.ContentPanel.Controls.Add(this.splitContainer1); - this.toolStripContainer1.ContentPanel.Size = new System.Drawing.Size(886, 585); + this.toolStripContainer1.ContentPanel.Size = new System.Drawing.Size(986, 685); this.toolStripContainer1.Dock = System.Windows.Forms.DockStyle.Fill; // // toolStripContainer1.LeftToolStripPanel @@ -191,15 +207,15 @@ private void InitializeComponent() this.toolStripContainer1.Location = new System.Drawing.Point(0, 0); this.toolStripContainer1.Name = "toolStripContainer1"; this.toolStripContainer1.RightToolStripPanelVisible = false; - this.toolStripContainer1.Size = new System.Drawing.Size(984, 639); + this.toolStripContainer1.Size = new System.Drawing.Size(1084, 739); this.toolStripContainer1.TabIndex = 7; this.toolStripContainer1.Text = "toolStripContainer1"; // // toolStripContainer1.TopToolStripPanel // + this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStripFile); this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStripTasks); this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStripPlayback); - this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStripFile); // // splitContainer1 // @@ -218,8 +234,8 @@ private void InitializeComponent() // this.splitContainer1.Panel2.Controls.Add(this.panelTasks); this.splitContainer1.Panel2Collapsed = true; - this.splitContainer1.Size = new System.Drawing.Size(886, 585); - this.splitContainer1.SplitterDistance = 597; + this.splitContainer1.Size = new System.Drawing.Size(986, 685); + this.splitContainer1.SplitterDistance = 693; this.splitContainer1.TabIndex = 7; // // videoCutterTimeline1 @@ -228,10 +244,10 @@ private void InitializeComponent() this.videoCutterTimeline1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); this.videoCutterTimeline1.HoverPosition = null; this.videoCutterTimeline1.Length = ((long)(0)); - this.videoCutterTimeline1.Location = new System.Drawing.Point(0, 521); + this.videoCutterTimeline1.Location = new System.Drawing.Point(0, 621); this.videoCutterTimeline1.Name = "videoCutterTimeline1"; this.videoCutterTimeline1.Position = ((long)(0)); - this.videoCutterTimeline1.Size = new System.Drawing.Size(886, 64); + this.videoCutterTimeline1.Size = new System.Drawing.Size(986, 64); this.videoCutterTimeline1.TabIndex = 4; // // panelTasks @@ -248,10 +264,15 @@ private void InitializeComponent() // listViewTasks // this.listViewTasks.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnStatus, this.columnFilename, - this.columnDuration}); + this.columnDuration, + this.columnOutputFile, + this.columnError}); this.listViewTasks.Dock = System.Windows.Forms.DockStyle.Fill; this.listViewTasks.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.listViewTasks.FullRowSelect = true; + this.listViewTasks.GridLines = true; this.listViewTasks.HideSelection = false; this.listViewTasks.Location = new System.Drawing.Point(0, 13); this.listViewTasks.Name = "listViewTasks"; @@ -260,9 +281,13 @@ private void InitializeComponent() this.listViewTasks.UseCompatibleStateImageBehavior = false; this.listViewTasks.View = System.Windows.Forms.View.Details; // + // columnStatus + // + this.columnStatus.Text = "Status"; + // // columnFilename // - this.columnFilename.Text = "Filename"; + this.columnFilename.Text = "Source file"; this.columnFilename.Width = 200; // // columnDuration @@ -270,6 +295,15 @@ private void InitializeComponent() this.columnDuration.Text = "Duration"; this.columnDuration.Width = 100; // + // columnOutputFile + // + this.columnOutputFile.Text = "Target file"; + // + // columnError + // + this.columnError.Text = "Message"; + this.columnError.Width = 200; + // // labelTasks // this.labelTasks.AutoSize = true; @@ -309,51 +343,6 @@ private void InitializeComponent() this.toolStripSelection.Text = "Selection"; this.toolStripSelection.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.toolStripSelection_ItemClicked); // - // toolStripTimeline - // - this.toolStripTimeline.Dock = System.Windows.Forms.DockStyle.None; - this.toolStripTimeline.ImageScalingSize = new System.Drawing.Size(32, 32); - this.toolStripTimeline.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripButtonTimelineZoomOut, - this.toolStripButtonTimelineZoomAuto, - this.toolStripButtonTimelineGoToCurrentPosition}); - this.toolStripTimeline.Location = new System.Drawing.Point(0, 392); - this.toolStripTimeline.Name = "toolStripTimeline"; - this.toolStripTimeline.Size = new System.Drawing.Size(98, 173); - this.toolStripTimeline.TabIndex = 21; - this.toolStripTimeline.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.toolStripTimeline_ItemClicked); - // - // toolStripPlayback - // - this.toolStripPlayback.Dock = System.Windows.Forms.DockStyle.None; - this.toolStripPlayback.ImageScalingSize = new System.Drawing.Size(32, 32); - this.toolStripPlayback.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripButtonPlabackPlayPause, - this.toolStripButtonPlabackMute}); - this.toolStripPlayback.Location = new System.Drawing.Point(301, 0); - this.toolStripPlayback.Name = "toolStripPlayback"; - this.toolStripPlayback.Size = new System.Drawing.Size(126, 54); - this.toolStripPlayback.TabIndex = 7; - this.toolStripPlayback.Text = "toolStrip2"; - this.toolStripPlayback.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.toolStripPlayback_ItemClicked); - // - // toolStripFile - // - this.toolStripFile.Dock = System.Windows.Forms.DockStyle.None; - this.toolStripFile.ImageScalingSize = new System.Drawing.Size(32, 32); - this.toolStripFile.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripButtonFileOpen, - this.toolStripButtonFilePrev, - this.toolStripButtonFileNext, - this.toolStripButtonFileSettings, - this.toolStripButtonFileAbout}); - this.toolStripFile.Location = new System.Drawing.Point(3, 0); - this.toolStripFile.Name = "toolStripFile"; - this.toolStripFile.Size = new System.Drawing.Size(298, 54); - this.toolStripFile.TabIndex = 20; - this.toolStripFile.Text = "File"; - this.toolStripFile.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.toolStripFile_ItemClicked); - // // toolStripButtonSelectionSetStart // this.toolStripButtonSelectionSetStart.Image = global::SimpleVideoCutter.Properties.Resources.streamline_icon_set_start_32x32; @@ -424,6 +413,20 @@ private void InitializeComponent() this.toolStripButtonSelectionEnqueue.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; this.toolStripButtonSelectionEnqueue.ToolTipText = "Enqueue selection to be processed by FFmpeg (E)"; // + // toolStripTimeline + // + this.toolStripTimeline.Dock = System.Windows.Forms.DockStyle.None; + this.toolStripTimeline.ImageScalingSize = new System.Drawing.Size(32, 32); + this.toolStripTimeline.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripButtonTimelineZoomOut, + this.toolStripButtonTimelineZoomAuto, + this.toolStripButtonTimelineGoToCurrentPosition}); + this.toolStripTimeline.Location = new System.Drawing.Point(0, 392); + this.toolStripTimeline.Name = "toolStripTimeline"; + this.toolStripTimeline.Size = new System.Drawing.Size(98, 173); + this.toolStripTimeline.TabIndex = 21; + this.toolStripTimeline.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.toolStripTimeline_ItemClicked); + // // toolStripButtonTimelineZoomOut // this.toolStripButtonTimelineZoomOut.Image = global::SimpleVideoCutter.Properties.Resources.streamline_icon_expand_5_32x32; @@ -454,17 +457,20 @@ private void InitializeComponent() this.toolStripButtonTimelineGoToCurrentPosition.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; this.toolStripButtonTimelineGoToCurrentPosition.ToolTipText = "Scroll timeline to current position (Ctrl+P)"; // - // toolStripButtonTasksShow + // toolStripPlayback // - this.toolStripButtonTasksShow.CheckOnClick = true; - this.toolStripButtonTasksShow.Image = global::SimpleVideoCutter.Properties.Resources.streamline_icon_task_list_clock_32x32; - this.toolStripButtonTasksShow.ImageTransparentColor = System.Drawing.Color.Magenta; - this.toolStripButtonTasksShow.Name = "toolStripButtonTasksShow"; - this.toolStripButtonTasksShow.Size = new System.Drawing.Size(69, 51); - this.toolStripButtonTasksShow.Text = "Show tasks"; - this.toolStripButtonTasksShow.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; - this.toolStripButtonTasksShow.ToolTipText = "Show tasks (T)"; - this.toolStripButtonTasksShow.CheckedChanged += new System.EventHandler(this.toolStripButtonShowTasks_CheckedChanged); + this.toolStripPlayback.Dock = System.Windows.Forms.DockStyle.None; + this.toolStripPlayback.ImageScalingSize = new System.Drawing.Size(32, 32); + this.toolStripPlayback.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripButtonPlabackPlayPause, + this.toolStripButtonPlabackMute, + this.toolStripButtonPlabackNextFrame}); + this.toolStripPlayback.Location = new System.Drawing.Point(382, 0); + this.toolStripPlayback.Name = "toolStripPlayback"; + this.toolStripPlayback.Size = new System.Drawing.Size(196, 54); + this.toolStripPlayback.TabIndex = 7; + this.toolStripPlayback.Text = "toolStrip2"; + this.toolStripPlayback.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.toolStripPlayback_ItemClicked); // // toolStripButtonPlabackPlayPause // @@ -486,6 +492,33 @@ private void InitializeComponent() this.toolStripButtonPlabackMute.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; this.toolStripButtonPlabackMute.ToolTipText = "Mute (Ctrl+M)"; // + // toolStripButtonPlabackNextFrame + // + this.toolStripButtonPlabackNextFrame.Image = global::SimpleVideoCutter.Properties.Resources.streamline_icon_arrow_button_circle_right_32x32; + this.toolStripButtonPlabackNextFrame.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripButtonPlabackNextFrame.Name = "toolStripButtonPlabackNextFrame"; + this.toolStripButtonPlabackNextFrame.Size = new System.Drawing.Size(70, 51); + this.toolStripButtonPlabackNextFrame.Text = "Next frame"; + this.toolStripButtonPlabackNextFrame.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; + this.toolStripButtonPlabackNextFrame.ToolTipText = "Next frame (.)"; + // + // toolStripFile + // + this.toolStripFile.Dock = System.Windows.Forms.DockStyle.None; + this.toolStripFile.ImageScalingSize = new System.Drawing.Size(32, 32); + this.toolStripFile.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripButtonFileOpen, + this.toolStripButtonFilePrev, + this.toolStripButtonFileNext, + this.toolStripButtonFileSettings, + this.toolStripButtonFileAbout}); + this.toolStripFile.Location = new System.Drawing.Point(3, 0); + this.toolStripFile.Name = "toolStripFile"; + this.toolStripFile.Size = new System.Drawing.Size(298, 54); + this.toolStripFile.TabIndex = 20; + this.toolStripFile.Text = "File"; + this.toolStripFile.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.toolStripFile_ItemClicked); + // // toolStripButtonFileOpen // this.toolStripButtonFileOpen.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButtonFileOpen.Image"))); @@ -538,7 +571,7 @@ private void InitializeComponent() // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(984, 661); + this.ClientSize = new System.Drawing.Size(1084, 761); this.Controls.Add(this.toolStripContainer1); this.Controls.Add(this.statusStrip); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); @@ -624,6 +657,10 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripButton toolStripButtonTimelineZoomOut; private System.Windows.Forms.ToolStripButton toolStripButtonTimelineZoomAuto; private System.Windows.Forms.ToolStripButton toolStripButtonTimelineGoToCurrentPosition; + private System.Windows.Forms.ColumnHeader columnStatus; + private System.Windows.Forms.ColumnHeader columnError; + private System.Windows.Forms.ColumnHeader columnOutputFile; + private System.Windows.Forms.ToolStripButton toolStripButtonPlabackNextFrame; } } diff --git a/src/SimpleVideoCutter/MainForm.cs b/src/SimpleVideoCutter/MainForm.cs index f1c58f8..dd53383 100644 --- a/src/SimpleVideoCutter/MainForm.cs +++ b/src/SimpleVideoCutter/MainForm.cs @@ -383,23 +383,35 @@ private void VideoCutterTimeline1_SelectionChanged(object sender, SelectionChang } + private void RefreshTasks() + { + listViewTasks.InvokeIfRequired(() => + { + var tasks = taskProcessor.GetTasks().Reverse(); + listViewTasks.Items.Clear(); + listViewTasks.Items.AddRange(tasks.Select( + task => + { + var item = new ListViewItem(task.StateLabel); + item.SubItems.Add(string.Format("{0}", task.InputFileName)); + item.SubItems.Add(string.Format("{0} sec", Math.Round(task.Duration / 1000.0f, 1))); + item.SubItems.Add(string.Format("{0}", task.OutputFilePath)); + item.SubItems.Add(string.Format("{0}", task.ErrorMessage)); + if (task.State == FFmpegTaskState.FinishedError) + item.BackColor = Color.Tomato; + return item; + }).ToArray()); + + listViewTasks.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); + columnStatus.Width = 80; + }); + } private void TaskProcessor_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Tasks") { - listViewTasks.InvokeIfRequired(() => - { - var tasks = taskProcessor.GetTasks(); - listViewTasks.Items.Clear(); - listViewTasks.Items.AddRange(tasks.Select( - task => - { - var item = new ListViewItem(task.InputFileName); - item.SubItems.Add(string.Format("{0} sec", Math.Round(task.Duration / 1000.0f, 1))); - return item; - }).ToArray()); - }); + RefreshTasks(); } } @@ -447,6 +459,7 @@ private void EnqeueNewTask() SelectionStart = selectionStart, Duration = selectionEnd - selectionStart, TaskId = Guid.NewGuid().ToString(), + Profile = VideoCutterSettings.Instance.FFmpegCutProfiles[0], }); ClearSelection(); toolStripButtonTasksShow.Checked = true; @@ -551,6 +564,7 @@ private void EnableButtons() toolStripPlayback.InvokeIfRequired(() => { toolStripButtonPlabackPlayPause.Enabled = isFileLoaded; + toolStripButtonPlabackNextFrame.Enabled = isFileLoaded; toolStripButtonPlabackPlayPause.Image = isPlaying ? Resources.streamline_icon_controls_pause_32x32 : Resources.streamline_icon_controls_play_32x32; toolStripButtonPlabackMute.Checked = VideoCutterSettings.Instance.Mute; }); @@ -593,6 +607,7 @@ private void toolStripButtonShowTasks_CheckedChanged(object sender, EventArgs e) private void ShowHideTasks() { + RefreshTasks(); splitContainer1.Panel2Collapsed = !toolStripButtonTasksShow.Checked; } @@ -688,6 +703,10 @@ private void toolStripPlayback_ItemClicked(object sender, ToolStripItemClickedEv { Mute(); } + else if (e.ClickedItem == toolStripButtonPlabackNextFrame) + { + NextFrame(); + } } private void toolStripSelection_ItemClicked(object sender, ToolStripItemClickedEventArgs e) diff --git a/src/SimpleVideoCutter/MainForm.resx b/src/SimpleVideoCutter/MainForm.resx index 4fafcf7..ffa1f21 100644 --- a/src/SimpleVideoCutter/MainForm.resx +++ b/src/SimpleVideoCutter/MainForm.resx @@ -132,9 +132,6 @@ 1027, 17 - - 881, 17 - 764, 17 @@ -167,6 +164,9 @@ RU5ErkJggg== + + 881, 17 + AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA diff --git a/src/SimpleVideoCutter/Properties/Resources.Designer.cs b/src/SimpleVideoCutter/Properties/Resources.Designer.cs index 91b54ac..97a82ee 100644 --- a/src/SimpleVideoCutter/Properties/Resources.Designer.cs +++ b/src/SimpleVideoCutter/Properties/Resources.Designer.cs @@ -230,6 +230,16 @@ internal static System.Drawing.Bitmap iconfinder_video_293710 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap streamline_icon_arrow_button_circle_right_32x32 { + get { + object obj = ResourceManager.GetObject("streamline-icon-arrow-button-circle-right@32x32", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/src/SimpleVideoCutter/Properties/Resources.resx b/src/SimpleVideoCutter/Properties/Resources.resx index 309d9f8..254a323 100644 --- a/src/SimpleVideoCutter/Properties/Resources.resx +++ b/src/SimpleVideoCutter/Properties/Resources.resx @@ -118,9 +118,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\Resources\iconfinder_chevron-right_293665.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\streamline\streamline-icon-controls-pause@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -145,15 +142,18 @@ ..\Resources\streamline\streamline-icon-task-list-add@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\streamline\streamline-icon-navigation-right-3@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\streamline\streamline-icon-set-start@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\iconfinder_next_293690.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\iconfinder_nav-left_293639.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\streamline\streamline-icon-video-player-slider@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\streamline\streamline-icon-navigation-right-3@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\iconfinder_check_293662.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -172,21 +172,15 @@ ..\Resources\iconfinder_video_293710.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\streamline\streamline-icon-arrow-rectangle-left-2@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\streamline\streamline-icon-set-end@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\iconfinder_previous-2_293643.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\iconfinder_chevron-right_293665.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\streamline\streamline-icon-go-to-start@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\iconfinder_nav-left_293639.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\streamline\streamline-icon-modern-tv-flat-screen@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -196,6 +190,9 @@ ..\Resources\streamline\streamline-icon-diagram-arrow-dash-left@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\streamline\streamline-icon-arrow-rectangle-right@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\streamline\streamline-icon-diagram-arrow-dash-right@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -205,27 +202,33 @@ ..\Resources\streamline\streamline-icon-arrow-button-right-3@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\iconfinder_list_293685.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\iconfinder_folder_293677.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\streamline\streamline-icon-information-circle@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\iconfinder_list_293685.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\streamline\streamline-icon-arrow-rectangle-left-2@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\streamline\streamline-icon-arrow-rectangle-right@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\iconfinder_previous-2_293643.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\iconfinder_clock_293667.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\streamline\streamline-icon-set-start@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\iconfinder_next_293690.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\iconfinder_nav-right_293640.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\streamline\streamline-icon-go-to-end@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\iconfinder_pause_293692.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -244,7 +247,7 @@ ..\Resources\iconfinder_cog_293670.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\streamline\streamline-icon-go-to-end@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\streamline\streamline-icon-arrow-button-circle-right@32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a \ No newline at end of file diff --git a/src/SimpleVideoCutter/Resources/streamline/streamline-icon-arrow-button-circle-right@32x32.png b/src/SimpleVideoCutter/Resources/streamline/streamline-icon-arrow-button-circle-right@32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..a4fcc9a68537431fc271dbe7175a7ac26e470bc1 GIT binary patch literal 581 zcmV-L0=oT)P)Px$|4BqaR9JM-0xaxu)O$nn4?%mZQfB4x(H^c zoQPuTuy-%mI23UrnvQRL*kfJ_0c*tI)A1Spxxf=9mM2ZBHldf2Mqvy{E#QZQu^9FY z?|Lau9`-UZuObc@e7b~Ky8;Jvv<=wOnnOG>(m8@F$YA}Jn|!!(j_YDay7J;phZcjP|7kDiR?@BM#!v9G)$3{TBs*xp@Oi~q3z`Jwk7O|1NZZNG7 zwQBuFWg)65#rmn%^Q5~aT#UgfmoE}@r_Xgda9!LGzlwPxCbJac26nT*BU$VCi(!j9KA0mkfK#3Ef&H zA{*?Gs!!9nwGG3GN(eV8mEo9``(=%Dqpebj!CpZb&kgYA{`AboutBox.cs + Form @@ -102,6 +103,7 @@ + @@ -200,6 +202,7 @@ + diff --git a/src/SimpleVideoCutter/TaskProcessor.cs b/src/SimpleVideoCutter/TaskProcessor.cs index bb0fd0c..5be4657 100644 --- a/src/SimpleVideoCutter/TaskProcessor.cs +++ b/src/SimpleVideoCutter/TaskProcessor.cs @@ -1,4 +1,6 @@ using FFmpeg.NET; +using SimpleVideoCutter.FFmpegNET; +using SimpleVideoCutter.Settings; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -12,7 +14,7 @@ namespace SimpleVideoCutter { public class TaskProcessor : INotifyPropertyChanged { - private ConcurrentQueue tasks = new ConcurrentQueue(); + private IList tasks = new List(); private FFmpegTask currentTask = null; private Thread workerThread = null; @@ -30,18 +32,20 @@ public void Start() public void EnqueueTask(FFmpegTask task) { - tasks.Enqueue(task); + lock (tasks) + { + tasks.Add(task); + } OnPropertyChanged("Tasks"); } public IList GetTasks() { - var result = tasks.ToList(); - - if (currentTask != null) - result.Insert(0, currentTask); - - return result; + lock (tasks) + { + var result = tasks.ToList(); + return result; + } } private void OnPropertyChanged(string propertyName) @@ -57,17 +61,33 @@ private void WorkerThread() { while (!StopRequest) { - if (currentTask == null && tasks.TryDequeue(out currentTask)) + if (currentTask == null) { + FFmpegTask taskToSchedule = null; + lock (tasks) + { + taskToSchedule = tasks.FirstOrDefault(t => t.State == FFmpegTaskState.Scheduled); + if (taskToSchedule == null) + { + Thread.Sleep(100); + continue; + } + } + + currentTask = taskToSchedule; + var ffmpeg = new Engine(VideoCutterSettings.Instance.FFmpegPath); ffmpeg.Complete += (object sender, FFmpeg.NET.Events.ConversionCompleteEventArgs e) => { + currentTask.State = FFmpegTaskState.FinishedOK; currentTask = null; OnPropertyChanged("Tasks"); OnTaskProgress("Done"); }; ffmpeg.Error += (object sender, FFmpeg.NET.Events.ConversionErrorEventArgs e) => { + currentTask.State = FFmpegTaskState.FinishedError; + currentTask.ErrorMessage = e.Exception.Message; currentTask = null; OnPropertyChanged("Tasks"); OnTaskProgress("Failure: "+e.Exception.Message); @@ -81,13 +101,23 @@ private void WorkerThread() try { - var options = new ConversionOptions(); - options.CutMedia(TimeSpan.FromMilliseconds(currentTask.SelectionStart), TimeSpan.FromMilliseconds(currentTask.Duration)); - Task taskConversion = ffmpeg.ConvertAsync(new MediaFile(currentTask.InputFilePath), new MediaFile(currentTask.OutputFilePath), options); + var ffmpegCutArguments = FFmpegArgumentBuilder.BuildArgumentsCutOperation( + currentTask.InputFilePath, + currentTask.OutputFilePath, + TimeSpan.FromMilliseconds(currentTask.SelectionStart), + TimeSpan.FromMilliseconds(currentTask.Duration), + currentTask.Profile.Arguments); + + currentTask.State = FFmpegTaskState.InProgress; + OnPropertyChanged("Tasks"); + + Task taskConversion = ffmpeg.ExecuteAsync(ffmpegCutArguments); taskConversion.Wait(); } catch (Exception e) { + currentTask.State = FFmpegTaskState.FinishedError; + currentTask.ErrorMessage = e.Message; currentTask = null; OnPropertyChanged("Tasks"); OnTaskProgress("Failure: " + e.Message); @@ -95,7 +125,7 @@ private void WorkerThread() } else { - Thread.Sleep(1000); + Thread.Sleep(100); } } } @@ -109,6 +139,32 @@ public class FFmpegTask public string InputFileName { get; set; } public long SelectionStart { get; set; } public long Duration { get; set; } + public FFmpegCutProfile Profile { get; set; } + public FFmpegTaskState State { get; set; } + public string ErrorMessage { get; set; } + + + public string StateLabel + { + get + { + switch (State) + { + case FFmpegTaskState.Scheduled: return "Scheduled"; + case FFmpegTaskState.InProgress: return "In progress"; + case FFmpegTaskState.FinishedOK: return "Done"; + case FFmpegTaskState.FinishedError: return "Error"; + default: return "Unrecognized"; + } + } + } + } + public enum FFmpegTaskState + { + Scheduled, + InProgress, + FinishedOK, + FinishedError, } public class TaskProgressEventArgs : EventArgs diff --git a/src/SimpleVideoCutter/VideoCutterSettings.cs b/src/SimpleVideoCutter/VideoCutterSettings.cs index 24d6d49..f38e713 100644 --- a/src/SimpleVideoCutter/VideoCutterSettings.cs +++ b/src/SimpleVideoCutter/VideoCutterSettings.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using SimpleVideoCutter.Settings; using System; using System.Collections.Generic; using System.IO; @@ -22,8 +23,12 @@ public class VideoCutterSettings public bool Mute { get; set; } = false; public bool Autostart { get; set; } = true; - public static VideoCutterSettings Instance { get; } = new VideoCutterSettings(); + public FFmpegCutProfile[] FFmpegCutProfiles = new FFmpegCutProfile[] + { + new FFmpegCutProfile() { Name = "lossless", Arguments = "-codec copy"}, + }; + public static VideoCutterSettings Instance { get; } = new VideoCutterSettings(); protected VideoCutterSettings() { From b6752b04afa7170bb834419e1acd5dcf968725ef Mon Sep 17 00:00:00 2001 From: Bartek Motyl <29923773+bartekmotyl@users.noreply.github.com> Date: Thu, 19 Dec 2019 22:00:34 +0100 Subject: [PATCH 2/2] Link in about box, {SameFolder}, drag&drop, --- src/SimpleVideoCutter/AboutBox.Designer.cs | 14 ++++++++ src/SimpleVideoCutter/AboutBox.cs | 5 +++ .../FormSettings.Designer.cs | 3 +- src/SimpleVideoCutter/FormSettings.resx | 3 -- src/SimpleVideoCutter/MainForm.Designer.cs | 13 ++++--- src/SimpleVideoCutter/MainForm.cs | 34 +++++++++++++++++++ src/SimpleVideoCutter/MainForm.resx | 6 ++-- .../Properties/AssemblyInfo.cs | 4 +-- 8 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/SimpleVideoCutter/AboutBox.Designer.cs b/src/SimpleVideoCutter/AboutBox.Designer.cs index 261b0ef..76534e1 100644 --- a/src/SimpleVideoCutter/AboutBox.Designer.cs +++ b/src/SimpleVideoCutter/AboutBox.Designer.cs @@ -35,6 +35,7 @@ private void InitializeComponent() this.labelCopyright = new System.Windows.Forms.Label(); this.okButton = new System.Windows.Forms.Button(); this.textBox1 = new System.Windows.Forms.TextBox(); + this.linkLabelGithub = new System.Windows.Forms.LinkLabel(); this.tableLayoutPanel.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit(); this.SuspendLayout(); @@ -50,6 +51,7 @@ private void InitializeComponent() this.tableLayoutPanel.Controls.Add(this.labelCopyright, 1, 2); this.tableLayoutPanel.Controls.Add(this.okButton, 1, 5); this.tableLayoutPanel.Controls.Add(this.textBox1, 1, 4); + this.tableLayoutPanel.Controls.Add(this.linkLabelGithub, 1, 3); this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel.Location = new System.Drawing.Point(9, 9); this.tableLayoutPanel.Name = "tableLayoutPanel"; @@ -134,6 +136,17 @@ private void InitializeComponent() this.textBox1.TabIndex = 25; this.textBox1.Text = "Icons: streamlineicons.com\r\nFFmpeg: www.ffmpeg.org"; // + // linkLabelGithub + // + this.linkLabelGithub.AutoSize = true; + this.linkLabelGithub.Location = new System.Drawing.Point(140, 93); + this.linkLabelGithub.Name = "linkLabelGithub"; + this.linkLabelGithub.Size = new System.Drawing.Size(247, 13); + this.linkLabelGithub.TabIndex = 26; + this.linkLabelGithub.TabStop = true; + this.linkLabelGithub.Text = "https://github.com/bartekmotyl/simple-video-cutter"; + this.linkLabelGithub.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelGithub_LinkClicked); + // // AboutBox // this.AcceptButton = this.okButton; @@ -166,5 +179,6 @@ private void InitializeComponent() private System.Windows.Forms.Button okButton; private System.Windows.Forms.Label labelVersion; private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.LinkLabel linkLabelGithub; } } diff --git a/src/SimpleVideoCutter/AboutBox.cs b/src/SimpleVideoCutter/AboutBox.cs index e92a53a..ad7e484 100644 --- a/src/SimpleVideoCutter/AboutBox.cs +++ b/src/SimpleVideoCutter/AboutBox.cs @@ -100,5 +100,10 @@ public string AssemblyCompany } } #endregion + + private void linkLabelGithub_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start(linkLabelGithub.Text); + } } } diff --git a/src/SimpleVideoCutter/FormSettings.Designer.cs b/src/SimpleVideoCutter/FormSettings.Designer.cs index ce79b4d..d077191 100644 --- a/src/SimpleVideoCutter/FormSettings.Designer.cs +++ b/src/SimpleVideoCutter/FormSettings.Designer.cs @@ -168,7 +168,8 @@ private void InitializeComponent() this.comboBoxOutputDirectory.Items.AddRange(new object[] { "{UserVideos}", "{UserDocuments}", - "{MyComputer}"}); + "{MyComputer}", + "{SameFolder}"}); this.comboBoxOutputDirectory.Location = new System.Drawing.Point(134, 37); this.comboBoxOutputDirectory.Name = "comboBoxOutputDirectory"; this.comboBoxOutputDirectory.Size = new System.Drawing.Size(344, 21); diff --git a/src/SimpleVideoCutter/FormSettings.resx b/src/SimpleVideoCutter/FormSettings.resx index 4557213..dce500f 100644 --- a/src/SimpleVideoCutter/FormSettings.resx +++ b/src/SimpleVideoCutter/FormSettings.resx @@ -123,9 +123,6 @@ 17, 17 - - 186, 17 - Pattern that defines how filenames of created files will be computed. Static parts are allowed as well as these pseudo-variable diff --git a/src/SimpleVideoCutter/MainForm.Designer.cs b/src/SimpleVideoCutter/MainForm.Designer.cs index 17e3d3e..2bc3ff6 100644 --- a/src/SimpleVideoCutter/MainForm.Designer.cs +++ b/src/SimpleVideoCutter/MainForm.Designer.cs @@ -100,7 +100,7 @@ private void InitializeComponent() this.toolStripTasks.ImageScalingSize = new System.Drawing.Size(32, 32); this.toolStripTasks.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripButtonTasksShow}); - this.toolStripTasks.Location = new System.Drawing.Point(301, 0); + this.toolStripTasks.Location = new System.Drawing.Point(306, 0); this.toolStripTasks.Name = "toolStripTasks"; this.toolStripTasks.Size = new System.Drawing.Size(81, 54); this.toolStripTasks.TabIndex = 5; @@ -213,9 +213,9 @@ private void InitializeComponent() // // toolStripContainer1.TopToolStripPanel // - this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStripFile); - this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStripTasks); this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStripPlayback); + this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStripTasks); + this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStripFile); // // splitContainer1 // @@ -465,7 +465,7 @@ private void InitializeComponent() this.toolStripButtonPlabackPlayPause, this.toolStripButtonPlabackMute, this.toolStripButtonPlabackNextFrame}); - this.toolStripPlayback.Location = new System.Drawing.Point(382, 0); + this.toolStripPlayback.Location = new System.Drawing.Point(388, 0); this.toolStripPlayback.Name = "toolStripPlayback"; this.toolStripPlayback.Size = new System.Drawing.Size(196, 54); this.toolStripPlayback.TabIndex = 7; @@ -512,7 +512,7 @@ private void InitializeComponent() this.toolStripButtonFileNext, this.toolStripButtonFileSettings, this.toolStripButtonFileAbout}); - this.toolStripFile.Location = new System.Drawing.Point(3, 0); + this.toolStripFile.Location = new System.Drawing.Point(8, 0); this.toolStripFile.Name = "toolStripFile"; this.toolStripFile.Size = new System.Drawing.Size(298, 54); this.toolStripFile.TabIndex = 20; @@ -569,6 +569,7 @@ private void InitializeComponent() // // MainForm // + this.AllowDrop = true; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1084, 761); @@ -582,6 +583,8 @@ private void InitializeComponent() this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); this.Load += new System.EventHandler(this.MainForm_Load); this.Shown += new System.EventHandler(this.MainForm_Shown); + this.DragDrop += new System.Windows.Forms.DragEventHandler(this.MainForm_DragDrop); + this.DragOver += new System.Windows.Forms.DragEventHandler(this.MainForm_DragOver); this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown); this.toolStripTasks.ResumeLayout(false); this.toolStripTasks.PerformLayout(); diff --git a/src/SimpleVideoCutter/MainForm.cs b/src/SimpleVideoCutter/MainForm.cs index dd53383..e809609 100644 --- a/src/SimpleVideoCutter/MainForm.cs +++ b/src/SimpleVideoCutter/MainForm.cs @@ -202,6 +202,7 @@ private void OpenFile() private string ReplaceStandardDirectoryPatterns(string str) { return str + .Replace("{SameFolder}", fileBeingPlayed) .Replace("{UserVideos}", Environment.GetFolderPath(Environment.SpecialFolder.MyVideos)) .Replace("{UserDocuments}", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)) .Replace("{MyComputer}", Environment.GetFolderPath(Environment.SpecialFolder.MyComputer)); @@ -806,5 +807,38 @@ private void toolStripTimeline_ItemClicked(object sender, ToolStripItemClickedEv videoCutterTimeline1.GoToCurrentPosition(); } } + + private string GetPathOfSingleDraggedFile(IDataObject data) + { + if (!data.GetDataPresent(DataFormats.FileDrop)) + return null; + + string[] files = (string[])data.GetData(DataFormats.FileDrop); + + if (files.Length != 1) + return null; + + var file = files[0]; + var ext = System.IO.Path.GetExtension(file); + if (VideoCutterSettings.Instance.VideoFilesExtensions.Contains(ext.ToLower())) + return file; + + return null; + } + + private void MainForm_DragOver(object sender, DragEventArgs e) + { + if (GetPathOfSingleDraggedFile(e.Data)!=null) + e.Effect = DragDropEffects.Copy; + } + + private void MainForm_DragDrop(object sender, DragEventArgs e) + { + var file = GetPathOfSingleDraggedFile(e.Data); + if (file != null) + { + OpenFile(file); + } + } } } diff --git a/src/SimpleVideoCutter/MainForm.resx b/src/SimpleVideoCutter/MainForm.resx index ffa1f21..4fafcf7 100644 --- a/src/SimpleVideoCutter/MainForm.resx +++ b/src/SimpleVideoCutter/MainForm.resx @@ -132,6 +132,9 @@ 1027, 17 + + 881, 17 + 764, 17 @@ -164,9 +167,6 @@ RU5ErkJggg== - - 881, 17 - AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA diff --git a/src/SimpleVideoCutter/Properties/AssemblyInfo.cs b/src/SimpleVideoCutter/Properties/AssemblyInfo.cs index 636d2a4..a65302b 100644 --- a/src/SimpleVideoCutter/Properties/AssemblyInfo.cs +++ b/src/SimpleVideoCutter/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.10.0.0")] -[assembly: AssemblyFileVersion("0.10.0.0")] +[assembly: AssemblyVersion("0.11.0.0")] +[assembly: AssemblyFileVersion("0.11.0.0")]