mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 19:18:06 +00:00
Improve API so that it is more object-oriented.
This commit is contained in:
parent
7276f565f2
commit
e53d4cf70d
11 changed files with 1113 additions and 815 deletions
|
|
@ -50,7 +50,7 @@ static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *old
|
|||
return result;
|
||||
}
|
||||
|
||||
void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) {
|
||||
void linphone_core_update_streams_destinations(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) {
|
||||
SalStreamDescription *new_audiodesc = NULL;
|
||||
SalStreamDescription *new_videodesc = NULL;
|
||||
char *rtp_addr, *rtcp_addr;
|
||||
|
|
@ -124,55 +124,55 @@ void linphone_call_update_frozen_payloads(LinphoneCall *call, SalMediaDescriptio
|
|||
}
|
||||
}
|
||||
|
||||
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md, LinphoneCallState target_state){
|
||||
SalMediaDescription *oldmd=call->resultdesc;
|
||||
int md_changed=0;
|
||||
|
||||
void linphone_call_update_streams(LinphoneCall *call, SalMediaDescription *new_md, LinphoneCallState target_state) {
|
||||
LinphoneCore *lc = linphone_call_get_core(call);
|
||||
SalMediaDescription *oldmd = call->resultdesc;
|
||||
int md_changed = 0;
|
||||
|
||||
if (!((call->state == LinphoneCallIncomingEarlyMedia) && (linphone_core_get_ring_during_incoming_early_media(lc)))) {
|
||||
linphone_core_stop_ringing(lc);
|
||||
}
|
||||
if (!new_md) {
|
||||
ms_error("linphone_core_update_streams() called with null media description");
|
||||
ms_error("linphone_call_update_streams() called with null media description");
|
||||
return;
|
||||
}
|
||||
linphone_call_update_biggest_desc(call, call->localdesc);
|
||||
sal_media_description_ref(new_md);
|
||||
call->resultdesc=new_md;
|
||||
if ((call->audiostream && call->audiostream->ms.state==MSStreamStarted) || (call->videostream && call->videostream->ms.state==MSStreamStarted)){
|
||||
call->resultdesc = new_md;
|
||||
if ((call->audiostream && (call->audiostream->ms.state == MSStreamStarted)) || (call->videostream && (call->videostream->ms.state == MSStreamStarted))) {
|
||||
clear_early_media_destinations(call);
|
||||
|
||||
/* we already started media: check if we really need to restart it*/
|
||||
if (oldmd){
|
||||
/* We already started media: check if we really need to restart it */
|
||||
if (oldmd) {
|
||||
md_changed = media_parameters_changed(call, oldmd, new_md);
|
||||
if ((md_changed & ( SAL_MEDIA_DESCRIPTION_CODEC_CHANGED
|
||||
|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED
|
||||
|SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED
|
||||
|SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED
|
||||
|SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION ))){
|
||||
|SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION ))) {
|
||||
ms_message("Media descriptions are different, need to restart the streams.");
|
||||
} else if ( call->playing_ringbacktone) {
|
||||
} else if (call->playing_ringbacktone) {
|
||||
ms_message("Playing ringback tone, will restart the streams.");
|
||||
} else {
|
||||
if (md_changed == SAL_MEDIA_DESCRIPTION_UNCHANGED) {
|
||||
if (call->all_muted){
|
||||
if (call->all_muted) {
|
||||
ms_message("Early media finished, unmuting inputs...");
|
||||
/*we were in early media, now we want to enable real media */
|
||||
/* We were in early media, now we want to enable real media */
|
||||
call->all_muted = FALSE;
|
||||
if (call->audiostream)
|
||||
linphone_core_enable_mic(lc, linphone_core_mic_enabled(lc));
|
||||
if (call->audiostream) linphone_core_enable_mic(lc, linphone_core_mic_enabled(lc));
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream && call->camera_enabled)
|
||||
if (call->videostream && call->camera_enabled) {
|
||||
linphone_call_enable_camera(call, linphone_call_camera_enabled(call));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*FIXME ZRTP, might be restarted in any cases ? */
|
||||
ms_message("No need to restart streams, SDP is unchanged.");
|
||||
goto end;
|
||||
}else {
|
||||
} else {
|
||||
if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED) {
|
||||
ms_message("Network parameters have changed, update them.");
|
||||
linphone_core_update_streams_destinations(lc, call, oldmd, new_md);
|
||||
linphone_core_update_streams_destinations(call, oldmd, new_md);
|
||||
}
|
||||
if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) {
|
||||
ms_message("Crypto parameters have changed, update them.");
|
||||
|
|
@ -182,34 +182,35 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
|
|||
}
|
||||
}
|
||||
}
|
||||
linphone_call_stop_media_streams (call);
|
||||
if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED){
|
||||
ms_message("Media ip type has changed, destroying sessions context on call [%p]",call);
|
||||
linphone_call_stop_media_streams(call);
|
||||
if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED) {
|
||||
ms_message("Media ip type has changed, destroying sessions context on call [%p]", call);
|
||||
ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]);
|
||||
ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]);
|
||||
ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]);
|
||||
}
|
||||
linphone_call_init_media_streams (call);
|
||||
linphone_call_init_media_streams(call);
|
||||
}
|
||||
|
||||
if (call->audiostream==NULL){
|
||||
/*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/
|
||||
linphone_call_init_media_streams (call);
|
||||
if (call->audiostream == NULL) {
|
||||
/* This happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them */
|
||||
linphone_call_init_media_streams(call);
|
||||
}
|
||||
|
||||
if (call->params->real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){
|
||||
if (call->params->real_early_media && (call->state == LinphoneCallOutgoingEarlyMedia)) {
|
||||
prepare_early_media_forking(call);
|
||||
}
|
||||
linphone_call_start_media_streams(call, target_state);
|
||||
if (call->state==LinphoneCallPausing && call->paused_by_app && bctbx_list_size(lc->calls)==1){
|
||||
linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
|
||||
if ((call->state == LinphoneCallPausing) && call->paused_by_app && (bctbx_list_size(lc->calls) == 1)) {
|
||||
linphone_core_play_named_tone(lc, LinphoneToneCallOnHold);
|
||||
}
|
||||
linphone_call_update_frozen_payloads(call, new_md);
|
||||
end:
|
||||
if (oldmd)
|
||||
sal_media_description_unref(oldmd);
|
||||
|
||||
end:
|
||||
if (oldmd) sal_media_description_unref(oldmd);
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){
|
||||
bctbx_list_t *elem;
|
||||
|
|
@ -476,7 +477,7 @@ static void call_ringing(SalOp *h){
|
|||
linphone_call_set_state(call,LinphoneCallOutgoingEarlyMedia,"Early media");
|
||||
linphone_core_stop_ringing(lc);
|
||||
ms_message("Doing early media...");
|
||||
linphone_core_update_streams(lc,call,md, call->state);
|
||||
linphone_call_update_streams(call, md, call->state);
|
||||
if ((linphone_call_params_get_audio_direction(linphone_call_get_current_params(call)) == LinphoneMediaDirectionInactive) && call->audiostream) {
|
||||
if (lc->ringstream != NULL) return; /* Already ringing! */
|
||||
start_remote_ring(lc, call);
|
||||
|
|
@ -523,7 +524,7 @@ static void process_call_accepted(LinphoneCore *lc, LinphoneCall *call, SalOp *o
|
|||
|
||||
#ifdef BUILD_UPNP
|
||||
if (call->upnp_session != NULL && rmd) {
|
||||
linphone_core_update_upnp_from_remote_media_description(call, rmd);
|
||||
linphone_call_update_upnp_from_remote_media_description(call, rmd);
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
|
||||
|
|
@ -582,8 +583,8 @@ static void process_call_accepted(LinphoneCore *lc, LinphoneCall *call, SalOp *o
|
|||
|
||||
if (next_state != LinphoneCallIdle){
|
||||
linphone_call_update_remote_session_id_and_ver(call);
|
||||
linphone_core_update_ice_state_in_call_stats(call);
|
||||
linphone_core_update_streams(lc, call, md, next_state);
|
||||
linphone_call_update_ice_state_in_call_stats(call);
|
||||
linphone_call_update_streams(call, md, next_state);
|
||||
linphone_call_fix_call_parameters(call, rmd);
|
||||
linphone_call_set_state(call, next_state, next_state_str);
|
||||
}else{
|
||||
|
|
@ -599,7 +600,7 @@ static void process_call_accepted(LinphoneCore *lc, LinphoneCall *call, SalOp *o
|
|||
case LinphoneCallIncomingReceived:
|
||||
case LinphoneCallIncomingEarlyMedia:
|
||||
ms_error("Incompatible SDP answer received, need to abort the call");
|
||||
linphone_core_abort_call(lc,call,_("Incompatible, check codecs or security settings..."));
|
||||
linphone_call_abort(call, _("Incompatible, check codecs or security settings..."));
|
||||
break;
|
||||
/*otherwise we are able to resume previous state*/
|
||||
default:
|
||||
|
|
@ -641,7 +642,7 @@ static void call_accepted(SalOp *op){
|
|||
|
||||
static void call_resumed(LinphoneCore *lc, LinphoneCall *call){
|
||||
linphone_core_notify_display_status(lc,_("We have been resumed."));
|
||||
_linphone_core_accept_call_update(lc,call,NULL,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
_linphone_call_accept_update(call,NULL,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}
|
||||
|
||||
static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
|
||||
|
|
@ -653,7 +654,7 @@ static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
|
|||
if (lp_config_get_int(lc->config, "sip", "inactive_video_on_pause", 0)) {
|
||||
linphone_call_params_set_video_direction(params, LinphoneMediaDirectionInactive);
|
||||
}
|
||||
_linphone_core_accept_call_update(lc,call,params,LinphoneCallPausedByRemote,"Call paused by remote");
|
||||
_linphone_call_accept_update(call,params,LinphoneCallPausedByRemote,"Call paused by remote");
|
||||
linphone_call_params_unref(params);
|
||||
}
|
||||
|
||||
|
|
@ -695,7 +696,7 @@ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t
|
|||
case LinphoneCallIncomingEarlyMedia:
|
||||
if (is_update) {
|
||||
linphone_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote");
|
||||
_linphone_core_accept_call_update(lc,call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate));
|
||||
_linphone_call_accept_update(call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate));
|
||||
}
|
||||
break;
|
||||
case LinphoneCallStreamsRunning:
|
||||
|
|
@ -709,7 +710,7 @@ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t
|
|||
break;
|
||||
case LinphoneCallPaused:
|
||||
/*we'll remain in pause state but accept the offer anyway according to default parameters*/
|
||||
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
|
||||
_linphone_call_accept_update(call,NULL,call->state,linphone_call_state_to_string(call->state));
|
||||
break;
|
||||
case LinphoneCallUpdating:
|
||||
case LinphoneCallPausing:
|
||||
|
|
@ -908,7 +909,7 @@ static void call_failure(SalOp *op){
|
|||
linphone_address_unref(call->log->to);
|
||||
}
|
||||
call->log->to = linphone_address_ref(redirection_to);
|
||||
linphone_core_restart_invite(lc, call);
|
||||
linphone_call_restart_invite(call);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -941,19 +942,19 @@ static void call_failure(SalOp *op){
|
|||
if (call->params->avpf_enabled == TRUE) {
|
||||
if (i == 0) ms_message("Retrying call [%p] with SAVP", call);
|
||||
call->params->avpf_enabled = FALSE;
|
||||
linphone_core_restart_invite(lc, call);
|
||||
linphone_call_restart_invite(call);
|
||||
return;
|
||||
} else if (!linphone_core_is_media_encryption_mandatory(lc)) {
|
||||
if (i == 0) ms_message("Retrying call [%p] with AVP", call);
|
||||
call->params->media_encryption = LinphoneMediaEncryptionNone;
|
||||
memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto));
|
||||
linphone_core_restart_invite(lc, call);
|
||||
linphone_call_restart_invite(call);
|
||||
return;
|
||||
}
|
||||
} else if (call->params->avpf_enabled == TRUE) {
|
||||
if (i == 0) ms_message("Retrying call [%p] with AVP", call);
|
||||
call->params->avpf_enabled = FALSE;
|
||||
linphone_core_restart_invite(lc, call);
|
||||
linphone_call_restart_invite(call);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1216,7 +1217,7 @@ static void ping_reply(SalOp *op){
|
|||
if (call){
|
||||
if (call->state==LinphoneCallOutgoingInit){
|
||||
call->ping_replied=TRUE;
|
||||
linphone_core_proceed_with_invite_if_ready(call->core,call,NULL);
|
||||
linphone_call_proceed_with_invite_if_ready(call, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -445,7 +445,7 @@ int LocalConference::removeFromConference(LinphoneCall *call, bool_t active){
|
|||
linphone_call_params_unref(params);
|
||||
} else{
|
||||
ms_message("Pausing call to actually remove from conference");
|
||||
err=_linphone_core_pause_call(m_core,call);
|
||||
err=_linphone_call_pause(call);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
|
@ -529,7 +529,7 @@ int LocalConference::enter() {
|
|||
return -1;
|
||||
}
|
||||
if (m_core->current_call != NULL) {
|
||||
_linphone_core_pause_call(m_core, m_core->current_call);
|
||||
_linphone_call_pause(m_core->current_call);
|
||||
}
|
||||
if (m_localParticipantStream==NULL) addLocalEndpoint();
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -630,12 +630,12 @@ void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall
|
|||
/*set this to FALSE once flexisip are updated everywhere, let's say in December 2016.*/
|
||||
bool_t use_nortpproxy = lp_config_get_int(lc->config, "sip", "ice_uses_nortpproxy", TRUE);
|
||||
_update_local_media_description_from_ice(call->localdesc, call->ice_session, use_nortpproxy);
|
||||
linphone_core_update_ice_state_in_call_stats(call);
|
||||
linphone_call_update_ice_state_in_call_stats(call);
|
||||
}
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
linphone_core_update_upnp_state_in_call_stats(call);
|
||||
linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
linphone_call_update_upnp_state_in_call_stats(call);
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
}
|
||||
|
|
@ -1504,7 +1504,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
if(!lc->rtp_conf.disable_upnp) {
|
||||
call->upnp_session = linphone_upnp_session_new(call);
|
||||
if (call->upnp_session != NULL) {
|
||||
if (linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op))<0) {
|
||||
if (linphone_call_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op))<0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
}
|
||||
|
|
@ -4365,7 +4365,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
default:
|
||||
break;
|
||||
}
|
||||
linphone_core_update_ice_state_in_call_stats(call);
|
||||
linphone_call_update_ice_state_in_call_stats(call);
|
||||
} else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
|
||||
if (evd->info.ice_processing_successful==FALSE) {
|
||||
ms_warning("No STUN answer from [%s], continuing without STUN",linphone_core_get_stun_server(call->core));
|
||||
|
|
@ -4373,14 +4373,14 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
linphone_call_on_ice_gathering_finished(call);
|
||||
switch (call->state) {
|
||||
case LinphoneCallUpdating:
|
||||
linphone_core_start_update_call(call->core, call);
|
||||
linphone_call_start_update(call);
|
||||
break;
|
||||
case LinphoneCallUpdatedByRemote:
|
||||
linphone_core_start_accept_call_update(call->core, call,call->prevstate,linphone_call_state_to_string(call->prevstate));
|
||||
linphone_call_start_accept_update(call, call->prevstate,linphone_call_state_to_string(call->prevstate));
|
||||
break;
|
||||
case LinphoneCallOutgoingInit:
|
||||
linphone_call_stop_media_streams_for_ice_gathering(call);
|
||||
linphone_core_proceed_with_invite_if_ready(call->core, call, NULL);
|
||||
linphone_call_proceed_with_invite_if_ready(call, NULL);
|
||||
break;
|
||||
case LinphoneCallIdle:
|
||||
linphone_call_stop_media_streams_for_ice_gathering(call);
|
||||
|
|
@ -4393,8 +4393,8 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
}
|
||||
} else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) {
|
||||
if (call->state==LinphoneCallUpdatedByRemote){
|
||||
linphone_core_start_accept_call_update(call->core, call,call->prevstate,linphone_call_state_to_string(call->prevstate));
|
||||
linphone_core_update_ice_state_in_call_stats(call);
|
||||
linphone_call_start_accept_update(call, call->prevstate, linphone_call_state_to_string(call->prevstate));
|
||||
linphone_call_update_ice_state_in_call_stats(call);
|
||||
}
|
||||
} else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) {
|
||||
ice_session_restart(call->ice_session, IR_Controlling);
|
||||
|
|
@ -4917,6 +4917,734 @@ RtpTransport* linphone_call_get_meta_rtcp_transport(LinphoneCall *call, int stre
|
|||
return meta_rtcp;
|
||||
}
|
||||
|
||||
int linphone_call_pause(LinphoneCall *call) {
|
||||
int err = _linphone_call_pause(call);
|
||||
if (err == 0) call->paused_by_app = TRUE;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Internal version that does not play tone indication*/
|
||||
int _linphone_call_pause(LinphoneCall *call) {
|
||||
LinphoneCore *lc;
|
||||
const char *subject = NULL;
|
||||
|
||||
if ((call->state != LinphoneCallStreamsRunning) && (call->state != LinphoneCallPausedByRemote)) {
|
||||
ms_warning("Cannot pause this call, it is not active.");
|
||||
return -1;
|
||||
}
|
||||
if (sal_media_description_has_dir(call->resultdesc, SalStreamSendRecv)) {
|
||||
subject = "Call on hold";
|
||||
} else if (sal_media_description_has_dir(call->resultdesc, SalStreamRecvOnly)) {
|
||||
subject = "Call on hold for me too";
|
||||
} else {
|
||||
ms_error("No reason to pause this call, it is already paused or inactive.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lc = linphone_call_get_core(call);
|
||||
call->broken = FALSE;
|
||||
linphone_call_set_state(call, LinphoneCallPausing, "Pausing call");
|
||||
linphone_call_make_local_media_description(call);
|
||||
#ifdef BUILD_UPNP
|
||||
if (call->upnp_session != NULL) {
|
||||
linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
}
|
||||
#endif // BUILD_UPNP
|
||||
sal_call_set_local_media_description(call->op, call->localdesc);
|
||||
if (sal_call_update(call->op, subject, FALSE) != 0) {
|
||||
linphone_core_notify_display_warning(lc, _("Could not pause the call"));
|
||||
}
|
||||
lc->current_call = NULL;
|
||||
linphone_core_notify_display_status(lc, _("Pausing the current call..."));
|
||||
if (call->audiostream || call->videostream || call->textstream)
|
||||
linphone_call_stop_media_streams(call);
|
||||
call->paused_by_app = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_call_resume(LinphoneCall *call) {
|
||||
LinphoneCore *lc;
|
||||
const char *subject = "Call resuming";
|
||||
char *remote_address;
|
||||
char *display_status;
|
||||
|
||||
if (call->state != LinphoneCallPaused) {
|
||||
ms_warning("we cannot resume a call that has not been established and paused before");
|
||||
return -1;
|
||||
}
|
||||
lc = linphone_call_get_core(call);
|
||||
if (call->params->in_conference == FALSE) {
|
||||
if (linphone_core_sound_resources_locked(lc)) {
|
||||
ms_warning("Cannot resume call %p because another call is locking the sound resources.", call);
|
||||
return -1;
|
||||
}
|
||||
linphone_core_preempt_sound_resources(lc);
|
||||
ms_message("Resuming call %p", call);
|
||||
}
|
||||
|
||||
call->was_automatically_paused = FALSE;
|
||||
call->broken = FALSE;
|
||||
|
||||
/* Stop playing music immediately. If remote side is a conference it
|
||||
prevents the participants to hear it while the 200OK comes back. */
|
||||
if (call->audiostream) audio_stream_play(call->audiostream, NULL);
|
||||
|
||||
linphone_call_make_local_media_description(call);
|
||||
#ifdef BUILD_UPNP
|
||||
if (call->upnp_session != NULL) {
|
||||
linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
}
|
||||
#endif // BUILD_UPNP
|
||||
if (!lc->sip_conf.sdp_200_ack) {
|
||||
sal_call_set_local_media_description(call->op, call->localdesc);
|
||||
} else {
|
||||
sal_call_set_local_media_description(call->op, NULL);
|
||||
}
|
||||
sal_media_description_set_dir(call->localdesc, SalStreamSendRecv);
|
||||
if (call->params->in_conference && !call->current_params->in_conference) subject = "Conference";
|
||||
if (sal_call_update(call->op, subject, FALSE) != 0) {
|
||||
return -1;
|
||||
}
|
||||
linphone_call_set_state(call, LinphoneCallResuming,"Resuming");
|
||||
if (call->params->in_conference == FALSE)
|
||||
lc->current_call = call;
|
||||
remote_address = linphone_call_get_remote_address_as_string(call);
|
||||
display_status = ms_strdup_printf("Resuming the call with with %s", remote_address);
|
||||
ms_free(remote_address);
|
||||
linphone_core_notify_display_status(lc, display_status);
|
||||
ms_free(display_status);
|
||||
|
||||
if (lc->sip_conf.sdp_200_ack) {
|
||||
/* We are NOT offering, set local media description after sending the call so that we are ready to
|
||||
process the remote offer when it will arrive. */
|
||||
sal_call_set_local_media_description(call->op, call->localdesc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void terminate_call(LinphoneCall *call) {
|
||||
LinphoneCore *lc = linphone_call_get_core(call);
|
||||
|
||||
if ((call->state == LinphoneCallIncomingReceived) && (call->non_op_error.reason != SalReasonRequestTimeout))
|
||||
call->non_op_error.reason=SalReasonDeclined;
|
||||
|
||||
/* Stop ringing */
|
||||
linphone_core_stop_ringing(lc);
|
||||
linphone_call_stop_media_streams(call);
|
||||
|
||||
#ifdef BUILD_UPNP
|
||||
linphone_call_delete_upnp_session(call);
|
||||
#endif // BUILD_UPNP
|
||||
|
||||
linphone_core_notify_display_status(lc, _("Call ended") );
|
||||
linphone_call_set_state(call, LinphoneCallEnd, "Call terminated");
|
||||
}
|
||||
|
||||
int linphone_call_terminate(LinphoneCall *call) {
|
||||
ms_message("Terminate call [%p] which is currently in state %s", call, linphone_call_state_to_string(call->state));
|
||||
switch (call->state) {
|
||||
case LinphoneCallReleased:
|
||||
case LinphoneCallEnd:
|
||||
case LinphoneCallError:
|
||||
ms_warning("No need to terminate a call [%p] in state [%s]", call, linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
case LinphoneCallIncomingReceived:
|
||||
case LinphoneCallIncomingEarlyMedia:
|
||||
return linphone_call_decline(call, LinphoneReasonDeclined);
|
||||
case LinphoneCallOutgoingInit:
|
||||
/* In state OutgoingInit, op has to be destroyed */
|
||||
sal_op_release(call->op);
|
||||
call->op = NULL;
|
||||
break;
|
||||
default:
|
||||
sal_call_terminate(call->op);
|
||||
break;
|
||||
}
|
||||
terminate_call(call);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) {
|
||||
char *real_url = NULL;
|
||||
LinphoneCore *lc;
|
||||
LinphoneAddress *real_parsed_url;
|
||||
|
||||
if (call->state != LinphoneCallIncomingReceived) {
|
||||
ms_error("Bad state for call redirection.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lc = linphone_call_get_core(call);
|
||||
real_parsed_url = linphone_core_interpret_url(lc, redirect_uri);
|
||||
if (!real_parsed_url) {
|
||||
/* Bad url */
|
||||
ms_error("Bad redirect URI: %s", redirect_uri ? redirect_uri : "NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
real_url = linphone_address_as_string(real_parsed_url);
|
||||
sal_call_decline(call->op, SalReasonRedirect, real_url);
|
||||
ms_free(real_url);
|
||||
sal_error_info_set(&call->non_op_error, SalReasonRedirect, 603, "Call redirected", NULL);
|
||||
terminate_call(call);
|
||||
linphone_address_unref(real_parsed_url);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_call_decline(LinphoneCall * call, LinphoneReason reason) {
|
||||
if ((call->state != LinphoneCallIncomingReceived) && (call->state != LinphoneCallIncomingEarlyMedia)) {
|
||||
ms_error("Cannot decline a call that is in state %s", linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sal_call_decline(call->op, linphone_reason_to_sal(reason), NULL);
|
||||
terminate_call(call);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_call_accept(LinphoneCall *call) {
|
||||
return linphone_call_accept_with_params(call, NULL);
|
||||
}
|
||||
|
||||
int linphone_call_accept_with_params(LinphoneCall *call, const LinphoneCallParams *params) {
|
||||
LinphoneCore *lc;
|
||||
SalOp *replaced;
|
||||
SalMediaDescription *new_md;
|
||||
bool_t was_ringing = FALSE;
|
||||
bctbx_list_t *iterator, *copy;
|
||||
|
||||
switch (call->state) {
|
||||
case LinphoneCallIncomingReceived:
|
||||
case LinphoneCallIncomingEarlyMedia:
|
||||
break;
|
||||
default:
|
||||
ms_error("linphone_core_accept_call_with_params() call [%p] is in state [%s], operation not permitted.",
|
||||
call, linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
}
|
||||
|
||||
lc = linphone_call_get_core(call);
|
||||
for (iterator = copy = bctbx_list_copy(linphone_core_get_calls(lc)); iterator != NULL; iterator = bctbx_list_next(iterator)) {
|
||||
LinphoneCall *a_call = (LinphoneCall *)bctbx_list_get_data(iterator);
|
||||
if (a_call == call) continue;
|
||||
switch (a_call->state) {
|
||||
case LinphoneCallOutgoingInit:
|
||||
case LinphoneCallOutgoingProgress:
|
||||
case LinphoneCallOutgoingRinging:
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
ms_message("Already existing call [%p] in state [%s], canceling it before accepting new call [%p]",
|
||||
a_call, linphone_call_state_to_string(a_call->state), call);
|
||||
linphone_call_terminate(a_call);
|
||||
break;
|
||||
default:
|
||||
break; /* Nothing to do */
|
||||
}
|
||||
}
|
||||
bctbx_list_free(copy);
|
||||
|
||||
/* Check if this call is supposed to replace an already running one */
|
||||
replaced = sal_call_get_replaces(call->op);
|
||||
if (replaced) {
|
||||
LinphoneCall *rc = (LinphoneCall *)sal_op_get_user_pointer(replaced);
|
||||
if (rc) {
|
||||
ms_message("Call %p replaces call %p. This last one is going to be terminated automatically.", call, rc);
|
||||
linphone_call_terminate(rc);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Try to be best-effort in giving real local or routable contact address */
|
||||
linphone_call_set_contact_op(call);
|
||||
if (params) {
|
||||
linphone_call_set_new_params(call, params);
|
||||
linphone_call_prepare_ice(call, TRUE);
|
||||
linphone_call_make_local_media_description(call);
|
||||
sal_call_set_local_media_description(call->op, call->localdesc);
|
||||
sal_op_set_sent_custom_header(call->op, params->custom_headers);
|
||||
}
|
||||
|
||||
/* Give a chance a set card prefered sampling frequency */
|
||||
if (call->localdesc->streams[0].max_rate > 0) {
|
||||
ms_message("Configuring prefered card sampling rate to [%i]", call->localdesc->streams[0].max_rate);
|
||||
if (lc->sound_conf.play_sndcard)
|
||||
ms_snd_card_set_preferred_sample_rate(lc->sound_conf.play_sndcard, call->localdesc->streams[0].max_rate);
|
||||
if (lc->sound_conf.capt_sndcard)
|
||||
ms_snd_card_set_preferred_sample_rate(lc->sound_conf.capt_sndcard, call->localdesc->streams[0].max_rate);
|
||||
}
|
||||
|
||||
if (!was_ringing && (call->audiostream->ms.state == MSStreamInitialized) && !lc->use_files) {
|
||||
audio_stream_prepare_sound(call->audiostream, lc->sound_conf.play_sndcard, lc->sound_conf.capt_sndcard);
|
||||
}
|
||||
|
||||
linphone_call_update_remote_session_id_and_ver(call);
|
||||
|
||||
sal_call_accept(call->op);
|
||||
linphone_core_notify_display_status(lc, _("Connected."));
|
||||
lc->current_call = call;
|
||||
linphone_call_set_state(call, LinphoneCallConnected, "Connected");
|
||||
new_md = sal_call_get_final_media_description(call->op);
|
||||
linphone_call_stop_ice_for_inactive_streams(call, new_md);
|
||||
if (new_md) {
|
||||
linphone_call_update_streams(call, new_md, LinphoneCallStreamsRunning);
|
||||
linphone_call_set_state(call, LinphoneCallStreamsRunning, "Connected (streams running)");
|
||||
} else {
|
||||
call->expect_media_in_ack = TRUE;
|
||||
}
|
||||
|
||||
ms_message("Call answered");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_call_accept_early_media(LinphoneCall* call) {
|
||||
return linphone_call_accept_early_media_with_params(call, NULL);
|
||||
}
|
||||
|
||||
int linphone_call_accept_early_media_with_params(LinphoneCall *call, const LinphoneCallParams *params) {
|
||||
SalMediaDescription* md;
|
||||
|
||||
if (call->state != LinphoneCallIncomingReceived) {
|
||||
ms_error("Bad state %s for linphone_core_accept_early_media_with_params()", linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try to be best-effort in giving real local or routable contact address for 100Rel case */
|
||||
linphone_call_set_contact_op(call);
|
||||
|
||||
/* If parameters are passed, update the media description */
|
||||
if (params) {
|
||||
linphone_call_set_new_params(call, params);
|
||||
linphone_call_make_local_media_description(call);
|
||||
sal_call_set_local_media_description(call->op, call->localdesc);
|
||||
sal_op_set_sent_custom_header(call->op, params->custom_headers);
|
||||
}
|
||||
|
||||
sal_call_notify_ringing(call->op, TRUE);
|
||||
|
||||
linphone_call_set_state(call, LinphoneCallIncomingEarlyMedia, "Incoming call early media");
|
||||
md = sal_call_get_final_media_description(call->op);
|
||||
if (md) linphone_call_update_streams(call, md, call->state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_call_update(LinphoneCall *call, const LinphoneCallParams *params) {
|
||||
int err = 0;
|
||||
LinphoneCallState nextstate;
|
||||
LinphoneCallState initial_state = call->state;
|
||||
const LinphoneCallParams *current_params;
|
||||
LinphoneCore *lc;
|
||||
|
||||
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
|
||||
bool_t has_video = FALSE;
|
||||
#endif
|
||||
|
||||
switch (initial_state) {
|
||||
case LinphoneCallIncomingReceived:
|
||||
case LinphoneCallIncomingEarlyMedia:
|
||||
case LinphoneCallOutgoingRinging:
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
nextstate = LinphoneCallEarlyUpdating;
|
||||
break;
|
||||
case LinphoneCallStreamsRunning:
|
||||
case LinphoneCallPausedByRemote:
|
||||
case LinphoneCallUpdatedByRemote:
|
||||
nextstate = LinphoneCallUpdating;
|
||||
break;
|
||||
case LinphoneCallPaused:
|
||||
nextstate = LinphoneCallPausing;
|
||||
break;
|
||||
case LinphoneCallOutgoingProgress:
|
||||
case LinphoneCallPausing:
|
||||
case LinphoneCallResuming:
|
||||
case LinphoneCallUpdating:
|
||||
nextstate = initial_state;
|
||||
break;
|
||||
default:
|
||||
ms_error("linphone_call_update() is not allowed in [%s] state", linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
}
|
||||
|
||||
lc = linphone_call_get_core(call);
|
||||
current_params = linphone_call_get_current_params(call);
|
||||
if ((current_params != NULL) && (current_params == params)) {
|
||||
ms_warning("linphone_call_update() is given the current params of the call, this probably not what you intend to do!");
|
||||
}
|
||||
|
||||
linphone_call_check_ice_session(call, IR_Controlling, TRUE);
|
||||
|
||||
if (params != NULL) {
|
||||
call->broken = FALSE;
|
||||
linphone_call_set_state(call, nextstate, "Updating call");
|
||||
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
|
||||
has_video = call->params->has_video;
|
||||
|
||||
/* Video removal */
|
||||
if ((call->videostream != NULL) && !params->has_video) {
|
||||
if (call->upnp_session != NULL) {
|
||||
if (linphone_call_update_upnp(call) < 0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */
|
||||
linphone_call_set_new_params(call, params);
|
||||
err = linphone_call_prepare_ice(call, FALSE);
|
||||
if (err == 1) {
|
||||
ms_message("Defer call update to gather ICE candidates");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
|
||||
/* Video adding */
|
||||
if (!has_video && call->params->has_video) {
|
||||
if(call->upnp_session != NULL) {
|
||||
ms_message("Defer call update to add uPnP port mappings");
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_call_update_upnp(call) < 0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
} else {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */
|
||||
if ((err = linphone_call_start_update(call)) && (call->state != initial_state)) {
|
||||
/* Restore initial state */
|
||||
linphone_call_set_state(call, initial_state, "Restore initial state");
|
||||
}
|
||||
} else {
|
||||
#ifdef VIDEO_ENABLED
|
||||
if ((call->videostream != NULL) && (call->state == LinphoneCallStreamsRunning)) {
|
||||
video_stream_set_sent_video_size(call->videostream, linphone_core_get_preferred_video_size(lc));
|
||||
video_stream_set_fps(call->videostream, linphone_core_get_preferred_framerate(lc));
|
||||
if (call->camera_enabled && (call->videostream->cam != lc->video_conf.device)) {
|
||||
video_stream_change_camera(call->videostream, lc->video_conf.device);
|
||||
} else {
|
||||
video_stream_update_video_params(call->videostream);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int linphone_call_start_update(LinphoneCall *call) {
|
||||
const char *subject;
|
||||
int err;
|
||||
bool_t no_user_consent = call->params->no_user_consent;
|
||||
LinphoneCore *lc = linphone_call_get_core(call);
|
||||
|
||||
linphone_call_fill_media_multicast_addr(call);
|
||||
|
||||
if (!no_user_consent) linphone_call_make_local_media_description(call);
|
||||
#ifdef BUILD_UPNP
|
||||
if (call->upnp_session != NULL) {
|
||||
linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
}
|
||||
#endif // BUILD_UPNP
|
||||
if (call->params->in_conference) {
|
||||
subject = "Conference";
|
||||
} else if (call->params->internal_call_update) {
|
||||
subject = "ICE processing concluded";
|
||||
} else if (no_user_consent) {
|
||||
subject = "Refreshing";
|
||||
} else {
|
||||
subject = "Media change";
|
||||
}
|
||||
linphone_core_notify_display_status(lc, _("Modifying call parameters..."));
|
||||
if (!lc->sip_conf.sdp_200_ack) {
|
||||
sal_call_set_local_media_description(call->op, call->localdesc);
|
||||
} else {
|
||||
sal_call_set_local_media_description(call->op, NULL);
|
||||
}
|
||||
if (call->dest_proxy && call->dest_proxy->op) {
|
||||
/* Give a chance to update the contact address if connectivity has changed */
|
||||
sal_op_set_contact_address(call->op, sal_op_get_contact_address(call->dest_proxy->op));
|
||||
} else {
|
||||
sal_op_set_contact_address(call->op, NULL);
|
||||
}
|
||||
err = sal_call_update(call->op, subject, no_user_consent);
|
||||
if (lc->sip_conf.sdp_200_ack) {
|
||||
/* We are NOT offering, set local media description after sending the call so that we are ready to
|
||||
process the remote offer when it will arrive. */
|
||||
sal_call_set_local_media_description(call->op, call->localdesc);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int linphone_call_defer_update(LinphoneCall *call) {
|
||||
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;
|
||||
}
|
||||
|
||||
int linphone_call_start_accept_update(LinphoneCall *call, LinphoneCallState next_state, const char *state_info) {
|
||||
SalMediaDescription *md;
|
||||
|
||||
if ((call->ice_session != NULL) && (ice_session_nb_losing_pairs(call->ice_session) > 0)) {
|
||||
/* Defer the sending of the answer until there are no losing pairs left */
|
||||
return 0;
|
||||
}
|
||||
|
||||
linphone_call_make_local_media_description(call);
|
||||
linphone_call_update_remote_session_id_and_ver(call);
|
||||
sal_call_set_local_media_description(call->op, call->localdesc);
|
||||
sal_call_accept(call->op);
|
||||
md = sal_call_get_final_media_description(call->op);
|
||||
linphone_call_stop_ice_for_inactive_streams(call, md);
|
||||
if (md && !sal_media_description_empty(md)) {
|
||||
linphone_call_update_streams(call, md, next_state);
|
||||
}
|
||||
linphone_call_set_state(call, next_state, state_info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info) {
|
||||
SalMediaDescription *remote_desc;
|
||||
bool_t keep_sdp_version;
|
||||
LinphoneCore *lc = linphone_call_get_core(call);
|
||||
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
|
||||
bool_t old_has_video = call->params->has_video;
|
||||
#endif
|
||||
|
||||
remote_desc = sal_call_get_remote_media_description(call->op);
|
||||
keep_sdp_version = lp_config_get_int(lc->config, "sip", "keep_sdp_version", 0);
|
||||
if (keep_sdp_version && (remote_desc->session_id == call->remote_session_id) && (remote_desc->session_ver == call->remote_session_ver)) {
|
||||
/* Remote has sent an INVITE with the same SDP as before, so send a 200 OK with the same SDP as before. */
|
||||
ms_warning("SDP version has not changed, send same SDP as before.");
|
||||
sal_call_accept(call->op);
|
||||
linphone_call_set_state(call, next_state, state_info);
|
||||
return 0;
|
||||
}
|
||||
if (params == NULL) {
|
||||
if (!sal_call_is_offerer(call->op)) {
|
||||
/* Reset call param for multicast because this param is only relevant when offering */
|
||||
linphone_call_params_enable_audio_multicast(call->params, FALSE);
|
||||
linphone_call_params_enable_video_multicast(call->params, FALSE);
|
||||
}
|
||||
} else {
|
||||
linphone_call_set_new_params(call, params);
|
||||
}
|
||||
|
||||
if (call->params->has_video && !linphone_core_video_enabled(lc)) {
|
||||
ms_warning("Requested video but video support is globally disabled. Refusing video.");
|
||||
call->params->has_video = FALSE;
|
||||
}
|
||||
if (call->current_params->in_conference) {
|
||||
ms_warning("Video isn't supported in conference");
|
||||
call->params->has_video = FALSE;
|
||||
}
|
||||
/* Update multicast params according to call params */
|
||||
linphone_call_fill_media_multicast_addr(call);
|
||||
|
||||
linphone_call_check_ice_session(call, IR_Controlled, TRUE);
|
||||
linphone_call_init_media_streams(call); /* So that video stream is initialized if necessary */
|
||||
if (linphone_call_prepare_ice(call, TRUE) == 1) {
|
||||
return 0; /* Deferred until completion of ICE gathering */
|
||||
}
|
||||
|
||||
#ifdef BUILD_UPNP
|
||||
if (call->upnp_session != NULL) {
|
||||
linphone_call_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(call->op));
|
||||
#ifdef VIDEO_ENABLED
|
||||
if ((call->params->has_video) && (call->params->has_video != old_has_video)) {
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_call_update_upnp(call) < 0) {
|
||||
/* uPnP update failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
} else return 0;
|
||||
}
|
||||
#endif // VIDEO_ENABLED
|
||||
}
|
||||
#endif // BUILD_UPNP
|
||||
|
||||
linphone_call_start_accept_update(call, next_state, state_info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params) {
|
||||
if (call->state != LinphoneCallUpdatedByRemote) {
|
||||
ms_error("linphone_call_accept_update(): invalid state %s to call this function.", linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
}
|
||||
if (call->expect_media_in_ack) {
|
||||
ms_error("linphone_call_accept_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)");
|
||||
return -1;
|
||||
}
|
||||
return _linphone_call_accept_update(call, params, call->prevstate, linphone_call_state_to_string(call->prevstate));
|
||||
}
|
||||
|
||||
int linphone_call_transfer(LinphoneCall *call, const char *refer_to) {
|
||||
char *real_url = NULL;
|
||||
LinphoneCore *lc = linphone_call_get_core(call);
|
||||
LinphoneAddress *real_parsed_url = linphone_core_interpret_url(lc, refer_to);
|
||||
|
||||
if (!real_parsed_url) {
|
||||
/* bad url */
|
||||
return -1;
|
||||
}
|
||||
//lc->call = NULL; // Do not do that you will lose the call afterward...
|
||||
real_url = linphone_address_as_string(real_parsed_url);
|
||||
sal_call_refer(call->op, real_url);
|
||||
ms_free(real_url);
|
||||
linphone_address_unref(real_parsed_url);
|
||||
linphone_call_set_transfer_state(call, LinphoneCallOutgoingInit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_call_transfer_to_another(LinphoneCall *call, LinphoneCall *dest) {
|
||||
int result = sal_call_refer_with_replaces (call->op, dest->op);
|
||||
linphone_call_set_transfer_state(call, LinphoneCallOutgoingInit);
|
||||
return result;
|
||||
}
|
||||
|
||||
int linphone_call_abort(LinphoneCall *call, const char *error) {
|
||||
LinphoneCore *lc = linphone_call_get_core(call);
|
||||
|
||||
sal_call_terminate(call->op);
|
||||
|
||||
/* Stop ringing */
|
||||
linphone_core_stop_ringing(lc);
|
||||
linphone_call_stop_media_streams(call);
|
||||
|
||||
#ifdef BUILD_UPNP
|
||||
linphone_call_delete_upnp_session(call);
|
||||
#endif // BUILD_UPNP
|
||||
|
||||
linphone_core_notify_display_status(lc, _("Call aborted"));
|
||||
linphone_call_set_state(call, LinphoneCallError, error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_call_proceed_with_invite_if_ready(LinphoneCall *call, LinphoneProxyConfig *dest_proxy) {
|
||||
bool_t ice_ready = FALSE;
|
||||
bool_t upnp_ready = FALSE;
|
||||
bool_t ping_ready = FALSE;
|
||||
|
||||
if (call->ice_session != NULL) {
|
||||
if (ice_session_candidates_gathered(call->ice_session)) ice_ready = TRUE;
|
||||
} else {
|
||||
ice_ready = TRUE;
|
||||
}
|
||||
#ifdef BUILD_UPNP
|
||||
if (call->upnp_session != NULL) {
|
||||
if (linphone_upnp_session_get_state(call->upnp_session) == LinphoneUpnpStateOk) upnp_ready = TRUE;
|
||||
} else {
|
||||
upnp_ready = TRUE;
|
||||
}
|
||||
#else
|
||||
upnp_ready=TRUE;
|
||||
#endif // BUILD_UPNP
|
||||
if (call->ping_op != NULL) {
|
||||
if (call->ping_replied == TRUE) ping_ready = TRUE;
|
||||
} else {
|
||||
ping_ready = TRUE;
|
||||
}
|
||||
|
||||
if ((ice_ready == TRUE) && (upnp_ready == TRUE) && (ping_ready == TRUE)) {
|
||||
return linphone_call_start_invite(call, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_call_start_invite(LinphoneCall *call, const LinphoneAddress *destination /* = NULL if to be taken from the call log */) {
|
||||
int err;
|
||||
char *real_url, *barmsg;
|
||||
char *from;
|
||||
LinphoneCore *lc = linphone_call_get_core(call);
|
||||
|
||||
/* Try to be best-effort in giving real local or routable contact address */
|
||||
linphone_call_set_contact_op(call);
|
||||
|
||||
linphone_core_stop_dtmf_stream(lc);
|
||||
linphone_call_make_local_media_description(call);
|
||||
|
||||
if (lc->ringstream == NULL) {
|
||||
if (lc->sound_conf.play_sndcard && lc->sound_conf.capt_sndcard) {
|
||||
/* Give a chance a set card prefered sampling frequency */
|
||||
if (call->localdesc->streams[0].max_rate > 0) {
|
||||
ms_snd_card_set_preferred_sample_rate(lc->sound_conf.play_sndcard, call->localdesc->streams[0].max_rate);
|
||||
}
|
||||
if (!lc->use_files) {
|
||||
audio_stream_prepare_sound(call->audiostream, lc->sound_conf.play_sndcard, lc->sound_conf.capt_sndcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
real_url = linphone_address_as_string(destination ? destination : call->log->to);
|
||||
from = linphone_address_as_string(call->log->from);
|
||||
|
||||
if (!lc->sip_conf.sdp_200_ack) {
|
||||
/* We are offering, set local media description before sending the call */
|
||||
sal_call_set_local_media_description(call->op, call->localdesc);
|
||||
}
|
||||
|
||||
barmsg = ms_strdup_printf("%s %s", _("Contacting"), real_url);
|
||||
linphone_core_notify_display_status(lc, barmsg);
|
||||
ms_free(barmsg);
|
||||
|
||||
linphone_call_ref(call); /* Take a ref because sal_call() may destroy the call if no SIP transport is available */
|
||||
err = sal_call(call->op, from, real_url);
|
||||
|
||||
if (err < 0) {
|
||||
if ((call->state != LinphoneCallError) && (call->state != LinphoneCallReleased)) {
|
||||
/* sal_call() may invoke call_failure() and call_released() SAL callbacks synchronously,
|
||||
in which case there is no need to perform a state change here. */
|
||||
linphone_core_notify_display_status(lc, _("Could not call"));
|
||||
linphone_call_stop_media_streams(call);
|
||||
linphone_call_set_state(call, LinphoneCallError, "Call failed");
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (lc->sip_conf.sdp_200_ack) {
|
||||
/* We are NOT offering, set local media description after sending the call so that we are ready to
|
||||
process the remote offer when it will arrive. */
|
||||
sal_call_set_local_media_description(call->op, call->localdesc);
|
||||
}
|
||||
call->log->call_id = ms_strdup(sal_op_get_call_id(call->op)); /* Must be known at that time */
|
||||
linphone_call_set_state(call, LinphoneCallOutgoingProgress, "Outgoing call in progress");
|
||||
|
||||
end:
|
||||
linphone_call_unref(call); /* Revert the ref taken before calling sal_call() */
|
||||
ms_free(real_url);
|
||||
ms_free(from);
|
||||
return err;
|
||||
}
|
||||
|
||||
int linphone_call_restart_invite(LinphoneCall *call) {
|
||||
linphone_call_create_op(call);
|
||||
linphone_call_stop_media_streams(call);
|
||||
ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]);
|
||||
ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]);
|
||||
ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]);
|
||||
linphone_call_init_media_streams(call);
|
||||
return linphone_call_start_invite(call, NULL);
|
||||
}
|
||||
|
||||
void linphone_call_set_broken(LinphoneCall *call){
|
||||
switch(call->state){
|
||||
/*for all the early states, we prefer to drop the call*/
|
||||
|
|
@ -4954,7 +5682,7 @@ static void linphone_call_repair_by_invite_with_replaces(LinphoneCall *call) {
|
|||
sal_op_kill_dialog(call->op);
|
||||
linphone_call_create_op(call);
|
||||
sal_call_set_replaces(call->op, call_id, from_tag, to_tag);
|
||||
linphone_core_start_invite(call->core, call, NULL);
|
||||
linphone_call_start_invite(call, NULL);
|
||||
}
|
||||
|
||||
void linphone_call_reinvite_to_recover_from_connection_loss(LinphoneCall *call) {
|
||||
|
|
|
|||
|
|
@ -2806,7 +2806,7 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
elapsed = (int)(current_real_time - call->log->start_date_time);
|
||||
/* get immediately a reference to next one in case the one
|
||||
we are going to examine is destroy and removed during
|
||||
linphone_core_start_invite() */
|
||||
linphone_call_start_invite() */
|
||||
calls=calls->next;
|
||||
linphone_call_background_tasks(call,one_second_elapsed);
|
||||
if (call->state==LinphoneCallOutgoingInit && (elapsed>=lc->sip_conf.delayed_timeout)){
|
||||
|
|
@ -2823,7 +2823,7 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
linphone_call_delete_upnp_session(call);
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
linphone_core_start_invite(lc,call, NULL);
|
||||
linphone_call_start_invite(call, NULL);
|
||||
}
|
||||
if (call->state==LinphoneCallIncomingReceived || call->state==LinphoneCallIncomingEarlyMedia){
|
||||
if (one_second_elapsed) ms_message("incoming call ringing for %i seconds",elapsed);
|
||||
|
|
@ -2920,7 +2920,7 @@ LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *
|
|||
|
||||
if (call->state!=LinphoneCallPaused){
|
||||
ms_message("Automatically pausing current call to accept transfer.");
|
||||
_linphone_core_pause_call(lc,call);
|
||||
_linphone_call_pause(call);
|
||||
call->was_automatically_paused=TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -3038,109 +3038,6 @@ const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAdd
|
|||
return linphone_core_get_primary_contact(lc);
|
||||
}
|
||||
|
||||
|
||||
int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy){
|
||||
bool_t ice_ready = FALSE;
|
||||
bool_t upnp_ready = FALSE;
|
||||
bool_t ping_ready = FALSE;
|
||||
|
||||
if (call->ice_session != NULL) {
|
||||
if (ice_session_candidates_gathered(call->ice_session)) ice_ready = TRUE;
|
||||
} else {
|
||||
ice_ready = TRUE;
|
||||
}
|
||||
#ifdef BUILD_UPNP
|
||||
if (call->upnp_session != NULL) {
|
||||
if (linphone_upnp_session_get_state(call->upnp_session) == LinphoneUpnpStateOk) upnp_ready = TRUE;
|
||||
} else {
|
||||
upnp_ready = TRUE;
|
||||
}
|
||||
#else
|
||||
upnp_ready=TRUE;
|
||||
#endif //BUILD_UPNP
|
||||
if (call->ping_op != NULL) {
|
||||
if (call->ping_replied == TRUE) ping_ready = TRUE;
|
||||
} else {
|
||||
ping_ready = TRUE;
|
||||
}
|
||||
|
||||
if ((ice_ready == TRUE) && (upnp_ready == TRUE) && (ping_ready == TRUE)) {
|
||||
return linphone_core_start_invite(lc, call, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_core_restart_invite(LinphoneCore *lc, LinphoneCall *call){
|
||||
linphone_call_create_op(call);
|
||||
linphone_call_stop_media_streams(call);
|
||||
ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]);
|
||||
ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]);
|
||||
ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]);
|
||||
linphone_call_init_media_streams(call);
|
||||
return linphone_core_start_invite(lc,call, NULL);
|
||||
}
|
||||
|
||||
int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const LinphoneAddress* destination /* = NULL if to be taken from the call log */){
|
||||
int err;
|
||||
char *real_url,*barmsg;
|
||||
char *from;
|
||||
/*try to be best-effort in giving real local or routable contact address */
|
||||
linphone_call_set_contact_op(call);
|
||||
|
||||
linphone_core_stop_dtmf_stream(lc);
|
||||
linphone_call_make_local_media_description(call);
|
||||
|
||||
if (lc->ringstream==NULL) {
|
||||
if (lc->sound_conf.play_sndcard && lc->sound_conf.capt_sndcard){
|
||||
/*give a chance a set card prefered sampling frequency*/
|
||||
if (call->localdesc->streams[0].max_rate>0) {
|
||||
ms_snd_card_set_preferred_sample_rate(lc->sound_conf.play_sndcard, call->localdesc->streams[0].max_rate);
|
||||
}
|
||||
if (!lc->use_files)
|
||||
audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard);
|
||||
}
|
||||
}
|
||||
real_url=linphone_address_as_string( destination ? destination : call->log->to);
|
||||
from=linphone_address_as_string(call->log->from);
|
||||
|
||||
if (!lc->sip_conf.sdp_200_ack){
|
||||
/*we are offering, set local media description before sending the call*/
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
}
|
||||
|
||||
barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url);
|
||||
linphone_core_notify_display_status(lc,barmsg);
|
||||
ms_free(barmsg);
|
||||
|
||||
linphone_call_ref(call); /* Take a ref because sal_call() may destroy the call if no SIP transport is available */
|
||||
err=sal_call(call->op,from,real_url);
|
||||
|
||||
if (err < 0){
|
||||
if (call->state != LinphoneCallError &&
|
||||
call->state != LinphoneCallReleased){
|
||||
/*sal_call() may invoke call_failure() and call_released() SAL callbacks synchronously,
|
||||
* in which case there is no need to perform a state change here.*/
|
||||
linphone_core_notify_display_status(lc,_("Could not call"));
|
||||
linphone_call_stop_media_streams(call);
|
||||
linphone_call_set_state(call,LinphoneCallError,"Call failed");
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (lc->sip_conf.sdp_200_ack){
|
||||
/*we are NOT offering, set local media description after sending the call so that we are ready to
|
||||
process the remote offer when it will arrive*/
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
}
|
||||
call->log->call_id=ms_strdup(sal_op_get_call_id(call->op)); /*must be known at that time*/
|
||||
linphone_call_set_state(call,LinphoneCallOutgoingProgress,"Outgoing call in progress");
|
||||
|
||||
end:
|
||||
linphone_call_unref(call); /* Revert the ref taken before calling sal_call() */
|
||||
ms_free(real_url);
|
||||
ms_free(from);
|
||||
return err;
|
||||
}
|
||||
|
||||
LinphoneCall * linphone_core_invite(LinphoneCore *lc, const char *url){
|
||||
LinphoneCall *call;
|
||||
LinphoneCallParams *p=linphone_core_create_call_params(lc, NULL);
|
||||
|
|
@ -3279,13 +3176,13 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
}
|
||||
else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
|
||||
#ifdef BUILD_UPNP
|
||||
if (linphone_core_update_upnp(lc,call)<0) {
|
||||
if (linphone_call_update_upnp(call) < 0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
} else {
|
||||
defer = TRUE;
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
#endif // BUILD_UPNP
|
||||
}
|
||||
|
||||
if (call->dest_proxy==NULL && lc->sip_conf.ping_with_options==TRUE){
|
||||
|
|
@ -3305,7 +3202,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
}
|
||||
|
||||
if (defer==FALSE) {
|
||||
if (linphone_core_start_invite(lc,call,NULL) != 0){
|
||||
if (linphone_call_start_invite(call,NULL) != 0){
|
||||
/*the call has already gone to error and released state, so do not return it*/
|
||||
call = NULL;
|
||||
}
|
||||
|
|
@ -3317,30 +3214,15 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
}
|
||||
|
||||
int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char *url) {
|
||||
char *real_url=NULL;
|
||||
LinphoneAddress *real_parsed_url=linphone_core_interpret_url(lc,url);
|
||||
|
||||
if (!real_parsed_url){
|
||||
/* bad url */
|
||||
return -1;
|
||||
}
|
||||
if (call==NULL){
|
||||
if (call == NULL) {
|
||||
ms_warning("No established call to refer.");
|
||||
return -1;
|
||||
}
|
||||
//lc->call=NULL; //Do not do that you will lose the call afterward . . .
|
||||
real_url=linphone_address_as_string (real_parsed_url);
|
||||
sal_call_refer(call->op,real_url);
|
||||
ms_free(real_url);
|
||||
linphone_address_unref(real_parsed_url);
|
||||
linphone_call_set_transfer_state(call, LinphoneCallOutgoingInit);
|
||||
return 0;
|
||||
return linphone_call_transfer(call, url);
|
||||
}
|
||||
|
||||
int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call, LinphoneCall *dest){
|
||||
int result = sal_call_refer_with_replaces (call->op,dest->op);
|
||||
linphone_call_set_transfer_state(call, LinphoneCallOutgoingInit);
|
||||
return result;
|
||||
int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call, LinphoneCall *dest) {
|
||||
return linphone_call_transfer_to_another(call, dest);
|
||||
}
|
||||
|
||||
bool_t linphone_core_is_incoming_invite_pending(LinphoneCore*lc){
|
||||
|
|
@ -3413,509 +3295,62 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
|
|||
ms_free(tmp);
|
||||
}
|
||||
|
||||
int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* call, const LinphoneCallParams* params) {
|
||||
if (call->state==LinphoneCallIncomingReceived){
|
||||
SalMediaDescription* md;
|
||||
|
||||
/*try to be best-effort in giving real local or routable contact address for 100Rel case*/
|
||||
linphone_call_set_contact_op(call);
|
||||
|
||||
// if parameters are passed, update the media description
|
||||
if ( params ) {
|
||||
linphone_call_set_new_params(call,params);
|
||||
linphone_call_make_local_media_description (call);
|
||||
sal_call_set_local_media_description ( call->op,call->localdesc );
|
||||
sal_op_set_sent_custom_header ( call->op,params->custom_headers );
|
||||
}
|
||||
|
||||
sal_call_notify_ringing(call->op, TRUE);
|
||||
|
||||
linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
if (md) linphone_core_update_streams(lc, call, md, call->state);
|
||||
return 0;
|
||||
}else{
|
||||
ms_error("Bad state %s for linphone_core_accept_early_media_with_params()", linphone_call_state_to_string(call->state));
|
||||
}
|
||||
|
||||
return -1;
|
||||
int linphone_core_accept_early_media_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) {
|
||||
return linphone_call_accept_early_media_with_params(call, params);
|
||||
}
|
||||
|
||||
int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call){
|
||||
return linphone_core_accept_early_media_with_params(lc, call, NULL);
|
||||
int linphone_core_accept_early_media(LinphoneCore *lc, LinphoneCall *call) {
|
||||
return linphone_call_accept_early_media(call);
|
||||
}
|
||||
|
||||
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
|
||||
const char *subject;
|
||||
int err;
|
||||
bool_t no_user_consent=call->params->no_user_consent;
|
||||
|
||||
linphone_call_fill_media_multicast_addr(call);
|
||||
|
||||
if (!no_user_consent) linphone_call_make_local_media_description(call);
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
if (call->params->in_conference){
|
||||
subject="Conference";
|
||||
}else if (call->params->internal_call_update){
|
||||
subject="ICE processing concluded";
|
||||
}else if (no_user_consent){
|
||||
subject="Refreshing";
|
||||
}else{
|
||||
subject="Media change";
|
||||
}
|
||||
linphone_core_notify_display_status(lc,_("Modifying call parameters..."));
|
||||
if (!lc->sip_conf.sdp_200_ack){
|
||||
sal_call_set_local_media_description (call->op,call->localdesc);
|
||||
} else {
|
||||
sal_call_set_local_media_description (call->op,NULL);
|
||||
}
|
||||
if (call->dest_proxy && call->dest_proxy->op){
|
||||
/*give a chance to update the contact address if connectivity has changed*/
|
||||
sal_op_set_contact_address(call->op,sal_op_get_contact_address(call->dest_proxy->op));
|
||||
}else sal_op_set_contact_address(call->op,NULL);
|
||||
err= sal_call_update(call->op,subject,no_user_consent);
|
||||
if (lc->sip_conf.sdp_200_ack){
|
||||
/*we are NOT offering, set local media description after sending the call so that we are ready to
|
||||
process the remote offer when it will arrive*/
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
}
|
||||
return err;
|
||||
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) {
|
||||
return linphone_call_update(call, params);
|
||||
}
|
||||
|
||||
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
|
||||
int err=0;
|
||||
LinphoneCallState nextstate, initial_state;
|
||||
const LinphoneCallParams *current_params;
|
||||
|
||||
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
|
||||
bool_t has_video = FALSE;
|
||||
#endif
|
||||
|
||||
switch(initial_state=call->state){
|
||||
case LinphoneCallIncomingReceived:
|
||||
case LinphoneCallIncomingEarlyMedia:
|
||||
case LinphoneCallOutgoingRinging:
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
nextstate=LinphoneCallEarlyUpdating;
|
||||
break;
|
||||
case LinphoneCallStreamsRunning:
|
||||
case LinphoneCallPausedByRemote:
|
||||
case LinphoneCallUpdatedByRemote:
|
||||
nextstate=LinphoneCallUpdating;
|
||||
break;
|
||||
case LinphoneCallPaused:
|
||||
nextstate=LinphoneCallPausing;
|
||||
break;
|
||||
case LinphoneCallOutgoingProgress:
|
||||
case LinphoneCallPausing:
|
||||
case LinphoneCallResuming:
|
||||
case LinphoneCallUpdating:
|
||||
nextstate=call->state;
|
||||
break;
|
||||
default:
|
||||
ms_error("linphone_core_update_call() is not allowed in [%s] state",linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
}
|
||||
|
||||
current_params = linphone_call_get_current_params(call);
|
||||
if ((current_params != NULL) && (current_params == params)) {
|
||||
ms_warning("linphone_core_update_call() is given the current params of the call, this probably not what you intend to do!");
|
||||
}
|
||||
|
||||
linphone_call_check_ice_session(call, IR_Controlling, TRUE);
|
||||
|
||||
if (params!=NULL){
|
||||
call->broken = FALSE;
|
||||
linphone_call_set_state(call,nextstate,"Updating call");
|
||||
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
|
||||
has_video = call->params->has_video;
|
||||
|
||||
// Video removing
|
||||
if((call->videostream != NULL) && !params->has_video) {
|
||||
if(call->upnp_session != NULL) {
|
||||
if (linphone_core_update_upnp(lc, call)<0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */
|
||||
linphone_call_set_new_params(call,params);
|
||||
err=linphone_call_prepare_ice(call,FALSE);
|
||||
if (err==1) {
|
||||
ms_message("Defer call update to gather ICE candidates");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
|
||||
// Video adding
|
||||
if (!has_video && call->params->has_video) {
|
||||
if(call->upnp_session != NULL) {
|
||||
ms_message("Defer call update to add uPnP port mappings");
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_core_update_upnp(lc, call)<0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
} else {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
|
||||
if ((err = linphone_core_start_update_call(lc, call)) && call->state!=initial_state) {
|
||||
/*Restore initial state*/
|
||||
linphone_call_set_state(call,initial_state,"Restore initial state");
|
||||
}
|
||||
|
||||
}else{
|
||||
#ifdef VIDEO_ENABLED
|
||||
if ((call->videostream != NULL) && (call->state == LinphoneCallStreamsRunning)) {
|
||||
video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
|
||||
video_stream_set_fps(call->videostream, linphone_core_get_preferred_framerate(lc));
|
||||
if (call->camera_enabled && call->videostream->cam!=lc->video_conf.device){
|
||||
video_stream_change_camera(call->videostream, lc->video_conf.device);
|
||||
}else video_stream_update_video_params(call->videostream);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return err;
|
||||
int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call) {
|
||||
return linphone_call_defer_update(call);
|
||||
}
|
||||
|
||||
int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){
|
||||
if (call->state==LinphoneCallUpdatedByRemote){
|
||||
if (call->expect_media_in_ack){
|
||||
ms_error("linphone_core_defer_call_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)");
|
||||
return -1;
|
||||
}
|
||||
call->defer_update=TRUE;
|
||||
return 0;
|
||||
}else{
|
||||
ms_error("linphone_core_defer_call_update() not done in state LinphoneCallUpdatedByRemote");
|
||||
}
|
||||
return -1;
|
||||
int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) {
|
||||
return linphone_call_accept_update(call, params);
|
||||
}
|
||||
|
||||
int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState next_state, const char *state_info){
|
||||
SalMediaDescription *md;
|
||||
if (call->ice_session != NULL) {
|
||||
if (ice_session_nb_losing_pairs(call->ice_session) > 0) {
|
||||
/* Defer the sending of the answer until there are no losing pairs left. */
|
||||
return 0;
|
||||
}
|
||||
static LinphoneCall * get_unique_call(LinphoneCore *lc) {
|
||||
LinphoneCall *call = linphone_core_get_current_call(lc);
|
||||
if ((call == NULL) && (linphone_core_get_calls_nb(lc) == 1)) {
|
||||
call = (LinphoneCall *)bctbx_list_get_data(linphone_core_get_calls(lc));
|
||||
}
|
||||
linphone_call_make_local_media_description(call);
|
||||
|
||||
linphone_call_update_remote_session_id_and_ver(call);
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
sal_call_accept(call->op);
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
linphone_call_stop_ice_for_inactive_streams(call, md);
|
||||
if (md && !sal_media_description_empty(md)){
|
||||
linphone_core_update_streams(lc, call, md, next_state);
|
||||
}
|
||||
linphone_call_set_state(call,next_state,state_info);
|
||||
return 0;
|
||||
return call;
|
||||
}
|
||||
|
||||
int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
|
||||
if (call->state != LinphoneCallUpdatedByRemote){
|
||||
ms_error("linphone_core_accept_update(): invalid state %s to call this function.",
|
||||
linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
}
|
||||
if (call->expect_media_in_ack){
|
||||
ms_error("linphone_core_accept_call_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)");
|
||||
return -1;
|
||||
}
|
||||
return _linphone_core_accept_call_update(lc, call, params, call->prevstate, linphone_call_state_to_string(call->prevstate));
|
||||
int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) {
|
||||
return linphone_core_accept_call_with_params(lc, call, NULL);
|
||||
}
|
||||
|
||||
int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info){
|
||||
SalMediaDescription *remote_desc;
|
||||
bool_t keep_sdp_version;
|
||||
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
|
||||
bool_t old_has_video = call->params->has_video;
|
||||
#endif
|
||||
|
||||
remote_desc = sal_call_get_remote_media_description(call->op);
|
||||
keep_sdp_version = lp_config_get_int(lc->config, "sip", "keep_sdp_version", 0);
|
||||
if (keep_sdp_version &&(remote_desc->session_id == call->remote_session_id) && (remote_desc->session_ver == call->remote_session_ver)) {
|
||||
/* Remote has sent an INVITE with the same SDP as before, so send a 200 OK with the same SDP as before. */
|
||||
ms_warning("SDP version has not changed, send same SDP as before.");
|
||||
sal_call_accept(call->op);
|
||||
linphone_call_set_state(call,next_state,state_info);
|
||||
return 0;
|
||||
}
|
||||
if (params==NULL){
|
||||
if (!sal_call_is_offerer(call->op)) {
|
||||
/*reset call param for multicast because this param is only relevant when offering*/
|
||||
linphone_call_params_enable_audio_multicast(call->params,FALSE);
|
||||
linphone_call_params_enable_video_multicast(call->params,FALSE);
|
||||
}
|
||||
}else
|
||||
linphone_call_set_new_params(call,params);
|
||||
|
||||
if (call->params->has_video && !linphone_core_video_enabled(lc)){
|
||||
ms_warning("linphone_core_accept_call_update(): requested video but video support is globally disabled. Refusing video.");
|
||||
call->params->has_video=FALSE;
|
||||
}
|
||||
if (call->current_params->in_conference) {
|
||||
ms_warning("Video isn't supported in conference");
|
||||
call->params->has_video = FALSE;
|
||||
}
|
||||
/*update multicast params according to call params*/
|
||||
linphone_call_fill_media_multicast_addr(call);
|
||||
|
||||
linphone_call_check_ice_session(call, IR_Controlled, TRUE);
|
||||
linphone_call_init_media_streams(call); /*so that video stream is initialized if necessary*/
|
||||
if (linphone_call_prepare_ice(call,TRUE)==1)
|
||||
return 0;/*deferred to completion of ICE gathering*/
|
||||
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(call->op));
|
||||
#ifdef VIDEO_ENABLED
|
||||
if ((call->params->has_video) && (call->params->has_video != old_has_video)) {
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_core_update_upnp(lc, call)<0) {
|
||||
/* uPnP update failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
} else return 0;
|
||||
}
|
||||
#endif //VIDEO_ENABLED
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
|
||||
linphone_core_start_accept_call_update(lc, call, next_state, state_info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call){
|
||||
return linphone_core_accept_call_with_params(lc,call,NULL);
|
||||
}
|
||||
|
||||
int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
|
||||
SalOp *replaced;
|
||||
SalMediaDescription *new_md;
|
||||
bool_t was_ringing=FALSE;
|
||||
bctbx_list_t * iterator, *copy;
|
||||
|
||||
if (call==NULL){
|
||||
//if just one call is present answer the only one ...
|
||||
if(linphone_core_get_calls_nb (lc) != 1)
|
||||
return -1;
|
||||
else
|
||||
call = (LinphoneCall*)linphone_core_get_calls(lc)->data;
|
||||
}
|
||||
|
||||
switch(call->state){
|
||||
case LinphoneCallIncomingReceived:
|
||||
case LinphoneCallIncomingEarlyMedia:
|
||||
break;
|
||||
default:
|
||||
ms_error("linphone_core_accept_call_with_params() call [%p] is in state [%s], operation not permitted.",
|
||||
call, linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
for (iterator=copy=bctbx_list_copy(linphone_core_get_calls(lc));iterator!=NULL;iterator=iterator->next) {
|
||||
LinphoneCall *a_call=(LinphoneCall*)iterator->data;
|
||||
if (a_call==call) continue;
|
||||
switch(a_call->state){
|
||||
case LinphoneCallOutgoingInit:
|
||||
case LinphoneCallOutgoingProgress:
|
||||
case LinphoneCallOutgoingRinging:
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
ms_message("Already existing call [%p] in state [%s], canceling it before accepting new call [%p]",a_call
|
||||
,linphone_call_state_to_string(a_call->state)
|
||||
,call);
|
||||
linphone_core_terminate_call(lc,a_call);
|
||||
break;
|
||||
default:
|
||||
break; /*nothing to do*/
|
||||
}
|
||||
}
|
||||
bctbx_list_free(copy);
|
||||
|
||||
/* check if this call is supposed to replace an already running one*/
|
||||
replaced=sal_call_get_replaces(call->op);
|
||||
if (replaced){
|
||||
LinphoneCall *rc=(LinphoneCall*)sal_op_get_user_pointer (replaced);
|
||||
if (rc){
|
||||
ms_message("Call %p replaces call %p. This last one is going to be terminated automatically.",
|
||||
call,rc);
|
||||
linphone_core_terminate_call(lc,rc);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*try to be best-effort in giving real local or routable contact address */
|
||||
linphone_call_set_contact_op(call);
|
||||
if (params){
|
||||
linphone_call_set_new_params(call,params);
|
||||
linphone_call_prepare_ice(call,TRUE);
|
||||
linphone_call_make_local_media_description(call);
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
sal_op_set_sent_custom_header(call->op,params->custom_headers);
|
||||
}
|
||||
|
||||
/*give a chance a set card prefered sampling frequency*/
|
||||
if (call->localdesc->streams[0].max_rate>0) {
|
||||
ms_message ("configuring prefered card sampling rate to [%i]",call->localdesc->streams[0].max_rate);
|
||||
if (lc->sound_conf.play_sndcard)
|
||||
ms_snd_card_set_preferred_sample_rate(lc->sound_conf.play_sndcard, call->localdesc->streams[0].max_rate);
|
||||
if (lc->sound_conf.capt_sndcard)
|
||||
ms_snd_card_set_preferred_sample_rate(lc->sound_conf.capt_sndcard, call->localdesc->streams[0].max_rate);
|
||||
}
|
||||
|
||||
if (!was_ringing && call->audiostream->ms.state==MSStreamInitialized && !lc->use_files){
|
||||
audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard);
|
||||
}
|
||||
|
||||
linphone_call_update_remote_session_id_and_ver(call);
|
||||
|
||||
sal_call_accept(call->op);
|
||||
linphone_core_notify_display_status(lc,_("Connected."));
|
||||
lc->current_call=call;
|
||||
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
|
||||
new_md=sal_call_get_final_media_description(call->op);
|
||||
linphone_call_stop_ice_for_inactive_streams(call, new_md);
|
||||
if (new_md){
|
||||
linphone_core_update_streams(lc, call, new_md, LinphoneCallStreamsRunning);
|
||||
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}else call->expect_media_in_ack=TRUE;
|
||||
|
||||
ms_message("call answered.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error){
|
||||
sal_call_terminate(call->op);
|
||||
|
||||
/*stop ringing*/
|
||||
linphone_core_stop_ringing(lc);
|
||||
linphone_call_stop_media_streams(call);
|
||||
|
||||
#ifdef BUILD_UPNP
|
||||
linphone_call_delete_upnp_session(call);
|
||||
#endif //BUILD_UPNP
|
||||
|
||||
linphone_core_notify_display_status(lc,_("Call aborted") );
|
||||
linphone_call_set_state(call,LinphoneCallError,error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void terminate_call(LinphoneCore *lc, LinphoneCall *call){
|
||||
if (call->state==LinphoneCallIncomingReceived){
|
||||
if (call->non_op_error.reason!=SalReasonRequestTimeout)
|
||||
call->non_op_error.reason=SalReasonDeclined;
|
||||
}
|
||||
/*stop ringing*/
|
||||
linphone_core_stop_ringing(lc);
|
||||
|
||||
linphone_call_stop_media_streams(call);
|
||||
|
||||
#ifdef BUILD_UPNP
|
||||
linphone_call_delete_upnp_session(call);
|
||||
#endif //BUILD_UPNP
|
||||
|
||||
linphone_core_notify_display_status(lc,_("Call ended") );
|
||||
linphone_call_set_state(call,LinphoneCallEnd,"Call terminated");
|
||||
}
|
||||
|
||||
int linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char *redirect_uri){
|
||||
|
||||
if (call->state==LinphoneCallIncomingReceived){
|
||||
char *real_url=NULL;
|
||||
LinphoneAddress *real_parsed_url=linphone_core_interpret_url(lc,redirect_uri);
|
||||
if (!real_parsed_url){
|
||||
/* bad url */
|
||||
ms_error("Bad redirect URI: %s", redirect_uri?redirect_uri:"NULL");
|
||||
return -1;
|
||||
}
|
||||
real_url=linphone_address_as_string (real_parsed_url);
|
||||
sal_call_decline(call->op,SalReasonRedirect,real_url);
|
||||
ms_free(real_url);
|
||||
sal_error_info_set(&call->non_op_error,SalReasonRedirect,603,"Call redirected",NULL);
|
||||
terminate_call(lc,call);
|
||||
linphone_address_unref(real_parsed_url);
|
||||
}else{
|
||||
ms_error("Bad state for call redirection.");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call) {
|
||||
LinphoneCall *call;
|
||||
if (the_call == NULL){
|
||||
call = linphone_core_get_current_call(lc);
|
||||
if (bctbx_list_size(lc->calls)==1){
|
||||
call=(LinphoneCall*)lc->calls->data;
|
||||
}else{
|
||||
ms_warning("No unique call to terminate !");
|
||||
int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) {
|
||||
if (call == NULL) {
|
||||
call = get_unique_call(lc);
|
||||
if (call == NULL) {
|
||||
ms_warning("No unique call to accept!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
call = the_call;
|
||||
}
|
||||
ms_message("Terminate call [%p] which is currently in state %s", call, linphone_call_state_to_string(call->state));
|
||||
switch (call->state) {
|
||||
case LinphoneCallReleased:
|
||||
case LinphoneCallEnd:
|
||||
case LinphoneCallError:
|
||||
ms_warning("No need to terminate a call [%p] in state [%s]",call,linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
case LinphoneCallIncomingReceived:
|
||||
case LinphoneCallIncomingEarlyMedia:
|
||||
return linphone_core_decline_call(lc,call,LinphoneReasonDeclined);
|
||||
case LinphoneCallOutgoingInit: {
|
||||
/* In state OutgoingInit, op has to be destroyed */
|
||||
sal_op_release(call->op);
|
||||
call->op = NULL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sal_call_terminate(call->op);
|
||||
break;
|
||||
}
|
||||
terminate_call(lc,call);
|
||||
return 0;
|
||||
return linphone_call_accept_with_params(call, params);
|
||||
}
|
||||
|
||||
int linphone_core_decline_call(LinphoneCore *lc, LinphoneCall * call, LinphoneReason reason){
|
||||
if (call->state!=LinphoneCallIncomingReceived && call->state!=LinphoneCallIncomingEarlyMedia){
|
||||
ms_error("linphone_core_decline_call(): Cannot decline a call that is in state %s",linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
}
|
||||
int linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char *redirect_uri) {
|
||||
return linphone_call_redirect(call, redirect_uri);
|
||||
}
|
||||
|
||||
sal_call_decline(call->op,linphone_reason_to_sal(reason),NULL);
|
||||
terminate_call(lc,call);
|
||||
return 0;
|
||||
int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *call) {
|
||||
if (call == NULL) {
|
||||
call = get_unique_call(lc);
|
||||
if (call == NULL) {
|
||||
ms_warning("No unique call to terminate!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return linphone_call_terminate(call);
|
||||
}
|
||||
|
||||
int linphone_core_terminate_all_calls(LinphoneCore *lc){
|
||||
|
|
@ -3928,6 +3363,10 @@ int linphone_core_terminate_all_calls(LinphoneCore *lc){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int linphone_core_decline_call(LinphoneCore *lc, LinphoneCall *call, LinphoneReason reason) {
|
||||
return linphone_call_decline(call, reason);
|
||||
}
|
||||
|
||||
const bctbx_list_t *linphone_core_get_calls(LinphoneCore *lc) {
|
||||
return lc->calls;
|
||||
}
|
||||
|
|
@ -3940,46 +3379,8 @@ LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc){
|
|||
return lc->current_call;
|
||||
}
|
||||
|
||||
int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call){
|
||||
int err=_linphone_core_pause_call(lc,call);
|
||||
if (err==0) call->paused_by_app=TRUE;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Internal version that does not play tone indication*/
|
||||
int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call){
|
||||
const char *subject=NULL;
|
||||
|
||||
if (call->state!=LinphoneCallStreamsRunning && call->state!=LinphoneCallPausedByRemote){
|
||||
ms_warning("Cannot pause this call, it is not active.");
|
||||
return -1;
|
||||
}
|
||||
if (sal_media_description_has_dir(call->resultdesc, SalStreamSendRecv)) {
|
||||
subject = "Call on hold";
|
||||
} else if (sal_media_description_has_dir(call->resultdesc, SalStreamRecvOnly)) {
|
||||
subject = "Call on hold for me too";
|
||||
} else {
|
||||
ms_error("No reason to pause this call, it is already paused or inactive.");
|
||||
return -1;
|
||||
}
|
||||
call->broken = FALSE;
|
||||
linphone_call_set_state(call, LinphoneCallPausing, "Pausing call");
|
||||
linphone_call_make_local_media_description(call);
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
if (sal_call_update(call->op,subject,FALSE) != 0){
|
||||
linphone_core_notify_display_warning(lc,_("Could not pause the call"));
|
||||
}
|
||||
lc->current_call=NULL;
|
||||
linphone_core_notify_display_status(lc,_("Pausing the current call..."));
|
||||
if (call->audiostream || call->videostream || call->textstream)
|
||||
linphone_call_stop_media_streams (call);
|
||||
call->paused_by_app=FALSE;
|
||||
return 0;
|
||||
int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call) {
|
||||
return linphone_call_pause(call);
|
||||
}
|
||||
|
||||
int linphone_core_pause_all_calls(LinphoneCore *lc){
|
||||
|
|
@ -3988,7 +3389,7 @@ int linphone_core_pause_all_calls(LinphoneCore *lc){
|
|||
LinphoneCall *call=(LinphoneCall *)elem->data;
|
||||
LinphoneCallState cs=linphone_call_get_state(call);
|
||||
if (cs==LinphoneCallStreamsRunning || cs==LinphoneCallPausedByRemote){
|
||||
_linphone_core_pause_call(lc,call);
|
||||
_linphone_call_pause(call);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -4006,7 +3407,7 @@ int linphone_core_preempt_sound_resources(LinphoneCore *lc){
|
|||
current_call=linphone_core_get_current_call(lc);
|
||||
if(current_call != NULL){
|
||||
ms_message("Pausing automatically the current call.");
|
||||
err = _linphone_core_pause_call(lc,current_call);
|
||||
err = _linphone_call_pause(current_call);
|
||||
}
|
||||
if (lc->ringstream){
|
||||
linphone_core_stop_ringing(lc);
|
||||
|
|
@ -4014,60 +3415,8 @@ int linphone_core_preempt_sound_resources(LinphoneCore *lc){
|
|||
return err;
|
||||
}
|
||||
|
||||
int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){
|
||||
char temp[255]={0};
|
||||
const char *subject="Call resuming";
|
||||
char *tmp;
|
||||
|
||||
if(call->state!=LinphoneCallPaused ){
|
||||
ms_warning("we cannot resume a call that has not been established and paused before");
|
||||
return -1;
|
||||
}
|
||||
if (call->params->in_conference==FALSE){
|
||||
if (linphone_core_sound_resources_locked(lc)){
|
||||
ms_warning("Cannot resume call %p because another call is locking the sound resources.",call);
|
||||
return -1;
|
||||
}
|
||||
linphone_core_preempt_sound_resources(lc);
|
||||
ms_message("Resuming call %p",call);
|
||||
}
|
||||
|
||||
call->was_automatically_paused=FALSE;
|
||||
call->broken = FALSE;
|
||||
|
||||
/* Stop playing music immediately. If remote side is a conference it
|
||||
prevents the participants to hear it while the 200OK comes back.*/
|
||||
if (call->audiostream) audio_stream_play(call->audiostream, NULL);
|
||||
|
||||
linphone_call_make_local_media_description(call);
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
if (!lc->sip_conf.sdp_200_ack){
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
} else {
|
||||
sal_call_set_local_media_description(call->op,NULL);
|
||||
}
|
||||
sal_media_description_set_dir(call->localdesc,SalStreamSendRecv);
|
||||
if (call->params->in_conference && !call->current_params->in_conference) subject="Conference";
|
||||
if ( sal_call_update(call->op,subject,FALSE) != 0){
|
||||
return -1;
|
||||
}
|
||||
linphone_call_set_state(call,LinphoneCallResuming,"Resuming");
|
||||
if (call->params->in_conference==FALSE)
|
||||
lc->current_call=call;
|
||||
snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",(tmp = linphone_call_get_remote_address_as_string(call)));
|
||||
ms_free(tmp);
|
||||
linphone_core_notify_display_status(lc,temp);
|
||||
|
||||
if (lc->sip_conf.sdp_200_ack){
|
||||
/*we are NOT offering, set local media description after sending the call so that we are ready to
|
||||
process the remote offer when it will arrive*/
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
}
|
||||
return 0;
|
||||
int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call) {
|
||||
return linphone_call_resume(call);
|
||||
}
|
||||
|
||||
static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *raddr){
|
||||
|
|
|
|||
|
|
@ -69,8 +69,12 @@ bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const LinphonePayloa
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt){
|
||||
if (pt->type==PAYLOAD_VIDEO) return TRUE;
|
||||
bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt) {
|
||||
return linphone_payload_type_is_vbr(pt);
|
||||
}
|
||||
|
||||
bool_t linphone_payload_type_is_vbr(const LinphonePayloadType *pt) {
|
||||
if (pt->type == PAYLOAD_VIDEO) return TRUE;
|
||||
return !!(pt->flags & PAYLOAD_TYPE_IS_VBR);
|
||||
}
|
||||
|
||||
|
|
@ -85,12 +89,20 @@ int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt,
|
|||
return -1;
|
||||
}
|
||||
|
||||
int linphone_core_get_payload_type_number(LinphoneCore *lc, const PayloadType *pt){
|
||||
int linphone_core_get_payload_type_number(LinphoneCore *lc, const PayloadType *pt) {
|
||||
return linphone_payload_type_get_number(pt);
|
||||
}
|
||||
|
||||
int linphone_payload_type_get_number(const PayloadType *pt) {
|
||||
return payload_type_get_number(pt);
|
||||
}
|
||||
|
||||
void linphone_core_set_payload_type_number(LinphoneCore *lc, PayloadType *pt, int number){
|
||||
payload_type_set_number(pt,number);
|
||||
void linphone_core_set_payload_type_number(LinphoneCore *lc, PayloadType *pt, int number) {
|
||||
linphone_payload_type_set_number(pt, number);
|
||||
}
|
||||
|
||||
void linphone_payload_type_set_number(PayloadType *pt, int number) {
|
||||
payload_type_set_number(pt, number);
|
||||
}
|
||||
|
||||
const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt){
|
||||
|
|
@ -772,8 +784,7 @@ const char *linphone_ice_state_to_string(LinphoneIceState state){
|
|||
return "invalid";
|
||||
}
|
||||
|
||||
void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
|
||||
{
|
||||
void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call) {
|
||||
IceCheckList *audio_check_list;
|
||||
IceCheckList *video_check_list;
|
||||
IceCheckList *text_check_list;
|
||||
|
|
@ -891,7 +902,7 @@ void linphone_call_stop_ice_for_inactive_streams(LinphoneCall *call, SalMediaDes
|
|||
}
|
||||
}
|
||||
|
||||
linphone_core_update_ice_state_in_call_stats(call);
|
||||
linphone_call_update_ice_state_in_call_stats(call);
|
||||
}
|
||||
|
||||
void _update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session, bool_t use_nortpproxy) {
|
||||
|
|
|
|||
|
|
@ -414,7 +414,7 @@ const LinphoneAuthInfo *_linphone_core_find_tls_auth_info(LinphoneCore *lc);
|
|||
const LinphoneAuthInfo *_linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain, bool_t ignore_realm);
|
||||
|
||||
void linphone_core_update_proxy_register(LinphoneCore *lc);
|
||||
int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error);
|
||||
int linphone_call_abort(LinphoneCall *call, const char *error);
|
||||
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
|
||||
|
||||
int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphonePresenceModel *presence);
|
||||
|
|
@ -532,7 +532,7 @@ void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, Linphone
|
|||
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call);
|
||||
LINPHONE_PUBLIC void linphone_core_enable_forced_ice_relay(LinphoneCore *lc, bool_t enable);
|
||||
LINPHONE_PUBLIC void linphone_core_enable_short_turn_refresh(LinphoneCore *lc, bool_t enable);
|
||||
void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call);
|
||||
void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call);
|
||||
LINPHONE_PUBLIC void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev);
|
||||
void linphone_call_stop_ice_for_inactive_streams(LinphoneCall *call, SalMediaDescription *result);
|
||||
void _update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session, bool_t use_nortpproxy);
|
||||
|
|
@ -579,14 +579,14 @@ 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_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy);
|
||||
int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const LinphoneAddress* destination/* = NULL if to be taken from the call log */);
|
||||
int linphone_core_restart_invite(LinphoneCore *lc, LinphoneCall *call);
|
||||
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 */);
|
||||
int linphone_call_restart_invite(LinphoneCall *call);
|
||||
/*
|
||||
* 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_core_start_update_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState next_state, const char *state_info);
|
||||
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 SalCallbacks linphone_sal_callbacks;
|
||||
|
|
@ -946,7 +946,7 @@ LinphoneToneDescription *linphone_core_get_call_error_tone(const LinphoneCore *l
|
|||
void linphone_core_play_call_error_tone(LinphoneCore *lc, LinphoneReason reason);
|
||||
void _linphone_core_set_tone(LinphoneCore *lc, LinphoneReason reason, LinphoneToneID id, const char *audiofile);
|
||||
LINPHONE_PUBLIC const char *linphone_core_get_tone_file(const LinphoneCore *lc, LinphoneToneID id);
|
||||
int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info);
|
||||
int _linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info);
|
||||
|
||||
typedef struct _LinphoneTaskList{
|
||||
MSList *hooks;
|
||||
|
|
@ -1148,7 +1148,7 @@ void linphone_call_make_local_media_description(LinphoneCall *call);
|
|||
void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, LinphoneCall *call, LinphoneCallParams *params);
|
||||
void linphone_call_increment_local_media_description(LinphoneCall *call);
|
||||
void linphone_call_fill_media_multicast_addr(LinphoneCall *call);
|
||||
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md, LinphoneCallState target_state);
|
||||
void linphone_call_update_streams(LinphoneCall *call, SalMediaDescription *new_md, LinphoneCallState target_state);
|
||||
|
||||
bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit);
|
||||
|
||||
|
|
@ -1199,7 +1199,7 @@ void linphone_call_set_broken(LinphoneCall *call);
|
|||
void linphone_call_repair_if_broken(LinphoneCall *call);
|
||||
void linphone_core_repair_calls(LinphoneCore *lc);
|
||||
int linphone_core_preempt_sound_resources(LinphoneCore *lc);
|
||||
int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
int _linphone_call_pause(LinphoneCall *call);
|
||||
|
||||
/*conferencing subsystem*/
|
||||
void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted);
|
||||
|
|
|
|||
|
|
@ -679,7 +679,7 @@ int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortB
|
|||
* uPnP Core interfaces
|
||||
*/
|
||||
|
||||
int linphone_core_update_upnp_audio_video(LinphoneCall *call, bool_t audio, bool_t video) {
|
||||
int linphone_call_update_upnp_audio_video(LinphoneCall *call, bool_t audio, bool_t video) {
|
||||
LinphoneCore *lc = call->core;
|
||||
UpnpContext *lupnp = lc->upnp;
|
||||
int ret = -1;
|
||||
|
|
@ -725,7 +725,7 @@ int linphone_core_update_upnp_audio_video(LinphoneCall *call, bool_t audio, bool
|
|||
|
||||
|
||||
|
||||
int linphone_core_update_upnp_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md) {
|
||||
int linphone_call_update_upnp_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md) {
|
||||
bool_t audio = FALSE;
|
||||
bool_t video = FALSE;
|
||||
int i;
|
||||
|
|
@ -741,14 +741,14 @@ int linphone_core_update_upnp_from_remote_media_description(LinphoneCall *call,
|
|||
}
|
||||
}
|
||||
|
||||
return linphone_core_update_upnp_audio_video(call, audio, video);
|
||||
return linphone_call_update_upnp_audio_video(call, audio, video);
|
||||
}
|
||||
|
||||
int linphone_core_update_upnp(LinphoneCore *lc, LinphoneCall *call) {
|
||||
return linphone_core_update_upnp_audio_video(call, call->audiostream!=NULL, call->videostream!=NULL);
|
||||
int linphone_call_update_upnp(LinphoneCall *call) {
|
||||
return linphone_call_update_upnp_audio_video(call, call->audiostream!=NULL, call->videostream!=NULL);
|
||||
}
|
||||
|
||||
void linphone_core_update_upnp_state_in_call_stats(LinphoneCall *call) {
|
||||
void linphone_call_update_upnp_state_in_call_stats(LinphoneCall *call) {
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].upnp_state = call->upnp_session->audio->state;
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].upnp_state = call->upnp_session->video->state;
|
||||
}
|
||||
|
|
@ -799,7 +799,7 @@ int linphone_upnp_call_process(LinphoneCall *call) {
|
|||
/*
|
||||
* Update stat
|
||||
*/
|
||||
linphone_core_update_upnp_state_in_call_stats(call);
|
||||
linphone_call_update_upnp_state_in_call_stats(call);
|
||||
|
||||
/*
|
||||
* Update session state
|
||||
|
|
@ -832,13 +832,13 @@ int linphone_upnp_call_process(LinphoneCall *call) {
|
|||
|
||||
switch (call->state) {
|
||||
case LinphoneCallUpdating:
|
||||
linphone_core_start_update_call(lc, call);
|
||||
linphone_call_start_update(call);
|
||||
break;
|
||||
case LinphoneCallUpdatedByRemote:
|
||||
linphone_core_start_accept_call_update(lc, call,call->prevstate,linphone_call_state_to_string(call->prevstate));
|
||||
linphone_call_start_accept_update(call, call->prevstate, linphone_call_state_to_string(call->prevstate));
|
||||
break;
|
||||
case LinphoneCallOutgoingInit:
|
||||
linphone_core_proceed_with_invite_if_ready(lc, call, NULL);
|
||||
linphone_call_proceed_with_invite_if_ready(call, NULL);
|
||||
break;
|
||||
case LinphoneCallIdle:
|
||||
linphone_call_update_local_media_description_from_ice_or_upnp(call);
|
||||
|
|
@ -1056,7 +1056,7 @@ bool_t linphone_core_upnp_hook(void *data) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
int linphone_core_update_local_media_description_from_upnp(SalMediaDescription *desc, UpnpSession *session) {
|
||||
int linphone_call_update_local_media_description_from_upnp(SalMediaDescription *desc, UpnpSession *session) {
|
||||
int i;
|
||||
SalStreamDescription *stream;
|
||||
UpnpStream *upnpStream;
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
typedef struct _UpnpSession UpnpSession;
|
||||
typedef struct _UpnpContext UpnpContext;
|
||||
|
||||
int linphone_core_update_local_media_description_from_upnp(SalMediaDescription *desc, UpnpSession *session);
|
||||
int linphone_core_update_upnp_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
|
||||
int linphone_core_update_upnp(LinphoneCore *lc, LinphoneCall *call);
|
||||
int linphone_call_update_local_media_description_from_upnp(SalMediaDescription *desc, UpnpSession *session);
|
||||
int linphone_call_update_upnp_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
|
||||
int linphone_call_update_upnp(LinphoneCall *call);
|
||||
|
||||
int linphone_upnp_call_process(LinphoneCall *call);
|
||||
UpnpSession* linphone_upnp_session_new(LinphoneCall *call);
|
||||
|
|
@ -43,6 +43,6 @@ LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *ctx);
|
|||
const char *linphone_upnp_context_get_external_ipaddress(UpnpContext *ctx);
|
||||
int linphone_upnp_context_get_external_port(UpnpContext *ctx);
|
||||
bool_t linphone_upnp_context_is_ready_for_register(UpnpContext *ctx);
|
||||
void linphone_core_update_upnp_state_in_call_stats(LinphoneCall *call);
|
||||
void linphone_call_update_upnp_state_in_call_stats(LinphoneCall *call);
|
||||
|
||||
#endif //LINPHONE_UPNP_H
|
||||
|
|
|
|||
|
|
@ -352,6 +352,176 @@ LINPHONE_PUBLIC RtpTransport * linphone_call_get_meta_rtp_transport(LinphoneCall
|
|||
**/
|
||||
LINPHONE_PUBLIC RtpTransport * linphone_call_get_meta_rtcp_transport(LinphoneCall *call, int stream_index);
|
||||
|
||||
/**
|
||||
* Pauses the call. If a music file has been setup using linphone_core_set_play_file(),
|
||||
* this file will be played to the remote user.
|
||||
* The only way to resume a paused call is to call linphone_call_resume().
|
||||
* @param[in] call LinphoneCall object
|
||||
* @return 0 on success, -1 on failure
|
||||
* @see linphone_call_resume()
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_pause(LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Resumes a call.
|
||||
* The call needs to have been paused previously with linphone_call_pause().
|
||||
* @param[in] call LinphoneCall object
|
||||
* @return 0 on success, -1 on failure
|
||||
* @see linphone_call_pause()
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_resume(LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Terminates a call.
|
||||
* @param[in] call LinphoneCall object
|
||||
* @return 0 on success, -1 on failure
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_terminate(LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Redirect the specified call to the given redirect URI.
|
||||
* @param[in] call A LinphoneCall object
|
||||
* @param[in] redirect_uri The URI to redirect the call to
|
||||
* @return 0 if successful, -1 on error.
|
||||
*/
|
||||
LINPHONE_PUBLIC int linphone_call_redirect(LinphoneCall *call, const char *redirect_uri);
|
||||
|
||||
/**
|
||||
* Decline a pending incoming call, with a reason.
|
||||
* @param[in] call A LinphoneCall object that must be in the IncomingReceived state
|
||||
* @param[in] reason The reason for rejecting the call: LinphoneReasonDeclined or LinphoneReasonBusy
|
||||
* @return 0 on success, -1 on failure
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_decline(LinphoneCall * call, LinphoneReason reason);
|
||||
|
||||
/**
|
||||
* Accept an incoming call.
|
||||
*
|
||||
* Basically the application is notified of incoming calls within the
|
||||
* call_state_changed callback of the #LinphoneCoreVTable structure, where it will receive
|
||||
* a LinphoneCallIncoming event with the associated LinphoneCall object.
|
||||
* The application can later accept the call using this method.
|
||||
* @param[in] call A LinphoneCall object
|
||||
* @return 0 on success, -1 on failure
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_accept(LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Accept an incoming call, with parameters.
|
||||
*
|
||||
* Basically the application is notified of incoming calls within the
|
||||
* call_state_changed callback of the #LinphoneCoreVTable structure, where it will receive
|
||||
* a LinphoneCallIncoming event with the associated LinphoneCall object.
|
||||
* The application can later accept the call using this method.
|
||||
* @param[in] call A LinphoneCall object
|
||||
* @param[in] params The specific parameters for this call, for example whether video is accepted or not. Use NULL to use default parameters
|
||||
* @return 0 on success, -1 on failure
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_accept_with_params(LinphoneCall *call, const LinphoneCallParams *params);
|
||||
|
||||
/**
|
||||
* Accept an early media session for an incoming call.
|
||||
* This is identical as calling linphone_call_accept_early_media_with_params() with NULL parameters.
|
||||
* @param[in] call A LinphoneCall object
|
||||
* @return 0 if successful, -1 otherwise
|
||||
* @see linphone_call_accept_early_media_with_params()
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_accept_early_media(LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* When receiving an incoming, accept to start a media session as early-media.
|
||||
* This means the call is not accepted but audio & video streams can be established if the remote party supports early media.
|
||||
* However, unlike after call acceptance, mic and camera input are not sent during early-media, though received audio & video are played normally.
|
||||
* The call can then later be fully accepted using linphone_call_accept() or linphone_call_accept_with_params().
|
||||
* @param[in] call A LinphoneCall object
|
||||
* @param[in] params The call parameters to use (can be NULL)
|
||||
* @return 0 if successful, -1 otherwise
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_accept_early_media_with_params(LinphoneCall *call, const LinphoneCallParams *params);
|
||||
|
||||
/**
|
||||
* Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore.
|
||||
* In this version this is limited to the following use cases:
|
||||
* - setting up/down the video stream according to the video parameter of the LinphoneCallParams (see linphone_call_params_enable_video() ).
|
||||
* - changing the size of the transmitted video after calling linphone_core_set_preferred_video_size()
|
||||
* In case no changes are requested through the LinphoneCallParams argument, then this argument can be omitted and set to NULL.
|
||||
* WARNING: Updating a call in the LinphoneCallPaused state will still result in a paused call even if the media directions set in the
|
||||
* params are sendrecv. To resume a paused call, you need to call linphone_call_resume().
|
||||
* @param[in] call A LinphoneCall update
|
||||
* @param[in] params The new call parameters to use (may be NULL)
|
||||
* @return 0 if successful, -1 otherwise.
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_update(LinphoneCall *call, const LinphoneCallParams *params);
|
||||
|
||||
/**
|
||||
* When receiving a #LinphoneCallUpdatedByRemote state notification, prevent LinphoneCore from performing an automatic answer.
|
||||
*
|
||||
* When receiving a #LinphoneCallUpdatedByRemote state notification (ie an incoming reINVITE), the default behaviour of
|
||||
* LinphoneCore is defined by the "defer_update_default" option of the "sip" section of the config. If this option is 0 (the default)
|
||||
* then the LinphoneCore automatically answers the reINIVTE with call parameters unchanged.
|
||||
* However when for example when the remote party updated the call to propose a video stream, it can be useful
|
||||
* to prompt the user before answering. This can be achieved by calling linphone_core_defer_call_update() during
|
||||
* the call state notification, to deactivate the automatic answer that would just confirm the audio but reject the video.
|
||||
* Then, when the user responds to dialog prompt, it becomes possible to call linphone_call_accept_update() to answer
|
||||
* the reINVITE, with eventually video enabled in the LinphoneCallParams argument.
|
||||
*
|
||||
* The #LinphoneCallUpdatedByRemote notification can also arrive when receiving an INVITE without SDP. In such case, an unchanged offer is made
|
||||
* in the 200Ok, and when the ACK containing the SDP answer is received, #LinphoneCallUpdatedByRemote is triggered to notify the application of possible
|
||||
* changes in the media session. However in such case defering the update has no meaning since we just generating an offer.
|
||||
*
|
||||
* @param[in] call A LinphoneCall object
|
||||
* @return 0 if successful, -1 if the linphone_call_defer_update() was done outside a valid #LinphoneCallUpdatedByRemote notification
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_defer_update(LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Accept call modifications initiated by other end.
|
||||
*
|
||||
* This call may be performed in response to a #LinphoneCallUpdatedByRemote state notification.
|
||||
* When such notification arrives, the application can decide to call linphone_call_defer_update() so that it can
|
||||
* have the time to prompt the user. linphone_call_get_remote_params() can be used to get information about the call parameters
|
||||
* requested by the other party, such as whether a video stream is requested.
|
||||
*
|
||||
* When the user accepts or refuse the change, linphone_call_accept_update() can be done to answer to the other party.
|
||||
* If params is NULL, then the same call parameters established before the update request will continue to be used (no change).
|
||||
* If params is not NULL, then the update will be accepted according to the parameters passed.
|
||||
* Typical example is when a user accepts to start video, then params should indicate that video stream should be used
|
||||
* (see linphone_call_params_enable_video()).
|
||||
* @param[in] call A LinphoneCall object
|
||||
* @param[in] params A LinphoneCallParams object describing the call parameters to accept
|
||||
* @return 0 if successful, -1 otherwise (actually when this function call is performed outside ot #LinphoneCallUpdatedByRemote state)
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params);
|
||||
|
||||
/**
|
||||
* Performs a simple call transfer to the specified destination.
|
||||
* The remote endpoint is expected to issue a new call to the specified destination.
|
||||
* The current call remains active and thus can be later paused or terminated.
|
||||
* It is possible to follow the progress of the transfer provided that transferee sends notification about it.
|
||||
* In this case, the transfer_state_changed callback of the #LinphoneCoreVTable is invoked to notify of the state of the new call at the other party.
|
||||
* The notified states are #LinphoneCallOutgoingInit , #LinphoneCallOutgoingProgress, #LinphoneCallOutgoingRinging and #LinphoneCallConnected.
|
||||
* @param[in] call The call to be transfered
|
||||
* @param[in] refer_to The destination the call is to be refered to
|
||||
* @return 0 on success, -1 on failure
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_transfer(LinphoneCall *call, const char *refer_to);
|
||||
|
||||
/**
|
||||
* Transfers a call to destination of another running call. This is used for "attended transfer" scenarios.
|
||||
* The transfered call is supposed to be in paused state, so that it is able to accept the transfer immediately.
|
||||
* The destination call is a call previously established to introduce the transfered person.
|
||||
* This method will send a transfer request to the transfered person. The phone of the transfered is then
|
||||
* expected to automatically call to the destination of the transfer. The receiver of the transfer will then automatically
|
||||
* close the call with us (the 'dest' call).
|
||||
* It is possible to follow the progress of the transfer provided that transferee sends notification about it.
|
||||
* In this case, the transfer_state_changed callback of the #LinphoneCoreVTable is invoked to notify of the state of the new call at the other party.
|
||||
* The notified states are #LinphoneCallOutgoingInit , #LinphoneCallOutgoingProgress, #LinphoneCallOutgoingRinging and #LinphoneCallConnected.
|
||||
* @param[in] call A running call you want to transfer
|
||||
* @param[in] dest A running call whose remote person will receive the transfer
|
||||
* @return 0 on success, -1 on failure
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_call_transfer_to_another(LinphoneCall *call, LinphoneCall *dest);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1146,8 +1146,9 @@ LINPHONE_PUBLIC LinphoneCall * linphone_core_invite_address_with_params(Linphone
|
|||
* @param[in] refer_to The destination the call is to be refered to
|
||||
* @return 0 on success, -1 on failure
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_transfer() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char *refer_to);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char *refer_to);
|
||||
|
||||
/**
|
||||
* Transfers a call to destination of another running call. This is used for "attended transfer" scenarios.
|
||||
|
|
@ -1164,8 +1165,9 @@ LINPHONE_PUBLIC int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *
|
|||
* @param[in] dest A running call whose remote person will receive the transfer
|
||||
* @return 0 on success, -1 on failure
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_transfer_to_another() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call, LinphoneCall *dest);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call, LinphoneCall *dest);
|
||||
|
||||
/**
|
||||
* Start a new call as a consequence of a transfer request received from a call.
|
||||
|
|
@ -1217,8 +1219,9 @@ LINPHONE_PUBLIC LinphoneCall *linphone_core_get_current_call(const LinphoneCore
|
|||
* @param[in] call The LinphoneCall object representing the call to be answered
|
||||
* @return 0 on success, -1 on failure
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_accept() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Accept an incoming call, with parameters.
|
||||
|
|
@ -1233,8 +1236,9 @@ LINPHONE_PUBLIC int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *ca
|
|||
* @param[in] params The specific parameters for this call, for example whether video is accepted or not. Use NULL to use default parameters
|
||||
* @return 0 on success, -1 on failure
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_accept_with_params() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params);
|
||||
|
||||
/**
|
||||
* When receiving an incoming, accept to start a media session as early-media.
|
||||
|
|
@ -1246,8 +1250,9 @@ LINPHONE_PUBLIC int linphone_core_accept_call_with_params(LinphoneCore *lc, Linp
|
|||
* @param[in] params The call parameters to use (can be NULL)
|
||||
* @return 0 if successful, -1 otherwise
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_accept_early_media_with_params() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* call, const LinphoneCallParams* params);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* call, const LinphoneCallParams* params);
|
||||
|
||||
/**
|
||||
* Accept an early media session for an incoming call.
|
||||
|
|
@ -1257,8 +1262,9 @@ LINPHONE_PUBLIC int linphone_core_accept_early_media_with_params(LinphoneCore* l
|
|||
* @return 0 if successful, -1 otherwise
|
||||
* @ingroup call_control
|
||||
* @see linphone_core_accept_early_media_with_params()
|
||||
* @deprecated Use linphone_call_accept_early_media() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call);
|
||||
|
||||
/**
|
||||
* Terminates a call.
|
||||
|
|
@ -1266,8 +1272,9 @@ LINPHONE_PUBLIC int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneC
|
|||
* @param[in] call The LinphoneCall object representing the call to be terminated
|
||||
* @return 0 on success, -1 on failure
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_terminate() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Redirect the specified call to the given redirect URI.
|
||||
|
|
@ -1276,8 +1283,9 @@ LINPHONE_PUBLIC int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall
|
|||
* @param[in] redirect_uri The URI to redirect the call to
|
||||
* @return 0 if successful, -1 on error.
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_redirect() instead
|
||||
*/
|
||||
LINPHONE_PUBLIC int linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char *redirect_uri);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char *redirect_uri);
|
||||
|
||||
/**
|
||||
* Decline a pending incoming call, with a reason.
|
||||
|
|
@ -1286,8 +1294,9 @@ LINPHONE_PUBLIC int linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *
|
|||
* @param[in] reason The reason for rejecting the call: LinphoneReasonDeclined or LinphoneReasonBusy
|
||||
* @return 0 on success, -1 on failure
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_decline() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_decline_call(LinphoneCore *lc, LinphoneCall * call, LinphoneReason reason);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_decline_call(LinphoneCore *lc, LinphoneCall * call, LinphoneReason reason);
|
||||
|
||||
/**
|
||||
* Terminates all the calls.
|
||||
|
|
@ -1306,8 +1315,9 @@ LINPHONE_PUBLIC int linphone_core_terminate_all_calls(LinphoneCore *lc);
|
|||
* @return 0 on success, -1 on failure
|
||||
* @ingroup call_control
|
||||
* @see linphone_core_resume_call()
|
||||
* @deprecated Use linphone_call_pause() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Pause all currently running calls.
|
||||
|
|
@ -1325,8 +1335,9 @@ LINPHONE_PUBLIC int linphone_core_pause_all_calls(LinphoneCore *lc);
|
|||
* @return 0 on success, -1 on failure
|
||||
* @ingroup call_control
|
||||
* @see linphone_core_pause_call()
|
||||
* @deprecated Use linphone_call_resume() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore.
|
||||
|
|
@ -1341,8 +1352,9 @@ LINPHONE_PUBLIC int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *ca
|
|||
* @param[in] params The new call parameters to use (may be NULL)
|
||||
* @return 0 if successful, -1 otherwise.
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_update() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params);
|
||||
|
||||
/**
|
||||
* When receiving a #LinphoneCallUpdatedByRemote state notification, prevent LinphoneCore from performing an automatic answer.
|
||||
|
|
@ -1364,8 +1376,9 @@ LINPHONE_PUBLIC int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *ca
|
|||
* @param[in] call The call for which to defer the update
|
||||
* @return 0 if successful, -1 if the linphone_core_defer_call_update() was done outside a valid #LinphoneCallUpdatedByRemote notification
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_defer_update() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Accept call modifications initiated by other end.
|
||||
|
|
@ -1385,8 +1398,9 @@ LINPHONE_PUBLIC int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCa
|
|||
* @param[in] params A LinphoneCallParams object describing the call parameters to accept
|
||||
* @return 0 if successful, -1 otherwise (actually when this function call is performed outside ot #LinphoneCallUpdatedByRemote state)
|
||||
* @ingroup call_control
|
||||
* @deprecated Use linphone_call_accept_update() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params);
|
||||
|
||||
/**
|
||||
* Create a LinphoneCallParams suitable for linphone_core_invite_with_params(), linphone_core_accept_call_with_params(), linphone_core_accept_early_media_with_params(),
|
||||
|
|
@ -1781,8 +1795,9 @@ LINPHONE_PUBLIC bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, cons
|
|||
* @param[in] pt The #LinphonePayloadType we want to know
|
||||
* @return TRUE if the payload type represents a VBR codec, FALSE if disabled.
|
||||
* @ingroup media_parameters
|
||||
* @deprecated Use linphone_payload_type_is_vbr() instead
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt);
|
||||
|
||||
/**
|
||||
* Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s.
|
||||
|
|
@ -1839,15 +1854,17 @@ LINPHONE_PUBLIC LinphonePayloadType* linphone_core_find_payload_type(LinphoneCor
|
|||
/**
|
||||
* Returns the payload type number assigned for this codec.
|
||||
* @ingroup media_parameters
|
||||
* @deprecated Use linphone_payload_type_get_number() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_get_payload_type_number(LinphoneCore *lc, const PayloadType *pt);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_get_payload_type_number(LinphoneCore *lc, const PayloadType *pt);
|
||||
|
||||
/**
|
||||
* Force a number for a payload type. The LinphoneCore does payload type number assignment automatically. THis function is to be used mainly for tests, in order
|
||||
* to override the automatic assignment mechanism.
|
||||
* @ingroup media_parameters
|
||||
* @deprecated Use linphone_payload_type_set_number() instead
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_core_set_payload_type_number(LinphoneCore *lc, PayloadType *pt, int number);
|
||||
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_payload_type_number(LinphoneCore *lc, PayloadType *pt, int number);
|
||||
|
||||
LINPHONE_PUBLIC const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt);
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,28 @@ LINPHONE_PUBLIC const char * linphone_payload_type_get_mime_type(const LinphoneP
|
|||
*/
|
||||
LINPHONE_PUBLIC int linphone_payload_type_get_channels(const LinphonePayloadType *pt);
|
||||
|
||||
/**
|
||||
* Returns the payload type number assigned for this codec.
|
||||
* @param[in] pt LinphonePayloadType object
|
||||
* @return The number of the payload type
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_payload_type_get_number(const PayloadType *pt);
|
||||
|
||||
/**
|
||||
* Force a number for a payload type. The LinphoneCore does payload type number assignment automatically. THis function is to be used mainly for tests, in order
|
||||
* to override the automatic assignment mechanism.
|
||||
* @param[in] pt LinphonePayloadType object
|
||||
* @param[in] number The number to assign to the payload type
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_payload_type_set_number(PayloadType *pt, int number);
|
||||
|
||||
/**
|
||||
* Tells whether the specified payload type represents a variable bitrate codec.
|
||||
* @param[in] pt LinphonePayloadType object
|
||||
* @return TRUE if the payload type represents a VBR codec, FALSE if disabled.
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_payload_type_is_vbr(const LinphonePayloadType *pt);
|
||||
|
||||
/**
|
||||
* @}
|
||||
**/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue