linphonecore_jni.cc 262 KB
Newer Older
jehan's avatar
jehan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
linphonecore_jni.cc
Copyright (C) 2010  Belledonne Communications, Grenoble, France

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
#include <jni.h>
20
#ifdef USE_JAVAH
21
#include "linphonecore_jni.h"
22
#endif
jehan's avatar
jehan committed
23
#include "linphonecore_utils.h"
24
#include <mediastreamer2/zrtp.h>
jehan's avatar
jehan committed
25

Guillaume Beraudo's avatar
Guillaume Beraudo committed
26

27 28
extern "C" {
#include "mediastreamer2/mediastream.h"
29
#include "mediastreamer2/mscommon.h"
François Grisez's avatar
François Grisez committed
30
#include "mediastreamer2/msmediaplayer.h"
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
31
#include "mediastreamer2/msutils.h"
Margaux Clerc's avatar
Margaux Clerc committed
32
#include "devices.h"
33
}
Simon Morlat's avatar
Simon Morlat committed
34
#include "mediastreamer2/msjava.h"
35
#include "private.h"
36 37
#include <cpu-features.h>

38 39
#include "lpconfig.h"

jehan's avatar
jehan committed
40 41
#ifdef ANDROID
#include <android/log.h>
Sylvain Berfini's avatar
Sylvain Berfini committed
42
extern "C" void libmsilbc_init();
43
#ifdef HAVE_X264
Simon Morlat's avatar
Simon Morlat committed
44
extern "C" void libmsx264_init();
45
#endif
46 47 48
#ifdef HAVE_OPENH264
extern "C" void libmsopenh264_init();
#endif
Simon Morlat's avatar
Simon Morlat committed
49 50 51
#ifdef HAVE_AMR
extern "C" void libmsamr_init();
#endif
52 53 54
#ifdef HAVE_SILK
extern "C" void libmssilk_init();
#endif
jehan's avatar
jehan committed
55 56 57
#ifdef HAVE_G729
extern "C" void libmsbcg729_init();
#endif
58 59
#ifdef HAVE_WEBRTC
extern "C" void libmswebrtc_init();
60
#endif
61 62 63
#ifdef HAVE_CODEC2
extern "C" void libmscodec2_init();
#endif
64
#include <belle-sip/wakelock.h>
jehan's avatar
jehan committed
65 66
#endif /*ANDROID*/

Ghislain MARY's avatar
Ghislain MARY committed
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
#define RETURN_USER_DATA_OBJECT(javaclass, funcprefix, cobj) \
	{ \
		jclass jUserDataObjectClass; \
		jmethodID jUserDataObjectCtor; \
		jobject jUserDataObj; \
		jUserDataObj = (jobject)funcprefix ## _get_user_data(cobj); \
		if (jUserDataObj == NULL) { \
			jUserDataObjectClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/" javaclass)); \
			jUserDataObjectCtor = env->GetMethodID(jUserDataObjectClass,"<init>", "(J)V"); \
			jUserDataObj = env->NewObject(jUserDataObjectClass, jUserDataObjectCtor, (jlong)funcprefix ## _ref(cobj)); \
			jUserDataObj = env->NewGlobalRef(jUserDataObj); \
			funcprefix ## _set_user_data(cobj, jUserDataObj); \
			env->DeleteGlobalRef(jUserDataObjectClass); \
		} \
		return jUserDataObj; \
	}

jehan's avatar
jehan committed
84
static JavaVM *jvm=0;
85
static const char* LogDomain = "Linphone";
86 87 88
static jclass handler_class;
static jmethodID loghandler_id;
static jobject handler_obj=NULL;
jehan's avatar
jehan committed
89

90
static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent *content);
91
static jobject create_java_linphone_buffer(JNIEnv *env, const LinphoneBuffer *buffer);
92
static LinphoneBuffer* create_c_linphone_buffer_from_java_linphone_buffer(JNIEnv *env, jobject jbuffer);
93
static jobject getTunnelConfig(JNIEnv *env, LinphoneTunnelConfig *cfg);
94

jehan's avatar
jehan committed
95
#ifdef ANDROID
96
void linphone_android_log_handler(int prio, char *str) {
97 98
	char *current;
	char *next;
99 100

	if (strlen(str) < 512) {
101
		__android_log_write(prio, LogDomain, str);
102 103 104 105
	} else {
		current = str;
		while ((next = strchr(current, '\n')) != NULL) {
			*next = '\0';
106
			__android_log_write(prio, LogDomain, current);
107 108
			current = next + 1;
		}
109
		__android_log_write(prio, LogDomain, current);
110
	}
jehan's avatar
jehan committed
111
}
112

113
static void linphone_android_ortp_log_handler(OrtpLogLevel lev, const char *fmt, va_list args) {
114 115 116 117
	char str[4096];
	const char *levname="undef";
	vsnprintf(str, sizeof(str) - 1, fmt, args);
	str[sizeof(str) - 1] = '\0';
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
118

119 120
	int prio;
	switch(lev){
121 122 123 124 125 126
	case ORTP_DEBUG:	prio = ANDROID_LOG_DEBUG;	levname="debug"; break;
	case ORTP_MESSAGE:	prio = ANDROID_LOG_INFO;	levname="message"; break;
	case ORTP_WARNING:	prio = ANDROID_LOG_WARN;	levname="warning"; break;
	case ORTP_ERROR:	prio = ANDROID_LOG_ERROR;	levname="error"; break;
	case ORTP_FATAL:	prio = ANDROID_LOG_FATAL;	levname="fatal"; break;
	default:			prio = ANDROID_LOG_DEFAULT;	break;
127
	}
128 129
	if (handler_obj){
		JNIEnv *env=ms_get_jni_env();
130 131 132 133 134 135 136
		jstring jdomain=env->NewStringUTF(LogDomain);
		jstring jlevname=env->NewStringUTF(levname);
		jstring jstr=env->NewStringUTF(str);
		env->CallVoidMethod(handler_obj,loghandler_id,jdomain,(jint)lev,jlevname,jstr,NULL);
		if (jdomain) env->DeleteLocalRef(jdomain);
		if (jlevname) env->DeleteLocalRef(jlevname);
		if (jstr) env->DeleteLocalRef(jstr);
137 138
	}else
		linphone_android_log_handler(prio, str);
139 140
}

141 142 143
int dumbMethodForAllowingUsageOfCpuFeaturesFromStaticLibMediastream() {
	return (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0);
}
144 145 146 147

int dumbMethodForAllowingUsageOfMsAudioDiffFromStaticLibMediastream() {
	return ms_audio_diff(NULL, NULL, NULL, 0, NULL, NULL);
}
jehan's avatar
jehan committed
148 149
#endif /*ANDROID*/

150

jehan's avatar
jehan committed
151 152
JNIEXPORT jint JNICALL  JNI_OnLoad(JavaVM *ajvm, void *reserved)
{
jehan's avatar
jehan committed
153
#ifdef ANDROID
Simon Morlat's avatar
Simon Morlat committed
154
	ms_set_jvm(ajvm);
155

jehan's avatar
jehan committed
156 157 158 159 160 161
#endif /*ANDROID*/
	jvm=ajvm;
	return JNI_VERSION_1_2;
}


jehan's avatar
jehan committed
162
//LinphoneFactory
jehan's avatar
jehan committed
163
extern "C" void Java_org_linphone_core_LinphoneCoreFactoryImpl_setDebugMode(JNIEnv*  env
jehan's avatar
jehan committed
164
		,jobject  thiz
165 166
		,jboolean isDebug
		,jstring  jdebugTag) {
jehan's avatar
jehan committed
167
	if (isDebug) {
168
		LogDomain = env->GetStringUTFChars(jdebugTag, NULL);
169
		linphone_core_enable_logs_with_cb(linphone_android_ortp_log_handler);
jehan's avatar
jehan committed
170 171 172 173
	} else {
		linphone_core_disable_logs();
	}
}
174

175 176 177 178 179 180 181 182
extern "C" jobject Java_org_linphone_core_LinphoneCoreFactoryImpl__1createTunnelConfig(JNIEnv*  env, jobject  thiz){
	jobject jobj;
	LinphoneTunnelConfig *cfg =  linphone_tunnel_config_new();
	jobj = getTunnelConfig(env, cfg); //this will take a ref.
	linphone_tunnel_config_unref(cfg);
	return jobj;
}

183 184 185 186 187 188 189 190 191 192 193 194 195 196
extern "C" void Java_org_linphone_core_LinphoneCoreFactoryImpl_enableLogCollection(JNIEnv* env
		,jobject  thiz
		,jboolean enable) {
	linphone_core_enable_log_collection(enable ? LinphoneLogCollectionEnabledWithoutPreviousLogHandler : LinphoneLogCollectionDisabled);
}

extern "C" void Java_org_linphone_core_LinphoneCoreFactoryImpl_setLogCollectionPath(JNIEnv* env
		,jobject  thiz
		,jstring jpath) {

	const char* path = env->GetStringUTFChars(jpath, NULL);
	linphone_core_set_log_collection_path(path);
	env->ReleaseStringUTFChars(jpath, path);
}
jehan's avatar
jehan committed
197 198
// LinphoneCore

199 200 201 202 203 204 205
/*
 * returns the java LinphoneProxyConfig associated with a C LinphoneProxyConfig.
**/
jobject getProxy(JNIEnv *env, LinphoneProxyConfig *proxy, jobject core){
	jobject jobj=0;

	if (proxy!=NULL){
206
		jclass proxyClass = (jclass)env->FindClass("org/linphone/core/LinphoneProxyConfigImpl");
207
		jmethodID proxyCtrId = env->GetMethodID(proxyClass,"<init>", "(Lorg/linphone/core/LinphoneCoreImpl;J)V");
208

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
		void *up=linphone_proxy_config_get_user_data(proxy);

		if (up==NULL){
			jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy);
			linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj));
			linphone_proxy_config_ref(proxy);
		}else{
			//promote the weak ref to local ref
			jobj=env->NewLocalRef((jobject)up);
			if (jobj == NULL){
				//the weak ref was dead
				jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy);
				linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj));
			}
		}
224
		env->DeleteLocalRef(proxyClass);
225 226 227 228 229 230 231 232
	}
	return jobj;
}

jobject getCall(JNIEnv *env, LinphoneCall *call){
	jobject jobj=0;

	if (call!=NULL){
233
		jclass callClass = (jclass)env->FindClass("org/linphone/core/LinphoneCallImpl");
234
		jmethodID callCtrId = env->GetMethodID(callClass,"<init>", "(J)V");
235

236 237 238 239 240 241 242 243 244 245
		void *up=linphone_call_get_user_pointer(call);

		if (up==NULL){
			jobj=env->NewObject(callClass,callCtrId,(jlong)call);
			jobj=env->NewGlobalRef(jobj);
			linphone_call_set_user_pointer(call,(void*)jobj);
			linphone_call_ref(call);
		}else{
			jobj=(jobject)up;
		}
246
		env->DeleteLocalRef(callClass);
247 248 249 250 251 252 253 254
	}
	return jobj;
}

jobject getChatMessage(JNIEnv *env, LinphoneChatMessage *msg){
	jobject jobj = 0;

	if (msg != NULL){
255
		jclass chatMessageClass = (jclass)env->FindClass("org/linphone/core/LinphoneChatMessageImpl");
256
		jmethodID chatMessageCtrId = env->GetMethodID(chatMessageClass,"<init>", "(J)V");
257

258 259 260 261 262 263 264 265 266
		void *up = linphone_chat_message_get_user_data(msg);

		if (up == NULL) {
			jobj = env->NewObject(chatMessageClass,chatMessageCtrId,(jlong)linphone_chat_message_ref(msg));
			jobj = env->NewGlobalRef(jobj);
			linphone_chat_message_set_user_data(msg,(void*)jobj);
		} else {
			jobj = (jobject)up;
		}
267
		env->DeleteLocalRef(chatMessageClass);
268 269 270 271
	}
	return jobj;
}

Margaux Clerc's avatar
Margaux Clerc committed
272
jobject getFriend(JNIEnv *env, LinphoneFriend *lfriend){
273 274
	jobject jobj=0;

Margaux Clerc's avatar
Margaux Clerc committed
275
	if (lfriend != NULL){
276 277 278 279 280
		jclass friendClass = (jclass)env->FindClass("org/linphone/core/LinphoneFriendImpl");
		jmethodID friendCtrId = env->GetMethodID(friendClass,"<init>", "(J)V");

		void *up=linphone_friend_get_user_data(lfriend);

Margaux Clerc's avatar
Margaux Clerc committed
281
		if (up == NULL){
282 283 284 285
			jobj=env->NewObject(friendClass,friendCtrId,(jlong)lfriend);
			linphone_friend_set_user_data(lfriend,(void*)env->NewWeakGlobalRef(jobj));
			linphone_friend_ref(lfriend);
		}else{
Margaux Clerc's avatar
Margaux Clerc committed
286

287 288 289 290 291 292 293 294 295 296 297
			jobj=env->NewLocalRef((jobject)up);
			if (jobj == NULL){
				jobj=env->NewObject(friendClass,friendCtrId,(jlong)lfriend);
				linphone_friend_set_user_data(lfriend,(void*)env->NewWeakGlobalRef(jobj));
			}
		}
		env->DeleteLocalRef(friendClass);
	}
	return jobj;
}

298 299 300 301
jobject getEvent(JNIEnv *env, LinphoneEvent *lev){
	if (lev==NULL) return NULL;
	jobject jev=(jobject)linphone_event_get_user_data(lev);
	if (jev==NULL){
302
		jclass linphoneEventClass = (jclass)env->FindClass("org/linphone/core/LinphoneEventImpl");
303
		jmethodID linphoneEventCtrId = env->GetMethodID(linphoneEventClass,"<init>", "(J)V");
304

305 306 307
		jev=env->NewObject(linphoneEventClass,linphoneEventCtrId,(jlong)linphone_event_ref(lev));
		jev=env->NewGlobalRef(jev);
		linphone_event_set_user_data(lev,jev);
308

309
		env->DeleteLocalRef(linphoneEventClass);
310 311 312 313
	}
	return jev;
}

jehan's avatar
jehan committed
314 315
class LinphoneCoreData {
public:
316
	LinphoneCoreData(JNIEnv *env, jobject lc, LinphoneCoreVTable *vTable, jobject alistener) {
jehan's avatar
jehan committed
317 318
		core = env->NewGlobalRef(lc);
		listener = env->NewGlobalRef(alistener);
319

320
		memset(vTable, 0, sizeof(LinphoneCoreVTable));
321

322
		listenerClass = (jclass)env->NewGlobalRef(env->GetObjectClass(alistener));
323

jehan's avatar
jehan committed
324
		/*displayStatus(LinphoneCore lc,String message);*/
325
		displayStatusId = env->GetMethodID(listenerClass,"displayStatus","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;)V");
326 327 328
		if (displayStatusId) {
			vTable->display_status = displayStatusCb;
		}
329

jehan's avatar
jehan committed
330
		/*void generalState(LinphoneCore lc,int state); */
331 332
		globalStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$GlobalState"));
		globalStateFromIntId = env->GetStaticMethodID(globalStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$GlobalState;");
333
		globalStateId = env->GetMethodID(listenerClass,"globalState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$GlobalState;Ljava/lang/String;)V");
334 335 336
		if (globalStateId) {
			vTable->global_state_changed = globalStateChange;
		}
337

338 339 340
		/*registrationState(LinphoneCore lc, LinphoneProxyConfig cfg, LinphoneCore.RegistrationState cstate, String smessage);*/
		registrationStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RegistrationState"));
		registrationStateFromIntId = env->GetStaticMethodID(registrationStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RegistrationState;");
341
		registrationStateId = env->GetMethodID(listenerClass,"registrationState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneProxyConfig;Lorg/linphone/core/LinphoneCore$RegistrationState;Ljava/lang/String;)V");
342 343 344
		if (registrationStateId) {
			vTable->registration_state_changed = registrationStateChange;
		}
345

346 347 348
		/*callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State cstate,String message);*/
		callStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCall$State"));
		callStateFromIntId = env->GetStaticMethodID(callStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCall$State;");
349
		callStateId = env->GetMethodID(listenerClass,"callState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;Ljava/lang/String;)V");
350 351 352
		if (callStateId) {
			vTable->call_state_changed = callStateChange;
		}
353

354
		transferStateId = env->GetMethodID(listenerClass,"transferState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;)V");
355 356 357
		if (transferStateId) {
			vTable->transfer_state_changed = transferStateChanged;
		}
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
358

359 360
		/*callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats);*/
		callStatsUpdatedId = env->GetMethodID(listenerClass, "callStatsUpdated", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCallStats;)V");
361 362 363
		if (callStatsUpdatedId) {
			vTable->call_stats_updated = callStatsUpdated;
		}
364

365
		/*callEncryption(LinphoneCore lc, LinphoneCall call, boolean encrypted,String auth_token);*/
366 367 368 369
		callEncryptionChangedId = env->GetMethodID(listenerClass,"callEncryptionChanged","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;ZLjava/lang/String;)V");
		if (callEncryptionChangedId) {
			vTable->call_encryption_changed = callEncryptionChange;
		}
370

jehan's avatar
jehan committed
371 372 373
		/*void ecCalibrationStatus(LinphoneCore.EcCalibratorStatus status, int delay_ms, Object data);*/
		ecCalibratorStatusClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$EcCalibratorStatus"));
		ecCalibratorStatusFromIntId = env->GetStaticMethodID(ecCalibratorStatusClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;");
374
		ecCalibrationStatusId = env->GetMethodID(listenerClass,"ecCalibrationStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;ILjava/lang/Object;)V");
375

376
		/*void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url)*/
377
		newSubscriptionRequestId = env->GetMethodID(listenerClass,"newSubscriptionRequest","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;Ljava/lang/String;)V");
378 379 380
		if (newSubscriptionRequestId) {
			vTable->new_subscription_requested = new_subscription_requested;
		}
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
381

382
		authInfoRequestedId = env->GetMethodID(listenerClass,"authInfoRequested","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
383 384 385
		if (authInfoRequestedId) {
			vTable->auth_info_requested = authInfoRequested;
		}
386 387

		/*void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf);*/
388
		notifyPresenceReceivedId = env->GetMethodID(listenerClass,"notifyPresenceReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;)V");
389 390 391
		if (notifyPresenceReceivedId) {
			vTable->notify_presence_received = notify_presence_received;
		}
392

Simon Morlat's avatar
Simon Morlat committed
393
		messageReceivedId = env->GetMethodID(listenerClass,"messageReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V");
394 395 396
		if (messageReceivedId) {
			vTable->message_received = message_received;
		}
397

398
		isComposingReceivedId = env->GetMethodID(listenerClass,"isComposingReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;)V");
399 400 401
		if (isComposingReceivedId) {
			vTable->is_composing_received = is_composing_received;
		}
402

Sylvain Berfini's avatar
Sylvain Berfini committed
403
		dtmfReceivedId = env->GetMethodID(listenerClass,"dtmfReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;I)V");
404 405 406
		if (dtmfReceivedId) {
			vTable->dtmf_received = dtmf_received;
		}
407

408 409 410 411
		infoReceivedId = env->GetMethodID(listenerClass,"infoReceived", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneInfoMessage;)V");
		if (infoReceivedId) {
			vTable->info_received = infoReceived;
		}
412

413 414
		subscriptionStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/SubscriptionState"));
		subscriptionStateFromIntId = env->GetStaticMethodID(subscriptionStateClass,"fromInt","(I)Lorg/linphone/core/SubscriptionState;");
415
		subscriptionStateId = env->GetMethodID(listenerClass,"subscriptionStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Lorg/linphone/core/SubscriptionState;)V");
416 417 418
		if (subscriptionStateId) {
			vTable->subscription_state_changed = subscriptionStateChanged;
		}
419

420 421
		publishStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/PublishState"));
		publishStateFromIntId = env->GetStaticMethodID(publishStateClass,"fromInt","(I)Lorg/linphone/core/PublishState;");
422
		publishStateId = env->GetMethodID(listenerClass,"publishStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Lorg/linphone/core/PublishState;)V");
423 424 425
		if (publishStateId) {
			vTable->publish_state_changed = publishStateChanged;
		}
426

427 428 429 430
		notifyRecvId = env->GetMethodID(listenerClass,"notifyReceived", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Ljava/lang/String;Lorg/linphone/core/LinphoneContent;)V");
		if (notifyRecvId) {
			vTable->notify_received = notifyReceived;
		}
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
431

432 433
		configuringStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RemoteProvisioningState"));
		configuringStateFromIntId = env->GetStaticMethodID(configuringStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;");
434
		configuringStateId = env->GetMethodID(listenerClass,"configuringStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;Ljava/lang/String;)V");
435 436 437
		if (configuringStateId) {
			vTable->configuring_status = configuringStatus;
		}
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
438

439 440 441 442
		fileTransferProgressIndicationId = env->GetMethodID(listenerClass, "fileTransferProgressIndication", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;I)V");
		if (fileTransferProgressIndicationId) {
			vTable->file_transfer_progress_indication = fileTransferProgressIndication;
		}
443

444 445 446 447 448 449 450 451 452
		fileTransferSendId = env->GetMethodID(listenerClass, "fileTransferSend", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;Ljava/nio/ByteBuffer;I)I");
		if (fileTransferSendId) {
			vTable->file_transfer_send = fileTransferSend;
		}

		fileTransferRecvId = env->GetMethodID(listenerClass, "fileTransferRecv", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;[BI)V");
		if (fileTransferRecvId) {
			vTable->file_transfer_recv = fileTransferRecv;
		}
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
453

454 455
		logCollectionUploadStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$LogCollectionUploadState"));
		logCollectionUploadStateFromIntId = env->GetStaticMethodID(logCollectionUploadStateClass, "fromInt", "(I)Lorg/linphone/core/LinphoneCore$LogCollectionUploadState;");
Sylvain Berfini's avatar
Sylvain Berfini committed
456
		logCollectionUploadProgressId = env->GetMethodID(listenerClass, "uploadProgressIndication", "(Lorg/linphone/core/LinphoneCore;II)V");
457 458 459 460 461 462 463
		if (logCollectionUploadProgressId) {
			vTable->log_collection_upload_progress_indication = logCollectionUploadProgressIndication;
		}
		logCollectionUploadStateId = env->GetMethodID(listenerClass, "uploadStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$LogCollectionUploadState;Ljava/lang/String;)V");
		if (logCollectionUploadStateId) {
			vTable->log_collection_upload_state_changed = logCollectionUploadStateChange;
		}
464 465 466

		chatMessageStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatMessage$State"));
		chatMessageStateFromIntId = env->GetStaticMethodID(chatMessageStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneChatMessage$State;");
467

468
		proxyClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneProxyConfigImpl"));
469
		proxyCtrId = env->GetMethodID(proxyClass,"<init>", "(Lorg/linphone/core/LinphoneCoreImpl;J)V");
470 471 472

		callClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCallImpl"));
		callCtrId = env->GetMethodID(callClass,"<init>", "(J)V");
473 474
		callSetAudioStatsId = env->GetMethodID(callClass, "setAudioStats", "(Lorg/linphone/core/LinphoneCallStats;)V");
		callSetVideoStatsId = env->GetMethodID(callClass, "setVideoStats", "(Lorg/linphone/core/LinphoneCallStats;)V");
jehan's avatar
jehan committed
475

476
		chatMessageClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatMessageImpl"));
477 478 479
		if (chatMessageClass) {
			chatMessageCtrId = env->GetMethodID(chatMessageClass,"<init>", "(J)V");
		}
480

481 482 483 484
		chatRoomClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatRoomImpl"));
		chatRoomCtrId = env->GetMethodID(chatRoomClass,"<init>", "(J)V");

		friendClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneFriendImpl"));;
485
		friendCtrId = env->GetMethodID(friendClass,"<init>", "(J)V");
486

jehan's avatar
jehan committed
487
		addressClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAddressImpl"));
488
		addressCtrId = env->GetMethodID(addressClass,"<init>", "(J)V");
jehan's avatar
jehan committed
489

490 491
		callStatsClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCallStatsImpl"));
		callStatsId = env->GetMethodID(callStatsClass, "<init>", "(JJ)V");
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
492

493 494
		infoMessageClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneInfoMessageImpl"));
		infoMessageCtor = env->GetMethodID(infoMessageClass,"<init>", "(J)V");
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
495

496 497
		linphoneEventClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneEventImpl"));
		linphoneEventCtrId = env->GetMethodID(linphoneEventClass,"<init>", "(J)V");
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
498

499 500
		subscriptionDirClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/SubscriptionDir"));
		subscriptionDirFromIntId = env->GetStaticMethodID(subscriptionDirClass,"fromInt","(I)Lorg/linphone/core/SubscriptionDir;");
jehan's avatar
jehan committed
501 502 503 504 505 506 507
	}

	~LinphoneCoreData() {
		JNIEnv *env = 0;
		jvm->AttachCurrentThread(&env,NULL);
		env->DeleteGlobalRef(core);
		env->DeleteGlobalRef(listener);
508
		env->DeleteGlobalRef(listenerClass);
jehan's avatar
jehan committed
509
		env->DeleteGlobalRef(globalStateClass);
510
		env->DeleteGlobalRef(configuringStateClass);
jehan's avatar
jehan committed
511 512
		env->DeleteGlobalRef(registrationStateClass);
		env->DeleteGlobalRef(callStateClass);
513
		env->DeleteGlobalRef(chatMessageStateClass);
jehan's avatar
jehan committed
514 515
		env->DeleteGlobalRef(proxyClass);
		env->DeleteGlobalRef(callClass);
516
		env->DeleteGlobalRef(chatMessageClass);
517 518
		env->DeleteGlobalRef(chatRoomClass);
		env->DeleteGlobalRef(friendClass);
519
		env->DeleteGlobalRef(infoMessageClass);
520 521 522
		env->DeleteGlobalRef(linphoneEventClass);
		env->DeleteGlobalRef(subscriptionStateClass);
		env->DeleteGlobalRef(subscriptionDirClass);
523
		env->DeleteGlobalRef(logCollectionUploadStateClass);
jehan's avatar
jehan committed
524 525 526 527
	}
	jobject core;
	jobject listener;

528
	jclass listenerClass;
jehan's avatar
jehan committed
529
	jmethodID displayStatusId;
530 531
	jmethodID newSubscriptionRequestId;
	jmethodID notifyPresenceReceivedId;
532
	jmethodID messageReceivedId;
533
	jmethodID isComposingReceivedId;
Sylvain Berfini's avatar
Sylvain Berfini committed
534
	jmethodID dtmfReceivedId;
535
	jmethodID callStatsUpdatedId;
536
	jmethodID transferStateId;
537
	jmethodID infoReceivedId;
538
	jmethodID subscriptionStateId;
539
	jmethodID authInfoRequestedId;
540
	jmethodID publishStateId;
541
	jmethodID notifyRecvId;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
542

543 544 545
	jclass configuringStateClass;
	jmethodID configuringStateId;
	jmethodID configuringStateFromIntId;
546 547 548 549 550 551 552 553 554 555 556 557 558

	jclass globalStateClass;
	jmethodID globalStateId;
	jmethodID globalStateFromIntId;

	jclass registrationStateClass;
	jmethodID registrationStateId;
	jmethodID registrationStateFromIntId;

	jclass callStateClass;
	jmethodID callStateId;
	jmethodID callStateFromIntId;

559 560 561 562 563
	jclass callStatsClass;
	jmethodID callStatsId;
	jmethodID callSetAudioStatsId;
	jmethodID callSetVideoStatsId;

564 565 566
	jclass chatMessageStateClass;
	jmethodID chatMessageStateFromIntId;

567 568
	jmethodID callEncryptionChangedId;

jehan's avatar
jehan committed
569 570 571 572
	jclass ecCalibratorStatusClass;
	jmethodID ecCalibrationStatusId;
	jmethodID ecCalibratorStatusFromIntId;

573 574 575 576 577 578
	jclass proxyClass;
	jmethodID proxyCtrId;

	jclass callClass;
	jmethodID callCtrId;

579 580 581
	jclass chatMessageClass;
	jmethodID chatMessageCtrId;

582 583 584 585 586 587
	jclass chatRoomClass;
	jmethodID chatRoomCtrId;

	jclass friendClass;
	jmethodID friendCtrId;

jehan's avatar
jehan committed
588 589
	jclass addressClass;
	jmethodID addressCtrId;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
590

591 592
	jclass infoMessageClass;
	jmethodID infoMessageCtor;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
593

594 595
	jclass linphoneEventClass;
	jmethodID linphoneEventCtrId;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
596

597 598
	jclass subscriptionStateClass;
	jmethodID subscriptionStateFromIntId;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
599

600 601
	jclass publishStateClass;
	jmethodID publishStateFromIntId;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
602

603 604
	jclass subscriptionDirClass;
	jmethodID subscriptionDirFromIntId;
jehan's avatar
jehan committed
605

606
	jmethodID fileTransferProgressIndicationId;
607 608
	jmethodID fileTransferSendId;
	jmethodID fileTransferRecvId;
609

610 611 612 613 614
	jclass logCollectionUploadStateClass;
	jmethodID logCollectionUploadStateId;
	jmethodID logCollectionUploadStateFromIntId;
	jmethodID logCollectionUploadProgressId;

jehan's avatar
jehan committed
615
	LinphoneCoreVTable vTable;
616

jehan's avatar
jehan committed
617 618 619 620
	static void displayStatusCb(LinphoneCore *lc, const char *message) {
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
621
			ms_error("cannot attach VM");
jehan's avatar
jehan committed
622 623
			return;
		}
624 625
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
626 627
		jstring msg = message ? env->NewStringUTF(message) : NULL;
		env->CallVoidMethod(lcData->listener,lcData->displayStatusId,lcData->core,msg);
628
		handle_possible_java_exception(env, lcData->listener);
629 630 631
		if (msg) {
			env->DeleteLocalRef(msg);
		}
jehan's avatar
jehan committed
632
	}
633
	static void authInfoRequested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) {
634 635 636 637 638 639
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
			ms_error("cannot attach VM");
			return;
		}
640 641
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
642 643 644
		jstring r = realm ? env->NewStringUTF(realm) : NULL;
		jstring u = username ? env->NewStringUTF(username) : NULL;
		jstring d = domain ? env->NewStringUTF(domain) : NULL;
645 646 647
		env->CallVoidMethod(lcData->listener,
							lcData->authInfoRequestedId,
							lcData->core,
648 649 650
							r,
							u,
							d);
651
		handle_possible_java_exception(env, lcData->listener);
652 653 654 655 656 657 658 659 660
		if (r) {
			env->DeleteLocalRef(r);
		}
		if (u) {
			env->DeleteLocalRef(u);
		}
		if (d) {
			env->DeleteLocalRef(d);
		}
jehan's avatar
jehan committed
661
	}
662 663 664 665 666 667 668 669 670
	static void setCoreIfNotDone(JNIEnv *env, jobject jcore, LinphoneCore *lc){
		jclass objClass = env->GetObjectClass(jcore);
		jfieldID myFieldID = env->GetFieldID(objClass, "nativePtr", "J");
		jlong fieldVal = env->GetLongField(jcore, myFieldID);
		if (fieldVal == 0){
			env->SetLongField(jcore, myFieldID, (jlong)lc);
		}
	}
	
671 672 673 674
	static void globalStateChange(LinphoneCore *lc, LinphoneGlobalState gstate,const char* message) {
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
675
			ms_error("cannot attach VM");
676 677
			return;
		}
678 679
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
680 681 682 683 684
		
		jobject jcore = lcData->core;
		/*at this stage, the java object may not be aware of its C object, because linphone_core_new() hasn't returned yet.*/
		setCoreIfNotDone(env,jcore, lc);
		
685
		jstring msg = message ? env->NewStringUTF(message) : NULL;
686 687 688
		env->CallVoidMethod(lcData->listener
							,lcData->globalStateId
							,lcData->core
jehan's avatar
jehan committed
689
							,env->CallStaticObjectMethod(lcData->globalStateClass,lcData->globalStateFromIntId,(jint)gstate),
690
							msg);
691
		handle_possible_java_exception(env, lcData->listener);
692 693 694
		if (msg) {
			env->DeleteLocalRef(msg);
		}
695
	}
jehan's avatar
jehan committed
696
	static void registrationStateChange(LinphoneCore *lc, LinphoneProxyConfig* proxy,LinphoneRegistrationState state,const char* message) {
jehan's avatar
jehan committed
697 698
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
699
		jobject jproxy;
jehan's avatar
jehan committed
700
		if (result != 0) {
701
			ms_error("cannot attach VM");
jehan's avatar
jehan committed
702 703
			return;
		}
704 705
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
706
		jstring msg = message ? env->NewStringUTF(message) : NULL;
jehan's avatar
jehan committed
707
		env->CallVoidMethod(lcData->listener
708
							,lcData->registrationStateId
jehan's avatar
jehan committed
709
							,lcData->core
710
							,(jproxy=getProxy(env,proxy,lcData->core))
jehan's avatar
jehan committed
711
							,env->CallStaticObjectMethod(lcData->registrationStateClass,lcData->registrationStateFromIntId,(jint)state),
712
							msg);
713
		handle_possible_java_exception(env, lcData->listener);
714 715 716
		if (msg) {
			env->DeleteLocalRef(msg);
		}
jehan's avatar
jehan committed
717
	}
718

jehan's avatar
jehan committed
719
	static void callStateChange(LinphoneCore *lc, LinphoneCall* call,LinphoneCallState state,const char* message) {
720 721
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
722
		jobject jcall;
723
		if (result != 0) {
724
			ms_error("cannot attach VM");
725 726
			return;
		}
727 728
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
729
		jstring msg = message ? env->NewStringUTF(message) : NULL;
730 731 732
		env->CallVoidMethod(lcData->listener
							,lcData->callStateId
							,lcData->core
733
							,(jcall=getCall(env,call))
jehan's avatar
jehan committed
734
							,env->CallStaticObjectMethod(lcData->callStateClass,lcData->callStateFromIntId,(jint)state),
735
							msg);
736
		handle_possible_java_exception(env, lcData->listener);
737
		if (state==LinphoneCallReleased) {
738 739 740
			linphone_call_set_user_pointer(call,NULL);
			env->DeleteGlobalRef(jcall);
		}
741 742 743
		if (msg) {
			env->DeleteLocalRef(msg);
		}
744
	}
745 746 747 748
	static void callEncryptionChange(LinphoneCore *lc, LinphoneCall* call, bool_t encrypted,const char* authentication_token) {
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
749
			ms_error("cannot attach VM");
750 751
			return;
		}
752 753
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
754 755 756
		env->CallVoidMethod(lcData->listener
							,lcData->callEncryptionChangedId
							,lcData->core
757
							,getCall(env,call)
758 759
							,encrypted
							,authentication_token ? env->NewStringUTF(authentication_token) : NULL);
760
		handle_possible_java_exception(env, lcData->listener);
761
	}
762
	static void notify_presence_received(LinphoneCore *lc,  LinphoneFriend *my_friend) {
763 764 765
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
766
			ms_error("cannot attach VM");
767 768
			return;
		}
769 770
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
771 772 773
		env->CallVoidMethod(lcData->listener
							,lcData->notifyPresenceReceivedId
							,lcData->core
Margaux Clerc's avatar
Margaux Clerc committed
774
							,getFriend(env,my_friend));
775
		handle_possible_java_exception(env, lcData->listener);
776
	}
777
	static void new_subscription_requested(LinphoneCore *lc,  LinphoneFriend *my_friend, const char* url) {
778 779 780
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
781
			ms_error("cannot attach VM");
782 783
			return;
		}
784 785
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
786 787 788
		env->CallVoidMethod(lcData->listener
							,lcData->newSubscriptionRequestId
							,lcData->core
Margaux Clerc's avatar
Margaux Clerc committed
789
							,getFriend(env,my_friend)
790
							,url ? env->NewStringUTF(url) : NULL);
791
		handle_possible_java_exception(env, lcData->listener);
792
	}
Sylvain Berfini's avatar
Sylvain Berfini committed
793 794 795 796
	static void dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf) {
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
797
			ms_error("cannot attach VM");
Sylvain Berfini's avatar
Sylvain Berfini committed
798 799
			return;
		}
800 801
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
Sylvain Berfini's avatar
Sylvain Berfini committed
802 803 804
		env->CallVoidMethod(lcData->listener
							,lcData->dtmfReceivedId
							,lcData->core
805
							,getCall(env,call)
Sylvain Berfini's avatar
Sylvain Berfini committed
806
							,dtmf);
807
		handle_possible_java_exception(env, lcData->listener);
Sylvain Berfini's avatar
Sylvain Berfini committed
808
	}
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
809
	static void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
810 811 812 813 814 815
		JNIEnv *env = 0;
		jobject jmsg;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
			ms_error("cannot attach VM");
			return;
816
		}
817 818 819 820 821 822 823 824
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
		/*note: we call linphone_chat_message_ref() because the application does not acquire the object when invoked from a callback*/
		env->CallVoidMethod(lcData->listener
							,lcData->messageReceivedId
							,lcData->core
							,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room)
							,(jmsg = getChatMessage(env, msg)));
825
		handle_possible_java_exception(env, lcData->listener);
826
	}
827 828 829 830 831 832 833
	static void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
			ms_error("cannot attach VM");
			return;
		}
834 835
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
836 837 838 839
		env->CallVoidMethod(lcData->listener
							,lcData->isComposingReceivedId
							,lcData->core
							,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room));
840
		handle_possible_java_exception(env, lcData->listener);
841
	}
jehan's avatar
jehan committed
842 843 844 845
	static void ecCalibrationStatus(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data) {
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
846
			ms_error("cannot attach VM");
jehan's avatar
jehan committed
847 848
			return;
		}
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
849

850 851 852 853 854 855 856 857 858 859
		LinphoneCoreVTable *table = (LinphoneCoreVTable*) data;
		if (table) {
			LinphoneCoreData* lcData = (LinphoneCoreData*) linphone_core_v_table_get_user_data(table);
			if (lcData->ecCalibrationStatusId) {
				jobject state = env->CallStaticObjectMethod(lcData->ecCalibratorStatusClass, lcData->ecCalibratorStatusFromIntId, (jint)status);
				env->CallVoidMethod(lcData->listener
								,lcData->ecCalibrationStatusId
								,lcData->core
								,state
								,delay_ms
860
								,NULL);
861
				handle_possible_java_exception(env, lcData->listener);
862 863 864 865
			}
			if (status != LinphoneEcCalibratorInProgress) {
				linphone_core_v_table_destroy(table);
			}
jehan's avatar
jehan committed
866 867 868
		}

	}
869 870 871 872 873 874
	static void callStatsUpdated(LinphoneCore *lc, LinphoneCall* call, const LinphoneCallStats *stats) {
		JNIEnv *env = 0;
		jobject statsobj;
		jobject callobj;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
875
			ms_error("cannot attach VM");
876 877
			return;
		}
878 879
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
880
		statsobj = env->NewObject(lcData->callStatsClass, lcData->callStatsId, (jlong)call, (jlong)stats);
881
		callobj = getCall(env, call);
882 883 884 885 886
		if (stats->type == LINPHONE_CALL_STATS_AUDIO)
			env->CallVoidMethod(callobj, lcData->callSetAudioStatsId, statsobj);
		else
			env->CallVoidMethod(callobj, lcData->callSetVideoStatsId, statsobj);
		env->CallVoidMethod(lcData->listener, lcData->callStatsUpdatedId, lcData->core, callobj, statsobj);
887
		handle_possible_java_exception(env, lcData->listener);
888
		if (statsobj) env->DeleteLocalRef(statsobj);
889
	}
890 891 892 893 894
	static void transferStateChanged(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState remote_call_state){
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		jobject jcall;
		if (result != 0) {
895
			ms_error("cannot attach VM");
896 897
			return;
		}
898 899
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);