mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-24 14:48:07 +00:00
support early media sending for outgoing calls
This commit is contained in:
parent
801508597b
commit
f55a93216d
10 changed files with 241 additions and 115 deletions
|
|
@ -144,7 +144,10 @@ static LPC_COMMAND commands[] = {
|
|||
},
|
||||
{ "call", lpc_cmd_call, "Call a SIP uri or number",
|
||||
#ifdef VIDEO_ENABLED
|
||||
"'call <sip-url or number> [--audio-only]' \t: initiate a call to the specified destination.\n"
|
||||
"'call <sip-url or number> [options]' \t: initiate a call to the specified destination.\n"
|
||||
"Options can be:\n"
|
||||
"--audio-only : initiate the call without video.\n"
|
||||
"--early-media : sends audio and video stream immediately when remote proposes early media.\n"
|
||||
#else
|
||||
"'call <sip-url or number>' \t: initiate a call to the specified destination.\n"
|
||||
#endif
|
||||
|
|
@ -542,17 +545,22 @@ lpc_cmd_call(LinphoneCore *lc, char *args)
|
|||
{
|
||||
LinphoneCall *call;
|
||||
LinphoneCallParams *cp=linphone_core_create_default_call_parameters (lc);
|
||||
char *opt;
|
||||
char *opt1,*opt2;
|
||||
if ( linphone_core_in_call(lc) )
|
||||
{
|
||||
linphonec_out("Terminate or hold on the current call first.\n");
|
||||
return 1;
|
||||
}
|
||||
opt=strstr(args,"--audio-only");
|
||||
if (opt){
|
||||
opt[0]='\0';
|
||||
opt1=strstr(args,"--audio-only");
|
||||
opt2=strstr(args,"--early-media");
|
||||
if (opt1){
|
||||
opt1[0]='\0';
|
||||
linphone_call_params_enable_video (cp,FALSE);
|
||||
}
|
||||
if (opt2){
|
||||
opt2[0]='\0';
|
||||
linphone_call_params_enable_early_media_sending(cp,TRUE);
|
||||
}
|
||||
if ( NULL == (call=linphone_core_invite_with_params(lc, args,cp)) )
|
||||
{
|
||||
linphonec_out("Error from linphone_core_invite.\n");
|
||||
|
|
|
|||
|
|
@ -356,10 +356,28 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L
|
|||
break;
|
||||
case LinphoneCallOutgoingInit:
|
||||
linphonec_call_identify(call);
|
||||
id=(long)linphone_call_get_user_pointer (call);
|
||||
from=linphone_call_get_remote_address_as_string(call);
|
||||
linphonec_out("Establishing call id to %s, assigned id %i\n", from,id);
|
||||
break;
|
||||
case LinphoneCallUpdatedByRemote:
|
||||
linphonec_call_updated(call);
|
||||
break;
|
||||
case LinphoneCallOutgoingProgress:
|
||||
linphonec_out("Call %i to %s in progress.\n", id, from);
|
||||
break;
|
||||
case LinphoneCallOutgoingRinging:
|
||||
linphonec_out("Call %i to %s ringing.\n", id, from);
|
||||
break;
|
||||
case LinphoneCallConnected:
|
||||
linphonec_out("Call %i with %s connected.\n", id, from);
|
||||
break;
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
linphonec_out("Call %i with %s early media.\n", id, from);
|
||||
break;
|
||||
case LinphoneCallError:
|
||||
linphonec_out("Call %i with %s error.\n", id, from);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,12 +27,60 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details);
|
||||
|
||||
static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){
|
||||
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
|
||||
SalMediaDescription *oldmd=call->resultdesc;
|
||||
|
||||
if (lc->ringstream!=NULL){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_call_start_media_streams(call);
|
||||
if (new_md!=NULL){
|
||||
sal_media_description_ref(new_md);
|
||||
call->media_pending=FALSE;
|
||||
}else{
|
||||
call->media_pending=TRUE;
|
||||
}
|
||||
call->resultdesc=new_md;
|
||||
if (call->audiostream && call->audiostream->ticker){
|
||||
/* we already started media: check if we really need to restart it*/
|
||||
if (oldmd){
|
||||
if (sal_media_description_equals(oldmd,new_md)){
|
||||
sal_media_description_unref(oldmd);
|
||||
if (call->all_muted){
|
||||
ms_message("Early media finished, unmuting inputs...");
|
||||
/*we were in early media, now we want to enable real media */
|
||||
linphone_call_enable_camera (call,linphone_call_camera_enabled (call));
|
||||
if (call->audiostream)
|
||||
linphone_core_mute_mic (lc, linphone_core_is_mic_muted(lc));
|
||||
}
|
||||
ms_message("No need to restart streams, SDP is unchanged.");
|
||||
return;
|
||||
}else{
|
||||
ms_message("Media descriptions are different, need to restart the streams.");
|
||||
}
|
||||
}
|
||||
linphone_call_stop_media_streams (call);
|
||||
linphone_call_init_media_streams (call);
|
||||
}
|
||||
if (oldmd)
|
||||
sal_media_description_unref(oldmd);
|
||||
|
||||
if (new_md) {
|
||||
bool_t all_muted=FALSE;
|
||||
bool_t send_ringbacktone=FALSE;
|
||||
|
||||
if (call->audiostream==NULL){
|
||||
/*this happens after pausing the call locally. The streams is destroyed and then we wait the 200Ok to recreate it*/
|
||||
linphone_call_init_media_streams (call);
|
||||
}
|
||||
if (call->state==LinphoneCallIncomingEarlyMedia ||
|
||||
(call->state==LinphoneCallOutgoingEarlyMedia && !call->params.real_early_media)){
|
||||
all_muted=TRUE;
|
||||
}else if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
|
||||
send_ringbacktone=TRUE;
|
||||
}
|
||||
linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
|
||||
}
|
||||
}
|
||||
|
||||
static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){
|
||||
|
|
@ -55,7 +103,9 @@ static void call_received(SalOp *h){
|
|||
char *tmp;
|
||||
LinphoneAddress *from_parsed;
|
||||
LinphoneAddress *from_addr, *to_addr;
|
||||
const char * early_media=linphone_core_get_remote_ringback_tone (lc);
|
||||
SalMediaDescription *md;
|
||||
bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE);
|
||||
const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc);
|
||||
|
||||
/* first check if we can answer successfully to this invite */
|
||||
if (lc->presence_mode==LinphoneStatusBusy ||
|
||||
|
|
@ -93,16 +143,14 @@ static void call_received(SalOp *h){
|
|||
|
||||
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
|
||||
sal_call_set_local_media_description(h,call->localdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(h);
|
||||
if (call->resultdesc)
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
if (call->resultdesc && sal_media_description_empty(call->resultdesc)){
|
||||
md=sal_call_get_final_media_description(h);
|
||||
|
||||
if (md && sal_media_description_empty(md)){
|
||||
sal_call_decline(h,SalReasonMedia,NULL);
|
||||
linphone_call_unref(call);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* the call is acceptable so we can now add it to our list */
|
||||
linphone_core_add_call(lc,call);
|
||||
|
||||
|
|
@ -136,17 +184,18 @@ static void call_received(SalOp *h){
|
|||
}else{
|
||||
/*TODO : play a tone within the context of the current call */
|
||||
}
|
||||
sal_call_notify_ringing(h,early_media!=NULL);
|
||||
#if !(__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000)
|
||||
linphone_call_init_media_streams(call);
|
||||
if (early_media!=NULL){
|
||||
linphone_call_start_early_media (call);
|
||||
linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
|
||||
|
||||
sal_call_notify_ringing(h,propose_early_media || ringback_tone!=NULL);
|
||||
|
||||
if (propose_early_media || ringback_tone!=NULL){
|
||||
linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
|
||||
linphone_core_update_streams(lc,call,md);
|
||||
}
|
||||
#endif
|
||||
ms_free(barmesg);
|
||||
ms_free(tmp);
|
||||
|
||||
linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
|
||||
|
||||
if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){
|
||||
linphone_core_accept_call(lc,call);
|
||||
}
|
||||
|
|
@ -183,8 +232,6 @@ static void call_ringing(SalOp *h){
|
|||
ms_message("Early media already started.");
|
||||
return;
|
||||
}
|
||||
sal_media_description_ref(md);
|
||||
call->resultdesc=md;
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Early media."));
|
||||
|
|
@ -194,8 +241,7 @@ static void call_ringing(SalOp *h){
|
|||
lc->ringstream=NULL;
|
||||
}
|
||||
ms_message("Doing early media...");
|
||||
linphone_call_start_media_streams(call);
|
||||
call->media_pending=TRUE;
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -207,33 +253,23 @@ 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);
|
||||
|
||||
SalMediaDescription *md;
|
||||
|
||||
if (call==NULL){
|
||||
ms_warning("No call to accept.");
|
||||
return ;
|
||||
}
|
||||
if ((call->audiostream!=NULL) && (call->audiostream->ticker!=NULL)){
|
||||
/*case where we accepted early media or already in call*/
|
||||
linphone_call_stop_media_streams(call);
|
||||
}
|
||||
if (call->audiostream==NULL){
|
||||
linphone_call_init_media_streams(call);
|
||||
}
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc){
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
call->media_pending=FALSE;
|
||||
}
|
||||
|
||||
md=sal_call_get_final_media_description(op);
|
||||
|
||||
if (call->state==LinphoneCallOutgoingProgress ||
|
||||
call->state==LinphoneCallOutgoingRinging ||
|
||||
call->state==LinphoneCallOutgoingEarlyMedia){
|
||||
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
|
||||
}
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
|
||||
if (sal_media_description_has_dir(call->resultdesc,SalStreamSendOnly) ||
|
||||
sal_media_description_has_dir(call->resultdesc,SalStreamInactive)){
|
||||
if (md && !sal_media_description_empty(md)){
|
||||
if (sal_media_description_has_dir(md,SalStreamSendOnly) ||
|
||||
sal_media_description_has_dir(md,SalStreamInactive)){
|
||||
if (lc->vtable.display_status){
|
||||
char *tmp=linphone_call_get_remote_address_as_string (call);
|
||||
char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp);
|
||||
|
|
@ -242,7 +278,7 @@ static void call_accepted(SalOp *op){
|
|||
ms_free(msg);
|
||||
}
|
||||
linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
|
||||
}else if (sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly)){
|
||||
}else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){
|
||||
/*we are put on hold when the call is initially accepted */
|
||||
if (lc->vtable.display_status){
|
||||
char *tmp=linphone_call_get_remote_address_as_string (call);
|
||||
|
|
@ -258,7 +294,7 @@ static void call_accepted(SalOp *op){
|
|||
}
|
||||
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}
|
||||
linphone_connect_incoming (lc,call);
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
}else{
|
||||
/*send a bye*/
|
||||
ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
|
||||
|
|
@ -274,18 +310,9 @@ static void call_ack(SalOp *op){
|
|||
return ;
|
||||
}
|
||||
if (call->media_pending){
|
||||
if (call->audiostream->ticker!=NULL){
|
||||
/*case where we accepted early media */
|
||||
linphone_call_stop_media_streams(call);
|
||||
linphone_call_init_media_streams(call);
|
||||
}
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc)
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
|
||||
linphone_connect_incoming(lc,call);
|
||||
SalMediaDescription *md=sal_call_get_final_media_description(op);
|
||||
if (md && !sal_media_description_empty(md)){
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}else{
|
||||
/*send a bye*/
|
||||
|
|
@ -293,7 +320,6 @@ static void call_ack(SalOp *op){
|
|||
linphone_core_abort_call(lc,call,"No codec intersection");
|
||||
return;
|
||||
}
|
||||
call->media_pending=FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -302,17 +328,14 @@ static void call_updating(SalOp *op){
|
|||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
LinphoneCallState prevstate=LinphoneCallIdle;
|
||||
SalMediaDescription *md;
|
||||
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc)
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc))
|
||||
md=sal_call_get_final_media_description(op);
|
||||
|
||||
if (md && !sal_media_description_empty(md))
|
||||
{
|
||||
if ((call->state==LinphoneCallPausedByRemote || call->state==LinphoneCallPaused) &&
|
||||
sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv) && strcmp(call->resultdesc->addr,"0.0.0.0")!=0){
|
||||
sal_media_description_has_dir(md,SalStreamSendRecv) && strcmp(md->addr,"0.0.0.0")!=0){
|
||||
/*make sure we can be resumed */
|
||||
if (lc->current_call!=NULL && lc->current_call!=call){
|
||||
ms_warning("Attempt to be resumed but already in call with somebody else!");
|
||||
|
|
@ -325,9 +348,9 @@ static void call_updating(SalOp *op){
|
|||
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}
|
||||
else if(call->state==LinphoneCallStreamsRunning &&
|
||||
( sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly)
|
||||
|| sal_media_description_has_dir(call->resultdesc,SalStreamInactive)
|
||||
|| strcmp(call->resultdesc->addr,"0.0.0.0")==0)){
|
||||
( sal_media_description_has_dir(md,SalStreamRecvOnly)
|
||||
|| sal_media_description_has_dir(md,SalStreamInactive)
|
||||
|| strcmp(md->addr,"0.0.0.0")==0)){
|
||||
if(lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("We are being paused..."));
|
||||
linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote");
|
||||
|
|
@ -340,9 +363,7 @@ static void call_updating(SalOp *op){
|
|||
}
|
||||
/*accept the modification (sends a 200Ok)*/
|
||||
sal_call_accept(op);
|
||||
linphone_call_stop_media_streams (call);
|
||||
linphone_call_init_media_streams (call);
|
||||
linphone_call_start_media_streams (call);
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
if (prevstate!=LinphoneCallIdle){
|
||||
linphone_call_set_state (call,prevstate,"Connected (streams running)");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -279,6 +279,8 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){
|
|||
return "LinphoneCallPausedByRemote";
|
||||
case LinphoneCallUpdatedByRemote:
|
||||
return "LinphoneCallUpdatedByRemote";
|
||||
case LinphoneCallIncomingEarlyMedia:
|
||||
return "LinphoneCallIncomingEarlyMedia";
|
||||
}
|
||||
return "undefined state";
|
||||
}
|
||||
|
|
@ -521,6 +523,17 @@ bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
|
|||
return cp->has_video;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable sending of real early media (during outgoing calls).
|
||||
**/
|
||||
void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){
|
||||
cp->real_early_media=enabled;
|
||||
}
|
||||
|
||||
bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){
|
||||
return cp->real_early_media;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
**/
|
||||
|
|
@ -638,9 +651,10 @@ static void post_configure_audio_streams(LinphoneCall*call){
|
|||
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)
|
||||
if (!call->audio_muted)
|
||||
audio_stream_set_mic_gain(st,mic_gain);
|
||||
call->audio_muted=FALSE;
|
||||
else
|
||||
audio_stream_set_mic_gain(st,0);
|
||||
|
||||
recv_gain = lc->sound_conf.soft_play_lev;
|
||||
if (recv_gain != 0) {
|
||||
|
|
@ -738,18 +752,21 @@ static RtpProfile *make_profile(LinphoneCore *lc, const SalMediaDescription *md,
|
|||
return prof;
|
||||
}
|
||||
|
||||
|
||||
static void setup_ring_player(LinphoneCore *lc, LinphoneCall *call){
|
||||
int pause_time=3000;
|
||||
audio_stream_play(call->audiostream,lc->sound_conf.ringback_tone);
|
||||
ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
|
||||
}
|
||||
|
||||
static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_early_media){
|
||||
|
||||
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone){
|
||||
LinphoneCore *lc=call->core;
|
||||
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
|
||||
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 !");
|
||||
|
|
@ -783,12 +800,11 @@ static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_e
|
|||
if (stream->port==0 || stream->dir==SalStreamRecvOnly){
|
||||
captcard=NULL;
|
||||
playfile=NULL;
|
||||
}else if (stream->dir==SalStreamSendOnly || send_early_media){
|
||||
}else if (stream->dir==SalStreamSendOnly){
|
||||
playcard=NULL;
|
||||
captcard=NULL;
|
||||
recfile=NULL;
|
||||
if (send_early_media)
|
||||
playfile=NULL;
|
||||
if (!send_ringbacktone) playfile=NULL;
|
||||
}
|
||||
/*if playfile are supplied don't use soundcards*/
|
||||
if (lc->use_files) {
|
||||
|
|
@ -809,13 +825,18 @@ static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_e
|
|||
captcard,
|
||||
captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc));
|
||||
post_configure_audio_streams(call);
|
||||
if (send_early_media) setup_ring_player(lc,call);
|
||||
if (all_inputs_muted){
|
||||
audio_stream_set_mic_gain(call->audiostream,0);
|
||||
}
|
||||
if (send_ringbacktone){
|
||||
setup_ring_player(lc,call);
|
||||
}
|
||||
audio_stream_set_rtcp_information(call->audiostream, cname, tool);
|
||||
}else ms_warning("No audio stream accepted ?");
|
||||
}
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (!send_early_media){
|
||||
{
|
||||
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpAvp,SalVideo);
|
||||
used_pt=-1;
|
||||
|
|
@ -859,7 +880,7 @@ static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_e
|
|||
/*either inactive or incompatible with local capabilities*/
|
||||
is_inactive=TRUE;
|
||||
}
|
||||
if (call->camera_active==FALSE){
|
||||
if (call->camera_active==FALSE || all_inputs_muted){
|
||||
cam=get_nowebcam_device();
|
||||
}
|
||||
if (!is_inactive){
|
||||
|
|
@ -876,21 +897,14 @@ static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_e
|
|||
}
|
||||
}
|
||||
#endif
|
||||
call->all_muted=all_inputs_muted;
|
||||
|
||||
goto end;
|
||||
end:
|
||||
ms_free(cname);
|
||||
linphone_address_destroy(me);
|
||||
}
|
||||
|
||||
|
||||
void linphone_call_start_media_streams(LinphoneCall *call){
|
||||
_linphone_call_start_media_streams(call,FALSE);
|
||||
}
|
||||
|
||||
void linphone_call_start_early_media(LinphoneCall *call){
|
||||
_linphone_call_start_media_streams(call,TRUE);
|
||||
}
|
||||
|
||||
static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){
|
||||
audio_stream_get_local_rtp_stats (st,&log->local_stats);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -467,8 +467,9 @@ static void sound_config_read(LinphoneCore *lc)
|
|||
|
||||
gain=lp_config_get_float(lc->config,"sound","playback_gain_db",0);
|
||||
linphone_core_set_playback_gain_db (lc,gain);
|
||||
|
||||
/*
|
||||
linphone_core_set_remote_ringback_tone (lc,lp_config_get_string(lc->config,"sound","ringback_tone",NULL));
|
||||
*/
|
||||
}
|
||||
|
||||
static void sip_config_read(LinphoneCore *lc)
|
||||
|
|
@ -2221,6 +2222,7 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call)
|
|||
LinphoneProxyConfig *cfg=NULL;
|
||||
const char *contact=NULL;
|
||||
SalOp *replaced;
|
||||
SalMediaDescription *new_md;
|
||||
|
||||
if (call==NULL){
|
||||
//if just one call is present answer the only one ...
|
||||
|
|
@ -2276,26 +2278,21 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call)
|
|||
contact=get_fixed_contact(lc,call,cfg);
|
||||
if (contact)
|
||||
sal_op_set_contact(call->op,contact);
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000
|
||||
linphone_call_init_media_streams(call);
|
||||
#else
|
||||
if (call->audiostream!=NULL && call->audiostream->ticker!=NULL){
|
||||
/*case where we sent early media*/
|
||||
linphone_call_stop_media_streams (call);
|
||||
linphone_call_init_media_streams (call);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (call->audiostream==NULL)
|
||||
linphone_call_init_media_streams(call);
|
||||
|
||||
sal_call_accept(call->op);
|
||||
if (lc->vtable.display_status!=NULL)
|
||||
lc->vtable.display_status(lc,_("Connected."));
|
||||
lc->current_call=call;
|
||||
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);
|
||||
new_md=sal_call_get_final_media_description(call->op);
|
||||
linphone_core_update_streams(lc, call, new_md);
|
||||
if (new_md){
|
||||
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
}else call->media_pending=TRUE;
|
||||
|
||||
ms_message("call answered.");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2946,17 +2943,12 @@ void linphone_core_mute_mic(LinphoneCore *lc, bool_t val){
|
|||
}
|
||||
|
||||
bool_t linphone_core_is_mic_muted(LinphoneCore *lc) {
|
||||
float gain=1.0;
|
||||
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 || call->audio_muted;
|
||||
return call->audio_muted;
|
||||
}
|
||||
|
||||
// returns rtp transmission status for an active stream
|
||||
|
|
|
|||
|
|
@ -178,6 +178,8 @@ typedef struct _LinphoneCallParams LinphoneCallParams;
|
|||
LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp);
|
||||
void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled);
|
||||
bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp);
|
||||
void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled);
|
||||
bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp);
|
||||
void linphone_call_params_destroy(LinphoneCallParams *cp);
|
||||
|
||||
/**
|
||||
|
|
@ -216,7 +218,8 @@ typedef enum _LinphoneCallState{
|
|||
LinphoneCallError, /**<The call encountered an error*/
|
||||
LinphoneCallEnd, /**<The call ended normally*/
|
||||
LinphoneCallPausedByRemote, /**<The call is paused by remote end*/
|
||||
LinphoneCallUpdatedByRemote /**<The call's parameters are updated, used for example when video is asked by remote */
|
||||
LinphoneCallUpdatedByRemote, /**<The call's parameters are updated, used for example when video is asked by remote */
|
||||
LinphoneCallIncomingEarlyMedia /**<We are proposing early media to an incoming call */
|
||||
} LinphoneCallState;
|
||||
|
||||
const char *linphone_call_state_to_string(LinphoneCallState cs);
|
||||
|
|
@ -779,8 +782,10 @@ void linphone_core_set_ring(LinphoneCore *lc, const char *path);
|
|||
const char *linphone_core_get_ring(const LinphoneCore *lc);
|
||||
void linphone_core_set_ringback(LinphoneCore *lc, const char *path);
|
||||
const char * linphone_core_get_ringback(const LinphoneCore *lc);
|
||||
|
||||
void linphone_core_set_remote_ringback_tone(LinphoneCore *lc,const char *);
|
||||
const char *linphone_core_get_remote_ringback_tone(const LinphoneCore *lc);
|
||||
|
||||
int linphone_core_preview_ring(LinphoneCore *lc, const char *ring,LinphoneCoreCbFunc func,void * userdata);
|
||||
void linphone_core_enable_echo_cancellation(LinphoneCore *lc, bool_t val);
|
||||
bool_t linphone_core_echo_cancellation_enabled(LinphoneCore *lc);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@
|
|||
struct _LinphoneCallParams{
|
||||
LinphoneCall *referer; /*in case this call creation is consecutive to an incoming transfer, this points to the original call */
|
||||
bool_t has_video;
|
||||
bool_t pad[3];
|
||||
bool_t real_early_media; /*send real media even during early media (for outgoing calls)*/
|
||||
bool_t pad[2];
|
||||
};
|
||||
|
||||
struct _LinphoneCall
|
||||
|
|
@ -90,6 +91,7 @@ struct _LinphoneCall
|
|||
bool_t media_pending;
|
||||
bool_t audio_muted;
|
||||
bool_t camera_active;
|
||||
bool_t all_muted; /*this flag is set during early medias*/
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -187,8 +189,7 @@ 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_call_init_media_streams(LinphoneCall *call);
|
||||
void linphone_call_start_media_streams(LinphoneCall *call);
|
||||
void linphone_call_start_early_media(LinphoneCall *call);
|
||||
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone);
|
||||
void linphone_call_stop_media_streams(LinphoneCall *call);
|
||||
|
||||
const char * linphone_core_get_identity(LinphoneCore *lc);
|
||||
|
|
@ -438,7 +439,7 @@ void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const
|
|||
|
||||
SalMediaDescription *create_local_media_description(LinphoneCore *lc,
|
||||
LinphoneCall *call, bool_t with_video, bool_t only_one_codec);
|
||||
|
||||
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md);
|
||||
#define linphone_core_ready(lc) ((lc)->state!=LinphoneGlobalStartup)
|
||||
void _linphone_core_configure_resolver();
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,72 @@ bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir
|
|||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
static bool_t fmtp_equals(const char *p1, const char *p2){
|
||||
if (p1 && p2 && strcmp(p1,p2)==0) return TRUE;
|
||||
if (p1==NULL && p2==NULL) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
*/
|
||||
|
||||
static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){
|
||||
if (p1->type!=p2->type) return FALSE;
|
||||
if (strcmp(p1->mime_type,p2->mime_type)!=0) return FALSE;
|
||||
if (p1->clock_rate!=p2->clock_rate) return FALSE;
|
||||
if (p1->channels!=p2->channels) return FALSE;
|
||||
/*
|
||||
Do not compare fmtp right now: they are modified internally when the call is started
|
||||
*/
|
||||
/*
|
||||
if (!fmtp_equals(p1->recv_fmtp,p2->recv_fmtp) ||
|
||||
!fmtp_equals(p1->send_fmtp,p2->send_fmtp))
|
||||
return FALSE;
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool_t payload_list_equals(const MSList *l1, const MSList *l2){
|
||||
const MSList *e1,*e2;
|
||||
for(e1=l1,e2=l2;e1!=NULL && e2!=NULL; e1=e1->next,e2=e2->next){
|
||||
PayloadType *p1=(PayloadType*)e1->data;
|
||||
PayloadType *p2=(PayloadType*)e2->data;
|
||||
if (!payload_type_equals(p1,p2))
|
||||
return FALSE;
|
||||
}
|
||||
if (e1!=NULL || e2!=NULL){
|
||||
/*means one list is longer than the other*/
|
||||
abort();
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2){
|
||||
if (sd1->proto!=sd2->proto) return FALSE;
|
||||
if (sd1->type!=sd2->type) return FALSE;
|
||||
if (strcmp(sd1->addr,sd2->addr)!=0) return FALSE;
|
||||
if (sd1->port!=sd2->port) return FALSE;
|
||||
if (!payload_list_equals(sd1->payloads,sd2->payloads)) return FALSE;
|
||||
if (sd1->bandwidth!=sd2->bandwidth) return FALSE;
|
||||
if (sd1->ptime!=sd2->ptime) return FALSE;
|
||||
/* compare candidates: TODO */
|
||||
if (sd1->dir!=sd2->dir) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2){
|
||||
int i;
|
||||
|
||||
if (strcmp(md1->addr,md2->addr)!=0) return FALSE;
|
||||
if (md1->nstreams!=md2->nstreams) return FALSE;
|
||||
if (md1->bandwidth!=md2->bandwidth) return FALSE;
|
||||
for(i=0;i<md1->nstreams;++i){
|
||||
if (!sal_stream_description_equals(&md1->streams[i],&md2->streams[i]))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void assign_string(char **str, const char *arg){
|
||||
if (*str){
|
||||
ms_free(*str);
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ SalMediaDescription *sal_media_description_new();
|
|||
void sal_media_description_ref(SalMediaDescription *md);
|
||||
void sal_media_description_unref(SalMediaDescription *md);
|
||||
bool_t sal_media_description_empty(const SalMediaDescription *md);
|
||||
bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2);
|
||||
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir dir);
|
||||
SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
|
||||
SalMediaProto proto, SalStreamType type);
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit ffacf56718c198cb80a290f7a65975916d8a9b6b
|
||||
Subproject commit b1a4c2b6470a6de62a8e58d4f2874eda091a8db3
|
||||
Loading…
Add table
Reference in a new issue