www.pudn.com > TAPI_DIALOUT.ZIP > 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); 
		} 
		 
	} 
}