📄 admdm.pas
字号:
FCallerIDProvided := False;
CheckReady;
{$IFDEF AdModemDebug}
FComPort.AddStringToLog('ConfigAndOpen');
{$ENDIF}
PassthroughMode := True;
Initialize;
DoStatus(msIdle);
DoConnect;
end;
function TAdCustomModem.ConvertXML(const S: string): string;
{ converts the '<CR>' and '<LF>' from LibModem into #13 and #10 }
var
Psn : Integer;
begin
Result := S;
while Pos('<CR>', AnsiUpperCase(Result)) > 0 do begin
Psn := Pos('<CR>', AnsiUpperCase(Result));
Delete(Result, Psn, Length('<CR>'));
Insert(#13, Result, Psn);
end;
while Pos('<LF>', AnsiUpperCase(Result)) > 0 do begin
Psn := Pos('<LF>', AnsiUpperCase(Result));
Delete(Result, Psn, Length('<LF>'));
Insert(#10, Result, Psn);
end;
{ XML also doubles any '%' char, strip that }
while Pos('%%', Result) > 0 do
Delete(Result, Pos('%%', Result), 1);
end;
constructor TAdCustomModem.Create(AOwner: TComponent);
{ we're being created }
begin
FSelectedDevice := TApdModemNameProp.Create;
FStatusDisplay := nil;
inherited;
Initialized := False;
PassthroughMode := False;
ResponsePacket := nil;
{ property inits }
FAnswerOnRing := 2;
FBPSRate := 0;
FConnected := False;
FDialTimeout := 60;
FFailCode := 0;
FModemCapFolder := ApxDefModemCapFolder;
FModemState := msUnknown;
FNegotiationResponses := TStringList.Create;
FRingCount := 0;
FRingWaitTimeout := 1200;
FSelectedDevice.Manufacturer := '';
FSelectedDevice.Name := '';
FStartTime := 0;
LmModem.Manufacturer := 'Generic Hayes compatible';
LmModem.Model := 'Generic modem';
LmModem.FriendlyName := 'Generic modem';
LibModem := TApdLibModem.Create(Self);
FModemConfig := DefaultDeviceConfig;
FCallerIDProvided := False;
with CallerIDInfo do begin
HasData := False;
Date := '';
Time := '';
Number := '';
Name := '';
Msg := '';
end;
FHandle := AllocateHWnd(ModemMessage);
FComPort := SearchComPort(Owner);
end;
{procedure TAdCustomModem.TriggerEvent(CP: TObject;} {!!.06}
{TriggerHandle: Word);} {!!.06}
procedure TAdCustomModem.TriggerEvent(CP : TObject; {!!.06}
Msg, TriggerHandle, Data: Word); {!!.06}
{ handle our DCD and timer triggers }
begin
if TriggerHandle = DCDTrigger then begin
if FComPort.DCD then
DoConnect
else
DoDisconnect;
end else if TriggerHandle = StatusTimerTrigger then begin
DoStatus(FModemState);
FComPort.SetTimerTrigger(StatusTimerTrigger, 1000, True);
if (FModemState = msConnectWait) and
(Integer(ElapsedTime div 1000) >= FDialTimeout) then begin
{ > DialTimeout elapsed, cancel }
PostMessage(Handle, apw_CancelCall, 0, 0);
DoFail(ecModemNoAnswer); {!!.04}
end;
end;
if Assigned(FSavedOnTrigger) then {!!.06}
FSavedOnTrigger(CP, Msg, TriggerHandle, Data); {!!.06}
end;
function TAdCustomModem.DefaultDeviceConfig: TApdModemConfig;
begin
with Result do begin
ConfigVersion := ApxModemConfigVersion;
{ port settings }
DataBits := 8;
Parity := pNone;
StopBits := 1;
if Assigned(FComPort) then
AttachedTo := FComPort.Dispatcher.DeviceName
else
AttachedTo := 'unknown';
Manufacturer := LmModem.Manufacturer;
ModemName := LmModem.FriendlyName;
ModemModel := LmModem.Model;
{ speaker options }
SpeakerVolume := svMed;
SpeakerMode := smDial;
{ connection control }
FlowControl := fcHard;
ErrorControl := [ecOn];
Compression := True;;
Modulation := smCCITT;;
ToneDial := True;
BlindDial := False;
CallSetupFailTimeout := 60;
InactivityTimeout := 0;
{ extra commands }
ExtraSettings := '';
FillChar(Padding, SizeOf(Padding), #0);
end;
end;
destructor TAdCustomModem.Destroy;
{ we're being destroyed }
begin
DeallocateHWnd(FHandle); {!!.02}
ResponsePacket.Free;
FNegotiationResponses.Free;
FSelectedDevice.Free;
LibModem.Free;
if Assigned(FComPort) then {!!.06}
FComPort.DeregisterUserCallbackEx(PortOpenCloseEx); {!!.05}
inherited Destroy;
end;
procedure TAdCustomModem.Dial(const ANumber: string);
{ initiate the dialing sequence }
begin
FCallerIDProvided := False;
CheckReady;
{$IFDEF AdModemDebug}
FComPort.AddStringToLog('dial');
{$ENDIF}
PrepForConnect(True);
FPhoneNumber := ANumber;
PassthroughMode := False;
if not Initialized then
Initialize;
FStartTime := AdTimeGetTime;
DoStatus(msDial);
Postmessage(Handle, apw_StartDial, 0, 0);
end;
procedure TAdCustomModem.DoCallerID;
{ Generate the OnModemCallerID event }
begin
FCallerIDProvided := True;
{$IFDEF AdModemDebug}
FComPort.AddStringToLog('CallerID');
{$ENDIF}
if Assigned(FOnModemCallerID) then
FOnModemCallerID(Self, FCallerIDInfo);
end;
procedure TAdCustomModem.DoConnect;
{ Generate the OnModemConnect event }
begin
PrepForConnect(False);
if not PassthroughMode then begin
if DCDTrigger = 0 then
DCDTrigger := FComPort.AddStatusTrigger(stModem);
FComPort.SetStatusTrigger(DCDTrigger, msDCDDelta, True);
end;
if Assigned(FOnModemConnect) and not(FConnected) then {!!.05}
FOnModemConnect(Self);
FConnected := True; {!!.05}
end;
procedure TAdCustomModem.DoDisconnect;
{ Generate the OnModemDisconnect event }
begin
PrepForConnect(False);
if Assigned(FOnModemDisconnect) and FConnected then {!!.05}
FOnModemDisconnect(Self);
FConnected := False; {!!.05}
end;
procedure TAdCustomModem.DoFail(Failure : Integer);
{ Generate the OnModemFail event }
begin
FFailCode := Failure;
{$IFDEF AdModemDebug}
FComPort.AddStringToLog('Fail: ' + IntToStr(FFailCode));
{$ENDIF}
if Assigned(FOnModemFail) then
FOnModemFail(Self, Failure)
else
case FFailCode of
{ literal strings converted to string consts } {!!.06}
ecModemRejectedCommand :
raise EModemRejectedCommand.CreateUnknown(
Format(secModemRejectedCommand + #13#10'%s',[LastCommand]), 0);
ecModemBusy :
raise EModemBusy.CreateUnknown(secModemBusy, 0);
ecDeviceNotSelected :
raise EDeviceNotSelected.CreateUnknown(secDeviceNotSelected, 0);
ecModemNotResponding :
raise EModemNotResponding.CreateUnknown(secModemNotResponding, 0);
ecModemDetectedBusy :
raise EModemDetectedBusy.CreateUnknown(secModemDetectedBusy, 0);
ecModemNoDialTone :
raise ENoDialTone.CreateUnknown(secModemNoDialtone, 0);
ecModemNoCarrier :
raise ENoCarrier.CreateUnknown(secModemNoCarrier, 0);
ecModemNoAnswer :
raise ENoAnswer.CreateUnknown(secModemNoAnswer, 0);
end;
FComPort.OnTrigger := FSavedOnTrigger; {!!.06}
end;
procedure TAdCustomModem.DoLog(LogCode: TApdModemLogCode);
{ generate the OnModemLog event }
begin
if Assigned(FOnModemLog) then
FOnModemLog(Self, LogCode);
end;
procedure TAdCustomModem.DoStatus(NewModemState: TApdModemState);
{ change FModemState and generate the event }
var
S : string;
Action : TApdModemStatusAction;
FirstState : Boolean;
begin
if FModemState <> NewModemState then begin
FirstState := True;
{ state changed, is it log-worthy? }
case NewModemState of
msIdle : if FModemState in [msAutoAnswerWait..msConnectWait] then
DoLog(mlConnectFail)
else
DoLog(mlNone);
msAutoAnswerBackground : DoLog(mlAutoAnswer);
msAnswerWait : DoLog(mlAnswer);
msDial : DoLog(mlDial);
msConnected : DoLog(mlConnect);
msHangup : DoLog(mlCancel);
msCancel : DoLog(mlCancel);
end;
end else
FirstState := False;
FModemState := NewModemState;
if Assigned(FOnModemStatus) then
FOnModemStatus(Self, ModemState);
if Assigned(FStatusDisplay) then begin
{ update the status display }
if FStatusDisplay.Started then
S := ModemStatusMsg(FModemState)
else
S := '';
case FModemState of
msConnectWait, msAutoAnswerWait :
if FirstState then
Action := msaUpdate
else
Action := msaDetailReplace;
msIdle, msConnected : Action := msaClose;
else
Action := msaUpdate;
end;
FStatusDisplay.UpdateDisplay(Self,
ModemStatusMsg(FModemState), { the status line }
IntToStr(ElapsedTime div 1000),
S, { for the detail list }
Action);
end;
end;
function TAdCustomModem.FailureCodeMsg(
const FailureCode: Integer): string;
{ convert a FailureCode into a string }
begin
Result := ErrorMsg(FailureCode); {!!.04}
(*case FailureCode of
ecDeviceNotSelected : Result := 'Device not selected';
ecModemRejectedCommand : Result := 'Modem rejected command';
ecModemBusy : Result := 'Modem is doing something else';
ecModemNotResponding : Result := 'Modem not responding';
ecModemDetectedBusy : Result := 'Called number is busy';
ecModemNoDialtone : Result := 'No dialtone';
ecModemNoCarrier : Result := 'No carrier';
ecModemNoAnswer : Result := 'No answer';
end;*)
end;
function TAdCustomModem.GetDevConfig: TApdModemConfig;
{ return the TApdModemConfig structure defining the selected modem }
begin
Result := FModemConfig;
end;
function TAdCustomModem.GetElapsedTime: DWORD;
begin
if FStartTime = 0 then
Result := 0 { not timing }
else
Result := AdTimeGetTime - FStartTime;
end;
function TAdCustomModem.GetNegotiationResponses: TStringList;
{ return the negotiation responses for this connection }
begin
Result := FNegotiationResponses;
end;
procedure TAdCustomModem.Initialize;
{ initialize the modem }
function PoundReplace(const str : string; Value : Integer) : string;
{ some modem init strings have variable params, replace them here }
var
I : Integer;
begin
Result := str;
I := Pos('<#>', Result);
{ remove the '<#>' }
Delete(Result, I, 3);
{ add the value }
Insert(IntToStr(Value), Result, I);
end;
var
ConfigInit : string;
begin
{ set the msInitializing state }
DoStatus(msInitializing);
{$IFDEF AdModemDebug}
FComPort.AddStringToLog('Initialize');
{$ENDIF}
if not DeviceSelected then {!!.04}
raise EDeviceNotSelected.Create(ecDeviceNotSelected, False);
if not SendCommands(LmModem.Init) then begin
{ fake it, using generic reset }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -