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

<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog336280.html" frameborder="0" width="336" scrolling="no" height="280"></iframe>

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源码库
// 产品版本:CXXSoftdelphicodesourcelib2.0
// 模块名称:Delphi之三汇模拟语音卡类
// 模块描述:
// 单元文件:unSHCard8B.pas
// 开发作者:成晓旭
// 备注:任何人使用此文件时,请保留此段自述文件,谢谢!
// 开发时间:2003-12-03
// 修改历史:
// 修改描述:
// ------------------------------------------------------------------------------
unitunSHCard8B;

interface
uses
Windows,
// unDJTC08a32,unDJNewSig,
unBaseDefine,
// unDJ160ADefine,unDJChanne160A,
unShpa3api,unSHChanne18B,unSH8BDefine;
type
TCXXCommCard8B
= class (TObject)
private

ChannelNumber:Word;
channelObject:arrayofTCXXSHChannel8B;
OnCardChannelState:TTrunkStatusEvent;

procedureReleaseCommDevice();
functionGetChannelObjectOrder(
const aChannelID:Word):Word;
functionInitChannel():
boolean ;
public

constructorCreate(
const trunkEvent:TTrunkStatusEvent);
destructorDestroy();override;

functionLoadCommDevice(
const loadAll: boolean = false ): boolean ;
functionStartup():
boolean ;
functionGetAFreeChannel():Word;
functionGetChannelNumber():Word;
functionDialPhone(
const aChannelID:Word; const DialPhoneNumber:PChar): boolean ;
functionHangUp(
const aChannelID:Word): boolean ;

end;


implementation

const
SH_ConfigFile
= ' C:ShCtiShConfig.ini ' ;
SH_IndexFile
= ' C:ShCtiShIndex.ini ' ;

... {TCXXCommCard8B}
constructorTCXXCommCard8B.Create(
const trunkEvent:TTrunkStatusEvent);
begin
ChannelNumber:
= 0 ;
Self.OnCardChannelState:
= trunkEvent;
end;

destructorTCXXCommCard8B.Destroy;
var
Loop:Word;
begin
if (Length(channelObject) > 0 )and(channelNumber > 0 )then
begin
for Loop: = 0 toChannelNumber - 1 do
begin
if Assigned(channelObject[Loop])then
begin
channelObject[Loop].Free();
channelObject[Loop]:
= nil;
end;
end;
end;
ReleaseCommDevice();
end;

functionTCXXCommCard8B.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;

procedureTCXXCommCard8B.ReleaseCommDevice();
begin
SsmCloseCti();
end;

functionTCXXCommCard8B.GetAFreeChannel():Word;
var
Loop:Word;
begin
Result:
= ErrorTrunkNumber;
for Loop: = Low(channelObject)toHigh(channelObject) do
begin
if NOTchannelObject[Loop].CheckDialOutEnabled()then continue ;
if (channelObject[Loop].GetChannelStatus() = atsFree)then
begin
Result:
= channelObject[Loop].GetChannelID();
break ;
end;
end;
end;

functionTCXXCommCard8B.GetChannelNumber():Word;
begin
Result:
= channelNumber;
end;

functionTCXXCommCard8B.GetChannelObjectOrder(
const aChannelID:Word):Word;
var
Loop:Word;
begin
Result:
= ErrorTrunkNumber;
for Loop: = Low(channelObject)toHigh(channelObject) do
begin
if (channelObject[Loop].GetChannelID = aChannelID)then
begin
Result:
= Loop;
break ;
end;
end;
end;

functionTCXXCommCard8B.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;

functionTCXXCommCard8B.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;

functionTCXXCommCard8B.Startup():
boolean ;
var
Loop:integer;
begin
for Loop: = 0 tochannelNumber - 1 do
begin
channelObject[Loop].Startup();
end;
Result:
= true ;
end;

functionTCXXCommCard8B.InitChannel():
boolean ;
var
number,Loop:integer;
begin
Result:
= false ;
number:
= SsmGetMaxCh();
if (number 0)thenExit;
ChannelNumber:
=number;
SetLength(channelObject,channelNumber);
forLoop:=0tochannelNumber-1do
begin
channelObject[Loop]:
=TCXXSHChannel8B.Create(OnCardChannelState);
channelObject[Loop].CreateCommChannel(Loop);
end;
Result:
=true;
end;

end.

6、 通道类源码:

// ------------------------------------------------------------------------------
//
// 产品名称:成晓旭的个人软件Delphi源码库
// 产品版本:CXXSoftdelphicodesourcelib2.0
// 模块名称:Delphi之三汇模拟语音卡通道类
// 模块描述:
// 单元文件:unSHChanne18B.pas
// 开发作者:成晓旭
// 备注:任何人使用此文件时,请保留此段自述文件,谢谢!
// 开发时间:2003-12-01
// 修改历史:
// 修改描述:
// ------------------------------------------------------------------------------
unitunSHChanne18B;

... {$DEFINEThreadChannel}

interface

uses
Windows,Classes,SysUtils,

unBaseDefine,unShpa3api,unSH8BDefine,
// unDJ160ADefine,
unDJTC08a32,unDJNewSig;

Type


... {$IFDEFThreadChannel}
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;

procedureChannelProcessor();
procedureInformTrunkStatus(
const aMsgFlag:TLVOperateFlag);

procedureClearTrunkStatus();
procedureClearChannelBuffer();
functionCheckSigHangup():
boolean ;
functionCheckCallIn():
boolean ;
functionSwitchOnCallIn():
boolean ;

procedureProcessCallInSuccess();
procedureProcessDialSuccess();

procedureProcessCheckDialSend();
procedureProcessDialOut();

procedureStop();

// 三汇卡专用方法
functionGetTrunkStateBySsm( const ssmState:integer):TTrunkState;
protected
... {$IFDEFThreadChannel}
procedureExecute();override;
... {$ENDIF}
public
strMessage:string;
OnChannelState:TTrunkStatusEvent;

constructorCreate(
const trunkEvent:TTrunkStatusEvent);
destructorDestroy();override;

procedureCreateCommChannel(
const aChennelID:Word);
procedureStartup();

functionGetChannelID():Word;
functionGetChannelStatus():TTrunkState;
functionGetChannelType():TChannelType;
functionDialPhone(
const DialPhoneNumber:PChar): boolean ;overload;
functionDialPhone(
const DialPhoneNumber:PChar; const PreDialNumber:PChar): boolean ;overload;
procedureChannelHangUp();

functionGetDialOut():
boolean ;

// 三汇卡特性方法
functionCheckDialOutEnabled(): boolean ;
class procedureInformInvodeError();
end;
implementation

... {TCXXSHChannel8B}

procedureTCXXSHChannel8B.ChannelHangUp();
begin
isDialOut:
= false ;
SsmHangUp(channelID);
ClearChannelBuffer();
ClearTrunkStatus();
InformTrunkStatus(lvofUpdate);
end;

procedureTCXXSHChannel8B.ChannelProcessor();
var
ssmState:integer;
begin
// ssmState:=SsmGetChState(channelID);
// channelState:=GetTrunkStateBySsm(ssmState);
CheckCallIn();
case channelStateof
atsFree:
begin
//
end;
atsCallIning:
begin
SwitchOnCallIn();
end;
atsCallInSuccess:
begin
if CheckSigHangup()thenExit;
ProcessCallInSuccess();
end;
atsCheckSendDial:
begin
ProcessCheckDialSend();
end;
atsDialing:
begin
ProcessDialOut();
end;
atsDialSuccess:
begin
if CheckSigHangup()thenExit;
ProcessDialSuccess();
strMessage:
= ' 拨号成功 ' ;
end;
atsHangOff:
begin
ChannelHangUp();
end;
end;
if (oldChannelState channelState)then
begin
oldChannelState:
= channelState;
InformTrunkStatus(lvofUpdate);
end;
end;

functionTCXXSHChannel8B.CheckCallIn():
boolean ;
begin
Result:
= false ;
if (SsmGetChState(channelID) = 2 )then // 检测到振铃信号
begin
SsmGetCallerId(channelID,aCallerId);
// 取出CALLERID信息
channelState: = atsCallIning;
Result:
= true ;
end;
... {
Result:
=RingDetect(channelID);
ifResultthen
begin
OffHook(channelID);
ifisDialOutthen
channelState:
=atsDialSuccess
else
channelState:
=atsCallIning;
end;
}

end;

functionTCXXSHChannel8B.CheckSigHangup():
boolean ;
begin
Result:
= false ;
if (SsmGetChState(channelID) = S_CALL_PENDING)then
begin
strMessage:
= ' 对方已挂机 ' ;
InformTrunkStatus(lvofUpdate);
SsmStopPlay(channelID);
channelState:
= atsHangOff;
Result:
= true ;
end;
end;

procedureTCXXSHChannel8B.ClearTrunkStatus();
begin
channelState:
= atsFree;
oldChannelState:
= channelState;
phoneNumber:
= '' ;
dtmfString:
= '' ;
strMessage:
= '' ;
isConntectd:
= false ;
end;

constructorTCXXSHChannel8B.Create(
const trunkEvent:TTrunkStatusEvent);
begin
GetMem(aCallerId,
50 );
Self.OnChannelState:
= trunkEvent;
... {$IFDEFThreadChannel}
Self.FreeOnTerminate:
= true ;
inheritedCreate(
true );
... {$ENDIF}
end;


destructorTCXXSHChannel8B.Destroy;
begin
ChannelHangUp();
Stop();
... {$IFNDEFThreadChannel}
inheritedDestroy();
... {$ENDIF}
InformTrunkStatus(lvofDelete);
FreeMem(aCallerId);
end;

functionTCXXSHChannel8B.DialPhone(
const DialPhoneNumber:PChar;
const PreDialNumber:PChar): boolean ;
begin
Result:
= false ;
if (channelState atsFree)thenExit;
phoneNumber:
= DialPhoneNumber;
Result:
= (SsmPickup(channelID) = 0 );
if NOTResultthenExit;
Result:
= (SsmAutoDial(channelID,DialPhoneNumber) = 0 );
if Resultthen
begin
isDialOut:
= true ;
channelState:
= atsCheckSendDial;
end;
end;

functionTCXXSHChannel8B.DialPhone(
const DialPhoneNumber:PChar): boolean ;
begin
Result:
= DialPhone(DialPhoneNumber, '' );
end;

... {$IFDEFThreadChannel}
procedureTCXXSHChannel8B.Execute;
begin
while NOTTerminated do
begin
Synchronize(ChannelProcessor);
Sleep(
10 );
end;
end;
... {$ENDIF}

functionTCXXSHChannel8B.GetChannelID():Word;
begin
Result:
= channelID;
end;

functionTCXXSHChannel8B.GetChannelStatus():TTrunkState;
begin
Result:
= channelState;
end;

procedureTCXXSHChannel8B.InformTrunkStatus(
const aMsgFlag:TLVOperateFlag);
begin
if NOTAssigned(OnChannelState)thenExit;
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;

procedureTCXXSHChannel8B.ProcessCallInSuccess();
begin

end;

functionTCXXSHChannel8B.SwitchOnCallIn():
boolean ;
begin
SsmPickup(channelID);
// 摘机
ClearChannelBuffer();
channelState:
= atsCallInSuccess;
Result:
= true ;
end;

procedureTCXXSHChannel8B.ProcessDialSuccess();
begin

end;

procedureTCXXSHChannel8B.CreateCommChannel(
const aChennelID:Word);
var
ct:integer;
begin
channelID:
= aChennelID;
ct:
= SsmGetChType(channelID);
if (ct 0)thenExit;
channelType:
=TChannelType(ct);
ClearTrunkStatus();
InformTrunkStatus(lvofAdd);
end;

functionTCXXSHChannel8B.GetChannelType():TChannelType;
begin
Result:
=channelType;
end;

functionTCXXSHChannel8B.GetDialOut():
boolean;
begin
Result:
=isDialOut;
end;

procedureTCXXSHChannel8B.ProcessCheckDialSend();
begin
//三汇卡直接转换状态
channelState:=atsDialing;
end;

procedureTCXXSHChannel8B.Startup();
begin
...{$IFDEFThreadChannel}
Resume();
...{$ENDIF}
end;

procedureTCXXSHChannel8B.Stop();
begin
...{$IFDEFThreadChannel}
Suspend();
Terminate();
...{$ENDIF}
end;

functionTCXXSHChannel8B.CheckDialOutEnabled():
boolean;
begin
//内线通道、坐席通道、磁石通道和录音通道不支持本SsmPicuup操作
Result:=NOT((channelType=ct1)or
(channelType
=ct2)or
(channelType
=ct3)or
(channelType
=ct10));
end;

classprocedureTCXXSHChannel8B.InformInvodeError;
var
msgBuffer:PAnsiChar;
begin
GetMem(msgBuffer,
255);
try
SsmGetLastErrMsg(msgBuffer);
//记录异常日志,或者通知用户
//Showmessage(msgBuffer);
finally
FreeMem(msgBuffer);
end;
end;

functionTCXXSHChannel8B.GetTrunkStateBySsm(
constssmState:integer):TTrunkState;
begin
Result:
=atsFree;
casessmStateof
0:Result:=atsFree;
4,5,6,9:Result:=atsCallIning;
7:Result:=atsHangOff;
//8:“断线”状态。只有录音通道才会进入本状态。暂时不处理
//8:Result:=atsHangOff;
//3:Result:=atsCallInSuccess;
end;
end;

procedureTCXXSHChannel8B.ProcessDialOut();
var
dState:integer;
begin
dState:
=SsmChkAutoDial(channelID);
casedStateof
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;

procedureTCXXSHChannel8B.ClearChannelBuffer();
begin
SsmClearRxDTMFBuf(channelID);
//清空驱动程序内部的DTMF按键号码接收缓冲区
SsmClearRxBuf(channelID);//清除指定通道ch上MODEM模块的接收缓冲区中的所有数据
//“抢拨”开关是指当在放音过程中收到对方的DTMF按键字符时,由驱动程序程序立即停止正在进行的放音操作。
//SsmSetDtmfStopPlay(channelID,true);//打开抢拨开关
end;

end.




你可能感兴趣的:(Delphi)