Use JavaFX Gradle plugin for proper module path setup
Replace manual classifier-based jar deps with the openjfx javafx-plugin which correctly sets up the JavaFX module path, native lib paths, and JVM args needed for media codecs (AVFoundation on macOS). This fixes 'media type not supported' which was caused by JavaFX being on classpath instead of module path — native .dylib codecs only load when JavaFX runs as a named module.
This commit is contained in:
@@ -44,9 +44,6 @@ fun LivePhotoPlayer(
|
||||
|
||||
log.info("LivePhotoPlayer: loading ${file.name} (${file.length() / 1024}KB)")
|
||||
|
||||
// Extract JavaFX native media libs from jar if needed
|
||||
extractJavafxNativeLibs()
|
||||
|
||||
val media = javafx.scene.media.Media(file.toURI().toString())
|
||||
val player = javafx.scene.media.MediaPlayer(media)
|
||||
|
||||
@@ -94,58 +91,3 @@ fun isJavaFxMediaAvailable(): Boolean {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract JavaFX native libraries from the classpath jars to a temp directory
|
||||
* and add that directory to java.library.path.
|
||||
*
|
||||
* This is needed when OpenJFX is loaded from classpath (not module path) —
|
||||
* the native .dylib/.so files inside the jar need to be extracted for the
|
||||
* media codecs (AVFoundation on macOS) to load correctly.
|
||||
*/
|
||||
private var nativeLibsExtracted = false
|
||||
|
||||
private fun extractJavafxNativeLibs() {
|
||||
if (nativeLibsExtracted) return
|
||||
nativeLibsExtracted = true
|
||||
|
||||
try {
|
||||
val tmpDir = File(System.getProperty("java.io.tmpdir"), "photophetch-javafx-natives")
|
||||
tmpDir.mkdirs()
|
||||
|
||||
// Find the javafx-media jar on the classpath
|
||||
val classLoader = Thread.currentThread().contextClassLoader
|
||||
val mediaClass = classLoader.loadClass("javafx.scene.media.MediaPlayer")
|
||||
val codeSource = mediaClass.protectionDomain?.codeSource?.location
|
||||
|
||||
if (codeSource != null) {
|
||||
val jarUrl = codeSource.toURI()
|
||||
val jarFile = java.util.jar.JarFile(File(jarUrl))
|
||||
|
||||
// Extract .dylib files (macOS native media codecs)
|
||||
jarFile.entries().asSequence()
|
||||
.filter { it.name.endsWith(".dylib") || it.name.endsWith(".so") }
|
||||
.forEach { entry ->
|
||||
val outFile = File(tmpDir, File(entry.name).name)
|
||||
if (!outFile.exists()) {
|
||||
jarFile.getInputStream(entry).use { input ->
|
||||
outFile.outputStream().use { output -> input.copyTo(output) }
|
||||
}
|
||||
log.info("Extracted native lib: ${outFile.name}")
|
||||
}
|
||||
}
|
||||
jarFile.close()
|
||||
}
|
||||
|
||||
// Add tmpDir to java.library.path via reflection (standard trick)
|
||||
val usrPathsField = ClassLoader::class.java.getDeclaredField("usr_paths")
|
||||
usrPathsField.isAccessible = true
|
||||
val paths = usrPathsField.get(null) as Array<String>
|
||||
if (tmpDir.absolutePath !in paths) {
|
||||
usrPathsField.set(null, paths + tmpDir.absolutePath)
|
||||
log.info("Added ${tmpDir.absolutePath} to java.library.path")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log.warn("extractJavafxNativeLibs failed (may still work): ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user