spicetools/overlay/windows/midi.cpp

130 lines
4.0 KiB
C++

#include "midi.h"
#include "launcher/launcher.h"
#include "util/logging.h"
namespace overlay::windows {
static std::string midi_cmd_str(uint8_t cmd) {
const char *name = "UNKNOWN";
switch (cmd) {
case 0x8:
name = "NOTE OFF";
break;
case 0x9:
name = "NOTE ON";
break;
case 0xA:
name = "POLY.PRESS.";
break;
case 0xB:
name = "CTRL CHANGE";
break;
case 0xC:
name = "PRG CHANGE";
break;
case 0xD:
name = "CHAN.PRESS.";
break;
case 0xE:
name = "PITCH BEND";
break;
case 0xF:
name = "SYSTEM";
break;
}
return fmt::format("{} (0x{:2X})", name, cmd);
}
MIDIWindow::MIDIWindow(SpiceOverlay *overlay) : Window(overlay) {
this->title = "MIDI Control";
this->init_size = ImVec2(
ImGui::GetIO().DisplaySize.x * 0.8f,
ImGui::GetIO().DisplaySize.y * 0.8f);
this->size_min = ImVec2(250, 200);
this->init_pos = ImVec2(
ImGui::GetIO().DisplaySize.x / 2 - this->init_size.x / 2,
ImGui::GetIO().DisplaySize.y / 2 - this->init_size.y / 2);
this->active = true;
// add hook for receiving midi messages
RI_MGR->add_callback_midi(this, MIDIWindow::midi_hook);
}
MIDIWindow::~MIDIWindow() {
RI_MGR->remove_callback_midi(this, MIDIWindow::midi_hook);
}
void MIDIWindow::build_content() {
// reset button
if (ImGui::Button("Reset")) {
this->midi_data.clear();
}
// autoscroll checkbox
ImGui::SameLine();
ImGui::Checkbox("Autoscroll", &this->autoscroll);
// log section
ImGui::BeginChild("MidiLog", ImVec2(), false);
// header
ImGui::Columns(5, "MidiLogColumns", true);
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Device"); ImGui::NextColumn();
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Command"); ImGui::NextColumn();
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Channel"); ImGui::NextColumn();
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Data 1"); ImGui::NextColumn();
ImGui::TextColored(ImVec4(1.f, 0.7f, 0, 1), "Data 2"); ImGui::NextColumn();
// data
ImGui::Separator();
for (auto &data : this->midi_data) {
// set color
srand(data.device->id * 2111);
float hue = ((float) rand()) / ((float) RAND_MAX);
ImGui::PushStyleColor(ImGuiCol_Text, ImColor::HSV(hue, 0.8f, 0.8f, 1.f).Value);
// data cells
ImGui::Text("%i: %s", (int) data.device->id, data.device->desc.c_str());
ImGui::NextColumn();
ImGui::Text("%s", midi_cmd_str(data.cmd).c_str());
ImGui::NextColumn();
ImGui::Text("0x%02X - %i", data.ch, data.ch);
ImGui::NextColumn();
ImGui::Text("0x%02X", data.b1);
ImGui::NextColumn();
ImGui::Text("0x%02X", data.b2);
ImGui::NextColumn();
// clean up
ImGui::PopStyleColor();
}
// autoscroll
if (this->autoscroll_apply) {
this->autoscroll_apply = false;
ImGui::SetScrollHereY(1.f);
}
// clean up section
ImGui::Columns();
ImGui::EndChild();
}
void MIDIWindow::midi_hook(void *user, rawinput::Device *device,
uint8_t cmd, uint8_t ch, uint8_t b1, uint8_t b2) {
auto This = (MIDIWindow*) user;
This->midi_data.emplace_back(MIDIData {
.device = device,
.cmd = cmd,
.ch = ch,
.b1 = b1,
.b2 = b2,
});
if (This->autoscroll) {
This->autoscroll_apply = true;
}
}
}