#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;
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;
lc->sip_conf.keepalive_period=lp_config_get_int(lc->config,"sip","keepalive_period",10000);
sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
sal_use_one_matching_codec_policy(lc->sal,lp_config_get_int(lc->config,"sip","only_one_codec",0));
+ sal_use_double_registrations(lc->sal,lp_config_get_int(lc->config,"sip","use_double_registrations",1));
}
static void rtp_config_read(LinphoneCore *lc)
jitt_comp=lp_config_get_int(lc->config,"rtp","audio_jitt_comp",60);
linphone_core_set_audio_jittcomp(lc,jitt_comp);
jitt_comp=lp_config_get_int(lc->config,"rtp","video_jitt_comp",60);
+ if (jitt_comp==0) jitt_comp=60;
+ lc->rtp_conf.video_jitt_comp=jitt_comp;
nortp_timeout=lp_config_get_int(lc->config,"rtp","nortp_timeout",30);
linphone_core_set_nortp_timeout(lc,nortp_timeout);
rtp_no_xmit_on_audio_mute=lp_config_get_int(lc->config,"rtp","rtp_no_xmit_on_audio_mute",FALSE);
{
memset (lc, 0, sizeof (LinphoneCore));
lc->data=userdata;
-
+ lc->ringstream_autorelease=TRUE;
+
memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable));
linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up");
one_second_elapsed=TRUE;
}
+ if (lc->ecc!=NULL){
+ LinphoneEcCalibratorStatus ecs=ec_calibrator_get_status(lc->ecc);
+ if (ecs!=LinphoneEcCalibratorInProgress){
+ if (lc->ecc->cb)
+ lc->ecc->cb(lc,ecs,lc->ecc->delay,lc->ecc->cb_data);
+ if (ecs==LinphoneEcCalibratorDone){
+ lp_config_set_int(lc->config, "sound", "ec_delay",MAX(lc->ecc->delay-10,0));
+ }
+ ec_calibrator_destroy(lc->ecc);
+ lc->ecc=NULL;
+ }
+ }
+
if (lc->preview_finished){
lc->preview_finished=0;
ring_stop(lc->ringstream);
lc_callback_obj_invoke(&lc->preview_finished_cb,lc);
}
- if (lc->ringstream && lc->dmfs_playing_start_time!=0
+ if (lc->ringstream && lc->ringstream_autorelease && lc->dmfs_playing_start_time!=0
&& (curtime-lc->dmfs_playing_start_time)>5){
ring_stop(lc->ringstream);
lc->ringstream=NULL;
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
int err=0;
if (params!=NULL){
- if (call->localdesc)
- sal_media_description_unref(call->localdesc);
call->params=*params;
- call->localdesc=create_local_media_description (lc,call);
+ update_local_media_description(lc,call,&call->localdesc);
call->camera_active=params->has_video;
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Modifying call parameters..."));
sal_call_set_local_media_description (call->op,call->localdesc);
- err=sal_call_update(call->op);
+ err=sal_call_update(call->op,"Media parameters update");
}else{
#ifdef VIDEO_ENABLED
if (call->videostream!=NULL){
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"));
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;
}
* Returns true if the specified sound device can capture sound.
*
* @ingroup media_parameters
+ * @param lc The LinphoneCore object
* @param devid the device name as returned by linphone_core_get_sound_devices()
**/
bool_t linphone_core_sound_device_can_capture(LinphoneCore *lc, const char *devid){
* Returns true if the specified sound device can play sound.
*
* @ingroup media_parameters
+ * @param lc The LinphoneCore object
* @param devid the device name as returned by linphone_core_get_sound_devices()
**/
bool_t linphone_core_sound_device_can_playback(LinphoneCore *lc, const char *devid){
* Sets the sound device used for ringing.
*
* @ingroup media_parameters
+ * @param lc The LinphoneCore object
* @param devid the device name as returned by linphone_core_get_sound_devices()
**/
int linphone_core_set_ringer_device(LinphoneCore *lc, const char * devid){
* Sets the sound device used for playback.
*
* @ingroup media_parameters
+ * @param lc The LinphoneCore object
* @param devid the device name as returned by linphone_core_get_sound_devices()
**/
int linphone_core_set_playback_device(LinphoneCore *lc, const char * devid){
* Sets the sound device used for capture.
*
* @ingroup media_parameters
+ * @param lc The LinphoneCore object
* @param devid the device name as returned by linphone_core_get_sound_devices()
**/
int linphone_core_set_capture_device(LinphoneCore *lc, const char * devid){
* Returns the name of the currently assigned sound device for ringing.
*
* @ingroup media_parameters
+ * @param lc The LinphoneCore object
**/
const char * linphone_core_get_ringer_device(LinphoneCore *lc)
{
* Returns the name of the currently assigned sound device for playback.
*
* @ingroup media_parameters
+ * @param lc The LinphoneCore object
**/
const char * linphone_core_get_playback_device(LinphoneCore *lc)
{
* Returns the name of the currently assigned sound device for capture.
*
* @ingroup media_parameters
+ * @param lc The LinphoneCore object
**/
const char * linphone_core_get_capture_device(LinphoneCore *lc)
{
/**
* Returns an unmodifiable array of available sound devices.
*
- * @ingroup media_parameters
* The array is NULL terminated.
+ *
+ * @ingroup media_parameters
+ * @param lc The LinphoneCore object
**/
const char** linphone_core_get_sound_devices(LinphoneCore *lc){
build_sound_devices_table(lc);
* Sets the path to a wav file used for ringing.
*
* @param path The file must be a wav 16bit linear. Local ring is disabled if null
+ * @param lc The LinphoneCore object
*
* @ingroup media_parameters
**/
void linphone_core_set_ring(LinphoneCore *lc,const char *path){
if (lc->sound_conf.local_ring!=0){
ms_free(lc->sound_conf.local_ring);
+ lc->sound_conf.local_ring=NULL;
}
- lc->sound_conf.local_ring=ms_strdup(path);
+ if (path)
+ lc->sound_conf.local_ring=ms_strdup(path);
if ( linphone_core_ready(lc) && lc->sound_conf.local_ring)
lp_config_set_string(lc->config,"sound","local_ring",lc->sound_conf.local_ring);
}
/**
* Returns the path to the wav file used for ringing.
*
+ * @param lc The LinphoneCore object
* @ingroup media_parameters
**/
const char *linphone_core_get_ring(const LinphoneCore *lc){
* initiate future calls with video or not. The two boolean parameters indicate in which
* direction video is enabled. Setting both to false disables video entirely.
*
+ * @param lc The LinphoneCore object
* @param vcap_enabled indicates whether video capture is enabled
* @param display_enabled indicates whether video display should be shown
*
* Sets the active video device.
*
* @ingroup media_parameters
+ * @param lc The LinphoneCore object
* @param id the name of the video device as returned by linphone_core_get_video_devices()
**/
int linphone_core_set_video_device(LinphoneCore *lc, const char *id){
/**
* Returns the name of the currently active video device.
*
+ * @param lc The LinphoneCore object
* @ingroup media_parameters
**/
const char *linphone_core_get_video_device(const LinphoneCore *lc){
}
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" },
}
}
if (lc->ringstream==NULL){
+ float amp=0.1;
MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
lc->ringstream=ring_start(NULL,0,ringcard);
+ ms_filter_call_method(lc->ringstream->gendtmf,MS_DTMF_GEN_SET_DEFAULT_AMPLITUDE,&);
lc->dmfs_playing_start_time=time(NULL);
}else{
if (lc->dmfs_playing_start_time!=0)
/**
* Plays a dtmf to the local user.
**/
-void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms){
+void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms, bool_t speaker){
MSFilter *f=get_dtmf_gen(lc);
if (f==NULL){
ms_error("No dtmf generator at this time !");
return;
}
+
+ if (!speaker && !linphone_core_in_call(lc)) {
+ // If not in call and user doesn't want sound to go out from speaker
+ // TODO: update dtmf generator to only output on output stream if speaker is false.
+ return;
+ }
+
if (duration_ms>0)
ms_filter_call_method(f, MS_DTMF_GEN_PLAY, &dtmf);
else ms_filter_call_method(f, MS_DTMF_GEN_START, &dtmf);
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
usleep(50000);
#endif
}
-
if (lc->friends)
ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_close_subscriptions);
linphone_core_set_state(lc,LinphoneGlobalShutdown,"Shutting down");
lc->msevq=NULL;
/* save all config */
net_config_uninit(lc);
- sip_config_uninit(lc);
rtp_config_uninit(lc);
+ if (lc->ringstream) ring_stop(lc->ringstream);
sound_config_uninit(lc);
video_config_uninit(lc);
codecs_config_uninit(lc);
ui_config_uninit(lc);
+ sip_config_uninit(lc);
if (lp_config_needs_commit(lc->config)) lp_config_sync(lc->config);
lp_config_destroy(lc->config);
lc->config = NULL; /* Mark the config as NULL to block further calls */
lc->call_logs=ms_list_free(lc->call_logs);
linphone_core_free_payload_types();
-
ortp_exit();
linphone_core_set_state(lc,LinphoneGlobalOff,"Off");
}
}
lc->netup_time=curtime;
lc->network_reachable=isReachable;
- }
+ if(!isReachable) {
+ sal_unlisten_ports (lc->sal);
+ } else {
+ apply_transports(lc);
+ }
+ }
+ void linphone_core_refresh_registers(LinphoneCore* lc) {
+ const MSList *elem=linphone_core_get_proxy_config_list(lc);
+ for(;elem!=NULL;elem=elem->next){
+ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
+ if (linphone_proxy_config_register_enabled(cfg) ) {
+ cfg->registered=0;
+ cfg->commit=TRUE;
+ }
+ }
+
+ }
void linphone_core_set_network_reachable(LinphoneCore* lc,bool_t isReachable) {
//first disable automatic mode
if (lc->auto_net_state_mon) {
}
return "unknown error";
}
+ /**
+ * enable signaling keep alive
+ */
+ void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable) {
+ if (enable > 0) {
+ sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
+ } else {
+ sal_set_keepalive_period(lc->sal,0);
+ }
+ }
+ /**
+ * Is signaling keep alive
+ */
+ bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc) {
+ return sal_get_keepalive_period(lc->sal) > 0;
+ }
+
+ void linphone_core_start_dtmf_stream(LinphoneCore* lc) {
+ get_dtmf_gen(lc); /*make sure ring stream is started*/
+ lc->ringstream_autorelease=FALSE; /*disable autorelease mode*/
+ }
+
+ void linphone_core_stop_dtmf_stream(LinphoneCore* lc) {
+ if (lc->ringstream) ring_stop(lc->ringstream);
+ lc->ringstream=NULL;
+ }
+
/**
* Enum describing failure reasons.
+ * @ingroup initializing
**/
enum _LinphoneReason{
LinphoneReasonNone,
struct _LinphoneCall;
typedef struct _LinphoneCall LinphoneCall;
+ /**
+ * LinphoneCallState enum represents the different state a call can reach into.
+ * The application is notified of state changes through the LinphoneCoreVTable::call_state_changed callback.
+ * @ingroup call_control
+ **/
typedef enum _LinphoneCallState{
- LinphoneCallIdle,
+ LinphoneCallIdle, /**<Initial call state */
LinphoneCallIncomingReceived, /**<This is a new incoming call */
LinphoneCallOutgoingInit, /**<An outgoing call is started */
LinphoneCallOutgoingProgress, /**<An outgoing call is in progress */
LinphoneCallPausedByRemote, /**<The call is paused by remote end*/
LinphoneCallUpdatedByRemote, /**<The call's parameters are updated, used for example when video is asked by remote */
LinphoneCallIncomingEarlyMedia, /**<We are proposing early media to an incoming call */
- LinphoneCallUpdated /**<The remote accepted the call update initiated by us */
+ LinphoneCallUpdated, /**<The remote accepted the call update initiated by us */
+ LinphoneCallReleased /**< The call object is no more retained by the core */
} LinphoneCallState;
const char *linphone_call_state_to_string(LinphoneCallState cs);
LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call);
const char *linphone_call_get_refer_to(const LinphoneCall *call);
bool_t linphone_call_has_transfer_pending(const LinphoneCall *call);
+ LinphoneCall *linphone_call_get_replaced_call(LinphoneCall *call);
int linphone_call_get_duration(const LinphoneCall *call);
const LinphoneCallParams * linphone_call_get_current_params(const LinphoneCall *call);
void linphone_call_enable_camera(LinphoneCall *lc, bool_t enabled);
* LinphoneRegistrationState describes proxy registration states.
**/
typedef enum _LinphoneRegistrationState{
- LinphoneRegistrationNone,
- LinphoneRegistrationProgress,
- LinphoneRegistrationOk,
- LinphoneRegistrationCleared,
- LinphoneRegistrationFailed
+ LinphoneRegistrationNone, /**<Initial state for registrations */
+ LinphoneRegistrationProgress, /**<Registration is in progress */
+ LinphoneRegistrationOk, /**< Registration is successful */
+ LinphoneRegistrationCleared, /**< Unregistration succeeded */
+ LinphoneRegistrationFailed /**<Registration failed */
}LinphoneRegistrationState;
/**
/**
* @}
*/
+
+
+ /**
+ * @addtogroup initializing
+ * @{
+ **/
+
+ /**
+ * LinphoneGlobalState describes the global state of the LinphoneCore object.
+ * It is notified via the LinphoneCoreVTable::global_state_changed
+ **/
typedef enum _LinphoneGlobalState{
LinphoneGlobalOff,
LinphoneGlobalStartup,
const char *linphone_global_state_to_string(LinphoneGlobalState gs);
- /**
- * @addtogroup initializing
- * @{
- **/
-
/**Call state notification callback prototype*/
typedef void (*LinphoneGlobalStateCb)(struct _LinphoneCore *lc, LinphoneGlobalState gstate, const char *message);
void linphone_core_set_play_file(LinphoneCore *lc, const char *file);
void linphone_core_set_record_file(LinphoneCore *lc, const char *file);
-void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms);
+void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms, bool_t speaker);
void linphone_core_stop_dtmf(LinphoneCore *lc);
int linphone_core_get_current_call_duration(const LinphoneCore *lc);
*/
bool_t linphone_core_is_network_reachabled(LinphoneCore* lc);
+ /**
+ * enable signaling keep alive. small udp packet sent periodically to keep udp NAT association
+ */
+ void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable);
+ /**
+ * Is signaling keep alive
+ */
+ bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc);
void *linphone_core_get_user_data(LinphoneCore *lc);
const MSList *linphone_core_get_calls(LinphoneCore *lc);
LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc);
-
+ /**
+ * force registration refresh to be initiated upon next iterate
+ * @ingroup proxies
+ */
+ void linphone_core_refresh_registers(LinphoneCore* lc);
#ifdef __cplusplus
}
#endif
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <jni.h>
- #include "linphonecore.h"
+ #include "linphonecore_utils.h"
+
#include "mediastreamer2/msjava.h"
#ifdef ANDROID
callStateId = env->GetMethodID(listernerClass,"callState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;Ljava/lang/String;)V");
callStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCall$State"));
callStateFromIntId = env->GetStaticMethodID(callStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCall$State;");
-
+ /*void ecCalibrationStatus(LinphoneCore.EcCalibratorStatus status, int delay_ms, Object data);*/
+ ecCalibrationStatusId = env->GetMethodID(listernerClass,"ecCalibrationStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;ILjava/lang/Object;)V");
+ ecCalibratorStatusClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$EcCalibratorStatus"));
+ ecCalibratorStatusFromIntId = env->GetStaticMethodID(ecCalibratorStatusClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;");
/*void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url)*/
newSubscriptionRequestId = env->GetMethodID(listernerClass,"newSubscriptionRequest","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;Ljava/lang/String;)V");
jmethodID callStateId;
jmethodID callStateFromIntId;
+ jclass ecCalibratorStatusClass;
+ jmethodID ecCalibrationStatusId;
+ jmethodID ecCalibratorStatusFromIntId;
+
jclass proxyClass;
jmethodID proxyCtrId;
,env->NewObject(lcData->addressClass,lcData->addressCtrId,(jlong)from)
,message ? env->NewStringUTF(message) : NULL);
}
+ static void ecCalibrationStatus(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data) {
+ JNIEnv *env = 0;
+ jint result = jvm->AttachCurrentThread(&env,NULL);
+ if (result != 0) {
+ ms_error("cannot attach VM\n");
+ return;
+ }
+ LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
+ env->CallVoidMethod(lcData->listener
+ ,lcData->ecCalibrationStatusId
+ ,lcData->core
+ ,env->CallStaticObjectMethod(lcData->ecCalibratorStatusClass,lcData->ecCalibratorStatusFromIntId,(jint)status)
+ ,delay_ms
+ ,data ? data : NULL);
+ if (data != NULL &&status !=LinphoneEcCalibratorInProgress ) {
+ //final state, releasing global ref
+ env->DeleteGlobalRef((jobject)data);
+ }
+
+ }
};
,jobject thiz
,jlong lc
,jchar dtmf
- ,jint duration) {
- linphone_core_play_dtmf((LinphoneCore*)lc,dtmf,duration);
+ ,jint duration
+ ,jboolean speaker) {
+ linphone_core_play_dtmf((LinphoneCore*)lc,dtmf,duration,speaker);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_stopDtmf( JNIEnv* env
,jobject thiz
return NULL;
}
}
+ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableKeepAlive(JNIEnv* env
+ ,jobject thiz
+ ,jlong lc
+ ,jboolean enable) {
+ linphone_core_enable_keep_alive((LinphoneCore*)lc,enable);
+
+ }
+ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isKeepAliveEnabled(JNIEnv* env
+ ,jobject thiz
+ ,jlong lc) {
+ return linphone_core_keep_alive_enabled((LinphoneCore*)lc);
+
+ }
+ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_startEchoCalibration(JNIEnv* env
+ ,jobject thiz
+ ,jlong lc
+ ,jobject data) {
+ return linphone_core_start_echo_calibration((LinphoneCore*)lc
+ , LinphoneCoreData::ecCalibrationStatus
+ , data?env->NewGlobalRef(data):NULL);
+
+ }
+
//ProxyConfig
return linphone_call_echo_limiter_enabled((LinphoneCall*)ptr);
}
+ extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getReplacedCall( JNIEnv* env
+ ,jobject thiz
+ ,jlong ptr) {
+ return (jlong)linphone_call_get_replaced_call((LinphoneCall*)ptr);
+ }
+
//LinphoneFriend
extern "C" long Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv* env