commit 473d45aa082af4cd8922bb69631efa52bd9ab296
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Wed, 30 Dec 2020 11:56:52 +0000
Initial commit
Diffstat:
A | .gitignore | | | 2 | ++ |
A | main.cpp | | | 183 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | makefile | | | 4 | ++++ |
3 files changed, 189 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,2 @@
+*.[od]
+main
diff --git a/main.cpp b/main.cpp
@@ -0,0 +1,183 @@
+#include <jack/jack.h>
+#include <jack/midiport.h>
+#include <jack/ringbuffer.h>
+
+#include <memory>
+#include <cassert>
+
+#include <thread>
+#include <chrono>
+#include <iostream>
+#include <iomanip>
+
+using namespace std::literals::chrono_literals;
+
+namespace jack {
+
+struct client
+{
+ client() = default;
+ client(char const* name, jack_options_t options)
+ : handle(create(name, options), deleter)
+ {}
+
+ void activate(void)
+ {
+ assert(not jack_activate(**this));
+ }
+
+ void set_process_callback(JackProcessCallback cb, void* arg)
+ {
+ jack_set_process_callback(**this, cb, arg);
+ }
+
+private:
+ static jack_client_t* create(char const* name, jack_options_t options)
+ {
+ jack_status_t status;
+ jack_client_t *ptr = jack_client_open(name, options, &status);;
+ if (ptr)
+ return ptr;
+
+ std::exit(1);
+ }
+
+ static void deleter(jack_client_t* const p)
+ {
+ assert(not jack_deactivate(p));
+ }
+
+ std::unique_ptr<jack_client_t, void (*)(jack_client_t*)> handle = {nullptr, deleter};
+
+ jack_client_t* operator *(void)
+ {
+ return handle.get();
+ }
+
+ friend struct port;
+};
+
+struct port
+{
+ port() = default;
+
+ port(client& _c, char const* name, char const* type, unsigned long flags, unsigned long buffer_size)
+ : c(*_c)
+ , p(jack_port_register(c, name, type, flags, buffer_size))
+ {
+ assert(p);
+ }
+ ~port()
+ {
+ if (p)
+ jack_port_unregister(c, p);
+ }
+ port(port const&) = delete;
+ port& operator =(port const&) = delete;
+
+ port(port&& old)
+ : c(old.c)
+ , p(old.p)
+ {
+ old.p = nullptr;
+ }
+ port& operator =(port&& old)
+ {
+ if (this != &old)
+ {
+ if (p)
+ jack_port_unregister(c, p);
+
+ c = old.c;
+ p = old.p;
+
+ old.p = nullptr;
+ }
+ return *this;
+ }
+
+ jack_port_t* operator *(void)
+ {
+ return p;
+ }
+
+private:
+ jack_client_t* c = nullptr;
+ jack_port_t* p = nullptr;
+};
+
+struct ringbuffer
+{
+ ringbuffer() = default;
+ ringbuffer(size_t size)
+ : handle(jack_ringbuffer_create(size), jack_ringbuffer_free)
+ {}
+
+ size_t write(void const* src, size_t size)
+ {
+ return jack_ringbuffer_write(**this, static_cast<char const*>(src), size);
+ }
+
+ size_t read(void* dst, size_t size)
+ {
+ return jack_ringbuffer_read(**this, static_cast<char*>(dst), size);
+ }
+
+private:
+ std::unique_ptr<jack_ringbuffer_t, void (*)(jack_ringbuffer_t*)> handle = {nullptr, jack_ringbuffer_free};
+
+ jack_ringbuffer_t* operator *(void)
+ {
+ return handle.get();
+ }
+};
+
+}
+
+jack::client client("h-synth", JackNoStartServer);
+jack::port p1(client, "port1", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
+
+jack::ringbuffer midi_data(1024);
+
+std::atomic_int midi_events;
+
+int cb_process(jack_nframes_t nframes, void* arg)
+{
+ void* buf = jack_port_get_buffer(*p1, nframes);
+
+ jack_midi_event_t event;
+ for (uint32_t i = 0; not jack_midi_event_get(&event, buf, i); ++i)
+ {
+ midi_data.write(event.buffer, event.size);
+ ++midi_events;
+ }
+// midi_events.notify_all();
+ return 0;
+}
+
+int main()
+{
+ client.set_process_callback(cb_process, nullptr);
+ client.activate();
+
+ int last = 0, current;
+
+ for (;;)
+ {
+ current = midi_events;
+ if (current == last)
+ continue;
+
+ last = current;
+
+// midi_events.wait();
+ std::cout << "processed " << midi_events << " MIDI events:\n" << std::hex;
+
+ for (unsigned char buf; midi_data.read(&buf, sizeof(buf)); /**/)
+ std::cout << std::setw(3) << +buf;
+
+ std::cout << std::dec << '\n';
+ }
+
+ return 0;
+}
diff --git a/makefile b/makefile
@@ -0,0 +1,4 @@
+CXXFLAGS := -std=c++20
+LDLIBS := -ljack
+
+main: