diff --git a/CMakeLists.txt b/CMakeLists.txt index 16b0d1e4e..69759f76b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,6 +234,9 @@ add_definitions("-DIN_LINPHONE") if(ENABLE_DEBUG_LOGS) add_definitions("-DDEBUG") endif() +if(ANDROID) + add_definitions("-DANDROID") +endif() set(STRICT_OPTIONS_CPP ) set(STRICT_OPTIONS_C ) @@ -295,6 +298,7 @@ else() endif() +add_subdirectory(java) add_subdirectory(coreapi) add_subdirectory(share) if(ENABLE_CONSOLE_UI) diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index f67c36b9a..014e5607a 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -119,6 +119,10 @@ set(LINPHONE_SOURCE_FILES_C vtables.c ) set(LINPHONE_SOURCE_FILES_CXX conference.cc) +if(ANDROID) + list(APPEND LINPHONE_SOURCE_FILES_CXX linphonecore_jni.cc) + set_source_files_properties(linphonecore_jni.cc PROPERTIES COMPILE_DEFINITIONS "USE_JAVAH") +endif() set(LINPHONE_SOURCE_FILES_OBJC) if (IOS) @@ -196,6 +200,9 @@ if(ENABLE_STATIC) set_target_properties(linphone-static PROPERTIES OUTPUT_NAME linphone) add_dependencies(linphone-static liblinphone-git-version) target_link_libraries(linphone-static ${LIBS}) + if(ANDROID) + add_dependencies(linphone-static linphonecore-jni-header) + endif() if(IOS) target_link_libraries(linphone-static "-framework Foundation" "-framework AVFoundation") endif() @@ -218,6 +225,9 @@ if(ENABLE_SHARED) target_link_libraries(linphone ${LIBS}) if(WIN32 AND CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") set_target_properties(linphone PROPERTIES PREFIX "lib") + elseif(ANDROID) + set_target_properties(linphone PROPERTIES OUTPUT_NAME "linphone-${CMAKE_SYSTEM_PROCESSOR}") + add_dependencies(linphone linphonecore-jni-header) endif() if(MSVC) if(CMAKE_BUILD_TYPE STREQUAL "Debug") diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 3b4a15212..73b993f99 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -29,7 +29,7 @@ extern "C" { #include "mediastreamer2/mscommon.h" #include "mediastreamer2/msmediaplayer.h" #include "mediastreamer2/msutils.h" -#include "devices.h" +#include "mediastreamer2/devices.h" } #include "mediastreamer2/msjava.h" #include "private.h" @@ -40,17 +40,6 @@ extern "C" { #ifdef ANDROID #include -/*there are declarations of the init routines of our plugins. - * Since there is no way to dlopen() installed in a non-standard place in the apk, - * we have to invoke the init routines manually*/ -extern "C" void libmsx264_init(MSFactory *factory); -extern "C" void libmsopenh264_init(MSFactory *factory); -extern "C" void libmsamr_init(MSFactory *factory); -extern "C" void libmssilk_init(MSFactory *factory); -extern "C" void libmsbcg729_init(MSFactory *factory); -extern "C" void libmswebrtc_init(MSFactory *factory); -extern "C" void libmscodec2_init(MSFactory *factory); - #include #endif /*ANDROID*/ @@ -1330,32 +1319,7 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* jobject core = env->NewGlobalRef(thiz); ljb->setCore(core); LinphoneCore *lc = linphone_core_new(vTable, userConfig, factoryConfig, ljb); - MSFactory *factory = linphone_core_get_ms_factory(lc); - -#ifdef HAVE_X264 - libmsx264_init(factory); -#endif -#ifdef HAVE_OPENH264 - libmsopenh264_init(factory); -#endif -#ifdef HAVE_AMR - libmsamr_init(factory); -#endif -#ifdef HAVE_SILK - libmssilk_init(factory); -#endif -#ifdef HAVE_G729 - libmsbcg729_init(factory); -#endif -#ifdef HAVE_WEBRTC - libmswebrtc_init(factory); -#endif -#ifdef HAVE_CODEC2 - libmscodec2_init(factory); -#endif - linphone_core_reload_ms_plugins(lc, NULL); - jlong nativePtr = (jlong)lc; if (userConfig) env->ReleaseStringUTFChars(juserConfig, userConfig); if (factoryConfig) env->ReleaseStringUTFChars(jfactoryConfig, factoryConfig); @@ -4675,8 +4639,7 @@ extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_createConference(JNIE jmethodID conference_constructor = env->GetMethodID(conference_class, "", "(J)V"); LinphoneConferenceParams *params = NULL; LinphoneConference *conference; - jobject jconference; - + if(jparams) params = (LinphoneConferenceParams *)env->GetLongField(jparams, params_native_ptr_attr); conference = linphone_core_create_conference_with_params((LinphoneCore *)corePtr, params); if(conference) return env->NewObject(conference_class, conference_constructor, (jlong)conference); @@ -5454,7 +5417,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_setContent linphone_content_set_string_buffer(content, tmp = env->GetStringUTFChars(jdata,NULL)); env->ReleaseStringUTFChars(jdata, tmp); - linphone_info_message_set_content((LinphoneInfoMessage*)infoptr, content); + linphone_info_message_set_content(infomsg, content); linphone_content_unref(content); } @@ -7208,3 +7171,8 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setUserCertificat if (path) env->ReleaseStringUTFChars(jpath, path); } +JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_reloadMsPlugins(JNIEnv *env, jobject jobj, jlong pcore, jstring jpath) { + const char *path = jpath ? env->GetStringUTFChars(jpath, NULL) : NULL; + linphone_core_reload_ms_plugins((LinphoneCore*)pcore, path); + if (path) env->ReleaseStringUTFChars(jpath, path); +} diff --git a/java/CMakeLists.txt b/java/CMakeLists.txt new file mode 100644 index 000000000..a27106c8e --- /dev/null +++ b/java/CMakeLists.txt @@ -0,0 +1,57 @@ +############################################################################ +# CMakeLists.txt +# Copyright (C) 2014 Belledonne Communications, Grenoble France +# +############################################################################ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################ + +if(ANDROID) + find_package(Java REQUIRED COMPONENTS Development) + + set(JNI_CLASSES + "org.linphone.core.LinphoneAddressImpl" + "org.linphone.core.LinphoneAuthInfoImpl" + "org.linphone.core.LinphoneCallImpl" + "org.linphone.core.LinphoneCallLogImpl" + "org.linphone.core.LinphoneCallParamsImpl" + "org.linphone.core.LinphoneCallStatsImpl" + "org.linphone.core.LinphoneChatMessageImpl" + "org.linphone.core.LinphoneChatRoomImpl" + "org.linphone.core.LinphoneCoreFactoryImpl" + "org.linphone.core.LinphoneCoreImpl" + "org.linphone.core.LinphoneFriendImpl" + "org.linphone.core.LinphoneProxyConfigImpl" + "org.linphone.core.PayloadTypeImpl" + "org.linphone.core.LpConfigImpl" + "org.linphone.core.LinphoneInfoMessageImpl" + "org.linphone.core.LinphoneEventImpl" + "org.linphone.core.PresenceActivityImpl" + "org.linphone.core.PresenceModelImpl" + "org.linphone.core.PresenceNoteImpl" + "org.linphone.core.PresencePersonImpl" + "org.linphone.core.PresenceServiceImpl" + "org.linphone.core.ErrorInfoImpl" + "org.linphone.core.TunnelConfigImpl" + ) + + # HACK: accessing mediastreamer2 source directory from here is just wrong! + add_custom_target(linphonecore-jni-header + COMMAND ${Java_JAVAH_EXECUTABLE} -o "${CMAKE_BINARY_DIR}/linphonecore_jni.h" -classpath "${CMAKE_CURRENT_SOURCE_DIR}/impl:${CMAKE_CURRENT_SOURCE_DIR}/common:${CMAKE_CURRENT_SOURCE_DIR}/../mediastreamer2/java/src" ${JNI_CLASSES} + BYPRODUCTS "${CMAKE_BINARY_DIR}/linphonecore_jni.h" + ) +endif() diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index f186bb525..2992b3c34 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -2302,4 +2302,10 @@ public interface LinphoneCore { * Set user certificates directory path (used by SRTP-DTLS). */ public void setUserCertificatesPath(String path); + + /** + * Reload mediastreamer2 plugins from specified directory. + * @param path The path from where plugins are to be loaded. + **/ + public void reloadMsPlugins(String path); } diff --git a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java index 7bb174ed4..f7de4785f 100644 --- a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java @@ -46,14 +46,13 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory { Throwable firstException=null; for (String abi : cpuabis){ Log.i("LinphoneCoreFactoryImpl","Trying to load liblinphone for " + abi); - ffmpegAbi=abi; - // FFMPEG (audio/video) - if (abi.startsWith("armeabi")) { - ffmpegAbi="arm"; - } - loadOptionalLibrary("ffmpeg-linphone-"+ffmpegAbi); + loadOptionalLibrary("ffmpeg-linphone-" + abi); //Main library try { + System.loadLibrary("bctoolbox-" + abi); + System.loadLibrary("ortp-" + abi); + System.loadLibrary("mediastreamer_base-" + abi); + System.loadLibrary("mediastreamer_voip-" + abi); System.loadLibrary("linphone-" + abi); Log.i("LinphoneCoreFactoryImpl","Loading done with " + abi); libLoaded=true; diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index d73e39767..b37e36702 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -33,6 +33,7 @@ import org.linphone.mediastream.video.AndroidVideoWindowImpl; import org.linphone.mediastream.video.capture.hwconf.Hacks; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.media.AudioManager; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.MulticastLock; @@ -179,6 +180,7 @@ class LinphoneCoreImpl implements LinphoneCore { private native static void setAndroidPowerManager(Object pm); private native void setAndroidWifiLock(long nativePtr,Object wifi_lock); private native void setAndroidMulticastLock(long nativePtr,Object multicast_lock); + private native void reloadMsPlugins(long nativePtr, String path); LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig, File factoryConfig, Object userdata) throws IOException { mListener = listener; @@ -204,6 +206,8 @@ class LinphoneCoreImpl implements LinphoneCore { } public void setContext(Object context) { mContext = (Context)context; + ApplicationInfo info = mContext.getApplicationInfo(); + reloadMsPlugins(info.nativeLibraryDir); mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); setAndroidPowerManager(mContext.getSystemService(Context.POWER_SERVICE)); if (Version.sdkAboveOrEqual(Version.API12_HONEYCOMB_MR1_31X)) { @@ -1653,4 +1657,8 @@ class LinphoneCoreImpl implements LinphoneCore { public void setUserCertificatesPath(String path) { setUserCertificatesPath(nativePtr, path); } + + public void reloadMsPlugins(String path) { + reloadMsPlugins(nativePtr, path); + } } diff --git a/mediastreamer2 b/mediastreamer2 index 803540f7c..4d74ddc90 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 803540f7c8161fcbb38f96dc0718b52ac7a36ba3 +Subproject commit 4d74ddc9089780e51ebf3d7b4475465b461e52e9 diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index cbbff1167..51590ca30 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -59,8 +59,14 @@ if(NOT IOS OR NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") endif() endif() -if(IOS) - add_library(linphonetester STATIC ${SOURCE_FILES}) +if(ANDROID OR IOS) + if(ANDROID) + add_library(linphonetester SHARED ${SOURCE_FILES}) + set_target_properties(linphonetester PROPERTIES OUTPUT_NAME "linphonetester-${CMAKE_SYSTEM_PROCESSOR}") + endif() + if(IOS) + add_library(linphonetester STATIC ${SOURCE_FILES}) + endif() target_include_directories(linphonetester PUBLIC ${BCTOOLBOX_TESTER_INCLUDE_DIRS}) target_link_libraries(linphonetester linphone ${BCTOOLBOX_TESTER_LIBRARIES}) install(TARGETS linphonetester @@ -72,7 +78,7 @@ if(IOS) install(FILES "liblinphone_tester.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/linphone PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ - ) + ) elseif(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") add_library(linphone_tester_static STATIC ${SOURCE_FILES}) target_include_directories(linphone_tester_static PUBLIC ${BCTOOLBOX_TESTER_INCLUDE_DIRS}) @@ -100,7 +106,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/BelledonneCommunications.Linphone.Tester.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE - ) + ) endif() else() add_executable(liblinphone_tester ${SOURCE_FILES}) diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index ff785448a..32cf58a44 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -84,13 +84,16 @@ static void liblinphone_android_ortp_log_handler(const char *domain, OrtpLogLeve void cunit_android_trace_handler(int level, const char *fmt, va_list args) { char buffer[CALLBACK_BUFFER_SIZE]; + jstring javaString; + jclass cls; + jmethodID method; + jint javaLevel = level; JNIEnv *env = current_env; if(env == NULL) return; vsnprintf(buffer, CALLBACK_BUFFER_SIZE, fmt, args); - jstring javaString = (*env)->NewStringUTF(env, buffer); - jint javaLevel = level; - jclass cls = (*env)->GetObjectClass(env, current_obj); - jmethodID method = (*env)->GetMethodID(env, cls, "printLog", "(ILjava/lang/String;)V"); + javaString = (*env)->NewStringUTF(env, buffer); + cls = (*env)->GetObjectClass(env, current_obj); + method = (*env)->GetMethodID(env, cls, "printLog", "(ILjava/lang/String;)V"); (*env)->CallVoidMethod(env, current_obj, method, javaLevel, javaString); (*env)->DeleteLocalRef(env,javaString); (*env)->DeleteLocalRef(env,cls);