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

📄 tapiline.cpp

📁 基于TAPI 2.0的软电话源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
{
	// 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,
										&params			);
	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 + -