2

I'm using C# WinForms to make a video converter, I'm using NReco.VideoConverter library. It has an EventHandler named ConvertProgress but I have never used EventHandlers, I was searching for some information on internet, but I still don't know how to apply it to my application.

I tried this:

public static event EventHandler<ConvertProgressEventArgs> _getPercent;
//...
_getPercent += ???
progressBar1.Value = ??

I'm stuck there, and I don't know what to do. Can someone help me?? Thanks in advance.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
ChrisCreateBoss
  • 323
  • 7
  • 21

2 Answers2

4

First off, get rid of your custom event. You want to listen/subscribe to their event, not yours.

Second, you need an actual instance of your converter, then subscribe to its event:

FFMpegConverter converter = new FFMpegConverter(); //May not work, for sample only
converter.ConvertProgress += UpdateProgress;

Now you need a method called UpdateProgress (you could also just use a lambda expression above):

private void UpdateProgress(object sender, ConvertProgressEventArgs e)
{
}

And in the body of that method, update your progress bar. Note that you need to marshal your change onto the UI thread. In Windows Forms that's done with Control.Invoke

progressBar1.Invoke(new Action(() =>
{
     progressBar1.Value = e.Processed; //Or whatever calculation you want
}));

For others, and if you haven't seen it, here's the documentation for that event: http://www.nrecosite.com/doc/NReco.VideoConverter/html/E_NReco_VideoConverter_FFMpegConverter_ConvertProgress.htm

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • @ChrisCreateBoss Yeah, unless you are familiar with events, its not much help :) FFMpeg documentation is good, but they don't have much in the way of "Usage" examples :( – BradleyDotNET Feb 26 '15 at 22:54
  • Yeah that's true... Otherwise, how do I convert your e.Processed to an integer(progressBar.Value needs an integer value to work). – ChrisCreateBoss Feb 26 '15 at 22:58
  • @ChrisCreateBoss There's another property on that event "TotalDuration". You would divide by that (to get the percent complete as a double) and scale it for your progress bar – BradleyDotNET Feb 26 '15 at 22:59
  • tried that but I still get "cannot implicity convert type TimeSpan to int" – ChrisCreateBoss Feb 26 '15 at 23:07
  • @ChrisCreateBoss Use `TotalMilliseconds` for each one (`processed.TotalMilliseconds / total.TotalMilliseconds`) – BradleyDotNET Feb 26 '15 at 23:09
  • Yes I used that too and I get "Cannot implicity convert type double to int" – ChrisCreateBoss Feb 26 '15 at 23:13
  • @ChrisCreateBoss That one you can just cast :) `(int)myDoubleValue` You can use `Math.Round` first if you want to control truncation/rounding – BradleyDotNET Feb 26 '15 at 23:14
  • Ok, that's fixed, now I'm getting that Cannot convert lambda expression to type delegate. Sorry, I have never used delegates, or event handlers, so I'm having many complications. – ChrisCreateBoss Feb 26 '15 at 23:18
  • @ChrisCreateBoss See my edit :) Sorry, couldn't remember if `Invoke` needed the explicit Action creation like `Dispatcher.BeginInvoke` (my WinForms is a bit rusty) – BradleyDotNET Feb 26 '15 at 23:19
  • Oh ok, one more thing, do I need a timer to update the progressBar or not? – ChrisCreateBoss Feb 26 '15 at 23:23
  • @ChrisCreateBoss Under this model I certainly wouldn't think so. The library is driving the updates to the progress bar – BradleyDotNET Feb 26 '15 at 23:24
  • @ChrisCreateBoss You'll have to debug it. I can't see your system :) Hint: Make sure the event is firing (by putting a breakpoint in `UpdateProgress`) and work from there. Also check the output window for any first chance exceptions. – BradleyDotNET Feb 27 '15 at 00:04
  • Yes, I tried that, but I don't get any errors or exceptions. I click on my "Convert" button, and the file conversion is successfull but the progressBar did not make something. – ChrisCreateBoss Feb 27 '15 at 00:11
  • @ChrisCreateBoss Like I said, you'll have to debug it. Start with making sure the event is actually firing. If its not, you either set up the handler wrong (or on the wrong object, if you just copy-pasted my code) or there is a bug in the library. – BradleyDotNET Feb 27 '15 at 00:13
  • Yes I debbuged, take a look to my code: `private void UpdateProgress(object sender, ConvertProgressEventArgs e) { conversionProgress.Invoke(new Action(() => { int progressValue = Convert.ToInt32(e.Processed.TotalMilliseconds / e.TotalDuration.TotalMilliseconds); conversionProgress.Value = progressValue; })); }` – ChrisCreateBoss Feb 27 '15 at 00:17
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/71835/discussion-between-bradleydotnet-and-chriscreateboss). – BradleyDotNET Feb 27 '15 at 00:20
  • I added a backgroundWorker to my form(to perform the video conversion), the conversion is going well as always, I tried to use the ProgressChanged event from the BGW but the progressBar is filling in a low time(the conversion ends and the progressBar is still in the middle) – ChrisCreateBoss Feb 27 '15 at 22:42
  • @ChrisCreateBoss Then you just need to change whatever counter you are using to populate `ProgressChanged` so it fills the bar up faster... – BradleyDotNET Feb 27 '15 at 22:59
  • How can that be done? For(i =0;i<10;i++){progressBar.value = e.convertProgress; } i wrote convert progress because Im writing from a mobile phone and dont have the code in my front but I think you know to what event Im refering – ChrisCreateBoss Feb 28 '15 at 01:23
  • @ChrisCreateBoss That code makes no sense. I think you need to ask a new question with the full code – BradleyDotNET Feb 28 '15 at 01:36
  • Ok, but thanks for your help, I hope you can help me with that one – ChrisCreateBoss Feb 28 '15 at 01:39
1

I have solved with redirection of standardError and read with streamreader in a method.

public double Progress{get;set;}

create new process

Process run = new Process();
run.StartInfo.FileName = Path.Combine(path, "ffmpeg.exe");
run.StartInfo.Arguments ="your string with output options";
run.StartInfo.UseShellExecute = false;
run.StartInfo.CreateNoWindow = true;
run.StartInfo.RedirectStandardError = true;
run.Start();
StreamReader sr = run.StandardError;
while (!sr.EndOfStream)
{
    getTotalSecondProcessed(sr.ReadLine());
}

and redirect output

private void getTotalSecondProcessed(string v)
{
   try
   {
       string[] split = v.Split(' ');
       foreach (var row in split)
       {
           if (row.StartsWith("time="))
           {
               var time = row.Split('=');
               Progress = TimeSpan.Parse(time[1]).TotalSeconds;
           }
       }      
       catch{}
   }

in WinForm create a method called by a timer_Tick

private void timer1_Tick(object sender, EventArgs e)
    {
        try
        {        
            int progress = int.Parse(utilityVideo.Progress.ToString("0"));

            if (progress > 0)
            {
                RefreshProgressBar(Progress);
            }
        }                
    }
    catch { }
    }

private void RefreshProgressBar(int currentTimeProcessed)
    {
        if (InvokeRequired)
        {
            BeginInvoke((MethodInvoker)delegate { RefreshProgressBar(currentTimeProcessed); });
            return;
        }
        progressBar1.Value = currentTimeProcessed;
    }
Spadieri
  • 11
  • 5