From d15ca4d4addcba73f1e9a798e4b742ec090cfd06 Mon Sep 17 00:00:00 2001
From: Ioannis Kappas <ioannis.kappas@gmamil.com>
Date: Sat, 25 Jun 2022 11:58:54 +0100
Subject: [PATCH v6 4/6] Build java-openjfx-media with gstreamer package

Output native lib to lib/openjfx
---
 gnu/packages/java.scm | 216 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 209 insertions(+), 7 deletions(-)

diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index eaf2f94c3e..03e43b47a0 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -70,6 +70,7 @@ (define-module (gnu packages java)
   #:use-module (gnu packages ghostscript) ;lcms
   #:use-module (gnu packages gnome)
   #:use-module (gnu packages groovy)
+  #:use-module (gnu packages gstreamer)
   #:use-module (gnu packages gtk)
   #:use-module (gnu packages guile)
   #:use-module (gnu packages icu4c)
@@ -3323,17 +3324,218 @@ (define-public java-openjfx-swt
 (define-public java-openjfx-media
   (package (inherit java-openjfx-build)
     (name "java-openjfx-media")
+    (native-inputs
+     (list gcc
+           icedtea-8
+           pkg-config))
+    (inputs
+     (list xz ;; workaround for gstreamer's elfutils bug#55793.
+           gstreamer
+           gst-plugins-base))
     (propagated-inputs
-     `(("java-openjxf-graphics" ,java-openjfx-graphics)))
+     (list java-openjfx-graphics))
     (arguments
      `(#:jar-name "java-openjfx-media.jar"
-       #:source-dir "modules/media/src/main/java"
-       #:tests? #f)); no tests
+       #:source-dir "modules/media/src/main/java:modules/media/src/tools/java"
+       ;; no tests available in src
+       #:tests? #f
+       #:modules ((ice-9 match)
+                  (ice-9 regex)
+                  (guix build ant-build-system)
+                  (guix build utils))
+       #:phases
+       (modify-phases %standard-phases
+         (replace 'build
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let ((lib (string-append (assoc-ref outputs "out")
+                                       "/lib/openjfx")))
+               ;; add native libs path to the java.library.path property. Used
+               ;; by the openjfx NativeLibLoader at runtime to locate its
+               ;; libraries.
+               (substitute* "modules/media/src/main/java/com/sun/media/jfxmediaimpl/NativeMediaManager.java"
+                 (((regexp-quote "public class NativeMediaManager {") all)
+                  (string-append
+                   all
+                   "\nstatic {\n"
+                   " String jlp = \""lib":\"+System.getProperty(\"java.library.path\");\n"
+                   " System.setProperty(\"java.library.path\", jlp);\n"
+                   "}\n"))))
+
+             (invoke "ant" "compile" "-Dclasses.dir=modules/media/build/classes/java/main")))
+
+         (add-after 'build 'generate-headers
+           (lambda* (#:key inputs #:allow-other-keys)
+             (let* ((classes "modules/media/build/classes/java/main")
+                    (media-generated-headers "modules/media/build/generated-src/headers")
+                    (media-generated-classes
+                     '("com.sun.media.jfxmedia.logging.Logger"
+                       "com.sun.media.jfxmedia.track.AudioTrack"
+                       "com.sun.media.jfxmedia.control.VideoDataBuffer"
+                       "com.sun.media.jfxmedia.control.VideoFormat$FormatTypes"
+                       "com.sun.media.jfxmediaimpl.NativeAudioClip"
+                       "com.sun.media.jfxmediaimpl.NativeMediaPlayer"
+                       "com.sun.media.jfxmediaimpl.NativeVideoBuffer"
+                       "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTPlatform"
+                       "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMedia"
+                       "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMediaPlayer"
+                       "com.sun.media.jfxmediaimpl.NativeAudioEqualizer"
+                       "com.sun.media.jfxmediaimpl.NativeEqualizerBand"
+                       "com.sun.media.jfxmediaimpl.NativeAudioSpectrum"))
+                    (graphics (assoc-ref inputs "java-openjfx-graphics")))
+               (mkdir-p media-generated-headers)
+               (invoke "java"
+                       "-Djava.ext.dirs="
+                       "-classpath" classes
+                       "headergen.HeaderGen"
+                       (string-append media-generated-headers "/" "jfxmedia_errors.h")
+                       classes)
+               (apply invoke
+                      "javah"
+                      "-Djava.ext.dirs="
+                      "-XDignore.symbol.file"
+                      "-XDuseUnsharedTable=true"
+                      "-d" media-generated-headers
+                      "-cp" (string-join (cons* classes (find-files graphics "\\.jar$")) ":")
+                      media-generated-classes))))
+
+         (add-after 'generate-headers 'media-native-lib
+             (lambda* (#:key inputs #:allow-other-keys)
+               (let* ((classes "modules/media/build/classes/java/main")
+                      (media-gen-headers "modules/media/build/generated-src/headers")
+                      (media-gen-src "modules/media/build/generated-src")
+                      (media-native-lib "modules/media/build/libs/linux/libjfxmedia.so")
+                      (media-native-obj "modules/media/build/native/linux")
+                      ;; ref: modules/media/src/main/native/jfxmedia/projects/linux/Makefile
+                      (media-native-src "modules/media/src/main/native/jfxmedia")
+                      (media-native-src-files
+                       '("jni/com_sun_media_jfxmedia_logging_Logger.cpp"
+                         "jni/JavaBandsHolder.cpp"
+                         "jni/JavaMediaWarningListener.cpp"
+                         "jni/JavaPlayerEventDispatcher.cpp"
+                         "jni/JniUtils.cpp"
+                         "jni/Logger.cpp"
+                         "jni/NativeVideoBuffer.cpp"
+                         "jni/NativeAudioEqualizer.cpp"
+                         "jni/NativeAudioSpectrum.cpp"
+                         "jni/NativeEqualizerBand.cpp"
+                         "jni/JavaInputStreamCallbacks.cpp"
+                         "PipelineManagement/AudioTrack.cpp"
+                         "PipelineManagement/Pipeline.cpp"
+                         "PipelineManagement/PipelineFactory.cpp"
+                         "PipelineManagement/Track.cpp"
+                         "PipelineManagement/VideoFrame.cpp"
+                         "PipelineManagement/VideoTrack.cpp"
+                         "PipelineManagement/SubtitleTrack.cpp"
+                         "MediaManagement/Media.cpp"
+                         "MediaManagement/MediaManager.cpp"
+                         "Locator/Locator.cpp"
+                         "Locator/LocatorStream.cpp"
+                         "Utils/MediaWarningDispatcher.cpp"
+                         "Utils/posix/posix_critical_section.cpp"
+                          "platform/gstreamer/GstMedia.cpp"
+                         "platform/gstreamer/GstMediaPlayer.cpp"
+                         "platform/gstreamer/GstPlatform.cpp"
+                         "platform/gstreamer/GstAudioEqualizer.cpp"
+                         "platform/gstreamer/GstAudioPlaybackPipeline.cpp"
+                         "platform/gstreamer/GstAudioSpectrum.cpp"
+                         "platform/gstreamer/GstAVPlaybackPipeline.cpp"
+                         "platform/gstreamer/GstElementContainer.cpp"
+                         "platform/gstreamer/GstJniUtils.cpp"
+                         "platform/gstreamer/GstMediaManager.cpp"
+                         "platform/gstreamer/GstPipelineFactory.cpp"
+                         "platform/gstreamer/GstVideoFrame.cpp"))
+                      (media-native-src-c "Utils/ColorConverter.c")
+                      (media-src "modules/media/src/main")
+                      (media-classes "modules/media/build/classes")
+                      (jdk (assoc-ref inputs "jdk"))
+                      (gstreamer (assoc-ref inputs "gstreamer"))
+                      (link-flags
+                       '("-pthread"
+                         "-static-libgcc" "-static-libstdc++" "-shared"
+                         "-z" "relro"
+                         "-Wl,--gc-sections"
+                         "$(pkg-config --libs gstreamer-1.0)"
+                         "$(pkg-config --libs gstreamer-plugins-base-1.0)"
+                         "$(pkg-config --libs gstreamer-app-1.0)"))
+                      (cc-flags
+                       `("-pthread"
+                         "-fno-strict-aliasing" "-fPIC" "-fno-omit-frame-pointer" ;; optimization flags
+                         "-fstack-protector"
+                         "-W" "-Wall"
+                         "-DTARGET_OS_LINUX=1"
+                         "-D_GNU_SOURCE"
+                         "-DGST_REMOVE_DEPRECATED"
+                         "-DGST_DISABLE_GST_DEBUG"
+                         "-DGST_DISABLE_LOADSAVE"
+                         "-DGST_DISABLE_XML"
+                         "-DHAVE_CONFIG_H"
+                         "-DJFXMEDIA_JNI_EXPORTS"
+                         "-DLINUX"
+                         "-DG_DISABLE_DEPRECATED"
+                         "-ffunction-sections"
+                         "-fdata-sections"
+                         "-fno-rtti"
+                         "$(pkg-config --cflags gstreamer-1.0)"
+                         "$(pkg-config --cflags gstreamer-plugins-base-1.0)"
+                         "$(pkg-config --cflags gstreamer-app-1.0)"
+                         "-I" ,(string-append jdk "/include")
+                         "-I" ,(string-append jdk "/include/linux"))))
+                 (mkdir-p media-native-obj)
+                 (for-each (lambda (cpp)
+                             (let ((cpp (string-append media-native-src "/" cpp)))
+                               (invoke "bash" "-c"
+                                       (string-join
+                                        (append
+                                         `("g++"
+                                           "-c"
+                                           "-I" ,media-gen-headers
+                                           "-I" ,media-gen-src
+                                           "-I" ,media-native-src
+                                           "-o" ,(string-append media-native-obj
+                                                                "/" (basename cpp ".cpp") ".obj"))
+                                         cc-flags (list cpp))))))
+                           media-native-src-files)
+                 (let ((c (string-append media-native-src "/" media-native-src-c)))
+                   (invoke "bash" "-c"
+                           (string-join
+                            (append
+                             `("g++"
+                               "-c"
+                               "-I" ,media-gen-headers
+                               "-I" ,media-gen-src
+                               "-I" ,media-native-src
+                               "-o" ,(string-append media-native-obj
+                                                    "/" (basename c ".c")
+                                                    ".obj"))
+                             cc-flags (list c)))))
+                 (mkdir-p (dirname media-native-lib))
+                 (invoke "bash" "-c"
+                         (string-join (append
+                                       `("gcc" "-o" ,media-native-lib)
+                                       link-flags
+                                       (find-files media-native-obj "\\.obj$")))))))
+
+         (add-after 'media-native-lib 'build-jar
+           (lambda _
+             (let* ((module (string-append "modules/media"))
+                    (resources (string-append module "/src/main/resources"))
+                    (classes (string-append module "/build/classes/java/main")))
+               (copy-recursively resources classes)
+
+               (invoke "ant" "jar" (string-append "-Dclasses.dir=" classes)))))
+
+         (add-after 'install 'install-native
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let ((lib (string-append (assoc-ref outputs "out") "/lib/openjfx")))
+               (for-each (lambda (file)
+                           (install-file file lib))
+                         (find-files "." "\\.so$"))))))))
+
     (description "OpenJFX is a client application platform for desktop,
-mobile and embedded systems built on Java.  Its goal is to produce a
-modern, efficient, and fully featured toolkit for developing rich client
-applications.  This package contains media-related classes for the
-OpenJFX distribution.")))
+mobile and embedded systems built on Java.  Its goal is to produce a modern,
+efficient, and fully featured toolkit for developing rich client applications.
+This package contains the set of classes for integrating audio and video into
+Java FX Applications.")))
 
 (define-public java-openjfx-controls
   (package (inherit java-openjfx-build)
-- 
2.34.0

