diff --git a/README.md b/README.md
index 80480c3..6a010a0 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,20 @@
-# ws-midi
+
ws-midi
> Send MIDI using WebSocket communication
+---
+
+
+
+- [Usage](#usage)
+ - [Usage with ngrok](#usage-with-ngrok)
+- [Requirements](#requirements)
+
+
+
+---
+
## Usage
* Clone the repo
@@ -13,6 +25,19 @@
* When it asks for an IP, that's your WAN IP (search "what's my IP" on Google)
* The receiver will have a virtual MIDI device called "ws-midi" to use in MIDI-capable apps
+
+### Usage with ngrok
+
+To get the connection working over network where we don't have access to the network-settings, we can use a service like ngrok to tunnel the connection:
+
+* Setup account at ngrok
+* Start ws-midi receiver on the remote host that should receive the signal
+* Start ngrok with `ngrok http 5006` (the port used by ws-midi) on the remote host
+* Start ws-midi send on the local host that should send the signal to the remote host
+ * Use the host url as provided by ngrok in this format: `wss://` (we don't need the port as this goes over HTTPS)
+
+This should then pipe the signal from a local host to the remote host and you should see the MIDI signals arriving there.
+
## Requirements
* node.js
diff --git a/receive.js b/receive.js
index 3c31a36..d4c1152 100644
--- a/receive.js
+++ b/receive.js
@@ -2,7 +2,10 @@ const term = require('terminal-kit').terminal;
const midi = require('midi');
const WebSocket = require('ws');
const { VIRTUAL_MIDI_DEVICE_NAME, PORT } = require('./constants.js');
-let ip;
+
+function heartbeat() {
+ this.isAlive = true;
+}
module.exports = () => {
term.clear();
@@ -45,12 +48,29 @@ module.exports = () => {
const wss = new WebSocket.Server({ port: PORT });
+ const interval = setInterval(function ping() {
+ wss.clients.forEach(function each(ws) {
+ if (ws.isAlive === false) return ws.terminate();
+
+ ws.isAlive = false;
+ ws.ping();
+ });
+ }, 10 * 1000);
+
+ wss.on('close', function close() {
+ clearInterval(interval);
+ });
+
wss.on('listening', function listening() {
term.black.bgGreen(`websocket server listening on ${PORT}\n`);
});
wss.on('connection', function connection(ws) {
console.log('new connection');
+
+ ws.isAlive = true;
+ ws.on('error', console.error);
+ ws.on('pong', heartbeat);
ws.on('message', function incoming(wsMessage) {
const message = JSON.parse(wsMessage)
diff --git a/send.js b/send.js
index 2131cd9..cb22aaa 100644
--- a/send.js
+++ b/send.js
@@ -2,7 +2,7 @@ const term = require('terminal-kit').terminal;
const midi = require('midi');
const WebSocket = require('ws');
const { VIRTUAL_MIDI_DEVICE_NAME, PORT } = require('./constants.js');
-let ip;
+let host;
module.exports = () => {
// Set up a new input.
@@ -37,20 +37,20 @@ module.exports = () => {
}
}
- term.cyan(`please enter the IP of the recipient\n`);
+ term.cyan(`please enter the HOST of the recipient in the format ws://host[:port] or wss://host[:port]\n`);
term.inputField((error, response) => {
term.clear();
- ip = response;
+ host = response;
- term.cyan(`opening websocket connection to ${ip}:${PORT}\n`);
- const ws = new WebSocket(`ws://${ip}:${PORT}`);
+ term.cyan(`opening websocket connection to ${host}\n`);
+ const ws = new WebSocket(`${host}`);
ws.on('open', () => {
term.clear();
- term.cyan(`opened websocket connection to ${ip}:${PORT}\n\n`);
+ term.cyan(`opened websocket connection to ${host}\n\n`);
- term.cyan(`please pick a midi input device to send to ${ip}:${PORT}\n`);
+ term.cyan(`please pick a midi input device to send to ${host}\n`);
term.singleColumnMenu(inputDeviceNames, {
cancelable: true,
@@ -66,7 +66,7 @@ module.exports = () => {
const midiInputDeviceId = response.selectedIndex;
- term.cyan(`opened websocket connection to ${ip}:${PORT}\n\n`);
+ term.cyan(`opened websocket connection to ${host}\n\n`);
term.cyan(`please pick a midi output device to route locally`);