diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/BundledVlcDiscoverer.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/BundledVlcDiscoverer.kt index 63765f0dd..ee1930fb0 100644 --- a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/BundledVlcDiscoverer.kt +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/BundledVlcDiscoverer.kt @@ -21,11 +21,11 @@ package com.vitorpamplona.amethyst.desktop.service.media import uk.co.caprica.vlcj.factory.discovery.strategy.NativeDiscoveryStrategy -import java.io.File /** * Discovers bundled VLC libraries on Windows and Linux. - * Reads the Compose application resources directory and looks for a vlc/ subdirectory. + * Uses [VlcResourceResolver] to find the VLC directory from the Compose application + * resources or development fallback paths. */ class BundledVlcDiscoverer : NativeDiscoveryStrategy { override fun supported(): Boolean { @@ -34,9 +34,8 @@ class BundledVlcDiscoverer : NativeDiscoveryStrategy { } override fun discover(): String { - val resourcesDir = System.getProperty("compose.application.resources.dir") ?: return "" - val vlcDir = File(resourcesDir, "vlc") - return if (vlcDir.isDirectory) vlcDir.absolutePath else "" + val vlcDir = VlcResourceResolver.findVlcDir() ?: return "" + return vlcDir.absolutePath } override fun onFound(path: String): Boolean = true diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/MacOsVlcDiscoverer.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/MacOsVlcDiscoverer.kt index 8e92dc92e..d7f9c02f2 100644 --- a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/MacOsVlcDiscoverer.kt +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/MacOsVlcDiscoverer.kt @@ -24,11 +24,12 @@ import com.sun.jna.NativeLibrary import uk.co.caprica.vlcj.binding.lib.LibC import uk.co.caprica.vlcj.binding.support.runtime.RuntimeUtil import uk.co.caprica.vlcj.factory.discovery.strategy.BaseNativeDiscoveryStrategy -import java.io.File /** * Discovers bundled VLC libraries on macOS. * Must force-load libvlccore before libvlc to avoid link errors. + * Uses [VlcResourceResolver] to find the VLC directory from the Compose application + * resources or development fallback paths. */ class MacOsVlcDiscoverer : BaseNativeDiscoveryStrategy( @@ -41,9 +42,8 @@ class MacOsVlcDiscoverer : } override fun discoveryDirectories(): List { - val resourcesDir = System.getProperty("compose.application.resources.dir") ?: return emptyList() - val vlcDir = File(resourcesDir, "vlc") - return if (vlcDir.isDirectory) listOf(vlcDir.absolutePath) else emptyList() + val vlcDir = VlcResourceResolver.findVlcDir() ?: return emptyList() + return listOf(vlcDir.absolutePath) } override fun onFound(path: String): Boolean { diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/VlcResourceResolver.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/VlcResourceResolver.kt new file mode 100644 index 000000000..c53af47fa --- /dev/null +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/service/media/VlcResourceResolver.kt @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 Vitor Pamplona + * + * 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.vitorpamplona.amethyst.desktop.service.media + +import java.io.File + +/** + * Resolves the bundled VLC directory, with fallbacks for development (Gradle run). + * + * Resolution order: + * 1. `compose.application.resources.dir` system property (set by packaged app) + * 2. Gradle `prepareAppResources` build output + * 3. Source `appResources` directory (platform-specific) + */ +object VlcResourceResolver { + private val currentPlatform: String by lazy { + val os = System.getProperty("os.name").lowercase() + when { + "mac" in os || "darwin" in os -> "macos" + "win" in os -> "windows" + else -> "linux" + } + } + + /** + * Returns the VLC directory if found, or null. + */ + fun findVlcDir(): File? { + // 1. Compose application resources dir (packaged app or plugin-provided) + System.getProperty("compose.application.resources.dir")?.let { dir -> + val vlcDir = File(dir, "vlc") + if (vlcDir.isDirectory) return vlcDir + } + + // 2. Gradle prepareAppResources build output (relative to working dir) + val buildOutput = File("desktopApp/build/compose/tmp/prepareAppResources/vlc") + if (buildOutput.isDirectory) return buildOutput + + // 3. Source appResources (platform-specific subdirectory) + val sourceResources = File("desktopApp/src/jvmMain/appResources/$currentPlatform/vlc") + if (sourceResources.isDirectory) return sourceResources + + return null + } +}