--- a/src/JackHandler.h Tue Sep 29 20:49:04 2020 +0200
+++ b/src/JackHandler.h Wed Sep 30 00:34:41 2020 +0200
@@ -17,6 +17,7 @@
#pragma once
#include <memory>
+#include <atomic>
#include <string>
#include <vector>
#include <iostream>
@@ -24,6 +25,7 @@
#include <locale>
#include <codecvt>
#include <sys/mman.h>
+#include <signal.h>
#include <jack/jack.h>
#include <jack/midiport.h>
@@ -41,6 +43,8 @@
namespace out {
namespace jack {
+int dequeueMessages(jack_nframes_t frames, void* arg);
+
class JackHandler : public relpipe::reader::handlers::RelationalReaderStringHandler {
private:
Configuration& configuration;
@@ -48,7 +52,18 @@
jack_client_t* jackClient = nullptr;
jack_port_t* jackPort = nullptr;
- //jack_ringbuffer_t* ringBuffer = nullptr;
+ jack_ringbuffer_t* ringBuffer = nullptr;
+
+ std::atomic<bool> continueProcessing{true};
+
+ const int RING_BUFFER_SIZE = 100;
+
+ struct MidiMessage {
+ uint8_t buffer[4096];
+ uint32_t size;
+ uint32_t time;
+ };
+
public:
JackHandler(Configuration& configuration) : configuration(configuration) {
@@ -57,9 +72,9 @@
jackClient = jack_client_open(clientName.c_str(), JackNullOption, nullptr);
if (jackClient == nullptr) throw JackException(L"Could not create JACK client.");
- //ringBuffer = jack_ringbuffer_create(RING_BUFFER_SIZE * sizeof (MidiMessage));
+ ringBuffer = jack_ringbuffer_create(RING_BUFFER_SIZE * sizeof (MidiMessage));
- //jack_set_process_callback(jackClient, relpipe::in::jack::enqueueMessage, this);
+ jack_set_process_callback(jackClient, relpipe::out::jack::dequeueMessages, this);
// TODO: report also other events (connections etc.)
jackPort = jack_port_register(jackClient, "output", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
@@ -72,26 +87,48 @@
}
void startRelation(const relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
-
+ // TODO: validate metadata and prepare attribute mappings (names and types are important, order does not matter)
+
}
void attribute(const relpipe::common::type::StringX& value) override {
-
+ // TODO: append to current message + if this is last attribute, put whole message to the ring buffer
+ // TODO: if (continueProcessing) {} ?
}
void endOfPipe() {
-
+ // TODO: send optional (configurable) MIDI events
+ // TODO: wait until the ring buffer is empty
+ }
+
+ int dequeueMessages(jack_nframes_t frames) {
+
+
+ // TODO: send events from the ring buffer to JACK + correct timing
+ std::cout << "dequeueMessages(" << frames << ")" << std::endl;
+
+
+ return 0;
+ }
+
+ void finish(int sig) {
+ continueProcessing = false;
}
virtual ~JackHandler() {
// Close JACK connection:
jack_deactivate(jackClient);
jack_client_close(jackClient);
- //jack_ringbuffer_free(ringBuffer);
+ jack_ringbuffer_free(ringBuffer);
}
};
+int dequeueMessages(jack_nframes_t frames, void* arg) {
+ JackHandler* instance = (JackHandler*) arg;
+ return instance->dequeueMessages(frames);
+}
+
}
}
}
--- a/src/relpipe-out-jack.cpp Tue Sep 29 20:49:04 2020 +0200
+++ b/src/relpipe-out-jack.cpp Wed Sep 30 00:34:41 2020 +0200
@@ -35,18 +35,26 @@
using namespace relpipe::reader;
using namespace relpipe::out::jack;
+static std::shared_ptr<JackHandler> jackHandler = nullptr;
+
+void finish(int sig) {
+ if (jackHandler) jackHandler->finish(sig);
+}
+
int main(int argc, char**argv) {
CLI cli(argc, argv);
CLI::untieStdIO();
-
+
int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR;
try {
+ signal(SIGHUP, finish);
+ signal(SIGINT, finish);
CLIParser cliParser;
Configuration configuration = cliParser.parse(cli.arguments());
std::shared_ptr<RelationalReader> reader(Factory::create(std::cin));
- JackHandler handler(configuration);
- reader->addHandler(&handler);
+ jackHandler.reset(new JackHandler(configuration));
+ reader->addHandler(jackHandler.get());
reader->process();
resultCode = CLI::EXIT_CODE_SUCCESS;