home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format 19 / af019.adf / player / Play590.c < prev    next >
C/C++ Source or Header  |  1978-04-04  |  15KB  |  699 lines

  1. /*
  2.  *    "PLAY590.C"
  3.  *
  4.  *    Version v1.0 Revision 13: November 13th (!) 1990
  5.  *
  6.  *    (C) Copyright 1990 by Mark Everingham. All Rights Reserved.
  7.  *
  8.  */
  9.  
  10. /* System include files */
  11.  
  12. #include <fcntl.h>
  13. #include <functions.h>
  14. #include <exec/memory.h>
  15. #include <devices/audio.h>
  16. #include <libraries/dos.h>
  17. #include <intuition/intuitionbase.h>
  18. #include <workbench/workbench.h>
  19. #include <workbench/startup.h>
  20. #include <workbench/icon.h>
  21.  
  22. /* Global structures & variables */
  23.  
  24. struct Unit *GetUnit();
  25.  
  26. struct FileHandle    *samplefile[2];
  27.  
  28. struct NewWindow MyNewWindow = {
  29.     459, 0, 181, 10,
  30.     0, 1,
  31.     CLOSEWINDOW,
  32.     WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|RMBTRAP|NOCAREREFRESH,
  33.     NULL, NULL,
  34.     (UBYTE *) "Play590 v1.0",
  35.     NULL, NULL,
  36.     0, 0, 0, 0,
  37.     WBENCHSCREEN
  38. };
  39. struct IntuitionBase    *IntuitionBase = NULL;
  40. struct Window        *mywindow;
  41. ULONG            IDCMPSigMask = 0L;
  42.  
  43. UBYTE            *audiobuffer[2][2];
  44.  
  45. UBYTE            allocSignal;
  46. struct MsgPort         AllocPort;
  47. struct IOAudio        AllocIO;
  48. UBYTE            ChannelMap[2][4] = {{1, 8, 2, 4}, {3, 5, 10, 12}};
  49. UBYTE            ChannelMask[2] = {9, 6};
  50.  
  51. struct MsgPort        AudioPort[2][2];
  52. UBYTE            AudioSignal[2][2];
  53. ULONG            AudioSigMask[2][2] = {0, 0};
  54.     
  55. struct IOAudio        AudIO[2][2];
  56.  
  57. extern struct IconBase *IconBase;
  58. struct DiskObject    *icon = NULL;
  59.  
  60. extern struct _dev *_devtab;
  61.  
  62. int            WorkBench;
  63. int            Window, Speed, Files, Repeats, Stereo, Volume;
  64. long            BufferSize;
  65. UBYTE            OldFilter;
  66.  
  67. struct Task        *mytask;
  68.  
  69. /* Array of error messages */
  70.  
  71. #define NUM_ERRORMSGS        10
  72.  
  73. char *ErrorMessage[NUM_ERRORMSGS] = {
  74.     "Play590 Error: Bad arguments",
  75.     "Play590 Error: Unable to open intuition library",
  76.     "Play590 Error: Unable to open window",
  77.     "Play590 Error: Unable to open sample file",
  78.     "Play590 Error: Out of memory",
  79.     "Play590 Error: Unable to open audio device",
  80.     "Play590 Error: Unable to open icon library",
  81.     "Play590 Error: Illegal argument value",
  82.     "Play590 Error: No sample files specified",
  83.     "Play590 Useage: [run >nil:] Play590 <sample1> [sample2] [-opt 1]..[-opt n]"
  84. };
  85.  
  86. /* Custom symbols */
  87.  
  88. #define ERROR_BADARGS        0
  89. #define ERROR_OPENINTUITION    1
  90. #define ERROR_OPENWINDOW    2
  91. #define ERROR_OPENSAMPLE    3
  92. #define ERROR_OUTOFMEM        4
  93. #define ERROR_OPENAUDIO        5
  94. #define ERROR_OPENICONLIB    6
  95. #define ERROR_ILLEGALARG    7
  96. #define ERROR_NOSAMPLES        8
  97. #define ERROR_USEAGE        9
  98.  
  99. #define DEFAULT_SPEED        16000
  100. #define DEFAULT_BUFFERSIZE    32768L
  101.  
  102. #define OPTION_WINDOW        'W'
  103. #define OPTION_SPEED        'S'
  104. #define OPTION_REPEATS        'R'
  105. #define OPTION_BUFFER        'B'
  106. #define OPTION_STEREO        '2'
  107. #define OPTION_FILTER        'F'
  108. #define OPTION_PRIORITY        'P'
  109. #define OPTION_VOLUME        'V'
  110.  
  111. /* main() - Parse CLI/WB then load and play samples */
  112.  
  113. main(argc, argv)
  114.     int argc;
  115.     char *argv[];
  116. {
  117.     int buffer, loops = 0, status, idcmp;
  118.  
  119.     WorkBench = !argc;
  120.     mytask = FindTask(0L);
  121.  
  122.     OldFilter = *((UBYTE *) 0xbfe001) & 2;
  123.  
  124.     if (WorkBench) {
  125.         OpenIntuitionBase();
  126.         ParseWorkbench((struct WBStartup *) argv);
  127.     } else
  128.         ParseCLI(argc, argv);
  129.  
  130.     OpenAll();
  131.  
  132.     if (!WorkBench) {
  133.         _devtab[2].mode &= (0xffff ^ O_STDIO);
  134.         close(0);
  135.         close(1);
  136.         close(2);
  137.     }
  138.  
  139.     do {
  140.         buffer=1;
  141.         ResetFiles();
  142.         ReadBuffers(0);
  143.         SendBuffers(0);
  144.         do {
  145.             status = ReadBuffers(buffer);
  146.             if (status)
  147.                 SendBuffers(buffer);
  148.             buffer ^= 1;
  149.             idcmp = WaitBuffers(buffer);
  150.         } while (!idcmp && status);
  151.         if (Repeats)
  152.             ++loops;
  153.     } while (!idcmp && (!Repeats || loops != Repeats));
  154.     
  155.     CloseAll();
  156.  
  157.     exit(0);
  158. }
  159.  
  160. /* Open system resources */
  161.  
  162. OpenAll()
  163. {
  164.     int channel;
  165.  
  166.     if (Window) {
  167.         if (!IntuitionBase)
  168.             OpenIntuitionBase();
  169.         OpenMyWindow();
  170.     }
  171.     OpenAudioDevice();
  172.  
  173.     for (channel = 0; channel < Files; ++channel) {
  174.         AllocBuffers(channel);
  175.         OpenAudioPort(channel);
  176.         SetupRequest(channel);
  177.     }        
  178. }
  179.  
  180. /* Close system resources */
  181.  
  182. CloseAll()
  183. {
  184.     int channel;
  185.  
  186.     for (channel = 0; channel < Files; ++channel) {
  187.         CloseAudioPort(channel);
  188.         FreeBuffers(channel);
  189.         CloseFile(channel);
  190.     }
  191.     CloseAudioDevice();
  192.     if (Window)
  193.         CloseMyWindow();
  194.     if (IntuitionBase)
  195.         CloseLibrary(IntuitionBase);
  196.     if (IconBase)
  197.         CloseIconBase();
  198.  
  199.     *((UBYTE *) 0xbfe001) &= 253;
  200.     *((UBYTE *) 0xbfe001) |= OldFilter;
  201. }
  202.  
  203. /* Open the intuition library */
  204.  
  205. OpenIntuitionBase()
  206. {
  207.     IntuitionBase = (struct IntuitionBase *)
  208.         OpenLibrary("intuition.library", 0L);
  209.     if (!IntuitionBase)
  210.         Quit(ERROR_OPENINTUITION);
  211. }
  212.  
  213. /* Open Play590 title window */
  214.  
  215. OpenMyWindow()
  216. {
  217.     mywindow = OpenWindow(&MyNewWindow);
  218.  
  219.     if (!mywindow)
  220.         Quit(ERROR_OPENWINDOW);
  221.  
  222.     IDCMPSigMask = 1L << mywindow->UserPort->mp_SigBit;
  223. }
  224.  
  225. /* Close title window */
  226.  
  227. CloseMyWindow()
  228. {
  229.     if (mywindow)
  230.         CloseWindow(mywindow);
  231. }
  232.  
  233. /* Open the icon library */
  234.  
  235. OpenIconBase()
  236. {
  237.     IconBase = (struct IconBase *)
  238.         OpenLibrary("icon.library", 0L);
  239.     if (!IconBase)
  240.         exit(ERROR_OPENICONLIB);
  241. }
  242.  
  243. /* Open the icon library */
  244.  
  245. CloseIconBase()
  246. {
  247.     if (icon)
  248.         FreeDiskObject(icon);
  249.     if (IconBase)
  250.         CloseLibrary(IconBase);
  251. }
  252.  
  253. /* Open sample files/files */
  254.  
  255. OpenFiles(filename, Stereo)
  256.     char *filename;
  257.     int Stereo;
  258. {
  259.     int file;
  260.  
  261.     for (file = 0; file <= Stereo; ++file)
  262.         if (Files < 2) {
  263.             samplefile[Files] = Open(filename, MODE_OLDFILE);
  264.             if (!samplefile[Files])
  265.                 Quit(ERROR_OPENSAMPLE);
  266.             ++Files;
  267.         } else
  268.             Quit(ERROR_BADARGS);
  269. }
  270.  
  271. /* Close sample file */
  272.  
  273. CloseFile(channel)
  274.     int channel;
  275. {
  276.     if (samplefile[channel])
  277.         Close(samplefile[channel]);
  278. }
  279.  
  280. /* Open port & audio.device and allocate channels */
  281.  
  282. OpenAudioDevice()
  283. {
  284.     allocSignal = AllocSignal(-1L);
  285.     if (allocSignal == -1L)
  286.         Quit(ERROR_OPENAUDIO);
  287.  
  288.     AllocPort.mp_SigTask        = mytask;
  289.     AllocPort.mp_Flags        = PA_SIGNAL;
  290.     AllocPort.mp_SigBit        = allocSignal;
  291.     AllocPort.mp_Node.ln_Type    = NT_MSGPORT;
  292.     
  293.     AddPort(&AllocPort);
  294.  
  295.     AllocIO.ioa_Request.io_Command            = ADCMD_ALLOCATE;
  296.     AllocIO.ioa_Request.io_Message.mn_Node.ln_Pri    = 50;
  297.     AllocIO.ioa_Request.io_Message.mn_ReplyPort    = &AllocPort;
  298.     AllocIO.ioa_Data                = &ChannelMap[Files - 1][0];
  299.     AllocIO.ioa_Length                = 4L;
  300.  
  301.     if (OpenDevice("audio.device", 0L, &AllocIO, 0L))
  302.         Quit(ERROR_OPENAUDIO);
  303. }
  304.  
  305. /* Close audio.device and remove port */
  306.  
  307. CloseAudioDevice()
  308. {
  309.     if (AllocIO.ioa_Request.io_Device)
  310.         CloseDevice(&AllocIO);
  311.  
  312.     if (AllocPort.mp_SigTask)
  313.         RemPort(&AllocPort);
  314.  
  315.     if (allocSignal != -1L)
  316.         FreeSignal(allocSignal);
  317. }
  318.  
  319. /* Allocate channel double-buffers */
  320.  
  321. AllocBuffers(channel)
  322.     int channel;
  323. {
  324.     int buffer;
  325.  
  326.     for (buffer = 0; buffer < 2; ++buffer) {
  327.         audiobuffer[channel][buffer] = AllocMem(BufferSize, MEMF_PUBLIC|MEMF_CHIP);
  328.         if (!audiobuffer[channel][buffer])
  329.             Quit(ERROR_OUTOFMEM);
  330.     }
  331. }
  332.         
  333. /* Free memory used by buffers */
  334.  
  335. FreeBuffers(channel)
  336.     int channel;
  337. {
  338.     int buffer;
  339.  
  340.     for (buffer = 0; buffer < 2; ++buffer)
  341.         if (audiobuffer[channel][buffer])
  342.             FreeMem(audiobuffer[channel][buffer], BufferSize);
  343. }
  344.  
  345. /* Open a replyport for an audio channel/buffer */
  346.  
  347. OpenAudioPort(channel)
  348.     int channel;
  349. {
  350.     int buffer;
  351.  
  352.     for (buffer = 0; buffer < 2; ++buffer) {
  353.         AudioSignal[channel][buffer] = AllocSignal(-1L);
  354.         if (AudioSignal[channel][buffer] == -1L)
  355.             Quit(ERROR_OPENAUDIO);
  356.         AudioSigMask[channel][buffer] = 1L << AudioSignal[channel][buffer];
  357.  
  358.         AudioPort[channel][buffer].mp_SigTask        = mytask;
  359.         AudioPort[channel][buffer].mp_Flags        = PA_SIGNAL;
  360.         AudioPort[channel][buffer].mp_SigBit        = AudioSignal[channel][buffer];
  361.         AudioPort[channel][buffer].mp_Node.ln_Type    = NT_MSGPORT;
  362.         AddPort(&AudioPort[channel][buffer]);
  363.     }
  364. }
  365.  
  366. /* Close audio replyport */
  367.  
  368. CloseAudioPort(channel)
  369.     int channel;
  370. {
  371.     int buffer;
  372.  
  373.     for (buffer = 0; buffer < 2; ++buffer) {
  374.         if (AudioPort[channel][buffer].mp_SigTask)
  375.             RemPort(&AudioPort[channel][buffer]);
  376.  
  377.         if (AudioSignal[channel][buffer] != -1L)
  378.             FreeSignal(AudioSignal[channel][buffer]);
  379.     }
  380. }
  381.  
  382. /* Setup AudioRequest structure ready for audio data */
  383.  
  384. SetupRequest(channel)
  385.     int channel;
  386. {
  387.     int buffer;
  388.  
  389.     for (buffer = 0; buffer < 2; ++buffer) { 
  390.         AudIO[channel][buffer].ioa_Request.io_Message.mn_ReplyPort    = &AudioPort[channel][buffer];
  391.         AudIO[channel][buffer].ioa_Request.io_Device            = AllocIO.ioa_Request.io_Device;
  392.         AudIO[channel][buffer].ioa_Request.io_Unit            = GetUnit(channel);
  393.         AudIO[channel][buffer].ioa_Request.io_Command            = CMD_WRITE;
  394.         AudIO[channel][buffer].ioa_Request.io_Flags            = ADIOF_PERVOL;
  395.         AudIO[channel][buffer].ioa_AllocKey                = AllocIO.ioa_AllocKey;
  396.         AudIO[channel][buffer].ioa_Data                    = audiobuffer[channel][buffer];
  397.         AudIO[channel][buffer].ioa_Length                = 0L;
  398.         AudIO[channel][buffer].ioa_Cycles                = 1;
  399.         AudIO[channel][buffer].ioa_Period                = (UWORD) (3579545L / Speed);
  400.         AudIO[channel][buffer].ioa_Volume                = Volume;
  401.     }
  402. }
  403.  
  404. /* Get the unit number of a channel */
  405.  
  406. struct Unit *GetUnit(channel)
  407.     int channel;
  408. {
  409.     ULONG units;
  410.  
  411.     units = (ULONG) AllocIO.ioa_Request.io_Unit;
  412.     
  413.     if (Files == 2)
  414.         units &= ChannelMask[channel];
  415.  
  416.     return ((struct Unit *) units);
  417. }
  418.  
  419. /* Reset the sample files to byte zero */
  420.  
  421. ResetFiles()
  422. {
  423.     int channel;
  424.  
  425.     for (channel = 0; channel < Files; ++channel) {
  426.         Seek(samplefile[channel], 0L, OFFSET_BEGINNING);
  427.         AudIO[channel][1].ioa_Length = 0L;
  428.     }
  429.  
  430. }
  431.  
  432. /* Read one/two channel buffers from sample files */
  433.  
  434. ReadBuffers(buffer)
  435.     int buffer;
  436. {
  437.     int channel;
  438.  
  439.     for (channel = 0; channel < Files; ++channel)
  440.         AudIO[channel][buffer].ioa_Length = Read(samplefile[channel], audiobuffer[channel][buffer], BufferSize);
  441.  
  442.     return (AudIO[0][buffer].ioa_Length != 0L);
  443. }
  444.  
  445. /* Send one/two channel buffers to audio.device */
  446.  
  447. SendBuffers(buffer)
  448.     int buffer;
  449. {
  450.     int channel;
  451.  
  452.     for (channel = 0; channel < Files; ++channel)
  453.         BeginIO(&AudIO[channel][buffer]);
  454. }
  455.  
  456. /* Wait for a pair of audio buffers to finish playing */
  457.  
  458. WaitBuffers(buffer)
  459.     int buffer;
  460. {
  461.     ULONG signals, status = 0L;
  462.  
  463.     do {
  464.         signals = Wait(AudioSigMask[0][buffer] | AudioSigMask[1][buffer] | IDCMPSigMask);
  465.     
  466.         if (signals & IDCMPSigMask)
  467.             return(TRUE);
  468.     
  469.         if (signals & AudioSigMask[0][buffer]) {
  470.             GetMsg(&AudioPort[0][buffer]);
  471.             status |= AudioSigMask[0][buffer];
  472.         }
  473.         if (signals & AudioSigMask[1][buffer]) {
  474.             GetMsg(&AudioPort[1][buffer]);
  475.             status |= AudioSigMask[1][buffer];
  476.         }
  477.     } while (status != (AudioSigMask[0][buffer] | AudioSigMask[1][buffer]));
  478.  
  479.     return(FALSE);
  480. }
  481.  
  482. /* Parse the command line for sample-names and options */
  483.  
  484. ParseCLI(argc, argv)
  485.     int argc;
  486.     char *argv[];
  487. {
  488.     int arg;
  489.     char optchar;
  490.  
  491.     if (argc == 1 || (argc == 2 && argv[1][0] == '?'))
  492.         Quit(ERROR_USEAGE);
  493.  
  494.     if (argc < 2)
  495.         Quit(ERROR_BADARGS);
  496.  
  497.     Window        = FALSE;
  498.     Speed        = DEFAULT_SPEED;
  499.     Files        = 0;
  500.     Repeats        = 1;
  501.     BufferSize    = DEFAULT_BUFFERSIZE;
  502.     Stereo        = FALSE;
  503.     Volume        = 64;
  504.  
  505.     for (arg = 1; arg < argc; ++arg)
  506.         if (argv[arg][0] == '-') {
  507.             optchar = toupper(argv[arg][1]);
  508.             switch (optchar) {
  509.                 case OPTION_WINDOW:
  510.                     Window = TRUE;
  511.                     break;
  512.                 case OPTION_SPEED:
  513.                     Speed = atoi(&argv[arg][2]);
  514.                     if (Speed <= 0)
  515.                         Quit(ERROR_ILLEGALARG);
  516.                     break;
  517.                 case OPTION_REPEATS:
  518.                     Repeats = atoi(&argv[arg][2]);
  519.                     if (Repeats < 0)
  520.                         Quit(ERROR_ILLEGALARG);
  521.                     break;
  522.                 case OPTION_BUFFER:
  523.                     BufferSize = (long) atoi(&argv[arg][2]);
  524.                     if (!BufferSize)
  525.                         Quit(ERROR_ILLEGALARG);
  526.                     if (BufferSize < 0)
  527.                         BufferSize = 65536L + BufferSize;
  528.                     break;
  529.                 case OPTION_STEREO:
  530.                     Stereo = TRUE;
  531.                     break;
  532.                 case OPTION_FILTER:
  533.                     *((UBYTE *) 0xbfe001) |= 2;
  534.                     break;
  535.                 case OPTION_PRIORITY:
  536.                     SetTaskPri(mytask, (long) atoi(&argv[arg][2]));
  537.                     break;
  538.                 case OPTION_VOLUME:
  539.                     Volume = atoi(&argv[arg][2]);
  540.                     if (Volume < 0 || Volume > 64)
  541.                         Quit(ERROR_ILLEGALARG);
  542.                     break;
  543.                 default:
  544.                     Quit(ERROR_BADARGS);
  545.             }
  546.         } else
  547.             OpenFiles(argv[arg], Stereo);
  548.  
  549.     if (!Files)
  550.         Quit(ERROR_NOSAMPLES);
  551. }
  552.  
  553. /* Null stub for standard Workbench startup code */
  554.  
  555. _wb_parse(pp, wbm)
  556.     register struct Process *pp;
  557.     struct WBStartup *wbm;
  558. {
  559. }
  560.  
  561. /* Parse the Workbench startup message for sample-names and options */
  562.  
  563. ParseWorkbench(wbmsg)
  564.     struct WBStartup *wbmsg;
  565. {
  566.     struct WBArg *wbarg;
  567.     int args, arg;
  568.     char *filename;
  569.  
  570.     OpenIconBase();
  571.  
  572.     Window        = TRUE;
  573.     Speed        = DEFAULT_SPEED;
  574.     Files        = 0;
  575.     Repeats        = 1;
  576.     BufferSize    = DEFAULT_BUFFERSIZE;
  577.     Stereo        = FALSE;
  578.     Volume        = 64;
  579.  
  580.     args = wbmsg->sm_NumArgs;
  581.     if (args > 3)
  582.         Quit(ERROR_BADARGS);
  583.     wbarg = wbmsg->sm_ArgList;
  584.  
  585.     for (arg = 0; arg < args; ++arg, ++wbarg)
  586.         ParseWBArg(wbarg);
  587.  
  588.     if (!Files)
  589.         Quit(ERROR_NOSAMPLES);
  590. }
  591.  
  592. /* Parse an individual Workbench argument for options */
  593.  
  594. ParseWBArg(wbarg)
  595.     struct WBArg *wbarg;
  596. {
  597.     struct FileLock *icondir, *olddir;
  598.     char **toolarray;
  599.     char *tooltype, *iconname;
  600.     int namebar;
  601.  
  602.     icondir = (struct FileLock *) wbarg->wa_Lock;
  603.     if (!icondir)
  604.         return(FALSE);
  605.  
  606.     iconname = wbarg->wa_Name;
  607.     olddir = CurrentDir(icondir);
  608.  
  609.     icon = GetDiskObject(iconname);
  610.     if (!icon)
  611.         return(FALSE);
  612.     toolarray = icon->do_ToolTypes;
  613.  
  614.     if (tooltype = FindToolType(toolarray, "PRIORITY"))
  615.         SetTaskPri(mytask, (long) atoi(tooltype));
  616.  
  617.     if (tooltype = FindToolType(toolarray, "WINDOW")) {
  618.         if (MatchToolValue(tooltype, "ON"))
  619.             Window = TRUE;
  620.         else
  621.             if (MatchToolValue(tooltype, "OFF"))
  622.                 Window = FALSE;
  623.             else
  624.                 Quit(ERROR_ILLEGALARG);
  625.     }
  626.     if (tooltype = FindToolType(toolarray, "SPEED")) {
  627.         Speed = atoi(tooltype);
  628.         if (Speed <= 0)
  629.             Quit(ERROR_ILLEGALARG);
  630.     }
  631.     if (tooltype = FindToolType(toolarray, "REPEATS")) {
  632.         Repeats = atoi(tooltype);
  633.         if (Repeats < 0)
  634.             Quit(ERROR_ILLEGALARG);
  635.     }
  636.     if (tooltype = FindToolType(toolarray, "BUFFER")) {
  637.         BufferSize = (long) atoi(tooltype);
  638.         if (!BufferSize)
  639.             Quit(ERROR_ILLEGALARG);
  640.         if (BufferSize < 0)
  641.             BufferSize = 65536L + BufferSize;
  642.     }
  643.     if (tooltype = FindToolType(toolarray, "MODE")) {
  644.         if (MatchToolValue(tooltype, "MONO"))
  645.             Stereo = FALSE;
  646.         else
  647.             if (MatchToolValue(tooltype, "STEREO"))
  648.                 Stereo = TRUE;
  649.             else
  650.                 Quit(ERROR_ILLEGALARG);
  651.     }
  652.     if (tooltype = FindToolType(toolarray, "FILTER")) {
  653.         if (MatchToolValue(tooltype, "ON"))
  654.             *((UBYTE *) 0xbfe001) &= 253;
  655.         else
  656.             if (MatchToolValue(tooltype, "OFF"))
  657.                 *((UBYTE *) 0xbfe001) |= 2;
  658.             else
  659.                 Quit(ERROR_ILLEGALARG);
  660.     }
  661.     if (tooltype = FindToolType(toolarray, "VOLUME")) {
  662.         Volume = atoi(tooltype);
  663.         if (Volume < 0 || Volume > 64)
  664.             Quit(ERROR_ILLEGALARG);
  665.     }
  666.  
  667.     if ((icon->do_Type == WBTOOL) && (tooltype = FindToolType(toolarray, "SAMPLE1")))
  668.         OpenFiles(tooltype, Stereo);
  669.     if ((icon->do_Type == WBTOOL) && (tooltype = FindToolType(toolarray, "SAMPLE2")))
  670.         OpenFiles(tooltype, Stereo);
  671.  
  672.     if (icon->do_Type != WBTOOL)
  673.         OpenFiles(iconname, Stereo);
  674.  
  675.     CurrentDir(olddir);
  676.     FreeDiskObject(icon);
  677.     icon = NULL;
  678. }
  679.  
  680. /* Close the system resources and exit */
  681.  
  682. Quit(error)
  683.     int error;
  684. {
  685.     if (WorkBench) {
  686.         if (IntuitionBase) {
  687.             DisplayBeep(IntuitionBase->ActiveScreen);
  688.             SetWindowTitles(IntuitionBase->ActiveWindow, -1L, ErrorMessage[error]);
  689.         }
  690.     } else {
  691.         if (_devtab[2].fd)
  692.             Write(_devtab[2].fd, ErrorMessage[error], (long) strlen(ErrorMessage[error]));
  693.             Write(_devtab[2].fd, "\n", 1L);
  694.     }
  695.  
  696.     CloseAll();
  697.     exit(RETURN_FAIL);
  698. }
  699.