score-addon-hardware/Hardware/MidiController.cpp

184 lines
4.8 KiB
C++
Raw Normal View History

2024-10-03 23:50:15 +01:00
#include <libremidi/libremidi.hpp>
#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<double, 2>& p1,
const std::array<double, 2>& 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;
}
}