Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2010-12

send complex command to linux

10 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

ugaciaka

Hi,

this is an example of what I do
===================================================

procedure TfrmMain.btnConvertClick(Sender: TObject);
var
  enumFile : TStringsEnumerator;
  AProcess: TProcess;
  AStringList: TStringList;
begin
  enumFile := clbFile.Items.GetEnumerator;
  AProcess := TProcess.Create(nil);
  AStringList := TStringList.Create;
  while enumFile.MoveNext do
  begin
    AProcess.CommandLine := 'flac -cd /home/ugaciaka/prova/prova.flac
+ | lame -h -b 320 - /home/ugaciaka/prova.mp3';
    AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes];
    AProcess.Execute;
    AStringList.LoadFromStream(AProcess.Output);
    AStringList.SaveToFile('output.txt');
  end;
  AStringList.Free;
  AProcess.Free;
end;
====================================================================
but not function, *but* if I write
AProcess.CommandLine := 'firefox gmail.google.com';

my process running correctly firefox.

In first case output.exe is similar to only ouput "lame".

Any resolution?

tnx

ugaciaka

Reply by email

silvioprog
to ugaciaka

2010/12/18 ugaciaka

Show quoted text 20 lines
Hi, this is an example of what I do =================================================== procedure TfrmMain.btnConvertClick(Sender: TObject); var enumFile : TStringsEnumerator; AProcess: TProcess; AStringList: TStringList; begin enumFile := clbFile.Items.GetEnumerator; AProcess := TProcess.Create(nil); AStringList := TStringList.Create; while enumFile.MoveNext do begin AProcess.CommandLine := 'flac -cd /home/ugaciaka/prova/prova.flac + | lame -h -b 320 - /home/ugaciaka/prova.mp3';

Try:

AProcess.CommandLine := 'sh -c "flac -cd /home/ugaciaka/prova/prova.flac + |
lame -h -b 320 - /home/ugaciaka/prova.mp3"';

Tip:

http://code.google.com/p/lazsolutions/source/browse/trunk/Core/LSUtils.pas?r=177#34

Show quoted text 23 lines
AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes]; AProcess.Execute; AStringList.LoadFromStream(AProcess.Output); AStringList.SaveToFile('output.txt'); end; AStringList.Free; AProcess.Free; end; ==================================================================== but not function, *but* if I write AProcess.CommandLine := 'firefox gmail.google.com'; my process running correctly firefox. In first case output.exe is similar to only ouput "lame". Any resolution? tnx ugaciaka
Silvio Cl?cio, *programmer* *ObjectPascal* -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20101218/bcee50da/attachment.html>

Reply by email

Henry Vermaak
to ugaciaka: this is an example of what I do ===================================================…
ugaciaka wrote 19 lines
Hi, this is an example of what I do =================================================== procedure TfrmMain.btnConvertClick(Sender: TObject); var ?enumFile : TStringsEnumerator; ?AProcess: TProcess; ?AStringList: TStringList; begin ?enumFile := clbFile.Items.GetEnumerator; ?AProcess := TProcess.Create(nil); ?AStringList := TStringList.Create; ?while enumFile.MoveNext do ?begin ? ?AProcess.CommandLine := 'flac -cd /home/ugaciaka/prova/prova.flac + | lame -h -b 320 - /home/ugaciaka/prova.mp3';

The shell interprets the | operator, and you are not in a shell, so you have to do it yourself (or call the command through the shell, e.g. /bin/sh -c "command").

Henry

Reply by email

Andrew Haines
to ugaciaka: this is an example of what I do ===================================================…
ugaciaka wrote 37 lines
Hi, this is an example of what I do =================================================== procedure TfrmMain.btnConvertClick(Sender: TObject); var enumFile : TStringsEnumerator; AProcess: TProcess; AStringList: TStringList; begin enumFile := clbFile.Items.GetEnumerator; AProcess := TProcess.Create(nil); AStringList := TStringList.Create; while enumFile.MoveNext do begin AProcess.CommandLine := 'flac -cd /home/ugaciaka/prova/prova.flac + | lame -h -b 320 - /home/ugaciaka/prova.mp3'; AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes]; AProcess.Execute; AStringList.LoadFromStream(AProcess.Output); AStringList.SaveToFile('output.txt'); end; AStringList.Free; AProcess.Free; end; ==================================================================== but not function, *but* if I write AProcess.CommandLine := 'firefox gmail.google.com'; my process running correctly firefox. In first case output.exe is similar to only ouput "lame". Any resolution?

Hi,

I solved your issue using two TProcess instances:

===================
function Min(A, B: Integer): Integer;
begin
  if A > B then
    Result := B
  else
    Result := A;
end;
procedure TForm1.ConvertFile(AFile: String);
var
  Flac: TProcess;
  Lame: TProcess;
  NewFile: String;
  procedure PipeOutput;
  var
    Buffer: array[0..127] of byte;
    RCount: Integer;
  begin
    if Flac.Output.NumBytesAvailable > 0 then
    begin
      RCount := Flac.Output.Read(Buffer, Min(128,
Flac.Output.NumBytesAvailable));
      Lame.Input.Write(Buffer, RCount);
    end
    else
      Sleep(1);
  end;
begin
  NewFile := ExtractFileNameWithoutExt(AFile)+'.mp3';
  Flac := TProcess.Create(nil);
  Lame := TProcess.Create(nil);
  Flac.CommandLine := 'flac -cd '+ AFile;
  Lame.CommandLine := 'lame -h -b 320 - '+ NewFile;
  Flac.Options := [poUsePipes];
  Lame.Options := [poUsePipes];
  Flac.Execute;
  Lame.Execute;
  while Flac.Running or (Flac.Output.NumBytesAvailable > 0) do
    PipeOutput;
  Flac.Free;
  Lame.Free;
end;
=========================

Regards,

Andrew

Reply by email

ugaciaka
to Andrew Haines

2010/12/18 Andrew Haines :

Show quoted text 5 lines
On 12/18/10 13:49, ugaciaka wrote: > Hi, > > this is an example of what I do > ===================================================

@Andrew Haines
tnx and very beautiful solution :-D

Reply by email

Andrew Haines
to ugaciaka
ugaciaka wrote 11 lines
2010/12/18 Andrew Haines : > On 12/18/10 13:49, ugaciaka wrote: >> Hi, >> >> this is an example of what I do >> =================================================== @Andrew Haines tnx and very beautiful solution :-D --

You are welcome :)

I played with this a bit more the other day and added a progressbar that gets updated as the file is converted. Flac writes to stderr too and we can read this to get the progress percent.

regards

Andrew

====== code ========
procedure TForm1.ConvertFile(AFile: String);
var
  Flac: TProcess;
  Lame: TProcess;
  NewFile: String;
  Line: String;
  procedure FillStdErr;
  var
    Buf: Char;
    FPos, i: Integer;
  begin
    while Flac.Stderr.NumBytesAvailable > 0 do
    begin
      Flac.Stderr.Read(Buf,1);
      if Buf in  [#13, #10] then
        begin
          if Length(Line) > 0 then
            ListBox1.Items.Add(Line);
          FPos := Pos('%', Line);
          if FPos > 0 then
            begin
              i := FPos;
              while Line[i]  ' ' do
                dec (i);
              Line := Copy(Line, i, FPos-i);
              ProgressBar1.Position:=StrToInt(Line); // 0 to 100
representing percent
            end;
          Line := '';
          Application.ProcessMessages; // so progress bar is updated
        end
      else
        Line := Line + Buf;
    end;
  end;
  procedure PipeOutput;
  var
    Buffer: array[0..127] of byte;
    RCount: Integer;
  begin
    if Flac.Output.NumBytesAvailable > 0 then
    begin
      RCount := Flac.Output.Read(Buffer, Min(128,
Flac.Output.NumBytesAvailable));
      Lame.Input.Write(Buffer, RCount);
    end
    else
      Sleep(1);
    FillStdErr;
  end;
begin
  NewFile := ExtractFileNameWithoutExt(AFile)+'.mp3';
  Flac := TProcess.Create(nil);
  Lame := TProcess.Create(nil);
  Flac.CommandLine := 'flac -cd '+ AFile;
  Lame.CommandLine := 'lame -h -b 320 - '+ NewFile;
  Flac.Options := [poUsePipes];
  Lame.Options := [poUsePipes];
  Flac.Execute;
  Lame.Execute;
  while Flac.Running or (Flac.Output.NumBytesAvailable > 0) do
    PipeOutput;
  ListBox1.Items.Add(Line);
  Flac.Free;
  Lame.Free;
end;

Reply by email

Lukasz Sokol
to Andrew Haines

Hi, I know you're not the original author, but...

Andrew Haines wrote 89 lines
On 12/19/10 03:44, ugaciaka wrote: > 2010/12/18 Andrew Haines : >> On 12/18/10 13:49, ugaciaka wrote: >>> Hi, >>> >>> this is an example of what I do >>> =================================================== > > @Andrew Haines > tnx and very beautiful solution :-D > > -- You are welcome :) I played with this a bit more the other day and added a progressbar that gets updated as the file is converted. Flac writes to stderr too and we can read this to get the progress percent. regards Andrew ====== code ======== procedure TForm1.ConvertFile(AFile: String); var Flac: TProcess; Lame: TProcess; NewFile: String; Line: String; procedure FillStdErr; var Buf: Char; FPos, i: Integer; begin while Flac.Stderr.NumBytesAvailable > 0 do begin Flac.Stderr.Read(Buf,1); if Buf in [#13, #10] then begin if Length(Line) > 0 then ListBox1.Items.Add(Line); FPos := Pos('%', Line); if FPos > 0 then begin i := FPos; while Line[i] ' ' do dec (i); Line := Copy(Line, i, FPos-i); ProgressBar1.Position:=StrToInt(Line); // 0 to 100 representing percent end; Line := ''; Application.ProcessMessages; // so progress bar is updated end else Line := Line + Buf; end; end; procedure PipeOutput; var Buffer: array[0..127] of byte; RCount: Integer; begin if Flac.Output.NumBytesAvailable > 0 then begin RCount := Flac.Output.Read(Buffer, Min(128, Flac.Output.NumBytesAvailable)); Lame.Input.Write(Buffer, RCount); end else Sleep(1); FillStdErr; end; begin NewFile := ExtractFileNameWithoutExt(AFile)+'.mp3'; Flac := TProcess.Create(nil); Lame := TProcess.Create(nil); Flac.CommandLine := 'flac -cd '+ AFile; Lame.CommandLine := 'lame -h -b 320 - '+ NewFile; Flac.Options := [poUsePipes]; Lame.Options := [poUsePipes]; Flac.Execute; Lame.Execute;
// should this
while Flac.Running or (Flac.Output.NumBytesAvailable > 0) do PipeOutput;
// or can this not happen ? And if it can, is it dangerous ?
  Flac.Running = false;
  Flac.Output.NumBytesAvailable > 0
// maybe the above condition should be split and we should wait yntil Running=true :
   while not Flac.Running do
     Sleep(1);
   while (Flac.Output.NumBytesAvailable > 0) do
     PipeOutput;
// ?

Lukasz

Show quoted text 13 lines
ListBox1.Items.Add(Line); Flac.Free; Lame.Free; end; -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Lukasz Sokol
to Andrew Haines: You are welcome :) I played with this a bit more the other day and added a progressbar…

Very Nice, can I ask, just:

On 21/12/2010 20:29, Andrew Haines wrote:
[...]

Show quoted text 66 lines
====== code ======== procedure TForm1.ConvertFile(AFile: String); var Flac: TProcess; Lame: TProcess; NewFile: String; Line: String; procedure FillStdErr; var Buf: Char; FPos, i: Integer; begin while Flac.Stderr.NumBytesAvailable > 0 do begin Flac.Stderr.Read(Buf,1); if Buf in [#13, #10] then begin if Length(Line) > 0 then ListBox1.Items.Add(Line); FPos := Pos('%', Line); if FPos > 0 then begin i := FPos; while Line[i] ' ' do dec (i); Line := Copy(Line, i, FPos-i); ProgressBar1.Position:=StrToInt(Line); // 0 to 100 representing percent end; Line := ''; Application.ProcessMessages; // so progress bar is updated end else Line := Line + Buf; end; end; procedure PipeOutput; var Buffer: array[0..127] of byte; RCount: Integer; begin if Flac.Output.NumBytesAvailable > 0 then begin RCount := Flac.Output.Read(Buffer, Min(128, Flac.Output.NumBytesAvailable)); Lame.Input.Write(Buffer, RCount); end else Sleep(1); FillStdErr; end; begin NewFile := ExtractFileNameWithoutExt(AFile)+'.mp3'; Flac := TProcess.Create(nil); Lame := TProcess.Create(nil); Flac.CommandLine := 'flac -cd '+ AFile; Lame.CommandLine := 'lame -h -b 320 - '+ NewFile; Flac.Options := [poUsePipes]; Lame.Options := [poUsePipes]; Flac.Execute; Lame.Execute;

[1]

while Flac.Running or (Flac.Output.NumBytesAvailable > 0) do PipeOutput;

Can this conditon happen to hit

Flac.Running=False
..NumBytesAvailable > 0 (it'll probably be some garbage, but still)

and would it be dangerous if so it happened ?

Maybe another
    while not Flac.Running do
      begin
	Sleep(1);
	Application.ProcessMessages; // or even without this one
      end;

be put at [1] ?

Lukasz

Show quoted text 6 lines
ListBox1.Items.Add(Line); Flac.Free; Lame.Free; end;

Reply by email

Andrew Haines
to Lukasz Sokol
Lukasz Sokol wrote 13 lines
Very Nice, can I ask, just: [1] > while Flac.Running or (Flac.Output.NumBytesAvailable > 0) do > PipeOutput; > Can this conditon happen to hit Flac.Running=False ..NumBytesAvailable > 0 (it'll probably be some garbage, but still)

No. Flac.Output is not initialized until Flac.Execute has succeded. As soon as Flac.Execute is called Flac.Running = true unless an error occurred.

I did while loop like that in case Flac stopped running but we hadn't finished reading all it's data.

Show quoted text 12 lines
and would it be dangerous if so it happened ? Maybe another while not Flac.Running do begin Sleep(1); Application.ProcessMessages; // or even without this one end; be put at [1] ?

This *could* cause an inescapable loop if for instance flac exited before this was reached because we gave it some wrong options.

A safer example would be:

begin
  Flac := TProcess.Create(nil);
  Flac.Commandline := 'flac <some options>';
  Flac.Options = [poUsePipes];
  try
    Flac.Execute; // this will raise an exception if it
                  // cannot find or execute the command
  except
    ShowMessage('Error running Flac! Command Not Found');
  end;
  if not Flac.Running then
  begin
    // this will happen if flac ran but encountered
    // problems
    if Flax.ExitStatus  0 then
      ShowMessage('Flac exited with an error: ' +
IntToStr(Flac.ExitStatus));
  end
  else // Flac ran and has already finished with some data or is still
running
  begin
    While Flac.Running or (Flac.Output.NumBytesAvailable > 0) do
      PipeOutput;
  end;
  Flac.Free;
end;

Hope this clears things up :)

Regards,

Andrew

PS I didn't compile that so ther may be an error or three :)

Reply by email

Andrew Haines
to Lukasz Sokol: Hi, I know you're not the original author, but... // should this // or can this not…
Lukasz Sokol wrote 8 lines
Hi, I know you're not the original author, but... // should this > while Flac.Running or (Flac.Output.NumBytesAvailable > 0) do > PipeOutput; > // or can this not happen ? And if it can, is it dangerous ?

It's my understanding that when Process.Execute returns, Process.Running is true. If it's False after Process.Execute is called then it has already run and exited cleanly or uncleanly which can be checked with Process.ExitStatus.

Some more info On TProcess can be found here:
http://wiki.lazarus.freepascal.org/Executing_External_Programs

See the "Reading Large Output" section on why it can be important to read data while the process is running rather than waiting until the end.

Somebody please correct me if I said anything that's incorrect.

Regards,

Andrew

Reply by email