]> sjero.net Git - linphone/commitdiff
merge public branch
authorJehan Monnier <jehan.monnier@linphone.org>
Mon, 11 Jul 2011 17:04:30 +0000 (19:04 +0200)
committerJehan Monnier <jehan.monnier@linphone.org>
Mon, 11 Jul 2011 17:04:30 +0000 (19:04 +0200)
29 files changed:
Makefile.am
configure.ac
console/linphonec.c
coreapi/callbacks.c
coreapi/help/doxygen.dox
coreapi/linphonecall.c
coreapi/linphonecore.c
coreapi/linphonecore.h
coreapi/linphonecore_jni.cc
coreapi/lpconfig.c
coreapi/lpconfig.h
coreapi/lsd.c
coreapi/offeranswer.c
coreapi/proxy.c
coreapi/sal.c
coreapi/sal.h
coreapi/sal_eXosip2.c
coreapi/sal_eXosip2.h
gtk/calllogs.c
gtk/friendlist.c
gtk/incall_view.c
gtk/main.c
gtk/main.ui
java/common/org/linphone/core/LinphoneCall.java
java/common/org/linphone/core/LinphoneCore.java
linphone-deps.filelist
mediastreamer2
oRTP
po/de.po

index d07aad6c6b0fbe5491d60b887fc94b03876eb0f5..b972eba81f822a082505b1ea660372dbb94a4655 100644 (file)
@@ -98,6 +98,7 @@ other-cherrypick:
                /mingw/bin/libstdc++-6.dll \
                /mingw/bin/libintl-8.dll \
                /mingw/bin/libiconv-2.dll \
+               /mingw/bin/libpthread-2.dll \
                $(INSTALLDIR_WITH_PREFIX)/bin/.
 
 
index 556941c0e4180a6fe3ce3e4d0effaeb9569829e9..08bcd8bf9e50887b7564ce76c6c495d19dbdf15d 100644 (file)
@@ -320,7 +320,11 @@ if test "$video" = "true"; then
        
        if test "$enable_x11" = "true"; then
                AC_CHECK_HEADERS(X11/Xlib.h)
-               AC_CHECK_LIB(X11,XUnmapWindow, X11_LIBS="-lX11")
+               if test "$build_macos" = "yes"; then 
+                       X11_LIBS="-L/usr/X11/lib -lX11"
+               else
+                       AC_CHECK_LIB(X11,XUnmapWindow, X11_LIBS="-lX11")
+               fi
                AC_SUBST(X11_LIBS)
        fi
        AC_DEFINE(VIDEO_ENABLED,1,[defined if video support is available])
index 38cf24f28e6d1ec69a0f39b16dfa7368591431fc..40a243607c10adedfedde0d58e703d6427de2a6d 100644 (file)
@@ -328,7 +328,7 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L
        long id=(long)linphone_call_get_user_pointer (call);
        switch(st){
                case LinphoneCallEnd:
-                       linphonec_out("Call %i with %s ended.\n", id, from);
+                       linphonec_out("Call %i with %s ended (%s).\n", id, from, linphone_reason_to_string(linphone_call_get_reason(call)));
                break;
                case LinphoneCallResuming:
                        linphonec_out("Resuming call %i with %s.\n", id, from);
@@ -358,7 +358,6 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L
                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:
index 046f7edb51188aa3efe53d5ef87fa5e64e571519..a101dbc8e9fc271fde9888cb7a1a7b35d822db8b 100644 (file)
@@ -49,7 +49,9 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
                /* we already started media: check if we really need to restart it*/
                if (oldmd){
                        if (!media_parameters_changed(call,oldmd,new_md) && !call->playing_ringbacktone){
-                               sal_media_description_unref(oldmd);
+                               /*as nothing has changed, keep the oldmd */
+                               call->resultdesc=oldmd;
+                               sal_media_description_unref(new_md);
                                if (call->all_muted){
                                        ms_message("Early media finished, unmuting inputs...");
                                        /*we were in early media, now we want to enable real media */
@@ -145,6 +147,7 @@ static void call_received(SalOp *h){
        if (is_duplicate_call(lc,from_addr,to_addr)){
                ms_warning("Receiving duplicated call, refusing this one.");
                sal_call_decline(h,SalReasonBusy,NULL);
+               sal_op_release(h);
                linphone_address_destroy(from_addr);
                linphone_address_destroy(to_addr);
                return;
index 99293c65b897c1543209085ba268ae14d33457bd..7d0a82849f2f398fc6e1f5af8632e45d5adcc472 100644 (file)
  *
 **/
 
+/**
+ * @defgroup call_misc Obtaining information about a running call: sound volumes, quality indicators
+ *
+ * When a call is running, it is possible to retrieve in real time current measured volumes and quality indicator.
+ *
+**/
+
 /**
  * @defgroup media_parameters Controlling media parameters
 **/
index 4230a156bc29c3bbb95ce23bc91158a67e551f1a..7e6e0380abe768faf05047df3b11145f5a648ad5 100644 (file)
@@ -223,7 +223,6 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
 /* this function is called internally to get rid of a call.
  It performs the following tasks:
  - remove the call from the internal list of calls
- - unref the LinphoneCall object
  - update the call logs accordingly
 */
 
@@ -586,6 +585,17 @@ void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int
        cp->audio_bw=bandwidth;
 }
 
+#ifdef VIDEO_ENABLED
+/**
+ * Request remote side to send us a Video Fast Update.
+**/
+void linphone_call_send_vfu_request(LinphoneCall *call)
+{
+       if (LinphoneCallStreamsRunning == linphone_call_get_state(call))
+               sal_call_send_vfu_request(call->op);
+}
+#endif
+
 /**
  *
 **/
@@ -659,6 +669,7 @@ void linphone_call_init_media_streams(LinphoneCall *call){
                int enabled=lp_config_get_int(lc->config,"sound","noisegate",0);
                audio_stream_enable_noise_gate(audiostream,enabled);
        }
+       
        if (lc->a_rtp)
                rtp_session_set_transports(audiostream->session,lc->a_rtp,lc->a_rtcp);
 
@@ -772,9 +783,6 @@ static void post_configure_audio_streams(LinphoneCall*call){
        }
 }
 
-
-
-
 static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){
        int bw;
        const MSList *elem;
@@ -782,15 +790,17 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m
        bool_t first=TRUE;
        int remote_bw=0;
        LinphoneCore *lc=call->core;
+       int up_ptime=0;
        *used_pt=-1;
        
        for(elem=desc->payloads;elem!=NULL;elem=elem->next){
                PayloadType *pt=(PayloadType*)elem->data;
                int number;
                
-               if (first) {
+               if ((pt->flags & PAYLOAD_TYPE_FLAG_CAN_SEND) && first) {
                        if (desc->type==SalAudio){
                                linphone_core_update_allocated_audio_bandwidth_in_call(call,pt);
+                               up_ptime=linphone_core_get_upload_ptime(lc);
                        }
                        *used_pt=payload_type_get_number(pt);
                        first=FALSE;
@@ -812,8 +822,11 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m
                        pt->normal_bitrate=-1;
                }
                if (desc->ptime>0){
+                       up_ptime=desc->ptime;
+               }
+               if (up_ptime>0){
                        char tmp[40];
-                       snprintf(tmp,sizeof(tmp),"ptime=%i",desc->ptime);
+                       snprintf(tmp,sizeof(tmp),"ptime=%i",up_ptime);
                        payload_type_append_send_fmtp(pt,tmp);
                }
                number=payload_type_get_number(pt);
@@ -843,6 +856,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
        const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc,
                                                        SalProtoRtpAvp,SalVideo);
 #endif
+       bool_t use_arc=linphone_core_adaptive_rate_control_enabled(lc);
        
        if(call->audiostream == NULL)
        {
@@ -866,7 +880,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
                        const char *playfile=lc->play_file;
                        const char *recfile=lc->rec_file;
                        call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt);
-                       bool_t use_ec;
+                       bool_t use_ec,use_arc_audio=use_arc;
 
                        if (used_pt!=-1){
                                if (playcard==NULL) {
@@ -897,11 +911,17 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
                                        playcard=NULL;
                                }
                                use_ec=captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc);
-#if defined(VIDEO_ENABLED) && defined(ANDROID)
-                               /*On android we have to disable the echo canceller to preserve CPU for video codecs */
-                               if (vstream && vstream->dir!=SalStreamInactive && vstream->payloads!=NULL)
+#if defined(VIDEO_ENABLED)
+                               if (vstream && vstream->dir!=SalStreamInactive && vstream->payloads!=NULL){
+                                       /*when video is used, do not make adaptive rate control on audio, it is stupid.*/
+                                       use_arc_audio=FALSE;
+       #if defined(ANDROID)
+                                       /*On android we have to disable the echo canceller to preserve CPU for video codecs */
                                        use_ec=FALSE;
+       #endif
+                               }
 #endif
+                               audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc_audio);
                                audio_stream_start_full(
                                        call->audiostream,
                                        call->audio_profile,
@@ -1005,6 +1025,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
 
 static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){
        audio_stream_get_local_rtp_stats (st,&log->local_stats);
+       log->quality=audio_stream_get_average_quality_rating(st);
 }
 
 void linphone_call_stop_media_streams(LinphoneCall *call){
@@ -1041,16 +1062,7 @@ void linphone_call_stop_media_streams(LinphoneCall *call){
        }
 }
 
-#ifdef VIDEO_ENABLED
-/**
- * Request remote side to send us VFU.
-**/
-void linphone_call_send_vfu_request(LinphoneCall *call)
-{
-       if (LinphoneCallStreamsRunning == linphone_call_get_state(call))
-               sal_call_send_vfu_request(call->op);
-}
-#endif
+
 
 void linphone_call_enable_echo_cancellation(LinphoneCall *call, bool_t enable) {
        if (call!=NULL && call->audiostream!=NULL && call->audiostream->ec){
@@ -1090,6 +1102,11 @@ bool_t linphone_call_echo_limiter_enabled(const LinphoneCall *call){
        }
 }
 
+/**
+ * @addtogroup call_misc
+ * @{
+**/ 
+
 /**
  * Returns the measured sound volume played locally (received from remote)
  * It is expressed in dbm0. 
@@ -1120,6 +1137,45 @@ float linphone_call_get_record_volume(LinphoneCall *call){
        return LINPHONE_VOLUME_DB_LOWEST;
 }
 
+/**
+ * Obtain real-time quality rating of the call
+ *
+ * Based on local RTP statistics and RTCP feedback, a quality rating is computed and updated
+ * during all the duration of the call. This function returns its value at the time of the function call.
+ * It is expected that the rating is updated at least every 5 seconds or so.
+ * The rating is a floating point number comprised between 0 and 5.
+ *
+ * 4-5 = good quality <br>
+ * 3-4 = average quality <br>
+ * 2-3 = poor quality <br>
+ * 1-2 = very poor quality <br>
+ * 0-1 = can't be worse, mostly unusable <br>
+ *
+ * @returns The function returns -1 if no quality measurement is available, for example if no 
+ * active audio stream exist. Otherwise it returns the quality rating.
+**/
+float linphone_call_get_current_quality(LinphoneCall *call){
+       if (call->audiostream){
+               return audio_stream_get_quality_rating(call->audiostream);
+       }
+       return -1;
+}
+
+/**
+ * Returns call quality averaged over all the duration of the call.
+ *
+ * See linphone_call_get_current_quality() for more details about quality measurement.
+**/
+float linphone_call_get_average_quality(LinphoneCall *call){
+       if (call->audiostream){
+               return audio_stream_get_average_quality_rating(call->audiostream);
+       }
+       return -1;
+}
+
+/**
+ * @}
+**/
 
 static void display_bandwidth(RtpSession *as, RtpSession *vs){
        ms_message("bandwidth usage: audio=[d=%.1f,u=%.1f] video=[d=%.1f,u=%.1f] kbit/sec",
@@ -1172,6 +1228,8 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
        if (call->videostream!=NULL)
                video_stream_iterate(call->videostream);
 #endif
+       if (call->audiostream!=NULL)
+               audio_stream_iterate(call->audiostream);
        if (one_second_elapsed && call->audiostream!=NULL && disconnect_timeout>0 )
                disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout);
        if (disconnected)
index 4c6deea9a9e42e08326cc619880fa6b5b0c3df88..934ebefa634d5e6e6cdbe7643e91608dbef3b370 100644 (file)
@@ -124,6 +124,7 @@ void call_logs_write_to_config_file(LinphoneCore *lc){
                lp_config_set_string(cfg,logsection,"start_date",cl->start_date);
                lp_config_set_int(cfg,logsection,"duration",cl->duration);
                if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey);
+               lp_config_set_float(cfg,logsection,"quality",cl->quality);
        }
        for(;i<lc->max_call_logs;++i){
                snprintf(logsection,sizeof(logsection),"call_log_%i",i);
@@ -151,6 +152,7 @@ static void call_logs_read_from_config_file(LinphoneCore *lc){
                        cl->duration=lp_config_get_int(cfg,logsection,"duration",0);
                        tmp=lp_config_get_string(cfg,logsection,"refkey",NULL);
                        if (tmp) cl->refkey=ms_strdup(tmp);
+                       cl->quality=lp_config_get_float(cfg,logsection,"quality",-1);
                        lc->call_logs=ms_list_append(lc->call_logs,cl);
                }else break;    
        }
@@ -464,6 +466,7 @@ static void sip_config_read(LinphoneCore *lc)
 
        sal_use_rport(lc->sal,lp_config_get_int(lc->config,"sip","use_rport",1));
        sal_use_101(lc->sal,lp_config_get_int(lc->config,"sip","use_101",1));
+       sal_reuse_authorization(lc->sal, lp_config_get_int(lc->config,"sip","reuse_authorization",0));
 
        tmp=lp_config_get_int(lc->config,"sip","use_rfc2833",0);
        linphone_core_set_use_rfc2833_for_dtmf(lc,tmp);
@@ -780,6 +783,26 @@ static void autoreplier_config_init(LinphoneCore *lc)
 }
 */
 
+/**
+ * Enable adaptive rate control (experimental feature, audio-only).
+ *
+ * Adaptive rate control consists in using RTCP feedback provided information to dynamically
+ * control the output bitrate of the encoders, so that we can adapt to the network conditions and
+ * available bandwidth.
+**/
+void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled){
+       lp_config_set_int(lc->config,"net","adaptive_rate_control",(int)enabled);
+}
+
+/**
+ * Returns whether adaptive rate control is enabled.
+ *
+ * See linphone_core_enable_adaptive_rate_control().
+**/
+bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc){
+       return lp_config_get_int(lc->config,"net","adaptive_rate_control",FALSE);
+}
+
 /**
  * Sets maximum available download bandwidth
  *
@@ -839,16 +862,38 @@ int linphone_core_get_upload_bandwidth(const LinphoneCore *lc){
        return lc->net_conf.upload_bw;
 }
 /**
- * set audio packetization time linphone expect to received from peer
+ * Set audio packetization time linphone expects to receive from peer
  */
 void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime) {
        lc->net_conf.down_ptime=ptime;
 }
 
-int  linphone_core_get_download_ptime(LinphoneCore *lc) {
+/**
+ * Get audio packetization time linphone expects to receive from peer
+ */
+int linphone_core_get_download_ptime(LinphoneCore *lc) {
        return lc->net_conf.down_ptime;
 }
 
+/**
+ * Set audio packetization time linphone will send (in absence of requirement from peer)
+ * A value of 0 stands for the current codec default packetization time.
+ *
+**/
+void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime){
+       lp_config_set_int(lc->config,"rtp","upload_ptime",ptime);
+}
+
+/**
+ * Set audio packetization time linphone will send (in absence of requirement from peer)
+ * A value of 0 stands for the current codec default packetization time.
+ *
+**/
+int linphone_core_get_upload_ptime(LinphoneCore *lc){
+       return lp_config_get_int(lc->config,"rtp","upload_ptime",0);
+}
+
+
 
 /**
  * Returns liblinphone's version as a string.
@@ -1373,13 +1418,13 @@ static int apply_transports(LinphoneCore *lc){
 
        sal_unlisten_ports (sal);
        if (tr->udp_port>0){
-               if (sal_listen_port (sal,anyaddr,tr->udp_port,SalTransportDatagram,FALSE)!=0){
+               if (sal_listen_port (sal,anyaddr,tr->udp_port,SalTransportUDP,FALSE)!=0){
                        transport_error(lc,"UDP",tr->udp_port);
                        return -1;
                }
        }
        if (tr->tcp_port>0){
-               if (sal_listen_port (sal,anyaddr,tr->tcp_port,SalTransportStream,FALSE)!=0){
+               if (sal_listen_port (sal,anyaddr,tr->tcp_port,SalTransportTCP,FALSE)!=0){
                        transport_error(lc,"TCP",tr->tcp_port);
                }
        }
@@ -1636,9 +1681,9 @@ void linphone_core_iterate(LinphoneCore *lc){
                 linphone_core_start_invite() */
                calls=calls->next;
                if (call->state==LinphoneCallOutgoingInit && (curtime-call->start_time>=2)){
-                               /*start the call even if the OPTIONS reply did not arrive*/
-                               linphone_core_start_invite(lc,call,NULL);
-                       }
+                       /*start the call even if the OPTIONS reply did not arrive*/
+                       linphone_core_start_invite(lc,call,NULL);
+               }
                if (call->dir==LinphoneCallIncoming && call->state==LinphoneCallOutgoingRinging){
                        elapsed=curtime-call->start_time;
                        ms_message("incoming call ringing for %i seconds",elapsed);
@@ -1996,7 +2041,6 @@ LinphoneCall * linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddr
 **/
 LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const LinphoneAddress *addr, const LinphoneCallParams *params)
 {
-       int err=0;
        const char *route=NULL;
        const char *from=NULL;
        LinphoneProxyConfig *proxy=NULL;
@@ -2049,7 +2093,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
        lc->current_call=call;
        linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call");
        if (dest_proxy!=NULL || lc->sip_conf.ping_with_options==FALSE){
-               err=linphone_core_start_invite(lc,call,dest_proxy);
+               linphone_core_start_invite(lc,call,dest_proxy);
        }else{
                /*defer the start of the call after the OPTIONS ping*/
                call->ping_op=sal_op_new(lc->sal);
@@ -4079,7 +4123,7 @@ LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *l
        return p;
 }
 
-const char *linphone_error_to_string(LinphoneReason err){
+const char *linphone_reason_to_string(LinphoneReason err){
        switch(err){
                case LinphoneReasonNone:
                        return "No error";
@@ -4092,6 +4136,10 @@ const char *linphone_error_to_string(LinphoneReason err){
        }
        return "unknown error";
 }
+
+const char *linphone_error_to_string(LinphoneReason err){
+       return linphone_reason_to_string(err);
+}
 /**
  * Enables signaling keep alive
  */
index 50fdb96d8590813de702745f4406d0fb8dafea0f..12bf726559b5a4ee09008da9996b507616677ae8 100644 (file)
@@ -152,6 +152,7 @@ typedef struct _LinphoneCallLog{
        void *user_pointer;
        rtp_stats_t local_stats;
        rtp_stats_t remote_stats;
+       float quality;
        struct _LinphoneCore *lc;
 } LinphoneCallLog;
 
@@ -255,6 +256,8 @@ LinphoneReason linphone_call_get_reason(const LinphoneCall *call);
 const char *linphone_call_get_remote_user_agent(LinphoneCall *call);
 float linphone_call_get_play_volume(LinphoneCall *call);
 float linphone_call_get_record_volume(LinphoneCall *call);
+float linphone_call_get_current_quality(LinphoneCall *call);
+float linphone_call_get_average_quality(LinphoneCall *call);
 void *linphone_call_get_user_pointer(LinphoneCall *call);
 void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
 /**
@@ -702,18 +705,25 @@ void linphone_core_set_upload_bandwidth(LinphoneCore *lc, int bw);
 
 int linphone_core_get_download_bandwidth(const LinphoneCore *lc);
 int linphone_core_get_upload_bandwidth(const LinphoneCore *lc);
+
+void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled);
+bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc);
 /**
- * set audio packetization time linphone expect to received from peer
+ * set audio packetization time linphone expect to receive from peer
  * @ingroup media_parameters
  *
  */
 void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime);
 /**
- * get audio packetization time linphone expect to received from peer, 0 means unspecified
+ * get audio packetization time linphone expect to receive from peer, 0 means unspecified
  * @ingroup media_parameters
  */
 int  linphone_core_get_download_ptime(LinphoneCore *lc);
 
+void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime);
+
+int linphone_core_get_upload_ptime(LinphoneCore *lc);
+
 /* returns a MSList of PayloadType */
 const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc);
 
index 4e201c845ec2bf7b1720a32b5a48c31334a33812..f858f8d1719198470ca5d05ae636befb0c799a50 100644 (file)
@@ -1023,6 +1023,18 @@ extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getReplacedCall(        JNIEnv
        return (jlong)linphone_call_get_replaced_call((LinphoneCall*)ptr);
 }
 
+extern "C" jfloat Java_org_linphone_core_LinphoneCallImpl_getCurrentQuality(   JNIEnv*  env
+                                                                                                                                               ,jobject  thiz
+                                                                                                                                               ,jlong ptr) {
+       return (jfloat)linphone_call_get_current_quality((LinphoneCall*)ptr);
+}
+
+extern "C" jfloat Java_org_linphone_core_LinphoneCallImpl_getAverageQuality(   JNIEnv*  env
+                                                                                                                                               ,jobject  thiz
+                                                                                                                                               ,jlong ptr) {
+       return (jfloat)linphone_call_get_average_quality((LinphoneCall*)ptr);
+}
+
 
 //LinphoneFriend
 extern "C" long Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv*  env
@@ -1194,6 +1206,15 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDownloadBandwidth(JNI
 extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUploadBandwidth(JNIEnv *env, jobject thiz, jlong lc, jint bw){
        linphone_core_set_upload_bandwidth((LinphoneCore *)lc, (int) bw);
 }
+
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDownloadPtime(JNIEnv *env, jobject thiz, jlong lc, jint ptime){
+       linphone_core_set_download_ptime((LinphoneCore *)lc, (int) ptime);
+}
+
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUploadPtime(JNIEnv *env, jobject thiz, jlong lc, jint ptime){
+       linphone_core_set_upload_ptime((LinphoneCore *)lc, (int) ptime);
+}
+
 extern "C" int Java_org_linphone_core_LinphoneProxyConfigImpl_getState(JNIEnv*  env,jobject thiz,jlong ptr) {
        return (int) linphone_proxy_config_get_state((const LinphoneProxyConfig *) ptr);
 }
index ce093cbaf6831ef5a11ba8d0ad499c0f03eed96f..0de019e57fdb9fd9cc06c98137f7bbd5df5d8125 100644 (file)
@@ -307,9 +307,14 @@ void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *ke
 
 void lp_config_set_int(LpConfig *lpconfig,const char *section, const char *key, int value){
        char tmp[30];
-       snprintf(tmp,30,"%i",value);
+       snprintf(tmp,sizeof(tmp),"%i",value);
+       lp_config_set_string(lpconfig,section,key,tmp);
+}
+
+void lp_config_set_float(LpConfig *lpconfig,const char *section, const char *key, float value){
+       char tmp[30];
+       snprintf(tmp,sizeof(tmp),"%f",value);
        lp_config_set_string(lpconfig,section,key,tmp);
-       lpconfig->modified++;
 }
 
 void lp_item_write(LpItem *item, FILE *file){
index bb731acbcee18e6bc4f91b9ad75253c7274d301b..ed7a66b1e6dfc1bd78e20aa1a71febf801969631 100644 (file)
@@ -86,6 +86,12 @@ void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *ke
  * @ingroup misc
 **/
 void lp_config_set_int(LpConfig *lpconfig,const char *section, const char *key, int value);
+/**
+ * Sets a float config item
+ *
+ * @ingroup misc
+**/
+void lp_config_set_float(LpConfig *lpconfig,const char *section, const char *key, float value);        
 /**
  * Writes the config file to disk.
  * 
index 1ad7c7db452f21e25ad22d2a381e622cfec61a1a..f22a5b2072776edf9d465ca1f19743a147143a45 100644 (file)
@@ -250,7 +250,6 @@ LinphoneSoundDaemon * linphone_sound_daemon_new(const char *cardname, int rate,
 
        lsd_player_init(&lsd->branches[0],mp,MS_ITC_SOURCE_ID,lsd);
        ms_filter_set_notify_callback(lsd->branches[0].player,(MSFilterNotifyFunc)lsd_player_configure,&lsd->branches[0]);
-       ms_filter_enable_synchronous_notifcations (lsd->branches[0].player,TRUE);
        for(i=1;i<MAX_BRANCHES;++i){
                mp.pin=i;
                lsd_player_init(&lsd->branches[i],mp,MS_FILE_PLAYER_ID,lsd);
index 5748a6d5bf67e899f91d1adc472cfe14740cff92..3e054508b1aa5a863287569b5ed9730957f49619 100644 (file)
@@ -61,7 +61,7 @@ static PayloadType * find_payload_type_best_match(const MSList *l, const Payload
 }
 
 static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t reading_response, bool_t one_matching_codec){
-       const MSList *e2;
+       const MSList *e2,*e1;
        MSList *res=NULL;
        PayloadType *matched;
        bool_t found_codec=FALSE;
@@ -85,6 +85,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
                        newp=payload_type_clone(matched);
                        if (p2->send_fmtp)
                                payload_type_set_send_fmtp(newp,p2->send_fmtp);
+                       newp->flags|=PAYLOAD_TYPE_FLAG_CAN_RECV|PAYLOAD_TYPE_FLAG_CAN_SEND;
                        res=ms_list_append(res,newp);
                        /* we should use the remote numbering even when parsing a response */
                        payload_type_set_number(newp,remote_number);
@@ -96,7 +97,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
                                 Indeed despite we must sent with the remote numbering, we must be able to receive with
                                 our local one.
                                */
-                               newp=payload_type_clone(matched);
+                               newp=payload_type_clone(newp);
                                payload_type_set_number(newp,local_number);
                                res=ms_list_append(res,newp);
                        }
@@ -104,6 +105,26 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
                        ms_message("No match for %s/%i",p2->mime_type,p2->clock_rate);
                }
        }
+       if (reading_response){
+               /* add remaning local payload as CAN_RECV only so that if we are in front of a non-compliant equipment we are still able to decode the RTP stream*/
+               for(e1=local;e1!=NULL;e1=e1->next){
+                       PayloadType *p1=(PayloadType*)e1->data;
+                       bool_t found=FALSE;
+                       for(e2=res;e2!=NULL;e2=e2->next){
+                               PayloadType *p2=(PayloadType*)e2->data;
+                               if (payload_type_get_number(p2)==payload_type_get_number(p1)){
+                                       found=TRUE;
+                                       break;
+                               }
+                       }
+                       if (!found){
+                               ms_message("Adding %s/%i for compatibility, just in case.",p1->mime_type,p1->clock_rate);
+                               p1=payload_type_clone(p1);
+                               p1->flags|=PAYLOAD_TYPE_FLAG_CAN_RECV;
+                               res=ms_list_append(res,p1);
+                       }
+               }
+       }
        return res;
 }
 
index a4a062dcaaf608d7ae06dd0bd87acbc06698272b..ff13f839e4545f99245f2642583ec0ec83564757 100644 (file)
@@ -259,7 +259,7 @@ static char *guess_contact_for_register(LinphoneProxyConfig *obj){
                
                linphone_core_get_sip_transports(obj->lc,&tr);
                if (tr.udp_port <= 0 && tr.tcp_port>0) {
-                       sal_address_add_param(contact,"transport","tcp");
+                       sal_address_set_param(contact,"transport","TCP");
                }
                ret=linphone_address_as_string(contact);
                linphone_address_destroy(contact);
@@ -269,10 +269,6 @@ static char *guess_contact_for_register(LinphoneProxyConfig *obj){
 }
 
 static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
-       const char *id_str;
-
-       if (obj->reg_identity!=NULL) id_str=obj->reg_identity;
-       else id_str=linphone_core_get_primary_contact(obj->lc);
        if (obj->reg_sendregister){
                char *contact;
                if (obj->op)
index b25f3945130230a8fdc487d701bdb8e8cfe82c3c..b237e9ad9e99f926a1b81710eaa6736e51cc0f08 100644 (file)
@@ -24,7 +24,27 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 **/
 
 #include "sal.h"
-
+const char* sal_transport_to_string(SalTransport transport) {
+    switch (transport) {
+        case SalTransportUDP:return "UDP";
+        case SalTransportTCP: return "TCP";
+        case SalTransportTLS:return "TLS";
+        case SalTransportDTLS:return "DTLS";
+        default: {
+            ms_fatal("Unexpected transport [%i]",transport);
+            return NULL;
+        }
+            
+    }
+}
+SalTransport sal_transport_parse(const char* param) {
+    if (strcasecmp("UDP",param)==0) return SalTransportUDP;
+    if (strcasecmp("TCP",param)==0) return SalTransportTCP;
+    if (strcasecmp("TLS",param)==0) return SalTransportTLS;
+    if (strcasecmp("DTLS",param)==0) return SalTransportDTLS;
+    ms_error("Unkown transport type[%s], returning UDP", param);
+    return SalTransportUDP;
+}
 SalMediaDescription *sal_media_description_new(){
        SalMediaDescription *md=ms_new0(SalMediaDescription,1);
        md->refcount=1;
@@ -309,3 +329,4 @@ void sal_auth_info_delete(const SalAuthInfo* auth_info) {
        if (auth_info->password) ms_free(auth_info->password);
        ms_free((void*)auth_info);
 }
+
index a89b862c05369740edde30ca3c2c72e685a6831e..47286b09c986ad8d6c69e5d2608c584858339349 100644 (file)
@@ -28,6 +28,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "mediastreamer2/mscommon.h"
 
+/*Dirty hack, keep in sync with mediastreamer2/include/mediastream.h */
+#ifndef PAYLOAD_TYPE_FLAG_CAN_RECV
+#define PAYLOAD_TYPE_FLAG_CAN_RECV     PAYLOAD_TYPE_USER_FLAG_1
+#define PAYLOAD_TYPE_FLAG_CAN_SEND     PAYLOAD_TYPE_USER_FLAG_2
+#endif
 struct Sal;
 
 typedef struct Sal Sal;
@@ -40,6 +45,15 @@ struct SalAddress;
 
 typedef struct SalAddress SalAddress;
 
+typedef enum {
+       SalTransportUDP, /*UDP*/
+       SalTransportTCP, /*TCP*/
+       SalTransportTLS, /*TLS*/
+       SalTransportDTLS /*DTLS*/
+}SalTransport;
+
+const char* sal_transport_to_string(SalTransport transport);
+SalTransport sal_transport_parse(const char*);
 /* Address manipulation API*/
 SalAddress * sal_address_new(const char *uri);
 SalAddress * sal_address_clone(const SalAddress *addr);
@@ -49,7 +63,8 @@ char *sal_address_get_display_name_unquoted(const SalAddress *addr);
 const char *sal_address_get_username(const SalAddress *addr);
 const char *sal_address_get_domain(const SalAddress *addr);
 const char * sal_address_get_port(const SalAddress *addr);
-int sal_address_get_port_int(const SalAddress *uri);
+int sal_address_get_port_int(const SalAddress *addr);
+SalTransport sal_address_get_transport(const SalAddress* addr);
 
 void sal_address_set_display_name(SalAddress *addr, const char *display_name);
 void sal_address_set_username(SalAddress *addr, const char *username);
@@ -60,8 +75,8 @@ void sal_address_clean(SalAddress *addr);
 char *sal_address_as_string(const SalAddress *u);
 char *sal_address_as_string_uri_only(const SalAddress *u);
 void sal_address_destroy(SalAddress *u);
-void sal_address_add_param(SalAddress *u,const char* name,const char* value);
-
+void sal_address_set_param(SalAddress *u,const char* name,const char* value);
+void sal_address_set_transport(SalAddress* addr,SalTransport transport);
 
 
 Sal * sal_init();
@@ -69,10 +84,6 @@ void sal_uninit(Sal* sal);
 void sal_set_user_pointer(Sal *sal, void *user_data);
 void *sal_get_user_pointer(const Sal *sal);
 
-typedef enum {
-       SalTransportDatagram,
-       SalTransportStream
-}SalTransport;
 
 typedef enum {
        SalAudio,
@@ -261,6 +272,7 @@ void sal_set_keepalive_period(Sal *ctx,unsigned int value);
 unsigned int sal_get_keepalive_period(Sal *ctx);
 void sal_use_session_timers(Sal *ctx, int expires);
 void sal_use_double_registrations(Sal *ctx, bool_t enabled);
+void sal_reuse_authorization(Sal *ctx, bool_t enabled);
 void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec);
 void sal_use_rport(Sal *ctx, bool_t use_rports);
 void sal_use_101(Sal *ctx, bool_t use_101);
@@ -313,6 +325,7 @@ int sal_call_send_dtmf(SalOp *h, char dtmf);
 int sal_call_terminate(SalOp *h);
 bool_t sal_call_autoanswer_asked(SalOp *op);
 void sal_call_send_vfu_request(SalOp *h);
+int sal_call_is_offerer(const SalOp *h);
 
 /*Registration*/
 int sal_register(SalOp *op, const char *proxy, const char *from, int expires);
@@ -337,6 +350,8 @@ int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus s
 /*ping: main purpose is to obtain its own contact address behind firewalls*/
 int sal_ping(SalOp *op, const char *from, const char *to);
 
+
+
 #define payload_type_set_number(pt,n)  (pt)->user_data=(void*)((long)n);
 #define payload_type_get_number(pt)            ((int)(long)(pt)->user_data)
 
index 33ef079c9fd7d8d1478f18a1fd52fb7145f578e7..7c04454b4966c5da0acf88c64d6533102477fe25 100644 (file)
@@ -32,6 +32,10 @@ static bool_t call_failure(Sal *sal, eXosip_event_t *ev);
 
 static void text_received(Sal *sal, eXosip_event_t *ev);
 
+static void masquerade_via(osip_message_t *msg, const char *ip, const char *port);
+static bool_t fix_message_contact(SalOp *op, osip_message_t *request,osip_message_t *last_answer);
+static void update_contact_from_response(SalOp *op, osip_message_t *response);
+
 void _osip_list_set_empty(osip_list_t *l, void (*freefunc)(void*)){
        void *data;
        while(!osip_list_eol(l,0)) {
@@ -189,6 +193,7 @@ void sal_op_release(SalOp *op){
                eXosip_event_free(op->pending_auth);
        if (op->rid!=-1){
                sal_remove_register(op->base.root,op->rid);
+               eXosip_register_remove(op->rid);
        }
        if (op->cid!=-1){
                ms_message("Cleaning cid %i",op->cid);
@@ -275,6 +280,7 @@ Sal * sal_init(){
        sal->double_reg=TRUE;
        sal->use_rports=TRUE;
        sal->use_101=TRUE;
+       sal->reuse_authorization=FALSE;
        return sal;
 }
 
@@ -351,11 +357,11 @@ int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int i
        int keepalive = ctx->keepalive_period;
        
        switch (tr) {
-       case SalTransportDatagram:
+       case SalTransportUDP:
                proto=IPPROTO_UDP;
                eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE, &keepalive);      
                break;
-       case SalTransportStream:
+       case SalTransportTCP:
                proto= IPPROTO_TCP;
                        keepalive=-1;   
                eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE,&keepalive);       
@@ -424,7 +430,8 @@ void sal_use_rport(Sal *ctx, bool_t use_rports){
 void sal_use_101(Sal *ctx, bool_t use_101){
        ctx->use_101=use_101;
 }
-static int extract_received_rport(osip_message_t *msg, const char **received, int *rportval){
+
+static int extract_received_rport(osip_message_t *msg, const char **received, int *rportval,SalTransport* transport){
        osip_via_t *via=NULL;
        osip_generic_param_t *param=NULL;
        const char *rport=NULL;
@@ -434,10 +441,7 @@ static int extract_received_rport(osip_message_t *msg, const char **received, in
        osip_message_get_via(msg,0,&via);
        if (!via) return -1;
 
-       /* it is useless to do that with tcp since client socket might have a different port
-               than the server socket.
-       */
-       if (strcasecmp(via->protocol,"tcp")==0) return -1;
+       *transport = sal_transport_parse(via->protocol);
        
        if (via->port && via->port[0]!='\0')
                *rportval=atoi(via->port);
@@ -507,6 +511,10 @@ static void sdp_process(SalOp *h){
        
 }
 
+int sal_call_is_offerer(const SalOp *h){
+       return h->sdp_offering;
+}
+
 int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc){
        if (desc)
                sal_media_description_ref(desc);
@@ -561,19 +569,18 @@ int sal_call(SalOp *h, const char *from, const char *to){
 
 int sal_call_notify_ringing(SalOp *h, bool_t early_media){
        osip_message_t *msg;
-       int err;
        
        /*if early media send also 180 and 183 */
        if (early_media && h->sdp_answer){
                msg=NULL;
                eXosip_lock();
-               err=eXosip_call_build_answer(h->tid,180,&msg);
+               eXosip_call_build_answer(h->tid,180,&msg);
                if (msg){
                        set_sdp(msg,h->sdp_answer);
                        eXosip_call_send_answer(h->tid,180,msg);
                }
                msg=NULL;
-               err=eXosip_call_build_answer(h->tid,183,&msg);
+               eXosip_call_build_answer(h->tid,183,&msg);
                if (msg){
                        set_sdp(msg,h->sdp_answer);
                        eXosip_call_send_answer(h->tid,183,msg);
@@ -792,7 +799,7 @@ int sal_call_terminate(SalOp *h){
        eXosip_lock();
        err=eXosip_call_terminate(h->cid,h->did);
        eXosip_unlock();
-       pop_auth_from_exosip();
+       if (!h->base.root->reuse_authorization) pop_auth_from_exosip();
        if (err!=0){
                ms_warning("Exosip could not terminate the call: cid=%i did=%i", h->cid,h->did);
        }
@@ -801,13 +808,21 @@ int sal_call_terminate(SalOp *h){
 }
 
 void sal_op_authenticate(SalOp *h, const SalAuthInfo *info){
-       if (h->pending_auth){
+    if (h->pending_auth){
                push_auth_to_exosip(info);
+               
+        /*FIXME exosip does not take into account this update register message*/
+       /*
+        if (fix_message_contact(h, h->pending_auth->request,h->pending_auth->response)) {
+            
+        };
+       */
+               update_contact_from_response(h,h->pending_auth->response);
                eXosip_lock();
                eXosip_default_action(h->pending_auth);
                eXosip_unlock();
                ms_message("eXosip_default_action() done");
-               pop_auth_from_exosip();
+               if (!h->base.root->reuse_authorization) pop_auth_from_exosip();
                
                if (h->auth_info) sal_auth_info_delete(h->auth_info); /*if already exist*/
                h->auth_info=sal_auth_info_clone(info); /*store auth info for subsequent request*/
@@ -826,8 +841,9 @@ void sal_op_cancel_authentication(SalOp *h) {
 static void set_network_origin(SalOp *op, osip_message_t *req){
        const char *received=NULL;
        int rport=5060;
-       char origin[64];
-       if (extract_received_rport(req,&received,&rport)!=0){
+       char origin[64]={0};
+    SalTransport transport;
+       if (extract_received_rport(req,&received,&rport,&transport)!=0){
                osip_via_t *via=NULL;
                char *tmp;
                osip_message_get_via(req,0,&via);
@@ -835,7 +851,11 @@ static void set_network_origin(SalOp *op, osip_message_t *req){
                tmp=osip_via_get_port(via);
                if (tmp) rport=atoi(tmp);
        }
-       snprintf(origin,sizeof(origin)-1,"sip:%s:%i",received,rport);
+    if (transport != SalTransportUDP) {
+        snprintf(origin,sizeof(origin)-1,"sip:%s:%i",received,rport);
+    } else {
+       snprintf(origin,sizeof(origin)-1,"sip:%s:%i;transport=%s",received,rport,sal_transport_to_string(transport)); 
+    }
        __sal_op_set_network_origin(op,origin);
 }
 
@@ -993,7 +1013,8 @@ static void handle_ack(Sal *sal,  eXosip_event_t *ev){
 static void update_contact_from_response(SalOp *op, osip_message_t *response){
        const char *received;
        int rport;
-       if (extract_received_rport(response,&received,&rport)==0){
+       SalTransport transport;
+       if (extract_received_rport(response,&received,&rport,&transport)==0){
                const char *contact=sal_op_get_contact(op);
                if (!contact){
                        /*no contact given yet, use from instead*/
@@ -1004,8 +1025,10 @@ static void update_contact_from_response(SalOp *op, osip_message_t *response){
                        char *tmp;
                        sal_address_set_domain(addr,received);
                        sal_address_set_port_int(addr,rport);
+                       if (transport!=SalTransportUDP)
+                               sal_address_set_transport(addr,transport);
                        tmp=sal_address_as_string(addr);
-                       ms_message("Contact address updated to %s for this dialog",tmp);
+                       ms_message("Contact address updated to %s",tmp);
                        sal_op_set_contact(op,tmp);
                        sal_address_destroy(addr);
                        ms_free(tmp);
@@ -1015,13 +1038,12 @@ static void update_contact_from_response(SalOp *op, osip_message_t *response){
 
 static int call_proceeding(Sal *sal, eXosip_event_t *ev){
        SalOp *op=find_op(sal,ev);
-       
-       if (op==NULL) {
+
+       if (op==NULL || op->terminated==TRUE) {
                ms_warning("This call has been canceled.");
                eXosip_lock();
                eXosip_call_terminate(ev->cid,ev->did);
                eXosip_unlock();
-               op->terminated=TRUE;
                return -1;
        }
        if (ev->did>0)
@@ -1056,9 +1078,12 @@ static void call_accepted(Sal *sal, eXosip_event_t *ev){
        SalOp *op=find_op(sal,ev);
        const char *contact;
        
-       if (op==NULL){
-               ms_error("A closed call is accepted ?");
-               return;
+       if (op==NULL || op->terminated==TRUE) {
+               ms_warning("This call has been already terminated.");
+               eXosip_lock();
+               eXosip_call_terminate(ev->cid,ev->did);
+               eXosip_unlock();
+               return ;
        }
 
        op->did=ev->did;
@@ -1600,39 +1625,20 @@ static void masquerade_via(osip_message_t *msg, const char *ip, const char *port
        }
 }
 
-static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *orig_request, osip_message_t *last_answer){
-       osip_message_t *msg;
+
+static bool_t fix_message_contact(SalOp *op, osip_message_t *request,osip_message_t *last_answer) {
+       osip_contact_t *ctt=NULL;
        const char *received;
        int rport;
-       osip_contact_t *ctt=NULL;
-       char *tmp;
+       SalTransport transport;
        char port[20];
-       SalAddress *addr;
-       Sal *sal=op->base.root;
 
-       if (sal->double_reg==FALSE) return FALSE;
-       
-       if (extract_received_rport(last_answer,&received,&rport)==-1) return FALSE;
-       osip_message_get_contact(orig_request,0,&ctt);
-       if (strcmp(ctt->url->host,received)==0){
-               /*ip address matches, check ports*/
-               const char *contact_port=ctt->url->port;
-               if (contact_port==NULL || contact_port[0]=='\0')
-                       contact_port="5060";
-               if (atoi(contact_port)==rport){
-                       ms_message("Register has up to date contact, doing nothing.");
-                       return FALSE;
-               }else ms_message("ports do not match, need to update the register (%s <> %i)", contact_port,rport);
-       }
-       eXosip_lock();
-       msg=NULL;
-       eXosip_register_build_register(op->rid,op->expires,&msg);
-       if (msg==NULL){
-               eXosip_unlock();
-               ms_warning("Fail to create a contact updated register.");
+       if (extract_received_rport(last_answer,&received,&rport,&transport)==-1) return FALSE;
+       osip_message_get_contact(request,0,&ctt);
+       if (ctt == NULL) {
+               /*nothing to update*/
                return FALSE;
        }
-       osip_message_get_contact(msg,0,&ctt);
        if (ctt->url->host!=NULL){
                osip_free(ctt->url->host);
        }
@@ -1642,19 +1648,69 @@ static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *ori
        }
        snprintf(port,sizeof(port),"%i",rport);
        ctt->url->port=osip_strdup(port);
-       if (op->masquerade_via) masquerade_via(msg,received,port);
-       eXosip_register_send_register(op->rid,msg);
-       eXosip_unlock();
+       if (op->masquerade_via) masquerade_via(request,received,port);
+
+       if (transport != SalTransportUDP) {
+               sal_address_set_param((SalAddress *)ctt, "transport", sal_transport_to_string(transport)); 
+       }
+       return TRUE;    
+}
+
+static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *orig_request, osip_message_t *last_answer){
+       osip_contact_t *ctt=NULL;
+       SalAddress* ori_contact_address=NULL;
+       const char *received;
+       int rport;
+       SalTransport transport;
+       char* tmp;
+       osip_message_t *msg=NULL;
+       Sal* sal=op->base.root;
+
+       if (sal->double_reg==FALSE ) return FALSE; 
+
+       if (extract_received_rport(last_answer,&received,&rport,&transport)==-1) return FALSE;
+       osip_message_get_contact(orig_request,0,&ctt);
        osip_contact_to_str(ctt,&tmp);
-       addr=sal_address_new(tmp);
+       ori_contact_address = sal_address_new((const char*)tmp);
+       
+       /*check if contact is up to date*/
+       if (strcmp(sal_address_get_domain(ori_contact_address),received) ==0 
+       && sal_address_get_port_int(ori_contact_address) == rport
+       && sal_address_get_transport(ori_contact_address) == transport) {
+               ms_message("Register has up to date contact, doing nothing.");
+               osip_free(tmp);     
+               return FALSE;
+       } else ms_message("contact do not match, need to update the register (%s with %s:%i;transport=%s)"
+                     ,tmp
+                     ,received
+                     ,rport
+                     ,sal_transport_to_string(transport));
        osip_free(tmp);
-       sal_address_clean(addr);
-       tmp=sal_address_as_string(addr);
-       sal_op_set_contact(op,tmp);
-       sal_address_destroy(addr);
-       ms_message("Resending new register with updated contact %s",tmp);
-       ms_free(tmp);
-       return TRUE;
+       sal_address_destroy(ori_contact_address);
+
+       if (transport == SalTransportUDP) {
+               eXosip_lock();
+               eXosip_register_build_register(op->rid,op->expires,&msg);
+               if (msg==NULL){
+                   eXosip_unlock();
+                   ms_warning("Fail to create a contact updated register.");
+                   return FALSE;
+               }
+               if (fix_message_contact(op,msg,last_answer)) {
+                       eXosip_register_send_register(op->rid,msg);
+                       eXosip_unlock();  
+                       ms_message("Resending new register with updated contact");
+                       return TRUE;
+               } else {
+                   ms_warning("Fail to send updated register.");
+                   eXosip_unlock();
+                   return FALSE;
+               }
+               eXosip_unlock();
+       }
+
+       update_contact_from_response(op,last_answer);
+       return FALSE;
 }
 
 static void registration_success(Sal *sal, eXosip_event_t *ev){
@@ -2080,8 +2136,16 @@ char *sal_address_as_string_uri_only(const SalAddress *u){
        osip_free(tmp);
        return ret;
 }
-void sal_address_add_param(SalAddress *u,const char* name,const char* value) {
-       osip_uri_uparam_add     (((osip_from_t*)u)->url,ms_strdup(name),ms_strdup(value));
+void sal_address_set_param(SalAddress *u,const char* name,const char* value) {
+       osip_uri_param_t *param=NULL;
+    osip_uri_uparam_get_byname(((osip_from_t*)u)->url,(char*)name,&param);
+    if (param == NULL){
+        osip_uri_uparam_add    (((osip_from_t*)u)->url,ms_strdup(name),ms_strdup(value));
+    } else {
+        osip_free(param->gvalue);
+        param->gvalue=osip_strdup(value);
+    }
+    
 }
 
 void sal_address_destroy(SalAddress *u){
@@ -2109,6 +2173,19 @@ int sal_address_get_port_int(const SalAddress *uri) {
                return 5060;
        }
 }
+SalTransport sal_address_get_transport(const SalAddress* addr) {
+    const osip_from_t *u=(const osip_from_t*)addr;
+    osip_uri_param_t *transport_param=NULL;
+    osip_uri_uparam_get_byname(u->url,"transport",&transport_param);
+    if (transport_param == NULL){
+        return SalTransportUDP;
+    }  else {
+        return sal_transport_parse(transport_param->gvalue);
+    }
+}
+void sal_address_set_transport(SalAddress* addr,SalTransport transport) {
+    sal_address_set_param(addr, "transport", sal_transport_to_string(transport));
+}
 
 /* sends a reinvite. Local media description may have changed by application since call establishment*/
 int sal_call_update(SalOp *h, const char *subject){
@@ -2136,3 +2213,6 @@ int sal_call_update(SalOp *h, const char *subject){
        eXosip_unlock();
        return err;
 }
+void sal_reuse_authorization(Sal *ctx, bool_t value) {
+       ctx->reuse_authorization=value;
+}
index a050f5133c8100f812bd19c12800cfb936613a6a..201cb65a9780583e1a5fc6b5812e4e40d5f52871 100644 (file)
@@ -44,6 +44,7 @@ struct Sal{
        bool_t double_reg;
        bool_t use_rports;
        bool_t use_101;
+       bool_t reuse_authorization;
 };
 
 struct SalOp{
index c196c2c41cc2b05d0f28e0577ac7eefc3ee7faeb..f336992d701b8dd13581807d544984dfa9978d68 100644 (file)
@@ -40,14 +40,20 @@ void linphone_gtk_call_log_update(GtkWidget *w){
                char *addr= linphone_address_as_string_uri_only (la);
                const char *display;
                gchar *logtxt;
+               gchar quality[20];
+               
                display=linphone_address_get_display_name (la);
                if (display==NULL){
                        display=linphone_address_get_username (la);
                        if (display==NULL)
                                display=linphone_address_get_domain (la);
                }
-               logtxt=g_markup_printf_escaped("<big><b>%s</b></big>\t<small><i>%s</i></small>\n"
-                                              "%s\t%i minutes %i seconds",display, addr, cl->start_date,
+               if (cl->quality!=-1){
+                       snprintf(quality,sizeof(quality),"%.1f",cl->quality);
+               }
+               logtxt=g_markup_printf_escaped("<big><b>%s</b></big>\t<small><i>%s</i>\t<i>Quality: %s</i></small>\n"
+                                              "%s\t%i minutes %i seconds\t",display, addr, cl->quality!=-1 ? quality : _("n/a"),
+                                              cl->start_date,
                                               cl->duration/60,cl->duration%60);
                gtk_list_store_append (store,&iter);
                gtk_list_store_set (store,&iter,
index f19307606aa10bac133d166f3fc29cdca50d426d..d1b116272f0c749138b4076f43ee6da388988c72 100644 (file)
@@ -70,7 +70,7 @@ static GdkPixbuf *create_status_picture(LinphoneOnlineStatus ss){
 void linphone_gtk_set_friend_status(GtkWidget *friendlist , LinphoneFriend * fid, const gchar *url, const gchar *status, const gchar *img){
        GtkTreeIter iter;
        LinphoneFriend *tmp=0;
-       gboolean found=FALSE;
+
        GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist));
        if (gtk_tree_model_get_iter_first(model,&iter)) {
                do{
@@ -81,10 +81,9 @@ void linphone_gtk_set_friend_status(GtkWidget *friendlist , LinphoneFriend * fid
                                gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_PRESENCE_STATUS,status,-1);
                                pixbuf = create_pixbuf(img);
                                if (pixbuf)
-                                 {
-                                   gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_PRESENCE_IMG, pixbuf,-1);
-                                 }
-                                 found=TRUE;
+                               {
+                                       gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_PRESENCE_IMG, pixbuf,-1);
+                               }
                        }
                }while(gtk_tree_model_iter_next(model,&iter));
        }
index 96f672cfc0d13827d35c00cc941437c0059d82ab..919adaa3cdc97bd0fa5cc13022e50a5cac7b43c9 100644 (file)
@@ -205,7 +205,6 @@ void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call, bool_t with_paus
 
        gtk_label_set_markup(GTK_LABEL(status),_("<b>Incoming call</b>"));
        gtk_widget_show_all(linphone_gtk_get_widget(callview,"answer_decline_panel"));
-       gtk_widget_hide(linphone_gtk_get_widget(callview,"duration_frame"));
        gtk_widget_hide(linphone_gtk_get_widget(callview,"mute_pause_buttons"));
        display_peer_name_in_label(callee,linphone_call_get_remote_address (call));
 
@@ -228,6 +227,57 @@ void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call, bool_t with_paus
        }else gtk_image_set_from_stock(GTK_IMAGE(animation),GTK_STOCK_EXECUTE,GTK_ICON_SIZE_DIALOG);
 }
 
+static void rating_to_color(float rating, GdkColor *color){
+       const char *colorname="grey";
+       if (rating>=4.0)
+               colorname="green";
+       else if (rating>=3.0)
+               colorname="white";
+       else if (rating>=2.0)
+               colorname="yellow";
+       else if (rating>=1.0)
+               colorname="orange";
+       else if (rating>=0)
+               colorname="red";
+       if (!gdk_color_parse(colorname,color)){
+               g_warning("Fail to parse color %s",colorname);
+       }
+}
+
+static const char *rating_to_text(float rating){
+       if (rating>=4.0)
+               return _("good");
+       if (rating>=3.0)
+               return _("average");
+       if (rating>=2.0)
+               return _("poor");
+       if (rating>=1.0)
+               return _("very poor");
+       if (rating>=0)
+               return _("too bad");
+       return _("unavailable");
+}
+
+static gboolean linphone_gtk_in_call_view_refresh(LinphoneCall *call){
+       GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
+       GtkWidget *qi=linphone_gtk_get_widget(callview,"quality_indicator");
+       float rating=linphone_call_get_current_quality(call);
+       GdkColor color;
+       gchar tmp[50];
+       linphone_gtk_in_call_view_update_duration(call);
+       if (rating>=0){
+               gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(qi),rating/5.0);
+               snprintf(tmp,sizeof(tmp),"%.1f (%s)",rating,rating_to_text(rating));
+               gtk_progress_bar_set_text(GTK_PROGRESS_BAR(qi),tmp);
+       }else{
+               gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(qi),0);
+               gtk_progress_bar_set_text(GTK_PROGRESS_BAR(qi),_("unavailable"));
+       }
+       rating_to_color(rating,&color);
+       gtk_widget_modify_bg(qi,GTK_STATE_NORMAL,&color);
+       return TRUE;
+}
+
 void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
        GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
        GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
@@ -235,10 +285,10 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
        GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration");
        GtkWidget *animation=linphone_gtk_get_widget(callview,"in_call_animation");
        GdkPixbufAnimation *pbuf=create_pixbuf_animation("incall_anim.gif");
+       guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
        
        display_peer_name_in_label(callee,linphone_call_get_remote_address (call));
 
-       gtk_widget_show(linphone_gtk_get_widget(callview,"duration_frame"));
        gtk_widget_show(linphone_gtk_get_widget(callview,"mute_pause_buttons"));
        gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
        gtk_label_set_markup(GTK_LABEL(status),_("<b>In call</b>"));
@@ -250,6 +300,10 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
        }else gtk_image_set_from_stock(GTK_IMAGE(animation),GTK_STOCK_EXECUTE,GTK_ICON_SIZE_DIALOG);
        linphone_gtk_enable_mute_button(
                                        GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),TRUE);
+       if (taskid==0){
+               taskid=g_timeout_add(250,(GSourceFunc)linphone_gtk_in_call_view_refresh,call);
+               g_object_set_data(G_OBJECT(callview),"taskid",GINT_TO_POINTER(taskid));
+       }
 }
 
 void linphone_gtk_in_call_view_set_paused(LinphoneCall *call){
@@ -283,6 +337,7 @@ void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_m
        GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
        GtkWidget *animation=linphone_gtk_get_widget(callview,"in_call_animation");
        GdkPixbuf *pbuf=create_pixbuf(linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png"));
+       guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
 
        if (error_msg==NULL)
                gtk_label_set_markup(GTK_LABEL(status),_("<b>Call ended.</b>"));
@@ -299,6 +354,7 @@ void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_m
        linphone_gtk_enable_mute_button(
                GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),FALSE);
        linphone_gtk_enable_hold_button(call,FALSE,TRUE);
+       if (taskid!=0) g_source_remove(taskid);
        g_timeout_add_seconds(2,(GSourceFunc)in_call_view_terminated,call);
 }
 
index b47296f27cb23dfd7607510f7eb269f0dd20d0a3..6968466d8ef35dfc6a246fa9d553819a77b11336 100644 (file)
@@ -632,15 +632,6 @@ void linphone_gtk_call_terminated(LinphoneCall *call, const char *error){
        update_video_title();
 }
 
-static gboolean in_call_timer(){
-       LinphoneCall *call=linphone_core_get_current_call(linphone_gtk_get_core());
-       if (call){
-               linphone_gtk_in_call_view_update_duration(call);
-               return TRUE;
-       }
-       return FALSE;
-}
-
 static bool_t all_other_calls_paused(LinphoneCall *refcall, const MSList *calls){
        for(;calls!=NULL;calls=calls->next){
                LinphoneCall *call=(LinphoneCall*)calls->data;
@@ -961,7 +952,6 @@ static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call
                        linphone_gtk_enable_mute_button(
                                GTK_BUTTON(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"main_mute")),
                        TRUE);
-                       g_timeout_add(250,(GSourceFunc)in_call_timer,NULL);
                break;
                case LinphoneCallError:
                        linphone_gtk_in_call_view_terminate (call,msg);
index aaa4ae4a40a549269e13e1a25df5637eb3c9c6f2..c24591a917c6a42645625e0ec990908dd1e68ce7 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy toplevel-contextual -->
@@ -62,7 +62,6 @@
       <object class="GtkVBox" id="vbox2">
         <property name="visible">True</property>
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-        <property name="orientation">vertical</property>
         <child>
           <object class="GtkMenuBar" id="menubar1">
             <property name="visible">True</property>
             <child>
               <object class="GtkVBox" id="main_frame">
                 <property name="visible">True</property>
-                <property name="orientation">vertical</property>
                 <child>
                   <object class="GtkHBox" id="address_bar">
                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="has_focus">True</property>
                                     <property name="tooltip_text" translatable="yes">Enter username, phone number, or full sip address</property>
-                                    <property name="invisible_char">&#x25CF;</property>
+                                    <property name="invisible_char"></property>
                                     <signal name="activate" handler="linphone_gtk_uri_bar_activate"/>
                                   </object>
                                   <packing>
                       <object class="GtkVBox" id="idle_frame">
                         <property name="visible">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="orientation">vertical</property>
                         <child>
                           <object class="GtkHBox" id="hbox5">
                             <property name="visible">True</property>
                             <child>
                               <object class="GtkVBox" id="vbox5">
                                 <property name="visible">True</property>
-                                <property name="orientation">vertical</property>
                                 <child>
                                   <object class="GtkFrame" id="contact_list_frame">
                                     <property name="visible">True</property>
                                           <object class="GtkVBox" id="vbox7">
                                             <property name="visible">True</property>
                                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                            <property name="orientation">vertical</property>
                                             <child>
                                               <object class="GtkHBox" id="filtering_box">
                                                 <property name="visible">True</property>
                                                     <property name="visible">True</property>
                                                     <property name="can_focus">True</property>
                                                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                                    <property name="invisible_char">&#x25CF;</property>
+                                                    <property name="invisible_char"></property>
                                                     <signal name="changed" handler="linphone_gtk_show_friends"/>
                                                   </object>
                                                   <packing>
                                                       <object class="GtkEntry" id="directory_search_entry">
                                                         <property name="visible">True</property>
                                                         <property name="can_focus">True</property>
-                                                        <property name="invisible_char">&#x25CF;</property>
+                                                        <property name="invisible_char">●</property>
+                                                        <signal name="focus_in_event" handler="linphone_gtk_directory_search_focus_in"/>
                                                         <signal name="activate" handler="linphone_gtk_directory_search_activate"/>
                                                         <signal name="icon_press" handler="linphone_gtk_directory_search_activate"/>
-                                                        <signal name="focus_in_event" handler="linphone_gtk_directory_search_focus_in"/>
                                                         <signal name="focus_out_event" handler="linphone_gtk_directory_search_focus_out"/>
                                                       </object>
                                                       <packing>
                     <child>
                       <object class="GtkVBox" id="keypad_frame">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
                         <child>
                           <object class="GtkFrame" id="frame3">
                             <property name="visible">True</property>
                     <child>
                       <object class="GtkVBox" id="vbox1">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
                         <child>
                           <object class="GtkImage" id="login_image">
                             <property name="visible">True</property>
                                       <object class="GtkEntry" id="login_username">
                                         <property name="visible">True</property>
                                         <property name="can_focus">True</property>
-                                        <property name="invisible_char">&#x25CF;</property>
+                                        <property name="invisible_char"></property>
                                       </object>
                                       <packing>
                                         <property name="left_attach">1</property>
                                         <property name="visible">True</property>
                                         <property name="can_focus">True</property>
                                         <property name="visibility">False</property>
-                                        <property name="invisible_char">&#x25CF;</property>
+                                        <property name="invisible_char"></property>
                                       </object>
                                       <packing>
                                         <property name="left_attach">1</property>
             <child>
               <object class="GtkVBox" id="vbox3">
                 <property name="visible">True</property>
-                <property name="orientation">vertical</property>
                 <child>
                   <object class="GtkImage" id="in_call_animation">
                     <property name="visible">True</property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkFrame" id="frame2">
+                  <object class="GtkLabel" id="in_call_uri">
                     <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <child>
-                      <object class="GtkLabel" id="in_call_uri">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">label</property>
-                        <property name="justify">center</property>
-                      </object>
-                    </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="label3">
-                        <property name="visible">True</property>
-                        <property name="use_markup">True</property>
-                      </object>
-                    </child>
+                    <property name="label" translatable="yes">label</property>
+                    <property name="justify">center</property>
                   </object>
                   <packing>
                     <property name="position">1</property>
                     <property name="position">2</property>
                   </packing>
                 </child>
-                <child>
-                  <object class="GtkFrame" id="duration_frame">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <child>
-                      <object class="GtkVBox" id="vbox4">
-                        <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkLabel" id="in_call_duration">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Duration</property>
-                            <property name="justify">center</property>
-                          </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="call_label">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Duration:</property>
-                        <property name="use_markup">True</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">3</property>
-                  </packing>
-                </child>
                 <child>
                   <object class="GtkHButtonBox" id="mute_pause_buttons">
                     <property name="visible">True</property>
                   <packing>
                     <property name="expand">False</property>
                     <property name="fill">False</property>
-                    <property name="position">4</property>
+                    <property name="position">3</property>
                   </packing>
                 </child>
               </object>
           </object>
         </child>
         <child type="label">
-          <object class="GtkLabel" id="in_call_status">
+          <object class="GtkHBox" id="heading_box">
             <property name="visible">True</property>
-            <property name="label" translatable="yes">In call</property>
-            <property name="use_markup">True</property>
-            <property name="justify">center</property>
+            <property name="homogeneous">True</property>
+            <child>
+              <object class="GtkLabel" id="in_call_status">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">In call</property>
+                <property name="use_markup">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="in_call_duration">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Duration</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="quality_indicator">
+                <property name="visible">True</property>
+                <property name="tooltip_text" translatable="yes">Call quality rating</property>
+              </object>
+              <packing>
+                <property name="position">2</property>
+              </packing>
+            </child>
           </object>
         </child>
       </object>
index 9f029b05317e00259a3aab6f945863fe8126c8e8..e0f7cde340e0cf308f903507b0ff10dda5399a94 100644 (file)
@@ -190,4 +190,28 @@ public interface LinphoneCall {
         * @return call duration computed from media start
         */
        int getDuration();
+       /**
+        * Obtain real-time quality rating of the call
+        *
+        * Based on local RTP statistics and RTCP feedback, a quality rating is computed and updated
+        * during all the duration of the call. This function returns its value at the time of the function call.
+        * It is expected that the rating is updated at least every 5 seconds or so.
+        * The rating is a floating point number comprised between 0 and 5.
+        *
+        * 4-5 = good quality <br>
+        * 3-4 = average quality <br>
+        * 2-3 = poor quality <br>
+        * 1-2 = very poor quality <br>
+        * 0-1 = can't be worse, mostly unusable <br>
+        *
+        * @returns The function returns -1 if no quality measurement is available, for example if no 
+        * active audio stream exist. Otherwise it returns the quality rating.
+        */
+       float getCurrentQuality();
+       /**
+        * Returns call quality averaged over all the duration of the call.
+        *
+        * See getCurrentQuality() for more details about quality measurement.
+        */
+       float getAverageQuality();
 }
index 1c7dd2ff990596dfa8bb56015c3933dcf93c6fed..4afe7182ffab96653cd2af52a7889e4f9fc8ab28 100644 (file)
@@ -531,6 +531,18 @@ public interface LinphoneCore {
        void setUploadBandwidth(int bw);
 
        void setDownloadBandwidth(int bw);
+       
+       /**
+        * Sets audio packetization interval suggested for remote end.
+        * @param ptime packetization interval in milliseconds
+        */
+       void setDownloadPtime(int ptime);
+       
+       /**
+        * Sets audio packetization interval sent to remote end.
+        * @param ptime packetization interval in milliseconds
+        */
+       void setUploadPtime(int ptime);
 
        void setPreferredVideoSize(VideoSize vSize);
        
index 22e069ed85b2a312647474f8136dbc3401081f1d..de01182cafcdce11acb815ad47551f13fd0f8f66 100755 (executable)
@@ -1,10 +1,9 @@
-./bin/avcodec-52.dll
-./bin/avutil-50.dll
+./bin/avcodec-53.dll
+./bin/avutil-51.dll
 ./bin/libeXosip2-6.dll
 ./bin/libogg-0.dll
 ./bin/libtheora-0.dll
 ./bin/libxml2-2.dll
 ./bin/libosip2-6.dll
 ./bin/libosipparser2-6.dll
-./bin/swscale-0.dll
-
+./bin/swscale-2.dll
index 3428fc9d84c363c677d0db0a3682b4bd2ca6d21a..06f75eec486b8a5be3032d387bc91d9f4ca135e3 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3428fc9d84c363c677d0db0a3682b4bd2ca6d21a
+Subproject commit 06f75eec486b8a5be3032d387bc91d9f4ca135e3
diff --git a/oRTP b/oRTP
index b0c5530bee255033f09011e5aab6d036e00520dc..662a65869902a927673d9ceff10781e217ca8e9d 160000 (submodule)
--- a/oRTP
+++ b/oRTP
@@ -1 +1 @@
-Subproject commit b0c5530bee255033f09011e5aab6d036e00520dc
+Subproject commit 662a65869902a927673d9ceff10781e217ca8e9d
index 55ce35cdf3b801846ec525fbabc727f2c7d2941d..d826a1ff9c4ee74c9eeedb442c03acd4b7084a07 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -7,7 +7,7 @@ msgstr ""
 "Project-Id-Version: linphone 0.7.1\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2011-04-08 22:32+0200\n"
-"PO-Revision-Date: 2011-04-10 02:35+0200\n"
+"PO-Revision-Date: 2011-05-27 23:45+0200\n"
 "Last-Translator: Gerhard Stengel <gstengel@gmx.net>\n"
 "Language-Team: German <kde-i18n-de@kde.org>\n"
 "Language: \n"
@@ -573,7 +573,7 @@ msgstr "Dauer:"
 
 #: ../gtk/main.ui.h:33
 msgid "Enable self-view"
-msgstr "Selbstansicht einschalten"
+msgstr "Selbstansicht ein"
 
 #: ../gtk/main.ui.h:34
 msgid "Enter username, phone number, or full sip address"
@@ -1391,7 +1391,7 @@ msgstr "Abmeldung von %s ist erfolgt."
 
 #: ../coreapi/callbacks.c:574
 msgid "no response timeout"
-msgstr "keine Zeitüberschreitung bei der Antwort"
+msgstr "Zeitüberschreitung bei der Antwort"
 
 #: ../coreapi/callbacks.c:577
 #, c-format