Delphi之东进模拟语音卡(D160A)可复用源码

  Delphi之东进模拟语音卡(D160A)可复用源码
  网友急需,先开源吧,文档过几天慢慢补。
  作者:成晓旭
  设计简介:
  1、 将卡、通道分别单独进行设计与封装。
  2、 所有的外部操作接口都封装在卡类这一类。
  3、 在我的项目中,在卡类这一级还增加了适配器或者代理,分别实现了Adapter或Proxy模式;以尽可能地解耦卡设备的实现细节与具体应用业务之间的关系。因为,我们的系统中使用了几家不同的卡设备,另一方面,这些卡设备,在不同的软件系统中,又有不同的业务应用需求。
  4、 当然,卡这一级,也可以实现一个统一的接口,这样对外部可以表现出相对统一的行为,以方便业务层代码的调用,比如说:在数据采集的应用中,统一的接口可以让采集控制层不必依赖于具体的采集设备和通信方式,可以一致地实现数据收发,不管通信方式是RS232、RS485、TCP/IP、PSTN,还是别的方式或者通信设备。
  5、 在通道设计中,核心的就是一个“状态机模式”,通过轮巡通道状态来管理硬件卡设备,并且,还自己设计了一个业务级的“业务状态机”,来抽象业务方面需要关心的“业务状态”,通过增加“业务状态机”这样一个中间层,以解耦业务状态与设备状态之间的依赖。(这一点,在我看到的所有卡厂商提供的各类Demo程序里面都没有这样做,这也无形中误导了很多的开发人员,我看到的所有应用软件开发的源码都是:设备细节、尤其是通道状态,与业务逻辑代码紧紧地耦合在一起,难解难分)。
  6、 此设计的另一个亮点是:IoC模式的应用(2004年自己在设计此类时还不知道这个概念,全凭自己的经验总结出这样的设计)。对通道进入“呼入成功”、“呼出成功”等业务状态的调用代码从通道类是解耦出来:设计一个接口,在各个业务状态的处理方法中,再调用接口方法,将具体的业务处理逻辑委托给实现此接口的对象。并且这个接口的实现是通过“依赖注入”实现IoC的。这样设计,就达到了很好的可复用性和灵活性。
  7、 当然,更好的实现可以采用AOP(面向方法编程)的思想或者实现技术,这样可复用性更好,如此设计,在业务与卡方法的调用之间,耦合度将是最低的。
  8、 目前的版本,没有在代码中体现接口的实现……
  9、 类图(以后补上):
   10、卡类源码:
  
王朝网络
//------------------------------------------------------------------------------
  
王朝网络
//
  
王朝网络
// 产品名称: 成晓旭的个人软件Delphi源码库
  
王朝网络
// 产品版本: CXXSoft delphi code source lib 2.0
  
王朝网络
// 模块名称: Delphi之东进模拟语音卡类
  
王朝网络
// 模块描述:
  
王朝网络
// 单元文件: unDJCard160A.pas
  
王朝网络
// 开发作者: 成晓旭
  
王朝网络
// 备注: 任何人使用此文件时,请保留此段自述文件,谢谢!
  
王朝网络
// 开发时间: 2004-08-03
  
王朝网络
// 修改历史:
  
王朝网络
// 修改描述:
  
王朝网络
//------------------------------------------------------------------------------
  
王朝网络
unit unDJCard160A;
  
王朝网络

  
王朝网络
interface
  
王朝网络
uses
  
王朝网络
Windows,
  
王朝网络
unDJTC08a32,unDJNewSig,
  
王朝网络
unBaseDefine,unDJ160ADefine,
  
王朝网络
unDJChanne160A;
  
王朝网络
type
  
王朝网络
TCXXCommCard160A = class(TObject)
  
王朝网络
private
  
王朝网络

  
王朝网络
ChannelNumber:Word;
  
王朝网络
channelObject:array of TCXXDJChannel160A;
  
王朝网络
OnCardChannelState:TTrunkStatusEvent;
  
王朝网络

  
王朝网络
procedure Stop();
  
王朝网络
procedure ReleaseCommDevice();
  
王朝网络
function GetChannelObjectOrder(const aChannelID:Word):Word;
  
王朝网络

  
王朝网络
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
  
王朝网络

  
王朝网络
王朝网络
...{ TCXXCommCard160A }
  
王朝网络
constructor TCXXCommCard160A.Create(const trunkEvent:TTrunkStatusEvent);
  
王朝网络
begin
  
王朝网络
ChannelNumber := 0;
  
王朝网络
Self.OnCardChannelState := trunkEvent;
  
王朝网络
end;
  
王朝网络

  
王朝网络
destructor TCXXCommCard160A.Destroy;
  
王朝网络
var
  
王朝网络
Loop:Word;
  
王朝网络
begin
  
王朝网络
Stop();
  
王朝网络
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 TCXXCommCard160A.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 TCXXCommCard160A.ReleaseCommDevice();
  
王朝网络
begin
  
王朝网络
DisableCard();
  
王朝网络
FreeDrv();
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXCommCard160A.GetAFreeChannel(): Word;
  
王朝网络
var
  
王朝网络
Loop:Word;
  
王朝网络
begin
  
王朝网络
Result := ErrorTrunkNumber;
  
王朝网络
for Loop := Low(channelObject) to High(channelObject) do
  
王朝网络
begin
  
王朝网络
if (channelObject[Loop].GetChannelType() = ctEmpty) then continue;
  
王朝网络
if (channelObject[Loop].GetChannelStatus() = atsFree) then
  
王朝网络
begin
  
王朝网络
Result := channelObject[Loop].GetChannelID();
  
王朝网络

  break;
  
王朝网络
end;
  
王朝网络
end;
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXCommCard160A.GetChannelNumber(): Word;
  
王朝网络
begin
  
王朝网络
Result := channelNumber;
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXCommCard160A.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 TCXXCommCard160A.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 TCXXCommCard160A.LoadCommDevice(const loadAll:boolean): boolean;
  
王朝网络
const
  
王朝网络
loadEmpty = true;
  
王朝网络
var
  
王朝网络
Loop,tempNumber:Word;
  
王朝网络
isFlag:LongInt;
  
王朝网络
function CheckLoadTrunk():boolean;
  
王朝网络
begin
  
王朝网络
Result := loadAll or ((NOT loadAll) and(TChannelType(CheckChType(Loop)) <> ctEmpty));
  
王朝网络
end;
  
王朝网络
begin
  
王朝网络
isFlag := LoadDRV();
  
王朝网络
Result := (isFlag=0);
  
王朝网络
if NOT Result then Exit;
  
王朝网络
tempNumber := CheckValidCh();
  
王朝网络
Result := EnableCard(tempNumber,1024*8)=0;
  
王朝网络
if NOT Result then
  
王朝网络
begin
  
王朝网络
FreeDrv();
  
王朝网络
Exit;
  
王朝网络
end;
  
王朝网络
Result := Sig_Init()=1;
  
王朝网络
if NOT Result then Exit;
  
王朝网络
SetBusyPara(700);
  
王朝网络
SetPackRate(PACK_64KBPS );
  
王朝网络
channelNumber := tempNumber;
  
王朝网络
SetLength(channelObject,channelNumber);
  
王朝网络
for Loop := 0 to channelNumber - 1 do
  
王朝网络
begin
  
王朝网络
if CheckLoadTrunk() then
  
王朝网络
begin
  
王朝网络
channelObject[Loop] := TCXXDJChannel160A.Create(OnCardChannelState);
  
王朝网络
channelObject[Loop].CreateCommChannel(Loop);
  
王朝网络
end;
  
王朝网络
end;
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXCommCard160A.Startup(): boolean;
  
王朝网络
var
  
王朝网络
Loop:integer;
  
王朝网络
begin
  
王朝网络
for Loop := 0 to channelNumber - 1 do
  
王朝网络
begin
  
王朝网络
channelObject[Loop].Resume();
  
王朝网络
end;
  
王朝网络
Result := true;
  
王朝网络
end;
  
王朝网络

  
王朝网络
procedure TCXXCommCard160A.Stop();
  
王朝网络
var
  
王朝网络
Loop:integer;
  
王朝网络
begin
  
王朝网络
for Loop := 0 to channelNumber - 1 do
  
王朝网络
begin
  
王朝网络
channelObject[Loop].Suspend();
  
王朝网络
channelObject[Loop].Terminate();
  
王朝网络
channelObject[Loop] := nil;
  
王朝网络
end;
  
王朝网络
end;
  
王朝网络

  
王朝网络
end.
  
王朝网络

  11、 通道类源码:
  
王朝网络
//------------------------------------------------------------------------------
  
王朝网络
//
  
王朝网络
// 产品名称: 成晓旭的个人软件Delphi源码库
  
王朝网络
// 产品版本: CXXSoft delphi code source lib 2.0
  
王朝网络
// 模块名称: Delphi之东进模拟语音卡通道类
  
王朝网络
// 模块描述:
  
王朝网络
// 单元文件: unDJChanne160A.pas
  
王朝网络
// 开发作者: 成晓旭
  
王朝网络
// 备注: 任何人使用此文件时,请保留此段自述文件,谢谢!
  
王朝网络
// 开发时间: 2004-08-03
  
王朝网络
// 修改历史:
  
王朝网络
// 修改描述:
  
王朝网络
//------------------------------------------------------------------------------
  
王朝网络
unit unDJChanne160A;
  
王朝网络

  
王朝网络
interface
  
王朝网络

  
王朝网络
uses
  
王朝网络
Windows,Classes,SysUtils,
  
王朝网络
unBaseDefine,unDJ160ADefine,
  
王朝网络
unDJTC08a32,unDJNewSig;
  
王朝网络
Type
  
王朝网络
TCXXDJChannel160A = class(TThread)
  
王朝网络
//TCXXDJChannel160A = class(TObject)
  
王朝网络
private
  
王朝网络
channelType:TChannelType;
  
王朝网络
oldChannelState,channelState:TTrunkState;
  
王朝网络
channelID:Word;
  
王朝网络
phoneNumber:string;
  
王朝网络
dtmfString:string;
  
王朝网络

  
王朝网络
isConntectd:boolean;
  
王朝网络

  
王朝网络
isDialOut:boolean;
  
王朝网络
aTrunkState:TTrunkStatus;
  
王朝网络

  
王朝网络
procedure InformTrunkStatus(const aMsgFlag: TLVOperateFlag);
  
王朝网络

  
王朝网络
procedure ClearTrunkStatus();
  
王朝网络
function CheckSigHangup():boolean;
  
王朝网络
function CheckCallIn():boolean;
  
王朝网络
function SwitchOnCallIn():boolean;
  
王朝网络

  
王朝网络
procedure ProcessCallInSuccess();
  
王朝网络
procedure ProcessDialSuccess();
  
王朝网络

  
王朝网络
procedure ProcessCheckDialSend();
  
王朝网络
protected
  
王朝网络
procedure Execute(); override;
  
王朝网络
public
  
王朝网络
strMessage:string;
  
王朝网络
OnChannelState:TTrunkStatusEvent;
  
王朝网络

  
王朝网络
constructor Create(const trunkEvent:TTrunkStatusEvent);
  
王朝网络
destructor Destroy();override;
  
王朝网络

  
王朝网络
procedure CreateCommChannel(const aChennelID: Word);
  
王朝网络
procedure ChannelProcessor();
  
王朝网络

  
王朝网络
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;
  
王朝网络
end;
  
王朝网络
implementation
  
王朝网络

  
王朝网络
王朝网络
...{ TCXXDJChannel160A }
  
王朝网络

  
王朝网络
procedure TCXXDJChannel160A.ChannelHangUp();
  
王朝网络
begin
  
王朝网络
isDialOut := false;
  
王朝网络
StopSigCheck(channelID);
  
王朝网络
HangUp(channelID);
  
王朝网络
Sig_ResetCheck(channelID);
  
王朝网络
StartSigCheck(channelID);
  
王朝网络
InitDTMFBuf(channelID);
  
王朝网络
ClearTrunkStatus();
  
王朝网络
InformTrunkStatus(lvofUpdate);
  
王朝网络
end;
  
王朝网络

  
王朝网络
procedure TCXXDJChannel160A.ChannelProcessor();
  
王朝网络
var
  
王朝网络
dState:Word;
  
王朝网络
begin
  
王朝网络
PUSH_PLAY();
  
王朝网络
FeedSigFunc();
  
王朝网络
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
  
王朝网络
dState := Sig_CheckDial(channelID);
  
王朝网络
case dState of
  
王朝网络
// S_NORESULT:
  
王朝网络
S_CONNECT:
  
王朝网络
begin
  
王朝网络
channelState := atsDialSuccess;
  
王朝网络
isConntectd := true;
  
王朝网络
end;
  
王朝网络
S_BUSY,
  
王朝网络
S_NOBODY,
  
王朝网络
S_NODIALSIG,
  
王朝网络
S_NOSIGNAL:
  
王朝网络
begin
  
王朝网络
channelState := atsHangOff;
  
王朝网络
end;
  
王朝网络
end;
  
王朝网络
strMessage := '拨号中...';
  
王朝网络
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 TCXXDJChannel160A.CheckCallIn(): boolean;
  
王朝网络
begin
  
王朝网络
Result := RingDetect(channelID);
  
王朝网络
if Result then
  
王朝网络
begin
  
王朝网络
OffHook(channelID);
  
王朝网络
if isDialOut then
  
王朝网络
channelState := atsDialSuccess
  
王朝网络
else
  
王朝网络
channelState := atsCallIning;
  
王朝网络
end;
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXDJChannel160A.CheckSigHangup(): boolean;
  
王朝网络
begin
  
王朝网络
Result := false;
  
王朝网络
if (Sig_CheckBusy(channelID)=1) then
  
王朝网络
begin
  
王朝网络
strMessage := '对方已挂机';
  
王朝网络
InformTrunkStatus(lvofUpdate);
  
王朝网络
StopPlayFile(channelID);
  
王朝网络
channelState := atsHangOff;
  
王朝网络
Result := true;
  
王朝网络
end;
  
王朝网络
end;
  
王朝网络

  
王朝网络
procedure TCXXDJChannel160A.ClearTrunkStatus();
  
王朝网络
begin
  
王朝网络
channelState := atsFree;
  
王朝网络
oldChannelState := channelState;
  
王朝网络
phoneNumber := '';
  
王朝网络
dtmfString := '';
  
王朝网络
strMessage := '';
  
王朝网络
isConntectd := false;
  
王朝网络
end;
  
王朝网络

  
王朝网络
constructor TCXXDJChannel160A.Create(const trunkEvent:TTrunkStatusEvent);
  
王朝网络
begin
  
王朝网络
Self.OnChannelState := trunkEvent;
  
王朝网络
Self.FreeOnTerminate := true;
  
王朝网络
inherited Create(true);
  
王朝网络
end;
  
王朝网络

  
王朝网络

  
王朝网络
destructor TCXXDJChannel160A.Destroy;
  
王朝网络
begin
  
王朝网络
Suspend();
  
王朝网络
ChannelHangUp();
  
王朝网络
//inherited Destroy();
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXDJChannel160A.DialPhone(const DialPhoneNumber:PChar;
  
王朝网络
const PreDialNumber:PChar): boolean;
  
王朝网络
begin
  
王朝网络
isDialOut := true;
  
王朝网络
phoneNumber := DialPhoneNumber;
  
王朝网络
OffHook(channelID);
  
王朝网络
InitDTMFBuf(channelID);
  
王朝网络
Result := Sig_StartDial(channelID,DialPhoneNumber,PreDialNumber,0)=1;
  
王朝网络
channelState := atsCheckSendDial;
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXDJChannel160A.DialPhone(
  
王朝网络
const DialPhoneNumber: PChar): boolean;
  
王朝网络
begin
  
王朝网络
Result := DialPhone(DialPhoneNumber,'');
  
王朝网络
end;
  
王朝网络

  
王朝网络
procedure TCXXDJChannel160A.Execute;
  
王朝网络
begin
  
王朝网络
while NOT Terminated do
  
王朝网络
begin
  
王朝网络
Synchronize(ChannelProcessor);
  
王朝网络
Sleep(10);
  
王朝网络
end;
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXDJChannel160A.GetChannelID(): Word;
  
王朝网络
begin
  
王朝网络
Result := channelID;
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXDJChannel160A.GetChannelStatus(): TTrunkState;
  
王朝网络
begin
  
王朝网络
Result := channelState;
  
王朝网络
end;
  
王朝网络

  
王朝网络
procedure TCXXDJChannel160A.InformTrunkStatus(const aMsgFlag: TLVOperateFlag);
  
王朝网络
begin
  
王朝网络
aTrunkState.lvFlag := aMsgFlag;
  
王朝网络
aTrunkState.TrunkID := IntToStr(channelID);
  
王朝网络
aTrunkState.TrunkType := channelType;
  
王朝网络
aTrunkState.TrunkTypeStr := ChannelTypeString[channelType];
  
王朝网络
aTrunkState.TrunkStep := channelState;
  
王朝网络
aTrunkState.TrunkStepStr := TrunkStateString[channelState];
  
王朝网络
aTrunkState.TrunkPhone := phoneNumber;
  
王朝网络
aTrunkState.TrunkData := dtmfString;
  
王朝网络
OnChannelState(aTrunkState);
  
王朝网络
end;
  
王朝网络

  
王朝网络
procedure TCXXDJChannel160A.ProcessCallInSuccess();
  
王朝网络
begin
  
王朝网络

  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXDJChannel160A.SwitchOnCallIn(): boolean;
  
王朝网络
begin
  
王朝网络
OffHook(channelID);
  
王朝网络
InitDTMFBuf(channelID);
  
王朝网络
StartSigCheck(channelID);
  
王朝网络
channelState := atsCallInSuccess;
  
王朝网络
Result := true;
  
王朝网络
end;
  
王朝网络

  
王朝网络
procedure TCXXDJChannel160A.ProcessDialSuccess();
  
王朝网络
begin
  
王朝网络

  
王朝网络
end;
  
王朝网络

  
王朝网络
procedure TCXXDJChannel160A.CreateCommChannel(const aChennelID: Word);
  
王朝网络
begin
  
王朝网络
channelID := aChennelID;
  
王朝网络
channelType := TChannelType(CheckChType(channelID));
  
王朝网络
ClearTrunkStatus();
  
王朝网络
InformTrunkStatus(lvofAdd);
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXDJChannel160A.GetChannelType(): TChannelType;
  
王朝网络
begin
  
王朝网络
Result := channelType;
  
王朝网络
end;
  
王朝网络

  
王朝网络
function TCXXDJChannel160A.GetDialOut(): boolean;
  
王朝网络
begin
  
王朝网络
Result := isDialOut;
  
王朝网络
end;
  
王朝网络

  
王朝网络
procedure TCXXDJChannel160A.ProcessCheckDialSend();
  
王朝网络
begin
  
王朝网络
if(CheckSendEnd(channelID) = 1) then
  
王朝网络
begin
  
王朝网络
StartSigCheck(channelID);
  
王朝网络
channelState := atsDialing;
  
王朝网络
end;
  
王朝网络
end;
  
王朝网络

  
王朝网络
end.
  
王朝网络