📄 adtapi.pas
字号:
{*********************************************************}
{* ADTAPI.PAS 4.04 *}
{* Copyright (C) TurboPower Software 1996-2002 *}
{* All rights reserved. *}
{*********************************************************}
{Global defines potentially affecting this unit}
{$I AWDEFINE.INC}
{Options required for this unit}
{$G+,X+,F+,B-,J+}
{$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
unit AdTapi;
{-Delphi serial port component}
interface
uses
WinTypes,
WinProcs,
Registry,
Classes,
Messages,
Controls,
Forms,
{$IFDEF Delphi6}
Variants,
{$ENDIF}
ExtCtrls,
Dialogs,
MMSystem,
SysUtils,
AdTUtil,
OoMisc,
AwUser,
AdExcept,
AdTSel,math, //wjs update
AdPort;
type
{TAPI states}
TTapiState = (tsIdle, tsOffering, tsAccepted, tsDialTone, tsDialing,
tsRingback, tsBusy, tsSpecialInfo, tsConnected,
tsProceeding, tsOnHold, tsConferenced, tsOnHoldPendConf,
tsOnHoldPendTransfer, tsDisconnected, tsUnknown);
TTapiConfigRec = record
DataSize : Cardinal;
Data : array[0..1023] of Byte;
end;
{Wave device states}
TWaveState = (wsIdle, wsPlaying, wsRecording, wsData);
TWaveMessage = (waPlayOpen, waPlayDone, waPlayClose,
waRecordOpen, waDataReady, waRecordClose);
{TAPI logging codes}
TTapiLogCode = (
ltapiNone, { None }
ltapiCallStart, { Call started }
ltapiCallFinish, { Call finished }
ltapiDial, { Dialing }
ltapiAccept, { Accepting an incoming call }
ltapiAnswer, { Answering an incoming call }
ltapiConnect, { Connected }
ltapiCancel, { Call cancelled }
ltapiDrop, { Call drop }
ltapiBusy, { Called number was busy }
ltapiDialFail, { Dial failed }
ltapiReceivedDigit); { Received a DTMF tone }
{TAPI status event}
TTapiStatusEvent = procedure(CP : TObject;
First, Last : Boolean;
Device, Message,
Param1, Param2, Param3 : LongInt) of object;
{TAPI log event}
TTapiLogEvent = procedure(CP : TObject; Log : TTapiLogCode) of object;
{TAPI DTMF event}
TTapiDTMFEvent = procedure(CP : TObject; Digit : Char;
ErrorCode: LongInt) of object;
{TAPI Caller ID event}
TTapiCallerIDEvent =
procedure(CP : TObject; ID, IDName: string) of object;
{TAPI wave notify event}
TTapiWaveNotify = procedure(CP : TObject;
Msg : TWaveMessage) of object;
{TAPI wave silence event}
TTapiWaveSilence = procedure(CP : TObject;
var StopRecording : Boolean;
var Hangup : Boolean) of object;
TTapiWaveBusy = procedure(CP : TObject; //wjs update
var StopRecording : Boolean;
var Hangup : Boolean) of object;
TTapiWaveRingback = procedure(CP : TObject; //wjs update
var RingbackTimes : integer;
var StopRecording : Boolean;
var Hangup : Boolean) of object;
const
MaxSecond = 5; //wjs update
Success = 0;
WaitErr_WaitAborted = 1;
WaitErr_WaitTimedOut = 2;
LineCallState_Any = 0;
WaitTimeout = 30000;
{ Base of error strings in the resource }
TapiErrorBase = 13800;
{ Base of status strings in the resource }
TapiStatusBase = 13500;
{ Offsets from TapiStatusBase for the separate TAPI message classes }
lcsBase = 0; { Line Call State }
ldsBase = 32; { Line Device State }
lrBase = 64; { Line Reply }
asBase = 96; { Apro-specific }
lcsdBase = 150; { Line Call State -- Disconnect }
{Defaults for TApdTapiLog properties}
DefTapiHistoryName = 'APROTAPI.HIS';
{Property inits}
DefMaxAttempts = 3;
DefAnsRings = 2;
DefRetryWait = 60; { seconds }
DefShowTapiDevices = True;
DefShowPorts = True;
DefMaxMessageLength = 60; { 1 minute }
DefWaveState = wsIdle;
DefUseSoundCard = False;
DefTrimSeconds = 1; //wjs update
DefSilenceThreshold = 50;
DefChannels = 1;
DefBitsPerSample = 16;
DefSamplesPerSecond = 8000;
DefMonitorRecording = False;
{Wave Error Types}
WaveInError = 1;
WaveOutError = 2;
MMioError = 3;
BufferSeconds = 1;
WaveOutBufferSeconds = 3;
type
THalfSecond = record //以下3行wjs update
Hi,Low:integer; //前半秒、后半秒
end;
{Forwards}
TApdAbstractTapiStatus = class;
TApdTapiLog = class;
{Custom TAPI component}
TApdCustomTapiDevice = class(TApdBaseComponent)
protected
{private data}
LineApp : TLineApp; {TAPI handle for this application}
LineExt : TLineExtensionID; {Line extension data}
LineHandle : TLine; {Handle of the opened line device}
CallHandle : TCall; {Handle of the current call}
SelectedLine : Integer; {Device ID of selected line}
VS : TVarString; {Used to return Cid}
DialTimer : TTimer; {Timer component}
RequestedId : LongInt; {ID being waited for}
AsyncReply : LongInt; {Requested reply}
CallState : LongInt; {Received CallState}
ReplyReceived : Boolean; {True if Line Reply received}
CallStateReceived : Boolean; {True if CallState received}
TapiInUse : Boolean; {True means a call is active}
TapiHasOpened : Boolean; {True means TAPI has been opened}
Initializing : Boolean; {True during StartTapi}
Connected : Boolean; {True when connected}
StoppingCall : Boolean; {True during HangupCall}
ShuttingDown : Boolean; {True during StopTapi}
RetryPending : Boolean; {True if a retry is pending}
TapiFailFired : Boolean; {True if OnTapiFailed fired}
ReplyWait : Boolean; {True if waiting for reply}
StateWait : Boolean; {True if waiting for call state}
PassThruMode : Boolean; {True if in passthrough mode}
WaveOutHeader : PWaveHdr; {Wave header for playing}
WaveInHeader : PWaveHdr; {Wave header for recording}
WaveOutHandle : HWaveOut; {Handle of the wave out device}
WaveInHandle : HWaveIn; {Handle of the wave in device}
BytesRecorded : LongInt; {Bytes recorded for this buffer}
TotalBytesRecorded : LongInt; {Bytes recorded overall }
WaveInBuffer1 : Pointer; {Buffer for wave recording}
WaveInBuffer2 : Pointer; {Buffer for wave recording}
WaveOutBuffer1 : Pointer; {Buffer for wave playing }
WaveOutBuffer2 : Pointer; {Buffer for wave playing }
ActiveBuffer : Byte; {The active wave in buffer}
MmioInHandle : Integer; {File handle for recording}
MmioOutHandle : Integer; {File handle for recording}
RootChunk : TMMCkInfo; {Root chunk for wave file}
DataChunk : TMMCkInfo; {Data chunk for wave file}
TempFileName : TFileName; {Temporary file for recording}
Channels : Byte; {# of channels for recording}
BitsPerSample : Byte; {Bits per sample for recording}
SamplesPerSecond : Integer; {Samples per sec for recording}
WaveInBufferSize : LongInt; {# of bytes in a wave in buffer}
BytesToPlay : LongInt; {# of bytes in the wave file}
BytesPlayed : LongInt; {# of bytes already played}
BytesInBuffer : LongInt; {# of bytes in current buffer}
ActiveWaveOutBuffer: Byte; {The active wave out buffer}
WaveOutBufferSize : LongInt; {# of bytes in wave out buffer}
{private data stores}
FAvgWaveInAmplitude: Integer; {Average amplitude for recording}
FCancelled : Boolean; {True if call was cancelled}
FDialing : Boolean; {True when dialing, False not}
FDialTime : LongInt; {Elapsed dial time}
FTapiDevices : TStrings; {List of tapi device names}
FSelectedDevice : string; {Name of selected device}
FApiVersion : LongInt; {Negotiated version}
FDeviceCount : DWORD; {Number of supported TAPI devices}
FTrueDeviceCount: DWORD; {Total number of TAPI devices}
FOpen : Boolean; {True to open a line device}
FCallInfo : PCallInfo; {Holds current call info}
FComPort : TApdCustomComPort; {Attached comport}
FStatusDisplay : TApdAbstractTapiStatus; {Built-in status display}
FTapiLog : TApdTapiLog; {Built-in logging component}
FNumber : string; {Last dialed number}
FMaxAttempts : Word; {Max number of dial attempts}
FAttempt : Word; {Dialing attempt number}
FRetryWait : Word; {Seconds between dialing attempts}
FAnsRings : Byte; {Rings to allow before answer}
FParentHWnd : HWnd; {Window handle of parent}
FShowTapiDevices: Boolean; {Show TAPI devices}
FShowPorts : Boolean; {Show ports}
FEnableVoice : Boolean; {Monitor DTMF Tones if capable}
FMaxMessageLength : LongInt; {Max message length for wave recording}
FWaveFileName : TFileName; {Wave file name}
FInterruptWave : Boolean; {Stops playing wave file on DTMF tone}
FHandle : HWnd; {Window handle for hidden window}
FWaveState : TWaveState; {Current wave device state}
FUseSoundCard : Boolean; {Play the sound through the sound card}
FSilence : TLineMonitorTone;
FTrimSeconds : Byte; {Trim silence after x seconds}
FSilenceThreshold : Integer; {Silence threshold for trimming}
FMonitorRecording : Boolean; {Echo wave recording to sound card}
FFailCode : Integer; {Failure code}
FFilterUnsupportedDevices: Boolean; {Display only supported devices}
FWaitingForCall: Boolean; {True if in AutoAnswer mode} {!!.04}
{Events}
FOnTapiCallerID : TTapiCallerIDEvent;
FOnTapiConnect : TNotifyEvent;
FOnTapiDTMF : TTapiDTMFEvent;
FOnTapiFail : TNotifyEvent;
FOnTapiLog : TTapiLogEvent;
FOnTapiPortClose : TNotifyEvent;
FOnTapiPortOpen : TNotifyEvent;
FOnTapiStatus : TTapiStatusEvent;
FOnTapiWaveNotify : TTapiWaveNotify;
FOnTapiWaveSilence : TTapiWaveSilence;
FOnTapiWaveBusy : TTapiWaveBusy; //wjs update
FOnTapiWaveRingback: TTapiWaveRingback; //wjs update
{Callback virtual methods}
procedure DoLineCallInfo(Device, P1, P2, P3 : LongInt); virtual;
procedure DoLineCallState(Device, P1, P2, P3 : LongInt); virtual;
procedure DoLineClose(Device, P1, P2, P3 : LongInt); virtual;
procedure DoLineCreate(Device, P1, P2, P3 : LongInt); virtual;
procedure DoLineDevState(Device, P1, P2, P3 : LongInt); virtual;
procedure DoLineGenerate(Device, P1, P2, P3 : LongInt); virtual;
procedure DoLineMonitorDigits(Device, P1, P2, P3 : LongInt); virtual;
procedure DoLineMonitorMedia(Device, P1, P2, P3 : LongInt); virtual;
procedure DoLineMonitorTone(Device, P1, P2, P3 : LongInt); virtual;
procedure DoLineReply(Device, P1, P2, P3 : LongInt); virtual;
procedure DoLineRequest(Device, P1, P2, P3 : LongInt); virtual;
function HandleLineErr(LineErr : LongInt): Boolean;
function HangupCall(AbortRetries : Boolean) : Boolean;
procedure UpdateCallInfo(Device : LongInt);
function WaitForCallState(DesiredCallState : LongInt) : LongInt;
function WaitForReply(ID : LongInt) : LongInt;
{Property access methods}
procedure SetOpen(NewOpen : Boolean);
{Private methods}
procedure AssureTapiReady;
function CidFromTapiDevice : LongInt;
procedure CheckVoiceCapable;
procedure CheckWaveException(ErrorCode : Integer; Mode : Integer);
procedure CheckWaveInSilence;
function CloseTapiPort : Boolean;
procedure CloseWaveFile;
procedure CreateDialTimer;
function DeviceIDFromName(const Name : string) : Integer;
procedure DialPrim(PassThru : Boolean);
procedure EnumLineDevices;
procedure FreeWaveInBuffers;
procedure FreeWaveOutBuffer;
function GetSelectedLine : Integer;
function GetWaveDeviceId(const Play : Boolean) : DWORD;
procedure LoadWaveOutBuffer;
procedure MonitorDTMF(var CallHandle: LongInt;
const DTMFMode: LongInt);
procedure OpenTapiPort;
procedure OpenWaveFile;
procedure PlayWaveOutBuffer;
procedure PrepareWaveInHeader;
function StartTapi : Boolean;
function StopTapi : Boolean;
procedure TapiDialTimer(Sender : TObject);
procedure WndProc(var Message : TMessage);
procedure WriteWaveBuffer;
{Property access methods}
function GetBPSRate : DWORD;
function GetCalledID: string;
function GetCalledIDName: string;
function GetCallerID : string;
function GetCallerIDName : string;
function GetComNumber : Integer;
function GetParentHWnd : HWnd;
function GetTapiState : TTapiState;
procedure SetStatusDisplay(const NewDisplay : TApdAbstractTapiStatus);
procedure SetTapiLog(const NewLog : TApdTapiLog);
procedure SetTapiDevices(const Values : TStrings);
procedure SetSelectedDevice(const NewDevice : string);
procedure SetEnableVoice(Value: Boolean);
procedure SetMonitorRecording(const Value : Boolean);
procedure SetFilterUnsupportedDevices(const Value: Boolean);
{Private properties}
property Open : Boolean
read FOpen write SetOpen;
{Event methods}
procedure TapiStatus(First, Last : Boolean; Device, Message,
Param1, Param2, Param3 : DWORD);
procedure TapiLogging(Log : TTapiLogCode);
procedure TapiPortOpen;
procedure TapiPortClose;
procedure TapiConnect;
procedure TapiFail;
procedure TapiDTMF(Digit : Char; ErrorCode: LongInt);
procedure TapiCallerID(ID, IDName: string);
procedure TapiWave(Msg : TWaveMessage);
{Overridden protected methods}
procedure Notification(AComponent : TComponent; Operation: TOperation);
override;
procedure Loaded; override;
public
{Creation/destruction}
constructor Create(AOwner : TComponent); override;
{-Create a TApdTapiDevice component}
destructor Destroy; override;
{-Destroy a TApdTapiDevice component}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -