Author Topic: pcl::ExternalProcess  (Read 7146 times)

Offline NKV

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 677
pcl::ExternalProcess
« on: 2013 December 19 20:26:59 »
Hi,
I have trouble to use pcl::ExternalProcess

Can you show a example how to execute that command: gnome-terminal -e 'ffmpeg -r 25 -i /home/user/Blink%05d.jpg /home/user/Blink.avi'
and redirect terminal output to PI Console?

There are example?

Best regards,
Nikolay.

Offline NKV

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 677
Re: pcl::ExternalProcess
« Reply #1 on: 2013 December 19 23:26:29 »
Now, i use code
Code: [Select]
code deleted because there are better solution.

The code working fine, but I can't use p.RedirectStandardOutput("Blink_avi.log" );
because some times required stdinput ( for "overwrite file Y/N" question )
and ByteArray pcl::ExternalProcess::StandardOutput ( ) always is empty.

Please help!
« Last Edit: 2013 December 23 08:51:26 by NKV »

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: pcl::ExternalProcess
« Reply #2 on: 2013 December 20 03:07:56 »
Hi Nikolay,

Yes, this is a common problem with ffmpeg. If you Google for "ffmpeg non-interactive" you'll see that you aren't alone.

The only solution is:

- Pass the -y option so all answers are 'yes' by default.

- Redirect the standard input from /dev/null:

p.RedirectStandardInput( "/dev/null" );

This should allow you to execute ffmpeg in a completely non-interactive way.

On a side note, why are you using gnome-terminal? You don't need it at all, and creating dependencies on these external utility programs is in general a very bad idea for a PixInsight module (for example, there is no guarantee that gnome-terminal be available on a specific X11 environment).

You should execute ffmpeg directly. If you want to show the standard output of the ffmpeg program in real time, this is quite easy to do with PixInsight's console. You can also open an auxiliary window with a TextBox control. To gather output from an external process, use the ExternalProcess::OnStandardOutputDataAvailable() and ExternalProcess::OnStandardErrorDataAvailable() event handlers, along with the ExternalProcess::StandardOutput() and ExternalProcess::StandardError() member functions.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline NKV

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 677
Re: pcl::ExternalProcess
« Reply #3 on: 2013 December 23 00:15:20 »
If you want to show the standard output of the ffmpeg program in real time, this is quite easy to do with PixInsight's console.
Easy for you, but not easy for me.

See picture.

ExternalProcess::OnStarted() and ExternalProcess::OnFinished working fine,
but I getting strange data from ExternalProcess::StandardOutput().
What's wrong in my code?

My code:
Code: [Select]
void BlinkInterface::__ExternalProcessOnStarted( ExternalProcess& p )
{
   Console().WriteLn("External processing started.");
   Console().WriteLn("PID="+String(p.PID()));
}

void BlinkInterface::__ExternalProcessOnFinished( ExternalProcess& p )
{
   Console().WriteLn("External processing finished.");
   Console().WriteLn("ExitCode="+String(p.ExitCode()));
}

void BlinkInterface::__ExternalProcessOnStandardOutputDataAvailable( ExternalProcess& p )
{
   Console().WriteLn("External processing OnStandardOutputDataAvailable.");
   ByteArray d(p.StandardOutput());
   
   for (size_t i = 0; i < d.Length(); ++i)
      Console().Write(char(d[i]));
}

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: pcl::ExternalProcess
« Reply #4 on: 2013 December 23 10:32:29 »
Mojibake!  :D

That happens because the process is sending data encoded as UTF-8 text. Try this way:

Code: [Select]
void BlinkInterface::__ExternalProcessOnStandardOutputDataAvailable( ExternalProcess& p )
{
   Console().WriteLn("External processing OnStandardOutputDataAvailable.");
   ByteArray d( p.StandardOutput() );
   String s = String::UTF8ToUTF16( static_cast<const char*>( d.Begin() ), 0, d.Length() );
   Console().Write( s );
}
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline NKV

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 677
Re: pcl::ExternalProcess
« Reply #5 on: 2013 December 23 23:05:03 »
Try this way:
Code: [Select]
   String s = String::UTF8ToUTF16( static_cast<const char*>( d.Begin() ), 0, d.Length() );
g++ make error: invalid static_cast from type ‘pcl::Array<unsigned char>::iterator {aka unsigned char*}’ to type ‘const char*’

I think, there are problem in ExternalProcess::StandardOutput()
See the result in attached test.log.txt or attached dump screen and sample code:
Code: [Select]
void BlinkInterface::__ExternalProcessOnStandardOutputDataAvailable( ExternalProcess& p )
{
   ByteArray d(p.StandardOutput());
   
   String fileName = "test.log";
   File f;
   if ( f.Exists( fileName ) )
      f.OpenForReadWrite(fileName), f.SeekEnd();
   else
      f.CreateForWriting( fileName );

   for(size_t i = 0; i< d.Length(); ++i)
      f.Write(d[i]);

   f.Close();
}

As you can see, ByteArray d(p.StandardOutput()) returns strange results which impossible to get from ffmpeg stdout:
Code: [Select]
G.l.o.b.a.l./.P.r.e.f.e.r.e.n.c.e.s./.P.r.o.c.e.s.s.I.n.t.e.r.f.a.c.e./.C.u.r.v.e.s.T.r.a.n.s.f.o.r.m.a.t.i.o.n./.T.r.a.n.s.l.u.c.e.n.c.y.A.c.t.i.v.a.t.i.o.n.E.f.f.e.c.t.s.

Offline NKV

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 677
Re: pcl::ExternalProcess
« Reply #6 on: 2013 December 24 03:32:01 »
Juan, can you add ExternalProcess example to SandBox module?

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: pcl::ExternalProcess
« Reply #7 on: 2014 January 01 09:29:17 »
Hi Nikolay,

I can confirm this problem. It is a bug in the PixInsight Core 1.8.0 application, which I already have identified and solved. I'll release the corresponding core application update next week.

Unfortunately, there's no workaround. However, you can continue working on your module without problems if you don't read the process' output channels. The rest of ExternalProcess works perfectly.

Sorry for the inconvenience.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: pcl::ExternalProcess
« Reply #8 on: 2014 January 07 02:14:48 »
This bug is now fixed in build 1073 of the PixInsight Core application, due for release in a few days.

As you probably have guessed, the problem was that the process' output channel data (either stdout or stderr, or combined channel data) was not being copied back to the caller's storage, and hence the returned ByteArray contained unpredictable garbage. This is now fixed and works as expected. Sorry for the trouble.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline NKV

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 677
Re: pcl::ExternalProcess
« Reply #9 on: 2014 January 07 04:11:39 »
Thank you!

Offline NKV

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 677
Re: pcl::ExternalProcess
« Reply #10 on: 2014 January 24 02:09:19 »
One more fighting with stdInput.

I want redirect PI Console command line to ExternalProcess stdInput. It's possible? How?

I ask you because pcl::Console::ReadChar()  function don't work.

PCL - PixInsight Class Library Version 2.0: This member function has not been implemented in the current PCL version. Calling it has not effect, and zero is always returned. 

How to get character or string from console?

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: pcl::ExternalProcess
« Reply #11 on: 2014 January 24 02:34:16 »
You can only redirect a process' stdin from a file; see ExternalProcess::RedirectStandardInput().

Obviously this is not what you want, or otherwise you wouldn't be asking for Console::ReadChar(). If you want your user to interact with a running external process through the process' stdin (for example, to answer the typical prompt "Are you sure (y/n)?"), then this is not possible. External processes must run without terminal interaction.

Let me know the specific process and task that you are trying to implement.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/