# HG changeset patch # User František Kučera # Date 1601418881 -7200 # Node ID baa8055c5b10a7e651f39704c8faeb98e16a2198 # Parent 01553c2ffa1d36ac2e5fea852960ae4c0e7a6a54 ring buffer, JACK callback skeleton, signal handler diff -r 01553c2ffa1d -r baa8055c5b10 src/JackHandler.h --- 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 +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include @@ -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 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 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); +} + } } } diff -r 01553c2ffa1d -r baa8055c5b10 src/relpipe-out-jack.cpp --- 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 = 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 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;