#include #include "MidiController.hpp" namespace RemoteControl { MidiController::MidiController() : grid{GRID} , previous_grid{BLACK} , current_grid{BLACK} , m_output{} , m_input{{.on_message = [this] (const libremidi::message& message) { if (message.get_message_type() == libremidi::message_type::CONTROL_CHANGE) switch (message.bytes[1]) { case SHIFT: shift = message.bytes[2] > 0; break; case PLAY: if (message.bytes[2] > 0) on_command(Controller::Play, shift); break; case STOP: if (message.bytes[2] > 0) on_command(Controller::Stop, shift); break; case UP: if (message.bytes[2] > 0) on_command(Controller::Up, shift); break; case DOWN: if (message.bytes[2] > 0) on_command(Controller::Down, shift); break; case LEFT: if (message.bytes[2] > 0) on_command(Controller::Left, shift); break; case RIGHT: if (message.bytes[2] > 0) on_command(Controller::Right, shift); break; default: break; } }, .ignore_sensing = false, .ignore_timing = false, .ignore_sysex = false, } } {} MidiController::~MidiController() { m_input.close_port(); m_output.close_port(); } void MidiController::setup(const QString& deviceName) { open_port_by_name(deviceName); if (m_output.is_port_open()) { using namespace libremidi; using e = channel_events; m_output.send_message(message PROGRAMER_MODE); m_output.send_message(e::note_on(1, u_int8_t{SHIFT}, u_int8_t{WHITE})); m_output.send_message(e::note_on(1, u_int8_t{PLAY}, u_int8_t{GREEN})); m_output.send_message(e::note_on(1, u_int8_t{STOP}, u_int8_t{ORANGE})); clear_grid(); } } void MidiController::update_grid() { for (int i{0}; i <= MAX_COLUMN_INDEX; i++) for (int j{0}; j <= MAX_ROW_INDEX; j++) { if (current_grid[i][j] != previous_grid[i][j]) m_output.send_message(libremidi::channel_events::note_on(1, grid[i][j], current_grid[i][j])); previous_grid[i][j] = current_grid[i][j]; current_grid[i][j] = BLACK; } } void MidiController::clear_grid() { for (int i{0}; i <= MAX_COLUMN_INDEX; i++) for (int j{0}; j <= MAX_ROW_INDEX; j++) { current_grid[i][j] = BLACK; m_output.send_message(libremidi::channel_events::note_on(1, grid[i][j], BLACK)); previous_grid[i][j] = BLACK; } } void MidiController::draw_line(const std::array& p1, const std::array& p2) { int p1x = int(p1[0] * MAX_ROW_INDEX); int p2x = int(p2[0] * MAX_ROW_INDEX); int p1y = int(p1[1] * MAX_COLUMN_INDEX); int p2y = int(p2[1] * MAX_COLUMN_INDEX); using namespace std; using namespace libremidi; using e = channel_events; // qDebug() << "p1y: " << p1y; // qDebug() << "p2y: " << p2y; if (p1y == p2y) // draw horizontal lines { if (p1y < 0 || p1y > MAX_COLUMN_INDEX) // vertical position out of range return; else { int start{min(p1x, p2x)}; int end{max(p1x, p2x)}; if (start > MAX_ROW_INDEX || end < 0) // horizonal position out of range return; int last{min(MAX_ROW_INDEX, end)}; // last index in range for (int i{max(0, start)}; i <= last; i++) // itterate from first index in range current_grid[p1y][i] = LIGHT_BLUE; } } else if (p1x == p2x) // draw verticatl lines { if (p1x < 0 || p1x > MAX_ROW_INDEX) // horizontal position out of range return; else { int start{min(p1y, p2y)}; int end{max(p1y, p2y)}; if (start > MAX_COLUMN_INDEX || end < 0) // vertical position out of range return; int last{min(MAX_COLUMN_INDEX, end)}; // last index in range for (int i{max(0, start)}; i <= last; i++) // itterate from first index in range current_grid[p1y][i] = LIGHT_BLUE; } } } void MidiController::open_port_by_name(const QString& deviceName) { libremidi::observer obs; for (const auto& input : obs.get_input_ports()) { if (deviceName == QString::fromStdString(input.port_name).split(":").back()) m_input.open_port(input); } // TODO : error handling here if (!m_input.is_port_connected()) return; for (const auto& output : obs.get_output_ports()) { if (deviceName == QString::fromStdString(output.port_name).split(":").back()) m_output.open_port(output); } // TODO : error handling here if (!m_output.is_port_connected()) return; } }