ref: c0979e3295ef4f20da953f4364db1a084c3c4541
dir: /ft2-clone-midi/
diff f75ed687deda27988f9a566c35efdc074ecf84ed uncommitted --- /dev/null +++ b/midi.c @@ -1,0 +1,167 @@ +#include <stdio.h> +#include <thread.h> +#include "ft2_header.h" +#include "ft2_edit.h" +#include "ft2_config.h" +#include "ft2_gui.h" +#include "ft2_midi.h" +#include "ft2_audio.h" +#include "ft2_mouse.h" +#include "ft2_pattern_ed.h" +#include "ft2_structs.h" +#include "rtmidi/rtmidi_c.h" + +static struct RtMidiWrapper notrt; +static RtMidiCCallback callback; +static int mpid = -1; +static char *epfile, *eptab[MAX_MIDI_DEVICES]; +static int neps; + +static int +scaneps(void) +{ + int fd, i, n, m; + char *s, *p, **t, **e, buf[512], *fl[32]; + Dir *d; + + e = eptab + nelem(eptab); + for(t=eptab; t<e; t++){ + free(*t); + *t = nil; + } + neps = 0; + t = eptab; + /* special case for plugging in any non endpoint file */ + if((s = getenv("midikbd")) != nil){ + *t++ = s; + neps++; + } + if((fd = open("/dev/usb", OREAD)) < 0){ + fprint(2, "scanusbep: %r\n"); + return neps; + } + n = dirreadall(fd, &d); + close(fd); + if(n < 0){ + fprint(2, "scanusbep: %r\n"); + return neps; + } + for(i=0; i<n; i++){ + snprint(buf, sizeof buf, "/dev/usb/%s/ctl", d[i].name); + if(epfile != nil && (s = strrchr(epfile, '/')) != nil){ + if(strncmp(buf, epfile, s - epfile) == 0) + goto gotit; + } + if((fd = open(buf, OREAD)) < 0) + continue; + if((m = pread(fd, buf, sizeof buf, 0)) <= 0) + continue; + close(fd); + buf[m-1] = 0; + if(getfields(buf, fl, nelem(fl), 0, " ") < 26) + continue; + if(strcmp(fl[0], "enabled") != 0 + || strcmp(fl[2], "r") != 0 && strcmp(fl[2], "rw") != 0 + || strcmp(fl[25], "idle") != 0) + continue; + gotit: + if((*t++ = smprint("/dev/usb/%s/data", d[i].name)) == nil) + sysfatal("smprint: %r\n"); + neps++; + if(t >= e) + break; + } + free(d); + return neps; +} + +unsigned int +rtmidi_get_port_count(RtMidiPtr) +{ + notrt.ok = true; + return scaneps(); +} + +char * +rtmidi_get_port_name(RtMidiPtr, unsigned int i) +{ + char *s; + + assert(i < neps); + if((s = strdup(eptab[i])) == nil) + sysfatal("strdup: %r"); + return s; +} + +void +rtmidi_in_cancel_callback(RtMidiInPtr) +{ +} + +void rtmidi_close_port(RtMidiPtr) +{ + threadkill(mpid); + mpid = -1; + callback = nil; + notrt.ok = false; + epfile = nil; +} + +void rtmidi_in_free(RtMidiInPtr) +{ +} + +RtMidiInPtr +rtmidi_in_create_default(void) +{ + notrt.ok = true; + return ¬rt; +} + +void +midiproc(void *ep) +{ + int fd, n, k; + uchar buf[1024]; + + if((fd = open((char*)ep, OREAD)) < 0){ + fprint(2, "midiproc: could not open stream: %r; exiting"); + goto end; + } + while((n = read(fd, buf, sizeof buf)) > 0){ + if(n & 3) + fprint(2, "midiproc: malformed message size %d\n", n); + for(k=0; k<n; k+=4) + if(callback != nil) + callback(.0, buf+k+1, 3, nil); + else + fprint(2, "midiproc: discarding message\n"); + } + fprint(2, "midiproc is off this merry-go-round: %r\n"); +end: + epfile = nil; + notrt.ok = false; + mpid = -1; +} + +void +rtmidi_open_port(RtMidiPtr, unsigned int i, char *) +{ + assert(mpid < 0); + assert(i < neps); + notrt.ok = true; + epfile = eptab[i]; + if((mpid = proccreate(midiproc, epfile, mainstacksize)) < 0) + sysfatal("proccreate: %r"); +} + +void +rtmidi_in_set_callback(RtMidiInPtr, RtMidiCCallback fn, void *) +{ + callback = fn; +} + +void +rtmidi_in_ignore_types(RtMidiInPtr, bool, bool, bool) +{ +} --- a/mkfile.plan9 +++ b/mkfile.plan9 @@ -2,7 +2,7 @@ BIN=/$objtype/bin/audio TARG=ft2 -CFLAGS=$CFLAGS -p -Isrc -I/sys/include/npe -D__plan9__ +CFLAGS=$CFLAGS -p -Isrc -Isrc/rtmidi -I/sys/include/npe -D__plan9__ -DHAS_MIDI HFILES=\ src/ft2_about.h\ @@ -122,6 +122,7 @@ src/smploaders/ft2_load_iff.$O\ src/smploaders/ft2_load_raw.$O\ src/smploaders/ft2_load_wav.$O\ + midi.$O\ default:V: all