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