]> sjero.net Git - linphone/commitdiff
Merge commit 'aab6c70'
authorJehan Monnier <jehan.monnier@linphone.org>
Tue, 3 Apr 2012 08:50:48 +0000 (10:50 +0200)
committerJehan Monnier <jehan.monnier@linphone.org>
Tue, 3 Apr 2012 08:50:48 +0000 (10:50 +0200)
15 files changed:
configure.ac
coreapi/callbacks.c
coreapi/chat.c
coreapi/linphonecall.c
coreapi/linphonecore.c
coreapi/linphonecore.h
coreapi/presence.c
coreapi/private.h
coreapi/sal.h
coreapi/sal_eXosip2.c
gtk/incall_view.c
gtk/linphone.h
gtk/main.c
linphone.spec.in
oRTP

index ce360445100e6653a255d51eb880cf4b7e368728..2bead21ddc9b1de1b86cbd8ad03eab28ac4b5830 100644 (file)
@@ -17,7 +17,7 @@ if test "$LINPHONE_EXTRA_VERSION" != "" ;then
        LINPHONE_VERSION=$LINPHONE_VERSION.${LINPHONE_EXTRA_VERSION}
 fi
 
-LIBLINPHONE_SO_CURRENT=4 dnl increment this number when you add/change/remove an interface
+LIBLINPHONE_SO_CURRENT=5 dnl increment this number when you add/change/remove an interface
 LIBLINPHONE_SO_REVISION=0 dnl increment this number when you change source code, without changing interfaces; set to 0 when incrementing CURRENT
 LIBLINPHONE_SO_AGE=0 dnl increment this number when you add an interface, set to 0 if you remove an interface
 
@@ -102,9 +102,13 @@ AC_SUBST(ALL_LINGUAS)
 AC_DEFINE_UNQUOTED(LINPHONE_ALL_LANGS, "$ALL_LINGUAS", [All supported languages])
 
 if test "$mingw_found" != "yes" ; then
-dnl gettext macro does not work properly under mingw. And we want to use the one provided by GTK.
-AM_GNU_GETTEXT([external])
-LIBS="$LIBS $LIBINTL"
+       dnl gettext macro does not work properly under mingw. And we want to use the one provided by GTK.
+       
+       dnl AM_GNU_GETTEXT pollutes CPPFLAGS: workaround this.
+       CPPFLAGS_save=$CPPFLAGS
+       AM_GNU_GETTEXT([external])
+       CPPFLAGS=$CPPFLAGS_save
+       LIBS="$LIBS $LIBINTL"
 else
        AC_DEFINE(ENABLE_NLS,1,[Tells whether localisation is possible])
        AC_DEFINE(HAVE_GETTEXT,1,[Tells wheter localisation is possible])
index a4181cfa0a02f8227bf2608260c1e7184ec9e166..34fd552af15461809a7592d674f863890df94ce1 100644 (file)
@@ -324,6 +324,7 @@ static void call_accepted(SalOp *op){
            call->state==LinphoneCallOutgoingRinging ||
            call->state==LinphoneCallOutgoingEarlyMedia){
                linphone_call_set_state(call,LinphoneCallConnected,"Connected");
+               if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
        }
        if (md && !sal_media_description_empty(md)){
                if (sal_media_description_has_dir(md,SalStreamSendOnly) ||
@@ -369,9 +370,9 @@ static void call_accepted(SalOp *op){
                                }
                        }
                        linphone_core_update_streams (lc,call,md);
-                       linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
                        if (!call->current_params.in_conference)
                                lc->current_call=call;
+                       linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
                }
        }else{
                /*send a bye*/
@@ -592,6 +593,10 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
        } else {
                linphone_call_set_state(call,LinphoneCallError,msg);
        }
+       if (call->referer && linphone_call_get_state(call->referer)==LinphoneCallPaused && call->referer->was_automatically_paused){
+               /*resume to the call that send us the refer automatically*/
+               linphone_core_resume_call(lc,call->referer);
+       }
 }
 
 static void call_released(SalOp *op){
@@ -745,12 +750,11 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){
                if (call->state!=LinphoneCallPaused){
                        ms_message("Automatically pausing current call to accept transfer.");
                        linphone_core_pause_call(lc,call);
+                       call->was_automatically_paused=TRUE;
                }
                linphone_core_start_refered_call(lc,call);
-               sal_call_accept_refer(op);
        }else if (lc->vtable.refer_received){
                lc->vtable.refer_received(lc,referto);
-               sal_call_accept_refer(op);
        }
 }
 
@@ -767,7 +771,7 @@ static void notify(SalOp *op, const char *from, const char *msg){
                lc->vtable.notify_recv(lc,call,from,msg);
 }
 
-static void notify_presence(SalOp *op, SalSubscribeState ss, SalPresenceStatus status, const char *msg){
+static void notify_presence(SalOp *op, SalSubscribeStatus ss, SalPresenceStatus status, const char *msg){
        LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
        linphone_notify_recv(lc,op,ss,status);
 }
@@ -796,6 +800,35 @@ static void ping_reply(SalOp *op){
        }
 }
 
+static void notify_refer(SalOp *op, SalReferStatus status){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       LinphoneCall *call=(LinphoneCall*) sal_op_get_user_pointer(op);
+       LinphoneCallState cstate;
+       if (call==NULL) {
+               ms_warning("Receiving notify_refer for unknown call.");
+               return ;
+       }
+       switch(status){
+               case SalReferTrying:
+                       cstate=LinphoneCallOutgoingProgress;
+               break;
+               case SalReferSuccess:
+                       cstate=LinphoneCallConnected;
+               break;
+               case SalReferFailed:
+                       cstate=LinphoneCallError;
+               break;
+               default:
+                       cstate=LinphoneCallError;
+       }
+       if (lc->vtable.transfer_state_changed)
+               lc->vtable.transfer_state_changed(lc,call,cstate);
+       if (cstate==LinphoneCallConnected){
+               /*automatically terminate the call as the transfer is complete.*/
+               linphone_core_terminate_call(lc,call);
+       }
+}
+
 SalCallbacks linphone_sal_callbacks={
        call_received,
        call_ringing,
@@ -815,6 +848,7 @@ SalCallbacks linphone_sal_callbacks={
        text_received,
        notify,
        notify_presence,
+       notify_refer,
        subscribe_received,
        subscribe_closed,
        ping_reply
index d90cf61e4ec6de92b81d93267e341359146abfe0..9847c2c3b88ad86c4c4af5def481bf75934576c6 100644 (file)
 void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg){
        const char *route=NULL;
        const char *identity=linphone_core_find_best_identity(cr->lc,cr->peer_url,&route);
-       SalOp *op;
+       SalOp *op=NULL;
        LinphoneCall *call;
-       if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL)
-       {
-               ms_message("send SIP message into the call\n");
-               op = call->op;
+       if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL){
+               if (call->state==LinphoneCallConnected ||
+                   call->state==LinphoneCallStreamsRunning ||
+                   call->state==LinphoneCallPaused ||
+                   call->state==LinphoneCallPausing ||
+                   call->state==LinphoneCallPausedByRemote){
+                       ms_message("send SIP message through the existing call.");
+                       op = call->op;
+               }
        }
-       else
-       {
+       if (op==NULL){
+               /*sending out of calls*/
                op = sal_op_new(cr->lc->sal);
                sal_op_set_route(op,route);
                if (cr->op!=NULL){
index 6ec119105824ee9b1b7b3ebe521a32cc2364544c..9c3ecfd11a18976aab1d1c6883913c0bdad682bb 100644 (file)
@@ -337,6 +337,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
        discover_mtu(lc,linphone_address_get_domain (to));
        if (params->referer){
                sal_call_set_referer(call->op,params->referer->op);
+               call->referer=linphone_call_ref(params->referer);
        }
        return call;
 }
@@ -406,6 +407,10 @@ static void linphone_call_set_terminated(LinphoneCall *call){
                linphone_core_stop_dtmf(lc);
                call->ringing_beep=FALSE;
        }
+       if (call->referer){
+               linphone_call_unref(call->referer);
+               call->referer=NULL;
+       }
 }
 
 void linphone_call_fix_call_parameters(LinphoneCall *call){
@@ -847,12 +852,18 @@ static void rendercb(void *data, const MSPicture *local, const MSPicture *remote
 
 #ifdef VIDEO_ENABLED
 static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const unsigned int event_id, const void *args){
+    LinphoneCall* call = (LinphoneCall*) user_pointer;
        ms_warning("In linphonecall.c: video_stream_event_cb");
        switch (event_id) {
                case MS_VIDEO_DECODER_DECODING_ERRORS:
                        ms_warning("Case is MS_VIDEO_DECODER_DECODING_ERRORS");
-                       linphone_call_send_vfu_request((LinphoneCall*) user_pointer);
+                       linphone_call_send_vfu_request(call);
                        break;
+        case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED:
+            ms_message("First video frame decoded successfully");
+            if (call->nextVideoFrameDecoded._func != NULL)
+                call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data);
+            break;
                default:
                        ms_warning("Unhandled event %i", event_id);
                        break;
@@ -860,6 +871,14 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u
 }
 #endif
 
+void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data) {
+    call->nextVideoFrameDecoded._func = cb;
+    call->nextVideoFrameDecoded._user_data = user_data;
+#ifdef VIDEO_ENABLED
+    ms_filter_call_method_noarg(call->videostream->decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION);
+#endif
+}
+
 void linphone_call_init_media_streams(LinphoneCall *call){
        LinphoneCore *lc=call->core;
        SalMediaDescription *md=call->localdesc;
@@ -903,18 +922,21 @@ void linphone_call_init_media_streams(LinphoneCall *call){
 #ifdef VIDEO_ENABLED
 
        if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].port>0){
+               int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0);
                call->videostream=video_stream_new(md->streams[1].port,linphone_core_ipv6_enabled(lc));
-        video_stream_enable_display_filter_auto_rotate(call->videostream, lp_config_get_int(lc->config,"video","display_filter_auto_rotate",0));
-       if( lc->video_conf.displaytype != NULL)
-               video_stream_set_display_filter_name(call->videostream,lc->video_conf.displaytype);
-       video_stream_set_event_callback(call->videostream,video_stream_event_cb, call);
-       if (lc->rtptf){
-               RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->video_port);
-               RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->video_port+1);
-               rtp_session_set_transports(call->videostream->session,vrtp,vrtcp);
-       }
-       call->videostream_app_evq = ortp_ev_queue_new();
-       rtp_session_register_event_queue(call->videostream->session,call->videostream_app_evq);
+               video_stream_enable_display_filter_auto_rotate(call->videostream, lp_config_get_int(lc->config,"video","display_filter_auto_rotate",0));
+               if (video_recv_buf_size>0) rtp_session_set_recv_buf_size(call->videostream->session,video_recv_buf_size);
+          
+               if( lc->video_conf.displaytype != NULL)
+                       video_stream_set_display_filter_name(call->videostream,lc->video_conf.displaytype);
+               video_stream_set_event_callback(call->videostream,video_stream_event_cb, call);
+               if (lc->rtptf){
+                       RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->video_port);
+                       RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->video_port+1);
+                       rtp_session_set_transports(call->videostream->session,vrtp,vrtcp);
+               }
+               call->videostream_app_evq = ortp_ev_queue_new();
+               rtp_session_register_event_queue(call->videostream->session,call->videostream_app_evq);
 #ifdef TEST_EXT_RENDERER
                video_stream_set_render_callback(call->videostream,rendercb,NULL);
 #endif
@@ -1276,6 +1298,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
                                cam=get_nowebcam_device();
                        }
                        if (!is_inactive){
+                call->log->video_enabled = TRUE;
                                video_stream_set_direction (call->videostream, dir);
                                ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation);
                                video_stream_set_device_rotation(call->videostream, lc->device_rotation);
index 63be1a7fcfe90a893c6a2064fa68367144b3b180..904f6a6c8c3fc7d0d4e9090cc41a57ae364b6b72 100644 (file)
@@ -132,6 +132,7 @@ void call_logs_write_to_config_file(LinphoneCore *lc){
                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);
+        lp_config_set_int(cfg,logsection,"video_enabled", cl->video_enabled);
        }
        for(;i<lc->max_call_logs;++i){
                snprintf(logsection,sizeof(logsection),"call_log_%i",i);
@@ -160,6 +161,7 @@ static void call_logs_read_from_config_file(LinphoneCore *lc){
                        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);
+            cl->video_enabled=lp_config_get_int(cfg,logsection,"video_enabled",0);
                        lc->call_logs=ms_list_append(lc->call_logs,cl);
                }else break;
        }
@@ -1941,12 +1943,20 @@ const char * linphone_core_get_route(LinphoneCore *lc){
 void linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call){
        if (call->refer_pending){
                LinphoneCallParams *cp=linphone_core_create_default_call_parameters(lc);
+               LinphoneCall *newcall;
                cp->has_video &= !!lc->video_policy.automatically_initiate;
                cp->referer=call;
                ms_message("Starting new call to refered address %s",call->refer_to);
                call->refer_pending=FALSE;
-               linphone_core_invite_with_params(lc,call->refer_to,cp);
+               newcall=linphone_core_invite_with_params(lc,call->refer_to,cp);
                linphone_call_params_destroy(cp);
+               if (newcall) linphone_core_notify_refer_state(lc,call,newcall);
+       }
+}
+
+void linphone_core_notify_refer_state(LinphoneCore *lc, LinphoneCall *referer, LinphoneCall *newcall){
+       if (referer->op!=NULL){
+               sal_call_notify_refer_state(referer->op,newcall ? newcall->op : NULL);
        }
 }
 
index 35fa25ad3442c80ff71d5704d212eb46570b0c9a..9ed6297107e65ccac6a5272bf9b73c8a10a123e8 100644 (file)
@@ -153,6 +153,7 @@ typedef struct _LinphoneCallLog{
        rtp_stats_t local_stats;
        rtp_stats_t remote_stats;
        float quality;
+    int video_enabled;
        struct _LinphoneCore *lc;
 } LinphoneCallLog;
 
@@ -225,6 +226,9 @@ typedef struct _LinphoneVideoPolicy LinphoneVideoPolicy;
 **/
 struct _LinphoneCall;
 typedef struct _LinphoneCall LinphoneCall;
+    
+/** Callback prototype */
+typedef void (*LinphoneCallCbFunc)(struct _LinphoneCall *call,void * user_data);
 
 /**
  * LinphoneCallState enum represents the different state a call can reach into.
@@ -286,6 +290,8 @@ void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t
 void linphone_call_send_vfu_request(LinphoneCall *call);
 void *linphone_call_get_user_pointer(LinphoneCall *call);
 void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
+void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data);
+    
 /**
  * Enables or disable echo cancellation for this call
  * @param call
@@ -613,6 +619,8 @@ typedef void (*DtmfReceived)(struct _LinphoneCore* lc, LinphoneCall *call, int d
 typedef void (*ReferReceived)(struct _LinphoneCore *lc, const char *refer_to);
 /** Callback prototype */
 typedef void (*BuddyInfoUpdated)(struct _LinphoneCore *lc, LinphoneFriend *lf);
+/** Callback prototype for in progress transfers. The new_call_state is the state of the call resulting of the transfer, at the other party. */
+typedef void (*LinphoneTransferStateChanged)(struct _LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state);
 
 /**
  * This structure holds all callbacks that the application should implement.
@@ -629,6 +637,8 @@ typedef struct _LinphoneVTable{
        TextMessageReceived text_received; /**< A text message has been received */
        DtmfReceived dtmf_received; /**< A dtmf has been received received */
        ReferReceived refer_received; /**< An out of call refer was received */
+       CallEncryptionChangedCb call_encryption_changed; /**<Notifies on change in the encryption of call streams */
+    LinphoneTransferStateChanged transfer_state_changed; /**<Notifies when a transfer is in progress */
        BuddyInfoUpdated buddy_info_updated; /**< a LinphoneFriend's BuddyInfo has changed*/
        NotifyReceivedCb notify_recv; /**< Other notifications*/
        DisplayStatusCb display_status; /**< Callback that notifies various events with human readable text.*/
@@ -636,7 +646,6 @@ typedef struct _LinphoneVTable{
        DisplayMessageCb display_warning;/** Callback to display a warning to the user */
        DisplayUrlCb display_url;
        ShowInterfaceCb show; /**< Notifies the application that it should show up*/
-       CallEncryptionChangedCb call_encryption_changed; /**<Notifies on change in the encryption of call streams */
 } LinphoneCoreVTable;
 
 /**
index d97f4ed9419548bb0d34a95e1e2ed872d4f36ba8..ca63572588c764cfcde05fa5b7ff39f8d6e13cc9 100644 (file)
@@ -101,7 +101,7 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
        ms_free(tmp);
 }
 
-void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeState ss, SalPresenceStatus sal_status){
+void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceStatus sal_status){
        char *tmp;
        LinphoneFriend *lf;
        LinphoneAddress *friend=NULL;
index ab317c981850205d8eb725bed7c5d2879b8fabb0..425b51008e39ca4aadf2268aa3347acbecd72681 100644 (file)
@@ -74,6 +74,12 @@ struct _LinphoneCallParams{
        bool_t pad;
        
 };
+    
+typedef struct _CallCallbackObj
+{
+    LinphoneCallCbFunc _func;
+    void * _user_data;
+}CallCallbackObj;
 
 static const int linphone_call_magic=0x3343;
 
@@ -84,6 +90,7 @@ struct _LinphoneCall
        SalMediaDescription *localdesc;
        SalMediaDescription *resultdesc;
        LinphoneCallDir dir;
+       LinphoneCall *referer; /*when this call is the result of a transfer, referer is set to the original call that caused the transfer*/
        struct _RtpProfile *audio_profile;
        struct _RtpProfile *video_profile;
        struct _LinphoneCallLog *log;
@@ -122,6 +129,8 @@ struct _LinphoneCall
        bool_t audiostream_encrypted;
        bool_t auth_token_verified;
        bool_t defer_update;
+       bool_t was_automatically_paused;
+    CallCallbackObj nextVideoFrameDecoded;
 };
 
 
@@ -193,7 +202,7 @@ SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os);
 void linphone_process_authentication(LinphoneCore* lc, SalOp *op);
 void linphone_authentication_ok(LinphoneCore *lc, SalOp *op);
 void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from);
-void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeState ss, SalPresenceStatus status);
+void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceStatus status);
 void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, SalOp *op);
 
 void linphone_subscription_answered(LinphoneCore *lc, SalOp *op);
@@ -549,6 +558,7 @@ void linphone_call_add_to_conf(LinphoneCall *call, bool_t muted);
 void linphone_call_remove_from_conf(LinphoneCall *call);
 void linphone_core_conference_check_uninit(LinphoneCore *lc);
 bool_t linphone_core_sound_resources_available(LinphoneCore *lc);
+void linphone_core_notify_refer_state(LinphoneCore *lc, LinphoneCall *referer, LinphoneCall *newcall);
 
 void __linphone_core_invalidate_registers(LinphoneCore* lc);
 
index e74e80c68ade8b88ad8b07c210b87b5e2968bab7..bbe4dafff035afb35ed82abe53c3700b2a032c90 100644 (file)
@@ -207,10 +207,16 @@ typedef enum SalPresenceStatus{
        SalPresenceAltService,
 }SalPresenceStatus;
 
-typedef enum SalSubscribeState{
+typedef enum SalReferStatus{
+       SalReferTrying,
+       SalReferSuccess,
+       SalReferFailed
+}SalReferStatus;
+
+typedef enum SalSubscribeStatus{
        SalSubscribeActive,
        SalSubscribeTerminated
-}SalSubscribeState;
+}SalSubscribeStatus;
 
 typedef void (*SalOnCallReceived)(SalOp *op);
 typedef void (*SalOnCallRinging)(SalOp *op);
@@ -228,8 +234,9 @@ typedef void (*SalOnVfuRequest)(SalOp *op);
 typedef void (*SalOnDtmfReceived)(SalOp *op, char dtmf);
 typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto);
 typedef void (*SalOnTextReceived)(Sal *sal, const char *from, const char *msg);
-typedef void (*SalOnNotify)(SalOp *op, const char *from, const char *value);
-typedef void (*SalOnNotifyPresence)(SalOp *op, SalSubscribeState ss, SalPresenceStatus status, const char *msg);
+typedef void (*SalOnNotify)(SalOp *op, const char *from, const char *event);
+typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state);
+typedef void (*SalOnNotifyPresence)(SalOp *op, SalSubscribeStatus ss, SalPresenceStatus status, const char *msg);
 typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *from);
 typedef void (*SalOnSubscribeClosed)(SalOp *salop, const char *from);
 typedef void (*SalOnPingReply)(SalOp *salop);
@@ -253,6 +260,7 @@ typedef struct SalCallbacks{
        SalOnTextReceived text_received;
        SalOnNotify notify;
        SalOnNotifyPresence notify_presence;
+       SalOnNotifyRefer notify_refer;
        SalOnSubscribeReceived subscribe_received;
        SalOnSubscribeClosed subscribe_closed;
        SalOnPingReply ping_reply;
@@ -340,6 +348,7 @@ 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);
+int sal_call_notify_refer_state(SalOp *h, SalOp *newcall);
 
 /*Registration*/
 int sal_register(SalOp *op, const char *proxy, const char *from, int expires);
index 6d66bf4c42d8f1ff8ea911d5f2587fe44a627dd0..a89a8a13c5e7b0bd264f63f0a1938b0fdff23ab7 100644 (file)
@@ -728,6 +728,45 @@ int sal_call_set_referer(SalOp *h, SalOp *refered_call){
        return 0;
 }
 
+static int send_notify_for_refer(int did, const char *sipfrag){
+       osip_message_t *msg;
+       eXosip_lock();
+       eXosip_call_build_notify(did,EXOSIP_SUBCRSTATE_ACTIVE,&msg);
+       if (msg==NULL){
+               eXosip_unlock();
+               ms_error("Could not build NOTIFY for refer.");
+               return -1;
+       }
+       osip_message_set_content_type(msg,"message/sipfrag");
+       osip_message_set_header(msg,"Event","refer");
+       osip_message_set_body(msg,sipfrag,strlen(sipfrag));
+       eXosip_call_send_request(did,msg);
+       eXosip_unlock();
+       return 0;
+}
+
+/* currently only support to notify trying and 200Ok*/
+int sal_call_notify_refer_state(SalOp *h, SalOp *newcall){
+       if (newcall==NULL){
+               /* in progress*/
+               send_notify_for_refer(h->did,"SIP/2.0 100 Trying\r\n");
+       }
+       else if (newcall->cid!=-1){
+               if (newcall->did==-1){
+                       /* not yet established*/
+                       if (!newcall->terminated){
+                               /* in progress*/
+                               send_notify_for_refer(h->did,"SIP/2.0 100 Trying\r\n");
+                       }
+               }else{
+                       if (!newcall->terminated){
+                               send_notify_for_refer(h->did,"SIP/2.0 200 Ok\r\n");
+                       }
+               }
+       }
+       return 0;
+}
+
 int sal_ping(SalOp *op, const char *from, const char *to){
        osip_message_t *options=NULL;
        
@@ -748,26 +787,6 @@ int sal_ping(SalOp *op, const char *from, const char *to){
        return -1;
 }
 
-int sal_call_accept_refer(SalOp *op){
-       osip_message_t *msg=NULL;
-       int err=0;
-       eXosip_lock();
-       err = eXosip_call_build_notify(op->did,EXOSIP_SUBCRSTATE_ACTIVE,&msg);
-       if(msg != NULL)
-       {
-               osip_message_set_header(msg,(const char *)"event","refer");
-               osip_message_set_content_type(msg,"message/sipfrag");
-               osip_message_set_body(msg,"SIP/2.0 100 Trying",sizeof("SIP/2.0 100 Trying"));
-               eXosip_call_send_request(op->did,msg);
-       }
-       else
-       {
-               ms_error("could not get a notify built\n");
-       }
-       eXosip_unlock();
-       return err;
-}
-
 int sal_call_refer(SalOp *h, const char *refer_to){
        osip_message_t *msg=NULL;
        int err=0;
@@ -1517,6 +1536,51 @@ static void process_refer(Sal *sal, SalOp *op, eXosip_event_t *ev){
        }
 }
 
+void process_notify(Sal *sal, eXosip_event_t *ev){
+       osip_header_t *h=NULL;
+       char *from=NULL;
+       SalOp *op=find_op(sal,ev);
+       osip_message_t *ans=NULL;
+
+       ms_message("Receiving NOTIFY request !");
+       osip_from_to_str(ev->request->from,&from);
+       osip_message_header_get_byname(ev->request,"Event",0,&h);
+       if(h){
+               osip_body_t *body=NULL;
+               //osip_content_type_t *ct=NULL;
+               osip_message_get_body(ev->request,0,&body);
+               //ct=osip_message_get_content_type(ev->request);
+               if (h->hvalue && strcasecmp(h->hvalue,"refer")==0){
+                       /*special handling of refer events*/
+                       if (body && body->body){
+                               osip_message_t *msg;
+                               osip_message_init(&msg);
+                               if (osip_message_parse_sipfrag(msg,body->body,strlen(body->body))==0){
+                                       int code=osip_message_get_status_code(msg);
+                                       if (code==100){
+                                               sal->callbacks.notify_refer(op,SalReferTrying);
+                                       }else if (code==200){
+                                               sal->callbacks.notify_refer(op,SalReferSuccess);
+                                       }else if (code>=400){
+                                               sal->callbacks.notify_refer(op,SalReferFailed);
+                                       }
+                               }
+                               osip_message_free(msg);
+                       }
+               }else{
+                       /*generic handling*/
+                       sal->callbacks.notify(op,from,h->hvalue);
+               }
+       }
+       /*answer that we received the notify*/
+       eXosip_lock();
+       eXosip_call_build_answer(ev->tid,200,&ans);
+       if (ans)
+               eXosip_call_send_answer(ev->tid,200,ans);
+       eXosip_unlock();
+       osip_free(from);
+}
+
 static void call_message_new(Sal *sal, eXosip_event_t *ev){
        osip_message_t *ans=NULL;
        if (ev->request){
@@ -1559,22 +1623,7 @@ static void call_message_new(Sal *sal, eXosip_event_t *ev){
                        ms_message("Receiving REFER request !");
                        process_refer(sal,op,ev);
                }else if(MSG_IS_NOTIFY(ev->request)){
-                       osip_header_t *h=NULL;
-                       char *from=NULL;
-                       SalOp *op=find_op(sal,ev);
-
-                       ms_message("Receiving NOTIFY request !");
-                       osip_from_to_str(ev->request->from,&from);
-                       osip_message_header_get_byname(ev->request,"Event",0,&h);
-                       if(h)
-                               sal->callbacks.notify(op,from,h->hvalue);
-                       /*answer that we received the notify*/
-                       eXosip_lock();
-                       eXosip_call_build_answer(ev->tid,200,&ans);
-                       if (ans)
-                               eXosip_call_send_answer(ev->tid,200,ans);
-                       eXosip_unlock();
-                       osip_free(from);
+                       process_notify(sal,ev);
                }else if (MSG_IS_OPTIONS(ev->request)){
                        eXosip_lock();
                        eXosip_call_build_answer(ev->tid,200,&ans);
index d693ac149acb60b0bd8889a68d91146765a18870..d19dba8c2c400f1f713afd71ccdd5742906b3952 100644 (file)
@@ -579,6 +579,28 @@ void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_m
                linphone_gtk_terminate_conference_participant(call);
 }
 
+void linphone_gtk_in_call_view_set_transfer_status(LinphoneCall *call,LinphoneCallState cstate){
+       GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
+       if (callview){
+               GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration");
+               const char *transfer_status="unknown";
+               switch(cstate){
+                       case LinphoneCallOutgoingProgress:
+                               transfer_status=_("Transfer in progress");
+                       break;
+                       case LinphoneCallConnected:
+                               transfer_status=_("Transfer done.");
+                       break;
+                       case LinphoneCallError:
+                               transfer_status=_("Transfer failed.");
+                       break;
+                       default:
+                       break;
+               }
+               gtk_label_set_text(GTK_LABEL(duration),transfer_status);
+       }
+}
+
 void linphone_gtk_draw_mute_button(GtkButton *button, gboolean active){
        g_object_set_data(G_OBJECT(button),"active",GINT_TO_POINTER(active));
        if (active){
index 7074bc87d551cde92d81edb6da1c142adbef0879..d4cafe28f359acad9ade88de52be65c4152f4e0b 100644 (file)
@@ -107,6 +107,7 @@ void linphone_gtk_in_call_view_update_duration(LinphoneCall *call);
 void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg);
 void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call);
 void linphone_gtk_in_call_view_set_paused(LinphoneCall *call);
+void linphone_gtk_in_call_view_set_transfer_status(LinphoneCall *call,LinphoneCallState cstate);
 void linphone_gtk_mute_clicked(GtkButton *button);
 void linphone_gtk_enable_mute_button(GtkButton *button, gboolean sensitive);
 void linphone_gtk_enable_hold_button(LinphoneCall *call, gboolean sensitive, gboolean holdon);
index 60c4556d7eff165493495371de577c1a613524f3..8191952684d3996edb0658dc2e9e1f2b35fafb2b 100644 (file)
@@ -63,6 +63,7 @@ static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const ch
 static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl);
 static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg);
 static void linphone_gtk_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t enabled, const char *token);
+static void linphone_gtk_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate);
 static gboolean linphone_gtk_auto_answer(LinphoneCall *call);
 static void linphone_gtk_status_icon_set_blinking(gboolean val);
 
@@ -225,6 +226,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
        vtable.refer_received=linphone_gtk_refer_received;
        vtable.buddy_info_updated=linphone_gtk_buddy_info_updated;
        vtable.call_encryption_changed=linphone_gtk_call_encryption_changed;
+       vtable.transfer_state_changed=linphone_gtk_transfer_state_changed;
 
        linphone_core_set_user_agent("Linphone", LINPHONE_VERSION);
        the_core=linphone_core_new(&vtable,config_file,factory_config_file,NULL);
@@ -1133,6 +1135,10 @@ static void linphone_gtk_call_encryption_changed(LinphoneCore *lc, LinphoneCall
        linphone_gtk_in_call_view_show_encryption(call);
 }
 
+static void linphone_gtk_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate){
+       linphone_gtk_in_call_view_set_transfer_status(call,cstate);
+}
+
 static void update_registration_status(LinphoneProxyConfig *cfg, LinphoneRegistrationState rs){
        GtkComboBox *box=GTK_COMBO_BOX(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"identities"));
        GtkTreeModel *model=gtk_combo_box_get_model(box);
index ff79974e66001f82aa539213fe3d668386be3d9d..86929b57580ebf88b3b46ec012f66b9dcc6c01da 100644 (file)
@@ -11,7 +11,7 @@
 
 Name:           linphone
 Version:        @VERSION@
-Release:        %(git describe --tags | sed 's/.*-\([0-9]*\)-g.*/\1/' || echo '1')%{?dist}
+Release:        %(git describe --tags --abbrev=40 | sed -rn 's/^.*-([0-9]+)-g[a-z0-9]{40}$/\1/p' || echo '1')%{?dist}
 Summary:        Phone anywhere in the whole world by using the Internet
 
 Group:          Applications/Communications
@@ -27,7 +27,7 @@ BuildRequires: gtk2-devel
 BuildRequires: libeXosip2-devel speex-devel gettext 
 BuildRequires: intltool gettext-devel 
 %if %{video}
-BuildRequires: ffmpeg-devel SDL-devel
+BuildRequires: ffmpeg-devel SDL-devel
 %endif
 
 %description
@@ -35,12 +35,12 @@ Linphone is a SIP compliant audio & video phone. It can be used to run calls
 over the internet. It has a gtk+ and console interface.
 
 %package devel
-Summary:        Development libraries for linphone
-Group:          Development/Libraries
-Requires:       %{name} = %{version}-%{release}
-Requires:      ortp-devel = @ORTP_VERSION@
-Requires:      mediastreamer2-devel = @MS2_VERSION@
-Requires:      glib2-devel
+Summary:       Development libraries for linphone
+Group:         Development/Libraries
+Requires:      %{name} = %{version}-%{release}
+Requires:      ortp-devel = @ORTP_VERSION@
+Requires:      mediastreamer-devel = @MS2_VERSION@
+Requires:      glib2-devel
 
 %description    devel
 Libraries and headers required to develop software with linphone.
diff --git a/oRTP b/oRTP
index 3fb614e2ed15803f2c96c223cceb5545a60f2431..04570bd7a02f9baa682c4667fbba16e8c951b62b 160000 (submodule)
--- a/oRTP
+++ b/oRTP
@@ -1 +1 @@
-Subproject commit 3fb614e2ed15803f2c96c223cceb5545a60f2431
+Subproject commit 04570bd7a02f9baa682c4667fbba16e8c951b62b