📄 dialfunc.pas
字号:
unit DialFunc;
interface
type APP_USER_STATE=(
USER_IDLE,
USER_GET_PHONE_NUM,
USER_WAIT_DIAL_TONE,
USER_WAIT_REMOTE_PICKUP,
USER_TALKING,
USER_WAIT_HANGUP
);
type TRUNK_CH_INFO=record
InUse:Integer;
DtmfBuf:array [0..250] of char;
end;
type USER_CH_INFO=record
EnCalled:boolean;
lineState:integer;
nStep:APP_USER_STATE;
nToTrkCh:Integer;
pPhoNumBuf:array [0..50] of char;
nTimeOut:Integer;
end;
///////////////////////////////////////////
function myGetAnIdleChannel():Integer;
function InitCtiBoard():boolean;
procedure DrawTrunkChState;
procedure DrawUserChState;
procedure DoUserWork;
procedure ExitCtiBoard;
procedure GetVersion;
///////////////////////////////////////////////////////////
var
nTotalCh:WORD;
UserCh:array [0..99]of USER_CH_INFO;
TrunkCh:array [0..99] of TRUNK_CH_INFO;
///////////////////////////////////////////////////////////
implementation
uses Shpa3api,Main,Windows, Messages, SysUtils, Classes, Graphics,
Controls, Forms, Dialogs,ComCtrls, ExtCtrls;
////////////////////////////////////////////////////////////
procedure DoUserWork;
var
ch:Integer;
i:Integer;
PhoNumLen:Integer;
begin
for i:=0 to nTotalCh-1 do
begin
if (SsmGetChType(i) <> 2) then continue;
case UserCh[i].nStep of
USER_IDLE:
begin
UserCh[i].pPhoNumBuf:='';
if (SsmGetHookState(i) = 1) then //user-pickup detected
UserCh[i].nStep := USER_GET_PHONE_NUM;
end;
USER_GET_PHONE_NUM:
begin
PhoNumLen:=StrToInt(MainForm.Edit1.Text);
if( SsmGetRxDtmfLen(i) >= PhoNumLen ) then
begin
SsmGetDtmfStr(i,@UserCh[i].pPhoNumBuf[0]);//retrieve phone num
UserCh[i].pPhoNumBuf[PhoNumLen] := #0;
ch:=myGetAnIdleChannel();
if(ch = -1) then//no idle trunk channel available
begin
SsmSendTone(i,1);
UserCh[i].nStep := USER_WAIT_HANGUP;
end
else begin
SsmPickup(ch);
TrunkCh[ch].InUse := 1;
UserCh[i].nToTrkCh := ch;
UserCh[i].nStep := USER_WAIT_DIAL_TONE;
end;
end
else if(SsmGetHookState(i) = 0) then //user-hangup detected
begin
SsmClearRxDtmfBuf(i);
UserCh[i].nStep := USER_IDLE;
end;
end;
USER_WAIT_DIAL_TONE:
begin
ch := UserCh[i].nToTrkCh;
if (SsmAutoDial(ch, UserCh[i].pPhoNumBuf) = 0) then
begin
TrunkCh[ch].InUse := 2;
UserCh[i].nStep := USER_WAIT_REMOTE_PICKUP;
end
else
begin
SsmHangup(ch);
TrunkCh[ch].InUse := 0;
SsmClearRxDtmfBuf(ch);
SsmSendTone(i, 1); //send busy tone
UserCh[i].nStep := USER_WAIT_HANGUP;
end;
end;
USER_WAIT_REMOTE_PICKUP:
begin
ch := UserCh[i].nToTrkCh;
UserCh[ch].lineState := SsmGetChState(ch);
if(SsmChkAutoDial(ch) = 7) then //remote user pickup
begin
SsmTalkWith(i, ch);
TrunkCh[ch].InUse := 4;
UserCh[i].nStep := USER_TALKING;
end
else if(SsmGetHookState(i) = 0) then //user hangup
begin
SsmHangup(ch);
TrunkCh[ch].InUse := 0;
SsmClearRxDtmfBuf(i);
UserCh[i].nStep := USER_IDLE;
end
else if((UserCh[ch].lineState = S_CALL_PENDING) or (SsmChkAutoDial(ch) =10)) then //busy tone or 30s time out
begin
SsmHangup(ch);
TrunkCh[ch].InUse := 0;
SsmSendTone(i,1); //send busy tone
UserCh[i].nStep := USER_WAIT_HANGUP;
end;
end;
USER_TALKING:
begin
ch := UserCh[i].nToTrkCh;
UserCh[ch].lineState := SsmGetChState(ch);
if( SsmGetHookState(i)=0)//user hang up
or ( UserCh[ch].lineState = S_CALL_PENDING ) then//remote user hangup
begin
SsmHangup(ch);
SsmStopTalkWith(ch, i);
SsmClearRxDtmfBuf(ch);
TrunkCh[ch].InUse := 0;
if( SsmGetHookState(i)=0 ) then//user hangup first
UserCh[i].nStep := USER_IDLE
else begin //remote user hangup first
SsmSendTone(i,1);//send busy tone
UserCh[i].nStep := USER_WAIT_HANGUP;
end;
end;
end;
USER_WAIT_HANGUP:
begin
if(SsmGetHookState(i) = 0) then//user hangup
begin
SsmStopSendTone(i);//stop sending busy tone
SsmClearRxDtmfBuf(i);
UserCh[i].nStep := USER_IDLE;
end;
end;
else UserCh[i].nStep := USER_IDLE;
end;//end case
end;//end for
end;
procedure DrawTrunkChState;
var
state:String;
tmpstr:String;
i:integer;
nindex:integer;
begin
nindex:=0;
for i:=0 to nTotalCh-1 do
begin
if( not UserCh[i].EnCalled ) then continue;
begin
case TrunkCh[i].InUse of
0: begin state:='空闲';TrunkCh[i].DtmfBuf:='';SsmClearRxDtmfBuf(i); end;
1: state:='摘机';
2: state:='拨号';
3: state:='等待被叫摘机';
4: state:='通话';
end;
tmpstr:=MainForm.TrunkChListView.Items[nindex].SubItems[0];
if state <> tmpstr then
MainForm.TrunkChListView.Items[nindex].SubItems[0]:=state;
SsmGetDtmfStr(i,@TrunkCh[i].DtmfBuf[0]);
tmpstr:=MainForm.TrunkChListView.Items[nindex].SubItems[1];
if tmpstr<>StrPas(@TrunkCh[i].DtmfBuf[0]) then
MainForm.TrunkChListView.Items[nindex].SubItems[1]:=StrPas(@TrunkCh[i].DtmfBuf[0]);
nindex:=nindex+1;
end;
end;
end;
procedure DrawUserChState;
var
state:String;
tmpstr:string;
i:Integer;
nindex:integer;
begin
nindex:=0;
for i:=0 to nTotalCh-1 do
if (SsmGetChType(i) = 2) Then
begin
case UserCh[i].nStep of
USER_IDLE: begin state:='空闲';UserCh[i].pPhoNumBuf:=''; SsmClearRxDtmfBuf(i);end;
USER_GET_PHONE_NUM: state := '接收电话号码';
USER_WAIT_DIAL_TONE: state := '等待拨号音';
USER_WAIT_REMOTE_PICKUP: state := '等待被叫摘机';
USER_TALKING: state := '正在通话';
USER_WAIT_HANGUP: state := '等待坐席挂机';
end;
tmpstr:=MainForm.UserChListView.Items[nindex].SubItems[0];
if state <> tmpstr then
MainForm.UserChListView.Items[nindex].SubItems[0]:=state;
tmpstr:=MainForm.UserChListView.Items[nindex].SubItems[1];
if UserCh[i].pPhoNumBuf <> tmpstr then
MainForm.UserChListView.Items[nindex].SubItems[1]:=StrPas(@UserCh[i].pPhoNumBuf[0]);
nindex:=nindex+1;
end;
end;
function InitCtiBoard():boolean;
var
CurPath:PChar;
ShConfig:string;
ShIndex:string;
ErrMsg:PChar;
i:integer;
nDirection:Integer;
begin
//Initialization of CTI driver
GetMem(CurPath,200);
GetCurrentDirectory(200,CurPath);
ShConfig:=StrPas(CurPath)+'\ShConfig.ini';
ShIndex:=StrPas(CurPath)+'\ShIndex.ini';
FreeMem(CurPath);
if SsmStartCti(@ShConfig[1], @ShIndex[1] )<>0 then
begin
GetMem(ErrMsg,200);
SsmGetLastErrMsg(ErrMsg);
Application.MessageBox(ErrMsg,'错误', MB_OK) ;
FreeMem(ErrMsg);
InitCtiBoard:=false;
Exit;
end;
//Initialization of channels on trunk-board
nTotalCh := SsmGetMaxCh();
for i:=0 to nTotalCh-1 do
begin
UserCh[i].EnCalled := false;
if( SsmGetChType(i) = 2 ) then
begin
SsmSetASDT(i, true);
UserCh[i].pPhoNumBuf:='';
UserCh[i].nStep := USER_IDLE;
end
else
begin
if( SsmGetAutoCallDirection(i,@nDirection) = 1 ) then //允许自动接续
begin
if( nDirection = 1) or (nDirection = 2 ) then //enable dial
begin
TrunkCh[i].InUse := 0;
TrunkCh[i].DtmfBuf:='';
SsmSetMinVocDtrEnergy (i, 30000);
UserCh[i].EnCalled := true;
end;
end;
end;
end;
InitCtiBoard:=True;
end;
procedure ExitCtiBoard;
begin
SsmCloseCti();
end;
procedure GetVersion;
begin
end;
function myGetAnIdleChannel():integer;
var
i:integer;
begin
for i:=0 to nTotalCh-1 do
begin
if( (TrunkCh[i].InUse = 0) and UserCh[i].EnCalled ) then break;
end;
if (i=nTotalCh) then myGetAnIdleChannel:=-1
else myGetAnIdleChannel:=i;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -