?? tapiline.cpp
字號:
// TapiLine.cpp : implementation file
//
#include "stdafx.h"
#include "dialer.h"
#include "TapiLine.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// A pointer to my class because TAPI needs a callback
CTapiLine* CTapiLine::MyThis = NULL;
/////////////////////////////////////////////////////////////////////////////
// CTapiLine
CTapiLine::CTapiLine()
{
MyThis = this;
m_LineHandle = NULL;
}
void CTapiLine::Create(HWND& hWnd)
{
m_hWnd = hWnd;
m_hInst =(HINSTANCE)::GetWindowLong(m_hWnd, GWL_HINSTANCE);
// Set the necessary properties to null
SetProp( m_hWnd, "HCALL", NULL );
SetProp( m_hWnd, "HLINE", NULL );
SetProp( m_hWnd, "HCOMM", NULL );
}
CTapiLine::~CTapiLine()
{
// drop the saved properties
RemoveProp( m_hWnd, "HCALL" );
RemoveProp( m_hWnd, "HLINE" );
RemoveProp( m_hWnd, "HCOMM" );
}
// ***********************************************
// This routine places the actual call
//
LONG CTapiLine::DialCall( LPTSTR PhoneNumber )
{
LONG retcode = 0; // local returns
DWORD i; // counter for lines
DWORD RetApiVersion; // return version
LINEEXTENSIONID ExtensionID; // struc for API call
//
// make sure you have a phone number
if( lstrlen( PhoneNumber ) < 1 )
return( ERRORS );
// Initialize the line, register the callback
if( m_LineHandle == NULL ) {
retcode = ::lineInitialize( &m_LineHandle, m_hInst,
(LINECALLBACK)lineCallbackFunc,
"MSM TAPI", &m_dwLines );
if( retcode < 0 ) {
TapiStatus("Tapi error..." );
return (retcode);
}
else
TapiStatus("Tapi initialized..." );
}
//
// go through all the lines to get API and properties
// if you find one that has the right properties,
// jump out and continue to next section of code
//
m_hLine = (HLINE)GetProp( m_hWnd, "HLINE" );
if( m_hLine == NULL )
{
for( i=0; i < m_dwLines; i++ )
{
// Negotiate the API Version for each line
retcode = ::lineNegotiateAPIVersion( m_LineHandle, i,
EARLY_TAPI_VERSION,
WIN95TAPIVERSION,
&RetApiVersion,
&ExtensionID );
retcode = ::lineOpen( m_LineHandle, i, &m_hLine,
RetApiVersion, 0, (DWORD)m_hWnd,
LINECALLPRIVILEGE_MONITOR |
LINECALLPRIVILEGE_OWNER,
LINEMEDIAMODE_DATAMODEM,
NULL );
if( retcode == 0 )
break;
}
if( retcode != 0 )
return( ERRORS );
}
//
// found a good line
SetProp( m_hWnd, "HLINE",(HANDLE)(HLINE)m_hLine );
//
// now set of properties of the line for outbound dialing
memset( &m_LineParams, 0, sizeof( LINECALLPARAMS ) );
m_LineParams.dwTotalSize = sizeof( LINECALLPARAMS );
m_LineParams.dwMinRate = 9600; // setting data rates
m_LineParams.dwMaxRate = 28800; //
m_LineParams.dwBearerMode = LINEBEARERMODE_VOICE;
m_LineParams.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
//
// finally place the call!
retcode = ::lineMakeCall( m_hLine, &m_hCall,
PhoneNumber, 0,
&m_LineParams );
if( retcode < 0 )
return (retcode); // tell'em how it turned out!
else
Delay(5000); // make a 5 secs delay... or according to ur needs
return( retcode ); // tell'em how it turned out!
}
//
// FUNCTION: lineCallbackFunc(..)
//
// PURPOSE: Receive asynchronous TAPI events
//
void CALLBACK CTapiLine::lineCallbackFunc(
DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
MyThis->SetCallbackParams(
dwDevice, dwMessage,
dwCallbackInstance,
dwParam1, dwParam2,
dwParam3);
}
void CTapiLine::SetCallbackParams(
DWORD dwDevice, DWORD dwMessage,
DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2,
DWORD dwParam3)
{
m_dwDevice = dwDevice;
m_dwMessage = dwMessage;
m_dwCallbackInstance = dwCallbackInstance;
m_dwParam1 = dwParam1;
m_dwParam2 = dwParam2;
m_dwParam3 = dwParam3;
// Load our own Override here because thats the virtual function...
TapiCallBack();
}
// *******************************************
// The callback to handle TAPI messages
//
// This routine handles all messages generated by TAPI services.
// Most of these messages are ignored here or just passsed on to
// the main dialog for posting to the progress window.
//
void CTapiLine::TapiCallBack()
{
switch (m_dwMessage)
{
case LINE_LINEDEVSTATE: // we'll ignore these for now...
switch (m_dwParam1)
{
case LINEDEVSTATE_REINIT:
TapiStatus("LINEDEVSTATE_REINIT..." );
break;
case LINEDEVSTATE_RINGING:
TapiStatus("LINEDEVSTATE_RINGING..." );
break;
}
break; // LINE_LINEDEVSTATE:
case LINE_CALLSTATE: // review the call state messages
HandleCallState();
break;
case LINE_CLOSE: // the line has been closed!
{
TapiStatus("LINE_CLOSED..." );
break;
}
case LINE_REPLY: // pass on TAPI_REPLY messages
{
TapiStatus("Line Reply..." );
::PostMessage( m_hWnd, WM_TAPI_LINE_REPLY,
m_dwParam2,
(LPARAM)(HCALL)m_dwDevice );
break;
}
//
// other messages that we'll ignore here
//
case LINE_REQUEST:
case LINE_ADDRESSSTATE:
break;
case LINE_CALLINFO:
break;
case LINE_DEVSPECIFIC:
break;
case LINE_DEVSPECIFICFEATURE:
break;
case LINE_GATHERDIGITS:
break;
case LINE_GENERATE:
break;
case LINE_MONITORDIGITS:
break;
case LINE_MONITORMEDIA:
break;
case LINE_MONITORTONE:
break;
} /* switch */
} /* TapiCallBack() */
void CTapiLine::HandleCallState()
{
// Error if this CALLSTATE doesn't apply to our call in progress.
if ((HCALL) m_dwDevice != m_hCall) {
TapiStatus("LINE_CALLSTATE: Unknown device ID ...");
return;
}
switch( m_dwParam1 )
{
case LINECALLSTATE_IDLE:
{
TapiStatus("Line is idle...");
::SendMessage(m_hWnd, WM_TAPI_IDLE, 0, 0);
HangupCall();
break;
}
case LINECALLSTATE_ACCEPTED: // just pass message on...
{
SetVarProps( (HWND)m_dwCallbackInstance, m_dwDevice );
::PostMessage( m_hWnd, WM_TAPI_CALL_ACCEPTED,
0, (LPARAM)(HCALL)m_dwDevice );
break;
}
case LINECALLSTATE_PROCEEDING: // post progress message
{
SetVarProps( (HWND)m_dwCallbackInstance, m_dwDevice );
::PostMessage( m_hWnd, WM_TAPI_CALL_PROCEEDING,
0, (LPARAM)(HCALL)m_dwDevice );
break;
}
case LINECALLSTATE_CONNECTED: // hey, we got through!
{
LineStateConnected();
break;
}
case LINECALLSTATE_OFFERING: // pass it on
{
TapiStatus("LINECALLSTATE_OFFERING...");
break;
}
case LINECALLSTATE_DIALTONE:
{
TapiStatus("Dial Tone...");
break;
}
case LINECALLSTATE_DIALING: // pass it on
{
TapiStatus("Dialing...");
::SendMessage(m_hWnd, WM_TAPI_DIALING, 0, 0);
break;
}
case LINECALLSTATE_BUSY:
{
TapiStatus("Line busy, shutting down...");
HangupCall();
break;
}
case LINECALLSTATE_SPECIALINFO:
{
TapiStatus("Special Info, probably couldn't dial number...");
HangupCall();
break;
}
case LINECALLSTATE_DISCONNECTED:
{
LPSTR pszReasonDisconnected;
switch (m_dwParam2)
{
case LINEDISCONNECTMODE_NORMAL:
pszReasonDisconnected = "Remote Party Disconnected";
::SendMessage(m_hWnd, WM_TAPI_DISCONNECT, 0, 0);
break;
case LINEDISCONNECTMODE_UNKNOWN:
pszReasonDisconnected = "Disconnected: Unknown reason";
break;
case LINEDISCONNECTMODE_REJECT:
pszReasonDisconnected = "Remote Party rejected call";
break;
case LINEDISCONNECTMODE_PICKUP:
pszReasonDisconnected =
"Disconnected: Local phone picked up";
break;
case LINEDISCONNECTMODE_FORWARDED:
pszReasonDisconnected = "Disconnected: Forwarded";
break;
case LINEDISCONNECTMODE_BUSY:
pszReasonDisconnected = "Disconnected: Busy";
break;
case LINEDISCONNECTMODE_NOANSWER:
pszReasonDisconnected = "Disconnected: No Answer";
break;
case LINEDISCONNECTMODE_BADADDRESS:
pszReasonDisconnected = "Disconnected: Bad Address";
break;
case LINEDISCONNECTMODE_UNREACHABLE:
pszReasonDisconnected = "Disconnected: Unreachable";
break;
case LINEDISCONNECTMODE_CONGESTION:
pszReasonDisconnected = "Disconnected: Congestion";
break;
case LINEDISCONNECTMODE_INCOMPATIBLE:
pszReasonDisconnected = "Disconnected: Incompatible";
break;
case LINEDISCONNECTMODE_UNAVAIL:
pszReasonDisconnected = "Disconnected: Unavail";
break;
case LINEDISCONNECTMODE_NODIALTONE:
pszReasonDisconnected = "Disconnected: No Dial Tone";
break;
default:
pszReasonDisconnected =
"Disconnected: LINECALLSTATE; Bad Reason";
break;
}
TapiStatus(pszReasonDisconnected);
HangupCall();
break;
}
} /* switch */
}
LONG CTapiLine::LineStateConnected()
{
TapiStatus("Hey I am connected!");
//
// local vars for processing
LPVARSTRING lpVarStringStruct = NULL;
size_t sizeofVarStringStruct = sizeof( VARSTRING ) + 1024;
long lreturn;
// get the comm handle. Be sure to drop this handle when
// the call is done or you'll get device unavailable errors
// and have to REBOOT!
lpVarStringStruct = ( LPVARSTRING )LocalAlloc( 0, sizeofVarStringStruct );
do
{
memset( lpVarStringStruct, 0, sizeofVarStringStruct );
lpVarStringStruct->dwTotalSize = (DWORD)sizeofVarStringStruct;
lreturn = lineGetID( 0, 0, (HCALL)m_dwDevice, LINECALLSELECT_CALL, lpVarStringStruct, "comm/datamodem" );
} while( lreturn != 0 );
//
// get comm device handle and save it to properties area
m_hComm = *( (LPHANDLE )( ( LPBYTE )lpVarStringStruct + lpVarStringStruct->dwStringOffset ) );
SetProp( (HWND)m_dwCallbackInstance, "HCOMM", m_hComm );
SetVarProps( (HWND)m_dwCallbackInstance, m_dwDevice );
//
// tell main dialog we got through
::SendMessage(m_hWnd, WM_TAPI_CONNECT,
TAPI_LINECALLSTATE_CONNECTED,
(LPARAM)(HANDLE)m_hComm );
LocalFree( lpVarStringStruct ); // drop mem space
return lreturn;
}
//
// FUNCTION: LONG HangupCall()
//
// PURPOSE: Hangup the call in progress if it exists.
//
LONG CTapiLine::HangupCall()
{
LONG retcode = 0; // some local stuff
TapiStatus("Stopping Call in progress...");
//
// try to get the handles
m_hCall = (HCALL)GetProp( m_hWnd, "HCALL" );
m_hComm = (HANDLE)GetProp( m_hWnd, "HCOMM" );
//
// if we have a comm handle, drop it
if( m_hComm != NULL )
{
CloseHandle( m_hComm );
SetProp( m_hWnd, "HCALL", NULL );
}
//
// if we have a call handle, drop it
if( m_hCall != NULL )
{
retcode = lineDrop( m_hCall, NULL, 0 );
TapiStatus("Call Dropped...");
SetProp( m_hWnd, "HCALL", NULL );
}
LINECALLINFO LineCallInfo;
//
// load call info into structure
memset( &LineCallInfo, 0, sizeof( LINECALLINFO ) );
LineCallInfo.dwTotalSize = sizeof( LINECALLINFO );
lineGetCallInfo( (HCALL)m_dwDevice, &LineCallInfo );
//
// deallocate the call
retcode = lineDeallocateCall( (HCALL)m_dwDevice );
TapiStatus("Call deallocated...");
//
// call went idle, do cleanup
m_hLine = (HLINE)GetProp( m_hWnd, "HLINE" );
//
// if we have a live line, close it
if( m_hLine != NULL )
{
retcode = lineClose( m_hLine );
TapiStatus("Line Closed...");
SetProp( m_hWnd, "HLINE", (HANDLE)NULL );
}
TapiStatus("Call stopped...");
return retcode;
}
// ***************************************************
// get line handle from LINECALLINFO structure
//
void CTapiLine::SetVarProps(HWND hWnd, DWORD hDevice )
{
LINECALLINFO LineCallInfo;
memset( &LineCallInfo, 0, sizeof( LINECALLINFO ) );
SetProp( hWnd, "HCALL", (HANDLE)(HCALL)hDevice );
LineCallInfo.dwTotalSize = sizeof( LINECALLINFO );
lineGetCallInfo( (HCALL)hDevice, &LineCallInfo );
SetProp(m_hWnd, "HLINE", (HANDLE)(HLINE)LineCallInfo.hLine );
return;
}
void CTapiLine::TapiStatus(LPSTR lpszError, BOOL bShowMsgBox)
{
strcpy(m_szMessage, lpszError);
::SendMessage(m_hWnd, WM_TAPI_STATUS, 0, 0);
// Give some delay if u want it ok..
Delay(400);
// u wanna show it using dialog box..
if(bShowMsgBox)
AfxMessageBox(m_szMessage);
// output it in the debugger
OutputDebugString(m_szMessage);
OutputDebugString("\n");
}
void CTapiLine::Delay(UINT lFactor)
{
MSG msg;
DWORD dwTimeStarted;
dwTimeStarted = GetTickCount();
// get control of message loop
while(GetTickCount() - dwTimeStarted < lFactor)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -