unit _oggenc;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, _wavesout_const,_ID3_const;

{$WARN UNIT_PLATFORM OFF}
{$WARN SYMBOL_PLATFORM OFF}

type
  Toggenc = class
  private
    { Private 宣言 }
    function GrabStdOut(ExeName,CommandLine:string):string;
  public
    { Public 宣言 }
    constructor Create;
    destructor Destroy; override;
    procedure Init;
    procedure FreeDLL;
    procedure Execute(WaveFilename:string;MPPSetting:TMPPSetting;Title:string;ID3:TID3);
  end;

implementation

uses oggencPrgDlg,
     _const;

procedure writelog(msg:string);
var
  fn:string;
  fs:TFileStream;
  tmp:string;
begin
  fn:=StartPath+'oggenc.log';

  if FileExists(fn)=True then begin
    fs:=TFileStream.Create(fn,fmOpenReadWrite or fmShareDenyWrite);
    end else begin
    fs:=TFileStream.Create(fn,fmCreate or fmShareDenyWrite);
  end;

  tmp:=msg+CRLF;
  fs.Position:=fs.Size;
  fs.WriteBuffer(tmp[1],length(tmp));
  fs.Free;
end;

constructor Toggenc.Create;
begin
  inherited Create;
end;

destructor Toggenc.Destroy;
begin
  inherited Destroy;
end;

procedure Toggenc.Init;
begin
end;

procedure Toggenc.FreeDLL;
begin
end;

procedure Toggenc.Execute(WaveFilename:string;MPPSetting:TMPPSetting;Title:string;ID3:TID3);
var
  param:string;
  procedure ChgChar(var str:string;src:string;dst:string);
  var
    p:integer;
  begin
    if (str='') or (src='') or (dst='') then exit;
    p:=AnsiPos(src,str);
    while (p<>0) do begin
      str:=copy(str,1,p-1)+dst+copy(str,p+1,length(str));
      p:=AnsiPos(src,str);
    end;
  end;
  procedure ChgChars(var str:string);
  begin
    ChgChar(str,'"','”');
    ChgChar(str,'*','＊');
    ChgChar(str,',','，');
    ChgChar(str,'/','／');
    ChgChar(str,':','：');
    ChgChar(str,';','；');
    ChgChar(str,'<','＜');
    ChgChar(str,'>','＞');
    ChgChar(str,'?','？');
    ChgChar(str,'\','￥');
    ChgChar(str,'|','｜');
  end;
  function Delete0DOnly(str:string):string;
  var
    p:integer;
  begin
    Result:='';
    str:=str+' ';
    p:=AnsiPos(char($0d),str);
    while (p<>0) do begin
      if str[p+1]=char($0a) then begin
        Result:=Result+copy(str,1,p-1)+CRLF;
        str:=copy(str,p+2,length(str));
        end else begin
        str:=copy(str,p+1,length(str));
      end;
      p:=AnsiPos(char($0d),str);
    end;
  end;
begin
  ChgChars(Title);

  with ID3 do begin
    ChgChars(Title);
    ChgChars(Artist);
    ChgChars(Album);
    ChgChars(Comment);
    ChgChars(Year);
    ChgChars(ID);
  end;

  writelog('StartEncord ['+formatdatetime('yyyy/mm/dd hh:nn:ss',now)+'] ------------------ ');
  writelog('');

  param:=GetOggCommandLine(MPPSetting,Title,ID3,False,WaveFilename);
  writelog('oggenc.exe '+param);
  writelog('');

  param:='"'+StartPath+'oggenc.exe" '+GetOggCommandLine(MPPSetting,Title,ID3,True,WaveFilename);

  Application.CreateForm(ToggencPrg, oggencPrg);
  oggencPrg.Show;
  writelog(Delete0DOnly(GrabStdOut(StartPath+'oggenc.exe',param)));
  oggencPrg.Close;
  oggencPrg.Release;

  DeleteFile(WaveFilename);
end;

function Toggenc.GrabStdOut(ExeName,CommandLine:string):string;
var
  hReadPipe, hWritePipe: THandle;
  hStdInReadPipe, hStdInWritePipe, hStdInWritePipeDup: THandle;
  hErrReadPipe, hErrWritePipe: THandle;
  sa: TSecurityAttributes;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  bufOut:string;
  dwOut, dwRet: DWord;
begin
  Result := '';

  with sa do
  begin
    nLength := sizeof(TSecurityAttributes);
    lpSecurityDescriptor := nil;
    bInheritHandle := true;
  end;

  hReadPipe := 0; hWritePipe := 0;
  hErrReadPipe := 0; hErrWritePipe := 0;

  CreatePipe(hStdInReadPipe, hStdInWritePipe, @sa, 8192);
  DuplicateHandle(GetCurrentProcess(), hStdInWritePipe, GetCurrentProcess(),
                  @hStdInWritePipeDup, 0, false, DUPLICATE_SAME_ACCESS);
  CloseHandle(hStdInWritePipe);

  CreatePipe(hReadPipe, hWritePipe, @sa, 8192);
  try
    CreatePipe(hErrReadPipe, hErrWritePipe, @sa, 8192);
    try
      ZeroMemory(@StartupInfo, sizeof(TStartupInfo));
      with StartupInfo do
      begin
        cb := sizeof(TStartupInfo);
        dwFlags := STARTF_USESTDHANDLES;
        // これがないと DOS 窓が表示されてしまう
        wShowWindow := SW_HIDE;
        // 標準 IO にパイプの端っこを指定してやる
        hStdInput := hStdInReadPipe;
        hStdOutput := hWritePipe;
        hStdError  := hErrWritePipe;
      end;

      // コンソールアプリ起動
      if CreateProcess(PChar(ExeName), PChar(CommandLine), @sa, nil, true, DETACHED_PROCESS,
                      nil, nil, StartupInfo, ProcessInfo) = true then begin
        try
          repeat
            Sleep(50);

            dwOut:=1;
            while (dwOut<>0) do begin
              PeekNamedPipe(hErrReadPipe, nil, 0, nil, @dwOut, nil);
              if (dwOut > 0) then
              begin
                SetLength(bufOut,8192);
                ReadFile(hErrReadPipe, bufOut[1], Length(bufOut) - 2, dwOut, nil);
                SetLength(bufOut, dwOut);
                oggencPrg.DrawText(bufOut);
                Result:=Result+bufOut;
              end;
            end;

            dwRet := WaitForSingleObject(ProcessInfo.hProcess, 0);
          until (dwRet = WAIT_OBJECT_0);        // コンソールアプリのプロセスが存在している間
        finally
          CloseHandle(ProcessInfo.hProcess);
          CloseHandle(ProcessInfo.hThread);
        end;
      end;
    finally
      CloseHandle(hStdInWritePipeDup);
      CloseHandle(hErrReadPipe);
      CloseHandle(hErrWritePipe);
    end;
  finally
    CloseHandle(hReadPipe);
    CloseHandle(hWritePipe);
  end;
  CloseHandle(hStdInReadPipe);
end;

end.
