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

来源:互联网 发布:电脑版翻译软件 编辑:程序博客网 时间:2024/05/09 11:30

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.

 




原创粉丝点击