home *** CD-ROM | disk | FTP | other *** search
/ Super PC 33 / Super PC 33 (Shareware).iso / spc / sonido / timidity / source / timidity.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-21  |  18.0 KB  |  785 lines

  1. /*
  2.  
  3.     TiMidity -- Experimental MIDI to WAVE converter
  4.     Copyright (C) 1995 Tuukka Toivonen <titoivon@snakemail.hut.fi>
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20. */
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #ifdef __WIN32__
  24. #include <string.h>
  25. #include <windows.h>
  26. #define rindex strrchr
  27. extern int optind;
  28. extern char *optarg;
  29. int getopt (int, char **, char *);
  30. #else
  31. #include <unistd.h>
  32. #include <strings.h>
  33. #endif
  34.  
  35. #include "config.h"
  36. #include "common.h"
  37. #ifdef __WIN32__
  38. #include "instrume.h"
  39. #else
  40. #include "instruments.h"
  41. #endif
  42. #include "playmidi.h"
  43. #include "readmidi.h"
  44. #include "output.h"
  45. #include "controls.h"
  46. #include "tables.h"
  47.  
  48. static int free_instruments_afterwards=0;
  49. static char def_instr_name[256]="";
  50.  
  51. #ifdef __WIN32__
  52. int intr;
  53. CRITICAL_SECTION critSect;
  54.  
  55. #pragma argsused
  56. static BOOL WINAPI handler (DWORD dw)
  57.     {
  58.     printf ("***BREAK\n");
  59.     intr = TRUE;
  60.     play_mode->purge_output ();
  61.     return TRUE;
  62.     }
  63. #endif
  64.  
  65. static void help(void)
  66. {
  67.   PlayMode **pmp=play_mode_list;
  68.   ControlMode **cmp=ctl_list;
  69.   printf(" TiMidity version " TIMID_VERSION " (C) 1995 Tuukka Toivonen "
  70.      "<titoivon@snakemail.hut.fi>\n"
  71.      " TiMidity is free software and comes with ABSOLUTELY NO WARRANTY.\n"
  72.      "\n"
  73. #ifdef __WIN32__
  74.      " Win32 version by Davide Moretti\n"
  75.      "\n"
  76. #endif
  77.      "Usage:\n"
  78.      "  %s [options] filename [...]\n"
  79.      "\n"
  80.      "  Use \"-\" as filename to read a MIDI file from stdin\n"
  81.      "\n"
  82.      "Options:\n"
  83. #if defined(AU_HPUX)
  84.      "  -o file Output to another file (or audio server) (Use \"-\" for stdout)\n"
  85. #elif defined (AU_LINUX)
  86.      "  -o file Output to another file (or device) (Use \"-\" for stdout)\n"
  87. #else
  88.      "  -o file Output to another file (Use \"-\" for stdout)\n"
  89. #endif
  90.      "  -O mode Select output mode and format (see below for list)\n"
  91.      "  -s f    Set sampling frequency to f (Hz or kHz)\n"
  92.      "  -a      Enable the antialiasing filter\n"
  93.      "  -f      "
  94. #ifdef FAST_DECAY
  95.                     "Disable"
  96. #else
  97.                     "Enable"
  98. #endif
  99.                               " fast decay mode\n"
  100.      "  -p n    Allow n-voice polyphony\n"
  101.      "  -A n    Amplify volume by n percent (may cause clipping)\n"
  102.      "  -C n    Set ratio of sampling and control frequencies\n"
  103.      "\n"
  104.      "  -L dir  Append dir to search path\n"
  105.      "  -c file Read extra configuration file\n"
  106.      "  -I n    Use program n as the default\n"
  107.      "  -P file Use patch file for all programs\n"
  108.      "  -D n    Play drums on channel n\n"
  109.      "  -Q n    Ignore channel n\n"
  110.      "  -F      Disable fast panning\n"
  111.      "  -U      Unload instruments from memory between MIDI files\n"
  112.      "\n"
  113.      "  -i mode Select user interface (see below for list)\n"
  114. #ifdef AU_LINUX
  115.      "  -B n    Set number of buffer fragments\n"
  116. #endif
  117.      "  -h      Display this help message\n"
  118.      "\n"
  119.      , program_name);
  120.  
  121.   printf("Available output modes (-O option):\n\n");
  122.   while (*pmp)
  123.      {
  124.         printf("  -O%c     %s\n", (*pmp)->id_character, (*pmp)->id_name);
  125.         pmp++;
  126.      }
  127.   printf("\nOutput format options (append to -O? option):\n\n"
  128.      "   `8'    8-bit sample width\n"
  129.      "   `1'    16-bit sample width\n"
  130.      "   `U'    uLaw encoding\n"
  131.      "   `l'    linear encoding\n"
  132.      "   `M'    monophonic\n"
  133.      "   `S'    stereo\n"
  134.      "   `s'    signed output\n"
  135.      "   `u'    unsigned output\n"
  136.      "   `x'    byte-swapped output\n");
  137.  
  138.   printf("\nAvailable interfaces (-i option):\n\n");
  139.   while (*cmp)
  140.      {
  141.         printf("  -i%c     %s\n", (*cmp)->id_character, (*cmp)->id_name);
  142.         cmp++;
  143.      }
  144.   printf("\nInterface options (append to -i? option):\n\n"
  145.      "   `v'    more verbose (cumulative)\n"
  146.      "   `q'    quieter (cumulative)\n"
  147.      "   `t'    trace playing\n\n");
  148. }
  149.  
  150. static void interesting_message(void)
  151. {
  152.   printf(
  153. "\n"
  154. " TiMidity version " TIMID_VERSION " -- Experimental MIDI to WAVE converter\n"
  155. " Copyright (C) 1995 Tuukka Toivonen <titoivon@snakemail.hut.fi>\n"
  156. "\n"
  157. #ifdef __WIN32__
  158. " Win32 version by Davide Moretti\n"
  159. "\n"
  160. #endif
  161. " This program is free software; you can redistribute it and/or modify\n"
  162. " it under the terms of the GNU General Public License as published by\n"
  163. " the Free Software Foundation; either version 2 of the License, or\n"
  164. " (at your option) any later version.\n"
  165. "\n"
  166. " This program is distributed in the hope that it will be useful,\n"
  167. " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  168. " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  169. " GNU General Public License for more details.\n"
  170. "\n"
  171. " You should have received a copy of the GNU General Public License\n"
  172. " along with this program; if not, write to the Free Software\n"
  173. " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
  174. "\n"
  175. );
  176.  
  177. }
  178.  
  179. static int set_channel_flag(int32 *flags, int32 i, char *name)
  180. {
  181.   if (i==0) *flags=0;
  182.   else if ((i<1 || i>16) && (i<-16 || i>-1))
  183.     {
  184.       fprintf(stderr, 
  185.           "%s must be between 1 and 16, or between -1 and -16, or 0\n", 
  186.           name);
  187.       return -1;
  188.     }
  189.   else
  190.     {
  191.       if (i>0) *flags |= (1<<(i-1));
  192.       else *flags &= ~ ((1<<(-1-i)));
  193.     }
  194.   return 0;
  195. }
  196.  
  197. static int set_value(int32 *param, int32 i, int32 low, int32 high, char *name)
  198. {
  199.   if (i<low || i > high)
  200.     {
  201.       fprintf(stderr, "%s must be between %ld and %ld\n", name, low, high);
  202.       return -1;
  203.     }
  204.   else *param=i;
  205.   return 0;
  206. }
  207.  
  208. static int set_play_mode(char *cp)
  209. {
  210.   PlayMode *pmp, **pmpp=play_mode_list;
  211.  
  212.   while ((pmp=*pmpp++))
  213.     {
  214.       if (pmp->id_character == *cp)
  215.     {
  216.       play_mode=pmp;
  217.       while (*(++cp))
  218.         switch(*cp)
  219.           {
  220.           case 'U': pmp->encoding |= PE_ULAW; break; /* uLaw */
  221.           case 'l': pmp->encoding &= ~PE_ULAW; break; /* linear */
  222.  
  223.           case '1': pmp->encoding |= PE_16BIT; break; /* 1 for 16-bit */
  224.           case '8': pmp->encoding &= ~PE_16BIT; break;
  225.  
  226.           case 'M': pmp->encoding |= PE_MONO; break;
  227.           case 'S': pmp->encoding &= ~PE_MONO; break; /* stereo */
  228.  
  229.           case 's': pmp->encoding |= PE_SIGNED; break;
  230.           case 'u': pmp->encoding &= ~PE_SIGNED; break;
  231.  
  232.           case 'x': pmp->encoding ^= PE_BYTESWAP; break; /* toggle */
  233.  
  234.           default:
  235.         fprintf(stderr, "Unknown format modifier `%c'\n", *cp);
  236.         return 1;
  237.           }
  238.       return 0;
  239.     }
  240.     }
  241.   
  242.   fprintf(stderr, "Playmode `%c' is not compiled in.\n", *cp);
  243.   return 1;
  244. }
  245.  
  246. static int set_ctl(char *cp)
  247. {
  248.   ControlMode *cmp, **cmpp=ctl_list;
  249.  
  250.   while ((cmp=*cmpp++))
  251.     {
  252.       if (cmp->id_character == *cp)
  253.     {
  254.       ctl=cmp;
  255.       while (*(++cp))
  256.         switch(*cp)
  257.           {
  258.           case 'v': cmp->verbosity++; break;
  259.           case 'q': cmp->verbosity--; break;
  260.           case 't': /* toggle */
  261.         cmp->trace_playing= (cmp->trace_playing) ? 0 : 1; 
  262.         break;
  263.  
  264.           default:
  265.         fprintf(stderr, "Unknown interface option `%c'\n", *cp);
  266.         return 1;
  267.           }
  268.       return 0;
  269.     }
  270.     }
  271.   
  272.   fprintf(stderr, "Interface `%c' is not compiled in.\n", *cp);
  273.   return 1;
  274. }
  275.  
  276. #define MAXWORDS 10
  277.  
  278. static int read_config_file(char *name)
  279. {
  280.   FILE *fp;
  281.   char tmp[1024], *w[MAXWORDS], *cp;
  282.   ToneBank *bank=0;
  283.   int i, j, k, line=0, words;
  284.   static int rcf_count=0;
  285.  
  286.   if (rcf_count>50)
  287.     {
  288.       fprintf(stderr, "Probable source loop in configuration files");
  289.       return (-1);
  290.     }
  291.  
  292.   if (!(fp=open_file(name, 1, OF_VERBOSE)))
  293.     return -1;
  294.  
  295.   while (fgets(tmp, sizeof(tmp), fp))
  296.     {
  297.       line++;
  298.       w[words=0]=strtok(tmp, " \t\r\n\240");
  299.       if (!w[0] || (*w[0]=='#')) continue;
  300.       while (w[words] && (words < MAXWORDS))
  301.     w[++words]=strtok(0," \t\r\n\240");
  302.       if (!strcmp(w[0], "dir"))
  303.     {
  304.       if (words < 2)
  305.         {
  306.           fprintf(stderr, "%s: line %d: No directory given\n", name, line);
  307.           return -2;
  308.         }
  309.       for (i=1; i<words; i++)
  310.         add_to_pathlist(w[i]);
  311.     }
  312.       else if (!strcmp(w[0], "source"))
  313.     {
  314.       if (words < 2)
  315.         {
  316.           fprintf(stderr, "%s: line %d: No file name given\n", name, line);
  317.           return -2;
  318.         }
  319.       for (i=1; i<words; i++)
  320.         {
  321.           rcf_count++;
  322.           read_config_file(w[i]);
  323.           rcf_count--;
  324.         }
  325.     }
  326.       else if (!strcmp(w[0], "default"))
  327.     {
  328.       if (words != 2)
  329.         {
  330.           fprintf(stderr, 
  331.               "%s: line %d: Must specify exactly one patch name\n",
  332.               name, line);
  333.           return -2;
  334.         }
  335.       strncpy(def_instr_name, w[1], 255);
  336.       def_instr_name[255]='\0';
  337.     }
  338.       else if (!strcmp(w[0], "drumset"))
  339.     {
  340.       if (words < 2)
  341.         {
  342.           fprintf(stderr, "%s: line %d: No drum set number given\n", 
  343.               name, line);
  344.           return -2;
  345.         }
  346.       i=atoi(w[1]);
  347.       if (i<0 || i>127)
  348.         {
  349.           fprintf(stderr, 
  350.               "%s: line %d: Drum set must be between 0 and 127\n",
  351.               name, line);
  352.           return -2;
  353.         }
  354.       if (!drumset[i])
  355.         {
  356.           drumset[i]=safe_malloc(sizeof(ToneBank));
  357.           memset(drumset[i], 0, sizeof(ToneBank));
  358.         }
  359.       bank=drumset[i];
  360.     }
  361.       else if (!strcmp(w[0], "bank"))
  362.     {
  363.       if (words < 2)
  364.         {
  365.           fprintf(stderr, "%s: line %d: No bank number given\n", 
  366.               name, line);
  367.           return -2;
  368.         }
  369.       i=atoi(w[1]);
  370.       if (i<0 || i>127)
  371.         {
  372.           fprintf(stderr, 
  373.               "%s: line %d: Tone bank must be between 0 and 127\n",
  374.               name, line);
  375.           return -2;
  376.         }
  377.       if (!tonebank[i])
  378.         {
  379.           tonebank[i]=safe_malloc(sizeof(ToneBank));
  380.           memset(tonebank[i], 0, sizeof(ToneBank));
  381.         }
  382.       bank=tonebank[i];
  383.     }
  384.       else {
  385.     if ((words < 2) || (*w[0] < '0' || *w[0] > '9'))
  386.       {
  387.         fprintf(stderr, "%s: line %d: syntax error\n", name, line);
  388.         return -2;
  389.       }
  390.     i=atoi(w[0]);
  391.     if (i<0 || i>127)
  392.       {
  393.         fprintf(stderr, "%s: line %d: Program must be between 0 and 127\n",
  394.             name, line);
  395.         return -2;
  396.       }
  397.     if (!bank)
  398.       {
  399.         fprintf(stderr, 
  400.             "%s: line %d: Must specify tone bank or drum set "
  401.             "before assignment\n",
  402.             name, line);
  403.         return -2;
  404.       }
  405.     if (bank->tone[i].name)
  406.       free(bank->tone[i].name);
  407.     strcpy((bank->tone[i].name=safe_malloc(strlen(w[1])+1)),w[1]);
  408.     bank->tone[i].note=bank->tone[i].amp=bank->tone[i].pan=
  409.       bank->tone[i].strip_loop=bank->tone[i].strip_envelope=
  410.         bank->tone[i].strip_tail=-1;
  411.  
  412.     for (j=2; j<words; j++)
  413.       {
  414.         if (!(cp=strchr(w[j], '=')))
  415.           {
  416.         fprintf(stderr, "%s: line %d: bad patch option %s\n",
  417.             name, line, w[j]);
  418.         return -2;
  419.           }
  420.         *cp++=0;
  421.         if (!strcmp(w[j], "amp"))
  422.           {
  423.         k=atoi(cp);
  424.         if ((k<0 || k>MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9'))
  425.           {
  426.             fprintf(stderr, 
  427.                 "%s: line %d: amplification must be between "
  428.                 "0 and %d\n", name, line, MAX_AMPLIFICATION);
  429.             return -2;
  430.           }
  431.         bank->tone[i].amp=k;
  432.           }
  433.         else if (!strcmp(w[j], "note"))
  434.           {
  435.         k=atoi(cp);
  436.         if ((k<0 || k>127) || (*cp < '0' || *cp > '9'))
  437.           {
  438.             fprintf(stderr, 
  439.                 "%s: line %d: note must be between 0 and 127\n", 
  440.                 name, line);
  441.             return -2;
  442.           }
  443.         bank->tone[i].note=k;
  444.           }
  445.         else if (!strcmp(w[j], "pan"))
  446.           {
  447.         if (!strcmp(cp, "center"))
  448.           k=64;
  449.         else if (!strcmp(cp, "left"))
  450.           k=0;
  451.         else if (!strcmp(cp, "right"))
  452.           k=127;
  453.         else 
  454.           k=((atoi(cp)+100) * 100) / 157;
  455.         if ((k<0 || k>127) || 
  456.             (k==0 && *cp!='-' && (*cp < '0' || *cp > '9')))
  457.           {
  458.             fprintf(stderr, 
  459.                 "%s: line %d: panning must be left, right, "
  460.                 "center, or between -100 and 100\n",
  461.                 name, line);
  462.             return -2;
  463.           }
  464.         bank->tone[i].pan=k;
  465.           }
  466.         else if (!strcmp(w[j], "keep"))
  467.           {
  468.         if (!strcmp(cp, "env"))
  469.           bank->tone[i].strip_envelope=0;
  470.         else if (!strcmp(cp, "loop"))
  471.           bank->tone[i].strip_loop=0;
  472.         else 
  473.           {
  474.             fprintf(stderr, "%s: line %d: keep must be env or loop\n",
  475.                 name, line);
  476.             return -2;
  477.           }
  478.           }
  479.         else if (!strcmp(w[j], "strip"))
  480.           {
  481.         if (!strcmp(cp, "env"))
  482.           bank->tone[i].strip_envelope=1;
  483.         else if (!strcmp(cp, "loop"))
  484.           bank->tone[i].strip_loop=1;
  485.         else if (!strcmp(cp, "tail"))
  486.           bank->tone[i].strip_tail=1;
  487.         else
  488.           {
  489.             fprintf(stderr, "%s: line %d: strip must be env, loop, or tail\n",
  490.                 name, line);
  491.             return -2;
  492.           }
  493.           }
  494.         else
  495.           {
  496.         fprintf(stderr, "%s: line %d: bad patch option %s\n",
  497.             name, line, w[j]);
  498.         return -2;
  499.           }
  500.       }
  501.       }
  502.     }
  503.   if (ferror(fp))
  504.     {
  505.       fprintf(stderr, "Can't read %s: %s\n", name, sys_errlist[errno]);
  506.       close_file(fp);
  507.       return -2;
  508.     }
  509.   close_file(fp);
  510.   return 0;
  511. }
  512.  
  513. static int play_midi_file(char *fn)
  514. {
  515.   MidiEvent *event;
  516.   int32 events, samples;
  517.   int rc;
  518.   FILE *fp;
  519.  
  520.   ctl->cmsg(CMSG_INFO, VERB_VERBOSE, "MIDI file: %s", fn);
  521.  
  522.   if (!strcmp(fn, "-"))
  523.     {
  524.       fp=stdin;
  525.       strcpy(current_filename, "(stdin)");
  526.     }
  527.   else if (!(fp=open_file(fn, 1, OF_VERBOSE)))
  528.     return -1;
  529.  
  530.   ctl->file_name(current_filename);
  531.  
  532.   event=read_midi_file(fp, &events, &samples);
  533.  
  534.   if (fp != stdin)
  535.     close_file(fp);
  536.  
  537.   if (!event)
  538.     return -1;
  539.  
  540.   ctl->cmsg(CMSG_INFO, VERB_NOISY, 
  541.        "%d supported events, %d samples", events, samples);
  542.  
  543.   ctl->total_time(samples);
  544.   ctl->master_volume(amplification);
  545.  
  546.   load_missing_instruments();
  547.   rc=play_midi(event, events, samples);
  548.   if (free_instruments_afterwards)
  549.     free_instruments();
  550.       
  551.   free(event);
  552.   return rc;
  553. }
  554.  
  555. #ifdef __WIN32__
  556. int __cdecl main(int argc, char **argv)
  557. #else
  558. int main(int argc, char **argv)
  559. #endif
  560. {
  561.   int
  562.     c, cmderr=0, i, got_a_configuration=0, try_config_again=0,
  563.     need_stdin=0, need_stdout=0;
  564.  
  565.   int32 
  566.     tmpi32, output_rate=DEFAULT_RATE;
  567.  
  568.   char 
  569.     *output_name=0;
  570.  
  571. #ifdef AU_LINUX
  572.   int buffer_fragments=-1;
  573. #endif
  574.  
  575. #ifdef DANGEROUS_RENICE
  576. #include <sys/resource.h>
  577.   int u_uid=getuid();
  578.   if (setpriority(PRIO_PROCESS, 0, DANGEROUS_RENICE) < 0)
  579.     fprintf(stderr, "Couldn't set priority to %d.\n", DANGEROUS_RENICE);
  580.   setreuid(u_uid, u_uid);
  581. #endif
  582.  
  583.   if ((program_name=rindex(argv[0], PATH_SEP))) program_name++;
  584.   else program_name=argv[0];
  585.   if (argc==1)
  586.     {
  587.       interesting_message();
  588.       return 0;
  589.     }
  590.  
  591.   if (!read_config_file(CONFIG_FILE))
  592.     got_a_configuration=1;
  593.  
  594.   while ((c=getopt(argc, argv, "UI:P:L:c:A:C:ap:fp:o:O:s:Q:FD:hi:"
  595. #ifdef AU_LINUX
  596.            "B:" /* buffer fragments */
  597. #endif
  598.            ))>0)
  599.     switch(c)
  600.       {
  601.       case 'U': free_instruments_afterwards=1; break;
  602.       case 'L': add_to_pathlist(optarg); try_config_again=1; break;
  603.       case 'c':
  604.     if (read_config_file(optarg)) cmderr++;
  605.     else got_a_configuration=1;
  606.     break;
  607.  
  608.       case 'Q':
  609.     if (set_channel_flag(&quietchannels, atoi(optarg), "Quiet channel"))
  610.       cmderr++;
  611.     break;
  612.  
  613.       case 'D':
  614.     if (set_channel_flag(&drumchannels, atoi(optarg), "Drum channel"))
  615.       cmderr++;
  616.     break;
  617.  
  618.       case 'O': /* output mode */
  619.     if (set_play_mode(optarg))
  620.       cmderr++;
  621.     break;
  622.  
  623.       case 'o':    output_name=optarg; break;
  624.  
  625.       case 'a': antialiasing_allowed=1; break;
  626.  
  627.       case 'f': fast_decay=(fast_decay) ? 0 : 1; break;
  628.  
  629.       case 'F': adjust_panning_immediately=0; break;
  630.  
  631.       case 's': /* sampling rate */
  632.     i=atoi(optarg);
  633.     if (i < 100) i *= 1000;
  634.     if (set_value(&output_rate, i, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE,
  635.               "Resampling frequency")) cmderr++;
  636.     break;
  637.  
  638.       case 'P': /* set overriding instrument */
  639.     strncpy(def_instr_name, optarg, 255);
  640.     def_instr_name[255]='\0';
  641.     break;
  642.  
  643.       case 'I':
  644.     if (set_value(&tmpi32, atoi(optarg), 0, 127, 
  645.               "Default program")) cmderr++;
  646.     else default_program=tmpi32;
  647.     break;
  648.       case 'A':
  649.     if (set_value(&lification, atoi(optarg), 1, MAX_AMPLIFICATION, 
  650.               "Amplification")) cmderr++;
  651.     break;
  652.       case 'C':
  653.     if (set_value(&control_ratio, atoi(optarg), 1, MAX_CONTROL_RATIO, 
  654.               "Control ratio")) cmderr++;
  655.     break;
  656.       case 'p':
  657.     if (set_value(&tmpi32, atoi(optarg), 1, MAX_VOICES, 
  658.               "Polyphony")) cmderr++;
  659.     else voices=tmpi32;
  660.     break;
  661.  
  662.       case 'i':
  663.     if (set_ctl(optarg))
  664.       cmderr++;
  665. #ifdef AU_LINUX
  666.     else if (buffer_fragments==-1 && ctl->trace_playing)
  667.       /* user didn't specify anything, so use 2 for real-time response */
  668.       buffer_fragments=2;
  669. #endif
  670.     break;
  671.  
  672. #ifdef AU_LINUX
  673.       case 'B':
  674.     if (set_value(&tmpi32, atoi(optarg), 0, 1000,
  675.               "Buffer fragments")) cmderr++;
  676.     else buffer_fragments=tmpi32;
  677.     break;
  678. #endif
  679.     
  680.       case 'h':
  681.     help();
  682.     return 0;
  683.     
  684.       default:
  685.     cmderr++; break;
  686.       }
  687.  
  688.   if (!got_a_configuration)
  689.     {
  690.       if (!try_config_again || read_config_file(CONFIG_FILE))
  691.     cmderr++;
  692.     }
  693.  
  694.   /* If there were problems, give up now */
  695.   if (cmderr || optind >= argc)
  696.     {
  697.       fprintf(stderr, "Try %s -h for help\n", program_name);
  698.       return 1; /* problems with command line */
  699.     }
  700.  
  701.   /* Set play mode parameters */
  702.   play_mode->rate=output_rate;
  703.   if (output_name)
  704.     {
  705.       play_mode->name=output_name;
  706.       if (!strcmp(output_name, "-"))
  707.     need_stdout=1;
  708.     }
  709. #ifdef AU_LINUX
  710.   if (buffer_fragments != -1)
  711.     play_mode->extra_param[0]=buffer_fragments;
  712. #endif
  713.  
  714.   init_tables();
  715.  
  716.   if (optind<argc)
  717.     {
  718.       int orig_optind=optind;
  719.  
  720.       while (optind<argc)
  721.     if (!strcmp(argv[optind++], "-"))
  722.       need_stdin=1;
  723.       optind=orig_optind;
  724.       
  725.       if (ctl->open(need_stdin, need_stdout))
  726.     {
  727.       fprintf(stderr, "Couldn't open %s\n", ctl->id_name);
  728.       play_mode->close_output();
  729.       return 3;
  730.     }
  731.       /* Open output device */
  732.         if (play_mode->open_output()<0)
  733.     {
  734.       fprintf(stderr, "Couldn't open %s\n", play_mode->id_name);
  735.       ctl->close();
  736.       return 2;
  737.     }
  738.  
  739.         if (!control_ratio)
  740.     {
  741.       control_ratio = play_mode->rate / CONTROLS_PER_SECOND;
  742.       if(control_ratio<1)
  743.          control_ratio=1;
  744.       else if (control_ratio > MAX_CONTROL_RATIO)
  745.          control_ratio=MAX_CONTROL_RATIO;
  746.     }
  747.  
  748.         if (*def_instr_name)
  749.     set_default_instrument(def_instr_name);
  750.  
  751. #ifdef __WIN32__
  752.         SetConsoleCtrlHandler (handler, TRUE);
  753.         InitializeCriticalSection (&critSect);
  754. #endif
  755.         for (;;)
  756.     {
  757.       switch(play_midi_file(argv[optind]))
  758.          {
  759.          case RC_REALLY_PREVIOUS:
  760.             if (optind>orig_optind)
  761.         optind--;
  762.             break;
  763.  
  764.          default: /* An error or something */
  765.          case RC_NEXT:
  766.             if (optind<(argc-1))
  767.         {
  768.           optind++;
  769.           break;
  770.         }
  771.             /* else fall through */
  772.  
  773.          case RC_QUIT:
  774.             play_mode->close_output();
  775.             ctl->close();
  776. #ifdef __WIN32__
  777.             DeleteCriticalSection (&critSect);
  778. #endif
  779.             return 0;
  780.          }
  781.     }
  782.      }
  783.   return 0;
  784. }
  785.