-
-
Notifications
You must be signed in to change notification settings - Fork 63
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
Is there a way to show save progress? #46
Comments
Hi and thanks for the feeback ! That's a very relevant question for someone who uses the library on large files. Right now there's nothing to allow what you describe, but I think it's a very useful feature. I need some time to research what are the .NET best practices on this matter. I'd be very tempted to use ReactiveX, but this might be disproportionnate - maybe there's already something that allows to do the job on the basic .NET framework itself. I'll keep you informed about the next steps. |
Thanks its very noticeable on my first test file which was 1.2GB (44 hours long) but even the second one at only 230mb locks up the program with no status for a good 10 seconds or so. |
I've added support for Sample code : private void displayProgress(float progress)
{
Console.WriteLine(progress * 100 + "%");
}
private void performWrite()
{
IProgress<float> progress = new Progress<float>(displayProgress);
Track t = new Track(s, progress);
t.AdditionalFields.Add(new KeyValuePair<string, string>("test","aaa"));
t.Save();
} Important : ATL minimum requirements will be .NET Framework 4.5 instead of .NET Framework 3.0 Don't hesitate if you have additional feedback. |
Nice! I'll give it a whirl when it is available. I'm already targeting 4.8 so that should not be a problem. |
Ok not sure if i'm doing this right or its a bug but all i am getting when using IProgress is 1% twice This is the log from 3 tests
and this is the code
|
First of all, the code sample I gave you had an incorrect line. The progress should actually be displayed that way. Sorry for the misdirection. Console.WriteLine(progress * 100 + "%"); Secondly, I've simplified the progress report to make it more consistent. It should become more intuitive in the next build. Just don't expect something fine-tuned; it will be 0-100 or 0-50-100. For now I can't do much more than that because the nunber of low-level elements to write is unknown until all of them have been actually written. Making the library count them all at the beginning of the process will slow down the whole operation and/or occupy more memory, which I can't accept just for the sake of reporting progress. |
Ah ok. Is it possible to even do it in 25% increments or does that add too much overhead? Does it go through this/add overhead even if you don’t initialize theTrack with the progress? |
As far as I can see, there are 3 ways to report about progress : 1/ Basic level of detail is to count the number of tag containers that have been written (my choice for the next build) e.g. if an MP3 file has an ID3v2 and an APE tag
2/ Medium level of detail is to report about how many zones have been written inside of each tag container. A zone is an area of the file that contains important data to write or to update. It won't do much of a difference for ID3v2 and APE because they both have one single zone, as their structure is very simple. WMA's or MP4/M4A's have a more complex structure and may have a few dozen zones to go through, which will give a more detailed report. To display a correct %, the library will need to count the zones of all tag containers before starting to update the file. Adapting the library to do that can be quite heavy to implement but should only generate a moderate overhead... and you won't see the difference with basic level when editing MP3s anyway : it will still jump 0-50-100. 3/ Ultimate level of detail is to report about how many bytes have been written. To know that, it is necessary to measure how many bytes need to be written on the whole file before starting the operation. In other words, the library will need to simulate the updating all tag containers before the update operation even begins. That's complex and generates a huge overhead for each file, just for the sake of displaying a progress indicator. => imho, choice 1 is the best tradeoff between ease of implementation and added value |
Ah ok. I figured it was as simple as hey this file is 500mb and I’ve written 200 so far and doing the math on that. Sounds like it is much more complicated. |
yeah, unfortunately |
So now the output shows 0% and 100% right after
|
M4B files usually have one single native tag container, so that totally makes sense. There's no finer detail than that, unfortunately, unless I dive deeper and count the zones (see yesterday's explanation). |
Ah I understand. I know it's not a priority but it would be cool if you could look into it more as you have time. I'm not sure how other (now obsolete) programs have done it in the past. I think Chapter & Verse was one that did show progress but it also used quicktime and itunes which is why it no longer works. If there was even a "quick save" and a "progress save" where the first did not do any counting and the 2nd did that might be workable. |
@ElmoFuntz Have you looked at setting this to help speed up file saving? It ends up using more RAM but even for large files it's not too bad. Settings.FileBufferSize = fileStream.Length > int.MaxValue
? int.MaxValue
: (int)fileStream.Length; |
Z mentioned that setting to me in another bug and setting it to 4096 dramatically reduced save times. |
Thanks for the workaround @CooPzZ. I hope this helps other people. FYI, I'm keeping this issue alive as I haven't found any satisfactory solution to implement a proper progress indicator that :
For all of you who are reading me, do not forget to take a look at the FAQ dedicated to performance : https://github.com/Zeugma440/atldotnet/wiki/4.-FAQ-(Frequently-Asked-Questions)#FAQM.5 |
No worries - I understand. I would think if there is a process per file type make it a dynamic with 2 stages:
Again to keep it simple you could export a status tag like I'm doing here and a percentage and let the calling application decide what to do with it, that way you don't need to keep a strict order of things either. I was thinking of extending your Status object to work like the Trace and call it very similarly as I'm using both at the moment - I might have a go at it, however I'm still learning the lib, and I think you were on the right track. |
I just attempted something - tell me if it fits your needs @CooPzZ NB : The app can't predict the effort required for each step, so you might see "peaks" while going from 0% to 100% |
Could you please give an example on how to use it with the section name coming out and the Track object? |
That part was intentionally left out as the current progress granularity is what I'll adapt the code and get back to you.
For now, section name is only recorded for debug purposes. Do you really need that for end user display ? |
No worries - that seems to be the part where most time is spent - well with the saving I've been doing. ie: I hit pause and 9 times out of 10 it's in that procedure - some times it going through the 300k of Zones. Keep in mind this is for big files only.
No but it makes more sense if it's goes through the procedures more than once. |
Hi @Zeugma440 , This is more of what I was thinking so you didn't need to fluff up and down the procedure tree - I hate when I have to do that - I'm not sure if its' a great pattern however it should be efficient and loose enough - it is loosely based on the observer pattern it think, but works much like the Trace statement.
To report progress, call the static procedure.. ie: There is no need to test if the progress object exists - the monitor will decide for you based on the listeners. And in the calling app you need to create the listener and subscribe to it in ATL once. Note this bit is in vb as I can't be bothered tonight to translate - maybe next week but hopefully you understand what I'm doing here.
Anyway hope that helps. |
Hey @CooPzZ The Observer is definitely a pattern to consider here to make things easier to handle, the same way logging has been designed. However I need to be careful with that one as some ATL clients use the library in a multi-threaded environment where multiple files may be being processed at the same time. We might need a progress token or something akin to differentiate feedback when used on multiple threads... or maybe use the tread ID itself (done that before somewhere) 🤔 |
Glad to see this is getting some attention. Also thanks Z for all of your hard work on this project over the years! |
@CooPzZ I haven't dived yet in architectural refactoring, but now every unbuffered zone should report its own progress. Here's a sample code to use IProgress<float> progress = new Progress<float>(p => Console.WriteLine(p));
Track theTrack = new Track(file_location, progress); I'll try to refactor the whole thing using an Observer pattern as soon as you confirm it behaves the way you expect. |
The update: |
Sorry Zeugma, try again - |
First of all, your video is super clear from beginning to end. Thanks for taking the time to capture it 👍 I haven't seen all your code, but something is telling me that your calling What might happen there is your own feedback being processed before ATL's because of it being prioritary (main thread) over ATL's ( Last but not least, the fact that your own progress runs is itself proof that ATL was logging something too, as the whole block inside => Did you try to run the app while disabling your own progress feedback to see if the ATL progress feedback covers the whole operation ?
If we're going deeper into that issue, I'll need to know which line of |
I'm sorry, I'm not sure if I'm doing threads right - but I can see that the progress isn't active to report back through the ATL progress when you see mine coming through Yes I have done it without mine and I don't see it doing anything during that period - 3rd vid. |
It is a threading issue, and the more I read about it, the more I get the feeling IProgress has to be used in conjunction with async / await... which ATL doesn't support for now. I'm gonna set up a new test project with a bona fide UI (instead of a Console) and experiment with that. Stay tuned ! |
Graphical UI is now working as expected ! My conclusions are :
Here's the downsides for each solution :
=> For now, I've chosen the simplest route, changing the public API from Track(string path, IProgress<float> writeProgress = null, bool load = true) to Track(string path, Action<float> writeProgress = null, bool load = true) UI refresh happens properly when feeding that to the Delegate private void displayProgress(float progress)
{
String str = (progress * 100).ToString() + "%";
Console.WriteLine(str);
ProgressLbl.Text = str;
Application.DoEvents();
} This should (hopefully) be the final update to this issue 🤞 |
@CooPzZ forgot to tag you as you're not this issue's OP |
Still got it - sorry, just haven't had a chance to check it. |
FYI, the tests to support The target API will be :
=> If you don't mind, I'd rather you spend time on #160 so that I can release a bugfix build for #160 and #159. The release after that one will contain support for |
This looks very good now and reports during that period. Excellent work. There is one case to note, which you may already know. I've added the Logs in the share for both. |
Roger. I have an idea about how to solve that too. I'll fix that along with the async implementation. |
Done ! The main branch is now More information there : https://github.com/Zeugma440/atldotnet/wiki/Progress-feedback Warning The API has changed (again) : the progress feedback handle must now be given as arguments to |
Thanks Zeugma -- ok playing with this today I couldn't find out why your progress was working differently to mine.
Is there something regarding this and progress we need to be aware of. |
If I may, instead of comparing your progress vs. mine, wouldn't it be better to wonder if the ATL standard progress is meaningful to the end user ? To answer your question, |
Sorry, I meant in my program, I'm using the same ATL progress object you've built in the UI-test (nothing of my progress method exists any more) I was getting a different output..
Instead of your remark around threads, the Otherwise the progress methods added work really well. I need a bit more time to comment on the resolution with different file types. |
The original issue reported by the OP has been answered with v4.11 (https://github.com/Zeugma440/atldotnet/wiki/Progress-feedback) Please open new issues if you detect bugs or improvements on the current reporting behaviour. |
I have started testing saving of metadata to my audio book files and at first thought it was failing because I was seeing some mdat atom not found errors in the log but it turns out it was just taking a long time to save. Is there a way to display out the metadata save progress?
The text was updated successfully, but these errors were encountered: