]> sjero.net Git - linphone/commitdiff
Merge branch 'master' of git.savannah.nongnu.org:/srv/git/linphone
authorGuillaume Beraudo <guillaume.beraudo@linphone.org>
Wed, 23 Feb 2011 15:13:08 +0000 (16:13 +0100)
committerGuillaume Beraudo <guillaume.beraudo@linphone.org>
Wed, 23 Feb 2011 15:13:08 +0000 (16:13 +0100)
Conflicts:
mediastreamer2

1  2 
coreapi/linphonecore.c
coreapi/linphonecore.h
coreapi/linphonecore_jni.cc
java/common/org/linphone/core/LinphoneCore.java
java/common/org/linphone/core/LinphoneCoreFactory.java

diff --combined coreapi/linphonecore.c
index 6af2fbfc9d5d5a1140c5ac663b92460a2036a2d8,7b6a01640f783df256b1f55773cd3f4a7db7da7c..167630e1a8e241895f9beed8c35e3c04e7b48193
@@@ -49,6 -49,8 +49,8 @@@ static void toggle_video_preview(Linpho
  #define LOCAL_RING "rings/oldphone.wav"
  /* same for remote ring (ringback)*/
  #define REMOTE_RING "ringback.wav"
+ #define HOLD_MUSIC "rings/toy-mono.wav"
  
  extern SalCallbacks linphone_sal_callbacks;
  
@@@ -452,6 -454,8 +454,8 @@@ static void sound_config_read(LinphoneC
                tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
        }
        linphone_core_set_ringback(lc,tmpbuf);
+       linphone_core_set_play_file(lc,lp_config_get_string(lc->config,"sound","hold_music",PACKAGE_SOUND_DIR "/" HOLD_MUSIC));
        check_sound_device(lc);
        lc->sound_conf.latency=0;
  
@@@ -571,6 -575,7 +575,7 @@@ static void sip_config_read(LinphoneCor
        lc->sip_conf.keepalive_period=lp_config_get_int(lc->config,"sip","keepalive_period",10000);
        sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
        sal_use_one_matching_codec_policy(lc->sal,lp_config_get_int(lc->config,"sip","only_one_codec",0));
+       sal_use_double_registrations(lc->sal,lp_config_get_int(lc->config,"sip","use_double_registrations",1));
  }
  
  static void rtp_config_read(LinphoneCore *lc)
        jitt_comp=lp_config_get_int(lc->config,"rtp","audio_jitt_comp",60);
        linphone_core_set_audio_jittcomp(lc,jitt_comp);
        jitt_comp=lp_config_get_int(lc->config,"rtp","video_jitt_comp",60);
+       if (jitt_comp==0) jitt_comp=60;
+       lc->rtp_conf.video_jitt_comp=jitt_comp;
        nortp_timeout=lp_config_get_int(lc->config,"rtp","nortp_timeout",30);
        linphone_core_set_nortp_timeout(lc,nortp_timeout);
        rtp_no_xmit_on_audio_mute=lp_config_get_int(lc->config,"rtp","rtp_no_xmit_on_audio_mute",FALSE);
@@@ -910,7 -917,8 +917,8 @@@ static void linphone_core_init (Linphon
  {
        memset (lc, 0, sizeof (LinphoneCore));
        lc->data=userdata;
+       lc->ringstream_autorelease=TRUE;
+       
        memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable));
  
        linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up");
@@@ -1635,6 -1643,19 +1643,19 @@@ void linphone_core_iterate(LinphoneCor
                one_second_elapsed=TRUE;
        }
  
+       if (lc->ecc!=NULL){
+               LinphoneEcCalibratorStatus ecs=ec_calibrator_get_status(lc->ecc);
+               if (ecs!=LinphoneEcCalibratorInProgress){
+                       if (lc->ecc->cb)
+                               lc->ecc->cb(lc,ecs,lc->ecc->delay,lc->ecc->cb_data);
+                       if (ecs==LinphoneEcCalibratorDone){
+                               lp_config_set_int(lc->config, "sound", "ec_delay",MAX(lc->ecc->delay-10,0));
+                       }
+                       ec_calibrator_destroy(lc->ecc);
+                       lc->ecc=NULL;
+               }
+       }
        if (lc->preview_finished){
                lc->preview_finished=0;
                ring_stop(lc->ringstream);
                lc_callback_obj_invoke(&lc->preview_finished_cb,lc);
        }
  
-       if (lc->ringstream && lc->dmfs_playing_start_time!=0 
+       if (lc->ringstream && lc->ringstream_autorelease && lc->dmfs_playing_start_time!=0 
            && (curtime-lc->dmfs_playing_start_time)>5){
                ring_stop(lc->ringstream);
                lc->ringstream=NULL;
@@@ -2176,15 -2197,13 +2197,13 @@@ bool_t linphone_core_inc_invite_pending
  int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
        int err=0;
        if (params!=NULL){
-               if (call->localdesc)
-                       sal_media_description_unref(call->localdesc);
                call->params=*params;
-               call->localdesc=create_local_media_description (lc,call);
+               update_local_media_description(lc,call,&call->localdesc);
                call->camera_active=params->has_video;
                if (lc->vtable.display_status)
                        lc->vtable.display_status(lc,_("Modifying call parameters..."));
                sal_call_set_local_media_description (call->op,call->localdesc);
-               err=sal_call_update(call->op);
+               err=sal_call_update(call->op,"Media parameters update");
        }else{
  #ifdef VIDEO_ENABLED
                if (call->videostream!=NULL){
@@@ -2411,13 -2430,23 +2430,23 @@@ LinphoneCall *linphone_core_get_current
  int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call)
  {
        LinphoneCall *call = the_call;
+       const char *subject=NULL;
  
        if (call->state!=LinphoneCallStreamsRunning && call->state!=LinphoneCallPausedByRemote){
                ms_warning("Cannot pause this call, it is not active.");
                return -1;
        }
-       
-       if (sal_call_hold(call->op,TRUE) != 0)
+       if (sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv)){
+               sal_media_description_set_dir(call->localdesc,SalStreamSendOnly);
+               subject="Call on hold";
+       }else if (sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly)){
+               sal_media_description_set_dir(call->localdesc,SalStreamSendOnly);
+               subject="Call on hold for me too";
+       }else{
+               ms_error("No reason to pause this call, it is already paused or inactive.");
+               return -1;
+       }
+       if (sal_call_update(call->op,subject) != 0)
        {
                if (lc->vtable.display_warning)
                        lc->vtable.display_warning(lc,_("Could not pause the call"));
@@@ -2467,14 -2496,14 +2496,14 @@@ int linphone_core_resume_call(LinphoneC
                return -1;
        }
        ms_message("Resuming call %p",call);
-       if(sal_call_hold(call->op,FALSE) != 0){
+       sal_media_description_set_dir(call->localdesc,SalStreamSendRecv);
+       if(sal_call_update(call->op,"Call resuming") != 0){
                return -1;
        }
        linphone_call_set_state (call,LinphoneCallResuming,"Resuming");
        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);
-       lc->current_call=call;
        return 0;
  }
  
@@@ -2687,6 -2716,7 +2716,7 @@@ static MSSndCard *get_card_from_string_
   * Returns true if the specified sound device can capture sound.
   *
   * @ingroup media_parameters
+  * @param lc The LinphoneCore object
   * @param devid the device name as returned by linphone_core_get_sound_devices()
  **/
  bool_t linphone_core_sound_device_can_capture(LinphoneCore *lc, const char *devid){
   * Returns true if the specified sound device can play sound.
   *
   * @ingroup media_parameters
+  * @param lc The LinphoneCore object
   * @param devid the device name as returned by linphone_core_get_sound_devices()
  **/
  bool_t linphone_core_sound_device_can_playback(LinphoneCore *lc, const char *devid){
   * Sets the sound device used for ringing.
   *
   * @ingroup media_parameters
+  * @param lc The LinphoneCore object
   * @param devid the device name as returned by linphone_core_get_sound_devices()
  **/
  int linphone_core_set_ringer_device(LinphoneCore *lc, const char * devid){
   * Sets the sound device used for playback.
   *
   * @ingroup media_parameters
+  * @param lc The LinphoneCore object
   * @param devid the device name as returned by linphone_core_get_sound_devices()
  **/
  int linphone_core_set_playback_device(LinphoneCore *lc, const char * devid){
   * Sets the sound device used for capture.
   *
   * @ingroup media_parameters
+  * @param lc The LinphoneCore object
   * @param devid the device name as returned by linphone_core_get_sound_devices()
  **/
  int linphone_core_set_capture_device(LinphoneCore *lc, const char * devid){
   * Returns the name of the currently assigned sound device for ringing.
   *
   * @ingroup media_parameters
+  * @param lc The LinphoneCore object
  **/
  const char * linphone_core_get_ringer_device(LinphoneCore *lc)
  {
   * Returns the name of the currently assigned sound device for playback.
   *
   * @ingroup media_parameters
+  * @param lc The LinphoneCore object
  **/
  const char * linphone_core_get_playback_device(LinphoneCore *lc)
  {
   * Returns the name of the currently assigned sound device for capture.
   *
   * @ingroup media_parameters
+  * @param lc The LinphoneCore object
  **/
  const char * linphone_core_get_capture_device(LinphoneCore *lc)
  {
  /**
   * Returns an unmodifiable array of available sound devices.
   *
-  * @ingroup media_parameters
   * The array is NULL terminated.
+  *
+  * @ingroup media_parameters
+  * @param lc The LinphoneCore object
  **/
  const char**  linphone_core_get_sound_devices(LinphoneCore *lc){
        build_sound_devices_table(lc);
@@@ -2829,14 -2868,17 +2868,17 @@@ void linphone_core_set_sound_source(Lin
   * Sets the path to a wav file used for ringing.
   *
   * @param path The file must be a wav 16bit linear. Local ring is disabled if null
+  * @param lc The LinphoneCore object
   *
   * @ingroup media_parameters
  **/
  void linphone_core_set_ring(LinphoneCore *lc,const char *path){
        if (lc->sound_conf.local_ring!=0){
                ms_free(lc->sound_conf.local_ring);
+               lc->sound_conf.local_ring=NULL;
        }
-       lc->sound_conf.local_ring=ms_strdup(path);
+       if (path)
+               lc->sound_conf.local_ring=ms_strdup(path);
        if ( linphone_core_ready(lc) && lc->sound_conf.local_ring)
                lp_config_set_string(lc->config,"sound","local_ring",lc->sound_conf.local_ring);
  }
  /**
   * Returns the path to the wav file used for ringing.
   *
+  * @param lc The LinphoneCore object
   * @ingroup media_parameters
  **/
  const char *linphone_core_get_ring(const LinphoneCore *lc){
@@@ -3112,6 -3155,7 +3155,7 @@@ static void toggle_video_preview(Linpho
   * initiate future calls with video or not. The two boolean parameters indicate in which
   * direction video is enabled. Setting both to false disables video entirely.
   *
+  * @param lc The LinphoneCore object
   * @param vcap_enabled indicates whether video capture is enabled
   * @param display_enabled indicates whether video display should be shown
   *
@@@ -3191,6 -3235,7 +3235,7 @@@ bool_t linphone_core_self_view_enabled(
   * Sets the active video device.
   *
   * @ingroup media_parameters
+  * @param lc The LinphoneCore object
   * @param id the name of the video device as returned by linphone_core_get_video_devices()
  **/
  int linphone_core_set_video_device(LinphoneCore *lc, const char *id){
  /**
   * Returns the name of the currently active video device.
   *
+  * @param lc The LinphoneCore object
   * @ingroup media_parameters
  **/
  const char *linphone_core_get_video_device(const LinphoneCore *lc){
@@@ -3371,6 -3417,10 +3417,10 @@@ void linphone_core_use_preview_window(L
  }
  
  static MSVideoSizeDef supported_resolutions[]={
+ #ifdef ENABLE_HD
+       {       {MS_VIDEO_SIZE_1080P_W,MS_VIDEO_SIZE_1080P_H}   ,       "1080p" },
+       {       {MS_VIDEO_SIZE_720P_W,MS_VIDEO_SIZE_720P_H}     ,       "1080p" },
+ #endif
        {       {MS_VIDEO_SIZE_SVGA_W,MS_VIDEO_SIZE_SVGA_H}     ,       "svga"  },
        {       {MS_VIDEO_SIZE_4CIF_W,MS_VIDEO_SIZE_4CIF_H}     ,       "4cif"  },
        {       {MS_VIDEO_SIZE_VGA_W,MS_VIDEO_SIZE_VGA_H}       ,       "vga"   },
@@@ -3519,8 -3569,10 +3569,10 @@@ static MSFilter *get_dtmf_gen(LinphoneC
                }
        }
        if (lc->ringstream==NULL){
+               float amp=0.1;
                MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
                lc->ringstream=ring_start(NULL,0,ringcard);
+               ms_filter_call_method(lc->ringstream->gendtmf,MS_DTMF_GEN_SET_DEFAULT_AMPLITUDE,&amp);
                lc->dmfs_playing_start_time=time(NULL);
        }else{
                if (lc->dmfs_playing_start_time!=0)
  /**
   * Plays a dtmf to the local user.
  **/
 -void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms){
 +void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms, bool_t speaker){
        MSFilter *f=get_dtmf_gen(lc);
        if (f==NULL){
                ms_error("No dtmf generator at this time !");
                return;
        }
 +
 +      if (!speaker && !linphone_core_in_call(lc)) {
 +              // If not in call and user doesn't want sound to go out from speaker
 +              // TODO: update dtmf generator to only output on output stream if speaker is false.
 +              return;
 +      }
 +
        if (duration_ms>0)
                ms_filter_call_method(f, MS_DTMF_GEN_PLAY, &dtmf);
        else ms_filter_call_method(f, MS_DTMF_GEN_START, &dtmf);
@@@ -3688,7 -3733,7 +3740,7 @@@ void sip_config_uninit(LinphoneCore *lc
        linphone_proxy_config_write_to_config_file(lc->config,NULL,i);
  
        for (i=0;i<20;i++){
-               linphone_core_iterate(lc);
+               sal_iterate(lc->sal);
  #ifndef WIN32
                usleep(100000);
  #else
@@@ -3825,7 -3870,6 +3877,6 @@@ static void linphone_core_uninit(Linpho
                usleep(50000);
  #endif
        }
        if (lc->friends)
                ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_close_subscriptions);
        linphone_core_set_state(lc,LinphoneGlobalShutdown,"Shutting down");
        lc->msevq=NULL;
        /* save all config */
        net_config_uninit(lc);
-       sip_config_uninit(lc);
        rtp_config_uninit(lc);
+       if (lc->ringstream) ring_stop(lc->ringstream);
        sound_config_uninit(lc);
        video_config_uninit(lc);
        codecs_config_uninit(lc);
        ui_config_uninit(lc);
+       sip_config_uninit(lc);
        if (lp_config_needs_commit(lc->config)) lp_config_sync(lc->config);
        lp_config_destroy(lc->config);
        lc->config = NULL; /* Mark the config as NULL to block further calls */
        lc->call_logs=ms_list_free(lc->call_logs);
  
        linphone_core_free_payload_types();
        ortp_exit();
        linphone_core_set_state(lc,LinphoneGlobalOff,"Off");
  }
@@@ -3875,8 -3919,24 +3926,24 @@@ static void set_network_reachable(Linph
        }
        lc->netup_time=curtime;
        lc->network_reachable=isReachable;
- }
+       if(!isReachable) {
+               sal_unlisten_ports (lc->sal);
+       } else {
+               apply_transports(lc);
+       }
  
+ }
+ void linphone_core_refresh_registers(LinphoneCore* lc) {
+       const MSList *elem=linphone_core_get_proxy_config_list(lc);
+       for(;elem!=NULL;elem=elem->next){
+               LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
+               if (linphone_proxy_config_register_enabled(cfg) ) {
+                       cfg->registered=0;
+                       cfg->commit=TRUE;
+               }
+       }
+       
+ }
  void linphone_core_set_network_reachable(LinphoneCore* lc,bool_t isReachable) {
        //first disable automatic mode
        if (lc->auto_net_state_mon) {
@@@ -4044,4 -4104,31 +4111,31 @@@ const char *linphone_error_to_string(Li
        }
        return "unknown error";
  }
+ /**
+  * enable signaling keep alive
+  */
+ void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable) {
+       if (enable > 0) {
+               sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
+       } else {
+               sal_set_keepalive_period(lc->sal,0);
+       }
+ }
+ /**
+  * Is signaling keep alive
+  */
+ bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc) {
+       return sal_get_keepalive_period(lc->sal) > 0;
+ }
+       
+ void linphone_core_start_dtmf_stream(LinphoneCore* lc) {
+       get_dtmf_gen(lc); /*make sure ring stream is started*/
+       lc->ringstream_autorelease=FALSE; /*disable autorelease mode*/
+ }
+ void linphone_core_stop_dtmf_stream(LinphoneCore* lc) {
+       if (lc->ringstream) ring_stop(lc->ringstream);
+       lc->ringstream=NULL;
+ }
  
diff --combined coreapi/linphonecore.h
index a2f86f429fe4380193c4dff76c049d12ae79c5e8,81ab3e949948770cfd2d3446fb0b07d20f8c747d..5e83ba462b8b6ffd7691343611d905ec3bd071ca
@@@ -185,6 -185,7 +185,7 @@@ void linphone_call_params_destroy(Linph
  
  /**
   * Enum describing failure reasons.
+  * @ingroup initializing
  **/
  enum _LinphoneReason{
        LinphoneReasonNone,
@@@ -203,8 -204,13 +204,13 @@@ const char *linphone_reason_to_string(L
  struct _LinphoneCall;
  typedef struct _LinphoneCall LinphoneCall;
  
+ /**
+  * LinphoneCallState enum represents the different state a call can reach into.
+  * The application is notified of state changes through the LinphoneCoreVTable::call_state_changed callback.
+  * @ingroup call_control
+ **/
  typedef enum _LinphoneCallState{
-       LinphoneCallIdle,
+       LinphoneCallIdle,                                       /**<Initial call state */
        LinphoneCallIncomingReceived, /**<This is a new incoming call */
        LinphoneCallOutgoingInit, /**<An outgoing call is started */
        LinphoneCallOutgoingProgress, /**<An outgoing call is in progress */
        LinphoneCallPausedByRemote, /**<The call is paused by remote end*/
        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 */
-       LinphoneCallUpdated /**<The remote accepted the call update initiated by us */
+       LinphoneCallUpdated, /**<The remote accepted the call update initiated by us */
+       LinphoneCallReleased /**< The call object is no more retained by the core */
  } LinphoneCallState;
  
  const char *linphone_call_state_to_string(LinphoneCallState cs);
@@@ -238,6 -245,7 +245,7 @@@ void linphone_call_unref(LinphoneCall *
  LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call);
  const char *linphone_call_get_refer_to(const LinphoneCall *call);
  bool_t linphone_call_has_transfer_pending(const LinphoneCall *call);
+ LinphoneCall *linphone_call_get_replaced_call(LinphoneCall *call);
  int linphone_call_get_duration(const LinphoneCall *call);
  const LinphoneCallParams * linphone_call_get_current_params(const LinphoneCall *call);
  void linphone_call_enable_camera(LinphoneCall *lc, bool_t enabled);
@@@ -301,11 -309,11 +309,11 @@@ typedef struct _LinphoneProxyConfig Lin
   * LinphoneRegistrationState describes proxy registration states.
  **/
  typedef enum _LinphoneRegistrationState{
-       LinphoneRegistrationNone,
-       LinphoneRegistrationProgress,
-       LinphoneRegistrationOk,
-       LinphoneRegistrationCleared,
-       LinphoneRegistrationFailed
+       LinphoneRegistrationNone, /**<Initial state for registrations */
+       LinphoneRegistrationProgress, /**<Registration is in progress */
+       LinphoneRegistrationOk, /**< Registration is successful */
+       LinphoneRegistrationCleared, /**< Unregistration succeeded */
+       LinphoneRegistrationFailed      /**<Registration failed */
  }LinphoneRegistrationState;
  
  /**
@@@ -484,6 -492,17 +492,17 @@@ void * linphone_chat_room_get_user_data
  /**
   * @}
   */
+ /**
+  * @addtogroup initializing
+  * @{
+ **/
+ /**
+  * LinphoneGlobalState describes the global state of the LinphoneCore object.
+  * It is notified via the LinphoneCoreVTable::global_state_changed
+ **/
  typedef enum _LinphoneGlobalState{
        LinphoneGlobalOff,
        LinphoneGlobalStartup,
  
  const char *linphone_global_state_to_string(LinphoneGlobalState gs);
  
- /**
-  * @addtogroup initializing
-  * @{
- **/
  
  /**Call state notification callback prototype*/
  typedef void (*LinphoneGlobalStateCb)(struct _LinphoneCore *lc, LinphoneGlobalState gstate, const char *message);
@@@ -897,7 -911,7 +911,7 @@@ void linphone_core_use_files(LinphoneCo
  void linphone_core_set_play_file(LinphoneCore *lc, const char *file);
  void linphone_core_set_record_file(LinphoneCore *lc, const char *file);
  
 -void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms);
 +void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms, bool_t speaker);
  void linphone_core_stop_dtmf(LinphoneCore *lc);
  
  int linphone_core_get_current_call_duration(const LinphoneCore *lc);
@@@ -919,6 -933,14 +933,14 @@@ void linphone_core_set_network_reachabl
   */
  bool_t linphone_core_is_network_reachabled(LinphoneCore* lc);
  
+ /**
+  *  enable signaling keep alive. small udp packet sent periodically to keep udp NAT association
+  */
+ void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable);
+ /**
+  * Is signaling keep alive
+  */
+ bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc);
  
  void *linphone_core_get_user_data(LinphoneCore *lc);
  
@@@ -950,7 -972,11 +972,11 @@@ int linphone_core_get_current_call_stat
  const MSList *linphone_core_get_calls(LinphoneCore *lc);
  
  LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc);
+ /**
+  * force registration refresh to be initiated upon next iterate
+  * @ingroup proxies
+  */
+ void linphone_core_refresh_registers(LinphoneCore* lc);       
  #ifdef __cplusplus
  }
  #endif
index 7eca2c823ae3c6ae617b6a1bd21be8d995374596,1284f81b2e412357fa2a13a2fcc79541f8cb36d1..1876fb9ee8223715f168362f09b3e50b160e8a8c
@@@ -17,7 -17,8 +17,8 @@@ along with this program; if not, write 
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   */
  #include <jni.h>
- #include "linphonecore.h"
+ #include "linphonecore_utils.h"
  #include "mediastreamer2/msjava.h"
  
  #ifdef ANDROID
@@@ -100,7 -101,10 +101,10 @@@ public
                callStateId = env->GetMethodID(listernerClass,"callState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;Ljava/lang/String;)V");
                callStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCall$State"));
                callStateFromIntId = env->GetStaticMethodID(callStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCall$State;");
+               /*void ecCalibrationStatus(LinphoneCore.EcCalibratorStatus status, int delay_ms, Object data);*/
+               ecCalibrationStatusId = env->GetMethodID(listernerClass,"ecCalibrationStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;ILjava/lang/Object;)V");
+               ecCalibratorStatusClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$EcCalibratorStatus"));
+               ecCalibratorStatusFromIntId = env->GetStaticMethodID(ecCalibratorStatusClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;");
                /*void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url)*/
                newSubscriptionRequestId = env->GetMethodID(listernerClass,"newSubscriptionRequest","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;Ljava/lang/String;)V");
  
        jmethodID callStateId;
        jmethodID callStateFromIntId;
  
+       jclass ecCalibratorStatusClass;
+       jmethodID ecCalibrationStatusId;
+       jmethodID ecCalibratorStatusFromIntId;
        jclass proxyClass;
        jmethodID proxyCtrId;
  
                                                        ,env->NewObject(lcData->addressClass,lcData->addressCtrId,(jlong)from)
                                                        ,message ? env->NewStringUTF(message) : NULL);
        }
+       static void ecCalibrationStatus(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data) {
+               JNIEnv *env = 0;
+               jint result = jvm->AttachCurrentThread(&env,NULL);
+               if (result != 0) {
+                       ms_error("cannot attach VM\n");
+                       return;
+               }
+               LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
+               env->CallVoidMethod(lcData->listener
+                                                       ,lcData->ecCalibrationStatusId
+                                                       ,lcData->core
+                                                       ,env->CallStaticObjectMethod(lcData->ecCalibratorStatusClass,lcData->ecCalibratorStatusFromIntId,(jint)status)
+                                                       ,delay_ms
+                                                       ,data ? data : NULL);
+               if (data != NULL &&status !=LinphoneEcCalibratorInProgress ) {
+                       //final state, releasing global ref
+                       env->DeleteGlobalRef((jobject)data);
+               }
+       }
  
  
  };
@@@ -480,9 -508,8 +508,9 @@@ extern "C" void Java_org_linphone_core_
                ,jobject  thiz
                ,jlong lc
                ,jchar dtmf
 -              ,jint duration) {
 -      linphone_core_play_dtmf((LinphoneCore*)lc,dtmf,duration);
 +              ,jint duration
 +              ,jboolean speaker) {
 +      linphone_core_play_dtmf((LinphoneCore*)lc,dtmf,duration,speaker);
  }
  extern "C" void Java_org_linphone_core_LinphoneCoreImpl_stopDtmf(     JNIEnv*  env
                ,jobject  thiz
@@@ -615,6 -642,29 +643,29 @@@ extern "C" jstring Java_org_linphone_co
                return NULL;
        }
  }
+ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableKeepAlive(JNIEnv*  env
+                                                                                                                               ,jobject  thiz
+                                                                                                                               ,jlong lc
+                                                                                                                               ,jboolean enable) {
+       linphone_core_enable_keep_alive((LinphoneCore*)lc,enable);
+ }
+ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isKeepAliveEnabled(JNIEnv*  env
+                                                                                                                               ,jobject  thiz
+                                                                                                                               ,jlong lc) {
+       return linphone_core_keep_alive_enabled((LinphoneCore*)lc);
+ }
+ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_startEchoCalibration(JNIEnv*  env
+                                                                                                                                                               ,jobject  thiz
+                                                                                                                                                               ,jlong lc
+                                                                                                                                                               ,jobject data) {
+       return linphone_core_start_echo_calibration((LinphoneCore*)lc
+                                                                                                       , LinphoneCoreData::ecCalibrationStatus
+                                                                                                       , data?env->NewGlobalRef(data):NULL);
+ }
  
  
  //ProxyConfig
@@@ -939,6 -989,12 +990,12 @@@ extern "C" jboolean Java_org_linphone_c
        return linphone_call_echo_limiter_enabled((LinphoneCall*)ptr);
  }
  
+ extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getReplacedCall(     JNIEnv*  env
+                                                                                                                                               ,jobject  thiz
+                                                                                                                                               ,jlong ptr) {
+       return (jlong)linphone_call_get_replaced_call((LinphoneCall*)ptr);
+ }
  
  //LinphoneFriend
  extern "C" long Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv*  env
index 2d5daff6d560744cfac767d3483ecd0cd59336c6,84a38ca7d32f322a35ab8a3d86d80dbd9c4c11f7..3b63d0a148e8bc19eb1c1b09e98312bacef87063
@@@ -25,7 -25,7 +25,7 @@@ import java.util.Vector
   * Linphone core main object created by method {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)}.  
   *
   */
- @SuppressWarnings("unchecked")
  public interface LinphoneCore {
        /**
         * linphone core states
                        return mStringValue;
                }               
        }
+       /**
+        *      EC Calibrator Status
+ .
+        *
+        */
+       static public class EcCalibratorStatus {
+               static private Vector values = new Vector();
+               /**
+                * Calibration in progress
+                */
+               static public EcCalibratorStatus InProgress = new EcCalibratorStatus(0,"InProgress");       
+               /**
+                * Calibration done
+                */
+               static public EcCalibratorStatus Done  = new EcCalibratorStatus(1,"Done");
+               /**
+                * Calibration in progress
+                */
+               static public EcCalibratorStatus Failed = new EcCalibratorStatus(2,"Failed");
+               private final int mValue;
+               private final String mStringValue;
+               private EcCalibratorStatus(int value,String stringValue) {
+                       mValue = value;
+                       values.addElement(this);
+                       mStringValue=stringValue;
+               }
+               public static EcCalibratorStatus fromInt(int value) {
+                       for (int i=0; i<values.size();i++) {
+                               EcCalibratorStatus status = (EcCalibratorStatus) values.elementAt(i);
+                               if (status.mValue == value) return status;
+                       }
+                       throw new RuntimeException("status not found ["+value+"]");
+               }
+               public String toString() {
+                       return mStringValue;
+               }
+               public int value(){
+                       return mValue;
+               }
+       }
        /**
         * clear all added proxy configs
         */
         * Initiate a dtmf signal to the speqker if not in call
         * @param number
         * @param duration in ms , -1 for unlimited
 +       * @param speaker play dtmf on speaker
         */
 -      public void playDtmf(char number,int duration);
 +      public void playDtmf(char number,int duration, boolean speaker);
        /**
         * stop current dtmf
         */
         */
        public boolean isEchoCancellationEnabled();
        /**
-        * not implemented yet
+        * set transport used for signaling (TCP or UDP)
+        * 
         * @param aTransport
         */
        public void setSignalingTransport(Transport aTransport);
+       /**
+        * get transport used for signaling (TCP or UDP)
+        * 
+        * @return  Transport;
+        */
+       public Transport getSignalingTransport();
        /**
         * not implemented
         * @param value
        public VideoSize getPreferredVideoSize();
        
        public PayloadType[] listVideoCodecs();
+       /**
+        * enable signaling keep alive. small udp packet sent periodically to keep udp NAT association
+        */
+       void enableKeepAlive(boolean enable);
+       /**
+        * get keep elive mode
+        * @return true if enable
+        */
+       boolean isKeepAliveEnabled();
+       /**
+        * Start an echo calibration of the sound devices, in order to find adequate settings for the echo canceler automatically.
+        * status is notified to {@link LinphoneCoreListener#ecCalibrationStatus(EcCalibratorStatus, int, Object)}
+        * @param User object
+        * @throws LinphoneCoreException if operation is still in progress;
+       **/
+       void startEchoCalibration(Object data) throws LinphoneCoreException;
  }
index 5cbd5ac5eb96016d7514352caa427e7ee59d4824,6629c3dc369eb6347876a88d61b9730f3c1306cc..836f86caafae945b443515fce163a53f1de11bf6
@@@ -21,7 -21,7 +21,7 @@@ package org.linphone.core
  
  
  
- @SuppressWarnings("unchecked")
  abstract public class LinphoneCoreFactory {
        
        private static String factoryName = "org.linphone.core.LinphoneCoreFactoryImpl";
                factoryName = className;
        }
        
 -      public static LinphoneCoreFactory instance() {
 +      public static final synchronized LinphoneCoreFactory instance() {
                try {
                if (theLinphoneCoreFactory == null) {
                        Class lFactoryClass = Class.forName(factoryName);
                        theLinphoneCoreFactory = (LinphoneCoreFactory) lFactoryClass.newInstance();
                }
                } catch (Exception e) {
 -                      System.err.println("cannot instanciate factory ["+factoryName+"]");
 +                      System.err.println("Cannot instanciate factory ["+factoryName+"]");
                }
                return theLinphoneCoreFactory;
        }