Address #9 and fix thread exits, add InterruptedException handlers, and make Microphone handling more stateful (don't run a thread all the time if nobody ever sets it)
This commit is contained in:
+12
-12
@@ -147,12 +147,12 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
protected abstract Class<? extends PacketHandler> getHandlerClass(ClientConnectionState state);
|
||||
|
||||
protected void start() {
|
||||
Thread networkThread = new Thread(networkReader);
|
||||
networkThread = new Thread(networkReader);
|
||||
networkThread.setName("TS3J/NetworkReader/" + networkThread.getId());
|
||||
networkThread.setDaemon(true);
|
||||
networkThread.start();
|
||||
|
||||
Thread handlerThread = new Thread(networkHandler);
|
||||
handlerThread = new Thread(networkHandler);
|
||||
handlerThread.setName("TS3J/NetworkHandler/" + handlerThread.getId());
|
||||
handlerThread.setDaemon(true);
|
||||
handlerThread.start();
|
||||
@@ -177,13 +177,14 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
Ts3Debugging.debug("State changing: " + state.name());
|
||||
|
||||
boolean initialState = this.connectionState == null;
|
||||
boolean wasDisconnected = this.connectionState == ClientConnectionState.DISCONNECTED;
|
||||
|
||||
if (wasDisconnected) setReading(true);
|
||||
if (state == ClientConnectionState.CONNECTING)
|
||||
setReading(true);
|
||||
|
||||
this.connectionState = state;
|
||||
|
||||
if (state == ClientConnectionState.DISCONNECTED) setReading(false);
|
||||
if (state == ClientConnectionState.DISCONNECTED)
|
||||
setReading(false);
|
||||
|
||||
connectionStateLock.notifyAll();
|
||||
|
||||
@@ -855,7 +856,7 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
return reading;
|
||||
}
|
||||
|
||||
protected void setReading(boolean b) {
|
||||
protected boolean setReading(boolean b) {
|
||||
if (this.reading != b) {
|
||||
this.reading = b;
|
||||
|
||||
@@ -865,7 +866,11 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getClientId() {
|
||||
@@ -945,14 +950,9 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
while (isReading()) {
|
||||
try {
|
||||
readQueue.put(readPacket());
|
||||
} catch (EOFException e) {
|
||||
} catch (EOFException | InterruptedException e) {
|
||||
break;
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof InterruptedException) {
|
||||
Thread.yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
exceptionHandler.accept(e);
|
||||
break;
|
||||
}
|
||||
|
||||
+31
-13
@@ -50,7 +50,7 @@ public class LocalTeamspeakClientSocket
|
||||
private volatile InetSocketAddress remote;
|
||||
|
||||
private Microphone microphone;
|
||||
private Thread microphoneThread;
|
||||
private HighPrecisionTimer microphoneThread;
|
||||
|
||||
private List<TS3Listener> listeners = new LinkedList<>();
|
||||
|
||||
@@ -281,6 +281,9 @@ public class LocalTeamspeakClientSocket
|
||||
protected void onConnect() {
|
||||
super.onConnect();
|
||||
|
||||
if (microphoneThread != null && !microphoneThread.isAlive())
|
||||
microphoneThread.start();
|
||||
|
||||
final ConnectedEvent connectedEvent = new ConnectedEvent(Collections.emptyMap());
|
||||
commandExecutionService.submit(() -> listeners.forEach(e -> e.onConnected(connectedEvent)));
|
||||
}
|
||||
@@ -391,15 +394,6 @@ public class LocalTeamspeakClientSocket
|
||||
setState(ClientConnectionState.CONNECTING);
|
||||
|
||||
waitForState(ClientConnectionState.CONNECTED, timeout);
|
||||
|
||||
microphoneThread = new HighPrecisionTimer(
|
||||
20,
|
||||
5F, // up to 100ms of drift/catchup
|
||||
new MicrophoneTask()
|
||||
);
|
||||
|
||||
microphoneThread.setDaemon(true);
|
||||
microphoneThread.start();
|
||||
} catch (TimeoutException e) {
|
||||
setState(ClientConnectionState.DISCONNECTED);
|
||||
|
||||
@@ -407,7 +401,7 @@ public class LocalTeamspeakClientSocket
|
||||
} catch (Throwable e) {
|
||||
setState(ClientConnectionState.DISCONNECTED);
|
||||
|
||||
throw new IOException(e);
|
||||
throw new IOException("Problem establishing client connection", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,6 +418,7 @@ public class LocalTeamspeakClientSocket
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
socket.close();
|
||||
commandExecutionService.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -520,13 +515,36 @@ public class LocalTeamspeakClientSocket
|
||||
if (this.microphone != microphone) {
|
||||
this.microphone = microphone;
|
||||
|
||||
if (microphone == null && microphoneThread != null) {
|
||||
microphoneThread.interrupt();
|
||||
if (microphone != null && microphoneThread == null) {
|
||||
microphoneThread = new HighPrecisionTimer(
|
||||
20,
|
||||
5F, // up to 100ms of drift/catchup
|
||||
new MicrophoneTask()
|
||||
);
|
||||
microphoneThread.setDaemon(true);
|
||||
|
||||
if (getState() != ClientConnectionState.DISCONNECTED)
|
||||
microphoneThread.start();
|
||||
} else if (microphone == null && microphoneThread != null) {
|
||||
microphoneThread.gracefulStop();
|
||||
microphoneThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setReading(boolean reading) {
|
||||
if (super.setReading(reading)) {
|
||||
if (!reading) {
|
||||
if (microphoneThread != null) microphoneThread.gracefulStop();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next command return_code we will create and buffer for sending.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.github.manevolent.ts3j;
|
||||
|
||||
import com.github.manevolent.ts3j.audio.*;
|
||||
import com.github.manevolent.ts3j.command.*;
|
||||
import com.github.manevolent.ts3j.enums.*;
|
||||
import com.github.manevolent.ts3j.event.*;
|
||||
import com.github.manevolent.ts3j.identity.LocalIdentity;
|
||||
import com.github.manevolent.ts3j.protocol.client.ClientConnectionState;
|
||||
@@ -22,6 +24,19 @@ public class ServerConnectionTest {
|
||||
client.setIdentity(identity);
|
||||
client.setNickname(ServerConnectionTest.class.getSimpleName());
|
||||
client.setHWID("TestTestTest");
|
||||
client.setMicrophone(new Microphone() {
|
||||
@Override public boolean isReady() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public CodecType getCodec() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public byte[] provide() {
|
||||
return new byte[0];
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
client.connect(
|
||||
@@ -31,19 +46,11 @@ public class ServerConnectionTest {
|
||||
|
||||
assertEquals(client.getState(), ClientConnectionState.CONNECTED);
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
client.setDescription("Heyo");
|
||||
|
||||
client.subscribeAll();
|
||||
|
||||
Thread.sleep(100000);
|
||||
|
||||
client.disconnect("BYE");
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
Thread.sleep(3000L);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user