@@ -1 +1 @@ | |||||
Subproject commit b7066201022a757cbcbd986d8c91d565e4daef90 | |||||
Subproject commit 383f24f6ed41facf25eda0d32b0f6bc9aee96e53 |
@@ -1,6 +1,7 @@ | |||||
#pragma once | #pragma once | ||||
#include "bridgeprotocol.hpp" | #include "bridgeprotocol.hpp" | ||||
#include "audio.hpp" | #include "audio.hpp" | ||||
#include "midi.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -8,6 +9,8 @@ namespace rack { | |||||
void bridgeInit(); | void bridgeInit(); | ||||
void bridgeDestroy(); | void bridgeDestroy(); | ||||
void bridgeMidiSubscribe(int channel, MidiInput *midi); | |||||
void bridgeMidiUnsubscribe(int channel, MidiInput *midi); | |||||
void bridgeAudioSubscribe(int channel, AudioIO *audio); | void bridgeAudioSubscribe(int channel, AudioIO *audio); | ||||
void bridgeAudioUnsubscribe(int channel, AudioIO *audio); | void bridgeAudioUnsubscribe(int channel, AudioIO *audio); | ||||
@@ -5,10 +5,16 @@ | |||||
namespace rack { | namespace rack { | ||||
static const int BRIDGE_NUM_PORTS = 16; | |||||
static const int BRIDGE_NUM_PARAMS = 16; | |||||
// A random number which prevents connection from other protocols and old Bridge versions | |||||
const uint32_t BRIDGE_HELLO = 0xff00fefd; | |||||
// TODO Change driver and port number to something less common | |||||
/** Driver ID in AudioIO and MidiIO */ | |||||
#define BRIDGE_DRIVER -5000 | |||||
#define BRIDGE_HOST "127.0.0.1" | |||||
#define BRIDGE_PORT 5000 | |||||
#define BRIDGE_NUM_PORTS 16 | |||||
/** Number of VST/AU automation parameters */ | |||||
#define BRIDGE_NUM_PARAMS 16 | |||||
/** An arbitrary number which prevents connection from other protocols (like WebSockets) and old Bridge versions */ | |||||
#define BRIDGE_HELLO 0xff00fefd | |||||
/** All commands are called from the client and served by the server | /** All commands are called from the client and served by the server | ||||
@@ -70,14 +70,14 @@ struct MidiInput : MidiIO { | |||||
MidiInput(); | MidiInput(); | ||||
~MidiInput(); | ~MidiInput(); | ||||
void setDriver(int driver) override; | void setDriver(int driver) override; | ||||
virtual void onMessage(const MidiMessage &message) {} | |||||
virtual void onMessage(MidiMessage message) {} | |||||
}; | }; | ||||
struct MidiInputQueue : MidiInput { | struct MidiInputQueue : MidiInput { | ||||
int queueSize = 8192; | int queueSize = 8192; | ||||
std::queue<MidiMessage> queue; | std::queue<MidiMessage> queue; | ||||
void onMessage(const MidiMessage &message) override; | |||||
void onMessage(MidiMessage message) override; | |||||
/** If a MidiMessage is available, writes `message` and return true */ | /** If a MidiMessage is available, writes `message` and return true */ | ||||
bool shift(MidiMessage *message); | bool shift(MidiMessage *message); | ||||
}; | }; | ||||
@@ -3,9 +3,6 @@ | |||||
#include "bridge.hpp" | #include "bridge.hpp" | ||||
#define BRIDGE_DRIVER -5000 | |||||
namespace rack { | namespace rack { | ||||
@@ -24,6 +24,7 @@ namespace rack { | |||||
struct BridgeClientConnection; | struct BridgeClientConnection; | ||||
static BridgeClientConnection *connections[BRIDGE_NUM_PORTS] = {}; | static BridgeClientConnection *connections[BRIDGE_NUM_PORTS] = {}; | ||||
static AudioIO *audioListeners[BRIDGE_NUM_PORTS] = {}; | static AudioIO *audioListeners[BRIDGE_NUM_PORTS] = {}; | ||||
static MidiInput *midiListeners[BRIDGE_NUM_PORTS] = {}; | |||||
static std::thread serverThread; | static std::thread serverThread; | ||||
static bool serverRunning = false; | static bool serverRunning = false; | ||||
@@ -51,7 +52,7 @@ struct BridgeClientConnection { | |||||
#else | #else | ||||
int flags = 0; | int flags = 0; | ||||
#endif | #endif | ||||
ssize_t actual = ::send(client, buffer, length, flags); | |||||
ssize_t actual = ::send(client, (const char*) buffer, length, flags); | |||||
if (actual != length) { | if (actual != length) { | ||||
ready = false; | ready = false; | ||||
return false; | return false; | ||||
@@ -74,7 +75,7 @@ struct BridgeClientConnection { | |||||
#else | #else | ||||
int flags = 0; | int flags = 0; | ||||
#endif | #endif | ||||
ssize_t actual = ::recv(client, buffer, length, flags); | |||||
ssize_t actual = ::recv(client, (char*) buffer, length, flags); | |||||
if (actual != length) { | if (actual != length) { | ||||
ready = false; | ready = false; | ||||
return false; | return false; | ||||
@@ -145,9 +146,12 @@ struct BridgeClientConnection { | |||||
} break; | } break; | ||||
case MIDI_MESSAGE_SEND_COMMAND: { | case MIDI_MESSAGE_SEND_COMMAND: { | ||||
uint8_t midiBuffer[3]; | |||||
recv(&midiBuffer, 3); | |||||
debug("MIDI: %02x %02x %02x", midiBuffer[0], midiBuffer[1], midiBuffer[2]); | |||||
MidiMessage message; | |||||
if (!recv(&message, 3)) { | |||||
ready = false; | |||||
return; | |||||
} | |||||
processMidi(message); | |||||
} break; | } break; | ||||
case AUDIO_SAMPLE_RATE_SET_COMMAND: { | case AUDIO_SAMPLE_RATE_SET_COMMAND: { | ||||
@@ -214,6 +218,14 @@ struct BridgeClientConnection { | |||||
} | } | ||||
} | } | ||||
void processMidi(MidiMessage message) { | |||||
if (!(0 <= port && port < BRIDGE_NUM_PORTS)) | |||||
return; | |||||
if (!midiListeners[port]) | |||||
return; | |||||
midiListeners[port]->onMessage(message); | |||||
} | |||||
void setSampleRate(int sampleRate) { | void setSampleRate(int sampleRate) { | ||||
this->sampleRate = sampleRate; | this->sampleRate = sampleRate; | ||||
refreshAudio(); | refreshAudio(); | ||||
@@ -288,29 +300,15 @@ static void serverConnect() { | |||||
#endif | #endif | ||||
// Get address | // Get address | ||||
#ifdef ARCH_WIN | |||||
struct addrinfo hints; | |||||
struct addrinfo *result = NULL; | |||||
ZeroMemory(&hints, sizeof(hints)); | |||||
hints.ai_family = AF_INET; | |||||
hints.ai_socktype = SOCK_STREAM; | |||||
hints.ai_protocol = IPPROTO_TCP; | |||||
hints.ai_flags = AI_PASSIVE; | |||||
err = getaddrinfo("127.0.0.1", "5000", &hints, &result); | |||||
if (err) { | |||||
warn("Could not get Bridge server address"); | |||||
return; | |||||
} | |||||
defer({ | |||||
freeaddrinfo(result); | |||||
}); | |||||
#else | |||||
struct sockaddr_in addr; | struct sockaddr_in addr; | ||||
memset(&addr, 0, sizeof(addr)); | memset(&addr, 0, sizeof(addr)); | ||||
addr.sin_family = AF_INET; | addr.sin_family = AF_INET; | ||||
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr); | |||||
addr.sin_port = htons(5000); | |||||
#ifdef ARCH_WIN | |||||
InetPton(AF_INET, BRIDGE_HOST, &addr.sin_addr); | |||||
#else | |||||
inet_pton(AF_INET, BRIDGE_HOST, &addr.sin_addr); | |||||
#endif | #endif | ||||
addr.sin_port = htons(BRIDGE_PORT); | |||||
// Open socket | // Open socket | ||||
#ifdef ARCH_WIN | #ifdef ARCH_WIN | ||||
@@ -389,6 +387,25 @@ void bridgeDestroy() { | |||||
serverThread.join(); | serverThread.join(); | ||||
} | } | ||||
void bridgeMidiSubscribe(int port, MidiInput *midi) { | |||||
if (!(0 <= port && port < BRIDGE_NUM_PORTS)) | |||||
return; | |||||
// Check if a Midi is already subscribed on the port | |||||
if (midiListeners[port]) | |||||
return; | |||||
midiListeners[port] = midi; | |||||
if (connections[port]) | |||||
connections[port]->refreshAudio(); | |||||
} | |||||
void bridgeMidiUnsubscribe(int port, MidiInput *midi) { | |||||
if (!(0 <= port && port < BRIDGE_NUM_PORTS)) | |||||
return; | |||||
if (midiListeners[port] != midi) | |||||
return; | |||||
midiListeners[port] = NULL; | |||||
} | |||||
void bridgeAudioSubscribe(int port, AudioIO *audio) { | void bridgeAudioSubscribe(int port, AudioIO *audio) { | ||||
if (!(0 <= port && port < BRIDGE_NUM_PORTS)) | if (!(0 <= port && port < BRIDGE_NUM_PORTS)) | ||||
return; | return; | ||||
@@ -2,9 +2,6 @@ | |||||
#include "bridge.hpp" | #include "bridge.hpp" | ||||
#define BRIDGE_DRIVER -5000 | |||||
namespace rack { | namespace rack { | ||||
@@ -133,11 +130,6 @@ static void midiInputCallback(double timeStamp, std::vector<unsigned char> *mess | |||||
if (message->size() >= 3) | if (message->size() >= 3) | ||||
msg.data2 = (*message)[2]; | msg.data2 = (*message)[2]; | ||||
// Filter channel | |||||
if (midiInput->channel >= 0) { | |||||
if (msg.status() != 0xf && msg.channel() != midiInput->channel) | |||||
return; | |||||
} | |||||
midiInput->onMessage(msg); | midiInput->onMessage(msg); | ||||
} | } | ||||
@@ -163,9 +155,18 @@ void MidiInput::setDriver(int driver) { | |||||
rtMidi = rtMidiIn; | rtMidi = rtMidiIn; | ||||
this->driver = rtMidiIn->getCurrentApi(); | this->driver = rtMidiIn->getCurrentApi(); | ||||
} | } | ||||
else if (driver == BRIDGE_DRIVER) { | |||||
} | |||||
} | } | ||||
void MidiInputQueue::onMessage(const MidiMessage &message) { | |||||
void MidiInputQueue::onMessage(MidiMessage message) { | |||||
// Filter channel | |||||
if (channel >= 0) { | |||||
if (message.status() != 0xf && message.channel() != channel) | |||||
return; | |||||
} | |||||
if ((int) queue.size() < queueSize) | if ((int) queue.size() < queueSize) | ||||
queue.push(message); | queue.push(message); | ||||
} | } | ||||