/* Virtual MIDI Keyboard Written, arranged, produced by Carl Ch. v. Loesch. (c) 1989, 1990. */ #include "Lynx.h" #include struct ArpBase *ArpBase; struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Window *win; struct RastPort *rp; #include struct MidiBase *MidiBase; struct MSource *source=0; struct MDest *dest=0; struct MRoute *droute=0, *sroute=0, *troute; struct MRouteInfo routeinfo = { MMF_NOTEOFF | MMF_NOTEON, 0xffff }; static UBYTE keytable[128] = { 0,61,63,0,66,68,70,0,73,75,0,78,80,82,0,0, /* 0..15 */ 62,64,65,67,69,71,72,74,76,77,79,81,0,0,0,0, /* 16..31 */ 42,44,46,0,49,51,0,54,56,58,0,0,0,0,0,0, /* 32..47 */ 41,43,45,47,48,50,52,53,55,57,59,0,0,0,0,0, /* 48..63 */ 0,0,60,0,83,0,0,0,0,0,0,0,0,0,0,0, /* 64..79 (tab,cr) */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80..95 */ 0,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 96..111 (rsh) */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 112..127 */ }; #define JOKES 6 static char jokes[JOKES][70] = { " INCORRECT PASSWORD. TRY AGAIN. ", " The password to go eat at the mensa is 'MAHLZEIT' ", " How many cans can a can can if a can can can cans? ", " The Lynx says: The best is yet to come... to come... to come... ", " The Lord of Sequence. The ultimate Amiga MIDI sequencer program. ", "Greet'ns to SNEAK, NOAK, KIR, MADGUIT, KBR, YETI, ANT, WIZ, CRACKAKAN.", }; struct NewWindow nw = { 0, 11, 640, 40, 1, 2, CLOSEWINDOW+RAWKEY, WINDOWCLOSE+WINDOWDEPTH+WINDOWDRAG+SMART_REFRESH, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN }; char keyboard[] = "Keyboard", *name = keyboard; char midiin[] = "MidiIn", *input = midiin; char midiout[] = "MidiOut", *output= midiout; char nomem[] = "Gimme RAM!"; char banner[] = "*| Virtual MIDI Keyboard V1.0 by Carlo \"Lynx\" von Loesch (c)89 |*"; char header[] = "*| Virtual MIDI Keyboard ", *title = header; FLAG logon = TRUE, thru = FALSE; EXPORT long videosig, sigs; main(argc, argv) long argc; char *argv[]; { register struct IntuiMessage *tuimsg; register union Event *e; register long t; register short s; ifnot (ArpBase = OpenLibrary("arp.library",ArpVersion)) Ciao("No ARP.Library"); IntuitionBase = ArpBase -> IntuiBase; GfxBase = ArpBase -> GfxBase; ifnot (MidiBase = ArpOpenLibrary (MIDINAME,MIDIVERSION)) Ciao ("No MIDI.Library"); for (t=1; tRPort; for (t=0; t<10; t++) DrawOctave (rp, t); ifnot (source = CreateMSource (name, NULL)) Ciao (nomem); ifnot (dest = CreateMDest (name, NULL)) Ciao (nomem); sroute = MRouteSource (source, output, NULL); droute = MRouteDest (input, dest, &routeinfo); sigs = videosig | (1L << dest->DestPort->SIGH); while (logon) { if (videosig != Wait (sigs)) while (e = GetMidiMsg (dest)) { Show (e->l); FreeMidiMsg (e); } else while (tuimsg = GetMsg (win->UserPort)) { t=tuimsg->Class; s=tuimsg->Code; ReplyMsg (tuimsg); select (t) { when RAWKEY: HitaKey(s); break; when CLOSEWINDOW: logon = FALSE; } } } Ciao ("Please close the window, it's cold outside. *grin* :-)"); } HitaKey (raw) short raw; { static union Event e; static char chan; static FLAG amiga = FALSE; #ifdef CTRL static FLAG ctrl = FALSE; #endif register UBYTE z; z = (UBYTE) (raw & 0x7f); if (z == 103) { if (raw & 0x80) amiga=FALSE; else amiga=TRUE; return; } #ifdef CTRL if (z == 99) { if (raw & 0x80) ctrl=FALSE; else ctrl=TRUE; return; } if (ctrl) select (raw) { when 51:/* C */ logon = FALSE; } else #endif if (amiga) select (raw) { when 0: /* ` */ Thru(); } else if (e.p[1] = keytable[z]) { e.p[0] = MS_NOTEON + chan; if (raw & 0x80) e.p[2] = 0; else e.p[2] = 64; /* I think 64 is the standard velocity value for non-dynamic keyboards */ PutMidiMsg (source, &e); Show (e); } else select (raw) { when 89:/*F10*/ Thru(); break; when 43:/* # */ Jokerman(); break; when 81:/*F2*/ chan+=2; if (chan>16) chan=1; when 80:/*F1*/ if (--chan<0) chan=15; title[0] = chan+49; Say (title); } } Thru() { register UBYTE *ret; if (thru = !thru) if (troute = MRoutePublic (input, output, routeinfo)) ret = "Route has been established."; else { thru = NO; ret = "No route could be established."; } else { DeleteMRoute (troute); ret = "Route deleted."; } Say (ret); } #define COLORS 4 #define DEPTH 2 #define TOP 11 #define BOT 37 #define MID 26 #define LEFMARG 5 Show (e) union Event e; { register long z, o; static char offs[12] = { 1, 6, 11, 16, 22, 27, 32, 37, 42, 47, 52, 58 }; static char white[12] = { 1, 0, 10, 0, 19, 28, 0, 37, 0, 46, 0, 55 }; z = e.p[2]; /* velocity */ if (!z || e.p[0] == MS_NOTEOFF) SetAPen (rp, 0L); else SetAPen (rp, z / (128/(COLORS-1)) + 1 ); if (z == 7) Jokerman(); z = e.p[1] % 12; o = 63 * (e.p[1]-z)/12 + LEFMARG; if (white[z]) RectFill (rp, o+white[z], MID+1, o+white[z]+7, BOT-1); z = o + offs[z] + 1; RectFill (rp, z, TOP+1, z+3, MID-1); } DrawOctave (raz, x) int raz, x; { x = 63*x + LEFMARG; Move (raz, x, TOP); /* box around it */ Draw (raz, x+63, TOP); Draw (raz, x+63, BOT); Draw (raz, x, BOT); Draw (raz, x, TOP); x+=9; Move (raz, x, BOT); DrawKey (raz, x, 3); x+=9; Move (raz, x, BOT); DrawKey (raz, x, 2); x+=9; Move (raz, x, BOT); Draw (raz, x, TOP); x+=9; Move (raz, x, BOT); DrawKey (raz, x, 4); x+=9; Move (raz, x, BOT); DrawKey (raz, x, 3); x+=9; Move (raz, x, BOT); DrawKey (raz, x, 2); } DrawKey (raz, x, i) int raz, x, i; { Draw (raz, x, MID); Draw (raz, x-i, MID); Draw (raz, x-i, TOP); Move (raz, x, MID); Draw (raz, x-i+5, MID); Draw (raz, x-i+5, TOP); } Jokerman() { static UBYTE joker = 0; SetWindowTitles (win, jokes[joker++], banner); if (joker==JOKES) joker = 0; } Say (str) char *str; { if (win) SetWindowTitles (win, -1L, str); } Ciao (str) char *str; { if (str) { Say (str); Delay (25L); } if (win) CloseWindowSafely (win); if (droute) DeleteMRoute (droute); if (sroute) DeleteMRoute (sroute); if (thru) DeleteMRoute (troute); if (dest) DeleteMDest (dest); if (source) DeleteMSource (source); if (ArpBase) CloseLibrary (ArpBase); exit (NULL); }