Delphi之三匯模擬語音卡(SHT-8B/PCI/FAX)可複用原始碼
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.
//
// 產品名稱: 成曉旭的個人軟體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.
//
// 產品名稱: 成曉旭的個人軟體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
相關文章
- Delphi之東進模擬語音卡(D160A)可複用原始碼原始碼
- Delphi之東進數字語音卡(SS1)可複用原始碼原始碼
- 用 DELPHI 為 WINDOWS 做一個帶聲音的模擬鬧鐘 (轉)Windows
- 符合PCI的Web應用開發指南:PCI是線上支付必過關卡Web
- 人工智慧語音機器人如何完美模模擬人語調?人工智慧機器人
- COST231-WI模型通道模擬,原始碼模擬matlab程式設計原始碼模型原始碼Matlab程式設計
- React Hooks 原始碼模擬與解讀ReactHook原始碼
- win10手機模擬器卡怎麼辦_win10手機模擬器卡頓嚴重修複方法Win10
- RTX下IK220計數卡的PCI示例程式碼,自己分析用
- 【原始碼】使用MATLAB進行ECG模擬原始碼Matlab
- Gem Mod音訊模擬工具音訊
- 原始碼分析axios(1)~原始碼分析、模擬axios的建立原始碼iOS
- IBM P670更換PCI卡IBM
- 語音直播系統原始碼開發語音直播系統部署搭建原始碼
- [轉]delphi 有授權許可的字串拷貝函式原始碼字串函式原始碼
- 如何用python模擬點選進行重複話語?Python
- 蒙特卡羅模擬技術 (轉載)
- elixir模擬ruby快速複製字串字串
- 對於複雜系統只能採用模擬性建模? - Cilliers
- Security8:許可權模擬
- HackingTeam原始碼洩漏——語音監控分析原始碼
- 語音聊天系統原始碼有哪些特色功能原始碼
- 語音聊天系統原始碼如何才能快速搭建原始碼
- 語音陪玩原始碼如何做到不卡頓?原始碼
- Python運用蒙特卡洛演算法模擬植物生長Python演算法
- Delphi5學習筆記之三筆記
- 企業髮卡網原始碼_知宇髮卡系統原始碼原始碼
- 通過模擬vuex的核心原始碼快速掌握其原理Vue原始碼
- 【原始碼】基於MPPT的光伏(PV)系統模擬原始碼
- 無線自組網AODV路由機制模擬原始碼路由原始碼
- 根據原始碼模擬實現express框架常用功能原始碼Express框架
- 蒙特卡洛模擬(1)————三門問題
- 模擬在頁面點選匯入csv
- 用ABAP模擬JavaScript的柯里化語言特性(Curry)JavaScript
- 可複用程式碼:元件的來龍去脈元件
- JDK 原始碼 Integer解讀之三(valueOf)JDK原始碼
- 用語音寫程式碼比鍵盤更快
- SSK:超級鍵盤模擬器,呼叫底層,可模擬所有按鍵