Delphi之三汇模拟语音卡(SHT-8B/PCI/FAX)可复用源码

Delphi之三汇模拟语音卡(SHT-8B/PCI/FAX)可复用源码

作者:成晓旭

设计简介:

1、   设计思路请参考本站Blog的另一篇文章:“Delphi之东进模拟语音卡(D160A)可复用源码”;链接http://blog.csdn.net/CXXSoft/archive/2006/08/23/1108211.aspx

2、   其实,仔细对比,你会发现这两种卡的代码类方法签名几乎99%是一样的,也就是说,这两都之间,还需要更进一步的抽象,以解决“重复代码”或者“相似代码”的问题。

3、   更高层次的抽象,请参考我的设计文档。

4、   类图(以后补上)

5、   卡类源码:

 

// ------------------------------------------------------------------------------
//
//       产品名称:   成晓旭的个人软件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  -   1   do
    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  -   1   do
  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  -   1   do
  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.

 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1206497


你可能感兴趣的:(Delphi)