]> sjero.net Git - linphone/commitdiff
support early media sending for outgoing calls
authorSimon Morlat <simon.morlat@linphone.org>
Wed, 24 Nov 2010 21:37:20 +0000 (22:37 +0100)
committerSimon Morlat <simon.morlat@linphone.org>
Wed, 24 Nov 2010 21:37:20 +0000 (22:37 +0100)
console/commands.c
console/linphonec.c
coreapi/callbacks.c
coreapi/linphonecall.c
coreapi/linphonecore.c
coreapi/linphonecore.h
coreapi/private.h
coreapi/sal.c
coreapi/sal.h
mediastreamer2

index a7aa22f76a30295826bdba259f8963850ab4a701..ab67569bc2a15177fc80f273f137a80b1e68d060 100644 (file)
@@ -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");
index 41b70a8163179f2549a51b475a80947f80edc531..8373f1f63326360ab53485fd5d0eb4b3880aaea3 100644 (file)
@@ -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;
        }
index d4f5193f37f9db769a0506a3749fff964bf09888..13f00a9941db0a0c68d528399ab4b3235197ae74 100644 (file)
@@ -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)");
                }
index 56509c9273693616cd9cc334b316430b11bdbc80..1d123b91aa4db3930f2456d03b2238e799755571 100644 (file)
@@ -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);
 }
index d06f3cf3b6170f9c1df1dc834409264998d26361..c21f08e666903417ec6c343dba44b50a5ba0b2d3 100644 (file)
@@ -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
index 012437f62f0d16b5f4f2639d515524034954eb09..83127b9a80133017c3d924fb562f06f5d4d3ee4f 100644 (file)
@@ -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);
index 969c337e9641cac568ec7e1ef9bff0587a59c64e..adc14ef325614923b140b9dbf929cc99e9d2d0fa 100644 (file)
@@ -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();
 
index ac44470a60ce3ba377f6e597e1bd66c0f85c9526..979969b2423daa93051bd32c705d8fbc81b3d780 100644 (file)
@@ -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);
index b0b3c7574254318649d2fa5ab3b9d0cfaf9a026b..e848f71fc934042e4ecb9c94c404b97cd508afa4 100644 (file)
@@ -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);
index ffacf56718c198cb80a290f7a65975916d8a9b6b..b1a4c2b6470a6de62a8e58d4f2874eda091a8db3 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ffacf56718c198cb80a290f7a65975916d8a9b6b
+Subproject commit b1a4c2b6470a6de62a8e58d4f2874eda091a8db3