-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved workflow (auto-create directories, quick save to sub directories, move/delete original file) #97
base: development
Are you sure you want to change the base?
Conversation
Thank you very much for submitting! I am currently a bit busy but will try to review as soon as possible. |
I have take a first look at the changes and posted some comments (I reviewed only a subset of changes so far, but already wanted to give feedback). I like the ideas very much, but I would really prefer to have separate submission for each of the concepts (at least for auto-creating directories, quick-save folders, post-processing actions), that would really simplify the review and allow to integrate some changes whilst still discussing others. Anyway, thanks again for taking the effort and posting your changes! |
videoViewHover.MediaPlayer.Media?.Dispose(); | ||
videoViewHover.MediaPlayer.Media = null; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If such a generic method is added, it should allow to be called in isolation (i.e. without calling OpenNextFileInDirectory
or OpenPrevFileInDirectory
which btw. can always fail, as there may be just one file in the directory).
But it means, that UnloadVideo
should properly update the whole state (including UI) after unloading the state.
So, we miss here, for example:
ClearAllSelections();
UpdateIndexLabel();
EnableButtons();
as well as clearing the fileBeingPlayed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably, UnloadVideo() can be removed completely, as OpenNextFileInDirectory() does all things necessary. I added the explicit unloading, because I once had a crash, and I noticed that OpenNextFileInDirectory() only implicitly unloaded the video. I didn't like that. Btw, setting fileBeingPlayed to null before calling OpenNextFileInDirectory() would require adjustments to that method. Let's save us the hassle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would love to keep the UnloadVideo
, as it would also fix the issue #18. I can imagine that closing a file (to make sure some other program can have exclusive access) may be useful in some workflows.
I think the changes I suggested would be enough (haven't checked though).
btw, setting fileBeingPlayed to null before calling OpenNextFileInDirectory() would require adjustments to that method. Let's save us the hassle.
Yes, currently this would be an issue, but I think adding a lastFileThatWasPlayed
variable would solve this issue nicely and should be rather straightforward,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UnloadVideo()
is ready to be used now.
src/SimpleVideoCutter/MainForm.cs
Outdated
@@ -30,6 +32,10 @@ public partial class MainForm : Form | |||
private string? fileToLoadOnStartup = null; | |||
private Debouncer debouncerHover = new Debouncer(); | |||
private bool playingSelection = false; | |||
private bool shouldAskForDeletionConfirmation = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not in VideoCutterSettings
(as e.g. KeepSelectionAfterCut
and others) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like to be reminded once per session. Plus, if that flag was saved in the settings as false
, we would need an extra checkbox somewhere to set it to true
again. Then again, why not? Wouldn't be much work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see your point and of course this is your preference. On the other hand, I would rather like to prefer to keep the consistency and make all the options to work the same way. One could argue ("I like it to be session scope setting") for other variables as well, e.g. KeepSelectionAfterCut
or ShowPreview
. If the new settings would behave differently, probably there would be bug reports "Deletion confirmation not saved" etc.
In general, having possibility to consider all (or some) of the settings as "session based" sound interesting, but I would rather look for a more consistent solution (and I honestly think that in this case global-settings is a better choice).
Plus, if that flag was saved in the settings as false, we would need an extra checkbox somewhere to set it to true again.
Yes, that's true. But I would tend to ignore this. I rather assume that people do not revisit this kind of decisions (have you ever revisited cookie banner setting on a page that you clicked once? 😅 ). So I would assume that possibility to edit the json file (or just delete it and start from scratch) would be a "good enough" workaround.
src/SimpleVideoCutter/MainForm.cs
Outdated
@@ -30,6 +32,10 @@ public partial class MainForm : Form | |||
private string? fileToLoadOnStartup = null; | |||
private Debouncer debouncerHover = new Debouncer(); | |||
private bool playingSelection = false; | |||
private bool shouldAskForDeletionConfirmation = true; | |||
private bool shouldNotifyIfCurrentFileIsBeingDeleted = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not in VideoCutterSettings
(as e.g. KeepSelectionAfterCut
and others) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
likewise
src/SimpleVideoCutter/MainForm.cs
Outdated
@@ -726,6 +834,8 @@ private IList<string> GetVideoFilesInDirectory(string currentFilePath) | |||
|
|||
private string? GetNextPrevFileInDirectory(string currentFilePath, int direction) | |||
{ | |||
Debug.WriteLine(currentFilePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather prefer not to keep Debug
-s in the code that is in development branch. Feel free to use them in the branch, but remove before opening PR (after testing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I forgot that line there. Just like a surgeon forgets scissors in the stomach sometimes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, that's not problem. Thanks!
@@ -13,6 +14,15 @@ public class VideoCutterSettings | |||
public string DefaultInitialDirectory { get; set; } = "{UserVideos}"; | |||
public string OutputDirectory { get; set; } = "{UserVideos}"; | |||
public string OutputFilePattern { get; set; } = "{FileDate}-{FileNameWithoutExtension}.{Timestamp}{FileExtension}"; | |||
public string[] QuickSubDirectories { get; set; } = Enumerable.Repeat("", 9).ToArray(); | |||
|
|||
public bool CreateMissingDirectories { get; set; } = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would opt for true
being the default. This seems to very useful and I do not think it would break any workflows of existing users.
src/SimpleVideoCutter/MainForm.cs
Outdated
confirmDeletionResult = MessageBox.Show( | ||
"As per the settings, the original file will be deleted. Is this OK? If you choose yes, original files will be deleted without another confirmation.", | ||
"Confirm Deletion", | ||
MessageBoxButtons.YesNo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would consider adding also a "cancel" option, that would mean the action is not constructed and the file is not being deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea!
src/SimpleVideoCutter/MainForm.cs
Outdated
if (this.shouldNotifyIfCurrentFileIsBeingDeleted) | ||
{ | ||
DialogResult dialogResult = MessageBox.Show("As per the settings, the original file will be deleted after the cut was saved." + | ||
" Since you are currently playing this file, the program will skip to the next file first." + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a user, I would probably prefer to only unload the current file, without proceeding to the next one automatically (why next? I usually browse file the the reverse date order so I go to previous one). Or at least do not start playing the next file automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recently cut about 30 files and enjoyed the jump to the next (I didn't care about the order, could also have been previous) file. Hm, it should be configurable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, in the end this is really a detail (whether to unload only or load another file immediately, next or prev). If there is a separate option to "close" file then I think it is not that important.
On the other hand, it can always happen that there is no more files in the folder, thus we end up with "no file loaded" sitaution and this has to be supported.
@@ -189,6 +197,7 @@ public class FFmpegTask | |||
public FFmpegTaskSelection[]? Selections { get; set; } | |||
public long OverallDuration { get; set; } | |||
public bool Lossless { get; set; } | |||
public IActionAfterTaskCompletion? ActionAfterTaskCompletion { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you tested this?
Currently it fails with exception, because the task is being XML-serialized (cloned) in the FormAddTask
constructor (I had the keep
option selected)
System.InvalidOperationException
HResult=0x80131509
Message=There was an error reflecting type 'SimpleVideoCutter.FFmpegTask'.
Source=System.Private.Xml
StackTrace:
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at SimpleVideoCutter.Utils.DeepCloneXML[T](T input) in C:\Users\bartek\Documents\git\simple-video-cutter-mr\src\SimpleVideoCutter\Utils.cs:line 23
at SimpleVideoCutter.FormAddTask..ctor(FFmpegTask task, Boolean selectionsOnKeyFrames) in C:\Users\bartek\Documents\git\simple-video-cutter-mr\src\SimpleVideoCutter\FormAddTask.cs:line 19
at SimpleVideoCutter.MainForm.PrepareTask(Boolean showAddTaskDialog) in C:\Users\bartek\Documents\git\simple-video-cutter-mr\src\SimpleVideoCutter\MainForm.cs:line 745
at SimpleVideoCutter.MainForm.EnqeueNewTask(Boolean showAddTaskDialog) in C:\Users\bartek\Documents\git\simple-video-cutter-mr\src\SimpleVideoCutter\MainForm.cs:line 782
at SimpleVideoCutter.MainForm.toolStripSelection_ItemClicked(Object sender, ToolStripItemClickedEventArgs e) in C:\Users\bartek\Documents\git\simple-video-cutter-mr\src\SimpleVideoCutter\MainForm.cs:line 1132
at System.Windows.Forms.ToolStrip.HandleItemClick(ToolStripItem dismissingItem)
at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ToolStrip.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, WM msg, IntPtr wparam, IntPtr lparam)
Inner Exception 1:
InvalidOperationException: Cannot serialize member 'SimpleVideoCutter.FFmpegTask.ActionAfterTaskCompletion' of type 'SimpleVideoCutter.Actions.IActionAfterTaskCompletion', see inner exception for more details.
Inner Exception 2:
NotSupportedException: Cannot serialize member SimpleVideoCutter.FFmpegTask.ActionAfterTaskCompletion of type SimpleVideoCutter.Actions.IActionAfterTaskCompletion because it is an interface.
I would consider saving (into the task) only the name of the selected action, and actually instantiate it when it will be about to execute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I never used Shift + E during later development, so I never stumbled upon that. Sorry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually pretty strange, because I think it worked me for the first time I had started the app in your branch (i.e. I was able to cut) but then it failed every time. And btw. I did not use Shift+E
, I just pressed the Cut
button.
Thanks for taking the time to review all that! And sorry for the PR containing so much stuff. Initially, I was just tinkering around (it's been at least 10 years since I developed with .NET) and didn't even think of making a PR. |
I will probably address the issues next weekend. |
|
||
namespace SimpleVideoCutter | ||
{ | ||
public partial class ChooseOutputDirectory : Form |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I report it here, but this comment applies also to other places)
I have recently cleaned up development branch from any compiler warnings. In your branch I see 133 warnings. For example here:
Severity Code Description Project File Line Suppression State
Warning (active) CS8618 Non-nullable field 'originalOutputDir' must contain a non-null value when exiting constructor. Consider declaring the field as nullable. SimpleVideoCutter ChooseOutputDirectoryDialog.cs 24
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cleaned them up in my fork. Though I did not count them, I made much less fixes than 133 (probably between 10 and 20).
The only messages I see now are related to duplicate names in FormSettings.resx
, and there are 118 of them. Could they have been introduced by my IDE by accident? I did not consciously edit that file.
Excerpt:
1>FormSettings.resx : warning MSB3568: Duplicate resource name ">>buttonCancel.Name" is not allowed, ignored.
1>FormSettings.resx : warning MSB3568: Duplicate resource name ">>buttonCancel.Type" is not allowed, ignored.
1>FormSettings.resx : warning MSB3568: Duplicate resource name ">>buttonCancel.Parent" is not allowed, ignored.
1>FormSettings.resx : warning MSB3568: Duplicate resource name ">>buttonCancel.ZOrder" is not allowed, ignored.
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It turned out that those resource names were there before my changes. Can I safely delete them?
Except for this, everything should be resolved now.
|
Hi @l3if3rik, just a short update from my side - I have seen you pushed lot of changes, but unfortunately I am very busy recently (plus vacation season) so had no time yet to review, and may still need some time to do it. Sorry for the delay and thanks for you effort! |
This bug flew under the radar for quite some time. The files in A method like |
That's basically all the stuff I developed in several branches on my fork. While your program is the best for my purposes, it lacked some features that I really needed.
I do not know how to work with translations, so it is all hard-coded English, currently.
To clarify this further, here are some screenshots: