linphonecore_jni.cc 354 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
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
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 19
 */
#include <jni.h>
20
#ifdef USE_JAVAH
21
#include "linphonecore_jni.h"
22
#endif
23
#include "linphone/core_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"
30
#include "mediastreamer2/msmediaplayer.h"
31
#include "mediastreamer2/msutils.h"
32
#include "mediastreamer2/devices.h"
33
}
Simon Morlat's avatar
Simon Morlat committed
34
#include "mediastreamer2/msjava.h"
35 36
#include "linphone/core.h"
#include "linphone/tunnel.h"
37
#include "linphone/account_creator.h"
38
#include "linphone/wrapper_utils.h"
39 40

#include "private.h" /*Included for multicast and wifi lock management by linphonecore. Very ugly.*/
41 42
#include <cpu-features.h>

43
#include "linphone/lpconfig.h"
44

45
#ifdef __ANDROID__
46
#include <android/log.h>
47
#include <belle-sip/wakelock.h>
48
#endif /* __ANDROID__ */
49

Ghislain MARY's avatar
Ghislain MARY committed
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
#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; \
	}

67
static JavaVM *jvm=0;
68
static const char* LogDomain = "Linphone";
69 70 71
static jclass handler_class;
static jmethodID loghandler_id;
static jobject handler_obj=NULL;
72

73
static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent *content);
74
static jobject create_java_linphone_buffer(JNIEnv *env, const LinphoneBuffer *buffer);
75
static LinphoneBuffer* create_c_linphone_buffer_from_java_linphone_buffer(JNIEnv *env, jobject jbuffer);
76
static jobject getTunnelConfig(JNIEnv *env, LinphoneTunnelConfig *cfg);
77

78
#ifdef __ANDROID__
79
void linphone_android_log_handler(int prio, char *str) {
80 81
	char *current;
	char *next;
82 83

	if (strlen(str) < 512) {
84
		__android_log_write(prio, LogDomain, str);
85 86 87
	} else {
		current = str;
		while ((next = strchr(current, '\n')) != NULL) {
88

89
			*next = '\0';
90 91
			if (next != str && next[-1] == '\r')
				next[-1] = '\0';
92
			__android_log_write(prio, LogDomain, current);
93 94
			current = next + 1;
		}
95
		__android_log_write(prio, LogDomain, current);
96
	}
97
}
98

Sylvain Berfini's avatar
Sylvain Berfini committed
99 100 101 102 103 104
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreFactoryImpl__1setLogHandler(JNIEnv *env, jobject jfactory, jobject jhandler) {
	if (handler_obj) {
		env->DeleteGlobalRef(handler_obj);
		handler_obj = NULL;
	}
	if (jhandler) {
105 106
		handler_class = (jclass) env->GetObjectClass(jhandler);
		loghandler_id = env->GetMethodID(handler_class, "log", "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)V");
107

108 109 110
		if (loghandler_id == NULL) {
			ms_fatal("log method not found");
		}
Sylvain Berfini's avatar
Sylvain Berfini committed
111 112 113 114
		handler_obj = env->NewGlobalRef(jhandler);
	}
}

Simon Morlat's avatar
Simon Morlat committed
115
static void linphone_android_ortp_log_handler(const char *domain, OrtpLogLevel lev, const char *fmt, va_list args) {
Erwan Croze's avatar
Erwan Croze committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
	char* str = bctbx_strdup_vprintf(fmt, args);
    const char *levname = "undef";

    if (str == NULL) return;

    int prio;
    switch(lev) {
    	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;
    }

    if (handler_obj) {
    	JNIEnv *env = ms_get_jni_env();
    	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);
    } else {
    	linphone_android_log_handler(prio, str);
    }
    bctbx_free(str);
144 145
}

146 147 148
int dumbMethodForAllowingUsageOfCpuFeaturesFromStaticLibMediastream() {
	return (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0);
}
149 150 151 152

int dumbMethodForAllowingUsageOfMsAudioDiffFromStaticLibMediastream() {
	return ms_audio_diff(NULL, NULL, NULL, 0, NULL, NULL);
}
153 154 155 156

extern "C" void setAndroidLogHandler() {
	linphone_core_enable_logs_with_cb(linphone_android_ortp_log_handler);
}
157 158 159 160 161 162

extern "C" void setMediastreamerAndroidContext(JNIEnv *env, void *context) {
	jclass ms_class = env->FindClass("org/linphone/mediastream/MediastreamerAndroidContext");
	jmethodID set_context = env->GetStaticMethodID(ms_class, "setContext", "(Ljava/lang/Object;)V");
	env->CallStaticVoidMethod(ms_class, set_context, (jobject)context);
}
163
#endif /* __ANDROID__ */
164

165

166 167
JNIEXPORT jint JNICALL  JNI_OnLoad(JavaVM *ajvm, void *reserved)
{
168
#ifdef __ANDROID__
Simon Morlat's avatar
Simon Morlat committed
169
	ms_set_jvm(ajvm);
170
#endif /* __ANDROID__ */
171 172 173 174
	jvm=ajvm;
	return JNI_VERSION_1_2;
}

175 176 177 178 179 180 181 182
static const char* GetStringUTFChars(JNIEnv* env, jstring string) {
	const char *cstring = string ? env->GetStringUTFChars(string, NULL) : NULL;
	return cstring;
}

static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char *cstring) {
	if (string) env->ReleaseStringUTFChars(string, cstring);
}
183

jehan's avatar
jehan committed
184
//LinphoneFactory
jehan's avatar
jehan committed
185
extern "C" void Java_org_linphone_core_LinphoneCoreFactoryImpl_setDebugMode(JNIEnv*  env
jehan's avatar
jehan committed
186
		,jobject  thiz
187 188
		,jboolean isDebug
		,jstring  jdebugTag) {
jehan's avatar
jehan committed
189
	if (isDebug) {
190
		LogDomain = GetStringUTFChars(env, jdebugTag);
191
		linphone_core_enable_logs_with_cb(linphone_android_ortp_log_handler);
jehan's avatar
jehan committed
192 193 194 195
	} else {
		linphone_core_disable_logs();
	}
}
196

197 198 199 200 201 202 203 204
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;
}

205 206 207 208 209 210 211 212 213 214
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) {

215
	const char* path = GetStringUTFChars(env, jpath);
216
	linphone_core_set_log_collection_path(path);
217
	ReleaseStringUTFChars(env, jpath, path);
218
}
Erwan Croze's avatar
Erwan Croze committed
219

220 221 222 223
extern "C" jlong Java_org_linphone_core_LinphoneCoreFactoryImpl_createErrorInfoNative(JNIEnv*  env, jobject  thiz){
	return (jlong)linphone_factory_create_error_info(linphone_factory_get());
}

Erwan Croze's avatar
Erwan Croze committed
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreFactoryImpl_getAllDialPlanNative(JNIEnv *env, jobject thiz) {
	LinphoneDialPlan *countries;
	jclass addr_class = env->FindClass("org/linphone/core/DialPlanImpl");
	jmethodID addr_constructor = env->GetMethodID(addr_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)V");
	jobjectArray jaddr_array;
	int i, size = 0;
	countries = (LinphoneDialPlan *)linphone_dial_plan_get_all();

	while (countries[size].country != NULL) size++;

	jaddr_array = env->NewObjectArray(size, addr_class, NULL);

	for (i=0; i < size ; i++) {
		jstring jcountry = env->NewStringUTF(countries[i].country);
		jstring jiso = env->NewStringUTF(countries[i].iso_country_code);
		jstring jccc = env->NewStringUTF(countries[i].ccc);
		jint jnnl = (jint)countries[i].nnl;
		jstring jicp = env->NewStringUTF(countries[i].icp);

		jobject jaddr = env->NewObject(addr_class, addr_constructor, jcountry, jiso, jccc, jnnl, jicp);

		env->SetObjectArrayElement(jaddr_array, i, jaddr);

		env->DeleteLocalRef(jcountry);
		env->DeleteLocalRef(jiso);
		env->DeleteLocalRef(jccc);
		env->DeleteLocalRef(jicp);
	}
	return jaddr_array;
}

255 256
// LinphoneCore

Sylvain Berfini's avatar
Sylvain Berfini committed
257
class LinphoneJavaBindings {
258
public:
Sylvain Berfini's avatar
Sylvain Berfini committed
259 260
	LinphoneJavaBindings(JNIEnv *env) {
		listenerClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCoreListener"));
261

262 263
		authMethodClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$AuthMethod"));
		authMethodFromIntId = env->GetStaticMethodID(authMethodClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$AuthMethod;");
264

265
		/*displayStatus(LinphoneCore lc,String message);*/
266
		displayStatusId = env->GetMethodID(listenerClass,"displayStatus","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;)V");
267

268
		/*void generalState(LinphoneCore lc,int state); */
269 270
		globalStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$GlobalState"));
		globalStateFromIntId = env->GetStaticMethodID(globalStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$GlobalState;");
271
		globalStateId = env->GetMethodID(listenerClass,"globalState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$GlobalState;Ljava/lang/String;)V");
272

273 274 275
		/*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;");
276
		registrationStateId = env->GetMethodID(listenerClass,"registrationState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneProxyConfig;Lorg/linphone/core/LinphoneCore$RegistrationState;Ljava/lang/String;)V");
277

278 279 280
		/*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;");
281
		callStateId = env->GetMethodID(listenerClass,"callState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;Ljava/lang/String;)V");
282

283
		transferStateId = env->GetMethodID(listenerClass,"transferState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;)V");
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
284

285 286 287
		/*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");

288
		/*callEncryption(LinphoneCore lc, LinphoneCall call, boolean encrypted,String auth_token);*/
289
		callEncryptionChangedId = env->GetMethodID(listenerClass,"callEncryptionChanged","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;ZLjava/lang/String;)V");
290

jehan's avatar
jehan committed
291 292 293
		/*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;");
294
		ecCalibrationStatusId = env->GetMethodID(listenerClass,"ecCalibrationStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;ILjava/lang/Object;)V");
295

296
		/*void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url)*/
297
		newSubscriptionRequestId = env->GetMethodID(listenerClass,"newSubscriptionRequest","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;Ljava/lang/String;)V");
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
298

299 300
		authInfoRequestedId = env->GetMethodID(listenerClass,"authInfoRequested","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
		authenticationRequestedId = env->GetMethodID(listenerClass,"authenticationRequested","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneAuthInfo;Lorg/linphone/core/LinphoneCore$AuthMethod;)V");
301 302

		/*void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf);*/
303
		notifyPresenceReceivedId = env->GetMethodID(listenerClass,"notifyPresenceReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;)V");
304

Simon Morlat's avatar
Simon Morlat committed
305
		messageReceivedId = env->GetMethodID(listenerClass,"messageReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V");
306

307 308
		messageReceivedUnableToDecryptedId = env->GetMethodID(listenerClass,"messageReceivedUnableToDecrypted","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V");

309
		isComposingReceivedId = env->GetMethodID(listenerClass,"isComposingReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;)V");
310

Sylvain Berfini's avatar
Sylvain Berfini committed
311
		dtmfReceivedId = env->GetMethodID(listenerClass,"dtmfReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;I)V");
312

313
		infoReceivedId = env->GetMethodID(listenerClass,"infoReceived", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneInfoMessage;)V");
314

315 316
		subscriptionStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/SubscriptionState"));
		subscriptionStateFromIntId = env->GetStaticMethodID(subscriptionStateClass,"fromInt","(I)Lorg/linphone/core/SubscriptionState;");
317
		subscriptionStateId = env->GetMethodID(listenerClass,"subscriptionStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Lorg/linphone/core/SubscriptionState;)V");
318

319 320
		publishStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/PublishState"));
		publishStateFromIntId = env->GetStaticMethodID(publishStateClass,"fromInt","(I)Lorg/linphone/core/PublishState;");
321
		publishStateId = env->GetMethodID(listenerClass,"publishStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Lorg/linphone/core/PublishState;)V");
322

323
		notifyRecvId = env->GetMethodID(listenerClass,"notifyReceived", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Ljava/lang/String;Lorg/linphone/core/LinphoneContent;)V");
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
324

325 326
		networkReachableId = env->GetMethodID(listenerClass,"networkReachableChanged", "(Lorg/linphone/core/LinphoneCore;Z)V");

327 328
		configuringStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RemoteProvisioningState"));
		configuringStateFromIntId = env->GetStaticMethodID(configuringStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;");
329
		configuringStateId = env->GetMethodID(listenerClass,"configuringStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;Ljava/lang/String;)V");
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
330

331
		fileTransferProgressIndicationId = env->GetMethodID(listenerClass, "fileTransferProgressIndication", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;I)V");
332

333 334 335
		fileTransferSendId = env->GetMethodID(listenerClass, "fileTransferSend", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;Ljava/nio/ByteBuffer;I)I");

		fileTransferRecvId = env->GetMethodID(listenerClass, "fileTransferRecv", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;[BI)V");
336

337 338
		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
339
		logCollectionUploadProgressId = env->GetMethodID(listenerClass, "uploadProgressIndication", "(Lorg/linphone/core/LinphoneCore;II)V");
340
		logCollectionUploadStateId = env->GetMethodID(listenerClass, "uploadStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$LogCollectionUploadState;Ljava/lang/String;)V");
341 342 343

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

345 346
		authInfoClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAuthInfoImpl"));
		authInfoCtrId = env->GetMethodID(authInfoClass,"<init>", "(J)V");
347

348
		proxyClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneProxyConfigImpl"));
349
		proxyCtrId = env->GetMethodID(proxyClass,"<init>", "(Lorg/linphone/core/LinphoneCoreImpl;J)V");
350 351 352

		callClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCallImpl"));
		callCtrId = env->GetMethodID(callClass,"<init>", "(J)V");
353

354
		chatMessageClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatMessageImpl"));
355 356 357
		if (chatMessageClass) {
			chatMessageCtrId = env->GetMethodID(chatMessageClass,"<init>", "(J)V");
		}
358

359 360 361
		chatRoomClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatRoomImpl"));
		chatRoomCtrId = env->GetMethodID(chatRoomClass,"<init>", "(J)V");

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

365
		friendListClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneFriendListImpl"));
366 367 368
		friendListCtrId = env->GetMethodID(friendListClass,"<init>", "(J)V");
		friendListCreatedId = env->GetMethodID(listenerClass, "friendListCreated", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriendList;)V");
		friendListRemovedId = env->GetMethodID(listenerClass, "friendListRemoved", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriendList;)V");
369 370
		friendListSyncStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneFriendList$State"));
		friendListSyncStateFromIntId = env->GetStaticMethodID(friendListSyncStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneFriendList$State;");
371

372 373 374
		natPolicyClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneNatPolicyImpl"));
		natPolicyCtrId = env->GetMethodID(natPolicyClass, "<init>", "(J)V");

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

378
		callStatsClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCallStatsImpl"));
379
		callStatsId = env->GetMethodID(callStatsClass, "<init>", "(J)V");
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
380

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

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

387 388
		subscriptionDirClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/SubscriptionDir"));
		subscriptionDirFromIntId = env->GetStaticMethodID(subscriptionDirClass,"fromInt","(I)Lorg/linphone/core/SubscriptionDir;");
389

390 391
		msFactoryClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/mediastream/Factory"));
		msFactoryCtrId = env->GetMethodID(msFactoryClass,"<init>", "(J)V");
392

393 394
		accountCreatorClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAccountCreatorImpl"));
		accountCreatorCtrId = env->GetMethodID(accountCreatorClass, "<init>", "(J)V");
Erwan Croze's avatar
Erwan Croze committed
395 396 397 398 399 400 401 402 403 404 405 406 407 408
		accountCreatorRequestStatusClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAccountCreator$RequestStatus"));
		accountCreatorRequestStatusFromIntId = env->GetStaticMethodID(accountCreatorRequestStatusClass,"fromInt","(I)Lorg/linphone/core/LinphoneAccountCreator$RequestStatus;");
		accountCreatorUsernameCheckClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAccountCreator$UsernameCheck"));
		accountCreatorUsernameCheckFromIntId = env->GetStaticMethodID(accountCreatorUsernameCheckClass,"fromInt","(I)Lorg/linphone/core/LinphoneAccountCreator$UsernameCheck;");
		accountCreatorPasswordCheckClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAccountCreator$PasswordCheck"));
		accountCreatorPasswordCheckFromIntId = env->GetStaticMethodID(accountCreatorPasswordCheckClass,"fromInt","(I)Lorg/linphone/core/LinphoneAccountCreator$PasswordCheck;");
		accountCreatorEmailCheckClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAccountCreator$EmailCheck"));
		accountCreatorEmailCheckFromIntId = env->GetStaticMethodID(accountCreatorEmailCheckClass,"fromInt","(I)Lorg/linphone/core/LinphoneAccountCreator$EmailCheck;");
		accountCreatorLanguageCheckClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAccountCreator$LanguageCheck"));
		accountCreatorLanguageCheckFromIntId = env->GetStaticMethodID(accountCreatorLanguageCheckClass,"fromInt","(I)Lorg/linphone/core/LinphoneAccountCreator$LanguageCheck;");
		accountCreatorCodeActivationCheckClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAccountCreator$ActivationCodeCheck"));
		accountCreatorCodeActivationCheckFromIntId = env->GetStaticMethodID(accountCreatorCodeActivationCheckClass,"fromInt","(I)Lorg/linphone/core/LinphoneAccountCreator$ActivationCodeCheck;");
		accountCreatorPhoneNumberCheckClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAccountCreator$PhoneNumberCheck"));
		accountCreatorPhoneNumberCheckFromIntId = env->GetStaticMethodID(accountCreatorPhoneNumberCheckClass,"fromInt","(I)Lorg/linphone/core/LinphoneAccountCreator$PhoneNumberCheck;");
409
	}
410

Sylvain Berfini's avatar
Sylvain Berfini committed
411 412 413
	void setCore(jobject c) {
		core = c;
	}
414

Sylvain Berfini's avatar
Sylvain Berfini committed
415 416 417
	jobject getCore() {
		return core;
	}
418

Sylvain Berfini's avatar
Sylvain Berfini committed
419
	~LinphoneJavaBindings() {
420 421
		JNIEnv *env = 0;
		jvm->AttachCurrentThread(&env,NULL);
422
		env->DeleteGlobalRef(listenerClass);
423
		env->DeleteGlobalRef(authMethodClass);
424
		env->DeleteGlobalRef(globalStateClass);
425
		env->DeleteGlobalRef(configuringStateClass);
426 427
		env->DeleteGlobalRef(registrationStateClass);
		env->DeleteGlobalRef(callStateClass);
428
		env->DeleteGlobalRef(chatMessageStateClass);
429
		env->DeleteGlobalRef(authInfoClass);
430 431
		env->DeleteGlobalRef(proxyClass);
		env->DeleteGlobalRef(callClass);
432
		env->DeleteGlobalRef(chatMessageClass);
433 434
		env->DeleteGlobalRef(chatRoomClass);
		env->DeleteGlobalRef(friendClass);
435
		env->DeleteGlobalRef(friendListClass);
436
		env->DeleteGlobalRef(friendListSyncStateClass);
437
		env->DeleteGlobalRef(natPolicyClass);
438
		env->DeleteGlobalRef(infoMessageClass);
439 440 441
		env->DeleteGlobalRef(linphoneEventClass);
		env->DeleteGlobalRef(subscriptionStateClass);
		env->DeleteGlobalRef(subscriptionDirClass);
442
		env->DeleteGlobalRef(logCollectionUploadStateClass);
443
		env->DeleteGlobalRef(msFactoryClass);
444
		env->DeleteGlobalRef(accountCreatorClass);
Erwan Croze's avatar
Erwan Croze committed
445 446 447 448 449 450 451
		env->DeleteGlobalRef(accountCreatorRequestStatusClass);
		env->DeleteGlobalRef(accountCreatorUsernameCheckClass);
		env->DeleteGlobalRef(accountCreatorPasswordCheckClass);
		env->DeleteGlobalRef(accountCreatorEmailCheckClass);
		env->DeleteGlobalRef(accountCreatorLanguageCheckClass);
		env->DeleteGlobalRef(accountCreatorCodeActivationCheckClass);
		env->DeleteGlobalRef(accountCreatorPhoneNumberCheckClass);
452
	}
453

454 455
	jobject core;

456
	jclass listenerClass;
457
	jmethodID displayStatusId;
458 459
	jmethodID newSubscriptionRequestId;
	jmethodID notifyPresenceReceivedId;
460
	jmethodID messageReceivedId;
461
	jmethodID messageReceivedUnableToDecryptedId;
462
	jmethodID isComposingReceivedId;
Sylvain Berfini's avatar
Sylvain Berfini committed
463
	jmethodID dtmfReceivedId;
464
	jmethodID callStatsUpdatedId;
465
	jmethodID transferStateId;
466
	jmethodID infoReceivedId;
467
	jmethodID subscriptionStateId;
468
	jmethodID authInfoRequestedId;
469
	jmethodID authenticationRequestedId;
470
	jmethodID publishStateId;
471
	jmethodID notifyRecvId;
472
	jmethodID networkReachableId;
473

474 475
	jclass authMethodClass;
	jmethodID authMethodFromIntId;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
476

477 478 479
	jclass configuringStateClass;
	jmethodID configuringStateId;
	jmethodID configuringStateFromIntId;
480 481 482 483 484 485 486 487 488 489 490 491 492

	jclass globalStateClass;
	jmethodID globalStateId;
	jmethodID globalStateFromIntId;

	jclass registrationStateClass;
	jmethodID registrationStateId;
	jmethodID registrationStateFromIntId;

	jclass callStateClass;
	jmethodID callStateId;
	jmethodID callStateFromIntId;

493 494 495
	jclass callStatsClass;
	jmethodID callStatsId;

496 497 498
	jclass chatMessageStateClass;
	jmethodID chatMessageStateFromIntId;

499 500
	jmethodID callEncryptionChangedId;

jehan's avatar
jehan committed
501 502 503
	jclass ecCalibratorStatusClass;
	jmethodID ecCalibrationStatusId;
	jmethodID ecCalibratorStatusFromIntId;
504

505 506
	jclass authInfoClass;
	jmethodID authInfoCtrId;
jehan's avatar
jehan committed
507

508 509 510 511 512 513
	jclass proxyClass;
	jmethodID proxyCtrId;

	jclass callClass;
	jmethodID callCtrId;

514 515 516
	jclass chatMessageClass;
	jmethodID chatMessageCtrId;

517 518 519 520 521 522
	jclass chatRoomClass;
	jmethodID chatRoomCtrId;

	jclass friendClass;
	jmethodID friendCtrId;

523 524 525 526
	jclass friendListClass;
	jmethodID friendListCtrId;
	jmethodID friendListCreatedId;
	jmethodID friendListRemovedId;
527 528
	jclass friendListSyncStateClass;
	jmethodID friendListSyncStateFromIntId;
529

530 531 532
	jclass natPolicyClass;
	jmethodID natPolicyCtrId;

jehan's avatar
jehan committed
533 534
	jclass addressClass;
	jmethodID addressCtrId;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
535

536 537
	jclass infoMessageClass;
	jmethodID infoMessageCtor;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
538

539 540
	jclass linphoneEventClass;
	jmethodID linphoneEventCtrId;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
541

542 543
	jclass subscriptionStateClass;
	jmethodID subscriptionStateFromIntId;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
544

545 546
	jclass publishStateClass;
	jmethodID publishStateFromIntId;
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
547

548 549
	jclass subscriptionDirClass;
	jmethodID subscriptionDirFromIntId;
jehan's avatar
jehan committed
550

551
	jmethodID fileTransferProgressIndicationId;
552 553
	jmethodID fileTransferSendId;
	jmethodID fileTransferRecvId;
554

555 556 557 558
	jclass logCollectionUploadStateClass;
	jmethodID logCollectionUploadStateId;
	jmethodID logCollectionUploadStateFromIntId;
	jmethodID logCollectionUploadProgressId;
559

560 561
	jclass msFactoryClass;
	jmethodID msFactoryCtrId;
562

563 564
	jclass accountCreatorClass;
	jmethodID accountCreatorCtrId;
Erwan Croze's avatar
Erwan Croze committed
565 566 567 568 569 570 571 572 573 574 575 576 577 578
	jclass accountCreatorRequestStatusClass;
	jmethodID accountCreatorRequestStatusFromIntId;
	jclass accountCreatorUsernameCheckClass;
	jmethodID accountCreatorUsernameCheckFromIntId;
	jclass accountCreatorPasswordCheckClass;
	jmethodID accountCreatorPasswordCheckFromIntId;
	jclass accountCreatorEmailCheckClass;
	jmethodID accountCreatorEmailCheckFromIntId;
	jclass accountCreatorLanguageCheckClass;
	jmethodID accountCreatorLanguageCheckFromIntId;
	jclass accountCreatorCodeActivationCheckClass;
	jmethodID accountCreatorCodeActivationCheckFromIntId;
	jclass accountCreatorPhoneNumberCheckClass;
	jmethodID accountCreatorPhoneNumberCheckFromIntId;
Sylvain Berfini's avatar
Sylvain Berfini committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
};

/*
 * returns the java LinphoneProxyConfig associated with a C LinphoneProxyConfig.
**/
jobject getProxy(JNIEnv *env, LinphoneProxyConfig *proxy, jobject core){
	jobject jobj=0;

	if (proxy!=NULL){
		LinphoneCore *lc = linphone_proxy_config_get_core(proxy);
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);

		void *up=linphone_proxy_config_get_user_data(proxy);

		if (up==NULL){
			jobj=env->NewObject(ljb->proxyClass, ljb->proxyCtrId, core, (jlong)proxy);
			linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj));
			linphone_proxy_config_ref(proxy);
		}else{
598
 			//promote the weak ref to local ref
Sylvain Berfini's avatar
Sylvain Berfini committed
599 600 601 602 603 604 605 606 607 608 609
			jobj=env->NewLocalRef((jobject)up);
			if (jobj == NULL){
				//the weak ref was dead
				jobj=env->NewObject(ljb->proxyClass, ljb->proxyCtrId, core, (jlong)proxy);
				linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj));
			}
		}
	}
	return jobj;
}

610 611 612 613 614 615 616 617 618 619
jobject getAuthInfo(JNIEnv *env, LinphoneCore *lc, LinphoneAuthInfo *authInfo, jobject core){
	jobject jobj = 0;

	if (authInfo && lc) {
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
		jobj = env->NewObject(ljb->authInfoClass, ljb->authInfoCtrId, core, (jlong)authInfo);
	}
	return jobj;
}

Sylvain Berfini's avatar
Sylvain Berfini committed
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
jobject getCall(JNIEnv *env, LinphoneCall *call){
	jobject jobj=0;

	if (call!=NULL){
		LinphoneCore *lc = linphone_call_get_core(call);
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);

		void *up=linphone_call_get_user_pointer(call);

		if (up==NULL){
			jobj=env->NewObject(ljb->callClass, ljb->callCtrId, (jlong)call);
			jobj=env->NewGlobalRef(jobj);
			linphone_call_set_user_pointer(call,(void*)jobj);
			linphone_call_ref(call);
		}else{
			jobj=(jobject)up;
		}
	}
	return jobj;
}

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

	if (msg != NULL){
		LinphoneChatRoom *room = linphone_chat_message_get_chat_room(msg);
		LinphoneCore *lc = linphone_chat_room_get_core(room);
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);

		void *up = linphone_chat_message_get_user_data(msg);

		if (up == NULL) {
652 653 654 655
			jobj = env->NewObject(ljb->chatMessageClass, ljb->chatMessageCtrId, (jlong)msg);
			void *userdata = (void*)env->NewWeakGlobalRef(jobj);
			linphone_chat_message_set_user_data(msg, userdata);
			linphone_chat_message_ref(msg);
Sylvain Berfini's avatar
Sylvain Berfini committed
656
		} else {
657 658 659 660 661 662
			jobj = env->NewLocalRef((jobject)up);
			if (jobj == NULL) {
				// takes implicit local ref
				jobj = env->NewObject(ljb->chatMessageClass, ljb->chatMessageCtrId, (jlong)msg);
				linphone_chat_message_set_user_data(msg, (void*)env->NewWeakGlobalRef(jobj));
			}
Sylvain Berfini's avatar
Sylvain Berfini committed
663 664 665 666 667
		}
	}
	return jobj;
}

668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
jobject getChatRoom(JNIEnv *env, LinphoneChatRoom *room) {
	jobject jobj = 0;

	if (room != NULL){
		LinphoneCore *lc = linphone_chat_room_get_core(room);
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);

		void *up = linphone_chat_room_get_user_data(room);
		if (up == NULL) {
			// take implicit local ref
			jobj = env->NewObject(ljb->chatRoomClass, ljb->chatRoomCtrId, (jlong)room);
			linphone_chat_room_set_user_data(room, (void*)env->NewWeakGlobalRef(jobj));
			linphone_chat_room_ref(room);
		} else {
			jobj = env->NewLocalRef((jobject)up);
			if (jobj == NULL) {
				// takes implicit local ref
685
				jobj = env->NewObject(ljb->chatRoomClass, ljb->chatRoomCtrId, (jlong)room);
686 687 688 689 690 691 692
				linphone_chat_room_set_user_data(room, (void*)env->NewWeakGlobalRef(jobj));
			}
		}
	}
	return jobj;
}

693
jobject getFriend(JNIEnv *env, LinphoneFriend *lfriend){
Sylvain Berfini's avatar
Sylvain Berfini committed
694 695
	jobject jobj=0;

696

Sylvain Berfini's avatar
Sylvain Berfini committed
697 698 699 700 701 702 703
	if (lfriend != NULL){
		LinphoneCore *lc = linphone_friend_get_core(lfriend);
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);

		void *up=linphone_friend_get_user_data(lfriend);

		if (up == NULL){
704 705

			// take implicit local ref
Sylvain Berfini's avatar
Sylvain Berfini committed
706 707 708 709 710 711 712
			jobj=env->NewObject(ljb->friendClass, ljb->friendCtrId, (jlong)lfriend);
			linphone_friend_set_user_data(lfriend,(void*)env->NewWeakGlobalRef(jobj));
			linphone_friend_ref(lfriend);
		}else{

			jobj=env->NewLocalRef((jobject)up);
			if (jobj == NULL){
713
				// takes implicit local ref
Sylvain Berfini's avatar
Sylvain Berfini committed
714 715 716 717 718 719 720 721
				jobj=env->NewObject(ljb->friendClass, ljb->friendCtrId, (jlong)lfriend);
				linphone_friend_set_user_data(lfriend,(void*)env->NewWeakGlobalRef(jobj));
			}
		}
	}
	return jobj;
}

722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
jobject getFriendList(JNIEnv *env, LinphoneFriendList *lfriendList){
	jobject jobj=0;

	if (lfriendList != NULL){
		LinphoneCore *lc = linphone_friend_list_get_core(lfriendList);
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);

		void *up=linphone_friend_list_get_user_data(lfriendList);

		if (up == NULL){
			jobj=env->NewObject(ljb->friendListClass, ljb->friendListCtrId, (jlong)lfriendList);
			linphone_friend_list_set_user_data(lfriendList,(void*)env->NewWeakGlobalRef(jobj));
			linphone_friend_list_ref(lfriendList);
		}else{

			jobj=env->NewLocalRef((jobject)up);
			if (jobj == NULL){
				jobj=env->NewObject(ljb->friendListClass, ljb->friendListCtrId, (jlong)lfriendList);
				linphone_friend_list_set_user_data(lfriendList,(void*)env->NewWeakGlobalRef(jobj));
			}
		}
	}
	return jobj;
}

747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
jobject getNatPolicy(JNIEnv *env, LinphoneNatPolicy *lNatPolicy) {
	jobject jobj = 0;

	if (lNatPolicy != NULL) {
		LinphoneCore *lc = lNatPolicy->lc;
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);

		void *up = linphone_nat_policy_get_user_data(lNatPolicy);
		if (up == NULL) {
			jobj = env->NewObject(ljb->natPolicyClass, ljb->natPolicyCtrId, (jlong)lNatPolicy);
			linphone_nat_policy_set_user_data(lNatPolicy, (void *)env->NewWeakGlobalRef(jobj));
			linphone_nat_policy_ref(lNatPolicy);
		} else {
			jobj = env->NewLocalRef((jobject)up);
			if (jobj == NULL) {
				jobj = env->NewObject(ljb->natPolicyClass, ljb->natPolicyCtrId, (jlong)lNatPolicy);
				linphone_nat_policy_set_user_data(lNatPolicy, (void *)env->NewWeakGlobalRef(jobj));
			}
		}
	}
	return jobj;
}

Sylvain Berfini's avatar
Sylvain Berfini committed
770 771 772 773 774 775 776 777 778 779 780 781 782 783
jobject getEvent(JNIEnv *env, LinphoneEvent *lev){
	if (lev==NULL) return NULL;
	jobject jev=(jobject)linphone_event_get_user_data(lev);
	if (jev==NULL){
		LinphoneCore *lc = linphone_event_get_core(lev);
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);

		jev=env->NewObject(ljb->linphoneEventClass, ljb->linphoneEventCtrId, (jlong)linphone_event_ref(lev));
		jev=env->NewGlobalRef(jev);
		linphone_event_set_user_data(lev,jev);
	}
	return jev;
}

784 785 786 787 788 789
jobject getXmlRpcRequest(JNIEnv *env, LinphoneXmlRpcRequest *lrequest) {
	jobject jobj = 0;

	if (lrequest != NULL) {
		jclass xmlRpcSessionClass = (jclass)env->FindClass("org/linphone/core/LinphoneXmlRpcRequestImpl");
		jmethodID xmlRpcSessionCtrId = env->GetMethodID(xmlRpcSessionClass, "<init>", "(J)V");
790

791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
		void *up = linphone_xml_rpc_request_get_user_data(lrequest);
		if (up == NULL) {
			jobj = env->NewObject(xmlRpcSessionClass, xmlRpcSessionCtrId, (jlong)lrequest);
			linphone_xml_rpc_request_set_user_data(lrequest, (void *)env->NewWeakGlobalRef(jobj));
			linphone_xml_rpc_request_ref(lrequest);
		} else {
			jobj = env->NewLocalRef((jobject)up);
			if (jobj == NULL) {
				jobj = env->NewObject(xmlRpcSessionClass, xmlRpcSessionCtrId, (jlong)lrequest);
				linphone_xml_rpc_request_set_user_data(lrequest, (void *)env->NewWeakGlobalRef(jobj));
			}
		}
	}
	return jobj;
}

807 808 809 810 811 812 813 814 815
jobject getAccountCreator(JNIEnv *env, LinphoneAccountCreator *account_creator) {
	jobject jobj = 0;

	if (account_creator != NULL) {
		LinphoneCore *lc = account_creator->core;
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);

		void *up = linphone_account_creator_get_user_data(account_creator);
		if (up == NULL) {
816
			jobj = env->NewObject(ljb->accountCreatorClass, ljb->accountCreatorCtrId, (jlong)account_creator);
817 818 819 820 821
			linphone_account_creator_set_user_data(account_creator, (void *)env->NewWeakGlobalRef(jobj));
			linphone_account_creator_ref(account_creator);
		} else {
			jobj = env->NewLocalRef((jobject)up);
			if (jobj == NULL) {
822
				jobj = env->NewObject(ljb->accountCreatorClass, ljb->accountCreatorCtrId, (jlong)account_creator);
823 824 825 826 827 828 829
				linphone_account_creator_set_user_data(account_creator, (void *)env->NewWeakGlobalRef(jobj));
			}
		}
	}
	return jobj;
}

Sylvain Berfini's avatar
Sylvain Berfini committed
830 831 832 833 834
class LinphoneCoreData {
public:
	LinphoneCoreData(JNIEnv *env, jobject lc, LinphoneCoreVTable *vTable, jobject alistener, LinphoneJavaBindings *ljb) {
		core = env->NewGlobalRef(lc);
		listener = env->NewGlobalRef(alistener);
835

Sylvain Berfini's avatar
Sylvain Berfini committed
836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
		memset(vTable, 0, sizeof(LinphoneCoreVTable));

		if (ljb->displayStatusId) {
			vTable->display_status = displayStatusCb;
		}

		if (ljb->globalStateId) {
			vTable->global_state_changed = globalStateChange;
		}

		if (ljb->registrationStateId) {
			vTable->registration_state_changed = registrationStateChange;
		}

		if (ljb->callStateId) {
			vTable->call_state_changed = callStateChange;
		}

		if (ljb->transferStateId) {
			vTable->transfer_state_changed = transferStateChanged;
		}

		if (ljb->callStatsUpdatedId) {
			vTable->call_stats_updated = callStatsUpdated;
		}

		if (ljb->callEncryptionChangedId) {
			vTable->call_encryption_changed = callEncryptionChange;
		}

		if (ljb->newSubscriptionRequestId) {
			vTable->new_subscription_requested = new_subscription_requested;
		}

		if (ljb->authInfoRequestedId) {
			vTable->auth_info_requested = authInfoRequested;
		}
873

874 875 876
		if (ljb->authenticationRequestedId) {
			vTable->authentication_requested = authenticationRequested;
		}
Sylvain Berfini's avatar
Sylvain Berfini committed
877 878 879 880 881 882 883 884 885

		if (ljb->notifyPresenceReceivedId) {
			vTable->notify_presence_received = notify_presence_received;
		}

		if (ljb->messageReceivedId) {
			vTable->message_received = message_received;
		}

886 887 888 889
		if (ljb->messageReceivedUnableToDecryptedId) {
		    vTable->message_received_unable_decrypt = message_received_unable_decrypt;
		}

Sylvain Berfini's avatar
Sylvain Berfini committed
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
		if (ljb->isComposingReceivedId) {
			vTable->is_composing_received = is_composing_received;
		}

		if (ljb->dtmfReceivedId) {
			vTable->dtmf_received = dtmf_received;
		}

		if (ljb->infoReceivedId) {
			vTable->info_received = infoReceived;
		}

		if (ljb->subscriptionStateId) {
			vTable->subscription_state_changed = subscriptionStateChanged;
		}

		if (ljb->publishStateId) {
			vTable->publish_state_changed = publishStateChanged;
		}

		if (ljb->notifyRecvId) {
			vTable->notify_received = notifyReceived;
		}

914 915 916 917
		if (ljb->networkReachableId) {
			vTable->network_reachable = networkReachableCb;
		}

Sylvain Berfini's avatar
Sylvain Berfini committed
918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
		if (ljb->configuringStateId) {
			vTable->configuring_status = configuringStatus;
		}

		if (ljb->fileTransferProgressIndicationId) {
			vTable->file_transfer_progress_indication = fileTransferProgressIndication;
		}

		if (ljb->fileTransferSendId) {
			vTable->file_transfer_send = fileTransferSend;
		}

		if (ljb->fileTransferRecvId) {
			vTable->file_transfer_recv = fileTransferRecv;
		}

		if (ljb->logCollectionUploadProgressId) {
			vTable->log_collection_upload_progress_indication = logCollectionUploadProgressIndication;
		}
		if (ljb->logCollectionUploadStateId) {
			vTable->log_collection_upload_state_changed = logCollectionUploadStateChange;
		}
940

941 942 943 944 945 946
		if (ljb->friendListCreatedId) {
			vTable->friend_list_created = friendListCreated;
		}
		if (ljb->friendListRemovedId) {
			vTable->friend_list_removed = friendListRemoved;
		}
Sylvain Berfini's avatar
Sylvain Berfini committed
947
	}
948

Sylvain Berfini's avatar
Sylvain Berfini committed
949 950 951 952 953 954
	~LinphoneCoreData() {
		JNIEnv *env = 0;
		jvm->AttachCurrentThread(&env,NULL);
		env->DeleteGlobalRef(core);
		env->DeleteGlobalRef(listener);
	}
955

Sylvain Berfini's avatar
Sylvain Berfini committed
956 957
	jobject core;
	jobject listener;
958

959
	LinphoneCoreVTable vTable;
960

961 962 963 964
	static void displayStatusCb(LinphoneCore *lc, const char *message) {
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
965
			ms_error("cannot attach VM");
966 967
			return;
		}
968

Sylvain Berfini's avatar
Sylvain Berfini committed
969
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
970 971
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
972
		jstring msg = message ? env->NewStringUTF(message) : NULL;
Sylvain Berfini's avatar
Sylvain Berfini committed
973
		env->CallVoidMethod(lcData->listener,ljb->displayStatusId,lcData->core,msg);
974
		handle_possible_java_exception(env, lcData->listener);
975 976 977
		if (msg) {
			env->DeleteLocalRef(msg);
		}
978
	}
979
	static void authInfoRequested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) {
980 981 982 983 984 985
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
			ms_error("cannot attach VM");
			return;
		}
986

Sylvain Berfini's avatar
Sylvain Berfini committed
987
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
988 989
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
990 991 992
		jstring r = realm ? env->NewStringUTF(realm) : NULL;
		jstring u = username ? env->NewStringUTF(username) : NULL;
		jstring d = domain ? env->NewStringUTF(domain) : NULL;
993
		env->CallVoidMethod(lcData->listener,
Sylvain Berfini's avatar
Sylvain Berfini committed
994
							ljb->authInfoRequestedId,
995
							lcData->core,
996 997
							r,
							u,
998
							d
999
   						);
1000
		handle_possible_java_exception(env, lcData->listener);
1001 1002 1003 1004 1005 1006 1007 1008 1009
		if (r) {
			env->DeleteLocalRef(r);
		}
		if (u) {
			env->DeleteLocalRef(u);
		}
		if (d) {
			env->DeleteLocalRef(d);
		}
1010
	}
1011 1012 1013 1014 1015 1016 1017
	static void authenticationRequested(LinphoneCore *lc, LinphoneAuthInfo *auth_info, LinphoneAuthMethod method) {
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
			ms_error("cannot attach VM");
			return;
		}
1018

1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
		env->CallVoidMethod(lcData->listener,
							ljb->authenticationRequestedId,
							lcData->core,
							getAuthInfo(env, lc, auth_info, lcData->core),
							env->CallStaticObjectMethod(ljb->authMethodClass,ljb->authMethodFromIntId,(jint)method)
   						);
		handle_possible_java_exception(env, lcData->listener);
	}
1030 1031 1032 1033 1034 1035 1036 1037
	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);
		}
	}
1038

1039 1040 1041 1042
	static void globalStateChange(LinphoneCore *lc, LinphoneGlobalState gstate,const char* message) {
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
1043
			ms_error("cannot attach VM");
1044 1045
			return;
		}
1046

Sylvain Berfini's avatar
Sylvain Berfini committed
1047
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
1048 1049
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
1050

1051 1052 1053
		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);
1054

1055
		jstring msg = message ? env->NewStringUTF(message) : NULL;
1056
		env->CallVoidMethod(lcData->listener
Sylvain Berfini's avatar
Sylvain Berfini committed
1057
							,ljb->globalStateId
1058
							,lcData->core
Sylvain Berfini's avatar
Sylvain Berfini committed
1059
							,env->CallStaticObjectMethod(ljb->globalStateClass,ljb->globalStateFromIntId,(jint)gstate),
1060
							msg);
1061
		handle_possible_java_exception(env, lcData->listener);
1062 1063 1064
		if (msg) {
			env->DeleteLocalRef(msg);
		}
1065
	}
1066
	static void registrationStateChange(LinphoneCore *lc, LinphoneProxyConfig* proxy,LinphoneRegistrationState state,const char* message) {
1067 1068
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
1069
		jobject jproxy;
1070
		if (result != 0) {
1071
			ms_error("cannot attach VM");
1072 1073
			return;
		}
1074

Sylvain Berfini's avatar
Sylvain Berfini committed
1075
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
1076 1077
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
1078
		jstring msg = message ? env->NewStringUTF(message) : NULL;
1079
		env->CallVoidMethod(lcData->listener
Sylvain Berfini's avatar
Sylvain Berfini committed
1080
							,ljb->registrationStateId
1081
							,lcData->core
1082
							,(jproxy=getProxy(env,proxy,lcData->core))
Sylvain Berfini's avatar
Sylvain Berfini committed
1083
							,env->CallStaticObjectMethod(ljb->registrationStateClass,ljb->registrationStateFromIntId,(jint)state),
1084
							msg);
1085
		handle_possible_java_exception(env, lcData->listener);
1086 1087 1088
		if (msg) {
			env->DeleteLocalRef(msg);
		}
1089 1090 1091
		if (jproxy) {
			env->DeleteLocalRef(jproxy);
		}
1092
	}
1093

1094
	static void callStateChange(LinphoneCore *lc, LinphoneCall* call,LinphoneCallState state,const char* message) {
1095 1096
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
1097
		jobject jcall;
1098
		if (result != 0) {
1099
			ms_error("cannot attach VM");
1100 1101
			return;
		}
1102

Sylvain Berfini's avatar
Sylvain Berfini committed
1103
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
1104 1105
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
1106
		jstring msg = message ? env->NewStringUTF(message) : NULL;
1107
		env->CallVoidMethod(lcData->listener
Sylvain Berfini's avatar
Sylvain Berfini committed
1108
							,ljb->callStateId
1109
							,lcData->core
1110
							,(jcall=getCall(env,call))
Sylvain Berfini's avatar
Sylvain Berfini committed
1111
							,env->CallStaticObjectMethod(ljb->callStateClass,ljb->callStateFromIntId,(jint)state),
1112
							msg);
1113
		handle_possible_java_exception(env, lcData->listener);
1114
		if (state==LinphoneCallReleased) {
1115 1116 1117
			linphone_call_set_user_pointer(call,NULL);
			env->DeleteGlobalRef(jcall);
		}
1118 1119 1120
		if (msg) {
			env->DeleteLocalRef(msg);
		}
1121
	}
1122 1123 1124 1125
	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) {
1126
			ms_error("cannot attach VM");
1127 1128
			return;
		}
1129

Sylvain Berfini's avatar
Sylvain Berfini committed
1130
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
1131 1132
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
1133
		env->CallVoidMethod(lcData->listener
Sylvain Berfini's avatar
Sylvain Berfini committed
1134
							,ljb->callEncryptionChangedId
1135
							,lcData->core
1136
							,getCall(env,call)
1137 1138
							,encrypted
							,authentication_token ? env->NewStringUTF(authentication_token) : NULL);
1139
		handle_possible_java_exception(env, lcData->listener);
1140
	}
1141
	static void notify_presence_received(LinphoneCore *lc,  LinphoneFriend *my_friend) {
1142 1143
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
1144
		jobject jfriend = NULL;
1145

1146
		if (result != 0) {
1147
			ms_error("cannot attach VM");
1148 1149
			return;
		}
1150

Sylvain Berfini's avatar
Sylvain Berfini committed
1151
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
1152 1153
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
1154
		jfriend = getFriend(env, my_friend);
1155
		env->CallVoidMethod(lcData->listener
Sylvain Berfini's avatar
Sylvain Berfini committed
1156
							,ljb->notifyPresenceReceivedId
1157
							,lcData->core
1158
							,jfriend);
1159
		handle_possible_java_exception(env, lcData->listener);
1160
		env->DeleteLocalRef(jfriend);
1161
	}
1162
	static void new_subscription_requested(LinphoneCore *lc,  LinphoneFriend *my_friend, const char* url) {
1163 1164 1165
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
1166
			ms_error("cannot attach VM");
1167 1168
			return;
		}
1169

Sylvain Berfini's avatar
Sylvain Berfini committed
1170
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
1171 1172
		LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc);
		LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table);
1173
		jobject jfriend =  getFriend(env, my_friend);
1174
		env->CallVoidMethod(lcData->listener
Sylvain Berfini's avatar
Sylvain Berfini committed
1175
							,ljb->newSubscriptionRequestId
1176
							,lcData->core
1177
							,jfriend
1178
							,url ? env->NewStringUTF(url) : NULL);
1179
		env->DeleteLocalRef(jfriend);
1180
		handle_possible_java_exception(env, lcData->listener);
1181
	}
Sylvain Berfini's avatar
Sylvain Berfini committed
1182 1183 1184 1185
	static void dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf) {
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
1186
			ms_error("cannot attach VM");
Sylvain Berfini's avatar
Sylvain Berfini committed
1187 1188
			return;
		}
1189

Sylvain Berfini's avatar
Sylvain Berfini committed
1190
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
1191 1192
		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
1193
		env->CallVoidMethod(lcData->listener
Sylvain Berfini's avatar
Sylvain Berfini committed
1194
							,ljb->dtmfReceivedId
Sylvain Berfini's avatar
Sylvain Berfini committed
1195
							,lcData->core
1196
							,getCall(env,call)
Sylvain Berfini's avatar
Sylvain Berfini committed
1197
							,dtmf);
1198
		handle_possible_java_exception(env, lcData->listener);
Sylvain Berfini's avatar
Sylvain Berfini committed
1199
	}
Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
1200
	static void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
1201 1202 1203 1204 1205
		JNIEnv *env = 0;
		jint result = jvm->AttachCurrentThread(&env,NULL);
		if (result != 0) {
			ms_error("cannot attach VM");
			return;
1206
		}
1207

1208 1209
		jobject jmsg;
		jobject jroom;
Sylvain Berfini's avatar
Sylvain Berfini committed
1210
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
1211 1212 1213 1214
		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
Sylvain Berfini's avatar
Sylvain Berfini committed
1215
							,ljb->messageReceivedId
1216
							,lcData->core
1217 1218
							,(jroom = getChatRoom(env, room))
							,(jmsg = getChatMessage(env, msg)));
1219
		handle_possible_java_exception(env, lcData->listener);
1220

1221 1222 1223 1224 1225 1226
		if (jmsg) {
			env->DeleteLocalRef(jmsg);
		}
		if (jroom) {
			env->DeleteLocalRef(jroom);
		}
1227
	}