Implemented start synchronization

This commit is contained in:
Mateusz Piątkowski 2023-01-06 17:34:21 +01:00 committed by Robert Bendun
parent 99f89c2e8b
commit 8d86dde405
4 changed files with 115 additions and 1 deletions

View File

@ -1583,6 +1583,18 @@ static Result<Value> builtin_call(Interpreter &i, std::vector<Value> args)
return callable(i, std::move(args)); return callable(i, std::move(args));
} }
static Result<Value> builtin_start(Interpreter &interpreter, std::span<Ast> args)
{
interpreter.starter.start();
auto result = algo::fold(args, Value{}, [&interpreter](auto const&, Ast const& ast)
-> Result<Value>
{
return Try(interpreter.eval((Ast)ast));
});
interpreter.starter.stop();
return result;
}
void Interpreter::register_builtin_functions() void Interpreter::register_builtin_functions()
{ {
auto &global = *Env::global; auto &global = *Env::global;
@ -1627,6 +1639,7 @@ void Interpreter::register_builtin_functions()
global.force_define("shuffle", builtin_shuffle); global.force_define("shuffle", builtin_shuffle);
global.force_define("sim", builtin_sim); global.force_define("sim", builtin_sim);
global.force_define("sort", builtin_sort); global.force_define("sort", builtin_sort);
global.force_define("start", builtin_start);
global.force_define("try", builtin_try); global.force_define("try", builtin_try);
global.force_define("typeof", builtin_typeof); global.force_define("typeof", builtin_typeof);
global.force_define("uniq", builtin_uniq); global.force_define("uniq", builtin_uniq);

View File

@ -1,8 +1,9 @@
#ifndef MUSIQUE_INTERPRETER_HH #ifndef MUSIQUE_INTERPRETER_HH
#define MUSIQUE_INTERPRETER_HH #define MUSIQUE_INTERPRETER_HH
#include <musique/midi/midi.hh>
#include <musique/interpreter/context.hh> #include <musique/interpreter/context.hh>
#include <musique/interpreter/starter.hh>
#include <musique/midi/midi.hh>
#include <musique/value/value.hh> #include <musique/value/value.hh>
#include <unordered_map> #include <unordered_map>
@ -25,6 +26,8 @@ struct Interpreter
std::function<std::optional<Error>(Interpreter&, Value)> default_action; std::function<std::optional<Error>(Interpreter&, Value)> default_action;
Starter starter;
Interpreter(); Interpreter();
~Interpreter(); ~Interpreter();
Interpreter(Interpreter &&) = delete; Interpreter(Interpreter &&) = delete;

View File

@ -0,0 +1,81 @@
#include <musique/interpreter/starter.hh>
#include <ableton/Link.hpp>
#include <musique/errors.hh>
struct Starter::Implementation
{
ableton::Link link = {30};
Implementation()
{
link.enable(true);
link.enableStartStopSync(true);
}
};
Starter::Starter()
: impl{std::make_shared<Starter::Implementation>()}
{
}
struct State
{
ableton::Link *link;
std::mutex mutex;
std::condition_variable condition;
};
void Starter::start()
{
ensure(impl != nullptr, "Starter wasn't initialized properly");
auto &link = impl->link;
auto const quantum = 4;
auto const sessionState = link.captureAppSessionState();
// If we already started continue
if (sessionState.isPlaying()) {
return;
}
auto state = std::make_shared<State>();
state->link = &link;
link.setStartStopCallback([state = state](bool is_playing)
{
if (is_playing) {
state->condition.notify_all();
}
});
std::jthread starter([quantum = quantum, state = state](std::stop_token token)
{
auto counter = 0;
while (!token.stop_requested()) {
auto const time = state->link->clock().micros();
auto sessionState = state->link->captureAppSessionState();
if (counter == 2) {
sessionState.setIsPlaying(true, time);
state->link->commitAppSessionState(sessionState);
return;
}
auto const phase = sessionState.phaseAtTime(time, quantum);
counter += phase == 0;
}
});
std::unique_lock lock(state->mutex);
state->condition.wait(lock);
}
void Starter::stop()
{
ensure(impl != nullptr, "Starter wasn't initialized properly");
auto &link = impl->link;
auto const time = link.clock().micros();
auto sessionState = link.captureAppSessionState();
sessionState.setIsPlaying(false, time);
link.commitAppSessionState(sessionState);
}

View File

@ -0,0 +1,17 @@
#ifndef MUSIQUE_STARTER_HH
#define MUSIQUE_STARTER_HH
#include <memory>
struct Starter
{
Starter();
void start();
void stop();
struct Implementation;
std::shared_ptr<Implementation> impl;
};
#endif // MUSIQUE_STARTER_HH