Search in sources :

Example 1 with AudioSourceFinishedEventImpl

use of org.javacord.core.event.audio.AudioSourceFinishedEventImpl in project Javacord by BtoBastian.

the class AudioUdpSocket method startSending.

/**
 * Starts polling frames from the audio connection and sending them through the socket.
 */
public void startSending() {
    if (shouldSend) {
        return;
    }
    shouldSend = true;
    DiscordApiImpl api = (DiscordApiImpl) connection.getChannel().getApi();
    api.getThreadPool().getSingleThreadExecutorService(threadName).submit(() -> {
        try {
            long nextFrameTimestamp = System.nanoTime();
            boolean dontSleep = true;
            boolean speaking = false;
            long framesOfSilenceToPlay = 5;
            while (shouldSend) {
                // Get the current audio source. If none is available, it will block the thread
                AudioSource source = connection.getCurrentAudioSourceBlocking();
                if (source == null) {
                    logger.error("Got null audio source without being interrupted ({})", connection);
                    return;
                }
                if (source.hasFinished()) {
                    connection.removeAudioSource();
                    dontSleep = true;
                    // Dispatch AudioSourceFinishedEvent AFTER removing the source.
                    // Otherwise, AudioSourceFinishedEvent#getNextSource() won't work
                    api.getEventDispatcher().dispatchAudioSourceFinishedEvent((ServerImpl) connection.getServer(), connection, ((AudioSourceBase) source).getDelegate(), new AudioSourceFinishedEventImpl(source, connection));
                    continue;
                }
                AudioPacket packet = null;
                byte[] frame = source.hasNextFrame() ? source.getNextFrame() : null;
                // If the source is muted, replace the frame with a muted frame
                if (source.isMuted()) {
                    frame = null;
                }
                if (frame != null || framesOfSilenceToPlay > 0) {
                    if (!speaking && frame != null) {
                        speaking = true;
                        connection.setSpeaking(true);
                    }
                    packet = new AudioPacket(frame, ssrc, sequence, ((int) sequence) * 960);
                    // We can stop sending frames of silence after 5 frames
                    if (frame == null) {
                        framesOfSilenceToPlay--;
                        if (framesOfSilenceToPlay == 0) {
                            speaking = false;
                            connection.setSpeaking(false);
                        }
                    } else {
                        framesOfSilenceToPlay = 5;
                    }
                }
                nextFrameTimestamp = nextFrameTimestamp + 20_000_000;
                sequence++;
                if (packet != null) {
                    packet.encrypt(secretKey);
                }
                try {
                    if (dontSleep) {
                        nextFrameTimestamp = System.nanoTime() + 20_000_000;
                        dontSleep = false;
                    } else {
                        Thread.sleep(Math.max(0, nextFrameTimestamp - System.nanoTime()) / 1_000_000);
                    }
                    if (packet != null) {
                        socket.send(packet.asUdpPacket(address));
                    }
                } catch (IOException e) {
                    logger.error("Failed to send audio packet for {}", connection);
                }
            }
        } catch (InterruptedException e) {
            if (shouldSend) {
                logger.debug("Got interrupted unexpectedly while waiting for next audio source packet");
            }
        }
    });
}
Also used : AudioSource(org.javacord.api.audio.AudioSource) DiscordApiImpl(org.javacord.core.DiscordApiImpl) AudioSourceFinishedEventImpl(org.javacord.core.event.audio.AudioSourceFinishedEventImpl) IOException(java.io.IOException)

Aggregations

IOException (java.io.IOException)1 AudioSource (org.javacord.api.audio.AudioSource)1 DiscordApiImpl (org.javacord.core.DiscordApiImpl)1 AudioSourceFinishedEventImpl (org.javacord.core.event.audio.AudioSourceFinishedEventImpl)1