static int TransferListener (rmt_transfer_event_t *event) { int ret_value = 0; if (Initialized) ret_value = OnTransferEvent (event); return (ret_value); }
/***************************************************************************** ** 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