Skip to content

Commit d0e1aa3

Browse files
Add support for custom library (#33)
1 parent ad52011 commit d0e1aa3

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ dependencies {
5353
}
5454
```
5555

56+
> [!NOTE]
57+
> ### Alternative: Custom Native Library
58+
>
59+
> You can bring your own `libdave` binary by using `-Djdave.library.path=/path/to/libdave.so` as a JVM argument or setting it using `System.setProperty(NativeLibraryLoader.LIBRARY_PATH_PROPERTY, path)` before loading the `LibDave` class.
60+
5661
## Example: JDA
5762

5863
To use this library with [JDA](https://github.com/discord-jda/JDA), you can use the [JDaveSessionFactory](api/src/main/java/club/minnced/discord/jdave/interop/JDaveSessionFactory.java) to configure the audio module:

api/src/main/java/club/minnced/discord/jdave/utils/NativeLibraryLoader.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,27 @@
1111
import java.util.StringJoiner;
1212
import org.jspecify.annotations.NonNull;
1313
import org.jspecify.annotations.Nullable;
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
1416

1517
public class NativeLibraryLoader {
18+
public static final String LIBRARY_PATH_PROPERTY = "jdave.library.path";
19+
20+
private static final Logger log = LoggerFactory.getLogger(NativeLibraryLoader.class);
21+
22+
/**
23+
* Returns the path to a local libdave binary, if set.
24+
*
25+
* <p>Uses {@link #LIBRARY_PATH_PROPERTY} to determine the path from system properties.
26+
* If the property is not set, this method returns null.
27+
*
28+
* @return The path to a local libdave binary, or null if not set.
29+
*/
30+
@Nullable
31+
public static String getLibraryPath() {
32+
return System.getProperty(LIBRARY_PATH_PROPERTY);
33+
}
34+
1635
@NonNull
1736
public static NativeLibrary getNativeLibrary() {
1837
return resolveLibrary("dave");
@@ -46,6 +65,11 @@ public static Path createTemporaryFile() {
4665

4766
@NonNull
4867
public static SymbolLookup getSymbolLookup() {
68+
String customLibraryPath = getLibraryPath();
69+
if (customLibraryPath != null) {
70+
return getSymbolLookupFromPath(customLibraryPath);
71+
}
72+
4973
Path tempFile = createTemporaryFile();
5074
return SymbolLookup.libraryLookup(tempFile, Arena.global());
5175
}
@@ -68,6 +92,23 @@ public static NativeLibrary resolveLibrary(
6892
return new NativeLibrary(os, arch, baseName);
6993
}
7094

95+
@NonNull
96+
private static SymbolLookup getSymbolLookupFromPath(@NonNull String customLibraryPath) {
97+
Path path = Path.of(customLibraryPath).toAbsolutePath();
98+
log.debug("Loading library from custom path: {}", path);
99+
if (!Files.exists(path)) {
100+
throw new IllegalStateException("Could not find library at path: " + path);
101+
}
102+
if (!Files.isRegularFile(path)) {
103+
throw new IllegalStateException("Path is not a regular file: " + path);
104+
}
105+
if (!Files.isReadable(path)) {
106+
throw new IllegalStateException("Path is not readable: " + path);
107+
}
108+
109+
return SymbolLookup.libraryLookup(path, Arena.global());
110+
}
111+
71112
@NonNull
72113
private static OperatingSystem getOperatingSystem(@NonNull String osName) {
73114
osName = osName.toLowerCase();

0 commit comments

Comments
 (0)