forked from mirrors/linphone-iphone
Refactoring of states, handling of media direction, late offering and so on.
Almost working except one test.
This commit is contained in:
parent
ca9647f975
commit
ed2385ce28
8 changed files with 334 additions and 316 deletions
|
|
@ -93,7 +93,6 @@ struct SalOp{
|
|||
belle_sip_header_referred_by_t *referred_by;
|
||||
SalMediaDescription *result;
|
||||
belle_sdp_session_description_t *sdp_answer;
|
||||
bool_t supports_session_timers;
|
||||
SalOpState state;
|
||||
SalOpDir dir;
|
||||
belle_sip_refresher_t* refresher;
|
||||
|
|
@ -101,14 +100,15 @@ struct SalOp{
|
|||
SalOpType type;
|
||||
SalPrivacyMask privacy;
|
||||
belle_sip_header_t *event; /*used by SalOpSubscribe kinds*/
|
||||
SalOpSDPHandling sdp_handling;
|
||||
int auth_requests; /*number of auth requested for this op*/
|
||||
bool_t cnx_ip_to_0000_if_sendonly_enabled;
|
||||
bool_t auto_answer_asked;
|
||||
bool_t sdp_offering;
|
||||
bool_t call_released;
|
||||
bool_t manual_refresher;
|
||||
bool_t has_auth_pending;
|
||||
SalOpSDPHandling sdp_handling;
|
||||
int auth_requests; /*number of auth requested for this op*/
|
||||
bool_t cnx_ip_to_0000_if_sendonly_enabled; /*for */
|
||||
bool_t supports_session_timers;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -302,10 +302,10 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
|
|||
&& (header_content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t))
|
||||
&& strcmp("application",belle_sip_header_content_type_get_type(header_content_type))==0
|
||||
&& strcmp("media_control+xml",belle_sip_header_content_type_get_subtype(header_content_type))==0) {
|
||||
unsigned int retry_in =1000*((float)rand()/RAND_MAX);
|
||||
belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry");
|
||||
ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in);
|
||||
belle_sip_object_unref(s);
|
||||
unsigned int retry_in =1000*((float)rand()/RAND_MAX);
|
||||
belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry");
|
||||
ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in);
|
||||
belle_sip_object_unref(s);
|
||||
}else {
|
||||
/*ignoring*/
|
||||
}
|
||||
|
|
@ -323,7 +323,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
|
|||
}
|
||||
break;
|
||||
case BELLE_SIP_DIALOG_TERMINATED: {
|
||||
if (code >= 300){
|
||||
if (strcmp("INVITE",method)==0 && code >= 300){
|
||||
call_set_error(op,response);
|
||||
}
|
||||
}
|
||||
|
|
@ -578,22 +578,27 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
|||
case BELLE_SIP_DIALOG_CONFIRMED:
|
||||
/*great ACK received*/
|
||||
if (strcmp("ACK",method)==0) {
|
||||
if (op->sdp_offering){
|
||||
SalReason reason;
|
||||
if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){
|
||||
if (sdp){
|
||||
if (op->base.remote_media)
|
||||
sal_media_description_unref(op->base.remote_media);
|
||||
op->base.remote_media=sal_media_description_new();
|
||||
sdp_to_media_description(sdp,op->base.remote_media);
|
||||
sdp_process(op);
|
||||
belle_sip_object_unref(sdp);
|
||||
}else{
|
||||
ms_warning("SDP expected in ACK but not found.");
|
||||
if (!op->pending_client_trans ||
|
||||
!belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state((belle_sip_transaction_t*)op->pending_client_trans))){
|
||||
if (op->sdp_offering){
|
||||
SalReason reason;
|
||||
if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){
|
||||
if (sdp){
|
||||
if (op->base.remote_media)
|
||||
sal_media_description_unref(op->base.remote_media);
|
||||
op->base.remote_media=sal_media_description_new();
|
||||
sdp_to_media_description(sdp,op->base.remote_media);
|
||||
sdp_process(op);
|
||||
belle_sip_object_unref(sdp);
|
||||
}else{
|
||||
ms_warning("SDP expected in ACK but not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
op->base.root->callbacks.call_ack(op);
|
||||
}else{
|
||||
ms_message("Ignored received ack since a new client transaction has been started since.");
|
||||
}
|
||||
op->base.root->callbacks.call_ack(op);
|
||||
} else if(strcmp("BYE",method)==0) {
|
||||
resp=sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
|
|
|
|||
|
|
@ -117,10 +117,8 @@ void linphone_call_update_frozen_payloads(LinphoneCall *call, SalMediaDescriptio
|
|||
}
|
||||
}
|
||||
|
||||
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
|
||||
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md, LinphoneCallState target_state){
|
||||
SalMediaDescription *oldmd=call->resultdesc;
|
||||
bool_t all_muted=FALSE;
|
||||
bool_t send_ringbacktone=FALSE;
|
||||
int md_changed=0;
|
||||
|
||||
|
||||
|
|
@ -144,7 +142,6 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
|
|||
call->biggestdesc=sal_media_description_ref(sal_call_get_remote_media_description(call->op));
|
||||
}
|
||||
sal_media_description_ref(new_md);
|
||||
call->expect_media_in_ack=FALSE;
|
||||
call->resultdesc=new_md;
|
||||
if ((call->audiostream && call->audiostream->ms.state==MSStreamStarted) || (call->videostream && call->videostream->ms.state==MSStreamStarted)){
|
||||
clear_early_media_destinations(call);
|
||||
|
|
@ -201,25 +198,11 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
|
|||
/*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->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
|
||||
send_ringbacktone=TRUE;
|
||||
}
|
||||
if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params->real_early_media){
|
||||
all_muted=TRUE;
|
||||
}
|
||||
|
||||
if (call->params->real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){
|
||||
prepare_early_media_forking(call);
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->state==LinphoneCallPausing) {
|
||||
/*change cam to noweb cam*/
|
||||
call->cam = get_nowebcam_device();
|
||||
} else if (call->state != LinphoneCallPaused) {
|
||||
/*restaure web cam*/
|
||||
call->cam = lc->video_conf.device;
|
||||
}
|
||||
#endif /*VIDEO*/
|
||||
linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
|
||||
linphone_call_start_media_streams(call, target_state);
|
||||
if (call->state==LinphoneCallPausing && call->paused_by_app && ms_list_size(lc->calls)==1){
|
||||
linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
|
||||
}
|
||||
|
|
@ -476,7 +459,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);
|
||||
linphone_core_update_streams(lc,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);
|
||||
|
|
@ -484,21 +467,35 @@ static void call_ringing(SalOp *h){
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* could be reach :
|
||||
* - when the call is accepted
|
||||
* - when a request is accepted (pause, resume)
|
||||
*/
|
||||
static void call_accepted(SalOp *op){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
SalMediaDescription *md, *rmd;
|
||||
bool_t update_state=TRUE;
|
||||
static void start_pending_refer(LinphoneCall *call){
|
||||
linphone_core_start_refered_call(call->core, call,NULL);
|
||||
}
|
||||
|
||||
if (call == NULL){
|
||||
ms_warning("No call to accept.");
|
||||
return ;
|
||||
static void process_call_accepted(LinphoneCore *lc, LinphoneCall *call, SalOp *op){
|
||||
SalMediaDescription *md, *rmd;
|
||||
LinphoneCallState next_state = LinphoneCallIdle;
|
||||
const char *next_state_str = NULL;
|
||||
LinphoneTaskList tl;
|
||||
|
||||
switch (call->state){/*immediately notify the connected state, even if errors occur after*/
|
||||
case LinphoneCallOutgoingProgress:
|
||||
case LinphoneCallOutgoingRinging:
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
/*immediately notify the connected state*/
|
||||
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
|
||||
{
|
||||
char *tmp=linphone_call_get_remote_address_as_string (call);
|
||||
char *msg=ms_strdup_printf(_("Call answered by %s"),tmp);
|
||||
linphone_core_notify_display_status(lc,msg);
|
||||
ms_free(tmp);
|
||||
ms_free(msg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
linphone_task_list_init(&tl);
|
||||
rmd=sal_call_get_remote_media_description(op);
|
||||
/*set privacy*/
|
||||
call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
|
||||
|
|
@ -517,128 +514,108 @@ static void call_accepted(SalOp *op){
|
|||
#endif //BUILD_UPNP
|
||||
|
||||
md=sal_call_get_final_media_description(op);
|
||||
|
||||
switch (call->state){
|
||||
case LinphoneCallOutgoingProgress:
|
||||
case LinphoneCallOutgoingRinging:
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
|
||||
if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
|
||||
break;
|
||||
case LinphoneCallEarlyUpdating:
|
||||
linphone_call_set_state(call,call->prevstate,"Early update accepted");
|
||||
update_state=FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (md == NULL && call->prevstate == LinphoneCallOutgoingEarlyMedia && call->resultdesc != NULL){
|
||||
ms_message("Using early media SDP since none was received with the 200 OK");
|
||||
md = call->resultdesc;
|
||||
}
|
||||
|
||||
if( (call->prevstate == LinphoneCallOutgoingEarlyMedia) && (md == NULL || sal_media_description_empty(md)) ){
|
||||
/* media description is null or empty because no SDP was received in the 200 OK, we can possibly use the early-media SDP. */
|
||||
if( call->resultdesc != NULL){
|
||||
ms_message("Using early media SDP since none were received with the 200 OK");
|
||||
md = call->resultdesc;
|
||||
}
|
||||
if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
|
||||
md = NULL;
|
||||
}
|
||||
|
||||
if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){
|
||||
linphone_call_update_remote_session_id_and_ver(call);
|
||||
linphone_core_update_ice_state_in_call_stats(call);
|
||||
if (sal_media_description_has_dir(md,SalStreamSendOnly) ||
|
||||
sal_media_description_has_dir(md,SalStreamInactive)){
|
||||
{
|
||||
char *tmp=linphone_call_get_remote_address_as_string (call);
|
||||
char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp);
|
||||
linphone_core_notify_display_status(lc,msg);
|
||||
ms_free(tmp);
|
||||
ms_free(msg);
|
||||
}
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
if (update_state) linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
|
||||
if (call->refer_pending)
|
||||
linphone_core_start_refered_call(lc,call,NULL);
|
||||
}else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){
|
||||
/*we are put on hold when the call is initially accepted */
|
||||
{
|
||||
char *tmp=linphone_call_get_remote_address_as_string (call);
|
||||
char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp);
|
||||
linphone_core_notify_display_status(lc,msg);
|
||||
ms_free(tmp);
|
||||
ms_free(msg);
|
||||
}
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
if (update_state) linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote");
|
||||
}else{
|
||||
if (call->state!=LinphoneCallUpdating){
|
||||
if (call->state==LinphoneCallResuming){
|
||||
linphone_core_notify_display_status(lc,_("Call resumed."));
|
||||
if (md){ /*there is a valid SDP in the response, either offer or answer, and we're able to start/update the streams*/
|
||||
switch (call->state){
|
||||
case LinphoneCallResuming:
|
||||
linphone_core_notify_display_status(lc,_("Call resumed."));
|
||||
/*intentionally no break*/
|
||||
case LinphoneCallConnected:
|
||||
if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
|
||||
/*intentionally no break*/
|
||||
case LinphoneCallUpdating:
|
||||
case LinphoneCallUpdatedByRemote:
|
||||
if (!sal_media_description_has_dir(call->localdesc, SalStreamInactive) &&
|
||||
(sal_media_description_has_dir(md,SalStreamRecvOnly) ||
|
||||
sal_media_description_has_dir(md,SalStreamInactive))){
|
||||
next_state = LinphoneCallPausedByRemote;
|
||||
next_state_str = "Call paused by remote";
|
||||
}else{
|
||||
{
|
||||
char *tmp=linphone_call_get_remote_address_as_string (call);
|
||||
char *msg=ms_strdup_printf(_("Call answered by %s."),tmp);
|
||||
linphone_core_notify_display_status(lc,msg);
|
||||
ms_free(tmp);
|
||||
ms_free(msg);
|
||||
}
|
||||
if (!call->current_params->in_conference)
|
||||
lc->current_call=call;
|
||||
next_state = LinphoneCallStreamsRunning;
|
||||
next_state_str = "Streams running";
|
||||
}
|
||||
}
|
||||
linphone_core_update_streams(lc,call,md);
|
||||
linphone_call_fix_call_parameters(call);
|
||||
if (!call->current_params->in_conference)
|
||||
lc->current_call=call;
|
||||
if (update_state) linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
|
||||
break;
|
||||
case LinphoneCallEarlyUpdating:
|
||||
next_state_str = "Early update accepted";
|
||||
next_state = call->prevstate;
|
||||
break;
|
||||
case LinphoneCallPausing:
|
||||
/*when we entered the pausing state, we always reach the paused state whatever the content of the remote SDP is.
|
||||
Our streams are all send-only (with music), soundcard and camera are never used*/
|
||||
next_state = LinphoneCallPaused;
|
||||
next_state_str = "Call paused";
|
||||
if (call->refer_pending)
|
||||
linphone_task_list_add(&tl, (LinphoneCoreIterateHook)start_pending_refer, call);
|
||||
break;
|
||||
default:
|
||||
ms_error("call_accepted(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state));
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
|
||||
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_fix_call_parameters(call);
|
||||
linphone_call_set_state(call, next_state, next_state_str);
|
||||
}else{
|
||||
ms_error("BUG: next_state is not set in call_accepted(), current state is %s", linphone_call_state_to_string(call->state));
|
||||
}
|
||||
}else{ /*invalid or no SDP*/
|
||||
switch (call->prevstate){
|
||||
/*send a bye only in case of outgoing state*/
|
||||
/*send a bye only in case of early states*/
|
||||
case LinphoneCallOutgoingInit:
|
||||
case LinphoneCallOutgoingProgress:
|
||||
case LinphoneCallOutgoingRinging:
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
ms_error("Incompatible SDP offer received in 200 OK, need to abort the call");
|
||||
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..."));
|
||||
break;
|
||||
/*otherwise we are able to resume previous state*/
|
||||
default:
|
||||
ms_message("Incompatible SDP offer received in 200 OK, restoring previous state[%s]",linphone_call_state_to_string(call->prevstate));
|
||||
ms_message("Incompatible SDP answer received, restoring previous state [%s]",linphone_call_state_to_string(call->prevstate));
|
||||
linphone_call_set_state(call,call->prevstate,_("Incompatible media parameters."));
|
||||
break;
|
||||
}
|
||||
}
|
||||
linphone_task_list_run(&tl);
|
||||
linphone_task_list_free(&tl);
|
||||
}
|
||||
|
||||
static void call_ack(SalOp *op){
|
||||
/*
|
||||
* could be reach :
|
||||
* - when the call is accepted
|
||||
* - when a request is accepted (pause, resume)
|
||||
*/
|
||||
static void call_accepted(SalOp *op){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
if (call==NULL){
|
||||
ms_warning("No call to be ACK'd");
|
||||
|
||||
if (call == NULL){
|
||||
ms_warning("call_accepted: call does no longer exist.");
|
||||
return ;
|
||||
}
|
||||
if (call->expect_media_in_ack){
|
||||
SalMediaDescription *md=sal_call_get_final_media_description(op);
|
||||
if (md && !sal_media_description_empty(md)){
|
||||
linphone_core_update_streams(lc,call,md);
|
||||
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}else{
|
||||
/*send a bye*/
|
||||
ms_error("Incompatible SDP response received in ACK, need to abort the call");
|
||||
linphone_core_abort_call(lc,call,"No codec intersection");
|
||||
return;
|
||||
}
|
||||
}
|
||||
process_call_accepted(lc, call, op);
|
||||
}
|
||||
|
||||
static void call_resumed(LinphoneCore *lc, LinphoneCall *call){
|
||||
/*when we are resumed, increment session id, because sdp is changed (a=recvonly disapears)*/
|
||||
linphone_call_increment_local_media_description(call);
|
||||
linphone_core_notify_display_status(lc,_("We have been resumed."));
|
||||
_linphone_core_accept_call_update(lc,call,NULL,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}
|
||||
|
||||
static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
|
||||
LinphoneCallParams *params;
|
||||
/*when we are paused, increment session id, because sdp is changed (a=recvonly appears)*/
|
||||
linphone_call_increment_local_media_description(call);
|
||||
|
||||
/* we are being paused */
|
||||
linphone_core_notify_display_status(lc,_("We are paused by other party."));
|
||||
params = linphone_call_params_copy(call->params);
|
||||
|
|
@ -649,100 +626,47 @@ static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
|
|||
linphone_call_params_unref(params);
|
||||
}
|
||||
|
||||
static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t is_update){
|
||||
/*first check if media capabilities are compatible*/
|
||||
SalMediaDescription *md;
|
||||
SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op);
|
||||
SalMediaDescription *prev_result_desc=call->resultdesc;
|
||||
|
||||
if (rmd!=NULL){
|
||||
if (call->state!=LinphoneCallPaused){
|
||||
/*in paused state, we must stay in paused state.*/
|
||||
linphone_call_make_local_media_description(lc,call);
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
}
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
|
||||
sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
|
||||
return;
|
||||
}
|
||||
if (is_update && prev_result_desc && md){
|
||||
int diff=sal_media_description_equals(prev_result_desc,md);
|
||||
if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){
|
||||
ms_warning("Cannot accept this update, it is changing parameters that require user approval");
|
||||
sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( call->state == LinphoneCallStreamsRunning) {
|
||||
/*reINVITE and in-dialogs UPDATE go here*/
|
||||
linphone_core_notify_display_status(lc,_("Call is updated by remote."));
|
||||
call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE);
|
||||
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
|
||||
if (call->defer_update==FALSE){
|
||||
linphone_core_accept_call_update(lc,call,NULL);
|
||||
}
|
||||
if (rmd==NULL){
|
||||
call->expect_media_in_ack=TRUE;
|
||||
}
|
||||
|
||||
} else if( call->state == LinphoneCallPausedByRemote ){
|
||||
/* FIXME: the comment below is meaningless. */
|
||||
/* Case where no SDP is present and we were paused by remote.
|
||||
* We send back an ACK with our SDP and expect the remote to send its own.
|
||||
* No state change here until an answer is received. */
|
||||
call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE);
|
||||
if (call->defer_update==FALSE){
|
||||
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
|
||||
}
|
||||
if (rmd==NULL){
|
||||
call->expect_media_in_ack=TRUE;
|
||||
}
|
||||
} else if (is_update){ /*SIP UPDATE case, can occur in early states*/
|
||||
linphone_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote");
|
||||
_linphone_core_accept_call_update(lc,call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate));
|
||||
}
|
||||
}
|
||||
|
||||
/* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/
|
||||
static void call_updating(SalOp *op, bool_t is_update){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t is_update){
|
||||
SalMediaDescription *rmd=sal_call_get_remote_media_description(op);
|
||||
|
||||
if (rmd==NULL){
|
||||
/* case of a reINVITE or UPDATE without SDP */
|
||||
call_updated_by_remote(lc,call,is_update);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE);
|
||||
|
||||
switch(call->state){
|
||||
case LinphoneCallPausedByRemote:
|
||||
if (sal_media_description_has_dir(rmd,SalStreamSendRecv) || sal_media_description_has_dir(rmd,SalStreamRecvOnly)){
|
||||
call_resumed(lc,call);
|
||||
}else call_updated_by_remote(lc,call,is_update);
|
||||
}else{
|
||||
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
|
||||
}
|
||||
break;
|
||||
/*SIP UPDATE CASE*/
|
||||
case LinphoneCallOutgoingRinging:
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
case LinphoneCallIncomingEarlyMedia:
|
||||
if (is_update) call_updated_by_remote(lc,call,is_update);
|
||||
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));
|
||||
}
|
||||
break;
|
||||
case LinphoneCallStreamsRunning:
|
||||
case LinphoneCallConnected:
|
||||
if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){
|
||||
call_paused_by_remote(lc,call);
|
||||
}else{
|
||||
call_updated_by_remote(lc,call,is_update);
|
||||
linphone_core_notify_display_status(lc,_("Call is updated by remote."));
|
||||
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
|
||||
if (call->defer_update == FALSE){
|
||||
linphone_core_accept_call_update(lc,call,NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LinphoneCallPaused:
|
||||
if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){
|
||||
call_paused_by_remote(lc,call);
|
||||
}else{
|
||||
call_updated_by_remote(lc,call,is_update);
|
||||
/*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));
|
||||
}
|
||||
break;
|
||||
case LinphoneCallUpdating:
|
||||
|
|
@ -766,6 +690,71 @@ static void call_updating(SalOp *op, bool_t is_update){
|
|||
}
|
||||
}
|
||||
|
||||
/* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/
|
||||
static void call_updating(SalOp *op, bool_t is_update){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
SalMediaDescription *rmd=sal_call_get_remote_media_description(op);
|
||||
|
||||
if (!call) {
|
||||
ms_error("call_updating(): call doesn't exist anymore");
|
||||
return ;
|
||||
}
|
||||
if (call->state!=LinphoneCallPaused){
|
||||
/*Refresh the local description, but in paused state, we don't change anything.*/
|
||||
linphone_call_make_local_media_description(lc,call);
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
}
|
||||
if (rmd == NULL){
|
||||
/* case of a reINVITE or UPDATE without SDP */
|
||||
call->expect_media_in_ack = TRUE;
|
||||
sal_call_accept(op); /*respond with an offer*/
|
||||
/*don't do anything else in this case, wait for the ACK to receive to notify the app*/
|
||||
}else {
|
||||
SalMediaDescription *md;
|
||||
SalMediaDescription *prev_result_desc=call->resultdesc;
|
||||
|
||||
call->expect_media_in_ack = FALSE;
|
||||
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
|
||||
sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
|
||||
return;
|
||||
}
|
||||
if (is_update && prev_result_desc && md){
|
||||
int diff=sal_media_description_equals(prev_result_desc,md);
|
||||
if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){
|
||||
ms_warning("Cannot accept this update, it is changing parameters that require user approval");
|
||||
sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
call_updated(lc, call, op, is_update);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void call_ack(SalOp *op){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
|
||||
if (call == NULL){
|
||||
ms_warning("call_ack(): no call for which an ack is expected");
|
||||
return;
|
||||
}
|
||||
if (call->expect_media_in_ack){
|
||||
switch(call->state){
|
||||
case LinphoneCallStreamsRunning:
|
||||
case LinphoneCallPausedByRemote:
|
||||
linphone_call_set_state(call, LinphoneCallUpdatedByRemote, "UpdatedByRemote");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
process_call_accepted(lc, call, op);
|
||||
}
|
||||
}
|
||||
|
||||
static void call_terminated(SalOp *op, const char *from){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
|
|
@ -922,16 +911,11 @@ static void call_failure(SalOp *op){
|
|||
msg=_("Incompatible media parameters.");
|
||||
linphone_core_notify_display_status(lc,msg);
|
||||
break;
|
||||
case SalReasonRequestPending:
|
||||
/*restore previous state, the application will decide to resubmit the action if relevant*/
|
||||
linphone_call_set_state(call,call->prevstate,msg);
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
linphone_core_notify_display_status(lc,_("Call failed."));
|
||||
}
|
||||
|
||||
/*some call error are not fatal*/
|
||||
/*some call errors are not fatal*/
|
||||
switch (call->state) {
|
||||
case LinphoneCallUpdating:
|
||||
case LinphoneCallPausing:
|
||||
|
|
|
|||
|
|
@ -43,11 +43,15 @@ static const char *EC_STATE_STORE = ".linphone.ecstate";
|
|||
static void linphone_call_stats_uninit(LinphoneCallStats *stats);
|
||||
static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr);
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
|
||||
MSWebCam *get_nowebcam_device(){
|
||||
#ifdef VIDEO_ENABLED
|
||||
return ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),"StaticImage: Static picture");
|
||||
}
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static bool_t generate_b64_crypto_key(int key_length, char* key_out, size_t key_out_size) {
|
||||
int b64_size;
|
||||
|
|
@ -818,9 +822,6 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
|
|||
|
||||
linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO);
|
||||
linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO);
|
||||
#ifdef VIDEO_ENABLED
|
||||
call->cam = call->core->video_conf.device;
|
||||
#endif
|
||||
}
|
||||
|
||||
void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
|
||||
|
|
@ -948,6 +949,7 @@ void linphone_call_fill_media_multicast_addr(LinphoneCall *call) {
|
|||
} else
|
||||
call->media_ports[1].multicast_ip[0]='\0';
|
||||
}
|
||||
|
||||
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){
|
||||
LinphoneCall *call = belle_sip_object_new(LinphoneCall);
|
||||
|
||||
|
|
@ -955,7 +957,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
|
|||
call->core=lc;
|
||||
linphone_call_outgoing_select_ip_version(call,to,cfg);
|
||||
linphone_call_get_local_ip(call, to);
|
||||
linphone_call_init_common(call,from,to);
|
||||
linphone_call_init_common(call, from, to);
|
||||
call->params = linphone_call_params_copy(params);
|
||||
|
||||
linphone_call_fill_media_multicast_addr(call);
|
||||
|
|
@ -1260,7 +1262,7 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
|
|||
call->prevstate=call->state;
|
||||
if (call->state==LinphoneCallEnd || call->state==LinphoneCallError){
|
||||
if (cstate!=LinphoneCallReleased){
|
||||
ms_warning("Spurious call state change from %s to %s, ignored." ,linphone_call_state_to_string(call->state)
|
||||
ms_fatal("Spurious call state change from %s to %s, ignored." ,linphone_call_state_to_string(call->state)
|
||||
,linphone_call_state_to_string(cstate));
|
||||
return;
|
||||
}
|
||||
|
|
@ -2547,9 +2549,8 @@ static RtpSession * create_audio_rtp_io_session(LinphoneCall *call) {
|
|||
return rtp_session;
|
||||
}
|
||||
|
||||
static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){
|
||||
static void linphone_call_start_audio_stream(LinphoneCall *call, LinphoneCallState next_state, bool_t use_arc){
|
||||
LinphoneCore *lc=call->core;
|
||||
LpConfig* conf;
|
||||
int used_pt=-1;
|
||||
char rtcp_tool[128]={0};
|
||||
const SalStreamDescription *stream;
|
||||
|
|
@ -2586,26 +2587,24 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b
|
|||
if (captcard==NULL) {
|
||||
ms_warning("No card defined for capture !");
|
||||
}
|
||||
/*Replace soundcard filters by inactive file players or recorders
|
||||
when placed in recvonly or sendonly mode*/
|
||||
/*Don't use file or soundcard capture when placed in recv-only mode*/
|
||||
if (stream->rtp_port==0
|
||||
|| stream->dir==SalStreamRecvOnly
|
||||
|| (stream->multicast_role == SalMulticastReceiver && is_multicast)){
|
||||
captcard=NULL;
|
||||
playfile=NULL;
|
||||
}else if (stream->dir==SalStreamSendOnly){
|
||||
}
|
||||
if (next_state == LinphoneCallPaused){
|
||||
/*in paused state, we never use soundcard*/
|
||||
playcard=NULL;
|
||||
/*jehan: why capture card should be null in this case ? Not very good to only rely on stream dir to detect paused state.
|
||||
* It can also be a simple call in one way audio*/
|
||||
captcard=NULL;
|
||||
recfile=NULL;
|
||||
/*And we will eventually play "playfile" if set by the user*/
|
||||
}
|
||||
if (send_ringbacktone){
|
||||
conf = linphone_core_get_config(lc);
|
||||
if (call->playing_ringbacktone){
|
||||
captcard=NULL;
|
||||
playfile=NULL;/* it is setup later*/
|
||||
if( conf && lp_config_get_int(conf,"sound","send_ringback_without_playback", 0) == 1){
|
||||
if (lp_config_get_int(lc->config,"sound","send_ringback_without_playback", 0) == 1){
|
||||
playcard = NULL;
|
||||
recfile = NULL;
|
||||
}
|
||||
|
|
@ -2629,7 +2628,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b
|
|||
if (captcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(captcard, stream->max_rate);
|
||||
audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc);
|
||||
media_stream_set_adaptive_bitrate_algorithm(&call->audiostream->ms,
|
||||
ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc)));
|
||||
ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc)));
|
||||
audio_stream_enable_adaptive_jittcomp(call->audiostream, linphone_core_audio_adaptive_jittcomp_enabled(lc));
|
||||
rtp_session_set_jitter_compensation(call->audiostream->ms.sessions.rtp_session,linphone_core_get_audio_jittcomp(lc));
|
||||
if (!call->params->in_conference && call->params->record_file){
|
||||
|
|
@ -2686,22 +2685,22 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b
|
|||
used_pt,
|
||||
&io
|
||||
);
|
||||
post_configure_audio_streams(call, muted && !send_ringbacktone);
|
||||
post_configure_audio_streams(call, (call->all_muted || call->audio_muted) && !call->playing_ringbacktone);
|
||||
}
|
||||
|
||||
ms_media_stream_sessions_set_encryption_mandatory(&call->audiostream->ms.sessions,linphone_core_is_media_encryption_mandatory(call->core));
|
||||
|
||||
if (stream->dir==SalStreamSendOnly && playfile!=NULL){
|
||||
if (next_state == LinphoneCallPaused && captcard == NULL && playfile != NULL){
|
||||
int pause_time=500;
|
||||
ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
|
||||
}
|
||||
if (send_ringbacktone){
|
||||
if (call->playing_ringbacktone){
|
||||
setup_ring_player(lc,call);
|
||||
}
|
||||
|
||||
if (call->params->in_conference){
|
||||
/*transform the graph to connect it to the conference filter */
|
||||
mute=stream->dir==SalStreamRecvOnly;
|
||||
mute = stream->dir==SalStreamRecvOnly;
|
||||
linphone_call_add_to_conf(call, mute);
|
||||
}
|
||||
call->current_params->in_conference=call->params->in_conference;
|
||||
|
|
@ -2737,7 +2736,7 @@ static RtpSession * create_video_rtp_io_session(LinphoneCall *call) {
|
|||
}
|
||||
#endif
|
||||
|
||||
static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inputs_muted){
|
||||
static void linphone_call_start_video_stream(LinphoneCall *call, LinphoneCallState next_state){
|
||||
#ifdef VIDEO_ENABLED
|
||||
LinphoneCore *lc=call->core;
|
||||
int used_pt=-1;
|
||||
|
|
@ -2810,11 +2809,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu
|
|||
/*either inactive or incompatible with local capabilities*/
|
||||
is_inactive=TRUE;
|
||||
}
|
||||
if (all_inputs_muted){
|
||||
cam=get_nowebcam_device();
|
||||
} else {
|
||||
cam = linphone_call_get_video_device(call);
|
||||
}
|
||||
cam = linphone_call_get_video_device(call);
|
||||
if (!is_inactive){
|
||||
if (sal_stream_description_has_srtp(vstream) == TRUE) {
|
||||
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, vstream->crypto_local_tag);
|
||||
|
|
@ -2934,13 +2929,29 @@ static void setZrtpCryptoTypesParameters(MSZrtpParams *params, LinphoneCore *lc)
|
|||
params->keyAgreementsCount = linphone_core_get_zrtp_key_agreement_suites(lc, params->keyAgreements);
|
||||
}
|
||||
|
||||
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone){
|
||||
void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState next_state){
|
||||
LinphoneCore *lc=call->core;
|
||||
bool_t use_arc=linphone_core_adaptive_rate_control_enabled(lc);
|
||||
bool_t use_arc = linphone_core_adaptive_rate_control_enabled(lc);
|
||||
#ifdef VIDEO_ENABLED
|
||||
const SalStreamDescription *vstream=sal_media_description_find_best_stream(call->resultdesc,SalVideo);
|
||||
#endif
|
||||
|
||||
switch (next_state){
|
||||
case LinphoneCallIncomingEarlyMedia:
|
||||
if (linphone_core_get_remote_ringback_tone(lc)){
|
||||
call->playing_ringbacktone = TRUE;
|
||||
}
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
if (!call->params->real_early_media){
|
||||
call->all_muted = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
call->playing_ringbacktone = FALSE;
|
||||
call->all_muted = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
call->current_params->audio_codec = NULL;
|
||||
call->current_params->video_codec = NULL;
|
||||
|
||||
|
|
@ -2958,18 +2969,16 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
|
|||
call, linphone_core_get_upload_bandwidth(lc),linphone_core_get_download_bandwidth(lc));
|
||||
|
||||
if (call->audiostream!=NULL) {
|
||||
linphone_call_start_audio_stream(call,all_inputs_muted||call->audio_muted,send_ringbacktone,use_arc);
|
||||
linphone_call_start_audio_stream(call, next_state, use_arc);
|
||||
} else {
|
||||
ms_warning("DTLS no audio stream!");
|
||||
}
|
||||
call->current_params->has_video=FALSE;
|
||||
if (call->videostream!=NULL) {
|
||||
if (call->audiostream) audio_stream_link_video(call->audiostream,call->videostream);
|
||||
linphone_call_start_video_stream(call,all_inputs_muted);
|
||||
linphone_call_start_video_stream(call, next_state);
|
||||
}
|
||||
|
||||
call->all_muted=all_inputs_muted;
|
||||
call->playing_ringbacktone=send_ringbacktone;
|
||||
call->up_bw=linphone_core_get_upload_bandwidth(lc);
|
||||
|
||||
/*might be moved in audio/video stream_start*/
|
||||
|
|
@ -4141,14 +4150,14 @@ void linphone_call_set_native_video_window_id(LinphoneCall *call, void *id) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
|
||||
MSWebCam *linphone_call_get_video_device(const LinphoneCall *call) {
|
||||
if (call->camera_enabled==FALSE)
|
||||
if (call->all_muted || call->camera_enabled == FALSE)
|
||||
return get_nowebcam_device();
|
||||
else
|
||||
return call->cam;
|
||||
return call->core->video_conf.device;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void linphone_call_set_audio_route(LinphoneCall *call, LinphoneAudioRoute route) {
|
||||
if (call != NULL && call->audiostream != NULL){
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ static ortp_mutex_t liblinphone_log_collection_mutex;
|
|||
static bool_t liblinphone_serialize_logs = FALSE;
|
||||
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime);
|
||||
static void linphone_core_run_hooks(LinphoneCore *lc);
|
||||
static void linphone_core_free_hooks(LinphoneCore *lc);
|
||||
|
||||
#include "enum.h"
|
||||
#include "contact_providers_priv.h"
|
||||
|
|
@ -1590,7 +1589,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
|
|||
lc->config=lp_config_ref(config);
|
||||
lc->data=userdata;
|
||||
lc->ringstream_autorelease=TRUE;
|
||||
|
||||
linphone_task_list_init(&lc->hooks);
|
||||
|
||||
memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable));
|
||||
_linphone_core_add_listener(lc, local_vtable, TRUE);
|
||||
|
|
@ -3177,11 +3176,11 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall*
|
|||
sal_op_set_sent_custom_header ( call->op,params->custom_headers );
|
||||
}
|
||||
|
||||
sal_call_notify_ringing(call->op,TRUE);
|
||||
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);
|
||||
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));
|
||||
|
|
@ -3273,6 +3272,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
|
|||
break;
|
||||
case LinphoneCallStreamsRunning:
|
||||
case LinphoneCallPaused:
|
||||
case LinphoneCallPausedByRemote:
|
||||
nextstate=LinphoneCallUpdating;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -3329,7 +3329,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
|
|||
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,call->cam = lc->video_conf.device);
|
||||
video_stream_change_camera(call->videostream, lc->video_conf.device);
|
||||
}else video_stream_update_video_params(call->videostream);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -3378,7 +3378,7 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call,
|
|||
sal_call_accept(call->op);
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
if (md && !sal_media_description_empty(md)){
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
linphone_core_update_streams(lc, call, md, next_state);
|
||||
linphone_call_fix_call_parameters(call);
|
||||
}
|
||||
linphone_call_set_state(call,next_state,state_info);
|
||||
|
|
@ -3613,7 +3613,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
|
|||
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
|
||||
new_md=sal_call_get_final_media_description(call->op);
|
||||
if (new_md){
|
||||
linphone_core_update_streams(lc, call, new_md);
|
||||
linphone_core_update_streams(lc, call, new_md, LinphoneCallStreamsRunning);
|
||||
linphone_call_fix_call_parameters(call);
|
||||
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}else call->expect_media_in_ack=TRUE;
|
||||
|
|
@ -6096,7 +6096,7 @@ LpConfig * linphone_core_create_lp_config(LinphoneCore *lc, const char *filename
|
|||
|
||||
static void linphone_core_uninit(LinphoneCore *lc)
|
||||
{
|
||||
linphone_core_free_hooks(lc);
|
||||
linphone_task_list_free(&lc->hooks);
|
||||
lc->video_conf.show_local = FALSE;
|
||||
|
||||
while(lc->calls)
|
||||
|
|
@ -6558,47 +6558,18 @@ void linphone_core_set_max_calls(LinphoneCore *lc, int max) {
|
|||
lc->max_calls=max;
|
||||
}
|
||||
|
||||
typedef struct Hook{
|
||||
LinphoneCoreIterateHook fun;
|
||||
void *data;
|
||||
}Hook;
|
||||
|
||||
static Hook *hook_new(LinphoneCoreIterateHook hook, void *hook_data){
|
||||
Hook *h=ms_new0(Hook,1);
|
||||
h->fun=hook;
|
||||
h->data=hook_data;
|
||||
return h;
|
||||
}
|
||||
|
||||
static void hook_invoke(Hook *h){
|
||||
h->fun(h->data);
|
||||
}
|
||||
|
||||
void linphone_core_add_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data){
|
||||
lc->hooks=ms_list_append(lc->hooks,hook_new(hook,hook_data));
|
||||
linphone_task_list_add(&lc->hooks, hook, hook_data);
|
||||
}
|
||||
|
||||
static void linphone_core_run_hooks(LinphoneCore *lc){
|
||||
ms_list_for_each(lc->hooks,(void (*)(void*))hook_invoke);
|
||||
}
|
||||
|
||||
static void linphone_core_free_hooks(LinphoneCore *lc){
|
||||
ms_list_for_each(lc->hooks,(void (*)(void*))ms_free);
|
||||
ms_list_free(lc->hooks);
|
||||
lc->hooks=NULL;
|
||||
linphone_task_list_run(&lc->hooks);
|
||||
}
|
||||
|
||||
void linphone_core_remove_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data){
|
||||
MSList *elem;
|
||||
for(elem=lc->hooks;elem!=NULL;elem=elem->next){
|
||||
Hook *h=(Hook*)elem->data;
|
||||
if (h->fun==hook && h->data==hook_data){
|
||||
lc->hooks = ms_list_remove_link(lc->hooks,elem);
|
||||
ms_free(h);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ms_error("linphone_core_remove_iterate_hook(): No such hook found.");
|
||||
linphone_task_list_remove(&lc->hooks, hook, hook_data);
|
||||
|
||||
}
|
||||
|
||||
void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file){
|
||||
|
|
|
|||
|
|
@ -1788,3 +1788,49 @@ const char *linphone_tunnel_mode_to_string(LinphoneTunnelMode mode) {
|
|||
return "invalid";
|
||||
}
|
||||
|
||||
|
||||
typedef struct Hook{
|
||||
LinphoneCoreIterateHook fun;
|
||||
void *data;
|
||||
}Hook;
|
||||
|
||||
void linphone_task_list_init(LinphoneTaskList *t){
|
||||
t->hooks = NULL;
|
||||
}
|
||||
|
||||
static Hook *hook_new(LinphoneCoreIterateHook hook, void *hook_data){
|
||||
Hook *h=ms_new0(Hook,1);
|
||||
h->fun=hook;
|
||||
h->data=hook_data;
|
||||
return h;
|
||||
}
|
||||
|
||||
static void hook_invoke(Hook *h){
|
||||
h->fun(h->data);
|
||||
}
|
||||
|
||||
void linphone_task_list_add(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data){
|
||||
t->hooks = ms_list_append(t->hooks,hook_new(hook,hook_data));
|
||||
}
|
||||
|
||||
void linphone_task_list_remove(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data){
|
||||
MSList *elem;
|
||||
for(elem=t->hooks;elem!=NULL;elem=elem->next){
|
||||
Hook *h=(Hook*)elem->data;
|
||||
if (h->fun==hook && h->data==hook_data){
|
||||
t->hooks = ms_list_remove_link(t->hooks,elem);
|
||||
ms_free(h);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ms_error("linphone_task_list_remove(): No such hook found.");
|
||||
}
|
||||
|
||||
void linphone_task_list_run(LinphoneTaskList *t){
|
||||
ms_list_for_each(t->hooks,(void (*)(void*))hook_invoke);
|
||||
}
|
||||
|
||||
void linphone_task_list_free(LinphoneTaskList *t){
|
||||
t->hooks = ms_list_free_with_data(t->hooks, (void (*)(void*))ms_free);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -295,7 +295,6 @@ struct _LinphoneCall{
|
|||
belle_sip_source_t *dtmfs_timer; /*DTMF timer needed to send a DTMF sequence*/
|
||||
|
||||
char *dtls_certificate_fingerprint; /**> This fingerprint is computed during stream init and is stored in call to be used when making local media description */
|
||||
MSWebCam *cam; /*webcam use for this call*/
|
||||
bool_t refer_pending;
|
||||
bool_t expect_media_in_ack;
|
||||
bool_t audio_muted;
|
||||
|
|
@ -450,7 +449,7 @@ void linphone_call_fix_call_parameters(LinphoneCall *call);
|
|||
void linphone_call_init_audio_stream(LinphoneCall *call);
|
||||
void linphone_call_init_video_stream(LinphoneCall *call);
|
||||
void linphone_call_init_media_streams(LinphoneCall *call);
|
||||
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone);
|
||||
void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState target_state);
|
||||
void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call);
|
||||
void linphone_call_stop_media_streams(LinphoneCall *call);
|
||||
void linphone_call_delete_ice_session(LinphoneCall *call);
|
||||
|
|
@ -757,6 +756,16 @@ const char *linphone_core_get_tone_file(const LinphoneCore *lc, LinphoneToneID i
|
|||
int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info);
|
||||
typedef struct _LinphoneConference LinphoneConference;
|
||||
|
||||
typedef struct _LinphoneTaskList{
|
||||
MSList *hooks;
|
||||
}LinphoneTaskList;
|
||||
|
||||
void linphone_task_list_init(LinphoneTaskList *t);
|
||||
void linphone_task_list_add(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data);
|
||||
void linphone_task_list_remove(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data);
|
||||
void linphone_task_list_run(LinphoneTaskList *t);
|
||||
void linphone_task_list_free(LinphoneTaskList *t);
|
||||
|
||||
struct _LinphoneCore
|
||||
{
|
||||
MSList* vtable_refs;
|
||||
|
|
@ -804,7 +813,7 @@ struct _LinphoneCore
|
|||
void *preview_window_id;
|
||||
time_t netup_time; /*time when network went reachable */
|
||||
struct _EcCalibrator *ecc;
|
||||
MSList *hooks;
|
||||
LinphoneTaskList hooks; /*tasks periodically executed in linphone_core_iterate()*/
|
||||
LinphoneConference conf_ctx;
|
||||
char* zrtp_secrets_cache;
|
||||
char* user_certificates_path;
|
||||
|
|
@ -892,7 +901,7 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
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);
|
||||
void linphone_core_update_streams(LinphoneCore *lc, 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -288,9 +288,9 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
|
|||
BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1));
|
||||
BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1));
|
||||
|
||||
result = wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+1)
|
||||
result = wait_for_until(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+1, 2000)
|
||||
&&
|
||||
wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1);
|
||||
wait_for_until(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1, 2000);
|
||||
|
||||
if (linphone_core_get_media_encryption(caller_mgr->lc) != LinphoneMediaEncryptionNone
|
||||
|| linphone_core_get_media_encryption(callee_mgr->lc) != LinphoneMediaEncryptionNone) {
|
||||
|
|
@ -4112,7 +4112,7 @@ static void video_call_with_re_invite_inactive_followed_by_re_invite_base(Linpho
|
|||
linphone_call_params_destroy(params);
|
||||
|
||||
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,1));
|
||||
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallPaused,1));
|
||||
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallPausedByRemote,1));
|
||||
|
||||
check_media_direction(marie,linphone_core_get_current_call(marie->lc),lcs,LinphoneMediaDirectionInactive,LinphoneMediaDirectionInactive);
|
||||
|
|
@ -4122,19 +4122,13 @@ static void video_call_with_re_invite_inactive_followed_by_re_invite_base(Linpho
|
|||
linphone_core_enable_sdp_200_ack(marie->lc,TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
currently update call cannot be used in paused state, might not be good.
|
||||
params=linphone_core_create_call_params(marie->lc,linphone_core_get_current_call(marie->lc));
|
||||
linphone_call_params_set_audio_direction(params,LinphoneMediaDirectionSendRecv);
|
||||
linphone_call_params_set_video_direction(params,LinphoneMediaDirectionSendRecv);
|
||||
linphone_core_update_call(marie->lc,linphone_core_get_current_call(marie->lc),params);
|
||||
linphone_call_params_destroy(params);
|
||||
*/
|
||||
|
||||
linphone_core_resume_call(marie->lc,linphone_core_get_current_call(marie->lc));
|
||||
|
||||
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallResuming,1));
|
||||
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
|
||||
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,3));
|
||||
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
|
||||
check_media_direction(marie,linphone_core_get_current_call(marie->lc),lcs,LinphoneMediaDirectionSendRecv,LinphoneMediaDirectionSendRecv);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue