/
DefaultSendSystem.java
117 lines (107 loc) · 4.28 KB
/
DefaultSendSystem.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
* Copyright 2015-2017 Austin Keener & Michael Ritter & Florian Spieß
*
* 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
*
* http://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.
*/
package net.dv8tion.jda.core.audio.factory;
import net.dv8tion.jda.core.audio.AudioConnection;
import net.dv8tion.jda.core.managers.impl.AudioManagerImpl;
import net.dv8tion.jda.core.utils.SimpleLog;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.NoRouteToHostException;
import java.net.SocketException;
import static net.dv8tion.jda.core.audio.AudioConnection.OPUS_FRAME_TIME_AMOUNT;
/**
* The default implementation of the {@link net.dv8tion.jda.core.audio.factory.IAudioSendSystem IAudioSendSystem}.
* <br>This implementation uses a Java thread, named based on: {@link IPacketProvider#getIdentifier()} + " Sending Thread".
*/
public class DefaultSendSystem implements IAudioSendSystem
{
private final IPacketProvider packetProvider;
private Thread sendThread;
public DefaultSendSystem(IPacketProvider packetProvider)
{
this.packetProvider = packetProvider;
}
@Override
public void start()
{
final DatagramSocket udpSocket = packetProvider.getUdpSocket();
sendThread = new Thread(AudioManagerImpl.AUDIO_THREADS, () ->
{
long lastFrameSent = System.currentTimeMillis();
while (!udpSocket.isClosed() && !sendThread.isInterrupted())
{
try
{
boolean changeTalking = (System.currentTimeMillis() - lastFrameSent) > OPUS_FRAME_TIME_AMOUNT;
DatagramPacket packet = packetProvider.getNextPacket(changeTalking);
if (packet != null)
udpSocket.send(packet);
}
catch (NoRouteToHostException e)
{
packetProvider.onConnectionLost();
}
catch (SocketException e)
{
//Most likely the socket has been closed due to the audio connection be closed. Next iteration will kill loop.
}
catch (Exception e)
{
AudioConnection.LOG.fatal(e);
}
finally
{
long sleepTime = (OPUS_FRAME_TIME_AMOUNT) - (System.currentTimeMillis() - lastFrameSent);
if (sleepTime > 0)
{
try
{
Thread.sleep(sleepTime);
}
catch (InterruptedException e)
{
//We've been asked to stop.
Thread.currentThread().interrupt();
}
}
if (System.currentTimeMillis() < lastFrameSent + 60) // If the sending didn't took longer than 60ms (3 times the time frame)
{
lastFrameSent += OPUS_FRAME_TIME_AMOUNT; // increase lastFrameSent
}
else
{
lastFrameSent = System.currentTimeMillis(); // else reset lastFrameSent to current time
}
}
}
});
sendThread.setUncaughtExceptionHandler((thread, throwable) ->
{
SimpleLog.getLog(DefaultSendSystem.class).fatal(throwable);
start();
});
sendThread.setDaemon(true);
sendThread.setName(packetProvider.getIdentifier() + " Sending Thread");
sendThread.setPriority((Thread.NORM_PRIORITY + Thread.MAX_PRIORITY) / 2);
sendThread.start();
}
@Override
public void shutdown()
{
if (sendThread != null)
sendThread.interrupt();
}
}