예제 #1
0
static int TransferListener (rmt_transfer_event_t *event) {
    int ret_value = 0;

    if (Initialized)
	ret_value = OnTransferEvent (event);
    return (ret_value);
}
예제 #2
0
/*****************************************************************************
** Procedure:  CJTLine::UnsolicitedEvent
**
** Arguments:  'lpBuff' - Our CEventBlock* pointer
**
** Returns:    void
**
** Description:  This function is called when no request processed a given
**               response from the device and it was directed at this line.
**
*****************************************************************************/
bool CJTLine::UnsolicitedEvent(LPCVOID lpBuff)
{
	// Cast our pointer back to an event block
	const CEventBlock* pBlock = static_cast<const CEventBlock*>(lpBuff);

#ifdef _DEBUG
	// Output a dump of the received block with all it's elements.
	_TSP_DTRACE(_T("EventHandler: %s"), pBlock->Dump().c_str());
#endif

	// See if there is a callid attached to this request. If so, pull it out and
	// attempt to locate the TSP++ call object which is associated with the call.
	CTSPICallAppearance* pCall = NULL;
	const CPECallID* pidCall = dynamic_cast<const CPECallID*>(pBlock->GetElement(CPBXElement::CallID));
	if (pidCall != NULL)
	{
		// Find the call associated with the callid
		pCall = FindCallByCallID(pidCall->GetCallID());

		// If we have no call object and this is NOT a CP/CD event then ignore it.
		// Our PBX switch has no mechanism for querying information on an existing call.
		// A production-level TSP might make some educated guesses here and possibly
		// create a new call to reflect this one.
		if (pCall == NULL && 
				(pBlock->GetEventType() != CEventBlock::CallDetected &&
				 pBlock->GetEventType() != CEventBlock::CallPlaced))
		{
			_TSP_DTRACE(_T("Ignoring event with unknown callid 0x%lx\n"), pidCall->GetCallID());
			return false;
		}
	}

	// Process the line event we just received.
	switch (pBlock->GetEventType())
	{
		// Agent state changed
		case CEventBlock::AgentStateChanged:
		{
			const CPEAgentState* peState = dynamic_cast<const CPEAgentState*>(pBlock->GetElement(CPBXElement::AgentState));
			OnAgentStateChange(peState->GetAgentState());
		}
		break;

		// Agent group changed
		case CEventBlock::AgentGroupChanged:
		{
			const CPEAgentID* peAgent = dynamic_cast<const CPEAgentID*>(pBlock->GetElement(CPBXElement::AgentID));
			const CPEAgentGroup* pePGroup = dynamic_cast<const CPEAgentGroup*>(pBlock->GetElement(CPBXElement::PrimaryAgentGroup));
			const CPEAgentGroup* peSGroup = dynamic_cast<const CPEAgentGroup*>(pBlock->GetElement(CPBXElement::SecondaryAgentGroup));
			OnAgentGroupChange(peAgent->GetAgentID().c_str(), pePGroup->GetAgentGroup(), peSGroup->GetAgentGroup());
		}
		break;

		// Call Detected or placed (via PlaceCall or PredictivePlaceCall) on the line.
		case CEventBlock::CallDetected:
		case CEventBlock::CallPlaced:
		{
			const CPECallInfo* peCaller = dynamic_cast<const CPECallInfo*>(pBlock->GetElement(CPBXElement::DNIS));
			const CPECallInfo* peCalled = dynamic_cast<const CPECallInfo*>(pBlock->GetElement(CPBXElement::ANI));
			pCall = OnNewCallDetected((pBlock->GetEventType() == CEventBlock::CallPlaced),
										pCall, pidCall->GetCallID(), peCaller, peCalled);
		}
		break;

		// Call released - callid is no longer valid.
		case CEventBlock::CallReleased:
			if (pCall != NULL)
			{
				pCall->SetCallState(LINECALLSTATE_IDLE);
				// If our current call count is now zero, then force the TSP to
				// re-evaluate our current agent state and features - this is
				// because we cannot rely on the PBX simulator to send the "ASC"
				// event after all calls are deallocated (vs. before). When a call
				// is transferred off a line, the "ASC" event precedes the "CR" event
				// and causes our agent features to be incorrectly reported.
				if (GetAddress(0)->GetAddressStatus()->dwNumActiveCalls == 0)
					OnAgentStateChange(-1);
			}
			break;

		// Call state has changed
		case CEventBlock::CallStateChange:
		{
			const CPECallState* pCS = dynamic_cast<const CPECallState*>(pBlock->GetElement(CPBXElement::CallState));
			OnCallStateChange(pCall, pCS);
		}
		break;

		// DTMF Digit detected on the call
		case CEventBlock::DigitDetected:
		{
			const CPEDigit* pDigit = dynamic_cast<const CPEDigit*>(pBlock->GetElement(CPBXElement::Digit));
			// Pass the digit through to the call - simulator up/down press for duration.
			pCall->OnDigit(LINEDIGITMODE_DTMF, pDigit->GetDigit());
			pCall->OnDigit(LINEDIGITMODE_DTMFEND, pDigit->GetDigit());
		}
		break;

		// Call queued to ACD (transfer event to ACD queue)
		case CEventBlock::CallQueued:
		{
			const CPEExtension* pTarget = dynamic_cast<const CPEExtension*>(pBlock->GetElement(CPBXElement::Queue));
			OnTransferEvent(pCall, 0, pTarget->GetExtension(), NULL, NULL);
		}
		break;

		// Predictive Dialer media detected
		case CEventBlock::CallMediaDetected:
		{
			const CPEAnswerType* pidAnswer = dynamic_cast<const CPEAnswerType*>(pBlock->GetElement(CPBXElement::AnswerType));
			OnPDialerMediaDetected(pCall, pidAnswer->GetAnswerType());
		}
		break;

		// Call Conference created
		case CEventBlock::CallConference:
		{
			const CPECallID* pidCall1 = dynamic_cast<const CPECallID*>(pBlock->GetElement(CPBXElement::ConfCallID1));
			const CPECallID* pidCall2 = dynamic_cast<const CPECallID*>(pBlock->GetElement(CPBXElement::ConfCallID2));
			OnConferenceEvent(pCall, pidCall1->GetCallID(), pidCall2->GetCallID());
		}
		break;

		// Call Transferred
		case CEventBlock::CallTransfer:
		{
			const CPECallID* pidOldCallId = dynamic_cast<const CPECallID*>(pBlock->GetElement(CPBXElement::OldCallID));
			const CPEExtension* pTarget = dynamic_cast<const CPEExtension*>(pBlock->GetElement(CPBXElement::TargetExtension));
			const CPECallInfo* peCaller = dynamic_cast<const CPECallInfo*>(pBlock->GetElement(CPBXElement::DNIS));
			const CPECallInfo* peCalled = dynamic_cast<const CPECallInfo*>(pBlock->GetElement(CPBXElement::ANI));
			OnTransferEvent(pCall, pidOldCallId->GetCallID(), pTarget->GetExtension(), peCaller, peCalled);
		}
		break;

		// Unknown or unhandled
		default:
			break;
	}

	// It doesn't really matter what we return to this function since we are letting
	// the library handle the request management directly. The caller doesn't look
	// at the return code for unsolicited handlers. If we were managing the
	// ReceiveData() ourselves then this could be used to continue looking for
	// an owner for a data event.
	return true;

}// CJTLine::UnsolicitedEvent