您的位置:首页 > 编程语言 > Delphi

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

2007-10-29 10:31 399 查看
2006年08月23日 10:36:00
[align=center]Delphi之东进模拟语音卡(D160A)可复用源码[/align][b]作者:成晓旭Bloghttp://blog.csdn.net/cxxsoft(声明:欢迎转载,请保证文章的完整性)[/b][align=center][/align]设计简介: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.


[align=left]11、 通道类源码:[/align]

//------------------------------------------------------------------------------


//


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



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1108211
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: