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

2006年09月11日 08:47:00

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

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

ChannelNumber:Word;
channelObject:array of TCXXSHChannel8B;
OnCardChannelState:TTrunkStatusEvent;

procedure ReleaseCommDevice();
function GetChannelObjectOrder(
const aChannelID:Word):Word;
function InitChannel():
boolean ;
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

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

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

destructor TCXXCommCard8B.Destroy;
var
Loop:Word;
begin
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 TCXXCommCard8B.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 TCXXCommCard8B.ReleaseCommDevice();
begin
SsmCloseCti() ;
end;

function TCXXCommCard8B.GetAFreeChannel(): Word;
var
Loop:Word;
begin
Result :
= ErrorTrunkNumber;
for Loop : = Low(channelObject) to High(channelObject) do
begin
if NOT channelObject[Loop].CheckDialOutEnabled() then continue ;
if (channelObject[Loop].GetChannelStatus() = atsFree) then
begin
Result :
= channelObject[Loop].GetChannelID();
break ;
end;
end;
end;

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

function TCXXCommCard8B.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 TCXXCommCard8B.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 TCXXCommCard8B.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;

function TCXXCommCard8B.Startup():
boolean ;
var
Loop:integer;
begin
for Loop : = 0 to channelNumber - 1 do
begin
channelObject[Loop].Startup();
end;
Result :
= true ;
end;

function TCXXCommCard8B.InitChannel():
boolean ;
var
number,Loop:integer;
begin
Result :
= false ;
number :
= SsmGetMaxCh();
if (number > 0 ) then Exit;
ChannelNumber :
= number;
SetLength(channelObject,channelNumber);
for Loop : = 0 to channelNumber - 1 do
begin
channelObject[Loop] :
= TCXXSHChannel8B.Create(OnCardChannelState);
channelObject[Loop].CreateCommChannel(Loop);
end;
Result :
= true ;
end;

end.

6、 通道类源码:

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

{$DEFINE ThreadChannel}

interface

uses
Windows,Classes,SysUtils,

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

Type


{$IFDEF ThreadChannel}
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;

procedure ChannelProcessor();
procedure InformTrunkStatus(
const aMsgFlag: TLVOperateFlag);

procedure ClearTrunkStatus();
procedure ClearChannelBuffer();
function CheckSigHangup():
boolean ;
function CheckCallIn():
boolean ;
function SwitchOnCallIn():
boolean ;

procedure ProcessCallInSuccess();
procedure ProcessDialSuccess();

procedure ProcessCheckDialSend();
procedure ProcessDialOut();

procedure Stop();

// 三汇卡专用方法
function GetTrunkStateBySsm( const ssmState: integer): TTrunkState;
protected
{$IFDEF ThreadChannel}
procedure Execute(); override;
{$ENDIF}
public
strMessage:string;
OnChannelState:TTrunkStatusEvent;

constructor Create(
const trunkEvent:TTrunkStatusEvent);
destructor Destroy();override;

procedure CreateCommChannel(
const aChennelID: Word);
procedure Startup();

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 ;

// 三汇卡特性方法
function CheckDialOutEnabled(): boolean ;
class procedure InformInvodeError();
end;
implementation

{ TCXXSHChannel8B }

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

procedure TCXXSHChannel8B.ChannelProcessor();
var
ssmState:integer;
begin
// ssmState := SsmGetChState(channelID);
// channelState := GetTrunkStateBySsm(ssmState);
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
ProcessDialOut();
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 TCXXSHChannel8B.CheckCallIn():
boolean ;
begin
Result :
= false ;
if (SsmGetChState(channelID) = 2 ) then // 检测到振铃信号
begin
SsmGetCallerId(channelID, aCallerId);
// 取出CALLERID信息
channelState : = atsCallIning;
Result :
= true ;
end;
{
Result :
= RingDetect(channelID);
if Result then
begin
OffHook(channelID);
if isDialOut then
channelState :
= atsDialSuccess
else
channelState :
= atsCallIning;
end;
}

end;

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

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

constructor TCXXSHChannel8B.Create(
const trunkEvent:TTrunkStatusEvent);
begin
GetMem(aCallerId,
50 );
Self.OnChannelState :
= trunkEvent;
{$IFDEF ThreadChannel}
Self.FreeOnTerminate :
= true ;
inherited Create(
true );
{$ENDIF}
end;


destructor TCXXSHChannel8B.Destroy;
begin
ChannelHangUp();
Stop();
{$IFNDEF ThreadChannel}
inherited Destroy();
{$ENDIF}
InformTrunkStatus(lvofDelete);
FreeMem(aCallerId);
end;

function TCXXSHChannel8B.DialPhone(
const DialPhoneNumber:PChar;
const PreDialNumber:PChar): boolean ;
begin
Result :
= false ;
if (channelState >< atsFree) then Exit;
phoneNumber :
= DialPhoneNumber;
Result :
= (SsmPickup(channelID) = 0 );
if NOT Result then Exit;
Result :
= (SsmAutoDial(channelID,DialPhoneNumber) = 0 );
if Result then
begin
isDialOut :
= true ;
channelState :
= atsCheckSendDial;
end;
end;

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

{$IFDEF ThreadChannel}
procedure TCXXSHChannel8B.Execute;
begin
while NOT Terminated do
begin
Synchronize(ChannelProcessor);
Sleep(
10 );
end;
end;
{$ENDIF}

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

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

procedure TCXXSHChannel8B.InformTrunkStatus(
const aMsgFlag: TLVOperateFlag);
begin
if NOT Assigned(OnChannelState) then Exit;
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;

procedure TCXXSHChannel8B.ProcessCallInSuccess();
begin

end;

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

procedure TCXXSHChannel8B.ProcessDialSuccess();
begin

end;

procedure TCXXSHChannel8B.CreateCommChannel(
const aChennelID: Word);
var
ct:integer;
begin
channelID :
= aChennelID;
ct :
= SsmGetChType(channelID);
if (ct > 0 ) then Exit;
channelType :
= TChannelType(ct);
ClearTrunkStatus();
InformTrunkStatus(lvofAdd);
end;

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

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

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

procedure TCXXSHChannel8B.Startup();
begin
{$IFDEF ThreadChannel}
Resume();
{$ENDIF}
end;

procedure TCXXSHChannel8B.Stop();
begin
{$IFDEF ThreadChannel}
Suspend();
Terminate();
{$ENDIF}
end;

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

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

function TCXXSHChannel8B.GetTrunkStateBySsm(
const ssmState: integer): TTrunkState;
begin
Result :
= atsFree;
case ssmState of
0 : Result : = atsFree;
4 , 5 , 6 , 9 : Result : = atsCallIning;
7 : Result : = atsHangOff;
// 8:"断线"状态。只有录音通道才会进入本状态。暂时不处理
// 8: Result := atsHangOff;
// 3: Result := atsCallInSuccess;
end;
end;

procedure TCXXSHChannel8B.ProcessDialOut();
var
dState:integer;
begin
dState :
= SsmChkAutoDial(channelID);
case dState of
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;

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

end.



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1206497


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值