ref: 164c86c9a8d474a8a9e240d4894ba5081928a364
parent: c4982a97396bc85953177c51eccfa00e3900889a
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Feb 10 17:43:04 EST 2020
plan9: make it play stuff through dmid+opl3 (still need proper timings and notes off)
--- a/plan9.c
+++ b/plan9.c
@@ -2,7 +2,18 @@
#include "field.h"
#include "gbuffer.h"
#include "sim.h"
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <thread.h>
+static struct {
+ u8int u[4];
+ int at;
+}noteoff[16*128]; /* 16 channels, 128 notes each */
+
+static char *buf;
+
Usz orca_round_up_power2(Usz x) {
assert(x <= SIZE_MAX / 2 + 1);
x -= 1;
@@ -42,17 +53,92 @@
static void
usage(void)
{
- print("usage: orca [-t ticks] [-f file]\n");
+ print("usage: orca [-q] [-t ticks] [-f file]\n");
exits("usage");
}
+static void
+process(Oevent_list *el, int tick)
+{
+ int i, off;
+ Oevent *e;
+ u8int u[4];
+
+ for (i = 0; i < el->count; i++) {
+ e = &el->buffer[i];
+ if (e->any.oevent_type == Oevent_type_midi_note) {
+ Oevent_midi_note const *n = &e->midi_note;
+ u[0] = 1;
+ u[1] = 0x90 | n->channel;
+ u[2] = (n->octave + 1)*12 + n->note;
+ u[3] = n->velocity;
+ write(1, u, 4);
+
+ off = n->channel*128 + u[2];
+ noteoff[off].u[1] = 0x80 | n->channel;
+ noteoff[off].u[2] = u[2];
+ noteoff[off].u[3] = 0;//u[3];
+ noteoff[off].at = tick + n->duration;
+ }
+ }
+
+ sleep(150);
+
+ for (i = 0; i < nelem(noteoff); i++) {
+ if (noteoff[i].at > 0 && noteoff[i].at < tick) {
+ write(1, noteoff[i].u, 4);
+ noteoff[i].at = 0;
+ }
+ }
+}
+
+static void
+field_draw(Field *f, int tick)
+{
+ Point p;
+ int x, y;
+
+ lockdisplay(display);
+ draw(screen, screen->r, display->black, nil, ZP);
+ p = screen->r.min;
+ p.x += 8;
+ p.y += 8;
+ for (y = 0; y < f->height; y++) {
+ for (x = 0; x < f->width; x++) {
+ u8int c = f->buffer[f->width*y + x];
+ buf[x] = (c > '\n' && c < 128) ? c : '?';
+ }
+ buf[x] = 0;
+ string(screen, p, display->white, ZP, display->defaultfont, buf);
+ p.y += display->defaultfont->height;
+ }
+
+ p.x = screen->r.min.x + 8;
+ p.y += 2 * display->defaultfont->height;
+ sprint(buf, "%df", tick);
+ string(screen, p, display->white, ZP, display->defaultfont, buf);
+
+ flushimage(display, 1);
+ unlockdisplay(display);
+}
+
void
-main(int argc, char **argv)
+threadmain(int argc, char **argv)
{
const char *input_file = "/fd/0";
int ticks = 1;
bool print_output = true;
Field field;
+ Mousectl *mctl;
+ Keyboardctl *kctl;
+ Rune key;
+ Mouse m;
+ Alt a[] = {
+ { nil, &m, CHANRCV },
+ { nil, nil, CHANRCV },
+ { nil, &key, CHANRCV },
+ { nil, nil, CHANNOBLK},
+ };
ARGBEGIN{
case 't':
@@ -61,6 +147,9 @@
case 'f':
input_file = EARGF(usage());
break;
+ case 'q':
+ print_output = false;
+ break;
}ARGEND;
field_init(&field);
@@ -89,6 +178,8 @@
}
exits(errstr);
}
+ buf = malloc(field.width+1);
+ memset(noteoff, 0, sizeof(noteoff));
Mbuf_reusable mbuf_r;
mbuf_reusable_init(&mbuf_r);
mbuf_reusable_ensure_size(&mbuf_r, field.height, field.width);
@@ -95,17 +186,50 @@
Oevent_list oevent_list;
oevent_list_init(&oevent_list);
Usz max_ticks = (Usz)ticks;
+
+ if(initdraw(nil, nil, "orca") < 0)
+ sysfatal("initdraw: %r");
+ if ((mctl = initmouse(nil, screen)) == nil)
+ sysfatal("initmouse: %r");
+ if ((kctl = initkeyboard(nil)) == nil)
+ sysfatal("initkeyboard: %r");
+
+ a[0].c = mctl->c;
+ a[1].c = mctl->resizec;
+ a[2].c = kctl->c;
+ unlockdisplay(display);
+
+ srand(time(0));
+ threadsetname("orca");
+
for (Usz i = 0; i < max_ticks; ++i) {
mbuffer_clear(mbuf_r.buffer, field.height, field.width);
oevent_list_clear(&oevent_list);
orca_run(field.buffer, mbuf_r.buffer, field.height, field.width, i,
&oevent_list, 0);
+ process(&oevent_list, i);
+ field_draw(&field, i);
+
+ switch (alt(a)) {
+ case 0: /* mouse */
+ break;
+ case 1: /* resize */
+ getwindow(display, Refnone);
+ break;
+ case 2: /* keyboard */
+ switch (key) {
+ case Kdel:
+ goto end;
+ }
+ }
}
+
+end:
mbuf_reusable_deinit(&mbuf_r);
oevent_list_deinit(&oevent_list);
if (print_output)
- field_fput(&field, stdout);
+ field_fput(&field, stderr);
field_deinit(&field);
- exits(nil);
+ threadexitsall(nil);
}