现在的位置: 首页 > 综合 > 正文

Delphi之东进数字语音卡(SS1)可复用源码

2013年06月03日 ⁄ 综合 ⁄ 共 7749字 ⁄ 字号 评论关闭

Delphi之东进数字语音卡(SS1)可复用源码

作者:成晓旭

Bloghttp://blog.csdn.net/cxxsoft

(声明:欢迎转载,请保证文章的完整性)

        由于工作原因,本人将不在从事商业应有软件的开发工作,现在开始逐级“解密”自己以前写的部分自有产权代码,但愿对后来的朋友有点参考、借鉴的价值。

        本代码是本人开发的计划开源的CIT通用平台的东进1号信令数字语言卡封装,设计思路与模拟语音卡的封装非常类似,在此不再赘述。有兴趣的朋友,请参考本人的另外一篇文章《Delphi之东进模拟语音卡(D160A)可复用源码》:http://blog.csdn.net/cxxsoft/archive/2006/08/23/1108211.aspx

        核心思想是一致的:卡、通道分别设计和实现;通道内,核心的还是状态机模式轮巡通道状态来管理硬件卡设备;板卡封装内实现不实现任何业务接口,但允许动态注入实现业务接口的对象,来近一步分发、处理板卡层采集的基础数据。

卡类源代码:

//------------------------------------------------------------------------------
//
//      产品名称:   成晓旭的个人软件Delphi源码库
//      产品版本:   CXXSoft delphi code source lib 2.0
//      模块名称:   Delphi之东进数字语音卡类
//      模块描述:   
//      单元文件:   unDJCardSS1.pas   
//      开发作者:   成晓旭
//      作者blog:   http://blog.csdn.net/CXXSoft
//      备注:       任何人使用此文件时,请保留此段自述文件,谢谢!
//      开发时间:   2005-01-09
//      修改历史:   
//      修改描述:
//------------------------------------------------------------------------------
unit unDJCardSS1;

interface
uses
  Windows,SysUtils,Classes,
  unBaseDefine,
  Tce1_32,
  Tce1_FSK;

type
  TDJCommCardSS1 
= class(TThread)
  
private
    onTrunkEvent:TTrunkSatausEvent;
    onRecEvent:TTrunkReceiveEvent;
    isLoadFSK:boolean;
    CommIsFSK:boolean;
    Trunks:array of TObject;
    function  InitCardForFSK():boolean;
    procedure FreeCardForFSK();
    procedure ThreadKernelProcess();
  
protected
    procedure Execute(); 
override;
  
public
    TotalTrunkNum,InTrunkNum,OutTrunkNum:Word;
    TrunkConnected:array of boolean;

    constructor Create(
const aStateEvent: TTrunkSatausEvent;const aRecEvent:TTrunkReceiveEvent);
    destructor Destroy(); 
override;
    
//初始化中继卡
    function  InitCard(const isFSKComm: boolean): Boolean;
    
//释放中继卡  
    function  FreeCommCard():boolean;
    
//开始运行中继卡管理模块
    procedure StartRunCommModule();
    
//获取一个空闲通道(指定通道类型)
    function  GetAFreeTrunkByType(const aTrunkType:TTrunkType):integer;
    
//获取一个空闲呼出通道
    function  GetAFreeTrunkByOut():integer;
    
//挂断指定通道
    procedure HangOfByTrunkID(const aChannelID:integer);
    
//通过指定通道拨号
    procedure DialPhoneByTrunkID(const aChannelID:integer;const phoneNumber,callerNumber:PChar;const aDevID:integer=-1);
    
//通过指定通道发送数据
    function  SendStringByTrunkID(const aChannelID:integer;const sendBuffer:PChar):boolean;
  end;

implementation

{ TDJCommCardSS1 }
uses
  unDJChannelSS1;

constructor TDJCommCardSS1.Create(
const aStateEvent: TTrunkSatausEvent;
  
const aRecEvent:TTrunkReceiveEvent);
begin
  inherited Create(
true);
  Self.FreeOnTerminate :
= true;
  onTrunkEvent :
= aStateEvent;
  onRecEvent :
= aRecEvent;
end;

destructor TDJCommCardSS1.Destroy();
begin
  Self.Suspend();
  Self.Terminate();
  FreeCommCard();
end;

procedure TDJCommCardSS1.DialPhoneByTrunkID(
const aChannelID: integer;
  
const phoneNumber, callerNumber: PChar;const aDevID:integer);
begin
  
if (aChannelID > ErrTrunkId) and (DJTrk_CheckTrunkFree(aChannelID)) then
    TDJCommChannelsSS1(Trunks[aChannelID]).StartDialPhone(phoneNumber,callerNumber,aDevID,);
end;

procedure TDJCommCardSS1.Execute;
begin
  
while NOT Terminated do
  begin
    Synchronize(ThreadKernelProcess);
    Sleep(
1);
  end;
end;

procedure TDJCommCardSS1.FreeCardForFSK();
begin
  
if CommIsFSK and isLoadFSK then
  begin
    DJFsk_Release();
  end;
end;

function TDJCommCardSS1.FreeCommCard(): boolean;
var
  Loop:Word;
begin
  Sleep(
1000);
  
if TotalTrunkNum > 0 then
  begin
    
for Loop:= 0 to TotalTrunkNum - 1 do
    begin
      
if Assigned(TDJCommChannelsSS1(Trunks[Loop])) then
      begin
        TDJCommChannelsSS1(Trunks[Loop]).Free();
        TDJCommChannelsSS1(Trunks[Loop]) :
= nil;
      end;
    end;
  end;
  DJSys_DisableCard();
  FreeCardForFSK();
  Result :
= true;
end;

function TDJCommCardSS1.GetAFreeTrunkByOut(): integer;
begin
  Result :
= GetAFreeTrunkByType(Type_Export);
end;

function TDJCommCardSS1.GetAFreeTrunkByType(
  
const aTrunkType: TTrunkType): integer;
var
  Loop:Word;
begin
  Result :
= ErrTrunkID;
  
for Loop := 0 to TotalTrunkNum - 1 do
  begin
    
if ((TDJCommChannelsSS1(Trunks[Loop]).GetTrunkType() = aTrunkType)
          and (DJTrk_CheckTrunkFree(Loop))) then
    begin
      Result :
= Loop;
      
break;
    end;
  end;
end;

procedure TDJCommCardSS1.HangOfByTrunkID(
const aChannelID: integer);
begin
  TDJCommChannelsSS1(Trunks[aChannelID]).InOutHangOff();
end;

function TDJCommCardSS1.InitCard(
const isFSKComm: boolean): Boolean;
const
  PromptFile 
= 'Prompt.ini';
var
  Loop: Integer;
  isOK: boolean;
  TimeOfNow: SystemTime;
begin
  Result :
= False;
  CommIsFSK :
= isFSKComm;
  isOK :
=(DJSys_EnableCard('',PromptFile)=_ERR_OK);
  
if Not isOK then exit;
  isOK :
= InitCardForFSK();
  
if NOT isOK then Exit;
  isLoadFSK :
= isOK;
  GetLocalTime(TimeOfNow);
  DJSys_SetSysTime(TimeOfNow.wHour,TimeOfNow.wMinute,TimeOfNow.wSecond);
  TotalTrunkNum:
=DJTrk_GetTotalTrunkNum();
  InTrunkNum:
=TotalTrunkNum shr 1;
  OutTrunkNum:
=TotalTrunkNum - InTrunkNum;

  SetLength(Trunks,TotalTrunkNum);
  SetLength(TrunkConnected,TotalTrunkNum);

  
for Loop:=0 to OutTrunkNum-1 do
    Trunks[Loop]:
=TDJCommChannelsSS1.Create(Self,Loop,Type_Export,CommIsFSK,onTrunkEvent,onRecEvent);
  
for Loop:=OutTrunkNum to TotalTrunkNum-1 do
    Trunks[Loop]:
=TDJCommChannelsSS1.Create(Self,Loop,Type_Import,CommIsFSK,onTrunkEvent,onRecEvent);
  
for Loop:= 0 to TotalTrunkNum - 1 do
  begin
    TDJCommChannelsSS1(Trunks[Loop]).ClearTrunkBuffer(csReceiving);
  end;

  DJSys_AutoApplyDtmf(ENABLEDTMF);    
//自动分配DTMF资源
  DJSys_EnableAutoKB();                 //自动回送KB信号
  isOK:=isOK and DJSys_EnableDtmfSend();
  Result :
= isOK;
end;

function TDJCommCardSS1.InitCardForFSK(): boolean;
var
  k:integer;
begin
  Result :
= true;
  
if CommIsFSK then
  begin
    k :
= DJFsk_InitForFsk(SZK_Mode);
    Result :
= (k = 1);
  end;
end;

function TDJCommCardSS1.SendStringByTrunkID(
const aChannelID: integer;
  
const sendBuffer: PChar):boolean;
begin
  Result :
= TDJCommChannelsSS1(Trunks[aChannelID]).SendString(sendBuffer);
end;

procedure TDJCommCardSS1.StartRunCommModule();
begin
  Resume();
end;

procedure TDJCommCardSS1.ThreadKernelProcess();
var
  Loop:Word;
begin
  DJSys_PushPlay();
  
for Loop := 0 to TotalTrunkNum - 1 do
  begin
    
try
      TDJCommChannelsSS1(Trunks[Loop]).DJChannelProcessor();
    except
    end;
  end;
end;

end.

 

通道类源代码:

//------------------------------------------------------------------------------
//
//      产品名称:   成晓旭的个人软件Delphi源码库
//      产品版本:   CXXSoft delphi code source lib 2.0
//      模块名称:   Delphi之东进数字语音卡通道类
//      模块描述:   
//      单元文件:   unDJChannelSS1.pas   
//      开发作者:   成晓旭
//      作者blog:   http://blog.csdn.net/CXXSoft
//      备注:       任何人使用此文件时,请保留此段自述文件,谢谢!
//      开发时间:   2005-01-09
//      修改历史:   
//      修改描述:
//------------------------------------------------------------------------------
unit unDJChannelSS1;

interface
uses
  Windows, SysUtils,
  unBaseDefine,
  Tce1_32,
  Tce1_FSK,
  unDJCardSS1;
type

  TCXXStatus 
= (csSending,csReceiving,csPlaying);
  
  TDJCommChannelsSS1 
= class(TObject)
  
private
    CommIsFSK:boolean;
    controller:TDJCommCardSS1;
    TrunkID:integer;
    TrunkStep:TTrunkStep;

    MaxBuffer: array [
0..DTMF_BUFFER_SIZE-1] of Char;
    msgChannel:TTrunkStatusInfo;
    msgFrame:TRecCommFrame;

    commFrameNumber,recPos:Word;
    subStatus:TCXXStatus;
    commPhone:
string;
    commFrameStr:
string;

    
//应该进一步优化为注入的接口,非简单的回调句柄
    onTrunkState:TTrunkSatausEvent;
    onRecEvent:TTrunkReceiveEvent;
    InOutType:TTrunkType;

    function  SendDataFromTrunk():boolean;
    function  CheckSendDataEnd():boolean;
    procedure SaveMaxBufferToFrameStr();
    procedure ProcessConnected();
    
//注意:此方法与具体业务的通信协议存在严重依赖关系(IoC实现依赖反转)
    function  CheckReceiveOverFSK(const dataBuffer:array of char;const dataNumber:Word):boolean;
    
//注意:此方法与具体业务的通信协议存在严重依赖关系(IoC实现依赖反转)
    function  CheckReceiveOverDTMF(const dataBuffer:array of char;const dataNumber:Word):boolean;
    function  GetCommData(
const dataBuffer:array of char;const dataNumber:Word):string;
    function  ReceiveDataFromTrunk():boolean;

抱歉!评论已关闭.