jni.mustache 21.9 KB
Newer Older
Sylvain Berfini's avatar
Sylvain Berfini committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
linphone_jni.cc
Copyright (C) 2017 Belledonne Communications SARL

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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include <jni.h>
#include <cpu-features.h>

23
#include "belle-sip/object.h"
Sylvain Berfini's avatar
Sylvain Berfini committed
24 25 26 27 28 29
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/mscommon.h"
#include "mediastreamer2/msmediaplayer.h"
#include "mediastreamer2/msutils.h"
#include "mediastreamer2/devices.h"
#include "mediastreamer2/msjava.h"
30
#include "linphone/core_utils.h"
Sylvain Berfini's avatar
Sylvain Berfini committed
31 32 33 34 35 36 37 38 39 40
#include "linphone/core.h"
#include "linphone/tunnel.h"
#include "linphone/account_creator.h"
#include "linphone/wrapper_utils.h"
#include "linphone/lpconfig.h"

#ifdef __ANDROID__
#include <android/log.h>
#endif /* __ANDROID__ */

41
static JavaVM *jvm = NULL;
Sylvain Berfini's avatar
Sylvain Berfini committed
42 43 44
static const char* LogDomain = "Linphone";
static jmethodID loghandler_id;
static jobject handler_obj=NULL;
Sylvain Berfini's avatar
Sylvain Berfini committed
45

Sylvain Berfini's avatar
Sylvain Berfini committed
46 47 48 49
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *ajvm, void *reserved) {
#ifdef __ANDROID__
	ms_set_jvm(ajvm);
#endif /* __ANDROID__ */
50
	jvm = ajvm;
Sylvain Berfini's avatar
Sylvain Berfini committed
51 52 53
	return JNI_VERSION_1_2;
}

54 55
#define belle_sip_java_user_data_key "java_object"

Sylvain Berfini's avatar
Sylvain Berfini committed
56 57 58 59 60 61 62
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);
63 64 65 66 67 68 69 70 71
}

static jlong GetObjectNativePtr(JNIEnv *env, jobject object) {
	jclass objClass = env->GetObjectClass(object);
	jfieldID nativePtrId = env->GetFieldID(objClass, "nativePtr", "J");
	jlong nativePtr = env->GetLongField(object, nativePtrId);
	return nativePtr;
}

72 73
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
void linphone_android_log_handler(int prio, char *str) {
	char *current;
	char *next;

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

			*next = '\0';
			if (next != str && next[-1] == '\r')
				next[-1] = '\0';
			__android_log_write(prio, LogDomain, current);
			current = next + 1;
		}
		__android_log_write(prio, LogDomain, current);
	}
}

static void linphone_android_ortp_log_handler(const char *domain, OrtpLogLevel lev, const char *fmt, va_list args) {
	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);
}

125
extern "C" void Java_org_linphone_core_FactoryImpl_setDebugMode(JNIEnv* env, jobject thiz, jboolean isDebug, jstring jdebugTag) {
126 127 128 129 130 131 132 133
	if (isDebug) {
		LogDomain = GetStringUTFChars(env, jdebugTag);
		linphone_core_enable_logs_with_cb(linphone_android_ortp_log_handler);
	} else {
		linphone_core_disable_logs();
	}
}

134 135 136 137 138 139 140 141
static jstring get_jstring_from_char(JNIEnv *env, const char* cString) {
    int len;
    jmethodID constructorString;
    jbyteArray bytesArray = NULL;
    jstring javaString = NULL;
    jclass classString = env->FindClass("java/lang/String");
    if (classString == 0) {
        ms_error("Cannot find java.lang.String class.\n");
142
        goto error;
143 144 145 146 147
    }

    constructorString = env->GetMethodID(classString, "<init>", "([BLjava/lang/String;)V");
    if (constructorString == 0) {
        ms_error("Cannot find String <init> method.\n");
148
        goto error;
149 150 151 152 153 154 155 156 157 158 159 160 161
    }

    len = (int)strlen(cString);
    bytesArray = env->NewByteArray(len);

    if (bytesArray) {
        env->SetByteArrayRegion(bytesArray, 0, len, (jbyte *)cString);
        jstring UTF8 = env->NewStringUTF("UTF8");
        javaString = (jstring)env->NewObject(classString, constructorString, bytesArray, UTF8);
        env->DeleteLocalRef(bytesArray);
        env->DeleteLocalRef(UTF8);
    }

162 163 164
    error:
    if (classString) env->DeleteLocalRef(classString);

165 166 167
    return javaString;
}

168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
#ifdef __ANDROID__
int dumbMethodForAllowingUsageOfCpuFeaturesFromStaticLibMediastream() {
        return (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0);
}

int dumbMethodForAllowingUsageOfMsAudioDiffFromStaticLibMediastream() {
        return ms_audio_diff(NULL, NULL, NULL, 0, NULL, NULL);
}

extern "C" void setAndroidLogHandler() {
        linphone_core_enable_logs_with_cb(linphone_android_ortp_log_handler);
}

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);
}
#endif

188 189
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

190 191 192
class LinphoneJavaBindings {
public:
	LinphoneJavaBindings(JNIEnv *env) {
193 194 195
		ms_factory_class = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/mediastream/Factory"));
		ms_factory_class_constructor = env->GetMethodID(ms_factory_class, "<init>", "(J)V");

196 197 198 199
		{{#objects}}
		{{cPrefix}}_class = (jclass)env->NewGlobalRef(env->FindClass("{{jniPath}}{{classImplName}}"));
		{{cPrefix}}_class_constructor = env->GetMethodID({{cPrefix}}_class, "<init>", "(J)V");
		{{/objects}}
200 201 202 203 204

		{{#enums}}
		{{cPrefix}}_class = (jclass)env->NewGlobalRef(env->FindClass("{{jniPath}}{{jniName}}"));
		{{cPrefix}}_class_constructor_from_int = env->GetStaticMethodID({{cPrefix}}_class, "fromInt", "(I)L{{jniPath}}{{jniName}};");
		{{/enums}}
205 206 207
	}

	~LinphoneJavaBindings() {
208 209 210 211
		JNIEnv *env = ms_get_jni_env();
                if (!env) {
                        ms_error("cannot attach VM");
                }
212 213 214

		env->DeleteGlobalRef(ms_factory_class);

215 216 217
		{{#objects}}
		env->DeleteGlobalRef({{cPrefix}}_class);
		{{/objects}}
218

219 220 221
		{{#enums}}
		env->DeleteGlobalRef({{cPrefix}}_class);
		{{/enums}}
222 223
	}

224 225 226
	jclass ms_factory_class;
	jmethodID ms_factory_class_constructor;

227 228 229 230
	{{#objects}}
	jclass {{cPrefix}}_class;
	jmethodID {{cPrefix}}_class_constructor;
	{{/objects}}
231 232 233 234 235

	{{#enums}}
	jclass {{cPrefix}}_class;
	jmethodID {{cPrefix}}_class_constructor_from_int;
	{{/enums}}
236 237
};

238
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
239

240 241 242
#ifdef __cplusplus
extern "C" {
#endif
243

Sylvain Berfini's avatar
Sylvain Berfini committed
244
{{#objects}}
245
jobject get{{className}}(JNIEnv *env, {{classCName}} *cptr) {
Sylvain Berfini's avatar
Sylvain Berfini committed
246 247
	jobject jobj = 0;

248 249
	if (cptr != NULL) {
		void *up = belle_sip_object_data_get((belle_sip_object_t *)cptr, belle_sip_java_user_data_key);
250
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get());
251 252 253 254 255
		if (!ljb) {
			ljb = new LinphoneJavaBindings(env);
			linphone_factory_set_user_data(linphone_factory_get(), ljb);
		}

256 257
		jclass {{cPrefix}}_class = ljb->{{cPrefix}}_class;
		jmethodID {{cPrefix}}_constructor = ljb->{{cPrefix}}_class_constructor;
Sylvain Berfini's avatar
Sylvain Berfini committed
258 259

		if (up == NULL) {
260 261
			jobj = env->NewObject({{cPrefix}}_class, {{cPrefix}}_constructor, (jlong)cptr);
			belle_sip_object_data_set((belle_sip_object_t *)cptr, belle_sip_java_user_data_key, (void*)env->NewWeakGlobalRef(jobj), NULL);
262
			{{#refCountable}}{{cPrefix}}_ref(cptr);{{/refCountable}}
Sylvain Berfini's avatar
Sylvain Berfini committed
263 264 265 266 267 268
		} else {
			jobj = env->NewLocalRef((jobject)up);
			if (jobj == NULL) {
				// Delete weak ref ?
				env->DeleteWeakGlobalRef((jobject)up);
				// takes implicit local ref
269 270
				jobj = env->NewObject({{cPrefix}}_class, {{cPrefix}}_constructor, (jlong)cptr);
				belle_sip_object_data_set((belle_sip_object_t *)cptr, belle_sip_java_user_data_key, (void*)env->NewWeakGlobalRef(jobj), NULL);
271
				{{#refCountable}}{{cPrefix}}_ref(cptr);{{/refCountable}}
Sylvain Berfini's avatar
Sylvain Berfini committed
272 273 274 275 276 277 278 279
			}
		}
	}
	return jobj;
}

void Java_{{jniPrefix}}{{classImplName}}_unref(JNIEnv* env, jobject thiz, jlong ptr) {
	{{classCName}} *cptr = ({{classCName}}*)ptr;
280 281
	jobject wref = (jobject)belle_sip_object_data_get((belle_sip_object_t *)cptr, belle_sip_java_user_data_key);
	belle_sip_object_data_set((belle_sip_object_t *)cptr, belle_sip_java_user_data_key, NULL, NULL);
Sylvain Berfini's avatar
Sylvain Berfini committed
282 283 284
	if (wref) {
		env->DeleteWeakGlobalRef(wref);
	}
285
	{{#refCountable}}{{cPrefix}}_unref(cptr);{{/refCountable}}
Sylvain Berfini's avatar
Sylvain Berfini committed
286 287 288
}

{{/objects}}
289 290 291 292 293 294 295 296 297 298 299
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static inline void handle_possible_java_exception(JNIEnv *env, jobject listener)
{
	if (env->ExceptionCheck()) {
		env->ExceptionDescribe();
		env->ExceptionClear();
		ms_error("Listener %p raised an exception",listener);
	}
}

300
{{#callbacks}}
301
static {{return}} {{callbackName}}({{params}}) {
302 303
	JNIEnv *env = ms_get_jni_env();
	if (!env) {
304
		ms_error("cannot attach VM");
305
		return{{returnIfFail}};
306 307
	}

308
	{{#isSingleListener}}
309
	{{classCName}} *cbs = {{cPrefix}}_get_callbacks({{firstParam}});
310 311
	{{/isSingleListener}}
	{{#isMultiListener}}
312
	{{classCName}} *cbs = {{cPrefix}}_get_current_callbacks({{firstParam}});
313
	{{/isMultiListener}}
314 315 316
	jobject jlistener = (jobject) {{cPrefix}}_cbs_get_user_data(cbs);

	if (jlistener == NULL) {
317
		ms_warning("{{callbackName}}() notification without listener");
318
		return{{returnIfFail}};
319 320 321 322 323 324 325
	}

	jclass jlistenerClass = (jclass) env->GetObjectClass(jlistener);
	jmethodID jcallback = env->GetMethodID(jlistenerClass, "{{jname}}", "{{jparams}}");
	env->DeleteLocalRef(jlistenerClass);

	{{#jobjects}}
326
	jobject j_{{objectName}} = get{{className}}(env, (Linphone{{className}} *){{objectName}});
327 328
	{{/jobjects}}
	{{#jenums}}
329
	LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get());
330 331 332
	jobject j_{{enumName}} = env->CallStaticObjectMethod(ljb->{{cEnumPrefix}}_class, ljb->{{cEnumPrefix}}_class_constructor_from_int, (jint){{enumName}});
	{{/jenums}}
	{{#jstrings}}
333
	jstring j_{{stringName}} = {{stringName}} ? get_jstring_from_char(env, {{stringName}}) : NULL;
334
	{{/jstrings}}
335

336 337 338 339 340 341 342 343 344 345
	{{#hasReturn}}{{jniUpcallType}} jni_upcall_result = {{/hasReturn}}env->{{jniUpcallMethod}}(jlistener, jcallback, {{params_impl}});
	{{#hasReturn}}
	{{#isJniUpcallObject}}
	{{return}} c_upcall_result = NULL;
	if (jni_upcall_result) c_upcall_result = ({{return}})GetObjectNativePtr(env, jni_upcall_result);
	{{/isJniUpcallObject}}
	{{#isJniUpcallBasicType}}
	{{return}} c_upcall_result = ({{return}}) jni_upcall_result;
	{{/isJniUpcallBasicType}}
	{{/hasReturn}}
346 347 348 349 350 351

	{{#jobjects}}
	if (j_{{objectName}}) {
		env->DeleteLocalRef(j_{{objectName}});
	}
	{{/jobjects}}
352 353 354 355 356
	{{#jenums}}
	if (j_{{enumName}}) {
		env->DeleteLocalRef(j_{{enumName}});
	}
	{{/jenums}}
357 358 359 360 361 362 363
	{{#jstrings}}
	if (j_{{stringName}}) {
		env->DeleteLocalRef(j_{{stringName}});
	}
	{{/jstrings}}

	handle_possible_java_exception(env, jlistener);
364
	{{#hasReturn}}
365
	return c_upcall_result;
366
	{{/hasReturn}}
367 368
}

369 370 371 372 373
{{/callbacks}}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

{{#interfaces}}
{{#isSingleListener}}
374
void Java_{{jniPackage}}{{className}}Impl_setListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) {
375 376 377 378 379 380 381 382 383
	{{classCName}} *cptr = ({{classCName}}*)ptr;
	{{classCName}}Cbs *cbs = {{cPrefix}}_get_callbacks(cptr);
	if (jlistener == NULL) {
		jobject listener = (jobject) {{cPrefix}}_cbs_get_user_data(cbs);
		{{cPrefix}}_cbs_set_user_data(cbs, NULL);
		if (listener != NULL) {
			env->DeleteGlobalRef(listener);
		}
	} else {
384 385 386 387 388 389 390 391 392 393 394
		jobject listener = (jobject) {{cPrefix}}_cbs_get_user_data(cbs);
		if (listener == NULL) {
			listener = env->NewGlobalRef(jlistener);
		} else {
			if (env->IsSameObject(listener, jlistener)) {
				return;
			} else {
				env->DeleteGlobalRef(listener);
				listener = env->NewGlobalRef(jlistener);
			}
		}
395 396 397 398 399 400
		{{cPrefix}}_cbs_set_user_data(cbs, listener);
		{{#callbacksList}}
		{{cPrefix}}_cbs_set_{{callback}}(cbs, {{callbackName}});
		{{/callbacksList}}
	}
}
401
{{/isSingleListener}}
402

403
{{#isMultiListener}}
404
void Java_{{jniPackage}}{{className}}Impl_addListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) {
405
	if (jlistener == NULL) return;
406 407 408 409 410 411 412
	{{classCName}} *cptr = ({{classCName}}*)ptr;
	jobject listener = env->NewGlobalRef(jlistener);
	{{classCName}}Cbs *cbs = linphone_factory_create_{{factoryName}}_cbs(NULL);
	{{cPrefix}}_cbs_set_user_data(cbs, listener);
	{{#callbacksList}}
	{{cPrefix}}_cbs_set_{{callback}}(cbs, {{callbackName}});
	{{/callbacksList}}
413
	{{cPrefix}}_add_callbacks(cptr, cbs);
Sylvain Berfini's avatar
Sylvain Berfini committed
414
	{{cPrefix}}_cbs_unref(cbs);
415 416
}

417
void Java_{{jniPackage}}{{className}}Impl_removeListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) {
418
	{{classCName}} *cptr = ({{classCName}}*)ptr;
Sylvain Berfini's avatar
Sylvain Berfini committed
419
	const bctbx_list_t *cbs_list = {{cPrefix}}_get_callbacks_list(cptr);
420
	bctbx_list_t *it;
421
	for (it = (bctbx_list_t *)cbs_list; it != NULL; it = it->next) {
422
		{{classCName}}Cbs *cbs = ({{classCName}}Cbs *)it->data;
423 424
		jobject listener = (jobject) {{cPrefix}}_cbs_get_user_data(cbs);
		if (env->IsSameObject(listener, jlistener)) {
425
			{{cPrefix}}_cbs_set_user_data(cbs, NULL);
426
			{{cPrefix}}_remove_callbacks(cptr, cbs);
427
			env->DeleteGlobalRef(listener);
428 429
			break;
		}
430
	}
431
	{{#isNotConstList}}bctbx_list_free(cbs_list);{{/isNotConstList}}
432 433
}
{{/isMultiListener}}
434 435
{{/interfaces}}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
436

437
jobject Java_{{jni_package}}CoreImpl_getMediastreamerFactory(JNIEnv *env, jobject thiz, jlong ptr) {
438 439 440 441 442 443
	LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get());
	MSFactory *factory = linphone_core_get_ms_factory((LinphoneCore*)ptr);
	return env->NewObject(ljb->ms_factory_class, ljb->ms_factory_class_constructor, (jlong)factory);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sylvain Berfini's avatar
Sylvain Berfini committed
444 445

{{#methods}}
446
{{#notEmpty}}
Sylvain Berfini's avatar
Sylvain Berfini committed
447
{{return}} {{name}}({{params}}) {
448 449
	{{#notStatic}}{{classCName}} *cptr = ({{classCName}}*)ptr;
	{{#isLinphoneFactory}}cptr = linphone_factory_get();{{/isLinphoneFactory}}
450 451 452
	if (cptr == 0) {
		return {{#hasReturn}}0{{/hasReturn}}{{#hasStringReturn}}0{{/hasStringReturn}}{{#hasListReturn}}0{{/hasListReturn}}{{#hasByteArrayReturn}}0{{/hasByteArrayReturn}};
	}
453
	{{/notStatic}}{{#strings}}
Sylvain Berfini's avatar
Sylvain Berfini committed
454
	const char* c_{{string}} = GetStringUTFChars(env, {{string}});
455 456 457
	{{/strings}}{{#bytes}}
	{{bytesargtype}} c_{{bytesargname}} = ({{bytesargtype}})env->GetByteArrayElements({{bytesargname}}, NULL);
	{{/bytes}}{{#objects}}
Sylvain Berfini's avatar
Sylvain Berfini committed
458 459
	{{objectClassCName}}* c_{{object}} = NULL;
	if ({{object}}) c_{{object}} = ({{objectClassCName}}*)GetObjectNativePtr(env, {{object}});
460 461
	{{/objects}}{{#lists}}
	bctbx_list_t *bctbx_list_{{list}} = NULL;
462 463
	int {{list}}_count = env->GetArrayLength({{list}});
	for (int i=0; i < {{list}}_count; i++) {
464 465 466 467 468 469 470 471 472 473
		{{#isStringList}}
		jstring obj = (jstring) env->GetObjectArrayElement({{list}}, i);
		const char *str = GetStringUTFChars(env, obj);
		if (str) {
			bctbx_list_{{list}} = bctbx_list_append(bctbx_list_{{list}}, ms_strdup(str));
			ReleaseStringUTFChars(env, obj, str);
		}
		{{/isStringList}}
		{{#isObjList}}
		jobject obj = env->GetObjectArrayElement({{list}}, i);
474
		bctbx_list_{{list}} = bctbx_list_append(bctbx_list_{{list}}, ({{objectClassCName}} *)GetObjectNativePtr(env, obj));
475 476 477
		{{/isObjList}}
	}
	{{/lists}}{{#hasListReturn}}
478
	{{#isConstList}}const {{/isConstList}}bctbx_list_t *list = {{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}});
479
	size_t count = bctbx_list_size(list);
480
	{{#isRealObjectArray}}
481
	LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get());
482 483
	jobjectArray jni_list_result = env->NewObjectArray((int)count, ljb->{{objectCPrefix}}_class, NULL);{{/isRealObjectArray}}
	{{#isStringObjectArray}}jobjectArray jni_list_result = env->NewObjectArray((int)count, env->FindClass("java/lang/String"), env->NewStringUTF(""));{{/isStringObjectArray}}
484 485 486
	for (size_t i = 0; i < count; i++) {
		{{#isRealObjectArray}}
		{{objectClassCName}}* c_object = ({{objectClassCName}}*)list->data;
487
		jobject object = get{{objectClassName}}(env, c_object);
488
		{{/isRealObjectArray}}
489
		{{#isStringObjectArray}}const char *cstring = (const char *)list->data;
490
		jstring object = cstring ? get_jstring_from_char(env, cstring) : 0;{{/isStringObjectArray}}
491
		if (object != 0) {
492
			env->SetObjectArrayElement(jni_list_result, (int)i, object);
493 494 495 496
			{{#isRealObjectArray}}env->DeleteLocalRef(object);{{/isRealObjectArray}}
		}
		list = bctbx_list_next(list);
	}
497
	{{#isNotConstList}}bctbx_list_free(list);{{/isNotConstList}}
498 499 500 501 502 503 504 505
	{{/hasListReturn}}{{#hasByteArrayReturn}}
	{{c_type_return}} jni_result = {{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}});
	if (!jni_result) return NULL;
	size_t jni_result_length = strlen((const char *)jni_result);
	jbyteArray array = env->NewByteArray((int)jni_result_length);
	env->SetByteArrayRegion(array, 0, (int)jni_result_length, (const jbyte*)jni_result);
	return array;
	{{/hasByteArrayReturn}}{{#hasStringReturn}}
506
	const char *c_string = {{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}}){{#returnObject}}){{/returnObject}};
507
	jstring jni_result = (c_string != NULL) ? get_jstring_from_char(env, c_string) : NULL;
508 509
	{{/hasStringReturn}}{{#hasNormalReturn}}
	{{#hasReturn}}{{return}} jni_result = ({{return}}){{#returnObject}}get{{returnClassName}}(env, (Linphone{{returnClassName}} *){{/returnObject}}{{/hasReturn}}{{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}}){{#returnObject}}){{/returnObject}};
510
	{{/hasNormalReturn}}{{#strings}}
Sylvain Berfini's avatar
Sylvain Berfini committed
511
	ReleaseStringUTFChars(env, {{string}}, c_{{string}});
512 513 514
	{{/strings}}{{#bytes}}
	env->ReleaseByteArrayElements({{bytesargname}}, (jbyte*)c_{{bytesargname}}, JNI_ABORT);
	{{/bytes}}{{#hasReturn}}return jni_result;{{/hasReturn}}{{#hasListReturn}}return jni_list_result;{{/hasListReturn}}
Sylvain Berfini's avatar
Sylvain Berfini committed
515
}
516
{{/notEmpty}}
517 518
{{/methods}}

519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Manually wrapped
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Java_org_linphone_core_CallImpl_setNativeVideoWindowId(JNIEnv *env, jobject thiz, jlong ptr, jobject id) {
	LinphoneCall *cptr = (LinphoneCall*)ptr;
	jobject oldWindow = (jobject) linphone_call_get_native_video_window_id(cptr);
	if (oldWindow == id) {
		ms_warning("Java_org_linphone_core_CallImpl_setNativeVideoWindowId(): new id (%p) is the same as the current one, skipping...", id);
		return;
	}
	if (id != NULL) {
		id = env->NewGlobalRef(id);
		ms_message("Java_org_linphone_core_CallImpl_setNativeVideoWindowId(): NewGlobalRef(%p)", id);
	} else ms_message("Java_org_linphone_core_CallImpl_setNativeVideoWindowId(): setting to NULL");
	linphone_call_set_native_video_window_id(cptr, (void *)id);
	if (oldWindow != NULL) {
		ms_message("Java_org_linphone_core_CallImpl_setNativeVideoWindowId(): DeleteGlobalRef(%p)", oldWindow);
		env->DeleteGlobalRef(oldWindow);
	}
}

void Java_org_linphone_core_CoreImpl_setNativePreviewWindowId(JNIEnv *env, jobject thiz, jlong ptr, jobject id) {
	LinphoneCore *cptr = (LinphoneCore*)ptr;
543
	jobject oldWindow = (jobject) linphone_core_get_native_preview_window_id(cptr);
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
	if (oldWindow == id) {
		ms_warning("Java_org_linphone_core_CoreImpl_setNativePreviewWindowId(): new id (%p) is the same as the current one, skipping...", id);
		return;
	}
	if (id != NULL) {
		id = env->NewGlobalRef(id);
		ms_message("Java_org_linphone_core_CoreImpl_setNativePreviewWindowId(): NewGlobalRef(%p)", id);
	} else ms_message("Java_org_linphone_core_CoreImpl_setNativePreviewWindowId(): setting to NULL");
	linphone_core_set_native_preview_window_id(cptr, (void *)id);
	if (oldWindow != NULL) {
		ms_message("Java_org_linphone_core_CoreImpl_setNativePreviewWindowId(): DeleteGlobalRef(%p)", oldWindow);
		env->DeleteGlobalRef(oldWindow);
	}
}

void Java_org_linphone_core_CoreImpl_setNativeVideoWindowId(JNIEnv *env, jobject thiz, jlong ptr, jobject id) {
	LinphoneCore *cptr = (LinphoneCore*)ptr;
561
	jobject oldWindow = (jobject) linphone_core_get_native_video_window_id(cptr);
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
	if (oldWindow == id) {
		ms_warning("Java_org_linphone_core_CoreImpl_setNativeVideoWindowId(): new id (%p) is the same as the current one, skipping...", id);
		return;
	}
	if (id != NULL) {
		id = env->NewGlobalRef(id);
		ms_message("Java_org_linphone_core_CoreImpl_setNativeVideoWindowId(): NewGlobalRef(%p)", id);
	} else ms_message("Java_org_linphone_core_CoreImpl_setNativeVideoWindowId(): setting to NULL");
	linphone_core_set_native_video_window_id(cptr, (void *)id);
	if (oldWindow != NULL) {
		ms_message("Java_org_linphone_core_CoreImpl_setNativeVideoWindowId(): DeleteGlobalRef(%p)", oldWindow);
		env->DeleteGlobalRef(oldWindow);
	}
}

577 578 579 580
jobject Java_org_linphone_core_FactoryImpl_getCore(JNIEnv *env, jobject thiz, jlong ptr, jlong lcPtr) {
	return getCore(env, (LinphoneCore*)lcPtr);
}

581 582
#ifdef __cplusplus
}
583
#endif