aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.classpath6
-rw-r--r--.gitignore1
-rw-r--r--.settings/org.eclipse.jdt.core.prefs15
-rw-r--r--.settings/org.eclipse.jdt.ui.prefs2
-rw-r--r--doc/HowToBuild.html115
-rw-r--r--doc/JogAmpMacOSVersions.md54
-rw-r--r--make/build-test.xml15
-rw-r--r--make/build.xml11
-rwxr-xr-xmake/gluegen-cpptasks-base.xml40
-rw-r--r--make/jogamp-androidtasks.xml21
-rwxr-xr-xmake/jogamp-env.xml80
-rwxr-xr-xmake/lib/cpptasks-version.txt1
-rw-r--r--make/lib/cpptasks.jarbin379917 -> 386216 bytes
-rwxr-xr-xmake/scripts/check-java-major-version.sh2
-rwxr-xr-xmake/scripts/java-win32.bat25
-rwxr-xr-xmake/scripts/java-win64.bat9
-rwxr-xr-xmake/scripts/make.gluegen.all.ios.amd64.sh2
-rwxr-xr-xmake/scripts/make.gluegen.all.ios.arm64.sh2
-rwxr-xr-xmake/scripts/make.gluegen.all.linux-x86_64.sh3
-rwxr-xr-xmake/scripts/make.gluegen.all.macosx.sh2
-rwxr-xr-xmake/scripts/make.gluegen.all.win32.bat29
-rwxr-xr-xmake/scripts/make.gluegen.all.win64.bat6
-rw-r--r--make/scripts/make.macosx.jdk_lipo_libs.sh30
-rwxr-xr-xmake/scripts/runtest-x32.bat16
-rwxr-xr-xmake/scripts/runtest-x64.bat4
-rwxr-xr-xmake/scripts/runtest.sh4
-rw-r--r--make/scripts/setenv-build-jogamp-x86.sh10
-rw-r--r--make/scripts/setenv-build-jogamp-x86_64.sh10
-rwxr-xr-xmake/scripts/test-win32-smb_share.bat24
-rw-r--r--src/java/com/jogamp/common/av/AudioFormat.java193
-rw-r--r--src/java/com/jogamp/common/av/AudioSink.java444
-rw-r--r--src/java/com/jogamp/common/av/AudioSinkFactory.java69
-rw-r--r--src/java/com/jogamp/common/av/TimeFrameI.java89
-rw-r--r--src/java/com/jogamp/common/jvm/JNILibLoaderBase.java13
-rw-r--r--src/java/com/jogamp/common/net/GenericURLStreamHandlerFactory.java5
-rw-r--r--src/java/com/jogamp/common/nio/Buffers.java473
-rw-r--r--src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java10
-rw-r--r--src/java/com/jogamp/common/os/Clock.java165
-rw-r--r--src/java/com/jogamp/common/os/NativeLibrary.java113
-rw-r--r--src/java/com/jogamp/common/os/Platform.java34
-rw-r--r--src/java/com/jogamp/common/util/IOUtil.java70
-rw-r--r--src/java/com/jogamp/common/util/IntIntHashMap.java5
-rw-r--r--src/java/com/jogamp/common/util/JarUtil.java23
-rw-r--r--src/java/com/jogamp/common/util/PerfCounterCtrl.java50
-rw-r--r--src/java/com/jogamp/common/util/PropertyAccess.java2
-rw-r--r--src/java/com/jogamp/common/util/ReflectionUtil.java5
-rw-r--r--src/java/com/jogamp/common/util/SecurityUtil.java51
-rw-r--r--src/java/com/jogamp/common/util/UnsafeUtil.java5
-rw-r--r--src/java/com/jogamp/common/util/VersionUtil.java14
-rw-r--r--src/java/com/jogamp/common/util/awt/AWTEDTExecutor.java20
-rw-r--r--src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java5
-rw-r--r--src/java/jogamp/common/Debug.java4
-rw-r--r--src/java/jogamp/common/av/JavaSoundAudioSink.java320
-rw-r--r--src/java/jogamp/common/av/NullAudioSink.java211
-rw-r--r--src/java/jogamp/common/os/PlatformPropsImpl.java87
-rw-r--r--src/junit/com/jogamp/common/nio/TestByteBufferInputStream.java2
-rw-r--r--src/junit/com/jogamp/common/util/IntIntHashMapTest.java25
-rw-r--r--src/junit/com/jogamp/common/util/LongIntHashMapTest.java25
-rw-r--r--src/junit/com/jogamp/common/util/TestIOUtil01.java112
-rw-r--r--src/junit/com/jogamp/common/util/TestIteratorIndexCORE.java22
-rw-r--r--src/junit/com/jogamp/common/util/locks/TestRecursiveLock01.java16
-rw-r--r--src/junit/com/jogamp/common/util/locks/TestRecursiveThreadGroupLock01.java6
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java38
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test1.h10
-rw-r--r--src/junit/com/jogamp/junit/util/MiscUtils.java2
-rw-r--r--src/native/common/Platforms.c25
-rw-r--r--src/native/common/jau_sys_Clock.c292
67 files changed, 3114 insertions, 480 deletions
diff --git a/.classpath b/.classpath
index e313144..5c52e09 100644
--- a/.classpath
+++ b/.classpath
@@ -23,11 +23,15 @@
<classpathentry kind="src" path="test/junit"/>
<classpathentry kind="src" path="jcpp/src/main/java"/>
<classpathentry kind="src" path="jcpp/src/test/java"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Ant"/>
<classpathentry kind="lib" path="make/lib/antlr.jar" sourcepath="make/lib/antlr-src.zip"/>
<classpathentry kind="lib" path="make/lib/junit.jar" sourcepath="make/lib/junit-sources.jar"/>
<classpathentry kind="lib" path="make/lib/semantic-versioning/semver.jar" sourcepath="make/lib/semantic-versioning/semver-src.zip"/>
<classpathentry kind="lib" path="make/lib/android-sdk/24/android.jar" sourcepath="make/lib/android-sdk/24/android-java-src.zip"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
+ <attributes>
+ <attribute name="module" value="true"/>
+ </attributes>
+ </classpathentry>
<classpathentry kind="output" path="build/eclipse-classes"/>
</classpath>
diff --git a/.gitignore b/.gitignore
index bc61b22..d3ffb41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ make/GnuCTreeParserTokenTypes.txt
make/STDCTokenTypes.txt
build*/
build-temp
+*.log
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..e50443c
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,15 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..7103be7
--- /dev/null
+++ b/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.ui.text.custom_code_templates=
diff --git a/doc/HowToBuild.html b/doc/HowToBuild.html
index 168cc27..dc4e680 100644
--- a/doc/HowToBuild.html
+++ b/doc/HowToBuild.html
@@ -38,10 +38,10 @@
<ul>
<li> <b>Java</b>
<ul>
- <li>Build &amp; Runtime: An <a href="http://openjdk.java.net/">OpenJDK</a> 11 compliant SDK.</li>
+ <li>Build &amp; Runtime: An <a href="http://openjdk.java.net/">OpenJDK</a> 17 compliant SDK.</li>
<li>Runtime: An OpenJDK 8 compliant JRE.</li>
</ul>
- You may find an appropriate <a href="http://openjdk.java.net/">OpenJDK</a> build @ <a href="https://adoptopenjdk.net/">AdoptOpenJDK</a>.<br/>
+ You may find an appropriate <a href="http://openjdk.java.net/">OpenJDK</a> build @ <a href="https://adoptium.net/temurin/releases/">Adoptium</a>.<br/>
<br/>
Or you may try one of the following SDK's and/or Runtimes:
<ul>
@@ -55,7 +55,7 @@
<li> Use your Unix distribution's version, if available, or</li>
<li> <a href="http://www.kernel.org/pub/software/scm/git/">Source Code for GNU/Linux, MacOS, ..</a>, or</li>
<li> Git on Windows is provided by <a href="https://cygwin.com">cygwin</a></li>
- <li> Git &ge; 2.11 on MacOS is provided by Xcode &ge; 8.3.3</li>
+ <li> Git &ge; 2.37 provided by Xcode &ge; 14</li>
</ul>
</li>
@@ -63,7 +63,7 @@
<ul>
<li> <b><a href="https://www.freebsd.org/releases/">FreeBSD</a></b> 12 or later <i>(todo: test)</i>
<ul>
- <li>openjdk11</li>
+ <li>openjdk17</li>
<li>ant</li>
<li>git</li>
<li>awk</li>
@@ -73,13 +73,13 @@
</ul>
</ul>
</li>
- <li> <b>GNU Linux</b> x86, 32- and 64-bit as well as Arm64, etc<br/>
+ <li> <b>GNU Linux</b> x86_64 as well as Arm64, etc<br/>
You may have to install a few developer packages ...
<ul>
- <li> <b>Debian</b> 10 or later
+ <li> <b>Debian</b> 11 or later
<ul>
- <li>openjdk-11-jre</li>
- <li>openjdk-11-jdk</li>
+ <li>openjdk-17-jre</li>
+ <li>openjdk-17-jdk</li>
<li>ant</li>
<li>git</li>
<li>gawk</li>
@@ -89,28 +89,19 @@
</ul>
One liner install command:
<ul>
- <li><b>Debian</b> 10 Buster
+ <li><b>Debian</b> 11 Bullseye
<pre>
-apt-get install openjdk-11-jre openjdk-11-jdk ant git-all gawk p7zip-full gcc cmake
+apt-get install openjdk-17-jre openjdk-17-jdk ant git-all gawk p7zip-full gcc cmake
</pre></li>
</ul>
Optional: Add <i>kernel</i> build utilities:
<pre>
apt-get install kernel-package build-essential
</pre>
- Optional: Add <i>multiarch</i> i386 next to amd64
- <ul>
- <li><b>Debian</b> 10 Buster
- <pre>
-dpkg --add-architecture i386
-apt-get update
-apt-get install lib32z1 lib32ncurses5 gcc-multilib lib32gcc1 lib32gomp1 lib32itm1 lib32quadmath0 libudev1:i386 libc6-i386 libc6-dev-i386 g++-multilib lib32stdc++6 openjdk-11-jre:i386 openjdk-11-jdk:i386
- </pre></li>
- </ul>
</li>
<li> <b>OpenSuSE</b> 15.0 or later
<ul>
- <li>java-11-openjdk</li>
+ <li>java-17-openjdk</li>
<li>ant</li>
<li>git</li>
<li>gawk</li>
@@ -121,7 +112,7 @@ apt-get install lib32z1 lib32ncurses5 gcc-multilib lib32gcc1 lib32gomp1 lib32itm
</li>
<li> <b>CentOS 7 / Red Hat Enterprise Linux 7.6</b> or later<br/>
<ul>
- <li>java-11-openjdk</li>
+ <li>java-17-openjdk</li>
<li>ant</li>
<li>git</li>
<li>gawk</li>
@@ -144,53 +135,73 @@ apt-get install lib32z1 lib32ncurses5 gcc-multilib lib32gcc1 lib32gomp1 lib32itm
<li><a href="https://www.openindiana.org/">OpenIndiana</a> using illumus's OpenSolaris continuation <i>(todo: test)</i></li>
</ul>
</li>
- <li> <b>MacOS and iOS</b> Intel and Arm64
+ <li> <b>MacOS and iOS</b> x86_64 and aarch64
<ul>
- <li>git &ge; 2.11 provided by Xcode &ge; 8.3.3</li>
+ <li>Build machine: <a href="http://www.apple.com/macosx/">Mac OS</a> 12.6.5 (Monterey)
+ <ul>
+ <li>Lowest test machine: <a href="http://www.apple.com/macosx/">Mac OS</a> 10.13.6 (High Sierra)</li>
+ <li>Minimum deployment target: <a href="http://www.apple.com/macosx/">Mac OS</a> 10.7 (Lion)</li>
+ </ul></li>
+ <li><a href="http://developer.apple.com/technologies/xcode.html">Xcode</a> 14.2 for clang, etc (included in MacOS)</li>
+ <li>MacOS SDK 11.3 from a previous XCode version or <a href="https://github.com/phracker/MacOSX-SDKs">from this alternative site</a>
+ <ul>
+ <li><i>export SDKROOT=macosx11.3</i></li>
+ <li>We use <i>-mmacosx-version-min=10.7</i> (Lion 10.7) minimum deployment target.</li>
+ </ul></li>
+ <li>git &ge; 2.37 provided by Xcode &ge; 14</li>
<li>awk is provided by MacOS</li>
- <li><a href="https://cmake.org/">CMake 3.15.2</a>, and install the <a href="https://stackoverflow.com/questions/30668601/installing-cmake-command-line-tools-on-a-mac">command line tools</a></li>
- <li><a href="http://www.apple.com/macosx/">Mac OS</a> 10.13 or later (note: may not work with earlier releases) </li>
- <li><a href="http://developer.apple.com/technologies/xcode.html">Xcode</a> 8.3.3 or later for gcc, etc (included in MacOS)</li>
+ <li><a href="https://cmake.org/">CMake 3.25.1</a>, and install the <a href="https://stackoverflow.com/questions/30668601/installing-cmake-command-line-tools-on-a-mac">command line tools</a>
+ <ul>
+ <li>Install symlinks to <i>/usr/local/bin</i>, run: <i>sudo "/Applications/CMake.app/Contents/bin/cmake-gui" --install</i></li>
+ </ul></li>
+ <li><a href="https://7-zip.org/">7-Zip 21.07</a> x86_64 and arm64 version</li>
+ <li>See also <a href="JogAmpMacOSVersions.md">MacOS Versions Related to JogAmp</a></li>
</ul>
- </li>
- <li> <b>Windows</b>/x86 (32 bit)
+ Prepare fat universal OpenJDK libraries
<ul>
- <li>Windows XP or later </li>
- <li>git is provided by <a href="https://cygwin.com">cygwin</a></li>
- <li>gawk is provided by <a href="https://cygwin.com">cygwin</a></li>
- <li> <a href="http://mingw-w64.org/">MinGW64</a> (<a href="https://sourceforge.net/projects/mingw-w64/files/">files on sourceforge</a>)
- <ul>
- <li> <a href="https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/8.1.0/threads-win32/sjlj/i686-8.1.0-release-win32-sjlj-rt_v6-rev0.7z">i686-8.1.0-release-win32-sjlj-rt_v6-rev0.7z</a>
- <ul>
- <li>version: 8.1.0</li>
- <li>host: x32</li>
- <li>threading: win32</li>
- <li>exceptions: SJLJ</li>
- <li>revision: 0</li>
- </ul></li>
- </ul>
- </li>
- <li><a href="https://cmake.org/">CMake 3.15.2</a> 32bit version</li>
+ <li>Open a terminal in your home folder, e.g. <i>/Users/jogamp</i></li>
+ <li>The OpenJDK library folder of each target platform, x86_64 or aarch64, is <i>/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home/lib</i></li>
+ <li>Transfer the x86_64 OpenJDK library folder to <i>temurin-17.jdk.amd64.lib</i><li>
+ <li>Transfer the aarch64 OpenJDK library folder to <i> temurin-17.jdk.arm64.lib</i></li>
+ <li>Run the script <i>gluegen/make/scripts/make.macosx.jdk_lipo_libs.sh</i></li>
+ <li>Fat universal OpenJDK libraries are produced into <i>temurin-17.jdk.fat.lib</i></li>
</ul>
+ Now we have to tell the <i>gluegen</i> build framework to use <i>temurin-17.jdk.fat.lib</i>,
+ by adding an <i>ant</i> macro in <i>$HOME/gluegen.properties</i>
+ <pre>
+ java.lib.dir.platform=/Users/jogamp/temurin-17.jdk.fat.lib
+ </pre>
+ Replace <i>jogamp</i> with your user name.
</li>
<li> <b>Windows</b>/x86_64 (64-bit)
<ul>
- <li>Windows XP or later </li>
+ <li>Windows 7 or later </li>
<li>git is provided by <a href="https://cygwin.com">cygwin</a></li>
<li>gawk is provided by <a href="https://cygwin.com">cygwin</a></li>
- <li> <a href="http://mingw-w64.org/">MinGW64</a> (<a href="https://sourceforge.net/projects/mingw-w64/files/">files on sourceforge</a>)
+ <li> <a href="http://mingw-w64.org/">MinGW64</a> (<a href="https://github.com/niXman/mingw-builds-binaries/releases">files on github</a>)
<ul>
- <li> <a href="https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/8.1.0/threads-win32/sjlj/x86_64-8.1.0-release-win32-sjlj-rt_v6-rev0.7z">x86_64-8.1.0-release-win32-sjlj-rt_v6-rev0.7z</a>
+ <li> <a href="https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev2/x86_64-12.2.0-release-posix-seh-msvcrt-rt_v10-rev2.7z">x86_64-12.2.0-release-posix-seh-msvcrt-rt_v10-rev2.7z</a>
<ul>
- <li>version: 8.1.0</li>
+ <li>version: 12.2.0</li>
<li>host: x64</li>
- <li>threading: win32</li>
- <li>exceptions: SJLJ</li>
- <li>revision: 0</li>
+ <li>threading: posix</li>
+ <li>exceptions: seh</li>
+ <li>c-runtime: msvcrt</li>
+ <li>revision: 2</li>
</ul></li>
+ <li> <s><a href="https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev2/x86_64-12.2.0-release-win32-seh-msvcrt-rt_v10-rev2.7z">x86_64-12.2.0-release-win32-seh-msvcrt-rt_v10-rev2.7z</a>
+ <ul>
+ <li>version: 12.2.0</li>
+ <li>host: x64</li>
+ <li>threading: win32</li>
+ <li>exceptions: seh</li>
+ <li>c-runtime: msvcrt</li>
+ <li>revision: 2</li>
+ </ul></s></li>
</ul>
</li>
- <li><a href="https://cmake.org/">CMake 3.15.2</a> 64bit version</li>
+ <li><a href="https://cmake.org/">CMake 3.25.1</a> 64bit version</li>
+ <li><a href="https://www.7-zip.org/">7-Zip 22.01</a> 64bit version</li>
</ul>
</li>
</ul>
diff --git a/doc/JogAmpMacOSVersions.md b/doc/JogAmpMacOSVersions.md
new file mode 100644
index 0000000..924c53f
--- /dev/null
+++ b/doc/JogAmpMacOSVersions.md
@@ -0,0 +1,54 @@
+# MacOS Versions Related to JogAmp
+
+References
+
+- [Mac OS Version History (wiki)](https://en.wikipedia.org/wiki/MacOS_version_history).
+- [Xcode Version Comparison Table (wiki)](https://en.wikipedia.org/wiki/Xcode#Version_comparison_table)
+
+## Overview
+
+| MacOS Version | Release Name | Darwin Version | JogAmp Relation |
+|:--------------|:-------------|:---------------|:-------------------------------------------|
+| 10.7 | Lion | 11 | Min deployment target |
+| | | | |
+| 10.13 | High Sierra | 17 | Test node 10.13.6, `x86_64` |
+| 10.14 | Mojave | 18 | |
+| 10.15 | Catalina | 19 | |
+| | | | |
+| 11 | Big Sur | 20 | |
+| 12 | Monterey | 21 | Build node 12.6.5, w/ Xcode 14.2, `x86_64` |
+| 13 | Ventura | 22 | Test node 13.1, `arm64` |
+
+## OpenJDK
+
+Available Java(tm) VMs
+
+- [OpenJDK](http://openjdk.java.net/) build @ [Adoptium](https://adoptium.net/temurin/releases/)
+ - [Adoptium Supported MacOS Versions](https://adoptium.net/supported-platforms/)
+ - MacOS 10.15, 11, 12, 13 for `x86_64` and `arm64`
+
+## JogAmp Build and Test Setup
+
+### MacOS 12.6.5 (Monterey), Darwin 21, `x86_64`
+
+ - Build and main test machine
+ - XCode 14.2 w/ SDK 11.3
+ - `export SDKROOT=macosx11.3` (*MacOS SDK*)
+ - `-mmacosx-version-min=10.7` (*Miniumum deployment target*)
+ - OpenJDK Temurin 17.0.5+8
+
+### MacOS 10.13.6 (High Sierra), Darwin 17, `x86_64`
+
+ - Test machine
+ - OpenJDK Temurin 17.0.5+8
+
+### MacOS 13.1 (Ventura), Darwin 22, `arm64`
+
+ - Test machine
+ - OpenJDK Temurin 17.0.5+8
+
+## Change History
+
+| Date | Note |
+|:-----------|:-----------------------------------------|
+| 2023-05-06 | Initial Version for JogAmp Release 2.5.0 |
diff --git a/make/build-test.xml b/make/build-test.xml
index a83333d..85437f6 100644
--- a/make/build-test.xml
+++ b/make/build-test.xml
@@ -177,7 +177,9 @@
<src path="${test.jcpp.base.dir}"/>
<src path="${build_t.gen}" />
</javac>
+ </target>
+ <target name="jar.build">
<jar destfile="${gluegen-test-util.jar}">
<fileset dir="${build_t.java}">
<include name="${test.junit.util.rel}/**/*.class"/>
@@ -198,7 +200,7 @@
</jar>
</target>
- <target name="android.package" depends="java.generate,java.build,native.build" if="isAndroid">
+ <target name="android.package" depends="java.generate,java.build,native.build,jar.build" if="isAndroid">
<aapt.signed
assetsdir="resources/assets-test"
jarbuilddir="${build_t}"
@@ -591,7 +593,7 @@ chmod 644 ${results}/* \${line.separator}
</gluegen>
</target>
- <target name="junit.test1.c.build" depends="junit.test1i.c.build, c.rename.lib.test1.mingw, junit.test1p1.c.build, c.rename.lib.test1p1.mingw, junit.test1p2.c.build, c.rename.lib.test1p2.mingw" unless="build.javaonly" />
+ <target name="junit.test1.c.build" depends="junit.test1i.c.build, junit.test1p1.c.build, junit.test1p2.c.build" unless="build.javaonly" />
<!-- this is the test1 implementation -->
<target name="junit.test1i.c.build">
@@ -609,9 +611,6 @@ chmod 644 ${results}/* \${line.separator}
linker.cfg.id="linker.test1.dll.cfg.id"/>
</target>
- <target name="c.rename.lib.test1.mingw" if="isMingW">
- <move file="${build_t.lib}/libtest1.so" tofile="${build_t.lib}/test1.dll" />
- </target>
<!-- this is a fixed binding to the test1 implementation -->
<target name="junit.test1p1.c.build">
@@ -632,9 +631,6 @@ chmod 644 ${results}/* \${line.separator}
compiler.cfg.id="${compiler.cfg.id}"
linker.cfg.id="linker.test1.fixed.cfg.id"/>
</target>
- <target name="c.rename.lib.test1p1.mingw" if="isMingW">
- <move file="${build_t.lib}/libBindingtest1p1.so" tofile="${build_t.lib}/Bindingtest1p1.dll" />
- </target>
<!-- this is a dynamic lookup binding to the test1 implementation -->
<target name="junit.test1p2.c.build">
@@ -654,9 +650,6 @@ chmod 644 ${results}/* \${line.separator}
compiler.cfg.id="${compiler.cfg.id}"
linker.cfg.id="linker.test1.runtime.cfg.id"/>
</target>
- <target name="c.rename.lib.test1p2.mingw" if="isMingW">
- <move file="${build_t.lib}/libBindingtest1p2.so" tofile="${build_t.lib}/Bindingtest1p2.dll" />
- </target>
<!--
diff --git a/make/build.xml b/make/build.xml
index 8cd6ea1..a4afadb 100644
--- a/make/build.xml
+++ b/make/build.xml
@@ -440,12 +440,6 @@
<target name="c.configure" depends="gluegen.cpptasks.detect.os,gluegen.cpptasks.setup.compiler,declare.win32,declare.linux,declare.android,declare.solaris,declare.macosx,declare.ios.amd64,declare.ios.arm64,declare.freebsd,declare.hpux,gluegen.cpptasks.configure.compiler" />
- <target name="c.rename.lib.mingw" if="isMingW">
- <!-- FIXME: this is a hack; the cpptask should have an option to change the
- suffix or at least understand the override from .so to .dll -->
- <move file="${build}/obj/libgluegen_rt.so" tofile="${build}/obj/gluegen_rt.dll" />
- </target>
-
<target name="c.manifest" if="isVC8Family">
<!-- exec mt, the Microsoft Manifest Tool, to include DLL manifests in order to resolve the location of msvcr80.dll -->
<msvc.manifest objdir="${build}/obj" dllname="gluegen_rt" />
@@ -526,8 +520,6 @@
</cc>
- <antcall target="c.rename.lib.mingw" inheritRefs="true" />
-
<gluegen.make.libsymbols builddir="${build}"
nativelib="${gluegen.lib.dir}/${output.lib.name.os}"
symbolsfile="${gluegen.lib.dir}/${native.library.prefix}${output.lib.name}.symbols" />
@@ -816,6 +808,7 @@
excludes="${gluegen.excludes.all} ${gluegen-rt.classes} ${java.part.android}"
memoryMaximumSize="${javac.memorymax}"
encoding="UTF-8"
+ source="${target.sourcelevel}"
target="${target.targetlevel}"
debug="${javacdebug}" debuglevel="${javacdebuglevel}">
<src path="${src.jcpp}" />
@@ -1339,12 +1332,12 @@
<copy todir="${archive}">
<fileset dir=".." includes="LICENSE.txt"/>
<fileset dir="${build}" includes="artifact.properties"/>
- <fileset dir="${build}" includes="gluegen-java-src.zip"/>
</copy>
<mkdir dir="${archive}/jar" />
<copy todir="${archive}/jar">
<fileset dir="${build}" includes="gluegen*.jar"/>
<fileset dir="${build}" includes="*.apk"/>
+ <fileset dir="${build}" includes="gluegen-java-src.zip"/>
</copy>
<mkdir dir="${archive}/lib" />
<copy todir="${archive}/lib">
diff --git a/make/gluegen-cpptasks-base.xml b/make/gluegen-cpptasks-base.xml
index 30cadf3..746f9cc 100755
--- a/make/gluegen-cpptasks-base.xml
+++ b/make/gluegen-cpptasks-base.xml
@@ -221,20 +221,10 @@
<condition property="c.strip.libraries"><isfalse value="${c.compiler.debug}"/></condition>
<!-- NOTE: the values of the macos<arch> attributes will not be overridden if already set externally -->
- <property name="macosppc" value="false" />
- <property name="macosx64" value="true" />
- <property name="macosx32" value="false" /> <!-- we disable 32bit on OSX for good now -->
+ <property name="macosppc" value="false" /> <!-- permanently disabled -->
+ <property name="macosx32" value="false" /> <!-- permanently disabled -->
+ <property name="macosx64" value="true" /> <!-- for x86_64 and arm64 -->
- <!-- Need a way to be able to disable the macosx64 property specification in a build.xml -->
- <condition property="use.macosppc">
- <istrue value="${macosppc}" />
- </condition>
- <condition property="use.macosx32">
- <and>
- <istrue value="${macosx32}" />
- <os family="mac"/>
- </and>
- </condition>
<condition property="use.macosx64">
<and>
<istrue value="${macosx64}" />
@@ -801,6 +791,7 @@
<echo message="os and arch: ${os.and.arch}" />
<echo message="os and arch.dot: ${os.and.arch.dot}" />
<echo message="os and arch.slash: ${os.and.arch.slash}" />
+ <echo message="native library: prefix '${native.library.prefix}', suffix '${native.library.suffix}'" />
</target>
<target name="gluegen.cpptasks.detect.os" depends="gluegen.properties.load.user,gluegen.cpptasks.detect.os.custom,gluegen.cpptasks.detect.os.1,gluegen.cpptasks.detect.os.2">
@@ -1236,20 +1227,19 @@
</defineset>
</compiler>
- <!-- MacOSX compiler configuration -->
+ <!--
+ MacOSX compiler configuration.
+ See and sync-with doc/HowToBuild.html and doc/JogAmpMacOSVersions.md
+ -->
<compiler id="compiler.cfg.macosx" name="${gcc.compat.compiler}">
- <!-- Note: Apple doesn't seem to provide ppc binaries on Snow Leopard -->
- <compilerarg value="-arch" if="use.macosppc"/>
- <compilerarg value="ppc" if="use.macosppc"/>
- <compilerarg value="-arch" if="use.macosx32"/>
- <compilerarg value="i386" if="use.macosx32"/>
<compilerarg value="-arch" if="use.macosx64"/>
<compilerarg value="x86_64" if="use.macosx64"/>
- <!-- Note: Apple doesn't seem to provide ppc64 binaries on Leopard -->
+ <compilerarg value="-arch" if="use.macosx64"/>
+ <compilerarg value="arm64" if="use.macosx64"/>
<compilerarg value="-Wmost" />
<compilerarg value="-ObjC" />
- <compilerarg value="-mmacosx-version-min=10.5"/>
+ <compilerarg value="-mmacosx-version-min=10.7"/>
<!-- sysincludepath path="${macosx.sdkroot}" if="macosx.sdkroot"/ -->
<defineset>
<define name="_DEBUG" if="c.compiler.use-debug"/>
@@ -1479,13 +1469,11 @@
<linker id="linker.cfg.macosx" name="${gcc.compat.compiler}">
<!-- compilerarg value="-v"/ -->
- <linkerarg value="-arch" if="use.macosppc"/>
- <linkerarg value="ppc" if="use.macosppc"/>
- <linkerarg value="-arch" if="use.macosx32"/>
- <linkerarg value="i386" if="use.macosx32"/>
<linkerarg value="-arch" if="use.macosx64"/>
<linkerarg value="x86_64" if="use.macosx64"/>
- <linkerarg value="-mmacosx-version-min=10.5"/>
+ <linkerarg value="-arch" if="use.macosx64"/>
+ <linkerarg value="arm64" if="use.macosx64"/>
+ <linkerarg value="-mmacosx-version-min=10.7"/>
<linkerarg value="-static-libgcc" if="isGCC"/>
<linkerarg value="-static-libstdc++" if="isGCC"/>
</linker>
diff --git a/make/jogamp-androidtasks.xml b/make/jogamp-androidtasks.xml
index 3289a2b..9236496 100644
--- a/make/jogamp-androidtasks.xml
+++ b/make/jogamp-androidtasks.xml
@@ -159,6 +159,7 @@
<echo>aapt.signed ${m.aapt.apkbasename}: compiling R.java...</echo>
<javac encoding="${m.aapt.java.encoding}"
+ includeAntRuntime="false"
source="${target.sourcelevel}"
target="${target.targetlevel}"
bootclasspath="${target.rt.jar}"
@@ -180,7 +181,7 @@
<!-- exec dir="." executable="dx" logError="true" failonerror="true" failifexecutionfails="true">
<arg line="- -dex"/>
<arg line="- -output=${m.aapt.dex.file}"/>
- <arg line="- -min-sdk-version=${android.api.level.min}"/>
+ <arg line="- -min-sdk-version=${android.api.level}"/>
<arg line="@{jarbuilddir}/@{jarbasename}.jar"/>
<arg line="${m.aapt.build.apk}/temp/classes"/>
</exec -->
@@ -191,7 +192,9 @@
<arg line="--classpath ${target.rt.jar}"/>
<d8-classpaths/>
- <arg line="--min-api ${android.api.level.min}"/>
+ <arg line="--min-api ${android.api.level}"/>
+
+ <!-- arg line="- -no-desugaring"/ -->
<arg line="--release"/>
<!-- arg line="- -debug"/ -->
@@ -235,11 +238,13 @@
<!-- Be Java6 keytool/jarsigner compatible, and hence Android compatible -->
<arg value="-sigalg"/>
- <arg value="MD5withRSA"/>
+ <arg value="SHA256withRSA"/>
<arg value="-keyalg"/>
<arg value="RSA"/>
<arg value="-keysize"/>
- <arg value="1024"/>
+ <arg value="2048"/>
+ <arg value="-validity"/>
+ <arg value="365"/>
<arg value="-keystore" />
<arg value="${m.aapt.build.apk}/debug.keystore" />
@@ -260,8 +265,8 @@
<!-- Be Java6 keytool/jarsigner compatible, and hence Android compatible -->
<echo>aapt.signed ${m.aapt.apkbasename}: signing w/ key @{keystore.alias} @ ${m.aapt.keystore.file}</echo>
<!-- signjar
- sigalg="MD5withRSA"
- digestalg="SHA1"
+ sigalg="SHA256withRSA"
+ digestalg="SHA256"
jar="${m.aapt.unsigned.package.file.name}"
signedjar="${m.aapt.signed.file.name}"
keystore="${m.aapt.keystore.file}"
@@ -273,9 +278,9 @@
<exec dir="." executable="jarsigner" failonerror="true">
<!-- Be Java6 keytool/jarsigner compatible, and hence Android compatible -->
<arg value="-sigalg"/>
- <arg value="MD5withRSA"/>
+ <arg value="SHA256withRSA"/>
<arg value="-digestalg"/>
- <arg value="SHA1"/>
+ <arg value="SHA256"/>
<arg value="-keystore" />
<arg value="${m.aapt.keystore.file}" />
diff --git a/make/jogamp-env.xml b/make/jogamp-env.xml
index a5575f8..cc8ed71 100755
--- a/make/jogamp-env.xml
+++ b/make/jogamp-env.xml
@@ -8,7 +8,7 @@
- Java 1.8 (Level 8.0)
- Android SDK API level 24 (Version 7.0 Nougat, released August 2016)
- Official production builds are performed _on_ OpenJDK 11
+ Official production builds are performed _on_ OpenJDK 11 or 17
and a Java JDK 11 or greater is required!
Target Java 8 baseline is chosen today, June 2019,
@@ -74,19 +74,65 @@
</condition>
</fail>
+ <condition property="minJava21" value="true">
+ <or>
+ <equals arg1="${ant.java.version}" arg2="21"/>
+ <equals arg1="${ant.java.version}" arg2="22"/>
+ <equals arg1="${ant.java.version}" arg2="23"/>
+ <equals arg1="${ant.java.version}" arg2="24"/>
+ <equals arg1="${ant.java.version}" arg2="25"/>
+ <equals arg1="${ant.java.version}" arg2="26"/>
+ <equals arg1="${ant.java.version}" arg2="27"/>
+ <equals arg1="${ant.java.version}" arg2="28"/>
+ </or>
+ </condition>
+ <echo message="minJava21 ${minJava21}"/>
+
+ <condition property="minJava17" value="true">
+ <or>
+ <equals arg1="${ant.java.version}" arg2="17"/>
+ <equals arg1="${ant.java.version}" arg2="18"/>
+ <equals arg1="${ant.java.version}" arg2="19"/>
+ <equals arg1="${ant.java.version}" arg2="20"/>
+ <istrue value="${minJava21}"/>
+ </or>
+ </condition>
+ <echo message="minJava17 ${minJava17}"/>
+
+ <condition property="minJava11" value="true">
+ <or>
+ <equals arg1="${ant.java.version}" arg2="11"/>
+ <equals arg1="${ant.java.version}" arg2="12"/>
+ <equals arg1="${ant.java.version}" arg2="13"/>
+ <equals arg1="${ant.java.version}" arg2="14"/>
+ <equals arg1="${ant.java.version}" arg2="15"/>
+ <equals arg1="${ant.java.version}" arg2="16"/>
+ <istrue value="${minJava17}"/>
+ </or>
+ </condition>
+ <echo message="minJava11 ${minJava11}"/>
+
+ <condition property="minJava9" value="true">
+ <or>
+ <equals arg1="${ant.java.version}" arg2="9"/>
+ <istrue value="${minJava11}"/>
+ </or>
+ </condition>
+ <echo message="minJava9 ${minJava9}"/>
+
+ <condition property="minJava8" value="true">
+ <or>
+ <equals arg1="${ant.java.version}" arg2="1.8"/>
+ <istrue value="${minJava9}"/>
+ </or>
+ </condition>
+ <echo message="minJava8 ${minJava8}"/>
+
<!-- Only for junit runtime tests Java [8-10] is allowed, for building Java 11 is required. -->
<fail message="Unsupported Java version: ${ant.java.version}. Make sure that the version of Java is 1.8 or greater.">
<condition>
<not>
- <or>
- <equals arg1="${ant.java.version}" arg2="1.8"/>
- <equals arg1="${ant.java.version}" arg2="9"/>
- <equals arg1="${ant.java.version}" arg2="10"/>
- <equals arg1="${ant.java.version}" arg2="11"/>
- <equals arg1="${ant.java.version}" arg2="12"/>
- <equals arg1="${ant.java.version}" arg2="13"/>
- <equals arg1="${ant.java.version}" arg2="14"/>
- </or>
+ <istrue value="${minJava8}"/>
</not>
</condition>
</fail>
@@ -101,15 +147,7 @@
</tstamp>
<condition property="javadoc.xarg1" value="-Xdoclint:none" else="-J-Ddummy=val">
- <or>
- <equals arg1="${ant.java.version}" arg2="1.8"/>
- <equals arg1="${ant.java.version}" arg2="9"/>
- <equals arg1="${ant.java.version}" arg2="10"/>
- <equals arg1="${ant.java.version}" arg2="11"/>
- <equals arg1="${ant.java.version}" arg2="12"/>
- <equals arg1="${ant.java.version}" arg2="13"/>
- <equals arg1="${ant.java.version}" arg2="14"/>
- </or>
+ <istrue value="${minJava8}"/>
</condition>
<echo message="javadoc.xarg1 ${javadoc.xarg1}"/>
@@ -122,7 +160,7 @@
<echo message="jogamp.jar.codebase ${jogamp.jar.codebase}"/>
<property name="jogamp.version.major" value="2"/>
- <property name="jogamp.version.minor" value="4"/>
+ <property name="jogamp.version.minor" value="5"/>
<property name="jogamp.version.submi" value="0"/>
<property name="jogamp.version.devel" value="-rc-${version.timestamp}"/> <!-- Devel RC Tag -->
<!-- property name="jogamp.version.devel" value=""/ --> <!-- Release tag -->
@@ -164,8 +202,6 @@
</not>
</condition>
- <property name="android.api.level.min" value="21" />
-
<condition property="android.api.level" value="${env.ANDROID_API_LEVEL}" else="24">
<not>
<equals arg1="${env.ANDROID_API_LEVEL}" arg2="$${env.ANDROID_API_LEVEL}" casesensitive="true" />
diff --git a/make/lib/cpptasks-version.txt b/make/lib/cpptasks-version.txt
index 339d395..231d444 100755
--- a/make/lib/cpptasks-version.txt
+++ b/make/lib/cpptasks-version.txt
@@ -1,5 +1,6 @@
Current cpptasks is from
<http://jogamp.org/git/?p=ant-cpptasks.git;a=summary>
+commit 19c854265956942497dc89444a9ee84f18383671
Original cpptasks is from
<http://ant-contrib.sourceforge.net/cpptasks/index.html>
diff --git a/make/lib/cpptasks.jar b/make/lib/cpptasks.jar
index dbefd44..bd29273 100644
--- a/make/lib/cpptasks.jar
+++ b/make/lib/cpptasks.jar
Binary files differ
diff --git a/make/scripts/check-java-major-version.sh b/make/scripts/check-java-major-version.sh
index 49c0445..fc9f53c 100755
--- a/make/scripts/check-java-major-version.sh
+++ b/make/scripts/check-java-major-version.sh
@@ -12,7 +12,7 @@ function dump_versions() {
#dump_version jogamp.common.Debug
javap -v `find . -name '*.class'` | grep -e '^Classfile' -e 'major version'
#for i in `find . -name '*.class'` ; do
- # dump_version `echo $i | sed -e 's/\//./g' -e 's/\.class//g'`
+ # dump_version `echo $i | sed -e 's/^\.\///g' -e 's/\//./g' -e 's/\.class//g'`
#done
cd $TDIR
}
diff --git a/make/scripts/java-win32.bat b/make/scripts/java-win32.bat
deleted file mode 100755
index 436d68b..0000000
--- a/make/scripts/java-win32.bat
+++ /dev/null
@@ -1,25 +0,0 @@
-
-set BLD_SUB=build-win32
-
-set J2RE_HOME=c:\jre-11.0.4+11_x32
-set JAVA_HOME=c:\jdk-11.0.4+11_x32
-set ANT_PATH=C:\apache-ant-1.10.5
-
-set BLD_DIR=..\%BLD_SUB%
-REM set LIB_DIR=..\%BLD_SUB%\obj;..\%BLD_SUB%\test\build\natives
-set LIB_DIR=..\%BLD_SUB%\test\build\natives
-
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw32\bin;%LIB_DIR%;%PATH%
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw32\bin;%PATH%
-
-set CP_ALL=.;lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar;lib/semantic-versioning/semver.jar;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\gluegen.jar;%BLD_DIR%\gluegen-test-util.jar;%BLD_DIR%\test\build\gluegen-test.jar
-
-echo CP_ALL %CP_ALL%
-
-set X_ARGS="-Drootrel.build=%BLD_SUB%" "-Dgluegen.root=.."
-REM set D_ARGS="-Djogamp.debug.Platform" "-Djogamp.debug.NativeLibrary"
-set D_ARGS="-Djogamp.debug.IOUtil" "-Djogamp.debug.IOUtil.Exe"
-REM set D_ARGS="-Djogamp.debug=all"
-
-%J2RE_HOME%\bin\java -classpath %CP_ALL% %X_ARGS% %D_ARGS% "-Djava.library.path=%LIB_DIR%" "-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true" %1 %2 %3 %4 %5 %6 %7 %8 %9 > java-win32.log 2>&1
-REM %J2RE_HOME%\bin\java -classpath %CP_ALL% %X_ARGS% %D_ARGS% "-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true" %1 %2 %3 %4 %5 %6 %7 %8 %9 > java-win32.log 2>&1
diff --git a/make/scripts/java-win64.bat b/make/scripts/java-win64.bat
index 575d937..26a4591 100755
--- a/make/scripts/java-win64.bat
+++ b/make/scripts/java-win64.bat
@@ -1,16 +1,14 @@
set BLD_SUB=build-win64
-set J2RE_HOME=c:\jre-11.0.4+11_x64
-set JAVA_HOME=c:\jdk-11.0.4+11_x64
+set J2RE_HOME=c:\jdk-17
+set JAVA_HOME=c:\jdk-17
set ANT_PATH=C:\apache-ant-1.10.5
set BLD_DIR=..\%BLD_SUB%
-REM set LIB_DIR=..\%BLD_SUB%\obj;..\%BLD_SUB%\test\build\natives
-set LIB_DIR=..\%BLD_SUB%\test\build\natives
+set LIB_DIR=%cd%\..\%BLD_SUB%\test\build\natives
set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw64\bin;%LIB_DIR%;%PATH%
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw64\bin;%PATH%
set CP_ALL=.;lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar;lib/semantic-versioning/semver.jar;lib\TestJarsInJar.jar;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\gluegen.jar;%BLD_DIR%\gluegen-test-util.jar;%BLD_DIR%\test\build\gluegen-test.jar
@@ -18,6 +16,7 @@ echo CP_ALL %CP_ALL%
set X_ARGS="-Drootrel.build=%BLD_SUB%" "-Dgluegen.root=.."
REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogamp.debug.JNILibLoader" "-Djogamp.debug.TempFileCache" "-Djogamp.debug.JarUtil" "-Djogamp.debug.TempJarCache"
+REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogamp.debug.NativeLibrary" "-Djogamp.debug.JNILibLoader" "-Djogamp.debug.TempFileCache" "-Djogamp.debug.JarUtil" "-Djogamp.debug.TempJarCache"
REM set D_ARGS="-Djogamp.debug.Platform" "-Djogamp.debug.NativeLibrary" "-Djogamp.debug.IOUtil"
REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogamp.debug.IOUtil.Exe" "-Djogamp.debug.IOUtil.Exe.NoStream"
REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogamp.debug.TempFileCache" "-Djogamp.debug.TempJarCache" "-Djogamp.debug.IOUtil.Exe" "-Djogamp.gluegen.UseNativeExeFile=true" "-Djava.io.tmpdir=c:\temp_noexec"
diff --git a/make/scripts/make.gluegen.all.ios.amd64.sh b/make/scripts/make.gluegen.all.ios.amd64.sh
index bda783d..ddc0fd7 100755
--- a/make/scripts/make.gluegen.all.ios.amd64.sh
+++ b/make/scripts/make.gluegen.all.ios.amd64.sh
@@ -16,7 +16,7 @@ fi
export SDKROOT=iphonesimulator13.2
xcrun --show-sdk-path
-JAVA_HOME=`/usr/libexec/java_home -version 11`
+JAVA_HOME=`/usr/libexec/java_home -version 17`
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME PATH
which java
diff --git a/make/scripts/make.gluegen.all.ios.arm64.sh b/make/scripts/make.gluegen.all.ios.arm64.sh
index a4e811d..13c9469 100755
--- a/make/scripts/make.gluegen.all.ios.arm64.sh
+++ b/make/scripts/make.gluegen.all.ios.arm64.sh
@@ -16,7 +16,7 @@ fi
export SDKROOT=iphoneos13.2
xcrun --show-sdk-path
-JAVA_HOME=`/usr/libexec/java_home -version 11`
+JAVA_HOME=`/usr/libexec/java_home -version 17`
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME PATH
which java
diff --git a/make/scripts/make.gluegen.all.linux-x86_64.sh b/make/scripts/make.gluegen.all.linux-x86_64.sh
index b0bbed7..aaac667 100755
--- a/make/scripts/make.gluegen.all.linux-x86_64.sh
+++ b/make/scripts/make.gluegen.all.linux-x86_64.sh
@@ -2,6 +2,9 @@
SDIR=`dirname $0`
+# export J2RE_HOME=/usr/lib/jvm/java-11-openjdk-amd64
+# export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
+
if [ -e $SDIR/setenv-build-jogamp-x86_64.sh ] ; then
. $SDIR/setenv-build-jogamp-x86_64.sh
fi
diff --git a/make/scripts/make.gluegen.all.macosx.sh b/make/scripts/make.gluegen.all.macosx.sh
index d61843a..9d30807 100755
--- a/make/scripts/make.gluegen.all.macosx.sh
+++ b/make/scripts/make.gluegen.all.macosx.sh
@@ -13,7 +13,7 @@ fi
# Force OSX SDK 10.6, if desired
# export SDKROOT=macosx10.6
-JAVA_HOME=`/usr/libexec/java_home -version 11`
+JAVA_HOME=`/usr/libexec/java_home -version 17`
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME PATH
diff --git a/make/scripts/make.gluegen.all.win32.bat b/make/scripts/make.gluegen.all.win32.bat
deleted file mode 100755
index caaf7f0..0000000
--- a/make/scripts/make.gluegen.all.win32.bat
+++ /dev/null
@@ -1,29 +0,0 @@
-set THISDIR="C:\JogAmp"
-
-set J2RE_HOME=c:\jre-11.0.4+11_x32
-set JAVA_HOME=c:\jdk-11.0.4+11_x32
-set ANT_PATH=C:\apache-ant-1.10.5
-set GIT_PATH=C:\cygwin64\bin
-set SEVENZIP=C:\Program Files\7-Zip
-
-set CMAKE_PATH=C:\cmake-3.15.2-win32-x86
-set CMAKE_C_COMPILER=c:\mingw32\bin\gcc
-
-set PATH=%J2RE_HOME%\bin;%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw32\bin;%CMAKE_PATH%\bin;%GIT_PATH%;%SEVENZIP%;%PATH%
-
-set LIB_GEN=%THISDIR%\lib
-set CLASSPATH=.;%THISDIR%\build-win32\classes
-REM -Dc.compiler.debug=true
-REM -DuseOpenMAX=true
-REM -DuseKD=true
-REM -Djogl.cg=1 -D-Dwindows.cg.lib=C:\Cg-2.2
-
-set SOURCE_LEVEL=1.8
-set TARGET_LEVEL=1.8
-set TARGET_RT_JAR=C:\jre1.8.0_212\lib\rt.jar
-
-REM set JOGAMP_JAR_CODEBASE=Codebase: *.jogamp.org
-set JOGAMP_JAR_CODEBASE=Codebase: *.goethel.localnet
-
-ant -Drootrel.build=build-win32 %1 %2 %3 %4 %5 %6 %7 %8 %9 > make.gluegen.all.win32.log 2>&1
-
diff --git a/make/scripts/make.gluegen.all.win64.bat b/make/scripts/make.gluegen.all.win64.bat
index 239f8e2..b0dc64e 100755
--- a/make/scripts/make.gluegen.all.win64.bat
+++ b/make/scripts/make.gluegen.all.win64.bat
@@ -1,12 +1,12 @@
set THISDIR="C:\JogAmp"
-set J2RE_HOME=c:\jre-11.0.4+11_x64
-set JAVA_HOME=c:\jdk-11.0.4+11_x64
+set J2RE_HOME=c:\jdk-17
+set JAVA_HOME=c:\jdk-17
set ANT_PATH=C:\apache-ant-1.10.5
set GIT_PATH=C:\cygwin64\bin
set SEVENZIP=C:\Program Files\7-Zip
-set CMAKE_PATH=C:\cmake-3.15.2-win64-x64
+set CMAKE_PATH=C:\cmake-3.25.1-windows-x86_64
set CMAKE_C_COMPILER=c:\mingw64\bin\gcc
set PATH=%J2RE_HOME%\bin;%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw64\bin;%CMAKE_PATH%\bin;%GIT_PATH%;%SEVENZIP%;%PATH%
diff --git a/make/scripts/make.macosx.jdk_lipo_libs.sh b/make/scripts/make.macosx.jdk_lipo_libs.sh
new file mode 100644
index 0000000..5619bc5
--- /dev/null
+++ b/make/scripts/make.macosx.jdk_lipo_libs.sh
@@ -0,0 +1,30 @@
+#! /bin/sh
+
+#
+# First unpack the OpenJDK (Temurin) package
+# for amd64 and arm64.
+# Then copy each lib-folder 'temurin-xy.jdk/Contents/Home/lib/'
+# to their respective target lib-folder:
+# - temurin-xy.jdk.amd64.lib/
+# - temurin-xy.jdk.arm64.lib/
+#
+# Now we can run this script producing fat lipo dylib files,
+# placed into
+# - temurin-xy.jdk.fat.lib
+#
+
+amd64_dir=$HOME/temurin-17.jdk.amd64.lib
+arm64_dir=$HOME/temurin-17.jdk.arm64.lib
+fat_dir=$HOME/temurin-17.jdk.fat.lib
+
+rm -rf $fat_dir
+mkdir $fat_dir
+
+for i in $amd64_dir/*.dylib ; do
+ bname=`basename $i`
+ if [ -e $arm64_dir/$bname ] ; then
+ lipo -create $i $arm64_dir/$bname -output $fat_dir/$bname
+ else
+ echo missing $arm64_dir/$bname
+ fi
+done
diff --git a/make/scripts/runtest-x32.bat b/make/scripts/runtest-x32.bat
deleted file mode 100755
index 6f169d5..0000000
--- a/make/scripts/runtest-x32.bat
+++ /dev/null
@@ -1,16 +0,0 @@
-REM set TEMP=C:\Documents and Settings\jogamp\temp-exec
-REM set TMP=C:\Documents and Settings\jogamp\temp-exec
-REM set TEMP=C:\Users\jogamp\temp-exec
-REM set TMP=C:\Users\jogamp\temp-exec
-
-REM scripts\java-win32.bat com.jogamp.common.GlueGenVersion
-REM scripts\java-win32.bat com.jogamp.common.util.TestVersionInfo
-REM scripts\java-win32.bat com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter
-REM scripts\java-win32.bat com.jogamp.gluegen.test.junit.generation.Test1p2ProcAddressEmitter
-REM scripts\java-win32.bat com.jogamp.common.util.TestTempJarCache
-scripts\java-win32.bat com.jogamp.common.util.TestPlatform01
-REM scripts\java-win32.bat com.jogamp.common.os.TestElfReader01
-REM scripts\java-win32.bat com.jogamp.common.util.TestIOUtilURIHandling
-REM scripts\java-win32.bat com.jogamp.common.nio.TestByteBufferInputStream
-REM scripts\java-win32.bat com.jogamp.common.nio.TestByteBufferOutputStream
-
diff --git a/make/scripts/runtest-x64.bat b/make/scripts/runtest-x64.bat
index 3507046..85f0d82 100755
--- a/make/scripts/runtest-x64.bat
+++ b/make/scripts/runtest-x64.bat
@@ -4,11 +4,11 @@ REM set TEMP=C:\Users\jogamp\temp-exec
REM set TMP=C:\Users\jogamp\temp-exec
REM scripts\java-win64.bat com.jogamp.common.GlueGenVersion
-scripts\java-win64.bat com.jogamp.common.util.TestVersionInfo
+REM scripts\java-win64.bat com.jogamp.common.util.TestVersionInfo
REM scripts\java-win64.bat com.jogamp.gluegen.jcpp.IncludeAbsoluteTest
-REM scripts\java-win64.bat com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter
+scripts\java-win64.bat com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter
REM scripts\java-win64.bat com.jogamp.gluegen.test.junit.generation.Test1p2ProcAddressEmitter
REM scripts\java-win64.bat com.jogamp.gluegen.test.junit.generation.Test1p2LoadJNIAndImplLib
REM scripts\java-win64.bat com.jogamp.gluegen.test.junit.generation.Test1p2DynamicLibraryBundle
diff --git a/make/scripts/runtest.sh b/make/scripts/runtest.sh
index 72279a6..4f40cd6 100755
--- a/make/scripts/runtest.sh
+++ b/make/scripts/runtest.sh
@@ -93,7 +93,7 @@ function onetest() {
#
#onetest com.jogamp.common.GlueGenVersion 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestSystemPropsAndEnvs 2>&1 | tee -a $LOG
-onetest com.jogamp.common.util.TestVersionInfo 2>&1 | tee -a $LOG
+#onetest com.jogamp.common.util.TestVersionInfo 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestVersionNumber 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestVersionSemantics 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestIteratorIndexCORE 2>&1 | tee -a $LOG
@@ -148,7 +148,7 @@ onetest com.jogamp.common.util.TestVersionInfo 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.jcpp.TokenPastingWhitespaceTest 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.jcpp.PreprocessorTest 2>&1 | tee -a $LOG
-#onetest com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter 2>&1 | tee -a $LOG
+onetest com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.test.junit.generation.Test1p2ProcAddressEmitter 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.test.junit.generation.Test1p2LoadJNIAndImplLib 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.test.junit.generation.Test1p2DynamicLibraryBundle 2>&1 | tee -a $LOG
diff --git a/make/scripts/setenv-build-jogamp-x86.sh b/make/scripts/setenv-build-jogamp-x86.sh
index 5c7ba06..c25474c 100644
--- a/make/scripts/setenv-build-jogamp-x86.sh
+++ b/make/scripts/setenv-build-jogamp-x86.sh
@@ -28,6 +28,16 @@ if [ ! -z "$J2RE_HOME" -a ! -z "$JAVA_HOME" ] ; then
fi
if [ -z "$FOUND_JAVA" ] ; then
+ if [ -e /usr/lib/jvm/java-17-openjdk-i386 ] ; then
+ J2RE_HOME=/usr/lib/jvm/java-17-openjdk-i386
+ JAVA_HOME=/usr/lib/jvm/java-17-openjdk-i386
+ PATH=$JAVA_HOME/bin:$PATH
+ export J2RE_HOME JAVA_HOME
+ FOUND_JAVA=1
+ fi
+fi
+
+if [ -z "$FOUND_JAVA" ] ; then
if [ -e /usr/lib/jvm/java-11-openjdk-i386 ] ; then
J2RE_HOME=/usr/lib/jvm/java-11-openjdk-i386
JAVA_HOME=/usr/lib/jvm/java-11-openjdk-i386
diff --git a/make/scripts/setenv-build-jogamp-x86_64.sh b/make/scripts/setenv-build-jogamp-x86_64.sh
index e9bf313..26dc5d0 100644
--- a/make/scripts/setenv-build-jogamp-x86_64.sh
+++ b/make/scripts/setenv-build-jogamp-x86_64.sh
@@ -28,6 +28,16 @@ if [ ! -z "$J2RE_HOME" -a ! -z "$JAVA_HOME" ] ; then
fi
if [ -z "$FOUND_JAVA" ] ; then
+ if [ -e /usr/lib/jvm/java-17-openjdk-amd64 ] ; then
+ J2RE_HOME=/usr/lib/jvm/java-17-openjdk-amd64
+ JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
+ PATH=$JAVA_HOME/bin:$PATH
+ export J2RE_HOME JAVA_HOME
+ FOUND_JAVA=1
+ fi
+fi
+
+if [ -z "$FOUND_JAVA" ] ; then
if [ -e /usr/lib/jvm/java-11-openjdk-amd64 ] ; then
J2RE_HOME=/usr/lib/jvm/java-11-openjdk-amd64
JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
diff --git a/make/scripts/test-win32-smb_share.bat b/make/scripts/test-win32-smb_share.bat
deleted file mode 100755
index ce1ab1f..0000000
--- a/make/scripts/test-win32-smb_share.bat
+++ /dev/null
@@ -1,24 +0,0 @@
-
-set SMB_ROOT=\\risa.goethel.localnet\deployment\test\jogamp
-
-set BLD_SUB=build-win32
-set J2RE_HOME=c:\jre8u202-b08_x32
-set JAVA_HOME=c:\jdk8u202-b08_x32
-set ANT_PATH=C:\apache-ant-1.9.4
-
-set PROJECT_ROOT=%SMB_ROOT%\gluegen
-set BLD_DIR=%PROJECT_ROOT%\%BLD_SUB%
-
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PATH%
-
-set D_ARGS="-Djogamp.debug=all"
-
-set LIB_DIR=
-
-set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%PROJECT_ROOT%\make\lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar
-
-echo CP_ALL %CP_ALL%
-
-%J2RE_HOME%\bin\java -classpath %CP_ALL% %D_ARGS% %X_ARGS% com.jogamp.common.GlueGenVersion > java-win.log 2>&1
-tail java-win.log
-
diff --git a/src/java/com/jogamp/common/av/AudioFormat.java b/src/java/com/jogamp/common/av/AudioFormat.java
new file mode 100644
index 0000000..2802f31
--- /dev/null
+++ b/src/java/com/jogamp/common/av/AudioFormat.java
@@ -0,0 +1,193 @@
+/**
+ * Copyright 2013-2023 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.common.av;
+
+/**
+ * Specifies the linear audio PCM format.
+ */
+public class AudioFormat {
+ /**
+ * @param sampleRate sample rate in Hz (1/s), e.g. 44100 Hz
+ * @param sampleSize sample size in bits, e.g. 16 bits
+ * @param channelCount number of channels, e.g. 2 channels for stereo
+ * @param signed true if signed PCM values, false for unsigned values
+ * @param fixedP true for fixed point values, false for unsigned floating point values with a sampleSize of 32 (float) or 64 (double)
+ * @param planar true for planar data package (each channel in own data buffer), false for packed data channels interleaved in one buffer.
+ * @param littleEndian true for little-endian byte order, false for big endian byte order
+ */
+ public AudioFormat(final int sampleRate, final int sampleSize, final int channelCount, final boolean signed, final boolean fixedP, final boolean planar, final boolean littleEndian) {
+ this.sampleRate = sampleRate;
+ this.sampleSize = sampleSize;
+ this.channelCount = channelCount;
+ this.signed = signed;
+ this.fixedP = fixedP;
+ this.planar = planar;
+ this.littleEndian = littleEndian;
+ if( !fixedP ) {
+ if( sampleSize != 32 && sampleSize != 64 ) {
+ throw new IllegalArgumentException("Floating point: sampleSize "+sampleSize+" bits");
+ }
+ if( !signed ) {
+ throw new IllegalArgumentException("Floating point: unsigned");
+ }
+ }
+ }
+
+ /** Sample rate in Hz (1/s, e.g. 44100 Hz. */
+ public final int sampleRate;
+ /** Sample size in bits, e.g. 16 bits. */
+ public final int sampleSize;
+ /** Number of channels, e.g. 2 channels for stereo. */
+ public final int channelCount;
+ /** Signed PCM values if true, otherwise unsigned values. */
+ public final boolean signed;
+ /** Fixed or floating point values. Floating point 'float' has {@link #sampleSize} 32, 'double' has {@link #sampleSize} 64. */
+ public final boolean fixedP;
+ /** Planar or packed samples. If planar, each channel has their own data buffer. If packed, channel data is interleaved in one buffer. */
+ public final boolean planar;
+ /** Little-endian byte order if true, otherwise big endian byte order. */
+ public final boolean littleEndian;
+
+
+ //
+ // Time <-> Bytes
+ //
+
+ /**
+ * Returns the byte size of the given duration in seconds
+ * according to {@link #sampleSize}, {@link #channelCount} and {@link #sampleRate}.
+ * <pre>
+ * final float bytesPerSample = sampleSize/8;
+ * return Math.round( duration * channelCount * bytesPerSample * sampleRate );
+ * </pre>
+ * <p>
+ * Time -> Byte Count
+ * </p>
+ * @param duration duration in seconds
+ */
+ public final int getDurationsByteSize(final float duration) {
+ final float bytesPerSample = sampleSize >>> 3; // /8
+ return Math.round( duration * channelCount * bytesPerSample * sampleRate );
+ }
+
+ /**
+ * Returns the duration in seconds of the given byte count
+ * according to {@link #sampleSize}, {@link #channelCount} and {@link #sampleRate}.
+ * <pre>
+ * final float bytesPerSample = sampleSize/8;
+ * return byteCount / ( channelCount * bytesPerSample * sampleRate )
+ * </pre>
+ * <p>
+ * Byte Count -> Time
+ * </p>
+ * @param byteCount size in bytes
+ */
+ public final float getBytesDuration(final int byteCount) {
+ final float bytesPerSample = sampleSize >>> 3; // /8
+ return byteCount / ( channelCount * bytesPerSample * sampleRate );
+ }
+
+ /**
+ * Returns the duration in seconds of the given sample count per frame and channel
+ * according to the {@link #sampleRate}, i.e.
+ * <pre>
+ * (float)sampleCount / sampleRate
+ * </pre>
+ * <p>
+ * Sample Count -> Time
+ * </p>
+ * @param sampleCount sample count per frame and channel
+ */
+ public final float getSamplesDuration(final int sampleCount) {
+ return (float)sampleCount / sampleRate;
+ }
+
+ /**
+ * Returns the rounded frame count of the given duration and frame duration, both in seconds.
+ * <pre>
+ * Math.max(1, Math.round( duration / frameDuration ))
+ * </pre>
+ * <p>
+ * Note: <code>frameDuration</code> can be derived by <i>sample count per frame and channel</i>
+ * via {@link #getSamplesDuration(int)} or by <i>byte count</i> via {@link #getBytesDuration(int)}.
+ * </p>
+ * <p>
+ * Frame Time -> Frame Count
+ * </p>
+ * @param duration duration in seconds
+ * @param frameDuration duration per frame in seconds, i.e. 1/frame_rate
+ * @see #getSamplesDuration(int)
+ * @see #getBytesDuration(int)
+ */
+ public final int getFrameCount(final float duration, final float frameDuration) {
+ return Math.max(1, Math.round( duration / frameDuration ));
+ }
+
+ /**
+ * Returns the byte size of given sample count
+ * according to the {@link #sampleSize}, i.e.:
+ * <pre>
+ * sampleCount * ( sampleSize / 8 )
+ * </pre>
+ * <p>
+ * Note: To retrieve the byte size for all channels,
+ * you need to pre-multiply <code>sampleCount</code> with {@link #channelCount}.
+ * </p>
+ * <p>
+ * Sample Count -> Byte Count
+ * </p>
+ * @param sampleCount sample count
+ */
+ public final int getSamplesByteCount(final int sampleCount) {
+ return sampleCount * ( sampleSize >>> 3 );
+ }
+
+ /**
+ * Returns the sample count of given byte count
+ * according to the {@link #sampleSize}, i.e.:
+ * <pre>
+ * ( byteCount * 8 ) / sampleSize
+ * </pre>
+ * <p>
+ * Note: If <code>byteCount</code> covers all channels and you request the sample size per channel,
+ * you need to divide the result by <code>sampleCount</code> by {@link #channelCount}.
+ * </p>
+ * <p>
+ * Byte Count -> Sample Count
+ * </p>
+ * @param byteCount number of bytes
+ */
+ public final int getBytesSampleCount(final int byteCount) {
+ return ( byteCount << 3 ) / sampleSize;
+ }
+
+ @Override
+ public String toString() {
+ return "AudioFormat[sampleRate "+sampleRate+", sampleSize "+sampleSize+", channelCount "+channelCount+
+ ", signed "+signed+", fixedP "+fixedP+", "+(planar?"planar":"packed")+", "+(littleEndian?"little":"big")+"-endian]"; }
+} \ No newline at end of file
diff --git a/src/java/com/jogamp/common/av/AudioSink.java b/src/java/com/jogamp/common/av/AudioSink.java
new file mode 100644
index 0000000..ac6441a
--- /dev/null
+++ b/src/java/com/jogamp/common/av/AudioSink.java
@@ -0,0 +1,444 @@
+/**
+ * Copyright 2013-2023 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.common.av;
+
+import java.nio.ByteBuffer;
+
+import jogamp.common.Debug;
+
+public interface AudioSink {
+ public static final boolean DEBUG = Debug.debug("AudioSink");
+
+ /** Default frame duration in millisecond, i.e. 1 {@link AudioFrame} per {@value} ms. */
+ public static final int DefaultFrameDuration = 32;
+
+ /** Initial audio queue size in milliseconds. {@value} ms, i.e. 16 {@link AudioFrame}s per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ public static final int DefaultInitialQueueSize = 16 * 32; // 512 ms
+ /** Audio queue grow size in milliseconds. {@value} ms, i.e. 16 {@link AudioFrame}s per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ public static final int DefaultQueueGrowAmount = 16 * 32; // 512 ms
+ /** Audio queue limit w/ video in milliseconds. {@value} ms, i.e. 96 {@link AudioFrame}s per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ public static final int DefaultQueueLimitWithVideo = 96 * 32; // 3072 ms
+ /** Audio queue limit w/o video in milliseconds. {@value} ms, i.e. 32 {@link AudioFrame}s per 32 ms. See {@link #init(AudioFormat, float, int, int, int)}.*/
+ public static final int DefaultQueueLimitAudioOnly = 32 * 32; // 1024 ms
+
+ /** Default {@link AudioFormat}, [type PCM, sampleRate 44100, sampleSize 16, channelCount 2, signed, fixedP, !planar, littleEndian]. */
+ public static final AudioFormat DefaultFormat = new AudioFormat(44100, 16, 2, true /* signed */,
+ true /* fixed point */, false /* planar */, true /* littleEndian */);
+
+ /**
+ * Abstract audio frame containing multiple audio samples per channel, tracking {@link TimeFrameI} pts and size in bytes.
+ * <p>
+ * One {@link AudioFrame} may contain multiple pairs of samples per channel,
+ * i.e. this {@link AudioFrame} does not limit a frame to be one sample per channel.
+ * See its application in {@link AudioSink#enqueueData(int, ByteBuffer, int)}.
+ * </p>
+ * <p>
+ * Implementations may assign actual data to queue frames from streaming, see {@link AudioDataFrame}.
+ * </p>
+ * @see AudioSink#enqueueData(int, ByteBuffer, int)
+ */
+ public static abstract class AudioFrame extends TimeFrameI {
+ protected int byteSize;
+
+ /**
+ * Ctor w/ zero duration, {@link #INVALID_PTS} and zero byte size
+ */
+ public AudioFrame() {
+ this.byteSize = 0;
+ }
+ /**
+ * Create a new instance
+ * @param pts frame pts in milliseconds
+ * @param duration frame duration in milliseconds
+ * @param byteCount size in bytes
+ */
+ public AudioFrame(final int pts, final int duration, final int byteCount) {
+ super(pts, duration);
+ this.byteSize=byteCount;
+ }
+
+ /** Get this frame's size in bytes. */
+ public final int getByteSize() { return byteSize; }
+ /** Set this frame's size in bytes. */
+ public final void setByteSize(final int size) { this.byteSize=size; }
+
+ @Override
+ public String toString() {
+ return "AudioFrame[pts " + pts + " ms, l " + duration + " ms, "+byteSize + " bytes]";
+ }
+ }
+ /**
+ * Audio data frame example of {@link AudioFrame} with actual audio data being attached.
+ */
+ public static class AudioDataFrame extends AudioFrame {
+ protected final ByteBuffer data;
+
+ /**
+ * Create a new instance
+ * @param pts frame pts in milliseconds
+ * @param duration frame duration in milliseconds
+ * @param bytes audio data
+ * @param byteCount size in bytes
+ */
+ public AudioDataFrame(final int pts, final int duration, final ByteBuffer bytes, final int byteCount) {
+ super(pts, duration, byteCount);
+ if( byteCount > bytes.remaining() ) {
+ throw new IllegalArgumentException("Give size "+byteCount+" exceeds remaining bytes in ls "+bytes+". "+this);
+ }
+ this.data=bytes;
+ }
+
+ /** Get this frame's data. */
+ public final ByteBuffer getData() { return data; }
+
+ @Override
+ public String toString() {
+ return "AudioDataFrame[pts " + pts + " ms, l " + duration + " ms, "+byteSize + " bytes, " + data + "]";
+ }
+ }
+
+ /**
+ * Makes the audio context current on the calling thread, if implementation utilizes context locking.
+ * <p>
+ * If implementation doesn't utilizes context locking, method always returns true.
+ * </p>
+ * <p>
+ * Recursive call to {@link #makeCurrent()} and hence {@link #release()} are supported.
+ * </p>
+ * <p>
+ * At any point in time one context can only be current by one thread,
+ * and one thread can only have one context current.
+ * </p>
+ * @param throwException if true, throws ALException if context is null, current thread holds another context or failed to natively make current
+ * @return true if current thread holds no other context and context successfully made current, otherwise false
+ * @see #release()
+ */
+ public boolean makeCurrent(final boolean throwException);
+
+ /**
+ * Releases control of this audio context from the current thread, if implementation utilizes context locking.
+ * <p>
+ * If implementation doesn't utilizes context locking, method always returns true.
+ * </p>
+ * <p>
+ * Recursive call to {@link #makeCurrent()} and hence {@link #release()} are supported.
+ * </p>
+ * @param throwException if true, throws ALException if context has not been previously made current on current thread
+ * or native release failed.
+ * @return true if context has previously been made current on the current thread and successfully released, otherwise false
+ * @see #makeCurrent()
+ */
+ public boolean release(final boolean throwException);
+
+ /**
+ * Returns the <code>available state</code> of this instance.
+ * <p>
+ * The <code>available state</code> is affected by this instance
+ * overall availability, i.e. after instantiation,
+ * as well as by {@link #destroy()}.
+ * </p>
+ */
+ public boolean isAvailable();
+
+ /** Returns the playback speed. */
+ public float getPlaySpeed();
+
+ /**
+ * Sets the playback speed.
+ * <p>
+ * To simplify test, play speed is <i>normalized</i>, i.e.
+ * <ul>
+ * <li><code>1.0f</code>: if <code> Math.abs(1.0f - rate) < 0.01f </code></li>
+ * </ul>
+ * </p>
+ * @return true if successful, otherwise false, i.e. due to unsupported value range of implementation.
+ */
+ public boolean setPlaySpeed(float s);
+
+ /** Returns the volume. */
+ public float getVolume();
+
+ /**
+ * Sets the volume [0f..1f].
+ * <p>
+ * To simplify test, volume is <i>normalized</i>, i.e.
+ * <ul>
+ * <li><code>0.0f</code>: if <code> Math.abs(v) < 0.01f </code></li>
+ * <li><code>1.0f</code>: if <code> Math.abs(1.0f - v) < 0.01f </code></li>
+ * </ul>
+ * </p>
+ * @return true if successful, otherwise false, i.e. due to unsupported value range of implementation.
+ */
+ public boolean setVolume(float v);
+
+ /**
+ * Returns the number of sources the used device is capable to mix.
+ * <p>
+ * This device attribute is only formally exposed and not used,
+ * since an audio sink is only utilizing one source.
+ * </p>
+ * <p>
+ * May return <code>-1</code> if undefined.
+ * </p>
+ * @return
+ */
+ public int getSourceCount();
+
+ /**
+ * Returns the default (minimum) latency in seconds
+ * <p>
+ * Latency might be the reciprocal mixer-refresh-interval [Hz], e.g. 50 Hz refresh-rate = 20ms minimum latency.
+ * </p>
+ * <p>
+ * May return 20ms for a 50 Hz refresh rate if undefined.
+ * </p>
+ */
+ public float getDefaultLatency();
+
+ /**
+ * Returns the native {@link AudioFormat} by this sink.
+ * <p>
+ * The native format is guaranteed to be supported
+ * and shall reflect this sinks most native format,
+ * i.e. best performance w/o data conversion.
+ * </p>
+ * <p>
+ * The native format is not impacted by {@link #setChannelLimit(int)}.
+ * </p>
+ * <p>
+ * May return {@link AudioSink#DefaultFormat} if undefined.
+ * </p>
+ * @see #init(AudioFormat, float, int, int, int)
+ */
+ public AudioFormat getNativeFormat();
+
+ /**
+ * Returns the preferred {@link AudioFormat} by this sink.
+ * <p>
+ * The preferred format is a subset of {@link #getNativeFormat()},
+ * impacted by {@link #setChannelLimit(int)}.
+ * </p>
+ * <p>
+ * Known {@link #AudioFormat} attributes considered by implementations:
+ * <ul>
+ * <li>ALAudioSink: {@link AudioFormat#sampleRate}.
+ * <li>ALAudioSink: {@link AudioFormat#channelCount}
+ * </ul>
+ * </p>
+ * @see #getNativeFormat()
+ * @see #init(AudioFormat, float, int, int, int)
+ * @see #setChannelLimit(int)
+ * @see #isSupported(AudioFormat)
+ */
+ public AudioFormat getPreferredFormat();
+
+ /**
+ * Limit maximum supported audio channels by user.
+ * <p>
+ * Must be set before {@link #getPreferredFormat()}, {@link #isSupported(AudioFormat)} and naturally {@link #init(AudioFormat, int, int, int, int)}.
+ * </p>
+ * <p>
+ * May be utilized to enforce 1 channel (mono) downsampling
+ * in combination with JOAL/OpenAL to experience spatial 3D position effects.
+ * </p>
+ * @param cc maximum supported audio channels, will be clipped [1..{@link #getNativeFormat()}.{@link AudioFormat#channelCount channelCount}]
+ * @see #getNativeFormat()
+ * @see #getPreferredFormat()
+ * @see #isSupported(AudioFormat)
+ * @see #init(AudioFormat, int, int, int, int)
+ */
+ public void setChannelLimit(final int cc);
+
+ /**
+ * Returns true if the given format is supported by the sink, otherwise false.
+ * <p>
+ * The {@link #getPreferredFormat()} is used to validate compatibility with the given format.
+ * </p>
+ * @see #init(AudioFormat, float, int, int, int)
+ * @see #getPreferredFormat()
+ */
+ public boolean isSupported(AudioFormat format);
+
+ /**
+ * Initializes the sink.
+ * <p>
+ * Implementation must match the given <code>requestedFormat</code> {@link AudioFormat}.
+ * </p>
+ * <p>
+ * Caller shall validate <code>requestedFormat</code> via {@link #isSupported(AudioFormat)}
+ * beforehand and try to find a suitable supported one.
+ * {@link #getPreferredFormat()} may help.
+ * </p>
+ * @param requestedFormat the requested {@link AudioFormat}.
+ * @param frameDurationHint average {@link AudioFrame} duration hint in milliseconds.
+ * May assist to shape the {@link AudioFrame} initial queue size using `initialQueueSize`.
+ * May assist to adjust latency of the backend, as currently used for JOAL's ALAudioSink.
+ * A value below 30ms or {@link #DefaultFrameDuration} may increase the audio processing load.
+ * Assumed as {@link #DefaultFrameDuration}, if <code>frameDuration < 1 ms</code>.
+ * @param initialQueueSize initial queue size in milliseconds, see {@link #DefaultInitialQueueSize}.
+ * May use `frameDurationHint` to determine initial {@link AudioFrame} queue size.
+ * @param queueGrowAmount queue grow size in milliseconds if queue is full, see {@link #DefaultQueueGrowAmount}.
+ * May use {@link #getAvgFrameDuration()} to determine {@link AudioFrame} queue growth amount.
+ * @param queueLimit maximum time in milliseconds the queue can hold (and grow), see {@link #DefaultQueueLimitWithVideo} and {@link #DefaultQueueLimitAudioOnly}.
+ * May use {@link #getAvgFrameDuration()} to determine {@link AudioFrame} queue limit.
+ * @return true if successful, otherwise false
+ * @see #enqueueData(int, ByteBuffer, int)
+ * @see #getAvgFrameDuration()
+ */
+ public boolean init(AudioFormat requestedFormat, int frameDurationHint,
+ int initialQueueSize, int queueGrowAmount, int queueLimit);
+
+ /**
+ * Returns the {@link AudioFormat} as chosen by {@link #init(AudioFormat, float, int, int, int)},
+ * i.e. it shall match the <i>requestedFormat</i>.
+ */
+ public AudioFormat getChosenFormat();
+
+ /**
+ * Returns the (minimum) latency in seconds of this sink as set by {@link #init(AudioFormat, float, int, int, int)}, see {@link #getDefaultLatency()}.
+ * <p>
+ * Latency might be the reciprocal mixer-refresh-interval [Hz], e.g. 50 Hz refresh-rate = 20ms minimum latency.
+ * </p>
+ * @see #init(AudioFormat, float, int, int, int)
+ */
+ public float getLatency();
+
+ /**
+ * Returns true, if {@link #play()} has been requested <i>and</i> the sink is still playing,
+ * otherwise false.
+ */
+ public boolean isPlaying();
+
+ /**
+ * Play buffers queued via {@link #enqueueData(AudioFrame)} from current internal position.
+ * If no buffers are yet queued or the queue runs empty, playback is being continued when buffers are enqueued later on.
+ * @see #enqueueData(AudioFrame)
+ * @see #pause()
+ */
+ public void play();
+
+ /**
+ * Pause playing buffers while keeping enqueued data incl. it's internal position.
+ * @see #play()
+ * @see #flush()
+ * @see #enqueueData(AudioFrame)
+ */
+ public void pause();
+
+ /**
+ * Flush all queued buffers, implies {@link #pause()}.
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ * @see #play()
+ * @see #pause()
+ * @see #enqueueData(AudioFrame)
+ * @see #init(AudioFormat, float, int, int, int)
+ */
+ public void flush();
+
+ /** Destroys this instance, i.e. closes all streams and devices allocated. */
+ public void destroy();
+
+ /**
+ * Returns the number of allocated buffers as requested by
+ * {@link #init(AudioFormat, float, int, int, int)}.
+ * @see #init(AudioFormat, float, int, int, int)
+ */
+ public int getFrameCount();
+
+ /**
+ * Returns the current enqueued frames count since {@link #init(AudioFormat, float, int, int, int)}.
+ * @see #init(AudioFormat, float, int, int, int)
+ */
+ public int getEnqueuedFrameCount();
+
+ /**
+ * Returns the current number of frames queued for playing.
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ * @see #init(AudioFormat, float, int, int, int)
+ */
+ public int getQueuedFrameCount();
+
+ /**
+ * Returns the current number of bytes queued for playing.
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ * @see #init(AudioFormat, float, int, int, int)
+ */
+ public int getQueuedByteCount();
+
+ /**
+ * Returns the current queued frame time in seconds for playing.
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ * @see #init(AudioFormat, float, int, int, int)
+ */
+ public float getQueuedTime();
+
+ /**
+ * Returns average frame duration last assessed @ {@link #enqueueData(int, ByteBuffer, int)} when queue was full.
+ * <pre>
+ * avgFrameDuration = {@link #getQueuedTime()} / {@link #getQueuedFrameCount()}
+ * </pre>
+ */
+ public float getAvgFrameDuration();
+
+ /**
+ * Return the current audio presentation timestamp (PTS) in milliseconds.
+ */
+ public int getPTS();
+
+ /**
+ * Returns the current number of frames in the sink available for writing.
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ * @see #init(AudioFormat, float, int, int, int)
+ */
+ public int getFreeFrameCount();
+
+ /**
+ * Enqueue <code>byteCount</code> bytes as a new {@link AudioFrame} to this sink.
+ * <p>
+ * The data must comply with the chosen {@link AudioFormat} as set via {@link #init(AudioFormat, float, int, int, int)}.
+ * </p>
+ * <p>
+ * {@link #init(AudioFormat, float, int, int, int)} must be called first.
+ * </p>
+ * @param pts presentation time stamp in milliseconds for the newly enqueued {@link AudioFrame}
+ * @param bytes audio data for the newly enqueued {@link AudioFrame}
+ * @returns the enqueued internal {@link AudioFrame}.
+ * @see #init(AudioFormat, float, int, int, int)
+ */
+ public AudioFrame enqueueData(int pts, ByteBuffer bytes, int byteCount);
+}
diff --git a/src/java/com/jogamp/common/av/AudioSinkFactory.java b/src/java/com/jogamp/common/av/AudioSinkFactory.java
new file mode 100644
index 0000000..f4a320b
--- /dev/null
+++ b/src/java/com/jogamp/common/av/AudioSinkFactory.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2013-2023 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.common.av;
+
+import com.jogamp.common.util.ReflectionUtil;
+
+import jogamp.common.av.NullAudioSink;
+
+public class AudioSinkFactory {
+ private static final String ALAudioSinkClazzName = "com.jogamp.openal.util.ALAudioSink";
+ private static final String JavaAudioSinkClazzName = "jogamp.common.av.JavaSoundAudioSink";
+
+ public static AudioSink createDefault(final ClassLoader cl) {
+ AudioSink sink = create(cl, ALAudioSinkClazzName);
+ if( null == sink ) {
+ sink = create(cl, JavaAudioSinkClazzName);
+ }
+ if( null == sink ) {
+ sink = createNull();
+ }
+ return sink;
+ }
+ public static AudioSink createNull() {
+ return new NullAudioSink();
+ }
+
+ public static AudioSink create(final ClassLoader cl, final String implName) {
+ final AudioSink audioSink;
+ if(ReflectionUtil.isClassAvailable(implName, cl)){
+ try {
+ audioSink = (AudioSink) ReflectionUtil.createInstance(implName, cl);
+ if( audioSink.isAvailable() ) {
+ return audioSink;
+ } else if(AudioSink.DEBUG) {
+ System.err.println("AudioSinkFactory: Couldn't instantiate AudioSink '"+implName+"'");
+ }
+ } catch (final Throwable t) {
+ if(AudioSink.DEBUG) { System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage()); t.printStackTrace(); }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/src/java/com/jogamp/common/av/TimeFrameI.java b/src/java/com/jogamp/common/av/TimeFrameI.java
new file mode 100644
index 0000000..400618f
--- /dev/null
+++ b/src/java/com/jogamp/common/av/TimeFrameI.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2013-2023 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.common.av;
+
+/**
+ * Integer time frame in milliseconds, maybe specialized for texture/video, audio, .. animated content.
+ * <p>
+ * Type and value range has been chosen to suit embedded CPUs
+ * and characteristics of audio / video streaming and animations.
+ * Milliseconds of type integer with a maximum value of {@link Integer#MAX_VALUE}
+ * will allow tracking time up 2,147,483.647 seconds or
+ * 24 days 20 hours 31 minutes and 23 seconds.
+ * </p>
+ * <p>
+ * Milliseconds granularity is also more than enough to deal with A-V synchronization,
+ * where the threshold usually lies within 22ms.
+ * </p>
+ * <p>
+ * Milliseconds granularity for displaying video frames might seem inaccurate
+ * for each single frame, i.e. 60Hz != 16ms, however, accumulated values diminish
+ * this error and vertical sync is achieved by build-in V-Sync of the video drivers.
+ * </p>
+ */
+public class TimeFrameI {
+ /** Constant marking an invalid PTS, i.e. Integer.MIN_VALUE == 0x80000000 == {@value}. Sync w/ native code. */
+ public static final int INVALID_PTS = 0x80000000;
+
+ /** Constant marking the end of the stream PTS, i.e. Integer.MIN_VALUE - 1 == 0x7FFFFFFF == {@value}. Sync w/ native code. */
+ public static final int END_OF_STREAM_PTS = 0x7FFFFFFF;
+
+ protected int pts;
+ protected int duration;
+
+ /**
+ * Ctor w/ zero duration and {@link #INVALID_PTS}.
+ */
+ public TimeFrameI() {
+ pts = INVALID_PTS;
+ duration = 0;
+ }
+ /**
+ * Create a new instance
+ * @param pts frame pts in milliseconds
+ * @param duration frame duration in milliseconds
+ */
+ public TimeFrameI(final int pts, final int duration) {
+ this.pts = pts;
+ this.duration = duration;
+ }
+
+ /** Get this frame's presentation timestamp (PTS) in milliseconds. */
+ public final int getPTS() { return pts; }
+ /** Set this frame's presentation timestamp (PTS) in milliseconds. */
+ public final void setPTS(final int pts) { this.pts = pts; }
+ /** Get this frame's duration in milliseconds. */
+ public final int getDuration() { return duration; }
+ /** Set this frame's duration in milliseconds. */
+ public final void setDuration(final int duration) { this.duration = duration; }
+
+ @Override
+ public String toString() {
+ return "TimeFrame[pts " + pts + " ms, l " + duration + " ms]";
+ }
+}
diff --git a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
index eee65d8..cccea1a 100644
--- a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
+++ b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
@@ -44,7 +44,6 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.HashSet;
@@ -56,6 +55,7 @@ import com.jogamp.common.net.Uri;
import com.jogamp.common.os.NativeLibrary;
import com.jogamp.common.util.JarUtil;
import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.SecurityUtil;
import com.jogamp.common.util.cache.TempJarCache;
import jogamp.common.Debug;
@@ -512,7 +512,7 @@ public class JNILibLoaderBase {
final String sunAppletLauncherProperty = "sun.jnlp.applet.launcher";
final String sunAppletLauncherClassName = "org.jdesktop.applet.util.JNLPAppletLauncher";
- final Method loadLibraryMethod = AccessController.doPrivileged(new PrivilegedAction<Method>() {
+ final Method loadLibraryMethod = SecurityUtil.doPrivileged(new PrivilegedAction<Method>() {
@Override
public Method run() {
// FIXME: remove
@@ -605,14 +605,14 @@ public class JNILibLoaderBase {
mode = 2;
} else {
if(DEBUG) {
- System.err.println("JNILibLoaderBase: System.loadLibrary("+libraryName+") - mode 3");
+ System.err.println("JNILibLoaderBase: System.loadLibrary("+libraryName+") - mode 3: SystemEnvLibraryPaths: "+NativeLibrary.getSystemEnvLibraryPaths());
}
try {
System.loadLibrary(libraryName);
mode = 3;
} catch (final UnsatisfiedLinkError ex1) {
if(DEBUG) {
- System.err.println("ERROR (retry w/ enumLibPath) - "+ex1.getMessage());
+ System.err.println("ERROR mode 3 - "+ex1.getMessage());
}
final List<String> possiblePaths = NativeLibrary.enumerateLibraryPaths(libraryName, libraryName, libraryName, cl);
// Iterate down these and see which one if any we can actually find.
@@ -629,7 +629,10 @@ public class JNILibLoaderBase {
System.err.println("n/a - "+ex2.getMessage());
}
if(!iter.hasNext()) {
- throw ex2;
+ // Avoid misleading final exception, use our own
+ throw new UnsatisfiedLinkError("Couldn't load library '"+libraryName+
+ "' generically including "+NativeLibrary.getSystemEnvLibraryPaths()+ // mode 3
+ ", nor as "+possiblePaths); // mode 4
}
}
}
diff --git a/src/java/com/jogamp/common/net/GenericURLStreamHandlerFactory.java b/src/java/com/jogamp/common/net/GenericURLStreamHandlerFactory.java
index 185142f..9b39657 100644
--- a/src/java/com/jogamp/common/net/GenericURLStreamHandlerFactory.java
+++ b/src/java/com/jogamp/common/net/GenericURLStreamHandlerFactory.java
@@ -3,11 +3,12 @@ package com.jogamp.common.net;
import java.net.URL;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
+import com.jogamp.common.util.SecurityUtil;
+
public class GenericURLStreamHandlerFactory implements URLStreamHandlerFactory {
private static GenericURLStreamHandlerFactory factory = null;
@@ -48,7 +49,7 @@ public class GenericURLStreamHandlerFactory implements URLStreamHandlerFactory {
*/
public synchronized static GenericURLStreamHandlerFactory register() {
if(null == factory) {
- factory = AccessController.doPrivileged(new PrivilegedAction<GenericURLStreamHandlerFactory>() {
+ factory = SecurityUtil.doPrivileged(new PrivilegedAction<GenericURLStreamHandlerFactory>() {
@Override
public GenericURLStreamHandlerFactory run() {
boolean ok = false;
diff --git a/src/java/com/jogamp/common/nio/Buffers.java b/src/java/com/jogamp/common/nio/Buffers.java
index 875163e..f37eaa9 100644
--- a/src/java/com/jogamp/common/nio/Buffers.java
+++ b/src/java/com/jogamp/common/nio/Buffers.java
@@ -50,11 +50,11 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.common.util.SecurityUtil;
import com.jogamp.common.util.UnsafeUtil;
import com.jogamp.common.util.ValueConv;
@@ -818,6 +818,156 @@ public class Buffers {
}
@SuppressWarnings("unchecked")
+ public static <B extends Buffer> B put3b(final B dest, final byte v1, final byte v2, final byte v3) {
+ if (dest instanceof ByteBuffer) {
+ final ByteBuffer b = (ByteBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof ShortBuffer) {
+ final ShortBuffer b = (ShortBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof IntBuffer) {
+ final IntBuffer b = (IntBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof LongBuffer) {
+ final LongBuffer b = (LongBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof CharBuffer) {
+ final CharBuffer b = (CharBuffer) dest;
+ b.put((char)v1);
+ b.put((char)v2);
+ b.put((char)v3);
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Byte doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B put4b(final B dest, final byte v1, final byte v2, final byte v3, final byte v4) {
+ if (dest instanceof ByteBuffer) {
+ final ByteBuffer b = (ByteBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof ShortBuffer) {
+ final ShortBuffer b = (ShortBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof IntBuffer) {
+ final IntBuffer b = (IntBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof LongBuffer) {
+ final LongBuffer b = (LongBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof CharBuffer) {
+ final CharBuffer b = (CharBuffer) dest;
+ b.put((char)v1);
+ b.put((char)v2);
+ b.put((char)v3);
+ b.put((char)v4);
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Byte doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B putb(final B dest, final byte[] src, final int offset, final int length) {
+ if (dest instanceof ByteBuffer) {
+ return (B) ((ByteBuffer) dest).put(src, offset, length);
+ } else if (dest instanceof ShortBuffer) {
+ final ShortBuffer b = (ShortBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else if (dest instanceof IntBuffer) {
+ final IntBuffer b = (IntBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else if (dest instanceof LongBuffer) {
+ final LongBuffer b = (LongBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else if (dest instanceof CharBuffer) {
+ final CharBuffer b = (CharBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put((char) src[offset+i]);
+ }
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Byte doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
public static <B extends Buffer> B puts(final B dest, final short v) {
if (dest instanceof ShortBuffer) {
return (B) ((ShortBuffer) dest).put(v);
@@ -835,6 +985,118 @@ public class Buffers {
}
@SuppressWarnings("unchecked")
+ public static <B extends Buffer> B put3s(final B dest, final short v1, final short v2, final short v3) {
+ if (dest instanceof ShortBuffer) {
+ final ShortBuffer b = (ShortBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof IntBuffer) {
+ final IntBuffer b = (IntBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof LongBuffer) {
+ final LongBuffer b = (LongBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Short doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B put4s(final B dest, final short v1, final short v2, final short v3, final short v4) {
+ if (dest instanceof ShortBuffer) {
+ final ShortBuffer b = (ShortBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof IntBuffer) {
+ final IntBuffer b = (IntBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof LongBuffer) {
+ final LongBuffer b = (LongBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Short doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B puts(final B dest, final short[] src, final int offset, final int length) {
+ if (dest instanceof ShortBuffer) {
+ return (B) ((ShortBuffer) dest).put(src, offset, length);
+ } else if (dest instanceof IntBuffer) {
+ final IntBuffer b = (IntBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else if (dest instanceof LongBuffer) {
+ final LongBuffer b = (LongBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Short doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
public static <B extends Buffer> B puti(final B dest, final int v) {
if (dest instanceof IntBuffer) {
return (B) ((IntBuffer) dest).put(v);
@@ -850,6 +1112,99 @@ public class Buffers {
}
@SuppressWarnings("unchecked")
+ public static <B extends Buffer> B put3i(final B dest, final int v1, final int v2, final int v3) {
+ if (dest instanceof IntBuffer) {
+ final IntBuffer b = (IntBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof LongBuffer) {
+ final LongBuffer b = (LongBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Integer doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B put4i(final B dest, final int v1, final int v2, final int v3, final int v4) {
+ if (dest instanceof IntBuffer) {
+ final IntBuffer b = (IntBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof LongBuffer) {
+ final LongBuffer b = (LongBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Integer doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B puti(final B dest, final int[] src, final int offset, final int length) {
+ if (dest instanceof IntBuffer) {
+ return (B) ((IntBuffer) dest).put(src, offset, length);
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else if (dest instanceof LongBuffer) {
+ final LongBuffer b = (LongBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Integer doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
public static <B extends Buffer> B putf(final B dest, final float v) {
if (dest instanceof FloatBuffer) {
return (B) ((FloatBuffer) dest).put(v);
@@ -865,14 +1220,126 @@ public class Buffers {
}
@SuppressWarnings("unchecked")
- public static <B extends Buffer> B putd(final B dest, final double v) {
+ public static <B extends Buffer> B put3f(final B dest, final float v1, final float v2, final float v3) {
+ if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Float doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B put4f(final B dest, final float v1, final float v2, final float v3, final float v4) {
if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Float doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B putf(final B dest, final float[] src, final int offset, final int length) {
+ if (dest instanceof FloatBuffer) {
+ return (B) ((FloatBuffer) dest).put(src, offset, length);
+ } else if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put(src[offset+i]);
+ }
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Float doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B putd(final B dest, final double v) {
+ if (dest instanceof DoubleBuffer) {
+ return (B) ((DoubleBuffer) dest).put(v);
+ } else if (dest instanceof FloatBuffer) {
return (B) ((FloatBuffer) dest).put((float) v);
} else {
throw new IllegalArgumentException("Double doesn't match Buffer Class: " + dest);
}
}
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B put3d(final B dest, final double v1, final double v2, final double v3) {
+ if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ return (B)b;
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ b.put((float) v1);
+ b.put((float) v2);
+ b.put((float) v3);
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Double doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B put4d(final B dest, final double v1, final double v2, final double v3, final double v4) {
+ if (dest instanceof DoubleBuffer) {
+ final DoubleBuffer b = (DoubleBuffer) dest;
+ b.put(v1);
+ b.put(v2);
+ b.put(v3);
+ b.put(v4);
+ return (B)b;
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ b.put((float) v1);
+ b.put((float) v2);
+ b.put((float) v3);
+ b.put((float) v4);
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Double doesn't match Buffer Class: " + dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <B extends Buffer> B putd(final B dest, final double[] src, final int offset, final int length) {
+ if (dest instanceof DoubleBuffer) {
+ return (B) ((DoubleBuffer) dest).put(src, offset, length);
+ } else if (dest instanceof FloatBuffer) {
+ final FloatBuffer b = (FloatBuffer) dest;
+ for(int i=0; i<length; ++i) {
+ b.put((float) src[offset+i]);
+ }
+ return (B)b;
+ } else {
+ throw new IllegalArgumentException("Float doesn't match Buffer Class: " + dest);
+ }
+ }
+
//----------------------------------------------------------------------
// Convenient put methods with generic target Buffer and value range conversion, i.e. normalization
//
@@ -1177,7 +1644,7 @@ public class Buffers {
final Method[] _mbbCleaner = { null };
final Method[] _cClean = { null };
final boolean hasCleaner;
- if( AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ if( SecurityUtil.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
try {
diff --git a/src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java b/src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java
index 6a56d6e..f0bf321 100644
--- a/src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java
+++ b/src/java/com/jogamp/common/nio/MappedByteBufferInputStream.java
@@ -38,9 +38,10 @@ import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
-import jogamp.common.Debug;
+import com.jogamp.common.os.Platform.OSType;
-import com.jogamp.common.os.Platform;
+import jogamp.common.Debug;
+import jogamp.common.os.PlatformPropsImpl;
/**
* An {@link InputStream} implementation based on an underlying {@link FileChannel}'s memory mapped {@link ByteBuffer},
@@ -136,8 +137,7 @@ public class MappedByteBufferInputStream extends InputStream {
static final boolean DEBUG;
static {
- Platform.initSingleton();
- if( Platform.is32Bit() ) {
+ if( PlatformPropsImpl.CPU_ARCH.is32Bit ) {
DEFAULT_SLICE_SHIFT = 29;
} else {
DEFAULT_SLICE_SHIFT = 30;
@@ -366,7 +366,7 @@ public class MappedByteBufferInputStream extends InputStream {
currentPosition = -1L;
}
if( fc.size() != newTotalSize ) {
- if( Platform.OSType.WINDOWS == Platform.getOSType() ) {
+ if( OSType.WINDOWS == PlatformPropsImpl.OS_TYPE ) {
// On Windows, we have to close all mapped slices.
// Otherwise we will receive:
// java.io.IOException: The requested operation cannot be performed on a file with a user-mapped section open
diff --git a/src/java/com/jogamp/common/os/Clock.java b/src/java/com/jogamp/common/os/Clock.java
new file mode 100644
index 0000000..9380442
--- /dev/null
+++ b/src/java/com/jogamp/common/os/Clock.java
@@ -0,0 +1,165 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020-2023 Gothel Software e.K.
+ * Copyright (c) 2020-2023 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package com.jogamp.common.os;
+
+import java.time.Instant;
+
+public class Clock {
+ private static final Instant t0;
+ static {
+ Platform.initSingleton(); // loads native gluegen_rt library
+ {
+ final long[/*2*/] val = { 0, 0 };
+ if( getMonotonicStartupTimeImpl(val) ) {
+ t0 = Instant.ofEpochSecond(val[0], val[1]);
+ } else {
+ t0 = Instant.EPOCH;
+ }
+ }
+ }
+
+ /**
+ * Returns current monotonic time since Unix Epoch `00:00:00 UTC on 1970-01-01`.
+ * <p>
+ * Returned timespec is passing machine precision and range of the underlying native API.
+ * </p>
+ * <p>
+ * Monotonic time shall be used for high-performance measurements of durations,
+ * since the underlying OS shall support fast calls.
+ * </p>
+ * <p>
+ * Note that {@link #currentNanos()} and {@link #getMonotonicNanos()}
+ * perform much better than this method, since they only return one long nanosecond value
+ * since module startup. <br/>
+ * The implementation of this method needs to write two long values into an array.
+ * </p>
+ * @see #getMonotonicStartupTime()
+ * @see #currentNanos()
+ * @see #getMonotonicNanos()
+ * @see #getWallClockTime()
+ */
+ public static Instant getMonotonicTime() {
+ final long[/*2*/] val = { 0, 0 };
+ if( getMonotonicTimeImpl(val) ) {
+ return Instant.ofEpochSecond(val[0], val[1]);
+ } else {
+ return Instant.EPOCH;
+ }
+ }
+ private static native boolean getMonotonicTimeImpl(final long[/*2*/] val);
+
+ /**
+ * Returns current wall-clock real-time since Unix Epoch `00:00:00 UTC on 1970-01-01`.
+ * <p>
+ * Returned Instant is passing machine precision and range of the underlying native API.
+ * </p>
+ * <p>
+ * Wall-Clock time shall be used for accurate measurements of the actual time only,
+ * since the underlying OS unlikely supports fast calls.
+ * </p>
+ * @see #getMonotonicStartupTime()
+ * @see #currentNanos()
+ * @see #getMonotonicNanos()
+ * @see #getMonotonicTime()
+ */
+ public static Instant getWallClockTime() {
+ final long[/*2*/] val = { 0, 0 };
+ if( getWallClockTimeImpl(val) ) {
+ return Instant.ofEpochSecond(val[0], val[1]);
+ } else {
+ return Instant.EPOCH;
+ }
+ }
+ private static native boolean getWallClockTimeImpl(final long[/*2*/] val);
+
+ /**
+ * Returns the monotonic startup time since module startup as used in {@link #currentNanos()} and {@link #getMonotonicNanos()}.
+ * @see #currentNanos()
+ * @see #getMonotonicNanos()
+ */
+ public static Instant getMonotonicStartupTime() { return t0; }
+ private static native boolean getMonotonicStartupTimeImpl(final long[/*2*/] val);
+
+ /**
+ * Returns current monotonic nanoseconds since start of this application.
+ * <p>
+ * Monotonic time shall be used for high-performance measurements of durations,
+ * since the underlying OS shall support fast calls.
+ * </p>
+ * <p>
+ * The returned nanoseconds are counted not from Unix Epoch but start of this module,
+ * hence it lasts for 9'223'372'036 seconds or 292 years using the 64-bit type `long`.
+ * </p>
+ * <p>
+ * Method name doesn't include the term `Time` intentionally,
+ * since the returned value represent the nanoseconds duration since module start.
+ * </p>
+ * @see #getMonotonicStartupTime()
+ * @see #getMonotonicNanos()
+ */
+ public static native long currentNanos();
+
+ /**
+ * Returns the Instant presentation of monotonic {@link #currentNanos()}.
+ * <p>
+ * Monotonic time shall be used for high-performance measurements of durations,
+ * since the underlying OS shall support fast calls.
+ * </p>
+ * <p>
+ * The returned nanoseconds are counted not from Unix Epoch but start of this module,
+ * hence it lasts for 9'223'372'036 seconds or 292 years using the 64-bit type `long`.
+ * </p>
+ * <p>
+ * Method name doesn't include the term `Time` intentionally,
+ * since the returned value represent the nanoseconds duration since module start.
+ * </p>
+ * @see #getMonotonicStartupTime()
+ * @see #currentNanos()
+ */
+ public static Instant getMonotonicNanos() {
+ final long nanos = currentNanos();
+ return Instant.ofEpochSecond(nanos/1000000000L, nanos%1000000000L);
+ }
+
+ /**
+ * Returns current monotonic time in milliseconds.
+ *
+ * @see #getMonotonicStartupTime()
+ * @see #currentNanos()
+ * @see #getMonotonicNanos()
+ */
+ public static native long currentTimeMillis();
+
+ /**
+ * Returns current wall-clock system `time of day` in seconds since Unix Epoch
+ * `00:00:00 UTC on 1 January 1970`.
+ *
+ * @see #getWallClockTime()
+ * @see #getMonotonicTime()
+ * @see #currentNanos()
+ * @see #getMonotonicNanos()
+ */
+ public static native long wallClockSeconds();
+}
diff --git a/src/java/com/jogamp/common/os/NativeLibrary.java b/src/java/com/jogamp/common/os/NativeLibrary.java
index 2a42bed..53db784 100644
--- a/src/java/com/jogamp/common/os/NativeLibrary.java
+++ b/src/java/com/jogamp/common/os/NativeLibrary.java
@@ -41,11 +41,12 @@
package com.jogamp.common.os;
import java.io.File;
+import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
@@ -59,6 +60,7 @@ import jogamp.common.os.WindowsDynamicLinkerImpl;
import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.SecurityUtil;
import com.jogamp.common.util.cache.TempJarCache;
/** Provides low-level, relatively platform-independent access to
@@ -78,6 +80,7 @@ public final class NativeLibrary implements DynamicLookupHelper {
private static final String[] prefixes;
private static final String[] suffixes;
private static final boolean isOSX;
+ private static String sys_env_lib_path_varname;
static {
// Instantiate dynamic linker implementation
@@ -85,6 +88,7 @@ public final class NativeLibrary implements DynamicLookupHelper {
case WINDOWS:
prefixes = new String[] { "" };
suffixes = new String[] { ".dll" };
+ sys_env_lib_path_varname = "PATH";
isOSX = false;
break;
@@ -92,6 +96,7 @@ public final class NativeLibrary implements DynamicLookupHelper {
case IOS:
prefixes = new String[] { "lib" };
suffixes = new String[] { ".dylib" };
+ sys_env_lib_path_varname = "DYLD_LIBRARY_PATH";
isOSX = true;
break;
@@ -105,6 +110,7 @@ public final class NativeLibrary implements DynamicLookupHelper {
default:
prefixes = new String[] { "lib" };
suffixes = new String[] { ".so" };
+ sys_env_lib_path_varname = "LD_LIBRARY_PATH";
isOSX = false;
break;
}
@@ -138,6 +144,35 @@ public final class NativeLibrary implements DynamicLookupHelper {
return "NativeLibrary[" + dynLink.getClass().getSimpleName() + ", " + libraryPath + ", 0x" + Long.toHexString(libraryHandle) + ", global " + global + "]";
}
+ /**
+ * Returns the system's environment variable name used for the dynamic linker to resolve library locations, e.g.
+ * - Windows: PATH
+ * - MacOS: DYLD_LIBRARY_PATH
+ * - Unix: LD_LIBRARY_PATH
+ */
+ public static final String getSystemEnvLibraryPathVarname() { return sys_env_lib_path_varname; }
+
+ /**
+ * Returns a list of system paths, from the {@link #getSystemEnvLibraryPathVarname()} variable.
+ */
+ public static final List<String> getSystemEnvLibraryPaths() {
+ final String paths =
+ SecurityUtil.doPrivileged(new PrivilegedAction<String>() {
+ @Override
+ public String run() {
+ return System.getenv(getSystemEnvLibraryPathVarname());
+ }
+ });
+ final List<String> res = new ArrayList<String>();
+ if( null != paths && paths.length() > 0 ) {
+ final StringTokenizer st = new StringTokenizer(paths, File.pathSeparator);
+ while (st.hasMoreTokens()) {
+ res.add(st.nextToken());
+ }
+ }
+ return res;
+ }
+
/** Opens the given native library, assuming it has the same base
name on all platforms.
<p>
@@ -418,29 +453,44 @@ public final class NativeLibrary implements DynamicLookupHelper {
final List<String> paths = new ArrayList<String>();
final String libName = selectName(windowsLibName, unixLibName, macOSXLibName);
if (libName == null) {
- return paths;
+ if (DEBUG) {
+ System.err.println("NativeLibrary.enumerateLibraryPaths: empty, no libName selected");
+ }
+ return paths;
+ }
+ if (DEBUG) {
+ System.err.println("NativeLibrary.enumerateLibraryPaths: libName '"+libName+"'");
}
// Allow user's full path specification to override our building of paths
final File file = new File(libName);
if (file.isAbsolute()) {
paths.add(libName);
+ if (DEBUG) {
+ System.err.println("NativeLibrary.enumerateLibraryPaths: done, absolute path found '"+libName+"'");
+ }
return paths;
}
final String[] baseNames = buildNames(libName);
+ if (DEBUG) {
+ System.err.println("NativeLibrary.enumerateLibraryPaths: baseNames: "+Arrays.toString(baseNames));
+ }
if( searchSystemPath && searchSystemPathFirst ) {
// Add just the library names to use the OS's search algorithm
for (int i = 0; i < baseNames.length; i++) {
+ if (DEBUG) {
+ System.err.println("NativeLibrary.enumerateLibraryPaths: add.ssp_1st: "+baseNames[i]);
+ }
paths.add(baseNames[i]);
}
// Add probable Mac OS X-specific paths
if ( isOSX ) {
// Add historical location
- addPaths("/Library/Frameworks/" + libName + ".framework", baseNames, paths);
+ addAbsPaths("add.ssp_1st_macos_old", "/Library/Frameworks/" + libName + ".framework", baseNames, paths);
// Add current location
- addPaths("/System/Library/Frameworks/" + libName + ".framework", baseNames, paths);
+ addAbsPaths("add.ssp_1st_macos_cur", "/System/Library/Frameworks/" + libName + ".framework", baseNames, paths);
}
}
@@ -448,12 +498,15 @@ public final class NativeLibrary implements DynamicLookupHelper {
// from the LWJGL library
final String clPath = findLibrary(libName, loader);
if (clPath != null) {
- paths.add(clPath);
+ if (DEBUG) {
+ System.err.println("NativeLibrary.enumerateLibraryPaths: add.clp: "+clPath);
+ }
+ paths.add(clPath);
}
// Add entries from java.library.path
final String[] javaLibraryPaths =
- AccessController.doPrivileged(new PrivilegedAction<String[]>() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<String[]>() {
@Override
public String[] run() {
int count = 0;
@@ -488,39 +541,44 @@ public final class NativeLibrary implements DynamicLookupHelper {
for( int i=0; i < javaLibraryPaths.length; i++ ) {
final StringTokenizer tokenizer = new StringTokenizer(javaLibraryPaths[i], File.pathSeparator);
while (tokenizer.hasMoreTokens()) {
- addPaths(tokenizer.nextToken(), baseNames, paths);
+ addRelPaths("add.java.library.path", tokenizer.nextToken(), baseNames, paths);
}
}
}
// Add current working directory
final String userDir =
- AccessController.doPrivileged(new PrivilegedAction<String>() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() {
return System.getProperty("user.dir");
}
});
- addPaths(userDir, baseNames, paths);
+ addAbsPaths("add.user.dir.std", userDir, baseNames, paths);
// Add current working directory + natives/os-arch/ + library names
// to handle Bug 1145 cc1 using an unpacked fat-jar
- addPaths(userDir+File.separator+"natives"+File.separator+PlatformPropsImpl.os_and_arch+File.separator, baseNames, paths);
+ addAbsPaths("add.user.dir.fat", userDir+File.separator+"natives"+File.separator+PlatformPropsImpl.os_and_arch, baseNames, paths);
if( searchSystemPath && !searchSystemPathFirst ) {
// Add just the library names to use the OS's search algorithm
for (int i = 0; i < baseNames.length; i++) {
+ if (DEBUG) {
+ System.err.println("NativeLibrary.enumerateLibraryPaths: add.ssp_lst: "+baseNames[i]);
+ }
paths.add(baseNames[i]);
}
// Add probable Mac OS X-specific paths
if ( isOSX ) {
// Add historical location
- addPaths("/Library/Frameworks/" + libName + ".Framework", baseNames, paths);
+ addAbsPaths("add.ssp_lst_macos_old", "/Library/Frameworks/" + libName + ".Framework", baseNames, paths);
// Add current location
- addPaths("/System/Library/Frameworks/" + libName + ".Framework", baseNames, paths);
+ addAbsPaths("add.ssp_lst_macos_cur", "/System/Library/Frameworks/" + libName + ".Framework", baseNames, paths);
}
}
-
+ if (DEBUG) {
+ System.err.println("NativeLibrary.enumerateLibraryPaths: done: "+paths.toString());
+ }
return paths;
}
@@ -600,10 +658,27 @@ public final class NativeLibrary implements DynamicLookupHelper {
return res;
}
- private static final void addPaths(final String path, final String[] baseNames, final List<String> paths) {
- for (int j = 0; j < baseNames.length; j++) {
- paths.add(path + File.separator + baseNames[j]);
- }
+ private static final void addRelPaths(final String cause, final String path, final String[] baseNames, final List<String> paths) {
+ final String abs_path;
+ try {
+ final File fpath = new File(path);
+ abs_path = fpath.getCanonicalPath();
+ } catch( final IOException ioe ) {
+ if (DEBUG) {
+ System.err.println("NativeLibrary.enumerateLibraryPaths: "+cause+": Exception "+ioe.getMessage()+", from path "+path);
+ }
+ return;
+ }
+ addAbsPaths(cause, abs_path, baseNames, paths);
+ }
+ private static final void addAbsPaths(final String cause, final String abs_path, final String[] baseNames, final List<String> paths) {
+ for (int j = 0; j < baseNames.length; j++) {
+ final String p = abs_path + File.separator + baseNames[j];
+ if (DEBUG) {
+ System.err.println("NativeLibrary.enumerateLibraryPaths: "+cause+": "+p+", from path "+abs_path);
+ }
+ paths.add(p);
+ }
}
private static boolean initializedFindLibraryMethod = false;
@@ -616,7 +691,7 @@ public final class NativeLibrary implements DynamicLookupHelper {
return null;
}
if (!initializedFindLibraryMethod) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
@@ -633,7 +708,7 @@ public final class NativeLibrary implements DynamicLookupHelper {
}
if (findLibraryMethod != null) {
try {
- return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ return SecurityUtil.doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() {
try {
diff --git a/src/java/com/jogamp/common/os/Platform.java b/src/java/com/jogamp/common/os/Platform.java
index ca3d60b..ffea42c 100644
--- a/src/java/com/jogamp/common/os/Platform.java
+++ b/src/java/com/jogamp/common/os/Platform.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright 2010-2023 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -28,7 +28,6 @@
package com.jogamp.common.os;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.TimeUnit;
@@ -37,6 +36,7 @@ import com.jogamp.common.net.Uri;
import com.jogamp.common.util.JarUtil;
import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.common.util.SecurityUtil;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.common.util.cache.TempJarCache;
@@ -287,7 +287,7 @@ public class Platform extends PlatformPropsImpl {
final boolean[] _USE_TEMP_JAR_CACHE = new boolean[] { false };
final boolean[] _AWT_AVAILABLE = new boolean[] { false };
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
@@ -521,26 +521,12 @@ public class Platform extends PlatformPropsImpl {
//
/**
- * Returns the unix based current time in milliseconds, based on <code>gettimeofday(..)</code>.
- * <p>
- * This is an alternative to {@link System#currentTimeMillis()} and {@link System#nanoTime()}.
- * While the named {@link System} methods do provide the required precision,
- * <code>gettimeofday()</code> <i>also</i> guarantees time accuracy, i.e. update interval.
- * </p>
- * @see #currentTimeMicros()
- */
- public static native long currentTimeMillis();
-
- /**
- * Returns the unix based current time in microseconds, based on <code>gettimeofday(..)</code>.
- * <p>
- * This is an alternative to {@link System#currentTimeMillis()} and {@link System#nanoTime()}.
- * While the named {@link System} methods do provide the required precision,
- * <code>gettimeofday()</code> <i>also</i> guarantees time accuracy, i.e. update interval.
- * </p>
- * @see #currentTimeMillis()
+ * Returns the unix based current time in milliseconds, see {@link Clock#currentTimeMillis()}.
+ * @see Clock#currentTimeMillis()
*/
- public static native long currentTimeMicros();
+ public static long currentTimeMillis() {
+ return Clock.currentTimeMillis();
+ }
/**
* Returns the estimated sleep jitter value in nanoseconds.
@@ -554,11 +540,11 @@ public class Platform extends PlatformPropsImpl {
}
private static long getCurrentSleepJitterImpl(final long nsDuration, final int splitInLoops) {
final long nsPeriod = nsDuration / splitInLoops;
- final long t0_ns = System.nanoTime();
+ final long t0_ns = Clock.currentNanos();
for(int i=splitInLoops; i>0; i--) {
try { TimeUnit.NANOSECONDS.sleep(nsPeriod); } catch (final InterruptedException e) { }
}
- return ( ( System.nanoTime() - t0_ns ) - nsDuration ) / splitInLoops;
+ return ( ( Clock.currentNanos() - t0_ns ) - nsDuration ) / splitInLoops;
}
}
diff --git a/src/java/com/jogamp/common/util/IOUtil.java b/src/java/com/jogamp/common/util/IOUtil.java
index 380cb00..e68c3b3 100644
--- a/src/java/com/jogamp/common/util/IOUtil.java
+++ b/src/java/com/jogamp/common/util/IOUtil.java
@@ -48,7 +48,6 @@ import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
@@ -79,7 +78,7 @@ public class IOUtil {
static {
final boolean _props[] = { false, false, false, false, false, false };
- final Method[] res = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
+ final Method[] res = SecurityUtil.doPrivileged(new PrivilegedAction<Method[]>() {
@Override
public Method[] run() {
final Method[] res = new Method[] { null, null };
@@ -172,7 +171,7 @@ public class IOUtil {
*/
/**
- * Copy the specified URL resource to the specified output file. The total
+ * Copy the complete specified URL resource to the specified output file. The total
* number of bytes written is returned.
*
* @param conn the open URLConnection
@@ -186,7 +185,7 @@ public class IOUtil {
int totalNumBytes = 0;
final InputStream in = new BufferedInputStream(conn.getInputStream());
try {
- totalNumBytes = copyStream2File(in, outFile, conn.getContentLength());
+ totalNumBytes = copyStream2File(in, outFile);
} finally {
in.close();
}
@@ -194,51 +193,47 @@ public class IOUtil {
}
/**
- * Copy the specified input stream to the specified output file. The total
+ * Copy the complete specified input stream to the specified output file. The total
* number of bytes written is returned.
*
* @param in the source
* @param outFile the destination
- * @param totalNumBytes informal number of expected bytes, maybe used for user feedback while processing. -1 if unknown
* @return
* @throws IOException
*/
- public static int copyStream2File(final InputStream in, final File outFile, int totalNumBytes) throws IOException {
+ public static int copyStream2File(final InputStream in, final File outFile) throws IOException {
final OutputStream out = new BufferedOutputStream(new FileOutputStream(outFile));
try {
- totalNumBytes = copyStream2Stream(in, out, totalNumBytes);
+ return copyStream2Stream(in, out);
} finally {
out.close();
}
- return totalNumBytes;
}
/**
- * Copy the specified input stream to the specified output stream. The total
+ * Copy the complete specified input stream to the specified output stream. The total
* number of bytes written is returned.
*
* @param in the source
* @param out the destination
- * @param totalNumBytes informal number of expected bytes, maybe used for user feedback while processing. -1 if unknown
* @return
* @throws IOException
*/
- public static int copyStream2Stream(final InputStream in, final OutputStream out, final int totalNumBytes) throws IOException {
- return copyStream2Stream(Platform.getMachineDataInfo().pageSizeInBytes(), in, out, totalNumBytes);
+ public static int copyStream2Stream(final InputStream in, final OutputStream out) throws IOException {
+ return copyStream2Stream(Platform.getMachineDataInfo().pageSizeInBytes(), in, out);
}
/**
- * Copy the specified input stream to the specified output stream. The total
+ * Copy the complete specified input stream to the specified output stream. The total
* number of bytes written is returned.
*
* @param bufferSize the intermediate buffer size, should be {@link MachineDataInfo#pageSizeInBytes()} for best performance.
* @param in the source
* @param out the destination
- * @param totalNumBytes informal number of expected bytes, maybe used for user feedback while processing. -1 if unknown
* @return
* @throws IOException
*/
- public static int copyStream2Stream(final int bufferSize, final InputStream in, final OutputStream out, final int totalNumBytes) throws IOException {
+ public static int copyStream2Stream(final int bufferSize, final InputStream in, final OutputStream out) throws IOException {
final byte[] buf = new byte[bufferSize];
int numBytes = 0;
while (true) {
@@ -262,7 +257,7 @@ public class IOUtil {
}
/**
- * Copy the specified input stream to a byte array, which is being returned.
+ * Copy the complete specified input stream to a byte array, which is being returned.
*/
public static byte[] copyStream2ByteArray(InputStream stream) throws IOException {
if( !(stream instanceof BufferedInputStream) ) {
@@ -295,8 +290,7 @@ public class IOUtil {
}
/**
- * Copy the specified input stream to a NIO ByteBuffer w/ native byte order, which is being returned.
- * <p>The implementation creates the ByteBuffer w/ {@link #copyStream2ByteArray(InputStream)}'s returned byte array.</p>
+ * Copy the complete specified input stream to a NIO ByteBuffer w/ native byte order, which is being returned.
*
* @param stream input stream, which will be wrapped into a BufferedInputStream, if not already done.
*/
@@ -305,11 +299,10 @@ public class IOUtil {
}
/**
- * Copy the specified input stream to a NIO ByteBuffer w/ native byte order, which is being returned.
- * <p>The implementation creates the ByteBuffer w/ {@link #copyStream2ByteArray(InputStream)}'s returned byte array.</p>
+ * Copy the complete specified input stream to a NIO ByteBuffer w/ native byte order, which is being returned.
*
* @param stream input stream, which will be wrapped into a BufferedInputStream, if not already done.
- * @param initialCapacity initial buffer capacity in bytes, if &gt; available bytes
+ * @param initialCapacity initial buffer capacity in bytes, if &lt; currently available bytes, initial buffer capacity is set to currently available bytes.
*/
public static ByteBuffer copyStream2ByteBuffer(InputStream stream, int initialCapacity) throws IOException {
if( !(stream instanceof BufferedInputStream) ) {
@@ -344,6 +337,39 @@ public class IOUtil {
return data;
}
+ /**
+ * Copy the specified input stream chunk to a NIO ByteBuffer w/ native byte order, which is being returned.
+ *
+ * @param stream input stream, which will be wrapped into a BufferedInputStream, if not already done.
+ * @param skipBytes initial bytes to skip from input stream.
+ * @param byteCount bytes to copy starting after skipBytes.
+ */
+ public static ByteBuffer copyStreamChunk2ByteBuffer(InputStream stream, int skipBytes, int byteCount) throws IOException {
+ if( !(stream instanceof BufferedInputStream) ) {
+ stream = new BufferedInputStream(stream);
+ }
+ final MachineDataInfo machine = Platform.getMachineDataInfo();
+ final ByteBuffer data = Buffers.newDirectByteBuffer( machine.pageAlignedSize( byteCount ) );
+ final byte[] chunk = new byte[machine.pageSizeInBytes()];
+ int numRead = 1; // EOS: -1 == numRead, EOF maybe reached earlier w/ 0 == numRead
+ while ( numRead > 0 && skipBytes > 0 ) {
+ final int chunk2Read = Math.min(machine.pageSizeInBytes(), skipBytes);
+ numRead = stream.read(chunk, 0, chunk2Read);
+ skipBytes -= numRead;
+ }
+ while ( numRead > 0 && byteCount > 0 ) {
+ final int chunk2Read = Math.min(machine.pageSizeInBytes(), byteCount);
+ numRead = stream.read(chunk, 0, chunk2Read);
+ if (numRead > 0) {
+ data.put(chunk, 0, numRead);
+ }
+ byteCount -= numRead;
+ }
+
+ data.flip();
+ return data;
+ }
+
/***
*
* RESOURCE / FILE NAME STUFF
diff --git a/src/java/com/jogamp/common/util/IntIntHashMap.java b/src/java/com/jogamp/common/util/IntIntHashMap.java
index f78b1e0..d74b79c 100644
--- a/src/java/com/jogamp/common/util/IntIntHashMap.java
+++ b/src/java/com/jogamp/common/util/IntIntHashMap.java
@@ -34,7 +34,6 @@ package com.jogamp.common.util;
import com.jogamp.common.JogampRuntimeException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
@@ -84,7 +83,7 @@ public class /*name*/IntIntHashMap/*name*/ implements Cloneable,
isPrimitive = valueClazz.isPrimitive();
if(!isPrimitive) {
- final EntryCM cm = AccessController.doPrivileged(new PrivilegedAction<EntryCM>() {
+ final EntryCM cm = SecurityUtil.doPrivileged(new PrivilegedAction<EntryCM>() {
@Override
@SuppressWarnings("unchecked")
public EntryCM run() {
@@ -502,7 +501,7 @@ public class /*name*/IntIntHashMap/*name*/ implements Cloneable,
private static Method getCloneMethod(final Object obj) {
final Class<?> clazz = obj.getClass();
- return AccessController.doPrivileged(new PrivilegedAction<Method>() {
+ return SecurityUtil.doPrivileged(new PrivilegedAction<Method>() {
@Override
public Method run() {
try {
diff --git a/src/java/com/jogamp/common/util/JarUtil.java b/src/java/com/jogamp/common/util/JarUtil.java
index aa5719c..9dc0fb6 100644
--- a/src/java/com/jogamp/common/util/JarUtil.java
+++ b/src/java/com/jogamp/common/util/JarUtil.java
@@ -418,14 +418,25 @@ public class JarUtil {
* <pre>
* class's jar url path + cutOffInclSubDir + relResPath,
* </pre>
+ * or with <code>cutOffInclSubDir</code> being <code>null</code> just
+ * <pre>
+ * class's jar url path + relResPath,
+ * </pre>
* Example #1
* <pre>
* classFromJavaJar = com.lighting.Test (in: file:/storage/TestLighting.jar)
+ * cutOffInclSubDir = null
+ * relResPath = LightAssets.jar
+ * Result : file:/storage/LightAssets.jar
+ * </pre>
+ * Example #2
+ * <pre>
+ * classFromJavaJar = com.lighting.Test (in: file:/storage/TestLighting.jar)
* cutOffInclSubDir = lights/
* relResPath = LightAssets.jar
* Result : file:/storage/lights/LightAssets.jar
* </pre>
- * Example #2
+ * Example #3
* <pre>
* classFromJavaJar = com.lighting.Test (in: file:/storage/lights/TestLighting.jar)
* cutOffInclSubDir = lights/
@@ -436,8 +447,9 @@ public class JarUtil {
* TODO: Enhance documentation!
*
* @param classFromJavaJar Used to get the root Uri for the class's Jar Uri.
- * @param cutOffInclSubDir The <i>cut off</i> included sub-directory prepending the relative resource path.
+ * @param cutOffInclSubDir Optional <i>cut off</i> included sub-directory prepending the relative resource path.
* If the root Uri includes cutOffInclSubDir, it is no more added to the result.
+ * Parameter will be ignored if <code>null</code>.
* @param relResPath The relative resource path. (Uri encoded)
* @return The resulting resource Uri, which is not tested.
* @throws IllegalArgumentException
@@ -451,7 +463,6 @@ public class JarUtil {
System.err.println("JarUtil.getRelativeOf: "+"(classFromJavaJar "+classFromJavaJar+", classJarUri "+classJarUri+
", cutOffInclSubDir "+cutOffInclSubDir+", relResPath "+relResPath+"): ");
}
-
final Uri jarSubUri = classJarUri.getContainedUri();
if(null == jarSubUri) {
throw new IllegalArgumentException("JarSubUri is null of: "+classJarUri);
@@ -460,9 +471,8 @@ public class JarUtil {
if( DEBUG ) {
System.err.println("JarUtil.getRelativeOf: "+"uri "+jarSubUri.toString()+" -> "+jarUriRoot);
}
-
final Uri.Encoded resUri;
- if( jarUriRoot.endsWith(cutOffInclSubDir.get()) ) {
+ if( null == cutOffInclSubDir || jarUriRoot.endsWith(cutOffInclSubDir.get()) ) {
resUri = jarUriRoot.concat(relResPath);
} else {
resUri = jarUriRoot.concat(cutOffInclSubDir).concat(relResPath);
@@ -470,7 +480,6 @@ public class JarUtil {
if( DEBUG ) {
System.err.println("JarUtil.getRelativeOf: "+"... -> "+resUri);
}
-
final Uri resJarUri = JarUtil.getJarFileUri(resUri);
if( DEBUG ) {
System.err.println("JarUtil.getRelativeOf: "+"fin "+resJarUri);
@@ -628,7 +637,7 @@ public class JarUtil {
final OutputStream out = new BufferedOutputStream(new FileOutputStream(destFile));
int numBytes = -1;
try {
- numBytes = IOUtil.copyStream2Stream(BUFFER_SIZE, in, out, -1);
+ numBytes = IOUtil.copyStream2Stream(BUFFER_SIZE, in, out);
} finally {
in.close();
out.close();
diff --git a/src/java/com/jogamp/common/util/PerfCounterCtrl.java b/src/java/com/jogamp/common/util/PerfCounterCtrl.java
new file mode 100644
index 0000000..2c79a2d
--- /dev/null
+++ b/src/java/com/jogamp/common/util/PerfCounterCtrl.java
@@ -0,0 +1,50 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2023 Gothel Software e.K.
+ * Copyright (c) 2023 JogAmp Community.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.jogamp.common.util;
+
+import java.io.PrintStream;
+import com.jogamp.common.os.Clock;
+
+/**
+ * Simple performance counter controller.
+ * <p>
+ * Implementation is expected to utilize nanosecond counter since module start,
+ * e.g. {@link Clock#currentNanos()}.
+ * </p>
+ */
+public interface PerfCounterCtrl {
+ /** Enable or disable performance counter. */
+ void enable(final boolean enable);
+
+ /** Clear performance counter. */
+ void clear();
+
+ /** Return the total duration in nanoseconds, covering all sub-counter. */
+ long getTotalDuration();
+
+ /** Print performance counter. */
+ void print(final PrintStream out);
+}
diff --git a/src/java/com/jogamp/common/util/PropertyAccess.java b/src/java/com/jogamp/common/util/PropertyAccess.java
index b6e9bdd..6dd550b 100644
--- a/src/java/com/jogamp/common/util/PropertyAccess.java
+++ b/src/java/com/jogamp/common/util/PropertyAccess.java
@@ -175,7 +175,7 @@ public class PropertyAccess {
}
private static final String getTrustedPropKey(final String propertyKey) {
- return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ return SecurityUtil.doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() {
try {
diff --git a/src/java/com/jogamp/common/util/ReflectionUtil.java b/src/java/com/jogamp/common/util/ReflectionUtil.java
index 0d76827..27ca983 100644
--- a/src/java/com/jogamp/common/util/ReflectionUtil.java
+++ b/src/java/com/jogamp/common/util/ReflectionUtil.java
@@ -51,6 +51,7 @@ import jogamp.common.Debug;
import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.JogampRuntimeException;
+import com.jogamp.common.os.Clock;
public final class ReflectionUtil {
@@ -125,9 +126,9 @@ public final class ReflectionUtil {
private static Class<?> getClassImpl(final String clazzName, final boolean initializeClazz, final ClassLoader cl) throws ClassNotFoundException {
if(DEBUG_STATS_FORNAME) {
- final long t0 = System.nanoTime();
+ final long t0 = Clock.currentNanos();
final Class<?> res = Class.forName(clazzName, initializeClazz, cl);
- final long t1 = System.nanoTime();
+ final long t1 = Clock.currentNanos();
final long nanoCosts = t1 - t0;
synchronized(forNameLock) {
forNameCount++;
diff --git a/src/java/com/jogamp/common/util/SecurityUtil.java b/src/java/com/jogamp/common/util/SecurityUtil.java
index 1b8b7c2..6d5b639 100644
--- a/src/java/com/jogamp/common/util/SecurityUtil.java
+++ b/src/java/com/jogamp/common/util/SecurityUtil.java
@@ -27,7 +27,6 @@
*/
package com.jogamp.common.util;
-import java.security.AccessController;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.Permission;
@@ -35,19 +34,63 @@ import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
+import jogamp.common.os.PlatformPropsImpl;
+
public class SecurityUtil {
+ @SuppressWarnings("removal")
private static final SecurityManager securityManager;
private static final Permission allPermissions;
private static final boolean DEBUG = false;
+ /**
+ * Call wrapper for {@link System#getSecurityManager()}.
+ * <p>
+ * {@link System#getSecurityManager()} is deprecated
+ * since Java 17 (JEP 411) and earmarked to be removed.<br/>
+ * </p>
+ * <p>
+ * On a Java 17 machine, this method will simply return null.
+ * </p>
+ */
+ @SuppressWarnings({ "deprecation", "removal" })
+ public static final SecurityManager getSecurityManager() {
+ if( PlatformPropsImpl.JAVA_17 ) {
+ return null;
+ } else {
+ return System.getSecurityManager();
+ }
+ }
+
+ /**
+ * Call wrapper for {@link java.security.AccessController#doPrivileged(PrivilegedAction)}.
+ * <p>
+ * {@link java.security.AccessController#doPrivileged(PrivilegedAction)} is deprecated
+ * since Java 17 (JEP 411) and earmarked to be removed.<br/>
+ * </p>
+ * <p>
+ * On a Java 17 machine, this method will simply invoke the given PrivilegedAction<T>.
+ * </p>
+ * @param <T> return type of PrivilegedAction<T>
+ * @param o the PrivilegedAction<T>
+ * @return the return type
+ */
+ @SuppressWarnings({ "deprecation", "removal" })
+ public static <T> T doPrivileged(final PrivilegedAction<T> o) {
+ if( PlatformPropsImpl.JAVA_17 ) {
+ return o.run();
+ } else {
+ return java.security.AccessController.doPrivileged( o );
+ }
+ }
+
static {
allPermissions = new AllPermission();
- securityManager = System.getSecurityManager();
+ securityManager = getSecurityManager();
if( DEBUG ) {
final boolean hasAllPermissions;
{
- final ProtectionDomain insecPD = AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
+ final ProtectionDomain insecPD = doPrivileged(new PrivilegedAction<ProtectionDomain>() {
@Override
public ProtectionDomain run() {
return SecurityUtil.class.getProtectionDomain();
@@ -64,7 +107,7 @@ public class SecurityUtil {
System.err.println("SecurityUtil: Has SecurityManager: "+ ( null != securityManager ) ) ;
System.err.println("SecurityUtil: Has AllPermissions: "+hasAllPermissions);
- final Certificate[] certs = AccessController.doPrivileged(new PrivilegedAction<Certificate[]>() {
+ final Certificate[] certs = doPrivileged(new PrivilegedAction<Certificate[]>() {
@Override
public Certificate[] run() {
return getCerts(SecurityUtil.class);
diff --git a/src/java/com/jogamp/common/util/UnsafeUtil.java b/src/java/com/jogamp/common/util/UnsafeUtil.java
index 6fde3fa..d1b2dd8 100644
--- a/src/java/com/jogamp/common/util/UnsafeUtil.java
+++ b/src/java/com/jogamp/common/util/UnsafeUtil.java
@@ -31,7 +31,6 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import com.jogamp.common.ExceptionUtils;
@@ -73,7 +72,7 @@ public class UnsafeUtil {
final Class<?>[] _illegalAccessLoggerClass = { null };
final Long[] _loggerOffset = { null };
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
Class<?> unsafeClass = null;
@@ -172,7 +171,7 @@ public class UnsafeUtil {
/**
* Issue the given user {@code action} while {@code jdk.internal.module.IllegalAcessLogger}'s {@code logger} has been temporarily disabled.
* <p>
- * The caller shall place this call into their own {@link AccessController#doPrivileged(PrivilegedAction)} block.
+ * The caller shall place this call into their own {@link SecurityUtil#doPrivileged(PrivilegedAction)} block.
* </p>
* <p>
* In case the runtime is not {@link PlatformPropsImpl#JAVA_9} or the logger is not accessible or disabling caused an exception,
diff --git a/src/java/com/jogamp/common/util/VersionUtil.java b/src/java/com/jogamp/common/util/VersionUtil.java
index 1e09034..eee3c4e 100644
--- a/src/java/com/jogamp/common/util/VersionUtil.java
+++ b/src/java/com/jogamp/common/util/VersionUtil.java
@@ -73,9 +73,17 @@ public class VersionUtil {
sb.append("Platform: Java Version: ").append(Platform.getJavaVersion()).append(" (").append(Platform.getJavaVersionNumber()).append("u").append(PlatformPropsImpl.JAVA_VERSION_UPDATE).append("), VM: ").append(Platform.getJavaVMName());
sb.append(", Runtime: ").append(Platform.getJavaRuntimeName()).append(Platform.getNewline());
sb.append("Platform: Java Vendor: ").append(Platform.getJavaVendor()).append(", ").append(Platform.getJavaVendorURL());
- sb.append(", JavaSE: ").append(PlatformPropsImpl.JAVA_SE);
- sb.append(", Java9: ").append(PlatformPropsImpl.JAVA_9);
- sb.append(", Java6: ").append(PlatformPropsImpl.JAVA_6);
+ if( PlatformPropsImpl.JAVA_21 ) {
+ sb.append(", Java21");
+ } else if( PlatformPropsImpl.JAVA_17 ) {
+ sb.append(", Java17");
+ } else if( PlatformPropsImpl.JAVA_9 ) {
+ sb.append(", Java9");
+ } else if( PlatformPropsImpl.JAVA_6 ) {
+ sb.append(", Java6");
+ } else if( PlatformPropsImpl.JAVA_SE ) {
+ sb.append(", JavaSE");
+ }
sb.append(", dynamicLib: ").append(PlatformPropsImpl.useDynamicLibraries);
sb.append(", AWT enabled: ").append(Platform.AWT_AVAILABLE);
sb.append(Platform.getNewline()).append(SEPERATOR);
diff --git a/src/java/com/jogamp/common/util/awt/AWTEDTExecutor.java b/src/java/com/jogamp/common/util/awt/AWTEDTExecutor.java
index ec9348d..cc5d5d1 100644
--- a/src/java/com/jogamp/common/util/awt/AWTEDTExecutor.java
+++ b/src/java/com/jogamp/common/util/awt/AWTEDTExecutor.java
@@ -48,17 +48,17 @@ public class AWTEDTExecutor implements RunnableExecutor {
if(EventQueue.isDispatchThread()) {
r.run();
} else {
- try {
- if(wait) {
- EventQueue.invokeAndWait(r);
- } else {
- EventQueue.invokeLater(r);
+ try {
+ if(wait) {
+ EventQueue.invokeAndWait(r);
+ } else {
+ EventQueue.invokeLater(r);
+ }
+ } catch (final InvocationTargetException e) {
+ throw new RuntimeException(e.getTargetException());
+ } catch (final InterruptedException e) {
+ throw new RuntimeException(e);
}
- } catch (final InvocationTargetException e) {
- throw new RuntimeException(e.getTargetException());
- } catch (final InterruptedException e) {
- throw new RuntimeException(e);
- }
}
}
diff --git a/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java b/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java
index 03ed5c1..2ced962 100644
--- a/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java
+++ b/src/java/com/jogamp/gluegen/runtime/ProcAddressTable.java
@@ -46,7 +46,6 @@ import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Iterator;
import java.util.LinkedHashSet;
@@ -89,7 +88,7 @@ public abstract class ProcAddressTable {
private final FunctionAddressResolver resolver;
static {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
DEBUG = (System.getProperty("jogamp.debug.ProcAddressHelper") != null);
@@ -207,7 +206,7 @@ public abstract class ProcAddressTable {
* </p>
*/
private final Field fieldForFunctionInSec(final String name) throws IllegalArgumentException {
- return AccessController.doPrivileged(new PrivilegedAction<Field>() {
+ return SecurityUtil.doPrivileged(new PrivilegedAction<Field>() {
@Override
public Field run() {
try {
diff --git a/src/java/jogamp/common/Debug.java b/src/java/jogamp/common/Debug.java
index 838b607..131018c 100644
--- a/src/java/jogamp/common/Debug.java
+++ b/src/java/jogamp/common/Debug.java
@@ -28,10 +28,10 @@
package jogamp.common;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.SecurityUtil;
/** Helper routines for logging and debugging. */
@@ -41,7 +41,7 @@ public class Debug extends PropertyAccess {
private static final boolean debugAll;
static {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
PropertyAccess.addTrustedPrefix("jogamp.");
diff --git a/src/java/jogamp/common/av/JavaSoundAudioSink.java b/src/java/jogamp/common/av/JavaSoundAudioSink.java
new file mode 100644
index 0000000..58f0fec
--- /dev/null
+++ b/src/java/jogamp/common/av/JavaSoundAudioSink.java
@@ -0,0 +1,320 @@
+/**
+ * Copyright 2013-2023 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.common.av;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.SourceDataLine;
+
+import com.jogamp.common.av.AudioFormat;
+import com.jogamp.common.av.AudioSink;
+
+/***
+ * JavaSound Audio Sink
+ * <p>
+ * FIXME: Parameterize .. all configs .. best via an init-method, passing requested
+ * audio capabilities
+ * </p>
+ */
+public final class JavaSoundAudioSink implements AudioSink {
+
+ // Chunk of audio processed at one time
+ public static final int BUFFER_SIZE = 1000;
+ public static final int SAMPLES_PER_BUFFER = BUFFER_SIZE / 2;
+ private static final boolean staticAvailable;
+
+ // Sample time values
+ // public static final double SAMPLE_TIME_IN_SECS = 1.0 / DEFAULT_SAMPLE_RATE;
+ // public static final double BUFFER_TIME_IN_SECS = SAMPLE_TIME_IN_SECS * SAMPLES_PER_BUFFER;
+
+ private javax.sound.sampled.AudioFormat format;
+ private DataLine.Info info;
+ private SourceDataLine auline;
+ private int bufferCount;
+ private final byte [] sampleData = new byte[BUFFER_SIZE];
+ private boolean available = false;
+ private final AudioFormat nativeFormat;
+ private int userMaxChannels = 8;
+ private AudioFormat preferredFormat = null;
+ private AudioFormat chosenFormat = null;
+
+ private volatile boolean playRequested = false;
+ private float volume = 1.0f;
+
+ static {
+ boolean ok = false;
+ try {
+ ok = AudioSystem.getAudioFileTypes().length > 0;
+ } catch (final Throwable t) {
+
+ }
+ staticAvailable=ok;
+ }
+
+ public JavaSoundAudioSink() {
+ available = false;
+ if( !staticAvailable ) {
+ nativeFormat = DefaultFormat;
+ return;
+ }
+ nativeFormat = new AudioFormat(DefaultFormat.sampleRate, DefaultFormat.sampleSize, getMaxSupportedChannels(),
+ DefaultFormat.signed, DefaultFormat.fixedP, DefaultFormat.planar, DefaultFormat.littleEndian);
+ preferredFormat = nativeFormat;
+ available = true;
+ }
+
+ @Override
+ public final boolean makeCurrent(final boolean throwException) { return true; }
+
+ @Override
+ public final boolean release(final boolean throwException) { return true; }
+
+ @Override
+ public String toString() {
+ return "JavaSoundSink[avail "+available+", dataLine "+info+", source "+auline+", bufferCount "+bufferCount+
+ ", chosen "+chosenFormat+", jsFormat "+format;
+ }
+
+ @Override
+ public final float getPlaySpeed() { return 1.0f; } // FIXME
+
+ @Override
+ public final boolean setPlaySpeed(final float rate) {
+ return false; // FIXME
+ }
+
+ @Override
+ public final float getVolume() {
+ // FIXME
+ return volume;
+ }
+
+ @Override
+ public final boolean setVolume(final float v) {
+ // FIXME
+ volume = v;
+ return true;
+ }
+
+ @Override
+ public int getSourceCount() {
+ return -1;
+ }
+
+ @Override
+ public float getDefaultLatency() {
+ return 20f/1000f; // fake 20ms
+ }
+
+ @Override
+ public float getLatency() {
+ return 20f/1000f; // fake 20ms
+ }
+
+ @Override
+ public final AudioFormat getNativeFormat() {
+ return nativeFormat;
+ }
+
+ @Override
+ public AudioFormat getPreferredFormat() {
+ return DefaultFormat;
+ }
+
+ @Override
+ public final void setChannelLimit(final int cc) {
+ userMaxChannels = Math.min(8, Math.max(1, cc));
+ preferredFormat = new AudioFormat(nativeFormat.sampleRate,
+ nativeFormat.sampleSize, getMaxSupportedChannels(),
+ nativeFormat.signed, nativeFormat.fixedP,
+ nativeFormat.planar, nativeFormat.littleEndian);
+ if( DEBUG ) {
+ System.out.println("ALAudioSink: channelLimit "+userMaxChannels+", preferredFormat "+preferredFormat);
+ }
+ }
+
+ private final int getMaxSupportedChannels() {
+ final int cc = 2;
+ return Math.min(userMaxChannels, cc);
+ }
+
+ @Override
+ public final boolean isSupported(final AudioFormat format) {
+ if( format.planar != preferredFormat.planar ||
+ format.fixedP != preferredFormat.fixedP ||
+ format.sampleRate > preferredFormat.sampleRate ||
+ format.channelCount > preferredFormat.channelCount )
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean init(final AudioFormat requestedFormat, final int frameDuration, final int initialQueueSize, final int queueGrowAmount, final int queueLimit) {
+ if( !staticAvailable ) {
+ return false;
+ }
+ if( !isSupported(requestedFormat) ) {
+ return false;
+ }
+ // Create the audio format we wish to use
+ format = new javax.sound.sampled.AudioFormat(requestedFormat.sampleRate, requestedFormat.sampleSize, requestedFormat.channelCount, requestedFormat.signed, !requestedFormat.littleEndian);
+
+ // Create dataline info object describing line format
+ info = new DataLine.Info(SourceDataLine.class, format);
+
+ // Clear buffer initially
+ Arrays.fill(sampleData, (byte) 0);
+ try{
+ // Get line to write data to
+ auline = (SourceDataLine) AudioSystem.getLine(info);
+ auline.open(format);
+ auline.start();
+ System.out.println("JavaSound audio sink");
+ available=true;
+ chosenFormat = requestedFormat;
+ } catch (final Exception e) {
+ available=false;
+ }
+ return true;
+ }
+
+ @Override
+ public final AudioFormat getChosenFormat() {
+ return chosenFormat;
+ }
+
+ @Override
+ public boolean isPlaying() {
+ return playRequested && auline.isRunning();
+ }
+
+ @Override
+ public void play() {
+ if( null != auline ) {
+ playRequested = true;
+ playImpl();
+ }
+ }
+ private void playImpl() {
+ if( playRequested && !auline.isRunning() ) {
+ auline.start();
+ }
+ }
+
+ @Override
+ public void pause() {
+ if( null != auline ) {
+ playRequested = false;
+ auline.stop();
+ }
+ }
+
+ @Override
+ public void flush() {
+ if( null != auline ) {
+ playRequested = false;
+ auline.stop();
+ auline.flush();
+ }
+ }
+
+ @Override
+ public final int getEnqueuedFrameCount() {
+ return 0; // FIXME
+ }
+
+ @Override
+ public int getFrameCount() {
+ return 1;
+ }
+
+ @Override
+ public int getQueuedFrameCount() {
+ return 0;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return available;
+ }
+
+ @Override
+ public void destroy() {
+ available = false;
+ chosenFormat = null;
+ // FIXEM: complete code!
+ }
+
+ @Override
+ public AudioFrame enqueueData(final int pts, final ByteBuffer byteBuffer, final int byteCount) {
+ final byte[] bytes = new byte[byteCount];
+ final int p = byteBuffer.position();
+ byteBuffer.get(bytes, 0, byteCount);
+ byteBuffer.position(p);
+
+ int written = 0;
+ int len;
+ int bytesLeft = byteCount;
+ while (bytesLeft > 0) {
+ len = auline.write(bytes, written, byteCount);
+ bytesLeft -= len;
+ written += len;
+ }
+ playImpl();
+ return new AudioDataFrame(pts, Math.round(1000f*chosenFormat.getBytesDuration(byteCount)), byteBuffer, byteCount);
+ }
+
+ @Override
+ public int getQueuedByteCount() {
+ return auline.getBufferSize() - auline.available();
+ }
+
+ @Override
+ public int getFreeFrameCount() {
+ return auline.available();
+ }
+
+ @Override
+ public float getQueuedTime() {
+ return chosenFormat.getBytesDuration( getQueuedByteCount() );
+ }
+
+ @Override
+ public float getAvgFrameDuration() {
+ return 0f;
+ }
+
+ @Override
+ public final int getPTS() { return 0; } // FIXME
+
+}
diff --git a/src/java/jogamp/common/av/NullAudioSink.java b/src/java/jogamp/common/av/NullAudioSink.java
new file mode 100644
index 0000000..904b863
--- /dev/null
+++ b/src/java/jogamp/common/av/NullAudioSink.java
@@ -0,0 +1,211 @@
+/**
+ * Copyright 2013-2023 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.common.av;
+
+import java.nio.ByteBuffer;
+
+import com.jogamp.common.av.AudioFormat;
+import com.jogamp.common.av.AudioSink;
+
+public final class NullAudioSink implements AudioSink {
+
+ private volatile float playSpeed = 1.0f;
+ private volatile boolean playRequested = false;
+ private volatile int playingPTS = AudioFrame.INVALID_PTS;
+ private float volume = 1.0f;
+
+ private AudioFormat chosenFormat;
+ private boolean available;
+
+ public NullAudioSink() {
+ available = true;
+ chosenFormat = null;
+ }
+
+ @Override
+ public final boolean makeCurrent(final boolean throwException) { return true; }
+
+ @Override
+ public final boolean release(final boolean throwException) { return true; }
+
+ @Override
+ public boolean isAvailable() {
+ return available;
+ }
+
+ @Override
+ public final float getPlaySpeed() { return playSpeed; }
+
+ @Override
+ public final boolean setPlaySpeed(float rate) {
+ if( Math.abs(1.0f - rate) < 0.01f ) {
+ rate = 1.0f;
+ }
+ playSpeed = rate;
+ return true;
+ }
+
+ @Override
+ public final float getVolume() {
+ // FIXME
+ return volume;
+ }
+
+ @Override
+ public final boolean setVolume(final float v) {
+ // FIXME
+ volume = v;
+ return true;
+ }
+
+ @Override
+ public int getSourceCount() {
+ return -1;
+ }
+
+ @Override
+ public float getDefaultLatency() {
+ return 0;
+ }
+
+ @Override
+ public float getLatency() {
+ return 0;
+ }
+
+ @Override
+ public AudioFormat getNativeFormat() {
+ return DefaultFormat;
+ }
+
+ @Override
+ public AudioFormat getPreferredFormat() {
+ return DefaultFormat;
+ }
+
+ @Override
+ public void setChannelLimit(final int cc) { }
+
+ @Override
+ public final boolean isSupported(final AudioFormat format) {
+ /**
+ * If we like to emulate constraints ..
+ *
+ if( format.planar || !format.littleEndian ) {
+ return false;
+ }
+ if( format.sampleRate != DefaultFormat.sampleRate ) {
+ return false;
+ }
+ */
+ return true;
+ }
+
+ @Override
+ public boolean init(final AudioFormat requestedFormat, final int frameDuration, final int initialQueueSize, final int queueGrowAmount, final int queueLimit) {
+ chosenFormat = requestedFormat;
+ return true;
+ }
+
+ @Override
+ public final AudioFormat getChosenFormat() {
+ return chosenFormat;
+ }
+
+ @Override
+ public boolean isPlaying() {
+ return playRequested;
+ }
+
+ @Override
+ public void play() {
+ playRequested = true;
+ }
+
+ @Override
+ public void pause() {
+ playRequested = false;
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void destroy() {
+ available = false;
+ chosenFormat = null;
+ }
+
+ @Override
+ public final int getEnqueuedFrameCount() {
+ return 0;
+ }
+
+ @Override
+ public int getFrameCount() {
+ return 0;
+ }
+
+ @Override
+ public int getQueuedFrameCount() {
+ return 0;
+ }
+
+ @Override
+ public int getQueuedByteCount() {
+ return 0;
+ }
+
+ @Override
+ public float getQueuedTime() {
+ return 0f;
+ }
+
+ @Override
+ public float getAvgFrameDuration() {
+ return 0f;
+ }
+
+ @Override
+ public final int getPTS() { return playingPTS; }
+
+ @Override
+ public int getFreeFrameCount() {
+ return 1;
+ }
+
+ @Override
+ public AudioFrame enqueueData(final int pts, final ByteBuffer bytes, final int byteCount) {
+ if( !available || null == chosenFormat ) {
+ return null;
+ }
+ playingPTS = pts;
+ return null;
+ }
+}
diff --git a/src/java/jogamp/common/os/PlatformPropsImpl.java b/src/java/jogamp/common/os/PlatformPropsImpl.java
index 1d38f30..aedf288 100644
--- a/src/java/jogamp/common/os/PlatformPropsImpl.java
+++ b/src/java/jogamp/common/os/PlatformPropsImpl.java
@@ -6,7 +6,6 @@ import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
-import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List;
@@ -23,6 +22,7 @@ import com.jogamp.common.os.Platform.ABIType;
import com.jogamp.common.os.Platform.CPUFamily;
import com.jogamp.common.os.Platform.CPUType;
import com.jogamp.common.os.Platform.OSType;
+import com.jogamp.common.util.SecurityUtil;
import com.jogamp.common.util.VersionNumber;
/**
@@ -38,16 +38,6 @@ import com.jogamp.common.util.VersionNumber;
public abstract class PlatformPropsImpl {
static final boolean DEBUG = Debug.debug("Platform");
- /** Selected {@link Platform.OSType#MACOS} or {@link Platform.OSType#IOS} {@link VersionNumber}s. */
- public static class OSXVersion {
- /** OSX Tiger, i.e. 10.4.0 */
- public static final VersionNumber Tiger = new VersionNumber(10,4,0);
- /** OSX Lion, i.e. 10.7.0 */
- public static final VersionNumber Lion = new VersionNumber(10,7,0);
- /** OSX Mavericks, i.e. 10.9.0 */
- public static final VersionNumber Mavericks = new VersionNumber(10,9,0);
- }
-
/**
* Returns {@code true} if the given {@link CPUType}s and {@link ABIType}s are compatible.
*/
@@ -59,15 +49,6 @@ public abstract class PlatformPropsImpl {
// static initialization order:
//
- /** Version 1.6. As a JVM version, it enables certain JVM 1.6 features. */
- public static final VersionNumber Version16;
- /** Version 1.7. As a JVM version, it enables certain JVM 1.7 features. */
- public static final VersionNumber Version17;
- /** Version 1.8. As a JVM version, it enables certain JVM 1.8 features. */
- public static final VersionNumber Version18;
- /** Version 1.9. As a JVM version, it enables certain JVM 1.9 features. Note the skipped first version number due to JEP 223. */
- public static final VersionNumber Version9;
-
public static final String OS;
public static final String OS_lower;
public static final String OS_VERSION;
@@ -93,10 +74,11 @@ public abstract class PlatformPropsImpl {
* </p>
*/
public static final boolean JAVA_6;
+
/**
* True only if being compatible w/ language level 9, e.g. JRE 9.
* <p>
- * Implies {@link #isJavaSE()} and {@link #JAVA_6}.
+ * Implies {@link #JAVA_6} and {@link #isJavaSE()}
* </p>
* <p>
* Since JRE 9, the version string has dropped the major release number,
@@ -105,6 +87,22 @@ public abstract class PlatformPropsImpl {
*/
public static final boolean JAVA_9;
+ /**
+ * True only if being compatible w/ language level 17, e.g. JRE 17 (LTS).
+ * <p>
+ * Implies {@link #JAVA_9}, {@link #JAVA_6} and {@link #isJavaSE()}
+ * </p>
+ */
+ public static final boolean JAVA_17;
+
+ /**
+ * True only if being compatible w/ language level 21, e.g. JRE 21 (LTS).
+ * <p>
+ * Implies {@link #JAVA_17}, {@link #JAVA_9}, {@link #JAVA_6} and {@link #isJavaSE()}
+ * </p>
+ */
+ public static final boolean JAVA_21;
+
public static final String NEWLINE;
public static final boolean LITTLE_ENDIAN;
@@ -122,11 +120,6 @@ public abstract class PlatformPropsImpl {
public static final boolean useDynamicLibraries;
static {
- Version16 = new VersionNumber(1, 6, 0);
- Version17 = new VersionNumber(1, 7, 0);
- Version18 = new VersionNumber(1, 8, 0);
- Version9 = new VersionNumber(9, 0, 0);
-
// We don't seem to need an AccessController.doPrivileged() block
// here as these system properties are visible even to unsigned Applets.
final boolean isAndroid = AndroidVersion.isAvailable; // also triggers it's static initialization
@@ -154,9 +147,41 @@ public abstract class PlatformPropsImpl {
JAVA_VM_NAME = System.getProperty("java.vm.name");
JAVA_RUNTIME_NAME = getJavaRuntimeNameImpl();
JAVA_SE = initIsJavaSE();
- JAVA_9 = JAVA_SE && JAVA_VERSION_NUMBER.compareTo(Version9) >= 0;
- JAVA_6 = JAVA_SE && ( isAndroid || JAVA_9 || JAVA_VERSION_NUMBER.compareTo(Version16) >= 0 ) ;
-
+ if( JAVA_SE ) {
+ if( JAVA_VERSION_NUMBER.compareTo(new VersionNumber(21, 0, 0)) >= 0 ) {
+ JAVA_21 = true;
+ JAVA_17 = true;
+ JAVA_9 = true;
+ JAVA_6 = true;
+ } else if( JAVA_VERSION_NUMBER.compareTo(new VersionNumber(17, 0, 0)) >= 0 ) {
+ JAVA_21 = false;
+ JAVA_17 = true;
+ JAVA_9 = true;
+ JAVA_6 = true;
+ } else if( JAVA_VERSION_NUMBER.compareTo(new VersionNumber(9, 0, 0)) >= 0 ) {
+ JAVA_21 = false;
+ JAVA_17 = false;
+ JAVA_9 = true;
+ JAVA_6 = true;
+ } else if( isAndroid || JAVA_VERSION_NUMBER.compareTo(new VersionNumber(1, 6, 0)) >= 0 ) {
+ JAVA_21 = false;
+ JAVA_17 = false;
+ JAVA_9 = false;
+ JAVA_6 = true;
+ } else {
+ // we probably don't support anything below 1.6
+ JAVA_21 = false;
+ JAVA_17 = false;
+ JAVA_9 = false;
+ JAVA_6 = false;
+ }
+ } else {
+ // we probably don't support anything below 1.6 or non JavaSE
+ JAVA_21 = false;
+ JAVA_17 = false;
+ JAVA_9 = false;
+ JAVA_6 = false;
+ }
NEWLINE = System.getProperty("line.separator");
OS = System.getProperty("os.name");
@@ -177,7 +202,7 @@ public abstract class PlatformPropsImpl {
final ABIType[] _elfAbiType = { null };
final int[] _elfLittleEndian = { 0 }; // 1 - little, 2 - big
final boolean[] _elfValid = { false };
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
RandomAccessFile in = null;
@@ -353,7 +378,7 @@ public abstract class PlatformPropsImpl {
private static final String getJavaRuntimeNameImpl() {
// the fast path, check property Java SE instead of traversing through the ClassLoader
- return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ return SecurityUtil.doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() {
return System.getProperty("java.runtime.name");
diff --git a/src/junit/com/jogamp/common/nio/TestByteBufferInputStream.java b/src/junit/com/jogamp/common/nio/TestByteBufferInputStream.java
index 90a954b..bbe815d 100644
--- a/src/junit/com/jogamp/common/nio/TestByteBufferInputStream.java
+++ b/src/junit/com/jogamp/common/nio/TestByteBufferInputStream.java
@@ -265,7 +265,7 @@ public class TestByteBufferInputStream extends SingletonJunitCase {
final long t1 = System.currentTimeMillis();
final File out = new File(fileOut);
- IOUtil.copyStream2File(bis, out, -1);
+ IOUtil.copyStream2File(bis, out);
final long t2 = System.currentTimeMillis();
final String suffix;
diff --git a/src/junit/com/jogamp/common/util/IntIntHashMapTest.java b/src/junit/com/jogamp/common/util/IntIntHashMapTest.java
index dc523f0..647e471 100644
--- a/src/junit/com/jogamp/common/util/IntIntHashMapTest.java
+++ b/src/junit/com/jogamp/common/util/IntIntHashMapTest.java
@@ -39,6 +39,7 @@ import java.util.Map.Entry;
import org.junit.BeforeClass;
import org.junit.Test;
+import com.jogamp.common.os.Clock;
import com.jogamp.common.os.Platform;
import com.jogamp.junit.util.SingletonJunitCase;
@@ -254,54 +255,54 @@ public class IntIntHashMapTest extends SingletonJunitCase {
" warmup: " + warmup);
out.println("put");
- long time = nanoTime();
+ long time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
intmap.put(pairs.keys[i], pairs.values[i]);
}
- final long intmapPutTime = (nanoTime() - time);
+ final long intmapPutTime = (Clock.currentNanos() - time);
out.println(" iimap: " + intmapPutTime/1000000.0f+"ms");
- time = nanoTime();
+ time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
map.put(pairs.keys[i], pairs.values[i]);
}
- final long mapPutTime = (nanoTime() - time);
+ final long mapPutTime = (Clock.currentNanos() - time);
out.println(" map: " + mapPutTime/1000000.0f+"ms");
System.out.println();
System.out.println("get");
- time = nanoTime();
+ time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
intmap.get(pairs.keys[i]);
}
- final long intmapGetTime = (nanoTime() - time);
+ final long intmapGetTime = (Clock.currentNanos() - time);
out.println(" iimap: " + intmapGetTime/1000000.0f+"ms");
- time = nanoTime();
+ time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
map.get(pairs.keys[i]);
}
- final long mapGetTime = (nanoTime() - time);
+ final long mapGetTime = (Clock.currentNanos() - time);
out.println(" map: " + mapGetTime/1000000.0f+"ms");
out.println();
out.println("remove");
- time = nanoTime();
+ time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
intmap.remove(pairs.keys[i]);
}
assertEquals(0, intmap.size());
- final long intmapRemoveTime = (nanoTime() - time);
+ final long intmapRemoveTime = (Clock.currentNanos() - time);
out.println(" iimap: " + intmapRemoveTime/1000000.0f+"ms");
- time = nanoTime();
+ time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
map.remove(pairs.keys[i]);
}
assertEquals(0, map.size());
- final long mapRemoveTime = (nanoTime() - time);
+ final long mapRemoveTime = (Clock.currentNanos() - time);
out.println(" map: " + mapRemoveTime/1000000.0f+"ms");
if(!warmup) {
diff --git a/src/junit/com/jogamp/common/util/LongIntHashMapTest.java b/src/junit/com/jogamp/common/util/LongIntHashMapTest.java
index 9ea4206..60f404d 100644
--- a/src/junit/com/jogamp/common/util/LongIntHashMapTest.java
+++ b/src/junit/com/jogamp/common/util/LongIntHashMapTest.java
@@ -39,6 +39,7 @@ import java.util.Map.Entry;
import org.junit.BeforeClass;
import org.junit.Test;
+import com.jogamp.common.os.Clock;
import com.jogamp.common.os.Platform;
import com.jogamp.junit.util.SingletonJunitCase;
@@ -143,55 +144,55 @@ public class LongIntHashMapTest extends SingletonJunitCase {
" warmup: " + warmup);
out.println("put");
- long time = nanoTime();
+ long time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
intmap.put(pairs.keys[i], pairs.values[i]);
}
- final long intmapPutTime = (nanoTime() - time);
+ final long intmapPutTime = (Clock.currentNanos() - time);
out.println(" iimap: " + intmapPutTime/1000000.0f+"ms");
- time = nanoTime();
+ time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
map.put(pairs.keys[i], pairs.values[i]);
}
- final long mapPutTime = (nanoTime() - time);
+ final long mapPutTime = (Clock.currentNanos() - time);
out.println(" map: " + mapPutTime/1000000.0f+"ms");
System.out.println();
System.out.println("get");
- time = nanoTime();
+ time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
intmap.get(pairs.keys[i]);
}
- final long intmapGetTime = (nanoTime() - time);
+ final long intmapGetTime = (Clock.currentNanos() - time);
out.println(" iimap: " + intmapGetTime/1000000.0f+"ms");
- time = nanoTime();
+ time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
map.get(pairs.keys[i]);
}
- final long mapGetTime = (nanoTime() - time);
+ final long mapGetTime = (Clock.currentNanos() - time);
out.println(" map: " + mapGetTime/1000000.0f+"ms");
out.println();
out.println("remove");
- time = nanoTime();
+ time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
intmap.remove(pairs.keys[i]);
}
assertEquals(0, intmap.size());
- final long intmapRemoveTime = (nanoTime() - time);
+ final long intmapRemoveTime = (Clock.currentNanos() - time);
out.println(" iimap: " + intmapRemoveTime/1000000.0f+"ms");
- time = nanoTime();
+ time = Clock.currentNanos();
for (int i = 0; i < iterations; i++) {
map.remove(pairs.keys[i]);
}
assertEquals(0, map.size());
- final long mapRemoveTime = (nanoTime() - time);
+ final long mapRemoveTime = (Clock.currentNanos() - time);
out.println(" map: " + mapRemoveTime/1000000.0f+"ms");
if(!warmup) {
diff --git a/src/junit/com/jogamp/common/util/TestIOUtil01.java b/src/junit/com/jogamp/common/util/TestIOUtil01.java
index 19bc8b0..c0e26a9 100644
--- a/src/junit/com/jogamp/common/util/TestIOUtil01.java
+++ b/src/junit/com/jogamp/common/util/TestIOUtil01.java
@@ -221,6 +221,118 @@ public class TestIOUtil01 extends SingletonJunitCase {
}
}
+ @Test
+ public void test21CopyStreamChunk01Buffer() throws IOException {
+ final URLConnection urlConn = IOUtil.getResource(tfilename, this.getClass().getClassLoader(), this.getClass());
+ Assert.assertNotNull(urlConn);
+ final BufferedInputStream bis = new BufferedInputStream( urlConn.getInputStream() );
+ final ByteBuffer bb;
+ final int skipBytes = 0;
+ final int byteCount = orig.length;
+ try {
+ bb = IOUtil.copyStreamChunk2ByteBuffer( bis, skipBytes, byteCount );
+ } finally {
+ IOUtil.close(bis, false);
+ }
+ Assert.assertTrue( machine.pageAlignedSize( byteCount ) >= byteCount );
+ Assert.assertEquals( machine.pageAlignedSize( byteCount ), bb.capacity() );
+ Assert.assertEquals(orig.length, bb.limit());
+ int i;
+ for(i=tsz-1; i>=0 && orig[i]==bb.get(i); i--) ;
+ Assert.assertTrue("Bytes not equal orig vs array", 0>i);
+ System.err.println(getTestMethodName()+" OK: ["+skipBytes+".."+(skipBytes+byteCount)+"): "+bb);
+ }
+
+ @Test
+ public void test22CopyStreamChunk02Buffer() throws IOException {
+ final URLConnection urlConn = IOUtil.getResource(tfilename, this.getClass().getClassLoader(), this.getClass());
+ Assert.assertNotNull(urlConn);
+ final BufferedInputStream bis = new BufferedInputStream( urlConn.getInputStream() );
+ final ByteBuffer bb;
+ final int skipBytes = 0;
+ final int byteCount = orig.length + machine.pageSizeInBytes(); // expect more data than exists, complete with actual data
+ try {
+ bb = IOUtil.copyStreamChunk2ByteBuffer( bis, skipBytes, byteCount );
+ } finally {
+ IOUtil.close(bis, false);
+ }
+ Assert.assertTrue( machine.pageAlignedSize( byteCount ) >= byteCount );
+ Assert.assertEquals( machine.pageAlignedSize( byteCount ), bb.capacity() );
+ Assert.assertEquals( orig.length, bb.limit() );
+ int i;
+ for(i=tsz-1; i>=0 && orig[i]==bb.get(i); i--) ;
+ Assert.assertTrue("Bytes not equal orig vs array", 0>i);
+ System.err.println(getTestMethodName()+" OK: ["+skipBytes+".."+(skipBytes+byteCount)+"): "+bb);
+ }
+
+ @Test
+ public void test23CopyStreamChunk03Buffer() throws IOException {
+ final URLConnection urlConn = IOUtil.getResource(tfilename, this.getClass().getClassLoader(), this.getClass());
+ Assert.assertNotNull(urlConn);
+ final BufferedInputStream bis = new BufferedInputStream( urlConn.getInputStream() );
+ final ByteBuffer bb;
+ final int skipBytes = 0;
+ final int byteCount = orig.length / 2; // take less data than exists
+ Assert.assertTrue( orig.length >= byteCount );
+ try {
+ bb = IOUtil.copyStreamChunk2ByteBuffer( bis, skipBytes, byteCount );
+ } finally {
+ IOUtil.close(bis, false);
+ }
+ Assert.assertTrue( machine.pageAlignedSize( byteCount ) >= byteCount );
+ Assert.assertEquals( machine.pageAlignedSize( byteCount ), bb.capacity() );
+ Assert.assertEquals( byteCount, bb.limit() );
+ int i;
+ for(i=byteCount-1; i>=0 && orig[i]==bb.get(i); i--) ;
+ Assert.assertTrue("Bytes not equal orig vs array", 0>i);
+ System.err.println(getTestMethodName()+" OK: ["+skipBytes+".."+(skipBytes+byteCount)+"): "+bb);
+ }
+
+ @Test
+ public void test24CopyStreamChunk04Buffer() throws IOException {
+ final URLConnection urlConn = IOUtil.getResource(tfilename, this.getClass().getClassLoader(), this.getClass());
+ Assert.assertNotNull(urlConn);
+ final BufferedInputStream bis = new BufferedInputStream( urlConn.getInputStream() );
+ final ByteBuffer bb;
+ final int skipBytes = orig.length / 2;
+ final int byteCount = orig.length / 4; // take less data than exists
+ Assert.assertTrue( orig.length >= skipBytes + byteCount );
+ Assert.assertTrue( orig.length >= byteCount );
+ try {
+ bb = IOUtil.copyStreamChunk2ByteBuffer( bis, skipBytes, byteCount );
+ } finally {
+ IOUtil.close(bis, false);
+ }
+ Assert.assertTrue( machine.pageAlignedSize( byteCount ) >= byteCount );
+ Assert.assertEquals( machine.pageAlignedSize( byteCount ), bb.capacity() );
+ Assert.assertEquals( byteCount, bb.limit() );
+ int i;
+ for(i=byteCount-1; i>=0 && orig[skipBytes+i]==bb.get(i); i--) ;
+ Assert.assertTrue("Bytes not equal orig vs array", 0>i);
+ System.err.println(getTestMethodName()+" OK: ["+skipBytes+".."+(skipBytes+byteCount)+"): "+bb);
+ }
+
+ @Test
+ public void test25CopyStreamChunk05Buffer() throws IOException {
+ final URLConnection urlConn = IOUtil.getResource(tfilename, this.getClass().getClassLoader(), this.getClass());
+ Assert.assertNotNull(urlConn);
+ final BufferedInputStream bis = new BufferedInputStream( urlConn.getInputStream() );
+ final ByteBuffer bb;
+ final int skipBytes = orig.length * 2; // skip all and more ..
+ final int byteCount = orig.length; // expect more data than left, won't take anything
+ Assert.assertTrue( orig.length < skipBytes + byteCount );
+ Assert.assertTrue( orig.length >= byteCount );
+ try {
+ bb = IOUtil.copyStreamChunk2ByteBuffer( bis, skipBytes, byteCount );
+ } finally {
+ IOUtil.close(bis, false);
+ }
+ Assert.assertTrue( machine.pageAlignedSize( byteCount ) >= byteCount );
+ Assert.assertEquals( machine.pageAlignedSize( byteCount ), bb.capacity() );
+ Assert.assertEquals( 0, bb.limit() );
+ System.err.println(getTestMethodName()+" OK: ["+skipBytes+".."+(skipBytes+byteCount)+"): "+bb);
+ }
+
public static void main(final String args[]) throws IOException {
final String tstname = TestIOUtil01.class.getName();
org.junit.runner.JUnitCore.main(tstname);
diff --git a/src/junit/com/jogamp/common/util/TestIteratorIndexCORE.java b/src/junit/com/jogamp/common/util/TestIteratorIndexCORE.java
index 8289587..70cb06b 100644
--- a/src/junit/com/jogamp/common/util/TestIteratorIndexCORE.java
+++ b/src/junit/com/jogamp/common/util/TestIteratorIndexCORE.java
@@ -45,7 +45,7 @@ public class TestIteratorIndexCORE extends SingletonJunitCase {
static int elems = 10;
static int loop = ( Platform.getCPUFamily() == Platform.CPUFamily.ARM ) ? 20 : 9999999;
- public void populate(final List l, int len) {
+ public void populate(final List<Integer> l, int len) {
while(len>0) {
l.add(new Integer(len--));
}
@@ -54,12 +54,12 @@ public class TestIteratorIndexCORE extends SingletonJunitCase {
@Test
public void test01ArrayListIterator() {
int sum=0;
- final ArrayList l = new ArrayList();
+ final ArrayList<Integer> l = new ArrayList<Integer>();
populate(l, elems);
for(int j=loop; j>0; j--) {
- for(final Iterator iter = l.iterator(); iter.hasNext(); ) {
- final Integer i = (Integer)iter.next();
+ for(final Iterator<Integer> iter = l.iterator(); iter.hasNext(); ) {
+ final Integer i = iter.next();
sum+=i.intValue();
}
}
@@ -69,12 +69,12 @@ public class TestIteratorIndexCORE extends SingletonJunitCase {
@Test
public void test0ArrayListIndex() {
int sum=0;
- final ArrayList l = new ArrayList();
+ final ArrayList<Integer> l = new ArrayList<Integer>();
populate(l, elems);
for(int j=loop; j>0; j--) {
for(int k = 0; k < l.size(); k++) {
- final Integer i = (Integer)l.get(k);
+ final Integer i = l.get(k);
sum+=i.intValue();
}
}
@@ -84,12 +84,12 @@ public class TestIteratorIndexCORE extends SingletonJunitCase {
@Test
public void test01LinkedListListIterator() {
int sum=0;
- final LinkedList l = new LinkedList();
+ final LinkedList<Integer> l = new LinkedList<Integer>();
populate(l, elems);
for(int j=loop; j>0; j--) {
- for(final Iterator iter = l.iterator(); iter.hasNext(); ) {
- final Integer i = (Integer)iter.next();
+ for(final Iterator<Integer> iter = l.iterator(); iter.hasNext(); ) {
+ final Integer i = iter.next();
sum+=i.intValue();
}
}
@@ -99,12 +99,12 @@ public class TestIteratorIndexCORE extends SingletonJunitCase {
@Test
public void test01LinkedListListIndex() {
int sum=0;
- final LinkedList l = new LinkedList();
+ final LinkedList<Integer> l = new LinkedList<Integer>();
populate(l, elems);
for(int j=loop; j>0; j--) {
for(int k = 0; k < l.size(); k++) {
- final Integer i = (Integer)l.get(k);
+ final Integer i = l.get(k);
sum+=i.intValue();
}
}
diff --git a/src/junit/com/jogamp/common/util/locks/TestRecursiveLock01.java b/src/junit/com/jogamp/common/util/locks/TestRecursiveLock01.java
index 7455618..e119569 100644
--- a/src/junit/com/jogamp/common/util/locks/TestRecursiveLock01.java
+++ b/src/junit/com/jogamp/common/util/locks/TestRecursiveLock01.java
@@ -37,6 +37,7 @@ import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
+import com.jogamp.common.os.Clock;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.InterruptSource;
import com.jogamp.junit.util.SingletonJunitCase;
@@ -57,7 +58,7 @@ public class TestRecursiveLock01 extends SingletonJunitCase {
}
}
- static void yield(final YieldMode mode) {
+ static void yield_thread(final YieldMode mode) {
switch(mode) {
case YIELD:
Thread.yield();
@@ -119,7 +120,7 @@ public class TestRecursiveLock01 extends SingletonJunitCase {
System.err.print("+");
}
while(l>0) l--;
- yield(yieldMode);
+ yield_thread(yieldMode);
} finally {
if(DEBUG) {
System.err.print("-");
@@ -141,6 +142,7 @@ public class TestRecursiveLock01 extends SingletonJunitCase {
incrDeferredThreadCount();
}
+ @Override
public void run() {
if(DEBUG) {
System.err.print("[a2");
@@ -151,7 +153,7 @@ public class TestRecursiveLock01 extends SingletonJunitCase {
System.err.print("+");
}
while(l>0) l--;
- yield(yieldMode);
+ yield_thread(yieldMode);
} finally {
if(DEBUG) {
System.err.print("-");
@@ -175,9 +177,9 @@ public class TestRecursiveLock01 extends SingletonJunitCase {
}
public final void lock() {
- long td = System.nanoTime();
+ long td = Clock.currentNanos();
locker.lock();
- td = System.nanoTime() - td;
+ td = Clock.currentNanos() - td;
final String cur = Thread.currentThread().getName();
ThreadStat ts = threadWaitMap.get(cur);
@@ -258,14 +260,17 @@ public class TestRecursiveLock01 extends SingletonJunitCase {
this.yieldMode = yieldMode;
}
+ @Override
public final void stop() {
shouldStop = true;
}
+ @Override
public final boolean isStopped() {
return stopped;
}
+ @Override
public void waitUntilStopped() {
synchronized(this) {
while(!stopped) {
@@ -279,6 +284,7 @@ public class TestRecursiveLock01 extends SingletonJunitCase {
}
+ @Override
public void run() {
synchronized(this) {
while(!shouldStop && loops>0) {
diff --git a/src/junit/com/jogamp/common/util/locks/TestRecursiveThreadGroupLock01.java b/src/junit/com/jogamp/common/util/locks/TestRecursiveThreadGroupLock01.java
index 30a0274..3cd40dd 100644
--- a/src/junit/com/jogamp/common/util/locks/TestRecursiveThreadGroupLock01.java
+++ b/src/junit/com/jogamp/common/util/locks/TestRecursiveThreadGroupLock01.java
@@ -53,7 +53,7 @@ public class TestRecursiveThreadGroupLock01 extends SingletonJunitCase {
}
}
- static void yield(final YieldMode mode) {
+ static void yield_thread(final YieldMode mode) {
switch(mode) {
case YIELD:
Thread.yield();
@@ -96,7 +96,7 @@ public class TestRecursiveThreadGroupLock01 extends SingletonJunitCase {
slaves[i].start();
}
while(slaveCounter<mark) {
- yield(yieldMode);
+ yield_thread(yieldMode);
}
}
} finally {
@@ -130,7 +130,7 @@ public class TestRecursiveThreadGroupLock01 extends SingletonJunitCase {
while(slaveCounter<mark) {
slaveCounter++;
} */
- yield(yieldMode);
+ yield_thread(yieldMode);
} finally {
if(DEBUG) {
System.err.println(tab+" "+name+" c "+slaveCounter+"]");
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java b/src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java
index 47e392a..6b841ad 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/BindingJNILibLoader.java
@@ -29,27 +29,31 @@
package com.jogamp.gluegen.test.junit.generation;
import com.jogamp.common.jvm.JNILibLoaderBase;
+import com.jogamp.common.util.SecurityUtil;
+
import java.security.*;
public class BindingJNILibLoader extends JNILibLoaderBase {
- public static void loadBindingtest1p1() {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- loadLibrary("Bindingtest1p1", null, true, BindingJNILibLoader.class.getClassLoader());
- return null;
- }
- });
- }
-
- public static void loadBindingtest1p2() {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- loadLibrary("Bindingtest1p2", null, true, BindingJNILibLoader.class.getClassLoader());
- return null;
- }
- });
- }
+ public static void loadBindingtest1p1() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ loadLibrary("Bindingtest1p1", null, true, BindingJNILibLoader.class.getClassLoader());
+ return null;
+ }
+ });
+ }
+
+ public static void loadBindingtest1p2() {
+ SecurityUtil.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ loadLibrary("Bindingtest1p2", null, true, BindingJNILibLoader.class.getClassLoader());
+ return null;
+ }
+ });
+ }
}
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h
index 4896165..9465cd9 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h
@@ -299,8 +299,8 @@ MYAPI MYAPIConfig * MYAPIENTRY typeTestAnonPointer(const MYAPIConfig * a);
#define HUGE_VALF_3 ((int) 1e53)
#define DOUBLE_DEFINE_BRACKETS_3 HUGE_VALF_3
-size_t unsigned_size_t_1;
-ptrdiff_t a_signed_pointer_t_1;
+extern size_t unsigned_size_t_1;
+extern ptrdiff_t a_signed_pointer_t_1;
MYAPI int32_t MYAPIENTRY typeTestInt32T(const int32_t i1, int32_t i2);
MYAPI uint32_t MYAPIENTRY typeTestUInt32T(const uint32_t ui1, uint32_t ui2);
@@ -462,8 +462,8 @@ typedef struct {
TK_Context ctx;
- const char modelNameArrayFixedLen[12]; /* 'Hello Array' len=11+1 */
- const char * modelNamePointerCString; /* 'Hello CString' len=13+1 */
+ char modelNameArrayFixedLen[12]; /* 'Hello Array' len=11+1 */
+ char * modelNamePointerCString; /* 'Hello CString' len=13+1 */
const char * modelNamePointerCustomLen; /* 'Hello Pointer' len=13+1 */
const int modelNamePointerCustomLenVal; /* 13+1 */
@@ -495,7 +495,7 @@ typedef struct {
TK_Context ctx;
char modelNameArrayFixedLen[12]; /* 'Hello Array' len=11+1 */
- const char * modelNamePointerCString; /* 'Hello CString' len=13+1 */
+ char * modelNamePointerCString; /* 'Hello CString' len=13+1 */
char * modelNamePointerCustomLen; /* 'Hello Pointer' len=13+1 */
int modelNamePointerCustomLenVal; /* 13+1 */
diff --git a/src/junit/com/jogamp/junit/util/MiscUtils.java b/src/junit/com/jogamp/junit/util/MiscUtils.java
index 3576fed..03d4d13 100644
--- a/src/junit/com/jogamp/junit/util/MiscUtils.java
+++ b/src/junit/com/jogamp/junit/util/MiscUtils.java
@@ -103,7 +103,7 @@ public class MiscUtils {
}
final InputStream in = new BufferedInputStream(new FileInputStream(src));
try {
- stats.totalBytes += IOUtil.copyStream2File(in, dest, 0);
+ stats.totalBytes += IOUtil.copyStream2File(in, dest);
} finally {
in.close();
}
diff --git a/src/native/common/Platforms.c b/src/native/common/Platforms.c
deleted file mode 100644
index f48d020..0000000
--- a/src/native/common/Platforms.c
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#include <jni.h>
-
-#include <assert.h>
-
-#include <gluegen_stdint.h>
-
-#include "com_jogamp_common_os_Platform.h"
-
-#include <sys/time.h>
-
-JNIEXPORT jlong JNICALL
-Java_com_jogamp_common_os_Platform_currentTimeMillis(JNIEnv *env, jclass _unused) {
- struct timeval tv;
- gettimeofday(&tv,NULL);
- return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_jogamp_common_os_Platform_currentTimeMicros(JNIEnv *env, jclass _unused) {
- struct timeval tv;
- gettimeofday(&tv,NULL);
- return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
-}
-
diff --git a/src/native/common/jau_sys_Clock.c b/src/native/common/jau_sys_Clock.c
new file mode 100644
index 0000000..e8a7210
--- /dev/null
+++ b/src/native/common/jau_sys_Clock.c
@@ -0,0 +1,292 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2020-2023 Gothel Software e.K.
+ * Copyright (c) 2020-2023 JogAmp Community.
+ * Copyright (c) 2020 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <jni.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <assert.h>
+
+#include <gluegen_stdint.h>
+
+#include "com_jogamp_common_os_Clock.h"
+
+#include <time.h>
+
+#if defined(_WIN32)
+ #include <windows.h>
+ #ifndef IN_WINPTHREAD
+ #define IN_WINPTHREAD 1
+ #endif
+ #include "pthread.h"
+ #include "pthread_time.h"
+#endif
+
+static const int64_t NanoPerMilli = 1000000L;
+static const int64_t MilliPerOne = 1000L;
+static const int64_t NanoPerSec = 1000000000L;
+
+static struct timespec startup_t = { .tv_sec = 0, .tv_nsec = 0 };
+
+static void throwNewRuntimeException(JNIEnv *env, const char* msg, ...) {
+ char buffer[512];
+ va_list ap;
+
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
+
+ fprintf(stderr, "RuntimeException: %s\n", buffer);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/RuntimeException"), buffer);
+ }
+ }
+}
+
+static jboolean throwNewRuntimeExceptionOnException(JNIEnv *env) {
+ if( (*env)->ExceptionCheck(env) ) {
+ (*env)->ExceptionDescribe(env);
+ (*env)->ExceptionClear(env);
+ throwNewRuntimeException(env, "An exception occured from JNI as shown.");
+ return JNI_TRUE;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_com_jogamp_common_os_Clock_getMonotonicTimeImpl(JNIEnv *env, jclass clazz, jlongArray jval) {
+ (void)clazz;
+
+ // Avoid GetPrimitiveArrayCritical(), which occasionally hangs on system call ::clock_gettime()
+ struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
+ int res = clock_gettime(CLOCK_MONOTONIC, &t);
+ const jlong val[] = { (jlong)t.tv_sec, (jlong)t.tv_nsec };
+ (*env)->SetLongArrayRegion(env, jval, 0, 2, val);
+ return 0 == res ? JNI_TRUE : JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_com_jogamp_common_os_Clock_getWallClockTimeImpl(JNIEnv *env, jclass clazz, jlongArray jval) {
+ (void)clazz;
+
+ // Avoid GetPrimitiveArrayCritical(), which occasionally hangs on system call ::clock_gettime()
+ struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
+ int res = clock_gettime(CLOCK_REALTIME, &t);
+ const jlong val[] = { (jlong)t.tv_sec, (jlong)t.tv_nsec };
+ (*env)->SetLongArrayRegion(env, jval, 0, 2, val);
+ return 0 == res ? JNI_TRUE : JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_com_jogamp_common_os_Clock_getMonotonicStartupTimeImpl(JNIEnv *env, jclass clazz, jlongArray jval) {
+ (void)clazz;
+
+ // Avoid GetPrimitiveArrayCritical(), which occasionally hangs on system call ::clock_gettime()
+ int res = clock_gettime(CLOCK_MONOTONIC, &startup_t);
+ const jlong val[] = { (jlong)startup_t.tv_sec, (jlong)startup_t.tv_nsec };
+ (*env)->SetLongArrayRegion(env, jval, 0, 2, val);
+ if( throwNewRuntimeExceptionOnException(env) ) {
+ return JNI_FALSE;
+ }
+ return 0 == res ? JNI_TRUE : JNI_FALSE;
+}
+
+/**
+ * See <http://man7.org/linux/man-pages/man2/clock_gettime.2.html>
+ * <p>
+ * Regarding avoiding kernel via VDSO,
+ * see <http://man7.org/linux/man-pages/man7/vdso.7.html>,
+ * clock_gettime seems to be well supported at least on kernel >= 4.4.
+ * Only bfin and sh are missing, while ia64 seems to be complicated.
+ */
+JNIEXPORT jlong JNICALL
+Java_com_jogamp_common_os_Clock_currentNanos(JNIEnv *env, jclass clazz) {
+ (void)env;
+ (void)clazz;
+
+ struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
+ if( 0 == clock_gettime(CLOCK_MONOTONIC, &t) ) {
+ struct timespec d = { .tv_sec = t.tv_sec - startup_t.tv_sec,
+ .tv_nsec = t.tv_nsec - startup_t.tv_nsec };
+ if ( 0 > d.tv_nsec ) {
+ d.tv_nsec += NanoPerSec;
+ d.tv_sec -= 1;
+ }
+ return (jlong) ( (int64_t)d.tv_sec * NanoPerSec + (int64_t)d.tv_nsec );
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * See <http://man7.org/linux/man-pages/man2/clock_gettime.2.html>
+ * <p>
+ * Regarding avoiding kernel via VDSO,
+ * see <http://man7.org/linux/man-pages/man7/vdso.7.html>,
+ * clock_gettime seems to be well supported at least on kernel >= 4.4.
+ * Only bfin and sh are missing, while ia64 seems to be complicated.
+ */
+JNIEXPORT jlong JNICALL
+Java_com_jogamp_common_os_Clock_currentTimeMillis(JNIEnv *env, jclass clazz) {
+ (void)env;
+ (void)clazz;
+
+ struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
+ if( 0 == clock_gettime(CLOCK_MONOTONIC, &t) ) {
+ int64_t res = (int64_t)t.tv_sec * MilliPerOne +
+ (int64_t)t.tv_nsec / NanoPerMilli;
+ return (jlong)res;
+ } else {
+ return 0;
+ }
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_jogamp_common_os_Clock_wallClockSeconds(JNIEnv *env, jclass clazz) {
+ (void)env;
+ (void)clazz;
+
+ struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
+ if( 0 == clock_gettime(CLOCK_REALTIME, &t) ) {
+ return (jlong)( (int64_t)( t.tv_sec ) );
+ } else {
+ return 0;
+ }
+}
+
+#if defined(_WIN32)
+
+#define POW10_7 10000000
+#define POW10_9 1000000000
+
+/* Number of 100ns-seconds between the beginning of the Windows epoch
+ * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970)
+ */
+#define DELTA_EPOCH_IN_100NS INT64_C(116444736000000000)
+
+static WINPTHREADS_INLINE int lc_set_errno(int result)
+{
+ if (result != 0) {
+ errno = result;
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * Source: https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-libraries/winpthreads/src/clock.c
+ * Public Domain within mingw-w64, included here to simplify linkage.
+ *
+ * Get the time of the specified clock clock_id and stores it in the struct
+ * timespec pointed to by tp.
+ * @param clock_id The clock_id argument is the identifier of the particular
+ * clock on which to act. The following clocks are supported:
+ * <pre>
+ * CLOCK_REALTIME System-wide real-time clock. Setting this clock
+ * requires appropriate privileges.
+ * CLOCK_MONOTONIC Clock that cannot be set and represents monotonic
+ * time since some unspecified starting point.
+ * CLOCK_PROCESS_CPUTIME_ID High-resolution per-process timer from the CPU.
+ * CLOCK_THREAD_CPUTIME_ID Thread-specific CPU-time clock.
+ * </pre>
+ * @param tp The pointer to a timespec structure to receive the time.
+ * @return If the function succeeds, the return value is 0.
+ * If the function fails, the return value is -1,
+ * with errno set to indicate the error.
+ */
+int clock_gettime(clockid_t clock_id, struct timespec *tp)
+{
+ unsigned __int64 t;
+ LARGE_INTEGER pf, pc;
+ union {
+ unsigned __int64 u64;
+ FILETIME ft;
+ } ct, et, kt, ut;
+
+ switch(clock_id) {
+ case CLOCK_REALTIME:
+ {
+ GetSystemTimeAsFileTime(&ct.ft);
+ t = ct.u64 - DELTA_EPOCH_IN_100NS;
+ tp->tv_sec = t / POW10_7;
+ tp->tv_nsec = ((int) (t % POW10_7)) * 100;
+
+ return 0;
+ }
+
+ case CLOCK_MONOTONIC:
+ {
+ if (QueryPerformanceFrequency(&pf) == 0)
+ return lc_set_errno(EINVAL);
+
+ if (QueryPerformanceCounter(&pc) == 0)
+ return lc_set_errno(EINVAL);
+
+ tp->tv_sec = pc.QuadPart / pf.QuadPart;
+ tp->tv_nsec = (int) (((pc.QuadPart % pf.QuadPart) * POW10_9 + (pf.QuadPart >> 1)) / pf.QuadPart);
+ if (tp->tv_nsec >= POW10_9) {
+ tp->tv_sec ++;
+ tp->tv_nsec -= POW10_9;
+ }
+
+ return 0;
+ }
+
+ case CLOCK_PROCESS_CPUTIME_ID:
+ {
+ if(0 == GetProcessTimes(GetCurrentProcess(), &ct.ft, &et.ft, &kt.ft, &ut.ft))
+ return lc_set_errno(EINVAL);
+ t = kt.u64 + ut.u64;
+ tp->tv_sec = t / POW10_7;
+ tp->tv_nsec = ((int) (t % POW10_7)) * 100;
+
+ return 0;
+ }
+
+ case CLOCK_THREAD_CPUTIME_ID:
+ {
+ if(0 == GetThreadTimes(GetCurrentThread(), &ct.ft, &et.ft, &kt.ft, &ut.ft))
+ return lc_set_errno(EINVAL);
+ t = kt.u64 + ut.u64;
+ tp->tv_sec = t / POW10_7;
+ tp->tv_nsec = ((int) (t % POW10_7)) * 100;
+
+ return 0;
+ }
+
+ default:
+ break;
+ }
+
+ return lc_set_errno(EINVAL);
+}
+
+#endif
+