分享
 
 
 

Delphi之東進模擬語音卡(D160A)可復用源碼

王朝delphi·作者佚名  2007-09-15
窄屏简体版  字體: |||超大  

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.

 
 
 
免責聲明:本文為網絡用戶發布,其觀點僅代表作者個人觀點,與本站無關,本站僅提供信息存儲服務。文中陳述內容未經本站證實,其真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考,並請自行核實相關內容。
2023年上半年GDP全球前十五強
 百态   2023-10-24
美眾議院議長啟動對拜登的彈劾調查
 百态   2023-09-13
上海、濟南、武漢等多地出現不明墜落物
 探索   2023-09-06
印度或要將國名改為「巴拉特」
 百态   2023-09-06
男子為女友送行,買票不登機被捕
 百态   2023-08-20
手機地震預警功能怎麽開?
 干货   2023-08-06
女子4年賣2套房花700多萬做美容:不但沒變美臉,面部還出現變形
 百态   2023-08-04
住戶一樓被水淹 還衝來8頭豬
 百态   2023-07-31
女子體內爬出大量瓜子狀活蟲
 百态   2023-07-25
地球連續35年收到神秘規律性信號,網友:不要回答!
 探索   2023-07-21
全球鎵價格本周大漲27%
 探索   2023-07-09
錢都流向了那些不缺錢的人,苦都留給了能吃苦的人
 探索   2023-07-02
倩女手遊刀客魅者強控制(強混亂強眩暈強睡眠)和對應控制抗性的關系
 百态   2020-08-20
美國5月9日最新疫情:美國確診人數突破131萬
 百态   2020-05-09
荷蘭政府宣布將集體辭職
 干货   2020-04-30
倩女幽魂手遊師徒任務情義春秋猜成語答案逍遙觀:鵬程萬裏
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案神機營:射石飲羽
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案昆侖山:拔刀相助
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案天工閣:鬼斧神工
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案絲路古道:單槍匹馬
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案鎮郊荒野:與虎謀皮
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案鎮郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案鎮郊荒野:指鹿為馬
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案金陵:小鳥依人
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案金陵:千金買鄰
 干货   2019-11-12
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有