major redesign of liblinphone in progress

This commit is contained in:
Simon Morlat 2010-08-16 17:08:28 +02:00
parent 725638c7bc
commit 675f7bcd9e
12 changed files with 788 additions and 846 deletions

View file

@ -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 \

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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){
}

View file

@ -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 "mediastreamer2/mediastream.h"
#include "mediastreamer2/msvolume.h"
#include "mediastreamer2/msequalizer.h"
#include "mediastreamer2/mseventqueue.h"
#include <ortp/telephonyevents.h>
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/mseventqueue.h"
#include "mediastreamer2/msvolume.h"
#include "mediastreamer2/msequalizer.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"));
if (lc->vtable.display_warning)
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"));
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;
lc->sound_conf.soft_play_lev=gaindb;
AudioStream *st=lc->audiostream;
if (!st) return; /*just return*/
LinphoneCall *call=linphone_core_get_current_call (lc);
AudioStream *st;
lc->sound_conf.soft_play_lev=gaindb;
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;
}

View file

@ -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 _LinphoneCallState{
LinphoneCallIdle,
LinphoneCallIncomingProgress,
LinphoneCallOutgoingInit,
LinphoneCallOutgoingProgress,
LinphoneCallOutgoingRinging,
LinphoneCallOutgoingEarlyMedia,
LinphoneCallConnected,
LinphoneCallStreamsRunning,
LinphoneCallPausing,
LinphoneCallPaused,
LinphoneCallResuming,
LinphoneCallRefered,
LinphoneCallError,
LinphoneCallEnd,
} LinphoneCallState;
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;
typedef enum _LinphoneGlobalState{
LinphoneGlobalOff,
LinphoneGlobalStartup,
LinphoneGlobalOn,
LinphoneGlobalShutdown
}LinphoneGlobalState;
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 _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);

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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;

@ -1 +1 @@
Subproject commit 4b5164714c2cf77a284f0213fc79e9b147e8563a
Subproject commit 04be0f4c3eac2d30828963b3617497bb9337e3bc