[bugui] refactor and add bugui submodule
This commit is contained in:
parent
b1c9378732
commit
e0ad7c817b
7 changed files with 31 additions and 312 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "Hardware/3rdparty/bugui"]
|
||||
path = Hardware/3rdparty/bugui
|
||||
url = https://codeberg.org/bugui/bugui.git
|
|
@ -9,18 +9,17 @@ if(NOT TARGET libremidi)
|
|||
return()
|
||||
endif()
|
||||
|
||||
|
||||
score_common_setup()
|
||||
|
||||
set(HDRS
|
||||
"Hardware/Controller.hpp"
|
||||
"Hardware/MidiController.hpp"
|
||||
add_subdirectory(Hardware/3rdparty/bugui)
|
||||
|
||||
set(HDRS
|
||||
"Hardware/Settings/Model.hpp"
|
||||
"Hardware/Settings/Presenter.hpp"
|
||||
"Hardware/Settings/View.hpp"
|
||||
"Hardware/Settings/Factory.hpp"
|
||||
|
||||
"Hardware/Controller.hpp"
|
||||
"Hardware/DocumentPlugin.hpp"
|
||||
"Hardware/ApplicationPlugin.hpp"
|
||||
|
||||
|
@ -28,24 +27,22 @@ set(HDRS
|
|||
)
|
||||
|
||||
set(SRCS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Hardware/Controller.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Hardware/MidiController.cpp"
|
||||
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Hardware/Settings/Model.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Hardware/Settings/Presenter.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Hardware/Settings/View.cpp"
|
||||
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Hardware/Controller.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Hardware/DocumentPlugin.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Hardware/ApplicationPlugin.cpp"
|
||||
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/score_addon_hardware.cpp"
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} ${SRCS} ${HDRS} ${QRCS})
|
||||
add_library(${PROJECT_NAME} ${SRCS} ${HDRS})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
score_plugin_scenario
|
||||
libremidi
|
||||
bugui
|
||||
)
|
||||
|
||||
setup_score_plugin(${PROJECT_NAME})
|
||||
|
|
1
Hardware/3rdparty/bugui
vendored
Submodule
1
Hardware/3rdparty/bugui
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit f97533d59cd0db29221dda683d845120617ae8a3
|
|
@ -1,37 +1,30 @@
|
|||
#include <wobjectimpl.h>
|
||||
|
||||
#include <score/application/ApplicationContext.hpp>
|
||||
#include <score/actions/ActionManager.hpp>
|
||||
#include <Scenario/Application/ScenarioActions.hpp>
|
||||
|
||||
#include "MidiController.hpp"
|
||||
|
||||
#include "Controller.hpp"
|
||||
|
||||
namespace Hardware
|
||||
{
|
||||
Controller::Controller(const score::DocumentContext& doc)
|
||||
: h_ofset{0.} // initial horizontal ofset
|
||||
, v_ofset{0.} // initial verticalal ofset
|
||||
, h_zoom{.125} // initial horizontal zoom
|
||||
, v_zoom{1.1} // initial verticalal zoom
|
||||
{
|
||||
commandCallback = [&doc, this](Controller::Commands com, const bool& shift) {
|
||||
: bugui::controller{[&doc, this]
|
||||
(commands com, const bool& shift)
|
||||
{
|
||||
switch (com)
|
||||
{
|
||||
case Controller::Play:
|
||||
case Play:
|
||||
if (shift)
|
||||
doc.app.actions.action<Actions::PlayGlobal>().action()->trigger();
|
||||
else
|
||||
doc.app.actions.action<Actions::Play>().action()->trigger();
|
||||
break;
|
||||
case Controller::Stop:
|
||||
case Stop:
|
||||
if (shift)
|
||||
doc.app.actions.action<Actions::Reinitialize>().action()->trigger();
|
||||
else
|
||||
doc.app.actions.action<Actions::Stop>().action()->trigger();
|
||||
break;
|
||||
case Controller::Up:
|
||||
case Up:
|
||||
if (shift)
|
||||
{
|
||||
v_zoom += .2;
|
||||
|
@ -43,7 +36,7 @@ Controller::Controller(const score::DocumentContext& doc)
|
|||
draw_intervals();
|
||||
}
|
||||
break;
|
||||
case Controller::Down:
|
||||
case Down:
|
||||
if (shift)
|
||||
{
|
||||
if (v_zoom > .2)
|
||||
|
@ -58,7 +51,7 @@ Controller::Controller(const score::DocumentContext& doc)
|
|||
draw_intervals();
|
||||
}
|
||||
break;
|
||||
case Controller::Left:
|
||||
case Left:
|
||||
if (shift)
|
||||
{
|
||||
if (h_zoom > .02)
|
||||
|
@ -76,7 +69,7 @@ Controller::Controller(const score::DocumentContext& doc)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case Controller::Right:
|
||||
case Right:
|
||||
if (shift)
|
||||
{
|
||||
h_zoom += .02;
|
||||
|
@ -96,15 +89,9 @@ Controller::Controller(const score::DocumentContext& doc)
|
|||
// qDebug() << "v_zoom: " << v_zoom;
|
||||
// qDebug() << "h_ofset: " << h_ofset;
|
||||
// qDebug() << "h_zoom: " << h_ofset;
|
||||
};
|
||||
}
|
||||
|
||||
void Controller::setup()
|
||||
{
|
||||
ctl = new MidiController{};
|
||||
ctl->on_command = commandCallback;
|
||||
ctl->setup();
|
||||
}
|
||||
}
|
||||
{}
|
||||
|
||||
void Controller::setup_scenario(Scenario::ProcessModel* s)
|
||||
{
|
||||
|
@ -135,11 +122,13 @@ void Controller::draw_intervals()
|
|||
auto def = c.duration.defaultDuration().sec() * h_zoom;
|
||||
auto st = (c.date().sec() * h_zoom) - h_ofset;
|
||||
auto y = (c.heightPercentage() * v_zoom) + v_ofset;
|
||||
ctl->draw_line({st, y}, {st + def, y});
|
||||
draw_line({st, y}, {st + def, y});
|
||||
}
|
||||
|
||||
ctl->update_grid();
|
||||
}
|
||||
update_grid();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include <wobjectimpl.h>
|
||||
W_OBJECT_IMPL(Hardware::Controller)
|
||||
|
|
|
@ -5,44 +5,27 @@
|
|||
#include <Scenario/Document/Interval/IntervalModel.hpp>
|
||||
#include <Scenario/Process/ScenarioModel.hpp>
|
||||
|
||||
#include <controller.hpp>
|
||||
|
||||
namespace Hardware
|
||||
{
|
||||
class MidiController;
|
||||
|
||||
class SCORE_ADDON_HARDWARE_EXPORT Controller
|
||||
: public QObject
|
||||
: public bugui::controller
|
||||
, public QObject
|
||||
{
|
||||
W_OBJECT(Controller)
|
||||
|
||||
public:
|
||||
explicit Controller(const score::DocumentContext& doc);
|
||||
|
||||
enum Commands
|
||||
{
|
||||
Play = 0,
|
||||
Stop,
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down
|
||||
};
|
||||
|
||||
void setup();
|
||||
void setup_scenario(Scenario::ProcessModel* s);
|
||||
void draw_intervals();
|
||||
|
||||
private:
|
||||
double h_ofset;
|
||||
double v_ofset;
|
||||
double h_zoom;
|
||||
double v_zoom;
|
||||
|
||||
MidiController* ctl;
|
||||
Scenario::ProcessModel* scenar;
|
||||
|
||||
std::function<void(Controller::Commands, const bool&)> commandCallback;
|
||||
|
||||
void on_interval_changed(const Scenario::IntervalModel &);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
#include <libremidi/libremidi.hpp>
|
||||
|
||||
#include "MidiController.hpp"
|
||||
|
||||
namespace Hardware
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
#ifndef MIDICONTROLLER_HPP
|
||||
#define MIDICONTROLLER_HPP
|
||||
|
||||
#include <Scenario/Application/ScenarioActions.hpp>
|
||||
#include <score/actions/ActionManager.hpp>
|
||||
|
||||
#include <libremidi/libremidi.hpp>
|
||||
|
||||
#include "Controller.hpp"
|
||||
|
||||
// Macros to temporarly act as the device description file
|
||||
#define PROGRAMER_MODE {240, 0, 32, 41, 2, 16, 44, 3, 247}
|
||||
|
||||
#define SHIFT 80
|
||||
#define PLAY 19
|
||||
#define STOP 8
|
||||
#define UP 91
|
||||
#define DOWN 92
|
||||
#define LEFT 93
|
||||
#define RIGHT 94
|
||||
|
||||
#define BLACK 0
|
||||
#define WHITE 2
|
||||
#define LIGHT_BLUE 36
|
||||
#define GREEN 64
|
||||
#define ORANGE 9
|
||||
|
||||
// Grid
|
||||
#define GRID \
|
||||
{81, 82, 83, 84, 85, 86, 87, 88}, \
|
||||
{71, 72, 73, 74, 75, 76, 77, 78}, \
|
||||
{61, 62, 63, 64, 65, 66, 67, 68}, \
|
||||
{51, 52, 53, 54, 55, 56, 57, 58}, \
|
||||
{41, 42, 43, 44, 45, 46, 47, 48}, \
|
||||
{31, 32, 33, 34, 35, 36, 37, 38}, \
|
||||
{21, 22, 23, 24, 25, 26, 27, 28}, \
|
||||
{11, 12, 13, 14, 15, 16, 17, 18}
|
||||
|
||||
#define MAX_ROW_INDEX 7
|
||||
#define MAX_COLUMN_INDEX 7
|
||||
|
||||
namespace Hardware
|
||||
{
|
||||
class MidiController
|
||||
{
|
||||
public:
|
||||
MidiController();
|
||||
~MidiController();
|
||||
|
||||
std::function<void(Controller::Commands, const bool&)> on_command;
|
||||
|
||||
void setup(const QString& deviceName = "Launchpad Pro Standalone Port");
|
||||
void update_grid();
|
||||
void clear_grid();
|
||||
void draw_line(const std::array<double, 2>& p1, const std::array<double, 2>& p2);
|
||||
|
||||
private:
|
||||
void open_port_by_name(const QString& deviceName);
|
||||
|
||||
u_int8_t grid[MAX_ROW_INDEX + 1][MAX_COLUMN_INDEX + 1];
|
||||
u_int8_t previous_grid[MAX_ROW_INDEX + 1][MAX_COLUMN_INDEX + 1];
|
||||
u_int8_t current_grid[MAX_ROW_INDEX + 1][MAX_COLUMN_INDEX + 1];
|
||||
bool shift{false};
|
||||
|
||||
libremidi::midi_out m_output;
|
||||
libremidi::midi_in m_input;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MIDICONTROLLER_HPP
|
Loading…
Add table
Reference in a new issue