diff --git a/pom.xml b/pom.xml
index b62a17dd..47e86251 100644
--- a/pom.xml
+++ b/pom.xml
@@ -181,6 +181,16 @@
Java-WebSocket
1.5.3
+
+ org.slf4j
+ slf4j-api
+ 1.7.36
+
+
+ org.slf4j
+ slf4j-simple
+ 1.7.36
+
diff --git a/src/main/java/sh/ball/gui/Gui.java b/src/main/java/sh/ball/gui/Gui.java
index 07af99d1..65848d5c 100644
--- a/src/main/java/sh/ball/gui/Gui.java
+++ b/src/main/java/sh/ball/gui/Gui.java
@@ -90,6 +90,7 @@ public class Gui extends Application {
stage.show();
stage.setOnCloseRequest(t -> {
+ controller.shutdown();
Platform.exit();
System.exit(0);
});
diff --git a/src/main/java/sh/ball/gui/controller/MainController.java b/src/main/java/sh/ball/gui/controller/MainController.java
index e7f77340..8d74e489 100644
--- a/src/main/java/sh/ball/gui/controller/MainController.java
+++ b/src/main/java/sh/ball/gui/controller/MainController.java
@@ -51,7 +51,7 @@ import sh.ball.audio.midi.MidiNote;
import sh.ball.engine.ObjectServer;
import sh.ball.engine.ObjectSet;
import sh.ball.gui.Gui;
-import sh.ball.oscilloscope.OscilloscopeServer;
+import sh.ball.oscilloscope.ByteWebSocketServer;
import sh.ball.parser.obj.ObjFrameSettings;
import sh.ball.parser.obj.ObjParser;
import sh.ball.parser.ParserFactory;
@@ -73,7 +73,7 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
private String openProjectPath;
private final FileChooser wavFileChooser = new FileChooser();
- private ObjectServer server;
+ private ObjectServer objectServer;
// audio
private int sampleRate;
@@ -106,6 +106,13 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
private final FileChooser osciFileChooser = new FileChooser();
private Stage stage;
+ // software oscilloscope
+ private static final int SOSCI_NUM_VERTICES = 4096;
+ private static final int SOSCI_VERTEX_SIZE = 2;
+ private static final int FRAME_SIZE = 2;
+ private byte[] buffer;
+ private ByteWebSocketServer webSocketServer;
+
@FXML
private EffectsController effectsController;
@FXML
@@ -206,6 +213,10 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
channelClosestToZero.put(slider, closestToZero);
}
+ public void shutdown() {
+ webSocketServer.shutdown();
+ }
+
// alternates between recording and not recording when called.
// If it is a non-timed recording, it is saved when this is called and
// recording is stopped. If it is a time recording, this function will cancel
@@ -457,15 +468,30 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
}
}
- server = new ObjectServer(this::enableObjectServerRendering, this::disableObjectServerRendering);
- new Thread(server).start();
- new OscilloscopeServer<>(audioPlayer, 2).start();
+ objectServer = new ObjectServer(this::enableObjectServerRendering, this::disableObjectServerRendering);
+ new Thread(objectServer).start();
+
+ webSocketServer = new ByteWebSocketServer();
+ webSocketServer.start();
+ this.buffer = new byte[FRAME_SIZE * SOSCI_NUM_VERTICES * SOSCI_VERTEX_SIZE];
+ new Thread(() -> sendAudioDataToWebSocket(webSocketServer)).start();
+ }
+
+ private void sendAudioDataToWebSocket(ByteWebSocketServer server) {
+ while (true) {
+ try {
+ audioPlayer.read(buffer);
+ server.send(buffer);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
}
private void enableObjectServerRendering() {
Platform.runLater(() -> {
objectServerRendering = true;
- ObjectSet set = server.getObjectSet();
+ ObjectSet set = objectServer.getObjectSet();
frameSources.forEach(FrameSource::disable);
set.enable();
@@ -483,7 +509,7 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
private void disableObjectServerRendering() {
Platform.runLater(() -> {
- server.getObjectSet().disable();
+ objectServer.getObjectSet().disable();
objectServerRendering = false;
changeFrameSource(currentFrameSource);
});
diff --git a/src/main/java/sh/ball/oscilloscope/ByteWebSocketServer.java b/src/main/java/sh/ball/oscilloscope/ByteWebSocketServer.java
new file mode 100644
index 00000000..11130d46
--- /dev/null
+++ b/src/main/java/sh/ball/oscilloscope/ByteWebSocketServer.java
@@ -0,0 +1,56 @@
+package sh.ball.oscilloscope;
+
+import org.java_websocket.WebSocket;
+import org.java_websocket.handshake.ClientHandshake;
+import org.java_websocket.server.WebSocketServer;
+
+import java.net.InetSocketAddress;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ByteWebSocketServer extends WebSocketServer {
+
+ private static final int TCP_PORT = 42988;
+
+ private final Set conns;
+
+ public ByteWebSocketServer() {
+ super(new InetSocketAddress(TCP_PORT));
+ this.conns = new HashSet<>();
+ }
+
+ public synchronized void send(byte[] bytes) {
+ for (WebSocket sock : conns) {
+ sock.send(bytes);
+ }
+ }
+
+ @Override
+ public synchronized void onOpen(WebSocket conn, ClientHandshake handshake) {
+ conns.add(conn);
+ }
+
+ @Override
+ public synchronized void onClose(WebSocket conn, int code, String reason, boolean remote) {
+ conns.remove(conn);
+ }
+
+ @Override
+ public synchronized void onMessage(WebSocket conn, String message) {}
+
+ @Override
+ public synchronized void onError(WebSocket conn, Exception ex) {
+ ex.printStackTrace();
+ if (conn != null) {
+ conns.remove(conn);
+ }
+ }
+
+ public synchronized void shutdown() {
+ conns.forEach(WebSocket::close);
+ conns.clear();
+ }
+
+ @Override
+ public void onStart() {}
+}
\ No newline at end of file
diff --git a/src/main/java/sh/ball/oscilloscope/OscilloscopeServer.java b/src/main/java/sh/ball/oscilloscope/OscilloscopeServer.java
deleted file mode 100644
index a27fc9fe..00000000
--- a/src/main/java/sh/ball/oscilloscope/OscilloscopeServer.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package sh.ball.oscilloscope;
-
-import org.java_websocket.WebSocket;
-import org.java_websocket.handshake.ClientHandshake;
-import org.java_websocket.server.WebSocketServer;
-import sh.ball.audio.AudioPlayer;
-
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.ShortBuffer;
-import java.util.HashSet;
-import java.util.Set;
-
-public class OscilloscopeServer extends WebSocketServer {
-
- private static final int TCP_PORT = 4444;
- private static final int NUM_VERTICES = 2048;
- private static final int VERTEX_SIZE = 2;
-
- private final Set conns;
- private final AudioPlayer audioPlayer;
- private final int frameSize;
- private final byte[] buffer;
-
- public OscilloscopeServer(AudioPlayer audioPlayer, int frameSize) {
- super(new InetSocketAddress(TCP_PORT));
- this.conns = new HashSet<>();
- this.audioPlayer = audioPlayer;
- this.frameSize = frameSize;
- this.buffer = new byte[frameSize * NUM_VERTICES * VERTEX_SIZE];
- }
-
- public void send(byte[] bytes) {
- for (WebSocket sock : conns) {
- sock.send(bytes);
- }
- }
-
- @Override
- public void onOpen(WebSocket conn, ClientHandshake handshake) {
- conns.add(conn);
- System.out.println("New connection from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
- }
-
- @Override
- public void onClose(WebSocket conn, int code, String reason, boolean remote) {
- conns.remove(conn);
- System.out.println("Closed connection to " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
- }
-
- @Override
- public void onMessage(WebSocket conn, String message) {
- System.out.println("Message from client: " + message);
- for (WebSocket sock : conns) {
- sock.send(message);
- }
- }
-
- @Override
- public void onError(WebSocket conn, Exception ex) {
- //ex.printStackTrace();
- if (conn != null) {
- conns.remove(conn);
- // do some thing if required
- }
- System.out.println("ERROR from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
- }
-
- @Override
- public void onStart() {
- new Thread(() -> {
- while (true) {
- try {
- audioPlayer.read(buffer);
- send(buffer);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
-}
\ No newline at end of file