Infrastructure for incoming MIDI messages ready
This commit is contained in:
parent
bf3f388acb
commit
7a3d211d09
2
Makefile
2
Makefile
@ -6,7 +6,7 @@ DEBUG_FLAGS=-O0 -ggdb -fsanitize=undefined
|
|||||||
CXX=g++
|
CXX=g++
|
||||||
|
|
||||||
LDFLAGS=-L./lib/midi/
|
LDFLAGS=-L./lib/midi/
|
||||||
LDLIBS=-lmidi-alsa -lasound -lreadline
|
LDLIBS=-lmidi-alsa -lasound -lpthread
|
||||||
|
|
||||||
Obj= \
|
Obj= \
|
||||||
context.o \
|
context.o \
|
||||||
|
@ -5,6 +5,46 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
struct Interpreter::Incoming_Midi_Callbacks
|
||||||
|
{
|
||||||
|
Value note_on{};
|
||||||
|
Value note_off{};
|
||||||
|
|
||||||
|
Incoming_Midi_Callbacks() = default;
|
||||||
|
|
||||||
|
Incoming_Midi_Callbacks(Incoming_Midi_Callbacks &&) = delete;
|
||||||
|
Incoming_Midi_Callbacks(Incoming_Midi_Callbacks const&) = delete;
|
||||||
|
|
||||||
|
Incoming_Midi_Callbacks& operator=(Incoming_Midi_Callbacks &&) = delete;
|
||||||
|
Incoming_Midi_Callbacks& operator=(Incoming_Midi_Callbacks const&) = delete;
|
||||||
|
|
||||||
|
void add_callbacks(midi::Connection &midi, Interpreter &interpreter)
|
||||||
|
{
|
||||||
|
register_callback(midi.note_on_callback, note_on, interpreter);
|
||||||
|
register_callback(midi.note_off_callback, note_off, interpreter);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ...T>
|
||||||
|
void register_callback(std::function<void(T...)> &target, Value &callback, Interpreter &i)
|
||||||
|
{
|
||||||
|
target = [interpreter = &i, callback = &callback](T ...source_args)
|
||||||
|
{
|
||||||
|
std::cout << "hello from callback!" << std::endl;
|
||||||
|
if (callback->type != Value::Type::Nil) {
|
||||||
|
auto result = (*callback)(*interpreter, { Value::from(Number(source_args))... });
|
||||||
|
// We discard this since callback is running in another thread.
|
||||||
|
(void) result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Interpreter::register_callbacks()
|
||||||
|
{
|
||||||
|
assert(callbacks != nullptr, "Interpreter constructor should initialize this field");
|
||||||
|
callbacks->add_callbacks(*midi_connection, *this);
|
||||||
|
}
|
||||||
|
|
||||||
/// Intrinsic implementation primitive providing a short way to check if arguments match required type signature
|
/// Intrinsic implementation primitive providing a short way to check if arguments match required type signature
|
||||||
static inline bool typecheck(std::vector<Value> const& args, auto const& ...expected_types)
|
static inline bool typecheck(std::vector<Value> const& args, auto const& ...expected_types)
|
||||||
{
|
{
|
||||||
@ -340,6 +380,9 @@ Interpreter::Interpreter()
|
|||||||
assert(!bool(Env::global), "Only one instance of interpreter can be at one time");
|
assert(!bool(Env::global), "Only one instance of interpreter can be at one time");
|
||||||
env = Env::global = Env::make();
|
env = Env::global = Env::make();
|
||||||
}
|
}
|
||||||
|
{ // MIDI input callbacks initialization
|
||||||
|
callbacks = std::make_unique<Interpreter::Incoming_Midi_Callbacks>();
|
||||||
|
}
|
||||||
{ // Global default functions initialization
|
{ // Global default functions initialization
|
||||||
auto &global = *Env::global;
|
auto &global = *Env::global;
|
||||||
|
|
||||||
|
22
src/main.cc
22
src/main.cc
@ -4,6 +4,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include <musique.hh>
|
#include <musique.hh>
|
||||||
#include <midi.hh>
|
#include <midi.hh>
|
||||||
@ -79,10 +80,12 @@ struct Runner
|
|||||||
|
|
||||||
midi::ALSA alsa;
|
midi::ALSA alsa;
|
||||||
Interpreter interpreter;
|
Interpreter interpreter;
|
||||||
|
std::thread midi_input_event_loop;
|
||||||
|
|
||||||
/// Setup interpreter and midi connection with given port
|
/// Setup interpreter and midi connection with given port
|
||||||
Runner(std::string input_port, std::string output_port)
|
Runner(std::string input_port, std::string output_port)
|
||||||
: alsa("musique")
|
: alsa("musique")
|
||||||
|
, interpreter{}
|
||||||
{
|
{
|
||||||
assert(the == nullptr, "Only one instance of runner is supported");
|
assert(the == nullptr, "Only one instance of runner is supported");
|
||||||
the = this;
|
the = this;
|
||||||
@ -92,8 +95,18 @@ struct Runner
|
|||||||
alsa.init_sequencer();
|
alsa.init_sequencer();
|
||||||
interpreter.midi_connection = &alsa;
|
interpreter.midi_connection = &alsa;
|
||||||
}
|
}
|
||||||
if (output_port.size()) alsa.connect_output(output_port);
|
if (output_port.size()) {
|
||||||
if (input_port.size()) alsa.connect_input(input_port);
|
std::cout << "Connected MIDI output to port " << output_port << ". Ready to play!" << std::endl;
|
||||||
|
alsa.connect_output(output_port);
|
||||||
|
}
|
||||||
|
if (input_port.size()) {
|
||||||
|
std::cout << "Connected MIDI input to port " << input_port << ". Ready for incoming messages!" << std::endl;
|
||||||
|
alsa.connect_input(input_port);
|
||||||
|
}
|
||||||
|
if (alsa_go) {
|
||||||
|
interpreter.register_callbacks();
|
||||||
|
midi_input_event_loop = std::thread([this] { handle_midi_event_loop(); });
|
||||||
|
}
|
||||||
|
|
||||||
Env::global->force_define("say", +[](Interpreter&, std::vector<Value> args) -> Result<Value> {
|
Env::global->force_define("say", +[](Interpreter&, std::vector<Value> args) -> Result<Value> {
|
||||||
for (auto it = args.begin(); it != args.end(); ++it) {
|
for (auto it = args.begin(); it != args.end(); ++it) {
|
||||||
@ -111,6 +124,11 @@ struct Runner
|
|||||||
Runner& operator=(Runner const&) = delete;
|
Runner& operator=(Runner const&) = delete;
|
||||||
Runner& operator=(Runner &&) = delete;
|
Runner& operator=(Runner &&) = delete;
|
||||||
|
|
||||||
|
void handle_midi_event_loop()
|
||||||
|
{
|
||||||
|
alsa.input_event_loop();
|
||||||
|
}
|
||||||
|
|
||||||
/// Run given source
|
/// Run given source
|
||||||
Result<void> run(std::string_view source, std::string_view filename, bool output = false)
|
Result<void> run(std::string_view source, std::string_view filename, bool output = false)
|
||||||
{
|
{
|
||||||
|
@ -920,6 +920,10 @@ struct Interpreter
|
|||||||
/// There is always at least one context
|
/// There is always at least one context
|
||||||
std::vector<Context> context_stack;
|
std::vector<Context> context_stack;
|
||||||
|
|
||||||
|
struct Incoming_Midi_Callbacks;
|
||||||
|
std::unique_ptr<Incoming_Midi_Callbacks> callbacks;
|
||||||
|
void register_callbacks();
|
||||||
|
|
||||||
Interpreter();
|
Interpreter();
|
||||||
~Interpreter();
|
~Interpreter();
|
||||||
Interpreter(Interpreter const&) = delete;
|
Interpreter(Interpreter const&) = delete;
|
||||||
|
Loading…
Reference in New Issue
Block a user