@@ -7,6 +7,7 @@ | |||||
#include <rtmidi.hpp> | #include <rtmidi.hpp> | ||||
#include <keyboard.hpp> | #include <keyboard.hpp> | ||||
#include <gamepad.hpp> | #include <gamepad.hpp> | ||||
#include <midiloopback.hpp> | |||||
#include <settings.hpp> | #include <settings.hpp> | ||||
#include <engine/Engine.hpp> | #include <engine/Engine.hpp> | ||||
#include <app/common.hpp> | #include <app/common.hpp> | ||||
@@ -174,6 +175,7 @@ int main(int argc, char* argv[]) { | |||||
rtmidiInit(); | rtmidiInit(); | ||||
keyboard::init(); | keyboard::init(); | ||||
gamepad::init(); | gamepad::init(); | ||||
midiloopback::init(); | |||||
INFO("Initializing plugins"); | INFO("Initializing plugins"); | ||||
plugin::init(); | plugin::init(); | ||||
INFO("Initializing browser"); | INFO("Initializing browser"); | ||||
@@ -189,6 +191,8 @@ int main(int argc, char* argv[]) { | |||||
// Initialize context | // Initialize context | ||||
contextSet(new Context); | contextSet(new Context); | ||||
INFO("Creating MIDI loopback"); | |||||
APP->midiLoopbackContext = new midiloopback::Context; | |||||
INFO("Creating engine"); | INFO("Creating engine"); | ||||
APP->engine = new engine::Engine; | APP->engine = new engine::Engine; | ||||
INFO("Creating history state"); | INFO("Creating history state"); | ||||
@@ -35,6 +35,11 @@ struct Scene; | |||||
} // namespace app | } // namespace app | ||||
namespace midiloopback { | |||||
struct Context; | |||||
} // namespace midiloopback | |||||
/** Rack instance state | /** Rack instance state | ||||
*/ | */ | ||||
struct Context { | struct Context { | ||||
@@ -44,6 +49,7 @@ struct Context { | |||||
window::Window* window = NULL; | window::Window* window = NULL; | ||||
history::State* history = NULL; | history::State* history = NULL; | ||||
patch::Manager* patch = NULL; | patch::Manager* patch = NULL; | ||||
midiloopback::Context* midiLoopbackContext = NULL; | |||||
~Context(); | ~Context(); | ||||
}; | }; | ||||
@@ -0,0 +1,25 @@ | |||||
#pragma once | |||||
#include <common.hpp> | |||||
#include <midi.hpp> | |||||
namespace rack { | |||||
namespace midiloopback { | |||||
struct Device; | |||||
struct Context { | |||||
Device* devices[1] = {}; | |||||
Context(); | |||||
~Context(); | |||||
}; | |||||
PRIVATE void init(); | |||||
} // namespace midiloopback | |||||
} // namespace rack |
@@ -4,7 +4,7 @@ | |||||
#include <engine/Engine.hpp> | #include <engine/Engine.hpp> | ||||
#include <app/Scene.hpp> | #include <app/Scene.hpp> | ||||
#include <history.hpp> | #include <history.hpp> | ||||
#include <settings.hpp> | |||||
#include <midiloopback.hpp> | |||||
namespace rack { | namespace rack { | ||||
@@ -38,6 +38,10 @@ Context::~Context() { | |||||
INFO("Deleting engine"); | INFO("Deleting engine"); | ||||
delete engine; | delete engine; | ||||
engine = NULL; | engine = NULL; | ||||
INFO("Deleting MIDI loopback"); | |||||
delete midiLoopbackContext; | |||||
midiLoopbackContext = NULL; | |||||
} | } | ||||
@@ -0,0 +1,103 @@ | |||||
#include <context.hpp> | |||||
#include <midiloopback.hpp> | |||||
namespace rack { | |||||
namespace midiloopback { | |||||
static const int DRIVER_ID = -12; | |||||
struct Device : midi::InputDevice, midi::OutputDevice { | |||||
std::string getName() override { | |||||
return "Loopback"; | |||||
} | |||||
void sendMessage(const midi::Message& message) override { | |||||
onMessage(message); | |||||
} | |||||
}; | |||||
struct Driver : midi::Driver { | |||||
std::string getName() override { | |||||
return "Loopback"; | |||||
} | |||||
// Input methods | |||||
std::vector<int> getInputDeviceIds() override { | |||||
return {0}; | |||||
} | |||||
int getDefaultInputDeviceId() override { | |||||
return 0; | |||||
} | |||||
std::string getInputDeviceName(int deviceId) override { | |||||
return getDevice(deviceId)->getName(); | |||||
} | |||||
midi::InputDevice* subscribeInput(int deviceId, midi::Input* input) override { | |||||
midi::InputDevice* inputDevice = getDevice(deviceId); | |||||
if (!inputDevice) | |||||
return NULL; | |||||
inputDevice->subscribe(input); | |||||
return inputDevice; | |||||
} | |||||
void unsubscribeInput(int deviceId, midi::Input* input) override { | |||||
midi::InputDevice* inputDevice = getDevice(deviceId); | |||||
if (!inputDevice) | |||||
return; | |||||
inputDevice->unsubscribe(input); | |||||
} | |||||
// Output methods | |||||
std::vector<int> getOutputDeviceIds() override { | |||||
return {0}; | |||||
} | |||||
int getDefaultOutputDeviceId() override { | |||||
return 0; | |||||
} | |||||
std::string getOutputDeviceName(int deviceId) override { | |||||
return getDevice(deviceId)->getName(); | |||||
} | |||||
midi::OutputDevice* subscribeOutput(int deviceId, midi::Output* output) override { | |||||
midi::OutputDevice* outputDevice = getDevice(deviceId); | |||||
if (!outputDevice) | |||||
return NULL; | |||||
outputDevice->subscribe(output); | |||||
return outputDevice; | |||||
} | |||||
void unsubscribeOutput(int deviceId, midi::Output* output) override { | |||||
midi::OutputDevice* outputDevice = getDevice(deviceId); | |||||
if (!outputDevice) | |||||
return; | |||||
outputDevice->unsubscribe(output); | |||||
} | |||||
// Custom methods | |||||
Device* getDevice(int deviceId) { | |||||
if (!APP->midiLoopbackContext) | |||||
return NULL; | |||||
if (deviceId != 0) | |||||
return NULL; | |||||
return APP->midiLoopbackContext->devices[deviceId]; | |||||
} | |||||
}; | |||||
Context::Context() { | |||||
devices[0] = new Device; | |||||
} | |||||
Context::~Context() { | |||||
delete devices[0]; | |||||
} | |||||
void init() { | |||||
Driver* driver = new Driver; | |||||
midi::addDriver(DRIVER_ID, driver); | |||||
} | |||||
} // namespace midiloopback | |||||
} // namespace rack |