jni.mustache 22.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
#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;
}

Sylvain Berfini's avatar
Sylvain Berfini committed
72 73 74 75 76 77
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);
}

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

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

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

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

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

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

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

		env->DeleteGlobalRef(ms_factory_class);

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

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

174 175 176
	jclass ms_factory_class;
	jmethodID ms_factory_class_constructor;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

{{#interfaces}}
{{#isSingleListener}}
319
void Java_{{jniPackage}}{{className}}Impl_setListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) {
320 321
{{/isSingleListener}}
{{#isMultiListener}}
322
void Java_{{jniPackage}}{{className}}Impl_addListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) {
323 324 325 326
{{/isMultiListener}}
	{{classCName}} *cptr = ({{classCName}}*)ptr;
	jobject listener = env->NewGlobalRef(jlistener);
	{{#isSingleListener}}
327
	{{classCName}}Cbs *cbs = {{cPrefix}}_get_callbacks(cptr);
328 329 330 331 332 333 334 335
	{{/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}}
336 337 338
	{{#isMultiListener}}
	{{cPrefix}}_add_callbacks(cptr, cbs);
	{{/isMultiListener}}
339 340 341
}
{{#isMultiListener}}

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

356 357
{{/interfaces}}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
358

359
jobject Java_{{jni_package}}CoreImpl_getMediastreamerFactory(JNIEnv *env, jobject thiz, jlong ptr) {
360 361 362 363 364
	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);
}

365
jobject Java_{{jni_package}}FactoryImpl_createCore(JNIEnv *env, jobject thiz, jobject jfactory, jobject jlistener, jstring jconfig_path, jstring jfactory_config_path, jobject jcontext) {
Sylvain Berfini's avatar
Sylvain Berfini committed
366 367
	LinphoneFactory *cptr = linphone_factory_get();
	SetObjectNativePtr(env, jfactory, (jlong)cptr); // Set the C factory ptr as Factory.nativePtr for next factory calls
368 369 370 371 372 373 374 375 376 377

	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);
Sylvain Berfini's avatar
Sylvain Berfini committed
378
	linphone_core_cbs_set_chat_room_state_changed(cbs, linphone_core_on_chat_room_state_changed);
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
	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);

411
	core = linphone_factory_create_core_2(linphone_factory_get(), cbs, config_path, factory_config_path, NULL, (void *)jcontext);
412 413 414 415 416 417 418

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

	return getCore(env, core);
}

419
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sylvain Berfini's avatar
Sylvain Berfini committed
420 421

{{#methods}}
422
{{#notEmpty}}
Sylvain Berfini's avatar
Sylvain Berfini committed
423
{{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
{{/notEmpty}}
487 488
{{/methods}}

489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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;
	jobject oldWindow = (jobject) linphone_core_get_native_video_window_id(cptr);
	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;
	jobject oldWindow = (jobject) linphone_core_get_native_preview_window_id(cptr);
	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);
	}
}

547 548 549
#ifdef __cplusplus
}
#endif