From 6c26de9e2877638bb7717a5c840382bd4610f732 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 7 Dec 2017 16:41:32 +0100 Subject: [PATCH] Various fixes in call handling. --- coreapi/callbacks.c | 15 - coreapi/private_functions.h | 12 - src/c-wrapper/api/c-call.cpp | 159 +++------- src/call/call-listener.h | 16 +- src/call/call-p.h | 22 +- src/call/call.cpp | 273 ++++++++++++++---- src/call/call.h | 5 + src/conference/conference.cpp | 82 +++++- src/conference/conference.h | 14 +- .../session/call-session-listener.h | 16 +- src/conference/session/call-session-p.h | 2 + src/conference/session/call-session.cpp | 97 ++++--- src/conference/session/call-session.h | 8 +- src/conference/session/media-session-p.h | 4 +- src/conference/session/media-session.cpp | 163 +++++------ src/conference/session/media-session.h | 3 + 16 files changed, 548 insertions(+), 343 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 1dd8d1c00..3345e6588 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -175,21 +175,6 @@ static void call_rejected(SalCallOp *h){ linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, linphone_address_new(h->get_from()), linphone_address_new(h->get_to()), ei); } -#if 0 -static void start_remote_ring(LinphoneCore *lc, LinphoneCall *call) { - if (lc->sound_conf.play_sndcard!=NULL){ - MSSndCard *ringcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; - if (call->localdesc->streams[0].max_rate>0) ms_snd_card_set_preferred_sample_rate(ringcard, call->localdesc->streams[0].max_rate); - /*we release sound before playing ringback tone*/ - if (call->audiostream) - audio_stream_unprepare_sound(call->audiostream); - if( lc->sound_conf.remote_ring ){ - lc->ringstream=ring_start(lc->factory, lc->sound_conf.remote_ring,2000,ringcard); - } - } -} -#endif - static void call_ringing(SalOp *h) { LinphonePrivate::CallSession *session = reinterpret_cast(h->get_user_pointer()); if (!session) return; diff --git a/coreapi/private_functions.h b/coreapi/private_functions.h index bb1c98d14..81e5ddf78 100644 --- a/coreapi/private_functions.h +++ b/coreapi/private_functions.h @@ -48,7 +48,6 @@ void linphone_call_notify_ack_processing(LinphoneCall *call, LinphoneHeaders *ms LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg); LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, LinphonePrivate::SalCallOp *op); -void _linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params); void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message); /* private: */ LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress * to); @@ -227,7 +226,6 @@ void _linphone_call_stats_set_rtcp_download_bandwidth (LinphoneCallStats *stats, void _linphone_call_stats_set_rtcp_upload_bandwidth (LinphoneCallStats *stats, float bandwidth); void _linphone_call_stats_set_ip_family_of_remote (LinphoneCallStats *stats, LinphoneAddressFamily family); bool_t _linphone_call_stats_rtcp_received_via_mux (const LinphoneCallStats *stats); -void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call); void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md, bool_t is_offer); void linphone_call_clear_unused_ice_candidates(LinphoneCall *call, const SalMediaDescription *md); bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md); @@ -252,20 +250,12 @@ void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *c void linphone_call_init_media_streams(LinphoneCall *call); void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call); void linphone_call_stop_media_streams(LinphoneCall *call); -void linphone_call_delete_upnp_session(LinphoneCall *call); int _linphone_core_apply_transports(LinphoneCore *lc); void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose); void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float progresses); void linphone_core_stop_waiting(LinphoneCore *lc); -int linphone_call_proceed_with_invite_if_ready(LinphoneCall *call, LinphoneProxyConfig *dest_proxy); -int linphone_call_start_invite(LinphoneCall *call, const LinphoneAddress *destination/* = NULL if to be taken from the call log */); -/* - * param automatic_offering aims is to take into account previous answer for video in case of automatic re-invite. - * Purpose is to avoid to re-ask video previously declined */ -int linphone_call_start_update(LinphoneCall *call); -int linphone_call_start_accept_update(LinphoneCall *call, LinphoneCallState next_state, const char *state_info); void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call); bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md); extern LinphonePrivate::Sal::Callbacks linphone_sal_callbacks; @@ -318,7 +308,6 @@ int linphone_core_get_calls_nb(const LinphoneCore *lc); void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message); void linphone_call_update_biggest_desc(LinphoneCall *call, SalMediaDescription *md); -void linphone_call_make_local_media_description(LinphoneCall *call); void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, LinphoneCall *call, LinphoneCallParams *params); bool_t linphone_core_is_payload_type_usable_for_bandwidth(const LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit); @@ -401,7 +390,6 @@ bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc); const char *linphone_core_create_uuid(LinphoneCore *lc); void linphone_configure_op(LinphoneCore *lc, LinphonePrivate::SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact); void linphone_configure_op_with_proxy(LinphoneCore *lc, LinphonePrivate::SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact, LinphoneProxyConfig *proxy); -void linphone_call_create_op(LinphoneCall *call); LinphoneContent * linphone_content_new(void); LinphoneContent * linphone_content_copy(const LinphoneContent *ref); SalBodyHandler *sal_body_handler_from_content(const LinphoneContent *content); diff --git a/src/c-wrapper/api/c-call.cpp b/src/c-wrapper/api/c-call.cpp index 8acfc076f..a7630a752 100644 --- a/src/c-wrapper/api/c-call.cpp +++ b/src/c-wrapper/api/c-call.cpp @@ -45,47 +45,53 @@ L_DECLARE_C_OBJECT_IMPL_WITH_XTORS(Call, LinphoneCallParams *currentParamsCache; LinphoneCallParams *paramsCache; LinphoneCallParams *remoteParamsCache; + LinphoneAddress *diversionAddressCache; LinphoneAddress *remoteAddressCache; + LinphoneAddress *toAddressCache; char *remoteContactCache; char *remoteUserAgentCache; + mutable char *toHeaderCache; /* TODO: all the fields need to be removed */ struct _LinphoneCore *core; - LinphoneErrorInfo *ei; LinphonePrivate::SalOp *op; LinphoneCallState transfer_state; /*idle if no transfer*/ - struct _AudioStream *audiostream; /**/ MSAudioEndpoint *endpoint; /*used for conferencing*/ char *refer_to; LinphoneCall *referer; /*when this call is the result of a transfer, referer is set to the original call that caused the transfer*/ LinphoneCall *transfer_target;/*if this call received a transfer request, then transfer_target points to the new call created to the refer target */ - LinphonePlayer *player; LinphoneChatRoom *chat_room; LinphoneConference *conf_ref; /**> Point on the associated conference if this call is part of a conference. NULL instead. */ bool_t refer_pending; - bool_t defer_update; - bool_t non_op_error; /*set when the LinphoneErrorInfo was set at higher level than sal*/ ) static void _linphone_call_constructor (LinphoneCall *call) { + call->currentParamsCache = linphone_call_params_new_for_wrapper(); + call->paramsCache = linphone_call_params_new_for_wrapper(); + call->remoteParamsCache = linphone_call_params_new_for_wrapper(); + call->diversionAddressCache = linphone_address_new(nullptr); + call->remoteAddressCache = linphone_address_new(nullptr); + call->toAddressCache = linphone_address_new(nullptr); } static void _linphone_call_destructor (LinphoneCall *call) { - if (call->currentParamsCache) { + if (call->currentParamsCache) linphone_call_params_unref(call->currentParamsCache); - call->currentParamsCache = nullptr; - } - if (call->paramsCache) { + if (call->paramsCache) linphone_call_params_unref(call->paramsCache); - call->paramsCache = nullptr; - } - if (call->remoteParamsCache) { + if (call->remoteParamsCache) linphone_call_params_unref(call->remoteParamsCache); - call->remoteParamsCache = nullptr; - } - if (call->remoteAddressCache) { + if (call->diversionAddressCache) + linphone_address_unref(call->diversionAddressCache); + if (call->remoteAddressCache) linphone_address_unref(call->remoteAddressCache); - call->remoteAddressCache = nullptr; - } + if (call->toAddressCache) + linphone_address_unref(call->toAddressCache); + if (call->remoteContactCache) + bctbx_free(call->remoteContactCache); + if (call->remoteUserAgentCache) + bctbx_free(call->remoteUserAgentCache); + if (call->toHeaderCache) + bctbx_free(call->toHeaderCache); bctbx_list_free_with_data(call->callbacks, (bctbx_list_free_func)linphone_call_cbs_unref); if (call->op) { call->op->release(); @@ -103,7 +109,6 @@ static void _linphone_call_destructor (LinphoneCall *call) { linphone_call_unref(call->transfer_target); call->transfer_target=nullptr; } - if (call->ei) linphone_error_info_unref(call->ei); } @@ -119,12 +124,6 @@ MSWebCam *get_nowebcam_device (MSFactory* f) { #endif } -void linphone_call_update_local_media_description_from_ice_or_upnp (LinphoneCall *call) {} - -void linphone_call_make_local_media_description (LinphoneCall *call) {} - -void linphone_call_create_op (LinphoneCall *call) {} - void linphone_call_set_state (LinphoneCall *call, LinphoneCallState cstate, const char *message) {} void linphone_call_init_media_streams (LinphoneCall *call) {} @@ -132,14 +131,6 @@ void linphone_call_init_media_streams (LinphoneCall *call) {} /*This function is not static because used internally in linphone-daemon project*/ void _post_configure_audio_stream (AudioStream *st, LinphoneCore *lc, bool_t muted) {} -#if 0 -static void setup_ring_player (LinphoneCore *lc, LinphoneCall *call) { - int pause_time=3000; - audio_stream_play(call->audiostream,lc->sound_conf.ringback_tone); - ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time); -} -#endif - #if 0 static bool_t linphone_call_sound_resources_available (LinphoneCall *call) { LinphoneCore *lc=call->core; @@ -149,28 +140,8 @@ static bool_t linphone_call_sound_resources_available (LinphoneCall *call) { } #endif -void linphone_call_delete_upnp_session (LinphoneCall *call) {} - void linphone_call_stop_media_streams (LinphoneCall *call) {} -#if 0 -static void linphone_call_lost (LinphoneCall *call) { - LinphoneCore *lc = call->core; - char *temp = nullptr; - char *from = nullptr; - - from = linphone_call_get_remote_address_as_string(call); - temp = ms_strdup_printf("Media connectivity with %s is lost, call is going to be closed.", from ? from : "?"); - if (from) ms_free(from); - ms_message("LinphoneCall [%p]: %s", call, temp); - call->non_op_error = TRUE; - linphone_error_info_set(call->ei,nullptr, LinphoneReasonIOError, 503, "Media lost", nullptr); - linphone_call_terminate(call); - linphone_core_play_named_tone(lc, LinphoneToneCallLost); - ms_free(temp); -} -#endif - void linphone_call_set_transfer_state (LinphoneCall *call, LinphoneCallState state) { #if 0 if (state != call->transfer_state) { @@ -183,33 +154,11 @@ void linphone_call_set_transfer_state (LinphoneCall *call, LinphoneCallState sta #endif } -void _linphone_call_set_new_params (LinphoneCall *call, const LinphoneCallParams *params) {} - /* Internal version that does not play tone indication*/ int _linphone_call_pause (LinphoneCall *call) { return 0; } -#if 0 -static void terminate_call (LinphoneCall *call) {} -#endif - -int linphone_call_start_update (LinphoneCall *call) { - return 0; -} - -int linphone_call_start_accept_update (LinphoneCall *call, LinphoneCallState next_state, const char *state_info) { - return 0; -} - -int linphone_call_proceed_with_invite_if_ready (LinphoneCall *call, LinphoneProxyConfig *dest_proxy) { - return 0; -} - -int linphone_call_start_invite (LinphoneCall *call, const LinphoneAddress *destination /* = NULL if to be taken from the call log */) { - return 0; -} - // ============================================================================= // Private functions. @@ -314,20 +263,19 @@ const LinphoneAddress *linphone_call_get_remote_address (const LinphoneCall *cal return call->remoteAddressCache; } -const LinphoneAddress *linphone_call_get_to_address (const LinphoneCall *call){ -#if 0 - return (const LinphoneAddress *)sal_op_get_to_address(call->op); -#else - return nullptr; -#endif +const LinphoneAddress *linphone_call_get_to_address (const LinphoneCall *call) { + L_SET_CPP_PTR_FROM_C_OBJECT(call->toAddressCache, &L_GET_CPP_PTR_FROM_C_OBJECT(call)->getToAddress()); + return call->toAddressCache; } const char *linphone_call_get_to_header (const LinphoneCall *call, const char *name) { -#if 0 - return sal_custom_header_find(sal_op_get_recv_custom_header(call->op),name); -#else - return nullptr; -#endif + string header = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getToHeader(name); + if (header.empty()) + return nullptr; + if (call->toHeaderCache) + bctbx_free(call->toHeaderCache); + call->toHeaderCache = bctbx_strdup(header.c_str()); + return call->toHeaderCache; } char *linphone_call_get_remote_address_as_string (const LinphoneCall *call) { @@ -335,11 +283,11 @@ char *linphone_call_get_remote_address_as_string (const LinphoneCall *call) { } const LinphoneAddress *linphone_call_get_diversion_address (const LinphoneCall *call) { -#if 0 - return call->op?(const LinphoneAddress *)sal_op_get_diversion_address(call->op):nullptr; -#else - return nullptr; -#endif + LinphonePrivate::Address diversionAddress(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getDiversionAddress()); + if (!diversionAddress.isValid()) + return nullptr; + L_SET_CPP_PTR_FROM_C_OBJECT(call->diversionAddressCache, &diversionAddress); + return call->diversionAddressCache; } LinphoneCallDir linphone_call_get_dir (const LinphoneCall *call) { @@ -536,11 +484,7 @@ LinphoneConference *linphone_call_get_conference (const LinphoneCall *call) { } void linphone_call_set_audio_route (LinphoneCall *call, LinphoneAudioRoute route) { -#if 0 - if (call && call->audiostream){ - audio_stream_set_audio_route(call->audiostream, (MSAudioRoute) route); - } -#endif + L_GET_CPP_PTR_FROM_C_OBJECT(call)->setAudioRoute(route); } int linphone_call_get_stream_count (const LinphoneCall *call) { @@ -608,22 +552,7 @@ LinphoneStatus linphone_call_update (LinphoneCall *call, const LinphoneCallParam } LinphoneStatus linphone_call_defer_update (LinphoneCall *call) { -#if 0 - if (call->state != LinphoneCallUpdatedByRemote) { - ms_error("linphone_call_defer_update() not done in state LinphoneCallUpdatedByRemote"); - return -1; - } - - if (call->expect_media_in_ack) { - ms_error("linphone_call_defer_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)"); - return -1; - } - - call->defer_update=TRUE; - return 0; -#else - return 0; -#endif + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->deferUpdate(); } LinphoneStatus linphone_call_accept_update (LinphoneCall *call, const LinphoneCallParams *params) { @@ -838,10 +767,6 @@ LinphoneCall *linphone_call_new_outgoing (LinphoneCore *lc, const LinphoneAddres cfg, nullptr, L_GET_CPP_PTR_FROM_C_OBJECT(params)); } L_SET_CPP_PTR_FROM_C_OBJECT(lcall, call); - lcall->currentParamsCache = linphone_call_params_new_for_wrapper(); - lcall->paramsCache = linphone_call_params_new_for_wrapper(); - lcall->remoteParamsCache = linphone_call_params_new_for_wrapper(); - lcall->remoteAddressCache = linphone_address_new(nullptr); return lcall; } @@ -859,10 +784,6 @@ LinphoneCall *linphone_call_new_incoming (LinphoneCore *lc, const LinphoneAddres nullptr, op, nullptr); } L_SET_CPP_PTR_FROM_C_OBJECT(lcall, call); - lcall->currentParamsCache = linphone_call_params_new_for_wrapper(); - lcall->paramsCache = linphone_call_params_new_for_wrapper(); - lcall->remoteParamsCache = linphone_call_params_new_for_wrapper(); - lcall->remoteAddressCache = linphone_address_new(nullptr); L_GET_PRIVATE_FROM_C_OBJECT(lcall)->initiateIncoming(); return lcall; } diff --git a/src/call/call-listener.h b/src/call/call-listener.h index 066dd5e07..bd26e1e53 100644 --- a/src/call/call-listener.h +++ b/src/call/call-listener.h @@ -32,14 +32,19 @@ public: virtual void onAckBeingSent (LinphoneHeaders *headers) = 0; virtual void onAckReceived (LinphoneHeaders *headers) = 0; + virtual void onBackgroundTaskToBeStarted () = 0; + virtual void onBackgroundTaskToBeStopped () = 0; + virtual bool onCallAccepted () = 0; virtual void onCallSetReleased () = 0; virtual void onCallSetTerminated () = 0; virtual void onCallStateChanged (LinphoneCallState state, const std::string &message) = 0; virtual void onCheckForAcceptation () = 0; virtual void onDtmfReceived (char dtmf) = 0; virtual void onIncomingCallStarted () = 0; - virtual void onIncomingCallToBeAdded () = 0; + virtual void onIncomingCallNotified () = 0; + virtual void onIncomingCallTimeoutCheck (int elapsed, bool oneSecondElapsed) = 0; virtual void onInfoReceived (const LinphoneInfoMessage *im) = 0; + virtual void onNoMediaTimeoutCheck (bool oneSecondElapsed) = 0; virtual void onEncryptionChanged (bool activated, const std::string &authToken) = 0; @@ -50,6 +55,15 @@ public: virtual void onFirstVideoFrameDecoded () = 0; virtual void onResetFirstVideoFrameDecoded () = 0; + + virtual void onPlayErrorTone (LinphoneReason reason) = 0; + virtual void onRingbackToneRequested (bool requested) = 0; + virtual void onStartRinging () = 0; + virtual void onStopRinging () = 0; + virtual void onStopRingingIfInCall () = 0; + virtual void onStopRingingIfNeeded () = 0; + + virtual bool isPlayingRingbackTone () = 0; }; LINPHONE_END_NAMESPACE diff --git a/src/call/call-p.h b/src/call/call-p.h index 2cfe8dabc..7e208681b 100644 --- a/src/call/call-p.h +++ b/src/call/call-p.h @@ -57,28 +57,48 @@ public: void createPlayer () const; private: + void startRemoteRing (); + void terminateBecauseOfLostMedia (); + /* CallListener */ void onAckBeingSent (LinphoneHeaders *headers) override; void onAckReceived (LinphoneHeaders *headers) override; + void onBackgroundTaskToBeStarted () override; + void onBackgroundTaskToBeStopped () override; + bool onCallAccepted () override; void onCallSetReleased () override; void onCallSetTerminated () override; void onCallStateChanged (LinphoneCallState state, const std::string &message) override; void onCheckForAcceptation () override; void onDtmfReceived (char dtmf) override; + void onIncomingCallNotified () override; void onIncomingCallStarted () override; - void onIncomingCallToBeAdded () override; + void onIncomingCallTimeoutCheck (int elapsed, bool oneSecondElapsed) override; void onInfoReceived (const LinphoneInfoMessage *im) override; + void onNoMediaTimeoutCheck (bool oneSecondElapsed) override; void onEncryptionChanged (bool activated, const std::string &authToken) override; void onStatsUpdated (const LinphoneCallStats *stats) override; void onResetCurrentCall () override; void onSetCurrentCall () override; void onFirstVideoFrameDecoded () override; void onResetFirstVideoFrameDecoded () override; + void onPlayErrorTone (LinphoneReason reason) override; + void onRingbackToneRequested (bool requested) override; + void onStartRinging () override; + void onStopRinging () override; + void onStopRingingIfInCall () override; + void onStopRingingIfNeeded () override; + bool isPlayingRingbackTone () override; mutable LinphonePlayer *player = nullptr; CallCallbackObj nextVideoFrameDecoded; + unsigned long backgroundTaskId = 0; + + bool ringingBeep = false; + bool playingRingbackTone = false; + L_DECLARE_PUBLIC(Call); }; diff --git a/src/call/call.cpp b/src/call/call.cpp index 1dfb19eeb..16515f034 100644 --- a/src/call/call.cpp +++ b/src/call/call.cpp @@ -89,6 +89,35 @@ void CallPrivate::createPlayer () const { // ----------------------------------------------------------------------------- +void CallPrivate::startRemoteRing () { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + if (!lc->sound_conf.play_sndcard) + return; + + MSSndCard *ringCard = lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; + int maxRate = static_pointer_cast(getActiveSession())->getPrivate()->getLocalDesc()->streams[0].max_rate; + if (maxRate > 0) + ms_snd_card_set_preferred_sample_rate(ringCard, maxRate); + // We release sound before playing ringback tone + AudioStream *as = reinterpret_cast(getMediaStream(LinphoneStreamTypeAudio)); + if (as) + audio_stream_unprepare_sound(as); + if (lc->sound_conf.remote_ring) { + lc->ringstream = ring_start(lc->factory, lc->sound_conf.remote_ring, 2000, ringCard); + } +} + +void CallPrivate::terminateBecauseOfLostMedia () { + L_Q(); + lInfo() << "Call [" << q << "]: Media connectivity with " << q->getRemoteAddressAsString() + << " is lost, call is going to be terminated"; + static_pointer_cast(getActiveSession())->terminateBecauseOfLostMedia(); + linphone_core_play_named_tone(q->getCore()->getCCore(), LinphoneToneCallLost); +} + +// ----------------------------------------------------------------------------- + void CallPrivate::onAckBeingSent (LinphoneHeaders *headers) { L_Q(); linphone_call_notify_ack_processing(L_GET_C_BACK_PTR(q), headers, false); @@ -99,6 +128,38 @@ void CallPrivate::onAckReceived (LinphoneHeaders *headers) { linphone_call_notify_ack_processing(L_GET_C_BACK_PTR(q), headers, true); } +void CallPrivate::onBackgroundTaskToBeStarted () { + backgroundTaskId = sal_begin_background_task("liblinphone call notification", nullptr, nullptr); +} + +void CallPrivate::onBackgroundTaskToBeStopped () { + if (backgroundTaskId != 0) { + sal_end_background_task(backgroundTaskId); + backgroundTaskId = 0; + } +} + +bool CallPrivate::onCallAccepted () { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + bool wasRinging = false; + + if (q->getCore()->getCurrentCall() != q->getSharedFromThis()) + linphone_core_preempt_sound_resources(lc); + + // Stop ringing + if (linphone_ringtoneplayer_is_started(lc->ringtoneplayer)) { + lInfo() << "Stop ringing"; + linphone_core_stop_ringing(lc); + wasRinging = true; + } + if (ringingBeep) { + linphone_core_stop_dtmf(lc); + ringingBeep = false; + } + return wasRinging; +} + void CallPrivate::onCallSetReleased () { L_Q(); linphone_call_unref(L_GET_C_BACK_PTR(q)); @@ -116,10 +177,12 @@ void CallPrivate::onCallSetTerminated () { #if 0 if (core->conf_ctx) linphone_conference_on_call_terminating(core->conf_ctx, lcall); - if (lcall->ringing_beep) { +#endif + if (ringingBeep) { linphone_core_stop_dtmf(core); - lcall->ringing_beep = false; + ringingBeep = false; } +#if 0 if (lcall->chat_room) linphone_chat_room_set_call(lcall->chat_room, nullptr); #endif // if 0 @@ -160,22 +223,46 @@ void CallPrivate::onDtmfReceived (char dtmf) { linphone_call_notify_dtmf_received(L_GET_C_BACK_PTR(q), dtmf); } -void CallPrivate::onIncomingCallStarted () { - L_Q(); - linphone_core_notify_incoming_call(q->getCore()->getCCore(), L_GET_C_BACK_PTR(q)); -} - -void CallPrivate::onIncomingCallToBeAdded () { +void CallPrivate::onIncomingCallNotified () { L_Q(); /* The call is acceptable so we can now add it to our list */ q->getCore()->getPrivate()->addCall(q->getSharedFromThis()); } +void CallPrivate::onIncomingCallStarted () { + L_Q(); + linphone_core_notify_incoming_call(q->getCore()->getCCore(), L_GET_C_BACK_PTR(q)); +} + +void CallPrivate::onIncomingCallTimeoutCheck (int elapsed, bool oneSecondElapsed) { + L_Q(); + if (oneSecondElapsed) + lInfo() << "Incoming call ringing for " << elapsed << " seconds"; + if (elapsed > q->getCore()->getCCore()->sip_conf.inc_timeout) { + lInfo() << "Incoming call timeout (" << q->getCore()->getCCore()->sip_conf.inc_timeout << ")"; + LinphoneReason declineReason = (q->getCore()->getCurrentCall() != q->getSharedFromThis()) + ? LinphoneReasonBusy : LinphoneReasonDeclined; + getActiveSession()->declineNotAnswered(declineReason); + } +} + void CallPrivate::onInfoReceived (const LinphoneInfoMessage *im) { L_Q(); linphone_call_notify_info_message_received(L_GET_C_BACK_PTR(q), im); } +void CallPrivate::onNoMediaTimeoutCheck (bool oneSecondElapsed) { + L_Q(); + int disconnectTimeout = linphone_core_get_nortp_timeout(q->getCore()->getCCore()); + bool disconnected = false; + AudioStream *as = reinterpret_cast(getMediaStream(LinphoneStreamTypeAudio)); + if (((q->getState() == LinphoneCallStreamsRunning) || (q->getState() == LinphoneCallPausedByRemote)) + && oneSecondElapsed && as && (as->ms.state == MSStreamStarted) && (disconnectTimeout > 0)) + disconnected = !audio_stream_alive(as, disconnectTimeout); + if (disconnected) + terminateBecauseOfLostMedia(); +} + void CallPrivate::onEncryptionChanged (bool activated, const string &authToken) { L_Q(); linphone_call_notify_encryption_changed(L_GET_C_BACK_PTR(q), activated, authToken.empty() ? nullptr : authToken.c_str()); @@ -212,6 +299,61 @@ void CallPrivate::onResetFirstVideoFrameDecoded () { #endif // ifdef VIDEO_ENABLED } +void CallPrivate::onPlayErrorTone (LinphoneReason reason) { + L_Q(); + linphone_core_play_call_error_tone(q->getCore()->getCCore(), reason); +} + +void CallPrivate::onRingbackToneRequested (bool requested) { + L_Q(); + if (requested && linphone_core_get_remote_ringback_tone(q->getCore()->getCCore())) + playingRingbackTone = true; + else if (!requested) + playingRingbackTone = false; +} + +void CallPrivate::onStartRinging () { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + if (lc->ringstream) + return; // Already ringing! + startRemoteRing(); +} + +void CallPrivate::onStopRinging () { + L_Q(); + linphone_core_stop_ringing(q->getCore()->getCCore()); +} + +void CallPrivate::onStopRingingIfInCall () { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + // We stop the ring only if we have this current call or if we are in call + if ((q->getCore()->getCallCount() == 1) || linphone_core_in_call(lc)) { + linphone_core_stop_ringing(lc); + } +} + +void CallPrivate::onStopRingingIfNeeded () { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + bool stopRinging = true; + bool ringDuringEarlyMedia = linphone_core_get_ring_during_incoming_early_media(lc); + for (const auto &call : q->getCore()->getCalls()) { + if ((call->getState() == LinphoneCallIncomingReceived) + || (ringDuringEarlyMedia && call->getState() == LinphoneCallIncomingEarlyMedia)) { + stopRinging = false; + break; + } + } + if (stopRinging) + linphone_core_stop_ringing(lc); +} + +bool CallPrivate::isPlayingRingbackTone () { + return playingRingbackTone; +} + // ============================================================================= Call::Call (CallPrivate &p, shared_ptr core) : Object(p), CoreAccessor(core) { @@ -224,17 +366,17 @@ Call::Call (CallPrivate &p, shared_ptr core) : Object(p), CoreAccessor(cor LinphoneStatus Call::accept (const MediaSessionParams *msp) { L_D(); - return static_cast(d->getActiveSession().get())->accept(msp); + return static_pointer_cast(d->getActiveSession())->accept(msp); } LinphoneStatus Call::acceptEarlyMedia (const MediaSessionParams *msp) { L_D(); - return static_cast(d->getActiveSession().get())->acceptEarlyMedia(msp); + return static_pointer_cast(d->getActiveSession())->acceptEarlyMedia(msp); } LinphoneStatus Call::acceptUpdate (const MediaSessionParams *msp) { L_D(); - return static_cast(d->getActiveSession().get())->acceptUpdate(msp); + return static_pointer_cast(d->getActiveSession())->acceptUpdate(msp); } void Call::cancelDtmfs () { @@ -252,6 +394,11 @@ LinphoneStatus Call::decline (const LinphoneErrorInfo *ei) { return d->getActiveSession()->decline(ei); } +LinphoneStatus Call::deferUpdate () { + L_D(); + return d->getActiveSession()->deferUpdate(); +} + void Call::oglRender () const { L_D(); static_pointer_cast(d->getActiveSession())->getPrivate()->oglRender(); @@ -259,7 +406,7 @@ void Call::oglRender () const { LinphoneStatus Call::pause () { L_D(); - return static_cast(d->getActiveSession().get())->pause(); + return static_pointer_cast(d->getActiveSession())->pause(); } LinphoneStatus Call::redirect (const std::string &redirectUri) { @@ -269,7 +416,7 @@ LinphoneStatus Call::redirect (const std::string &redirectUri) { LinphoneStatus Call::resume () { L_D(); - return static_cast(d->getActiveSession().get())->resume(); + return static_pointer_cast(d->getActiveSession())->resume(); } LinphoneStatus Call::sendDtmf (char dtmf) { @@ -284,27 +431,27 @@ LinphoneStatus Call::sendDtmfs (const std::string &dtmfs) { void Call::sendVfuRequest () { L_D(); - static_cast(d->getActiveSession().get())->sendVfuRequest(); + static_pointer_cast(d->getActiveSession())->sendVfuRequest(); } void Call::startRecording () { L_D(); - static_cast(d->getActiveSession().get())->startRecording(); + static_pointer_cast(d->getActiveSession())->startRecording(); } void Call::stopRecording () { L_D(); - static_cast(d->getActiveSession().get())->stopRecording(); + static_pointer_cast(d->getActiveSession())->stopRecording(); } LinphoneStatus Call::takePreviewSnapshot (const string &file) { L_D(); - return static_cast(d->getActiveSession().get())->takePreviewSnapshot(file); + return static_pointer_cast(d->getActiveSession())->takePreviewSnapshot(file); } LinphoneStatus Call::takeVideoSnapshot (const string &file) { L_D(); - return static_cast(d->getActiveSession().get())->takeVideoSnapshot(file); + return static_pointer_cast(d->getActiveSession())->takeVideoSnapshot(file); } LinphoneStatus Call::terminate (const LinphoneErrorInfo *ei) { @@ -314,7 +461,7 @@ LinphoneStatus Call::terminate (const LinphoneErrorInfo *ei) { LinphoneStatus Call::update (const MediaSessionParams *msp) { L_D(); - return static_cast(d->getActiveSession().get())->update(msp); + return static_pointer_cast(d->getActiveSession())->update(msp); } void Call::zoomVideo (float zoomFactor, float *cx, float *cy) { @@ -323,74 +470,74 @@ void Call::zoomVideo (float zoomFactor, float *cx, float *cy) { void Call::zoomVideo (float zoomFactor, float cx, float cy) { L_D(); - static_cast(d->getActiveSession().get())->zoomVideo(zoomFactor, cx, cy); + static_pointer_cast(d->getActiveSession())->zoomVideo(zoomFactor, cx, cy); } // ----------------------------------------------------------------------------- bool Call::cameraEnabled () const { L_D(); - return static_cast(d->getActiveSession().get())->cameraEnabled(); + return static_pointer_cast(d->getActiveSession())->cameraEnabled(); } bool Call::echoCancellationEnabled () const { L_D(); - return static_cast(d->getActiveSession().get())->echoCancellationEnabled(); + return static_pointer_cast(d->getActiveSession())->echoCancellationEnabled(); } bool Call::echoLimiterEnabled () const { L_D(); - return static_cast(d->getActiveSession().get())->echoLimiterEnabled(); + return static_pointer_cast(d->getActiveSession())->echoLimiterEnabled(); } void Call::enableCamera (bool value) { L_D(); - static_cast(d->getActiveSession().get())->enableCamera(value); + static_pointer_cast(d->getActiveSession())->enableCamera(value); } void Call::enableEchoCancellation (bool value) { L_D(); - static_cast(d->getActiveSession().get())->enableEchoCancellation(value); + static_pointer_cast(d->getActiveSession())->enableEchoCancellation(value); } void Call::enableEchoLimiter (bool value) { L_D(); - static_cast(d->getActiveSession().get())->enableEchoLimiter(value); + static_pointer_cast(d->getActiveSession())->enableEchoLimiter(value); } bool Call::getAllMuted () const { L_D(); - return static_cast(d->getActiveSession().get())->getAllMuted(); + return static_pointer_cast(d->getActiveSession())->getAllMuted(); } LinphoneCallStats *Call::getAudioStats () const { L_D(); - return static_cast(d->getActiveSession().get())->getAudioStats(); + return static_pointer_cast(d->getActiveSession())->getAudioStats(); } string Call::getAuthenticationToken () const { L_D(); - return static_cast(d->getActiveSession().get())->getAuthenticationToken(); + return static_pointer_cast(d->getActiveSession())->getAuthenticationToken(); } bool Call::getAuthenticationTokenVerified () const { L_D(); - return static_cast(d->getActiveSession().get())->getAuthenticationTokenVerified(); + return static_pointer_cast(d->getActiveSession())->getAuthenticationTokenVerified(); } float Call::getAverageQuality () const { L_D(); - return static_cast(d->getActiveSession().get())->getAverageQuality(); + return static_pointer_cast(d->getActiveSession())->getAverageQuality(); } const MediaSessionParams *Call::getCurrentParams () const { L_D(); - return static_cast(d->getActiveSession().get())->getCurrentParams(); + return static_pointer_cast(d->getActiveSession())->getCurrentParams(); } float Call::getCurrentQuality () const { L_D(); - return static_cast(d->getActiveSession().get())->getCurrentQuality(); + return static_pointer_cast(d->getActiveSession())->getCurrentQuality(); } LinphoneCallDir Call::getDirection () const { @@ -398,6 +545,11 @@ LinphoneCallDir Call::getDirection () const { return d->getActiveSession()->getDirection(); } +const Address &Call::getDiversionAddress () const { + L_D(); + return d->getActiveSession()->getDiversionAddress(); +} + int Call::getDuration () const { L_D(); return d->getActiveSession()->getDuration(); @@ -415,27 +567,27 @@ LinphoneCallLog *Call::getLog () const { RtpTransport *Call::getMetaRtcpTransport (int streamIndex) const { L_D(); - return static_cast(d->getActiveSession().get())->getMetaRtcpTransport(streamIndex); + return static_pointer_cast(d->getActiveSession())->getMetaRtcpTransport(streamIndex); } RtpTransport *Call::getMetaRtpTransport (int streamIndex) const { L_D(); - return static_cast(d->getActiveSession().get())->getMetaRtpTransport(streamIndex); + return static_pointer_cast(d->getActiveSession())->getMetaRtpTransport(streamIndex); } float Call::getMicrophoneVolumeGain () const { L_D(); - return static_cast(d->getActiveSession().get())->getMicrophoneVolumeGain(); + return static_pointer_cast(d->getActiveSession())->getMicrophoneVolumeGain(); } void *Call::getNativeVideoWindowId () const { L_D(); - return static_cast(d->getActiveSession().get())->getNativeVideoWindowId(); + return static_pointer_cast(d->getActiveSession())->getNativeVideoWindowId(); } const MediaSessionParams *Call::getParams () const { L_D(); - return static_cast(d->getActiveSession().get())->getMediaParams(); + return static_pointer_cast(d->getActiveSession())->getMediaParams(); } LinphonePlayer *Call::getPlayer () const { @@ -447,7 +599,7 @@ LinphonePlayer *Call::getPlayer () const { float Call::getPlayVolume () const { L_D(); - return static_cast(d->getActiveSession().get())->getPlayVolume(); + return static_pointer_cast(d->getActiveSession())->getPlayVolume(); } LinphoneReason Call::getReason () const { @@ -457,7 +609,7 @@ LinphoneReason Call::getReason () const { float Call::getRecordVolume () const { L_D(); - return static_cast(d->getActiveSession().get())->getRecordVolume(); + return static_pointer_cast(d->getActiveSession())->getRecordVolume(); } const Address &Call::getRemoteAddress () const { @@ -477,7 +629,7 @@ string Call::getRemoteContact () const { const MediaSessionParams *Call::getRemoteParams () const { L_D(); - return static_cast(d->getActiveSession().get())->getRemoteParams(); + return static_pointer_cast(d->getActiveSession())->getRemoteParams(); } string Call::getRemoteUserAgent () const { @@ -487,7 +639,7 @@ string Call::getRemoteUserAgent () const { float Call::getSpeakerVolumeGain () const { L_D(); - return static_cast(d->getActiveSession().get())->getSpeakerVolumeGain(); + return static_pointer_cast(d->getActiveSession())->getSpeakerVolumeGain(); } LinphoneCallState Call::getState () const { @@ -497,47 +649,62 @@ LinphoneCallState Call::getState () const { LinphoneCallStats *Call::getStats (LinphoneStreamType type) const { L_D(); - return static_cast(d->getActiveSession().get())->getStats(type); + return static_pointer_cast(d->getActiveSession())->getStats(type); } int Call::getStreamCount () const { L_D(); - return static_cast(d->getActiveSession().get())->getStreamCount(); + return static_pointer_cast(d->getActiveSession())->getStreamCount(); } MSFormatType Call::getStreamType (int streamIndex) const { L_D(); - return static_cast(d->getActiveSession().get())->getStreamType(streamIndex); + return static_pointer_cast(d->getActiveSession())->getStreamType(streamIndex); } LinphoneCallStats *Call::getTextStats () const { L_D(); - return static_cast(d->getActiveSession().get())->getTextStats(); + return static_pointer_cast(d->getActiveSession())->getTextStats(); +} + +const Address &Call::getToAddress () const { + L_D(); + return d->getActiveSession()->getToAddress(); +} + +string Call::getToHeader (const std::string &name) const { + L_D(); + return d->getActiveSession()->getToHeader(name); } LinphoneCallStats *Call::getVideoStats () const { L_D(); - return static_cast(d->getActiveSession().get())->getVideoStats(); + return static_pointer_cast(d->getActiveSession())->getVideoStats(); } bool Call::mediaInProgress () const { L_D(); - return static_cast(d->getActiveSession().get())->mediaInProgress(); + return static_pointer_cast(d->getActiveSession())->mediaInProgress(); +} + +void Call::setAudioRoute (LinphoneAudioRoute route) { + L_D(); + static_pointer_cast(d->getActiveSession())->setAudioRoute(route); } void Call::setAuthenticationTokenVerified (bool value) { L_D(); - static_cast(d->getActiveSession().get())->setAuthenticationTokenVerified(value); + static_pointer_cast(d->getActiveSession())->setAuthenticationTokenVerified(value); } void Call::setMicrophoneVolumeGain (float value) { L_D(); - static_cast(d->getActiveSession().get())->setMicrophoneVolumeGain(value); + static_pointer_cast(d->getActiveSession())->setMicrophoneVolumeGain(value); } void Call::setNativeVideoWindowId (void *id) { L_D(); - static_cast(d->getActiveSession().get())->setNativeVideoWindowId(id); + static_pointer_cast(d->getActiveSession())->setNativeVideoWindowId(id); } void Call::setNextVideoFrameDecodedCallback (LinphoneCallCbFunc cb, void *user_data) { @@ -549,12 +716,12 @@ void Call::setNextVideoFrameDecodedCallback (LinphoneCallCbFunc cb, void *user_d void Call::setParams (const MediaSessionParams *msp) { L_D(); - static_cast(d->getActiveSession().get())->setParams(msp); + static_pointer_cast(d->getActiveSession())->setParams(msp); } void Call::setSpeakerVolumeGain (float value) { L_D(); - static_cast(d->getActiveSession().get())->setSpeakerVolumeGain(value); + static_pointer_cast(d->getActiveSession())->setSpeakerVolumeGain(value); } LINPHONE_END_NAMESPACE diff --git a/src/call/call.h b/src/call/call.h index dad14d183..164bc02cd 100644 --- a/src/call/call.h +++ b/src/call/call.h @@ -47,6 +47,7 @@ public: void cancelDtmfs (); LinphoneStatus decline (LinphoneReason reason); LinphoneStatus decline (const LinphoneErrorInfo *ei); + LinphoneStatus deferUpdate (); void oglRender () const; LinphoneStatus pause (); LinphoneStatus redirect (const std::string &redirectUri); @@ -77,6 +78,7 @@ public: const MediaSessionParams *getCurrentParams () const; float getCurrentQuality () const; LinphoneCallDir getDirection () const; + const Address &getDiversionAddress () const; int getDuration () const; const LinphoneErrorInfo *getErrorInfo () const; LinphoneCallLog *getLog () const; @@ -100,8 +102,11 @@ public: int getStreamCount () const; MSFormatType getStreamType (int streamIndex) const; LinphoneCallStats *getTextStats () const; + const Address &getToAddress () const; + std::string getToHeader (const std::string &name) const; LinphoneCallStats *getVideoStats () const; bool mediaInProgress () const; + void setAudioRoute (LinphoneAudioRoute route); void setAuthenticationTokenVerified (bool value); void setMicrophoneVolumeGain (float value); void setNativeVideoWindowId (void *id); diff --git a/src/conference/conference.cpp b/src/conference/conference.cpp index 384611bb9..15d8619cf 100644 --- a/src/conference/conference.cpp +++ b/src/conference/conference.cpp @@ -134,10 +134,23 @@ void Conference::onAckReceived (const shared_ptr &session, Li d->callListener->onAckReceived(headers); } -void Conference::onCallSessionAccepted (const shared_ptr &session) { +void Conference::onBackgroundTaskToBeStarted (const shared_ptr &session) { L_D(); if (d->callListener) - d->callListener->onIncomingCallToBeAdded(); + d->callListener->onBackgroundTaskToBeStarted(); +} + +void Conference::onBackgroundTaskToBeStopped (const shared_ptr &session) { + L_D(); + if (d->callListener) + d->callListener->onBackgroundTaskToBeStopped(); +} + +bool Conference::onCallSessionAccepted (const shared_ptr &session) { + L_D(); + if (d->callListener) + return d->callListener->onCallAccepted(); + return false; } void Conference::onCallSessionSetReleased (const shared_ptr &session) { @@ -164,24 +177,42 @@ void Conference::onCheckForAcceptation (const shared_ptr &ses d->callListener->onCheckForAcceptation(); } -void Conference::onDtmfReceived (const std::shared_ptr &session, char dtmf) { +void Conference::onDtmfReceived (const shared_ptr &session, char dtmf) { L_D(); if (d->callListener) d->callListener->onDtmfReceived(dtmf); } +void Conference::onIncomingCallSessionNotified (const shared_ptr &session) { + L_D(); + if (d->callListener) + d->callListener->onIncomingCallNotified(); +} + void Conference::onIncomingCallSessionStarted (const shared_ptr &session) { L_D(); if (d->callListener) d->callListener->onIncomingCallStarted(); } -void Conference::onInfoReceived (const std::shared_ptr &session, const LinphoneInfoMessage *im) { +void Conference::onIncomingCallSessionTimeoutCheck (const shared_ptr &session, int elapsed, bool oneSecondElapsed) { + L_D(); + if (d->callListener) + d->callListener->onIncomingCallTimeoutCheck(elapsed, oneSecondElapsed); +} + +void Conference::onInfoReceived (const shared_ptr &session, const LinphoneInfoMessage *im) { L_D(); if (d->callListener) d->callListener->onInfoReceived(im); } +void Conference::onNoMediaTimeoutCheck (const shared_ptr &session, bool oneSecondElapsed) { + L_D(); + if (d->callListener) + d->callListener->onNoMediaTimeoutCheck(oneSecondElapsed); +} + void Conference::onEncryptionChanged (const shared_ptr &session, bool activated, const string &authToken) { L_D(); if (d->callListener) @@ -218,6 +249,49 @@ void Conference::onResetFirstVideoFrameDecoded (const shared_ptrcallListener->onResetFirstVideoFrameDecoded(); } +void Conference::onPlayErrorTone (const shared_ptr &session, LinphoneReason reason) { + L_D(); + if (d->callListener) + d->callListener->onPlayErrorTone(reason); +} + +void Conference::onRingbackToneRequested (const shared_ptr &session, bool requested) { + L_D(); + if (d->callListener) + d->callListener->onRingbackToneRequested(requested); +} + +void Conference::onStartRinging (const shared_ptr &session) { + L_D(); + if (d->callListener) + d->callListener->onStartRinging(); +} + +void Conference::onStopRinging (const shared_ptr &session) { + L_D(); + if (d->callListener) + d->callListener->onStopRinging(); +} + +void Conference::onStopRingingIfInCall (const shared_ptr &session) { + L_D(); + if (d->callListener) + d->callListener->onStopRingingIfInCall(); +} + +void Conference::onStopRingingIfNeeded (const shared_ptr &session) { + L_D(); + if (d->callListener) + d->callListener->onStopRingingIfNeeded(); +} + +bool Conference::isPlayingRingbackTone (const shared_ptr &session) { + L_D(); + if (d->callListener) + return d->callListener->isPlayingRingbackTone(); + return false; +} + // ----------------------------------------------------------------------------- shared_ptr Conference::findParticipant (const IdentityAddress &addr) const { diff --git a/src/conference/conference.h b/src/conference/conference.h index 7c019e045..08ec935bd 100644 --- a/src/conference/conference.h +++ b/src/conference/conference.h @@ -68,20 +68,32 @@ private: /* CallSessionListener */ void onAckBeingSent (const std::shared_ptr &session, LinphoneHeaders *headers) override; void onAckReceived (const std::shared_ptr &session, LinphoneHeaders *headers) override; - void onCallSessionAccepted (const std::shared_ptr &session) override; + void onBackgroundTaskToBeStarted (const std::shared_ptr &session) override; + void onBackgroundTaskToBeStopped (const std::shared_ptr &session) override; + bool onCallSessionAccepted (const std::shared_ptr &session) override; void onCallSessionSetReleased (const std::shared_ptr &session) override; void onCallSessionSetTerminated (const std::shared_ptr &session) override; void onCallSessionStateChanged (const std::shared_ptr &session, LinphoneCallState state, const std::string &message) override; void onCheckForAcceptation (const std::shared_ptr &session) override; void onDtmfReceived (const std::shared_ptr &session, char dtmf) override; + void onIncomingCallSessionNotified (const std::shared_ptr &session) override; void onIncomingCallSessionStarted (const std::shared_ptr &session) override; + void onIncomingCallSessionTimeoutCheck (const std::shared_ptr &session, int elapsed, bool oneSecondElapsed) override; void onInfoReceived (const std::shared_ptr &session, const LinphoneInfoMessage *im) override; + void onNoMediaTimeoutCheck (const std::shared_ptr &session, bool oneSecondElapsed) override; void onEncryptionChanged (const std::shared_ptr &session, bool activated, const std::string &authToken) override; void onStatsUpdated (const LinphoneCallStats *stats) override; void onResetCurrentSession (const std::shared_ptr &session) override; void onSetCurrentSession (const std::shared_ptr &session) override; void onFirstVideoFrameDecoded (const std::shared_ptr &session) override; void onResetFirstVideoFrameDecoded (const std::shared_ptr &session) override; + void onPlayErrorTone (const std::shared_ptr &session, LinphoneReason reason) override; + void onRingbackToneRequested (const std::shared_ptr &session, bool requested) override; + void onStartRinging (const std::shared_ptr &session) override; + void onStopRinging (const std::shared_ptr &session) override; + void onStopRingingIfInCall (const std::shared_ptr &session) override; + void onStopRingingIfNeeded (const std::shared_ptr &session) override; + bool isPlayingRingbackTone (const std::shared_ptr &session) override; protected: explicit Conference ( diff --git a/src/conference/session/call-session-listener.h b/src/conference/session/call-session-listener.h index 7ac9b231e..8f8a31eb5 100644 --- a/src/conference/session/call-session-listener.h +++ b/src/conference/session/call-session-listener.h @@ -32,14 +32,19 @@ public: virtual void onAckBeingSent (const std::shared_ptr &session, LinphoneHeaders *headers) = 0; virtual void onAckReceived (const std::shared_ptr &session, LinphoneHeaders *headers) = 0; - virtual void onCallSessionAccepted (const std::shared_ptr &session) = 0; + virtual void onBackgroundTaskToBeStarted (const std::shared_ptr &session) = 0; + virtual void onBackgroundTaskToBeStopped (const std::shared_ptr &session) = 0; + virtual bool onCallSessionAccepted (const std::shared_ptr &session) = 0; virtual void onCallSessionSetReleased (const std::shared_ptr &session) = 0; virtual void onCallSessionSetTerminated (const std::shared_ptr &session) = 0; virtual void onCallSessionStateChanged (const std::shared_ptr &session, LinphoneCallState state, const std::string &message) = 0; virtual void onCheckForAcceptation (const std::shared_ptr &session) = 0; virtual void onDtmfReceived (const std::shared_ptr &session, char dtmf) = 0; + virtual void onIncomingCallSessionNotified (const std::shared_ptr &session) = 0; virtual void onIncomingCallSessionStarted (const std::shared_ptr &session) = 0; + virtual void onIncomingCallSessionTimeoutCheck (const std::shared_ptr &session, int elapsed, bool oneSecondElapsed) = 0; virtual void onInfoReceived (const std::shared_ptr &session, const LinphoneInfoMessage *im) = 0; + virtual void onNoMediaTimeoutCheck (const std::shared_ptr &session, bool oneSecondElapsed) = 0; virtual void onEncryptionChanged (const std::shared_ptr &session, bool activated, const std::string &authToken) = 0; @@ -50,6 +55,15 @@ public: virtual void onFirstVideoFrameDecoded (const std::shared_ptr &session) = 0; virtual void onResetFirstVideoFrameDecoded (const std::shared_ptr &session) = 0; + + virtual void onPlayErrorTone (const std::shared_ptr &session, LinphoneReason reason) = 0; + virtual void onRingbackToneRequested (const std::shared_ptr &session, bool requested) = 0; + virtual void onStartRinging (const std::shared_ptr &session) = 0; + virtual void onStopRinging (const std::shared_ptr &session) = 0; + virtual void onStopRingingIfInCall (const std::shared_ptr &session) = 0; + virtual void onStopRingingIfNeeded (const std::shared_ptr &session) = 0; + + virtual bool isPlayingRingbackTone (const std::shared_ptr &session) = 0; }; LINPHONE_END_NAMESPACE diff --git a/src/conference/session/call-session-p.h b/src/conference/session/call-session-p.h index 5a84788c8..6d9828163 100644 --- a/src/conference/session/call-session-p.h +++ b/src/conference/session/call-session-p.h @@ -101,7 +101,9 @@ protected: CallSessionParams *params = nullptr; mutable CallSessionParams *currentParams = nullptr; CallSessionParams *remoteParams = nullptr; + mutable Address diversionAddress; mutable Address remoteContactAddress; + mutable Address toAddress; std::string subject; LinphoneCallDir direction = LinphoneCallOutgoing; diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index b93335ca3..6ca45ebeb 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -150,14 +150,10 @@ void CallSessionPrivate::startIncomingNotification () { setState(LinphoneCallIncomingReceived, "Incoming CallSession"); - /* From now on, the application is aware of the call and supposed to take background task or already submitted notification to the user. - * We can then drop our background task. */ -#if 0 - if (call->bg_task_id!=0) { - sal_end_background_task(call->bg_task_id); - call->bg_task_id=0; - } -#endif + // From now on, the application is aware of the call and supposed to take background task or already submitted + // notification to the user. We can then drop our background task. + if (listener) + listener->onBackgroundTaskToBeStopped(q->getSharedFromThis()); if (state == LinphoneCallIncomingReceived) { handleIncomingReceivedStateInIncomingNotification(); @@ -287,10 +283,8 @@ bool CallSessionPrivate::failure () { else setState(LinphoneCallEnd, ei->full_string ? ei->full_string : ""); } -#if 0 // TODO: handle in Call class - if (ei->reason != SalReasonNone) - linphone_core_play_call_error_tone(core, linphone_reason_from_sal(ei->reason)); -#endif + if ((ei->reason != SalReasonNone) && listener) + listener->onPlayErrorTone(q->getSharedFromThis(), linphone_reason_from_sal(ei->reason)); } #if 0 LinphoneCall *referer=call->referer; @@ -328,11 +322,11 @@ void CallSessionPrivate::pingReply () { } void CallSessionPrivate::remoteRinging () { + L_Q(); /* Set privacy */ currentParams->setPrivacy((LinphonePrivacyMask)op->get_privacy()); -#if 0 - if (lc->ringstream == NULL) start_remote_ring(lc, call); -#endif + if (listener) + listener->onStartRinging(q->getSharedFromThis()); lInfo() << "Remote ringing..."; setState(LinphoneCallOutgoingRinging, "Remote ringing"); } @@ -379,6 +373,7 @@ void CallSessionPrivate::replaceOp (SalCallOp *newOp) { } void CallSessionPrivate::terminated () { + L_Q(); switch (state) { case LinphoneCallEnd: case LinphoneCallError: @@ -397,11 +392,9 @@ void CallSessionPrivate::terminated () { #if 0 if (call->refer_pending) linphone_core_start_refered_call(lc,call,NULL); - //we stop the call only if we have this current call or if we are in call - if ((bctbx_list_size(lc->calls) == 1) || linphone_core_in_call(lc)) { - linphone_core_stop_ringing(lc); - } #endif + if (listener) + listener->onStopRingingIfInCall(q->getSharedFromThis()); setState(LinphoneCallEnd, "Call ended"); } @@ -976,6 +969,24 @@ LinphoneStatus CallSession::decline (const LinphoneErrorInfo *ei) { return 0; } +LinphoneStatus CallSession::declineNotAnswered (LinphoneReason reason) { + L_D(); + d->log->status = LinphoneCallMissed; + d->nonOpError = true; + linphone_error_info_set(d->ei, nullptr, reason, linphone_reason_to_error_code(reason), "Not answered", nullptr); + return decline(reason); +} + +LinphoneStatus CallSession::deferUpdate () { + L_D(); + if (d->state != LinphoneCallUpdatedByRemote) { + lError() << "CallSession::deferUpdate() not done in state LinphoneCallUpdatedByRemote"; + return -1; + } + d->deferUpdate = true; + return 0; +} + void CallSession::initiateIncoming () {} bool CallSession::initiateOutgoing () { @@ -999,20 +1010,8 @@ void CallSession::iterate (time_t currentRealTime, bool oneSecondElapsed) { startInvite(nullptr, ""); } if ((d->state == LinphoneCallIncomingReceived) || (d->state == LinphoneCallIncomingEarlyMedia)) { - if (oneSecondElapsed) - lInfo() << "Incoming call ringing for " << elapsed << " seconds"; - if (elapsed > getCore()->getCCore()->sip_conf.inc_timeout) { - lInfo() << "Incoming call timeout (" << getCore()->getCCore()->sip_conf.inc_timeout << ")"; -#if 0 - LinphoneReason declineReason = (core->current_call != call) ? LinphoneReasonBusy : LinphoneReasonDeclined; -#endif - d->log->status = LinphoneCallMissed; -#if 0 - call->non_op_error = TRUE; - linphone_error_info_set(call->ei, NULL, decline_reason, linphone_reason_to_error_code(decline_reason), "Not answered", NULL); - linphone_call_decline(call, decline_reason); -#endif - } + if (d->listener) + d->listener->onIncomingCallSessionTimeoutCheck(getSharedFromThis(), elapsed, oneSecondElapsed); } if ((getCore()->getCCore()->sip_conf.in_call_timeout > 0) && (d->log->connected_date_time != 0) && ((currentRealTime - d->log->connected_date_time) > getCore()->getCCore()->sip_conf.in_call_timeout)) { @@ -1054,13 +1053,12 @@ LinphoneStatus CallSession::redirect (const Address &redirectAddr) { void CallSession::startIncomingNotification () { L_D(); - if (d->listener) - d->listener->onCallSessionAccepted(getSharedFromThis()); + if (d->listener) { + d->listener->onIncomingCallSessionNotified(getSharedFromThis()); + d->listener->onBackgroundTaskToBeStarted(getSharedFromThis()); + } /* Prevent the CallSession from being destroyed while we are notifying, if the user declines within the state callback */ shared_ptr ref = getSharedFromThis(); -#if 0 - call->bg_task_id=sal_begin_background_task("liblinphone call notification", NULL, NULL); -#endif if (d->deferIncomingNotification) { lInfo() << "Defer incoming notification"; return; @@ -1162,6 +1160,18 @@ LinphoneCallDir CallSession::getDirection () const { return d->direction; } +const Address& CallSession::getDiversionAddress () const { + L_D(); + if (d->op) { + char *addrStr = sal_address_as_string(d->op->get_diversion_address()); + d->diversionAddress = Address(addrStr); + bctbx_free(addrStr); + } else { + d->diversionAddress = Address(); + } + return d->diversionAddress; +} + int CallSession::getDuration () const { L_D(); switch (d->state) { @@ -1240,6 +1250,17 @@ LinphoneCallState CallSession::getState () const { return d->state; } +const Address& CallSession::getToAddress () const { + L_D(); + d->toAddress = Address(d->op->get_to()); + return d->toAddress; +} + +string CallSession::getToHeader (const string &name) const { + L_D(); + return L_C_TO_STRING(sal_custom_header_find(d->op->get_recv_custom_header(), name.c_str())); +} + // ----------------------------------------------------------------------------- string CallSession::getRemoteUserAgent () const { diff --git a/src/conference/session/call-session.h b/src/conference/session/call-session.h index d1e5ab231..466e9a141 100644 --- a/src/conference/session/call-session.h +++ b/src/conference/session/call-session.h @@ -57,6 +57,8 @@ public: virtual void configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to); LinphoneStatus decline (LinphoneReason reason); LinphoneStatus decline (const LinphoneErrorInfo *ei); + LinphoneStatus declineNotAnswered (LinphoneReason reason); + virtual LinphoneStatus deferUpdate (); virtual void initiateIncoming (); virtual bool initiateOutgoing (); virtual void iterate (time_t currentRealTime, bool oneSecondElapsed); @@ -69,6 +71,7 @@ public: CallSessionParams *getCurrentParams () const; LinphoneCallDir getDirection () const; + const Address& getDiversionAddress () const; int getDuration () const; const LinphoneErrorInfo * getErrorInfo () const; LinphoneCallLog * getLog () const; @@ -79,9 +82,10 @@ public: std::string getRemoteContact () const; const Address *getRemoteContactAddress () const; const CallSessionParams *getRemoteParams (); - LinphoneCallState getState () const; - std::string getRemoteUserAgent () const; + LinphoneCallState getState () const; + const Address& getToAddress () const; + std::string getToHeader (const std::string &name) const; protected: explicit CallSession (CallSessionPrivate &p, const std::shared_ptr &core); diff --git a/src/conference/session/media-session-p.h b/src/conference/session/media-session-p.h index 19f3b0205..24e840f4f 100644 --- a/src/conference/session/media-session-p.h +++ b/src/conference/session/media-session-p.h @@ -190,6 +190,7 @@ private: void postConfigureAudioStreams (bool muted); void setPlaybackGainDb (AudioStream *stream, float gain); void setSymmetricRtp (bool value); + void setupRingbackPlayer (); void startAudioStream (LinphoneCallState targetState, bool videoWillBeUsed); void startStreams (LinphoneCallState targetState); void startTextStream (); @@ -238,7 +239,7 @@ private: void terminate () override; void updateCurrentParams () const override; - void accept (const MediaSessionParams *params); + void accept (const MediaSessionParams *params, bool wasRinging); LinphoneStatus acceptUpdate (const CallSessionParams *csp, LinphoneCallState nextState, const std::string &stateInfo) override; void refreshSockets (); @@ -321,7 +322,6 @@ private: bool audioMuted = false; bool automaticallyPaused = false; bool pausedByApp = false; - bool playingRingbackTone = false; bool recordActive = false; std::string onHoldFile; diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp index 7d10394b7..bee007427 100644 --- a/src/conference/session/media-session.cpp +++ b/src/conference/session/media-session.cpp @@ -249,22 +249,8 @@ bool MediaSessionPrivate::failure () { if (stop) return true; -#if 0 - /* Stop ringing */ - bool_t ring_during_early_media = linphone_core_get_ring_during_incoming_early_media(lc); - bool_t stop_ringing = TRUE; - bctbx_list_t *calls = lc->calls; - while(calls) { - if (((LinphoneCall *)calls->data)->state == LinphoneCallIncomingReceived || (ring_during_early_media && ((LinphoneCall *)calls->data)->state == LinphoneCallIncomingEarlyMedia)) { - stop_ringing = FALSE; - break; - } - calls = calls->next; - } - if(stop_ringing) { - linphone_core_stop_ringing(lc); - } -#endif + if (listener) + listener->onStopRingingIfNeeded(q->getSharedFromThis()); stopStreams(); return false; } @@ -301,16 +287,13 @@ void MediaSessionPrivate::remoteRinging () { } setState(LinphoneCallOutgoingEarlyMedia, "Early media"); -#if 0 - linphone_core_stop_ringing(lc); -#endif + if (listener) + listener->onStopRinging(q->getSharedFromThis()); lInfo() << "Doing early media..."; updateStreams(md, state); if ((q->getCurrentParams()->getAudioDirection() == LinphoneMediaDirectionInactive) && audioStream) { -#if 0 - if (lc->ringstream != NULL) return; /* Already ringing! */ - start_remote_ring(lc, call); -#endif + if (listener) + listener->onStartRinging(q->getSharedFromThis()); } } else { linphone_core_stop_dtmf_stream(q->getCore()->getCCore()); @@ -318,9 +301,8 @@ void MediaSessionPrivate::remoteRinging () { /* Already doing early media */ return; } -#if 0 - if (lc->ringstream == NULL) start_remote_ring(lc, call); -#endif + if (listener) + listener->onStartRinging(q->getSharedFromThis()); lInfo() << "Remote ringing..."; setState(LinphoneCallOutgoingRinging, "Remote ringing"); } @@ -2580,6 +2562,13 @@ void MediaSessionPrivate::setSymmetricRtp (bool value) { } } +void MediaSessionPrivate::setupRingbackPlayer () { + L_Q(); + int pauseTime = 3000; + audio_stream_play(audioStream, q->getCore()->getCCore()->sound_conf.ringback_tone); + ms_filter_call_method(audioStream->soundread, MS_FILE_PLAYER_LOOP, &pauseTime); +} + void MediaSessionPrivate::startAudioStream (LinphoneCallState targetState, bool videoWillBeUsed) { L_Q(); const SalStreamDescription *stream = sal_media_description_find_best_stream(resultDesc, SalAudio); @@ -2614,7 +2603,7 @@ void MediaSessionPrivate::startAudioStream (LinphoneCallState targetState, bool recfile = ""; /* And we will eventually play "playfile" if set by the user */ } - if (playingRingbackTone) { + if (listener && listener->isPlayingRingbackTone(q->getSharedFromThis())) { captcard = nullptr; playfile = ""; /* It is setup later */ if (lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sound", "send_ringback_without_playback", 0) == 1) { @@ -2710,18 +2699,15 @@ void MediaSessionPrivate::startAudioStream (LinphoneCallState targetState, bool (linphone_core_rtcp_enabled(q->getCore()->getCCore()) && !isMulticast) ? (stream->rtcp_port ? stream->rtcp_port : stream->rtp_port + 1) : 0, usedPt, &io); if (err == 0) - postConfigureAudioStreams((allMuted || audioMuted) && !playingRingbackTone); + postConfigureAudioStreams((allMuted || audioMuted) && (listener && !listener->isPlayingRingbackTone(q->getSharedFromThis()))); } ms_media_stream_sessions_set_encryption_mandatory(&audioStream->ms.sessions, isEncryptionMandatory()); if ((targetState == LinphoneCallPaused) && !captcard && !playfile.empty()) { int pauseTime = 500; ms_filter_call_method(audioStream->soundread, MS_FILE_PLAYER_LOOP, &pauseTime); } -#if 0 - if (playingRingbacktone) { - setup_ring_player(lc,call); - } -#endif + if (listener && listener->isPlayingRingbackTone(q->getSharedFromThis())) + setupRingbackPlayer(); if (getParams()->getPrivate()->getInConference() && q->getCore()->getCCore()->conf_ctx) { /* Transform the graph to connect it to the conference filter */ #if 0 @@ -2751,16 +2737,16 @@ void MediaSessionPrivate::startStreams (LinphoneCallState targetState) { L_Q(); switch (targetState) { case LinphoneCallIncomingEarlyMedia: - if (linphone_core_get_remote_ringback_tone(q->getCore()->getCCore())) { - playingRingbackTone = true; - } + if (listener) + listener->onRingbackToneRequested(q->getSharedFromThis(), true); BCTBX_NO_BREAK; case LinphoneCallOutgoingEarlyMedia: if (!getParams()->earlyMediaSendingEnabled()) allMuted = true; break; default: - playingRingbackTone = false; + if (listener) + listener->onRingbackToneRequested(q->getSharedFromThis(), false); allMuted = false; break; } @@ -3192,10 +3178,8 @@ void MediaSessionPrivate::updateStreams (SalMediaDescription *newMd, LinphoneCal | SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED | SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION)) lInfo() << "Media descriptions are different, need to restart the streams"; -#if 0 - else if (call->playing_ringbacktone) - ms_message("Playing ringback tone, will restart the streams."); -#endif + else if (listener && listener->isPlayingRingbackTone(q->getSharedFromThis())) + lInfo() << "Playing ringback tone, will restart the streams"; else { if (allMuted && (targetState == LinphoneCallStreamsRunning)) { lInfo() << "Early media finished, unmuting inputs..."; @@ -3595,6 +3579,7 @@ void MediaSessionPrivate::updateReportingMediaInfo (int statsType) { // ----------------------------------------------------------------------------- void MediaSessionPrivate::executeBackgroundTasks (bool oneSecondElapsed) { + L_Q(); switch (state) { case LinphoneCallStreamsRunning: case LinphoneCallOutgoingEarlyMedia: @@ -3624,16 +3609,8 @@ void MediaSessionPrivate::executeBackgroundTasks (bool oneSecondElapsed) { handleStreamEvents(mainVideoStreamIndex); handleStreamEvents(mainTextStreamIndex); -#if 0 - int disconnectTimeout = linphone_core_get_nortp_timeout(core); - bool disconnected = false; - if (((state == LinphoneCallStreamsRunning) || (state == LinphoneCallPausedByRemote)) && oneSecondElapsed && audioStream - && (audioStream->ms.state == MSStreamStarted) && (disconnectTimeout > 0)) { - disconnected = !audio_stream_alive(audioStream, disconnectTimeout); - } - if (disconnected) - linphone_call_lost(call); -#endif + if (listener) + listener->onNoMediaTimeoutCheck(q->getSharedFromThis(), oneSecondElapsed); } void MediaSessionPrivate::reportBandwidth () { @@ -3684,9 +3661,9 @@ void MediaSessionPrivate::reportBandwidthForStream (MediaStream *ms, LinphoneStr // ----------------------------------------------------------------------------- void MediaSessionPrivate::abort (const string &errorMsg) { -#if 0 - linphone_core_stop_ringing(lc); -#endif + L_Q(); + if (listener) + listener->onStopRinging(q->getSharedFromThis()); stopStreams(); CallSessionPrivate::abort(errorMsg); } @@ -3790,22 +3767,9 @@ LinphoneStatus MediaSessionPrivate::startUpdate (const string &subject) { } void MediaSessionPrivate::terminate () { -#if 0 // TODO: handle in Call class - /* Stop ringing */ - bool_t stop_ringing = TRUE; - bool_t ring_during_early_media = linphone_core_get_ring_during_incoming_early_media(lc); - const bctbx_list_t *calls = linphone_core_get_calls(lc); - while(calls) { - if (((LinphoneCall *)calls->data)->state == LinphoneCallIncomingReceived || (ring_during_early_media && ((LinphoneCall *)calls->data)->state == LinphoneCallIncomingEarlyMedia)) { - stop_ringing = FALSE; - break; - } - calls = calls->next; - } - if(stop_ringing) { - linphone_core_stop_ringing(lc); - } -#endif + L_Q(); + if (listener) + listener->onStopRingingIfNeeded(q->getSharedFromThis()); stopStreams(); CallSessionPrivate::terminate(); @@ -3903,7 +3867,7 @@ void MediaSessionPrivate::updateCurrentParams () const { // ----------------------------------------------------------------------------- -void MediaSessionPrivate::accept (const MediaSessionParams *msp) { +void MediaSessionPrivate::accept (const MediaSessionParams *msp, bool wasRinging) { L_Q(); if (msp) { setParams(new MediaSessionParams(*msp)); @@ -3923,11 +3887,10 @@ void MediaSessionPrivate::accept (const MediaSessionParams *msp) { ms_snd_card_set_preferred_sample_rate(q->getCore()->getCCore()->sound_conf.capt_sndcard, localDesc->streams[0].max_rate); } -#if 0 - if (!was_ringing && (audioStream->ms.state == MSStreamInitialized) && !core->use_files) { - audio_stream_prepare_sound(audioStream, core->sound_conf.play_sndcard, core->sound_conf.capt_sndcard); + LinphoneCore *lc = q->getCore()->getCCore(); + if (!wasRinging && (audioStream->ms.state == MSStreamInitialized) && !lc->use_files) { + audio_stream_prepare_sound(audioStream, lc->sound_conf.play_sndcard, lc->sound_conf.capt_sndcard); } -#endif CallSessionPrivate::accept(nullptr); @@ -4174,26 +4137,11 @@ LinphoneStatus MediaSession::accept (const MediaSessionParams *msp) { LinphoneStatus result = d->checkForAcceptation(); if (result < 0) return result; -#if 0 - bool_t was_ringing = FALSE; + bool wasRinging = false; + if (d->listener) + wasRinging = d->listener->onCallSessionAccepted(getSharedFromThis()); - if (lc->current_call != call) { - linphone_core_preempt_sound_resources(lc); - } - - /* Stop ringing */ - if (linphone_ringtoneplayer_is_started(lc->ringtoneplayer)) { - ms_message("Stop ringing"); - linphone_core_stop_ringing(lc); - was_ringing = TRUE; - } - if (call->ringing_beep) { - linphone_core_stop_dtmf(lc); - call->ringing_beep = FALSE; - } -#endif - - d->accept(msp); + d->accept(msp, wasRinging); lInfo() << "CallSession accepted"; return 0; } @@ -4291,6 +4239,20 @@ void MediaSession::configure (LinphoneCallDir direction, LinphoneProxyConfig *cf } } +LinphoneStatus MediaSession::deferUpdate () { + L_D(); + if (d->state != LinphoneCallUpdatedByRemote) { + lError() << "MediaSession::deferUpdate() not done in state LinphoneCallUpdatedByRemote"; + return -1; + } + if (d->expectMediaInAck) { + lError() << "MediaSession::deferUpdate() is not possible during a late offer incoming reINVITE (INVITE without SDP)"; + return -1; + } + d->deferUpdate = true; + return 0; +} + void MediaSession::initiateIncoming () { L_D(); CallSession::initiateIncoming(); @@ -4488,6 +4450,13 @@ void MediaSession::stopRecording () { d->recordActive = false; } +void MediaSession::terminateBecauseOfLostMedia () { + L_D(); + d->nonOpError = true; + linphone_error_info_set(d->ei, nullptr, LinphoneReasonIOError, 503, "Media lost", nullptr); + terminate(); +} + LinphoneStatus MediaSession::update (const MediaSessionParams *msp, const string &subject) { L_D(); LinphoneCallState nextState; @@ -4899,6 +4868,12 @@ bool MediaSession::mediaInProgress () const { return false; } +void MediaSession::setAudioRoute (LinphoneAudioRoute route) { + L_D(); + if (d->audioStream) + audio_stream_set_audio_route(d->audioStream, (MSAudioRoute)route); +} + void MediaSession::setAuthenticationTokenVerified (bool value) { L_D(); if (!d->audioStream || !media_stream_started(&d->audioStream->ms)) { diff --git a/src/conference/session/media-session.h b/src/conference/session/media-session.h index 59688f4db..2a78b7d2e 100644 --- a/src/conference/session/media-session.h +++ b/src/conference/session/media-session.h @@ -47,6 +47,7 @@ public: LinphoneStatus acceptUpdate (const MediaSessionParams *msp); void cancelDtmfs (); void configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to) override; + LinphoneStatus deferUpdate () override; void initiateIncoming () override; bool initiateOutgoing () override; void iterate (time_t currentRealTime, bool oneSecondElapsed) override; @@ -59,6 +60,7 @@ public: int startInvite (const Address *destination, const std::string &subject = "", const Content *content = nullptr) override; void startRecording (); void stopRecording (); + void terminateBecauseOfLostMedia (); LinphoneStatus update (const MediaSessionParams *msp, const std::string &subject = ""); void resetFirstVideoFrameDecoded (); @@ -96,6 +98,7 @@ public: LinphoneCallStats * getTextStats () const; LinphoneCallStats * getVideoStats () const; bool mediaInProgress () const; + void setAudioRoute (LinphoneAudioRoute route); void setAuthenticationTokenVerified (bool value); void setMicrophoneVolumeGain (float value); void setNativeVideoWindowId (void *id);