home *** CD-ROM | disk | FTP | other *** search
/ Sound, Music & MIDI Collection 2 / SMMVOL2.bin / MIDI_PAT / MTOOLS.ZIP / PLAYRDEV.EXE / API.DOC < prev    next >
Encoding:
Text File  |  1993-09-14  |  23.2 KB  |  630 lines

  1. -----------------------------------------------------------------------------   
  2.  
  3.        PLAY/R AND PLAY/D APPLICATION PROGRAMMING INTERFACE
  4.  
  5. -----------------------------------------------------------------------------
  6.         Copyright 1992, Kevin Weiner, All rights reserved
  7.  
  8.            Proprietary material - not for distribution
  9. ----------------------------------------------------------------------------- 
  10.  
  11. Contents
  12.  
  13.  Programming Interface Basics
  14.  API Functions
  15.  Timing Considerations
  16.  Driver Command Line Options
  17.  Langauge Libraries
  18.  Distribution License Terms
  19.  
  20. -----------------------------------------------------------------------------
  21.  
  22.  
  23.            **********************************
  24.            *  Programming Interface Basics  *
  25.            **********************************
  26.  
  27. This document describes the application programming interface (API) for
  28. the Play/R program.  Except where noted, this information also applies
  29. to the Play/D program (Play/D does not include a pop up control window).
  30.  
  31. The Play/R API is based on the use of a "software interrupt" (the
  32. assembly language int instruction), a facility which allows
  33. independently running programs to communicate with each other.  Many
  34. high level languages provide the ability to set up machine registers and
  35. then issue the software interrupt.  Play/R runs as a TSR - a Terminate
  36. and Stay Resident program.  It employs IDC's TesSeRact memory resident
  37. support facility which, among other things, acts as an intermediary in
  38. communications between Play/R and other programs.  TesSeRact passes
  39. command information from the application to Play/R via the DOS multiplex
  40. interrupt 2Fh. 
  41.  
  42. There are two types of interrupt 2Fh calls which must be made.  The
  43. first type establishes whether or not Play/R is loaded, and obtains an
  44. id number for subsequent calls.  The second type is used for normal
  45. communications with Play/R.  They differ slightly in the set up of
  46. machine registers prior to the interrupt call. 
  47.  
  48. To test for the presence of Play/R, set up the machine registers as
  49. follows:
  50.  
  51.      AX        TesSeRact's multiplex id - always 5453h.
  52.      BX        0
  53.      CX        0
  54.      DS:SI     The segment (DS) and offset (SI) of an eight-character
  55.            string "Play/R  ", which identifies the TSR to be located.
  56.            Note - Both Play/R and Play/R share the same internal name.
  57.  
  58. Then perform the interrupt 2Fh.  The value in AX after the call
  59. determines its success.  If AX is FFFFh, Play/R was located and register
  60. CX contains its TSR id, which must be saved for subsequent calls.  If AX
  61. is other than FFFFh, Play/R was not found. 
  62.  
  63. Calls to perform actual Play/R functions are very similar, with the
  64. registers set up as follows:
  65.  
  66.      AX        5453h     (TesSeRact multiplex id)
  67.      BX        20h       (TesSeRact user call function)
  68.      CX        The Play/R id number returned by the call described above.
  69.      ES:DI     The segment (ES) and offset (DI) of a parameter block to be
  70.            passed to Play/R.  This is where all the information passed 
  71.            in and out of Play/R is placed.
  72.       
  73. The parameter area passed to Play/R via this call is an array of at
  74. least 32 bytes.  There is a set of about two dozen API functions which
  75. may be called.  In all cases, the value of the first byte of the
  76. parameter block selects the function, and the remaining bytes are used
  77. to send or receive other information.  The various functions and the
  78. layout of the parameter block are described in the following section. 
  79. It is usually convenient to implement a routine in the high-level
  80. language which checks for the presence of Play/R, and another which
  81. makes the function calls, maintaining the parameter block as a global
  82. array. 
  83.  
  84. ------------------------------------------------------------
  85.  Note: See "Language Libraries" section for information on 
  86.  included high-level libraries.         
  87. ------------------------------------------------------------
  88.  
  89.  
  90.                *******************
  91.                *  API functions  *
  92.                *******************
  93.  
  94. In the following, you should assume that the parameter block used to
  95. pass information to and from Play/R is a byte array named "param", and
  96. that it is indexed starting at zero.  Then param[0] (using Pascal/C
  97. index notation) will always contain the number of the API function to be
  98. performed.  The contents of positions 1 thru N will vary depending on
  99. the nature of the function.  Some functions will change the values in
  100. the param array when data is requested.  In some cases, param[0] may
  101. change during the call, so you should not depend on any array position
  102. remaining the same after a function completes. 
  103.  
  104.  
  105. Function 0:  Pause song.  Does not stop already sounding notes.  Use
  106.          function 9 after function 0 to completely silence output
  107.          (except possibly for brief pauses).  
  108.          
  109.  
  110. Function 1:  Begin playing song (or continue playing if paused).  A song
  111.          must have already been loaded via function 4 or 8.
  112.  
  113.  
  114. Function 2:  Trigger pop up of user control window.  Play/R only.
  115.  
  116.  
  117. Function 3:  Rewind song and pause.  Stops all sounding notes.
  118.  
  119.  
  120. Function 4:  Load MIDI song file and start playing immediately.
  121.  
  122.      Call data: param[1..n] = A zero-byte terminated MIDI file name
  123.                   string. 
  124.  
  125.            To load a play list (a text file with one MIDI file name
  126.            per line), prefix the file name with "@" to identify it 
  127.            as a list.
  128.            
  129.      Return data:   param[0]  =  File load status:
  130.  
  131.              0 = File loaded successfully
  132.              1 = File not found
  133.              2 = Not MIDI file format
  134.              3 = Unexpected end of file
  135.              4 = Format not supported
  136.              5 = Track not found
  137.              6 = I/O error reading file
  138.              7 = Not enough memory 
  139.              8 = Unsupported time base
  140.              255 = Nothing loaded
  141.  
  142.  
  143. Function 5:   Get play status
  144.  
  145.      Return data:   param[0]  =  1 if playing, 0 if paused.
  146.             param[1]  =  1 if at end of song, else 0.
  147.             param[2..5]  =  Song position in milliseconds 
  148.                     (double word integer).
  149.             param[6]  =  Number of songs in play list.
  150.             param[7]  =  Current song number in play list.
  151.  
  152.  
  153. Function 6:   Return file load status (obsolete - use function 5)
  154.  
  155. Function 7:   Return song finished status (obsolete - use function 5)
  156.  
  157.  
  158. Function 8:   Load MIDI file - same as function 4, but play does not begin
  159.           automatically. 
  160.  
  161.  
  162. Function 9:   Stop all sounding notes (use with long pauses to quiet
  163.           active notes). 
  164.  
  165.  
  166. Function 10:  Enable/disable user initiated pop up.  (Play/R only)
  167.  
  168.      Call data:     param[1]  =  1 - Enable
  169.                  0 - Disable
  170.  
  171.  
  172. Function 11:  Adjust overall volume level.
  173.  
  174.      Call data:     param[1]  =  Amount to adjust volume.  May range from
  175.             -127 to +127 as a 1-byte, 2's complement number.
  176.  
  177.  
  178. Function 12:  Reset MIDI interface.  Restores playable "UART" status.
  179.  
  180.      Call data:     param[1]  = 0  (or specific device number - see fcn 20)
  181.  
  182.  
  183. Function 13:  Set timer mode.
  184.  
  185.      Call data:     param[1]  =  1 to 3  (See "Timing Considerations" below)
  186.  
  187.  
  188. Function 14:  Get channel attributes.  Returns one of three possible sets
  189.           of information about MIDI channel usage:  channel mapping, 
  190.           muting, and transpose.
  191.  
  192.      Call data      param[1]  =  0   Return channel mapping
  193.                  1   Return channel enable status (muting)
  194.                  2   Return channel transpose
  195.  
  196.      Return data:   param[2..17] = 16 channel channel attribute values.
  197.  
  198.             Channel mapping:  The returned bytes represent 
  199.             the output channels to which the original MIDI
  200.             file channels are now being redirected.
  201.  
  202.             Channel enable: For each corresponding channel, 
  203.             if the data byte is 1, the channel is enabled; 
  204.             if 0, the channel is disabled (muted).
  205.  
  206.             Channel transpose: The returned bytes indicate 
  207.             the note transposition for each channel, from 
  208.             -127 to +127.  These values are 8-bit two's 
  209.             complement numbers.
  210.               
  211.  
  212. Function 15:  Set channel attributes.
  213.  
  214.      Call data      param[1]  =  0   Set channel mapping
  215.                  1   Set channel enable status
  216.                  2   Set channel transpose
  217.  
  218.             param[2..17] = 16 channel attribute values.  
  219.                    See function 14 above.
  220.  
  221.  
  222. Function 16:  Set song position in milliseconds
  223.  
  224.      Call data:     param[1..4] = Song position n in milliseconds. 
  225.             For n less than zero, fast forward abs(n) 
  226.             milliseconds.  Double word integer.
  227.  
  228.  
  229. Function 17:  Skip forward in play list.
  230.  
  231.      Call data:     param[1] = Number of songs to skip.  If 0 then
  232.             1 is assumed.  Skipping past the end of the list 
  233.             skips to song 1.  The current song number and size
  234.             of play list may be obtained using function 5.
  235.  
  236.  
  237. Function 18:  Set song looping mode.
  238.  
  239.      Call data:     param[1] = Loop mode:
  240.             0 = no looping
  241.             1 = loop song
  242.             2 = loop play list (startup default)
  243.  
  244.  
  245. Function 19:  Reserved
  246.  
  247.  
  248. Some of the following functions can work with multiple MIDI interfaces. 
  249. Play/R supports up to 4 devices, each of which is selected in these
  250. function calls by a "device number".  Use function 20 to identify the
  251. particular type of device associated with each device number.  In most
  252. cases, however, it will be appropriate to use the default device,
  253. selected as device zero.  Each device to be used must appear as a
  254. separate -d option on the playr/playd command line (or corresponding
  255. environment variables must be set - see MidiTools manual Appendix A).
  256.  
  257.  
  258. Function 20:  Get MIDI device name and description.
  259.  
  260.      Call data:     param[1]  =  Device number (counting from 1)
  261.  
  262.      Return data:   param[1]  =  Same device number, or 0 if no more 
  263.                  devices.
  264.             param[2..4]  =  3-character device name
  265.             param[5..24]  =  20-character device description
  266.  
  267.      Call this function repeatedly, incrementing param[1], until param[1]
  268.      returns with 0 to obtain all available devices.  To get just the
  269.      default device, use function 26 first to obtain its device number.
  270.      Then call function 20 with the returned number.
  271.  
  272.  
  273. Function 21:  Send MIDI bytes (short).
  274.  
  275.      Call data:     param[1]  =  Device number  (0 = default device)
  276.             param[2]  =  Number of MIDI bytes to send
  277.             param[3..n]  =  MIDI data bytes
  278.  
  279.  
  280. Function 22:  Send MIDI bytes (long).
  281.  
  282.      Call data:     param[1]  =  Device number  (0 = default device)
  283.             param[2..3]  =  Number of MIDI bytes (word)
  284.             param[4..7]  =  32-bit pointer to MIDI buffer
  285.             param[8..11]  =  reserved; must be 0
  286.  
  287.  
  288. Function 23:  Check for MIDI input.
  289.  
  290.      Call data:     param[1] = Device number  (0 = default device)
  291.  
  292.      Return data:   param[2] = 1 if data waiting, 0 if none
  293.  
  294.      Note: playr.exe (or playd.exe) must be run with the -s option
  295.        to enable interrupt-driven, buffered input.  Otherwise, 
  296.        only a very small buffer is allocated, and polled input 
  297.        is used, possibly resulting in lost data.
  298.  
  299.  
  300. Function 24:  Get MIDI input bytes. 
  301.  
  302.      Call data:     param[1]  =  Device number  (0 = default device)
  303.             param[2..3]  =  Max size of receiving buffer (word)
  304.             param[4..7]  =  32-bit pointer to buffer
  305.      
  306.      Return data:   param[8..9]  =  Number of bytes transferred
  307.             param[10]  =  1 if more data remains, 0 if no more data
  308.  
  309.  
  310. Function 25:  Get absolute time in milliseconds.
  311.  
  312.      Return data:   param[1..4]  =  Reference time as a double word integer.
  313.  
  314.      The time returned is the number of milliseconds since the driver 
  315.      was loaded, and continues incrementing regardless of other machine
  316.      operations.
  317.  
  318.  
  319. Function 26:  Get default MIDI device number.
  320.  
  321.      Return data:   param[1]  =  Default device number
  322.  
  323.      To obtain the name/description of the default device, use the
  324.      returned value with function 20.
  325.  
  326.  
  327. Function 27:  Get direct entry addresses of routines in MIDI driver.
  328.  
  329.      This function returns the addresses of the lowest level routines
  330.      in the MIDI driver.  These allow the API calls to be bypassed and
  331.      improve performance where speed is critical.  Setting up these
  332.      calls can be a tricky process - see the C and Pascal libraries
  333.      for examples if implementing this yourself.
  334.  
  335.      Return data:   param[1..4]   = midiPutByte
  336.             param[5..8]   = midiInputReady
  337.             param[9..12]  = midiGetByte
  338.             param[13..16] = midiClearInput
  339.             param[17..20] = msTimer
  340.             param[21..24] = midiGetMessage
  341.             param[25..28] = midiResend
  342.             param[29..32] = midiPutMessage
  343.  
  344.      midiPutByte - Write a single MIDI byte.
  345.  
  346.         Pascal:  procedure midiPutByte(dev, data: integer);
  347.         C:       VOID FAR PASCAL midiPutByte ( INT dev, INT data )
  348.  
  349.  
  350.      midiInputReady - Test for input data waiting.
  351.  
  352.         Pascal:  function midiInputReady(dev: integer): boolean;
  353.         C:       CHAR FAR PASCAL midiPutByte ( INT dev )
  354.  
  355.  
  356.      midiGetByte - Read a single MIDI byte.  Returns -1 if no data
  357.                arrives within 200 ms.  Use with midiInputReady
  358.                for best results.
  359.  
  360.         Pascal:  procedure midiGetByte(dev: integer; var data: integer);
  361.         C:       VOID FAR PASCAL midiGetByte ( INT dev, INT FAR *data )
  362.  
  363.  
  364.      midiClearInput - Clear all unread data from device.
  365.  
  366.         Pascal:  procedure midiClearInput(dev: integer);
  367.         C:       VOID FAR PASCAL midiClearInput ( INT dev )
  368.  
  369.  
  370.      msTimer - Return reference time in milliseconds.
  371.  
  372.         Pascal:  function msTimer: longint;
  373.         C:       LONG FAR PASCAL msTimer()
  374.  
  375.  
  376.      midiGetMessage - Get a full MIDI message from specified device,
  377.               returning message ordinal, channel, and two
  378.               data bytes (one or both may be unused).
  379.  
  380.         Pascal:  procedure midiGetMessage(dev: integer;
  381.               var msg: messages; var chan, data1, data2: byte);
  382.  
  383.         C:       VOID FAR PASCAL midiGetMessage ( INT dev,
  384.              messages FAR *msg, byte FAR *chan,
  385.              byte FAR *data1, byte FAR *data2)
  386.  
  387.      midiResend - Resend data just read by midiGetMessage;
  388.  
  389.         Pascal:  procedure midiResend(dev: integer);
  390.         C:       VOID FAR PASCAL midiResend ( INT dev )
  391.  
  392.  
  393.      midiPutMessage - Send a full MIDI message using specified device,
  394.               message ordinal, channel, and two data bytes.
  395.  
  396.         Pascal:  procedure midiPutMessage(dev: integer;
  397.               msg: messages; chan, data1, data2: byte);
  398.  
  399.         C:       VOID FAR PASCAL midiPutMessage ( INT dev,
  400.              messages msg, byte chan, byte data1, byte data2)
  401.  
  402.  
  403.        Notes:  The dev parameter on all routines specifies the
  404.            MIDI device number to use.  It must be 1 or greater,
  405.            unlike the API functions which accept 0.
  406.  
  407.            MIDI input/output bytes in midiGetByte and midiPutByte are
  408.            actually passed in the low byte of an integer parameter.
  409.  
  410.            Data type "byte" is an unsigned char.
  411.  
  412.            Data type "messages" is defined in Pascal as:
  413.  
  414.            messages = (noteoff, noteon, polyat, ctrlchange,
  415.                  progchange, chanat, pitchwheel,
  416.                    sysex, quarter, songpos, songsel, tune,
  417.                  eox, undefsc,
  418.                    clock, startc, continue, stopc, actsens,
  419.                  mreset, undefrt,
  420.                    dummy, none);
  421.  
  422.            and in C as:
  423.  
  424.            typedef enum { ...same list as above... } messages;
  425.  
  426.           (These definitions are included in MIDI.INC and MLIB.H.)
  427.  
  428.  
  429.  
  430.               ***************************
  431.               *  Timing Considerations  *
  432.               ***************************
  433.  
  434. Since DOS was not designed as a real time operating system, there is no
  435. one timing method that is perfect for every application.  Because of
  436. this, Play/R offers several timing modes which you must evaluate in
  437. terms of your own application.  Although the player can generally tell
  438. within less than a millisecond what time it is, if control is not passed
  439. to it periodically, play cannot proceed.  This is where the various
  440. modes come in. 
  441.  
  442. Mode 1 is the simplest, relying on DOS to wake up the player
  443. periodically when it is idling, waiting for keyboard input.  Since some
  444. applications, such as GRASP, bypass DOS and do their own keyboard input,
  445. control is never passed to the player. 
  446.  
  447. Mode 2 relies on the system clock to wake it up via interrupts
  448. approximately every 55 milliseconds.  Mode 1 idle processing is also
  449. used if available to smooth timing.  This will work much better for most
  450. applications, but 55 milliseconds may not be precise enough for some
  451. compositions.  Let your ear be the judge. 
  452.  
  453. Mode 3 is a little more forceful than mode 2.  Mode 2 is very polite,
  454. and won't interrupt DOS, but this may cause long pauses while doing
  455. certain operations which rely heavily on DOS.  Although technically
  456. "unsafe", all but the most time critical operations, such as network
  457. access, will continue unhindered when using this mode. 
  458.  
  459. When 55 millisecond resolution is not adequate, you may use the -c
  460. option on playr.exe/playd.exe if running on a 286 or better.  This
  461. replaces the 55 ms timer in modes 2 and 3 with the AT real time clock,
  462. at a resolution of 1 ms.  The disadvantage of this mode is that 1000
  463. interrupts per second tend to slow down other operations.  Again, you
  464. must decide if this slowdown is significant for the intended application
  465. and target hardware. 
  466.  
  467.  
  468.  
  469.           *********************************
  470.           *  Driver Command Line Options  *
  471.           *********************************
  472.  
  473. The following options may be included on the playr/playd command
  474. line (separated by spaces):
  475.  
  476. -a   Indicates the amount of memory (in K bytes; 1K = 1024 bytes)
  477.      to allocate for MIDI file storage.  The default is -a24 (24K bytes).
  478.  
  479. -m   Selects the timer mode: 1, 2, or 3.  The default is -m1.  See
  480.      "Timing Considerations" above.
  481.  
  482. -c   Use the AT real time clock on 286 or better machines for
  483.      modes 2 and 3.  (Not compatible with Microsoft Windows)
  484.  
  485. -h   For use with Microsoft Windows only: Uses the MidiTools virtual
  486.      timer device (timer.386) if it has been installed, and Play/R is
  487.      running in a DOS window in 386 enhanced mode (not supported in
  488.      standard mode).  This provides better timer resolution than the
  489.      normal Windows clock.
  490.  
  491. -l   Specifies that LIM EMS (expanded memory) is to be used for
  492.      MIDI file storage if available.  This reduces the resident
  493.      size of Play/R.
  494.  
  495. -d   Specifies the type of MIDI interface in use.  Also, it is
  496.      used to give additional information about the device if a
  497.      non-standard setup is being used.  For the majority of users,
  498.      this option will not be needed.  The supported interfaces are
  499.      listed below.  Use -d, followed by the device name as shown
  500.      to select one.
  501.  
  502.       Roland MPU-401 and compatibles       -dmpu
  503.       IBM PC Music Feature                 -dmfc
  504.       Sound Blaster MIDI interface         -dsbmidi
  505.       Key Electronics MIDIator             -dmidiator
  506.       Generic serial interface 38400 baud  -dser
  507.       AdLib compatible FM sound            -dadlib
  508.       Sound Blaster compatible FM sound    -dsbfm
  509.  
  510.      The first 3 letters of the device name are sufficient.
  511.  
  512.     Note: The MIDIator and generic serial interfaces cannot be detected
  513.     automatically and the -dmid or -dser option must always be specified
  514.     if one is in use.
  515.  
  516.      Non-standard IRQ and I/O port information can be added
  517.      following the device id if necessary:   -d<dev>:<irq>:<ioaddr>
  518.  
  519.      For example, to define an MPU-compatible interface using IRQ 5
  520.      and I/O address 336 (hex), use:  -dmpu:5:336
  521.  
  522.      If only the I/O address was required but the default IRQ
  523.      was alright, use:  -dmpu::336
  524.  
  525.      The irq and ioaddr are not relevant for -dmid and -dser, though
  526.      the first option number can be given to indicate use of com
  527.      port 2 instead of the default com 1.  (ex: -dmid:2)
  528.  
  529. -i   This option applies to the AdLib and Sound Blaster FM sound
  530.      options, and specifies the name of an instrument bank (.IBK)
  531.      file used to obtain instrument sounds when using standard MIDI
  532.      files.  Note that CMF files usually contain their own instrument
  533.      definitions and will override this option.
  534.  
  535. -v   Shows the MIDI device, I/O address, and IRQ number selected
  536.      prior to program startup.  You may wish to include this option
  537.      if you suspect that automatic detection is not choosing the
  538.      desired options, or to verify the IRQ being used.
  539.  
  540.  
  541. -s   Determines the size of the MIDI receive buffer.  Follow -s
  542.      with a number up to 63, indicating the size of the buffer in
  543.      K bytes (1K=1024 bytes).  By default, no buffer is used, and
  544.      Play/R operates in polled input mode.
  545.  
  546. -r   Remove Play/R from memory if it is already loaded.
  547.  
  548.  
  549.  
  550.              ************************
  551.              *  Language Libraries  *
  552.              ************************
  553.  
  554. In order to simplify use of the Play/R API, basic interfaces in several
  555. languages have been included.  Not all features have been implemented 
  556. for each language.  See the documentation file for the language of 
  557. interest for details on the specific API.
  558.  
  559.    Language                         Source files      Documentation
  560.    ------------------------------   ------------      -------------
  561.    C  (Microsoft, Borland)          MLIB.C            MLIB_C.DOC
  562.                     MLIB.H           
  563.  
  564.    Pascal  (Borland, Stony Brook)   MLIB.PAS          MLIB_PAS.DOC
  565.                     MIDI.INC
  566.    
  567.    MS Quick Basic                   MLIB.QB           MLIB_BAS.DOC
  568.                     MLIB.BI
  569.  
  570.    MS Visual Basic for DOS          MLIB.VB           MLIB_BAS.DOC
  571.                     MLIB.BI
  572.    
  573.    GRASP (animation language)       MIDI.TXT          GRASP.DOC
  574.                     MIDI_MM.TXT
  575.  
  576.    A DOS command line program implementing many of the MIDI file
  577.    functions is available as an alternative for use in languages 
  578.    which do not support software interrupts, but which can execute 
  579.    DOS commands.  See PRC.DOC for information on this program. 
  580.  
  581.  
  582.  
  583.              ********************************
  584.              *  Distribution License Terms  *
  585.              ********************************
  586.  
  587.  
  588. Play/R:  The Play/R module MAY NOT be redistributed under any circumstances
  589.      without written permission from FM Software.
  590.  
  591.  
  592. Play/D:  The Play/D module MAY be distributed royalty-free only when used
  593.      as an integral part of a commercial end user application developed 
  594.      by the individual (or organization) who purchased MidiTools.  The
  595.      playing of MIDI song files must be secondary to the purpose of the
  596.      application.  The following statement must be included in the
  597.      documentation for the application: "FM Software Play/D MIDI driver
  598.      distributed by permission."
  599.  
  600.      This distribution license also applies to shareware products with 
  601.      required registration, but not to software offered in the public 
  602.      domain or without payment required.  Unlimited internal use by 
  603.      the purchaser is permitted.
  604.  
  605.      Software packages intended for use in applications development
  606.      DO NOT qualify as end user applications under this license.
  607.      Play/D may not be distributed with such products without being
  608.      separately licensed.  Royalty and other licensing options are
  609.      available from FM Software.
  610.  
  611.      A keyed demo version of Play/D with no distribution restrictions 
  612.      is available.  Contact FM Software for details.
  613.  
  614.  
  615. PRC:     The PRC program may be freely distributed with applications using
  616.      Play/D.
  617.  
  618. Language Libraries:
  619.  
  620.      The high-level language API libraries included may be incorporated
  621.      in your applications which use Play/D and may be distributed in
  622.      binary form only.                 
  623.  
  624. Other MidiTools modules:  
  625.  
  626.      No other MidiTools modules may be distributed under any
  627.      circumstances without written permission from FM Software.
  628.  
  629. -------------------------------------------------------------------------------
  630.