/* M I D I R E C Little MIDI Recorder Written, arranged, produced by Carl Ch. v. Loesch. V0.1 February'89, V0.2 August'89, V0.3 July'90 V1.0 August'90. #define DEBUG */ #include "Lynx.h" extern struct Menu Menu1; extern struct NewWindow NewWindowStructure1; EXPORT char ret[80]; #include EXPORT struct MidiBase *MidiBase; EXPORT struct MSource *source=0; EXPORT struct MDest *dest=0; EXPORT struct MRoute *droute=0, *sroute=0, *troute; static struct MRouteInfo routeinfo = { MMF_CHAN + MMF_SYSRT, 0xffff }; EXPORT char prgname[] = "Recorder", *name = prgname; EXPORT char midiin[] = "MidiIn", *input = midiin; EXPORT char midiout[] = "MidiOut", *output= midiout; #include EXPORT struct ArpBase *ArpBase; EXPORT struct IntuitionBase *IntuitionBase; EXPORT char file[FCHARS+DSIZE+1]="", dir[DSIZE+1]="Sequences", loadname[FCHARS+1]="Hello", savename[FCHARS+1]="Hello"; EXPORT struct FileRequester *freq; EXPORT struct Window *win; #define TAPELEN 15000 EXPORT struct Tape { union Event event; short clock; } *tape; #define RECORDERPRIO 3L EXPORT char banner[] = "*| Little MIDI Recorder V1.0 by Carlo \"Lynx\" von Loesch (c)90 |*"; EXPORT char *title = banner; EXPORT char nomem[] = "Out of RAM"; EXPORT ULONG tc = 0, tl = 0, ck = 0, nextck, lastck; EXPORT FLAG on = YES, thru = NO, play = NO, rec = NO; EXPORT long midisig, videosig, sigs; main(argc, argv) long argc; char *argv[]; { register long t; register short s; register union Event *e; ifnot (ArpBase = OpenLibrary("arp.library",ArpVersion)) Ciao("No ARP.Library"); IntuitionBase = ArpBase -> IntuiBase; ifnot (MidiBase = ArpOpenLibrary (MIDINAME,MIDIVERSION)) Ciao ("No MIDI.Library"); ifnot (tape = ArpAlloc (TAPELEN * sizeof(struct Tape))) Ciao (nomem); for (t=1; tDestPort->SIGH; win = MyOpenWindow(&NewWindowStructure1); Say (banner); SetMenuStrip (win, &Menu1); sigs = videosig | midisig; ifnot (freq = ArpAllocFreq()) Ciao (nomem); freq->fr_Dir = dir; freq->fr_Window = win; freq -> fr_FuncFlags = FRF_NewWindFunc; #ifdef RECORDERPRIO SetTaskPri(FindTask((char *) 0L), RECORDERPRIO); #endif while (on) { t = Wait (sigs); if (t == midisig) while (e = GetMidiMsg (dest)) { HandleMIDI (e->l); FreeMidiMsg (e); } else MyCheckTui(); } Ciao (NULL); } HandleMIDI (e) union Event e; { if (e.p[0] > 0xf0) select (e.p[0]) { when MS_CLOCK: if (play) PlayIt(); break; when MS_START: Rewind(); when MS_CONTINUE: play=YES; LBUG ("PLAY at clk", ck); break; when MS_STOP: play=NO; LBUG ("STOP at clk", ck); break; otherwise XBUG ("Weird Event", e.l); } else if (rec && play && tl < TAPELEN) { #ifdef TOUCHSTART if (!tl) ck=1; /* start counting from first input, ignoring sync */ #endif tape[tl].clock = ck - lastck; tape[tl++].event = e; lastck = ck; } } PlayIt() { if (!rec && (ck == nextck)) { PutMidiMsg (source, &tape[tc++].event); while (tape[tc].clock == 0) PutMidiMsg (source, &tape[tc++].event); if (tc < tl) nextck = ck + tape[tc].clock; else nextck = 0; } ck++; } Thru() { if (thru = !thru) if (troute = MRoutePublic (input, output, routeinfo)) SPrintf (ret, "Route between %s and %s has been established.", input, output); else { thru = NO; SPrintf (ret, "No route between %s and %s could be established.", input, output); } else { DeleteMRoute (troute); SPrintf (ret, "Ok. No more route between %s and %s.", input, output); } Say (ret); } Record() { rec=!rec; FBUG ("RECORD", rec); Rewind(); } Rewind() { tc=0; ck=1; nextck=(ULONG) tape[0].clock; lastck=1; if (rec) tl=0; LBUG ("REWIND with tl", tl); } SaveIt() { if (tl) Save (file, &tape[0],(long) tl*sizeof(struct Tape)); } LoadIt() { play=NO; Rewind(); tl = Load (file, &tape[0],(long) TAPELEN*sizeof(struct Tape)) / sizeof(struct Tape); } Help() { SPrintf (ret, "Clock: %ld, Counter: %ld, SeqLength: %ld.", ck, tc, tl); Say (ret); } MyCheckTui() { register struct IntuiMessage *tuimsg; register ULONG class, obj; register USHORT code; while (tuimsg = GetMsg (win->UserPort)) { class = tuimsg->Class; code = tuimsg->Code; obj= tuimsg->IAddress; ReplyMsg (tuimsg); switch (class) { case MENUPICK: DoMenu(code); break; case GADGETUP: HandleEvent (obj); break; case CLOSEWINDOW: Ciao (NULL); } } } DoMenu (code) USHORT code; { NBUG (" MenuCode", code); select (MENUNUM(code)) { when 0: select (ITEMNUM(code)) { when 0: LoadAs(); break; when 1: LoadIt(); break; when 2: SaveAs(); break; when 3: SaveIt(); break; when 4: Ciao(NULL); } break; when 1: select (ITEMNUM(code)) { when 0: Help(); break; when 1: Thru(); } } } Say (str) char *str; { if (win) SetWindowTitles (win, -1L, str); } Ciao (str) char *str; { 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) { if (str) Puts(str); CloseLibrary (ArpBase); } exit (str ? 4404L : 0L); }