/* * GLIB - a Generic LIBrarian and editor for synths * * Machine dependent stuff. * * Amiga version. */ #include "glib.h" #include #include #include #include #include #include #include #include #include #include #include #include struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Screen *S; struct Window *W; struct RastPort *R; int Rows, Cols; #define TOPEDGE 8 /* how much of screen bar to show */ int WindowWidth = 640; int WindowHeight = 200 - TOPEDGE; /* standard WB colors */ #define BLUE 0 #define WHITE 1 #define BLACK 2 #define ORANGE 3 hello() { windinit(); openmidi(); } bye() { closemidi(); windexit(0); } int MouseX, MouseY, MouseButtons; int Mouseok = 0; /* getmouse - get current row and column of mouse */ getmouse(amr,amc) int *amr; int *amc; { *amr = MouseY / 8; *amc = MouseX / 8; } /* statmouse - return mouse button state (0=nothing pressed,1=left,2=right) */ statmouse() { nextevent(MOUSEBUTTONS, 0); return MouseButtons; } /* Return when either a console key or mouse button is pressed. */ mouseorkey() { return nextevent(MOUSEBUTTONS | VANILLAKEY, 1); } flushconsole() { while (nextevent(VANILLAKEY, 0) >= 0) ; } getconsole() { return nextevent(VANILLAKEY, 1); } cursor(state) int state; { int x, y; x = R->cp_x; y = R->cp_y - R->Font->tf_Baseline; SetDrMd(R, COMPLEMENT); RectFill(R, x, y, x+8, y+R->Font->tf_YSize-1); SetDrMd(R, JAM2); } nextevent(flags, wait) long flags; int wait; { register int class, code; register struct IntuiMessage *message; int result; cursor(1); ModifyIDCMP(W, CLOSEWINDOW | flags); while (1) { if (wait) { /* get next event, waiting if none are available */ while ((message = (struct IntuiMessage *)GetMsg(W->UserPort)) == NULL) { Wait(1<UserPort->mp_SigBit); } } else { /* get next event, but return if none are available */ message = (struct IntuiMessage *)GetMsg(W->UserPort); if (message == NULL) { result = -1; break; } } class = message->Class; code = message->Code; MouseX = message->MouseX; MouseY = message->MouseY; ReplyMsg((struct Message *)message); switch (class) { case VANILLAKEY: result = code; break; case CLOSEWINDOW: result = 'q'; break; case MOUSEBUTTONS: switch (code) { case SELECTDOWN: MouseButtons = 1; break; case MENUDOWN: MouseButtons = 2; break; default: MouseButtons = 0; break; } result = MOUSE; break; default: continue; } break; } cursor(0); return result; } /*------------------------------------------------------------------------ * MIDI I/O Routines for Amiga. * * Uses low-level serial I/O for simultaneous reads and writes. */ struct MsgPort *MidiInPort, *MidiOutPort; struct IOExtSer *MidiIn, *MidiOut; int SerOpen = 0; char MidiInBuf; int MidiDataAvail = 0; /* * start an asynchronous read request from MIDI IN */ startmidiread() { MidiIn->IOSer.io_Data = (APTR) &MidiInBuf; MidiIn->IOSer.io_Length = 1; MidiIn->IOSer.io_Command = CMD_READ; MidiIn->IOSer.io_Flags = IOF_QUICK; /* use quick I/O */ BeginIO((struct IORequest *) MidiIn); /* did I/O complete quickly? */ if ((MidiIn->IOSer.io_Flags & IOF_QUICK)) { /* wow, data's coming in fast! */ MidiDataAvail = 1; } else { /* no data this time, it'll arrive later */ MidiDataAvail = 0; } } /* * get a byte from MIDI IN. * assumes startmidiread has been previously done. if statmidi has been * checked, this function will not wait. otherwise, it will wait for * a single byte to arrive if none is available. */ getmidi() { register struct Message *io; int result; /* return previously-received data, if available */ if (MidiDataAvail) { result = MidiInBuf; /* start a new I/O */ startmidiread(); return result; } /* read next available byte */ io = (struct Message *) CheckIO((struct IORequest *) MidiIn); if (io == FALSE) { /* wait for next byte */ WaitIO((struct IORequest *) MidiIn); io = &MidiIn->IOSer.io_Message; } Remove(&io->mn_Node); result = MidiInBuf; startmidiread(); /* start I/O for next byte */ return result; } /* * write a byte to MIDI OUT */ sendmidi(c) int c; { char buf = c; MidiOut->IOSer.io_Data = (APTR) &buf; MidiOut->IOSer.io_Length = 1; MidiOut->IOSer.io_Command = CMD_WRITE; DoIO((struct IORequest *) MidiOut); /* synchronous request */ } /* * check if any midi data is waiting to be received */ statmidi() { /* check if data has previously been received */ if (MidiDataAvail) return 1; /* check if i/o has completed */ return (CheckIO((struct IORequest *) MidiIn) == FALSE) ? 0 : 1; } openmidi() { /* create message port for serial device */ MidiInPort = (struct MsgPort *) CreatePort(SERIALNAME,0); if (MidiInPort == NULL) fatal("Can't create MidiInPort"); /* create i/o request block for serial device */ MidiIn = (struct IOExtSer *) CreateExtIO(MidiInPort, sizeof(struct IOExtSer)); if (MidiIn == NULL) fatal("Can't create MidiIn"); /* open the serial device */ MidiIn->io_SerFlags = SERF_SHARED; SerOpen = OpenDevice(SERIALNAME,0,(struct IORequest *) MidiIn,0) == 0 ? 1 : 0; if (SerOpen == 0) fatal("Can't open serial.device"); /* set serial device parameters */ MidiIn->io_Baud = 31250; MidiIn->io_RBufLen = 8192; /* large input buffer - if your synth * sends dumps larger than this you * will have to increase it. */ MidiIn->io_SerFlags = SERF_RAD_BOOGIE; MidiIn->IOSer.io_Command = SDCMD_SETPARAMS; DoIO((struct IORequest *) MidiIn); /* clone MidiIn into MidiOut to allow simultaneous i/o */ MidiOutPort = (struct MsgPort *) CreatePort("MidiOut",0); if (MidiOutPort == NULL) fatal("Can't create MidiOutPort"); MidiOut = (struct IOExtSer *) CreateExtIO(MidiOutPort, sizeof(struct IOExtSer)); *MidiOut = *MidiIn; MidiOut->IOSer.io_Message.mn_ReplyPort = MidiOutPort; /* get the MIDI IN port started */ startmidiread(); } closemidi() { if (SerOpen) CloseDevice((struct IORequest *)MidiIn); if (MidiIn) DeleteExtIO((struct IORequest *)MidiIn); if (MidiOut) DeleteExtIO((struct IORequest *)MidiOut); if (MidiInPort) DeletePort(MidiInPort); if (MidiOutPort) DeletePort(MidiOutPort); } flushmidi() { while ( STATMIDI ) getmidi(); } long milliclock() { unsigned int clock[2]; long milli; timer(clock); milli = clock[0] * 1000 + clock[1] / 1000; return milli; } millisleep(n) { Delay(n/20); } char * alloc(n) { char *p; if ( (p=malloc((unsigned)n)) == (char *)NULL ) { fatal("GLIB is out of memory!"); } return(p); } struct TextAttr font = { "topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT }; struct NewScreen ns = { 0,0,640,200,2,BLACK,WHITE,HIRES,CUSTOMSCREEN,&font,"",NULL,NULL }; windinit() { struct NewWindow nw; if (S != NULL) return; IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0); GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0); if (IntuitionBase == NULL || GfxBase == NULL) exit(1); if ((S = (struct Screen *) OpenScreen(&ns)) == NULL) exit(1); nw.LeftEdge = 0; nw.TopEdge = TOPEDGE; nw.Width = WindowWidth; nw.Height = WindowHeight; nw.DetailPen = BLACK; nw.BlockPen = WHITE; nw.Title = NULL; nw.Flags = SMART_REFRESH | ACTIVATE | BACKDROP | BORDERLESS | NOCAREREFRESH | RMBTRAP; nw.IDCMPFlags = CLOSEWINDOW | VANILLAKEY; nw.Type = CUSTOMSCREEN; nw.FirstGadget = NULL; nw.CheckMark = NULL; nw.Screen = S; nw.BitMap = NULL; if ((W = (struct Window *) OpenWindow(&nw)) == NULL) exit(1); R = W->RPort; SetAPen(R, ORANGE); SetBPen(R, BLACK); ShowTitle(S, FALSE); Cols=80; Rows=24; } windgoto(r,c) int r,c; { Move(R, c*8, r*8 + R->Font->tf_Baseline); } windeeol() { int x, y; x = R->cp_x; y = R->cp_y - R->Font->tf_Baseline; SetAPen(R, BLACK); RectFill(R, x, y, WindowWidth, y+R->Font->tf_YSize-1); SetAPen(R, ORANGE); } winderaserow(r) { windgoto(r,0); windeeol(); } windexit(r) int r; { if (W) CloseWindow(W); if (S) CloseScreen(S); exit(r); } windclear() { SetAPen(R, BLACK); RectFill(R, 0, 0, WindowWidth, WindowHeight); SetAPen(R, ORANGE); } /* windgets - get a line of input from the console, handling backspaces */ windgets(s) char *s; { char *origs = s; int c; SetAPen(R, WHITE); while ( (c=getconsole()) != '\n' && c!='\r' && c!= EOF ) { if ( c == '\b' ) { if ( s > origs ) { wbackspace(); s--; } } else if (c == 24) { while (s > origs) { wbackspace(); s--; } } else if (isprint(c)) { windputc(c); *s++ = c; } windrefresh(); } *s = '\0'; SetAPen(R, ORANGE); } windstr(s) char *s; { Text(R, s, strlen(s)); } windputc(c) int c; { char s = c; Text(R, &s, 1); } wbackspace() { int x, y; x = R->cp_x; y = R->cp_y; Move(R, x-8, y); windputc(' '); Move(R, x-8, y); } windrefresh() { } beep() { DisplayBeep(S); } windhigh() { } windnorm() { } struct IntuiText fataltext = { 1,0,COMPLEMENT,16,32,NULL,NULL,NULL }; struct IntuiText canceltext = { 1,0,COMPLEMENT,2,2,NULL,"cancel",NULL }; fatal(text) char *text; { fataltext.IText = text; AutoRequest(W, &fataltext, NULL, &canceltext, 0, 0, 320, 90); bye(); } /**************** * openls(), nextls(), and closels() are used to scan the current directory. ***************/ struct FileInfoBlock *lsinfo = NULL; openls() { } char * nextls() { int error; if (lsinfo == NULL) { lsinfo = (struct FileInfoBlock *) alloc(sizeof(struct FileInfoBlock)); error = dfind(lsinfo, "#?", 0); } else { error = dnext(lsinfo); } if (error == 0) { return lsinfo->fib_FileName; } else { return NULL; } } closels() { free(lsinfo); lsinfo = NULL; }