summaryrefslogtreecommitdiffstats
path: root/src/server/JackDriver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/JackDriver.cpp')
-rw-r--r--src/server/JackDriver.cpp245
1 files changed, 106 insertions, 139 deletions
diff --git a/src/server/JackDriver.cpp b/src/server/JackDriver.cpp
index 6d15f3a8..e508c850 100644
--- a/src/server/JackDriver.cpp
+++ b/src/server/JackDriver.cpp
@@ -17,62 +17,58 @@
#include "JackDriver.hpp"
#include "Buffer.hpp"
+#include "BufferFactory.hpp"
+#include "BufferRef.hpp"
#include "DuplexPort.hpp"
#include "Engine.hpp"
+#include "FrameTimer.hpp"
#include "GraphImpl.hpp"
-#include "PortImpl.hpp"
+#include "PortType.hpp"
+#include "RunContext.hpp"
#include "ThreadManager.hpp"
#include "ingen_config.h"
#include "util.hpp"
-#include "ingen/Configuration.hpp"
-#include "ingen/LV2Features.hpp"
-#include "ingen/Log.hpp"
-#include "ingen/URI.hpp"
-#include "ingen/URIMap.hpp"
-#include "ingen/World.hpp"
-#include "ingen/fmt.hpp"
-#include "lv2/atom/util.h"
-
+#include <ingen/Atom.hpp>
+#include <ingen/Configuration.hpp>
+#include <ingen/Log.hpp>
+#include <ingen/Properties.hpp>
+#include <ingen/URI.hpp>
+#include <ingen/URIMap.hpp>
+#include <ingen/URIs.hpp>
+#include <ingen/World.hpp>
+#include <lv2/atom/atom.h>
+#include <lv2/atom/forge.h>
+#include <lv2/atom/util.h>
+#include <raul/Path.hpp>
+#include <raul/Semaphore.hpp>
+
+#include <jack/jack.h>
#include <jack/midiport.h>
-#ifdef INGEN_JACK_SESSION
-#include <jack/session.h>
-#include "ingen/Serialiser.hpp"
-#endif
-#ifdef HAVE_JACK_METADATA
-#include <jack/metadata.h>
+#include <jack/transport.h>
+
+#if USE_JACK_METADATA
#include "jackey.h"
+#include <jack/metadata.h>
#endif
#include <cassert>
#include <chrono>
-#include <cstdlib>
-#include <cstring>
-#include <mutex>
+#include <cstdint>
+#include <map>
#include <string>
#include <utility>
using jack_sample_t = jack_default_audio_sample_t;
-namespace ingen {
-namespace server {
+namespace ingen::server {
JackDriver::JackDriver(Engine& engine)
- : _engine(engine)
- , _sem(0)
- , _flag(false)
- , _client(nullptr)
- , _block_length(0)
- , _seq_size(0)
- , _sample_rate(0)
- , _is_activated(false)
- , _old_bpm(120.0f)
- , _old_frame(0)
- , _old_rolling(false)
+ : _engine(engine)
+ , _forge()
+ , _midi_event_type(_engine.world().uris().midi_MidiEvent)
{
- _midi_event_type = _engine.world().uris().midi_MidiEvent;
- lv2_atom_forge_init(
- &_forge, &engine.world().uri_map().urid_map_feature()->urid_map);
+ lv2_atom_forge_init(&_forge, &engine.world().uri_map().urid_map());
}
JackDriver::~JackDriver()
@@ -88,17 +84,6 @@ JackDriver::attach(const std::string& server_name,
{
assert(!_client);
if (!jack_client) {
-#ifdef INGEN_JACK_SESSION
- const std::string uuid = _engine.world().jack_uuid();
- if (!uuid.empty()) {
- _client = jack_client_open(client_name.c_str(),
- JackSessionID, nullptr,
- uuid.c_str());
- _engine.log().info("Connected to Jack as `%1%' (UUID `%2%')\n",
- client_name.c_str(), uuid);
- }
-#endif
-
// Try supplied server name
if (!_client && !server_name.empty()) {
if ((_client = jack_client_open(client_name.c_str(),
@@ -108,7 +93,7 @@ JackDriver::attach(const std::string& server_name,
}
}
- // Either server name not specified, or supplied server name does not exist
+ // Server name not specified, or that server doesn't exist
// Connect to default server
if (!_client) {
if ((_client = jack_client_open(client_name.c_str(), JackNullOption, nullptr))) {
@@ -122,12 +107,13 @@ JackDriver::attach(const std::string& server_name,
return false;
}
} else {
- _client = (jack_client_t*)jack_client;
+ _client = static_cast<jack_client_t*>(jack_client);
}
_sample_rate = jack_get_sample_rate(_client);
_block_length = jack_get_buffer_size(_client);
- _seq_size = jack_port_type_get_buffer_size(_client, JACK_DEFAULT_MIDI_TYPE);
+ _seq_size = static_cast<uint32_t>(
+ jack_port_type_get_buffer_size(_client, JACK_DEFAULT_MIDI_TYPE));
_fallback_buffer = AudioBufPtr(
static_cast<float*>(
@@ -137,14 +123,13 @@ JackDriver::attach(const std::string& server_name,
jack_set_thread_init_callback(_client, thread_init_cb, this);
jack_set_buffer_size_callback(_client, block_length_cb, this);
-#ifdef INGEN_JACK_SESSION
- jack_set_session_callback(_client, session_cb, this);
-#endif
for (auto& p : _ports) {
register_port(p);
}
+ _timer = std::make_unique<FrameTimer>(_block_length, _sample_rate);
+
return true;
}
@@ -174,10 +159,10 @@ JackDriver::activate()
if (jack_activate(_client)) {
_engine.log().error("Could not activate Jack client, aborting\n");
return false;
- } else {
- _engine.log().info("Activated Jack client `%1%'\n",
- world.conf().option("jack-name").ptr<char>());
}
+
+ _engine.log().info("Activated Jack client `%1%'\n",
+ world.conf().option("jack-name").ptr<char>());
return true;
}
@@ -204,7 +189,7 @@ JackDriver::deactivate()
}
EnginePort*
-JackDriver::get_port(const Raul::Path& path)
+JackDriver::get_port(const raul::Path& path)
{
for (auto& p : _ports) {
if (p.graph_port()->path() == path) {
@@ -216,14 +201,14 @@ JackDriver::get_port(const Raul::Path& path)
}
void
-JackDriver::add_port(RunContext& context, EnginePort* port)
+JackDriver::add_port(RunContext& ctx, EnginePort* port)
{
_ports.push_back(*port);
DuplexPort* graph_port = port->graph_port();
if (graph_port->is_a(PortType::AUDIO) || graph_port->is_a(PortType::CV)) {
- const SampleCount nframes = context.nframes();
- jack_port_t* jport = (jack_port_t*)port->handle();
+ const SampleCount nframes = ctx.nframes();
+ auto* jport = static_cast<jack_port_t*>(port->handle());
void* jbuf = jack_port_get_buffer(jport, nframes);
/* Jack fails to return a buffer if this is too soon after registering
@@ -235,7 +220,7 @@ JackDriver::add_port(RunContext& context, EnginePort* port)
}
void
-JackDriver::remove_port(RunContext& context, EnginePort* port)
+JackDriver::remove_port(RunContext&, EnginePort* port)
{
_ports.erase(_ports.iterator_to(*port));
}
@@ -267,7 +252,7 @@ JackDriver::register_port(EnginePort& port)
void
JackDriver::unregister_port(EnginePort& port)
{
- if (jack_port_unregister(_client, (jack_port_t*)port.handle())) {
+ if (jack_port_unregister(_client, static_cast<jack_port_t*>(port.handle()))) {
_engine.log().error("Failed to unregister Jack port\n");
}
@@ -275,30 +260,33 @@ JackDriver::unregister_port(EnginePort& port)
}
void
-JackDriver::rename_port(const Raul::Path& old_path,
- const Raul::Path& new_path)
+JackDriver::rename_port(const raul::Path& old_path,
+ const raul::Path& new_path)
{
- EnginePort* eport = get_port(old_path);
+ const EnginePort* eport = get_port(old_path);
if (eport) {
-#ifdef HAVE_JACK_PORT_RENAME
- jack_port_rename(
- _client, (jack_port_t*)eport->handle(), new_path.substr(1).c_str());
+#if USE_JACK_PORT_RENAME
+ jack_port_rename(_client,
+ static_cast<jack_port_t*>(eport->handle()),
+ new_path.substr(1).c_str());
#else
- jack_port_set_name((jack_port_t*)eport->handle(),
+ jack_port_set_name(static_cast<jack_port_t*>(eport->handle()),
new_path.substr(1).c_str());
#endif
}
}
void
-JackDriver::port_property(const Raul::Path& path,
+JackDriver::port_property(const raul::Path& path,
const URI& uri,
const Atom& value)
{
-#ifdef HAVE_JACK_METADATA
+#if USE_JACK_METADATA
EnginePort* eport = get_port(path);
if (eport) {
- const jack_port_t* const jport = (const jack_port_t*)eport->handle();
+ const auto* const jport =
+ static_cast<const jack_port_t*>(eport->handle());
+
port_property_internal(jport, uri, value);
}
#endif
@@ -309,7 +297,7 @@ JackDriver::port_property_internal(const jack_port_t* jport,
const URI& uri,
const Atom& value)
{
-#ifdef HAVE_JACK_METADATA
+#if USE_JACK_METADATA
if (uri == _engine.world().uris().lv2_name) {
jack_set_property(_client, jack_port_uuid(jport),
JACK_METADATA_PRETTY_NAME, value.ptr<char>(), "text/plain");
@@ -348,11 +336,11 @@ JackDriver::create_port(DuplexPort* graph_port)
}
void
-JackDriver::pre_process_port(RunContext& context, EnginePort* port)
+JackDriver::pre_process_port(RunContext& ctx, EnginePort* port)
{
- const URIs& uris = context.engine().world().uris();
- const SampleCount nframes = context.nframes();
- jack_port_t* jack_port = (jack_port_t*)port->handle();
+ const URIs& uris = ctx.engine().world().uris();
+ const SampleCount nframes = ctx.nframes();
+ auto* jack_port = static_cast<jack_port_t*>(port->handle());
DuplexPort* graph_port = port->graph_port();
Buffer* graph_buf = graph_port->buffer(0).get();
void* jack_buf = jack_port_get_buffer(jack_port, nframes);
@@ -360,12 +348,12 @@ JackDriver::pre_process_port(RunContext& context, EnginePort* port)
if (graph_port->is_a(PortType::AUDIO) || graph_port->is_a(PortType::CV)) {
graph_port->set_driver_buffer(jack_buf, nframes * sizeof(float));
if (graph_port->is_input()) {
- graph_port->monitor(context);
+ graph_port->monitor(ctx);
} else {
graph_port->buffer(0)->clear(); // TODO: Avoid when possible
}
} else if (graph_port->buffer_type() == uris.atom_Sequence) {
- graph_buf->prepare_write(context);
+ graph_buf->prepare_write(ctx);
if (graph_port->is_input()) {
// Copy events from Jack port buffer into graph port buffer
const jack_nframes_t event_count = jack_midi_get_event_count(jack_buf);
@@ -378,16 +366,16 @@ JackDriver::pre_process_port(RunContext& context, EnginePort* port)
}
}
}
- graph_port->monitor(context);
+ graph_port->monitor(ctx);
}
}
void
-JackDriver::post_process_port(RunContext& context, EnginePort* port)
+JackDriver::post_process_port(RunContext& ctx, EnginePort* port) const
{
- const URIs& uris = context.engine().world().uris();
- const SampleCount nframes = context.nframes();
- jack_port_t* jack_port = (jack_port_t*)port->handle();
+ const URIs& uris = ctx.engine().world().uris();
+ const SampleCount nframes = ctx.nframes();
+ auto* jack_port = static_cast<jack_port_t*>(port->handle());
DuplexPort* graph_port = port->graph_port();
void* jack_buf = port->buffer();
@@ -400,13 +388,15 @@ JackDriver::post_process_port(RunContext& context, EnginePort* port)
if (graph_port->buffer_type() == uris.atom_Sequence) {
// Copy LV2 MIDI events to Jack MIDI buffer
- Buffer* const graph_buf = graph_port->buffer(0).get();
- LV2_Atom_Sequence* seq = graph_buf->get<LV2_Atom_Sequence>();
+ Buffer* const graph_buf = graph_port->buffer(0).get();
+ auto* seq = graph_buf->get<LV2_Atom_Sequence>();
jack_midi_clear_buffer(jack_buf);
- LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
- const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body);
- if (ev->body.type == _midi_event_type) {
+ LV2_ATOM_SEQUENCE_FOREACH (seq, ev) {
+ const auto* buf =
+ static_cast<const uint8_t*>(LV2_ATOM_BODY(&ev->body));
+
+ if (ev->body.type == this->_midi_event_type) {
jack_midi_event_write(
jack_buf, ev->time.frames, buf, ev->body.size);
}
@@ -421,10 +411,9 @@ JackDriver::post_process_port(RunContext& context, EnginePort* port)
}
void
-JackDriver::append_time_events(RunContext& context,
- Buffer& buffer)
+JackDriver::append_time_events(RunContext& ctx, Buffer& buffer)
{
- const URIs& uris = context.engine().world().uris();
+ const URIs& uris = ctx.engine().world().uris();
const jack_position_t* pos = &_position;
const bool rolling = (_transport_state == JackTransportRolling);
@@ -443,7 +432,10 @@ JackDriver::append_time_events(RunContext& context,
// Build an LV2 position object to append to the buffer
LV2_Atom pos_buf[16];
LV2_Atom_Forge_Frame frame;
- lv2_atom_forge_set_buffer(&_forge, (uint8_t*)pos_buf, sizeof(pos_buf));
+ lv2_atom_forge_set_buffer(&_forge,
+ reinterpret_cast<uint8_t*>(pos_buf),
+ sizeof(pos_buf));
+
lv2_atom_forge_object(&_forge, &frame, 0, uris.time_Position);
lv2_atom_forge_key(&_forge, uris.time_frame);
lv2_atom_forge_long(&_forge, pos->frame);
@@ -464,9 +456,17 @@ JackDriver::append_time_events(RunContext& context,
}
// Append position to buffer at offset 0 (start of this cycle)
- LV2_Atom* lpos = (LV2_Atom*)pos_buf;
- buffer.append_event(
- 0, lpos->size, lpos->type, (const uint8_t*)LV2_ATOM_BODY_CONST(lpos));
+ auto* lpos = static_cast<LV2_Atom*>(pos_buf);
+ buffer.append_event(0,
+ lpos->size,
+ lpos->type,
+ static_cast<const uint8_t*>(LV2_ATOM_BODY_CONST(lpos)));
+}
+
+SampleCount
+JackDriver::frame_time() const
+{
+ return _timer->frame_time(_engine.current_time()) + _engine.block_length();
}
/**** Jack Callbacks ****/
@@ -491,6 +491,7 @@ JackDriver::_process_cb(jack_nframes_t nframes)
_transport_state = jack_transport_query(_client, &_position);
+ _timer->update(_engine.current_time(), start_of_current_cycle - _engine.block_length());
_engine.locate(start_of_current_cycle, nframes);
// Read input
@@ -515,7 +516,7 @@ JackDriver::_process_cb(jack_nframes_t nframes)
}
void
-JackDriver::_thread_init_cb()
+JackDriver::thread_init_cb(void*)
{
ThreadManager::set_flag(THREAD_PROCESS);
ThreadManager::set_flag(THREAD_IS_REAL_TIME);
@@ -532,56 +533,22 @@ JackDriver::_shutdown_cb()
int
JackDriver::_block_length_cb(jack_nframes_t nframes)
{
+ const URIs& uris = _engine.world().uris();
+
if (_engine.root_graph()) {
_block_length = nframes;
- _seq_size = jack_port_type_get_buffer_size(_client, JACK_DEFAULT_MIDI_TYPE);
+ _seq_size = static_cast<uint32_t>(
+ jack_port_type_get_buffer_size(_client, JACK_DEFAULT_MIDI_TYPE));
_engine.root_graph()->set_buffer_size(
- _engine.run_context(), *_engine.buffer_factory(), PortType::AUDIO,
+ _engine.run_context(), *_engine.buffer_factory(),
+ uris.atom_Sound,
_engine.buffer_factory()->audio_buffer_size(nframes));
_engine.root_graph()->set_buffer_size(
- _engine.run_context(), *_engine.buffer_factory(), PortType::ATOM,
+ _engine.run_context(), *_engine.buffer_factory(),
+ uris.atom_Sequence,
_seq_size);
}
return 0;
}
-#ifdef INGEN_JACK_SESSION
-void
-JackDriver::_session_cb(jack_session_event_t* event)
-{
- _engine.log().info("Jack session save to %1%\n", event->session_dir);
-
- const std::string cmd = fmt("ingen -eg -n %1% -u %2% -l ${SESSION_DIR}",
- jack_get_client_name(_client),
- event->client_uuid);
-
- SPtr<Serialiser> serialiser = _engine.world().serialiser();
- if (serialiser) {
- std::lock_guard<std::mutex> lock(_engine.world().rdf_mutex());
-
- SPtr<Node> root(_engine.root_graph(), NullDeleter<Node>);
- serialiser->write_bundle(root,
- URI(std::string("file://") + event->session_dir));
- }
-
- event->command_line = (char*)malloc(cmd.size() + 1);
- memcpy(event->command_line, cmd.c_str(), cmd.size() + 1);
- jack_session_reply(_client, event);
-
- switch (event->type) {
- case JackSessionSave:
- break;
- case JackSessionSaveAndQuit:
- _engine.log().warn("Jack session quit\n");
- _engine.quit();
- break;
- case JackSessionSaveTemplate:
- break;
- }
-
- jack_session_event_free(event);
-}
-#endif
-
-} // namespace server
-} // namespace ingen
+} // namespace ingen::server