- 浏览: 903893 次
文章分类
最新评论
-
wen262856298:
$ = function (id)
function $() -
wchengyu:
http://huihai.iteye.com/blog/10 ...
spring mvc 3 最简单demo -
maling765775866:
yy
js生成级联下拉列表 -
maling765775866:
yy[color=orange][/color]
js生成级联下拉列表 -
hu_teye:
运行报错了
android抽屉实现
Delphi之东进数字语音卡(SS1)可复用源码
Delphi之东进数字语音卡(SS1)可复用源码
作者:成晓旭
Blog:http://blog.csdn.net/cxxsoft
(声明:欢迎转载,请保证文章的完整性)
由于工作原因,本人将不在从事商业应有软件的开发工作,现在开始逐级“解密”自己以前写的部分自有产权代码,但愿对后来的朋友有点参考、借鉴的价值。
本代码是本人开发的计划开源的CIT通用平台的东进1号信令数字语言卡封装,设计思路与模拟语音卡的封装非常类似,在此不再赘述。有兴趣的朋友,请参考本人的另外一篇文章《Delphi之东进模拟语音卡(D<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="160" unitname="a">160A</chmetcnv>)可复用源码》:http://blog.csdn.net/cxxsoft/archive/2006/08/23/1108211.aspx
核心思想是一致的:卡、通道分别设计和实现;通道内,核心的还是“状态机模式”轮巡通道状态来管理硬件卡设备;板卡封装内实现不实现任何业务接口,但允许动态注入实现业务接口的对象,来近一步分发、处理板卡层采集的基础数据。
卡类源代码:
//------------------------------------------------------------------------------
//
//产品名称:成晓旭的个人软件Delphi源码库
//产品版本:CXXSoftdelphicodesourcelib2.0
//模块名称:Delphi之东进数字语音卡类
//模块描述:
//单元文件:unDJCardSS1.pas
//开发作者:成晓旭
//作者blog:http://blog.csdn.net/CXXSoft
//备注:任何人使用此文件时,请保留此段自述文件,谢谢!
//开发时间:2005-01-09
//修改历史:
//修改描述:
//------------------------------------------------------------------------------
unitunDJCardSS1;
interface
uses
Windows,SysUtils,Classes,
unBaseDefine,
Tce1_32,
Tce1_FSK;
type
TDJCommCardSS1=class(TThread)
private
onTrunkEvent:TTrunkSatausEvent;
onRecEvent:TTrunkReceiveEvent;
isLoadFSK:boolean;
CommIsFSK:boolean;
Trunks:arrayofTObject;
functionInitCardForFSK():boolean;
procedureFreeCardForFSK();
procedureThreadKernelProcess();
protected
procedureExecute();override;
public
TotalTrunkNum,InTrunkNum,OutTrunkNum:Word;
TrunkConnected:arrayofboolean;
constructorCreate(constaStateEvent:TTrunkSatausEvent;constaRecEvent:TTrunkReceiveEvent);
destructorDestroy();override;
//初始化中继卡
functionInitCard(constisFSKComm:boolean):Boolean;
//释放中继卡
functionFreeCommCard():boolean;
//开始运行中继卡管理模块
procedureStartRunCommModule();
//获取一个空闲通道(指定通道类型)
functionGetAFreeTrunkByType(constaTrunkType:TTrunkType):integer;
//获取一个空闲呼出通道
functionGetAFreeTrunkByOut():integer;
//挂断指定通道
procedureHangOfByTrunkID(constaChannelID:integer);
//通过指定通道拨号
procedureDialPhoneByTrunkID(constaChannelID:integer;constphoneNumber,callerNumber:PChar;constaDevID:integer=-1);
//通过指定通道发送数据
functionSendStringByTrunkID(constaChannelID:integer;constsendBuffer:PChar):boolean;
end;
implementation
...{TDJCommCardSS1}
uses
unDJChannelSS1;
constructorTDJCommCardSS1.Create(constaStateEvent:TTrunkSatausEvent;
constaRecEvent:TTrunkReceiveEvent);
begin
inheritedCreate(true);
Self.FreeOnTerminate:=true;
onTrunkEvent:=aStateEvent;
onRecEvent:=aRecEvent;
end;
destructorTDJCommCardSS1.Destroy();
begin
Self.Suspend();
Self.Terminate();
FreeCommCard();
end;
procedureTDJCommCardSS1.DialPhoneByTrunkID(constaChannelID:integer;
constphoneNumber,callerNumber:PChar;constaDevID:integer);
begin
if(aChannelID>ErrTrunkId)and(DJTrk_CheckTrunkFree(aChannelID))then
TDJCommChannelsSS1(Trunks[aChannelID]).StartDialPhone(phoneNumber,callerNumber,aDevID,);
end;
procedureTDJCommCardSS1.Execute;
begin
whileNOTTerminateddo
begin
Synchronize(ThreadKernelProcess);
Sleep(1);
end;
end;
procedureTDJCommCardSS1.FreeCardForFSK();
begin
ifCommIsFSKandisLoadFSKthen
begin
DJFsk_Release();
end;
end;
functionTDJCommCardSS1.FreeCommCard():boolean;
var
Loop:Word;
begin
Sleep(1000);
ifTotalTrunkNum>0then
begin
forLoop:=0toTotalTrunkNum-1do
begin
ifAssigned(TDJCommChannelsSS1(Trunks[Loop]))then
begin
TDJCommChannelsSS1(Trunks[Loop]).Free();
TDJCommChannelsSS1(Trunks[Loop]):=nil;
end;
end;
end;
DJSys_DisableCard();
FreeCardForFSK();
Result:=true;
end;
functionTDJCommCardSS1.GetAFreeTrunkByOut():integer;
begin
Result:=GetAFreeTrunkByType(Type_Export);
end;
functionTDJCommCardSS1.GetAFreeTrunkByType(
constaTrunkType:TTrunkType):integer;
var
Loop:Word;
begin
Result:=ErrTrunkID;
forLoop:=0toTotalTrunkNum-1do
begin
if((TDJCommChannelsSS1(Trunks[Loop]).GetTrunkType()=aTrunkType)
and(DJTrk_CheckTrunkFree(Loop)))then
begin
Result:=Loop;
break;
end;
end;
end;
procedureTDJCommCardSS1.HangOfByTrunkID(constaChannelID:integer);
begin
TDJCommChannelsSS1(Trunks[aChannelID]).InOutHangOff();
end;
functionTDJCommCardSS1.InitCard(constisFSKComm:boolean):Boolean;
const
PromptFile='Prompt.ini';
var
Loop:Integer;
isOK:boolean;
TimeOfNow:SystemTime;
begin
Result:=False;
CommIsFSK:=isFSKComm;
isOK:=(DJSys_EnableCard('',PromptFile)=_ERR_OK);
ifNotisOKthenexit;
isOK:=InitCardForFSK();
ifNOTisOKthenExit;
isLoadFSK:=isOK;
GetLocalTime(TimeOfNow);
DJSys_SetSysTime(TimeOfNow.wHour,TimeOfNow.wMinute,TimeOfNow.wSecond);
TotalTrunkNum:=DJTrk_GetTotalTrunkNum();
InTrunkNum:=TotalTrunkNumshr1;
OutTrunkNum:=TotalTrunkNum-InTrunkNum;
SetLength(Trunks,TotalTrunkNum);
SetLength(TrunkConnected,TotalTrunkNum);
forLoop:=0toOutTrunkNum-1do
Trunks[Loop]:=TDJCommChannelsSS1.Create(Self,Loop,Type_Export,CommIsFSK,onTrunkEvent,onRecEvent);
forLoop:=OutTrunkNumtoTotalTrunkNum-1do
Trunks[Loop]:=TDJCommChannelsSS1.Create(Self,Loop,Type_Import,CommIsFSK,onTrunkEvent,onRecEvent);
forLoop:=0toTotalTrunkNum-1do
begin
TDJCommChannelsSS1(Trunks[Loop]).ClearTrunkBuffer(csReceiving);
end;
DJSys_AutoApplyDtmf(ENABLEDTMF);//自动分配DTMF资源
DJSys_EnableAutoKB();//自动回送KB信号
isOK:=isOKandDJSys_EnableDtmfSend();
Result:=isOK;
end;
functionTDJCommCardSS1.InitCardForFSK():boolean;
var
k:integer;
begin
Result:=true;
ifCommIsFSKthen
begin
k:=DJFsk_InitForFsk(SZK_Mode);
Result:=(k=1);
end;
end;
functionTDJCommCardSS1.SendStringByTrunkID(constaChannelID:integer;
constsendBuffer:PChar):boolean;
begin
Result:=TDJCommChannelsSS1(Trunks[aChannelID]).SendString(sendBuffer);
end;
procedureTDJCommCardSS1.StartRunCommModule();
begin
Resume();
end;
procedureTDJCommCardSS1.ThreadKernelProcess();
var
Loop:Word;
begin
DJSys_PushPlay();
forLoop:=0toTotalTrunkNum-1do
begin
try
TDJCommChannelsSS1(Trunks[Loop]).DJChannelProcessor();
except
end;
end;
end;
end.
//
//产品名称:成晓旭的个人软件Delphi源码库
//产品版本:CXXSoftdelphicodesourcelib2.0
//模块名称:Delphi之东进数字语音卡类
//模块描述:
//单元文件:unDJCardSS1.pas
//开发作者:成晓旭
//作者blog:http://blog.csdn.net/CXXSoft
//备注:任何人使用此文件时,请保留此段自述文件,谢谢!
//开发时间:2005-01-09
//修改历史:
//修改描述:
//------------------------------------------------------------------------------
unitunDJCardSS1;
interface
uses
Windows,SysUtils,Classes,
unBaseDefine,
Tce1_32,
Tce1_FSK;
type
TDJCommCardSS1=class(TThread)
private
onTrunkEvent:TTrunkSatausEvent;
onRecEvent:TTrunkReceiveEvent;
isLoadFSK:boolean;
CommIsFSK:boolean;
Trunks:arrayofTObject;
functionInitCardForFSK():boolean;
procedureFreeCardForFSK();
procedureThreadKernelProcess();
protected
procedureExecute();override;
public
TotalTrunkNum,InTrunkNum,OutTrunkNum:Word;
TrunkConnected:arrayofboolean;
constructorCreate(constaStateEvent:TTrunkSatausEvent;constaRecEvent:TTrunkReceiveEvent);
destructorDestroy();override;
//初始化中继卡
functionInitCard(constisFSKComm:boolean):Boolean;
//释放中继卡
functionFreeCommCard():boolean;
//开始运行中继卡管理模块
procedureStartRunCommModule();
//获取一个空闲通道(指定通道类型)
functionGetAFreeTrunkByType(constaTrunkType:TTrunkType):integer;
//获取一个空闲呼出通道
functionGetAFreeTrunkByOut():integer;
//挂断指定通道
procedureHangOfByTrunkID(constaChannelID:integer);
//通过指定通道拨号
procedureDialPhoneByTrunkID(constaChannelID:integer;constphoneNumber,callerNumber:PChar;constaDevID:integer=-1);
//通过指定通道发送数据
functionSendStringByTrunkID(constaChannelID:integer;constsendBuffer:PChar):boolean;
end;
implementation
...{TDJCommCardSS1}
uses
unDJChannelSS1;
constructorTDJCommCardSS1.Create(constaStateEvent:TTrunkSatausEvent;
constaRecEvent:TTrunkReceiveEvent);
begin
inheritedCreate(true);
Self.FreeOnTerminate:=true;
onTrunkEvent:=aStateEvent;
onRecEvent:=aRecEvent;
end;
destructorTDJCommCardSS1.Destroy();
begin
Self.Suspend();
Self.Terminate();
FreeCommCard();
end;
procedureTDJCommCardSS1.DialPhoneByTrunkID(constaChannelID:integer;
constphoneNumber,callerNumber:PChar;constaDevID:integer);
begin
if(aChannelID>ErrTrunkId)and(DJTrk_CheckTrunkFree(aChannelID))then
TDJCommChannelsSS1(Trunks[aChannelID]).StartDialPhone(phoneNumber,callerNumber,aDevID,);
end;
procedureTDJCommCardSS1.Execute;
begin
whileNOTTerminateddo
begin
Synchronize(ThreadKernelProcess);
Sleep(1);
end;
end;
procedureTDJCommCardSS1.FreeCardForFSK();
begin
ifCommIsFSKandisLoadFSKthen
begin
DJFsk_Release();
end;
end;
functionTDJCommCardSS1.FreeCommCard():boolean;
var
Loop:Word;
begin
Sleep(1000);
ifTotalTrunkNum>0then
begin
forLoop:=0toTotalTrunkNum-1do
begin
ifAssigned(TDJCommChannelsSS1(Trunks[Loop]))then
begin
TDJCommChannelsSS1(Trunks[Loop]).Free();
TDJCommChannelsSS1(Trunks[Loop]):=nil;
end;
end;
end;
DJSys_DisableCard();
FreeCardForFSK();
Result:=true;
end;
functionTDJCommCardSS1.GetAFreeTrunkByOut():integer;
begin
Result:=GetAFreeTrunkByType(Type_Export);
end;
functionTDJCommCardSS1.GetAFreeTrunkByType(
constaTrunkType:TTrunkType):integer;
var
Loop:Word;
begin
Result:=ErrTrunkID;
forLoop:=0toTotalTrunkNum-1do
begin
if((TDJCommChannelsSS1(Trunks[Loop]).GetTrunkType()=aTrunkType)
and(DJTrk_CheckTrunkFree(Loop)))then
begin
Result:=Loop;
break;
end;
end;
end;
procedureTDJCommCardSS1.HangOfByTrunkID(constaChannelID:integer);
begin
TDJCommChannelsSS1(Trunks[aChannelID]).InOutHangOff();
end;
functionTDJCommCardSS1.InitCard(constisFSKComm:boolean):Boolean;
const
PromptFile='Prompt.ini';
var
Loop:Integer;
isOK:boolean;
TimeOfNow:SystemTime;
begin
Result:=False;
CommIsFSK:=isFSKComm;
isOK:=(DJSys_EnableCard('',PromptFile)=_ERR_OK);
ifNotisOKthenexit;
isOK:=InitCardForFSK();
ifNOTisOKthenExit;
isLoadFSK:=isOK;
GetLocalTime(TimeOfNow);
DJSys_SetSysTime(TimeOfNow.wHour,TimeOfNow.wMinute,TimeOfNow.wSecond);
TotalTrunkNum:=DJTrk_GetTotalTrunkNum();
InTrunkNum:=TotalTrunkNumshr1;
OutTrunkNum:=TotalTrunkNum-InTrunkNum;
SetLength(Trunks,TotalTrunkNum);
SetLength(TrunkConnected,TotalTrunkNum);
forLoop:=0toOutTrunkNum-1do
Trunks[Loop]:=TDJCommChannelsSS1.Create(Self,Loop,Type_Export,CommIsFSK,onTrunkEvent,onRecEvent);
forLoop:=OutTrunkNumtoTotalTrunkNum-1do
Trunks[Loop]:=TDJCommChannelsSS1.Create(Self,Loop,Type_Import,CommIsFSK,onTrunkEvent,onRecEvent);
forLoop:=0toTotalTrunkNum-1do
begin
TDJCommChannelsSS1(Trunks[Loop]).ClearTrunkBuffer(csReceiving);
end;
DJSys_AutoApplyDtmf(ENABLEDTMF);//自动分配DTMF资源
DJSys_EnableAutoKB();//自动回送KB信号
isOK:=isOKandDJSys_EnableDtmfSend();
Result:=isOK;
end;
functionTDJCommCardSS1.InitCardForFSK():boolean;
var
k:integer;
begin
Result:=true;
ifCommIsFSKthen
begin
k:=DJFsk_InitForFsk(SZK_Mode);
Result:=(k=1);
end;
end;
functionTDJCommCardSS1.SendStringByTrunkID(constaChannelID:integer;
constsendBuffer:PChar):boolean;
begin
Result:=TDJCommChannelsSS1(Trunks[aChannelID]).SendString(sendBuffer);
end;
procedureTDJCommCardSS1.StartRunCommModule();
begin
Resume();
end;
procedureTDJCommCardSS1.ThreadKernelProcess();
var
Loop:Word;
begin
DJSys_PushPlay();
forLoop:=0toTotalTrunkNum-1do
begin
try
TDJCommChannelsSS1(Trunks[Loop]).DJChannelProcessor();
except
end;
end;
end;
end.
通道类源代码:
//------------------------------------------------------------------------------
//
//产品名称:成晓旭的个人软件Delphi源码库
//产品版本:CXXSoftdelphicodesourcelib2.0
//模块名称:Delphi之东进数字语音卡通道类
//模块描述:
//单元文件:unDJChannelSS1.pas
//开发作者:成晓旭
//作者blog:http://blog.csdn.net/CXXSoft
//备注:任何人使用此文件时,请保留此段自述文件,谢谢!
//开发时间:2005-01-09
//修改历史:
//修改描述:
//------------------------------------------------------------------------------
unitunDJChannelSS1;
interface
uses
Windows,SysUtils,
unBaseDefine,
Tce1_32,
Tce1_FSK,
unDJCardSS1;
type
TCXXStatus=(csSending,csReceiving,csPlaying);
TDJCommChannelsSS1=class(TObject)
private
CommIsFSK:boolean;
controller:TDJCommCardSS1;
TrunkID:integer;
TrunkStep:TTrunkStep;
MaxBuffer:array[0..DTMF_BUFFER_SIZE-1]ofChar;
msgChannel:TTrunkStatusInfo;
msgFrame:TRecCommFrame;
commFrameNumber,recPos:Word;
subStatus:TCXXStatus;
commPhone:string;
commFrameStr:string;
//应该进一步优化为注入的接口,非简单的回调句柄
onTrunkState:TTrunkSatausEvent;
onRecEvent:TTrunkReceiveEvent;
InOutType:TTrunkType;
functionSendDataFromTrunk():boolean;
functionCheckSendDataEnd():boolean;
procedureSaveMaxBufferToFrameStr();
procedureProcessConnected();
//注意:此方法与具体业务的通信协议存在严重依赖关系(IoC实现依赖反转)
functionCheckReceiveOverFSK(constdataBuffer:arrayofchar;constdataNumber:Word):boolean;
//注意:此方法与具体业务的通信协议存在严重依赖关系(IoC实现依赖反转)
functionCheckReceiveOverDTMF(constdataBuffer:arrayofchar;constdataNumber:Word):boolean;
functionGetCommData(constdataBuffer:arrayofchar;constdataNumber:Word):string;
functionReceiveDataFromTrunk():boolean;
procedureInformChannelStatus(constaStep:TTrunkStep;constlvof:TLVOperateFlag);
procedureInformBusinessStatus(constaCommData:string;constcif:TCommInformFlag);
procedureInformDialStatus(constaStep:TTrunkStep);
procedureInWaitingIntoToConnect();
functionGetCommFrameFromSendString(constcommFrame:string):string;
procedureRegisterTrunkEvent(consttrunkStateEvent:TTrunkSatausEvent);
procedureRegisterReceiveEvent(consttrunkRecEvent:TTrunkReceiveEvent);
public
constructorCreate(consttrunkController:TDJCommCardSS1;constTrkID:Integer;
constTrunkType:TTrunkType;constisFSKComm:boolean;
constaStateEvent:TTrunkSatausEvent;constaRecEvent:TTrunkReceiveEvent);
destructorDestroy;override;
//获取通道状态
functionGetTrunkType():TTrunkType;
procedureDJChannelProcessor();
//通道挂机
procedureInOutHangOff();
//开始拨号
procedureStartDialPhone(constphoneNumber,callerNumber:PChar;constaDevID:integer=-1);
//发送通信数据
functionSendString(constpchSend:PChar):boolean;
//清空通道数据缓冲
procedureClearTrunkBuffer(constaSB:TCXXStatus);
//获取通道号
functionGetTrunkID():integer;
end;
implementation
...{TDJCommChannelsSS1}
const
Frame_FillChar=#0;
Leader_Flag=$55;
HeadNumber=30;
hasLeader=true;
functionTDJCommChannelsSS1.CheckSendDataEnd():boolean;
begin
Result:=false;
ifCommIsFSKthen
begin
if(DJFsk_CheckSendFSKEnd(TrunkID,SZK_Mode)=1)then
begin
DJFsk_StopSend(TrunkID,SZK_Mode);
Result:=true;
end;
end
else
begin
ifDJTrk_CheckDtmfSendEnd(TrunkID)then
begin
DJVoc_StopPlayFile(TrunkID);
Result:=true;
end;
end;
ifResultthen
ClearTrunkBuffer(csReceiving);
end;
procedureTDJCommChannelsSS1.ClearTrunkBuffer(constaSB:TCXXStatus);
begin
subStatus:=aSB;
ifCommIsFSKthen
DJFsk_ResetFskBuffer(TrunkID,SZK_Mode)
else
DJTrk_InitDtmfBufNew(TrunkID);
commFrameNumber:=0;
recPos:=0;
end;
constructorTDJCommChannelsSS1.Create(consttrunkController:TDJCommCardSS1;constTrkID:Integer;
constTrunkType:TTrunkType;constisFSKComm:boolean;
constaStateEvent:TTrunkSatausEvent;constaRecEvent:TTrunkReceiveEvent);
var
t:TTrunkType;
begin
inheritedCreate;
RegisterTrunkEvent(aStateEvent);
RegisterReceiveEvent(aRecEvent);
controller:=trunkController;
TrunkID:=TrkID;
commPhone:='';
TrunkStep:=TTrunkStep(-1);
t:=TrunkType;
ifDJTrk_SetTrunkType(TrkID,t)then
InOutType:=TrunkType;
CommIsFSK:=isFSKComm;
controller.TrunkConnected[TrunkID]:=false;
ClearTrunkBuffer(csReceiving);
InformChannelStatus(Step_Free,lvofAdd);
end;
destructorTDJCommChannelsSS1.Destroy();
begin
inherited;
DJTrk_BackwardHangUp(TrunkID);
end;
procedureTDJCommChannelsSS1.DJChannelProcessor();
var
aStep:TTrunkStep;
begin
//DJSys_PushPlay();
aStep:=DJTrk_GetTrunkStatus(TrunkID);
//状态变化
ifTrunkStep<>aStepthen
begin
TrunkStep:=aStep;
InformChannelStatus(TrunkStep,lvofUpdate);
end;
//前向挂机
if(TrunkStep<>Step_Free)andDJTrk_CheckForwardHangUp(TrunkID)then
begin
InOutHangOff();
end;
//入中继拨入,等待接续(建立连接)
if(TrunkStep=Step_Wait)and(DJTrk_CheckTrunkIn(TrunkID))then
begin
InWaitingIntoToConnect();
end;
//通道连接已经建立
if(TrunkStep=Step_Connect)then
begin
ProcessConnected();
end;
//出通道拨号失败
ifTrunkStep=Step_DialFailthen
begin
InformDialStatus(TrunkStep);
end;
ifTrunkStep=Step_Delaythen
Exit;
//出入通道空闲
ifTrunkStep=Step_Freethen
begin
//等待接收呼入
end;
end;
functionTDJCommChannelsSS1.GetTrunkID():integer;
begin
Result:=Self.TrunkID;
end;
procedureTDJCommChannelsSS1.InformChannelStatus(constaStep:TTrunkStep;constlvof:TLVOperateFlag);
begin
msgChannel.lvFlag:=lvof;
msgChannel.TrunkID:=IntToStr(Self.TrunkID);
msgChannel.DeviceID:='';
msgChannel.TrunkTypeStr:=TrunkTypeInStr[InOutType];
msgChannel.TrunkStep:=Ord(aStep);
msgChannel.TrunkStepStr:=TrunkStepInStr[aStep];
ifaStep=Step_Freethen
begin
msgChannel.Phone:='';
msgChannel.Data:='';
end
else
begin
msgChannel.Phone:=commPhone;
msgChannel.Data:=commFrameStr;
end;
ifAssigned(onTrunkState)then
onTrunkState(msgChannel);
end;
procedureTDJCommChannelsSS1.InformDialStatus(constaStep:TTrunkStep);
var
dStatus:TDialStatus;
begin
dStatus:=DJTrk_GetDialStatus(TrunkID);
casedStatusof
DS_Busy,DS_OverTime,DS_NoUser,DS_LineError:
begin
InOutHangOff();
end;
end;
end;
procedureTDJCommChannelsSS1.InformBusinessStatus(constaCommData:string;constcif:TCommInformFlag);
begin
//依赖注入的业务处理接口调用,实现业务处理的
end;
procedureTDJCommChannelsSS1.InOutHangOff();
begin
DJTrk_BackwardHangUp(TrunkID);
controller.TrunkConnected[TrunkID]:=false;
InformBusinessStatus('',cifDisconnected);
end;
procedureTDJCommChannelsSS1.InWaitingIntoToConnect;
begin
DJVoc_PlayFile(TrunkID,'.Voicedtmf13');
DJVoc_StopPlayFile(TrunkID);
end;
procedureTDJCommChannelsSS1.ProcessConnected();
var
ss:TCXXStatus;
begin
ifNOTcontroller.TrunkConnected[TrunkID]then
begin
controller.TrunkConnected[TrunkID]:=true;
ss:=csReceiving;
InformBusinessStatus('',cifConnected);
ClearTrunkBuffer(ss);
end;
casesubStatusof
csSending:
begin
ifCheckSendDataEnd()then
begin
InformChannelStatus(Step_Connect,lvofUpdate);
InformBusinessStatus(commFrameStr,cifSend);
end;
end;
csReceiving:
begin
ifReceiveDataFromTrunk()then
begin
msgFrame.CommFrame:=commFrameStr;
msgFrame.CommType:=Comm_FSK;
InformChannelStatus(Step_Connect,lvofUpdate);
InformBusinessStatus(commFrameStr,cifReceive);
end;
end;
csPlaying:
begin
end;
end;
end;
functionTDJCommChannelsSS1.ReceiveDataFromTrunk():boolean;
var
num,Loop:integer;
tempBuffer:array[0..DTMF_BUFFER_SIZE-1]ofChar;
begin
Result:=false;
try
ifSelf.CommIsFSKthen
begin
//FSK方式版本
FillChar(tempBuffer,DTMF_BUFFER_SIZE,Frame_FillChar);
num:=DJFsk_GetFSK(TrunkID,tempBuffer,SZK_MODE);
if(num>0)then
begin
ifCheckReceiveOverFSK(tempBuffer,num)then
begin
Self.commFrameStr:=GetCommData(tempBuffer,num);
Self.ClearTrunkBuffer(csReceiving);
Result:=true;
end;
end;
end
else
begin
//DTMF方式版本
num:=DJTrk_GetReceiveDtmfNumNew(TrunkID);
ifnum>0then
begin
forLoop:=0tonum-1do
begin
MaxBuffer[recPos+Loop]:=DJTrk_GetDtmfCodeNew(TrunkID);
recPos:=(recPos+1)modDTMF_BUFFER_SIZE;
end;
Inc(commFrameNumber,num);
ifCheckReceiveOverDTMF(tempBuffer,num)then
begin
ClearTrunkBuffer(csReceiving);
Result:=true;
end;
end;
end;
except
Result:=false;
end;
end;
procedureTDJCommChannelsSS1.RegisterReceiveEvent(
consttrunkRecEvent:TTrunkReceiveEvent);
begin
onRecEvent:=trunkRecEvent;
end;
procedureTDJCommChannelsSS1.RegisterTrunkEvent(
consttrunkStateEvent:TTrunkSatausEvent);
begin
onTrunkState:=trunkStateEvent;
end;
procedureTDJCommChannelsSS1.SaveMaxBufferToFrameStr();
var
Loop:Word;
begin
commFrameStr:='';
forLoop:=0tocommFrameNumber-1do
begin
commFrameStr:=commFrameStr+MaxBuffer[Loop];
end;
end;
functionTDJCommChannelsSS1.SendDataFromTrunk():boolean;
begin
Result:=false;
ifcontroller.TrunkConnected[TrunkID]then
begin
ifCommIsFSKthen
begin
Result:=DJFsk_SendFSK(TrunkID,@MaxBuffer[0],commFrameNumber,SZK_Mode)=1;
end
else
begin
Result:=DJTrk_SendDtmfStr(TrunkID,@MaxBuffer[0])=1;
end;
end;
ifResultthen
subStatus:=csSending;
end;
functionTDJCommChannelsSS1.SendString(constpchSend:PChar):boolean;
var
Loop:integer;
strTemp:string;
begin
Result:=false;
ifSelf.CommIsFSKandhasLeaderthen
begin
//加FSK前导字符的版本
strTemp:=GetCommFrameFromSendString(pchSend);
commFrameNumber:=Length(strTemp);
ifcommFrameNumber>0then
begin
forLoop:=0tocommFrameNumber-1do
MaxBuffer[Loop]:=strTemp[Loop+1];
MaxBuffer[commFrameNumber]:=#0;
SaveMaxBufferToFrameStr();
Result:=SendDataFromTrunk();
end;
end
else
begin
//不加前导字符的版本
commFrameNumber:=Length(pchSend);
ifcommFrameNumber>0then
begin
forLoop:=0tocommFrameNumber-1do
MaxBuffer[Loop]:=pchSend[Loop];
MaxBuffer[commFrameNumber]:=#0;
SaveMaxBufferToFrameStr();
Result:=SendDataFromTrunk();
end;
end;
end;
procedureTDJCommChannelsSS1.StartDialPhone(constphoneNumber,
callerNumber:PChar;constaDevID:integer);
begin
ifDJTrk_CheckTrunkFree(TrunkID)and(Trim(phoneNumber)<>'')then
begin
commPhone:=Trim(phoneNumber);
DJTrk_StartDial(TrunkID,PChar(commPhone),'');
end;
end;
functionTDJCommChannelsSS1.CheckReceiveOverFSK(constdataBuffer:arrayofchar;
constdataNumber:Word):boolean;
begin
//业务实现方法:判定通信帧串发送结束
Result:=true;
end;
functionTDJCommChannelsSS1.GetCommData(constdataBuffer:arrayofchar;
constdataNumber:Word):string;
var
Loop:Word;
begin
Result:='';
ifdataNumber<=0thenExit;
forLoop:=0todataNumber-1do
begin
if(dataBuffer[Loop]<>Frame_FillChar)then
Result:=Result+dataBuffer[Loop];
end;
end;
functionTDJCommChannelsSS1.GetCommFrameFromSendString(
constcommFrame:string):string;
var
Loop:integer;
begin
Result:=commFrame;
forLoop:=0toHeadNumber-1do
Result:=CHR(Leader_Flag)+Result;
end;
functionTDJCommChannelsSS1.CheckReceiveOverDTMF(
constdataBuffer:arrayofchar;constdataNumber:Word):boolean;
begin
//业务实现方法:判定通信帧串发送结束
Result:=true;
end;
functionTDJCommChannelsSS1.GetTrunkType():TTrunkType;
begin
Result:=Self.InOutType;
end;
end.
//
//产品名称:成晓旭的个人软件Delphi源码库
//产品版本:CXXSoftdelphicodesourcelib2.0
//模块名称:Delphi之东进数字语音卡通道类
//模块描述:
//单元文件:unDJChannelSS1.pas
//开发作者:成晓旭
//作者blog:http://blog.csdn.net/CXXSoft
//备注:任何人使用此文件时,请保留此段自述文件,谢谢!
//开发时间:2005-01-09
//修改历史:
//修改描述:
//------------------------------------------------------------------------------
unitunDJChannelSS1;
interface
uses
Windows,SysUtils,
unBaseDefine,
Tce1_32,
Tce1_FSK,
unDJCardSS1;
type
TCXXStatus=(csSending,csReceiving,csPlaying);
TDJCommChannelsSS1=class(TObject)
private
CommIsFSK:boolean;
controller:TDJCommCardSS1;
TrunkID:integer;
TrunkStep:TTrunkStep;
MaxBuffer:array[0..DTMF_BUFFER_SIZE-1]ofChar;
msgChannel:TTrunkStatusInfo;
msgFrame:TRecCommFrame;
commFrameNumber,recPos:Word;
subStatus:TCXXStatus;
commPhone:string;
commFrameStr:string;
//应该进一步优化为注入的接口,非简单的回调句柄
onTrunkState:TTrunkSatausEvent;
onRecEvent:TTrunkReceiveEvent;
InOutType:TTrunkType;
functionSendDataFromTrunk():boolean;
functionCheckSendDataEnd():boolean;
procedureSaveMaxBufferToFrameStr();
procedureProcessConnected();
//注意:此方法与具体业务的通信协议存在严重依赖关系(IoC实现依赖反转)
functionCheckReceiveOverFSK(constdataBuffer:arrayofchar;constdataNumber:Word):boolean;
//注意:此方法与具体业务的通信协议存在严重依赖关系(IoC实现依赖反转)
functionCheckReceiveOverDTMF(constdataBuffer:arrayofchar;constdataNumber:Word):boolean;
functionGetCommData(constdataBuffer:arrayofchar;constdataNumber:Word):string;
functionReceiveDataFromTrunk():boolean;
procedureInformChannelStatus(constaStep:TTrunkStep;constlvof:TLVOperateFlag);
procedureInformBusinessStatus(constaCommData:string;constcif:TCommInformFlag);
procedureInformDialStatus(constaStep:TTrunkStep);
procedureInWaitingIntoToConnect();
functionGetCommFrameFromSendString(constcommFrame:string):string;
procedureRegisterTrunkEvent(consttrunkStateEvent:TTrunkSatausEvent);
procedureRegisterReceiveEvent(consttrunkRecEvent:TTrunkReceiveEvent);
public
constructorCreate(consttrunkController:TDJCommCardSS1;constTrkID:Integer;
constTrunkType:TTrunkType;constisFSKComm:boolean;
constaStateEvent:TTrunkSatausEvent;constaRecEvent:TTrunkReceiveEvent);
destructorDestroy;override;
//获取通道状态
functionGetTrunkType():TTrunkType;
procedureDJChannelProcessor();
//通道挂机
procedureInOutHangOff();
//开始拨号
procedureStartDialPhone(constphoneNumber,callerNumber:PChar;constaDevID:integer=-1);
//发送通信数据
functionSendString(constpchSend:PChar):boolean;
//清空通道数据缓冲
procedureClearTrunkBuffer(constaSB:TCXXStatus);
//获取通道号
functionGetTrunkID():integer;
end;
implementation
...{TDJCommChannelsSS1}
const
Frame_FillChar=#0;
Leader_Flag=$55;
HeadNumber=30;
hasLeader=true;
functionTDJCommChannelsSS1.CheckSendDataEnd():boolean;
begin
Result:=false;
ifCommIsFSKthen
begin
if(DJFsk_CheckSendFSKEnd(TrunkID,SZK_Mode)=1)then
begin
DJFsk_StopSend(TrunkID,SZK_Mode);
Result:=true;
end;
end
else
begin
ifDJTrk_CheckDtmfSendEnd(TrunkID)then
begin
DJVoc_StopPlayFile(TrunkID);
Result:=true;
end;
end;
ifResultthen
ClearTrunkBuffer(csReceiving);
end;
procedureTDJCommChannelsSS1.ClearTrunkBuffer(constaSB:TCXXStatus);
begin
subStatus:=aSB;
ifCommIsFSKthen
DJFsk_ResetFskBuffer(TrunkID,SZK_Mode)
else
DJTrk_InitDtmfBufNew(TrunkID);
commFrameNumber:=0;
recPos:=0;
end;
constructorTDJCommChannelsSS1.Create(consttrunkController:TDJCommCardSS1;constTrkID:Integer;
constTrunkType:TTrunkType;constisFSKComm:boolean;
constaStateEvent:TTrunkSatausEvent;constaRecEvent:TTrunkReceiveEvent);
var
t:TTrunkType;
begin
inheritedCreate;
RegisterTrunkEvent(aStateEvent);
RegisterReceiveEvent(aRecEvent);
controller:=trunkController;
TrunkID:=TrkID;
commPhone:='';
TrunkStep:=TTrunkStep(-1);
t:=TrunkType;
ifDJTrk_SetTrunkType(TrkID,t)then
InOutType:=TrunkType;
CommIsFSK:=isFSKComm;
controller.TrunkConnected[TrunkID]:=false;
ClearTrunkBuffer(csReceiving);
InformChannelStatus(Step_Free,lvofAdd);
end;
destructorTDJCommChannelsSS1.Destroy();
begin
inherited;
DJTrk_BackwardHangUp(TrunkID);
end;
procedureTDJCommChannelsSS1.DJChannelProcessor();
var
aStep:TTrunkStep;
begin
//DJSys_PushPlay();
aStep:=DJTrk_GetTrunkStatus(TrunkID);
//状态变化
ifTrunkStep<>aStepthen
begin
TrunkStep:=aStep;
InformChannelStatus(TrunkStep,lvofUpdate);
end;
//前向挂机
if(TrunkStep<>Step_Free)andDJTrk_CheckForwardHangUp(TrunkID)then
begin
InOutHangOff();
end;
//入中继拨入,等待接续(建立连接)
if(TrunkStep=Step_Wait)and(DJTrk_CheckTrunkIn(TrunkID))then
begin
InWaitingIntoToConnect();
end;
//通道连接已经建立
if(TrunkStep=Step_Connect)then
begin
ProcessConnected();
end;
//出通道拨号失败
ifTrunkStep=Step_DialFailthen
begin
InformDialStatus(TrunkStep);
end;
ifTrunkStep=Step_Delaythen
Exit;
//出入通道空闲
ifTrunkStep=Step_Freethen
begin
//等待接收呼入
end;
end;
functionTDJCommChannelsSS1.GetTrunkID():integer;
begin
Result:=Self.TrunkID;
end;
procedureTDJCommChannelsSS1.InformChannelStatus(constaStep:TTrunkStep;constlvof:TLVOperateFlag);
begin
msgChannel.lvFlag:=lvof;
msgChannel.TrunkID:=IntToStr(Self.TrunkID);
msgChannel.DeviceID:='';
msgChannel.TrunkTypeStr:=TrunkTypeInStr[InOutType];
msgChannel.TrunkStep:=Ord(aStep);
msgChannel.TrunkStepStr:=TrunkStepInStr[aStep];
ifaStep=Step_Freethen
begin
msgChannel.Phone:='';
msgChannel.Data:='';
end
else
begin
msgChannel.Phone:=commPhone;
msgChannel.Data:=commFrameStr;
end;
ifAssigned(onTrunkState)then
onTrunkState(msgChannel);
end;
procedureTDJCommChannelsSS1.InformDialStatus(constaStep:TTrunkStep);
var
dStatus:TDialStatus;
begin
dStatus:=DJTrk_GetDialStatus(TrunkID);
casedStatusof
DS_Busy,DS_OverTime,DS_NoUser,DS_LineError:
begin
InOutHangOff();
end;
end;
end;
procedureTDJCommChannelsSS1.InformBusinessStatus(constaCommData:string;constcif:TCommInformFlag);
begin
//依赖注入的业务处理接口调用,实现业务处理的
end;
procedureTDJCommChannelsSS1.InOutHangOff();
begin
DJTrk_BackwardHangUp(TrunkID);
controller.TrunkConnected[TrunkID]:=false;
InformBusinessStatus('',cifDisconnected);
end;
procedureTDJCommChannelsSS1.InWaitingIntoToConnect;
begin
DJVoc_PlayFile(TrunkID,'.Voicedtmf13');
DJVoc_StopPlayFile(TrunkID);
end;
procedureTDJCommChannelsSS1.ProcessConnected();
var
ss:TCXXStatus;
begin
ifNOTcontroller.TrunkConnected[TrunkID]then
begin
controller.TrunkConnected[TrunkID]:=true;
ss:=csReceiving;
InformBusinessStatus('',cifConnected);
ClearTrunkBuffer(ss);
end;
casesubStatusof
csSending:
begin
ifCheckSendDataEnd()then
begin
InformChannelStatus(Step_Connect,lvofUpdate);
InformBusinessStatus(commFrameStr,cifSend);
end;
end;
csReceiving:
begin
ifReceiveDataFromTrunk()then
begin
msgFrame.CommFrame:=commFrameStr;
msgFrame.CommType:=Comm_FSK;
InformChannelStatus(Step_Connect,lvofUpdate);
InformBusinessStatus(commFrameStr,cifReceive);
end;
end;
csPlaying:
begin
end;
end;
end;
functionTDJCommChannelsSS1.ReceiveDataFromTrunk():boolean;
var
num,Loop:integer;
tempBuffer:array[0..DTMF_BUFFER_SIZE-1]ofChar;
begin
Result:=false;
try
ifSelf.CommIsFSKthen
begin
//FSK方式版本
FillChar(tempBuffer,DTMF_BUFFER_SIZE,Frame_FillChar);
num:=DJFsk_GetFSK(TrunkID,tempBuffer,SZK_MODE);
if(num>0)then
begin
ifCheckReceiveOverFSK(tempBuffer,num)then
begin
Self.commFrameStr:=GetCommData(tempBuffer,num);
Self.ClearTrunkBuffer(csReceiving);
Result:=true;
end;
end;
end
else
begin
//DTMF方式版本
num:=DJTrk_GetReceiveDtmfNumNew(TrunkID);
ifnum>0then
begin
forLoop:=0tonum-1do
begin
MaxBuffer[recPos+Loop]:=DJTrk_GetDtmfCodeNew(TrunkID);
recPos:=(recPos+1)modDTMF_BUFFER_SIZE;
end;
Inc(commFrameNumber,num);
ifCheckReceiveOverDTMF(tempBuffer,num)then
begin
ClearTrunkBuffer(csReceiving);
Result:=true;
end;
end;
end;
except
Result:=false;
end;
end;
procedureTDJCommChannelsSS1.RegisterReceiveEvent(
consttrunkRecEvent:TTrunkReceiveEvent);
begin
onRecEvent:=trunkRecEvent;
end;
procedureTDJCommChannelsSS1.RegisterTrunkEvent(
consttrunkStateEvent:TTrunkSatausEvent);
begin
onTrunkState:=trunkStateEvent;
end;
procedureTDJCommChannelsSS1.SaveMaxBufferToFrameStr();
var
Loop:Word;
begin
commFrameStr:='';
forLoop:=0tocommFrameNumber-1do
begin
commFrameStr:=commFrameStr+MaxBuffer[Loop];
end;
end;
functionTDJCommChannelsSS1.SendDataFromTrunk():boolean;
begin
Result:=false;
ifcontroller.TrunkConnected[TrunkID]then
begin
ifCommIsFSKthen
begin
Result:=DJFsk_SendFSK(TrunkID,@MaxBuffer[0],commFrameNumber,SZK_Mode)=1;
end
else
begin
Result:=DJTrk_SendDtmfStr(TrunkID,@MaxBuffer[0])=1;
end;
end;
ifResultthen
subStatus:=csSending;
end;
functionTDJCommChannelsSS1.SendString(constpchSend:PChar):boolean;
var
Loop:integer;
strTemp:string;
begin
Result:=false;
ifSelf.CommIsFSKandhasLeaderthen
begin
//加FSK前导字符的版本
strTemp:=GetCommFrameFromSendString(pchSend);
commFrameNumber:=Length(strTemp);
ifcommFrameNumber>0then
begin
forLoop:=0tocommFrameNumber-1do
MaxBuffer[Loop]:=strTemp[Loop+1];
MaxBuffer[commFrameNumber]:=#0;
SaveMaxBufferToFrameStr();
Result:=SendDataFromTrunk();
end;
end
else
begin
//不加前导字符的版本
commFrameNumber:=Length(pchSend);
ifcommFrameNumber>0then
begin
forLoop:=0tocommFrameNumber-1do
MaxBuffer[Loop]:=pchSend[Loop];
MaxBuffer[commFrameNumber]:=#0;
SaveMaxBufferToFrameStr();
Result:=SendDataFromTrunk();
end;
end;
end;
procedureTDJCommChannelsSS1.StartDialPhone(constphoneNumber,
callerNumber:PChar;constaDevID:integer);
begin
ifDJTrk_CheckTrunkFree(TrunkID)and(Trim(phoneNumber)<>'')then
begin
commPhone:=Trim(phoneNumber);
DJTrk_StartDial(TrunkID,PChar(commPhone),'');
end;
end;
functionTDJCommChannelsSS1.CheckReceiveOverFSK(constdataBuffer:arrayofchar;
constdataNumber:Word):boolean;
begin
//业务实现方法:判定通信帧串发送结束
Result:=true;
end;
functionTDJCommChannelsSS1.GetCommData(constdataBuffer:arrayofchar;
constdataNumber:Word):string;
var
Loop:Word;
begin
Result:='';
ifdataNumber<=0thenExit;
forLoop:=0todataNumber-1do
begin
if(dataBuffer[Loop]<>Frame_FillChar)then
Result:=Result+dataBuffer[Loop];
end;
end;
functionTDJCommChannelsSS1.GetCommFrameFromSendString(
constcommFrame:string):string;
var
Loop:integer;
begin
Result:=commFrame;
forLoop:=0toHeadNumber-1do
Result:=CHR(Leader_Flag)+Result;
end;
functionTDJCommChannelsSS1.CheckReceiveOverDTMF(
constdataBuffer:arrayofchar;constdataNumber:Word):boolean;
begin
//业务实现方法:判定通信帧串发送结束
Result:=true;
end;
functionTDJCommChannelsSS1.GetTrunkType():TTrunkType;
begin
Result:=Self.InOutType;
end;
end.
相关推荐
1、 将卡、通道分别单独进行设计与封装。2、 所有的外部操作接口都封装在卡类这一类。3、 在我的项目中,在卡类这一级还增加了适配器或者代理,分别实现了Adapter或Proxy模式;以尽可能地解耦卡设备的实现细节与具体...
(请参考作者blog:http://blog.csdn.net/cxxsoft) 设计简介: 1、 设计思路请参考本站Blog的另一篇文章:“Delphi之东进模拟语音卡(D160A)可复用源码”;链接...
东进语音卡tc08a32的接口文件,适用于Delphi2010及以上版本。
Bin :编译后的程序均放在此文件夹 Flow :流程编辑器源... 基于东进语音卡DN081A的电话呼转系统。即电话打入后,将此通话通过另外一个电话线转接到其它电话上,并连通通话,同时对双方通话进行录音。可通过Web查询。
语音卡内线连通模块的Delphi实现源码..rar
delphi语音聊天源码.rar delphi语音聊天源码.rar
精典源码delphi源码下载 宾馆软件.zip 精典源码delphi源码下载 宾馆软件.zip 精典源码delphi源码下载 宾馆软件.zip 精典源码delphi源码下载 宾馆软件.zip 精典源码delphi源码下载 宾馆软件.zip 精典源码delphi源码...
精典源码delphi源码下载 远程控制.zip 精典源码delphi源码下载 远程控制.zip 精典源码delphi源码下载 远程控制.zip 精典源码delphi源码下载 远程控制.zip 精典源码delphi源码下载 远程控制.zip 精典源码delphi源码...
本实例是一个提高效率、人性化的程序,语音卡可以实现各种业务的语音操作,编写各行各业的电话程控系统,其中来电显示是最常用、最实用的一项功能。在开发语音卡相关软件时,需要知到对方拔进的电话号码及拔进时间。...
精典源码delphi源码下载 仓储物流商业源码.zip 精典源码delphi源码下载 仓储物流商业源码.zip 精典源码delphi源码下载 仓储物流商业源码.zip 精典源码delphi源码下载 仓储物流商业源码.zip 精典源码delphi源码下载 ...
Delphi:语音故障报修系统(需要TWVID语音卡).zip源码Delphi项目程序源码下载Delphi:语音故障报修系统(需要TWVID语音卡).zip源码Delphi项目程序源码下载 1.合个人学习技术做项目参考 2.适合学生做毕业设计参考 3....
Delphi语音卡操作实例..rar
DELPHI数字图像处理 源码 为Delphi数字图像处理及高级应用的配套资料
精典源码delphi源码下载 吨地磅称量系统.zip 精典源码delphi源码下载 吨地磅称量系统.zip 精典源码delphi源码下载 吨地磅称量系统.zip 精典源码delphi源码下载 吨地磅称量系统.zip 精典源码delphi源码下载 吨地磅...
在文本框内输入中文或英文,点击朗读按钮,即可发声朗读
Delphi实现语音播报的代码,并有详实的说明注释。
精典源码delphi源码下载 语音故障报修系统(需要tw8vid语音卡).zip
精典源码delphi源码下载 niceerp企业管理系统.zip 精典源码delphi源码下载 niceerp企业管理系统.zip 精典源码delphi源码下载 niceerp企业管理系统.zip 精典源码delphi源码下载 niceerp企业管理系统.zip 精典源码...
语音卡自动服务程序Delphi7源码,测试中没有发现是什么语音卡,这个代码也是前几年的,比较早的源码了,有兴趣的可下载测试一番。相关代码如下: 0:begin if (GetCallerIDStr(chno,callID) = ID_STEP_OK) or ...
精典源码delphi源码下载 大型oa管理系统.zip 精典源码delphi源码下载 大型oa管理系统.zip 精典源码delphi源码下载 大型oa管理系统.zip 精典源码delphi源码下载 大型oa管理系统.zip 精典源码delphi源码下载 大型oa...