{
$Log: acs_cdrom.inc,v $
Revision 1.12  2006/08/31 20:10:56  z0m3ie
*** empty log message ***

Revision 1.11  2006/07/04 17:12:45  z0m3ie
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)

Revision 1.3  2006/01/03 15:37:51  z0m3ie
*** empty log message ***

Revision 1.2  2005/12/26 17:31:39  z0m3ie
fixed some problems in acs_dsfiles
fixed some problems in acs_vorbis
reworked all buffers

Revision 1.1  2005/12/19 18:35:16  z0m3ie
*** empty log message ***

Revision 1.4  2005/12/04 16:54:34  z0m3ie
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)

Revision 1.3  2005/10/02 16:51:46  z0m3ie
*** empty log message ***

Revision 1.2  2005/09/13 21:54:11  z0m3ie
acs is localizeable now (ACS_Strings)

Revision 1.1  2005/09/12 22:04:52  z0m3ie
modified structure again, fileformats are now in an sperat folder.
all File In/Out classes are capsulated from TFileIn and TFileOut

Revision 1.5  2005/09/09 21:33:43  z0m3ie
linux corrections

Revision 1.4  2005/09/08 22:19:00  z0m3ie
completed akrip based CDIn

Revision 1.3  2005/09/07 20:53:22  z0m3ie
begon to add MPEG and WMA support using DirectX

Revision 1.2  2005/09/04 17:59:38  z0m3ie
moving CDIn support to AKRip mostly
begon to add mpegin support for Win with mpg123

Revision 1.1  2005/08/25 20:18:00  z0m3ie
Version 2.4 restructure
TCDPlayer removed (fits not in component structure)
TMP3ToWavConverter removed (fits not in component structure)

}

type
  MSFAddr = array[0..3] of Byte;

  function Toc2MSF(t : MSFAddr) : TACSCDMSF;
  begin
    Result.Minute := t[1];
    Result.Second := t[2];
    Result.Frame := t[3];
  end;

  procedure TACSCDIn.OpenCD;
  var
    GetCD: GETCDHAND;
  begin
    with GetCD do
      begin
        Size := SizeOf(GETCDHAND);
        Ver := 1;
        ha := 0;
        tgt := FCurrentDrive;
        lun := 0;
        readType := CDR_ANY;
        jitterCorr := false;
        numJitter := 0;
        numOverlap := 0;
      end;
    FCDHandle := GetCDHandle(GetCD);
  end;

  procedure TACSCDIn.CloseCD;
  begin
    if FCDHandle <> 0 then
      CloseCDHandle(FCDHandle);
    FCDHandle := 0;
  end;

  function TACSCDIn.GetInfo : TACSCDInfo;
  var
    i : Integer;
  begin
    OpenCD;
    Result := cdiUnknown;
    ModifyCDParms(FCDHandle, CDP_MSF, DWORD(true));
    FillChar(FToc, SizeOf(FToc),0);
    if ReadTOC(FCDHandle, FTOC) <> 1 then
    begin
      Result := cdiNoDisc;
      Exit;
    end;
    for i := 0 to FToc.lastTrack-1 do
    begin
      if (FToc.Tracks[i].adr and $04) = 0 then
      begin
        case Result of
          cdiUnknown : Result := cdiDiscAudio;
          cdiDiscData : Result := cdiDiscMixed;
        end;
      end else
      begin
        case Result of
          cdiUnknown : Result := cdiDiscData;
          cdiDiscAudio : Result := cdiDiscMixed;
        end;
      end;
    end;
    CloseCD;
  end;

  function TACSCDIn.GetStatus : TACSCDStatus;
  var
    ms : Integer;
    AP : LongBool;
  begin
    if FPlaying then
      Result := cdsPlaying
    else if (GetInfo <> cdiNoDisc) and (GetInfo <> cdiUnknown) then
      Result := cdsReady
    else
      Result := cdsNotReady;
  end;

  function TACSCDIn.GetNumTracks : Integer;
  begin
    OpenCD;
    if FToc.lastTrack = 0 then
      begin
        ModifyCDParms(FCDHandle, CDP_MSF, DWORD(true));
        if ReadTOC(FCDHandle, FTOC) <> 1 then
          begin
            Result := -1;
            Exit;
          end;
      end;
    Result := FToc.lastTrack;
    CloseCD;
  end;

  FUNCTION TACSCDIn.GetTrackInfo(const vIndex : Integer) : TACSCDTrackInfo;
  VAR
    Frames: Integer;
    tmpmsf : TACSCDMSF;
  BEGIN
    IF Busy THEN
      RAISE EACSException.Create(strBusy);
    IF (vIndex IN [0..GetNumTracks-1]) = False THEN
      RAISE EACSException.Create(strTrackoutofrange);
    IF (FToc.Tracks[vIndex].adr and $04) = 0 THEN
      Result.TrackType := ttAudio
    ELSE
      Result.TrackType := ttData;
    Result.TrackStart.Minute := FToc.Tracks[vIndex].addr[1];
    Result.TrackStart.Second := FToc.Tracks[vIndex].addr[2];
    Result.TrackStart.Frame := FToc.Tracks[vIndex].addr[3];
    Frames := MSF2Frames(Toc2MSF(MSFAddr(FToc.Tracks[vIndex+1].addr)))-MSF2Frames(Toc2MSF(MSFAddr(FToc.Tracks[vIndex].addr)));
    Frames2MSF(Frames, Result.TrackLength);
  end;

  procedure TACSCDIn.SetST;
  begin
    if Self.Busy then raise EACSException.Create(strBusy);
    FStartTrack := Track;
    FStartPos.Track := FStartTrack;
    FillChar(FStartPos.MSF, SizeOf(FStartPos.MSF), 0);
  end;

  procedure TACSCDIn.SetET;
  begin
    if Self.Busy then raise EACSException.Create(strBusy);
    FEndTrack := Track;
    FEndPos.Track := FEndTrack+1;
    FillChar(FEndPos.MSF, SizeOf(FEndPos.MSF), 0);
  end;

  procedure TACSCDIn.SetSP;
  begin
    if Self.Busy then raise EACSException.Create(strBusy);
    FStartPos := Pos;
  end;

  procedure TACSCDIn.SetEP;
  begin
    if Self.Busy then raise EACSException.Create(strBusy);
    FEndPos := Pos;
    if Pos.Track = EndOfDisc.Track then FEndPos.Track := TracksCount + 1;
  end;

  function TACSCDIn.GetSize : Integer;
  var
    Sect1, Sect2 : Integer;
  begin
    if Busy then
    begin
      Result := FRipEnd-FRipStart*CD_FRAMESIZE_RAW;
      Exit;
    end;
    Sect1 := MSF2Frames(Toc2MSF(MSFAddr(FToc.tracks[FStartPos.Track].addr)));
    Sect1 := Sect1 + MSF2Frames(FStartPos.MSF);
    Sect2 := MSF2Frames(Toc2MSF(MSFAddr(FToc.tracks[FEndPos.Track].addr)));
    Sect2 := Sect2 + MSF2Frames(FEndPos.MSF);
    Result := (Sect2 - Sect1)*CD_FRAMESIZE_RAW;
  end;

  procedure TACSCDIn.Init;
  var
    Sect1, Sect2 : Integer;
  begin
    if Busy then raise EACSException.Create(strBusy);
    if Status = cdsNotReady then
      raise EACSException.Create(strDrivenotready);
    if (FStartPos.Track in [0..GetNumTracks-1]) = False then
      raise EACSException.Create(strTrackoutofRange);
    if Tracks[FStartPos.Track].TrackType = ttData then
      raise EACSException.Create(strnoAudioTreck);
    OpenCD;
    FSize := GetSize;
    FBusy := True;
    BufStart := 1;
    BufEnd := 0;
    FPosition := 0;
    Sect1 := MSF2Frames(Toc2MSF(MSFAddr(FToc.tracks[FStartPos.Track].addr)));
    Sect1 := Sect1 + MSF2Frames(FStartPos.MSF);
    Sect2 := MSF2Frames(Toc2MSF(MSFAddr(FToc.tracks[FEndPos.Track].addr)));
    Sect2 := Sect2 + MSF2Frames(FEndPos.MSF);
    FRipEnd := Sect2;
    FRipStart := Sect1;
    SetLength(FBuffer,(BUF_SIZE * CD_FRAMESIZE_RAW)+TRACKBUFEXTRA);
  end;

  procedure TACSCDIn.Flush;
  begin
    CloseCD;
    FBusy := False;
    Setlength(FBuffer,0);
    FBuffer := nil;
    FSize := 0;
  end;

  function TACSCDIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer;
  var
    Abort : LongBool;
    fnum : Integer;
  begin
    if not Busy then  raise EACSException.Create(strStreamnotOpen);
    if BufStart > BufEnd then //Buffer clear try to fill it
    begin
      BufStart := 1;
      Abort := False;
      if FRipEnd-FRipStart > BUF_SIZE then
        fNum := BUF_SIZE
      else
        fNum := FRipEnd-FRipStart;
      FiBuffer^.startFrame := FRipStart;
      FiBuffer^.numFrames := fNum;
      FiBuffer^.maxLen := FiBuffer^.numFrames * CD_FRAMESIZE_RAW;
      FiBuffer^.len := 0;
      FiBuffer^.status := 0;
      FiBuffer^.startOffset := 0;
      if ReadCDAudioLBA(FCDHandle,FiBuffer) = 1 then
        begin
          Inc(FRipStart,FiBuffer^.numFrames);
          BufEnd := FiBuffer^.len;
        end;
    end;
    if BufferSize < (BufEnd - BufStart + 1) then
      Result := BufferSize
    else
      Result := BufEnd - BufStart + 1;
    Move(FiBuffer^.buf[BufStart-1],Buffer^, Result);
    Inc(BufStart, Result);
    Inc(FPosition, Result);
  end;

  procedure TACSCDIn.SetCurrentDrive;
  begin
    if Value in [0..FCDList.num-1] then
      FCurrentDrive := Value;
    OpenCD;
    FillChar(FToc, SizeOf(FToc),0);
    ModifyCDParms(FCDHandle, CDP_MSF, DWORD(true));
    ReadTOC(FCDHandle, FTOC);
    CloseCD;
  end;

  function TACSCDIn.GetDrivesCount : Integer;
  begin
    Result := FCDList.num;
  end;

  function TACSCDIn.GetDriveName : string;
  begin
    Result := FCDList.Cd[FCurrentDrive].id;
  end;

  procedure TACSCDIn.Eject;
  begin
    if Busy then raise EACSException.Create(strBusy);
  end;

  procedure TACSCDIn.CloseTray;
  begin
  end;

  constructor TACSCDIn.Create;
  begin
    inherited Create(AOwner);
    AppPath := ExtractFilePath(ParamStr(0));
    if AppPath[length(AppPath)] <> '\' then AppPath := AppPath + '\';
    CDRIPInit(AppPath);
    if not (csDesigning in ComponentState) then
    if not CDRipLoaded then
      raise EACSException.Create(akriplib + ' could not be loaded.');
    FillChar(FCDList, SizeOf(FCDList),0);
    FCDList.max := MAXCDLIST;
    GetCDList(FCDList);
  end;

  destructor TACSCDIn.Destroy;
  begin
    if Busy then
      Flush;
    CloseCD;
    inherited Destroy;
  end;

