unit playunit;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
var
strOutput: String;
lstStatus: TStringList;
procedure Play(filename: string; PlayDone: TNotifyEvent = nil; TerminateProcess: boolean = true; CommandLineApp: string = '');
procedure StopPlaying;
implementation
uses
process, TZXTools;
var
StopPlay: boolean = false;
AppClosing: boolean = false;
type
TPlayThread = class(TThread)
private
procedure Done;
procedure ShowStatus;
protected
procedure Execute; override;
public
FOnPlayDone: TNotifyEvent;
FFilename: string;
FCommandLineApp: string;
FTerminateProcess: boolean;
constructor Create(const filename: string; PlayDone: TNotifyEvent = nil;
TerminateProcess: boolean = true; CommandLineApp: string = '');
end;
{ TPlayThread }
constructor TPlayThread.Create(const filename: string; PlayDone: TNotifyEvent;
TerminateProcess: boolean; CommandLineApp: string);
begin
FOnPlayDone := PlayDone;
FTerminateProcess := TerminateProcess;
FFilename := filename;
FCommandLineApp := CommandLineApp;
inherited create(false);
FreeOnTerminate := true;
end;
procedure TPlayThread.Done;
begin
if assigned(FOnPlayDone) then
FOnPlayDone(self);
end;
// Will play back the TZX in a thread to not block the UI
procedure TPlayThread.ShowStatus;
begin
TZXTools.strLastStatus := strOutput;
end;
procedure TPlayThread.Execute;
var
PlayProc: TProcess;
OutputStream : TStream;
BytesRead : longint;
Buffer : array[1..2048] of byte;
begin
PlayProc := TProcess.create(nil);
try
PlayProc.executable := FCommandLineApp;
PlayProc.parameters.add('-v');
PlayProc.parameters.add(FFilename);
PlayProc.Options := [poUsePipes, poNoConsole];
PlayProc.execute;
// Create a stream object to store the generated output in
OutputStream := TMemoryStream.Create;
lstStatus := TStringList.Create;
while PlayProc.Running do begin
if StopPlay or AppClosing then begin
if StopPlay or FTerminateProcess then
PlayProc.terminate(1);
exit;
end
else
// Poll the buffer
BytesRead := PlayProc.Output.Read(Buffer, 2048); // Read the buffer
// Add the bytes that were read to the stream for later usage
OutputStream.Write(Buffer, BytesRead);
// Read what's in the buffer
OutputStream.Position := 0;
lstStatus.LoadFromStream(OutputStream);
strOutput := lstStatus.Text;
// Update status
synchronize(@Showstatus);
sleep(1);
end;
finally
// *** Below works fine to get output after playback has finished
// *** However I need to get output as playback proceeds
// Create a stream object to store the generated output in
{*OutputStream := TMemoryStream.Create;
lstStatus := TStringList.Create;
repeat
// Poll the buffer
BytesRead := PlayProc.Output.Read(Buffer, 2048); // Read the buffer
// Add the bytes that were read to the stream for later usage
OutputStream.Write(Buffer, BytesRead);
until BytesRead = 0;
// Read what's in the buffer
OutputStream.Position := 0;
lstStatus.LoadFromStream(OutputStream);
strOutput := lstStatus.Text;
// Update status
synchronize(@Showstatus);*}
// Clean up
PlayProc.free;
OutputStream.Free;
lstStatus.Free;
if assigned(FOnPlayDone) and not AppClosing then
synchronize(@Done);
end;
end;
procedure Play(filename: string; PlayDone: TNotifyEvent; TerminateProcess: boolean; CommandLineApp: string);
begin
StopPlay := false;
TPlayThread.create(filename, PlayDone, TerminateProcess, CommandLineApp);
end;
procedure StopPlaying;
begin
StopPlay := true;
end;
finalization
AppClosing := true;
end.