summaryrefslogtreecommitdiff
path: root/midinator.c
diff options
context:
space:
mode:
Diffstat (limited to 'midinator.c')
-rw-r--r--midinator.c203
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;
}