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