diff --git a/console/commands.c b/console/commands.c index 6d0d005..ac26249 100644 --- a/console/commands.c +++ b/console/commands.c @@ -550,14 +550,16 @@ lpc_cmd_call(LinphoneCore *lc, char *args) { LinphoneCall *call; LinphoneCallParams *cp=linphone_core_create_default_call_parameters (lc); - char *opt1,*opt2; + char *opt1,*opt2,*opt3; if ( linphone_core_in_call(lc) ) { - linphonec_out("Terminate or hold on the current call first.\n"); - return 1; + //linphonec_out("Terminate or hold on the current call first.\n"); + //return 1; + linphonec_out("The call is processing in pause\n"); } opt1=strstr(args,"--audio-only"); opt2=strstr(args,"--early-media"); + opt3=strstr(args,"--on-hold"); if (opt1){ opt1[0]='\0'; linphone_call_params_enable_video (cp,FALSE); @@ -566,6 +568,10 @@ lpc_cmd_call(LinphoneCore *lc, char *args) opt2[0]='\0'; linphone_call_params_enable_early_media_sending(cp,TRUE); } + if (opt3){ + opt3[0]='\0'; + linphone_call_params_set_on_hold (cp,TRUE); + } if ( NULL == (call=linphone_core_invite_with_params(lc, args,cp)) ) { linphonec_out("Error from linphone_core_invite.\n"); @@ -1383,7 +1389,7 @@ static int lpc_cmd_resume(LinphoneCore *lc, char *args){ if(linphone_core_in_call(lc)) { - linphonec_out("There is already a call in process pause or stop it first"); + linphonec_out("There is already a call in process pause or stop it first\n"); return 1; } if (args) @@ -1953,7 +1959,7 @@ static int lpc_cmd_status(LinphoneCore *lc, char *args) LinphoneCallState call_state=LinphoneCallIdle; if (call) call_state=linphone_call_get_state(call); - switch(call_state){ + switch(call_state){ case LinphoneCallOutgoingInit: linphonec_out("hook=outgoing_init sip:%s\n",linphonec_get_callee()); break; diff --git a/console/linphonec.c b/console/linphonec.c index d3bba84..b1d3c97 100644 --- a/console/linphonec.c +++ b/console/linphonec.c @@ -365,6 +365,12 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L case LinphoneCallUpdatedByRemote: linphonec_call_updated(call); break; + case LinphoneCallResumed: + linphonec_out("Call %i with %s is now resumed.\n", id, from); + break; + case LinphoneCallResumedByRemote: + linphonec_out("Call %i with %s is now resumed by remote.\n", id, from); + break; case LinphoneCallOutgoingProgress: linphonec_out("Call %i to %s in progress.\n", id, from); break; @@ -380,6 +386,9 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L case LinphoneCallError: linphonec_out("Call %i with %s error.\n", id, from); break; + case LinphoneCallPausedAndPausedByRemote: + linphonec_out("Call %i is paused by us and the remote too\n"); + break; default: break; } @@ -393,7 +402,7 @@ static void linphonec_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, const LinphoneAddress *from, const char *msg) { - linphonec_out("Message received from %s: %s\n", linphone_address_as_string(from), msg); + linphonec_out("%s: %s\n", linphone_address_as_string(from), msg); // TODO: provide mechanism for answering.. ('say' command?) } @@ -718,7 +727,7 @@ linphonec_init(int argc, char **argv) */ linphonec=linphone_core_new (&linphonec_vtable, configfile_name, factory_configfile_name, NULL); linphone_core_enable_video(linphonec,vcap_enabled,display_enabled); - if (display_enabled && window_id != 0) + if (display_enabled && window_id != 0) { printf ("Setting window_id: 0x%x\n", window_id); linphone_core_set_native_video_window_id(linphonec,window_id); diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index bf60f4c..b6c5ab5 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -33,7 +33,7 @@ static bool_t media_parameters_changed(LinphoneCall *call, SalMediaDescription * void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){ SalMediaDescription *oldmd=call->resultdesc; - + if (lc->ringstream!=NULL){ ring_stop(lc->ringstream); lc->ringstream=NULL; @@ -70,13 +70,13 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia linphone_call_stop_media_streams (call); linphone_call_init_media_streams (call); } - if (oldmd) + if (oldmd) sal_media_description_unref(oldmd); - + if (new_md) { bool_t all_muted=FALSE; bool_t send_ringbacktone=FALSE; - + if (call->audiostream==NULL){ /*this happens after pausing the call locally. The streams is destroyed and then we wait the 200Ok to recreate it*/ linphone_call_init_media_streams (call); @@ -88,7 +88,10 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia (call->state==LinphoneCallOutgoingEarlyMedia && !call->params.real_early_media)){ all_muted=TRUE; } - linphone_call_start_media_streams(call,all_muted,send_ringbacktone); + if(call->state != LinphoneCallPaused && call->state != LinphoneCallPausedByRemote && call->state != LinphoneCallPausedAndPausedByRemote) + linphone_call_start_media_streams(call,all_muted,send_ringbacktone); + else + ms_message("Do not start the media stream when paused"); } } @@ -153,13 +156,13 @@ static void call_received(SalOp *h){ call=linphone_call_new_incoming(lc,from_addr,to_addr,h); sal_call_set_local_media_description(h,call->localdesc); md=sal_call_get_final_media_description(h); - if (md && sal_media_description_empty(md)){ sal_call_decline(h,SalReasonMedia,NULL); linphone_call_unref(call); return; } + /* the call is acceptable so we can now add it to our list */ linphone_core_add_call(lc,call); @@ -175,7 +178,8 @@ static void call_received(SalOp *h){ /* play the ring if this is the only call*/ if (lc->sound_conf.ring_sndcard!=NULL && ms_list_size(lc->calls)==1){ - lc->current_call=call; + //AUREL : Should not be done here ...we won't be able to do correct multiple calls + //lc->current_call=call; if (lc->ringstream && lc->dmfs_playing_start_time!=0){ ring_stop(lc->ringstream); lc->ringstream=NULL; @@ -193,11 +197,9 @@ static void call_received(SalOp *h){ }else{ /*TODO : play a tone within the context of the current call */ } - linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */ linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call"); - if (call->state==LinphoneCallIncomingReceived){ sal_call_notify_ringing(h,propose_early_media || ringback_tone!=NULL); @@ -210,7 +212,6 @@ static void call_received(SalOp *h){ } } linphone_call_unref(call); - ms_free(barmesg); ms_free(tmp); } @@ -232,12 +233,13 @@ static void call_ringing(SalOp *h){ lc->ringstream=NULL; lc->dmfs_playing_start_time=0; } + //we have to inform that we received a ringing here because we could ring and receive a ringing from another call in process + linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing"); if (lc->ringstream!=NULL) return; /*already ringing !*/ if (lc->sound_conf.play_sndcard!=NULL){ MSSndCard *ringcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; ms_message("Remote ringing..."); lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard); - linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing"); } }else{ /*accept early media */ @@ -255,7 +257,7 @@ static void call_ringing(SalOp *h){ lc->ringstream=NULL; } ms_message("Doing early media..."); - linphone_core_update_streams (lc,call,md); + linphone_core_update_streams(lc,call,md); } } @@ -268,14 +270,14 @@ 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; - + if (call==NULL){ ms_warning("No call to accept."); return ; } - + md=sal_call_get_final_media_description(op); - + if (call->state==LinphoneCallOutgoingProgress || call->state==LinphoneCallOutgoingRinging || call->state==LinphoneCallOutgoingEarlyMedia){ @@ -284,6 +286,7 @@ static void call_accepted(SalOp *op){ if (md && !sal_media_description_empty(md)){ if (sal_media_description_has_dir(md,SalStreamSendOnly) || sal_media_description_has_dir(md,SalStreamInactive)){ + //pausing state if (lc->vtable.display_status){ char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp); @@ -291,8 +294,11 @@ static void call_accepted(SalOp *op){ ms_free(tmp); ms_free(msg); } - linphone_core_update_streams (lc,call,md); - linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); + linphone_core_update_streams(lc,call,md); + if (call->state==LinphoneCallPausing) + linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); + else if (call->state==LinphoneCallPausingAndPausedByRemote) + linphone_call_set_state(call,LinphoneCallPausedAndPausedByRemote,"Call paused while paused by remote"); }else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){ /*we are put on hold when the call is initially accepted */ if (lc->vtable.display_status){ @@ -302,19 +308,42 @@ static void call_accepted(SalOp *op){ ms_free(tmp); ms_free(msg); } - linphone_core_update_streams (lc,call,md); - linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); + linphone_core_update_streams(lc,call,md); + //AUREL can we be paused ourself too because of multicalls? + if(call->state == LinphoneCallPaused) + linphone_call_set_state(call,LinphoneCallPausedAndPausedByRemote,"Call paused and paused by remote"); + else + linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote"); }else{ - if (lc->vtable.display_status){ - lc->vtable.display_status(lc,_("Call answered - connected.")); - } - if (call->state==LinphoneCallStreamsRunning){ - /*media was running before, the remote as acceted a call modification (that is - a reinvite made by us. We must notify the application this reinvite was accepted*/ - linphone_call_set_state(call, LinphoneCallUpdated, "Call updated"); + //can we go through all those states ??!! + switch(call->state) + { + case LinphoneCallStreamsRunning : + /*media was running before, the remote as acceted a call modification (that is + a reinvite made by us. We must notify the application this reinvite was accepted*/ + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Call updated - connected.")); + linphone_call_set_state(call, LinphoneCallUpdated, "Call updated"); + break; + case LinphoneCallResuming : + case LinphoneCallConnected : + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Call resumed - connected.")); + linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams resumed)"); + break; + case LinphoneCallResumingAndPausedByRemote : + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Call resumed by paused by remote.")); + linphone_call_set_state(call,LinphoneCallPausedByRemote,"Paused by remote"); + //we do not have to go through update_streams and set_state to stream running + return; + break; + default : + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Call answered - connected.")); } linphone_core_update_streams (lc,call,md); - linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running"); + linphone_call_set_state(call,LinphoneCallStreamsRunning, "Streams running"); } }else{ /*send a bye*/ @@ -355,45 +384,96 @@ static void call_updating(SalOp *op){ LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); LinphoneCallState prevstate=LinphoneCallIdle; SalMediaDescription *md; - + md=sal_call_get_final_media_description(op); - - if (md && !sal_media_description_empty(md)) - { - if ((call->state==LinphoneCallPausedByRemote || call->state==LinphoneCallPaused) && - sal_media_description_has_dir(md,SalStreamSendRecv) && strcmp(md->addr,"0.0.0.0")!=0){ - /*make sure we can be resumed */ - if (lc->current_call!=NULL && lc->current_call!=call){ - ms_warning("Attempt to be resumed but already in call with somebody else!"); - /*we are actively running another call, reject with a busy*/ - sal_call_decline (op,SalReasonBusy,NULL); + + if (md ==NULL || sal_media_description_empty(md)) + return; + if (sal_media_description_has_dir(md,SalStreamSendRecv) && strcmp(md->addr,"0.0.0.0")!=0){ + //resume or resumed + /*make sure we can be resumed */ + // Remote can resume a call without being the current call + if (lc->current_call!=NULL && lc->current_call!=call && call->state != LinphoneCallPausedAndPausedByRemote){ + ms_warning("Attempt to be resumed but already in call with somebody else!"); + /*we are actively running another call, reject with a busy*/ + sal_call_decline (op,SalReasonBusy,NULL); + return; + } + // Remote want resume the call that we have paused : Forbidden +//when we get an update we do not have to send decline ... +// if ( call->state == LinphoneCallPaused ) +// { +// ms_warning("Attempt to be resumed but without having paused the call!"); +// /*we are actively running another call, reject with a busy*/ +// sal_call_decline (op,SalReasonBusy,NULL); +// return; +// } + + prevstate=call->state; + //if(lc->vtable.display_status) + // lc->vtable.display_status(lc,_("We have been resumed by the distant...")); + //if(prevstate != LinphoneCallPausedAndPausedByRemote) + // linphone_call_set_state (call,LinphoneCallResumedByRemote,"We have been resumed..."); + switch(prevstate) + { + case LinphoneCallPausedByRemote : + if(lc->vtable.display_status) + lc->vtable.display_status(lc,_("We have been resumed by the distant...")); + linphone_call_set_state (call,LinphoneCallResumedByRemote,"We have been resumed..."); + linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams resumed)"); + linphone_core_update_streams (lc,call,md); + lc->current_call = call;//we have to point the call as the current one + break; + case LinphoneCallPausedAndPausedByRemote : + if(lc->vtable.display_status) + lc->vtable.display_status(lc,_("We have been resumed by the distant...")); + linphone_call_set_state (call,LinphoneCallResumedByRemote,"We have been resumed..."); + linphone_call_set_state (call,LinphoneCallPaused,"We are still locally paused"); + break; + case LinphoneCallPaused : + case LinphoneCallStreamsRunning : + // When registered on a proxy, the proxy can send INVITE during communication + break; + default : + ms_warning("Attempt to be resumed without have being already paused by remote and already in paused status"); + sal_call_decline (op,SalReasonForbidden,NULL); return; - } - if(lc->vtable.display_status) - lc->vtable.display_status(lc,_("We have been resumed...")); - linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)"); } - else if(call->state==LinphoneCallStreamsRunning && - ( sal_media_description_has_dir(md,SalStreamRecvOnly) - || sal_media_description_has_dir(md,SalStreamInactive) - || strcmp(md->addr,"0.0.0.0")==0)){ - if(lc->vtable.display_status) - lc->vtable.display_status(lc,_("We are being paused...")); - linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote"); - if (lc->current_call!=call){ - ms_error("Inconsitency detected: current call is %p but call %p is being paused !",lc->current_call,call); + }else{ + if ( sal_media_description_has_dir(md,SalStreamRecvOnly) + || sal_media_description_has_dir(md,SalStreamInactive) + || strcmp(md->addr,"0.0.0.0")==0) + { + //pause or paused + switch(call->state) + { + case LinphoneCallStreamsRunning : + if(lc->vtable.display_status) + lc->vtable.display_status(lc,_("We are being paused...")); + linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote"); + linphone_core_update_streams (lc,call,md); + if (lc->current_call!=call) + ms_error("Inconsistency detected: current call is %p but call %p is being paused !",lc->current_call,call); + break; + case LinphoneCallPaused : + if(lc->vtable.display_status) + lc->vtable.display_status(lc,_("We are being paused while we paused the call...")); + linphone_call_set_state (call,LinphoneCallPausedAndPausedByRemote,"Call paused and paused by remote"); + break; + default: + break; } }else{ - prevstate=call->state; - linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote"); - } - /*accept the modification (sends a 200Ok)*/ - sal_call_accept(op); - linphone_core_update_streams (lc,call,md); - if (prevstate!=LinphoneCallIdle){ - linphone_call_set_state (call,prevstate,"Connected (streams running)"); + //if none resume nor pause asked + prevstate=call->state; + linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote"); + linphone_core_update_streams (lc,call,md); + if (prevstate!=LinphoneCallIdle && prevstate!=LinphoneCallPausedByRemote ) + linphone_call_set_state (call,prevstate,"Connected (streams updated)"); } } + /*accept the modification (sends a 200Ok)*/ + sal_call_accept(op); } static void call_terminated(SalOp *op, const char *from){ @@ -597,6 +677,7 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); if (call){ +#ifndef REFER_HANDLED_BY_EXTERNAL if (call->refer_to!=NULL){ ms_free(call->refer_to); } @@ -608,15 +689,31 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){ lc->vtable.display_status(lc,msg); ms_free(msg); } + sal_call_accept_refer(op); if (call->state!=LinphoneCallPaused){ ms_message("Automatically pausing current call to accept transfer."); linphone_core_pause_call(lc,call); } linphone_core_start_refered_call(lc,call); - sal_call_accept_refer(op); }else if (lc->vtable.refer_received){ lc->vtable.refer_received(lc,referto); sal_call_accept_refer(op); +#else + if (call->refer_to!=NULL){ + ms_free(call->refer_to); + } + call->refer_to=ms_strdup(referto); + linphone_call_set_state(call,LinphoneCallRefered,"Refered"); + if (lc->vtable.display_status){ + char *msg=ms_strdup_printf(_("We are transfered to %s"),referto); + lc->vtable.display_status(lc,msg); + ms_free(msg); + } + if (lc->vtable.refer_received){ + lc->vtable.refer_received(lc,referto); + if(op)sal_call_accept_refer(op); + } +#endif } } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 89e730a..e9de0a2 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -65,12 +65,11 @@ SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCa LinphoneAddress *addr=linphone_address_new(me); const char *username=linphone_address_get_username (addr); SalMediaDescription *md=sal_media_description_new(); - + md->nstreams=1; strncpy(md->addr,call->localip,sizeof(md->addr)); strncpy(md->username,username,sizeof(md->username)); md->bandwidth=linphone_core_get_download_bandwidth(lc); - /*set audio capabilities */ strncpy(md->streams[0].addr,call->localip,sizeof(md->streams[0].addr)); md->streams[0].port=call->audio_port; @@ -279,10 +278,20 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){ return "LinphoneCallPausedByRemote"; case LinphoneCallUpdatedByRemote: return "LinphoneCallUpdatedByRemote"; + case LinphoneCallResumed: + return "LinphoneCallResumed"; + case LinphoneCallResumedByRemote: + return "LinphoneCallResumedByRemote"; case LinphoneCallIncomingEarlyMedia: return "LinphoneCallIncomingEarlyMedia"; case LinphoneCallUpdated: return "LinphoneCallUpdated"; + case LinphoneCallPausingAndPausedByRemote: + return "LinphoneCallPausingAndPausedByRemote"; + case LinphoneCallPausedAndPausedByRemote: + return "LinphoneCallPausedAndPausedByRemote"; + case LinphoneCallResumingAndPausedByRemote: + return "LinphoneCallResumingAndPausedByRemote"; } return "undefined state"; } @@ -514,6 +523,20 @@ bool_t linphone_call_camera_enabled (const LinphoneCall *call){ /** * **/ +void linphone_call_params_set_on_hold(LinphoneCallParams *cp, bool_t on_hold){ + cp->on_hold=on_hold; +} + +/** + * +**/ +bool_t linphone_call_params_get_on_hold(const LinphoneCallParams *cp){ + return cp->on_hold; +} + +/** + * +**/ void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){ cp->has_video=enabled; } @@ -619,13 +642,15 @@ void linphone_call_init_media_streams(LinphoneCall *call){ static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'}; static void linphone_core_dtmf_received(RtpSession* s, int dtmf, void* user_data){ - LinphoneCore* lc = (LinphoneCore*)user_data; + LinphoneCall *call = (LinphoneCall*)user_data; + LinphoneCore* lc = call->core; if (dtmf<0 || dtmf>15){ ms_warning("Bad dtmf value %i",dtmf); return; } - if (lc->vtable.dtmf_received != NULL) - lc->vtable.dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]); + //we should not consider the DTMF received outside the current communication + if (lc->vtable.dtmf_received != NULL && call != NULL) + lc->vtable.dtmf_received(lc, call, dtmf_tab[dtmf]); } static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){ @@ -663,7 +688,7 @@ static void post_configure_audio_streams(LinphoneCall*call){ if (!call->audio_muted) audio_stream_set_mic_gain(st,mic_gain); - else + else audio_stream_set_mic_gain(st,0); recv_gain = lc->sound_conf.soft_play_lev; @@ -709,13 +734,10 @@ static void post_configure_audio_streams(LinphoneCall*call){ if (lc->vtable.dtmf_received!=NULL){ /* replace by our default action*/ audio_stream_play_received_dtmfs(call->audiostream,FALSE); - rtp_session_signal_connect(call->audiostream->session,"telephone-event",(RtpCallback)linphone_core_dtmf_received,(unsigned long)lc); + rtp_session_signal_connect(call->audiostream->session,"telephone-event",(RtpCallback)linphone_core_dtmf_received,(unsigned long)call); } } - - - static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){ int bw; const MSList *elem; @@ -773,7 +795,6 @@ static void setup_ring_player(LinphoneCore *lc, LinphoneCall *call){ ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time); } - void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone){ LinphoneCore *lc=call->core; LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc); @@ -784,7 +805,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc, SalProtoRtpAvp,SalVideo); #endif - + if(call->audiostream == NULL) { ms_fatal("start_media_stream() called without prior init !"); @@ -874,7 +895,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut } #ifdef VIDEO_ENABLED { - + used_pt=-1; /* shutdown preview */ if (lc->previewstream!=NULL) { @@ -928,8 +949,12 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut used_pt, jitt_comp, cam); video_stream_set_rtcp_information(call->videostream, cname,tool); } - }else ms_warning("No video stream accepted."); + }else{ + call->params.has_video=FALSE; + ms_warning("No video stream accepted."); + } }else{ + call->params.has_video=FALSE; ms_warning("No valid video stream defined."); } } @@ -937,7 +962,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut call->all_muted=all_inputs_muted; call->playing_ringbacktone=send_ringbacktone; call->up_bw=linphone_core_get_upload_bandwidth(lc); - + goto end; end: ms_free(cname); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 40d4257..cf9f37d 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -486,6 +486,7 @@ static void sip_config_read(LinphoneCore *lc) sal_use_session_timers(lc->sal,200); } + tmp=lp_config_get_int(lc->config,"sip","use_rfc2833",0); linphone_core_set_use_rfc2833_for_dtmf(lc,tmp); @@ -561,7 +562,7 @@ static void sip_config_read(LinphoneCore *lc) break; } } - + /*for tuning or test*/ lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0); lc->sip_conf.register_only_when_network_is_up= @@ -1693,7 +1694,7 @@ void linphone_core_iterate(LinphoneCore *lc){ if (call->videostream!=NULL) video_stream_iterate(call->videostream); #endif - if (call->audiostream!=NULL && disconnect_timeout>0) + if (call->audiostream!=NULL && call->state != LinphoneCallPausing && call->state != LinphoneCallPausedByRemote && call->state != LinphoneCallPaused && disconnect_timeout>0) disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout); } if (linphone_core_video_preview_enabled(lc)){ @@ -1933,7 +1934,7 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphonePro } real_url=linphone_address_as_string(call->log->to); from=linphone_address_as_string(call->log->from); - err=sal_call(call->op,from,real_url); + err=sal_call(call->op,from,real_url,call->params.on_hold); if (lc->sip_conf.sdp_200_ack){ call->media_pending=TRUE; @@ -2051,11 +2052,14 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const LinphoneProxyConfig *dest_proxy=NULL; LinphoneCall *call; - if (linphone_core_in_call(lc)){ + //TODO AUREL + /* + if (linphone_core_in_call(lc) && !(params->on_hold)){ if (lc->vtable.display_warning) lc->vtable.display_warning(lc,_("Sorry, you have to pause or stop the current call first !")); return NULL; } + */ if(!linphone_core_can_we_add_call(lc)){ if (lc->vtable.display_warning) lc->vtable.display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls")); @@ -2092,7 +2096,8 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const return NULL; } /* this call becomes now the current one*/ - lc->current_call=call; + if(!params->on_hold) + lc->current_call=call; linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call"); if (dest_proxy!=NULL || lc->sip_conf.ping_with_options==FALSE){ err=linphone_core_start_invite(lc,call,dest_proxy); @@ -2173,7 +2178,7 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){ * @return 0 if successful, -1 otherwise. **/ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ - int err=0; + int err = 0; if (params!=NULL){ if (call->localdesc) sal_media_description_unref(call->localdesc); @@ -2192,7 +2197,6 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho } #endif } - return err; } @@ -2227,7 +2231,7 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) if (call->state==LinphoneCallConnected){ /*call already accepted*/ - return -1; + return -2; } /* check if this call is supposed to replace an already running one*/ @@ -2243,7 +2247,7 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) if (lc->current_call!=NULL && lc->current_call!=call){ ms_warning("Cannot accept this call, there is already one running."); - return -1; + return -3; } /*can accept a new call only if others are on hold */ @@ -2251,9 +2255,15 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) MSList *elem; for(elem=lc->calls;elem!=NULL;elem=elem->next){ LinphoneCall *c=(LinphoneCall*)elem->data; - if (c!=call && (c->state!=LinphoneCallPaused && c->state!=LinphoneCallPausing)){ + if (c!=call && ( + c->state!=LinphoneCallPaused && + c->state!=LinphoneCallPausing && + c->state!=LinphoneCallPausedAndPausedByRemote && + c->state!=LinphoneCallPausingAndPausedByRemote && + c->state!=LinphoneCallIncomingReceived + )){ ms_warning("Cannot accept this call as another one is running, pause it before."); - return -1; + return -4; } } } @@ -2278,10 +2288,8 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) contact=get_fixed_contact(lc,call,dest_proxy); if (contact) sal_op_set_contact(call->op,contact); - if (call->audiostream==NULL) - linphone_call_init_media_streams(call); - + linphone_call_init_media_streams (call); sal_call_accept(call->op); if (lc->vtable.display_status!=NULL) lc->vtable.display_status(lc,_("Connected.")); @@ -2291,8 +2299,7 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) linphone_core_update_streams(lc, call, new_md); if (new_md){ linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)"); - }else call->media_pending=TRUE; - + }else call->media_pending=TRUE; ms_message("call answered."); return 0; } @@ -2421,7 +2428,10 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call) if (lc->vtable.display_warning) lc->vtable.display_warning(lc,_("Could not pause the call")); } - linphone_call_set_state(call,LinphoneCallPausing,"Pausing call"); + if (call->state==LinphoneCallStreamsRunning) + linphone_call_set_state(call,LinphoneCallPausing,"Pausing call"); + else if (call->state==LinphoneCallPausedByRemote) + linphone_call_set_state(call,LinphoneCallPausingAndPausedByRemote,"Pausing call while paused by remote"); if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Pausing the current call...")); lc->current_call=NULL; @@ -2455,7 +2465,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call) char temp[255]={0}; LinphoneCall *call = the_call; - if(call->state!=LinphoneCallPaused ){ + if(call->state!=LinphoneCallPaused && call->state!=LinphoneCallPausedAndPausedByRemote){ ms_warning("we cannot resume a call that has not been established and paused before"); return -1; } @@ -2469,7 +2479,10 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call) if(sal_call_hold(call->op,FALSE) != 0){ return -1; } - linphone_call_set_state (call,LinphoneCallResuming,"Resuming"); + if (call->state == LinphoneCallPaused) + linphone_call_set_state (call,LinphoneCallResuming,"Resuming"); + else if (call->state == LinphoneCallPausedAndPausedByRemote) + linphone_call_set_state (call,LinphoneCallResumingAndPausedByRemote,"Resuming while paused by remote"); snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",linphone_call_get_remote_address_as_string(call)); if (lc->vtable.display_status) lc->vtable.display_status(lc,temp); @@ -3333,7 +3346,6 @@ void linphone_core_set_native_video_window_id(LinphoneCore *lc, unsigned long id } #endif } - /** * Returns the native window handle of the video preview window, casted as an unsigned long. * @@ -3680,11 +3692,11 @@ void sip_config_uninit(LinphoneCore *lc) for (i=0;i<20;i++){ linphone_core_iterate(lc); -#ifndef WIN32 + #ifndef WIN32 usleep(100000); -#else + #else Sleep(100); -#endif + #endif } ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy); @@ -3846,6 +3858,9 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_core_free_payload_types(); + // Uninit Mediastreamer + ms_exit() ; + ortp_exit(); linphone_core_set_state(lc,LinphoneGlobalOff,"Off"); } @@ -3898,7 +3913,7 @@ void linphone_core_destroy(LinphoneCore *lc){ * @ingroup call_control **/ int linphone_core_get_calls_nb(const LinphoneCore *lc){ - return ms_list_size(lc->calls);; + return ms_list_size(lc->calls); } /** @@ -4019,6 +4034,9 @@ LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc){ LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc){ LinphoneCallParams *p=ms_new0(LinphoneCallParams,1); p->has_video=linphone_core_video_enabled(lc); + //TODO AUREL!! Not implemented yet because here we can generate calls in hold ... the upper API have to consider it... + //p->on_hold=linphone_core_in_call(lc)?TRUE:FALSE; + p->on_hold=FALSE; return p; } @@ -4035,4 +4053,3 @@ const char *linphone_error_to_string(LinphoneReason err){ } return "unknown error"; } - diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 8726167..4cc99e4 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -169,13 +169,15 @@ char * linphone_call_log_to_str(LinphoneCallLog *cl); /** * The LinphoneCallParams is an object containing various call related parameters. - * It can be used to retrieve parameters from a currently running call or modify the call's characteristics + * It can be used to retrieve parameters from a currently running call or modify the call's characteristics * dynamically. **/ struct _LinphoneCallParams; typedef struct _LinphoneCallParams LinphoneCallParams; LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp); +void linphone_call_params_set_on_hold(LinphoneCallParams *cp, bool_t on_hold); +bool_t linphone_call_params_get_on_hold(const LinphoneCallParams *cp); void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled); bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp); void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled); @@ -220,8 +222,14 @@ typedef enum _LinphoneCallState{ LinphoneCallEnd, /**nstreams;++i){ const SalStreamDescription *ss=&md->streams[i]; - if (ss->dir==stream_dir) found=TRUE; - else{ - if (ss->dir!=SalStreamInactive) return FALSE; - } + if (ss->dir==stream_dir) + return TRUE; } - return found; + return FALSE; } /* @@ -285,3 +282,4 @@ void sal_auth_info_delete(const SalAuthInfo* auth_info) { if (auth_info->password) ms_free(auth_info->password); ms_free((void*)auth_info); } + diff --git a/coreapi/sal.h b/coreapi/sal.h index 4086dd1..049f9a2 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -280,7 +280,7 @@ void *sal_op_get_user_pointer(const SalOp *op); /*Call API*/ int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc); -int sal_call(SalOp *h, const char *from, const char *to); +int sal_call(SalOp *h, const char *from, const char *to, bool_t holdon); int sal_call_notify_ringing(SalOp *h, bool_t early_media); /*accept an incoming call or, during a call accept a reINVITE*/ int sal_call_accept(SalOp*h); diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c index 315c566..271b404 100644 --- a/coreapi/sal_eXosip2.c +++ b/coreapi/sal_eXosip2.c @@ -213,6 +213,7 @@ void sal_op_release(SalOp *op){ if (op->auth_info) { sal_auth_info_delete(op->auth_info); } + __sal_op_free(op); } @@ -460,7 +461,7 @@ static void sdp_process(SalOp *h){ offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec); h->sdp_answer=media_description_to_sdp(h->result); /*once we have generated the SDP answer, we modify the result description for processing by the upper layer. - It should contains media parameters constraint from the remote offer, not our response*/ + It should contains media parameters constraint from the remote offer, not our response*/ strcpy(h->result->addr,h->base.remote_media->addr); h->result->bandwidth=h->base.remote_media->bandwidth; for(i=0;iresult->nstreams;++i){ @@ -484,7 +485,7 @@ int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc){ return 0; } -int sal_call(SalOp *h, const char *from, const char *to){ +int sal_call(SalOp *h, const char *from, const char *to, bool_t holdon){ int err; osip_message_t *invite=NULL; sal_op_set_from(h,from); @@ -506,6 +507,7 @@ int sal_call(SalOp *h, const char *from, const char *to){ } if (h->base.local_media){ h->sdp_offering=TRUE; + sal_media_description_set_dir(h->base.local_media, holdon ? SalStreamSendOnly : SalStreamSendRecv); set_sdp_from_desc(invite,h->base.local_media); }else h->sdp_offering=FALSE; if (h->replaces){ @@ -782,6 +784,7 @@ void sal_op_authenticate(SalOp *h, const SalAuthInfo *info){ h->pending_auth=NULL; if (h->auth_info) sal_auth_info_delete(h->auth_info); /*if already exist*/ h->auth_info=sal_auth_info_clone(info); /*store auth info for subsequent request*/ + } } @@ -1030,6 +1033,12 @@ static void call_accepted(Sal *sal, eXosip_event_t *ev){ if (op->base.local_media) sdp_process(op); } eXosip_call_build_ack(ev->did,&msg); + if(msg == NULL) + { + ms_error("Cannot build ACK message within call accepted ?"); + return; + + } contact=sal_op_get_contact(op); if (contact) { _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free); @@ -1980,7 +1989,7 @@ int sal_call_hold(SalOp *h, bool_t holdon) osip_message_t *reinvite=NULL; if(eXosip_call_build_request(h->did,"INVITE",&reinvite) != OSIP_SUCCESS || reinvite==NULL) return -1; - osip_message_set_subject(reinvite,holdon ? "Phone call hold" : "Phone call resume" ); + osip_message_set_subject(reinvite,holdon ? "Phone call hold" : "Phone call resume" ); osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO"); if (h->base.root->session_expires!=0){ osip_message_set_header(reinvite, "Session-expires", "200");