home *** CD-ROM | disk | FTP | other *** search
/ Da Capo / da_capo_vol1.bin / programs / amiga / midi / midi_playground / sourcecode / serial.c < prev    next >
C/C++ Source or Header  |  1993-01-23  |  7KB  |  292 lines

  1. /**************************************************************************
  2. * serial.c:    Serial port access functions.
  3. *        Part of MP, the MIDI Playground.
  4. *
  5. * Author:    Daniel Barrett
  6. * Version:    See the file "version.h".
  7. * Copyright:    None!  This program is in the Public Domain.
  8. *        Please share it with others.
  9. ***************************************************************************/
  10.  
  11.     
  12. #include "mp.h"
  13. #include "midi.h"
  14.  
  15. static struct MsgPort    *MidiPort    = NULL;
  16. static struct IOExtSer    *Midi        = NULL;
  17. long serialFlags            = 0L;
  18.  
  19. #define    F_MIDIPORT    1
  20. #define    F_MIDI        2
  21. #define    F_DEVICE    4
  22. #define    F_SERPARAMS    8
  23.  
  24.  
  25. BOOL AllDigits(char *str);
  26. char *GetEnv(char *str);
  27. BOOL MakeSerialDeviceName(char *str, char *device, int *unit);
  28.  
  29.     
  30. /****************************************************************************
  31.  * SerialSetup:  Open the serial port and its message port.
  32.  * Allow for an alternate MIDI device in an environment variable.
  33.  ***************************************************************************/
  34.  
  35. BOOL SerialSetup(FLAGS sysex)
  36. {
  37.     char deviceName[BUFSIZ], *envVar;
  38.     int unit;
  39.  
  40.     /* Set the defaults. */
  41.  
  42.     strcpy(deviceName, DEFAULT_MIDI_DEVICE);
  43.     unit = DEFAULT_MIDI_UNIT;
  44.  
  45.     /* If environment variable is set, find the real MIDI device info. */
  46.  
  47.     if ((envVar = GetEnv(MIDI_ENV_VAR))
  48.     && (!MakeSerialDeviceName(envVar, deviceName, &unit)))
  49.         return(FALSE);
  50.  
  51.     /* Create a port. */
  52.  
  53.     if (! (MidiPort = CreatePort(0, 0)) )
  54.     {
  55.         fprintf(stderr, "Cannot create port\n");
  56.         SerialShutdown();
  57.         return(FALSE);
  58.     }
  59.     else
  60.         serialFlags |= F_MIDIPORT;
  61.  
  62.     /* Create an extended I/O structure. */
  63.  
  64.     if (! (Midi = (struct IOExtSer *)
  65.     CreateExtIO(MidiPort, sizeof(struct IOExtSer))))
  66.     {
  67.         fprintf(stderr, "Cannot create extended I/O structure\n");
  68.         SerialShutdown();
  69.         return(FALSE);
  70.     }
  71.     else
  72.         serialFlags |= F_MIDI;
  73.  
  74.     /* Open the serial device. */
  75.  
  76.     Midi->io_SerFlags = SERF_SHARED;
  77.     if (OpenDevice(deviceName, unit, (struct IORequest *)Midi, 0))
  78.     {
  79.         fprintf(stderr,
  80.             "Cannot open serial device \"%s\", unit %d.\n",
  81.             deviceName, unit);
  82.         SerialShutdown();
  83.         return(FALSE);
  84.     }
  85.     else
  86.         serialFlags |= F_DEVICE;
  87.  
  88.     /* Set the serial device parameters. */
  89.  
  90.     Midi->io_SerFlags        = SERF_RAD_BOOGIE;
  91.     if (sysex)
  92.     {
  93.         Midi->io_TermArray.TermArray0    = 0xF7F7F7F7;
  94.         Midi->io_TermArray.TermArray1    = 0xF7F7F7F7;
  95.         Midi->io_SerFlags |= SERF_EOFMODE;
  96.     }
  97.     Midi->io_Baud            = MIDI_BAUD_RATE;
  98.     Midi->io_ExtFlags        = 0;    /* For future compatibility */
  99.     Midi->IOSer.io_Command        = SDCMD_SETPARAMS;
  100.  
  101.     if (DoIO((struct IORequest *)Midi) != 0)
  102.      {
  103.         fprintf(stderr, "Cannot set serial parameters.\n");
  104.         SerialShutdown();
  105.         return(FALSE);
  106.     }
  107.     else
  108.         serialFlags |= F_SERPARAMS;
  109.  
  110.     return(TRUE);
  111. }
  112.  
  113.  
  114. /****************************************************************************
  115.  * SerialShutdown:  Close the serial port and its message port.
  116.  ***************************************************************************/
  117.  
  118. void SerialShutdown(void)
  119. {
  120.     if (serialFlags & F_DEVICE)
  121.     {
  122.         ResetSerialPort();
  123.         AbortIO((struct IORequest *)Midi);
  124.         WaitIO((struct IORequest *)Midi);
  125.         CloseDevice((struct IORequest *)Midi);
  126.     }
  127.  
  128.     if (serialFlags & F_MIDI)
  129.         DeleteExtIO((struct IORequest *)Midi);
  130.  
  131.     if (serialFlags & F_MIDIPORT)
  132.         DeletePort(MidiPort);
  133. }
  134.  
  135. /****************************************************************************
  136.  * ResetSerialPort:  Clear all data from the serial port.
  137.  ***************************************************************************/
  138.  
  139. void ResetSerialPort(void)
  140. {
  141.     Midi->IOSer.io_Command = CMD_CLEAR;
  142.     DoIO((struct IORequest *)Midi);
  143. }
  144.  
  145.  
  146. /****************************************************************************
  147.  * Is any data there?
  148.  ***************************************************************************/
  149.  
  150. long AnyMidiData(void)
  151. {
  152.     Midi->IOSer.io_Command = SDCMD_QUERY;
  153.     DoIO((struct IORequest *)Midi);
  154.     return(Midi->IOSer.io_Actual);
  155. }
  156.  
  157.     
  158. /****************************************************************************
  159.  * PrepareToReadMidi:    Prepare a READ request for the MIDI port.
  160.  * PrepareToWriteMidi:    Prepare a WRITE request for the MIDI port.
  161.  ***************************************************************************/
  162.  
  163. void PrepareToReadMidi(UBYTE buf[], int len)
  164. {
  165.     Midi->IOSer.io_Command = CMD_READ;
  166.     Midi->IOSer.io_Data = (APTR)buf;
  167.     Midi->IOSer.io_Length = len;
  168. }
  169.  
  170.  
  171. void PrepareToWriteMidi(UBYTE buf[], int len)
  172. {
  173.     Midi->IOSer.io_Command = CMD_WRITE;
  174.     Midi->IOSer.io_Data = (APTR)buf;
  175.     Midi->IOSer.io_Length = len;
  176. }
  177.  
  178.  
  179. /****************************************************************************
  180. * DoTheIO:  General-purpose MIDI I/O routine.  Quits on ^C.
  181. ****************************************************************************/
  182.  
  183. long DoTheIO(void)
  184. {
  185.     int mask, temp;
  186.     long bytesDone = 0L;
  187.  
  188.     mask = SIGBREAKF_CTRL_C | (1L << MidiPort->mp_SigBit);
  189.     SendIO((struct IORequest *)Midi);
  190.  
  191.     while (1)
  192.     {
  193.         temp = Wait(mask);
  194.         if (temp & SIGBREAKF_CTRL_C)
  195.         {
  196.             bytesDone = CTRL_C_NO_BYTES;
  197.             break;
  198.         }
  199.  
  200.         if (CheckIO((struct IORequest *)Midi))
  201.         {
  202.             WaitIO((struct IORequest *)Midi);
  203.             bytesDone = Midi->IOSer.io_Actual;
  204.             break;
  205.         }
  206.     }
  207.  
  208.     AbortIO((struct IORequest *)Midi);
  209.     WaitIO((struct IORequest *)Midi);
  210.     return(bytesDone);
  211. }
  212.  
  213.  
  214. /****************************************************************************
  215. * Fast serial reading routine, from idea on 1.3 RKM's page 863.
  216. * If any data is waiting, get all of it with DoIO().  Otherwise, post an
  217. * asynchronous request for 1 byte.  Repeat this in the calling program.
  218. ****************************************************************************/
  219.  
  220. long FastSerialRead(UBYTE buf[])
  221. {
  222.     long bytesWaiting, bytesRead;
  223.  
  224.     if ((bytesWaiting = AnyMidiData()) > 0)
  225.     {
  226.         PrepareToReadMidi(buf, MIN(bytesWaiting, BUFSIZ));
  227.         DoIO((struct IORequest *)Midi);
  228.         return(Midi->IOSer.io_Actual);
  229.     }
  230.     else
  231.     {
  232.         PrepareToReadMidi(buf, 1);
  233.         return(DoTheIO());
  234.     }
  235. }
  236.  
  237.     
  238. /****************************************************************************
  239. * Allow the use of another MIDI device than serial.device.
  240. * Environment variable syntax is "DEVICENAME:UNITNUMBER".
  241. * For example:  "midi.device:2".
  242. *
  243. * "device" MUST be preallocated.
  244. ****************************************************************************/
  245.  
  246. BOOL MakeSerialDeviceName(char *str, char *device, int *unit)
  247. {
  248.     while (str && *str && (*str != ':'))
  249.         *(device++) = *(str++);
  250.  
  251.     *device = '\0';
  252.  
  253.     if ((*str != ':') || *(str+1) == '\0')
  254.     {
  255.         fprintf(stderr,
  256.             "Your MIDI device name (variable "
  257.             MIDI_ENV_VAR
  258.             ") is missing a colon\nand/or a unit number.\n");
  259.         return(FALSE);
  260.     }
  261.     str++;
  262.  
  263.     if (!AllDigits(str))
  264.     {
  265.         fprintf(stderr,
  266.             "Your MIDI device unit number (variable "
  267.             MIDI_ENV_VAR
  268.             ") must be\na positive integer.\n");
  269.         return(FALSE);
  270.     }
  271.     else
  272.         *unit = atoi(str);
  273.  
  274.     return(TRUE);
  275. }
  276.  
  277.  
  278. /* AllDigits:    Return TRUE iff the string "str" consists only of digits. */
  279.  
  280. BOOL AllDigits(char *str)
  281. {
  282.     if ((!str) || (*str == '\0'))        /* NULL or empty string. */
  283.         return(FALSE);
  284.     else
  285.         while (*str)            /* For each character... */
  286.             if (!isdigit(*str))    /*  if not a digit...    */
  287.                 return(FALSE);    /*  goodbye!             */
  288.             else
  289.                 str++;
  290.     return(TRUE);                /* All were digits.      */
  291. }
  292.