home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / amiga / midi / obrst103.lha / OberSuite-1.03 / SourceCode / serial.c < prev    next >
C/C++ Source or Header  |  1993-01-23  |  8KB  |  314 lines

  1. /**************************************************************************
  2. * serial.c:    Low-level serial device functions.
  3. *        A part of OberSuite for the Commodore Amiga.
  4. *
  5. * Author:    Daniel Barrett, barrett@cs.umass.edu.
  6. * Version:    1.0.
  7. * Copyright:    None!  This program is in the Public Domain.
  8. *        Please share it with others.
  9. ***************************************************************************/
  10.  
  11. #include "decl.h"
  12. #include "midi.h"
  13. #include "oberheim.h"
  14.  
  15. /***************************************************************************
  16. * A "placeholder" value indicating that a field needs to be filled in later.
  17. ***************************************************************************/
  18.  
  19. #define    FILL_IN_LATER        0
  20.  
  21. /***************************************************************************
  22. * "Global" variables for the serial port structure.
  23. ***************************************************************************/
  24.  
  25. static struct MsgPort    *MidiPort    = NULL;
  26. static struct IOExtSer    *Midi        = NULL;
  27. static long serialFlags            = 0L;
  28.  
  29. /***************************************************************************
  30. * Flags that indicate which structures have been allocated.
  31. ***************************************************************************/
  32.  
  33. #define    F_MIDIPORT    1
  34. #define    F_MIDI        2
  35. #define    F_DEVICE    4
  36. #define    F_SERPARAMS    8
  37.  
  38. /****************************************************************************
  39. * Prototypes.
  40. ****************************************************************************/
  41.  
  42. BOOL MakeSerialDeviceName(char *str, char *device, int *unit);
  43.  
  44.  
  45. /****************************************************************************
  46. * SerialSetup:  Open the serial port and its message port.
  47. * By default, we use the device DEFAULT_MIDI_DEVICE, unit DEFAULT_MIDI_UNIT.
  48. * However, the user may set an environment variable ENVIRONMENT_VAR to
  49. * indicate the presence of an alternate MIDI device.
  50. ****************************************************************************/
  51.  
  52. BOOL SerialSetup(void)
  53. {
  54.     char deviceName[BUFSIZ], *envVar;
  55.     int unit;
  56.  
  57.    /* Assume we are using the default MIDI device. */
  58.  
  59.     strcpy(deviceName, DEFAULT_MIDI_DEVICE);
  60.     unit = DEFAULT_MIDI_UNIT;
  61.  
  62.    /*
  63.     * If the user has set the environment variable, use that MIDI device
  64.     * instead.  If the environment variable value is illegal, quit.
  65.     */
  66.  
  67.     if ((envVar = GetEnv(ENVIRONMENT_VAR))
  68.     && (!MakeSerialDeviceName(envVar, deviceName, &unit)))
  69.         return(FALSE);
  70.  
  71.    /* Do the magic incantations to open the serial device. */
  72.  
  73.     if (! (MidiPort = CreatePort(0, 0)) )
  74.     {
  75.         ErrorMsg(ERROR_CREATEPORT);
  76.         SerialShutdown();
  77.         return(FALSE);
  78.     }
  79.     else
  80.         serialFlags |= F_MIDIPORT;
  81.  
  82.     if (! (Midi = (struct IOExtSer *)
  83.     CreateExtIO(MidiPort, sizeof(struct IOExtSer))))
  84.     {
  85.         ErrorMsg(ERROR_IOEXTSER);
  86.         SerialShutdown();
  87.         return(FALSE);
  88.     }
  89.     else
  90.         serialFlags |= F_MIDI;
  91.  
  92.     Midi->io_SerFlags = SERF_SHARED;
  93.     if (OpenDevice(deviceName, unit, (struct IORequest *)Midi, 0))
  94.     {
  95.         ErrorMsg(ERROR_OPENDEVICE);
  96.  
  97.         if (envVar && ERR_OUTPUT_ALLOWED)
  98.         {
  99.             fprintf(stderr,
  100.                 "Perhaps you have the value of your "
  101.                 ENVIRONMENT_VAR
  102.                 " variable set incorrectly;\n"
  103.                 " its value is currently set to \"%s\"\n"
  104.                 " (meaning \"DEVICE=%s, UNIT=%d\".)\n",
  105.                 envVar, deviceName, unit);
  106.         }
  107.  
  108.         SerialShutdown();
  109.         return(FALSE);
  110.     }
  111.     else
  112.         serialFlags |= F_DEVICE;
  113.  
  114.     Midi->io_SerFlags        = SERF_RAD_BOOGIE | SERF_EOFMODE;
  115.     Midi->io_Baud            = MIDI_BAUD_RATE;
  116.     Midi->io_TermArray.TermArray0    = 0xF7F7F7F7;
  117.     Midi->io_TermArray.TermArray1    = 0xF7F7F7F7;
  118.     Midi->io_ExtFlags        = 0;    /* For future compatibility */
  119.     Midi->IOSer.io_Command        = SDCMD_SETPARAMS;
  120.     if (DoIO((struct IORequest *)Midi) != 0)
  121.      {
  122.         ErrorMsg(ERROR_SETPARAMS);
  123.         SerialShutdown();
  124.         return(FALSE);
  125.     }
  126.     else
  127.         serialFlags |= F_SERPARAMS;
  128.  
  129.     return(TRUE);
  130. }
  131.  
  132.  
  133. /****************************************************************************
  134. * SerialShutdown:  Close the serial port and its message port.
  135. * Be sure to close things in the opposite order in which they were opened.
  136. ****************************************************************************/
  137.  
  138. void SerialShutdown(void)
  139. {
  140.     if (serialFlags & F_DEVICE)
  141.     {
  142.         ResetSerialPort();
  143.         AbortIO((struct IORequest *)Midi);
  144.         WaitIO((struct IORequest *)Midi);
  145.         CloseDevice((struct IORequest *)Midi);
  146.     }
  147.  
  148.     if (serialFlags & F_MIDI)
  149.         DeleteExtIO((struct IORequest *)Midi);
  150.  
  151.     if (serialFlags & F_MIDIPORT)
  152.         DeletePort(MidiPort);
  153. }
  154.  
  155. /****************************************************************************
  156.  * ResetSerialPort:  Clear all data from the serial port.
  157.  ***************************************************************************/
  158.  
  159. void ResetSerialPort(void)
  160. {
  161.     Midi->IOSer.io_Command = CMD_CLEAR;
  162.     DoIO((struct IORequest *)Midi);
  163. }
  164.  
  165.  
  166. /****************************************************************************
  167.  * Is any data there?
  168.  ***************************************************************************/
  169.  
  170. long AnyMidiData(void)
  171. {
  172.     Midi->IOSer.io_Command = SDCMD_QUERY;
  173.     DoIO((struct IORequest *)Midi);
  174.     return(Midi->IOSer.io_Actual);
  175. }
  176.  
  177.     
  178. /****************************************************************************
  179.  * PrepareToReadMidi:    Prepare a READ request for the MIDI port.
  180.  * PrepareToWriteMidi:    Prepare a WRITE request for the MIDI port.
  181.  ***************************************************************************/
  182.  
  183. void PrepareToReadMidi(UBYTE buf[], int len)
  184. {
  185.     Midi->IOSer.io_Command = CMD_READ;
  186.     Midi->IOSer.io_Data = (APTR)buf;
  187.     Midi->IOSer.io_Length = len;
  188. }
  189.  
  190.  
  191. void PrepareToWriteMidi(UBYTE buf[], int len)
  192. {
  193.     Midi->IOSer.io_Command = CMD_WRITE;
  194.     Midi->IOSer.io_Data = (APTR)buf;
  195.     Midi->IOSer.io_Length = len;
  196. }
  197.  
  198.  
  199. /****************************************************************************
  200. * DoTheIO:  General-purpose MIDI I/O routine.  Quits on ^C.
  201. ****************************************************************************/
  202.  
  203. long DoTheIO(void)
  204. {
  205.     int mask, temp;
  206.     long bytesDone = 0L;
  207.  
  208.     mask = SIGBREAKF_CTRL_C | (1L << MidiPort->mp_SigBit);
  209.     SendIO((struct IORequest *)Midi);
  210.  
  211.     while (1)
  212.     {
  213.         temp = Wait(mask);
  214.         if (temp & SIGBREAKF_CTRL_C)
  215.         {
  216.             bytesDone = CTRL_C_NO_BYTES;
  217.             break;
  218.         }
  219.  
  220.         if (CheckIO((struct IORequest *)Midi))
  221.         {
  222.             WaitIO((struct IORequest *)Midi);
  223.             bytesDone = Midi->IOSer.io_Actual;
  224.             break;
  225.         }
  226.     }
  227.  
  228.     AbortIO((struct IORequest *)Midi);
  229.     WaitIO((struct IORequest *)Midi);
  230.     return(bytesDone);
  231. }
  232.  
  233.  
  234. /****************************************************************************
  235.  * RequestOnePatch:  Request a patch dump from an Oberheim synth.
  236.  ***************************************************************************/
  237.  
  238. void RequestOnePatch(UBYTE patchNum, int mode)
  239. {
  240.     static UBYTE request[7] = {    SYSEX_BEGIN,
  241.                     OBERHEIM_SYSEX_ID,
  242.                     OBERHEIM_DEVICE_NUMBER,
  243.                     DUMP_REQUEST,
  244.                     FILL_IN_LATER,
  245.                     FILL_IN_LATER,
  246.                     SYSEX_END    };
  247.  
  248.     request[BYTE_PATCHTYPE]   = (UBYTE)mode;
  249.     request[BYTE_PATCHNUMBER] = patchNum;
  250.  
  251.     ResetSerialPort();
  252.     Midi->IOSer.io_Command    = CMD_WRITE;
  253.     Midi->IOSer.io_Data    = (APTR)request;
  254.     Midi->IOSer.io_Length    = sizeof(request);
  255.     (void)DoTheIO();
  256. }
  257.  
  258.  
  259. /***************************************************************************
  260. * Environment variable functions.
  261. ***************************************************************************/
  262.  
  263. /*
  264.  * Given the string "str", break it into the device name and unit number.
  265.  * Environment variable syntax is "DEVICENAME:UNITNUMBER".
  266.  * For example:  "midi.device:2".
  267.  *
  268.  * "device" MUST preallocated.
  269.  */
  270.  
  271. BOOL MakeSerialDeviceName(char *str, char *device, int *unit)
  272. {
  273.    /*
  274.     * Copy "str" into the device name, until we reach a ':' or run out
  275.     * of data.
  276.     */
  277.  
  278.     while (str && *str && (*str != ':'))
  279.         *(device++) = *(str++);
  280.  
  281.    /* Terminate the device name, so it is a valid string. */
  282.  
  283.     *device = '\0';
  284.  
  285.    /* If we did not reach a colon, complain and exit! */
  286.  
  287.     if ((*str != ':') || *(str+1) == '\0')
  288.     {
  289.         ErrorMsg(ERROR_OBDEVICE);
  290.         return(FALSE);
  291.     }
  292.  
  293.    /* Skip the colon. */
  294.  
  295.     str++;
  296.  
  297.    /*
  298.     * The remaining string data must represent a non-negative integer.
  299.     * If so, grab the data as the value of "unit".
  300.     * Otherwise, complain and exit!
  301.     */
  302.     if (!AllDigits(str))
  303.     {
  304.         ErrorMsg(ERROR_OBUNIT);
  305.         return(FALSE);
  306.     }
  307.     else
  308.         *unit = atoi(str);
  309.  
  310.    /* If we got here, everything is just groovy! */
  311.  
  312.     return(TRUE);
  313. }
  314.