Skip to content

Commit

Permalink
load/save state and fix bug when clearing channels
Browse files Browse the repository at this point in the history
  • Loading branch information
HackerFoo committed Nov 12, 2020
1 parent db66dba commit 30439ec
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ DTASK_TARGETS := midi_tasks
DTASK_GENERATED_HEADERS := $(patsubst %, .gen/%.h, $(DTASK_TARGETS))
INCLUDE += -I $(DTASK_SRC)

LIBS += -lasound
LIBS += -lasound -lz

.PHONY: all
all: midipush
Expand Down
7 changes: 6 additions & 1 deletion default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ with pkgs;
stdenv.mkDerivation rec {
name = "midipush";
src = ./.;
buildInputs = [ python alsaLib fluidsynth ];
buildInputs = [
python
alsaLib
fluidsynth
zlib # for crc32
];
sf = "${soundfont-fluid}/share/soundfonts/FluidR3_GM2-2.sf2";
shellHook = ''
start_sf () {
Expand Down
19 changes: 6 additions & 13 deletions midi_tasks.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,6 @@ typedef union {

DTASK(note_record, struct { uint64_t notes[BEATS][16]; }) {
int channel = *DREF_PASS(channel);
if(*DREF_PASS(disable_channel) & (1ull << channel)) {
return false;
}
if(*DREF(new_button)) {
if(!*DREF_PASS(deleting)) {
memset(DREF(note_record), 0, sizeof(note_record_t));
Expand Down Expand Up @@ -208,38 +205,34 @@ DTASK(record, map_t) {
if(!*DREF(deleting)) {
map_clear(record);
} else {
unsigned char noteon = 0x90 | channel;
FORMAP(i, record) {
pair_t *p = &record[i];
msg_data_t msg = { .data = p->second };
if((msg.byte[0]) == noteon) {
if((msg.byte[0] & 0xf) == channel) {
p->second = 0;
}
}
}
return true;
}
if(*DREF_PASS(disable_channel) & (1ull << channel)) {
return false;
}
if(*DREF(deleting)) {
map_iterator it = map_iterator_begin(record, beat);
pair_t *p = map_find_iter(&it);
unsigned char noteon = 0x90 | channel;
while(p) {
msg_data_t msg = { .data = p->second };
if((msg.byte[0]) == noteon) {
if((msg.byte[0] & 0xf) == channel) {
p->second = 0;
}
p = map_next(&it, p);
}
} else if(*DREF(recording)) {
} else {
if(state->events & DELETING) {
// delete disabled, so collect garbage
int n = map_filter(record, nonzero_value);
printf("%d notes discarded\n", n);
}
if(state->events & PUSH_MIDI_MSG_IN) {
if(*DREF(recording) &&
state->events & PUSH_MIDI_MSG_IN) {
const seg_t *msg_in = DREF(push_midi_msg_in);
unsigned char control = msg_in->s[0] & 0xf0;
if(ONEOF(control, 0x80, 0x90)) {
Expand Down Expand Up @@ -297,7 +290,7 @@ DTASK(set_page, struct { int val, set, keep; }) {
p->val = (c - 102) * 8 | (p->val & 0x07);
p->set |= 0x38;
} else if(top) {
p->val = p->val & 0x38 | (c - 20);
p->val = (p->val & 0x38) | (c - 20);
p->set |= 0x07;
}
} else if (p->set) {
Expand Down
59 changes: 58 additions & 1 deletion midipush.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <sys/time.h>
#include <poll.h>
#include <stdarg.h>
#include <zlib.h> // crc32

#include "dtask.h"
#include "types.h"
Expand All @@ -40,6 +41,8 @@
#include "midi_tasks.h"
#include "midipush.h"

#define STATE_FILE "midipush.state"

const int initial = PRINT_MIDI_MSG | LIGHT_BAR | PLAYBACK | SHOW_PROGRAM | PASSTHROUGH | SHOW_DISABLE_CHANNEL | TRANSPOSE;

static snd_rawmidi_t *rawmidi_in = NULL, *rawmidi_out = NULL, *synth_out = NULL;
Expand Down Expand Up @@ -289,6 +292,54 @@ int get_pfds(snd_rawmidi_t *m, struct pollfd *pfds, int pfds_n) {
return n;
}

static
bool load_state(const char *name, midi_tasks_state_t *state) {
int fd = open(name, O_RDONLY);
if(fd >= 0) {
char *task_specific = (char *)state + sizeof(dtask_state_t);
size_t task_specific_size = sizeof(*state) - sizeof(dtask_state_t);
read(fd, task_specific, task_specific_size);
read(fd, record, static_sizeof(record)); // ***
uLong crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, task_specific, task_specific_size);
crc = crc32(crc, record, static_sizeof(record));
state->record = record;
uLong crc_read;
read(fd, &crc_read, sizeof(crc_read));
close(fd);
if(crc == crc_read) {
printf("state loaded from: %s\n", name);
return true;
} else {
printf("bad crc: %s\n", name);
memset(task_specific, 0, task_specific_size);
memset(record, 0, static_sizeof(record));
}
} else {
printf("failed to load: %s\n", name);
}
return false;
}

static
void save_state(const char *name, midi_tasks_state_t *state) {
int fd = open(name, O_WRONLY | O_CREAT, 0644);
if(fd >= 0) {
char *task_specific = (char *)state + sizeof(dtask_state_t);
size_t task_specific_size = sizeof(*state) - sizeof(dtask_state_t);
uLong crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, task_specific, task_specific_size);
crc = crc32(crc, record, static_sizeof(record));
write(fd, task_specific, task_specific_size);
write(fd, record, static_sizeof(record)); // ***
write(fd, &crc, sizeof(crc));
close(fd);
printf("state saved to: %s\n", name);
} else {
printf("failed to save: %s\n", name);
}
}

STATIC_ALLOC(record, pair_t, 1 << 15);
int main(int argc, char *argv[]) {
static_alloc_init();
Expand Down Expand Up @@ -331,16 +382,22 @@ int main(int argc, char *argv[]) {
n = snd_rawmidi_open(NULL, &synth_out, portname, SND_RAWMIDI_SYNC | SND_RAWMIDI_NONBLOCK);
assert_throw(n >= 0, "Problem opening MIDI port: %s", snd_strerror(n));

if(!load_state(STATE_FILE, &midi_state)) {
midi_state.record = init_map(record, record_size);
}

pfds_in_n = get_pfds(rawmidi_in, pfds_in, LENGTH(pfds_in));
dtask_enable((dtask_state_t *)&midi_state, initial);
dtask_select((dtask_state_t *)&midi_state);
midi_state.record = init_map(record, record_size);
while(read_midi_msgs(rawmidi_in, midi_input_rb, &midi_state)) {
poll(pfds_in, pfds_in_n, 10);
gettimeofday(&midi_state.time_of_day, NULL);
dtask_run((dtask_state_t *)&midi_state, TIME_OF_DAY);
}

dtask_disable((dtask_state_t *)&midi_state, initial);
save_state(STATE_FILE, &midi_state);

snd_rawmidi_close(rawmidi_in);
snd_rawmidi_close(rawmidi_out);
return 0;
Expand Down

0 comments on commit 30439ec

Please sign in to comment.