//------------------------------------------------------------------------------ // // 产品名称: 成晓旭的个人软件Delphi源码库 // 产品版本: CXXSoft delphi code source lib 2.0 // 模块名称: Delphi之三汇模拟语音卡类 // 模块描述: // 单元文件: unSHCard8B.pas // 开发作者: 成晓旭 // 备注: 任何人使用此文件时,请保留此段自述文件,谢谢! // 开发时间: 2003-12-03 // 修改历史: // 修改描述: //------------------------------------------------------------------------------ unit unSHCard8B; interface uses Windows, //unDJTC08a32,unDJNewSig, unBaseDefine, //unDJ160ADefine,unDJChanne160A, unShpa3api,unSHChanne18B,unSH8BDefine; type TCXXCommCard8B =class(TObject) private ChannelNumber:Word; channelObject:array of TCXXSHChannel8B; OnCardChannelState:TTrunkStatusEvent; procedure ReleaseCommDevice(); function GetChannelObjectOrder(const aChannelID:Word):Word; function InitChannel():boolean; public constructor Create(const trunkEvent:TTrunkStatusEvent); destructor Destroy(); override; function LoadCommDevice(const loadAll:boolean=false):boolean; function Startup():boolean; function GetAFreeChannel():Word; function GetChannelNumber():Word; function DialPhone(const aChannelID:Word;const DialPhoneNumber:PChar):boolean; function HangUp(const aChannelID:Word):boolean; end; implementation const SH_ConfigFile ='C:ShCtiShConfig.ini'; SH_IndexFile ='C:ShCtiShIndex.ini'; ...{ TCXXCommCard8B } constructor TCXXCommCard8B.Create(const trunkEvent:TTrunkStatusEvent); begin ChannelNumber :=0; Self.OnCardChannelState := trunkEvent; end; destructor TCXXCommCard8B.Destroy; var Loop:Word; begin if (Length(channelObject) >0) and (channelNumber >0) then begin for Loop :=0 to ChannelNumber -1do begin if Assigned(channelObject[Loop]) then begin channelObject[Loop].Free(); channelObject[Loop] := nil; end; end; end; ReleaseCommDevice(); end; function TCXXCommCard8B.DialPhone(const aChannelID: Word; const DialPhoneNumber: PChar): boolean; var K:Word; begin Result :=false; K := GetChannelObjectOrder(aChannelID); if (K <> ErrorTrunkNumber) and (Assigned(channelObject[K])) then begin Result := channelObject[K].DialPhone(DialPhoneNumber); end; end; procedure TCXXCommCard8B.ReleaseCommDevice(); begin SsmCloseCti() ; end; function TCXXCommCard8B.GetAFreeChannel(): Word; var Loop:Word; begin Result := ErrorTrunkNumber; for Loop := Low(channelObject) to High(channelObject) do begin if NOT channelObject[Loop].CheckDialOutEnabled() then continue; if (channelObject[Loop].GetChannelStatus() = atsFree) then begin Result := channelObject[Loop].GetChannelID(); break; end; end; end; function TCXXCommCard8B.GetChannelNumber(): Word; begin Result := channelNumber; end; function TCXXCommCard8B.GetChannelObjectOrder( const aChannelID: Word): Word; var Loop:Word; begin Result := ErrorTrunkNumber; for Loop := Low(channelObject) to High(channelObject) do begin if (channelObject[Loop].GetChannelID = aChannelID) then begin Result := Loop; break; end; end; end; function TCXXCommCard8B.HangUp(const aChannelID: Word): boolean; var K:Word; begin Result :=false; K := GetChannelObjectOrder(aChannelID); if (K <> ErrorTrunkNumber) and (Assigned(channelObject[K])) then begin channelObject[K].ChannelHangUp(); Result :=true; end; end; function TCXXCommCard8B.LoadCommDevice(const loadAll:boolean): boolean; const loadEmpty =true; begin Result :=false; if SsmStartCti(SH_ConfigFile,SH_IndexFile) <>0 then begin TCXXSHChannel8B.InformInvodeError(); Exit; end; if(SsmGetMaxUsableBoard() <> SsmGetMaxCfgBoard()) then begin //部分板卡初始化失败,取出失败原因 TCXXSHChannel8B.InformInvodeError(); Exit; end; Result := InitChannel(); end; function TCXXCommCard8B.Startup(): boolean; var Loop:integer; begin for Loop :=0 to channelNumber -1do begin channelObject[Loop].Startup(); end; Result :=true; end; function TCXXCommCard8B.InitChannel():boolean; var number,Loop:integer; begin Result :=false; number := SsmGetMaxCh(); if (number <0) then Exit; ChannelNumber := number; SetLength(channelObject,channelNumber); for Loop :=0 to channelNumber -1do begin channelObject[Loop] := TCXXSHChannel8B.Create(OnCardChannelState); channelObject[Loop].CreateCommChannel(Loop); end; Result :=true; end; end.
6、通道类源码:
//------------------------------------------------------------------------------ // // 产品名称: 成晓旭的个人软件Delphi源码库 // 产品版本: CXXSoft delphi code source lib 2.0 // 模块名称: Delphi之三汇模拟语音卡通道类 // 模块描述: // 单元文件: unSHChanne18B.pas // 开发作者: 成晓旭 // 备注: 任何人使用此文件时,请保留此段自述文件,谢谢! // 开发时间: 2003-12-01 // 修改历史: // 修改描述: //------------------------------------------------------------------------------ unit unSHChanne18B; ...{$DEFINE ThreadChannel} interface uses Windows,Classes,SysUtils, unBaseDefine,unShpa3api,unSH8BDefine, //unDJ160ADefine, unDJTC08a32,unDJNewSig; Type ...{$IFDEF ThreadChannel} TCXXSHChannel8B =class(TThread) ...{$ELSE} TCXXSHChannel8B =class(TObject) ...{$ENDIF} private channelType:TChannelType; oldChannelState,channelState:TTrunkState; channelID:Word; phoneNumber:string; dtmfString:string; aCallerId:PAnsiChar; isConntectd:boolean; isDialOut:boolean; aTrunkState:TTrunkStatus; procedure ChannelProcessor(); procedure InformTrunkStatus(const aMsgFlag: TLVOperateFlag); procedure ClearTrunkStatus(); procedure ClearChannelBuffer(); function CheckSigHangup():boolean; function CheckCallIn():boolean; function SwitchOnCallIn():boolean; procedure ProcessCallInSuccess(); procedure ProcessDialSuccess(); procedure ProcessCheckDialSend(); procedure ProcessDialOut(); procedure Stop(); //三汇卡专用方法 function GetTrunkStateBySsm(const ssmState: integer): TTrunkState; protected ...{$IFDEF ThreadChannel} procedure Execute(); override; ...{$ENDIF} public strMessage:string; OnChannelState:TTrunkStatusEvent; constructor Create(const trunkEvent:TTrunkStatusEvent); destructor Destroy();override; procedure CreateCommChannel(const aChennelID: Word); procedure Startup(); function GetChannelID():Word; function GetChannelStatus():TTrunkState; function GetChannelType():TChannelType; function DialPhone(const DialPhoneNumber:PChar):boolean;overload; function DialPhone(const DialPhoneNumber:PChar;const PreDialNumber:PChar):boolean;overload; procedure ChannelHangUp(); function GetDialOut():boolean; //三汇卡特性方法 function CheckDialOutEnabled():boolean; class procedure InformInvodeError(); end; implementation ...{ TCXXSHChannel8B } procedure TCXXSHChannel8B.ChannelHangUp(); begin isDialOut :=false; SsmHangUp(channelID); ClearChannelBuffer(); ClearTrunkStatus(); InformTrunkStatus(lvofUpdate); end; procedure TCXXSHChannel8B.ChannelProcessor(); var ssmState:integer; begin // ssmState := SsmGetChState(channelID); // channelState := GetTrunkStateBySsm(ssmState); CheckCallIn(); case channelState of atsFree: begin // end; atsCallIning: begin SwitchOnCallIn(); end; atsCallInSuccess: begin if CheckSigHangup() then Exit; ProcessCallInSuccess(); end; atsCheckSendDial: begin ProcessCheckDialSend(); end; atsDialing: begin ProcessDialOut(); end; atsDialSuccess: begin if CheckSigHangup() then Exit; ProcessDialSuccess(); strMessage :='拨号成功'; end; atsHangOff: begin ChannelHangUp(); end; end; if (oldChannelState <> channelState) then begin oldChannelState := channelState; InformTrunkStatus(lvofUpdate); end; end; function TCXXSHChannel8B.CheckCallIn(): boolean; begin Result :=false; if(SsmGetChState(channelID)=2) then //检测到振铃信号 begin SsmGetCallerId(channelID, aCallerId); //取出CALLERID信息 channelState := atsCallIning; Result :=true; end; ...{ Result := RingDetect(channelID); if Result then begin OffHook(channelID); if isDialOut then channelState := atsDialSuccess else channelState := atsCallIning; end; } end; function TCXXSHChannel8B.CheckSigHangup(): boolean; begin Result :=false; if (SsmGetChState(channelID) = S_CALL_PENDING) then begin strMessage :='对方已挂机'; InformTrunkStatus(lvofUpdate); SsmStopPlay(channelID); channelState := atsHangOff; Result :=true; end; end; procedure TCXXSHChannel8B.ClearTrunkStatus(); begin channelState := atsFree; oldChannelState := channelState; phoneNumber :=''; dtmfString :=''; strMessage :=''; isConntectd :=false; end; constructor TCXXSHChannel8B.Create(const trunkEvent:TTrunkStatusEvent); begin GetMem(aCallerId,50); Self.OnChannelState := trunkEvent; ...{$IFDEF ThreadChannel} Self.FreeOnTerminate :=true; inherited Create(true); ...{$ENDIF} end; destructor TCXXSHChannel8B.Destroy; begin ChannelHangUp(); Stop(); ...{$IFNDEF ThreadChannel} inherited Destroy(); ...{$ENDIF} InformTrunkStatus(lvofDelete); FreeMem(aCallerId); end; function TCXXSHChannel8B.DialPhone(const DialPhoneNumber:PChar; const PreDialNumber:PChar): boolean; begin Result :=false; if (channelState <> atsFree) then Exit; phoneNumber := DialPhoneNumber; Result := (SsmPickup(channelID) =0); if NOT Result then Exit; Result := (SsmAutoDial(channelID,DialPhoneNumber)=0); if Result then begin isDialOut :=true; channelState := atsCheckSendDial; end; end; function TCXXSHChannel8B.DialPhone( const DialPhoneNumber: PChar): boolean; begin Result := DialPhone(DialPhoneNumber,''); end; ...{$IFDEF ThreadChannel} procedure TCXXSHChannel8B.Execute; begin while NOT Terminated do begin Synchronize(ChannelProcessor); Sleep(10); end; end; ...{$ENDIF} function TCXXSHChannel8B.GetChannelID(): Word; begin Result := channelID; end; function TCXXSHChannel8B.GetChannelStatus(): TTrunkState; begin Result := channelState; end; procedure TCXXSHChannel8B.InformTrunkStatus(const aMsgFlag: TLVOperateFlag); begin if NOT Assigned(OnChannelState) then Exit; aTrunkState.lvFlag := aMsgFlag; aTrunkState.TrunkID := IntToStr(channelID); aTrunkState.TrunkType := Ord(channelType); aTrunkState.TrunkTypeStr := ChannelTypeString[channelType]; aTrunkState.TrunkStep := Ord(channelState); aTrunkState.TrunkStepStr := TrunkStateString[channelState]; aTrunkState.TrunkPhone := phoneNumber; aTrunkState.TrunkData := dtmfString; OnChannelState(aTrunkState); end; procedure TCXXSHChannel8B.ProcessCallInSuccess(); begin end; function TCXXSHChannel8B.SwitchOnCallIn(): boolean; begin SsmPickup(channelID); //摘机 ClearChannelBuffer(); channelState := atsCallInSuccess; Result :=true; end; procedure TCXXSHChannel8B.ProcessDialSuccess(); begin end; procedure TCXXSHChannel8B.CreateCommChannel(const aChennelID: Word); var ct:integer; begin channelID := aChennelID; ct := SsmGetChType(channelID); if (ct <0) then Exit; channelType := TChannelType(ct); ClearTrunkStatus(); InformTrunkStatus(lvofAdd); end; function TCXXSHChannel8B.GetChannelType(): TChannelType; begin Result := channelType; end; function TCXXSHChannel8B.GetDialOut(): boolean; begin Result := isDialOut; end; procedure TCXXSHChannel8B.ProcessCheckDialSend(); begin //三汇卡直接转换状态 channelState := atsDialing; end; procedure TCXXSHChannel8B.Startup(); begin ...{$IFDEF ThreadChannel} Resume(); ...{$ENDIF} end; procedure TCXXSHChannel8B.Stop(); begin ...{$IFDEF ThreadChannel} Suspend(); Terminate(); ...{$ENDIF} end; function TCXXSHChannel8B.CheckDialOutEnabled(): boolean; begin //内线通道、坐席通道、磁石通道和录音通道不支持本SsmPicuup操作 Result := NOT((channelType = ct1) or (channelType = ct2) or (channelType = ct3) or (channelType = ct10)); end; class procedure TCXXSHChannel8B.InformInvodeError; var msgBuffer:PAnsiChar; begin GetMem(msgBuffer,255); try SsmGetLastErrMsg(msgBuffer); //记录异常日志,或者通知用户 //Showmessage(msgBuffer); finally FreeMem(msgBuffer); end; end; function TCXXSHChannel8B.GetTrunkStateBySsm( const ssmState: integer): TTrunkState; begin Result := atsFree; case ssmState of 0: Result := atsFree; 4,5,6,9: Result := atsCallIning; 7: Result := atsHangOff; //8:“断线”状态。只有录音通道才会进入本状态。暂时不处理 //8: Result := atsHangOff; //3: Result := atsCallInSuccess; end; end; procedure TCXXSHChannel8B.ProcessDialOut(); var dState:integer; begin dState := SsmChkAutoDial(channelID); case dState of DIAL_VOICE, DIAL_VOICEF1, DIAL_VOICEF2: begin channelState := atsDialSuccess; isConntectd :=true; end; DIAL_STANDBY, DIAL_NO_DIALTONE, DIAL_ECHO_NOVOICE, DIAL_NOVOICE, DIAL_NOANSWER, DIAL_FAILURE, DIAL_INVALID_PHONUM: begin channelState := atsHangOff; end; end; strMessage :='拨号中...'; end; procedure TCXXSHChannel8B.ClearChannelBuffer(); begin SsmClearRxDTMFBuf(channelID); //清空驱动程序内部的DTMF按键号码接收缓冲区 SsmClearRxBuf(channelID); //清除指定通道ch上MODEM模块的接收缓冲区中的所有数据 //“抢拨” 开关是指当在放音过程中收到对方的DTMF按键字符时,由驱动程序程序立即停止正在进行的放音操作。 //SsmSetDtmfStopPlay(channelID,true); //打开抢拨开关 end; end.