NextPVR Forums
  • ______
  • Home
  • New Posts
  • Wiki
  • Members
  • Help
  • Search
  • Register
  • Login
  • Home
  • Wiki
  • Members
  • Help
  • Search
NextPVR Forums Public Developers v
« Previous 1 … 46 47 48 49 50 … 93 Next »
Redirecting stdout from a process invoked from a plugin

 
  • 0 Vote(s) - 0 Average
Redirecting stdout from a process invoked from a plugin
Ton
Offline

Member

Posts: 233
Threads: 16
Joined: Aug 2005
#11
2006-11-19, 08:50 AM
In my "MVPRecoder" app, I do something similar....

One other thing I have done is start seperate "stdout" and "stderr" reader-threads to check / evaluate what's written to stdout/stderr...

Here's the (C#) code:

Code:
            Process proc = new Process();
            proc.EnableRaisingEvents = false;
            proc.StartInfo.FileName = recode_path;
            proc.StartInfo.Arguments = command_line;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.RedirectStandardError = true;
            
            proc.Start();

            StdReader cOut = new StdReader();
            cOut.theReader = proc.StandardOutput;
            Thread tOut = new Thread(new ThreadStart(cOut.StdOutReader));

            StdReader cErr = new StdReader();
            cErr.theReader = proc.StandardError;
            Thread tErr = new Thread(new ThreadStart(cErr.StdErrReader));

            tOut.Start();
            tErr.Start();
            proc.WaitForExit();
            tOut.Abort();
            tErr.Abort();

And here's the code for the stdout/stderr reader class:

Code:
    class StdReader
    {
        public StreamReader theReader;
        public string data;
        
        public void StdErrReader() {
            
            try {
                while (true) {
                    data = theReader.ReadLine();
                    // Ignore all standard errors...
                    if (!data.StartsWith("WARNING"))
                        if (!data.StartsWith("ERROR: SCR:"))
                            if (!data.StartsWith("1 duplicate frame(s)"))
                                if (data.IndexOf("buffer underflow") == 0)
                                    Console.WriteLine(data);
                }
            } catch {}
        }
        public void StdOutReader() {
            
            try {
                while (true) {
                    data = theReader.ReadLine();
                    if (data.StartsWith("Pos:")) {
                        Console.Write("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
                        Console.Write(data.Substring(4, 28).TrimStart());
                     }
                }
            } catch {}
        }    
    }
the "\b\b"'s are interpreted by the console on WinX to delete previous character on the console..... That way you can make a nice progress-indicator (from the command-line anyway).
//Ton
alibert
Offline

Posting Freak

Posts: 974
Threads: 83
Joined: Apr 2005
#12
2006-11-19, 12:30 PM
Hi,
ubu Wrote:Any ideas? Sympathy, even?

since .NET 2, there two new events in the Process class: ErrorDataReceived and OutputDataReceived. Instead of doing a "busy wait" on the process' output, you can simply add an eventhandler and you'll get the output deleivered to the handler method.

In my DboxRecorder plugin, I'm doing something like this:

Code:
// Start the process
ggrabProcess = new Process();
ggrabProcess.StartInfo = ggrabStartInfo;
ggrabProcess.ErrorDataReceived += new DataReceivedEventHandler(GgrabErrorDataReceived);
ggrabProcess.Start();

// Start the asynchronous read of the standard error stream
ggrabProcess.BeginErrorReadLine();

And:

Code:
private void GgrabErrorDataReceived(object sender, DataReceivedEventArgs e)
{
    if (IRecordingSource.RecordingStatus.RECORDING_IN_PROGRESS == RecordingStatus &&
        null != e.Data && true == e.Data.Contains("timeout"))

[...]

-alibert
Ton
Offline

Member

Posts: 233
Threads: 16
Joined: Aug 2005
#13
2006-11-19, 07:17 PM
Cool,

I'll implement that when I update MVPRecode to 2.0.....

Thanks for sharing that...
//Ton
acheyne
Offline

Member

Posts: 81
Threads: 20
Joined: Dec 2005
#14
2006-11-20, 04:08 PM
ubu - Sorry for not actually trying to compile and run that - I'm on a machine without a C# development environment. I was simply looking at some C/C++ code I have that does what you want. I had assumed that C# is built on top of the lower level SDKs and would work properly.

My other suggestion would be to start your process up through a separate thread if your only problem is having to wait for the app to exit.
GBPVR 1.1.5 on
Pentium 4 2.0GHz
PVR-350
NVidia GeForce 5200 TV-Out
NiteShdw
Offline

Member

Posts: 71
Threads: 5
Joined: Sep 2005
#15
2006-11-20, 06:36 PM
alibert Wrote:Hi,


since .NET 2, there two new events in the Process class: ErrorDataReceived and OutputDataReceived. Instead of doing a "busy wait" on the process' output, you can simply add an eventhandler and you'll get the output deleivered to the handler method.

My first attemp was to use that same function "BeginReadLine()" with EventHandlers. I came across the problem that the Event was only fired at the beginning and end of running comskip. After the program was finished, I basically just ended up with the line that said "Commercials found".

I also had this problem with mpgtx. What I think is happening is that rather than doing a WriteLine (or equivilent), the console apps are do a write and then writing backspaces and rewriting the line in order to show a progress indicator. Apparently, the BeginReadLine() function doesn't fire the event until an actual line break is written to the buffer.

So, is it possible to just read the underlying stream as it's being written? And use my own buffer to check for certains strings (like "95%")?
Ton
Offline

Member

Posts: 233
Threads: 16
Joined: Aug 2005
#16
2006-11-20, 08:34 PM
Well, if you look at my post earlier, you see that I started a seperate thread....

in that thread my code currently uses "ReadLine" to read from the buffer (thus waiting for the line-feed to start reading), but you could replace that with another read-function (that reads a max number of characters), and that should allow you to catch the characters as they're being written...

Only thing I'm not sure of (and I lack the time to do a quick "looksee" for you), is what happens (underwater) with the backspaces....
//Ton
ubu
Offline

Posting Freak

Posts: 792
Threads: 54
Joined: Jan 2006
#17
2006-11-20, 09:11 PM
acheyne Wrote:My other suggestion would be to start your process up through a separate thread if your only problem is having to wait for the app to exit.
As I said in my earlier response:
Quote:In the event, I was able to produce an identical result by creating a separate thread (using a BackgroundWorker object) and then using that to run the code that invokes the application and writes its output to a file.
Thanks to everybody for their suggestions. The posts from Ton and alibert really point up the fact that .Net (usually) offers a number of different ways to solve the same problem. Unfortunately this creates a new problem: deciding which is the best one to use Wink.

NiteShdw Wrote:Could you post the code that you are using now to redirect standard output while waiting for the application to finish?
I'll post the code for my version of the solution later today. Gotta run now.
[SIZE=1]GBPVR v1.3.11 [/SIZE][SIZE=1]HVR-1250, [/SIZE][SIZE=1]ES7300[/SIZE][SIZE=1], 4GB, GeForce 9300, LianLi, Vista.[/SIZE]
[SIZE=1]GBPVR v1.0.08 [/SIZE][SIZE=1]PVR-150, [/SIZE][SIZE=1]P4 2.26GHz, [/SIZE][SIZE=1]1GB,[/SIZE][SIZE=1] GeForce 6200, [/SIZE]Coupden, XP[SIZE=1]
[/SIZE]

Author: UbuStream plugin, UbuRadio plugin, EPGExtra utility.
ubu
Offline

Posting Freak

Posts: 792
Threads: 54
Joined: Jan 2006
#18
2006-11-21, 04:29 AM (This post was last modified: 2006-11-21, 04:58 AM by ubu.)
NiteShdw Wrote:Could you post the code that you are using now to redirect standard output while waiting for the application to finish?
So here's the approach I took (somewhat simplified for demonstration purposes) using a BackgroundWorker to run my processes asynchronously. It seems to work very well. I'm actually starting 1 to n processes within the background thread and, when they have all completed, reading the output file(s) they created. The stdout of each is captured to a separate log file for later perusal.

The actual method to run the process (which I have in a separate class - UbuStreamImporter):
Code:
public void Download_From_DynSource(String dynSourceApp)
        {
            String logFile = dynSourceApp.Replace(".exe", ".Playlist.log");
            ProcessStartInfo startInfo = new ProcessStartInfo(dynSourceApp, "");
            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardOutput = true;
            startInfo.CreateNoWindow = true;
            Process myProcess = Process.Start(startInfo);
            String logLines = myProcess.StandardOutput.ReadToEnd();
            myProcess.WaitForExit();
            File.WriteAllText(logFile, logLines);
         }
In the plugin class, I add: BackgroundWorker backgroundWorker = new BackgroundWorker();
and then, in the plugin constructor:
Code:
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
            Initiate_DynSource_Downloads();
Then:
Code:
private void Initiate_DynSource_Downloads()
        {
            ArrayList myDynSourceList = new ArrayList();
            foreach (DataRow myDynSource in xmlSchema11.Dynamic_Sources.Rows)
            {
                String myDynSourceApp = myDynSource["DynSource_App"].ToString();
                myDynSourceList.Add(myDynSourceApp);
            }
            backgroundWorker.RunWorkerAsync(myDynSourceList);
        }
The RunWorkerAsync call triggers this method:
Code:
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            ArrayList myDynSourceList = new ArrayList();
            myDynSourceList = (ArrayList)e.Argument;
            UbuStreamImporter myImporter = new UbuStreamImporter();
            foreach (String myDynSourceApp in myDynSourceList)
                myImporter.Download_From_DynSource(myDynSourceApp);
        }
I need to know when the processes have all finished since I want to read the file(s) the apps have created. When the backgroundWorker thread completes, this method gets called:
Code:
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
             foreach (DataRow myDynSource in xmlSchema11.Dynamic_Sources.Rows)
                Import_From_DynSource(myDynSource);
             refreshStationList();
        }
I didn't need to use it but one neat feature is you can use BackgroundWorker.ReportProgress to return the percentage of completion and a "state object" back to the calling thread (so you can check on it's progress from time to time). One caveat (obvious, I suppose): code residing in the background thread can't refer to variables (or anything else) in the parent thread.

As I said in my previous post, I'm not sure if this is a better or worse approach than those Ton and alibert are using. Just different. Smile alibert's solution is startlingly elegant (and certainly the simplest - it passes the "Ockham's Razor" test). If you needed to know when the process had completed (as I do), you could just check Process.HasExited from time to time, I guess.
[SIZE=1]GBPVR v1.3.11 [/SIZE][SIZE=1]HVR-1250, [/SIZE][SIZE=1]ES7300[/SIZE][SIZE=1], 4GB, GeForce 9300, LianLi, Vista.[/SIZE]
[SIZE=1]GBPVR v1.0.08 [/SIZE][SIZE=1]PVR-150, [/SIZE][SIZE=1]P4 2.26GHz, [/SIZE][SIZE=1]1GB,[/SIZE][SIZE=1] GeForce 6200, [/SIZE]Coupden, XP[SIZE=1]
[/SIZE]

Author: UbuStream plugin, UbuRadio plugin, EPGExtra utility.
alibert
Offline

Posting Freak

Posts: 974
Threads: 83
Joined: Apr 2005
#19
2006-11-21, 12:15 PM
Hi,

ubu Wrote:If you needed to know when the process had completed (as I do), you could just check Process.HasExited from time to time, I guess.

there's an event for this purpose, too:

http://msdn2.microsoft.com/en-us/library...xited.aspx

-alibert
ww4397
Offline

Senior Member

Posts: 382
Threads: 47
Joined: Oct 2005
#20
2007-01-18, 06:14 PM
Ton Wrote:Cool,

I'll implement that when I update MVPRecode to 2.0.....

Thanks for sharing that...

Where can I find MVPRecode? I don't see it on the Wiki.
« Next Oldest | Next Newest »

Users browsing this thread: 2 Guest(s)

Pages (3): « Previous 1 2 3 Next »


Possibly Related Threads…
Thread Author Replies Views Last Post
  PIP plugin for Kodi sgilani 2 3,011 2022-10-17, 12:44 AM
Last Post: sgilani
  Disable stdout mvallevand 0 1,234 2021-08-29, 04:01 PM
Last Post: mvallevand
  New Systems Plugin kirschey 10 3,489 2020-11-14, 08:01 PM
Last Post: sub
  VIdeo playback from plugin mvallevand 5 3,582 2015-08-06, 10:43 PM
Last Post: sub
  Attention Sub: Open TV / Custom Data Grabber plugin Benoire 2 2,977 2014-11-14, 02:05 AM
Last Post: Benoire
  API docs to help with plugin development? McBainUK 3 2,828 2013-06-08, 06:14 PM
Last Post: sub
  Refreshing TV Guide Data (after System plugin EPG update) imilne 13 6,264 2013-03-24, 08:03 PM
Last Post: imilne
  sabnzbd plugin to show processed files Wakalaka 1 2,000 2013-03-12, 06:48 AM
Last Post: psycik
  Plugin problems with started from the command line mvallevand 11 5,146 2012-08-12, 07:56 PM
Last Post: sub
  Get NextPVR data directory from outside a plugin McBainUK 3 2,304 2012-02-11, 05:42 PM
Last Post: mvallevand

  • View a Printable Version
  • Subscribe to this thread
Forum Jump:

© Designed by D&D, modified by NextPVR - Powered by MyBB

Linear Mode
Threaded Mode