184 lines
4.8 KiB
C++
184 lines
4.8 KiB
C++
|
#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;
|
||
|
}
|
||
|
|
||
|
}
|