⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tapiline.cpp

📁 基于TAPI 2.0的软电话源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// ----------------------------------------------------------------------------
// IP Office SDK (c) Avaya 2001. All rights reserved.
//
// PROJECT:  TapiSample
// FILE:     tapiline.cpp
// CREATED:  Geoff Froud, based on previous work by Carl Muller
//
// See tapisample.h for an explanation of this program.
//
// This is the implementation file for the tapi support classes.
// See tapiline.h for the definition of this class
//
// ----------------------------------------------------------------------------

#include "stdafx.h"
#include "tapisample.h"
#include "tapisampleDlg.h"
#include "tapidescribe.h"

// ============================================================================
// Static functions
// ============================================================================

// ----------------------------------------------------------------------------
// Get a string from a TAPI structure
void getTapiString(CString& result, void *ptr, DWORD Size, DWORD Offset)
{
	if (Size > 0)
	{
		char *buffer = result.GetBufferSetLength(Size + 1);
		memcpy(buffer, &((BYTE *) ptr)[Offset], Size);
		buffer[Size] = 0;
		result.ReleaseBuffer();
	}
	else
		result.Empty();
}

// ----------------------------------------------------------------------------
// Get device capabilities information from TAPI
// Note: The calling function must delete the info structure later on!
HRESULT loopLineGetDevCaps(HLINEAPP hLineApp, DWORD DeviceID,
	DWORD APIVersion, DWORD ExtVersion, LINEDEVCAPS*& pLineDevCaps)
{
	size_t CurrentSize = 512; // Starting value - usually big enough
	HRESULT hr;

	for (;;)
	{
		// Allocate some memory for the call
		pLineDevCaps = (LINEDEVCAPS *) new BYTE[CurrentSize];
		ZeroMemory(&pLineDevCaps[0], CurrentSize);
		pLineDevCaps->dwTotalSize = CurrentSize;

		// Ask TAPI for some information
		hr = ::lineGetDevCaps(hLineApp, DeviceID, APIVersion, ExtVersion, pLineDevCaps);

		// Cope with variable length structures
		if (hr == LINEERR_STRUCTURETOOSMALL)
		{
			if (pLineDevCaps->dwNeededSize <= 0)
				break;
			CurrentSize = pLineDevCaps->dwNeededSize;
			delete [] pLineDevCaps;
			pLineDevCaps = NULL;
		}
		else
			break;
	}
	return hr;
}

// ----------------------------------------------------------------------------
// Get call information from TAPI
// Note: The calling function must delete the info structure later on!
HRESULT loopLineGetCallInfo(HCALL hCall, LINECALLINFO*& pCallInfo)
{
	size_t CurrentSize = 512; // Starting value - usually big enough
	HRESULT hr;

	for (;;)
	{
		// Allocate some memory for the call
		pCallInfo = (LINECALLINFO *) new BYTE[CurrentSize];
		ZeroMemory(&pCallInfo[0], CurrentSize);
		pCallInfo->dwTotalSize = CurrentSize;

		// Ask TAPI for some information
		hr = ::lineGetCallInfo(hCall, pCallInfo);

		// Cope with variable length structures
		if (hr == LINEERR_STRUCTURETOOSMALL)
		{
			if (pCallInfo->dwNeededSize <= 0)
				break;
			CurrentSize = pCallInfo->dwNeededSize;
			delete [] pCallInfo;
			pCallInfo = NULL;
		}
		else
			break;
	}
	return hr;
}


// ----------------------------------------------------------------------------
// Get identification information from TAPI
HRESULT loopLineGetID(DWORD& result, HLINE hLine, DWORD AddressID,
	HCALL hCall, DWORD Select, LPCSTR pszDeviceClass)
{
	VARSTRING* pVarString = NULL;
	result = 0xffffffff;
	size_t CurrentSize = 512; // Starting value - usually big enough
	HRESULT hr;

	for (;;)
	{
		// Allocate some memory for the call
		pVarString = (VARSTRING *) new BYTE[CurrentSize];
		ZeroMemory(&pVarString[0], CurrentSize);
		pVarString->dwTotalSize = CurrentSize;

		// Ask TAPI for some information
		hr = ::lineGetID(hLine, AddressID, hCall, Select, pVarString, pszDeviceClass);

		// Cope with variable length structures
		if (hr == LINEERR_STRUCTURETOOSMALL)
		{
			if (pVarString->dwNeededSize <= 0)
				break;
			CurrentSize = pVarString->dwNeededSize;
			delete [] pVarString;
			pVarString = NULL;
		}
		else
			break;
	}
	if (hr == S_OK)
		result = ((DWORD *) (((BYTE *) pVarString) + pVarString->dwStringOffset))[0];
	delete [] pVarString;
	return hr;
}

// ----------------------------------------------------------------------------
// Get address capabilities information from TAPI
HRESULT loopLineGetAddressCaps(HLINEAPP hLineApp, DWORD DeviceID, DWORD AddressID,
	DWORD APIVersion, DWORD ExtVersion, LINEADDRESSCAPS*& pAddressCaps)
{
	size_t CurrentSize = 512; // Starting value - usually big enough
	HRESULT hr;

	for (;;)
	{
		// Allocate some memory for the call
		pAddressCaps = (LINEADDRESSCAPS *) new BYTE[CurrentSize];
		ZeroMemory(&pAddressCaps[0], CurrentSize);
		pAddressCaps->dwTotalSize = CurrentSize;

		// Ask TAPI for some information
		hr = ::lineGetAddressCaps(hLineApp, DeviceID, AddressID, APIVersion,
			ExtVersion, pAddressCaps);

		// Cope with variable length structures
		if (hr == LINEERR_STRUCTURETOOSMALL)
		{
			if (pAddressCaps->dwNeededSize <= 0)
				break;
			CurrentSize = pAddressCaps->dwNeededSize;
			delete [] pAddressCaps;
			pAddressCaps = NULL;
		}
		else
			break;
	}
	return hr;
}

// Get address capabilities information from TAPI
HRESULT loopLineGetAddressStatus(HLINE hLine, DWORD AddressID,
	LINEADDRESSSTATUS*& pAddressStatus)
{
	size_t CurrentSize = 512; // Starting value - usually big enough
	HRESULT hr;

	for (;;)
	{
		// Allocate some memory for the call
		pAddressStatus = (LINEADDRESSSTATUS *) new BYTE[CurrentSize];
		ZeroMemory(&pAddressStatus[0], CurrentSize);
		pAddressStatus->dwTotalSize = CurrentSize;

		// Ask TAPI for some information
		hr = ::lineGetAddressStatus(hLine, AddressID, pAddressStatus);

		// Cope with variable length structures
		if (hr == LINEERR_STRUCTURETOOSMALL)
		{
			if (pAddressStatus->dwNeededSize <= 0)
				break;
			CurrentSize = pAddressStatus->dwNeededSize;
			delete [] pAddressStatus;
			pAddressStatus = NULL;
		}
		else
			break;
	}
	return hr;
}

// ----------------------------------------------------------------------------
// Get call status information from TAPI
HRESULT loopLineGetCallStatus(HCALL hCall, LINECALLSTATUS*& pCallStatus)
{
	size_t CurrentSize = 512; // Starting value - usually big enough
	HRESULT hr;

	for (;;)
	{
		// Allocate some memory for the call
		pCallStatus = (LINECALLSTATUS *) new BYTE[CurrentSize];
		ZeroMemory(&pCallStatus[0], CurrentSize);
		pCallStatus->dwTotalSize = CurrentSize;

		// Ask TAPI for some information
		hr = ::lineGetCallStatus(hCall, pCallStatus);

		// Cope with variable length structures
		if (hr == LINEERR_STRUCTURETOOSMALL)
		{
			if (pCallStatus->dwNeededSize <= 0)
				break;
			CurrentSize = pCallStatus->dwNeededSize;
			delete [] pCallStatus;
			pCallStatus = NULL;
		}
		else
			break;
	}
	return hr;
}


// ----------------------------------------------------------------------------
// Line Event Handling
static void CALLBACK TapiLineCallback(
	DWORD   dwDevice,
	DWORD   nMsg,
	DWORD   dwInstance,
	DWORD   dwParam1,
	DWORD   dwParam2,
	DWORD   dwParam3)
{
	switch( nMsg )
	{
	case LINE_CREATE:
		// We have been asked to create a line.  We can't do this, the number
		// of lines is dictated by the IP Office Telephony Service Provider, so
		// we'll ignore this request.
		break;

	case LINE_REQUEST:
		// We have received an assisted telephony request.  This application
		// doesn't handle assisted telephony requests, so we'll ignore it.
		break;

	default:
		// We have received an event relevant to an existing line
		TapiLine* pLine = (TapiLine*) dwInstance;
		if (pLine)
			pLine->OnEvent(dwDevice, nMsg, dwParam1, dwParam2, dwParam3);
		break;
	}
}


// ============================================================================
// TAPI line class
// ============================================================================

// ----------------------------------------------------------------------------
// Create a TAPI line wrapper object
TapiLine::TapiLine(TapiApplication &Parent) :
	m_Parent(Parent)
{
	m_LineID = 0;
	m_hLine = 0;

	m_hConnectedCall = 0;
	m_hWaitingCall = 0;
	m_hHeldCall = 0;
	m_hPendingCall = 0;
	m_hConferenceCall = 0;
	m_hConsultationCall = 0;
}

// ----------------------------------------------------------------------------
// Destroy a TAPI line wrapper object
TapiLine::~TapiLine()
{
	if (m_hLine)
		::lineClose(m_hLine);
	m_hLine = 0;
}

// ----------------------------------------------------------------------------
// Ask TAPI to make a call - only works if we are not on a call.
void TapiLine::MakeCall(LPCTSTR pszAddress)
{
	if ((m_hConnectedCall == 0) && (m_hWaitingCall == 0)) // No currently active call
	{
		// Calculate the size of the parameter structure, and allocate it.
		size_t cbDestAddress = strlen(pszAddress) + 1;
		size_t cbCallParams = sizeof(LINECALLPARAMS) + cbDestAddress;
		LINECALLPARAMS* pCallParams = (LINECALLPARAMS*)(new BYTE[cbCallParams]);
		// Setup the parameters
		if (pCallParams)
		{
			ZeroMemory(pCallParams, cbCallParams);
			pCallParams->dwTotalSize = cbCallParams;
			pCallParams->dwBearerMode = LINEBEARERMODE_VOICE;
			pCallParams->dwMinRate = 0;   // Use device default
			pCallParams->dwMaxRate = 0;   // Use device default
			pCallParams->dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
			pCallParams->dwCallParamFlags = 0; // No flags
			pCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
			pCallParams->dwAddressID = 0; // Use the main (and only) line address
			// Variable length strings
			pCallParams->dwDisplayableAddressSize = cbDestAddress;
			pCallParams->dwDisplayableAddressOffset = sizeof(LINECALLPARAMS);
			char* pszDisplayableAddress = (char*)((BYTE*)pCallParams + sizeof(LINECALLPARAMS));
			strcpy(pszDisplayableAddress, pszAddress);
		}
		// Ask TAPI to make the call
		HRESULT tr = ::lineMakeCall(m_hLine, &m_hWaitingCall, pszAddress, 0, pCallParams);
		delete[] pCallParams;
		if (tr > 0)
		{
			// Store the request details so that we can match up the 
			// asynchronous reply from TAPI.
			REQUEST_INFO ri = { "MakeCall", m_hWaitingCall };
			m_Requests.SetAt(tr, ri);
		}
		m_Parent.CheckError(tr, "MakeCall");
	}
	else
		m_Parent.m_Dlg.AddText("Error(MakeCall: There is already an Active call)");
}

// ----------------------------------------------------------------------------
// Drop the line - only works if a call is connected or an outgoing call is
// alerting
void TapiLine::DropCall(HCALL hCall /*= 0*/)
{
    if (hCall)
    {
		HRESULT tr = ::lineDrop(hCall, NULL, 0);
		if (tr > 0)
		{
			// Store the request details so that we can match up the 
			// asynchronous reply from TAPI.
			REQUEST_INFO ri = { "DropCall", hCall };
			m_Requests.SetAt(tr, ri);
		}
		m_Parent.CheckError(tr, "DropCall");
    }
	else if (m_hWaitingCall) // Outgoing call
	{
		HRESULT tr = ::lineDrop(m_hWaitingCall, NULL, 0);
		if (tr > 0)
		{
			// Store the request details so that we can match up the 
			// asynchronous reply from TAPI.
			REQUEST_INFO ri = { "DropCall", m_hWaitingCall };
			m_Requests.SetAt(tr, ri);
		}
		m_Parent.CheckError(tr, "DropCall");
	}
	else if (m_hConnectedCall) // Active call
	{
		HRESULT tr = ::lineDrop(m_hConnectedCall, NULL, 0);
		if (tr > 0)
		{
			// Store the request details so that we can match up the 
			// asynchronous reply from TAPI.
			REQUEST_INFO ri = { "DropCall", m_hConnectedCall };
			m_Requests.SetAt(tr, ri);
		}
		m_Parent.CheckError(tr, "DropCall");
	}
	else
		m_Parent.m_Dlg.AddText("Error(DropCall: No Active Call)");
}


// ----------------------------------------------------------------------------
// Hold the current call - only works if call is currently pending
void TapiLine::AnswerCall()
{
	if (m_hPendingCall)
	{
		HRESULT tr = ::lineAnswer(m_hPendingCall, NULL, 0);
		if (tr > 0)
		{
			REQUEST_INFO ri = { "AnswerCall", m_hPendingCall };
			m_Requests.SetAt(tr, ri);
		}
		m_Parent.CheckError(tr, "AnswerCall");
	}
	else
		m_Parent.m_Dlg.AddText("Error(AnswerCall: No Pending Call)");
}

// ----------------------------------------------------------------------------
// Hold the current call - only works if call is connected
void TapiLine::HoldCall()
{
	if (m_hConnectedCall)
	{
		HRESULT tr = ::lineHold(m_hConnectedCall);
		if (tr > 0)
		{
			REQUEST_INFO ri = { "HoldCall", m_hConnectedCall };
			m_Requests.SetAt(tr, ri);
		}
		m_Parent.CheckError(tr, "HoldCall");
	}
	else
		m_Parent.m_Dlg.AddText("Error(HoldCall: No Active Call)");
}

// ----------------------------------------------------------------------------
// Retrieve the call from hold - only works if call is currently proceeding
void TapiLine::UnholdCall()
{
	if (m_hHeldCall)
	{
		HRESULT tr = ::lineUnhold(m_hHeldCall);
		if (tr > 0)
		{
			REQUEST_INFO ri = { "UnholdCall", m_hHeldCall };
			m_Requests.SetAt(tr, ri);
		}
		m_Parent.CheckError(tr, "UnholdCall");
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -