diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 31094d71e651a692bcbf2e186dffea62d4327786..5ae7539e72aeb904c20e14438bd7bf7f940638a9 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -32,7 +32,6 @@ liblinphone_la_SOURCES=\ authentication.c \ lpconfig.c lpconfig.h \ chat.c \ - general_state.c \ linphonecall.c \ sipsetup.c sipsetup.h \ siplogin.c \ diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index a9d4e2c837019f303ed168fd998f0de61b8a8247..7c52c83273a32d6fc2089da71fd2489bb45626ac 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -30,19 +30,14 @@ static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){ lc->vtable.show(lc); if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Connected.")); - if (lc->vtable.connected_recv) - lc->vtable.connected_recv(lc,call); - call->state=LinphoneCallAVRunning; + linphone_call_set_state(call,LinphoneCallConnected,"Connected"); if (lc->ringstream!=NULL){ ring_stop(lc->ringstream); lc->ringstream=NULL; } - if(!linphone_core_in_call(lc)) - { - linphone_core_set_as_current_call(lc,call); - } - if(call == linphone_core_get_current_call(lc)) - linphone_core_start_media_streams(lc,call); + + linphone_call_start_media_streams(call); + linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)"); } static void call_received(SalOp *h){ @@ -52,25 +47,20 @@ static void call_received(SalOp *h){ const char *from,*to; char *tmp; LinphoneAddress *from_parsed; - LinphoneGeneralStateContext gctx; /* first check if we can answer successfully to this invite */ - if (lc->presence_mode!=LINPHONE_STATUS_ONLINE){ - ms_message("Not present !! presence mode : %d\n",lc->presence_mode); - if (lc->presence_mode==LINPHONE_STATUS_BUSY) + if (lc->presence_mode==LinphoneStatusBusy || + lc->presence_mode==LinphoneStatusOffline || + lc->presence_mode==LinphoneStatusDoNotDisturb || + lc->presence_mode==LinphoneStatusMoved){ + if (lc->presence_mode==LinphoneStatusBusy ) sal_call_decline(h,SalReasonBusy,NULL); - else if (lc->presence_mode==LINPHONE_STATUS_AWAY - ||lc->presence_mode==LINPHONE_STATUS_BERIGHTBACK - ||lc->presence_mode==LINPHONE_STATUS_ONTHEPHONE - ||lc->presence_mode==LINPHONE_STATUS_OUTTOLUNCH - ||lc->presence_mode==LINPHONE_STATUS_OFFLINE) + else if (lc->presence_mode==LinphoneStatusOffline) sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL); - else if (lc->presence_mode==LINPHONE_STATUS_NOT_DISTURB) + else if (lc->presence_mode==LinphoneStatusDoNotDisturb) sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL); - else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_MOVED) + else if (lc->alt_contact!=NULL && lc->presence_mode==LinphoneStatusMoved) sal_call_decline(h,SalReasonRedirect,lc->alt_contact); - else - sal_call_decline(h,SalReasonBusy,NULL); sal_op_release(h); return; } @@ -84,12 +74,6 @@ static void call_received(SalOp *h){ call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),h); - if(linphone_core_get_current_call(lc)!=NULL) //we are already in call just inform that an incoming call is going on - { - char temp[256]; - snprintf(temp,sizeof(temp)-1,"A new incoming call from %s during call",from); - lc->vtable.display_status(lc,temp); - } sal_call_set_local_media_description(h,call->localdesc); call->resultdesc=sal_call_get_final_media_description(h); if (call->resultdesc) @@ -111,8 +95,7 @@ static void call_received(SalOp *h){ linphone_address_clean(from_parsed); tmp=linphone_address_as_string(from_parsed); linphone_address_destroy(from_parsed); - gctx.call=call; - gstate_new_state(lc, GSTATE_CALL_IN_INVITE, gctx, tmp); + linphone_call_set_state(call,LinphoneCallIncomingProgress,"Incoming call"); barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"), (sal_call_autoanswer_asked(h)) ?_(" and asked autoanswer."):_(".")); if (lc->vtable.show) lc->vtable.show(lc); @@ -131,12 +114,10 @@ static void call_received(SalOp *h){ ms_message("the local ring is already started"); } } - call->state=LinphoneCallRinging; sal_call_notify_ringing(h); #if !(__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000) - linphone_core_init_media_streams(lc,call); + linphone_call_init_media_streams(call); #endif - if (lc->vtable.inv_recv) lc->vtable.inv_recv(lc,call); ms_free(barmesg); ms_free(tmp); } @@ -145,15 +126,12 @@ static void call_ringing(SalOp *h){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(h); SalMediaDescription *md; - LinphoneGeneralStateContext gctx; if (call==NULL) return; - gctx.call=call; if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Remote ringing.")); - if (lc->vtable.ringing_recv) - lc->vtable.ringing_recv(lc,call); + md=sal_call_get_final_media_description(h); if (md==NULL){ if (lc->ringstream!=NULL) return; /*already ringing !*/ @@ -161,12 +139,11 @@ static void call_ringing(SalOp *h){ 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); - - gstate_new_state(lc, GSTATE_CALL_OUT_RINGING, gctx, NULL); + linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing"); } }else{ /*accept early media */ - if (lc->audiostream && lc->audiostream->ticker!=NULL){ + if (call->audiostream && call->audiostream->ticker!=NULL){ /*streams already started */ ms_message("Early media already started."); return; @@ -176,17 +153,15 @@ static void call_ringing(SalOp *h){ if (lc->vtable.show) lc->vtable.show(lc); if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Early media.")); - gstate_new_state(lc, GSTATE_CALL_OUT_RINGING, gctx, NULL); + linphone_call_set_state(call,LinphoneCallOutgoingEarlyMedia,"Early media"); if (lc->ringstream!=NULL){ ring_stop(lc->ringstream); lc->ringstream=NULL; } ms_message("Doing early media..."); - if(call == linphone_core_get_current_call(lc)) - linphone_core_start_media_streams(lc,call); + linphone_call_start_media_streams(call); call->media_pending=TRUE; } - call->state=LinphoneCallRinging; } /* @@ -197,25 +172,15 @@ static void call_ringing(SalOp *h){ 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); - LinphoneGeneralStateContext gctx; + if (call==NULL){ ms_warning("No call to accept."); return ; } - gctx.call=call; - if (call->state==LinphoneCallAVRunning){ - ms_message("GET 200Ok of resume\n"); - if(lc->vtable.ack_resumed_recv) - lc->vtable.ack_resumed_recv(lc,call); - return ; //already accepted - } - if ((lc->audiostream!=NULL) && (lc->audiostream->ticker!=NULL)){ - /*case where we accepted early media */ - if(call == linphone_core_get_current_call(lc)) - { - linphone_core_stop_media_streams(lc,call); - linphone_core_init_media_streams(lc,call); - } + if ((call->audiostream!=NULL) && (call->audiostream->ticker!=NULL)){ + /*case where we accepted early media or already in call*/ + linphone_call_stop_media_streams(call); + linphone_call_init_media_streams(call); } if (call->resultdesc) sal_media_description_unref(call->resultdesc); @@ -225,17 +190,12 @@ static void call_accepted(SalOp *op){ call->media_pending=FALSE; } if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){ - //if we initiated a pause - if(call->state == LinphoneCallPaused) - { - ms_message("GET 200Ok of pause\n"); - if(lc->vtable.ack_paused_recv) - lc->vtable.ack_paused_recv(lc,call); - }//if there is an accepted incoming call - else - { - linphone_core_set_as_current_call (lc,call); - gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, gctx, NULL); + if (call->state==LinphoneCallPausing || sal_media_description_has_dir(call->resultdesc,SalStreamSendOnly)){ + /*we initiated a pause*/ + linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); + linphone_call_set_media_streams_dir (call,SalStreamSendOnly); + linphone_call_start_media_streams (call); + }else{ linphone_connect_incoming(lc,call); } }else{ @@ -248,20 +208,15 @@ static void call_accepted(SalOp *op){ 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); - LinphoneGeneralStateContext gctx; if (call==NULL){ ms_warning("No call to be ACK'd"); return ; } - gctx.call=call; if (call->media_pending){ - if (lc->audiostream->ticker!=NULL){ + if (call->audiostream->ticker!=NULL){ /*case where we accepted early media */ - if(call == linphone_core_get_current_call(lc)) - { - linphone_core_stop_media_streams(lc,call); - linphone_core_init_media_streams(lc,call); - } + linphone_call_stop_media_streams(call); + linphone_call_init_media_streams(call); } if (call->resultdesc) sal_media_description_unref(call->resultdesc); @@ -269,17 +224,18 @@ static void call_ack(SalOp *op){ if (call->resultdesc) sal_media_description_ref(call->resultdesc); if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){ - gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, gctx, NULL); linphone_connect_incoming(lc,call); }else{ /*send a bye*/ ms_error("Incompatible SDP response received in ACK, need to abort the call"); - linphone_core_terminate_call(lc,NULL); + linphone_core_abort_call(lc,call,"No codec intersection"); + return; } call->media_pending=FALSE; } } +/* this callback is called when an incoming re-INVITE modifies the session*/ static void call_updated(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); @@ -291,37 +247,24 @@ static void call_updated(SalOp *op){ if (call->resultdesc && !sal_media_description_empty(call->resultdesc)) { - if( (call->state == LinphoneCallPaused) && strcmp(call->resultdesc->addr,"0.0.0.0")) - { + if (call->state==LinphoneCallPaused && + sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv) && strcmp(call->resultdesc->addr,"0.0.0.0")!=0){ if(lc->vtable.display_status) - lc->vtable.display_status(lc,"we have been resumed..."); - call->state = LinphoneCallAVRunning; - lc->vtable.resumed_recv(lc,call); - //we have to keep sending when holded - //linphone_core_start_media_streams(lc,call); + lc->vtable.display_status(lc,_("We have been resumed...")); + linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)"); + linphone_call_set_media_streams_dir (call,SalStreamSendRecv); } - else if( (call->state != LinphoneCallPaused) && !strcmp(call->resultdesc->addr,"0.0.0.0")) - { + else if(call->state==LinphoneCallStreamsRunning && + sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly) && !strcmp(call->resultdesc->addr,"0.0.0.0")){ if(lc->vtable.display_status) - lc->vtable.display_status(lc,"we have been paused..."); - call->state = LinphoneCallPaused; - lc->vtable.paused_recv(lc,call); - //we have to keep sending when holded - /* - if(call == linphone_core_get_current_call(lc)) - { - linphone_core_stop_media_streams(lc,call); - linphone_core_init_media_streams(lc,call); - } - */ + lc->vtable.display_status(lc,_("We are being paused...")); + linphone_call_set_state (call,LinphoneCallPaused,"Call paused"); + linphone_call_set_media_streams_dir (call,SalStreamRecvOnly); } else { - if(call == linphone_core_get_current_call(lc)) - { - linphone_core_stop_media_streams(lc,call); - linphone_core_init_media_streams(lc,call); - } + linphone_call_stop_media_streams (call); + linphone_call_init_media_streams (call); linphone_connect_incoming(lc,call); } } @@ -330,9 +273,8 @@ static void call_updated(SalOp *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); - LinphoneGeneralStateContext gctx; - gctx.call=call; - if (linphone_call_get_state(call)==LinphoneCallTerminated){ + + if (linphone_call_get_state(call)==LinphoneCallEnd || linphone_call_get_state(call)==LinphoneCallError){ ms_warning("call_terminated: ignoring."); return; } @@ -342,25 +284,13 @@ static void call_terminated(SalOp *op, const char *from){ ring_stop(lc->ringstream); lc->ringstream=NULL; } - if(call == linphone_core_get_current_call(lc)) - linphone_core_stop_media_streams(lc,call); + linphone_call_stop_media_streams(call); if (lc->vtable.show!=NULL) lc->vtable.show(lc); if (lc->vtable.display_status!=NULL) lc->vtable.display_status(lc,_("Call terminated.")); - call->state=LinphoneCallTerminated; - gstate_new_state(lc, GSTATE_CALL_END, gctx, NULL); - if (lc->vtable.bye_recv!=NULL){ - LinphoneAddress *addr=linphone_address_new(from); - char *tmp; - linphone_address_clean(addr); - tmp=linphone_address_as_string(addr); - if (lc->vtable.bye_recv!=NULL) - lc->vtable.bye_recv(lc,call); - ms_free(tmp); - linphone_address_destroy(addr); - } - linphone_call_set_terminated(call); + + linphone_call_set_state(call, LinphoneCallEnd,"Call ended"); } static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details, int code){ @@ -372,9 +302,12 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de char *msg603=_("Call declined."); const char *msg=details; LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - LinphoneGeneralStateContext gctx; - gctx.call=call; + if (call==NULL){ + ms_warning("Call faillure reported on already cleaned call ?"); + return ; + } + if (lc->vtable.show) lc->vtable.show(lc); if (error==SalErrorNoResponse){ @@ -427,19 +360,15 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de lc->vtable.display_status(lc,_("Call failed.")); } } - if (lc->vtable.failure_recv) - lc->vtable.failure_recv(lc,call,code); + if (lc->ringstream!=NULL) { ring_stop(lc->ringstream); lc->ringstream=NULL; } - if(call == linphone_core_get_current_call(lc)) - linphone_core_stop_media_streams(lc,call); - if (call!=NULL) { - if (sr!=SalReasonDeclined) gstate_new_state(lc, GSTATE_CALL_ERROR, gctx, msg); - else gstate_new_state(lc, GSTATE_CALL_END, gctx, NULL); - linphone_call_set_terminated(call); - } + linphone_call_stop_media_streams (call); + if (sr!=SalReasonDeclined) linphone_call_set_state(call,LinphoneCallError,msg); + else linphone_call_set_state(call,LinphoneCallEnd,"Call declined."); + } static void auth_requested(SalOp *h, const char *realm, const char *username){ @@ -474,32 +403,47 @@ static void register_success(SalOp *op, bool_t registered){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op); char *msg; - LinphoneGeneralStateContext gctx; - gctx.proxy=cfg; + cfg->registered=registered; - gstate_new_state(lc, GSTATE_REG_OK,gctx, NULL); - if (cfg->registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op)); - else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op)); - if (lc->vtable.display_status) + linphone_proxy_config_set_state(cfg, registered ? LinphoneRegistrationOk : LinphoneRegistrationCleared , + registered ? "Registration sucessful" : "Unregistration done"); + if (lc->vtable.display_status){ + if (cfg->registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op)); + else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op)); lc->vtable.display_status(lc,msg); - ms_free(msg); + ms_free(msg); + } + } static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneGeneralStateContext gctx; - char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op),(details!=NULL) ? details : _("no response timeout")); - if (lc->vtable.display_status) lc->vtable.display_status(lc,msg); - gctx.proxy=(LinphoneProxyConfig*)sal_op_get_user_pointer (op); - gstate_new_state(lc, GSTATE_REG_FAILED, gctx, msg); - ms_free(msg); + LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op); + + if (cfg==NULL){ + ms_warning("Registration failed for unknown proxy config."); + return ; + } + if (details==NULL) + details=_("no response timeout"); + + if (lc->vtable.display_status) { + char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op),details ); + lc->vtable.display_status(lc,msg); + ms_free(msg); + } + linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,details); } static void vfu_request(SalOp *op){ + LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer (op); #ifdef VIDEO_ENABLED - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - if (lc->videostream) - video_stream_send_vfu(lc->videostream); + if (call==NULL){ + ms_warning("VFU request but no call !"); + return ; + } + if (call->videostream) + video_stream_send_vfu(call->videostream); #endif } @@ -557,7 +501,7 @@ static void ping_reply(SalOp *op){ LinphoneCall *call=(LinphoneCall*) sal_op_get_user_pointer(op); ms_message("ping reply !"); if (call){ - if (call->state==LinphoneCallPreEstablishing){ + if (call->state==LinphoneCallOutgoingInit){ linphone_core_start_invite(call->core,call,NULL); } } diff --git a/coreapi/friend.c b/coreapi/friend.c index 7ba2437419643526bf2cecfeabc451054c79669c..1af7a4cb5c8e5276eb219bc0902114b6c44bea3e 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -29,37 +29,37 @@ const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){ const char *str=NULL; switch(ss){ - case LINPHONE_STATUS_ONLINE: + case LinphoneStatusOnline: str=_("Online"); break; - case LINPHONE_STATUS_BUSY: + case LinphoneStatusBusy: str=_("Busy"); break; - case LINPHONE_STATUS_BERIGHTBACK: + case LinphoneStatusBeRightBack: str=_("Be right back"); break; - case LINPHONE_STATUS_AWAY: + case LinphoneStatusAway: str=_("Away"); break; - case LINPHONE_STATUS_ONTHEPHONE: + case LinphoneStatusOnThePhone: str=_("On the phone"); break; - case LINPHONE_STATUS_OUTTOLUNCH: + case LinphoneStatusOutToLunch: str=_("Out to lunch"); break; - case LINPHONE_STATUS_NOT_DISTURB: + case LinphoneStatusDoNotDisturb: str=_("Do not disturb"); break; - case LINPHONE_STATUS_MOVED: + case LinphoneStatusMoved: str=_("Moved"); break; - case LINPHONE_STATUS_ALT_SERVICE: + case LinphoneStatusAltService: str=_("Using another messaging service"); break; - case LINPHONE_STATUS_OFFLINE: + case LinphoneStatusOffline: str=_("Offline"); break; - case LINPHONE_STATUS_PENDING: + case LinphoneStatusPending: str=_("Pending"); break; default: @@ -138,7 +138,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ }else from=linphone_core_get_primary_contact(fr->lc); if (fr->outsub==NULL){ /* people for which we don't have yet an answer should appear as offline */ - fr->status=LINPHONE_STATUS_OFFLINE; + fr->status=LinphoneStatusOffline; /* if (fr->lc->vtable.notify_recv) fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr); @@ -157,7 +157,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ LinphoneFriend * linphone_friend_new(){ LinphoneFriend *obj=ms_new0(LinphoneFriend,1); obj->pol=LinphoneSPAccept; - obj->status=LINPHONE_STATUS_OFFLINE; + obj->status=LinphoneStatusOffline; obj->subscribe=TRUE; return obj; } @@ -243,37 +243,37 @@ int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscri SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os){ switch(os){ - case LINPHONE_STATUS_OFFLINE: + case LinphoneStatusOffline: return SalPresenceOffline; break; - case LINPHONE_STATUS_ONLINE: + case LinphoneStatusOnline: return SalPresenceOnline; break; - case LINPHONE_STATUS_BUSY: + case LinphoneStatusBusy: return SalPresenceBusy; break; - case LINPHONE_STATUS_BERIGHTBACK: + case LinphoneStatusBeRightBack: return SalPresenceBerightback; break; - case LINPHONE_STATUS_AWAY: + case LinphoneStatusAway: return SalPresenceAway; break; - case LINPHONE_STATUS_ONTHEPHONE: + case LinphoneStatusOnThePhone: return SalPresenceOnthephone; break; - case LINPHONE_STATUS_OUTTOLUNCH: + case LinphoneStatusOutToLunch: return SalPresenceOuttolunch; break; - case LINPHONE_STATUS_NOT_DISTURB: + case LinphoneStatusDoNotDisturb: return SalPresenceDonotdisturb; break; - case LINPHONE_STATUS_MOVED: + case LinphoneStatusMoved: return SalPresenceMoved; break; - case LINPHONE_STATUS_ALT_SERVICE: + case LinphoneStatusAltService: return SalPresenceAltService; break; - case LINPHONE_STATUS_PENDING: + case LinphoneStatusPending: return SalPresenceOffline; break; default: @@ -347,7 +347,7 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){ if (fr->inc_subscribe_pending){ switch(fr->pol){ case LinphoneSPWait: - linphone_friend_notify(fr,LINPHONE_STATUS_PENDING); + linphone_friend_notify(fr,LinphoneStatusPending); break; case LinphoneSPAccept: if (fr->lc!=NULL) @@ -356,7 +356,7 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){ } break; case LinphoneSPDeny: - linphone_friend_notify(fr,LINPHONE_STATUS_OFFLINE); + linphone_friend_notify(fr,LinphoneStatusOffline); break; } fr->inc_subscribe_pending=FALSE; diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index c5c7f3eb1b87d1730a68bda539297aa3560827be..0a3807442a022bd796b0d07a1fd0add60594c6d5 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -27,6 +27,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "private.h" +#include "mediastreamer2/mediastream.h" +#include "mediastreamer2/msvolume.h" +#include "mediastreamer2/msequalizer.h" + static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, bool_t only_one_codec){ @@ -43,17 +47,17 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, bool_t on } static SalMediaDescription *create_local_media_description(LinphoneCore *lc, - const char *localip, const char *username, bool_t only_one_codec){ + LinphoneCall *call, const char *username, bool_t only_one_codec){ MSList *l; PayloadType *pt; SalMediaDescription *md=sal_media_description_new(); md->nstreams=1; - strncpy(md->addr,localip,sizeof(md->addr)); + 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,localip,sizeof(md->streams[0].addr)); - md->streams[0].port=linphone_core_get_audio_port(lc); + strncpy(md->streams[0].addr,call->localip,sizeof(md->streams[0].addr)); + md->streams[0].port=call->audio_port; md->streams[0].proto=SalProtoRtpAvp; md->streams[0].type=SalAudio; md->streams[0].ptime=lc->net_conf.down_ptime; @@ -67,7 +71,7 @@ static SalMediaDescription *create_local_media_description(LinphoneCore *lc, if (linphone_core_video_enabled (lc)){ md->nstreams++; - md->streams[1].port=linphone_core_get_video_port(lc); + md->streams[1].port=call->video_port; md->streams[1].proto=SalProtoRtpAvp; md->streams[1].type=SalVideo; l=make_codec_list(lc,lc->codecs_conf.video_codecs,only_one_codec); @@ -78,15 +82,43 @@ static SalMediaDescription *create_local_media_description(LinphoneCore *lc, return md; } +static int find_port_offset(LinphoneCore *lc){ + int offset; + MSList *elem; + int audio_port; + bool_t already_used=FALSE; + for(offset=0;offset<100;++offset){ + audio_port=linphone_core_get_audio_port (lc)+offset; + already_used=FALSE; + for(elem=lc->calls;elem!=NULL;elem=elem->next){ + LinphoneCall *call=(LinphoneCall*)elem->data; + if (call->audio_port==audio_port) { + already_used=TRUE; + break; + } + } + if (!already_used) break; + } + if (offset==100){ + ms_error("Could not find any free port !"); + return -1; + } + return offset; +} + static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){ + int port_offset; call->refcnt=1; - call->state=LinphoneCallInit; + call->state=LinphoneCallIdle; call->start_time=time(NULL); call->media_start_time=0; call->log=linphone_call_log_new(call, from, to); - linphone_core_notify_all_friends(call->core,LINPHONE_STATUS_ONTHEPHONE); - if (linphone_core_get_firewall_policy(call->core)==LINPHONE_POLICY_USE_STUN) - linphone_core_run_stun_tests(call->core,call); + linphone_core_notify_all_friends(call->core,LinphoneStatusOnThePhone); + port_offset=find_port_offset (call->core); + if (port_offset==-1) return; + call->audio_port=linphone_core_get_audio_port(call->core)+port_offset; + call->video_port=linphone_core_get_video_port(call->core)+port_offset; + } static void discover_mtu(LinphoneCore *lc, const char *remote){ @@ -110,9 +142,11 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr sal_op_set_user_pointer(call->op,call); call->core=lc; linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip); - call->localdesc=create_local_media_description (lc,call->localip, - linphone_address_get_username(from),FALSE); linphone_call_init_common(call,from,to); + call->localdesc=create_local_media_description (lc,call, + linphone_address_get_username(from),FALSE); + if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun) + linphone_core_run_stun_tests(call->core,call); discover_mtu(lc,linphone_address_get_domain (to)); return call; } @@ -143,9 +177,11 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro linphone_address_clean(from); linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip); - call->localdesc=create_local_media_description (lc,call->localip, - linphone_address_get_username(me),lc->sip_conf.only_one_codec); linphone_call_init_common(call, from, to); + call->localdesc=create_local_media_description (lc,call, + linphone_address_get_username(me),lc->sip_conf.only_one_codec); + if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun) + linphone_core_run_stun_tests(call->core,call); discover_mtu(lc,linphone_address_get_domain(from)); linphone_address_destroy(me); return call; @@ -158,27 +194,26 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro - update the call logs accordingly */ -void linphone_call_set_terminated(LinphoneCall *call){ +static void linphone_call_set_terminated(LinphoneCall *call){ LinphoneCallStatus status=LinphoneCallAborted; LinphoneCore *lc=call->core; - - if (ms_list_size(lc->calls)==0) - linphone_core_notify_all_friends(lc,lc->prev_mode); linphone_core_update_allocated_audio_bandwidth(lc); - if (call->state==LinphoneCallAVRunning || call->state==LinphoneCallPaused){ + if (call->state==LinphoneCallEnd){ status=LinphoneCallSuccess; } linphone_call_log_completed(call->log,call, status); - call->state=LinphoneCallTerminated; if (linphone_core_del_call(lc,call) != 0){ - ms_error("could not remove the call from the list !!!"); + ms_error("Could not remove the call from the list !!!"); } - if (call == linphone_core_get_current_call(lc)){ - ms_message("destroying the current call\n"); - linphone_core_unset_the_current_call(lc); + if (call == lc->current_call){ + ms_message("Resetting the current call"); + lc->current_call=NULL; } + if (ms_list_size(lc->calls)==0) + linphone_core_notify_all_friends(lc,lc->presence_mode); + if (call->op!=NULL) { /* so that we cannot have anymore upcalls for SAL concerning this call*/ @@ -188,6 +223,17 @@ void linphone_call_set_terminated(LinphoneCall *call){ linphone_call_unref(call); } +void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){ + LinphoneCore *lc=call->core; + if (call->state!=cstate){ + call->state=cstate; + if (lc->vtable.call_state_changed) + lc->vtable.call_state_changed(lc,call,cstate,message); + } + if (call->state==LinphoneCallEnd || call->state==LinphoneCallError) + linphone_call_set_terminated (call); +} + static void linphone_call_destroy(LinphoneCall *obj) { if (obj->op!=NULL) { @@ -234,13 +280,6 @@ void linphone_call_unref(LinphoneCall *obj){ linphone_call_destroy(obj); } -/** - * Returns true if the call is paused. -**/ -bool_t linphone_call_paused(LinphoneCall *call){ - return call->state==LinphoneCallPaused; -} - /** * Returns the remote address associated to this call * @@ -301,3 +340,334 @@ LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call){ * @} **/ + +#ifdef TEST_EXT_RENDERER +static void rendercb(void *data, const MSPicture *local, const MSPicture *remote){ + ms_message("rendercb, local buffer=%p, remote buffer=%p", + local ? local->planes[0] : NULL, remote? remote->planes[0] : NULL); +} +#endif + +void linphone_call_init_media_streams(LinphoneCall *call){ + LinphoneCore *lc=call->core; + SalMediaDescription *md=call->localdesc; + AudioStream *audiostream; + + call->audiostream=audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc)); + if (linphone_core_echo_limiter_enabled(lc)){ + const char *type=lp_config_get_string(lc->config,"sound","el_type","mic"); + if (strcasecmp(type,"mic")==0) + audio_stream_enable_echo_limiter(audiostream,ELControlMic); + else if (strcasecmp(type,"full")==0) + audio_stream_enable_echo_limiter(audiostream,ELControlFull); + } + audio_stream_enable_gain_control(audiostream,TRUE); + if (linphone_core_echo_cancellation_enabled(lc)){ + int len,delay,framesize; + len=lp_config_get_int(lc->config,"sound","ec_tail_len",0); + delay=lp_config_get_int(lc->config,"sound","ec_delay",0); + framesize=lp_config_get_int(lc->config,"sound","ec_framesize",0); + audio_stream_set_echo_canceller_params(audiostream,len,delay,framesize); + } + audio_stream_enable_automatic_gain_control(audiostream,linphone_core_agc_enabled(lc)); + { + int enabled=lp_config_get_int(lc->config,"sound","noisegate",0); + audio_stream_enable_noise_gate(audiostream,enabled); + } + if (lc->a_rtp) + rtp_session_set_transports(audiostream->session,lc->a_rtp,lc->a_rtcp); + +#ifdef VIDEO_ENABLED + if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].port>0){ + call->videostream=video_stream_new(md->streams[1].port,linphone_core_ipv6_enabled(lc)); +#ifdef TEST_EXT_RENDERER + video_stream_set_render_callback(call->videostream,rendercb,NULL); +#endif + } +#else + lc->videostream=NULL; +#endif +} + + +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; + 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]); +} + +static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){ + if (st->equalizer){ + MSFilter *f=st->equalizer; + int enabled=lp_config_get_int(lc->config,"sound","eq_active",0); + const char *gains=lp_config_get_string(lc->config,"sound","eq_gains",NULL); + ms_filter_call_method(f,MS_EQUALIZER_SET_ACTIVE,&enabled); + if (enabled){ + if (gains){ + do{ + int bytes; + MSEqualizerGain g; + if (sscanf(gains,"%f:%f:%f %n",&g.frequency,&g.gain,&g.width,&bytes)==3){ + ms_message("Read equalizer gains: %f(~%f) --> %f",g.frequency,g.width,g.gain); + ms_filter_call_method(f,MS_EQUALIZER_SET_GAIN,&g); + gains+=bytes; + }else break; + }while(1); + } + } + } +} + + +static void post_configure_audio_streams(LinphoneCall*call){ + AudioStream *st=call->audiostream; + LinphoneCore *lc=call->core; + float mic_gain=lp_config_get_float(lc->config,"sound","mic_gain",1); + float thres = 0; + float recv_gain; + float ng_thres=lp_config_get_float(lc->config,"sound","ng_thres",0.05); + float ng_floorgain=lp_config_get_float(lc->config,"sound","ng_floorgain",0); + int dc_removal=lp_config_get_int(lc->config,"sound","dc_removal",0); + + if (mic_gain!=-1) + audio_stream_set_mic_gain(st,mic_gain); + call->audio_muted=FALSE; + + recv_gain = lc->sound_conf.soft_play_lev; + if (recv_gain != 0) { + linphone_core_set_playback_gain_db (lc,recv_gain); + } + if (st->volsend){ + ms_filter_call_method(st->volsend,MS_VOLUME_REMOVE_DC,&dc_removal); + } + if (linphone_core_echo_limiter_enabled(lc)){ + float speed=lp_config_get_float(lc->config,"sound","el_speed",-1); + thres=lp_config_get_float(lc->config,"sound","el_thres",-1); + float force=lp_config_get_float(lc->config,"sound","el_force",-1); + int sustain=lp_config_get_int(lc->config,"sound","el_sustain",-1); + MSFilter *f=NULL; + if (st->el_type!=ELInactive){ + f=st->volsend; + if (speed==-1) speed=0.03; + if (force==-1) force=25; + ms_filter_call_method(f,MS_VOLUME_SET_EA_SPEED,&speed); + ms_filter_call_method(f,MS_VOLUME_SET_EA_FORCE,&force); + if (thres!=-1) + ms_filter_call_method(f,MS_VOLUME_SET_EA_THRESHOLD,&thres); + if (sustain!=-1) + ms_filter_call_method(f,MS_VOLUME_SET_EA_SUSTAIN,&sustain); + } + } + + if (st->volsend){ + ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres); + ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&ng_floorgain); + } + if (st->volrecv){ + /* parameters for a limited noise-gate effect, using echo limiter threshold */ + float floorgain = 1/mic_gain; + ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&thres); + ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&floorgain); + } + parametrize_equalizer(lc,st); + 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); + } +} + + + + +static RtpProfile *make_profile(LinphoneCore *lc, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){ + int bw; + const MSList *elem; + RtpProfile *prof=rtp_profile_new("Call profile"); + bool_t first=TRUE; + int remote_bw=0; + *used_pt=-1; + + for(elem=desc->payloads;elem!=NULL;elem=elem->next){ + PayloadType *pt=(PayloadType*)elem->data; + + if (first) { + if (desc->type==SalAudio){ + linphone_core_update_allocated_audio_bandwidth_in_call(lc,pt); + } + *used_pt=payload_type_get_number(pt); + first=FALSE; + } + if (desc->bandwidth>0) remote_bw=desc->bandwidth; + else if (md->bandwidth>0) { + /*case where b=AS is given globally, not per stream*/ + remote_bw=md->bandwidth; + if (desc->type==SalVideo){ + remote_bw-=lc->audio_bw; + } + } + + if (desc->type==SalAudio){ + bw=get_min_bandwidth(lc->up_audio_bw,remote_bw); + }else bw=get_min_bandwidth(lc->up_video_bw,remote_bw); + if (bw>0) pt->normal_bitrate=bw*1000; + else if (desc->type==SalAudio){ + pt->normal_bitrate=-1; + } + if (desc->ptime>0){ + char tmp[40]; + snprintf(tmp,sizeof(tmp),"ptime=%i",desc->ptime); + payload_type_append_send_fmtp(pt,tmp); + } + rtp_profile_set_payload(prof,payload_type_get_number(pt),pt); + } + return prof; +} + +void linphone_call_start_media_streams(LinphoneCall *call){ + LinphoneCore *lc=call->core; + LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc); + const char *tool="linphone-" LINPHONE_VERSION; + char *cname; + int used_pt=-1; + if(call->audiostream == NULL) + { + ms_fatal("start_media_stream() called without prior init !"); + return; + } + /* adjust rtp jitter compensation. It must be at least the latency of the sound card */ + int jitt_comp=MAX(lc->sound_conf.latency,lc->rtp_conf.audio_jitt_comp); + + if (call->media_start_time==0) call->media_start_time=time(NULL); + + cname=linphone_address_as_string_uri_only(me); + { + const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc, + SalProtoRtpAvp,SalAudio); + if (stream && stream->port!=0){ + call->audio_profile=make_profile(lc,call->resultdesc,stream,&used_pt); + if (!lc->use_files){ + MSSndCard *playcard=lc->sound_conf.lsd_card ? + lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; + MSSndCard *captcard=lc->sound_conf.capt_sndcard; + if (playcard==NULL) { + ms_warning("No card defined for playback !"); + goto end; + } + if (captcard==NULL) { + ms_warning("No card defined for capture !"); + goto end; + } + audio_stream_start_now( + call->audiostream, + call->audio_profile, + stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr, + stream->port, + stream->port+1, + used_pt, + jitt_comp, + playcard, + captcard, + linphone_core_echo_cancellation_enabled(lc)); + }else{ + audio_stream_start_with_files( + call->audiostream, + call->audio_profile, + stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr, + stream->port, + stream->port+1, + used_pt, + 100, + lc->play_file, + lc->rec_file); + } + post_configure_audio_streams(call); + audio_stream_set_rtcp_information(call->audiostream, cname, tool); + }else ms_warning("No audio stream defined ?"); + } +#ifdef VIDEO_ENABLED + { + const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc, + SalProtoRtpAvp,SalVideo); + /* shutdown preview */ + if (lc->previewstream!=NULL) { + video_preview_stop(lc->previewstream); + lc->previewstream=NULL; + } + if (stream && stream->port!=0 && (lc->video_conf.display || lc->video_conf.capture)) { + const char *addr=stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr; + call->video_profile=make_profile(lc,call->resultdesc,stream,&used_pt); + video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc)); + video_stream_enable_self_view(call->videostream,lc->video_conf.selfview); + if (lc->video_conf.display && lc->video_conf.capture) + video_stream_start(call->videostream, + call->video_profile, addr, stream->port, + stream->port+1, + used_pt, jitt_comp, lc->video_conf.device); + else if (lc->video_conf.display) + video_stream_recv_only_start(call->videostream, + call->video_profile, addr, stream->port, + used_pt, jitt_comp); + else if (lc->video_conf.capture) + video_stream_send_only_start(call->videostream, + call->video_profile, addr, stream->port, + stream->port+1, + used_pt, jitt_comp, lc->video_conf.device); + video_stream_set_rtcp_information(call->videostream, cname,tool); + }else{ + ms_warning("No valid video stream defined."); + } + } +#endif + goto end; + end: + ms_free(cname); + linphone_address_destroy(me); +} + + + +static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){ + audio_stream_get_local_rtp_stats (st,&log->local_stats); +} + +void linphone_call_stop_media_streams(LinphoneCall *call){ + LinphoneCore *lc=call->core; + if (call->audiostream!=NULL) { + linphone_call_log_fill_stats (call->log,call->audiostream); + audio_stream_stop(call->audiostream); + call->audiostream=NULL; + } +#ifdef VIDEO_ENABLED + if (call->videostream!=NULL){ + if (lc->video_conf.display && lc->video_conf.capture) + video_stream_stop(call->videostream); + else if (lc->video_conf.display) + video_stream_recv_only_stop(call->videostream); + else if (lc->video_conf.capture) + video_stream_send_only_stop(call->videostream); + call->videostream=NULL; + } + +#endif + if (call->audio_profile){ + rtp_profile_clear_all(call->audio_profile); + rtp_profile_destroy(call->audio_profile); + call->audio_profile=NULL; + } + if (call->video_profile){ + rtp_profile_clear_all(call->video_profile); + rtp_profile_destroy(call->video_profile); + call->video_profile=NULL; + } +} + +void linphone_call_set_media_streams_dir(LinphoneCall *call, SalStreamDir dir){ +} + diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 3da96b3c04b1bcf846f763bc287eed53288f623a..20f28384c7cf2485a73d6c8a2984885332d1f448 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -21,13 +21,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sipsetup.h" #include "lpconfig.h" #include "private.h" + +#include <ortp/telephonyevents.h> #include "mediastreamer2/mediastream.h" +#include "mediastreamer2/mseventqueue.h" #include "mediastreamer2/msvolume.h" #include "mediastreamer2/msequalizer.h" -#include "mediastreamer2/mseventqueue.h" - -#include <ortp/telephonyevents.h> - #ifdef INET6 #ifndef WIN32 @@ -907,18 +906,21 @@ static void linphone_core_free_payload_types(void){ linphone_payload_types=NULL; } +void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message){ + if (lc->vtable.global_state_changed){ + lc->vtable.global_state_changed(lc,gstate,message); + } +} + static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vtable, const char *config_path, const char *factory_config_path, void * userdata) { - LinphoneGeneralStateContext gctx={0}; memset (lc, 0, sizeof (LinphoneCore)); lc->data=userdata; memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable)); - gstate_initialize(lc); - gstate_new_state(lc, GSTATE_POWER_STARTUP, gctx, NULL); - + linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up"); ortp_init(); linphone_core_assign_payload_type(&payload_type_pcmu8000,0,NULL); linphone_core_assign_payload_type(&payload_type_gsm,3,NULL); @@ -977,13 +979,12 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta sip_config_read(lc); /* this will start eXosip*/ video_config_read(lc); //autoreplier_config_init(&lc->autoreplier_conf); - lc->prev_mode=LINPHONE_STATUS_ONLINE; - lc->presence_mode=LINPHONE_STATUS_ONLINE; + lc->presence_mode=LinphoneStatusOnline; lc->max_call_logs=15; ui_config_read(lc); if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Ready")); - gstate_new_state(lc, GSTATE_POWER_ON, gctx, NULL); + linphone_core_set_state(lc,LinphoneGlobalOn,"Ready"); lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon; lc->ready=TRUE; @@ -1068,7 +1069,7 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact) /*result must be an array of chars at least LINPHONE_IPADDR_SIZE */ void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result){ - if (linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_NAT_ADDRESS + if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress && linphone_core_get_nat_address(lc)!=NULL){ strncpy(result,linphone_core_get_nat_address(lc),LINPHONE_IPADDR_SIZE); return; @@ -1493,9 +1494,7 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){ snprintf(temp,sizeof(temp),"Remote end seems to have disconnected, the call is going to be closed."); } if (lc->vtable.display_warning!=NULL) - lc->vtable.display_warning(lc,temp); - if(lc->vtable.failure_recv) - lc->vtable.failure_recv(lc,call, 480);//480 Temporarily Unavailable + lc->vtable.display_warning(lc,temp); linphone_core_terminate_call(lc,call); } @@ -1656,11 +1655,11 @@ void linphone_core_iterate(LinphoneCore *lc){ we are going to examine is destroy and removed during linphone_core_start_invite() */ calls=calls->next; - if (call->state==LinphoneCallPreEstablishing && (curtime-call->start_time>=2)){ + if (call->state==LinphoneCallOutgoingInit && (curtime-call->start_time>=2)){ /*start the call even if the OPTIONS reply did not arrive*/ linphone_core_start_invite(lc,call,NULL); } - if (call->dir==LinphoneCallIncoming && call->state==LinphoneCallRinging){ + if (call->dir==LinphoneCallIncoming && call->state==LinphoneCallOutgoingRinging){ elapsed=curtime-call->start_time; ms_message("incoming call ringing for %i seconds",elapsed); if (elapsed>lc->sip_conf.inc_timeout){ @@ -1672,28 +1671,28 @@ void linphone_core_iterate(LinphoneCore *lc){ call = linphone_core_get_current_call(lc); if(call) { - if (call->state==LinphoneCallAVRunning) + if (call->state==LinphoneCallConnected) { if (one_second_elapsed) { RtpSession *as=NULL,*vs=NULL; lc->prevtime=curtime; - if (lc->audiostream!=NULL) - as=lc->audiostream->session; - if (lc->videostream!=NULL) - vs=lc->videostream->session; + if (call->audiostream!=NULL) + as=call->audiostream->session; + if (call->videostream!=NULL) + vs=call->videostream->session; display_bandwidth(as,vs); } #ifdef VIDEO_ENABLED - if (lc->videostream!=NULL) - video_stream_iterate(lc->videostream); + if (call->videostream!=NULL) + video_stream_iterate(call->videostream); #endif - if (lc->audiostream!=NULL && disconnect_timeout>0) - disconnected=!audio_stream_alive(lc->audiostream,disconnect_timeout); + if (call->audiostream!=NULL && disconnect_timeout>0) + disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout); } } if (linphone_core_video_preview_enabled(lc)){ - if (lc->previewstream==NULL) + if (lc->previewstream==NULL && lc->calls==NULL) toggle_video_preview(lc,TRUE); #ifdef VIDEO_ENABLED else video_stream_iterate(lc->previewstream); @@ -1739,8 +1738,6 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url) if (enum_lookup(enum_domain,&enumres)<0){ if (lc->vtable.display_status!=NULL) lc->vtable.display_status(lc,_("Could not resolve this number.")); - if(lc->vtable.failure_recv) - lc->vtable.failure_recv(lc,NULL,400); ms_free(enum_domain); return NULL; } @@ -1857,7 +1854,7 @@ static char *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphonePr const char *localip=call->localip; /* first use user's supplied ip address if asked*/ - if (linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_NAT_ADDRESS){ + if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){ ctt=linphone_core_get_primary_contact_parsed(lc); return ms_strdup_printf("sip:%s@%s",linphone_address_get_username(ctt), linphone_core_get_nat_address(lc)); @@ -1906,17 +1903,16 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphonePro char *contact; char *real_url,*barmsg; char *from; - LinphoneGeneralStateContext gctx; + /*try to be best-effort in giving real local or routable contact address */ contact=get_fixed_contact(lc,call,dest_proxy); if (contact){ sal_op_set_contact(call->op, contact); ms_free(contact); } - call->state=LinphoneCallInit; + //TODO : should probably not be done here - if(! linphone_core_in_call(lc) ) - linphone_core_init_media_streams(lc,call); + linphone_call_init_media_streams(call); if (!lc->sip_conf.sdp_200_ack){ call->media_pending=TRUE; sal_call_set_local_media_description(call->op,call->localdesc); @@ -1935,15 +1931,12 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphonePro ms_free(barmsg); if (err<0){ - ms_warning("Could not initiate call."); if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("could not call")); - if(call == linphone_core_get_current_call(lc)) - linphone_core_stop_media_streams(lc,call); - linphone_call_set_terminated (call); + lc->vtable.display_status(lc,_("Could not call")); + linphone_call_stop_media_streams(call); + linphone_call_set_state(call,LinphoneCallError,"Call failed"); }else { - gctx.call=call; - gstate_new_state(lc, GSTATE_CALL_OUT_INVITE, gctx, real_url); + linphone_call_set_state(call,LinphoneCallOutgoingProgress,"Outgoing call in progress"); } ms_free(real_url); ms_free(from); @@ -2028,7 +2021,7 @@ LinphoneCall * linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddr err=linphone_core_start_invite(lc,call,dest_proxy); }else{ /*defer the start of the call after the OPTIONS ping*/ - call->state=LinphoneCallPreEstablishing; + linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call"); call->ping_op=sal_op_new(lc->sal); sal_ping(call->ping_op,from,real_url); sal_op_set_user_pointer(call->ping_op,call); @@ -2074,334 +2067,6 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){ return FALSE; } -#ifdef TEST_EXT_RENDERER -static void rendercb(void *data, const MSPicture *local, const MSPicture *remote){ - ms_message("rendercb, local buffer=%p, remote buffer=%p", - local ? local->planes[0] : NULL, remote? remote->planes[0] : NULL); -} -#endif - -void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call){ -#ifdef PRINTF_DEBUG - printf("%s(%d)\n",__FUNCTION__,__LINE__); -#endif - SalMediaDescription *md=call->localdesc; - lc->audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc)); - if (linphone_core_echo_limiter_enabled(lc)){ - const char *type=lp_config_get_string(lc->config,"sound","el_type","mic"); - if (strcasecmp(type,"mic")==0) - audio_stream_enable_echo_limiter(lc->audiostream,ELControlMic); - else if (strcasecmp(type,"full")==0) - audio_stream_enable_echo_limiter(lc->audiostream,ELControlFull); - } - audio_stream_enable_gain_control(lc->audiostream,TRUE); - if (linphone_core_echo_cancellation_enabled(lc)){ - int len,delay,framesize; - len=lp_config_get_int(lc->config,"sound","ec_tail_len",0); - delay=lp_config_get_int(lc->config,"sound","ec_delay",0); - framesize=lp_config_get_int(lc->config,"sound","ec_framesize",0); - audio_stream_set_echo_canceller_params(lc->audiostream,len,delay,framesize); - } - audio_stream_enable_automatic_gain_control(lc->audiostream,linphone_core_agc_enabled(lc)); - { - int enabled=lp_config_get_int(lc->config,"sound","noisegate",0); - audio_stream_enable_noise_gate(lc->audiostream,enabled); - } - if (lc->a_rtp) - rtp_session_set_transports(lc->audiostream->session,lc->a_rtp,lc->a_rtcp); - -#ifdef VIDEO_ENABLED - if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].port>0){ - lc->videostream=video_stream_new(md->streams[1].port,linphone_core_ipv6_enabled(lc)); -#ifdef TEST_EXT_RENDERER - video_stream_set_render_callback(lc->videostream,rendercb,NULL); -#endif - } -#else - lc->videostream=NULL; -#endif -} - -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; - 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]); -} - -static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){ - if (st->equalizer){ - MSFilter *f=st->equalizer; - int enabled=lp_config_get_int(lc->config,"sound","eq_active",0); - const char *gains=lp_config_get_string(lc->config,"sound","eq_gains",NULL); - ms_filter_call_method(f,MS_EQUALIZER_SET_ACTIVE,&enabled); - if (enabled){ - if (gains){ - do{ - int bytes; - MSEqualizerGain g; - if (sscanf(gains,"%f:%f:%f %n",&g.frequency,&g.gain,&g.width,&bytes)==3){ - ms_message("Read equalizer gains: %f(~%f) --> %f",g.frequency,g.width,g.gain); - ms_filter_call_method(f,MS_EQUALIZER_SET_GAIN,&g); - gains+=bytes; - }else break; - }while(1); - } - } - } -} - -static void post_configure_audio_streams(LinphoneCore *lc){ - AudioStream *st=lc->audiostream; - float mic_gain=lp_config_get_float(lc->config,"sound","mic_gain",1); - float thres = 0; - float recv_gain; - float ng_thres=lp_config_get_float(lc->config,"sound","ng_thres",0.05); - float ng_floorgain=lp_config_get_float(lc->config,"sound","ng_floorgain",0); - int dc_removal=lp_config_get_int(lc->config,"sound","dc_removal",0); - - if (mic_gain!=-1) - audio_stream_set_mic_gain(st,mic_gain); - lc->audio_muted=FALSE; - - recv_gain = lc->sound_conf.soft_play_lev; - if (recv_gain != 0) { - linphone_core_set_playback_gain_db (lc,recv_gain); - } - if (st->volsend){ - ms_filter_call_method(st->volsend,MS_VOLUME_REMOVE_DC,&dc_removal); - } - if (linphone_core_echo_limiter_enabled(lc)){ - float speed=lp_config_get_float(lc->config,"sound","el_speed",-1); - thres=lp_config_get_float(lc->config,"sound","el_thres",-1); - float force=lp_config_get_float(lc->config,"sound","el_force",-1); - int sustain=lp_config_get_int(lc->config,"sound","el_sustain",-1); - MSFilter *f=NULL; - if (st->el_type!=ELInactive){ - f=st->volsend; - if (speed==-1) speed=0.03; - if (force==-1) force=25; - ms_filter_call_method(f,MS_VOLUME_SET_EA_SPEED,&speed); - ms_filter_call_method(f,MS_VOLUME_SET_EA_FORCE,&force); - if (thres!=-1) - ms_filter_call_method(f,MS_VOLUME_SET_EA_THRESHOLD,&thres); - if (sustain!=-1) - ms_filter_call_method(f,MS_VOLUME_SET_EA_SUSTAIN,&sustain); - } - } - - if (st->volsend){ - ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres); - ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&ng_floorgain); - } - if (st->volrecv){ - /* parameters for a limited noise-gate effect, using echo limiter threshold */ - float floorgain = 1/mic_gain; - ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&thres); - ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&floorgain); - } - parametrize_equalizer(lc,st); - if (lc->vtable.dtmf_received!=NULL){ - /* replace by our default action*/ - audio_stream_play_received_dtmfs(lc->audiostream,FALSE); - rtp_session_signal_connect(lc->audiostream->session,"telephone-event",(RtpCallback)linphone_core_dtmf_received,(unsigned long)lc); - } -} - -static RtpProfile *make_profile(LinphoneCore *lc, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){ - int bw; - const MSList *elem; - RtpProfile *prof=rtp_profile_new("Call profile"); - bool_t first=TRUE; - int remote_bw=0; - *used_pt=-1; - - for(elem=desc->payloads;elem!=NULL;elem=elem->next){ - PayloadType *pt=(PayloadType*)elem->data; - - if (first) { - if (desc->type==SalAudio){ - linphone_core_update_allocated_audio_bandwidth_in_call(lc,pt); - } - *used_pt=payload_type_get_number(pt); - first=FALSE; - } - if (desc->bandwidth>0) remote_bw=desc->bandwidth; - else if (md->bandwidth>0) { - /*case where b=AS is given globally, not per stream*/ - remote_bw=md->bandwidth; - if (desc->type==SalVideo){ - remote_bw-=lc->audio_bw; - } - } - - if (desc->type==SalAudio){ - bw=get_min_bandwidth(lc->up_audio_bw,remote_bw); - }else bw=get_min_bandwidth(lc->up_video_bw,remote_bw); - if (bw>0) pt->normal_bitrate=bw*1000; - else if (desc->type==SalAudio){ - pt->normal_bitrate=-1; - } - if (desc->ptime>0){ - char tmp[40]; - snprintf(tmp,sizeof(tmp),"ptime=%i",desc->ptime); - payload_type_append_send_fmtp(pt,tmp); - } - rtp_profile_set_payload(prof,payload_type_get_number(pt),pt); - } - return prof; -} - -void linphone_core_start_media_streams(LinphoneCore *lc, LinphoneCall *call){ - LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc); - const char *tool="linphone-" LINPHONE_VERSION; - char *cname; - int used_pt=-1; - if(lc->audiostream == NULL) - { - ms_warning("init media stream is needed before starting"); - linphone_core_init_media_streams(lc,call); - /* - * example of problem : - * 2 incomings calls, you answer and pause one, afterward if you try to answer the other call you will get SEGFAULT - */ - } - /* adjust rtp jitter compensation. It must be at least the latency of the sound card */ - int jitt_comp=MAX(lc->sound_conf.latency,lc->rtp_conf.audio_jitt_comp); - - if (call->media_start_time==0) call->media_start_time=time(NULL); - - cname=linphone_address_as_string_uri_only(me); - { - const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc, - SalProtoRtpAvp,SalAudio); - if (stream && stream->port!=0){ - call->audio_profile=make_profile(lc,call->resultdesc,stream,&used_pt); - if (!lc->use_files){ - MSSndCard *playcard=lc->sound_conf.lsd_card ? - lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; - MSSndCard *captcard=lc->sound_conf.capt_sndcard; - if (playcard==NULL) { - ms_warning("No card defined for playback !"); - goto end; - } - if (captcard==NULL) { - ms_warning("No card defined for capture !"); - goto end; - } - audio_stream_start_now( - lc->audiostream, - call->audio_profile, - stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr, - stream->port, - stream->port+1, - used_pt, - jitt_comp, - playcard, - captcard, - linphone_core_echo_cancellation_enabled(lc)); - }else{ - audio_stream_start_with_files( - lc->audiostream, - call->audio_profile, - stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr, - stream->port, - stream->port+1, - used_pt, - 100, - lc->play_file, - lc->rec_file); - } - post_configure_audio_streams(lc); - audio_stream_set_rtcp_information(lc->audiostream, cname, tool); - }else ms_warning("No audio stream defined ?"); - } -#ifdef VIDEO_ENABLED - { - const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc, - SalProtoRtpAvp,SalVideo); - /* shutdown preview */ - if (lc->previewstream!=NULL) { - video_preview_stop(lc->previewstream); - lc->previewstream=NULL; - } - if (stream && stream->port!=0 && (lc->video_conf.display || lc->video_conf.capture)) { - const char *addr=stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr; - call->video_profile=make_profile(lc,call->resultdesc,stream,&used_pt); - video_stream_set_sent_video_size(lc->videostream,linphone_core_get_preferred_video_size(lc)); - video_stream_enable_self_view(lc->videostream,lc->video_conf.selfview); - if (lc->video_conf.display && lc->video_conf.capture) - video_stream_start(lc->videostream, - call->video_profile, addr, stream->port, - stream->port+1, - used_pt, jitt_comp, lc->video_conf.device); - else if (lc->video_conf.display) - video_stream_recv_only_start(lc->videostream, - call->video_profile, addr, stream->port, - used_pt, jitt_comp); - else if (lc->video_conf.capture) - video_stream_send_only_start(lc->videostream, - call->video_profile, addr, stream->port, - stream->port+1, - used_pt, jitt_comp, lc->video_conf.device); - video_stream_set_rtcp_information(lc->videostream, cname,tool); - }else{ - ms_warning("No valid video stream defined."); - } - } -#endif - goto end; - end: - ms_free(cname); - linphone_address_destroy(me); - call->state=LinphoneCallAVRunning; -} - -static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){ - audio_stream_get_local_rtp_stats (st,&log->local_stats); -} - -void linphone_core_stop_media_streams(LinphoneCore *lc, LinphoneCall *call){ -#ifdef PRINTF_DEBUG - printf("%s(%d)\n",__FUNCTION__,__LINE__); -#endif - if (lc->audiostream!=NULL) { - linphone_call_log_fill_stats (call->log,lc->audiostream); - audio_stream_stop(lc->audiostream); - lc->audiostream=NULL; - } -#ifdef VIDEO_ENABLED - if (lc->videostream!=NULL){ - if (lc->video_conf.display && lc->video_conf.capture) - video_stream_stop(lc->videostream); - else if (lc->video_conf.display) - video_stream_recv_only_stop(lc->videostream); - else if (lc->video_conf.capture) - video_stream_send_only_stop(lc->videostream); - lc->videostream=NULL; - } - if (linphone_core_video_preview_enabled(lc)){ - if (lc->previewstream==NULL){ - lc->previewstream=video_preview_start(lc->video_conf.device, lc->video_conf.vsize); - } - } -#endif - if (call->audio_profile){ - rtp_profile_clear_all(call->audio_profile); - rtp_profile_destroy(call->audio_profile); - call->audio_profile=NULL; - } - if (call->video_profile){ - rtp_profile_clear_all(call->video_profile); - rtp_profile_destroy(call->video_profile); - call->video_profile=NULL; - } -} /** * Accept an incoming call. @@ -2421,7 +2086,6 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) { LinphoneProxyConfig *cfg=NULL; const char *contact=NULL; - LinphoneGeneralStateContext gctx; if (call==NULL){ //if just one call is present answer the only one ... @@ -2431,11 +2095,23 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) call = linphone_core_get_calls(lc)->data; } - if (call->state==LinphoneCallAVRunning){ + if (call->state==LinphoneCallConnected){ /*call already accepted*/ return -1; } + /*can accept a new call only if others are on hold */ + { + 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)){ + ms_warning("Cannot accept this call as another one is running, pause it before."); + return -1; + } + } + } + /*stop ringing */ if (lc->ringstream!=NULL) { ms_message("stop ringing"); @@ -2454,23 +2130,37 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) if (contact) sal_op_set_contact(call->op,contact); #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 - linphone_core_init_media_streams(lc,call); + linphone_call_init_media_streams(call); #endif sal_call_accept(call->op); if (lc->vtable.display_status!=NULL) lc->vtable.display_status(lc,_("Connected.")); - gctx.call=call; - gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, gctx, NULL); + linphone_call_set_state(call,LinphoneCallConnected,"Connected"); call->resultdesc=sal_call_get_final_media_description(call->op); if (call->resultdesc){ + linphone_call_start_media_streams(call); sal_media_description_ref(call->resultdesc); - if(call == linphone_core_get_current_call(lc)) - linphone_core_start_media_streams(lc, call); }else call->media_pending=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*/ + if (lc->ringstream!=NULL) { + ring_stop(lc->ringstream); + lc->ringstream=NULL; + } + linphone_call_stop_media_streams(call); + if (lc->vtable.display_status!=NULL) + lc->vtable.display_status(lc,_("Call aborted") ); + linphone_call_set_state(call,LinphoneCallError,error); + return 0; +} + + /** * Terminates a call. * @@ -2482,7 +2172,6 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call) int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call) { LinphoneCall *call; - LinphoneGeneralStateContext gctx; if (the_call == NULL){ call = linphone_core_get_current_call(lc); if(call == NULL){ @@ -2501,13 +2190,10 @@ int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call) ring_stop(lc->ringstream); lc->ringstream=NULL; } - if(call == linphone_core_get_current_call(lc)) - linphone_core_stop_media_streams(lc,call); + linphone_call_stop_media_streams(call); if (lc->vtable.display_status!=NULL) lc->vtable.display_status(lc,_("Call ended") ); - gctx.call=call; - gstate_new_state(lc, GSTATE_CALL_END, gctx, NULL); - linphone_call_set_terminated(call); + linphone_call_set_state(call,LinphoneCallEnd,"Call terminated"); return 0; } @@ -2551,11 +2237,9 @@ bool_t linphone_core_in_call(const LinphoneCore *lc){ * * @ingroup call_control **/ -LinphoneCall *linphone_core_get_current_call(LinphoneCore *lc) +LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc) { - if(lc->current_call != NULL) - return lc->current_call; - return NULL; + return lc->current_call; } /** @@ -2579,25 +2263,23 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call) } else { - ms_error("LinphoneCall was null\n"); - return -2; + ms_error("LinphoneCall was null"); + return -1; } } if(linphone_core_get_current_call(lc) != call) { - ms_error("The call asked to be paused was not the current on\n"); - return -3; + ms_error("The call asked to be paused was not the current on"); + return -1; } - if(sal_call_hold(call->op,TRUE) != 0) + if (sal_call_hold(call->op,TRUE) != 0) { - lc->vtable.display_warning(lc,_("Could not pause the call")); - } - call->state = LinphoneCallPaused; - linphone_core_unset_the_current_call(lc); - linphone_core_stop_media_streams(lc,call); - //have to be done ... because if another call is incoming before this pause, you will get sound on the end point paused - linphone_core_init_media_streams(lc,call); - lc->vtable.display_status(lc,_("Pause the current 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 (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Pausing the current call...")); return 0; } @@ -2608,7 +2290,7 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call) **/ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call) { - char temp[255]; + char temp[255]={0}; LinphoneCall *call = the_call; if(lc == NULL) { @@ -2630,26 +2312,25 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call) return -2; } } - if(call->state == LinphoneCallInit || call->state == LinphoneCallPreEstablishing || call->state == LinphoneCallRinging ) + if(call->state!=LinphoneCallPaused ) { ms_warning("we cannot resume a call when the communication is not established"); - return -3; + return -1; } if(linphone_core_get_current_call(lc) != NULL) { ms_error("There is already a call in process pause or stop it first\n"); - return -4; + return -1; } - linphone_core_init_media_streams(lc,call); if(sal_call_hold(call->op,FALSE) != 0) { lc->vtable.display_warning(lc,_("Could not resume the call")); } - call->state = LinphoneCallAVRunning; + linphone_call_set_state (call,LinphoneCallResuming,"Resuming"); linphone_core_set_as_current_call(lc,call); - linphone_core_start_media_streams(lc,call); - snprintf(temp,sizeof(temp),"Resume the call with %s",linphone_call_get_remote_address_as_string(call)); - lc->vtable.display_status(lc,temp); + 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); return 0; } @@ -2746,7 +2427,6 @@ void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away, */ linphone_core_send_publish(lc,presence_mode); } - lc->prev_mode=lc->presence_mode; lc->presence_mode=presence_mode; } @@ -2802,10 +2482,15 @@ void linphone_core_set_ring_level(LinphoneCore *lc, int level){ **/ void linphone_core_set_playback_gain_db (LinphoneCore *lc, float gaindb){ float gain=gaindb; + LinphoneCall *call=linphone_core_get_current_call (lc); + AudioStream *st; + lc->sound_conf.soft_play_lev=gaindb; - AudioStream *st=lc->audiostream; - if (!st) return; /*just return*/ + if (call==NULL || (st=call->audiostream)==NULL){ + ms_message("linphone_core_set_playback_gain_db(): no active call."); + return; + } if (st->volrecv){ ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain); }else ms_warning("Could not apply gain: gain control wasn't activated."); @@ -2817,13 +2502,7 @@ void linphone_core_set_playback_gain_db (LinphoneCore *lc, float gaindb){ * @ingroup media_parameters **/ float linphone_core_get_playback_gain_db(LinphoneCore *lc) { - float gain=0; - AudioStream *st=lc->audiostream; - if (st->volrecv){ - ms_filter_call_method(st->volrecv,MS_VOLUME_GET_GAIN_DB,&gain); - }else ms_warning("Could not get gain: gain control wasn't activated."); - - return gain; + return lc->sound_conf.soft_play_lev; } /** @@ -3128,39 +2807,46 @@ bool_t linphone_core_echo_limiter_enabled(const LinphoneCore *lc){ * @ingroup media_parameters **/ void linphone_core_mute_mic(LinphoneCore *lc, bool_t val){ - if (lc->audiostream!=NULL){ - audio_stream_set_mic_gain(lc->audiostream, - (val==TRUE) ? 0 : 1.0); // REVISIT: take mic_gain value - if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){ - audio_stream_mute_rtp(lc->audiostream,val); - } - lc->audio_muted=val; + LinphoneCall *call=linphone_core_get_current_call(lc); + if (call==NULL){ + ms_warning("linphone_core_mute_mic(): No current call !"); + return; + } + if (call->audiostream!=NULL){ + audio_stream_set_mic_gain(call->audiostream, + (val==TRUE) ? 0 : lp_config_get_float(lc->config,"sound","mic_gain",1)); + if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){ + audio_stream_mute_rtp(call->audiostream,val); + } + call->audio_muted=val; } } bool_t linphone_core_is_mic_muted(LinphoneCore *lc) { float gain=1.0; - if (lc->audiostream && lc->audiostream->volsend){ - ms_filter_call_method(lc->audiostream->volsend,MS_VOLUME_GET_GAIN,&gain); + LinphoneCall *call=linphone_core_get_current_call(lc); + if (call==NULL){ + ms_warning("linphone_core_is_mic_muted(): No current call !"); + return FALSE; + } + if (call->audiostream && call->audiostream->volsend){ + ms_filter_call_method(call->audiostream->volsend,MS_VOLUME_GET_GAIN,&gain); }else ms_warning("Could not get gain: gain control wasn't activated. "); - return gain==0; -} - -// returns audio mute status for active stream -bool_t linphone_core_is_audio_muted(LinphoneCore *lc){ - if( lc->audiostream != NULL ) - return (lc->audio_muted); - return FALSE; + return gain==0 || call->audio_muted; } // returns rtp transmission status for an active stream // if audio is muted and config parameter rtp_no_xmit_on_audio_mute // was set on then rtp transmission is also muted bool_t linphone_core_is_rtp_muted(LinphoneCore *lc){ - if( (lc->audiostream != NULL) && - linphone_core_get_rtp_no_xmit_on_audio_mute(lc)){ - return lc->audio_muted; + LinphoneCall *call=linphone_core_get_current_call(lc); + if (call==NULL){ + ms_warning("linphone_core_is_mic_muted(): No current call !"); + return FALSE; + } + if( linphone_core_get_rtp_no_xmit_on_audio_mute(lc)){ + return call->audio_muted; } return FALSE; } @@ -3184,12 +2870,17 @@ bool_t linphone_core_agc_enabled(const LinphoneCore *lc){ **/ void linphone_core_send_dtmf(LinphoneCore *lc, char dtmf) { + LinphoneCall *call=linphone_core_get_current_call(lc); + if (call==NULL){ + ms_warning("linphone_core_send_dtmf(): no active call"); + return; + } /*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/ if (linphone_core_get_use_rfc2833_for_dtmf(lc)!=0 || linphone_core_get_use_info_for_dtmf(lc)==0) { /* In Band DTMF */ - if (lc->audiostream!=NULL){ - audio_stream_send_dtmf(lc->audiostream,dtmf); + if (call->audiostream!=NULL){ + audio_stream_send_dtmf(call->audiostream,dtmf); } else { @@ -3198,10 +2889,6 @@ void linphone_core_send_dtmf(LinphoneCore *lc, char dtmf) } if (linphone_core_get_use_info_for_dtmf(lc)!=0){ /* Out of Band DTMF (use INFO method) */ - LinphoneCall *call=linphone_core_get_current_call(lc); - if (call==NULL){ - return; - } sal_call_send_dtmf(call->op,dtmf); } } @@ -3281,17 +2968,15 @@ void linphone_core_clear_call_logs(LinphoneCore *lc){ static void toggle_video_preview(LinphoneCore *lc, bool_t val){ #ifdef VIDEO_ENABLED - if (lc->videostream==NULL){ - if (val){ - if (lc->previewstream==NULL){ - lc->previewstream=video_preview_start(lc->video_conf.device, - lc->video_conf.vsize); - } - }else{ - if (lc->previewstream!=NULL){ - video_preview_stop(lc->previewstream); - lc->previewstream=NULL; - } + if (val){ + if (lc->previewstream==NULL){ + lc->previewstream=video_preview_start(lc->video_conf.device, + lc->video_conf.vsize); + } + }else{ + if (lc->previewstream!=NULL){ + video_preview_stop(lc->previewstream); + lc->previewstream=NULL; } } #endif @@ -3360,10 +3045,11 @@ bool_t linphone_core_video_preview_enabled(const LinphoneCore *lc){ * This function works at any time, including during calls. **/ void linphone_core_enable_self_view(LinphoneCore *lc, bool_t val){ + LinphoneCall *call=linphone_core_get_current_call (lc); lc->video_conf.selfview=val; #ifdef VIDEO_ENABLED - if (lc->videostream){ - video_stream_enable_self_view(lc->videostream,val); + if (call && call->videostream){ + video_stream_enable_self_view(call->videostream,val); } #endif } @@ -3422,12 +3108,13 @@ const char *linphone_core_get_video_device(const LinphoneCore *lc){ int linphone_core_set_static_picture(LinphoneCore *lc, const char *path) { #ifdef VIDEO_ENABLED VideoStream *vs = NULL; + LinphoneCall *call=linphone_core_get_current_call (lc); /* Select the video stream from the call in the first place */ - if (lc && lc->videostream) { - vs = lc->videostream; + if (call && call->videostream) { + vs = call->videostream; } /* If not in call, select the video stream from the preview */ - if (vs == NULL && lc && lc->previewstream) { + if (vs == NULL && lc->previewstream) { vs = lc->previewstream; } @@ -3457,8 +3144,9 @@ int linphone_core_set_static_picture(LinphoneCore *lc, const char *path) { **/ unsigned long linphone_core_get_native_video_window_id(const LinphoneCore *lc){ #ifdef VIDEO_ENABLED - if (lc->videostream) - return video_stream_get_native_window_id(lc->videostream); + LinphoneCall *call=linphone_core_get_current_call (lc); + if (call->videostream) + return video_stream_get_native_window_id(call->videostream); if (lc->previewstream) return video_stream_get_native_window_id(lc->previewstream); #endif @@ -3561,26 +3249,28 @@ void linphone_core_use_files(LinphoneCore *lc, bool_t yesno){ } void linphone_core_set_play_file(LinphoneCore *lc, const char *file){ + LinphoneCall *call=linphone_core_get_current_call(lc); if (lc->play_file!=NULL){ ms_free(lc->play_file); lc->play_file=NULL; } if (file!=NULL) { lc->play_file=ms_strdup(file); - if (lc->audiostream->ticker) - audio_stream_play(lc->audiostream,file); + if (call && call->audiostream && call->audiostream->ticker) + audio_stream_play(call->audiostream,file); } } void linphone_core_set_record_file(LinphoneCore *lc, const char *file){ + LinphoneCall *call=linphone_core_get_current_call(lc); if (lc->rec_file!=NULL){ ms_free(lc->rec_file); lc->rec_file=NULL; } if (file!=NULL) { lc->rec_file=ms_strdup(file); - if (lc->audiostream) - audio_stream_record(lc->audiostream,file); + if (call && call->audiostream) + audio_stream_record(call->audiostream,file); } } @@ -3656,9 +3346,9 @@ void linphone_core_set_audio_transports(LinphoneCore *lc, RtpTransport *rtp, Rtp int linphone_core_get_current_call_stats(LinphoneCore *lc, rtp_stats_t *local, rtp_stats_t *remote){ LinphoneCall *call=linphone_core_get_current_call (lc); if (call!=NULL){ - if (lc->audiostream!=NULL){ + if (call->audiostream!=NULL){ memset(remote,0,sizeof(*remote)); - audio_stream_get_local_rtp_stats (lc->audiostream,local); + audio_stream_get_local_rtp_stats (call->audiostream,local); return 0; } } @@ -3837,7 +3527,6 @@ LpConfig *linphone_core_get_config(LinphoneCore *lc){ static void linphone_core_uninit(LinphoneCore *lc) { - LinphoneGeneralStateContext gctx; while(lc->calls) { LinphoneCall *the_call = lc->calls->data; @@ -3852,8 +3541,7 @@ static void linphone_core_uninit(LinphoneCore *lc) if (lc->friends) ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_close_subscriptions); - gctx.call=NULL; - gstate_new_state(lc, GSTATE_POWER_SHUTDOWN, gctx, NULL); + linphone_core_set_state(lc,LinphoneGlobalShutdown,"Shutting down"); #ifdef VIDEO_ENABLED if (lc->previewstream!=NULL){ video_preview_stop(lc->previewstream); @@ -3880,7 +3568,7 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_core_free_payload_types(); ortp_exit(); - gstate_new_state(lc, GSTATE_POWER_OFF, gctx, NULL); + linphone_core_set_state(lc,LinphoneGlobalOff,"Off"); } static void set_network_reachable(LinphoneCore* lc,bool_t isReachable){ @@ -4033,6 +3721,12 @@ static PayloadType* find_payload_type_from_list(const char* type, int rate,const return NULL; } +/** + * Get payload type from mime type and clock rate + * @ingroup media_parameters + * This function searches in audio and video codecs for the given payload type name and clockrate. + * Returns NULL if not found. + */ PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate) { PayloadType* result = find_payload_type_from_list(type, rate, linphone_core_get_audio_codecs(lc)); if (result) { @@ -4043,6 +3737,6 @@ PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, return result; } } - //not found + /*not found*/ return NULL; } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index fb94db8dbbd9eac5a105bb4de1129a5a90732a02..774dcc817cde9b6244f199f2b373a8bc6b4bf9c5 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -161,18 +161,9 @@ char * linphone_call_log_to_str(LinphoneCallLog *cl); struct _LinphoneCall; typedef struct _LinphoneCall LinphoneCall; -typedef enum _LinphoneCallState{ - LinphoneCallInit, - LinphoneCallPreEstablishing, - LinphoneCallRinging, - LinphoneCallAVRunning, - LinphoneCallPaused, - LinphoneCallTerminated -}LinphoneCallState; -LinphoneCallState linphone_call_get_state(const LinphoneCall *call); +enum _LinphoneCallState linphone_call_get_state(const LinphoneCall *call); bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call); -bool_t linphone_call_paused(LinphoneCall *call); const LinphoneAddress * linphone_core_get_current_call_remote_address(struct _LinphoneCore *lc); const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call); char *linphone_call_get_remote_address_as_string(const LinphoneCall *call); @@ -189,18 +180,18 @@ typedef enum{ }LinphoneSubscribePolicy; typedef enum _LinphoneOnlineStatus{ - LINPHONE_STATUS_OFFLINE, - LINPHONE_STATUS_ONLINE, - LINPHONE_STATUS_BUSY, - LINPHONE_STATUS_BERIGHTBACK, - LINPHONE_STATUS_AWAY, - LINPHONE_STATUS_ONTHEPHONE, - LINPHONE_STATUS_OUTTOLUNCH, - LINPHONE_STATUS_NOT_DISTURB, - LINPHONE_STATUS_MOVED, - LINPHONE_STATUS_ALT_SERVICE, - LINPHONE_STATUS_PENDING, - LINPHONE_STATUS_END + LinphoneStatusOffline, + LinphoneStatusOnline, + LinphoneStatusBusy, + LinphoneStatusBeRightBack, + LinphoneStatusAway, + LinphoneStatusOnThePhone, + LinphoneStatusOutToLunch, + LinphoneStatusDoNotDisturb, + LinphoneStatusMoved, + LinphoneStatusAltService, + LinphoneStatusPending, + LinphoneStatusEnd }LinphoneOnlineStatus; const char *linphone_online_status_to_string(LinphoneOnlineStatus ss); @@ -371,86 +362,59 @@ void linphone_chat_room_destroy(LinphoneChatRoom *cr); void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud); void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr); -/* describes the different groups of states */ -typedef enum _gstate_group { - GSTATE_GROUP_POWER, - GSTATE_GROUP_REG, - GSTATE_GROUP_CALL -} gstate_group_t; - -typedef enum _gstate { - /* states for GSTATE_GROUP_POWER */ - GSTATE_POWER_OFF = 0, /* initial state */ - GSTATE_POWER_STARTUP, - GSTATE_POWER_ON, - GSTATE_POWER_SHUTDOWN, - /* states for GSTATE_GROUP_REG */ - GSTATE_REG_NONE = 10, /* initial state */ - GSTATE_REG_OK, - GSTATE_REG_FAILED, - GSTATE_REG_PENDING, /* a registration request is ongoing*/ - /* states for GSTATE_GROUP_CALL */ - GSTATE_CALL_IDLE = 20, /* initial state */ - GSTATE_CALL_OUT_INVITE, - GSTATE_CALL_OUT_CONNECTED, - GSTATE_CALL_IN_INVITE, - GSTATE_CALL_IN_CONNECTED, - GSTATE_CALL_END, - GSTATE_CALL_ERROR, - GSTATE_CALL_OUT_RINGING, /*remote ringing*/ - GSTATE_CALL_PAUSED, - GSTATE_CALL_RESUMED, - GSTATE_INVALID -} gstate_t; - -struct _LinphoneGeneralState { - gstate_t old_state; - gstate_t new_state; - gstate_group_t group; - const char *message; -}; -typedef struct _LinphoneGeneralState LinphoneGeneralState; - - -typedef union _LinphoneGeneralStateContext{ - LinphoneCall *call; - LinphoneProxyConfig *proxy; -}LinphoneGeneralStateContext; +typedef enum _LinphoneCallState{ + LinphoneCallIdle, + LinphoneCallIncomingProgress, + LinphoneCallOutgoingInit, + LinphoneCallOutgoingProgress, + LinphoneCallOutgoingRinging, + LinphoneCallOutgoingEarlyMedia, + LinphoneCallConnected, + LinphoneCallStreamsRunning, + LinphoneCallPausing, + LinphoneCallPaused, + LinphoneCallResuming, + LinphoneCallRefered, + LinphoneCallError, + LinphoneCallEnd, +} LinphoneCallState; + +typedef enum _LinphoneGlobalState{ + LinphoneGlobalOff, + LinphoneGlobalStartup, + LinphoneGlobalOn, + LinphoneGlobalShutdown +}LinphoneGlobalState; + +typedef enum _LinphoneRegistrationState{ + LinphoneRegistrationNone, + LinphoneRegistrationProgress, + LinphoneRegistrationOk, + LinphoneRegistrationCleared, + LinphoneRegistrationFailed +}LinphoneRegistrationState; /** * @addtogroup initializing * @{ **/ + +/**Call state notification callback prototype*/ +typedef void (*LinphoneGlobalStateCb)(struct _LinphoneCore *lc, LinphoneGlobalState gstate, const char *message); +/**Call state notification callback prototype*/ +typedef void (*LinphoneCallStateCb)(struct _LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message); +/**Registration state notification callback prototype*/ +typedef void (*LinphoneRegistrationStateCb)(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneCallState cstate, const char *message); /** Callback prototype */ typedef void (*ShowInterfaceCb)(struct _LinphoneCore *lc); /** Callback prototype */ -typedef void (*InviteReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call); -/** Callback prototype */ -typedef void (*ByeReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call); -/** Callback prototype */ -typedef void (*RingingReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call); -/** Callback prototype */ -typedef void (*ConnectedReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call); -/** Callback prototype */ -typedef void (*FailureReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call, int error_code); -/** Callback prototype */ -typedef void (*PausedReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call); -/** Callback prototype */ -typedef void (*ResumedReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call); -/** Callback prototype */ -typedef void (*AckPausedReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call); -/** Callback prototype */ -typedef void (*AckResumedReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call); -/** Callback prototype */ typedef void (*DisplayStatusCb)(struct _LinphoneCore *lc, const char *message); /** Callback prototype */ typedef void (*DisplayMessageCb)(struct _LinphoneCore *lc, const char *message); /** Callback prototype */ typedef void (*DisplayUrlCb)(struct _LinphoneCore *lc, const char *message, const char *url); /** Callback prototype */ -typedef void (*DisplayQuestionCb)(struct _LinphoneCore *lc, const char *message); -/** Callback prototype */ typedef void (*LinphoneCoreCbFunc)(struct _LinphoneCore *lc,void * user_data); /** Callback prototype */ typedef void (*NotifyReceivedCb)(struct _LinphoneCore *lc, const char *from, const char *msg); @@ -465,8 +429,6 @@ typedef void (*CallLogUpdated)(struct _LinphoneCore *lc, struct _LinphoneCallLog /** Callback prototype */ typedef void (*TextMessageReceived)(struct _LinphoneCore *lc, LinphoneChatRoom *room, const char *from, const char *message); /** Callback prototype */ -typedef void (*GeneralStateChange)(struct _LinphoneCore *lc, LinphoneGeneralState *gstate, LinphoneGeneralStateContext ctx); -/** Callback prototype */ typedef void (*DtmfReceived)(struct _LinphoneCore* lc, LinphoneCall *call, int dtmf); /** Callback prototype */ typedef void (*ReferReceived)(struct _LinphoneCore *lc, LinphoneCall *call, const char *refer_to); @@ -475,20 +437,12 @@ typedef void (*BuddyInfoUpdated)(struct _LinphoneCore *lc, LinphoneFriend *lf); /** * This structure holds all callbacks that the application should implement. - * + * None is mandatory. **/ -typedef struct _LinphoneVTable -{ - InviteReceivedCb inv_recv; /**< Notifies incoming calls */ - ByeReceivedCb bye_recv; /**< Notify calls terminated by far end*/ - RingingReceivedCb ringing_recv; /**< Notify that the distant phone is ringing*/ - ConnectedReceivedCb connected_recv; /**< Notify that the distant phone answered the call*/ - FailureReceivedCb failure_recv; /**< Notify that the call failed*/ - PausedReceivedCb paused_recv; /**< Notify that the call has been paused*/ - ResumedReceivedCb resumed_recv; /**< Notify that the call has been resumed*/ - AckPausedReceivedCb ack_paused_recv;/**< Notify that the previous command pause sent to the call has been acknowledge*/ - AckResumedReceivedCb ack_resumed_recv;/**< Notify that the previous command resumed sent to the call has been acknowledge*/ - GeneralStateChange general_state; /**< State notification callback */ +typedef struct _LinphoneVTable{ + LinphoneGlobalStateCb global_state_changed; /**<Notifies globlal state changes*/ + LinphoneRegistrationStateCb registration_state_changed;/**<Notifies registration state changes*/ + LinphoneCallStateCb call_state_changed;/**<Notifies call state changes*/ NotifyPresenceReceivedCb notify_presence_recv; /**< Notify received presence events*/ NewUnknownSubscriberCb new_unknown_subscriber; /**< Notify about unknown subscriber */ AuthInfoRequested auth_info_requested; /**< Ask the application some authentication information */ @@ -518,9 +472,9 @@ typedef struct _LCCallbackObj typedef enum _LinphoneFirewallPolicy{ - LINPHONE_POLICY_NO_FIREWALL, - LINPHONE_POLICY_USE_NAT_ADDRESS, - LINPHONE_POLICY_USE_STUN + LinphonePolicyNoFirewall, + LinphonePolicyUseNatAddress, + LinphonePolicyUseStun } LinphoneFirewallPolicy; typedef enum _LinphoneWaitingState{ @@ -559,7 +513,7 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc); bool_t linphone_core_in_call(const LinphoneCore *lc); -LinphoneCall *linphone_core_get_current_call(LinphoneCore *lc); +LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc); int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call); @@ -605,13 +559,6 @@ void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime); */ int linphone_core_get_download_ptime(LinphoneCore *lc); -#ifdef VINCENT_MAURY_RSVP -/* QoS functions */ -int linphone_core_set_rpc_mode(LinphoneCore *lc, int on); /* on = 1 (RPC_ENABLE = 1) */ -int linphone_core_set_rsvp_mode(LinphoneCore *lc, int on); /* on = 1 (RSVP_ENABLE = 1) */ -int linphone_core_change_qos(LinphoneCore *lc, int answer); /* answer = 1 for yes, 0 for no */ -#endif - /* returns a MSList of PayloadType */ const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc); @@ -625,12 +572,6 @@ bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, PayloadType *pt); int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enable); -/* - * get payload type from mime type an clock rate - * @ingroup media_parameters - * iterates both audio an video - * return NULL if not found - */ PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate) ; const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt); @@ -825,7 +766,6 @@ void linphone_core_use_files(LinphoneCore *lc, bool_t yesno); void linphone_core_set_play_file(LinphoneCore *lc, const char *file); void linphone_core_set_record_file(LinphoneCore *lc, const char *file); -gstate_t linphone_core_get_state(const LinphoneCore *lc, gstate_group_t group); int linphone_core_get_current_call_duration(const LinphoneCore *lc); const LinphoneAddress *linphone_core_get_remote_address(LinphoneCore *lc); diff --git a/coreapi/misc.c b/coreapi/misc.c index 58f325d94ddffc9fe99731969ca7fda7d1221bcc..ced4f3396dd1da6fa91eacdc50c5c13007583162 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -497,10 +497,10 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ lc->vtable.display_status(lc,_("Stun lookup in progress...")); /*create the two audio and video RTP sockets, and send STUN message to our stun server */ - sock1=create_socket(linphone_core_get_audio_port(lc)); + sock1=create_socket(call->audio_port); if (sock1<0) return; if (video_enabled){ - sock2=create_socket(linphone_core_get_video_port(lc)); + sock2=create_socket(call->video_port); if (sock2<0) return ; } sendStunRequest(sock1,(struct sockaddr*)&ss,ss_len,11,TRUE); diff --git a/coreapi/presence.c b/coreapi/presence.c index c56861d9df1a5ebcd1ea4c6d4b434b44e2e89798..57e764c38e5ee0fa10191523766d12a165ae4728 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -92,36 +92,36 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeState ss, Sal char *tmp; LinphoneFriend *lf; LinphoneAddress *friend=NULL; - LinphoneOnlineStatus estatus=LINPHONE_STATUS_OFFLINE; + LinphoneOnlineStatus estatus=LinphoneStatusOffline; switch(sal_status){ case SalPresenceOffline: - estatus=LINPHONE_STATUS_OFFLINE; + estatus=LinphoneStatusOffline; break; case SalPresenceOnline: - estatus=LINPHONE_STATUS_ONLINE; + estatus=LinphoneStatusOnline; break; case SalPresenceBusy: - estatus=LINPHONE_STATUS_BUSY; + estatus=LinphoneStatusBusy; break; case SalPresenceBerightback: - estatus=LINPHONE_STATUS_AWAY; + estatus=LinphoneStatusBeRightBack; break; case SalPresenceAway: - estatus=LINPHONE_STATUS_AWAY; + estatus=LinphoneStatusAway; break; case SalPresenceOnthephone: - estatus=LINPHONE_STATUS_ONTHEPHONE; + estatus=LinphoneStatusOnThePhone; break; case SalPresenceOuttolunch: - estatus=LINPHONE_STATUS_OUTTOLUNCH; + estatus=LinphoneStatusOutToLunch; break; case SalPresenceDonotdisturb: - estatus=LINPHONE_STATUS_BUSY; + estatus=LinphoneStatusDoNotDisturb; break; case SalPresenceMoved: case SalPresenceAltService: - estatus=LINPHONE_STATUS_AWAY; + estatus=LinphoneStatusMoved; break; } lf=linphone_find_friend_by_out_subscribe(lc->friends,op); diff --git a/coreapi/private.h b/coreapi/private.h index 818fc779e95c949dd6f07c86b6c974c5c98a762a..28caaaf9daadab7f947d43a8dffb7f7e03627134 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -54,12 +54,6 @@ #endif #endif - -/* private: set a new state */ -void gstate_new_state(struct _LinphoneCore *lc, gstate_t new_state, LinphoneGeneralStateContext context, const char *message); -/*private*/ -void gstate_initialize(struct _LinphoneCore *lc); - struct _LinphoneCall { struct _LinphoneCore *core; @@ -76,28 +70,32 @@ struct _LinphoneCall time_t media_start_time; /*time at which it was accepted, media streams established*/ LinphoneCallState state; int refcnt; - bool_t media_pending; void * user_pointer; + int audio_port; + int video_port; + struct _AudioStream *audiostream; /**/ + struct _VideoStream *videostream; + bool_t media_pending; + bool_t audio_muted; }; LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to); LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op); -void linphone_call_set_terminated(LinphoneCall *call); +void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message); /* private: */ LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *local, LinphoneAddress * remote); void linphone_call_log_completed(LinphoneCallLog *calllog, LinphoneCall *call, LinphoneCallStatus status); void linphone_call_log_destroy(LinphoneCallLog *cl); - -void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call); - void linphone_auth_info_write_config(struct _LpConfig *config, LinphoneAuthInfo *obj, int pos); void linphone_core_update_proxy_register(LinphoneCore *lc); void linphone_core_refresh_subscribes(LinphoneCore *lc); +int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error); int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphoneOnlineStatus os); +void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState rstate, const char *message); int linphone_online_status_to_eXosip(LinphoneOnlineStatus os); void linphone_friend_close_subscriptions(LinphoneFriend *lf); @@ -172,8 +170,11 @@ int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char void linphone_core_text_received(LinphoneCore *lc, const char *from, const char *msg); -void linphone_core_start_media_streams(LinphoneCore *lc, struct _LinphoneCall *call); -void linphone_core_stop_media_streams(LinphoneCore *lc, struct _LinphoneCall *call); +void linphone_call_init_media_streams(LinphoneCall *call); +void linphone_call_start_media_streams(LinphoneCall *call); +void linphone_call_set_media_streams_dir(LinphoneCall *call, SalStreamDir dir); +void linphone_call_stop_media_streams(LinphoneCall *call); + const char * linphone_core_get_identity(LinphoneCore *lc); const char * linphone_core_get_route(LinphoneCore *lc); bool_t linphone_core_is_in_communication_with(LinphoneCore *lc, const char *to); @@ -372,8 +373,6 @@ struct _LinphoneCore MSList *chatrooms; int max_call_logs; int missed_calls; - struct _AudioStream *audiostream; /**/ - struct _VideoStream *videostream; struct _VideoStream *previewstream; struct _MSEventQueue *msevq; RtpTransport *a_rtp,*a_rtcp; @@ -381,7 +380,6 @@ struct _LinphoneCore MSList *subscribers; /* unknown subscribers */ int minutes_away; LinphoneOnlineStatus presence_mode; - LinphoneOnlineStatus prev_mode; char *alt_contact; void *data; char *play_file; @@ -392,9 +390,6 @@ struct _LinphoneCore int dw_video_bw; int up_video_bw; int audio_bw; - gstate_t gstate_power; - gstate_t gstate_reg; - gstate_t gstate_call; LinphoneWaitingCallback wait_cb; void *wait_ctx; bool_t use_files; @@ -404,16 +399,16 @@ struct _LinphoneCore bool_t preview_finished; bool_t auto_net_state_mon; bool_t network_reachable; - bool_t audio_muted; }; bool_t linphone_core_can_we_add_call(LinphoneCore *lc); int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call); int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call); int linphone_core_set_as_current_call(LinphoneCore *lc, LinphoneCall *call); -int linphone_core_unset_the_current_call(LinphoneCore *lc); int linphone_core_get_calls_nb(const LinphoneCore *lc); +void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message); + #define HOLD_OFF (0) #define HOLD_ON (1) diff --git a/coreapi/proxy.c b/coreapi/proxy.c index e4870c78155e4ceff47eb154a2567d978b37108d..848c8e4df2ce9ec6bff62ded6123695d332e880b 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -262,10 +262,8 @@ static char *guess_contact_for_register(LinphoneProxyConfig *obj){ } static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ - LinphoneGeneralStateContext gctx; const char *id_str; - gctx.proxy=obj; if (obj->reg_identity!=NULL) id_str=obj->reg_identity; else id_str=linphone_core_get_primary_contact(obj->lc); if (obj->reg_sendregister){ @@ -277,10 +275,10 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ sal_op_set_contact(obj->op,contact); ms_free(contact); sal_op_set_user_pointer(obj->op,obj); - if (!sal_register(obj->op,obj->reg_proxy,obj->reg_identity,obj->expires)) { - gstate_new_state(obj->lc,GSTATE_REG_PENDING, gctx, NULL); + if (sal_register(obj->op,obj->reg_proxy,obj->reg_identity,obj->expires)==0) { + linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress,"Registration in progress"); } else { - gstate_new_state(obj->lc,GSTATE_REG_FAILED, gctx, NULL); + linphone_proxy_config_set_state(obj,LinphoneRegistrationFailed,"Registration failed"); } } } @@ -799,6 +797,12 @@ void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) { return cr->user_data; } +void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){ + LinphoneCore *lc=cfg->lc; + if (lc && lc->vtable.registration_state_changed){ + lc->vtable.registration_state_changed(lc,cfg,state,message); + } +} diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c index 923dfdf1b590bdf6f43faa181c6fe595741136d4..ec0b7aff88f09af691d254bc12090fc2eea1e939 100644 --- a/coreapi/sal_eXosip2.c +++ b/coreapi/sal_eXosip2.c @@ -1782,13 +1782,9 @@ int sal_address_get_port_int(const SalAddress *uri) { } } -/** +/* * Send a re-Invite used to hold the current call - * - * @ingroup call_control - * @param lc the LinphoneCore object - * @param url the destination of the call (sip address). -**/ +*/ int sal_call_hold(SalOp *h, bool_t holdon) { int err=0; diff --git a/mediastreamer2 b/mediastreamer2 index 4b5164714c2cf77a284f0213fc79e9b147e8563a..04be0f4c3eac2d30828963b3617497bb9337e3bc 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 4b5164714c2cf77a284f0213fc79e9b147e8563a +Subproject commit 04be0f4c3eac2d30828963b3617497bb9337e3bc