static void handleUnmuteVideoForFirstConnectedCall (CallControlManagerPtr ccmPtr) { //If there is more than 1 call with a mix of audio/video calls //the we may need to look at the cc_sdp_direction_t to figure out //which CONNECTED call is actually a video call and is sending video CC_CallPtr call = getFirstCallInGivenState(ccmPtr, CONNECTED); if (call != NULL) { CSFLogDebugS(logTag, "Unmuting (video) 1st connected call..."); if (!call->unmuteVideo()) { CSFLogDebugS(logTag, "Attempt to unmute (video) failed."); } CC_CallInfoPtr info = call->getCallInfo(); if (info->isVideoMuted()) { CSFLogDebugS(logTag, "UNMUTE FAILED TO BE REFLECTED IN CALL INFO."); } } else { CSFLogDebugS(logTag, "No calls exist that can be unmuted (video)."); } }
static void handlePickUpFirstCallWithAnswerCaps (CallControlManagerPtr ccmPtr) { CC_CallPtr answerableCall = getFirstCallWithCapability(ccmPtr, CC_CallCapabilityEnum::canAnswerCall); if (answerableCall != NULL) { CSFLogDebugS(logTag, "Answering incoming call..."); // CC_SDP_DIRECTION_SENDRECV means 2 way video. We could use CC_SDP_DIRECTION_INACTIVE to answer with no video // Note that we are attempting to negotiate video on every call, even tough // some calls might not have video capability - so maybe we need to check the call first. cc_sdp_direction_t videoPref = getActiveVideoPref(); #ifndef NOVIDEO videoPref = (showVideoAutomatically) ? videoPref : CC_SDP_DIRECTION_INACTIVE; #endif if (!answerableCall->answerCall(videoPref)) { CSFLogDebugS(logTag, "Attempt to answer incoming call failed."); } #ifndef NOVIDEO if(videoPref != CC_SDP_DIRECTION_INACTIVE) { answerableCall->setRemoteWindow((VideoWindowHandle)hVideoWindow); } #endif } else { CSFLogDebugS(logTag, "No calls exist that can be answered."); } }
void VideoWindowWorkItem::Run () { VideoWindow vNewWnd; vWnd = vNewWnd; vWnd.SetWindowStyle(WT_FRAME|WT_NORMAL/*|WT_NOWINPROC*/); vWnd.InitWindow(); #ifdef WIN32 hVideoWindow = (HWND)vWnd.GetRenderingWindowHandle(); #else hVideoWindow = (Window)vWnd.GetRenderingWindowHandle(); #endif CSFLogDebug(logTag, "new window handle: %d", (int) hVideoWindow); // if there is a current call, make sure it gets the window handle as soon as possible if (ccmPtr != NULL) { CC_CallPtr call = getFirstCallInGivenState(ccmPtr, CONNECTED); if (call != NULL) { CSFLogDebug(logTag, "setting rem window on current call: %d\n", (int) hVideoWindow); call->setRemoteWindow((VideoWindowHandle)hVideoWindow); } } #ifdef WIN32 MSG Msg; while(GetMessage(&Msg, hVideoWindow, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); switch (Msg.message) { case WM_WINDOWCLOSE: vWnd.CloseWindow(); return; case WM_DESTROY: vWnd.CloseWindow(); return; } if (endWindowWorkItem == true) break; } #else while(true) { CSFLogDebugS(logTag, "_WindowThreadEvent.TimedWait(-1);"); _WindowThreadEvent.TimedWait(base::TimeDelta::FromMilliseconds(-1)); CSFLogDebugS(logTag, "return from _WindowThreadEvent.await(-1);"); if (endWindowWorkItem == true) break; } #endif endWindowWorkItem = false; // so we do not immediately end the next one CSFLogDebugS(logTag, "VideoWindowWorkItem exiting"); }
static void handleOriginateP2PPhoneCall (CallControlManagerPtr ccmPtr, const string & phoneNumberToCall) { string digits = phoneNumberToCall; digits.erase(remove_if(digits.begin(), digits.end(), std::not1(std::ptr_fun(isPhoneDNDigit))), digits.end()); CC_DevicePtr devicePtr = ccmPtr->getActiveDevice(); if (devicePtr != NULL) { CC_CallPtr outgoingCall = devicePtr->createCall(); CSFLogDebugS(logTag, "Created call, "); cc_sdp_direction_t videoPref = getActiveVideoPref(); const char * pMediaTypeStr = getUserFriendlyNameForVideoPref(videoPref); #ifndef NOVIDEO CSFLogDebug(logTag, " SUHAS SUHAS SUHAS SUHAS SUHAS SUHAS SUHAS "); // associate the video window - even if this is not a video call, it might be escalated later, so // it is easier to always associate them outgoingCall->setRemoteWindow((VideoWindowHandle)hVideoWindow); #endif CSFLogDebug(logTag, " dialing (%s) # %s...", pMediaTypeStr, digits.c_str()); if (outgoingCall->originateP2PCall(videoPref, digits, PEERIPAddress)) { CSFLogDebug(logTag, "Dialing (%s) %s...", pMediaTypeStr, digits.c_str()); } else { CSFLogDebugS(logTag, "Attempt to originate call failed."); } } }
static void handleRemoveVideoFromConnectedCall( CallControlManagerPtr ccmPtr) { CC_CallPtr call = getFirstCallInGivenState(ccmPtr, CONNECTED); if(call != NULL) { if(call->getCallInfo()->hasCapability(CC_CallCapabilityEnum::canUpdateVideoMediaCap)) { if(call->updateVideoMediaCap(CC_SDP_DIRECTION_INACTIVE)) { CSFLogDebugS(logTag, "Removed video from first connected call."); } else { CSFLogDebugS(logTag, "Failed to remove video from first connected call."); } } else { CSFLogDebugS(logTag, "Cannot add video to this call - capability not currently available."); } } else { CSFLogDebugS(logTag, "No currently connected calls, cannot remove video."); } }
void printCallSummary(CC_DevicePtr devicePtr) { if (devicePtr == NULL) { return; } CC_DeviceInfoPtr deviceInfoPtr = devicePtr->getDeviceInfo(); if (deviceInfoPtr == NULL) { return; } vector<CC_CallPtr> calls = deviceInfoPtr->getCalls(); CSFLogDebugS(logTag, " List of all calls "); for (vector<CC_CallPtr>::iterator it = calls.begin(); it != calls.end(); it++) { CC_CallPtr call = *it; if (call==NULL) { continue; } CC_CallInfoPtr callInfoPtr = call->getCallInfo(); if (callInfoPtr==NULL) { continue; } bool audioMute = callInfoPtr->isAudioMuted(); bool videoMute = callInfoPtr->isVideoMuted(); PRINT_OFFSET_1; PRINT_EVENT_INFO_NICELY_USING_GETNAME("CallState", callInfoPtr, getCallState, call_state_getname); PRINT_OFFSET_1; PRINT_EVENT_INFO_NICELY_USING_GETNAME("CallType", callInfoPtr, getCallType, call_type_getname); PRINT_OFFSET_1; PRINT_EVENT_INFO_NICELY_USING_GETNAME("VideoDirection", callInfoPtr, getVideoDirection, sdp_direction_getname); PRINT_OFFSET_1; CSFLogDebugS(logTag, "(AudioMute "); CSFLogDebugS(logTag, "----------"); CSFLogDebug(logTag, " %s )", (audioMute) ? "true" : "false"); PRINT_OFFSET_1; CSFLogDebugS(logTag, "(VideoMute "); CSFLogDebugS(logTag, "----------"); CSFLogDebug(logTag, " %s )", (videoMute) ? "true" : "false"); PRINT_OFFSET_1; printCallPartiesInfo(callInfoPtr); PRINT_OFFSET_1; CSFLogDebugS(logTag, "(CallCaps "); CSFLogDebugS(logTag, "----------"); printCallCapabilities(callInfoPtr, WRAPPED_LINE_ALIGNMENT_OFFSET_2); }//end for (calls) CSFLogDebugS(logTag, "End of List"); }
/** This function gets a snapshot of all calls and examines each one in turn. If it find a call whose state is one of the specified states then it returns that call. @param [in] ccmPtr - @param [in] callStates - A vector of the call states being checked for. All existing calls are examined and the first (in no particular order) call that is in one of those states is returned, if there is one. @return Returns a NULL_PTR if there are no calls in the given states. If a call is found in the given states then that CC_CallPtr is returned. */ static CC_CallPtr getFirstCallInGivenStates (CallControlManagerPtr ccmPtr, const vector<cc_call_state_t>& callStates) { CSFLogDebugS(logTag, "getFirstCallInGivenStates()"); if (ccmPtr == NULL) { return NULL_PTR(CC_Call); } CC_DevicePtr devicePtr = ccmPtr->getActiveDevice(); if (devicePtr == NULL) { CSFLogDebugS(logTag, "devicePtr was NULL, returning"); return NULL_PTR(CC_Call); } CC_DeviceInfoPtr deviceInfoPtr = devicePtr->getDeviceInfo(); if (deviceInfoPtr == NULL) { CSFLogDebugS(logTag, "deviceInfoPtr was NULL, returning"); return NULL_PTR(CC_Call); } vector<CC_CallPtr> calls = deviceInfoPtr->getCalls(); for (vector<CC_CallPtr>::iterator it = calls.begin(); it != calls.end(); it++) { CC_CallPtr call = *it; if (call == NULL) { continue; } CC_CallInfoPtr callInfoPtr = call->getCallInfo(); if (callInfoPtr == NULL) { continue; } CSFLogDebugS(logTag, "about to check call for states"); for (vector<cc_call_state_t>::const_iterator it = callStates.begin(); it != callStates.end(); it++) { cc_call_state_t callState = *it; if (callInfoPtr->getCallState() == callState) { return call; } } }//end for (calls) return NULL_PTR(CC_Call); }
//Returns true if given capability is available on entry to this function, or became //available within the specified timeframe bool awaitCallCapability (CC_CallPtr call, CC_CallCapabilityEnum::CC_CallCapability capToWaitFor, int timeoutMilliSeconds) { int nTimeStart = GetTimeNow(); int remainingTimeout = timeoutMilliSeconds; do { CC_CallInfoPtr info = call->getCallInfo(); if (info != NULL) { if (info->hasCapability(capToWaitFor)) { return true; } } else { CSFLogDebugS(logTag, "CC_CallPtr->getCallInfo() failed"); return false; } int nTimeElapsed = GetTimeElapsedSince( nTimeStart ); remainingTimeout -= nTimeElapsed; } while (_callCapsMayHaveChanged.TimedWait(base::TimeDelta::FromMilliseconds(remainingTimeout))); return false; }
/** This function gets a snapshot of all calls and examines each one in turn. If it find a call that is in the specified state then it returns this call. @param [in] ccmPtr - @param [in] callState - This is the call state being checked for. All existing calls are examined and the first (in no particular order) call that is in this state is returned, if there is one. @return Returns a NULL_PTR if there are no calls in the given state. If a call is found in the given state then that CC_CallPtr is returned. */ static CC_CallPtr getFirstCallInGivenState (CallControlManagerPtr ccmPtr, cc_call_state_t callState) { if (ccmPtr == NULL) { return NULL_PTR(CC_Call); } CC_DevicePtr devicePtr = ccmPtr->getActiveDevice(); if (devicePtr == NULL) { return NULL_PTR(CC_Call); } CC_DeviceInfoPtr deviceInfoPtr = devicePtr->getDeviceInfo(); if (deviceInfoPtr == NULL) { return NULL_PTR(CC_Call); } vector<CC_CallPtr> calls = deviceInfoPtr->getCalls(); for (vector<CC_CallPtr>::iterator it = calls.begin(); it != calls.end(); it++) { CC_CallPtr call = *it; if (call == NULL) { continue; } CC_CallInfoPtr callInfoPtr = call->getCallInfo(); if (callInfoPtr == NULL) { continue; } if (callInfoPtr->getCallState() == callState) { return call; } }//end for (calls) return NULL_PTR(CC_Call); }
/** This function gets a snapshot of all calls and examines each one in turn. If it find a call that has the specified capability then it returns this call. @param [in] ccmPtr - @param [in] cap - This is the capability being examined. All existing calls are examined and the first (in no particular order) call that has this capability is returned, if there is one. @return Returns a NULL_PTR if there are no calls with the given capability. If a call is found with the given capability then that CC_CallPtr is returned. */ static CC_CallPtr getFirstCallWithCapability (CallControlManagerPtr ccmPtr, CC_CallCapabilityEnum::CC_CallCapability cap) { if (ccmPtr == NULL) { return NULL_PTR(CC_Call); } CC_DevicePtr devicePtr = ccmPtr->getActiveDevice(); if (devicePtr == NULL) { return NULL_PTR(CC_Call); } CC_DeviceInfoPtr deviceInfoPtr = devicePtr->getDeviceInfo(); if (deviceInfoPtr == NULL) { return NULL_PTR(CC_Call); } vector<CC_CallPtr> calls = deviceInfoPtr->getCalls(); for (vector<CC_CallPtr>::iterator it = calls.begin(); it != calls.end(); it++) { CC_CallPtr call = *it; if (call == NULL) { continue; } CC_CallInfoPtr callInfoPtr = call->getCallInfo(); if (callInfoPtr == NULL) { continue; } if (callInfoPtr->hasCapability(cap)) { return call; } }//end for (calls) return NULL_PTR(CC_Call); }
static void handleEndFirstCallWithEndCallCaps (CallControlManagerPtr ccmPtr) { CC_CallPtr endableCall = getFirstCallWithCapability(ccmPtr, CC_CallCapabilityEnum::canEndCall); if (endableCall != NULL) { CSFLogDebugS(logTag, "Hanging up 1st call that can be ended..."); if (!endableCall->endCall()) { CSFLogDebugS(logTag, "\nAttempt to end call failed."); } } else { CSFLogDebugS(logTag, "No calls exist that can be ended."); } }
static void handleHoldFirstCallWithHoldCaps (CallControlManagerPtr ccmPtr) { CC_CallPtr holdableCall = getFirstCallWithCapability(ccmPtr, CC_CallCapabilityEnum::canHold); if (holdableCall != NULL) { CSFLogDebugS(logTag, "Putting 1st call that can be held on HOLD..."); if (!holdableCall->hold(CC_HOLD_REASON_NONE)) { CSFLogDebugS(logTag, "Attempt to HOLD call failed."); } } else { CSFLogDebugS(logTag, "No calls exist that can be put on HOLD."); } }
static void handleSendDTMFDigitOnFirstCallWithDTMFCaps (CallControlManagerPtr ccmPtr, const cc_digit_t & dtmfDigit) { CC_CallPtr dtmfAbleCall = getFirstCallWithCapability(ccmPtr, CC_CallCapabilityEnum::canSendDigit); if (dtmfAbleCall != NULL) { CSFLogDebug(logTag, "Sending DTMF digit \"%s\" on first call that allows DTMF.", digit_getname(dtmfDigit)); if (!dtmfAbleCall->sendDigit(dtmfDigit)) { CSFLogDebugS(logTag, "Attempt to send DTMF digit failed."); } } else { CSFLogDebugS(logTag, "Cannot send DTMF digit as there are no calls that allow DTMF."); } }
static void handleResumeFirstCallWithResumeCaps (CallControlManagerPtr ccmPtr) { CC_CallPtr resumableCall = getFirstCallWithCapability(ccmPtr, CC_CallCapabilityEnum::canResume); if (resumableCall != NULL) { cc_sdp_direction_t videoPref = getActiveVideoPref(); CSFLogDebug(logTag, "RESUMING 1st HELD call as a (%s) call...", getUserFriendlyNameForVideoPref(videoPref)); if (!resumableCall->resume(videoPref)) { CSFLogDebugS(logTag, "Attempt to RESUME call failed."); } } else { CSFLogDebugS(logTag, "No calls exist that can be RESUMED."); } }
static void handleVideoAvailableChangeOnConnectedCall(CallControlManagerPtr ccmPtr) { vector<cc_call_state_t> permittedCallStates; permittedCallStates.push_back(CONNECTED); permittedCallStates.push_back(RINGOUT); permittedCallStates.push_back(OFFHOOK); CSFLogDebugS(logTag, "About to getFirstCallInGivenStates()"); CC_CallPtr call = getFirstCallInGivenStates(ccmPtr, permittedCallStates); if (call != NULL) { if(call->getCallInfo()->getVideoDirection() == CC_SDP_DIRECTION_INACTIVE) { //A GUI client would hide the video window at this point CSFLogDebugS(logTag, "Video now inactive."); } else if(call->getCallInfo()->getVideoDirection() == CC_SDP_DIRECTION_SENDRECV) { //A GUI client would (re)display the video window at this point CSFLogDebugS(logTag, "Video now active in both directions."); } else if(call->getCallInfo()->getVideoDirection() == CC_SDP_DIRECTION_RECVONLY) { //A GUI client would (re)display the video window at this point CSFLogDebugS(logTag, "Video now active in receive direction."); } else { //We're not supporting either send-only or video, //we should never end up in this state. CSFLogDebugS(logTag, "Video now in unsupported configuration."); } } else { CSFLogDebugS(logTag,"Notified of VideoAvailable change, but no connected call to apply it to."); } }
static void handleAddVideoToConnectedCall( CallControlManagerPtr ccmPtr) { #ifndef NOVIDEO CC_CallPtr call = getFirstCallInGivenState(ccmPtr, CONNECTED); if(call != NULL) { if(call->getCallInfo()->getVideoDirection() == CC_SDP_DIRECTION_SENDRECV) { CSFLogDebugS(logTag, "First connected call already has video."); } else { if(call->getCallInfo()->hasCapability(CC_CallCapabilityEnum::canUpdateVideoMediaCap)) { if(call->updateVideoMediaCap(CC_SDP_DIRECTION_SENDRECV)) { call->setRemoteWindow((VideoWindowHandle)hVideoWindow); CSFLogDebugS(logTag, "Video added to first connected call."); } else { CSFLogDebugS(logTag, "Failed to add video to first connected call."); } } else { CSFLogDebugS(logTag, "Cannot add video to this call - capability not currently available."); } } } else { CSFLogDebugS(logTag, "No currently connected calls, cannot add video."); } #endif }
static void handleUnmuteAudioForFirstConnectedCall (CallControlManagerPtr ccmPtr) { CC_CallPtr call = getFirstCallInGivenState(ccmPtr, CONNECTED); if (call != NULL) { CSFLogDebugS(logTag, "Unmuting (audio) 1st connected call..."); if (!call->unmuteAudio()) { CSFLogDebugS(logTag, "Attempt to unmute (audio) failed."); } CC_CallInfoPtr info = call->getCallInfo(); if (info->isAudioMuted()) { // note that when CTI adds mute it might fail here, because the setAudioMute will not be a synchronous call // So we might change this check for CTI when that time comes. CSFLogDebugS(logTag, "MUTE FAILED TO BE REFLECTED IN CALL INFO"); } } else { CSFLogDebugS(logTag, "No calls exist that can be unmuted (audio)."); } }
bool CC_SIPCCCall::transferComplete (CC_CallPtr otherLeg, cc_sdp_direction_t video_pref) { return (CCAPI_Call_transferComplete(callHandle, ((CC_SIPCCCall*)otherLeg.get())->callHandle, video_pref) == CC_SUCCESS); }
void CC_CapsPrinter::onCallEvent (ccapi_call_event_e callEvent, CC_CallPtr call, CC_CallInfoPtr info, char* sdp ) { base::AutoLock lock(eventPrinterMutex); printHeaderBlockIfNotAlreadyPrinted(); CSFLogDebugS(logTag, "C:"); printCurrentThreadID(); std::string eventNameStr = truncateLeft(call_event_getname(callEvent), EVENT_NAME_FIELD_WIDTH); CSFLogDebug(logTag, "%*s %s ", EVENT_NAME_FIELD_WIDTH, eventNameStr.c_str(), call->toString().c_str()); switch (callEvent) { case CCAPI_CALL_EV_CALLINFO: printCallPartiesInfo(info); break; case CCAPI_CALL_EV_STATE: /* Whenever we get a CCAPI_CALL_EV_STATE the expectation is that we call getCapabilitySet() to get the current list of caps, or we call hasCapability(ccapi_call_capability_e) to determine if a given capability is available or not. */ PRINT_EVENT_INFO_NICELY_USING_GETNAME("CallState", info, getCallState, call_state_getname); PRINT_OFFSET_1; if (info->getCallState() == RINGIN) { printCallPartiesInfo(info); } PRINT_OFFSET_1; PRINT_EVENT_INFO_NICELY_USING_GETNAME("CallType", info, getCallType, call_type_getname); PRINT_OFFSET_1; PRINT_EVENT_INFO_NICELY_USING_GETNAME("VideoDirection", info, getVideoDirection, sdp_direction_getname); PRINT_OFFSET_1; CSFLogDebugS(logTag, "(CallCaps "); CSFLogDebugS(logTag, "----------"); printCallCapabilities(info, WRAPPED_LINE_ALIGNMENT_OFFSET_2); break; case CCAPI_CALL_EV_STATUS: PRINT_EVENT_INFO_NICELY_FOR_STRING ("CallStatus", info, getStatus); break; case CCAPI_CALL_EV_ATTR: PRINT_EVENT_INFO_NICELY_USING_GETNAME("CallAttr", info, getCallAttr, call_attr_getname); break; case CCAPI_CALL_EV_SECURITY: PRINT_EVENT_INFO_NICELY_USING_GETNAME("CallSecurity", info, getSecurity, call_security_getname); break; case CCAPI_CALL_EV_CAPABILITY: // printCallCapabilities(info, WRAPPED_LINE_ALIGNMENT_OFFSET_1); break; case CCAPI_CALL_EV_VIDEO_AVAIL: PRINT_EVENT_INFO_NICELY_USING_GETNAME("VideoDirection", info, getVideoDirection, sdp_direction_getname); PRINT_OFFSET_1; break; case CCAPI_CALL_EV_VIDEO_OFFERED: PRINT_EVENT_INFO_NICELY_USING_GETNAME("VideoDirection", info, getVideoDirection, sdp_direction_getname); PRINT_OFFSET_1; break; default: break; }//end switch }
// Volume change: If a RINGIN call exists, adjust ringer volume. // If CONNECTED exists, adjust current call volume. // Otherwise, adjust default call volume. static void handleAdjustVolume (CallControlManagerPtr ccmPtr, int adjust) { CC_CallPtr call = getFirstCallInGivenState(ccmPtr, RINGIN); if (call != NULL) { CSFLogDebug(logTag, "Changing ringer volume %d...", adjust); int currentVolume = ccmPtr->getAudioControl()->getRingerVolume(); if (currentVolume == -1) { CSFLogDebugS(logTag, "Attempt to determine ringer volume failed."); } else { int newVolume = currentVolume + adjust; newVolume = newVolume > 100 ? 100 : newVolume < 0 ? 0 : newVolume; if(!ccmPtr->getAudioControl()->setRingerVolume(newVolume)) { CSFLogDebugS(logTag, "Attempt to adjust ringer volume failed."); } } return; } call = getFirstCallInGivenState(ccmPtr, CONNECTED); if (call != NULL) { CSFLogDebug(logTag, "Changing call volume %d...", adjust); CC_CallInfoPtr info = call->getCallInfo(); int currentVolume = info->getVolume(); if (currentVolume == -1) { CSFLogDebugS(logTag, "Attempt to determine call volume failed."); } else { int newVolume = currentVolume + adjust; newVolume = newVolume > 100 ? 100 : newVolume < 0 ? 0 : newVolume; if(!call->setVolume(newVolume)) { CSFLogDebugS(logTag, "Attempt to adjust call volume failed."); } } return; } CSFLogDebug(logTag, "Changing default call volume %d...", adjust); int currentVolume = ccmPtr->getAudioControl()->getDefaultVolume(); if (currentVolume == -1) { CSFLogDebugS(logTag, "Attempt to determine default call volume failed."); } else { int newVolume = currentVolume + adjust; newVolume = newVolume > 100 ? 100 : newVolume < 0 ? 0 : newVolume; if(!ccmPtr->getAudioControl()->setDefaultVolume(newVolume)) { CSFLogDebugS(logTag, "Attempt to adjust default call volume failed."); } } }
bool CC_SIPCCCall::joinAcrossLine (CC_CallPtr target) { return (CCAPI_Call_joinAcrossLine(callHandle, ((CC_SIPCCCall*)target.get())->callHandle) == CC_SUCCESS); }
bool CC_SIPCCCall::directTransfer (CC_CallPtr target) { return (CCAPI_Call_directTransfer(callHandle, ((CC_SIPCCCall*)target.get())->callHandle) == CC_SUCCESS); }