diff --git a/.gitignore b/.gitignore index 4e06bcb..f9a5b6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,13 @@ JSyphon/native_src/JSyphon.xcodeproj/project.xcworkspace/xcuserdata JSyphon/native_src/JSyphon.xcodeproj/xcuserdata +JSyphon/src/jsyphon/JSyphon*.class +JSyphon/native_libs/libSyphon.dylib # symlink to Syphon generated from compile.h +JSyphon/native_libs/JSyphon.so # ignore this lib? +JSyphon/native_libs/Sypho +JSyphon/native_libs/libJSyphon.jnilib # ignore this lib? +JSyphon/microsoft-jdk-*.pkg +#JSyphon/jar/jsyphon.jar # not sure if we want this? +Syphon-Framework +Syphon +jdk +.DS_Store diff --git a/JSyphon/native_src/JSyphon.xcodeproj/project.pbxproj b/JSyphon/native_src/JSyphon.xcodeproj/project.pbxproj index b26f60c..cfe8879 100644 --- a/JSyphon/native_src/JSyphon.xcodeproj/project.pbxproj +++ b/JSyphon/native_src/JSyphon.xcodeproj/project.pbxproj @@ -10,11 +10,13 @@ 1BB1292B135611510079EA84 /* jsyphon_JSyphonServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BB1278B1355324B0079EA84 /* jsyphon_JSyphonServer.m */; }; 1BB129691356115B0079EA84 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; }; 1BB1296A1356115B0079EA84 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BB127A6135532BB0079EA84 /* OpenGL.framework */; }; - 1BB1296B1356115B0079EA84 /* JavaVM.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BB127AC135532FD0079EA84 /* JavaVM.framework */; }; - 1BB1296C1356115B0079EA84 /* JavaNativeFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BB127B2135533180079EA84 /* JavaNativeFoundation.framework */; }; 1BB129DC1356E7860079EA84 /* jsyphon_JSyphonClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1BB129D91356E7860079EA84 /* jsyphon_JSyphonClient.h */; }; 1BB129DD1356E7860079EA84 /* jsyphon_JSyphonImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 1BB129DA1356E7860079EA84 /* jsyphon_JSyphonImage.h */; }; 1BB12A0E135776E50079EA84 /* jsyphon_JSyphonClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BB12A0D135776E50079EA84 /* jsyphon_JSyphonClient.m */; }; + 2E02077A2A490BF200BDEA9B /* libjli.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E0207792A490BF200BDEA9B /* libjli.dylib */; }; + 2E76E7572A491F0000C7D061 /* jsyphon_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E76E7532A491F0000C7D061 /* jsyphon_utils.h */; }; + 2E76E7582A491F0000C7D061 /* jsyphon_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E76E7552A491F0000C7D061 /* jsyphon_utils.m */; }; + 2E76E7592A491F0000C7D061 /* jsyphon_imports.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E76E7562A491F0000C7D061 /* jsyphon_imports.h */; }; 415E166D166FC3830060AAB9 /* jsyphon_JSyphonServerList.m in Sources */ = {isa = PBXBuildFile; fileRef = 415E166C166FC3830060AAB9 /* jsyphon_JSyphonServerList.m */; }; 41928310166FCDD9008F1FE8 /* jsyphon_JSyphonServerList.h in Headers */ = {isa = PBXBuildFile; fileRef = 4192830F166FCDD9008F1FE8 /* jsyphon_JSyphonServerList.h */; }; 41B03CCB13CD8D9200CE4F36 /* SyphonNameboundClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 41B03CC713CD8D9200CE4F36 /* SyphonNameboundClient.h */; }; @@ -46,13 +48,15 @@ 1BB1278A1355324B0079EA84 /* jsyphon_JSyphonServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsyphon_JSyphonServer.h; sourceTree = ""; }; 1BB1278B1355324B0079EA84 /* jsyphon_JSyphonServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = jsyphon_JSyphonServer.m; sourceTree = ""; }; 1BB127A6135532BB0079EA84 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; - 1BB127AC135532FD0079EA84 /* JavaVM.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaVM.framework; path = /System/Library/Frameworks/JavaVM.framework; sourceTree = ""; }; - 1BB127B2135533180079EA84 /* JavaNativeFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaNativeFoundation.framework; path = /System/Library/Frameworks/JavaVM.framework/Versions/A/Frameworks/JavaNativeFoundation.framework; sourceTree = ""; }; 1BB12926135611160079EA84 /* libJSyphon.jnilib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libJSyphon.jnilib; sourceTree = BUILT_PRODUCTS_DIR; }; 1BB129D91356E7860079EA84 /* jsyphon_JSyphonClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsyphon_JSyphonClient.h; sourceTree = ""; }; 1BB129DA1356E7860079EA84 /* jsyphon_JSyphonImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsyphon_JSyphonImage.h; sourceTree = ""; }; 1BB12A0B13576F0C0079EA84 /* jsyphon_JSyphonImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = jsyphon_JSyphonImage.m; sourceTree = ""; }; 1BB12A0D135776E50079EA84 /* jsyphon_JSyphonClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = jsyphon_JSyphonClient.m; sourceTree = ""; }; + 2E0207792A490BF200BDEA9B /* libjli.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libjli.dylib; path = "../../../../../../../../../../Library/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/Home/lib/libjli.dylib"; sourceTree = ""; }; + 2E76E7532A491F0000C7D061 /* jsyphon_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsyphon_utils.h; sourceTree = SOURCE_ROOT; }; + 2E76E7552A491F0000C7D061 /* jsyphon_utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = jsyphon_utils.m; sourceTree = SOURCE_ROOT; }; + 2E76E7562A491F0000C7D061 /* jsyphon_imports.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsyphon_imports.h; sourceTree = SOURCE_ROOT; }; 32DBCF630370AF2F00C91783 /* JSyphon_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSyphon_Prefix.pch; sourceTree = ""; }; 415E166C166FC3830060AAB9 /* jsyphon_JSyphonServerList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = jsyphon_JSyphonServerList.m; sourceTree = ""; }; 4192830F166FCDD9008F1FE8 /* jsyphon_JSyphonServerList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsyphon_JSyphonServerList.h; sourceTree = ""; }; @@ -70,11 +74,10 @@ buildActionMask = 2147483647; comments = "#!/bin/bash\necho \"$BUILT_PRODUCTS_DIR/libJSyphon.dylib\"\necho \"$SOURCE_ROOT/../native_libs/libJSyphon.dylib\"\n\ncp -RfL \"$BUILT_PRODUCTS_DIR/libJSyphon.dylib\" \"$SOURCE_ROOT/../native_libs/\""; files = ( + 2E02077A2A490BF200BDEA9B /* libjli.dylib in Frameworks */, E2DDA92317D8DDD700C03F2F /* Syphon.framework in Frameworks */, 1BB129691356115B0079EA84 /* Cocoa.framework in Frameworks */, 1BB1296A1356115B0079EA84 /* OpenGL.framework in Frameworks */, - 1BB1296B1356115B0079EA84 /* JavaVM.framework in Frameworks */, - 1BB1296C1356115B0079EA84 /* JavaNativeFoundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -90,6 +93,7 @@ 089C167CFE841241C02AAC07 /* Resources */, 089C1671FE841209C02AAC07 /* Frameworks and Libraries */, 19C28FB8FE9D52D311CA2CBB /* Products */, + 2E0207772A490BF100BDEA9B /* Frameworks */, ); name = JSyphon; sourceTree = ""; @@ -128,8 +132,6 @@ children = ( 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */, 1BB127A6135532BB0079EA84 /* OpenGL.framework */, - 1BB127AC135532FD0079EA84 /* JavaVM.framework */, - 1BB127B2135533180079EA84 /* JavaNativeFoundation.framework */, ); name = "Linked Frameworks"; sourceTree = ""; @@ -179,6 +181,14 @@ name = Client; sourceTree = ""; }; + 2E0207772A490BF100BDEA9B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2E0207792A490BF200BDEA9B /* libjli.dylib */, + ); + name = Frameworks; + sourceTree = ""; + }; 32C88E010371C26100C91783 /* Other Sources */ = { isa = PBXGroup; children = ( @@ -200,6 +210,9 @@ 41B03CC413CD8D9200CE4F36 /* Shared */ = { isa = PBXGroup; children = ( + 2E76E7562A491F0000C7D061 /* jsyphon_imports.h */, + 2E76E7532A491F0000C7D061 /* jsyphon_utils.h */, + 2E76E7552A491F0000C7D061 /* jsyphon_utils.m */, 41B03CC713CD8D9200CE4F36 /* SyphonNameboundClient.h */, 41B03CC813CD8D9200CE4F36 /* SyphonNameboundClient.m */, ); @@ -223,6 +236,8 @@ buildActionMask = 2147483647; files = ( 1BB129DC1356E7860079EA84 /* jsyphon_JSyphonClient.h in Headers */, + 2E76E7592A491F0000C7D061 /* jsyphon_imports.h in Headers */, + 2E76E7572A491F0000C7D061 /* jsyphon_utils.h in Headers */, 1BB129DD1356E7860079EA84 /* jsyphon_JSyphonImage.h in Headers */, 41B03CCB13CD8D9200CE4F36 /* SyphonNameboundClient.h in Headers */, 41928310166FCDD9008F1FE8 /* jsyphon_JSyphonServerList.h in Headers */, @@ -317,6 +332,7 @@ buildActionMask = 2147483647; files = ( 1BB1292B135611510079EA84 /* jsyphon_JSyphonServer.m in Sources */, + 2E76E7582A491F0000C7D061 /* jsyphon_utils.m in Sources */, 1BB12A0E135776E50079EA84 /* jsyphon_JSyphonClient.m in Sources */, 41B03CCC13CD8D9200CE4F36 /* SyphonNameboundClient.m in Sources */, 415E166D166FC3830060AAB9 /* jsyphon_JSyphonServerList.m in Sources */, @@ -357,7 +373,6 @@ FRAMEWORK_SEARCH_PATHS = ( "\"$(SRCROOT)/../../../Syphon-Framework/build/$(CONFIGURATION)/\"/**", "$(inherited)", - "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaVM.framework/Versions/A/Frameworks\"", "\"$(SRCROOT)/../../../Syphon-Framework/build/Release\"", ); GCC_DYNAMIC_NO_PIC = NO; @@ -365,7 +380,17 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + HEADER_SEARCH_PATHS = ( + "/Library/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/Home/include/**", + "$(SRCROOT)/../jdk/src/java.desktop/macosx/native/libosxapp", + "$(SRCROOT)/../jdk/src/java.base/share/native/libjava", + "$(SRCROOT)/../jdk/src/java.base/unix/native/libjava", + ); INSTALL_PATH = ""; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LOCAL_LIBRARY_DIR)/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/Home/lib", + ); OTHER_LDFLAGS = ( "-framework", Foundation, @@ -389,13 +414,22 @@ FRAMEWORK_SEARCH_PATHS = ( "\"$(SRCROOT)/../../../Syphon-Framework/build/$(CONFIGURATION)/\"/**", "$(inherited)", - "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaVM.framework/Versions/A/Frameworks\"", "\"$(SRCROOT)/../../../Syphon-Framework/build/Release\"", ); GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; + HEADER_SEARCH_PATHS = ( + "/Library/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/Home/include/**", + "$(SRCROOT)/../jdk/src/java.desktop/macosx/native/libosxapp", + "$(SRCROOT)/../jdk/src/java.base/share/native/libjava", + "$(SRCROOT)/../jdk/src/java.base/unix/native/libjava", + ); INSTALL_PATH = ""; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LOCAL_LIBRARY_DIR)/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/Home/lib", + ); OTHER_LDFLAGS = ( "-framework", Foundation, @@ -438,10 +472,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.8; + MACOSX_DEPLOYMENT_TARGET = 13.3; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; - VALID_ARCHS = "i386 x86_64"; + VALID_ARCHS = "i386 x86_64 arm64"; }; name = Debug; }; @@ -475,10 +509,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.8; + MACOSX_DEPLOYMENT_TARGET = 13.3; ONLY_ACTIVE_ARCH = NO; SDKROOT = macosx; - VALID_ARCHS = "i386 x86_64"; + VALID_ARCHS = "i386 x86_64 arm64"; }; name = Release; }; diff --git a/JSyphon/native_src/compile.sh b/JSyphon/native_src/compile.sh index a97b988..e4800d7 100755 --- a/JSyphon/native_src/compile.sh +++ b/JSyphon/native_src/compile.sh @@ -1,6 +1,29 @@ -gcc -arch x86_64 -o ../native_libs/JSyphon.so -shared -I/System/Library/Frameworks/JavaVM.framework/Headers \ --F../native_libs/ -F/System/Library/Frameworks/JavaVM.framework/Frameworks/ \ - -framework Cocoa -framework Foundation -framework OpenGL -framework JavaVM -framework Syphon -framework JavaNativeFoundation \ -jsyphon_JSyphonServer.m -lc +# was x86_64 but let's use real arch to build on arm64 as well +ARCH=`uname -m` +OS=`uname -s` + +ln -s Syphon-Framework ../../Syphon +ln -s Syphon ../native_libs/libSyphon.dylib +# macOS ARM: if OS is Darwin and arch is ARM, use `javac -h` on the .java files directly +if [ "$OS" = "Darwin" ] && ([ "$ARCH" = "arm64" ] || [ "$ARCH" = "aarch64" ]); then + echo "macOS ARM64 detected" + + # we may need to link to libjli.dylib, eg /Library/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/MacOS/libjli.dylib + gcc -arch $ARCH -o ../native_libs/JSyphon.so -shared \ + -L../native_libs/ \ + -L/Library/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/MacOS \ + -I../../ \ + -I/Library/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/microsoft-17.jdk/Contents/Home/include/darwin \ + -I../jdk/src/java.desktop/macosx/native/libosxapp -I../jdk/src/java.base/share/native/libjava -I../jdk/src/java.base/unix/native/libjava \ + -framework Cocoa -framework Foundation -framework OpenGL \ + jsyphon_utils.m jsyphon_JSyphonServer.m -lc -ljli -lSyphon + + install_name_tool -change @loader_path/../Frameworks/Syphon.framework/Versions/A/Syphon "`pwd`/../native_libs/Syphon.framework/Versions/A/Syphon" ../native_libs/libJSyphon.jnilib +else + gcc -arch $ARCH -o ../native_libs/JSyphon.so -shared -I/System/Library/Frameworks/JavaVM.framework/Headers \ + -F../native_libs/ -F/System/Library/Frameworks/JavaVM.framework/Frameworks/ \ + -framework Cocoa -framework Foundation -framework OpenGL -framework JavaVM -framework Syphon -framework JavaNativeFoundation \ + jsyphon_JSyphonServer.m -lc + install_name_tool -change @loader_path/../Frameworks/Syphon.framework/Versions/A/Syphon "`pwd`/../native_libs/Syphon.framework/Versions/A/Syphon" ../native_libs/JSyphon.so +fi -install_name_tool -change @loader_path/../Frameworks/Syphon.framework/Versions/A/Syphon "`pwd`/../native_libs/Syphon.framework/Versions/A/Syphon" ../native_libs/JSyphon.so \ No newline at end of file diff --git a/JSyphon/native_src/gen_headers.sh b/JSyphon/native_src/gen_headers.sh index 06201c8..b603d7e 100755 --- a/JSyphon/native_src/gen_headers.sh +++ b/JSyphon/native_src/gen_headers.sh @@ -1,9 +1,27 @@ cd ../bin -javah jsyphon.JSyphonClient -javah jsyphon.JSyphonImage -javah jsyphon.JSyphonServer -javah jsyphon.JSyphonServerList +files=(JSyphonClient JSyphonImage JSyphonServer JSyphonServerList) + +ARCH=`uname -m` +OS=`uname -s` + +# macOS ARM: if OS is Darwin and arch is ARM, use `javac -h` on the .java files directly +if [ "$OS" = "Darwin" ] && ([ "$ARCH" = "arm64" ] || [ "$ARCH" = "aarch64" ]); then + echo "macOS ARM64 detected" + JAVAH="javac -h ." + PRE="../src/jsyphon/" + END=".java" +else + JAVAH="javah" + END="" + PRE="jsyphon." +fi + +for i in "${files[@]}" +do + echo $JAVAH $PRE$i$END + $JAVAH $PRE$i$END +done mv jsyphon_*.h ../native_src/ cd ../native_src diff --git a/JSyphon/native_src/jsyphon_JSyphonClient.m b/JSyphon/native_src/jsyphon_JSyphonClient.m index d83cfff..b76f185 100644 --- a/JSyphon/native_src/jsyphon_JSyphonClient.m +++ b/JSyphon/native_src/jsyphon_JSyphonClient.m @@ -1,15 +1,6 @@ -#import -#import // JNI Cocoa helper -#import - -#import -#import -#import - +#import "jsyphon_imports.h" #import -#import - // pass options in case they are needed in the future... JNIEXPORT jlong JNICALL Java_jsyphon_JSyphonClient_init(JNIEnv * env, jobject jobj, jobject options) { @@ -81,7 +72,26 @@ JNIEXPORT jboolean JNICALL Java_jsyphon_JSyphonClient_isValid(JNIEnv * env, jobj JNIEXPORT jobject JNICALL Java_jsyphon_JSyphonClient_serverDescription(JNIEnv * env, jobject jobj, jlong ptr) { jobject serverdesc = nil; - + // This methods returns a ArrayList: + // (realm kdc* null) null (mapping-domain mapping-realm)* + jclass jc_arrayListClass = (*env)->FindClass(env, "java/util/ArrayList"); + CHECK_NULL_RETURN(jc_arrayListClass, NULL); + jmethodID jm_arrayListCons = (*env)->GetMethodID(env, jc_arrayListClass, "", "()V"); + CHECK_NULL_RETURN(jm_arrayListCons, NULL); + jmethodID jm_listAdd = (*env)->GetMethodID(env, jc_arrayListClass, "add", "(Ljava/lang/Object;)Z"); + CHECK_NULL_RETURN(jm_listAdd, NULL); + serverdesc = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons); + CHECK_NULL_RETURN(serverdesc, NULL); + + SyphonNameboundClient* boundClient = jlong_to_ptr(ptr); + [boundClient lockClient]; + SyphonClient *client = [(SyphonNameboundClient*)boundClient client]; + ADD(serverdesc, client); + ADDNULL(serverdesc); + [boundClient unlockClient]; + return serverdesc; + + /* JNF_COCOA_ENTER(env); SyphonNameboundClient* boundClient = jlong_to_ptr(ptr); @@ -100,6 +110,7 @@ JNIEXPORT jobject JNICALL Java_jsyphon_JSyphonClient_serverDescription(JNIEnv * JNF_COCOA_EXIT(env); return serverdesc; + */ } @@ -127,37 +138,47 @@ JNIEXPORT jobject JNICALL Java_jsyphon_JSyphonClient_newFrameDataForContext(JNIE { jobject imgdata = nil; - JNF_COCOA_ENTER(env); + //JNF_COCOA_ENTER(env); - SyphonNameboundClient* boundClient = jlong_to_ptr(ptr); + SyphonNameboundClient* boundClient = jlong_to_ptr(ptr); [boundClient lockClient]; SyphonClient *client = [(SyphonNameboundClient*)boundClient client]; - SyphonImage* img = [client newFrameImage]; + SyphonImage* img = [client newFrameImage]; NSSize texSize = [img textureSize]; - NSNumber *name = [NSNumber numberWithInt:[img textureName]]; - NSNumber *width = [NSNumber numberWithFloat:texSize.width]; - NSNumber *height = [NSNumber numberWithFloat:texSize.height]; - - NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys: - name, @"name", - width, @"width", - height, @"height", - nil]; - - - JNFTypeCoercer* coecer = [JNFDefaultCoercions defaultCoercer]; - [JNFDefaultCoercions addMapCoercionTo:coecer]; - - imgdata = [coecer coerceNSObject:dic withEnv:env]; + NSNumber *name = [NSNumber numberWithInt:[img textureName]]; + NSNumber *width = [NSNumber numberWithFloat:texSize.width]; + NSNumber *height = [NSNumber numberWithFloat:texSize.height]; + + NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys: + name, @"name", + width, @"width", + height, @"height", + nil]; + + jclass jc_arrayListClass = (*env)->FindClass(env, "java/util/ArrayList"); + CHECK_NULL_RETURN(jc_arrayListClass, NULL); + jmethodID jm_arrayListCons = (*env)->GetMethodID(env, jc_arrayListClass, "", "()V"); + CHECK_NULL_RETURN(jm_arrayListCons, NULL); + jmethodID jm_listAdd = (*env)->GetMethodID(env, jc_arrayListClass, "add", "(Ljava/lang/Object;)Z"); + CHECK_NULL_RETURN(jm_listAdd, NULL); + imgdata = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons); + CHECK_NULL_RETURN(imgdata, NULL); + + //JNFTypeCoercer* coecer = [JNFDefaultCoercions defaultCoercer]; + //[JNFDefaultCoercions addMapCoercionTo:coecer]; + + ADD(imgdata, dic); + ADDNULL(imgdata); + //imgdata = [coecer coerceNSObject:dic withEnv:env]; [img release]; [boundClient unlockClient]; - JNF_COCOA_EXIT(env); + //JNF_COCOA_EXIT(env); return imgdata; } diff --git a/JSyphon/native_src/jsyphon_JSyphonImage.m b/JSyphon/native_src/jsyphon_JSyphonImage.m index a525365..63dd31c 100644 --- a/JSyphon/native_src/jsyphon_JSyphonImage.m +++ b/JSyphon/native_src/jsyphon_JSyphonImage.m @@ -1,12 +1,4 @@ -#import -#import // JNI Cocoa helper -#import - -#import -#import -#import - -#import +#import "jsyphon_imports.h" JNIEXPORT jint JNICALL Java_jsyphon_JSyphonImage_textureName(JNIEnv * env, jobject jobj) diff --git a/JSyphon/native_src/jsyphon_JSyphonServer.m b/JSyphon/native_src/jsyphon_JSyphonServer.m index bc4a820..9f86c8c 100644 --- a/JSyphon/native_src/jsyphon_JSyphonServer.m +++ b/JSyphon/native_src/jsyphon_JSyphonServer.m @@ -1,36 +1,43 @@ -#import -#import // JNI Cocoa helper -#import - -#import -#import -#import - -#import +#import "jsyphon_imports.h" JNIEXPORT jlong JNICALL Java_jsyphon_JSyphonServer_initWithName (JNIEnv * env, jobject jobj, jstring name, jobject options) { jlong ptr = 0; - - JNF_COCOA_ENTER(env); - + + //JNF_COCOA_ENTER(env); + CGLContextObj cgl_ctx = CGLGetCurrentContext(); - + NSString* sname = JNFJavaToNSString(env, name); NSDictionary* sopt = nil; if (options != nil) { - JNFTypeCoercer* coecer = [JNFDefaultCoercions defaultCoercer]; - [JNFDefaultCoercions addMapCoercionTo:coecer]; - sopt = [coecer coerceJavaObject:options withEnv:env]; + jclass jc_arrayListClass = (*env)->FindClass(env, "java/util/ArrayList"); + CHECK_NULL_RETURN(jc_arrayListClass, NULL); + jmethodID jm_arrayListCons = (*env)->GetMethodID(env, jc_arrayListClass, "", "()V"); + CHECK_NULL_RETURN(jm_arrayListCons, NULL); + jmethodID jm_listAdd = (*env)->GetMethodID(env, jc_arrayListClass, "add", "(Ljava/lang/Object;)Z"); + CHECK_NULL_RETURN(jm_listAdd, NULL); + ptr = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons); + CHECK_NULL_RETURN(ptr, NULL); + + //JNFTypeCoercer* coecer = [JNFDefaultCoercions defaultCoercer]; + // [JNFDefaultCoercions addMapCoercionTo:coecer]; + + ADD(ptr, options); + ADDNULL(ptr); + + //JNFTypeCoercer* coecer = [JNFDefaultCoercions defaultCoercer]; + //[JNFDefaultCoercions addMapCoercionTo:coecer]; + //sopt = [coecer coerceJavaObject:options withEnv:env]; } - - SyphonServer* server = [[SyphonServer alloc] initWithName:sname context:cgl_ctx options:nil]; + + SyphonServer* server = [[SyphonServer alloc] initWithName:sname context:cgl_ctx options:nil]; ptr = ptr_to_jlong(server); - - JNF_COCOA_EXIT(env); - return ptr; + //JNF_COCOA_EXIT(env); + + return ptr; } JNIEXPORT jstring JNICALL Java_jsyphon_JSyphonServer_getName (JNIEnv * env, jobject jobj, jlong ptr) diff --git a/JSyphon/native_src/jsyphon_JSyphonServerList.m b/JSyphon/native_src/jsyphon_JSyphonServerList.m index 3c61c8d..f0e2428 100644 --- a/JSyphon/native_src/jsyphon_JSyphonServerList.m +++ b/JSyphon/native_src/jsyphon_JSyphonServerList.m @@ -1,36 +1,43 @@ -#import -#import // JNI Cocoa helper -#import - -#import -#import -#import - -#import +#import "jsyphon_imports.h" JNIEXPORT jobject JNICALL Java_jsyphon_JSyphonServerList_getList(JNIEnv * env, jobject jobj) { - jobject serverlist = nil; - - JNF_COCOA_ENTER(env); - + jobject serverlist = nil; + + //JNF_COCOA_ENTER(env); + NSArray *servers = [[SyphonServerDirectory sharedDirectory] servers]; NSMutableArray *output = [NSMutableArray arrayWithCapacity:[servers count]]; - + for (NSDictionary *description in servers) { NSDictionary *simple = [NSDictionary dictionaryWithObjectsAndKeys:[description objectForKey:SyphonServerDescriptionNameKey], @"Name", - [description objectForKey:SyphonServerDescriptionAppNameKey], @"App Name", nil]; + [description objectForKey:SyphonServerDescriptionAppNameKey], @"App Name", nil]; [output addObject:simple]; } - JNFTypeCoercer* coecer = [JNFDefaultCoercions defaultCoercer]; - [JNFDefaultCoercions addMapCoercionTo:coecer]; - - serverlist = [coecer coerceNSObject:servers withEnv:env]; - - JNF_COCOA_EXIT(env); - - return serverlist; - + jclass jc_arrayListClass = (*env)->FindClass(env, "java/util/ArrayList"); + CHECK_NULL_RETURN(jc_arrayListClass, NULL); + jmethodID jm_arrayListCons = (*env)->GetMethodID(env, jc_arrayListClass, "", "()V"); + CHECK_NULL_RETURN(jm_arrayListCons, NULL); + jmethodID jm_listAdd = (*env)->GetMethodID(env, jc_arrayListClass, "add", "(Ljava/lang/Object;)Z"); + CHECK_NULL_RETURN(jm_listAdd, NULL); + serverlist = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons); + CHECK_NULL_RETURN(serverlist, NULL); + + //JNFTypeCoercer* coecer = [JNFDefaultCoercions defaultCoercer]; + //[JNFDefaultCoercions addMapCoercionTo:coecer]; + + ADD(serverlist, servers); + ADDNULL(serverlist); + + //JNFTypeCoercer* coecer = [JNFDefaultCoercions defaultCoercer]; + //[JNFDefaultCoercions addMapCoercionTo:coecer]; + + //serverlist = [coecer coerceNSObject:servers withEnv:env]; + + //JNF_COCOA_EXIT(env); + + return serverlist; + } \ No newline at end of file diff --git a/JSyphon/native_src/jsyphon_imports.h b/JSyphon/native_src/jsyphon_imports.h new file mode 100644 index 0000000..51e8785 --- /dev/null +++ b/JSyphon/native_src/jsyphon_imports.h @@ -0,0 +1,38 @@ +#ifndef _Included_jsyphon_JSyphon_imports +#define _Included_jsyphon_JSyphon_imports + +#if defined(__arm64__) +// can get ARM-compatible JDK from https://learn.microsoft.com/en-us/java/openjdk/download +// headers will likely install into "/Library/Java/JavaVirtualMachines/microsoft-*.jdk/Contents/Home/include" +#import "jni.h" +#import "jni_md.h" +#import "JNIUtilities.h" +#import "jsyphon_utils.h" + +#define JNF_COCOA_ENTER JNI_COCOA_ENTER +#define JNF_COCOA_EXIT JNI_COCOA_EXIT +#define JNFJavaToNSString _JavaStringToNSString +#define JNFNSToJavaString _NSStringToJavaString + +#define ADD(list, str) { \ + jobject localeObj = (*env)->NewStringUTF(env, [str UTF8String]); \ + (*env)->CallBooleanMethod(env, list, jm_listAdd, localeObj); \ + (*env)->DeleteLocalRef(env, localeObj); \ +} + +#define ADDNULL(list) (*env)->CallBooleanMethod(env, list, jm_listAdd, NULL) + +#else +// non-ARM +#import +#import // JNI Cocoa helper +#import +#endif + +#import +#import +#import + +#import + +#endif diff --git a/JSyphon/native_src/jsyphon_utils.h b/JSyphon/native_src/jsyphon_utils.h new file mode 100644 index 0000000..38e8966 --- /dev/null +++ b/JSyphon/native_src/jsyphon_utils.h @@ -0,0 +1,13 @@ +#include + +#ifndef _Included_jsyphon_JSyphon_utils +#define _Included_jsyphon_JSyphon_utils +#ifdef __cplusplus +extern "C" { +#endif +JNIEXPORT jstring JNICALL _NSStringToJavaString(JNIEnv *, NSString *); +JNIEXPORT NSString* JNICALL _JavaStringToNSString(JNIEnv *, jstring); +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/JSyphon/native_src/jsyphon_utils.m b/JSyphon/native_src/jsyphon_utils.m new file mode 100644 index 0000000..8a1e94c --- /dev/null +++ b/JSyphon/native_src/jsyphon_utils.m @@ -0,0 +1,32 @@ +#import "jsyphon_imports.h" + +JNIEXPORT jstring JNICALL _NSStringToJavaString(JNIEnv* env, NSString *str) { + if (str == NULL) { + return NULL; + } + jsize len = [str length]; + unichar *buffer = (unichar*)calloc(len, sizeof(unichar)); + if (buffer == NULL) { + return NULL; + } + NSRange crange = NSMakeRange(0, len); + [str getCharacters:buffer range:crange]; + jstring jStr = (*env)->NewString(env, buffer, len); + free(buffer); + CHECK_EXCEPTION(); + return jStr; +} + +JNIEXPORT NSString* JNICALL _JavaStringToNSString(JNIEnv *env, jstring jstr) { + if (jstr == NULL) { + return NULL; + } + jsize len = (*env)->GetStringLength(env, jstr); + const jchar *chars = (*env)->GetStringChars(env, jstr, NULL); + if (chars == NULL) { + return NULL; + } + NSString *result = [NSString stringWithCharacters:(UniChar *)chars length:len]; + (*env)->ReleaseStringChars(env, jstr, chars); + return result; +} \ No newline at end of file diff --git a/README.md b/README.md index fcefbe3..f24eb31 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,26 @@ JSyphon - a Java Native Interface for Syphon. It has been tested with JOGL via P Getting Started: ==== -* After cloning the repository, use ```git submodule update --init``` to pull in the Syphon-Framework and Shared repos +* Just run `install.sh` and all the following will be done! If anything fails, you'll need to investigate further, or follow the instructions below to install one by one. + +```sh +sh -x install.sh +``` + +Installing Manually: +==== + +* After cloning the repository, pull in the Syphon-Framework and Shared repos + +```sh +git submodule update --init +``` * Update the Syphon-Framework and Shaded submodules: -```bash +```sh cd Syphon-Framework/ -git pull origin master +git pull origin main cd ../Shared/ git pull origin master cd .. @@ -22,13 +35,21 @@ git add Shared git commit -m "Updated Syphon submodules" ``` -* Change into the JSyphon subfolder: +* Change into the JSyphon subfolder: -```cd JSyphon``` +```sh +cd JSyphon +``` -* Build jsyphon.jar, by running ```ant dist``` inside the ant folder: +* Ensure you have Apache ant installed, such as installing from [MacPorts](https://www.macports.org/install.php) or [Homebrew](https://docs.brew.sh/Installation): -```bash +```sh +ant -version || brew install ant || sudo port install apache-ant +``` + +* Build jsyphon.jar inside the ant folder: + +```sh cd ant ant dist cd .. @@ -38,23 +59,41 @@ The resulting jsyphon.jar file will be placed inside the jar folder. * Generate the headers changing into the native_src folder and running the script gen_headers.sh script: -```bash +```sh cd native_src ./gen_headers.sh cd .. ``` +* On ARM macOS (Apple Silicon), you'll want a [Microsoft OpenJDK](https://learn.microsoft.com/en-us/java/openjdk/download) build downloaded and installed for the platform and may need to update the `microsoft` paths in `JSyphon/native_src/compile.sh` and `JSyphon/JSyphon.xcodeproj/project.pbxproj` to point to the correct include directory (currently pointing to v17) + +```sh +if [ `uname -m` = "arm64" ]; then + if ls /Library/Java/JavaVirtualMachines/microsoft-*.jdk 1> /dev/null 2>&1; then + echo Microsoft OpenJDK found; + else + curl -L https://aka.ms/download-jdk/microsoft-jdk-17.0.7-macOS-aarch64.pkg > microsoft-jdk-17.0.7-macOS-aarch64.pkg && open microsoft-jdk-17.0.7-macOS-aarch64.pkg; + fi +fi +``` + +* On ARM macOS (Apple Silicon), you'll likely need a more recent openjdk for headers: + +```sh +git clone --depth=1 https://github.com/openjdk/jdk/ +``` + * Open the JSyphon XCode project inside native_src, and build it. This will generate a debug version of the library, which will print several messages at runtime. You need to archive it to create a release version without debug mesages. You can also build/archive the project from the command line (it requires the Command Line Tools Package, see [here](https://developer.apple.com/library/content/technotes/tn2339/_index.html) for more info) with the following line for building: -```bash +```sh xcodebuild -scheme libJSyphon build -project native_src/JSyphon.xcodeproj ``` and this other one for archiving: -```bash +```sh xcodebuild -scheme libJSyphon archive -project native_src/JSyphon.xcodeproj ``` @@ -68,3 +107,5 @@ Acknowledgments Initial JSyphon implementation by Skye Book and Anton Marini. Finishing up implementation of JSyphonClient, server listing, ClientTest example by Andres Colubri. + +Porting to Apple Silicon (macOS ARM64) + install.sh by [samy kamkar](https://github.com/samyk). diff --git a/Syphon-Framework b/Syphon-Framework index fc4f4a2..cb3d8ec 160000 --- a/Syphon-Framework +++ b/Syphon-Framework @@ -1 +1 @@ -Subproject commit fc4f4a2a71c0a8c7539a91093ad26c0c237602d6 +Subproject commit cb3d8ec506dc6ed0d5d9d099ffc5e120719a1a6a diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..6f7c5f4 --- /dev/null +++ b/install.sh @@ -0,0 +1,31 @@ +#!sh -x +git submodule update --init && +cd Syphon-Framework/ && +git pull origin main && +cd ../Shared/ && +git pull origin master && +cd .. && +git add Syphon-Framework && +git add Shared && +git commit -m "Updated Syphon submodules" || true && +cd JSyphon && +(ant -version || brew install ant || sudo port install apache-ant) && +cd ant && +ant dist && +cd .. && +cd native_src && +./gen_headers.sh && +cd .. && +if [ `uname -m` = "arm64" ]; then + if ls /Library/Java/JavaVirtualMachines/microsoft-*.jdk 1> /dev/null 2>&1; then + echo Microsoft OpenJDK found; + else + curl -L https://aka.ms/download-jdk/microsoft-jdk-17.0.7-macOS-aarch64.pkg > microsoft-jdk-17.0.7-macOS-aarch64.pkg && open microsoft-jdk-17.0.7-macOS-aarch64.pkg && echo && echo && echo "Opening Microsoft JDK -- please install, then return here and PRESS RETURN to continue" && read ans; + fi +fi && +if ls jdk 1> /dev/null 2>&1; then + echo github.com/openjdk/jdk found in jdk; +else + git clone --depth=1 https://github.com/openjdk/jdk/; +fi && +xcodebuild -scheme libJSyphon build -project native_src/JSyphon.xcodeproj