diff --git a/README b/README index 05b0b1dcb..658f07ae0 100644 --- a/README +++ b/README @@ -16,7 +16,7 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol. - libswscale (part of ffmpeg too) for better scaling performance - theora (optional) + if you want uPnP support: - - libupnp + - libupnp (version 1.6 branch (not patched with 18-url-upnpstrings.patch)) with their corresponding -dev or -devel package if you don't use source packages. diff --git a/README.macos b/README.macos index bb78575bf..dd39c2f6e 100644 --- a/README.macos +++ b/README.macos @@ -99,4 +99,20 @@ For a better appearance, you can install the gtk-quartz-engine (a gtk theme) tha Generate a new bundle to have it included. +libiconv hack +************* + +The Makefile.am rules used to generate the bundle fetch a libiconv.2.dylib from a linphone download page. +This library adds some additional symbols so that dependencies requiring the iconv from /usr/lib and the ones requiring from the bundle are both satisfied. +In case this library needs to generated, here are the commands: + $ wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz + $ cd libiconv-1.14 + $ patch -p1 < ../linphone/build/macos/libiconv-macos.patch + $ ./configure --prefix=/opt/local --disable-static 'CFLAGS=-arch i386 -arch x86_64 -mmacosx-version-min=10.5' 'LDFLAGS=-arch i386 -arch x86_64 -mmacosx-version-min=10.5' CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5" && make + $ make install DESTDIR=/tmp + +The resulted library can be found in /tmp/opt/local/lib + + + diff --git a/build/macos/libiconv-macos.patch b/build/macos/libiconv-macos.patch new file mode 100644 index 000000000..e0654843f --- /dev/null +++ b/build/macos/libiconv-macos.patch @@ -0,0 +1,26 @@ +--- libiconv-1.14.orig/lib/iconv.c 2013-03-14 16:30:50.000000000 +0100 ++++ libiconv-1.14/lib/iconv.c 2013-03-15 10:24:38.000000000 +0100 +@@ -607,4 +607,23 @@ + strong_alias (libiconv_close, iconv_close) + #endif + ++#undef iconv_open ++#undef iconv ++#undef iconv_close ++ ++LIBICONV_DLL_EXPORTED iconv_t iconv_open (const char* tocode, const char* fromcode){ ++ return libiconv_open(tocode,fromcode); ++} ++ ++LIBICONV_DLL_EXPORTED size_t iconv (iconv_t icd, ++ ICONV_CONST char* * inbuf, size_t *inbytesleft, ++ char* * outbuf, size_t *outbytesleft){ ++ return libiconv(icd,inbuf,inbytesleft,outbuf,outbytesleft); ++} ++ ++LIBICONV_DLL_EXPORTED int iconv_close (iconv_t icd){ ++ return libiconv_close(icd); ++} ++ ++ + #endif diff --git a/configure.ac b/configure.ac index ae2d59386..7bc526bbb 100644 --- a/configure.ac +++ b/configure.ac @@ -183,7 +183,12 @@ AC_ARG_ENABLE(upnp, ) if test "$build_upnp" != "false" ; then - PKG_CHECK_MODULES([LIBUPNP], [libupnp], [build_upnp=true], + PKG_CHECK_MODULES([LIBUPNP], [libupnp], + [if pkg-config --atleast-version=1.6 "libupnp < 1.7"; then + build_upnp=true + else + AC_MSG_ERROR([libupnp >= 1.6 < 1.5 required.]) + fi], [if test "$build_upnp" == "true" ; then AC_MSG_ERROR([libupnp not found.]) else @@ -439,19 +444,6 @@ fi dnl setup flags for exosip library LP_SETUP_EXOSIP -dnl check exosip support of DSCP in exosip -AC_MSG_CHECKING([for DSCP support in exosip]) -AC_TRY_COMPILE([#include ], - [int dscp=0;eXosip_set_option(EXOSIP_OPT_SET_DSCP,&dscp);], - has_exosip_dscp=yes, - has_exosip_dscp=no -) -AC_MSG_RESULT($has_exosip_dscp) -if test "$has_exosip_dscp" = "yes" ; then - AC_DEFINE( HAVE_EXOSIP_DSCP, 1, [Define if exosip dscp available] ) -fi - - if test "$console_ui" = "true" ; then dnl check gnu readline LP_CHECK_READLINE @@ -679,7 +671,6 @@ AC_ARG_ENABLE(msg-storage, [enable_msg_storage=auto] ) -echo "enable_msg_storage = $enable_msg_storage" AM_CONDITIONAL(BUILD_MSG_STORAGE, test x$enable_msg_storage = xtrue) if test x$enable_msg_storage != xfalse; then diff --git a/console/commands.c b/console/commands.c index 22b09a5a6..67b2446f4 100644 --- a/console/commands.c +++ b/console/commands.c @@ -2510,13 +2510,15 @@ static int lpc_cmd_camera(LinphoneCore *lc, char *args){ const LinphoneCallParams *cp=linphone_call_get_current_params (call); if (args){ linphone_call_enable_camera(call,activated); - if ((activated && !linphone_call_params_video_enabled (cp))){ - /*update the call to add the video stream*/ - LinphoneCallParams *ncp=linphone_call_params_copy(cp); - linphone_call_params_enable_video(ncp,TRUE); - linphone_core_update_call(lc,call,ncp); - linphone_call_params_destroy (ncp); - linphonec_out("Trying to bring up video stream...\n"); + if (linphone_call_get_state(call)==LinphoneCallStreamsRunning){ + if ((activated && !linphone_call_params_video_enabled (cp))){ + /*update the call to add the video stream*/ + LinphoneCallParams *ncp=linphone_call_params_copy(cp); + linphone_call_params_enable_video(ncp,TRUE); + linphone_core_update_call(lc,call,ncp); + linphone_call_params_destroy (ncp); + linphonec_out("Trying to bring up video stream...\n"); + } } } if (linphone_call_camera_enabled (call)) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index dd5ab7edc..8a6ea631c 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -151,7 +151,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia bool_t send_ringbacktone=FALSE; if (call->audiostream==NULL){ - /*this happens after pausing the call locally. The streams is destroyed and then we wait the 200Ok to recreate it*/ + /*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/ linphone_call_init_media_streams (call); } if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){ @@ -163,6 +163,9 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia } linphone_call_start_media_streams(call,all_muted,send_ringbacktone); } + if (call->state==LinphoneCallPausing && call->paused_by_app && ms_list_size(lc->calls)==1){ + linphone_core_play_named_tone(lc,LinphoneToneCallOnHold); + } } #if 0 static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){ @@ -654,6 +657,7 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de } else if (sr == SalReasonBusy) { call->reason=LinphoneReasonBusy; linphone_call_set_state(call,LinphoneCallError,"User is busy."); + linphone_core_play_named_tone(lc,LinphoneToneBusy); } else { linphone_call_set_state(call,LinphoneCallError,msg); } @@ -809,7 +813,7 @@ 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); + _linphone_core_pause_call(lc,call); call->was_automatically_paused=TRUE; /*then we will start the refered when the pause is accepted, in order to serialize transactions within the dialog. * Indeed we need to avoid to send a NOTIFY to inform about of state of the refered call while the pause isn't completed. diff --git a/coreapi/conference.c b/coreapi/conference.c index 16be62613..c9d51b151 100644 --- a/coreapi/conference.c +++ b/coreapi/conference.c @@ -240,7 +240,7 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a err=linphone_core_update_call(lc,call,&call->params); } else{ ms_message("Pausing call to actually remove from conference"); - err=linphone_core_pause_call(lc,call); + err=_linphone_core_pause_call(lc,call); } return err; @@ -339,7 +339,7 @@ int linphone_core_enter_conference(LinphoneCore *lc){ return -1; } if (lc->current_call != NULL) { - linphone_core_pause_call(lc, lc->current_call); + _linphone_core_pause_call(lc, lc->current_call); } LinphoneConference *conf=&lc->conf_ctx; if (conf->local_participant==NULL) add_local_endpoint(conf,lc); diff --git a/coreapi/ec-calibrator.c b/coreapi/ec-calibrator.c index 8efbabb1b..e19559fc4 100644 --- a/coreapi/ec-calibrator.c +++ b/coreapi/ec-calibrator.c @@ -133,6 +133,9 @@ static void on_tone_received(void *data, MSFilter *f, unsigned int event_id, voi static void ecc_play_tones(EcCalibrator *ecc){ MSDtmfGenCustomTone tone; MSToneDetectorDef expected_tone; + + memset(&tone,0,sizeof(tone)); + memset(&expected_tone,0,sizeof(expected_tone)); ms_filter_set_notify_callback(ecc->det,on_tone_received,ecc); @@ -161,7 +164,7 @@ static void ecc_play_tones(EcCalibrator *ecc){ /*play an initial tone to startup the audio playback/capture*/ - tone.frequency=140; + tone.frequencies[0]=140; tone.duration=1000; tone.amplitude=0.5; @@ -172,17 +175,17 @@ static void ecc_play_tones(EcCalibrator *ecc){ /* play the three tones*/ - tone.frequency=2000; + tone.frequencies[0]=2000; tone.duration=100; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); ms_usleep(300000); - tone.frequency=2300; + tone.frequencies[0]=2300; tone.duration=100; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); ms_usleep(300000); - tone.frequency=2500; + tone.frequencies[0]=2500; tone.duration=100; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); ms_sleep(1); diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index dba7381c7..e9640701f 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -254,6 +254,14 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * l=ms_list_append(l,pt); md->streams[0].payloads=l; + // if ZRTP is enabled, put the hello hash into the audiostream's desc + if (call->audiostream && call->audiostream->ms.zrtp_context!=NULL){ + ortp_zrtp_get_hello_hash(call->audiostream->ms.zrtp_context, + md->streams[0].zrtp_hello_hash, + sizeof(md->streams[0].zrtp_hello_hash)); + ms_message("Audio stream zrtp hash: %s", md->streams[0].zrtp_hello_hash); + } + if (call->params.has_video){ md->n_active_streams++; md->streams[1].rtp_port=call->video_port; @@ -262,6 +270,13 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * md->streams[1].type=SalVideo; l=make_codec_list(lc,lc->codecs_conf.video_codecs,0,NULL,-1); md->streams[1].payloads=l; + // if ZRTP is enabled, put the hello hash into the audiostream's desc + if (call->videostream->ms.zrtp_context!=NULL){ + ortp_zrtp_get_hello_hash(call->videostream->ms.zrtp_context, + md->streams[1].zrtp_hello_hash, + sizeof(md->streams[1].zrtp_hello_hash)); + ms_message("Video stream zrtp hash: %s", md->streams[1].zrtp_hello_hash); + } } if (md->n_total_streams < md->n_active_streams) md->n_total_streams = md->n_active_streams; @@ -1294,6 +1309,20 @@ void linphone_call_init_video_stream(LinphoneCall *call){ void linphone_call_init_media_streams(LinphoneCall *call){ linphone_call_init_audio_stream(call); linphone_call_init_video_stream(call); + + // moved from linphone_call_start_media_streams, because ZRTP needs to be + // at least partially initialized so that the SDP can contain 'zrtp-hash' + if (call->params.media_encryption==LinphoneMediaEncryptionZRTP) { + OrtpZrtpParams params; + /*will be set later when zrtp is activated*/ + call->current_params.media_encryption=LinphoneMediaEncryptionNone; + + params.zid_file=call->core->zrtp_secrets_cache; + audio_stream_enable_zrtp(call->audiostream,¶ms); + } else if (call->params.media_encryption==LinphoneMediaEncryptionSRTP){ + call->current_params.media_encryption=linphone_call_are_all_streams_encrypted(call) ? + LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone; + } } @@ -1736,16 +1765,10 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut call->playing_ringbacktone=send_ringbacktone; call->up_bw=linphone_core_get_upload_bandwidth(lc); + // ZRTP was initialized in linphone_call_init_media_streams with a + // partially iniitalized RtpSession, and now needs to get an update if (call->params.media_encryption==LinphoneMediaEncryptionZRTP) { - OrtpZrtpParams params; - /*will be set later when zrtp is activated*/ - call->current_params.media_encryption=LinphoneMediaEncryptionNone; - - params.zid_file=lc->zrtp_secrets_cache; - audio_stream_enable_zrtp(call->audiostream,¶ms); - }else if (call->params.media_encryption==LinphoneMediaEncryptionSRTP){ - call->current_params.media_encryption=linphone_call_are_all_streams_encrypted(call) ? - LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone; + ortp_zrtp_start_engine(call->audiostream->ms.zrtp_context,call->audiostream->ms.session); } /*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again @@ -2114,7 +2137,7 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){ if (from) { snprintf(temp,sizeof(temp),"Remote end %s seems to have disconnected, the call is going to be closed.",from); - free(from); + ms_free(from); } else { @@ -2123,6 +2146,7 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){ if (lc->vtable.display_warning!=NULL) lc->vtable.display_warning(lc,temp); linphone_core_terminate_call(lc,call); + linphone_core_play_named_tone(lc,LinphoneToneCallFailed); } static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index b704347da..93d0b8b80 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2118,9 +2118,10 @@ void linphone_core_iterate(LinphoneCore *lc){ ms_message("incoming call ringing for %i seconds",elapsed); if (elapsed>lc->sip_conf.inc_timeout){ ms_message("incoming call timeout (%i)",lc->sip_conf.inc_timeout); + LinphoneReason decline_reason=lc->current_call ? LinphoneReasonBusy : LinphoneReasonDeclined; call->log->status=LinphoneCallMissed; call->reason=LinphoneReasonNotAnswered; - linphone_core_terminate_call(lc,call); + linphone_core_decline_call(lc,call,decline_reason); } } if (lc->sip_conf.in_call_timeout > 0 && elapsed>lc->sip_conf.in_call_timeout) { @@ -2754,7 +2755,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ }else{ /* else play a tone within the context of the current call */ call->ringing_beep=TRUE; - linphone_core_play_tone(lc); + linphone_core_play_named_tone(lc,LinphoneToneCallWaiting); } linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call"); @@ -3124,8 +3125,14 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, sal_call_set_local_media_description(call->op,call->localdesc); } - if (call->audiostream==NULL) + if (call->audiostream==NULL){ linphone_call_init_media_streams(call); + // the local media description must be regenerated after the audiostream + // is initialized, otherwise the ZRTP hello hash will not be available + linphone_call_make_local_media_description(lc,call); + sal_call_set_local_media_description(call->op,call->localdesc); + } + if (!was_ringing && call->audiostream->ms.ticker==NULL){ audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard); } @@ -3305,8 +3312,7 @@ bool_t linphone_core_in_call(const LinphoneCore *lc){ * * @ingroup call_control **/ -LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc) -{ +LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc){ return lc->current_call; } @@ -3316,7 +3322,14 @@ LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc) * * @ingroup call_control **/ -int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call) +int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call){ + int err=_linphone_core_pause_call(lc,call); + if (err==0) call->paused_by_app=TRUE; + return err; +} + +/* Internal version that does not play tone indication*/ +int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call) { const char *subject=NULL; @@ -3354,6 +3367,7 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call) lc->vtable.display_status(lc,_("Pausing the current call...")); if (call->audiostream || call->videostream) linphone_call_stop_media_streams (call); + call->paused_by_app=FALSE; return 0; } @@ -3367,7 +3381,7 @@ int linphone_core_pause_all_calls(LinphoneCore *lc){ LinphoneCall *call=(LinphoneCall *)elem->data; LinphoneCallState cs=linphone_call_get_state(call); if (cs==LinphoneCallStreamsRunning || cs==LinphoneCallPausedByRemote){ - linphone_core_pause_call(lc,call); + _linphone_core_pause_call(lc,call); } } return 0; @@ -3382,7 +3396,11 @@ void linphone_core_preempt_sound_resources(LinphoneCore *lc){ current_call=linphone_core_get_current_call(lc); if(current_call != NULL){ ms_message("Pausing automatically the current call."); - linphone_core_pause_call(lc,current_call); + _linphone_core_pause_call(lc,current_call); + } + if (lc->ringstream){ + ring_stop(lc->ringstream); + lc->ringstream=NULL; } } @@ -4693,7 +4711,7 @@ int linphone_core_get_device_rotation(LinphoneCore *lc ) { * **/ void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation) { -ms_message("%s : rotation=%d\n", __FUNCTION__, rotation); + ms_message("%s : rotation=%d\n", __FUNCTION__, rotation); lc->device_rotation = rotation; #ifdef VIDEO_ENABLED LinphoneCall *call=linphone_core_get_current_call(lc); @@ -4905,13 +4923,54 @@ void linphone_core_play_tone(LinphoneCore *lc){ ms_error("No dtmf generator at this time !"); return; } + memset(&def,0,sizeof(def)); def.duration=300; - def.frequency=500; + def.frequencies[0]=500; def.amplitude=1; def.interval=2000; ms_filter_call_method(f, MS_DTMF_GEN_PLAY_CUSTOM,&def); } +void linphone_core_play_named_tone(LinphoneCore *lc, LinphoneToneID toneid){ + if (linphone_core_tone_indications_enabled(lc)){ + MSFilter *f=get_dtmf_gen(lc); + MSDtmfGenCustomTone def; + if (f==NULL){ + ms_error("No dtmf generator at this time !"); + return; + } + memset(&def,0,sizeof(def)); + def.amplitude=1; + /*these are french tones, excepted the failed one, which is USA congestion tone (does not exist in France)*/ + switch(toneid){ + case LinphoneToneCallOnHold: + case LinphoneToneCallWaiting: + def.duration=300; + def.frequencies[0]=440; + def.interval=2000; + break; + case LinphoneToneBusy: + def.duration=500; + def.frequencies[0]=440; + def.interval=500; + def.repeat_count=3; + break; + case LinphoneToneCallFailed: + def.duration=250; + def.frequencies[0]=480; + def.frequencies[0]=620; + def.interval=250; + def.repeat_count=3; + + break; + default: + ms_warning("Unhandled tone id."); + } + if (def.duration>0) + ms_filter_call_method(f, MS_DTMF_GEN_PLAY_CUSTOM,&def); + } +} + /** * @ingroup media_parameters * diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index 4608beecf..db4e5de5c 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -190,6 +190,7 @@ void lp_config_parse(LpConfig *lpconfig, FILE *file){ if (pos2-pos1>=0){ /* found a pair key,value */ + if (cur!=NULL){ LpItem *item=lp_section_find_item(cur,key); if (item==NULL){ @@ -198,7 +199,7 @@ void lp_config_parse(LpConfig *lpconfig, FILE *file){ ms_free(item->value); item->value=strdup(pos1); } - /*printf("Found %s %s={%s}\n",cur->name,key,pos1);*/ + /*ms_message("Found %s=%s",key,pos1);*/ }else{ ms_warning("found key,item but no sections"); } @@ -212,6 +213,7 @@ void lp_config_parse(LpConfig *lpconfig, FILE *file){ LpConfig * lp_config_new(const char *filename){ LpConfig *lpconfig=lp_new0(LpConfig,1); if (filename!=NULL){ + ms_message("Using (r/w) config information from %s", filename); lpconfig->filename=ortp_strdup(filename); lpconfig->file=fopen(filename,"rw"); if (lpconfig->file!=NULL){ @@ -237,6 +239,7 @@ LpConfig * lp_config_new(const char *filename){ int lp_config_read_file(LpConfig *lpconfig, const char *filename){ FILE* f=fopen(filename,"r"); if (f!=NULL){ + ms_message("Reading config information from %s", filename); lp_config_parse(lpconfig,f); fclose(f); return 0; diff --git a/coreapi/misc.c b/coreapi/misc.c index e84c8cce9..35a58e200 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -876,7 +876,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, for (i = 0; i < md->n_total_streams; i++) { const SalStreamDescription *stream = &md->streams[i]; IceCheckList *cl = ice_session_check_list(call->ice_session, i); - if (cl == NULL) { + if ((cl == NULL) && (i < md->n_active_streams)) { cl = ice_check_list_new(); ice_session_add_check_list(call->ice_session, cl); switch (stream->type) { @@ -1005,6 +1005,9 @@ unsigned int linphone_core_get_audio_features(LinphoneCore *lc){ return ret; } +bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc){ + return lp_config_get_int(lc->config,"sound","tone_indications",1); +} #ifdef HAVE_GETIFADDRS diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index 9823c24a6..eefe34d45 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -261,6 +261,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap, result->ice_completed = local_cap->ice_completed; memcpy(result->ice_candidates, local_cap->ice_candidates, sizeof(result->ice_candidates)); memcpy(result->ice_remote_candidates, local_cap->ice_remote_candidates, sizeof(result->ice_remote_candidates)); + memcpy(result->zrtp_hello_hash,local_cap->zrtp_hello_hash, sizeof(result->zrtp_hello_hash)); } /** diff --git a/coreapi/private.h b/coreapi/private.h index 13087dc04..5e265c616 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -211,6 +211,7 @@ struct _LinphoneCall bool_t was_automatically_paused; bool_t ping_replied; bool_t record_active; + bool_t paused_by_app; }; @@ -678,6 +679,8 @@ void ec_calibrator_destroy(EcCalibrator *ecc); void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed); void linphone_core_preempt_sound_resources(LinphoneCore *lc); +int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call); + /*conferencing subsystem*/ void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted); /* When a conference participant pause the conference he may send a music. @@ -718,6 +721,15 @@ void linphone_chat_message_store_state(LinphoneChatMessage *msg); void linphone_core_message_storage_init(LinphoneCore *lc); void linphone_core_message_storage_close(LinphoneCore *lc); +typedef enum _LinphoneToneID{ + LinphoneToneBusy, + LinphoneToneCallWaiting, + LinphoneToneCallOnHold, + LinphoneToneCallFailed +}LinphoneToneID; +void linphone_core_play_named_tone(LinphoneCore *lc, LinphoneToneID id); +bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc); + #ifdef __cplusplus } #endif diff --git a/coreapi/sal.h b/coreapi/sal.h index 25d8d20bc..5f38c15ab 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -140,7 +140,7 @@ typedef struct SalIceRemoteCandidate { } SalIceRemoteCandidate; #define SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES 2 - +#define SAL_MEDIA_DESCRIPTION_MAX_ZRTP_HELLO_HASH 128 #define SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN 256 #define SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN 256 @@ -172,6 +172,7 @@ typedef struct SalStreamDescription{ SalIceRemoteCandidate ice_remote_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES]; char ice_ufrag[SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN]; char ice_pwd[SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN]; + char zrtp_hello_hash[SAL_MEDIA_DESCRIPTION_MAX_ZRTP_HELLO_HASH]; bool_t ice_mismatch; bool_t ice_completed; } SalStreamDescription; diff --git a/coreapi/sal_eXosip2_sdp.c b/coreapi/sal_eXosip2_sdp.c index 9297077e6..139446448 100644 --- a/coreapi/sal_eXosip2_sdp.c +++ b/coreapi/sal_eXosip2_sdp.c @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sal.h" #include -#define keywordcmp(key,b) strncmp(key,b,sizeof(key)) +#define keywordcmp(key,b) strcmp(key,b) #ifdef FOR_LATER @@ -108,6 +108,17 @@ static int _sdp_message_get_a_ptime(sdp_message_t *sdp, int mline){ return 0; } +static char * _sdp_message_get_a_zrtp_hash(sdp_message_t *sdp, int mline){ + int i; + sdp_attribute_t *attr; + for (i=0;(attr=sdp_message_attribute_get(sdp,mline,i))!=NULL;i++){ + if (keywordcmp("zrtp-hash",attr->a_att_field)==0){ + return attr->a_att_value; + } + } + return NULL; +} + static int _sdp_message_get_mline_dir(sdp_message_t *sdp, int mline){ int i; sdp_attribute_t *attr; @@ -337,6 +348,11 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription int_2char(desc->bandwidth)); if (desc->ptime>0) sdp_message_a_attribute_add(msg,lineno,osip_strdup("ptime"), int_2char(desc->ptime)); + + // if the ZRTP hello hash is available, create an a attribute for it + if (desc->zrtp_hello_hash[0]) + sdp_message_a_attribute_add(msg,lineno,osip_strdup("zrtp-hash"), osip_strdup(desc->zrtp_hello_hash)); + strip_well_known_rtpmaps=ms_list_size(desc->payloads)>5; if (desc->payloads){ for(elem=desc->payloads;elem!=NULL;elem=elem->next){ @@ -433,7 +449,7 @@ static int payload_type_fill_from_rtpmap(PayloadType *pt, const char *rtpmap){ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){ int i,j; - const char *mtype,*proto,*rtp_port,*rtp_addr,*number; + const char *mtype,*proto,*rtp_port,*rtp_addr,*number,*zrtp_info; const char *sess; sdp_bandwidth_t *sbw=NULL; sdp_attribute_t *attr; @@ -490,7 +506,12 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){ stream->rtp_port=atoi(rtp_port); if (stream->rtp_port > 0) desc->n_active_streams++; - + + // if the SDP contains a zrtp-hash, add it to the StreamDesc + zrtp_info = _sdp_message_get_a_zrtp_hash(msg, i); + if (zrtp_info != NULL) + strncpy(stream->zrtp_hello_hash, zrtp_info, sizeof(stream->zrtp_hello_hash)); + stream->ptime=_sdp_message_get_a_ptime(msg,i); if (strcasecmp("audio", mtype) == 0){ stream->type=SalAudio; @@ -528,7 +549,8 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){ for (j = 0; ((attr = sdp_message_attribute_get(msg, i, j)) != NULL); j++) { if ((keywordcmp("rtcp", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) { char tmp[256]; - int nb = sscanf(attr->a_att_value, "%d IN IP4 %s", &stream->rtcp_port, tmp); + // added bounds check + int nb = sscanf(attr->a_att_value, "%d IN IP4 %256s", &stream->rtcp_port, tmp); if (nb == 1) { /* SDP rtcp attribute only contains the port */ } else if (nb == 2) { diff --git a/m4/exosip.m4 b/m4/exosip.m4 index 31769e00d..e7c72647d 100644 --- a/m4/exosip.m4 +++ b/m4/exosip.m4 @@ -20,6 +20,19 @@ EXOSIP_LIBS="$OSIP_LIBS -leXosip2 " CPPFLAGS_save=$CPPFLAGS CPPFLAGS="$OSIP_CFLAGS $CPPFLAGS" AC_CHECK_HEADER([eXosip2/eXosip.h], ,AC_MSG_ERROR([Could not find eXosip2 headers !])) + +dnl check exosip support of DSCP in exosip +AC_MSG_CHECKING([for DSCP support in exosip]) +AC_TRY_COMPILE([#include ], + [int dscp=0;eXosip_set_option(EXOSIP_OPT_SET_DSCP,&dscp);], + has_exosip_dscp=yes, + has_exosip_dscp=no +) +AC_MSG_RESULT($has_exosip_dscp) +if test "$has_exosip_dscp" = "yes" ; then + AC_DEFINE( HAVE_EXOSIP_DSCP, 1, [Define if exosip dscp available] ) +fi + CPPFLAGS=$CPPFLAGS_save diff --git a/mediastreamer2 b/mediastreamer2 index 28c3383b5..430cc1376 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 28c3383b5e98196ab394f6616f11c195e6759d28 +Subproject commit 430cc1376d68b1a8d82799357abea9e3e1c536f8 diff --git a/oRTP b/oRTP index 20b527144..c702c0ea0 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 20b527144f9850dd9065d96db7a20244e8a8b227 +Subproject commit c702c0ea0e66bbe1f27c79690003d9748b01560f