Browse Source

Remove obsolete MidiIO code, serialize power meter state to settings

tags/v0.6.1
Andrew Belt 7 years ago
parent
commit
c42a9c8aab
9 changed files with 18 additions and 481 deletions
  1. +1
    -1
      include/engine.hpp
  2. +0
    -1
      include/util/common.hpp
  3. +0
    -264
      src/Core/MidiIO.cpp
  4. +0
    -206
      src/Core/MidiIO.hpp
  5. +1
    -1
      src/app/ModuleWidget.cpp
  6. +1
    -1
      src/app/RackWidget.cpp
  7. +4
    -4
      src/app/Toolbar.cpp
  8. +2
    -2
      src/engine.cpp
  9. +9
    -1
      src/settings.cpp

+ 1
- 1
include/engine.hpp View File

@@ -135,7 +135,7 @@ Your plugin needs to have a clear purpose for manipulating other modules and wir
*/
extern std::vector<Module*> gModules;
extern std::vector<Wire*> gWires;
extern bool gCpuMeters;
extern bool gPowerMeter;


} // namespace rack

+ 0
- 1
include/util/common.hpp View File

@@ -146,7 +146,6 @@ struct StringCaseInsensitiveCompare {
}
};


////////////////////
// Operating-system specific utilities
// system.cpp


+ 0
- 264
src/Core/MidiIO.cpp View File

@@ -1,264 +0,0 @@
#if 0
#include <list>
#include <algorithm>
#include "core.hpp"
#include "MidiIO.hpp"


using namespace rack;


/**
* MidiIO implements the shared functionality of all midi modules, namely:
* + Channel Selection (including helper for storing json)
* + Interface Selection (including helper for storing json)
* + rtMidi initialisation (input or output)
*/
MidiIO::MidiIO(bool isOut) {
channel = -1;
this->isOut = isOut;

// TODO
// Support MIDI out
assert(!isOut);
};

void MidiIO::setChannel(int channel) {
this->channel = channel;
}

std::unordered_map<std::string, MidiInWrapper *> MidiIO::midiInMap = {};

json_t *MidiIO::addBaseJson(json_t *rootJ) {
if (deviceName != "") {
json_object_set_new(rootJ, "interfaceName", json_string(deviceName.c_str()));
json_object_set_new(rootJ, "channel", json_integer(channel));
}
return rootJ;
}

void MidiIO::baseFromJson(json_t *rootJ) {
json_t *portNameJ = json_object_get(rootJ, "interfaceName");
if (portNameJ) {
openDevice(json_string_value(portNameJ));
}

json_t *channelJ = json_object_get(rootJ, "channel");
if (channelJ) {
setChannel(json_integer_value(channelJ));
}
}

std::vector<std::string> MidiIO::getDevices() {
std::vector<std::string> names = {};

if (isOut) {
// TODO
return names;
}

RtMidiIn *m;
try {
m = new RtMidiIn();
}
catch (RtMidiError &error) {
warn("Failed to create RtMidiIn: %s", error.getMessage().c_str());
return names;
}

for (unsigned int i = 0; i < m->getPortCount(); i++) {
names.push_back(m->getPortName(i));
}

if (!isPortOpen())
delete (m);

return names;
}

void MidiIO::openDevice(std::string deviceName) {

if (this->id > 0 || this->deviceName != "") {
close();
}

MidiInWrapper *mw = midiInMap[deviceName];

if (!mw) {
try {
mw = new MidiInWrapper();
midiInMap[deviceName] = mw;


for (unsigned int i = 0; i < mw->getPortCount(); i++) {
if (deviceName == mw->getPortName(i)) {
mw->openPort(i);
break;
}
}

if (!mw->isPortOpen()) {
warn("Failed to create RtMidiIn: No such device %s", deviceName.c_str());
this->deviceName = "";
this->id = -1;
return;
}
}
catch (RtMidiError &error) {
warn("Failed to create RtMidiIn: %s", error.getMessage().c_str());
this->deviceName = "";
this->id = -1;
return;
}
}

this->deviceName = deviceName;

id = midiInMap[deviceName]->add();
onDeviceChange();
}

void MidiIO::setIgnores(bool ignoreSysex, bool ignoreTime, bool ignoreSense) {
bool sy = true, ti = true, se = true;

midiInMap[deviceName]->ignoresMap[id].midiSysex = ignoreSysex;
midiInMap[deviceName]->ignoresMap[id].midiTime = ignoreTime;
midiInMap[deviceName]->ignoresMap[id].midiSense = ignoreSense;

for (auto kv : midiInMap[deviceName]->ignoresMap) {
sy = sy && kv.second.midiSysex;
ti = ti && kv.second.midiTime;
se = se && kv.second.midiSense;
}

midiInMap[deviceName]->ignoreTypes(se, ti, se);


}

std::string MidiIO::getDeviceName() {
return deviceName;
}

double MidiIO::getMessage(std::vector<unsigned char> *msg) {
MidiMessage next_msg = MidiMessage();

MidiInWrapper *mw = midiInMap[deviceName];

if (!mw) {
warn("Device not opened!: %s", deviceName.c_str());
return 0;
}

next_msg.timeStamp = mw->getMessage(&next_msg.bytes);
if (next_msg.bytes.size() > 0) {
for (auto &kv : mw->idMessagesMap) {

kv.second.push_back(next_msg);
}
}


if (mw->idMessagesMap[id].size() > 0) {
next_msg = mw->idMessagesMap[id].front();
mw->idMessagesMap[id].pop_front();
}

*msg = next_msg.bytes;

return next_msg.timeStamp;
}

bool MidiIO::isPortOpen() {
return id > 0;
}

void MidiIO::close() {

MidiInWrapper *mw = midiInMap[deviceName];

if (!mw || id < 0) {
//warn("Trying to close already closed device!");
return;
}

setIgnores(); // reset ignore types for this instance

mw->erase(id);

if (mw->idMessagesMap.size() == 0) {
mw->closePort();
midiInMap.erase(deviceName);
delete (mw);
}

id = -1;
deviceName = "";
}


void MidiItem::onAction(EventAction &e) {
midiModule->resetMidi(); // reset Midi values
midiModule->openDevice(text);
}

void MidiChoice::onAction(EventAction &e) {
Menu *menu = gScene->createMenu();
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x;

{
MidiItem *midiItem = new MidiItem();
midiItem->midiModule = midiModule;
midiItem->text = "";
menu->addChild(midiItem);
}

std::vector<std::string> deviceNames = midiModule->getDevices();
for (unsigned int i = 0; i < deviceNames.size(); i++) {
MidiItem *midiItem = new MidiItem();
midiItem->midiModule = midiModule;
midiItem->text = deviceNames[i];
menu->addChild(midiItem);
}
}

void MidiChoice::step() {
if (midiModule->getDeviceName() == "") {
text = "No Device";
return;
}
std::string name = midiModule->getDeviceName();
text = ellipsize(name, 15);
}

void ChannelItem::onAction(EventAction &e) {
midiModule->resetMidi(); // reset Midi values
midiModule->setChannel(channel);
}

void ChannelChoice::onAction(EventAction &e) {
Menu *menu = gScene->createMenu();
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x;

{
ChannelItem *channelItem = new ChannelItem();
channelItem->midiModule = midiModule;
channelItem->channel = -1;
channelItem->text = "All";
menu->addChild(channelItem);
}
for (int channel = 0; channel < 16; channel++) {
ChannelItem *channelItem = new ChannelItem();
channelItem->midiModule = midiModule;
channelItem->channel = channel;
channelItem->text = stringf("%d", channel + 1);
menu->addChild(channelItem);
}
}

void ChannelChoice::step() {
text = (midiModule->channel >= 0) ? stringf("%d", midiModule->channel + 1) : "All";
}
#endif

+ 0
- 206
src/Core/MidiIO.hpp View File

@@ -1,206 +0,0 @@
#if 0
#include <unordered_map>
#include "rack.hpp"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-override"
#include "rtmidi/RtMidi.h"
#pragma GCC diagnostic pop


using namespace rack;


struct IgnoreFlags {
bool midiSysex = true;
bool midiTime = true;
bool midiSense = true;
};

struct MidiMessage {
std::vector<unsigned char> bytes;
double timeStamp;

MidiMessage() : bytes(0), timeStamp(0.0) {};
};

/**
* This class allows to use one instance of rtMidiIn with
* multiple modules. A MidiIn port will be opened only once while multiple
* instances can use it simultaniously, each receiving all its incoming messages.
*/
struct MidiInWrapper : RtMidiIn {

std::unordered_map<int, std::list<MidiMessage>> idMessagesMap;
std::unordered_map<int, IgnoreFlags> ignoresMap;

int uid_c = 0;

MidiInWrapper() : RtMidiIn() {
idMessagesMap = {};
};

int add() {
int id = ++uid_c;
idMessagesMap[id] = {};
ignoresMap[id] = IgnoreFlags();
return id;
}

void erase(int id) {
idMessagesMap.erase(id);
ignoresMap.erase(id);
}
};

/**
* Note: MidiIO is not thread safe which might become
* important in the future
*/
struct MidiIO {
private:
static std::unordered_map<std::string, MidiInWrapper *> midiInMap;
/* TODO: add for midi out*/
int id = -1;
std::string deviceName = "";
bool isOut = false;

public:
int channel;


MidiIO(bool isOut = false);

~MidiIO() {
close();
}

std::vector<std::string> getDevices();

void openDevice(std::string deviceName);

void setIgnores(bool ignoreSysex = true, bool ignoreTime = true, bool ignoreSense = true);

std::string getDeviceName();

void setChannel(int channel);

double getMessage(std::vector<unsigned char> *msg);

json_t *addBaseJson(json_t *rootJ);

void baseFromJson(json_t *rootJ);

bool isPortOpen();

void close();

/* called when midi port is set */
virtual void resetMidi() {}

/* called if a user switches or sets the device (and after this device is initialised)*/
virtual void onDeviceChange() {}
};


struct TransitionSmoother {
enum TransitionFunction {
SMOOTHSTEP,
EXP,
LIN,
};

enum TransitionMode {
DELTA,
CONST,
};

float start;
float end;
float x;
float delta;
float step;
TransitionFunction t;


void set(float start, float end, int l = 1500, TransitionFunction t = LIN, TransitionMode m = DELTA, bool reset = true) {
this->start = start;
this->end = end;
this->delta = end - start;
this->t = t;

if (reset || x >= 1) {
this->x = 0;
}

switch (m) {
case DELTA:
/* If the change is smaller, the transition phase is longer */
this->step = delta > 0 ? delta / l : -delta / l;
break;
case CONST:
this->step = 1.0 / l;
break;
}

}

float next() {
float next = start;

x += step;
if (x >= 1)
return end;

switch (t) {
case SMOOTHSTEP:
next += delta * x * x * (3 - 2 * x);
break;
case EXP:
next += delta * x * x;
break;
case LIN:
next += delta * x;
break;
}

if ((delta > 0 && next > end) || (delta <= 0 && next < end))
return end;

return next;;
}
};


//////////////////////
// MIDI module widgets
//////////////////////

struct MidiItem : MenuItem {
MidiIO *midiModule;

void onAction(EventAction &e) override;
};

struct MidiChoice : ChoiceButton {
MidiIO *midiModule;

void step() override;
void onAction(EventAction &e) override;
};

struct ChannelItem : MenuItem {
MidiIO *midiModule;
int channel;

void onAction(EventAction &e) override;
};

struct ChannelChoice : ChoiceButton {
MidiIO *midiModule;

void step() override;
void onAction(EventAction &e) override;
};

#endif

+ 1
- 1
src/app/ModuleWidget.cpp View File

@@ -190,7 +190,7 @@ void ModuleWidget::draw(NVGcontext *vg) {
Widget::draw(vg);

// CPU meter
if (module && gCpuMeters) {
if (module && gPowerMeter) {
nvgBeginPath(vg);
nvgRect(vg,
0, box.size.y - 20,


+ 1
- 1
src/app/RackWidget.cpp View File

@@ -165,7 +165,7 @@ void RackWidget::revert() {
}

void RackWidget::disconnect() {
if (!osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK_CANCEL, "Clear all patch cables?"))
if (!osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK_CANCEL, "Remove all patch cables?"))
return;

for (Widget *w : moduleContainer->children) {


+ 4
- 4
src/app/Toolbar.cpp View File

@@ -89,13 +89,13 @@ struct DisconnectCablesButton : TooltipIconButton {
}
};

struct MeterButton : TooltipIconButton {
MeterButton() {
struct PowerMeterButton : TooltipIconButton {
PowerMeterButton() {
setSVG(SVG::load(assetGlobal("res/icons/noun_305536_cc.svg")));
tooltipText = "Toggle power meter (see manual for explanation)";
}
void onAction(EventAction &e) override {
gCpuMeters ^= true;
gPowerMeter ^= true;
}
};

@@ -175,7 +175,7 @@ Toolbar::Toolbar() {
layout->addChild(wireTensionSlider);

layout->addChild(new SampleRateButton());
layout->addChild(new MeterButton());
layout->addChild(new PowerMeterButton());

struct ZoomSlider : Slider {
void onAction(EventAction &e) override {


+ 2
- 2
src/engine.cpp View File

@@ -17,7 +17,7 @@ namespace rack {
bool gPaused = false;
std::vector<Module*> gModules;
std::vector<Wire*> gWires;
bool gCpuMeters = false;
bool gPowerMeter = false;

static bool running = false;
static float sampleRate = 44100.f;
@@ -90,7 +90,7 @@ static void engineStep() {
// Step modules
for (Module *module : gModules) {
std::chrono::high_resolution_clock::time_point startTime;
if (gCpuMeters) {
if (gPowerMeter) {
startTime = std::chrono::high_resolution_clock::now();

module->step();


+ 9
- 1
src/settings.cpp View File

@@ -67,6 +67,9 @@ static json_t *settingsToJson() {
// moduleBrowser
json_object_set_new(rootJ, "moduleBrowser", appModuleBrowserToJson());

// powerMeter
json_object_set_new(rootJ, "powerMeter", json_boolean(gPowerMeter));

return rootJ;
}

@@ -132,9 +135,14 @@ static void settingsFromJson(json_t *rootJ) {
skipAutosaveOnLaunch = json_boolean_value(skipAutosaveOnLaunchJ);

// moduleBrowser
json_t * moduleBrowserJ = json_object_get(rootJ, "moduleBrowser");
json_t *moduleBrowserJ = json_object_get(rootJ, "moduleBrowser");
if (moduleBrowserJ)
appModuleBrowserFromJson(moduleBrowserJ);

// powerMeter
json_t *powerMeterJ = json_object_get(rootJ, "powerMeter");
if (powerMeterJ)
gPowerMeter = json_boolean_value(powerMeterJ);
}




Loading…
Cancel
Save