385 lines
9.7 KiB
PHP
385 lines
9.7 KiB
PHP
{
|
|
$Log: acs_cdrom.inc,v $
|
|
Revision 1.7 2006/08/31 20:10:56 z0m3ie
|
|
*** empty log message ***
|
|
|
|
Revision 1.6 2006/07/04 17:12:45 z0m3ie
|
|
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
|
|
|
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
|
|
|
|
}
|
|
|
|
function GetTocEntry(cd_fd, Track : Integer): TACSCDTrackInfo;
|
|
var
|
|
Entry : cdrom_tocentry;
|
|
toc : cdrom_tochdr;
|
|
frames1, frames2 : Integer;
|
|
begin
|
|
fpioctl(cd_fd, CDROMREADTOCHDR, @toc);
|
|
Entry.cdte_format := CDROM_MSF;
|
|
Entry.cdte_track := Track+toc.cdth_trk0-1;
|
|
fpioctl(cd_fd, CDROMREADTOCENTRY, @Entry);
|
|
frames1 := MSF2Frames(TACSCDMSF(Entry.cdte_addr.msf));
|
|
if (Entry.cdte_adr_ctrl and CDROM_DATA_TRACK) <> 0 then
|
|
Result.TrackType := ttData
|
|
else Result.TrackType := ttAudio;
|
|
if Entry.cdte_track < toc.cdth_trk1 then Inc(Entry.cdte_track)
|
|
else Entry.cdte_track := CDROM_LEADOUT;
|
|
fpioctl(cd_fd, CDROMREADTOCENTRY, @Entry);
|
|
frames2 := MSF2Frames(TACSCDMSF(Entry.cdte_addr.msf));
|
|
Frames2MSF(frames2-frames1, Result.TrackLength);
|
|
end;
|
|
|
|
function GetCDStatus(cd_fd : Integer) : TACSCDStatus;
|
|
(* not all drivers support the CDROM_DRIVE_STATUS ioctl
|
|
we use this ioctl first and then some other tecnique
|
|
if it is not supported. *)
|
|
var
|
|
sci : cdrom_subchnl;
|
|
res :Integer;
|
|
Data: Integer;
|
|
begin
|
|
Data := CDSL_CURRENT;
|
|
res := fpioctl(cd_fd, CDROM_DRIVE_STATUS, @Data);
|
|
case res of
|
|
CDS_TRAY_OPEN, CDS_NO_DISC, CDS_DRIVE_NOT_READY:
|
|
begin
|
|
Result := cdsNotReady;
|
|
Exit;
|
|
end;
|
|
end;
|
|
(* Either the disc is ok or no information
|
|
from the driver. Trying CDROMSUBCHNL.*)
|
|
sci.cdsc_format := CDROM_MSF;
|
|
if fpioctl(cd_fd, CDROMSUBCHNL, @sci) < 0 then
|
|
begin
|
|
Result := cdsNotReady;
|
|
Exit;
|
|
end;
|
|
case sci.cdsc_audiostatus of
|
|
CDROM_AUDIO_PLAY : Result := cdsPlaying;
|
|
CDROM_AUDIO_PAUSED : Result := cdsPaused;
|
|
CDROM_AUDIO_ERROR : Result := cdsNotReady;
|
|
else Result := cdsReady;
|
|
end;
|
|
end;
|
|
|
|
function GetCDInfo(cd_fd : Integer) : TACSCDInfo;
|
|
var
|
|
res : Integer;
|
|
Data: Integer;
|
|
begin
|
|
Result := cdiUnknown;
|
|
Data := CDSL_CURRENT;
|
|
res := fpioctl(cd_fd, CDROM_DRIVE_STATUS, @Data);
|
|
case res of
|
|
CDS_TRAY_OPEN, CDS_NO_DISC: Result := cdiNoDisc;
|
|
CDS_DISC_OK :
|
|
begin
|
|
res := fpioctl(cd_fd, CDROM_DISC_STATUS, @Data);
|
|
case res of
|
|
CDS_AUDIO : Result := cdiDiscAudio;
|
|
CDS_MIXED : Result := cdiDiscMixed;
|
|
else Result := cdiDiscData;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TACSCDIn.OpenCD;
|
|
begin
|
|
if FCurrentDrive >= length(DrivesPaths) then
|
|
exit;
|
|
if FOpened = 0 then
|
|
begin
|
|
_cd_fd := fpopen(PChar(DrivesPaths[FCurrentDrive]), O_RDONLY or O_NONBLOCK);
|
|
if _cd_fd < 0 then
|
|
raise EACSException.Create(IntToStr(errno));
|
|
end;
|
|
Inc(FOpened);
|
|
end;
|
|
|
|
|
|
procedure TACSCDIn.CloseCD;
|
|
begin
|
|
if FOpened = 1 then fpclose(_cd_fd);
|
|
if FOpened > 0 then Dec(FOpened);
|
|
end;
|
|
|
|
function TACSCDIn.GetInfo;
|
|
begin
|
|
if Busy then raise EACSException.Create(strBusy);
|
|
OpenCD;
|
|
Result := GetCDInfo(_cd_fd);
|
|
CloseCD;
|
|
end;
|
|
|
|
function TACSCDIn.GetStatus;
|
|
begin
|
|
if FCurrentDrive >= length(DrivesPaths) then
|
|
exit;
|
|
if Busy then raise EACSException.Create(strBusy);
|
|
if Fopened = 0 then
|
|
_cd_fd := fpopen(PChar(DrivesPaths[FCurrentDrive]), O_RDONLY or O_NONBLOCK);
|
|
if _cd_fd < 0 then
|
|
begin
|
|
Result := cdsNotReady;
|
|
Exit;
|
|
end;
|
|
Inc(FOpened);
|
|
Result := GetCDStatus(_cd_fd);
|
|
CloseCD;
|
|
end;
|
|
|
|
function TACSCDIn.GetNumTracks;
|
|
var
|
|
toc : cdrom_tochdr;
|
|
begin
|
|
if Busy then raise EACSException.Create(strBusy);
|
|
OpenCD;
|
|
if GetStatus <> cdsNotReady then
|
|
begin
|
|
fpioctl(_cd_fd, CDROMREADTOCHDR, @toc);
|
|
Result := toc.cdth_trk1 - toc.cdth_trk0 + 1;
|
|
end else Result := 0;
|
|
CloseCD;
|
|
end;
|
|
|
|
function TACSCDIn.GetTrackInfo;
|
|
begin
|
|
if Busy then raise EACSException.Create(strBusy);
|
|
OpenCD;
|
|
if (vIndex in [1..GetNumTracks]) = False then
|
|
begin
|
|
fpclose(_cd_fd);
|
|
FOpened := 0;
|
|
raise EACSException.Create(strTrackOutofRange);
|
|
end;
|
|
Result := GetTocEntry(_cd_fd, vIndex);
|
|
CloseCD;
|
|
end;
|
|
|
|
function GetTrackMSF(cd_fd, Track : Integer) : TACSCDMSF;
|
|
var
|
|
entry : cdrom_tocentry;
|
|
hdr : cdrom_tochdr;
|
|
begin
|
|
fpioctl(cd_fd, CDROMREADTOCHDR, @hdr);
|
|
entry.cdte_format := CDROM_MSF;
|
|
entry.cdte_track := Track + hdr.cdth_trk0 - 1;
|
|
if entry.cdte_track > hdr.cdth_trk1 then
|
|
entry.cdte_track := CDROM_LEADOUT;
|
|
fpioctl(cd_fd, CDROMREADTOCENTRY, @entry);
|
|
Result := TACSCDMSF(entry.cdte_addr.msf);
|
|
end;
|
|
|
|
function GetPosMSF(cd_fd : Integer; Pos : TACSCDPosition) : TACSCDMSF;
|
|
var
|
|
msf1 : TACSCDMSF;
|
|
frames : Integer;
|
|
begin
|
|
msf1 := TACSCDMSF(GetTrackMSF(cd_fd, Pos.Track));
|
|
frames := MSF2Frames(msf1);
|
|
frames := frames + MSF2Frames(Pos.MSF);
|
|
Frames2MSF(frames, msf1);
|
|
Result := msf1;
|
|
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;
|
|
OpenCD;
|
|
FEndPos.Track := FEndTrack + 1;
|
|
FillChar(FEndPos.MSF, SizeOf(FEndPos.MSF), 0);
|
|
CloseCD;
|
|
end;
|
|
|
|
procedure TACSCDIn.SetSP;
|
|
begin
|
|
if Self.Busy then raise EACSException.Create(strBusy);
|
|
Self.FStartPos := Pos;
|
|
end;
|
|
|
|
procedure TACSCDIn.SetEP;
|
|
begin
|
|
if Self.Busy then raise EACSException.Create(strBusy);
|
|
Self.FEndPos := Pos;
|
|
end;
|
|
|
|
constructor TACSCDIn.Create;
|
|
begin
|
|
inherited Create(AOwner);
|
|
FCurrentDrive := 0;
|
|
end;
|
|
|
|
function TACSCDIn.GetSize;
|
|
var
|
|
msf1, msf2 : TACSCDMSF;
|
|
begin
|
|
if Busy then raise EACSException.Create(strBusy);
|
|
OpenCD;
|
|
msf1 := GetPosMSF(_cd_fd, FStartPos);
|
|
msf2 := GetPosMSF(_cd_fd, FEndPos);
|
|
CloseCD;
|
|
Result := ((msf2.minute*60 + msf2.second)*75 + msf2.frame -
|
|
((msf1.minute*60 + msf1.second)*75 + msf1.frame))*CD_FRAMESIZE_RAW;
|
|
end;
|
|
|
|
procedure TACSCDIn.Init;
|
|
begin
|
|
if Busy then raise EACSException.Create(strBusy);
|
|
if not (DiscInfo in [cdiDiscAudio, cdiDiscMixed]) then
|
|
raise EACSException.Create(strNoAudioCD);
|
|
FSize := GetSize;
|
|
FBusy := True;
|
|
BufStart := 1;
|
|
BufEnd := 0;
|
|
FPosition := 0;
|
|
OpenCD;
|
|
FCurPos := GetPosMSF(_cd_fd, FStartPos);
|
|
FEndMSF := GetPosMSF(_cd_fd, FEndPos);
|
|
// GetMem(FBuffer,BUF_SIZE * CD_FRAMESIZE_RAW);
|
|
end;
|
|
|
|
procedure TACSCDIn.Flush;
|
|
begin
|
|
CloseCD;
|
|
FBusy := False;
|
|
// FreeMem(FBuffer);
|
|
FSize := 0;
|
|
end;
|
|
|
|
function TACSCDIn.GetData;
|
|
var
|
|
StartFrame, EndFrame : Integer;
|
|
cdaudio : cdrom_read_audio;
|
|
begin
|
|
if not Busy then raise EACSException.Create(strStreamnotopen);
|
|
StartFrame := MSF2Frames(FCurPos);
|
|
EndFrame := MSF2Frames(FEndMSF);
|
|
if BufStart > BufEnd then
|
|
begin
|
|
if EndFrame = StartFrame then
|
|
begin
|
|
Result := 0;
|
|
Exit;
|
|
end;
|
|
BufStart := 1;
|
|
if (EndFrame - StartFrame) > (BUF_SIZE) then
|
|
cdaudio.nframes := BUF_SIZE
|
|
else
|
|
cdaudio.nframes := EndFrame - StartFrame;
|
|
cdaudio.addr_format := CDROM_MSF;
|
|
cdaudio.addr.msf := cdrom_msf0(FCurPos);
|
|
cdaudio.buf := Pointer(FBuffer);
|
|
fpioctl(_cd_fd, CDROMREADAUDIO, @cdaudio);
|
|
BufEnd := cdaudio.nframes * CD_FRAMESIZE_RAW;
|
|
StartFrame := MSF2Frames(FCurPos) + cdaudio.nframes;
|
|
Frames2MSF(StartFrame, FCurPos);
|
|
end;
|
|
if BufferSize < (BufEnd - BufStart + 1)
|
|
then Result := BufferSize
|
|
else Result := BufEnd - BufStart + 1;
|
|
Move(FBuffer[BufStart], Buffer^, Result);
|
|
Inc(BufStart, Result);
|
|
Inc(FPosition, Result);
|
|
end;
|
|
|
|
procedure TACSCDIn.Eject;
|
|
var
|
|
Data: Integer;
|
|
begin
|
|
if Busy then raise EACSException.Create(strBusy);
|
|
OpenCD;
|
|
Data := 0;
|
|
fpioctl(_cd_fd, CDROMEJECT,@Data);
|
|
CloseCD;
|
|
end;
|
|
|
|
procedure TACSCDIn.CloseTray;
|
|
var
|
|
Data: Integer;
|
|
begin
|
|
OpenCD;
|
|
Data := 0;
|
|
fpioctl(_cd_fd, CDROMCLOSETRAY,@Data);
|
|
CloseCD;
|
|
end;
|
|
|
|
procedure CountDrives;
|
|
var
|
|
_cd_fd, i : Integer;
|
|
fname : String;
|
|
sci : cdrom_subchnl;
|
|
res :Integer;
|
|
Data: Integer;
|
|
begin
|
|
DrivesCount := 0;
|
|
Data := CDSL_CURRENT;
|
|
for i := 0 to 3 do
|
|
begin
|
|
fname := '/dev/hd'+chr(ord('a')+i);
|
|
_cd_fd := fpopen(PChar(fname), O_RDONLY or O_NONBLOCK);
|
|
if _cd_fd >= 0 then
|
|
begin
|
|
res := fpioctl(_cd_fd, CDROM_DRIVE_STATUS, @Data);
|
|
case res of
|
|
CDS_TRAY_OPEN, CDS_NO_DISC, CDS_DRIVE_NOT_READY:
|
|
begin
|
|
inc(DrivesCount);
|
|
setlength(DrivesPaths,DrivesCount);
|
|
DrivesPaths[DrivesCount-1] := fname;
|
|
fpclose(_cd_fd);
|
|
continue;
|
|
end;
|
|
end;
|
|
(* Either the disc is ok or no information
|
|
from the driver. Trying CDROMSUBCHNL.*)
|
|
sci.cdsc_format := CDROM_MSF;
|
|
if fpioctl(_cd_fd, CDROMSUBCHNL, @sci) >= 0 then
|
|
begin
|
|
inc(DrivesCount);
|
|
setlength(DrivesPaths,DrivesCount);
|
|
DrivesPaths[DrivesCount-1] := fname;
|
|
end;
|
|
fpclose(_cd_fd);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TACSCDIn.GetDrivesCount : Integer;
|
|
begin
|
|
Result := DrivesCount;
|
|
end;
|
|
|
|
procedure TACSCDIn.SetCurrentDrive(Value : Integer);
|
|
begin
|
|
if Busy then raise EACSException.Create(strBusy);
|
|
FCurrentDrive := Value;
|
|
end;
|
|
|
|
function TACSCDIn.GetDriveName : String;
|
|
begin
|
|
Result := '';
|
|
end;
|
|
|
|
destructor TACSCDIn.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
|