private void OnCallStateChanged(IntPtr lc, IntPtr callPtr, LinphoneCallState cstate, string message) { if (linphoneCore == IntPtr.Zero) return; LOG.Info(string.Format( "OnCallStateChanged: State - {0}, CallPtr - {1}, Message: {2}", cstate, callPtr, message)); var newstate = VATRPCallState.None; var direction = LinphoneCallDir.LinphoneCallIncoming; string remoteParty = ""; IntPtr addressStringPtr; bool removeCall = false; // detecting direction, state and source-destination data by state switch (cstate) { case LinphoneCallState.LinphoneCallIncomingReceived: case LinphoneCallState.LinphoneCallIncomingEarlyMedia: newstate = cstate == LinphoneCallState.LinphoneCallIncomingReceived ? VATRPCallState.InProgress : VATRPCallState.EarlyMedia; addressStringPtr = LinphoneAPI.linphone_call_get_remote_address_as_string(callPtr); if (addressStringPtr != IntPtr.Zero) { identity = Marshal.PtrToStringAnsi(addressStringPtr); LinphoneAPI.ortp_free(addressStringPtr); } remoteParty = identity; break; case LinphoneCallState.LinphoneCallOutgoingEarlyMedia: case LinphoneCallState.LinphoneCallConnected: newstate = VATRPCallState.Connected; break; case LinphoneCallState.LinphoneCallStreamsRunning: newstate = VATRPCallState.StreamsRunning; break; case LinphoneCallState.LinphoneCallPausedByRemote: newstate = VATRPCallState.RemotePaused; break; case LinphoneCallState.LinphoneCallPausing: newstate = VATRPCallState.LocalPausing; break; case LinphoneCallState.LinphoneCallPaused: newstate = VATRPCallState.LocalPaused; break; case LinphoneCallState.LinphoneCallResuming: newstate = VATRPCallState.LocalResuming; break; case LinphoneCallState.LinphoneCallOutgoingInit: case LinphoneCallState.LinphoneCallOutgoingProgress: case LinphoneCallState.LinphoneCallOutgoingRinging: newstate = cstate != LinphoneCallState.LinphoneCallOutgoingRinging ? VATRPCallState.Trying : VATRPCallState.Ringing; direction = LinphoneCallDir.LinphoneCallOutgoing; addressStringPtr = LinphoneAPI.linphone_call_get_remote_address_as_string(callPtr); if (addressStringPtr != IntPtr.Zero) { remoteParty = Marshal.PtrToStringAnsi(addressStringPtr); LinphoneAPI.ortp_free(addressStringPtr); } break; case LinphoneCallState.LinphoneCallError: string linphoneLibraryVersion = VATRP.LinphoneWrapper.LinphoneAPI.linphone_core_get_version_asString(); LOG.Info("OnCallStateChanged: CallState=LinphoneCallError .LinphoneLib Version: " + linphoneLibraryVersion); newstate = VATRPCallState.Error; removeCall = true; break; case LinphoneCallState.LinphoneCallEnd: newstate = VATRPCallState.Closed; removeCall = true; break; case LinphoneCallState.LinphoneCallReleased: if ((_declinedCallsList != null) && _declinedCallsList.Contains(callPtr)) { LOG.Info(" trying to remove callPtr from declinedCallList"); _declinedCallsList.Remove(callPtr); } LOG.Info(" calling linphone_call_unref"); try { LinphoneAPI.linphone_call_unref(callPtr); LOG.Info(" passed unref"); } catch (Exception ex) { LOG.Error("LinphoneService.OnCallStateChanged: Exception occured while calling linphone_call_unref. Details: " + ex.Message); } return; } lock (callLock) { VATRPCall call = FindCall(callPtr); if (call == null) { if (_declinedCallsList.Contains(callPtr)) return; if (GetActiveCallsCount > 1) { callPtr = LinphoneAPI.linphone_call_ref(callPtr); var cmd = new DeclineCallCommand(callPtr, LinphoneReason.LinphoneReasonBusy); commandQueue.Enqueue(cmd); _declinedCallsList.Add(callPtr); return; } if (!removeCall) { LOG.Info("Call not found. Adding new call into list. ID - " + callPtr + " Calls count: " + callsList.Count); callPtr = LinphoneAPI.linphone_call_ref(callPtr); call = new VATRPCall(callPtr) {CallState = newstate, CallDirection = direction}; CallParams from = direction == LinphoneCallDir.LinphoneCallIncoming ? call.From : call.To; CallParams to = direction == LinphoneCallDir.LinphoneCallIncoming ? call.To : call.From; if ( !VATRPCall.ParseSipAddressEx(remoteParty, out from.DisplayName, out from.Username, out from.HostAddress, out from.HostPort)) from.Username = "******"; if ( !VATRPCall.ParseSipAddressEx(remoteParty, out to.DisplayName, out to.Username, out to.HostAddress, out to.HostPort)) to.Username = "******"; IntPtr chatPtr = LinphoneAPI.linphone_call_get_chat_room(callPtr); if (chatPtr != IntPtr.Zero) { VATRPContact contact; var contactAddress = string.Empty; if (direction == LinphoneCallDir.LinphoneCallIncoming) { contactAddress = string.Format("{0}@{1}", from.Username, from.HostAddress); contact = new VATRPContact(new ContactID(contactAddress, chatPtr)) { DisplayName = from.DisplayName, Fullname = from.Username, SipUsername = from.Username }; } else { contactAddress = string.Format("{0}@{1}", to.Username, to.HostAddress); contact = new VATRPContact(new ContactID(contactAddress, chatPtr)) { DisplayName = to.DisplayName, Fullname = to.Username, SipUsername = to.Username }; } contact.RegistrationName = contactAddress; call.ChatRoom = manager.ChatService.InsertRttChat(contact, chatPtr, callPtr); var loggedContact = manager.ContactService.FindLoggedInContact(); if (loggedContact != null) call.ChatRoom.AddContact(loggedContact); } callsList.Add(call); } } if (call != null) { call.LinphoneMessage = message; call.CallState = newstate; if (call.CallState == VATRPCallState.Error || call.CallState == VATRPCallState.Closed) { IntPtr errorReason = LinphoneAPI.linphone_call_get_error_info(callPtr); if (errorReason != IntPtr.Zero) { call.SipErrorCode = LinphoneAPI.linphone_error_info_get_protocol_code(errorReason); } } if (CallStateChangedEvent != null) CallStateChangedEvent(call); if (removeCall) { callsList.Remove(call); LOG.Info(string.Format("Call removed from list. Call - {0}. Total calls in list: {1}", callPtr, callsList.Count)); } } } }
public void DeclineCall(IntPtr callPtr) { if (linphoneCore == IntPtr.Zero) { if (ErrorEvent != null) ErrorEvent(null, "Cannot terminate calls when Linphone Core is not working."); return; } lock (callLock) { VATRPCall call = FindCall(callPtr); if (call == null) { LOG.Warn("Cannot decline call. Cause - Null call"); return; } call.CallState = VATRPCallState.Closed; LOG.Info("Decline Call: " + callPtr); LOG.Info(string.Format("Call removed from list. Call - {0}. Total calls in list: {1}", callPtr, callsList.Count)); } var cmd = new DeclineCallCommand(callPtr, LinphoneReason.LinphoneReasonDeclined); lock (commandQueue) { commandQueue.Enqueue(cmd); } }