diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a691045 --- /dev/null +++ b/.gitignore @@ -0,0 +1,69 @@ +# Java +.mtj.tmp/ +*.class +*.jar +*.war +*.ear +*.nar +hs_err_pid* + +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +pom.xml.bak +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + +# Gradle +bin/ +build/ +.gradle +.gradletasknamecache +gradle-app.setting +!gradle-wrapper.jar + +# IntelliJ +out/ +.idea/ +.idea_modules/ +*.iml +*.ipr +*.iws + +# Eclipse +.settings/ +tmp/ +.metadata +.classpath +.project +*.tmp +*.bak +*.swp +*~.nib +local.properties +.loadpath +.factorypath + +# NetBeans +nbproject/private/ +nbbuild/ +dist/ +nbdist/ +nbactions.xml +nb-configuration.xml + +# Visual Studio Code +.vscode/ +.code-workspace + +# OS X +.DS_Store + +# Server +./server \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..494de10 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Brandon Li + +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. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c074e0f --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +# Static EMC Installers + +Static EMC Installers is a lightweight library which downloads +an assortment of static compiled executables to your respective +operating system. It detects what type of operating system you are using +and installs the proper binary. + +## Setup +1) Add Jitpack to your repositories: + +Maven: +```xml + + jitpack.io + https://jitpack.io + +``` + +Gradle Groovy: +```groovy +maven { url 'https://jitpack.io' } +``` + +Gradle Kotlin DSL: +```kotlin +maven("https://jitpack.io") +``` + +2) Add the repository into your project: + +Maven +```xml + + com.github.MinecraftMediaLibrary + emc-installers + master-SNAPSHOT + +``` + +Gradle Groovy: +```groovy +implementation 'com.github.MinecraftMediaLibrary:emc-installers:master-SNAPSHOT' +``` + +Gradle Kotlin DSL: +```kotlin +implementation("com.github.MinecraftMediaLibrary:emc-installers:master-SNAPSHOT") +``` + +## Usage +Using the library is pretty easy. Define an `FFmpegInstaller` +using the factory methods: (as an example) + +```java +// Creates an installer with default installation directory +final FFmpegInstaller installer = FFmpegInstaller.create(); + +// Creates an installer with the installation directory "path/to/dir" +final FFmpegInstaller installer = FFmpegInstaller.create(Paths.get("path/to/dir")); + +// Downloads the FFmpeg executable +final Path executable = installer.download(); +``` + +That's it! + + diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..b501d1b --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,77 @@ +plugins { + java + `java-library` + `maven-publish` + id("com.github.hierynomus.license-base") version "0.16.1" +} + +group = "io.github.pulsebeat02" +version = "v1.0.1" + +repositories { + mavenCentral() +} + +dependencies { + compileOnlyApi("com.google.guava:guava:31.0.1-jre") + testRuntimeOnly("com.google.guava:guava:31.0.1-jre") + compileOnlyApi("uk.co.caprica:vlcj:4.7.1") + testRuntimeOnly("uk.co.caprica:vlcj:4.7.1") + compileOnlyApi("uk.co.caprica:vlcj-natives:4.1.0") + testRuntimeOnly("uk.co.caprica:vlcj-natives:4.1.0") + compileOnlyApi("net.java.dev.jna:jna:5.9.0") + testRuntimeOnly("net.java.dev.jna:jna:5.9.0") + compileOnlyApi("net.java.dev.jna:jna-platform:5.9.0") + testRuntimeOnly("net.java.dev.jna:jna-platform:5.9.0") +} + +sourceSets { + main { + java { + srcDir("src/main/java") + } + resources { + srcDir("src/main/resources") + } + } +} + +tasks { + java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + publish { + dependsOn(clean) + dependsOn(build) + } +} + +publishing { + repositories { + maven { + setUrl("https://pulsebeat02.jfrog.io/artifactory/pulse-gradle") + credentials { + username = "" + password = "" + } + } + } + publications { + create("maven") { + from(components["java"]) + } + } +} + +subprojects { + + apply(plugin = "com.github.hierynomus.license-base") + + license { + header = rootProject.file("LICENSE") + encoding = "UTF-8" + mapping("java", "SLASHSTAR_STYLE") + includes(listOf("**/*.java", "**/*.kts")) + } +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7454180 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..e750102 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..744e882 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MSYS* | MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..ac1b06f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..14657f6 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "emc-installers" + diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/OS.java b/src/main/java/io/github/pulsebeat02/emcinstallers/OS.java new file mode 100644 index 0000000..87a9030 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/OS.java @@ -0,0 +1,107 @@ +/** + * MIT License + * + * Copyright (c) 2021 Brandon Li + * + * 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 io.github.pulsebeat02.emcinstallers; + +import com.google.common.collect.ImmutableSet; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Locale; +import java.util.Set; + +public enum OS { + + LINUX, + FREEBSD, + MAC, + WINDOWS; + + private static final String OS_ARCH; + private static final OS CURRENT; + private static final boolean BITS_64; + private static final boolean ARM; + private static final Path EXECUTABLES; + + static { + OS_ARCH = System.getProperty("os.arch").toLowerCase(Locale.ROOT); + CURRENT = getOperatingSystem0(); + BITS_64 = is64Bits0(); + ARM = isArm0(); + EXECUTABLES = getPath0(); + } + + private static OS getOperatingSystem0() { + final Set prefix = ImmutableSet.of("nix", "nux", "aix"); + final String os = System.getProperty("os.name").toLowerCase(); + if (os.contains("win")) { + return WINDOWS; + } else if (prefix.stream().anyMatch(os::contains)) { + return LINUX; + } else if (os.contains("mac")) { + return MAC; + } else if (isFreeBsd(os)) { + return FREEBSD; + } else { + throw new AssertionError("Unsupported Operating System!"); + } + } + + private static boolean isFreeBsd(final String os) { + return os.contains("freebsd"); + } + + private static boolean is64Bits0() { + if (CURRENT == WINDOWS) { + final String arch = System.getenv("PROCESSOR_ARCHITECTURE"); + final String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432"); + return arch != null && arch.endsWith("64") + || wow64Arch != null && wow64Arch.endsWith("64"); + } else { + return OS_ARCH.contains("64"); + } + } + + private static Path getPath0() { + return Paths.get(System.getProperty("user.home"), "static-emc"); + } + + private static boolean isArm0() { + return OS_ARCH.contains("arm"); + } + + public static OS getOperatingSystem() { + return CURRENT; + } + + public static boolean isBits64() { + return BITS_64; + } + + public static boolean isArm() { + return ARM; + } + + public static Path getExecutablePath() { + return EXECUTABLES; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/BaseInstaller.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/BaseInstaller.java new file mode 100644 index 0000000..a23b3e2 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/BaseInstaller.java @@ -0,0 +1,143 @@ +/** + * MIT License + * + * Copyright (c) 2021 Brandon Li + * + * 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 io.github.pulsebeat02.emcinstallers.implementation; + +import static io.github.pulsebeat02.emcinstallers.OS.WINDOWS; +import static io.github.pulsebeat02.emcinstallers.OS.getExecutablePath; +import static io.github.pulsebeat02.emcinstallers.OS.getOperatingSystem; +import static io.github.pulsebeat02.emcinstallers.OS.isArm; +import static io.github.pulsebeat02.emcinstallers.OS.isBits64; + +import com.google.common.collect.Table; +import io.github.pulsebeat02.emcinstallers.OS; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.file.Files; +import java.nio.file.Path; + +public abstract class BaseInstaller implements Installer { + + private final Table bits32; + private final Table bits64; + private final String url; + private Path path; + + public BaseInstaller( + final Path folder, + final String name, + final Table bits32, + final Table bits64) { + this.path = folder.resolve(name); + this.bits32 = bits32; + this.bits64 = bits64; + this.url = this.getDownloadUrl(); + if (this.url == null) { + throw new AssertionError(""); + } + this.createFiles(); + } + + public BaseInstaller(final String name, final Table bits32, + final Table bits64) { + this(getExecutablePath(), name, bits32, bits64); + } + + private String getDownloadUrl() { + final OS os = getOperatingSystem(); + final boolean arm = isArm(); + return isBits64() ? this.bits64.get(os, arm) : this.bits32.get(os, arm); + } + + private String getFilename() { + return this.url.substring(this.url.lastIndexOf('/') + 1); + } + + private void createFiles() { + if (Files.notExists(this.path)) { + try { + Files.createDirectories(this.path.getParent()); + } catch (final IOException e) { + e.printStackTrace(); + } + } + } + + @Override + public Path download(final boolean chmod) throws IOException { + if (Files.exists(this.path)) { + return this.path; + } else { + Files.createFile(this.path); + } + try (final ReadableByteChannel readableByteChannel = + Channels.newChannel(new URL(this.url).openStream()); + final FileChannel channel = new FileOutputStream(this.path.toFile()).getChannel()) { + channel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE); + } + if (chmod) { + this.changePermissions(); + } + this.renameFile(); + return this.path; + } + + private void renameFile() throws IOException { + if (getOperatingSystem() == WINDOWS) { + final Path newPath = this.path.resolveSibling(String.format("%s.exe", this.getFilename())); + Files.move(this.path, newPath); + this.path = newPath; + } + } + + private void changePermissions() throws IOException { + if (getOperatingSystem() != WINDOWS) { + final ProcessBuilder builder = new ProcessBuilder("chmod", "777", this.path.toString()); + try { + builder.start().waitFor(); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + } + + public String getUrl() { + return this.url; + } + + public Table getBits32() { + return this.bits32; + } + + public Table getBits64() { + return this.bits64; + } + + public Path getPath() { + return this.path; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/Installer.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/Installer.java new file mode 100644 index 0000000..40d4ccd --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/Installer.java @@ -0,0 +1,50 @@ +/** + * MIT License + * + * Copyright (c) 2021 Brandon Li + * + * 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 io.github.pulsebeat02.emcinstallers.implementation; + +import java.io.IOException; +import java.nio.file.Path; + +public interface Installer { + + /** + * Downloads the binary into the specified directory with the file name "ffmpeg". If the file + * already exists there, it will return the path of that file assuming that FFmpeg has already + * been installed. Otherwise, it downloads a new file. If chmod is set to true, it will change the + * file permissions to 777 you can use {@ProcessBuilder} or {@Process} to use the binary. It + * returns the path of the downloaded executable + * + * @param chmod whether chmod 777 should be applied (if not windows) + * @return the path of the download executable + * @throws IOException if an issue occurred during file creation, downloading, or renaming. + */ + Path download(final boolean chmod) throws IOException; + + /** + * Returns whether the operating system is *most likely* supported. + * + * @return whether the current operating system is supported or not + */ + boolean isSupported(); +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/ffmpeg/FFmpegInstaller.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/ffmpeg/FFmpegInstaller.java new file mode 100644 index 0000000..0efc815 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/ffmpeg/FFmpegInstaller.java @@ -0,0 +1,116 @@ +/** + * MIT License + * + * Copyright (c) 2021 Brandon Li + * + * 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 io.github.pulsebeat02.emcinstallers.implementation.ffmpeg; + +import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Table; +import io.github.pulsebeat02.emcinstallers.OS; +import io.github.pulsebeat02.emcinstallers.implementation.BaseInstaller; +import java.nio.file.Path; + +public final class FFmpegInstaller extends BaseInstaller { + + public static final String VERSION; + private static final Table BITS_64; + private static final Table BITS_32; + + static { + VERSION = "b4.4"; + BITS_64 = ImmutableTable.builder() + .put(OS.LINUX, true, + String.format( + "https://github.com/eugeneware/ffmpeg-static/releases/download/%s/linux-arm64", + VERSION)) + .put(OS.LINUX, false, + String.format( + "https://github.com/eugeneware/ffmpeg-static/releases/download/%s/linux-x64", + VERSION)) + .put(OS.MAC, true, + String.format( + "https://github.com/eugeneware/ffmpeg-static/releases/download/%s/darwin-arm64", + VERSION)) + .put(OS.MAC, false, + String.format( + "https://github.com/eugeneware/ffmpeg-static/releases/download/%s/darwin-x64", + VERSION)) + .put(OS.WINDOWS, false, + String.format( + "https://github.com/eugeneware/ffmpeg-static/releases/download/%s/win32-x64", + VERSION)) + .put(OS.FREEBSD, false, + String.format( + "https://github.com/eugeneware/ffmpeg-static/releases/download/%s/freebsd-x64", + VERSION)) + .build(); + BITS_32 = ImmutableTable.builder() + .put(OS.LINUX, true, + String.format( + "https://github.com/eugeneware/ffmpeg-static/releases/download/%s/linux-arm", + VERSION)) + .put(OS.LINUX, false, + String.format( + "https://github.com/eugeneware/ffmpeg-static/releases/download/%s/linux-ia32", + VERSION)) + .put(OS.WINDOWS, false, + String.format( + "https://github.com/eugeneware/ffmpeg-static/releases/download/%s/win32-ia32", + VERSION)) + .build(); + } + + FFmpegInstaller(final Path folder) { + super(folder, "ffmpeg", BITS_32, BITS_64); + } + + FFmpegInstaller() { + super("ffmpeg", BITS_32, BITS_64); + } + + /** + * Constructs a new FFmpegInstaller with the specified directory for the executable. + * + * @param executable directory + * @return new FFmpegInstaller + */ + public static FFmpegInstaller create(final Path executable) { + return new FFmpegInstaller(executable); + } + + /** + * Constructs a new FFmpegInstaller with the default directory for the executable. + *

+ * For Windows, it is C:/Program Files/static-emc Otherwise, it is [user home + * directory]/static-emc + * + * @return new FFmpegInstaller + */ + public static FFmpegInstaller create() { + return new FFmpegInstaller(); + } + + @Override + public boolean isSupported() { + return true; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/rtsp/RTSPInstaller.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/rtsp/RTSPInstaller.java new file mode 100644 index 0000000..02aa457 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/rtsp/RTSPInstaller.java @@ -0,0 +1,96 @@ +/** + * MIT License + * + * Copyright (c) 2021 Brandon Li + * + * 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 io.github.pulsebeat02.emcinstallers.implementation.rtsp; + +import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Table; +import io.github.pulsebeat02.emcinstallers.OS; +import io.github.pulsebeat02.emcinstallers.implementation.BaseInstaller; +import java.nio.file.Path; + +public final class RTSPInstaller extends BaseInstaller { + + private static final Table BITS_64; + private static final Table BITS_32; + + static { + BITS_64 = ImmutableTable.builder() + .put(OS.LINUX, true, + "https://github.com/MinecraftMediaLibrary/rtsmp-binaries/raw/main/executables/linux-arm64") + .put(OS.LINUX, false, + "https://github.com/MinecraftMediaLibrary/rtsmp-binaries/raw/main/executables/linux-amd64") + .put(OS.MAC, true, + "https://github.com/MinecraftMediaLibrary/rtsmp-binaries/raw/main/executables/darwin-arm64") + .put(OS.MAC, false, + "https://github.com/MinecraftMediaLibrary/rtsmp-binaries/raw/main/executables/darwin-amd64") + .put(OS.WINDOWS, false, + "https://github.com/MinecraftMediaLibrary/rtsmp-binaries/raw/main/executables/windows-amd64.exe") + .put(OS.FREEBSD, false, + "https://github.com/MinecraftMediaLibrary/rtsmp-binaries/raw/main/executables/freebsd-amd64") + .build(); + BITS_32 = ImmutableTable.builder() + .put(OS.LINUX, true, + "https://github.com/MinecraftMediaLibrary/rtsmp-binaries/raw/main/executables/linux-arm") + .put(OS.LINUX, false, + "https://github.com/MinecraftMediaLibrary/rtsmp-binaries/raw/main/executables/linux-ia32") + .put(OS.WINDOWS, false, + "https://github.com/MinecraftMediaLibrary/rtsmp-binaries/raw/main/executables/windows-ia32.exe") + .build(); + } + + RTSPInstaller(final Path folder) { + super(folder, "simple-rtsp-server", BITS_32, BITS_64); + } + + RTSPInstaller() { + super("simple-rtsp-server", BITS_32, BITS_64); + } + + /** + * Constructs a new FFmpegInstaller with the specified directory for the executable. + * + * @param executable directory + * @return new FFmpegInstaller + */ + public static RTSPInstaller create(final Path executable) { + return new RTSPInstaller(executable); + } + + /** + * Constructs a new RTSPInstaller with the default directory for the executable. + *

+ * For Windows, it is C:/Program Files/static-emc Otherwise, it is [user home + * directory]/static-emc + * + * @return new FFmpegInstaller + */ + public static RTSPInstaller create() { + return new RTSPInstaller(); + } + + @Override + public boolean isSupported() { + return true; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/VLCInstallationKit.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/VLCInstallationKit.java new file mode 100644 index 0000000..b0c43f8 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/VLCInstallationKit.java @@ -0,0 +1,120 @@ +/** + * MIT License + *

+ * Copyright (c) 2021 Brandon Li + *

+ * 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 io.github.pulsebeat02.emcinstallers.implementation.vlc; + +import static io.github.pulsebeat02.emcinstallers.OS.MAC; +import static io.github.pulsebeat02.emcinstallers.OS.getExecutablePath; + +import io.github.pulsebeat02.emcinstallers.OS; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.installation.VLCInstaller; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.EnhancedNativeDiscovery; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DirectoryProviderDiscoveryStrategy; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Optional; + +public final class VLCInstallationKit { + + private final Path[] others; + + VLCInstallationKit(final Path... others) { + this.others = others; + } + + VLCInstallationKit() { + this(getExecutablePath()); + } + + /** + * Attempts to search for the VLC binary in common installation paths. If a library has been found + * and loaded successfully, it will be available to be used by VLCJ. Otherwise, if a library could + * not be found, it will download the respective binary for the user operating system and load + * that libvlc that way. + * + * @return Optional containing path if found, otherwise empty + * @throws IOException if an issue occurred during installation + */ + public Optional start() throws IOException { + return this.installBinary(true, this.others); + } + + private Optional installBinary(final boolean chmod, final Path... others) + throws IOException { + this.addExtraSearchPaths(others); + final Optional binary = this.searchAndLoadBinary(); + if (binary.isPresent()) { + return binary; + } + return this.loadInstalledBinaries(chmod); + } + + private Optional loadInstalledBinaries(final boolean chmod) throws IOException { + this.addDownloadedSearchPath(chmod); + return this.searchAndLoadBinary(); + } + + private void addDownloadedSearchPath(final boolean chmod) throws IOException { + DirectoryProviderDiscoveryStrategy.addSearchDirectory( + this.getProperPath(VLCInstaller.create().download(chmod))); + } + + private Path getProperPath(final Path path) { + if (OS.getOperatingSystem() == MAC) { + return path.resolve("Contents").resolve("MacOS").resolve("lib"); + } + return path; + } + + private void addExtraSearchPaths(final Path[] others) { + Arrays.stream(others).forEach(DirectoryProviderDiscoveryStrategy::addSearchDirectory); + } + + private Optional searchAndLoadBinary() { + final EnhancedNativeDiscovery discovery = new EnhancedNativeDiscovery(); + if (discovery.discover()) { + return Optional.of(Paths.get(discovery.getDiscoveredPath())); + } + return Optional.empty(); + } + + /** + * Constructs a new VLCInstallationKit with default parameters for downloading/loading libvlc into + * the runtime. + * + * @return a new VLCInstallationKit + */ + public static VLCInstallationKit create() { + return new VLCInstallationKit(); + } + + /** + * Constructs a new VLCInstallationKit with the specified path(s) for downloading/loading libvlc + * into the runtime. + * + * @param others the desired paths to search + * @return a new VLCInstallationKit + */ + public static VLCInstallationKit create(final Path... others) { + return new VLCInstallationKit(others); + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/InstallationStrategy.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/InstallationStrategy.java new file mode 100644 index 0000000..a9636df --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/InstallationStrategy.java @@ -0,0 +1,35 @@ +/** + * MIT License + * + * Copyright (c) 2021 Brandon Li + * + * 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 io.github.pulsebeat02.emcinstallers.implementation.vlc.installation; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; + +public interface InstallationStrategy { + + Optional getInstalledPath(); + + Path execute() throws IOException; +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/ManualInstallationStrategy.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/ManualInstallationStrategy.java new file mode 100644 index 0000000..96adb14 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/ManualInstallationStrategy.java @@ -0,0 +1,45 @@ +/** + * MIT License + * + * Copyright (c) 2021 Brandon Li + * + * 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 io.github.pulsebeat02.emcinstallers.implementation.vlc.installation; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public abstract class ManualInstallationStrategy implements InstallationStrategy { + + private final VLCInstaller installer; + + public ManualInstallationStrategy(final VLCInstaller installer) { + this.installer = installer; + } + + public void deleteFile(final Path dmg) throws IOException { + Files.deleteIfExists(dmg); + } + + public VLCInstaller getInstaller() { + return this.installer; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/VLCInstaller.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/VLCInstaller.java new file mode 100644 index 0000000..19e400a --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/VLCInstaller.java @@ -0,0 +1,127 @@ +/** + * MIT License + * + * Copyright (c) 2021 Brandon Li + * + * 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 io.github.pulsebeat02.emcinstallers.implementation.vlc.installation; + +import static io.github.pulsebeat02.emcinstallers.OS.MAC; +import static io.github.pulsebeat02.emcinstallers.OS.WINDOWS; +import static io.github.pulsebeat02.emcinstallers.OS.getOperatingSystem; + +import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Table; +import io.github.pulsebeat02.emcinstallers.OS; +import io.github.pulsebeat02.emcinstallers.implementation.BaseInstaller; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.installation.platform.osx.OSXInstallationStrategy; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.installation.platform.win.WinInstallationStrategy; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; + +public final class VLCInstaller extends BaseInstaller { + + public static final String VERSION; + private static final Table BITS_64; + private static final Table BITS_32; + + static { + VERSION = "3.0.16"; + BITS_64 = ImmutableTable.builder() + .put(MAC, true, + String.format("https://mirror.csclub.uwaterloo.ca/vlc/vlc/%s/macosx/vlc-%s-arm64.dmg", + VERSION, VERSION)) + .put(MAC, false, + String.format( + "https://mirror.csclub.uwaterloo.ca/vlc/vlc/%s/macosx/vlc-%s-universal.dmg", + VERSION, VERSION)) + .put(WINDOWS, false, + String.format("https://mirror.csclub.uwaterloo.ca/vlc/vlc/%s/win64/vlc-%s-win64.zip", + VERSION, VERSION)) + .build(); + BITS_32 = ImmutableTable.builder() + .put(WINDOWS, false, + String.format("https://mirror.csclub.uwaterloo.ca/vlc/vlc/%s/win32/vlc-%s-win32.zip", + VERSION, VERSION)) + .build(); + } + + VLCInstaller(final Path folder) { + super(folder, "vlc", BITS_32, BITS_64); + } + + VLCInstaller() { + super("vlc", BITS_32, BITS_64); + } + + /** + * Constructs a new VLCInstaller with the specified directory for the executable. + * + * @param executable directory + * @return new VLCInstaller + */ + public static VLCInstaller create(final Path executable) { + return new VLCInstaller(executable); + } + + /** + * Constructs a new VLCInstaller with the default directory for the executable. + *

+ * For Windows, it is C:/Program Files/static-emc Otherwise, it is [user home + * directory]/static-emc + * + * @return new VLCInstaller + */ + public static VLCInstaller create() { + return new VLCInstaller(); + } + + @Override + public Path download(final boolean chmod) throws IOException { + + final InstallationStrategy strategy = this.getStrategy(); + final Optional optional = strategy.getInstalledPath(); + if (optional.isPresent()) { + return optional.get(); + } + + super.download(chmod); + + return strategy.execute(); + } + + private InstallationStrategy getStrategy() { + switch (getOperatingSystem()) { + case MAC: + return new OSXInstallationStrategy(this); + case WINDOWS: + return new WinInstallationStrategy(this); + default: + throw new AssertionError("Operating System not Supported!"); + } + } + + @Override + public boolean isSupported() { + final OS os = getOperatingSystem(); + return os == WINDOWS || os == MAC; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/platform/osx/OSXInstallationStrategy.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/platform/osx/OSXInstallationStrategy.java new file mode 100644 index 0000000..de41b71 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/platform/osx/OSXInstallationStrategy.java @@ -0,0 +1,84 @@ +/** + * MIT License + * + * Copyright (c) 2021 Brandon Li + * + * 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 io.github.pulsebeat02.emcinstallers.implementation.vlc.installation.platform.osx; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.installation.VLCInstaller; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.installation.ManualInstallationStrategy; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; + +public final class OSXInstallationStrategy extends ManualInstallationStrategy { + + public OSXInstallationStrategy( + final VLCInstaller installer) { + super(installer); + } + + @Override + public Optional getInstalledPath() { + final Path path = this.getInstaller().getPath().getParent().resolve("VLC.app"); + return Files.exists(path) ? Optional.of(path) : Optional.empty(); + } + + @Override + public Path execute() throws IOException { + final String vlc = "VLC.app"; + final Path dmg = this.getInstaller().getPath(); + final Path disk = Paths.get("/Volumes/VLC media player"); + final Path app = dmg.getParent().resolve(vlc); + this.mountDisk(dmg); + this.copyApplication(disk.resolve(vlc), app); + this.changePermissions(app); + this.unmountDisk(disk); + this.deleteFile(dmg); + return app; + } + + private void unmountDisk(final Path disk) throws IOException { + this.runNativeProcess("diskutil", "unmount", disk.toString()); + } + + private void changePermissions(final Path app) throws IOException { + this.runNativeProcess("chmod", "-R", "755", app.toString()); + } + + private void mountDisk(final Path dmg) throws IOException { + this.runNativeProcess("/usr/bin/hdiutil", "attach", dmg.toString()); + } + + private void copyApplication(final Path src, final Path app) throws IOException { + this.runNativeProcess("rsync", "-a", String.format("%s/", src.toString()), app.toString()); + } + + private void runNativeProcess(final String... arguments) throws IOException { + try { + new ProcessBuilder(arguments).start().waitFor(); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/platform/win/WinInstallationStrategy.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/platform/win/WinInstallationStrategy.java new file mode 100644 index 0000000..5741a8f --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/installation/platform/win/WinInstallationStrategy.java @@ -0,0 +1,94 @@ +/** + * MIT License + * + * Copyright (c) 2021 Brandon Li + * + * 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 io.github.pulsebeat02.emcinstallers.implementation.vlc.installation.platform.win; + +import com.google.common.io.ByteStreams; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.installation.VLCInstaller; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.installation.ManualInstallationStrategy; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Enumeration; +import java.util.Optional; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public final class WinInstallationStrategy extends ManualInstallationStrategy { + + public WinInstallationStrategy( + final VLCInstaller installer) { + super(installer); + } + + @Override + public Optional getInstalledPath() { + final Path path = this.getInstaller().getPath().getParent().resolve("VLC"); + return Files.exists(path) ? Optional.of(path) : Optional.empty(); + } + + @Override + public Path execute() throws IOException { + final Path zip = this.getInstaller().getPath(); + final Path parent = zip.getParent(); + final Path temp = parent.resolve("temp-vlc"); + final Path path = parent.resolve("VLC"); + this.extractArchive(zip, temp); + this.deleteFile(zip); + this.moveFiles(temp, path); + this.deleteFile(temp); + return path; + } + + private void extractArchive(final Path zip, final Path temp) throws IOException { + try (final ZipFile zipFile = new ZipFile(zip.toFile())) { + final Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) { + final ZipEntry entry = entries.nextElement(); + final Path entryDestination = temp.resolve(entry.getName()); + if (entry.isDirectory()) { + this.createDirectories(entryDestination); + } else { + this.createDirectories(entryDestination.getParent()); + try (final InputStream in = zipFile.getInputStream(entry); + final OutputStream out = new FileOutputStream(entryDestination.toFile())) { + ByteStreams.copy(in, out); + } + } + } + } + } + + private void createDirectories(final Path path) throws IOException { + if (Files.notExists(path)) { + Files.createDirectories(path); + } + } + + private void moveFiles(final Path temp, final Path dest) throws IOException { + Files.move(temp.resolve(String.format("vlc-%s", VLCInstaller.VERSION)), dest); + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/EnhancedNativeDiscovery.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/EnhancedNativeDiscovery.java new file mode 100644 index 0000000..a99f887 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/EnhancedNativeDiscovery.java @@ -0,0 +1,108 @@ +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search; + +import static uk.co.caprica.vlcj.binding.LibVlc.libvlc_new; +import static uk.co.caprica.vlcj.binding.LibVlc.libvlc_release; + +import com.sun.jna.NativeLibrary; +import com.sun.jna.StringArray; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy.BaseNativeDiscoveryStrategy; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy.NativeDiscoveryStrategy; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy.linux.LinuxNativeDiscoveryStrategy; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy.osx.OsxNativeDiscoveryStrategy; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy.win.WindowsNativeDiscoveryStrategy; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import uk.co.caprica.vlcj.binding.RuntimeUtil; +import uk.co.caprica.vlcj.binding.internal.libvlc_instance_t; +import uk.co.caprica.vlcj.support.version.LibVlcVersion; + +public class EnhancedNativeDiscovery { + + private static final List DEFAULT_STRATEGIES; + private static boolean FOUND; + + static { + DEFAULT_STRATEGIES = Arrays.asList( + new LinuxNativeDiscoveryStrategy(), + new OsxNativeDiscoveryStrategy(), + new WindowsNativeDiscoveryStrategy()); + } + + private final List discoveryStrategies; + private NativeDiscoveryStrategy successfulStrategy; + private String discoveredPath; + + public EnhancedNativeDiscovery(final NativeDiscoveryStrategy... discoveryStrategies) { + this.discoveryStrategies = + discoveryStrategies.length > 0 ? Arrays.asList(discoveryStrategies) : DEFAULT_STRATEGIES; + } + + public final boolean discover() { + if (FOUND) { + return true; + } else { + for (final NativeDiscoveryStrategy discoveryStrategy : this.discoveryStrategies) { + if (discoveryStrategy.supported()) { + final Optional optional = discoveryStrategy.discover(); + if (optional.isPresent()) { + final String path = optional.get(); + this.addLibvlc(discoveryStrategy, path); + this.tryPluginPath(path, discoveryStrategy); + return this.attemptLibraryLoad(discoveryStrategy, path); + } + } + } + return false; + } + } + + private boolean attemptLibraryLoad(final NativeDiscoveryStrategy discoveryStrategy, + final String path) { + if (this.tryLoadingLibrary()) { + this.successfulStrategy = discoveryStrategy; + this.discoveredPath = path; + FOUND = true; + return true; + } else { + return false; + } + } + + private void addLibvlc(final NativeDiscoveryStrategy discoveryStrategy, final String path) { + if (discoveryStrategy.onFound(path)) { + NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), path); + } + } + + private void tryPluginPath(final String path, final NativeDiscoveryStrategy discoveryStrategy) { + final String env = System.getenv(BaseNativeDiscoveryStrategy.PLUGIN_ENV_NAME); + if (env == null || env.length() == 0) { + discoveryStrategy.onSetPluginPath(path); + } + } + + private boolean tryLoadingLibrary() { + try { + final libvlc_instance_t instance = libvlc_new(0, new StringArray(new String[0])); + if (instance != null) { + libvlc_release(instance); + final LibVlcVersion version = new LibVlcVersion(); + if (version.isSupported()) { + return true; + } + } + } catch (final UnsatisfiedLinkError e) { + System.err.println(e.getMessage()); + } + return false; + } + + public NativeDiscoveryStrategy getDiscoveryStrategy() { + return this.successfulStrategy; + } + + public String getDiscoveredPath() { + return this.discoveredPath; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/DirectoryProviderDiscoveryStrategy.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/DirectoryProviderDiscoveryStrategy.java new file mode 100644 index 0000000..db421f8 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/DirectoryProviderDiscoveryStrategy.java @@ -0,0 +1,89 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.linux.LinuxWellKnownDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.misc.ConfigurationFileDiscoveryDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.misc.CustomWellKnownDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.misc.JnaLibraryPathDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.osx.OsxWellKnownDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.path.SystemPathDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.path.UserDirDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.win.WindowsInstallDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy.BaseNativeDiscoveryStrategy; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +public abstract class DirectoryProviderDiscoveryStrategy extends BaseNativeDiscoveryStrategy { + + private static final Set DIRECTORY_PROVIDERS; + + static { + DIRECTORY_PROVIDERS = new TreeSet<>((o1, o2) -> o2.priority() - o1.priority()); + DIRECTORY_PROVIDERS.addAll(Arrays.asList( + new ConfigurationFileDiscoveryDirectoryProvider(), + new JnaLibraryPathDirectoryProvider(), + new LinuxWellKnownDirectoryProvider(), + new OsxWellKnownDirectoryProvider(), + new SystemPathDirectoryProvider(), + new UserDirDirectoryProvider(), + new WindowsInstallDirectoryProvider() + )); + } + + private final Set directoryProviders; + + public DirectoryProviderDiscoveryStrategy(final String[] filenamePatterns, + final String[] pluginPathFormats) { + super(filenamePatterns, pluginPathFormats); + this.directoryProviders = DIRECTORY_PROVIDERS; + } + + @Override + public final List discoveryDirectories() { + final List directories = new ArrayList<>(); + for (final DiscoveryDirectoryProvider provider : this.getSupportedProviders()) { + directories.addAll(Arrays.asList(provider.directories())); + } + return directories; + } + + private List getSupportedProviders() { + final List result = new ArrayList<>(); + for (final DiscoveryDirectoryProvider list : this.directoryProviders) { + if (list.supported()) { + result.add(list); + } + } + return this.sort(result); + } + + private List sort(final List providers) { + return providers; + } + + public static void addSearchDirectory(final Path path) { + DIRECTORY_PROVIDERS.add(new CustomWellKnownDirectoryProvider(path.toString())); + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/DiscoveryDirectoryProvider.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/DiscoveryDirectoryProvider.java new file mode 100644 index 0000000..2abd4b7 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/DiscoveryDirectoryProvider.java @@ -0,0 +1,29 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider; + +public interface DiscoveryDirectoryProvider { + + int priority(); + + String[] directories(); + + boolean supported(); +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/DiscoveryProviderPriority.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/DiscoveryProviderPriority.java new file mode 100644 index 0000000..6754d66 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/DiscoveryProviderPriority.java @@ -0,0 +1,30 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider; + +public interface DiscoveryProviderPriority { + + int CONFIG_FILE = 1; + int JNA_LIBRARY_PATH = -1; + int USER_DIR = -2; + int INSTALL_DIR = -3; + int WELL_KNOWN_DIRECTORY = -3; + int SYSTEM_PATH = -4; +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/WellKnownDirectoryProvider.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/WellKnownDirectoryProvider.java new file mode 100644 index 0000000..f5b5b7c --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/WellKnownDirectoryProvider.java @@ -0,0 +1,28 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider; + +public abstract class WellKnownDirectoryProvider implements DiscoveryDirectoryProvider { + + @Override + public int priority() { + return DiscoveryProviderPriority.WELL_KNOWN_DIRECTORY; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/linux/LinuxWellKnownDirectoryProvider.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/linux/LinuxWellKnownDirectoryProvider.java new file mode 100644 index 0000000..c5cc181 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/linux/LinuxWellKnownDirectoryProvider.java @@ -0,0 +1,52 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.linux; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.WellKnownDirectoryProvider; +import uk.co.caprica.vlcj.binding.RuntimeUtil; + +public class LinuxWellKnownDirectoryProvider extends WellKnownDirectoryProvider { + + private static final String[] DIRECTORIES; + + static { + final String usr = "/usr"; + final String lib = String.format("%s/lib", usr); + final String locallib = "/usr/local/lib"; + DIRECTORIES = new String[]{ + String.format("%s/x86_64-linux-gnu", lib), + String.format("%s64", lib), + String.format("%s/lib64", locallib), + String.format("%s/i386-linux-gnu", lib), + lib, + locallib + }; + } + + @Override + public String[] directories() { + return DIRECTORIES; + } + + @Override + public boolean supported() { + return RuntimeUtil.isNix(); + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/misc/ConfigurationFileDiscoveryDirectoryProvider.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/misc/ConfigurationFileDiscoveryDirectoryProvider.java new file mode 100644 index 0000000..d7c37ba --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/misc/ConfigurationFileDiscoveryDirectoryProvider.java @@ -0,0 +1,69 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2020 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.misc; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryProviderPriority; +import java.io.IOException; +import java.io.Reader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; + +public class ConfigurationFileDiscoveryDirectoryProvider implements DiscoveryDirectoryProvider { + + private static final String CONFIG_DIR; + private static final String CONFIG_FILE_NAME; + private static final String PROPERTY_NAME; + + static { + CONFIG_DIR = String.format("%s/.config/vlcj", System.getProperty("user.home")); + CONFIG_FILE_NAME = "vlcj.config"; + PROPERTY_NAME = "nativeDirectory"; + } + + @Override + public int priority() { + return DiscoveryProviderPriority.CONFIG_FILE; + } + + @Override + public String[] directories() { + final Path file = Paths.get(CONFIG_DIR, CONFIG_FILE_NAME); + final Properties properties = new Properties(); + try (final Reader reader = Files.newBufferedReader(file)) { + properties.load(reader); + final String directory = properties.getProperty(PROPERTY_NAME); + if (directory != null) { + return new String[]{directory}; + } + } catch (final IOException e) { + e.printStackTrace(); + } + return new String[0]; + } + + @Override + public boolean supported() { + final Path file = Paths.get(CONFIG_DIR, CONFIG_FILE_NAME); + return Files.exists(file) && Files.isRegularFile(file) && Files.isReadable(file); + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/misc/CustomWellKnownDirectoryProvider.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/misc/CustomWellKnownDirectoryProvider.java new file mode 100644 index 0000000..11803b1 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/misc/CustomWellKnownDirectoryProvider.java @@ -0,0 +1,28 @@ +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.misc; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryProviderPriority; + +public class CustomWellKnownDirectoryProvider implements DiscoveryDirectoryProvider { + + private final String[] directories; + + public CustomWellKnownDirectoryProvider(final String... directories) { + this.directories = directories; + } + + @Override + public int priority() { + return DiscoveryProviderPriority.WELL_KNOWN_DIRECTORY; + } + + @Override + public String[] directories() { + return this.directories; + } + + @Override + public boolean supported() { + return true; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/misc/JnaLibraryPathDirectoryProvider.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/misc/JnaLibraryPathDirectoryProvider.java new file mode 100644 index 0000000..7e36cb6 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/misc/JnaLibraryPathDirectoryProvider.java @@ -0,0 +1,47 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.misc; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryProviderPriority; + +public class JnaLibraryPathDirectoryProvider implements DiscoveryDirectoryProvider { + + private static final String SYSTEM_PROPERTY_NAME; + + static { + SYSTEM_PROPERTY_NAME = "jna.library.path"; + } + + @Override + public int priority() { + return DiscoveryProviderPriority.JNA_LIBRARY_PATH; + } + + @Override + public String[] directories() { + return System.getProperty("jna.library.path").split("/"); + } + + @Override + public boolean supported() { + return System.getProperty(SYSTEM_PROPERTY_NAME) != null; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/osx/OsxWellKnownDirectoryProvider.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/osx/OsxWellKnownDirectoryProvider.java new file mode 100644 index 0000000..190ef0d --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/osx/OsxWellKnownDirectoryProvider.java @@ -0,0 +1,47 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.osx; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.WellKnownDirectoryProvider; +import uk.co.caprica.vlcj.binding.RuntimeUtil; + +public class OsxWellKnownDirectoryProvider extends WellKnownDirectoryProvider { + + private static final String[] DIRECTORIES; + + static { + final String contents = "/Applications/VLC.app/Contents"; + DIRECTORIES = new String[]{ + String.format("%s/Frameworks", contents), + String.format("%s/MacOS/lib", contents) + }; + } + + @Override + public String[] directories() { + return DIRECTORIES; + } + + @Override + public boolean supported() { + return RuntimeUtil.isMac(); + } + +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/path/SystemPathDirectoryProvider.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/path/SystemPathDirectoryProvider.java new file mode 100644 index 0000000..ca62185 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/path/SystemPathDirectoryProvider.java @@ -0,0 +1,43 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.path; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryProviderPriority; + +public class SystemPathDirectoryProvider implements DiscoveryDirectoryProvider { + + @Override + public int priority() { + return DiscoveryProviderPriority.SYSTEM_PATH; + } + + @Override + public String[] directories() { + final String path = System.getenv("PATH"); + return path != null ? path.split("/") : new String[0]; + } + + @Override + public boolean supported() { + return true; + } + +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/path/UserDirDirectoryProvider.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/path/UserDirDirectoryProvider.java new file mode 100644 index 0000000..877accd --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/path/UserDirDirectoryProvider.java @@ -0,0 +1,43 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.path; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryProviderPriority; + +public class UserDirDirectoryProvider implements DiscoveryDirectoryProvider { + + @Override + public int priority() { + return DiscoveryProviderPriority.USER_DIR; + } + + @Override + public String[] directories() { + final String path = System.getProperty("user.dir"); + return path != null ? new String[]{path} : new String[0]; + } + + @Override + public boolean supported() { + return true; + } + +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/win/WindowsInstallDirectoryProvider.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/win/WindowsInstallDirectoryProvider.java new file mode 100644 index 0000000..88a7574 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/provider/win/WindowsInstallDirectoryProvider.java @@ -0,0 +1,63 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.win; + +import static com.sun.jna.platform.win32.WinReg.HKEY_LOCAL_MACHINE; + +import com.sun.jna.platform.win32.Advapi32Util; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryDirectoryProvider; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DiscoveryProviderPriority; +import uk.co.caprica.vlcj.binding.RuntimeUtil; + +public class WindowsInstallDirectoryProvider implements DiscoveryDirectoryProvider { + + private static final String VLC_REGISTRY_KEY; + private static final String VLC_INSTALL_DIR_KEY; + + static { + VLC_REGISTRY_KEY = "SOFTWARE\\VideoLAN\\VLC"; + VLC_INSTALL_DIR_KEY = "InstallDir"; + } + + @Override + public int priority() { + return DiscoveryProviderPriority.INSTALL_DIR; + } + + @Override + public String[] directories() { + final String installDir = this.getVlcInstallDir(); + return installDir != null ? new String[]{installDir} : new String[0]; + } + + @Override + public boolean supported() { + return RuntimeUtil.isWindows(); + } + + private String getVlcInstallDir() { + try { + return Advapi32Util.registryGetStringValue(HKEY_LOCAL_MACHINE, VLC_REGISTRY_KEY, + VLC_INSTALL_DIR_KEY); + } catch (final Exception e) { + return null; + } + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/BaseNativeDiscoveryStrategy.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/BaseNativeDiscoveryStrategy.java new file mode 100644 index 0000000..0c8e7c1 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/BaseNativeDiscoveryStrategy.java @@ -0,0 +1,118 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +public abstract class BaseNativeDiscoveryStrategy implements NativeDiscoveryStrategy { + + public static final String PLUGIN_ENV_NAME = "VLC_PLUGIN_PATH"; + + private final Pattern[] patternsToMatch; + private final String[] pluginPathFormats; + + public BaseNativeDiscoveryStrategy(final String[] filenamePatterns, + final String[] pluginPathFormats) { + this.patternsToMatch = new Pattern[filenamePatterns.length]; + this.pluginPathFormats = pluginPathFormats; + this.compilePatterns(filenamePatterns); + } + + private void compilePatterns(final String[] filenamePatterns) { + for (int i = 0; i < filenamePatterns.length; i++) { + this.patternsToMatch[i] = Pattern.compile(filenamePatterns[i]); + } + } + + @Override + public final Optional discover() { + return this.discoveryDirectories().stream().parallel().filter(this::find).findAny(); + } + + protected abstract List discoveryDirectories(); + + private boolean find(final String directoryName) { + + final Path dir = Paths.get(directoryName); + if (Files.notExists(dir)) { + return false; + } + + final Set matches = new HashSet<>(this.patternsToMatch.length); + try (final Stream stream = Files.walk(dir, 1).parallel()) { + return stream.anyMatch(this.getMatchingPatternFile(matches)); + } catch (final IOException e) { + e.printStackTrace(); + } + + return false; + } + + private Predicate getMatchingPatternFile(final Set matches) { + return file -> { + for (final Pattern pattern : this.patternsToMatch) { + if (this.validatePattern(matches, file, pattern)) { + return true; + } + } + return false; + }; + } + + private boolean validatePattern(final Set matches, final Path file, + final Pattern pattern) { + final Matcher matcher = pattern.matcher(file.getFileName().toString()); + if (matcher.matches()) { + matches.add(pattern.pattern()); + return matches.size() == this.patternsToMatch.length; + } + return false; + } + + @Override + public boolean onFound(final String path) { + return true; + } + + @Override + public final boolean onSetPluginPath(final String path) { + for (final String pathFormat : this.pluginPathFormats) { + final String pluginPath = String.format(pathFormat, path); + if (Files.exists(Paths.get(pluginPath))) { + return this.setPluginPath(pluginPath); + } + } + return false; + } + + protected abstract boolean setPluginPath(String pluginPath); + +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/NativeDiscoveryStrategy.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/NativeDiscoveryStrategy.java new file mode 100644 index 0000000..698a55c --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/NativeDiscoveryStrategy.java @@ -0,0 +1,33 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy; + +import java.util.Optional; + +public interface NativeDiscoveryStrategy { + + boolean supported(); + + Optional discover(); + + boolean onFound(String path); + + boolean onSetPluginPath(String path); +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/linux/LinuxNativeDiscoveryStrategy.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/linux/LinuxNativeDiscoveryStrategy.java new file mode 100644 index 0000000..a284828 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/linux/LinuxNativeDiscoveryStrategy.java @@ -0,0 +1,51 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy.linux; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DirectoryProviderDiscoveryStrategy; +import uk.co.caprica.vlcj.binding.LibC; +import uk.co.caprica.vlcj.binding.RuntimeUtil; + +public class LinuxNativeDiscoveryStrategy extends DirectoryProviderDiscoveryStrategy { + + private static final String[] FILENAME_PATTERNS = new String[]{ + "libvlc\\.so(?:\\.\\d)*", + "libvlccore\\.so(?:\\.\\d)*" + }; + + private static final String[] PLUGIN_PATH_FORMATS = new String[]{ + "%s/plugins", + "%s/vlc/plugins" + }; + + public LinuxNativeDiscoveryStrategy() { + super(FILENAME_PATTERNS, PLUGIN_PATH_FORMATS); + } + + @Override + public boolean supported() { + return RuntimeUtil.isNix(); + } + + @Override + protected boolean setPluginPath(final String pluginPath) { + return LibC.INSTANCE.setenv(PLUGIN_ENV_NAME, pluginPath, 1) == 0; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/osx/OsxNativeDiscoveryStrategy.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/osx/OsxNativeDiscoveryStrategy.java new file mode 100644 index 0000000..35eda67 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/osx/OsxNativeDiscoveryStrategy.java @@ -0,0 +1,62 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy.osx; + +import com.sun.jna.NativeLibrary; +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DirectoryProviderDiscoveryStrategy; +import uk.co.caprica.vlcj.binding.LibC; +import uk.co.caprica.vlcj.binding.RuntimeUtil; + +public class OsxNativeDiscoveryStrategy extends DirectoryProviderDiscoveryStrategy { + + private static final String[] FILENAME_PATTERNS = new String[]{ + "libvlc\\.dylib", + "libvlccore\\.dylib" + }; + + private static final String[] PLUGIN_PATH_FORMATS = new String[]{ + "%s/../plugins" + }; + + public OsxNativeDiscoveryStrategy() { + super(FILENAME_PATTERNS, PLUGIN_PATH_FORMATS); + } + + @Override + public boolean supported() { + return RuntimeUtil.isMac(); + } + + @Override + public boolean onFound(final String path) { + this.forceLoadLibVlcCore(path); + return true; + } + + private void forceLoadLibVlcCore(final String path) { + NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcCoreLibraryName(), path); + NativeLibrary.getInstance(RuntimeUtil.getLibVlcCoreLibraryName()); + } + + @Override + protected boolean setPluginPath(final String pluginPath) { + return LibC.INSTANCE.setenv(PLUGIN_ENV_NAME, pluginPath, 1) == 0; + } +} diff --git a/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/win/WindowsNativeDiscoveryStrategy.java b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/win/WindowsNativeDiscoveryStrategy.java new file mode 100644 index 0000000..6174238 --- /dev/null +++ b/src/main/java/io/github/pulsebeat02/emcinstallers/implementation/vlc/search/strategy/win/WindowsNativeDiscoveryStrategy.java @@ -0,0 +1,51 @@ +/* + * This file is part of VLCJ. + * + * VLCJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VLCJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VLCJ. If not, see . + * + * Copyright 2009-2019 Caprica Software Limited. + */ + +package io.github.pulsebeat02.emcinstallers.implementation.vlc.search.strategy.win; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.search.provider.DirectoryProviderDiscoveryStrategy; +import uk.co.caprica.vlcj.binding.LibC; +import uk.co.caprica.vlcj.binding.RuntimeUtil; + +public class WindowsNativeDiscoveryStrategy extends DirectoryProviderDiscoveryStrategy { + + private static final String[] FILENAME_PATTERNS = new String[]{ + "libvlc\\.dll", + "libvlccore\\.dll" + }; + + private static final String[] PLUGIN_PATH_FORMATS = new String[]{ + "%s\\plugins", + "%s\\vlc\\plugins" + }; + + public WindowsNativeDiscoveryStrategy() { + super(FILENAME_PATTERNS, PLUGIN_PATH_FORMATS); + } + + @Override + public boolean supported() { + return RuntimeUtil.isWindows(); + } + + @Override + protected boolean setPluginPath(final String pluginPath) { + return LibC.INSTANCE._putenv(String.format("%s=%s", PLUGIN_ENV_NAME, pluginPath)) == 0; + } +} diff --git a/src/test/java/io/github/pulsebeat02/ffmpeginstaller/InstallerTest.java b/src/test/java/io/github/pulsebeat02/ffmpeginstaller/InstallerTest.java new file mode 100644 index 0000000..a06f755 --- /dev/null +++ b/src/test/java/io/github/pulsebeat02/ffmpeginstaller/InstallerTest.java @@ -0,0 +1,12 @@ +package io.github.pulsebeat02.ffmpeginstaller; + +import io.github.pulsebeat02.emcinstallers.implementation.vlc.VLCInstallationKit; +import java.io.IOException; + +public final class InstallerTest { + + public static void main(final String[] args) throws IOException { + final VLCInstallationKit kit = VLCInstallationKit.create(); + System.out.println(kit.start().get()); + } +}