diff --git a/AUTHORS b/AUTHORS index 386427a4f..5ecb46722 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,57 +1,13 @@ -Simon MORLAT (simon dot morlat at linphone dot org) wrotes: - - main graphical program (gnome) - - RTP library (oRTP) - - SIP user-agent library (osipua) - - audio library (mediastreamer), for codec and i/o handling. - - sipomatic, the automatic sip replier, which is often used for testing. +Main authors: -Florian Wintertein < f-win at gmx dot net > wrotes the console version of linphone (linphonec) +Belledonne Communications SARL team: + Simon Morlat, Jehan Monnier, Guillaume Beraudo + +Contributors: + +Florian Wintertein < f-win at gmx dot net > originaly wrotes the console version of linphone (linphonec) in console/ directory. -Aymeric Moizard (jack at atosc dot org) wrotes: - - the oSIP SIP transactionnal stack (not part of linphone) - - some piece of code of the osip distribution have been reused in osipua - - presence information support in osipua - - and contributes to some parts of osipua (digest authentification) -For more information about oSIP, see http://osip.atosc.org - -Sharath Udupa is developing the media_api, a usefull library to manage audio and video streams -for basic calls as well as conference. - Sandro Santilli < strk at keybit dot net > wrote enhancements in the -console interface (readline, new commands) and some bug fixes for -the core api. +console interface (readline, new commands). -Bryan Ogawa ( bko at cisco dot com ) sent a patch that made the linphone-0.7.1 release. -This patch fixed several issues in the SIP part while working with proxies. - -Koichi KUNITAKE < kunitake at linux-ipv6 dot org > has contributed a patch bringing -full IPv6 support. - -The Speex codec is a project from Jean Marc Valin. See http://speex.sourceforge.net for more -information. - -The GSM library was written by : - Jutta Degener and Carsten Bormann,Technische Universitaet Berlin. - -The LPC10-1.5 library was written by: - Andy Fingerhut - Applied Research Laboratory <-- this line is optional if - Washington University, Campus Box 1045/Bryan 509 you have limited space - One Brookings Drive - Saint Louis, MO 63130-4899 - jaf@arl.wustl.edu - http://www.arl.wustl.edu/~jaf/ - - See text files in gsmlib and lpc10-1.5 directories for further information. - -G711 library has some code from the alsa-lib on http://www.alsa-project.org - -Icons by Pablo Marcelo Moia. - -Translations: -fr: Simon Morlat -en: Simon Morlat and Delphine Perreau -it: Alberto Zanoni -de: Jean-Jacques Sarton -es: Jesús Benítez diff --git a/NEWS b/NEWS index ab77e8202..7f8aac530 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -linphone-3.4.0 -- XXXXX +linphone-3.4.0 -- February 2nd, 2011 * implement multiple calls feature: - call hold (with possibility to play a music file) - call resume diff --git a/build/android/Android.mk b/build/android/Android.mk index a292a0ec0..48a4c75be 100755 --- a/build/android/Android.mk +++ b/build/android/Android.mk @@ -53,7 +53,7 @@ LOCAL_CFLAGS += \ -D_BYTE_ORDER=_LITTLE_ENDIAN \ -DORTP_INET6 \ -DENABLE_TRACE \ - -DLINPHONE_VERSION=\"Linphone-3.3.x\" \ + -DLINPHONE_VERSION=\"3.4.0\" \ -DLINPHONE_PLUGINS_DIR=\"\\tmp\" \ -DLOG_DOMAIN=\"Linphone\" diff --git a/configure.ac b/configure.ac index 8db4ab8a3..3e0eefcc9 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT([linphone],[3.3.99.10],[linphone-developers@nongnu.org]) +AC_INIT([linphone],[3.4.0],[linphone-developers@nongnu.org]) AC_CANONICAL_SYSTEM AC_CONFIG_SRCDIR([coreapi/linphonecore.c]) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index f92047913..62cf00835 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -303,18 +303,30 @@ static void call_accepted(SalOp *op){ ms_free(msg); } linphone_core_update_streams (lc,call,md); - linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); + linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote"); }else{ - if (lc->vtable.display_status){ - lc->vtable.display_status(lc,_("Call answered - connected.")); - } if (call->state==LinphoneCallStreamsRunning){ /*media was running before, the remote as acceted a call modification (that is a reinvite made by us. We must notify the application this reinvite was accepted*/ linphone_call_set_state(call, LinphoneCallUpdated, "Call updated"); + }else{ + if (call->state==LinphoneCallResuming){ + if (lc->vtable.display_status){ + lc->vtable.display_status(lc,_("Call resumed.")); + } + }else{ + if (lc->vtable.display_status){ + char *tmp=linphone_call_get_remote_address_as_string (call); + char *msg=ms_strdup_printf(_("Call answered by %s."),tmp); + lc->vtable.display_status(lc,msg); + ms_free(tmp); + ms_free(msg); + } + } } linphone_core_update_streams (lc,call,md); linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running"); + lc->current_call=call; } }else{ /*send a bye*/ @@ -349,6 +361,7 @@ static void call_ack(SalOp *op){ } } + /* this callback is called when an incoming re-INVITE modifies the session*/ static void call_updating(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); @@ -360,32 +373,22 @@ static void call_updating(SalOp *op){ if (md && !sal_media_description_empty(md)) { - if ((call->state==LinphoneCallPausedByRemote || call->state==LinphoneCallPaused) && - sal_media_description_has_dir(md,SalStreamSendRecv) && strcmp(md->addr,"0.0.0.0")!=0){ - /*make sure we can be resumed */ - if (lc->current_call!=NULL && lc->current_call!=call){ - ms_warning("Attempt to be resumed but already in call with somebody else!"); - /*we are actively running another call, reject with a busy*/ - sal_call_decline (op,SalReasonBusy,NULL); - return; + if (sal_media_description_has_dir(call->localdesc,SalStreamSendRecv)){ + ms_message("Our local status is SalStreamSendRecv"); + if (sal_media_description_has_dir (md,SalStreamRecvOnly) || sal_media_description_has_dir(md,SalStreamInactive)){ + /* we are being paused */ + if(lc->vtable.display_status) + lc->vtable.display_status(lc,_("We are being paused...")); + linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote"); + }else if (!sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv) && sal_media_description_has_dir(md,SalStreamSendRecv)){ + if(lc->vtable.display_status) + lc->vtable.display_status(lc,_("We have been resumed...")); + linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)"); + lc->current_call=call; + }else{ + prevstate=call->state; + linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote"); } - if(lc->vtable.display_status) - lc->vtable.display_status(lc,_("We have been resumed...")); - linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)"); - } - else if(call->state==LinphoneCallStreamsRunning && - ( sal_media_description_has_dir(md,SalStreamRecvOnly) - || sal_media_description_has_dir(md,SalStreamInactive) - || strcmp(md->addr,"0.0.0.0")==0)){ - if(lc->vtable.display_status) - lc->vtable.display_status(lc,_("We are being paused...")); - linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote"); - if (lc->current_call!=call){ - ms_error("Inconsitency detected: current call is %p but call %p is being paused !",lc->current_call,call); - } - }else{ - prevstate=call->state; - linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote"); } /*accept the modification (sends a 200Ok)*/ sal_call_accept(op); diff --git a/coreapi/ec-calibrator.c b/coreapi/ec-calibrator.c index df56ff686..4c8a37586 100644 --- a/coreapi/ec-calibrator.c +++ b/coreapi/ec-calibrator.c @@ -110,18 +110,18 @@ static void ecc_play_tones(EcCalibrator *ecc){ /*play an initial tone to startup the audio playback/capture*/ ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); - sleep(2); + ms_sleep(2); ms_filter_set_notify_callback(ecc->gen,on_tone_sent,ecc); tone.frequency=2000; tone.duration=100; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); - sleep(1); + ms_sleep(1); ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); - sleep(1); + ms_sleep(1); ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); - sleep(1); + ms_sleep(1); if (ecc->sent_count==3 && ecc->recv_count==3){ int delay=ecc->acc/3; diff --git a/coreapi/help/doxygen.dox b/coreapi/help/doxygen.dox index 8707785b2..32ed3da1a 100644 --- a/coreapi/help/doxygen.dox +++ b/coreapi/help/doxygen.dox @@ -34,6 +34,13 @@ /** * @defgroup call_control Placing and receiving calls + * + * The #LinphoneCall object represents an incoming or outgoing call managed by the #LinphoneCore. + * Outgoing calls can be created using linphone_core_invite() or linphone_core_invite_address(), while incoming calls are notified to the application + * through the LinphoneCoreVTable::call_state_changed callback. + * + * See the basic call \ref basic_call_tutorials "tutorial". + * **/ /** diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index a92609637..a8838af10 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mediastreamer2/msequalizer.h" #include "mediastreamer2/msfileplayer.h" #include "mediastreamer2/msjpegwriter.h" +#include "mediastreamer2/mseventqueue.h" #ifdef VIDEO_ENABLED static MSWebCam *get_nowebcam_device(){ @@ -473,6 +474,20 @@ int linphone_call_get_duration(const LinphoneCall *call){ return time(NULL)-call->media_start_time; } +/** + * Returns the call object this call is replacing, if any. + * Call replacement can occur during call transfers. + * By default, the core automatically terminates the replaced call and accept the new one. + * This function allows the application to know whether a new incoming call is a one that replaces another one. +**/ +LinphoneCall *linphone_call_get_replaced_call(LinphoneCall *call){ + SalOp *op=sal_call_get_replaces(call->op); + if (op){ + return (LinphoneCall*)sal_op_get_user_pointer(op); + } + return NULL; +} + /** * Indicate whether camera input should be sent to remote end. **/ @@ -505,21 +520,21 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){ } /** - * + * Returns TRUE if camera pictures are sent to the remote party. **/ bool_t linphone_call_camera_enabled (const LinphoneCall *call){ return call->camera_active; } /** - * + * Enable video stream. **/ void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){ cp->has_video=enabled; } /** - * + * Returns whether video is enabled. **/ bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){ return cp->has_video; @@ -969,6 +984,7 @@ void linphone_call_stop_media_streams(LinphoneCall *call){ video_stream_stop(call->videostream); call->videostream=NULL; } + ms_event_queue_skip(call->core->msevq); #endif if (call->audio_profile){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 72bc5e2d0..7afdf85fa 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -49,6 +49,8 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val); #define LOCAL_RING "rings/oldphone.wav" /* same for remote ring (ringback)*/ #define REMOTE_RING "ringback.wav" +#define HOLD_MUSIC "rings/toy-mono.wav" + extern SalCallbacks linphone_sal_callbacks; @@ -452,6 +454,8 @@ static void sound_config_read(LinphoneCore *lc) tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING; } linphone_core_set_ringback(lc,tmpbuf); + + linphone_core_set_play_file(lc,lp_config_get_string(lc->config,"sound","hold_music",PACKAGE_SOUND_DIR "/" HOLD_MUSIC)); check_sound_device(lc); lc->sound_conf.latency=0; @@ -571,6 +575,7 @@ static void sip_config_read(LinphoneCore *lc) lc->sip_conf.keepalive_period=lp_config_get_int(lc->config,"sip","keepalive_period",10000); sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period); sal_use_one_matching_codec_policy(lc->sal,lp_config_get_int(lc->config,"sip","only_one_codec",0)); + sal_use_double_registrations(lc->sal,lp_config_get_int(lc->config,"sip","use_double_registrations",1)); } static void rtp_config_read(LinphoneCore *lc) @@ -2199,7 +2204,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Modifying call parameters...")); sal_call_set_local_media_description (call->op,call->localdesc); - err=sal_call_update(call->op); + err=sal_call_update(call->op,"Media parameters update"); }else{ #ifdef VIDEO_ENABLED if (call->videostream!=NULL){ @@ -2426,13 +2431,23 @@ LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc) int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call) { LinphoneCall *call = the_call; + const char *subject=NULL; if (call->state!=LinphoneCallStreamsRunning && call->state!=LinphoneCallPausedByRemote){ ms_warning("Cannot pause this call, it is not active."); return -1; } - - if (sal_call_hold(call->op,TRUE) != 0) + if (sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv)){ + sal_media_description_set_dir(call->localdesc,SalStreamSendOnly); + subject="Call on hold"; + }else if (sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly)){ + sal_media_description_set_dir(call->localdesc,SalStreamSendOnly); + subject="Call on hold for me too"; + }else{ + ms_error("No reason to pause this call, it is already paused or inactive."); + return -1; + } + if (sal_call_update(call->op,subject) != 0) { if (lc->vtable.display_warning) lc->vtable.display_warning(lc,_("Could not pause the call")); @@ -2482,14 +2497,14 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call) return -1; } ms_message("Resuming call %p",call); - if(sal_call_hold(call->op,FALSE) != 0){ + sal_media_description_set_dir(call->localdesc,SalStreamSendRecv); + if(sal_call_update(call->op,"Call resuming") != 0){ return -1; } linphone_call_set_state (call,LinphoneCallResuming,"Resuming"); snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",linphone_call_get_remote_address_as_string(call)); if (lc->vtable.display_status) lc->vtable.display_status(lc,temp); - lc->current_call=call; return 0; } @@ -3386,6 +3401,10 @@ void linphone_core_use_preview_window(LinphoneCore *lc, bool_t yesno){ } static MSVideoSizeDef supported_resolutions[]={ +#ifdef ENABLE_HD + { {MS_VIDEO_SIZE_1080P_W,MS_VIDEO_SIZE_1080P_H} , "1080p" }, + { {MS_VIDEO_SIZE_720P_W,MS_VIDEO_SIZE_720P_H} , "1080p" }, +#endif { {MS_VIDEO_SIZE_SVGA_W,MS_VIDEO_SIZE_SVGA_H} , "svga" }, { {MS_VIDEO_SIZE_4CIF_W,MS_VIDEO_SIZE_4CIF_H} , "4cif" }, { {MS_VIDEO_SIZE_VGA_W,MS_VIDEO_SIZE_VGA_H} , "vga" }, @@ -3696,7 +3715,7 @@ void sip_config_uninit(LinphoneCore *lc) linphone_proxy_config_write_to_config_file(lc->config,NULL,i); for (i=0;i<20;i++){ - linphone_core_iterate(lc); + sal_iterate(lc->sal); #ifndef WIN32 usleep(100000); #else diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 04be47483..82709208d 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -185,6 +185,7 @@ void linphone_call_params_destroy(LinphoneCallParams *cp); /** * Enum describing failure reasons. + * @ingroup initializing **/ enum _LinphoneReason{ LinphoneReasonNone, @@ -203,8 +204,13 @@ const char *linphone_reason_to_string(LinphoneReason err); struct _LinphoneCall; typedef struct _LinphoneCall LinphoneCall; +/** + * LinphoneCallState enum represents the different state a call can reach into. + * The application is notified of state changes through the LinphoneCoreVTable::call_state_changed callback. + * @ingroup call_control +**/ typedef enum _LinphoneCallState{ - LinphoneCallIdle, + LinphoneCallIdle, /**payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE); result->proto=local_offer->proto; result->type=local_offer->type; - result->dir=compute_dir(local_offer->dir,remote_answer->dir); + result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir); if (result->payloads && !only_telephone_event(result->payloads)){ strcpy(result->addr,remote_answer->addr); @@ -150,13 +174,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap, result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec); result->proto=local_cap->proto; result->type=local_cap->type; - if (remote_offer->dir==SalStreamSendOnly) - result->dir=SalStreamRecvOnly; - else if (remote_offer->dir==SalStreamRecvOnly){ - result->dir=SalStreamSendOnly; - }else if (remote_offer->dir==SalStreamInactive){ - result->dir=SalStreamInactive; - }else result->dir=SalStreamSendRecv; + result->dir=compute_dir_incoming(local_cap->dir,remote_offer->dir); if (result->payloads && !only_telephone_event(result->payloads)){ strcpy(result->addr,local_cap->addr); result->port=local_cap->port; diff --git a/coreapi/sal.c b/coreapi/sal.c index 6f80436c6..ec8a6fc6d 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -79,19 +79,41 @@ void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_ } } -bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){ + +static bool_t is_null_address(const char *addr){ + return strcmp(addr,"0.0.0.0")==0 || strcmp(addr,"::0")==0; +} + +/*check for the presence of at least one stream with requested direction */ +static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){ int i; - bool_t found=FALSE; /* we are looking for at least one stream with requested direction, inactive streams are ignored*/ for(i=0;instreams;++i){ const SalStreamDescription *ss=&md->streams[i]; - if (ss->dir==stream_dir) found=TRUE; - else{ - if (ss->dir!=SalStreamInactive) return FALSE; - } + if (ss->dir==stream_dir) return TRUE; + if (stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->addr))) + return TRUE; } - return found; + return FALSE; +} + +bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){ + if (stream_dir==SalStreamRecvOnly){ + if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv)) return FALSE; + else return TRUE; + }else if (stream_dir==SalStreamSendOnly){ + if (has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv)) return FALSE; + else return TRUE; + }else if (stream_dir==SalStreamSendRecv){ + return has_dir(md,SalStreamSendRecv); + }else{ + /*SalStreamInactive*/ + if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv) || has_dir(md,SalStreamRecvOnly)) + return FALSE; + else return TRUE; + } + return FALSE; } /* diff --git a/coreapi/sal.h b/coreapi/sal.h index f20555b0a..24cc8582a 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -257,6 +257,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_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec); int sal_iterate(Sal *sal); MSList * sal_get_pending_auths(Sal *sal); @@ -292,8 +293,7 @@ int sal_call_notify_ringing(SalOp *h, bool_t early_media); /*accept an incoming call or, during a call accept a reINVITE*/ int sal_call_accept(SalOp*h); int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/); -int sal_call_hold(SalOp *h, bool_t holdon); -int sal_call_update(SalOp *h); +int sal_call_update(SalOp *h, const char *subject); SalMediaDescription * sal_call_get_final_media_description(SalOp *h); int sal_call_refer(SalOp *h, const char *refer_to); int sal_call_refer_with_replaces(SalOp *h, SalOp *other_call_h); diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c index 4d1de476a..5c65cf80a 100644 --- a/coreapi/sal_eXosip2.c +++ b/coreapi/sal_eXosip2.c @@ -264,6 +264,7 @@ Sal * sal_init(){ eXosip_init(); sal=ms_new0(Sal,1); sal->keepalive_period=30; + sal->double_reg=TRUE; return sal; } @@ -397,6 +398,10 @@ MSList *sal_get_pending_auths(Sal *sal){ return ms_list_copy(sal->pending_auths); } +void sal_use_double_registrations(Sal *ctx, bool_t enabled){ + ctx->double_reg=enabled; +} + static int extract_received_rport(osip_message_t *msg, const char **received, int *rportval){ osip_via_t *via=NULL; osip_generic_param_t *param=NULL; @@ -840,6 +845,9 @@ static SalOp *find_op(Sal *sal, eXosip_event_t *ev){ if (ev->sid>0){ return sal_find_out_subscribe(sal,ev->sid); } + if (ev->nid>0){ + return sal_find_in_subscribe(sal,ev->nid); + } if (ev->response) return sal_find_other(sal,ev->response); return NULL; } @@ -1556,6 +1564,9 @@ static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *ori char *tmp; 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); @@ -1787,6 +1798,7 @@ static bool_t process_event(Sal *sal, eXosip_event_t *ev){ other_request_reply(sal,ev); break; case EXOSIP_MESSAGE_REQUESTFAILURE: + case EXOSIP_NOTIFICATION_REQUESTFAILURE: if (ev->response) { switch (ev->response->status_code) { case 407: @@ -2003,37 +2015,8 @@ int sal_address_get_port_int(const SalAddress *uri) { } } -/* - * Send a re-Invite used to hold the current call -*/ -int sal_call_hold(SalOp *h, bool_t holdon) -{ - int err=0; - - osip_message_t *reinvite=NULL; - if(eXosip_call_build_request(h->did,"INVITE",&reinvite) != OSIP_SUCCESS || reinvite==NULL) - return -1; - osip_message_set_subject(reinvite,holdon ? "Phone call hold" : "Phone call resume" ); - osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO"); - if (h->base.root->session_expires!=0){ - osip_message_set_header(reinvite, "Session-expires", "200"); - osip_message_set_supported(reinvite, "timer"); - } - //add something to say that the distant sip phone will be in sendonly/sendrecv mode - if (h->base.local_media){ - h->sdp_offering=TRUE; - sal_media_description_set_dir(h->base.local_media, holdon ? SalStreamSendOnly : SalStreamSendRecv); - set_sdp_from_desc(reinvite,h->base.local_media); - }else h->sdp_offering=FALSE; - eXosip_lock(); - err = eXosip_call_send_request(h->did, reinvite); - eXosip_unlock(); - - return err; -} - /* sends a reinvite. Local media description may have changed by application since call establishment*/ -int sal_call_update(SalOp *h){ +int sal_call_update(SalOp *h, const char *subject){ int err=0; osip_message_t *reinvite=NULL; @@ -2043,7 +2026,7 @@ int sal_call_update(SalOp *h){ return -1; } eXosip_unlock(); - osip_message_set_subject(reinvite,osip_strdup("Phone call parameters updated")); + osip_message_set_subject(reinvite,subject); osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO"); if (h->base.root->session_expires!=0){ osip_message_set_header(reinvite, "Session-expires", "200"); diff --git a/coreapi/sal_eXosip2.h b/coreapi/sal_eXosip2.h index 7d50ae823..4db203362 100644 --- a/coreapi/sal_eXosip2.h +++ b/coreapi/sal_eXosip2.h @@ -41,6 +41,7 @@ struct Sal{ int keepalive_period; void *up; bool_t one_matching_codec; + bool_t double_reg; }; struct SalOp{ @@ -78,6 +79,7 @@ void sal_exosip_subscription_closed(Sal *sal,eXosip_event_t *ev); void sal_exosip_in_subscription_closed(Sal *sal, eXosip_event_t *ev); SalOp * sal_find_out_subscribe(Sal *sal, int sid); +SalOp * sal_find_in_subscribe(Sal *sal, int nid); void sal_exosip_fix_route(SalOp *op); void _osip_list_set_empty(osip_list_t *l, void (*freefunc)(void*)); diff --git a/coreapi/sal_eXosip2_presence.c b/coreapi/sal_eXosip2_presence.c index 154c8d07e..52b1485a9 100644 --- a/coreapi/sal_eXosip2_presence.c +++ b/coreapi/sal_eXosip2_presence.c @@ -50,7 +50,7 @@ void sal_remove_out_subscribe(Sal *sal, SalOp *op){ sal->out_subscribes=ms_list_remove(sal->out_subscribes,op); } -static SalOp * sal_find_in_subscribe(Sal *sal, int nid){ +SalOp * sal_find_in_subscribe(Sal *sal, int nid){ const MSList *elem; SalOp *op; for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){ @@ -569,6 +569,7 @@ int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_ if (msg!=NULL){ const char *identity=sal_op_get_contact(op); if (identity==NULL) identity=sal_op_get_to(op); + _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free); osip_message_set_contact(msg,identity); add_presence_body(msg,status); eXosip_insubscription_send_request(op->did,msg); diff --git a/gtk/incall_view.c b/gtk/incall_view.c index 3941bfe72..9a4861a5d 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -201,6 +201,7 @@ void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call, bool_t with_paus GtkWidget *animation=linphone_gtk_get_widget(callview,"in_call_animation"); GdkPixbufAnimation *pbuf=create_pixbuf_animation("calling_anim.gif"); GtkWidget *answer_button; + GtkWidget *image; gtk_label_set_markup(GTK_LABEL(status),_("Incoming call")); gtk_widget_show_all(linphone_gtk_get_widget(callview,"answer_decline_panel")); @@ -209,14 +210,17 @@ void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call, bool_t with_paus display_peer_name_in_label(callee,linphone_call_get_remote_address (call)); answer_button=linphone_gtk_get_widget(callview,"accept_call"); - gtk_button_set_image(GTK_BUTTON(answer_button), - create_pixmap (linphone_gtk_get_ui_config("start_call_icon","startcall-green.png"))); + image=create_pixmap (linphone_gtk_get_ui_config("start_call_icon","startcall-green.png")); if (with_pause){ gtk_button_set_label(GTK_BUTTON(answer_button), _("Pause all calls\nand answer")); }else gtk_button_set_label(GTK_BUTTON(answer_button),_("Answer")); - gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(callview,"decline_call")), - create_pixmap (linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png"))); + gtk_button_set_image(GTK_BUTTON(answer_button),image); + gtk_widget_show(image); + + image=create_pixmap (linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png")); + gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(callview,"decline_call")),image); + gtk_widget_show(image); if (pbuf!=NULL){ gtk_image_set_from_animation(GTK_IMAGE(animation),pbuf); diff --git a/gtk/main.c b/gtk/main.c index 643f948d9..77689b397 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1446,6 +1446,7 @@ int main(int argc, char *argv[]){ settings=gtk_settings_get_default(); g_type_class_unref (g_type_class_ref (GTK_TYPE_IMAGE_MENU_ITEM)); + g_type_class_unref (g_type_class_ref (GTK_TYPE_BUTTON)); g_object_set(settings, "gtk-menu-images", TRUE, NULL); g_object_set(settings, "gtk-button-images", TRUE, NULL); #ifdef WIN32 diff --git a/java/common/org/linphone/core/LinphoneCall.java b/java/common/org/linphone/core/LinphoneCall.java index 66418a930..545793eee 100644 --- a/java/common/org/linphone/core/LinphoneCall.java +++ b/java/common/org/linphone/core/LinphoneCall.java @@ -110,7 +110,11 @@ public interface LinphoneCall { * The remote accepted the call update initiated by us */ public static final State CallUpdated = new State(17, "CallUpdated"); - + + /** + * The call object is now released. + */ + public static final State CallReleased = new State(18,"CallReleased"); private State(int value,String stringValue) { mValue = value; @@ -174,5 +178,9 @@ public interface LinphoneCall { * @return true if echo limiter is enabled. */ public boolean isEchoLimiterEnabled(); - + /** + * Returns the object associated to a call this one is replacing. + * Call replacement can occur during transfer scenarios. + */ + public LinphoneCall getReplacedCall(); } diff --git a/linphone-deps.filelist b/linphone-deps.filelist index 1cfc61b07..19ea6ecde 100755 --- a/linphone-deps.filelist +++ b/linphone-deps.filelist @@ -1,10 +1,10 @@ ./bin/avcodec-52.dll ./bin/avutil-50.dll -./bin/libeXosip2-4.dll +./bin/libeXosip2-6.dll ./bin/libogg.dll ./bin/libtheora.dll ./bin/libxml2-2.dll -./bin/libosip2-4.dll -./bin/libosipparser2-4.dll +./bin/libosip2-6.dll +./bin/libosipparser2-6.dll ./bin/swscale-0.dll diff --git a/mediastreamer2 b/mediastreamer2 index 47f19a376..0fc8db730 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 47f19a376ee7f5bfea93714bc094a8f4ffcebce4 +Subproject commit 0fc8db73037bab398ece764874192d1d7df6af28 diff --git a/oRTP b/oRTP index c8b487f32..6a26fdcbe 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit c8b487f32fe225f8b1961754db9140eb282a0d28 +Subproject commit 6a26fdcbe2e19bad50f4c010bdd173810140ada8 diff --git a/share/Makefile.am b/share/Makefile.am index 6def02724..a96607b71 100644 --- a/share/Makefile.am +++ b/share/Makefile.am @@ -8,7 +8,7 @@ LINPHONE_RINGS=rings/orig.wav \ rings/oldphone-mono-30s.caf \ rings/rock.wav \ rings/bigben.wav \ - rings/toy.wav \ + rings/toy-mono.wav \ rings/sweet.wav \ rings/synth.wav \ rings/tapping.wav diff --git a/share/rings/toy-mono.wav b/share/rings/toy-mono.wav new file mode 100644 index 000000000..a6e0093a5 Binary files /dev/null and b/share/rings/toy-mono.wav differ diff --git a/share/rings/toy.wav b/share/rings/toy.wav deleted file mode 100644 index 7a5198492..000000000 Binary files a/share/rings/toy.wav and /dev/null differ