diff options
Diffstat (limited to 'midinator.c')
-rw-r--r-- | midinator.c | 203 |
1 files changed, 165 insertions, 38 deletions
diff --git a/midinator.c b/midinator.c index 40b9c1d..4d2c6e1 100644 --- a/midinator.c +++ b/midinator.c @@ -1,17 +1,26 @@ /* * midinator.c * - * Poke MIDI devices - * * (c) 2012 Thomas White <taw@bitwiz.org.uk> * + * This file is part of MIDInator. + * + * MIDInator is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MIDInator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MIDInator. If not, see <http://www.gnu.org/licenses/>. + * */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #include <stdarg.h> #include <stdlib.h> #include <stdio.h> @@ -22,6 +31,10 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> +#include <pthread.h> +#include <unistd.h> + +#include "fifo.h" static void show_help(const char *s) @@ -35,7 +48,132 @@ static void show_help(const char *s) } -static void midi_readable(int fd) +struct wargs +{ + FIFO *f; + int fd; +}; + + +static unsigned char get_midi(FIFO *f) +{ + do { + + int err; + char c; + c = fifo_pop(f, &err); + if ( err == 0 ) return c; + + usleep(1); + + } while ( 1 ); +} + + +static void *process_midi(void *pv) +{ + struct wargs *w = pv; + unsigned char c; + int ch, cmd; + FIFO *f; + int fd; + + f = w->f; + fd = w->fd; + + do { + + c = get_midi(f); + + if ( c == 0xfe ) { + unsigned char sbuf[32]; + sbuf[0] = 0xfe; + write(fd, sbuf, 1); + continue; + } + + ch = c & 0x0f; + cmd = c & 0xf0; + + + if ( cmd == 0x90 ) { + + unsigned char sbuf[32]; + int note, vel; + + note = get_midi(f); + vel = get_midi(f); + + sbuf[0] = 0x91; + sbuf[1] = note - 12; + sbuf[2] = vel >> 1; + + write(fd, sbuf, 3); + + } + + /* Control change or mode message */ + if ( cmd == 0xb0 ) { + + int ctrl, data; + + ctrl = get_midi(f); + data = get_midi(f); + + if ( ctrl == 0x40 ) { + unsigned char sbuf[32]; + sbuf[0] = 0xb1; + sbuf[1] = 0x40; + sbuf[2] = data; + write(fd, sbuf, 3); + } + + } + + /* Program change */ + if ( cmd == 0xc0 ) { + + unsigned char sbuf[32]; + int prog; + + prog = get_midi(f); + + sbuf[0] = 0xc1; + sbuf[1] = prog; + + write(fd, sbuf, 2); + + } + + /* Yamaha panel data */ + if ( c == 0xf0 ) { + + unsigned char v; + unsigned char buf[32]; + int i = 0; + + printf("Panel data: "); + buf[i++] = 0xf0; + do { + v = get_midi(f); + buf[i++] = v; + if ( v != 0xf7 ) { + printf("%02hhx ", v); + } + } while ( v != 0xf7 ); + printf("\n"); + + write(fd, buf, i); + + } + + } while ( 1 ); + + return NULL; +} + + +static void midi_readable(int fd, FIFO *f) { int rval, i; unsigned char buf[32]; @@ -47,39 +185,10 @@ static void midi_readable(int fd) return; } - if ( buf[0] == 0xfe ) { - write(fd, buf, 1); - return; - } - for ( i=0; i<rval; i++ ) { - if ( i != 0 ) printf(" : "); - printf("%hhx", buf[i]); - } - printf("\n"); - - if ( (buf[0] & 0xf0) == 0x90 ) { - unsigned char sbuf[32]; - sbuf[0] = 0x91; - sbuf[1] = buf[1] + 12; - sbuf[2] = buf[2] >> 0; - write(fd, sbuf, 3); + fifo_push(f, buf[i]); } - if ( (buf[0] & 0xf0) == 0xc0 ) { - unsigned char sbuf[32]; - sbuf[0] = 0xc1; - sbuf[1] = buf[1]; - write(fd, sbuf, 2); - } - - if ( (buf[0] & 0xf0) == 0xf0 ) { - unsigned char sbuf[32]; - sbuf[0] = buf[0]; - sbuf[1] = buf[1]; - sbuf[2] = buf[2]; - write(fd, sbuf, 3); - } } @@ -88,6 +197,9 @@ int main(int argc, char *argv[]) int c; int fd; int rval; + FIFO *f; + pthread_t thread; + struct wargs wargs; /* Long options */ const struct option longopts[] = { @@ -128,6 +240,19 @@ int main(int argc, char *argv[]) write(fd, sbuf, 3); } + f = fifo_new(); + if ( f == NULL ) { + fprintf(stderr, "Couldn't create FIFO.\n"); + exit(1); + } + + wargs.f = f; + wargs.fd = fd; + if ( pthread_create(&thread, NULL, process_midi, (void *)&wargs) ) { + fprintf(stderr, "Couldn't start processing thread\n"); + exit(1); + } + do { fd_set fds; @@ -149,7 +274,7 @@ int main(int argc, char *argv[]) rval = 1; } else if ( sval != 0 ) { - midi_readable(fd); + midi_readable(fd, f); } /* else timeout */ @@ -157,5 +282,7 @@ int main(int argc, char *argv[]) close(fd); + pthread_join(thread, NULL); + return 0; } |