⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dialfunc.pas

📁 三汇CTI示例程序源码
💻 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 + -