📄 tapiline.cpp
字号:
{
// This line (us) has been closed down
m_hLine = 0;
// Describe this event
CString info;
info.Format("Close()");
m_Parent.m_Dlg.AddText(info);
}
// ----------------------------------------------------------------------------
// Handle a LINE_ADDRESSSTATE message from TAPI
void TapiLine::OnAddressState(DWORD AddressID, DWORD AddressState)
{
CString state;
CString info;
info.Format("Address(%d, %s)", AddressID,
DescribeAddressStatus(state, AddressState));
m_Parent.m_Dlg.AddText(info);
// Get further information about the address change
LINEADDRESSSTATUS AddressStatus = { sizeof(LINEADDRESSSTATUS) };
HRESULT hr = ::lineGetAddressStatus(m_hLine, AddressID, &AddressStatus);
m_Parent.CheckError(hr, "GetAddressStatus");
info.Format("[NumInUse=%d, NumActiveCalls=%d, NumOnHoldCalls=%d, "
"NumOnHoldPendCalls=%d]",
AddressStatus.dwNumInUse, AddressStatus.dwNumActiveCalls,
AddressStatus.dwNumOnHoldCalls, AddressStatus.dwNumOnHoldPendCalls);
m_Parent.m_Dlg.AddText(info);
}
// ----------------------------------------------------------------------------
// Handle a LINE_CALLINFO message from TAPI
void TapiLine::OnCallInfo(HCALL hCall, DWORD CallInfoState)
{
CString state, which, info;
// Which call is this information about?
which.Format("%d/", hCall);
if (hCall == m_hConnectedCall) which += "Active";
else if (hCall == m_hWaitingCall) which += "Waiting";
else if (hCall == m_hHeldCall) which += "Held";
else if (hCall == m_hPendingCall) which += "Pending";
else if (hCall == m_hConferenceCall) which += "Conference";
else which += "Unknown";
// Put the information into the dialog box
info.Format("CallInfo(%s: %s)", LPCTSTR(which), DescribeCallInfo(state, CallInfoState));
m_Parent.m_Dlg.AddText(info);
// Get further information about the call info
CString s1, s2, Trunk, CallerID, CalledID, ConnectedID, RedirectingID, RedirectionID, CallData;
LINECALLINFO* pCallInfo = NULL;
/*HRESULT hr = */loopLineGetCallInfo(hCall, pCallInfo);
if (pCallInfo->dwTrunk == 0xffffffff)
Trunk = "Unknown";
else
Trunk.Format("%ld", pCallInfo->dwTrunk);
getTapiString(CallerID, pCallInfo, pCallInfo->dwCallerIDSize, pCallInfo->dwCallerIDOffset);
getTapiString(CalledID, pCallInfo, pCallInfo->dwCalledIDSize, pCallInfo->dwCalledIDOffset);
getTapiString(ConnectedID, pCallInfo, pCallInfo->dwConnectedIDSize, pCallInfo->dwConnectedIDOffset);
getTapiString(RedirectingID, pCallInfo, pCallInfo->dwRedirectingIDSize, pCallInfo->dwRedirectingIDOffset);
getTapiString(RedirectionID, pCallInfo, pCallInfo->dwRedirectionIDSize, pCallInfo->dwRedirectionIDOffset);
getTapiString(CallData, pCallInfo, pCallInfo->dwCallDataSize, pCallInfo->dwCallDataOffset);
info.Format("[AddressID=%d, Origin=%s, Reason=%s, Trunk=%s, "
"CallerID=%s, CalledID=%s, ConnectedID=%s, RedirectingID=%s, RedirectionID=%s, CallData=%s]",
pCallInfo->dwAddressID,
DescribeCallOrigin(s1, pCallInfo->dwOrigin),
DescribeCallReason(s2, pCallInfo->dwReason),
LPCTSTR(Trunk), LPCTSTR(CallerID), LPCTSTR(CalledID), LPCTSTR(ConnectedID),
LPCTSTR(RedirectingID), LPCTSTR(RedirectionID),
LPCTSTR(CallData));
m_Parent.m_Dlg.AddText(info);
delete [] pCallInfo;
}
// ----------------------------------------------------------------------------
// Handle a LINE_CALLSTATE message from TAPI
void TapiLine::OnCallState(HCALL hCall, DWORD CallState, DWORD CallStateDetail, DWORD CallPrivilege)
{
// if (CallState & LINECALLSTATE_DISCONNECTED)
// DropCall(hCall); // This seems to hang up the wrong call!!!
CString info, which, s1, s2;
// Which call is this information about?
which.Format("%d/", hCall);
if (hCall == m_hConnectedCall) which += "Active";
else if (hCall == m_hWaitingCall) which += "Waiting";
else if (hCall == m_hHeldCall) which += "Held";
else if (hCall == m_hPendingCall) which += "Pending";
else if (hCall == m_hConferenceCall) which += "Conference";
else if (hCall == m_hConsultationCall) which += "Consultation";
else which += "Unknown";
// Describe the event to the dialog box
info.Format("CallState(%s: %s, %s, %s)",
LPCTSTR(which),
DescribeCallState(s1, CallState),
DescribeCallStateDetail(CallState, CallStateDetail),
DescribePrivilege(s2, CallPrivilege));
m_Parent.m_Dlg.AddText(info);
// Handle releasing resources when they go idle
// This is necessary to allow another call to be made!
if (CallState & LINECALLSTATE_DISCONNECTED)
//DropCall(hCall); // This seems to hang up the wrong call!!!
;
else if (CallState & LINECALLSTATE_IDLE)
{
HRESULT Result = ::lineDeallocateCall(hCall);
// Describe the error message returned from TAPI
if (Result)
{
info.Format("LineDeallocate(0x%08lx = %s)",
Result, DescribeError(Result));
m_Parent.m_Dlg.AddText(info);
}
else
{
if (hCall == m_hConnectedCall) m_hConnectedCall = 0;
else if (hCall == m_hWaitingCall) m_hWaitingCall = 0;
else if (hCall == m_hHeldCall) m_hHeldCall = 0;
else if (hCall == m_hPendingCall) m_hPendingCall = 0;
else if (hCall == m_hConferenceCall) m_hConferenceCall = 0;
}
}
// Has a call been answered / retrieved?
else if (CallState & LINECALLSTATE_CONNECTED)
{
if (hCall == m_hWaitingCall) m_hWaitingCall = 0;
if (hCall == m_hPendingCall) m_hPendingCall = 0;
if (hCall == m_hHeldCall) m_hHeldCall = 0;
if (hCall == m_hConferenceCall) m_hConferenceCall = 0;
m_hConnectedCall = hCall;
}
// Has a call been put on hold?
else if (CallState & (LINECALLSTATE_ONHOLDPENDTRANSFER | LINECALLSTATE_ONHOLD
| LINECALLSTATE_ONHOLDPENDCONF))
{
if (hCall == m_hConnectedCall) m_hConnectedCall = m_hHeldCall;
m_hHeldCall = hCall;
}
// Is a call proceeding?
else if (CallState & (LINECALLSTATE_DIALING | LINECALLSTATE_PROCEEDING))
{
m_hWaitingCall = hCall;
}
m_Parent.m_Dlg.CheckButtons();
}
// ----------------------------------------------------------------------------
// Handle a LINE_APPNEWCALL message from TAPI
void TapiLine::OnNewCall(DWORD AddressID, HCALL hCall, DWORD CallPrivilege)
{
// We can answer this if we want
m_hPendingCall = hCall;
m_Parent.m_Dlg.CheckButtons();
// Mention the new call
CString info, s1;
info.Format("NewCall(%d, %s)", AddressID, DescribePrivilege(s1, CallPrivilege));
m_Parent.m_Dlg.AddText(info);
// Get further information about the address change
LINEADDRESSSTATUS AddressStatus = { sizeof(LINEADDRESSSTATUS) };
HRESULT hr = ::lineGetAddressStatus(m_hLine, AddressID, &AddressStatus);
m_Parent.CheckError(hr, "GetAddressStatus");
info.Format("[NumInUse=%d, NumActiveCalls=%d, NumOnHoldCalls=%d, "
"NumOnHoldPendCalls=%d]",
AddressStatus.dwNumInUse, AddressStatus.dwNumActiveCalls,
AddressStatus.dwNumOnHoldCalls, AddressStatus.dwNumOnHoldPendCalls);
m_Parent.m_Dlg.AddText(info);
}
// ----------------------------------------------------------------------------
// Handle a LINE_LINEDEVSTATE message from TAPI
void TapiLine::OnLineDevState(DWORD DeviceState, DWORD DeviceStateDetail1, DWORD DeviceStateDetail2)
{
CString state;
CString info;
info.Format("DeviceState(%s, %d, %d)",
DescribeDeviceStatus(state, DeviceState),
DeviceStateDetail1, DeviceStateDetail2);
m_Parent.m_Dlg.AddText(info);
}
// ============================================================================
// TAPI application class
// ============================================================================
// ----------------------------------------------------------------------------
// Create a TAPI application interface class
TapiApplication::TapiApplication(CTapisampleDlg& Dlg) :
m_Dlg(Dlg)
{
m_extension = 0;
m_hLineApp = 0;
m_NumDevs = 0;
m_ApiVersions = 0;
m_CurrentLine = -1;
}
// ----------------------------------------------------------------------------
// Destroy a TAPI application interface class
TapiApplication::~TapiApplication()
{
if (m_ApiVersions)
delete [] m_ApiVersions;
}
// ----------------------------------------------------------------------------
// Shutdown our channel to TAPI
void TapiApplication::ShutdownTAPI()
{
if (m_pLines)
{
DWORD LineID;
for (LineID = 0; LineID < m_NumDevs; LineID++)
{
delete m_pLines[LineID];
}
delete [] m_pLines;
m_pLines = NULL;
}
if (m_hLineApp )
{
::lineShutdown(m_hLineApp);
m_hLineApp = 0;
}
}
// ----------------------------------------------------------------------------
// Initialise TAPI
void TapiApplication::InitialiseTAPI()
{
const DWORD dwLoVersion = 0x00020000; // TAPI v2.0
const DWORD dwHiVersion = TAPI_CURRENT_VERSION;
HLINEAPP hLineApp;
DWORD dwAPIVersion = dwHiVersion;
LINEINITIALIZEEXPARAMS params = { sizeof(LINEINITIALIZEEXPARAMS) };
params.dwOptions = LINEINITIALIZEEXOPTION_USEHIDDENWINDOW;
HINSTANCE hInst = ::AfxGetInstanceHandle();
LPCTSTR pszAppName = ::AfxGetAppName();
HRESULT tr = ::lineInitializeEx( &hLineApp,
hInst,
TapiLineCallback,
pszAppName,
&m_NumDevs,
&dwAPIVersion,
¶ms );
if (S_OK == tr)
{
// Save the handle
m_hLineApp = hLineApp;
// Negotiate the API versions
// (Necessary to get proper notifications)
TRACE("Number of devices: %d\n", m_NumDevs);
if (m_NumDevs > 0)
{
m_ApiVersions = new DWORD[m_NumDevs];
if (m_ApiVersions)
{
LINEEXTENSIONID dummy;
for (DWORD LineID = 0; LineID < m_NumDevs; LineID++)
{
if (S_OK != ::lineNegotiateAPIVersion( m_hLineApp,
LineID,
dwLoVersion,
dwHiVersion,
&m_ApiVersions[LineID],
&dummy) )
{
m_ApiVersions[LineID] = 0;
}
//TRACE("API Ver: %X\n", m_ApiVersions[LineID]);
}
}
}
}
}
// ----------------------------------------------------------------------------
// Open valid TAPI lines
void TapiApplication::OpenValidLines()
{
// Get and open valid lines
DWORD nLines = m_NumDevs;
DWORD nOpenedLines = 0;
m_pLines = new PTAPILINE[nLines];
if (m_pLines != NULL)
{
memset(m_pLines, 0, nLines * sizeof(PTAPILINE));
for (DWORD LineID = 0; LineID < nLines; LineID++ )
{
LINEDEVCAPS *pDevCaps = NULL;
HRESULT tr = loopLineGetDevCaps(m_hLineApp, LineID,
m_ApiVersions[LineID], 0, pDevCaps);
// This is how you are supposed to select TAPI lines,
// i.e. according to the line's capabilities
if( (S_OK == tr) &&
(pDevCaps->dwBearerModes & LINEBEARERMODE_VOICE) &&
(pDevCaps->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE) &&
(pDevCaps->dwLineFeatures & LINEFEATURE_MAKECALL) )
{
// Retrieve the name of the TAPI service provider
CString info, s1, s2;
getTapiString(s1, pDevCaps, pDevCaps->dwProviderInfoSize,
pDevCaps->dwProviderInfoOffset);
info.Format("[Provider = %s]", LPCTSTR(s1));
// Skip TSPs that we are not interested in by looking for the
// Provider name of the IP Office TAPI driver
if (s1 != CString("Avaya"))
continue;
TRACE(info);
TRACE("API version: %X\n", m_ApiVersions[LineID]);
// m_Dlg.AddText(info);
getTapiString(s1, pDevCaps, pDevCaps->dwLineNameSize,
pDevCaps->dwLineNameOffset);
TRACE("[Line Name = %s]\n", LPCTSTR(s1));
// Instantiate a TapiLine class for every line that we open
m_pLines[LineID] = new TapiLine(*this);
if (m_pLines[LineID])
{
tr = m_pLines[LineID]->Open(LineID,
LINECALLPRIVILEGE_OWNER,
LINEMEDIAMODE_INTERACTIVEVOICE /*| LINEMEDIAMODE_UNKNOWN*/);
if (S_OK == tr)
{
nOpenedLines++;
// The following code looks up and displays the line ID
// However, this is the same as the LineID variable
//DWORD id;
//loopLineGetID(id, m_pLines[LineID]->m_hLine, 0, 0,
// LINECALLSELECT_LINE, "tapi/line");
//info.Format("[Line ID = %ld]", id);
//m_Dlg.AddText(info);
LINEADDRESSSTATUS* pAddressStatus = NULL;
loopLineGetAddressStatus(m_pLines[LineID]->m_hLine, 0, pAddressStatus);
// Tell the user about the capabilities of this line
info.Format("[Supported Line States = %s]",
DescribeDeviceStatus(s1, pDevCaps->dwLineStates));
// m_Dlg.AddText(info);
// Find out about each address
for (DWORD AddressID = 0; AddressID < pDevCaps->dwNumAddresses;
AddressID++)
{
// Find out its capabilities
LINEADDRESSCAPS *pAddressCaps = NULL;
tr = loopLineGetAddressCaps(m_hLineApp,
LineID, AddressID,
m_ApiVersions[LineID], 0, pAddressCaps);
// Find and use the name of the extension we control
getTapiString(s1, pAddressCaps, pAddressCaps->dwAddressSize, pAddressCaps->dwAddressOffset);
info.Format("[Extn ID = %s]", s1);
TRACE("[Extn ID = %s]\n",s1);
//* m_Dlg.AddText(info);
DWORD ext = atoi(s1);
m_pLines[LineID]->m_extension = ext;
if (m_CurrentLine == -1)
{
m_CurrentLine = LineID;
m_extension = ext;
m_Dlg.SetExtension(s1);
}
// Tell the user about the capabilities of this address
/* info.Format("[MaxNumActive = %d, MaxNumOnHold = %d, "
"MaxNumOnHoldPending = %d, MaxNumConference = %d, "
"MaxNumTransConf = %d]",
pAddressCaps->dwMaxNumActiveCalls,
pAddressCaps->dwMaxNumOnHoldCalls,
pAddressCaps->dwMaxNumOnHoldPendingCalls,
pAddressCaps->dwMaxNumConference,
pAddressCaps->dwMaxNumTransConf);
m_Dlg.AddText(info);
info.Format("[Supported Address() = %s]",
DescribeAddressStatus(s1, pAddressCaps->dwAddressStates));
m_Dlg.AddText(info);
info.Format("[Supported CallState() = %s]",
DescribeCallState(s1, pAddressCaps->dwCallStates));
m_Dlg.AddText(info);
info.Format("[Supported CallInfo() = %s]",
DescribeCallInfo(s1, pAddressCaps->dwCallInfoStates));
m_Dlg.AddText(info);
info.Format("[Call Completion Capabilities = %s]",
DescribeCallCompletion(s1, pAddressCaps->dwCallCompletionModes));
m_Dlg.AddText(info);
info.Format("[Call Features = %s %s]",
DescribeCallFeatures(s1, pAddressCaps->dwCallFeatures),
DescribeCallFeatures2(s2, pAddressCaps->dwCallFeatures2) );
m_Dlg.AddText(info);
info.Format("[Address Capabilities = %s]",
DescribeAddressCapabilities(s1, pAddressCaps->dwAddrCapFlags));
m_Dlg.AddText(info);*/
delete [] pAddressCaps;
}
}
else
{
delete m_pLines[LineID]; m_pLines[LineID] = NULL;
}
}
}
delete [] pDevCaps;
}
}
TRACE("Number of Open Lines: %d\n", nOpenedLines);
if( !nOpenedLines )
{
delete[] m_pLines;
m_pLines = NULL;
}
m_Dlg.CheckButtons();
}
// ----------------------------------------------------------------------------
// Note an immediate error message
void TapiApplication::CheckError(HRESULT hr, LPCTSTR pszCommand)
{
if (hr < 0)
{
CString info;
info.Format("Error(%s:0x%lx)", pszCommand, hr);
m_Dlg.AddText(info);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -