📄 tapiline.cpp
字号:
// ----------------------------------------------------------------------------
// 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 + -