diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index b02d07e86..29c961d51 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -3323,7 +3323,7 @@ static void linphone_call_start_text_stream(LinphoneCall *call) { if (is_multicast) rtp_session_set_multicast_ttl(call->textstream->ms.sessions.rtp_session,tstream->ttl); text_stream_start(call->textstream, call->text_profile, rtp_addr, tstream->rtp_port, rtcp_addr, (linphone_core_rtcp_enabled(lc) && !is_multicast) ? (tstream->rtcp_port ? tstream->rtcp_port : tstream->rtp_port + 1) : 0, used_pt); - ms_filter_add_notify_callback(call->textstream->rttsink, real_time_text_character_received, call, TRUE); + ms_filter_add_notify_callback(call->textstream->rttsink, real_time_text_character_received, call, FALSE); ms_media_stream_sessions_set_encryption_mandatory(&call->textstream->ms.sessions,linphone_core_is_media_encryption_mandatory(call->core)); } else ms_warning("No text stream accepted."); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 9b52e7fcf..34a5f6717 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1684,6 +1684,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab ms_init(); linphone_core_register_default_codecs(lc); + linphone_core_register_offer_answer_providers(lc); /* Get the mediastreamer2 event queue */ /* This allows to run event's callback in linphone_core_iterate() */ lc->msevq=ms_factory_create_event_queue(ms_factory_get_fallback()); diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 9638fe9de..92a648b60 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -196,177 +196,36 @@ extern "C" void Java_org_linphone_core_LinphoneCoreFactoryImpl_setLogCollectionP } // LinphoneCore -/* - * returns the java LinphoneProxyConfig associated with a C LinphoneProxyConfig. -**/ -jobject getProxy(JNIEnv *env, LinphoneProxyConfig *proxy, jobject core){ - jobject jobj=0; - - if (proxy!=NULL){ - jclass proxyClass = (jclass)env->FindClass("org/linphone/core/LinphoneProxyConfigImpl"); - jmethodID proxyCtrId = env->GetMethodID(proxyClass,"", "(Lorg/linphone/core/LinphoneCoreImpl;J)V"); - - void *up=linphone_proxy_config_get_user_data(proxy); - - if (up==NULL){ - jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy); - linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj)); - linphone_proxy_config_ref(proxy); - }else{ - //promote the weak ref to local ref - jobj=env->NewLocalRef((jobject)up); - if (jobj == NULL){ - //the weak ref was dead - jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy); - linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj)); - } - } - env->DeleteLocalRef(proxyClass); - } - return jobj; -} - -jobject getCall(JNIEnv *env, LinphoneCall *call){ - jobject jobj=0; - - if (call!=NULL){ - jclass callClass = (jclass)env->FindClass("org/linphone/core/LinphoneCallImpl"); - jmethodID callCtrId = env->GetMethodID(callClass,"", "(J)V"); - - void *up=linphone_call_get_user_pointer(call); - - if (up==NULL){ - jobj=env->NewObject(callClass,callCtrId,(jlong)call); - jobj=env->NewGlobalRef(jobj); - linphone_call_set_user_pointer(call,(void*)jobj); - linphone_call_ref(call); - }else{ - jobj=(jobject)up; - } - env->DeleteLocalRef(callClass); - } - return jobj; -} - -jobject getChatMessage(JNIEnv *env, LinphoneChatMessage *msg){ - jobject jobj = 0; - - if (msg != NULL){ - jclass chatMessageClass = (jclass)env->FindClass("org/linphone/core/LinphoneChatMessageImpl"); - jmethodID chatMessageCtrId = env->GetMethodID(chatMessageClass,"", "(J)V"); - - void *up = linphone_chat_message_get_user_data(msg); - - if (up == NULL) { - jobj = env->NewObject(chatMessageClass,chatMessageCtrId,(jlong)linphone_chat_message_ref(msg)); - jobj = env->NewGlobalRef(jobj); - linphone_chat_message_set_user_data(msg,(void*)jobj); - } else { - jobj = (jobject)up; - } - env->DeleteLocalRef(chatMessageClass); - } - return jobj; -} - -jobject getFriend(JNIEnv *env, LinphoneFriend *lfriend){ - jobject jobj=0; - - if (lfriend != NULL){ - jclass friendClass = (jclass)env->FindClass("org/linphone/core/LinphoneFriendImpl"); - jmethodID friendCtrId = env->GetMethodID(friendClass,"", "(J)V"); - - void *up=linphone_friend_get_user_data(lfriend); - - if (up == NULL){ - jobj=env->NewObject(friendClass,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){ - jobj=env->NewObject(friendClass,friendCtrId,(jlong)lfriend); - linphone_friend_set_user_data(lfriend,(void*)env->NewWeakGlobalRef(jobj)); - } - } - env->DeleteLocalRef(friendClass); - } - return jobj; -} - -jobject getEvent(JNIEnv *env, LinphoneEvent *lev){ - if (lev==NULL) return NULL; - jobject jev=(jobject)linphone_event_get_user_data(lev); - if (jev==NULL){ - jclass linphoneEventClass = (jclass)env->FindClass("org/linphone/core/LinphoneEventImpl"); - jmethodID linphoneEventCtrId = env->GetMethodID(linphoneEventClass,"", "(J)V"); - - jev=env->NewObject(linphoneEventClass,linphoneEventCtrId,(jlong)linphone_event_ref(lev)); - jev=env->NewGlobalRef(jev); - linphone_event_set_user_data(lev,jev); - - env->DeleteLocalRef(linphoneEventClass); - } - return jev; -} - -class LinphoneCoreData { +class LinphoneJavaBindings { public: - LinphoneCoreData(JNIEnv *env, jobject lc, LinphoneCoreVTable *vTable, jobject alistener) { - core = env->NewGlobalRef(lc); - listener = env->NewGlobalRef(alistener); - - memset(vTable, 0, sizeof(LinphoneCoreVTable)); - - listenerClass = (jclass)env->NewGlobalRef(env->GetObjectClass(alistener)); - + LinphoneJavaBindings(JNIEnv *env) { + listenerClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCoreListener")); + /*displayStatus(LinphoneCore lc,String message);*/ displayStatusId = env->GetMethodID(listenerClass,"displayStatus","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;)V"); - if (displayStatusId) { - vTable->display_status = displayStatusCb; - } /*void generalState(LinphoneCore lc,int state); */ globalStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$GlobalState")); globalStateFromIntId = env->GetStaticMethodID(globalStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$GlobalState;"); globalStateId = env->GetMethodID(listenerClass,"globalState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$GlobalState;Ljava/lang/String;)V"); - if (globalStateId) { - vTable->global_state_changed = globalStateChange; - } /*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;"); registrationStateId = env->GetMethodID(listenerClass,"registrationState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneProxyConfig;Lorg/linphone/core/LinphoneCore$RegistrationState;Ljava/lang/String;)V"); - if (registrationStateId) { - vTable->registration_state_changed = registrationStateChange; - } /*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;"); callStateId = env->GetMethodID(listenerClass,"callState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;Ljava/lang/String;)V"); - if (callStateId) { - vTable->call_state_changed = callStateChange; - } transferStateId = env->GetMethodID(listenerClass,"transferState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;)V"); - if (transferStateId) { - vTable->transfer_state_changed = transferStateChanged; - } /*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"); - if (callStatsUpdatedId) { - vTable->call_stats_updated = callStatsUpdated; - } /*callEncryption(LinphoneCore lc, LinphoneCall call, boolean encrypted,String auth_token);*/ callEncryptionChangedId = env->GetMethodID(listenerClass,"callEncryptionChanged","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;ZLjava/lang/String;)V"); - if (callEncryptionChangedId) { - vTable->call_encryption_changed = callEncryptionChange; - } /*void ecCalibrationStatus(LinphoneCore.EcCalibratorStatus status, int delay_ms, Object data);*/ ecCalibratorStatusClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$EcCalibratorStatus")); @@ -375,92 +234,44 @@ public: /*void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url)*/ newSubscriptionRequestId = env->GetMethodID(listenerClass,"newSubscriptionRequest","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;Ljava/lang/String;)V"); - if (newSubscriptionRequestId) { - vTable->new_subscription_requested = new_subscription_requested; - } authInfoRequestedId = env->GetMethodID(listenerClass,"authInfoRequested","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - if (authInfoRequestedId) { - vTable->auth_info_requested = authInfoRequested; - } /*void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf);*/ notifyPresenceReceivedId = env->GetMethodID(listenerClass,"notifyPresenceReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;)V"); - if (notifyPresenceReceivedId) { - vTable->notify_presence_received = notify_presence_received; - } messageReceivedId = env->GetMethodID(listenerClass,"messageReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V"); - if (messageReceivedId) { - vTable->message_received = message_received; - } isComposingReceivedId = env->GetMethodID(listenerClass,"isComposingReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;)V"); - if (isComposingReceivedId) { - vTable->is_composing_received = is_composing_received; - } dtmfReceivedId = env->GetMethodID(listenerClass,"dtmfReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;I)V"); - if (dtmfReceivedId) { - vTable->dtmf_received = dtmf_received; - } infoReceivedId = env->GetMethodID(listenerClass,"infoReceived", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneInfoMessage;)V"); - if (infoReceivedId) { - vTable->info_received = infoReceived; - } subscriptionStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/SubscriptionState")); subscriptionStateFromIntId = env->GetStaticMethodID(subscriptionStateClass,"fromInt","(I)Lorg/linphone/core/SubscriptionState;"); subscriptionStateId = env->GetMethodID(listenerClass,"subscriptionStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Lorg/linphone/core/SubscriptionState;)V"); - if (subscriptionStateId) { - vTable->subscription_state_changed = subscriptionStateChanged; - } publishStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/PublishState")); publishStateFromIntId = env->GetStaticMethodID(publishStateClass,"fromInt","(I)Lorg/linphone/core/PublishState;"); publishStateId = env->GetMethodID(listenerClass,"publishStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Lorg/linphone/core/PublishState;)V"); - if (publishStateId) { - vTable->publish_state_changed = publishStateChanged; - } notifyRecvId = env->GetMethodID(listenerClass,"notifyReceived", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Ljava/lang/String;Lorg/linphone/core/LinphoneContent;)V"); - if (notifyRecvId) { - vTable->notify_received = notifyReceived; - } configuringStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RemoteProvisioningState")); configuringStateFromIntId = env->GetStaticMethodID(configuringStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;"); configuringStateId = env->GetMethodID(listenerClass,"configuringStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;Ljava/lang/String;)V"); - if (configuringStateId) { - vTable->configuring_status = configuringStatus; - } fileTransferProgressIndicationId = env->GetMethodID(listenerClass, "fileTransferProgressIndication", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;I)V"); - if (fileTransferProgressIndicationId) { - vTable->file_transfer_progress_indication = fileTransferProgressIndication; - } fileTransferSendId = env->GetMethodID(listenerClass, "fileTransferSend", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;Ljava/nio/ByteBuffer;I)I"); - if (fileTransferSendId) { - vTable->file_transfer_send = fileTransferSend; - } fileTransferRecvId = env->GetMethodID(listenerClass, "fileTransferRecv", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;[BI)V"); - if (fileTransferRecvId) { - vTable->file_transfer_recv = fileTransferRecv; - } logCollectionUploadStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$LogCollectionUploadState")); logCollectionUploadStateFromIntId = env->GetStaticMethodID(logCollectionUploadStateClass, "fromInt", "(I)Lorg/linphone/core/LinphoneCore$LogCollectionUploadState;"); logCollectionUploadProgressId = env->GetMethodID(listenerClass, "uploadProgressIndication", "(Lorg/linphone/core/LinphoneCore;II)V"); - if (logCollectionUploadProgressId) { - vTable->log_collection_upload_progress_indication = logCollectionUploadProgressIndication; - } logCollectionUploadStateId = env->GetMethodID(listenerClass, "uploadStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$LogCollectionUploadState;Ljava/lang/String;)V"); - if (logCollectionUploadStateId) { - vTable->log_collection_upload_state_changed = logCollectionUploadStateChange; - } chatMessageStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatMessage$State")); chatMessageStateFromIntId = env->GetStaticMethodID(chatMessageStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneChatMessage$State;"); @@ -499,12 +310,18 @@ public: subscriptionDirClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/SubscriptionDir")); subscriptionDirFromIntId = env->GetStaticMethodID(subscriptionDirClass,"fromInt","(I)Lorg/linphone/core/SubscriptionDir;"); } + + void setCore(jobject c) { + core = c; + } + + jobject getCore() { + return core; + } - ~LinphoneCoreData() { + ~LinphoneJavaBindings() { JNIEnv *env = 0; jvm->AttachCurrentThread(&env,NULL); - env->DeleteGlobalRef(core); - env->DeleteGlobalRef(listener); env->DeleteGlobalRef(listenerClass); env->DeleteGlobalRef(globalStateClass); env->DeleteGlobalRef(configuringStateClass); @@ -522,8 +339,8 @@ public: env->DeleteGlobalRef(subscriptionDirClass); env->DeleteGlobalRef(logCollectionUploadStateClass); } + jobject core; - jobject listener; jclass listenerClass; jmethodID displayStatusId; @@ -611,6 +428,227 @@ public: jmethodID logCollectionUploadStateId; jmethodID logCollectionUploadStateFromIntId; jmethodID logCollectionUploadProgressId; +}; + +/* + * 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{ + //promote the weak ref to local ref + 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; +} + +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) { + jobj = env->NewObject(ljb->chatMessageClass, ljb->chatMessageCtrId, (jlong)linphone_chat_message_ref(msg)); + jobj = env->NewGlobalRef(jobj); + linphone_chat_message_set_user_data(msg,(void*)jobj); + } else { + jobj = (jobject)up; + } + } + return jobj; +} + +jobject getFriend(JNIEnv *env, LinphoneFriend *lfriend){ + jobject jobj=0; + + 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){ + 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){ + jobj=env->NewObject(ljb->friendClass, ljb->friendCtrId, (jlong)lfriend); + linphone_friend_set_user_data(lfriend,(void*)env->NewWeakGlobalRef(jobj)); + } + } + } + return jobj; +} + +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; +} + +class LinphoneCoreData { +public: + LinphoneCoreData(JNIEnv *env, jobject lc, LinphoneCoreVTable *vTable, jobject alistener, LinphoneJavaBindings *ljb) { + core = env->NewGlobalRef(lc); + listener = env->NewGlobalRef(alistener); + + 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; + } + + if (ljb->notifyPresenceReceivedId) { + vTable->notify_presence_received = notify_presence_received; + } + + if (ljb->messageReceivedId) { + vTable->message_received = message_received; + } + + 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; + } + + 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; + } + } + + ~LinphoneCoreData() { + JNIEnv *env = 0; + jvm->AttachCurrentThread(&env,NULL); + env->DeleteGlobalRef(core); + env->DeleteGlobalRef(listener); + } + + jobject core; + jobject listener; LinphoneCoreVTable vTable; @@ -621,10 +659,12 @@ public: ms_error("cannot attach VM"); return; } + + 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); jstring msg = message ? env->NewStringUTF(message) : NULL; - env->CallVoidMethod(lcData->listener,lcData->displayStatusId,lcData->core,msg); + env->CallVoidMethod(lcData->listener,ljb->displayStatusId,lcData->core,msg); handle_possible_java_exception(env, lcData->listener); if (msg) { env->DeleteLocalRef(msg); @@ -637,13 +677,15 @@ public: ms_error("cannot attach VM"); return; } + + 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); jstring r = realm ? env->NewStringUTF(realm) : NULL; jstring u = username ? env->NewStringUTF(username) : NULL; jstring d = domain ? env->NewStringUTF(domain) : NULL; env->CallVoidMethod(lcData->listener, - lcData->authInfoRequestedId, + ljb->authInfoRequestedId, lcData->core, r, u, @@ -675,6 +717,8 @@ public: ms_error("cannot attach VM"); return; } + + 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); @@ -684,9 +728,9 @@ public: jstring msg = message ? env->NewStringUTF(message) : NULL; env->CallVoidMethod(lcData->listener - ,lcData->globalStateId + ,ljb->globalStateId ,lcData->core - ,env->CallStaticObjectMethod(lcData->globalStateClass,lcData->globalStateFromIntId,(jint)gstate), + ,env->CallStaticObjectMethod(ljb->globalStateClass,ljb->globalStateFromIntId,(jint)gstate), msg); handle_possible_java_exception(env, lcData->listener); if (msg) { @@ -701,14 +745,16 @@ public: ms_error("cannot attach VM"); return; } + + 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); jstring msg = message ? env->NewStringUTF(message) : NULL; env->CallVoidMethod(lcData->listener - ,lcData->registrationStateId + ,ljb->registrationStateId ,lcData->core ,(jproxy=getProxy(env,proxy,lcData->core)) - ,env->CallStaticObjectMethod(lcData->registrationStateClass,lcData->registrationStateFromIntId,(jint)state), + ,env->CallStaticObjectMethod(ljb->registrationStateClass,ljb->registrationStateFromIntId,(jint)state), msg); handle_possible_java_exception(env, lcData->listener); if (msg) { @@ -724,14 +770,16 @@ public: ms_error("cannot attach VM"); return; } + + 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); jstring msg = message ? env->NewStringUTF(message) : NULL; env->CallVoidMethod(lcData->listener - ,lcData->callStateId + ,ljb->callStateId ,lcData->core ,(jcall=getCall(env,call)) - ,env->CallStaticObjectMethod(lcData->callStateClass,lcData->callStateFromIntId,(jint)state), + ,env->CallStaticObjectMethod(ljb->callStateClass,ljb->callStateFromIntId,(jint)state), msg); handle_possible_java_exception(env, lcData->listener); if (state==LinphoneCallReleased) { @@ -749,10 +797,12 @@ public: ms_error("cannot attach VM"); return; } + + 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 - ,lcData->callEncryptionChangedId + ,ljb->callEncryptionChangedId ,lcData->core ,getCall(env,call) ,encrypted @@ -766,10 +816,12 @@ public: ms_error("cannot attach VM"); return; } + + 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 - ,lcData->notifyPresenceReceivedId + ,ljb->notifyPresenceReceivedId ,lcData->core ,getFriend(env,my_friend)); handle_possible_java_exception(env, lcData->listener); @@ -781,10 +833,12 @@ public: ms_error("cannot attach VM"); return; } + + 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 - ,lcData->newSubscriptionRequestId + ,ljb->newSubscriptionRequestId ,lcData->core ,getFriend(env,my_friend) ,url ? env->NewStringUTF(url) : NULL); @@ -797,10 +851,12 @@ public: ms_error("cannot attach VM"); return; } + + 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 - ,lcData->dtmfReceivedId + ,ljb->dtmfReceivedId ,lcData->core ,getCall(env,call) ,dtmf); @@ -814,13 +870,15 @@ public: ms_error("cannot attach VM"); return; } + + 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); /*note: we call linphone_chat_message_ref() because the application does not acquire the object when invoked from a callback*/ env->CallVoidMethod(lcData->listener - ,lcData->messageReceivedId + ,ljb->messageReceivedId ,lcData->core - ,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room) + ,env->NewObject(ljb->chatRoomClass,ljb->chatRoomCtrId,(jlong)room) ,(jmsg = getChatMessage(env, msg))); handle_possible_java_exception(env, lcData->listener); } @@ -831,12 +889,14 @@ public: ms_error("cannot attach VM"); return; } + + 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 - ,lcData->isComposingReceivedId + ,ljb->isComposingReceivedId ,lcData->core - ,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room)); + ,env->NewObject(ljb->chatRoomClass,ljb->chatRoomCtrId,(jlong)room)); handle_possible_java_exception(env, lcData->listener); } static void ecCalibrationStatus(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data) { @@ -847,13 +907,14 @@ public: return; } + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); LinphoneCoreVTable *table = (LinphoneCoreVTable*) data; - if (table) { + if (table && ljb) { LinphoneCoreData* lcData = (LinphoneCoreData*) linphone_core_v_table_get_user_data(table); - if (lcData->ecCalibrationStatusId) { - jobject state = env->CallStaticObjectMethod(lcData->ecCalibratorStatusClass, lcData->ecCalibratorStatusFromIntId, (jint)status); + if (ljb->ecCalibrationStatusId) { + jobject state = env->CallStaticObjectMethod(ljb->ecCalibratorStatusClass, ljb->ecCalibratorStatusFromIntId, (jint)status); env->CallVoidMethod(lcData->listener - ,lcData->ecCalibrationStatusId + ,ljb->ecCalibrationStatusId ,lcData->core ,state ,delay_ms @@ -875,15 +936,17 @@ public: ms_error("cannot attach VM"); return; } + + 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); - statsobj = env->NewObject(lcData->callStatsClass, lcData->callStatsId, (jlong)call, (jlong)stats); + statsobj = env->NewObject(ljb->callStatsClass, ljb->callStatsId, (jlong)call, (jlong)stats); callobj = getCall(env, call); if (stats->type == LINPHONE_CALL_STATS_AUDIO) - env->CallVoidMethod(callobj, lcData->callSetAudioStatsId, statsobj); + env->CallVoidMethod(callobj, ljb->callSetAudioStatsId, statsobj); else - env->CallVoidMethod(callobj, lcData->callSetVideoStatsId, statsobj); - env->CallVoidMethod(lcData->listener, lcData->callStatsUpdatedId, lcData->core, callobj, statsobj); + env->CallVoidMethod(callobj, ljb->callSetVideoStatsId, statsobj); + env->CallVoidMethod(lcData->listener, ljb->callStatsUpdatedId, lcData->core, callobj, statsobj); handle_possible_java_exception(env, lcData->listener); if (statsobj) env->DeleteLocalRef(statsobj); } @@ -895,13 +958,15 @@ public: ms_error("cannot attach VM"); return; } + + 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 - ,lcData->transferStateId + ,ljb->transferStateId ,lcData->core ,(jcall=getCall(env,call)) - ,env->CallStaticObjectMethod(lcData->callStateClass,lcData->callStateFromIntId,(jint)remote_call_state) + ,env->CallStaticObjectMethod(ljb->callStateClass,ljb->callStateFromIntId,(jint)remote_call_state) ); handle_possible_java_exception(env, lcData->listener); } @@ -912,14 +977,16 @@ public: ms_error("cannot attach VM"); return; } + + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); LinphoneInfoMessage *copy_info=linphone_info_message_copy(info); LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc); LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table); env->CallVoidMethod(lcData->listener - ,lcData->infoReceivedId + ,ljb->infoReceivedId ,lcData->core ,getCall(env,call) - ,env->NewObject(lcData->infoMessageClass,lcData->infoMessageCtor,(jlong)copy_info) + ,env->NewObject(ljb->infoMessageClass,ljb->infoMessageCtor,(jlong)copy_info) ); handle_possible_java_exception(env, lcData->listener); } @@ -932,12 +999,14 @@ public: ms_error("cannot attach VM"); return; } + + 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); jevent=getEvent(env,ev); - jstate=env->CallStaticObjectMethod(lcData->subscriptionStateClass,lcData->subscriptionStateFromIntId,(jint)state); + jstate=env->CallStaticObjectMethod(ljb->subscriptionStateClass,ljb->subscriptionStateFromIntId,(jint)state); env->CallVoidMethod(lcData->listener - ,lcData->subscriptionStateId + ,ljb->subscriptionStateId ,lcData->core ,jevent ,jstate @@ -958,12 +1027,14 @@ public: ms_error("cannot attach VM"); return; } + + 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); jevent=getEvent(env,ev); - jstate=env->CallStaticObjectMethod(lcData->publishStateClass,lcData->publishStateFromIntId,(jint)state); + jstate=env->CallStaticObjectMethod(ljb->publishStateClass,ljb->publishStateFromIntId,(jint)state); env->CallVoidMethod(lcData->listener - ,lcData->publishStateId + ,ljb->publishStateId ,lcData->core ,jevent ,jstate @@ -978,11 +1049,13 @@ public: ms_error("cannot attach VM"); return; } + + 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); jevent=getEvent(env,ev); env->CallVoidMethod(lcData->listener - ,lcData->notifyRecvId + ,ljb->notifyRecvId ,lcData->core ,jevent ,env->NewStringUTF(evname) @@ -998,9 +1071,11 @@ public: ms_error("cannot attach VM"); return; } + + 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, lcData->configuringStateId, lcData->core, env->CallStaticObjectMethod(lcData->configuringStateClass,lcData->configuringStateFromIntId,(jint)status), message ? env->NewStringUTF(message) : NULL); + env->CallVoidMethod(lcData->listener, ljb->configuringStateId, lcData->core, env->CallStaticObjectMethod(ljb->configuringStateClass,ljb->configuringStateFromIntId,(jint)status), message ? env->NewStringUTF(message) : NULL); handle_possible_java_exception(env, lcData->listener); } @@ -1013,11 +1088,13 @@ public: ms_error("cannot attach VM"); return; } + + 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); jobject jcontent = content ? create_java_linphone_content(env, content) : NULL; env->CallVoidMethod(lcData->listener, - lcData->fileTransferProgressIndicationId, + ljb->fileTransferProgressIndicationId, lcData->core, (jmsg = getChatMessage(env, message)), jcontent, @@ -1037,12 +1114,14 @@ public: ms_error("cannot attach VM"); return; } + + 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); jobject jcontent = content ? create_java_linphone_content(env, content) : NULL; jobject jbuffer = buff ? env->NewDirectByteBuffer(buff, asking) : NULL; *size = env->CallIntMethod(lcData->listener, - lcData->fileTransferSendId, + ljb->fileTransferSendId, lcData->core, (jmsg = getChatMessage(env, message)), jcontent, @@ -1065,6 +1144,8 @@ public: ms_error("cannot attach VM"); return; } + + 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); @@ -1073,7 +1154,7 @@ public: jobject jcontent = content ? create_java_linphone_content(env, content) : NULL; env->CallVoidMethod(lcData->listener, - lcData->fileTransferRecvId, + ljb->fileTransferRecvId, lcData->core, (jmsg = getChatMessage(env, message)), jcontent, @@ -1091,10 +1172,12 @@ public: ms_error("cannot attach VM"); return; } + + 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 - ,lcData->logCollectionUploadProgressId + ,ljb->logCollectionUploadProgressId ,lcData->core ,(jlong)offset ,(jlong)total); @@ -1107,13 +1190,15 @@ public: ms_error("cannot attach VM"); return; } + + 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); jstring msg = info ? env->NewStringUTF(info) : NULL; env->CallVoidMethod(lcData->listener - ,lcData->logCollectionUploadStateId + ,ljb->logCollectionUploadStateId ,lcData->core - ,env->CallStaticObjectMethod(lcData->logCollectionUploadStateClass,lcData->logCollectionUploadStateFromIntId,(jint)state), + ,env->CallStaticObjectMethod(ljb->logCollectionUploadStateClass,ljb->logCollectionUploadStateFromIntId,(jint)state), msg); handle_possible_java_exception(env, lcData->listener); if (msg) { @@ -1142,8 +1227,10 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* const char* userConfig = juserConfig?env->GetStringUTFChars(juserConfig, NULL):NULL; const char* factoryConfig = jfactoryConfig?env->GetStringUTFChars(jfactoryConfig, NULL):NULL; + LinphoneJavaBindings *ljb = new LinphoneJavaBindings(env); + LinphoneCoreVTable *vTable = linphone_core_v_table_new(); - LinphoneCoreData* ldata = new LinphoneCoreData(env, thiz, vTable, jlistener); + LinphoneCoreData* ldata = new LinphoneCoreData(env, thiz, vTable, jlistener, ljb); linphone_core_v_table_set_user_data(vTable, ldata); ms_init(); // Initialize mediastreamer2 before loading the plugins @@ -1174,7 +1261,9 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* #endif jobject core = env->NewGlobalRef(thiz); - jlong nativePtr = (jlong)linphone_core_new(vTable, userConfig, factoryConfig, core); + ljb->setCore(core); + LinphoneCore *lc = linphone_core_new(vTable, userConfig, factoryConfig, ljb); + jlong nativePtr = (jlong)lc; if (userConfig) env->ReleaseStringUTFChars(juserConfig, userConfig); if (factoryConfig) env->ReleaseStringUTFChars(jfactoryConfig, factoryConfig); @@ -1182,7 +1271,7 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_delete(JNIEnv* env, jobject thiz, jlong native_ptr) { LinphoneCore *lc=(LinphoneCore*)native_ptr; - jobject core = (jobject)linphone_core_get_user_data(lc); + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); jobject multicast_lock = lc->multicast_lock; jobject multicast_lock_class = lc->multicast_lock_class; @@ -1197,14 +1286,19 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_delete(JNIEnv* env, jobj if (multicast_lock) env->DeleteGlobalRef(multicast_lock); if (multicast_lock_class) env->DeleteGlobalRef(multicast_lock_class); - if (core) { - env->DeleteGlobalRef(core); + if (ljb) { + jobject core = ljb->getCore(); + if (core) { + env->DeleteGlobalRef(core); + } + delete ljb; } } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addListener(JNIEnv* env, jobject thiz, jlong lc, jobject jlistener) { + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *) linphone_core_get_user_data((LinphoneCore *)lc); LinphoneCoreVTable *vTable = linphone_core_v_table_new(); - LinphoneCoreData* ldata = new LinphoneCoreData(env, thiz, vTable, jlistener); + LinphoneCoreData* ldata = new LinphoneCoreData(env, thiz, vTable, jlistener, ljb); linphone_core_v_table_set_user_data(vTable, ldata); linphone_core_add_listener((LinphoneCore*)lc, vTable); } @@ -1340,8 +1434,8 @@ extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getProxyConfigList(JNIEnv* env, jobject thiz, jlong lc) { const MSList* proxies = linphone_core_get_proxy_config_list((LinphoneCore*)lc); int proxyCount = ms_list_size(proxies); - jclass cls = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneProxyConfigImpl")); - jobjectArray jProxies = env->NewObjectArray(proxyCount,cls,NULL); + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data((LinphoneCore *)lc); + jobjectArray jProxies = env->NewObjectArray(proxyCount,ljb->proxyClass,NULL); for (int i = 0; i < proxyCount; i++ ) { LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data; @@ -1351,7 +1445,7 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getProxyConfigLi } proxies = proxies->next; } - env->DeleteGlobalRef(cls); + return jProxies; } @@ -1850,8 +1944,8 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getFriendList(JN ,jlong lc) { const MSList* friends = linphone_core_get_friend_list((LinphoneCore*)lc); int friendsSize = ms_list_size(friends); - jclass cls = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneFriendImpl")); - jobjectArray jFriends = env->NewObjectArray(friendsSize,cls,NULL); + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data((LinphoneCore *)lc); + jobjectArray jFriends = env->NewObjectArray(friendsSize,ljb->friendClass,NULL); for (int i = 0; i < friendsSize; i++) { LinphoneFriend* lfriend = (LinphoneFriend*)friends->data; @@ -1861,8 +1955,7 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getFriendList(JN } friends = friends->next; } - - env->DeleteGlobalRef(cls); + return jFriends; } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPresenceInfo(JNIEnv* env @@ -2039,8 +2132,9 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_startEchoCalibration(JNI ,jobject thiz ,jlong lc ,jobject data) { + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *) linphone_core_get_user_data((LinphoneCore *)lc); LinphoneCoreVTable *vTable = linphone_core_v_table_new(); - LinphoneCoreData* ldata = new LinphoneCoreData(env, thiz, vTable, data); + LinphoneCoreData* ldata = new LinphoneCoreData(env, thiz, vTable, data, ljb); linphone_core_v_table_set_user_data(vTable, ldata); return (jint)linphone_core_start_echo_calibration((LinphoneCore*)lc, ldata->ecCalibrationStatus, NULL, NULL, vTable); @@ -3003,7 +3097,8 @@ extern "C" jobject Java_org_linphone_core_LinphoneFriendImpl_getCore(JNIEnv* en ,jlong ptr) { LinphoneCore *lc=linphone_friend_get_core((LinphoneFriend*)ptr); if (lc!=NULL){ - jobject core = (jobject)linphone_core_get_user_data(lc); + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); + jobject core = ljb->getCore(); return core; } return NULL; @@ -3379,15 +3474,15 @@ static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageS jobject jmessage = getChatMessage(env, msg); env->DeleteLocalRef(clazz); - jclass chatMessageStateClass = (jclass)env->FindClass("org/linphone/core/LinphoneChatMessage$State"); - jmethodID chatMessageStateFromIntId = env->GetStaticMethodID(chatMessageStateClass, "fromInt","(I)Lorg/linphone/core/LinphoneChatMessage$State;"); - env->CallVoidMethod(listener, method, jmessage, env->CallStaticObjectMethod(chatMessageStateClass, chatMessageStateFromIntId, (jint)state)); + 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); + env->CallVoidMethod(listener, method, jmessage, env->CallStaticObjectMethod(ljb->chatMessageStateClass, ljb->chatMessageStateFromIntId, (jint)state)); if (state == LinphoneChatMessageStateDelivered || state == LinphoneChatMessageStateNotDelivered) { env->DeleteGlobalRef(listener); msg->message_state_changed_user_data = NULL; } - env->DeleteLocalRef(chatMessageStateClass); } static void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total) { @@ -3521,18 +3616,18 @@ static void chat_room_impl_callback(LinphoneChatMessage* msg, LinphoneChatMessag jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageStateChanged","(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneChatMessage$State;)V"); jobject jmessage=(jobject)linphone_chat_message_get_user_data(msg); - jclass chatMessageStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatMessage$State")); - jmethodID chatMessageStateFromIntId = env->GetStaticMethodID(chatMessageStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneChatMessage$State;"); + 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); env->CallVoidMethod( listener, method, jmessage, - env->CallStaticObjectMethod(chatMessageStateClass,chatMessageStateFromIntId,(jint)state)); + env->CallStaticObjectMethod(ljb->chatMessageStateClass,ljb->chatMessageStateFromIntId,(jint)state)); if (state == LinphoneChatMessageStateDelivered || state == LinphoneChatMessageStateNotDelivered) { env->DeleteGlobalRef(listener); env->DeleteGlobalRef(jmessage); - env->DeleteGlobalRef(chatMessageStateClass); linphone_chat_message_set_user_data(msg,NULL); } } @@ -3541,7 +3636,8 @@ extern "C" jobject Java_org_linphone_core_LinphoneChatRoomImpl_getCore(JNIEnv* ,jobject thiz ,jlong chatroom_ptr){ LinphoneCore *lc=linphone_chat_room_get_core((LinphoneChatRoom*)chatroom_ptr); - jobject core = (jobject)linphone_core_get_user_data(lc); + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); + jobject core = ljb->getCore(); return core; } @@ -4336,6 +4432,7 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_tunnelGetServers const MSList *servers = linphone_tunnel_get_servers(tunnel); const MSList *it; int i; + tunnelConfigArray = env->NewObjectArray(ms_list_size(servers), tunnelConfigClass, NULL); for(it = servers, i=0; it != NULL; it = it->next, i++) { LinphoneTunnelConfig *conf = (LinphoneTunnelConfig *)it->data; @@ -4934,7 +5031,8 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreFactoryImpl__1setLogHa JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneEventImpl_getCore(JNIEnv *env, jobject jobj, jlong evptr){ LinphoneCore *lc=linphone_event_get_core((LinphoneEvent*)evptr); - jobject core = (jobject)linphone_core_get_user_data(lc); + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); + jobject core = ljb->getCore(); return core; } diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index 15abe2ca6..0fc099460 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -31,12 +31,8 @@ static bool_t only_telephone_event(const MSList *l){ return TRUE; } -typedef struct _PayloadTypeMatcher{ - const char *mime_type; - PayloadType *(*match_func)(const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads); -}PayloadTypeMatcher; -static PayloadType * opus_match(const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads){ +static PayloadType * opus_match(MSOfferAnswerContext *ctx, const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads, bool_t reading_response){ PayloadType *pt; const MSList *elem; PayloadType *candidate=NULL; @@ -50,15 +46,25 @@ static PayloadType * opus_match(const MSList *local_payloads, const PayloadType pt->channels=1; /*so that we respond with same number of channels */ candidate=pt; }else if (refpt->channels==2){ - return pt; + return payload_type_clone(pt); } } } - return candidate; + return candidate ? payload_type_clone(candidate) : NULL; } +static MSOfferAnswerContext *opus_offer_answer_create_context(void){ + static MSOfferAnswerContext opus_oa = {opus_match, NULL}; + return &opus_oa; +} + +MSOfferAnswerProvider opus_offer_answer_provider={ + "opus", + opus_offer_answer_create_context +}; + /* the reason for this matcher is for some stupid uncompliant phone that offer G729a mime type !*/ -static PayloadType * g729A_match(const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads){ +static PayloadType * g729A_match(MSOfferAnswerContext *ctx, const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads, bool_t reading_response){ PayloadType *pt; const MSList *elem; PayloadType *candidate=NULL; @@ -70,38 +76,57 @@ static PayloadType * g729A_match(const MSList *local_payloads, const PayloadType candidate=pt; } } - return candidate; + return candidate ? payload_type_clone(candidate) : NULL; } -static PayloadType * amr_match(const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads){ - PayloadType *pt; - char value[10]; - const MSList *elem; - PayloadType *candidate=NULL; +static MSOfferAnswerContext *g729a_offer_answer_create_context(void){ + static MSOfferAnswerContext g729_oa = {g729A_match, NULL}; + return &g729_oa; +} - for (elem=local_payloads;elem!=NULL;elem=elem->next){ - pt=(PayloadType*)elem->data; +MSOfferAnswerProvider g729a_offer_answer_provider={ + "G729A", + g729a_offer_answer_create_context +}; + +static PayloadType * red_match(MSOfferAnswerContext *ctx, const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads, bool_t reading_response) { + const MSList *elem_local, *elem_remote; + PayloadType *red = NULL; + + for (elem_local = local_payloads; elem_local != NULL; elem_local = elem_local->next) { + PayloadType *pt = (PayloadType*)elem_local->data; - if ( pt->mime_type && refpt->mime_type - && strcasecmp(pt->mime_type, refpt->mime_type)==0 - && pt->clock_rate==refpt->clock_rate - && pt->channels==refpt->channels) { - int octedalign1=0,octedalign2=0; - if (pt->recv_fmtp!=NULL && fmtp_get_value(pt->recv_fmtp,"octet-align",value,sizeof(value))){ - octedalign1=atoi(value); - } - if (refpt->send_fmtp!=NULL && fmtp_get_value(refpt->send_fmtp,"octet-align",value,sizeof(value))){ - octedalign2=atoi(value); - } - if (octedalign1==octedalign2) { - candidate=pt; - break; /*exact match */ + if (strcasecmp(pt->mime_type, payload_type_t140_red.mime_type) == 0) { + red = payload_type_clone(pt); + + for (elem_remote = remote_payloads; elem_remote != NULL; elem_remote = elem_remote->next) { + PayloadType *pt2 = (PayloadType*)elem_remote->data; + if (strcasecmp(pt2->mime_type, payload_type_t140.mime_type) == 0) { + int t140_payload_number = payload_type_get_number(pt2); + char *red_fmtp = ms_strdup_printf("%i/%i/%i", t140_payload_number, t140_payload_number, t140_payload_number); + /*modify the local payload and the return value*/ + payload_type_set_recv_fmtp(pt, red_fmtp); + payload_type_set_recv_fmtp(red, red_fmtp); + ms_free(red_fmtp); + break; + } } + break; } } - return candidate; + return red; } +static MSOfferAnswerContext *red_offer_answer_create_context(void){ + static MSOfferAnswerContext red_oa = {red_match, NULL}; + return &red_oa; +} + +MSOfferAnswerProvider red_offer_answer_provider={ + "red", + red_offer_answer_create_context +}; + static PayloadType * generic_match(const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads){ PayloadType *pt; const MSList *elem; @@ -113,55 +138,31 @@ static PayloadType * generic_match(const MSList *local_payloads, const PayloadTy && strcasecmp(pt->mime_type, refpt->mime_type)==0 && pt->clock_rate==refpt->clock_rate && pt->channels==refpt->channels) - return pt; + return payload_type_clone(pt); } return NULL; } -static PayloadType * red_match(const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads) { - const MSList *elem_local, *elem_remote; - PayloadType *red = NULL; - for (elem_local = local_payloads; elem_local != NULL; elem_local = elem_local->next) { - PayloadType *pt = (PayloadType*)elem_local->data; - - if (strcasecmp(pt->mime_type, payload_type_t140_red.mime_type) == 0) { - red = pt; - - for (elem_remote = remote_payloads; elem_remote != NULL; elem_remote = elem_remote->next) { - PayloadType *pt2 = (PayloadType*)elem_remote->data; - if (strcasecmp(pt2->mime_type, payload_type_t140.mime_type) == 0) { - int t140_payload_number = payload_type_get_number(pt2); - const char *red_fmtp = ms_strdup_printf("%i/%i/%i", t140_payload_number, t140_payload_number, t140_payload_number); - payload_type_set_recv_fmtp(red, red_fmtp); - break; - } - } - break; - } - } - return red; +void linphone_core_register_offer_answer_providers(LinphoneCore *lc){ + MSFactory *factory = ms_factory_get_fallback(); + ms_factory_register_offer_answer_provider(factory, &red_offer_answer_provider); + ms_factory_register_offer_answer_provider(factory, &g729a_offer_answer_provider); + ms_factory_register_offer_answer_provider(factory, &opus_offer_answer_provider); } -static PayloadTypeMatcher matchers[]={ - {"opus", opus_match}, - {"G729A", g729A_match}, - {"AMR", amr_match}, - {"AMR-WB", amr_match}, - {"red", red_match}, - {NULL, NULL} -}; - - /* * Returns a PayloadType from the local list that matches a PayloadType offered or answered in the remote list */ -static PayloadType * find_payload_type_best_match(const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads){ - PayloadTypeMatcher *m; - for(m=matchers;m->mime_type!=NULL;++m){ - if (refpt->mime_type && strcasecmp(m->mime_type,refpt->mime_type)==0){ - return m->match_func(local_payloads, refpt, remote_payloads); - } +static PayloadType * find_payload_type_best_match(const MSList *local_payloads, const PayloadType *refpt, + const MSList *remote_payloads, bool_t reading_response){ + PayloadType *ret = NULL; + MSOfferAnswerContext *ctx = ms_factory_create_offer_answer_context(ms_factory_get_fallback(), refpt->mime_type); + if (ctx){ + ms_message("Doing offer/answer processing with specific provider for codec [%s]", refpt->mime_type); + ret = ms_offer_answer_context_match_payload(ctx, local_payloads, refpt, remote_payloads, reading_response); + ms_offer_answer_context_destroy(ctx); + return ret; } return generic_match(local_payloads, refpt, remote_payloads); } @@ -175,9 +176,8 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t for(e2=remote;e2!=NULL;e2=e2->next){ PayloadType *p2=(PayloadType*)e2->data; - matched=find_payload_type_best_match(local,p2,remote); + matched=find_payload_type_best_match(local, p2, remote, reading_response); if (matched){ - PayloadType *newp; int local_number=payload_type_get_number(matched); int remote_number=payload_type_get_number(p2); @@ -189,37 +189,36 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t } } - newp=payload_type_clone(matched); if (p2->send_fmtp){ - payload_type_append_send_fmtp(newp,p2->send_fmtp); + payload_type_append_send_fmtp(matched,p2->send_fmtp); } - newp->flags|=PAYLOAD_TYPE_FLAG_CAN_RECV|PAYLOAD_TYPE_FLAG_CAN_SEND; + matched->flags|=PAYLOAD_TYPE_FLAG_CAN_RECV|PAYLOAD_TYPE_FLAG_CAN_SEND; if (p2->flags & PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED) { - newp->flags |= PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED; + matched->flags |= PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED; /* Negotiation of AVPF features (keep common features) */ - newp->avpf.features &= p2->avpf.features; - newp->avpf.rpsi_compatibility = p2->avpf.rpsi_compatibility; + matched->avpf.features &= p2->avpf.features; + matched->avpf.rpsi_compatibility = p2->avpf.rpsi_compatibility; /* Take bigger AVPF trr interval */ if (p2->avpf.trr_interval < matched->avpf.trr_interval) { - newp->avpf.trr_interval = matched->avpf.trr_interval; + matched->avpf.trr_interval = matched->avpf.trr_interval; } } - res=ms_list_append(res,newp); + res=ms_list_append(res,matched); /* we should use the remote numbering even when parsing a response */ - payload_type_set_number(newp,remote_number); - payload_type_set_flag(newp, PAYLOAD_TYPE_FROZEN_NUMBER); + payload_type_set_number(matched,remote_number); + payload_type_set_flag(matched, PAYLOAD_TYPE_FROZEN_NUMBER); if (reading_response && remote_number!=local_number){ ms_warning("For payload type %s, proposed number was %i but the remote phone answered %i", - newp->mime_type, local_number, remote_number); + matched->mime_type, local_number, remote_number); /* We must add this payload type with our local numbering in order to be able to receive it. Indeed despite we must sent with the remote numbering, we must be able to receive with our local one. */ - newp=payload_type_clone(newp); - payload_type_set_number(newp,local_number); - payload_type_set_flag(newp, PAYLOAD_TYPE_FROZEN_NUMBER); - res=ms_list_append(res,newp); + matched=payload_type_clone(matched); + payload_type_set_number(matched,local_number); + payload_type_set_flag(matched, PAYLOAD_TYPE_FROZEN_NUMBER); + res=ms_list_append(res,matched); } }else{ if (p2->channels>0) diff --git a/coreapi/private.h b/coreapi/private.h index b0c73003a..797b19708 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -1083,6 +1083,7 @@ void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState s LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss); LinphoneContent *linphone_content_from_sal_body(const SalBody *ref); void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc); +void linphone_core_register_offer_answer_providers(LinphoneCore *lc); struct _LinphoneContent { diff --git a/mediastreamer2 b/mediastreamer2 index 3caf56649..ca35de0fb 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 3caf56649034b6f5ec633372ae0c24416b9013a5 +Subproject commit ca35de0fbd6b7e1a93f0f2bd1ea9983074e6c6f7