summaryrefslogtreecommitdiffstats
path: root/matriseq.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2015-11-09 06:58:14 +0000
committerDavid Robillard <d@drobilla.net>2015-11-09 06:58:14 +0000
commit92d4404abbe1373386e7fa7bd42a3acd1e4eeba3 (patch)
tree2e87d6ecccfeaef07f39b57e21421d54dfc5e873 /matriseq.c
parentd75f8b95fca74098d8b939e7236acde7c6b3a9ae (diff)
downloadmatriseq.lv2-92d4404abbe1373386e7fa7bd42a3acd1e4eeba3.tar.gz
matriseq.lv2-92d4404abbe1373386e7fa7bd42a3acd1e4eeba3.tar.bz2
matriseq.lv2-92d4404abbe1373386e7fa7bd42a3acd1e4eeba3.zip
Rewrite Matriseq for the Launchpad Pro
git-svn-id: http://svn.drobilla.net/lad/trunk/plugins/matriseq@5817 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'matriseq.c')
-rw-r--r--matriseq.c483
1 files changed, 287 insertions, 196 deletions
diff --git a/matriseq.c b/matriseq.c
index 4290709..5a111ae 100644
--- a/matriseq.c
+++ b/matriseq.c
@@ -1,6 +1,6 @@
/*
- This file is part of Matriseq.
- Copyright 2007-2012 David Robillard <http://drobilla.net/>
+ Matriseq, a simple step sequencer for the Launchpad Pro.
+ Copyright 2007-2015 David Robillard <http://drobilla.net/>
Matriseq is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
@@ -21,12 +21,9 @@
#include <stdlib.h>
#include <string.h>
-#include "naub/naub.h"
-#include "zix/thread.h"
-#include "zix/ring.h"
-
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
#include "lv2/lv2plug.in/ns/ext/log/log.h"
+#include "lv2/lv2plug.in/ns/ext/log/logger.h"
#include "lv2/lv2plug.in/ns/ext/midi/midi.h"
#include "lv2/lv2plug.in/ns/ext/time/time.h"
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
@@ -37,15 +34,69 @@
#define GRID_H 8
#define GRID_W 8
#define SEQ_H (8 * 8)
+#define SEQ_W 16
#define NOTE_MIN 28
#define STEP_TYPE 16
#define RING_SIZE 4096
+static const uint8_t msg_set_col[] = { 0xF0, 0x00, 0x20, 0x29, 0x02, 0x10, 0xC };
+static const uint8_t msg_set_row[] = { 0xF0, 0x00, 0x20, 0x29, 0x02, 0x10, 0xD };
+static const uint8_t msg_show_text[] = { 0xF0, 0x00, 0x20, 0x29, 0x02, 0x10, 0x14 };
+static const uint8_t msg_light_led[] = { 0xF0, 0x00, 0x20, 0x29, 0x02, 0x10, 0xA };
+
typedef enum {
- MATRISEQ_IN = 0,
- MATRISEQ_OUT = 1
+ BLACK = 0,
+ DARK_GREY = 1,
+ LIGHT_GREY = 2,
+ WHITE = 3,
+ RED = 5,
+ YELLOW = 13,
+ DARK_GREEN = 15,
+ GREEN = 21
+} Color;
+
+typedef enum {
+ MATRISEQ_CONTROL_IN = 0,
+ MATRISEQ_CONTROL_OUT = 1,
+ MATRISEQ_PLAYBACK = 2
} PortIndex;
+typedef enum {
+ BOTTOM_1 = 1,
+ BOTTOM_2 = 2,
+ BOTTOM_3 = 3,
+ BOTTOM_4 = 4,
+ BOTTOM_5 = 5,
+ BOTTOM_6 = 6,
+ BOTTOM_7 = 7,
+ BOTTOM_8 = 8,
+ LEFT_1 = 10,
+ LEFT_2 = 20,
+ LEFT_3 = 30,
+ LEFT_4 = 40,
+ LEFT_5 = 50,
+ LEFT_6 = 60,
+ LEFT_7 = 70,
+ LEFT_8 = 80,
+ RIGHT_1 = 19,
+ RIGHT_2 = 29,
+ RIGHT_3 = 39,
+ RIGHT_4 = 49,
+ RIGHT_5 = 59,
+ RIGHT_6 = 69,
+ RIGHT_7 = 79,
+ RIGHT_8 = 89,
+ TOP_1 = 91,
+ TOP_2 = 92,
+ TOP_3 = 93,
+ TOP_4 = 94,
+ TOP_5 = 95,
+ TOP_6 = 96,
+ TOP_7 = 97,
+ TOP_8 = 98,
+ TOP_9 = 99
+} ButtonID;
+
// URIDs used by this plugin
typedef struct {
LV2_URID atom_Blank;
@@ -60,23 +111,19 @@ typedef struct {
typedef struct {
// Port buffers
- LV2_Atom_Sequence* in;
- LV2_Atom_Sequence* out;
+ LV2_Atom_Sequence* control_in;
+ LV2_Atom_Sequence* control_out;
+ LV2_Atom_Sequence* playback;
// Features
LV2_URID_Map* map;
LV2_Log_Log* log;
- // LV2 stuff
- LV2_Atom_Forge forge;
+ LV2_Log_Logger logger;
+ LV2_Atom_Forge control_forge;
+ LV2_Atom_Forge playback_forge;
MatriseqURIs uris;
- // USB stuff
- NaubWorld* naub;
- ZixRing* ring;
- ZixThread thread;
- bool exit;
-
// State
double rate;
float bpm;
@@ -86,24 +133,12 @@ typedef struct {
uint32_t step;
uint8_t page_x;
uint8_t page_y;
- uint32_t seq[SEQ_H][STEP_TYPE];
+ uint32_t seq[SEQ_H][SEQ_W];
+ uint32_t last_inquiry;
+ bool refresh;
+ bool attached;
} Matriseq;
-// Log a message to the host if available, or stderr otherwise.
-LV2_LOG_FUNC(3, 4)
-static void
-print(Matriseq* self, LV2_URID type, const char* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- if (self->log) {
- self->log->vprintf(self->log->handle, type, fmt, args);
- } else {
- vfprintf(stderr, fmt, args);
- }
- va_end(args);
-}
-
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor,
double rate,
@@ -124,7 +159,7 @@ instantiate(const LV2_Descriptor* descriptor,
}
}
if (!self->map) {
- print(self, self->uris.log_Error, "Missing feature urid:map.\n");
+ lv2_log_error(&self->logger, "Missing feature urid:map\n");
free(self);
return NULL;
}
@@ -139,21 +174,18 @@ instantiate(const LV2_Descriptor* descriptor,
self->uris.time_barBeat = map->map(map->handle, LV2_TIME__barBeat);
self->uris.time_beatsPerMinute = map->map(map->handle, LV2_TIME__beatsPerMinute);
self->uris.time_speed = map->map(map->handle, LV2_TIME__speed);
- lv2_atom_forge_init(&self->forge, self->map);
-
- // Initialise USB stuff
- self->naub = NULL;
- self->ring = zix_ring_new(RING_SIZE);
+ lv2_atom_forge_init(&self->control_forge, self->map);
+ lv2_atom_forge_init(&self->playback_forge, self->map);
+ lv2_log_logger_init(&self->logger, self->map, self->log);
// Initialise state
self->rate = rate;
self->bpm = 140.0f;
- self->speed = 0.0f;
+ //self->speed = 0.0f;
+ self->speed = 1.0f;
self->beats_per_bar = 4;
self->page_y = 1; // Start at note 36 (kick)
- zix_ring_mlock(self->ring);
-
return (LV2_Handle)self;
}
@@ -165,165 +197,198 @@ connect_port(LV2_Handle instance,
Matriseq* self = (Matriseq*)instance;
switch ((PortIndex)port) {
- case MATRISEQ_IN:
- self->in = (LV2_Atom_Sequence*)data;
+ case MATRISEQ_CONTROL_IN:
+ self->control_in = (LV2_Atom_Sequence*)data;
break;
- case MATRISEQ_OUT:
- self->out = (LV2_Atom_Sequence*)data;
+ case MATRISEQ_CONTROL_OUT:
+ self->control_out = (LV2_Atom_Sequence*)data;
+ break;
+ case MATRISEQ_PLAYBACK:
+ self->playback = (LV2_Atom_Sequence*)data;
break;
}
}
static uint32_t*
-get_cell(Matriseq* self, NaubControlID control)
+get_cell(Matriseq* self, uint8_t pad_x, uint8_t pad_y)
{
- const uint32_t x = (self->page_x * GRID_W) + control.x;
- const uint32_t y = (self->page_y * GRID_H) + (7 - control.y);
- return &self->seq[y][x];
+ const uint32_t seq_x = (self->page_x * GRID_W) + pad_x;
+ const uint32_t seq_y = (self->page_y * GRID_H) + pad_y;
+ return &self->seq[seq_y][seq_x];
}
static void
-set_button(Matriseq* self, NaubControlID control, bool active)
+on_button(Matriseq* self, uint8_t num, uint8_t value)
{
- int32_t value = 0;
- if (*get_cell(self, control)) {
- value = active ? naub_rgb(1, 0, 0) : naub_rgb(1, 1, 0);
- } else {
- value = active ? naub_rgb(0, 0.4, 0) : naub_rgb(0, 0, 0);
+ if (!value) {
+ return; // Ignore button release
}
- naub_set_control(self->naub, control, value);
-}
-static void
-set_column(Matriseq* self, uint32_t step, bool active)
-{
- for (int y = 0; y < 8; ++y) {
- const NaubControlID control = { 0, 0, step % GRID_W, y };
- set_button(self, control, active);
+ if (num == TOP_1 && self->page_y < 7) { // Page up
+ ++self->page_y;
+ self->refresh = true;
+ } else if (num == TOP_2 && self->page_y > 0) { // Page down
+ --self->page_y;
+ self->refresh = true;
+ } else if (num == TOP_3 && self->page_x > 0) { // Page left
+ --self->page_x;
+ self->refresh = true;
+ } else if (num == TOP_4 && self->page_x < 1) { // Page right
+ ++self->page_x;
+ self->refresh = true;
+ } else if (num % 10 == 9) { // Right button column
+ self->page_y = num / 10 - 1;
+ self->refresh = true;
+ } else if (num <= BOTTOM_8) { // Bottom button row
+ if ((num - 1) * GRID_W < SEQ_W) {
+ self->page_x = num - 1;
+ self->refresh = true;
+ }
}
}
static void
-set_page_indicators(Matriseq* self)
+write_control(Matriseq* self, uint32_t t, const uint8_t* msg, uint32_t n)
{
- const NaubControlID page_x_but = { 0, 1, self->page_x, 0 };
- const NaubControlID page_y_but = { 0, 2, 0, 7 - self->page_y };
- naub_set_control(self->naub, page_x_but, naub_rgb(0, 1, 0));
- naub_set_control(self->naub, page_y_but, naub_rgb(0, 1, 0));
+ lv2_atom_forge_frame_time(&self->control_forge, t);
+ lv2_atom_forge_atom(&self->control_forge, n, self->uris.midi_MidiEvent);
+ lv2_atom_forge_write(&self->control_forge, msg, n);
}
+/** Pad on the central 8x8 grid pressed. */
static void
-show_page(Matriseq* self)
+on_pad(Matriseq* self, uint32_t t, uint8_t x, uint8_t y, uint8_t vel)
{
- for (uint32_t y = 0; y < 8; ++y) {
- for (uint32_t x = 0; x < 8; ++x) {
- const NaubControlID control = { 0, 0, x, y };
- set_button(self, control, x == self->step);
- }
+ if (vel > 0) {
+ // Flip sequence cell
+ uint32_t* cell = get_cell(self, x, y);
+ *cell = !*cell;
+
+ // Illuminate pad
+ const uint8_t msg[] = { 0xF0, 0x00, 0x20, 0x29, 0x02, 0x10, 0xA,
+ (y + 1) * 10 + x + 1,
+ *cell ? GREEN : BLACK,
+ 0xF7 };
+
+ write_control(self, t, msg, sizeof(msg));
}
}
-static void
-pad_event(void* instance, const NaubEvent* event)
+static uint8_t
+step_button_color(Matriseq* self, uint8_t step, uint8_t col)
{
- Matriseq* self = (Matriseq*)instance;
- if (event->type != NAUB_EVENT_BUTTON) { // Odd...
- return;
- }
-
- const NaubControlID control = event->button.control;
-
- if (control.group == 1 && event->button.pressed) {
- const NaubControlID old_page_x_but = { 0, 1, self->page_x, 0 };
- const NaubControlID old_page_y_but = { 0, 2, 0, 7 - self->page_y };
- if (control.x == 0 && self->page_y < 7) {
- ++self->page_y;
- } else if (control.x == 1 && self->page_y > 0) {
- --self->page_y;
- } else if (control.x == 2 && self->page_x > 0) {
- --self->page_x;
- } else if (control.x == 3 && self->page_x < 1) {
- ++self->page_x;
- } else {
- return;
- }
+ const uint32_t page_begin = self->page_x * 8;
+ const uint32_t page_end = (self->page_x + 1) * 8;
- // Turn off old page indicator buttons
- naub_set_control(self->naub, old_page_x_but, naub_rgb(0, 0, 0));
- naub_set_control(self->naub, old_page_y_but, naub_rgb(0, 0, 0));
-
- // Turn on new page indicator buttons
- set_page_indicators(self);
-
- // Update grid display
- show_page(self);
- } else if (control.group == 0) {
- if (event->button.pressed) {
- naub_set_control(self->naub, control, naub_rgb(1, 0, 0));
- } else {
- uint32_t* cell = get_cell(self, control);
- *cell = *cell ? 0 : 1;
- set_button(self, control, self->step == control.y);
- }
+ if (step >= page_begin && step < page_end && step % 8 == col) {
+ return GREEN;
+ } else if (self->page_x == col) {
+ return DARK_GREY;
}
-
- naub_flush(self->naub);
+ return BLACK;
}
-static void*
-pad_thread(void* instance)
+/** Display scrolling text banner. */
+static void
+pad_show_text(Matriseq* self, uint32_t t, const char* text)
{
- Matriseq* self = (Matriseq*)instance;
- uint32_t step = self->step;
-
- // Initialise pad
- set_page_indicators(self);
- set_column(self, step, true);
- naub_flush(self->naub);
-
- while (!naub_handle_events_timeout(self->naub, 10) && !self->exit) {
- uint32_t new_step;
- if (zix_ring_read_space(self->ring) >= sizeof(new_step)) {
- zix_ring_read(self->ring, &new_step, sizeof(new_step));
+ const size_t len = strlen(text);
+ uint8_t msg[sizeof(msg_show_text) + 3 + len + 1];
+ memcpy(msg, msg_show_text, sizeof(msg_show_text));
+
+ uint8_t* ptr = msg + sizeof(msg_show_text);
+ *ptr++ = DARK_GREY; // Text color
+ *ptr++ = 0; // Loop
+ *ptr++ = 7; // Speed (1-7)
+ memcpy((char*)ptr, text, len);
+ ptr += len;
+ *ptr++ = 0xF7;
+ write_control(self, t, msg, sizeof(msg));
+}
- const uint32_t begin = self->page_x * GRID_W;
- const uint32_t end = (self->page_x + 1) * GRID_W;
+/** Update step indicators when the page has not changed. */
+static void
+pad_update_step(Matriseq* self, uint32_t t, uint32_t old_step, uint32_t new_step)
+{
+ // Turn off old step indicator
+ const uint8_t off_msg[] = { 0xF0, 0x00, 0x20, 0x29, 0x02, 0x10, 0xA,
+ old_step % 8 + 1,
+ step_button_color(self, new_step, old_step % 8),
+ 0xF7 };
+ write_control(self, t, off_msg, sizeof(off_msg));
+
+ // Turn on new step indicator
+ const uint8_t on_msg[] = { 0xF0, 0x00, 0x20, 0x29, 0x02, 0x10, 0xA,
+ new_step % 8 + 1,
+ step_button_color(self, new_step, new_step % 8),
+ 0xF7 };
+ write_control(self, t, on_msg, sizeof(on_msg));
+}
- // De-highlight old active row
- if (step >= begin && step < end) {
- set_column(self, step, false);
- }
+/** Refresh page and step indicators. */
+static void
+pad_refresh_position(Matriseq* self, uint32_t t)
+{
+ // Set bottom horizontal tick/page indicators
+ uint8_t xmsg[sizeof(msg_set_row) + 11];
+ memcpy(xmsg, msg_set_row, sizeof(msg_set_row));
+
+ uint8_t* ptr = xmsg + sizeof(msg_set_row);
+ *ptr++ = 0; // Row number 0 (bottom)
+ *ptr++ = 0; // Non-existent bottom left button color
+ for (int i = 0; i < 8; ++i) {
+ *ptr++ = step_button_color(self, self->step, i);
+ }
+ *ptr++ = 0xF7;
+ write_control(self, t, xmsg, sizeof(xmsg));
+
+ // Set right vertical page indicators
+ uint8_t ymsg[sizeof(msg_set_col) + 11];
+ memcpy(ymsg, msg_set_col, sizeof(msg_set_col));
+
+ ptr = ymsg + sizeof(msg_set_col);
+ *ptr++ = 9; // Column number 9 (right)
+ *ptr++ = 0; // Non-existent bottom right button color
+ for (int i = 0; i < 8; ++i) {
+ *ptr++ = self->page_y == i ? DARK_GREY : BLACK;
+ }
+ *ptr++ = 0xF7;
+ write_control(self, t, ymsg, sizeof(ymsg));
+}
- // Highlight new active row
- if (new_step >= begin && new_step < end) {
- set_column(self, new_step, true);
- }
+static void
+pad_clear(Matriseq* self, uint32_t t)
+{
+ const uint8_t msg[] = { 0xF0, 0x00, 0x20, 0x29, 0x02, 0x10, 0xE, 0, 0xF7 };
+ write_control(self, t, msg, sizeof(msg));
+}
- // Send bulk update to device
- naub_flush(self->naub);
+static void
+pad_refresh_grid(Matriseq* self, uint32_t t)
+{
+ uint8_t msg[136];
+ memcpy(msg, msg_light_led, sizeof(msg_light_led));
+ uint8_t* ptr = msg + sizeof(msg_light_led);
+ for (uint32_t y = 0; y < 8; ++y) {
+ for (uint32_t x = 0; x < 8; ++x) {
+ const uint32_t gx = (self->page_x * GRID_W) + x;
+ const uint32_t gy = (self->page_y * GRID_H) + y;
- step = new_step;
+ *ptr++ = (y + 1) * 10 + x + 1;
+ *ptr++ = self->seq[gy][gx] ? GREEN : BLACK;
}
}
- return NULL;
+
+ *ptr++ = 0xF7;
+ write_control(self, t, msg, sizeof(msg));
}
static void
-activate(LV2_Handle instance)
+send_device_inquiry(Matriseq* self, uint32_t t)
{
- Matriseq* self = (Matriseq*)instance;
- self->naub = naub_world_new(self, pad_event);
- if (self->naub) {
- if (!naub_world_open(
- self->naub, NAUB_VENDOR_NOVATION, NAUB_PRODUCT_LAUNCHPAD)) {
- if (zix_thread_create(&self->thread, 1024, pad_thread, self)) {
- print(self, self->uris.log_Error, "Failed to create thread\n");
- return;
- }
- } else {
- print(self, self->uris.log_Error, "Failed to open controller\n");
- }
- }
+ const uint8_t msg[] = { 0xF0, 0x7E, 0x7F, 0x06, 0x01, 0xF7 };
+ write_control(self, t, msg, sizeof(msg));
+ self->last_inquiry = self->time_frames;
}
static void
@@ -335,16 +400,25 @@ run(LV2_Handle instance, uint32_t n_frames)
const float s_per_beat = 60.0f / self->bpm;
const float s_per_step = s_per_beat * self->beats_per_bar / STEP_TYPE;
- // Prepare for writing to out port
- const uint32_t out_capacity = self->out->atom.size;
- lv2_atom_forge_set_buffer(&self->forge, (uint8_t*)self->out, out_capacity);
-
- // Initialise output port to empty sequence
- LV2_Atom_Forge_Frame out_frame;
- lv2_atom_forge_sequence_head(&self->forge, &out_frame, 0);
+ // Set output buffers for forges
+ lv2_atom_forge_set_buffer(
+ &self->control_forge, (uint8_t*)self->control_out, self->control_out->atom.size);
+ lv2_atom_forge_set_buffer(
+ &self->playback_forge, (uint8_t*)self->playback, self->playback->atom.size);
+
+ // Initialise outputs to empty sequence
+ LV2_Atom_Forge_Frame control_frame;
+ LV2_Atom_Forge_Frame playback_frame;
+ lv2_atom_forge_sequence_head(&self->control_forge, &control_frame, 0);
+ lv2_atom_forge_sequence_head(&self->playback_forge, &playback_frame, 0);
+
+ if (!self->attached && self->time_frames - self->last_inquiry > self->rate) {
+ // Haven't heard from Launchpad, send device inquiry once a second
+ send_device_inquiry(self, 0);
+ }
// Work forwards in time frame by frame, handling events as we go
- const LV2_Atom_Sequence* in = self->in;
+ const LV2_Atom_Sequence* in = self->control_in;
const LV2_Atom_Event* ev = lv2_atom_sequence_begin(&in->body);
for (uint32_t t = 0; t < n_frames; ++t) {
while (!lv2_atom_sequence_is_end(&in->body, in->atom.size, ev) &&
@@ -371,6 +445,27 @@ run(LV2_Handle instance, uint32_t n_frames)
self->speed = ((LV2_Atom_Float*)speed)->body;
}
}
+ } else if (ev->body.type == uris->midi_MidiEvent) {
+ const uint8_t* const msg = (const uint8_t*)(ev + 1);
+ switch (lv2_midi_message_type(msg)) {
+ case LV2_MIDI_MSG_NOTE_ON:
+ on_pad(self, t, msg[1] % 10 - 1, msg[1] / 10 - 1, msg[2]);
+ break;
+ case LV2_MIDI_MSG_CONTROLLER:
+ on_button(self, msg[1], msg[2]);
+ break;
+ case LV2_MIDI_MSG_SYSTEM_EXCLUSIVE:
+ if (msg[1] == 0x7E) {
+ // Launchpad responded to device inquiry, initialise
+ pad_clear(self, t);
+ pad_refresh_position(self, t);
+ pad_refresh_grid(self, t);
+ pad_show_text(self, t, "Matriseq");
+ self->attached = true;
+ }
+ default:
+ break;
+ }
}
ev = lv2_atom_sequence_next(ev);
@@ -380,21 +475,30 @@ run(LV2_Handle instance, uint32_t n_frames)
const uint32_t step = (uint32_t)(time_s / s_per_step) % STEP_TYPE;
if (step != self->step) {
// Update step
+ const uint32_t last_step = self->step;
+ pad_update_step(self, t, self->step, step);
self->step = step;
if (step == 0) {
self->time_frames = 0;
}
- // Notify USB thread of new step
- zix_ring_write(self->ring, &self->step, sizeof(self->step));
+ // Send note offs for enabled notes last step
+ for (uint32_t y = 0; y < SEQ_H; ++y) {
+ if (self->seq[y][last_step]) {
+ const uint8_t off[] = { 0x80, NOTE_MIN + y, 0x40 };
+ lv2_atom_forge_frame_time(&self->playback_forge, t);
+ lv2_atom_forge_atom(&self->playback_forge, 3, self->uris.midi_MidiEvent);
+ lv2_atom_forge_write(&self->playback_forge, off, 3);
+ }
+ }
// Send note ons for enabled notes this step
for (uint32_t y = 0; y < SEQ_H; ++y) {
if (self->seq[y][step]) {
const uint8_t on[] = { 0x90, NOTE_MIN + y, 0x40 };
- lv2_atom_forge_frame_time(&self->forge, t);
- lv2_atom_forge_atom(&self->forge, 3, self->uris.midi_MidiEvent);
- lv2_atom_forge_write(&self->forge, on, 3);
+ lv2_atom_forge_frame_time(&self->playback_forge, t);
+ lv2_atom_forge_atom(&self->playback_forge, 3, self->uris.midi_MidiEvent);
+ lv2_atom_forge_write(&self->playback_forge, on, 3);
}
}
}
@@ -403,25 +507,18 @@ run(LV2_Handle instance, uint32_t n_frames)
++self->time_frames;
}
}
-}
-static void
-deactivate(LV2_Handle instance)
-{
- Matriseq* self = (Matriseq*)instance;
- self->exit = true;
- void* thread_ret = NULL;
- zix_thread_join(self->thread, &thread_ret);
- naub_world_free(self->naub);
- self->naub = NULL;
+ if (self->refresh) {
+ pad_refresh_position(self, n_frames - 1);
+ pad_refresh_grid(self, n_frames - 1);
+ self->refresh = false;
+ }
}
static void
cleanup(LV2_Handle instance)
{
- Matriseq* self = (Matriseq*)instance;
- zix_ring_free(self->ring);
- free(self);
+ free(instance);
}
static const void*
@@ -434,21 +531,15 @@ static const LV2_Descriptor descriptor = {
MATRISEQ_URI,
instantiate,
connect_port,
- activate,
+ NULL,
run,
- deactivate,
+ NULL,
cleanup,
extension_data
};
-LV2_SYMBOL_EXPORT
-const LV2_Descriptor*
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
lv2_descriptor(uint32_t index)
{
- switch (index) {
- case 0:
- return &descriptor;
- default:
- return NULL;
- }
+ return (index == 0) ? &descriptor : NULL;
}