unit threadedencode;

interface

uses
  Classes,lamenc_nice_interface,windows,id3,sysutils,global,forms;

type
  tmp3encode = class(TThread)
  private
    { Private declarations }
   mes : string;
   c : dword;
   cmax : integer;
   size : dword;
   ftracknumber : integer;
   finfile, foutfile : string;
   ftrackname,falbumname,fartistname : string;
   ffinished : boolean;
  protected

    procedure Execute; override;
    procedure log;
    procedure setprogsize;
    procedure stopmpifnec;
    procedure progvis;
    procedure prognotvis;
    procedure writethetag;
  public
  property tracknumber  : integer read ftracknumber write ftracknumber;
  property infile : string read finfile write finfile;
  property outfile : string read foutfile write foutfile;
  property trackname : string read ftrackname write ftrackname;
  property albumname : string read falbumname write falbumname;
  property artistname : string read fartistname write fartistname;
  property finished : boolean read ffinished;
  property position : dword read c write c;
  end;

implementation
uses empripmain,main,jukeboxform;

{ Important: Methods and properties of objects in VCL can only be used in a
  method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure mp3encode.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ mp3encode }

procedure tmp3encode.writethetag;
var
ti : tid3tag;
begin
   ti.track:=ftrackname;
   ti.artist:=fartistname;
   ti.album:=falbumname;
   ti.genre:=#0#0;
   ti.field:='TAG';
   writetag(foutfile,ti);
end;


procedure tmp3encode.progvis;
begin
//ripmain.encprogress.visible:=true;
end;


procedure tmp3encode.prognotvis;
begin
//ripmain.encprogress.visible:=false;
//ripmain.encprogress.position:=1;
//ripmain.encprogress.max:=1;

end;

procedure tmp3encode.stopmpifnec;
var
key : word;
o : thandle;
begin
if uppercase(mainform.mp.filename)=uppercase(foutfile) then  begin
   logent('Track in use, rejecting current track');
   {mainform.stopclick(nil);
   mainform.mp.close;
   mainform.mp.filename:=cachepath+'\blank.mp3';
   mainform.mp.open;}
   key:=VK_MULTIPLY;
   jukebox.FormKeydown(nil,key,[]);

   o:=CreateFile(pchar(foutfile),GENERIC_READ,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,FILE_FLAG_SEQUENTIAL_SCAN);
   if o=INVALID_HANDLE_VALUE  then begin
      mainform.mp.close;
      mainform.mp.filename:=cachepath+'\blank.mp3';
      mainform.mp.open;
      end else closehandle(o);
   end;
end;


procedure tmp3encode.log;
begin
logent('    '+mes);
end;



procedure tmp3encode.setprogsize;
begin
//ripmain.encprogress.position:=0;
//ripmain.encprogress.max:=cmax;
end;


procedure tmp3encode.Execute;
var
hand : THBESTREAM;
bc : Tbeconfig;
bufsize,samples : dword;
ibuf,obuf : pointer;
written : dword;
i,o : thandle;
res : dword;
done : dword;
IsWritten,toread,isread : dword;
success : boolean;
progressunit : real;
tknm : integer;
begin
returnvalue:=0;
progressunit:=0;



ffinished:=false;
success:=true;

tknm:=ftracknumber;

mes:='Encoding data for track '+inttostr(tknm)+' "'+ftrackname+'"';
synchronize(log);


i:=createfile(pchar(finfile),GENERIC_READ,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_TEMPORARY,0);

if (i=INVALID_HANDLE_VALUE) then begin
mes:='Error opening extracted wave file:'+finfile;
synchronize(log);
//cancelop:=true;
ffinished:=true;
synchronize(prognotvis);
exit;
end;


//Check mp does not have file and close if necesay

synchronize(stopmpifnec);

o:=CreateFile(pchar(foutfile),GENERIC_WRITE,0,nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);


if (o=INVALID_HANDLE_VALUE) then begin
mes:='Error creating output file:'+finfile;
synchronize(log);
//cancelop:=true;
ffinished:=true;
closehandle(i);
synchronize(prognotvis);
exit;
end;




bc.format.dwconfig:=BE_CONFIG_MP3;
bc.format.mp3.dwSampleRate:=44100;
bc.format.mp3.byMode:=BE_MP3_MODE_STEREO;
bc.format.mp3.wbitrate:=config.bitrate;
bc.format.mp3.bcopyright:=false;
bc.format.mp3.bCRC:=true;
bc.format.mp3.bOriginal:=false;
bc.format.mp3.bPrivate:=false;
res:=beInitStream(bc,samples,bufsize,hand);
if res=BE_ERR_SUCCESSFUL then begin
getmem(ibuf,(bufsize*2));
getmem(obuf,(samples*2));


size:=getfilesize(i,nil);
cmax:=100;
if size<>0 then progressunit := cmax / size;


c:=0;
synchronize(setprogsize);
synchronize(progvis);
done:=0;


while(done<>size) do begin
   if (done+(samples*2)<size) then toread:=samples*2 else toRead:=size-done;
   readfile(i,ibuf^,toRead,isRead,nil);


   //isRead:=i.Read(ibuf^,toRead);

   if isread<>toread then begin
      mes:='Error reading input file: "'+ftrackname;
      synchronize(log);
      success:=false;
      break;
   end;

   if beEncodeChunk(hand,(toread div 2),ibuf,obuf,written) <> BE_ERR_SUCCESSFUL then begin
      mes:='Error encoding data: track '+inttostr(tknm)+' "'+ftrackname+'"';
      synchronize(log);
      success:=false;
      break;
     end;

     WriteFile(o,obuf^,written,IsWritten,nil);


   if terminated=true then begin
      mes:='Aborting encoding data: "'+ftrackname+'"';
      synchronize(log);
      success:=false;
      break;
   end;

   //IsWritten:=o.Write(obuf^,written);
  //Combing signed and unisigned error so typecast to dword
  if IsWritten<>dword(written) then begin
      mes:='Error writing output file: "'+ftrackname+'"';
      synchronize(log);
      success:=false;
      break;
   end;

   done:=done+toread;

   c:=round(done*progressunit);
  end;

beDeinitStream(hand,obuf,written);
WriteFile(o,obuf^,written,dword(IsWritten),nil);
beCloseStream(hand);


freemem(ibuf);
freemem(obuf);




if success=false then begin
   mes:='Aborted encoding data for '+inttostr(tknm)+' "'+ftrackname+'"';
   synchronize(log);
end;

ffinished:=true;
end else begin
mes:='Error Initalizing Encoder';
synchronize(log);
end;


c:=cmax;


closehandle(o);
closehandle(i);
//Tag MP3 files
if success=true then begin
   synchronize(writethetag);
end;

deletefile(finfile);
if success=false then deletefile(foutfile);

synchronize(prognotvis);

c:=0;
ffinished:=true;

end;

end.