diff --git a/README.md b/README.md index 0273091..39da05e 100644 --- a/README.md +++ b/README.md @@ -8,56 +8,44 @@ This is a rust implementation of the original JDA-NAS natives. This can be used ## Setup -[ ![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-api?color=blue&label=udpqueue-api) ](https://search.maven.org/artifact/club.minnced/udpqueue-api) +[![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-api?color=blue&label=udpqueue-api)](https://search.maven.org/artifact/club.minnced/udpqueue-api) Supported native platforms: Linux x86 (intel): -[ ![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-x86-64?color=blue&label=linux-x86-64&logo=linux&logoColor=white) ](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-x86-64) -[ ![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-x86?color=blue&label=linux-x86&logo=linux&logoColor=white) ](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-x86) -[ ![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-musl-x86-64?color=blue&label=linux-musl-x86-64&logo=linux&logoColor=white) ](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-musl-x86) +[![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-x86-64?color=blue&label=linux-x86-64&logo=linux&logoColor=white)](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-x86-64) +[![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-x86?color=blue&label=linux-x86&logo=linux&logoColor=white)](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-x86) +[![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-musl-x86-64?color=blue&label=linux-musl-x86-64&logo=linux&logoColor=white)](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-musl-x86) Linux ARM (v7 and x64): -[ ![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-aarch64?color=blue&label=linux-aarch64&logo=linux&logoColor=white) ](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-aarch64) -[ ![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-arm?color=blue&label=linux-arm&logo=linux&logoColor=white) ](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-arm) -[ ![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-musl-aarch64?color=blue&label=linux-musl-aarch64&logo=linux&logoColor=white) ](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-musl-aarch64) +[![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-aarch64?color=blue&label=linux-aarch64&logo=linux&logoColor=white)](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-aarch64) +[![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-arm?color=blue&label=linux-arm&logo=linux&logoColor=white)](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-arm) +[![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-linux-musl-aarch64?color=blue&label=linux-musl-aarch64&logo=linux&logoColor=white)](https://search.maven.org/artifact/club.minnced/udpqueue-native-linux-musl-aarch64) Windows x86 (intel): -[ ![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-win-x86-64?color=blue&label=win-x86-64&logo=windows&logoColor=white) ](https://search.maven.org/artifact/club.minnced/udpqueue-native-win-x86-64) -[ ![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-win-x86?color=blue&label=win-x86&logo=windows&logoColor=white) ](https://search.maven.org/artifact/club.minnced/udpqueue-native-win-x86) +[![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-win-x86-64?color=blue&label=win-x86-64&logo=windows&logoColor=white)](https://search.maven.org/artifact/club.minnced/udpqueue-native-win-x86-64) +[![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-win-x86?color=blue&label=win-x86&logo=windows&logoColor=white)](https://search.maven.org/artifact/club.minnced/udpqueue-native-win-x86) MacOS/Darwin universal (x86 intel & aarch64 M1): -[ ![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-darwin?color=blue&label=darwin&logo=apple&logoColor=white) ](https://search.maven.org/artifact/club.minnced/udpqueue-native-darwin) +[![](https://img.shields.io/maven-central/v/club.minnced/udpqueue-native-darwin?color=blue&label=darwin&logo=apple&logoColor=white)](https://search.maven.org/artifact/club.minnced/udpqueue-native-darwin) More platforms can be added on request. Linux shared libraries are compiled against **GLIBC 2.18**. -While this project is published to maven-central, the lavaplayer commons dependency is currently only available through jcenter. So you will have to depend on jcenter for now. - -1. Add the original [jda-nas](https://github.com/sedmelluq/jda-nas) dependency to your project, and exclude `udp-queue` from its transitive dependencies: +Simply install the version of `udpqueue-native-*` for your platform: ```gradle repositories { mavenCentral() } -dependencies { - implementation("com.sedmelluq:jda-nas:1.1.0") { - exclude(module="udp-queue") - } -} -``` - -2. Add udpqueue natives - -```gradle dependencies { // Fully modular, choose which platforms to use! - implementation("club.minnced:udpqueue-native-linux-x86-64:0.2.7") // adds linux 64bit - implementation("club.minnced:udpqueue-native-win-x86-64:0.2.7") // adds windows 64bit + implementation("club.minnced:udpqueue-native-linux-x86-64:0.2.9") // adds linux 64bit + implementation("club.minnced:udpqueue-native-win-x86-64:0.2.9") // adds windows 64bit } ``` @@ -68,15 +56,19 @@ Use `./install.sh ` to install the jar for your specific platform in ma To add all supported platforms, you can use this: ```gradle +repositories { + mavenCentral() +} + dependencies { - implementation("club.minnced:udpqueue-native-linux-x86-64:0.2.7") - implementation("club.minnced:udpqueue-native-linux-x86:0.2.7") - implementation("club.minnced:udpqueue-native-linux-aarch64:0.2.7") - implementation("club.minnced:udpqueue-native-linux-arm:0.2.7") - implementation("club.minnced:udpqueue-native-linux-musl-x86-64:0.2.7") - implementation("club.minnced:udpqueue-native-linux-musl-aarch64:0.2.7") - implementation("club.minnced:udpqueue-native-win-x86-64:0.2.7") - implementation("club.minnced:udpqueue-native-win-x86:0.2.7") - implementation("club.minnced:udpqueue-native-darwin:0.2.7") + implementation("club.minnced:udpqueue-native-linux-x86-64:0.2.9") + implementation("club.minnced:udpqueue-native-linux-x86:0.2.9") + implementation("club.minnced:udpqueue-native-linux-aarch64:0.2.9") + implementation("club.minnced:udpqueue-native-linux-arm:0.2.9") + implementation("club.minnced:udpqueue-native-linux-musl-x86-64:0.2.9") + implementation("club.minnced:udpqueue-native-linux-musl-aarch64:0.2.9") + implementation("club.minnced:udpqueue-native-win-x86-64:0.2.9") + implementation("club.minnced:udpqueue-native-win-x86:0.2.9") + implementation("club.minnced:udpqueue-native-darwin:0.2.9") } ``` diff --git a/api/build.gradle.kts b/api/build.gradle.kts index bd5730d..1eef0b9 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -14,6 +14,7 @@ repositories { dependencies { implementation("org.slf4j:slf4j-api:1.7.25") implementation("dev.arbjerg:lava-common:1.5.4") + compileOnly("net.dv8tion:JDA:5.0.2") } val javadoc: Javadoc by tasks diff --git a/api/src/main/java/com/sedmelluq/discord/lavaplayer/jdaudp/NativeAudioSendFactory.java b/api/src/main/java/com/sedmelluq/discord/lavaplayer/jdaudp/NativeAudioSendFactory.java new file mode 100644 index 0000000..07ee02f --- /dev/null +++ b/api/src/main/java/com/sedmelluq/discord/lavaplayer/jdaudp/NativeAudioSendFactory.java @@ -0,0 +1,101 @@ +package com.sedmelluq.discord.lavaplayer.jdaudp; + +import com.sedmelluq.discord.lavaplayer.udpqueue.natives.UdpQueueManager; +import com.sedmelluq.lava.common.tools.DaemonThreadFactory; +import com.sedmelluq.lava.common.tools.ExecutorTools; +import net.dv8tion.jda.api.audio.factory.IAudioSendFactory; +import net.dv8tion.jda.api.audio.factory.IAudioSendSystem; +import net.dv8tion.jda.api.audio.factory.IPacketProvider; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentHashMap.KeySetView; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +public class NativeAudioSendFactory implements IAudioSendFactory { + private static final int DEFAULT_BUFFER_DURATION = 400; + private static final int PACKET_INTERVAL = 20; + private static final int MAXIMUM_PACKET_SIZE = 4096; + + private final int bufferDuration; + private final AtomicLong identifierCounter = new AtomicLong(); + private final KeySetView systems = ConcurrentHashMap.newKeySet(); + private final Object lock = new Object(); + private volatile UdpQueueManager queueManager; + private ScheduledExecutorService scheduler; + + public NativeAudioSendFactory() { + this(DEFAULT_BUFFER_DURATION); + } + + public NativeAudioSendFactory(int bufferDuration) { + this.bufferDuration = bufferDuration; + } + + private void initialiseQueueManager() { + scheduler = new ScheduledThreadPoolExecutor(1, new DaemonThreadFactory("native-udp")); + queueManager = new UdpQueueManager(bufferDuration / PACKET_INTERVAL, + TimeUnit.MILLISECONDS.toNanos(PACKET_INTERVAL), MAXIMUM_PACKET_SIZE); + + scheduler.scheduleWithFixedDelay(this::populateQueues, 0, 40, TimeUnit.MILLISECONDS); + + Thread thread = new Thread(process(queueManager)); + thread.setPriority((Thread.NORM_PRIORITY + Thread.MAX_PRIORITY) / 2); + thread.setDaemon(true); + thread.start(); + } + + private ScheduledExecutorService shutdownQueueManager() { + queueManager.close(); + queueManager = null; + + ScheduledExecutorService currentScheduler = scheduler; + scheduler = null; + return currentScheduler; + } + + @Override + public IAudioSendSystem createSendSystem(IPacketProvider packetProvider) { + return new NativeAudioSendSystem(identifierCounter.incrementAndGet(), this, packetProvider); + } + + void addInstance(NativeAudioSendSystem system) { + synchronized (lock) { + systems.add(system); + + if (queueManager == null) { + initialiseQueueManager(); + } + } + } + + void removeInstance(NativeAudioSendSystem system) { + ScheduledExecutorService schedulerToShutDown = null; + + synchronized (lock) { + if (systems.remove(system) && systems.isEmpty() && queueManager != null) { + schedulerToShutDown = shutdownQueueManager(); + } + } + + if (schedulerToShutDown != null) { + ExecutorTools.shutdownExecutor(schedulerToShutDown, "native udp queue populator"); + } + } + + private void populateQueues() { + UdpQueueManager manager = queueManager; /* avoid getfield opcode */ + + if (manager != null) { + for (NativeAudioSendSystem system : systems) { + system.populateQueue(manager); + } + } + } + + private static Runnable process(UdpQueueManager unbake) { + return unbake::process; + } +} \ No newline at end of file diff --git a/api/src/main/java/com/sedmelluq/discord/lavaplayer/jdaudp/NativeAudioSendSystem.java b/api/src/main/java/com/sedmelluq/discord/lavaplayer/jdaudp/NativeAudioSendSystem.java new file mode 100644 index 0000000..141802e --- /dev/null +++ b/api/src/main/java/com/sedmelluq/discord/lavaplayer/jdaudp/NativeAudioSendSystem.java @@ -0,0 +1,44 @@ +package com.sedmelluq.discord.lavaplayer.jdaudp; + +import com.sedmelluq.discord.lavaplayer.udpqueue.natives.UdpQueueManager; +import net.dv8tion.jda.api.audio.factory.IAudioSendSystem; +import net.dv8tion.jda.api.audio.factory.IPacketProvider; + +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; + +public class NativeAudioSendSystem implements IAudioSendSystem { + private final long queueKey; + private final NativeAudioSendFactory audioSendSystem; + private final IPacketProvider packetProvider; + + public NativeAudioSendSystem(long queueKey, NativeAudioSendFactory audioSendSystem, IPacketProvider packetProvider) { + this.queueKey = queueKey; + this.audioSendSystem = audioSendSystem; + this.packetProvider = packetProvider; + } + + @Override + public void start() { + audioSendSystem.addInstance(this); + } + + @Override + public void shutdown() { + audioSendSystem.removeInstance(this); + } + + void populateQueue(UdpQueueManager queueManager) { + int remaining = queueManager.getRemainingCapacity(queueKey); + boolean emptyQueue = queueManager.getCapacity() - remaining > 0; + + for (int i = 0; i < remaining; i++) { + ByteBuffer packet = packetProvider.getNextPacketRaw(emptyQueue); + InetSocketAddress address = packetProvider.getSocketAddress(); + + if (packet == null || !queueManager.queuePacket(queueKey, packet, address)) { + break; + } + } + } +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 07d9da8..d4c2b61 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -47,7 +47,7 @@ subprojects { } group = "club.minnced" - version = "0.2.8" + version = "0.2.9" // See https://github.com/sedmelluq/lavaplayer/blob/master/common/src/main/java/com/sedmelluq/lava/common/natives/architecture/DefaultArchitectureTypes.java // identifier is the suffix used after the system name