📄 tele.cpp
字号:
#include <Windows.h>
#include <StdLib.h>
#include <String.h>
#include <StdArg.h>
#include <Dos.h>
#include "Tele.h"
#define MAX_CHANNEL 4
#define MAX_FILE ( CN_LAST + 10 )
static char* VoiceFiles[ MAX_FILE ] =
{
NULL, // 0: CN_END,
NULL, // 1: CN_NOTHING
"0.VOC", // 2
"1.VOC", // 3
"2.VOC", // 4
"3.VOC", // 5
"4.VOC", // 6
"5.VOC", // 7
"6.VOC", // 8
"7.VOC", // 9
"8.VOC", // A
"9.VOC", // B
"Shi.VOC", // C
"Bai.VOC", // E
"Qian.VOC", // F
"Wan.VOC", // 10
"Yi.VOC", // 11
"Dian.VOC", // 12
"Fu.VOC", // 13
"Yuan.VOC", // 14
"Jiao.VOC", // 15
"Fen.VOC", // 16
};
static char* ChannelVoiceFiles[ MAX_CHANNEL ][ MAX_FILE ];
struct MTeleMsg
{
UINT uMsg;
char* lpParam;
WORD wParam;
WORD wStatus;
BOOL ( *Hook )( MMsg& msg );
};
enum
{
stStart,
stCheckSignal,
stProcess,
stEnd,
};
static MTeleMsg teleMsg[ MAX_CHANNEL ];
static BOOL DefaultTeleHook( MMsg& )
{
return TRUE;
}
void SetTeleHook( int nChannel, BOOL ( *HookFunc )( MMsg& ) )
{
teleMsg[ nChannel ].Hook = HookFunc;
}
static void inline ClearTeleMsg( int nChannel )
{
SendTeleMsg( nChannel, tmNull, NULL );
}
void ResetTeleHook( int nChannel )
{
ClearTeleMsg( nChannel );
teleMsg[ nChannel ].Hook = DefaultTeleHook;
HangUp( nChannel );
}
void SendTeleMsg( int nChannel, UINT uMsg, char* lpParam, WORD wParam )
{
teleMsg[ nChannel ].uMsg = uMsg;
teleMsg[ nChannel ].lpParam = lpParam;
teleMsg[ nChannel ].wParam = wParam;
teleMsg[ nChannel ].wStatus = stStart;
}
void PlaySentence( int nChannel, ... )
{
va_list ap;
va_start( ap, nChannel );
static char szSentence[ MAX_CHANNEL ][ 50 ];
int nPtr = CN_LAST;
char *pSentence = szSentence[ nChannel ],
*arg;
//while( ( arg = va_arg( ap, char* ) ) != NULL )
while( FP_OFF( arg = va_arg( ap, char* ) ) )
{
if( *arg >= 'A' && *arg <= 'Z' )
{
*pSentence ++ = nPtr;
ChannelVoiceFiles[ nChannel ][ nPtr ++ ] = arg;
}
else
{
TW_MakeSentence( atof( arg ), pSentence );
char *p = strchr( pSentence, CN_POINT );
if( p != NULL )
{
*p = CN_YUAN;
int nFen = p[ 2 ];
p[ 2 ] = CN_JIAO;
p[ 3 ] = 0;
if( nFen != 0 )
{
p[ 3 ] = nFen;
p[ 4 ] = CN_FEN;
p[ 5 ] = 0;
}
}
else
{
p = pSentence + strlen( pSentence );
p[ 0 ] = CN_YUAN;
p[ 1 ] = 0;
}
pSentence += strlen( pSentence );
}
}
va_end( ap );
*pSentence = 0;
SendTeleMsg( nChannel, tmPlaySentence, szSentence[ nChannel ] );
}
static BOOL Failed( int nChannel )
{
WORD nSigCount, nSigLen;
int nSignal = TW_CheckSignal( nChannel, &nSigCount, &nSigLen );
if( ( ( nSignal == SIG_BUSY1 ||
nSignal == SIG_BUSY2 ) && nSigCount >= 3 ) ||
TW_TimerElapsed( nChannel ) < 0
)
{
//HangUp( nChannel );
return TRUE;
}
else return FALSE;
}
static BOOL PlayFailed( int nChannel )
{
if( TW_MonitorBusy( nChannel, SIG_BUSY1, 5 ) ||
TW_MonitorBusy( nChannel, SIG_BUSY2, 5 ) )
{
TW_StopPlayFile( nChannel ); // 对方挂机
//HangUp( nChannel );
return TRUE;
}
else return FALSE;
}
static BOOL bOffHook[ MAX_CHANNEL ];
static int nCounter[ MAX_CHANNEL ];
static char szNumber[ MAX_CHANNEL ][ 30 ];
static BOOL bFirstNumber[ MAX_CHANNEL ];
static void InitGetANumber( int nChannel )
{
bFirstNumber[ nChannel ] = TRUE;
}
static BOOL GetANumber( int nChannel )
{
int ch = TW_GetDTMFChar( nChannel );
if( ch == -1 ) return FALSE;
if( bFirstNumber[ nChannel ] && ch == '4' )
{
bFirstNumber[ nChannel ] = FALSE;
return FALSE;
}
else
{
szNumber[ nChannel ][ nCounter[ nChannel ] ++ ] = ch;
return TRUE;
}
}
void OffHook( int nChannel )
{
TW_OffHookCtrl( nChannel );
bOffHook[ nChannel ] = TRUE;
TW_FlushDTMF( nChannel );
nCounter[ nChannel ] = 0;
}
void HangUp( int nChannel )
{
TW_HangUpCtrl( nChannel );
bOffHook[ nChannel ] = FALSE;
}
//static BOOL bReverse = FALSE; /* You can change to TRUE */
BOOL GetTeleMsg( MMsg& msg )
{
for( int nChannel = 0; nChannel < MAX_CHANNEL; nChannel ++ )
{
//TW_VoiceData = ChannelVoiceFiles[ nChannel ];
TW_SetVoice( ChannelVoiceFiles[ nChannel ] );
BOOL bResult = FALSE;
msg.uMsg = WM_MESSAGE;
msg.lParam = nChannel;
WORD nSignal, nSigCount, nSigLen;
if( !bOffHook[ nChannel ] && TW_RingDetect( nChannel ) > 1 )
{
OffHook( nChannel );
msg.wParam = tmRing;
bResult = TRUE;
}
else switch( teleMsg[ nChannel ].uMsg )
{
case tmDialing:
switch( teleMsg[ nChannel ].wStatus )
{
case stStart:
// 等待拨号音
OffHook( nChannel );
TW_StartTimer( nChannel, 4 );
teleMsg[ nChannel ].wStatus = stCheckSignal;
break;
case stCheckSignal:
nSignal = TW_CheckSignal( nChannel, &nSigCount, &nSigLen );
if( nSignal == SIG_DIAL )
{
// 拨号...
TW_StartDial( nChannel, teleMsg[ nChannel ].lpParam );
teleMsg[ nChannel ].wStatus = stProcess;
}
else if( nSignal != SIG_UNKNOWN )
{
HangUp( nChannel );
ClearTeleMsg( nChannel );
msg.wParam = tmDialingError;
bResult = TRUE; // 未检测到拨号音
}
break;
case stProcess:
if( TW_DialRest( nChannel ) == 0 )
{
// 等待对方摘机...
TW_StartTimer( nChannel, 30 );
TW_StartMonitor( nChannel );
teleMsg[ nChannel ].wStatus = stEnd;
}
break;
case stEnd: // 只适用于有极性反转功能的线路
/*if( ( bReverse && TW_ListenerOffHook( nChannel ) ) ||
( !bReverse && TW_MonitorOffHook( nChannel, 25 ) ) // 1 Second
)*/
if( TW_ListenerOffHook( nChannel ) ||
TW_MonitorOffHook( nChannel, 25 ) ) // 1 Second
{
ClearTeleMsg( nChannel );
msg.wParam = tmDialingOK;
bResult = TRUE; // 对方摘机
}
else if( Failed( nChannel ) )
{
ClearTeleMsg( nChannel );
msg.wParam = tmDialingError;
bResult = TRUE; //忙音或超时
}
break;
}
break;
case tmGetNumber:
int ch;
switch( teleMsg[ nChannel ].wStatus )
{
case stStart:
TW_FlushDTMF( nChannel ); // If Max_channel >= 4
TW_StartTimer( nChannel, 30 );
teleMsg[ nChannel ].wStatus = stProcess;
break;
case stProcess:
if( Failed( nChannel ) )
{
ClearTeleMsg( nChannel );
msg.wParam = tmGetNumberError;
bResult = TRUE; //对方已挂机或超时
}
else if( ( ch = TW_GetDTMFChar( nChannel ) ) != -1 )
{
szNumber[ nChannel ][ nCounter[ nChannel ] ++ ] = ch;
szNumber[ nChannel ][ nCounter[ nChannel ] ] = 0;
strcpy( teleMsg[ nChannel ].lpParam, szNumber[ nChannel ] );
if( nCounter[ nChannel ] == teleMsg[ nChannel ].wParam
|| ch == '#' )
{
ClearTeleMsg( nChannel );
msg.wParam = tmGetNumberOK;
bResult = TRUE; //拨号成功
}
else
{
msg.wParam = tmGetANumber;
bResult = TRUE; //Get a Number
}
}
break;
}
break;
case tmPlayFile:
switch( teleMsg[ nChannel ].wStatus )
{
case stStart:
InitGetANumber( nChannel );
if( TW_StartPlayFile( nChannel, teleMsg[ nChannel ].lpParam,
0l, 0x7fffffffl ) == -1 )
{
HangUp( nChannel );
ClearTeleMsg( nChannel );
msg.wParam = tmPlayFileError;
bResult = TRUE; //文件播放失败
}
else teleMsg[ nChannel ].wStatus = stProcess;
break;
case stProcess:
if( TW_PlayFileRest( nChannel ) == 0 )
{
ClearTeleMsg( nChannel );
msg.wParam = tmPlayFileOK;
bResult = TRUE; //文件播放成功
}
else if( PlayFailed( nChannel )
|| GetANumber( nChannel )
)
{
ClearTeleMsg( nChannel );
msg.wParam = tmPlayFileError;
bResult = TRUE; //文件播放失败
}
break;
}
break;
case tmPlaySentence:
switch( teleMsg[ nChannel ].wStatus )
{
case stStart:
if( TW_PlaySentence( nChannel,
teleMsg[ nChannel ].lpParam ) == -1 )
{
HangUp( nChannel );
ClearTeleMsg( nChannel );
msg.wParam = tmPlaySentenceError;
bResult = TRUE; //句子播放失败
}
else teleMsg[ nChannel ].wStatus = stProcess;
break;
case stProcess:
if( TW_PlaySentenceRest( nChannel ) == 0 )
{
ClearTeleMsg( nChannel );
msg.wParam = tmPlaySentenceOK;
bResult = TRUE; //句子播放成功
}
else if( PlayFailed( nChannel ) )
{
ClearTeleMsg( nChannel );
msg.wParam = tmPlaySentenceError;
bResult = TRUE; //句子播放失败
}
break;
}
break;
}
if( !bResult ) msg.uMsg = WM_NULL;
teleMsg[ nChannel ].Hook( msg );
}
return FALSE;
}
BOOL InitTele()
{
//if( TW_Installed() < 1 ) return FALSE;
int nChannelCount = TW_Installed();
TW_Initialize();
TW_CompressRatio( RATE_64K );
//extern int TW_CloseFile = 1; // For Dos
//TW_SetClose( 1 );
// For Dos
//static unsigned VoiceLen[ MAX_FILE ];
//for( int i = 0; i < MAX_FILE; i++ ) VoiceLen[ i ] = FILE_FLAG;
//TW_VoiceLen = VoiceLen;
for( int nChannel = 0; nChannel < MAX_CHANNEL; nChannel ++ )
{
bOffHook[ nChannel ] = FALSE;
memcpy( ChannelVoiceFiles[ nChannel ], VoiceFiles,
MAX_FILE * sizeof( char * ) );
ResetTeleHook( nChannel );
}
TW_PulseMode( 0x00 );
//return TRUE;
return ( nChannelCount >= 1 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -