jni.mustache 19.8 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 41
#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>
#include <belle-sip/wakelock.h>
#endif /* __ANDROID__ */

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

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

55 56
#define belle_sip_java_user_data_key "java_object"

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

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;
}

Sylvain Berfini's avatar
Sylvain Berfini committed
73 74 75 76 77 78
static void SetObjectNativePtr(JNIEnv *env, jobject object, jlong ptr) {
	jclass objClass = env->GetObjectClass(object);
	jfieldID nativePtrId = env->GetFieldID(objClass, "nativePtr", "J");
	env->SetLongField(object, nativePtrId, ptr);
}

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 125 126 127 128 129 130 131
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);
}

132
extern "C" void Java_org_linphone_core_FactoryImpl_setDebugMode(JNIEnv* env, jobject thiz, jboolean isDebug, jstring jdebugTag) {
133 134 135 136 137 138 139 140 141 142
	if (isDebug) {
		LogDomain = GetStringUTFChars(env, jdebugTag);
		linphone_core_enable_logs_with_cb(linphone_android_ortp_log_handler);
	} else {
		linphone_core_disable_logs();
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

143 144 145
class LinphoneJavaBindings {
public:
	LinphoneJavaBindings(JNIEnv *env) {
146 147 148
		ms_factory_class = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/mediastream/Factory"));
		ms_factory_class_constructor = env->GetMethodID(ms_factory_class, "<init>", "(J)V");

149 150 151 152
		{{#objects}}
		{{cPrefix}}_class = (jclass)env->NewGlobalRef(env->FindClass("{{jniPath}}{{classImplName}}"));
		{{cPrefix}}_class_constructor = env->GetMethodID({{cPrefix}}_class, "<init>", "(J)V");
		{{/objects}}
153 154 155 156 157

		{{#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}}
158 159 160 161 162
	}

	~LinphoneJavaBindings() {
		JNIEnv *env = 0;
		jvm->AttachCurrentThread(&env,NULL);
163 164 165

		env->DeleteGlobalRef(ms_factory_class);

166 167 168
		{{#objects}}
		env->DeleteGlobalRef({{cPrefix}}_class);
		{{/objects}}
169

170 171 172
		{{#enums}}
		env->DeleteGlobalRef({{cPrefix}}_class);
		{{/enums}}
173 174
	}

175 176 177
	jclass ms_factory_class;
	jmethodID ms_factory_class_constructor;

178 179 180 181
	{{#objects}}
	jclass {{cPrefix}}_class;
	jmethodID {{cPrefix}}_class_constructor;
	{{/objects}}
182 183 184 185 186

	{{#enums}}
	jclass {{cPrefix}}_class;
	jmethodID {{cPrefix}}_class_constructor_from_int;
	{{/enums}}
187 188
};

189
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
190 191 192
#ifdef __cplusplus
extern "C" {
#endif
193

Sylvain Berfini's avatar
Sylvain Berfini committed
194
{{#objects}}
195
jobject get{{className}}(JNIEnv *env, {{classCName}} *cptr) {
Sylvain Berfini's avatar
Sylvain Berfini committed
196 197
	jobject jobj = 0;

198 199
	if (cptr != NULL) {
		void *up = belle_sip_object_data_get((belle_sip_object_t *)cptr, belle_sip_java_user_data_key);
200
		LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get());
201 202 203 204 205
		if (!ljb) {
			ljb = new LinphoneJavaBindings(env);
			linphone_factory_set_user_data(linphone_factory_get(), ljb);
		}

206 207
		jclass {{cPrefix}}_class = ljb->{{cPrefix}}_class;
		jmethodID {{cPrefix}}_constructor = ljb->{{cPrefix}}_class_constructor;
Sylvain Berfini's avatar
Sylvain Berfini committed
208 209

		if (up == NULL) {
210 211 212
			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);
			{{cPrefix}}_ref(cptr);
Sylvain Berfini's avatar
Sylvain Berfini committed
213 214 215 216 217 218
		} else {
			jobj = env->NewLocalRef((jobject)up);
			if (jobj == NULL) {
				// Delete weak ref ?
				env->DeleteWeakGlobalRef((jobject)up);
				// takes implicit local ref
219 220 221
				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);
				{{cPrefix}}_ref(cptr);
Sylvain Berfini's avatar
Sylvain Berfini committed
222 223 224 225 226 227 228 229
			}
		}
	}
	return jobj;
}

void Java_{{jniPrefix}}{{classImplName}}_unref(JNIEnv* env, jobject thiz, jlong ptr) {
	{{classCName}} *cptr = ({{classCName}}*)ptr;
230 231
	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
232 233 234 235 236 237 238
	if (wref) {
		env->DeleteWeakGlobalRef(wref);
	}
	{{cPrefix}}_unref(cptr);
}

{{/objects}}
239 240 241 242 243 244 245 246 247 248 249
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

250
{{#callbacks}}
251 252
static {{return}} {{callbackName}}({{params}}) {
	JNIEnv *env = 0;
253 254
	jint jvmResult = jvm->AttachCurrentThread(&env,NULL);
	if (jvmResult != 0) {
255
		ms_error("cannot attach VM");
256
		return{{returnIfFail}};
257 258
	}

259
	{{#isSingleListener}}
260
	{{classCName}}Cbs *cbs = {{cPrefix}}_get_callbacks({{firstParam}});
261 262
	{{/isSingleListener}}
	{{#isMultiListener}}
263
	{{classCName}}Cbs *cbs = {{cPrefix}}_get_current_callbacks({{firstParam}});
264
	{{/isMultiListener}}
265 266 267 268
	jobject jlistener = (jobject) {{cPrefix}}_cbs_get_user_data(cbs);

	if (jlistener == NULL) {
		ms_warning("{{name}}() notification without listener");
269
		return{{returnIfFail}};
270 271 272 273 274 275 276
	}

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

	{{#jobjects}}
277
	jobject j_{{objectName}} = get{{className}}(env, (Linphone{{className}} *){{objectName}});
278 279
	{{/jobjects}}
	{{#jenums}}
280
	LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get());
281 282 283 284 285 286
	jobject j_{{enumName}} = env->CallStaticObjectMethod(ljb->{{cEnumPrefix}}_class, ljb->{{cEnumPrefix}}_class_constructor_from_int, (jint){{enumName}});
	{{/jenums}}
	{{#jstrings}}
	jstring j_{{stringName}} = {{stringName}} ? env->NewStringUTF({{stringName}}) : NULL;
	{{/jstrings}}
	
287 288 289 290 291 292 293 294 295 296
	{{#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}}
297 298 299 300 301 302 303 304 305 306 307 308 309

	{{#jobjects}}
	if (j_{{objectName}}) {
		env->DeleteLocalRef(j_{{objectName}});
	}
	{{/jobjects}}
	{{#jstrings}}
	if (j_{{stringName}}) {
		env->DeleteLocalRef(j_{{stringName}});
	}
	{{/jstrings}}

	handle_possible_java_exception(env, jlistener);
310
	{{#hasReturn}}
311
	return c_upcall_result;
312
	{{/hasReturn}}
313 314
}

315 316 317 318 319
{{/callbacks}}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

{{#interfaces}}
{{#isSingleListener}}
320
void Java_{{jniPackage}}{{className}}Impl_setListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) {
321 322
{{/isSingleListener}}
{{#isMultiListener}}
323
void Java_{{jniPackage}}{{className}}Impl_addListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) {
324 325 326 327
{{/isMultiListener}}
	{{classCName}} *cptr = ({{classCName}}*)ptr;
	jobject listener = env->NewGlobalRef(jlistener);
	{{#isSingleListener}}
328
	{{classCName}}Cbs *cbs = {{cPrefix}}_get_callbacks(cptr);
329 330 331 332 333 334 335 336
	{{/isSingleListener}}
	{{#isMultiListener}}
	{{classCName}}Cbs *cbs = linphone_factory_create_{{factoryName}}_cbs(NULL);
	{{/isMultiListener}}
	{{cPrefix}}_cbs_set_user_data(cbs, listener);
	{{#callbacksList}}
	{{cPrefix}}_cbs_set_{{callback}}(cbs, {{callbackName}});
	{{/callbacksList}}
337 338 339
	{{#isMultiListener}}
	{{cPrefix}}_add_callbacks(cptr, cbs);
	{{/isMultiListener}}
340 341 342
}
{{#isMultiListener}}

343
void Java_{{jniPackage}}{{className}}Impl_removeListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) {
344
	{{classCName}} *cptr = ({{classCName}}*)ptr;
Sylvain Berfini's avatar
Sylvain Berfini committed
345
	const bctbx_list_t *cbs_list = {{cPrefix}}_get_callbacks_list(cptr);
346
	bctbx_list_t *it;
347
	for (it = (bctbx_list_t *)cbs_list; it != NULL; it = it->next) {
348 349 350 351 352 353
		{{classCName}}Cbs *cbs = ({{classCName}}Cbs *)it->data;
		if ({{cPrefix}}_cbs_get_user_data(cbs) == jlistener) {
			{{cPrefix}}_remove_callbacks(cptr, cbs);
			break;
		}
	}	
354 355 356
}
{{/isMultiListener}}

357 358
{{/interfaces}}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
359

360
jobject Java_{{jni_package}}CoreImpl_getMediastreamerFactory(JNIEnv *env, jobject thiz, jlong ptr) {
361 362 363 364 365
	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
366 367 368
jobject Java_{{jni_package}}FactoryImpl_createCore(JNIEnv *env, jobject thiz, jobject jfactory, jobject jlistener, jstring jconfig_path, jstring jfactory_config_path) {
	LinphoneFactory *cptr = linphone_factory_get();
	SetObjectNativePtr(env, jfactory, (jlong)cptr); // Set the C factory ptr as Factory.nativePtr for next factory calls
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419

	LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(cptr);
	jobject listener = env->NewGlobalRef(jlistener);

	const char *config_path = GetStringUTFChars(env, jconfig_path);
	const char *factory_config_path = GetStringUTFChars(env, jfactory_config_path);
	LinphoneCore *core = NULL;

	linphone_core_cbs_set_user_data(cbs, listener);
	linphone_core_cbs_set_transfer_state_changed(cbs, linphone_core_on_transfer_state_changed);
	linphone_core_cbs_set_chat_room_instantiated(cbs, linphone_core_on_chat_room_instantiated);
	linphone_core_cbs_set_friend_list_created(cbs, linphone_core_on_friend_list_created);
	linphone_core_cbs_set_subscription_state_changed(cbs, linphone_core_on_subscription_state_changed);
	linphone_core_cbs_set_call_log_updated(cbs, linphone_core_on_call_log_updated);
	linphone_core_cbs_set_call_state_changed(cbs, linphone_core_on_call_state_changed);
	linphone_core_cbs_set_authentication_requested(cbs, linphone_core_on_authentication_requested);
	linphone_core_cbs_set_notify_presence_received_for_uri_or_tel(cbs, linphone_core_on_notify_presence_received_for_uri_or_tel);
	linphone_core_cbs_set_buddy_info_updated(cbs, linphone_core_on_buddy_info_updated);
	linphone_core_cbs_set_network_reachable(cbs, linphone_core_on_network_reachable);
	linphone_core_cbs_set_notify_received(cbs, linphone_core_on_notify_received);
	linphone_core_cbs_set_new_subscription_requested(cbs, linphone_core_on_new_subscription_requested);
	linphone_core_cbs_set_registration_state_changed(cbs, linphone_core_on_registration_state_changed);
	linphone_core_cbs_set_notify_presence_received(cbs, linphone_core_on_notify_presence_received);
	linphone_core_cbs_set_ec_calibration_audio_init(cbs, linphone_core_on_ec_calibration_audio_init);
	linphone_core_cbs_set_message_received(cbs, linphone_core_on_message_received);
	linphone_core_cbs_set_ec_calibration_result(cbs, linphone_core_on_ec_calibration_result);
	linphone_core_cbs_set_info_received(cbs, linphone_core_on_info_received);
	linphone_core_cbs_set_call_stats_updated(cbs, linphone_core_on_call_stats_updated);
	linphone_core_cbs_set_friend_list_removed(cbs, linphone_core_on_friend_list_removed);
	linphone_core_cbs_set_refer_received(cbs, linphone_core_on_refer_received);
	linphone_core_cbs_set_configuring_status(cbs, linphone_core_on_configuring_status);
	linphone_core_cbs_set_call_created(cbs, linphone_core_on_call_created);
	linphone_core_cbs_set_publish_state_changed(cbs, linphone_core_on_publish_state_changed);
	linphone_core_cbs_set_call_encryption_changed(cbs, linphone_core_on_call_encryption_changed);
	linphone_core_cbs_set_is_composing_received(cbs, linphone_core_on_is_composing_received);
	linphone_core_cbs_set_message_received_unable_decrypt(cbs, linphone_core_on_message_received_unable_decrypt);
	linphone_core_cbs_set_log_collection_upload_progress_indication(cbs, linphone_core_on_log_collection_upload_progress_indication);
	linphone_core_cbs_set_version_update_check_result_received(cbs, linphone_core_on_version_update_check_result_received);
	linphone_core_cbs_set_ec_calibration_audio_uninit(cbs, linphone_core_on_ec_calibration_audio_uninit);
	linphone_core_cbs_set_global_state_changed(cbs, linphone_core_on_global_state_changed);
	linphone_core_cbs_set_log_collection_upload_state_changed(cbs, linphone_core_on_log_collection_upload_state_changed);
	linphone_core_cbs_set_dtmf_received(cbs, linphone_core_on_dtmf_received);

	core = linphone_factory_create_core(linphone_factory_get(), cbs, config_path, factory_config_path);

	ReleaseStringUTFChars(env, jconfig_path, config_path);
	ReleaseStringUTFChars(env, jfactory_config_path, factory_config_path);

	return getCore(env, core);
}

420
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sylvain Berfini's avatar
Sylvain Berfini committed
421 422 423

{{#methods}}
{{return}} {{name}}({{params}}) {
424
	{{#notStatic}}{{classCName}} *cptr = ({{classCName}}*)ptr;{{/notStatic}}{{#strings}}
Sylvain Berfini's avatar
Sylvain Berfini committed
425
	const char* c_{{string}} = GetStringUTFChars(env, {{string}});
426 427 428
	{{/strings}}{{#bytes}}
	{{bytesargtype}} c_{{bytesargname}} = ({{bytesargtype}})env->GetByteArrayElements({{bytesargname}}, NULL);
	{{/bytes}}{{#objects}}
Sylvain Berfini's avatar
Sylvain Berfini committed
429 430
	{{objectClassCName}}* c_{{object}} = NULL;
	if ({{object}}) c_{{object}} = ({{objectClassCName}}*)GetObjectNativePtr(env, {{object}});
431 432
	{{/objects}}{{#lists}}
	bctbx_list_t *bctbx_list_{{list}} = NULL;
433 434
	int {{list}}_count = env->GetArrayLength({{list}});
	for (int i=0; i < {{list}}_count; i++) {
435 436 437 438 439 440 441 442 443 444
		{{#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);
445
		bctbx_list_{{list}} = bctbx_list_append(bctbx_list_{{list}}, ({{objectClassCName}} *)GetObjectNativePtr(env, obj));
446 447 448
		{{/isObjList}}
	}
	{{/lists}}{{#hasListReturn}}
449
	const bctbx_list_t *list = {{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}});
450
	size_t count = bctbx_list_size(list);
451
	{{#isRealObjectArray}}
452
	LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get());
453 454
	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}}
455 456 457
	for (size_t i = 0; i < count; i++) {
		{{#isRealObjectArray}}
		{{objectClassCName}}* c_object = ({{objectClassCName}}*)list->data;
458
		jobject object = get{{objectClassName}}(env, c_object);
459
		{{/isRealObjectArray}}
460 461
		{{#isStringObjectArray}}const char *cstring = (const char *)list->data;
		jstring object = cstring ? env->NewStringUTF(cstring) : 0;{{/isStringObjectArray}}
462
		if (object != 0) {
463
			env->SetObjectArrayElement(jni_list_result, (int)i, object);
464 465 466 467
			{{#isRealObjectArray}}env->DeleteLocalRef(object);{{/isRealObjectArray}}
		}
		list = bctbx_list_next(list);
	}
468 469 470 471 472 473 474 475
	{{/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}}
476 477 478 479
	const char *c_string = {{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}}){{#returnObject}}){{/returnObject}};
	jstring jni_result = (c_string != NULL) ? env->NewStringUTF(c_string) : NULL;
	{{/hasStringReturn}}{{#hasNormalReturn}}
	{{#hasReturn}}{{return}} jni_result = ({{return}}){{#returnObject}}get{{returnClassName}}(env, (Linphone{{returnClassName}} *){{/returnObject}}{{/hasReturn}}{{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}}){{#returnObject}}){{/returnObject}};
480
	{{/hasNormalReturn}}{{#strings}}
Sylvain Berfini's avatar
Sylvain Berfini committed
481
	ReleaseStringUTFChars(env, {{string}}, c_{{string}});
482 483 484
	{{/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
485 486
}

487 488 489 490 491
{{/methods}}

#ifdef __cplusplus
}
#endif