fluidsynth.c
上传用户:tjmskj2
上传日期:2020-08-17
资源大小:577k
文件大小:24k
源码类别:

midi

开发平台:

C/C++

  1. /* FluidSynth - A Software Synthesizer
  2.  *
  3.  * Copyright (C) 2003  Peter Hanappe and others.
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Library General Public License
  7.  * as published by the Free Software Foundation; either version 2 of
  8.  * the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Library General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Library General Public
  16.  * License along with this library; if not, write to the Free
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18.  * 02111-1307, USA
  19.  */
  20. #if HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include "fluidsynth_priv.h"
  27. #if !defined(WIN32) && !defined(MACINTOSH)
  28. #define _GNU_SOURCE
  29. #include <getopt.h>
  30. #endif
  31. #include "fluidsynth.h"
  32. #if defined(WIN32) && !defined(MINGW32)
  33. #include "config_win32.h"
  34. #endif
  35. #ifdef HAVE_SIGNAL_H
  36. #include "signal.h"
  37. #endif
  38. #include "fluid_lash.h"
  39. #ifndef WITH_MIDI
  40. #define WITH_MIDI 1
  41. #endif
  42. void print_usage(void);
  43. void print_help(fluid_settings_t *settings);
  44. void print_welcome(void);
  45. static fluid_cmd_handler_t* newclient(void* data, char* addr);
  46. /*
  47.  * the globals
  48.  */
  49. fluid_cmd_handler_t* cmd_handler = NULL;
  50. int option_help = 0; /* set to 1 if "-o help" is specified */
  51. /*
  52.  * support for the getopt function
  53.  */
  54. #if !defined(WIN32) && !defined(MACINTOSH)
  55. #define GETOPT_SUPPORT 1
  56. int getopt(int argc, char * const argv[], const char *optstring);
  57. extern char *optarg;
  58. extern int optind, opterr, optopt;
  59. #endif
  60. /* Process a command line option -o setting=value, for example: -o synth.polyhony=16 */
  61. void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg)
  62. {
  63.   char* val;
  64.   int hints;
  65.   int ival;
  66.   for (val = optarg; *val != ''; val++) {
  67.     if (*val == '=') {
  68.       *val++ = 0;
  69.       break;
  70.     }
  71.   }
  72.   /* did user request list of settings */
  73.   if (strcmp (optarg, "help") == 0)
  74.   {
  75.     option_help = 1;
  76.     return;
  77.   }
  78.   switch(fluid_settings_get_type(settings, optarg)){
  79.   case FLUID_NUM_TYPE:
  80.     if (!fluid_settings_setnum (settings, optarg, atof (val)))
  81.     {
  82.       fprintf (stderr, "Failed to set floating point parameter '%s'n", optarg);
  83.       exit (1);
  84.     }
  85.     break;
  86.   case FLUID_INT_TYPE:
  87.     hints = fluid_settings_get_hints (settings, optarg);
  88.     if (hints & FLUID_HINT_TOGGLED)
  89.     {
  90.       if (FLUID_STRCMP (val, "yes") == 0 || FLUID_STRCMP (val, "True") == 0
  91.           || FLUID_STRCMP (val, "TRUE") == 0 || FLUID_STRCMP (val, "true") == 0
  92.           || FLUID_STRCMP (val, "T") == 0)
  93.         ival = 1;
  94.       else ival = atoi (val);
  95.     }
  96.     else ival = atoi (val);
  97.     if (!fluid_settings_setint (settings, optarg, ival))
  98.     {
  99.       fprintf (stderr, "Failed to set integer parameter '%s'n", optarg);
  100.       exit (1);
  101.     }
  102.     break;
  103.   case FLUID_STR_TYPE:
  104.     if (!fluid_settings_setstr (settings, optarg, val))
  105.     {
  106.       fprintf (stderr, "Failed to set string parameter '%s'n", optarg);
  107.       exit (1);
  108.     }
  109.     break;
  110.   default:
  111.     fprintf (stderr, "Setting parameter '%s' not foundn", optarg);
  112.     exit (1);
  113.   }
  114. }
  115. static void
  116. print_pretty_int (int i)
  117. {
  118.   if (i == INT_MAX) printf ("MAXINT");
  119.   else if (i == INT_MIN) printf ("MININT");
  120.   else printf ("%d", i);
  121. }
  122. typedef struct
  123. {
  124.   int count;            /* Total count of options */
  125.   int curindex;         /* Current index in options */
  126. } OptionBag;
  127. /* Function to display each string option value */
  128. static void
  129. settings_option_foreach_func (void *data, char *name, char *option)
  130. {
  131.   OptionBag *bag = data;
  132.   bag->curindex++;
  133.   if (bag->curindex < bag->count)
  134.     printf ("'%s',", option);
  135.   else printf ("'%s'", option);
  136. }
  137. /* fluid_settings_foreach function for displaying option help  "-o help" */
  138. static void
  139. settings_foreach_func (void *data, char *name, int type)
  140. {
  141.   fluid_settings_t *settings = (fluid_settings_t *)data;
  142.   double dmin, dmax, ddef;
  143.   int imin, imax, idef, hints;
  144.   char *defstr;
  145.   int count;
  146.   OptionBag bag;
  147.   switch (type)
  148.   {
  149.   case FLUID_NUM_TYPE:
  150.     fluid_settings_getnum_range (settings, name, &dmin, &dmax);
  151.     ddef = fluid_settings_getnum_default (settings, name);
  152.     printf ("%-24s FLOAT [min=%0.3f, max=%0.3f, def=%0.3f]n",
  153.     name, dmin, dmax, ddef);
  154.     break;
  155.   case FLUID_INT_TYPE:
  156.     fluid_settings_getint_range (settings, name, &imin, &imax);
  157.     idef = fluid_settings_getint_default (settings, name);
  158.     hints = fluid_settings_get_hints (settings, name);
  159.     if (!(hints & FLUID_HINT_TOGGLED))
  160.     {
  161.       printf ("%-24s INT   [min=", name);
  162.       print_pretty_int (imin);
  163.       printf (", max=");
  164.       print_pretty_int (imax);
  165.       printf (", def=");
  166.       print_pretty_int (idef);
  167.       printf ("]n");
  168.     }
  169.     else printf ("%-24s BOOL  [def=%s]n", name, idef ? "True" : "False");
  170.     break;
  171.   case FLUID_STR_TYPE:
  172.     printf ("%-24s STR", name);
  173.     defstr = fluid_settings_getstr_default (settings, name);
  174.     count = fluid_settings_option_count (settings, name);
  175.     if (defstr || count > 0)
  176.     {
  177.       if (defstr && count > 0) printf ("   [def='%s' vals:", defstr);
  178.       else if (defstr) printf ("   [def='%s'", defstr);
  179.       else printf ("   [vals:");
  180.       if (count > 0)
  181.       {
  182.         bag.count = count;
  183.         bag.curindex = 0;
  184.         fluid_settings_foreach_option (settings, name, &bag,
  185.                                        settings_option_foreach_func);
  186.       }
  187.       printf ("]n");
  188.     }
  189.     else printf ("n");
  190.     break;
  191.   case FLUID_SET_TYPE:
  192.     printf ("%-24s SETn", name);
  193.     break;
  194.   }
  195. }
  196. /* Output options for a setting string to stdout */
  197. static void
  198. show_settings_str_options (fluid_settings_t *settings, char *name)
  199. {
  200.   OptionBag bag;
  201.   bag.count = fluid_settings_option_count (settings, name);
  202.   bag.curindex = 0;
  203.   fluid_settings_foreach_option (settings, name, &bag,
  204.                                  settings_option_foreach_func);
  205.   printf ("n");
  206. }
  207. static void
  208. fast_render_loop(fluid_settings_t* settings, fluid_synth_t* synth, fluid_player_t* player)
  209. {
  210.   fluid_file_renderer_t* renderer;
  211.   renderer = new_fluid_file_renderer (synth);
  212.   if (!renderer) return;
  213.   while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) {
  214.     if (fluid_file_renderer_process_block(renderer) != FLUID_OK) {
  215.       break;
  216.     }
  217.   }
  218.   delete_fluid_file_renderer(renderer);
  219. }
  220. #ifdef HAVE_SIGNAL_H
  221. /*
  222.  * handle_signal
  223.  */
  224. void handle_signal(int sig_num)
  225. {
  226. }
  227. #endif
  228. /*
  229.  * main
  230.  */
  231. int main(int argc, char** argv)
  232. {
  233.   fluid_settings_t* settings;
  234.   int arg1 = 1;
  235.   char buf[512];
  236.   int c, i;
  237.   int interactive = 1;
  238.   int midi_in = 1;
  239.   fluid_player_t* player = NULL;
  240.   fluid_midi_router_t* router = NULL;
  241.   //fluid_sequencer_t* sequencer = NULL;
  242.   fluid_midi_driver_t* mdriver = NULL;
  243.   fluid_audio_driver_t* adriver = NULL;
  244.   fluid_synth_t* synth = NULL;
  245.   fluid_server_t* server = NULL;
  246.   char* config_file = NULL;
  247.   int audio_groups = 0;
  248.   int audio_channels = 0;
  249.   int with_server = 0;
  250.   int dump = 0;
  251.   int fast_render = 0;
  252.   int connect_lash = 1;
  253.   char *optchars = "a:C:c:dE:f:F:G:g:hijK:L:lm:nO:o:p:R:r:sT:Vvz:";
  254. #ifdef LASH_ENABLED
  255.   int enabled_lash = 0; /* set to TRUE if lash gets enabled */
  256.   fluid_lash_args_t *lash_args;
  257.   lash_args = fluid_lash_extract_args (&argc, &argv);
  258. #endif
  259.   print_welcome ();
  260.   settings = new_fluid_settings();
  261. #ifdef GETOPT_SUPPORT /* pre section of GETOPT supported argument handling */
  262.   opterr = 0;
  263.   while (1) {
  264.     int option_index = 0;
  265.     static struct option long_options[] = {
  266.       {"audio-bufcount", 1, 0, 'c'},
  267.       {"audio-bufsize", 1, 0, 'z'},
  268.       {"audio-channels", 1, 0, 'L'},
  269.       {"audio-driver", 1, 0, 'a'},
  270.       {"audio-file-endian", 1, 0, 'E'},
  271.       {"audio-file-format", 1, 0, 'O'},
  272.       {"audio-file-type", 1, 0, 'T'},
  273.       {"audio-groups", 1, 0, 'G'},
  274.       {"chorus", 1, 0, 'C'},
  275.       {"connect-jack-outputs", 0, 0, 'j'},
  276.       {"disable-lash", 0, 0, 'l'},
  277.       {"dump", 0, 0, 'd'},
  278.       {"fast-render", 1, 0, 'F'},
  279.       {"gain", 1, 0, 'g'},
  280.       {"help", 0, 0, 'h'},
  281.       {"load-config", 1, 0, 'f'},
  282.       {"midi-channels", 1, 0, 'K'},
  283.       {"midi-driver", 1, 0, 'm'},
  284.       {"no-midi-in", 0, 0, 'n'},
  285.       {"no-shell", 0, 0, 'i'},
  286.       {"option", 1, 0, 'o'},
  287.       {"portname", 1, 0, 'p'},
  288.       {"reverb", 1, 0, 'R'},
  289.       {"sample-rate", 1, 0, 'r'},
  290.       {"server", 0, 0, 's'},
  291.       {"verbose", 0, 0, 'v'},
  292.       {"version", 0, 0, 'V'},
  293.       {0, 0, 0, 0}
  294.     };
  295.     c = getopt_long(argc, argv, optchars, long_options, &option_index);
  296.     if (c == -1) {
  297.       break;
  298.     }
  299. #else /* "pre" section to non getopt argument handling */
  300.   for (i = 1; i < argc; i++) {
  301.     char *optarg;
  302.     /* Skip non switch arguments (assume they are file names) */
  303.     if ((argv[i][0] != '-') || (argv[i][1] == '')) break;
  304.     c = argv[i][1];
  305.     optarg = strchr (optchars, c); /* find the option character in optchars */
  306.     if (optarg && optarg[1] == ':') /* colon follows if switch argument expected */
  307.     {
  308.       if (++i >= argc)
  309.       {
  310. printf ("Option -%c requires an argumentn", c);
  311. print_usage();
  312. exit(0);
  313.       }
  314.       else
  315.       {
  316. optarg = argv[i];
  317. if (optarg[0] == '-')
  318. {
  319.   printf ("Expected argument to option -%c found switch insteadn", c);
  320.   print_usage();
  321.   exit(0);
  322. }
  323.       }
  324.     }
  325.     else optarg = "";
  326. #endif
  327.     switch (c) {
  328. #ifdef GETOPT_SUPPORT
  329.     case 0: /* shouldn't normally happen, a long option's flag is set to NULL */
  330.       printf ("option %s", long_options[option_index].name);
  331.       if (optarg) {
  332. printf (" with arg %s", optarg);
  333.       }
  334.       printf ("n");
  335.       break;
  336. #endif
  337.     case 'a':
  338.       if (FLUID_STRCMP (optarg, "help") == 0)
  339.       {
  340.         printf ("-a options (audio driver):n   ");
  341.         show_settings_str_options (settings, "audio.driver");
  342.         exit (0);
  343.       }
  344.       else fluid_settings_setstr(settings, "audio.driver", optarg);
  345.       break;
  346.     case 'C':
  347.       if ((optarg != NULL) && ((strcmp(optarg, "0") == 0) || (strcmp(optarg, "no") == 0))) {
  348. fluid_settings_setint(settings, "synth.chorus.active", FALSE);
  349.       } else {
  350. fluid_settings_setint(settings, "synth.chorus.active", TRUE);
  351.       }
  352.       break;
  353.     case 'c':
  354.       fluid_settings_setint(settings, "audio.periods", atoi(optarg));
  355.       break;
  356.     case 'd':
  357.       fluid_settings_setint(settings, "synth.dump", TRUE);
  358.       dump = 1;
  359.       break;
  360.     case 'E':
  361.       if (FLUID_STRCMP (optarg, "help") == 0)
  362.       {
  363.         printf ("-E options (audio file byte order):n   ");
  364.         show_settings_str_options (settings, "audio.file.endian");
  365. #if LIBSNDFILE_SUPPORT
  366.         printf ("nauto: Use audio file format's default endian byte ordern"
  367.                 "cpu: Use CPU native byte ordern");
  368. #else
  369.         printf ("nNOTE: No libsndfile support!n"
  370.                 "cpu: Use CPU native byte ordern");
  371. #endif
  372.         exit (0);
  373.       }
  374.       else fluid_settings_setstr(settings, "audio.file.endian", optarg);
  375.       break;
  376.     case 'f':
  377.       config_file = optarg;
  378.       break;
  379.     case 'F':
  380.       fluid_settings_setstr(settings, "audio.file.name", optarg);
  381.       fast_render = 1;
  382.       break;
  383.     case 'G':
  384.       audio_groups = atoi(optarg);
  385.       break;
  386.     case 'g':
  387.       fluid_settings_setnum(settings, "synth.gain", atof(optarg));
  388.       break;
  389.     case 'h':
  390.       print_help(settings);
  391.       break;
  392.     case 'i':
  393.       interactive = 0;
  394.       break;
  395.     case 'j':
  396.       fluid_settings_setint(settings, "audio.jack.autoconnect", 1);
  397.       break;
  398.     case 'K':
  399.       fluid_settings_setint(settings, "synth.midi-channels", atoi(optarg));
  400.       break;
  401.     case 'L':
  402.       audio_channels = atoi(optarg);
  403.       fluid_settings_setint(settings, "synth.audio-channels", audio_channels);
  404.       break;
  405.     case 'l': /* disable LASH */
  406.       connect_lash = 0;
  407.       break;
  408.     case 'm':
  409.       if (FLUID_STRCMP (optarg, "help") == 0)
  410.       {
  411.         printf ("-m options (MIDI driver):n   ");
  412.         show_settings_str_options (settings, "midi.driver");
  413.         exit (0);
  414.       }
  415.       else fluid_settings_setstr(settings, "midi.driver", optarg);
  416.       break;
  417.     case 'n':
  418.       midi_in = 0;
  419.       break;
  420.     case 'O':
  421.       if (FLUID_STRCMP (optarg, "help") == 0)
  422.       {
  423.         printf ("-O options (audio file format):n   ");
  424.         show_settings_str_options (settings, "audio.file.format");
  425. #if LIBSNDFILE_SUPPORT
  426.         printf ("ns8, s16, s24, s32: Signed PCM audio of the given number of bitsn");
  427.         printf ("float, double: 32 bit and 64 bit floating point audion");
  428.         printf ("u8: Unsigned 8 bit audion");
  429. #else
  430.         printf ("nNOTE: No libsndfile support!n");
  431. #endif
  432.         exit (0);
  433.       }
  434.       else fluid_settings_setstr(settings, "audio.file.format", optarg);
  435.       break;
  436.     case 'o':
  437.       process_o_cmd_line_option(settings, optarg);
  438.       break;
  439.     case 'p' :
  440.       fluid_settings_setstr(settings, "midi.portname", optarg);
  441.       break;
  442.     case 'R':
  443.       if ((optarg != NULL) && ((strcmp(optarg, "0") == 0) || (strcmp(optarg, "no") == 0))) {
  444. fluid_settings_setint(settings, "synth.reverb.active", FALSE);
  445.       } else {
  446. fluid_settings_setint(settings, "synth.reverb.active", TRUE);
  447.       }
  448.       break;
  449.     case 'r':
  450.       fluid_settings_setnum(settings, "synth.sample-rate", atof(optarg));
  451.       break;
  452.     case 's':
  453.       with_server = 1;
  454.       break;
  455.     case 'T':
  456.       if (FLUID_STRCMP (optarg, "help") == 0)
  457.       {
  458.         printf ("-T options (audio file type):n   ");
  459.         show_settings_str_options (settings, "audio.file.type");
  460. #if LIBSNDFILE_SUPPORT
  461.         printf ("nauto: Determine type from file name extension, defaults to "wav"n");
  462. #else
  463.         printf ("nNOTE: No libsndfile support!n");
  464. #endif
  465.         exit (0);
  466.       }
  467.       else fluid_settings_setstr(settings, "audio.file.type", optarg);
  468.       break;
  469.     case 'V':
  470.       printf("FluidSynth %sn", VERSION);
  471.       exit (0);
  472.       break;
  473.     case 'v':
  474.       fluid_settings_setint(settings, "synth.verbose", TRUE);
  475.       break;
  476.     case 'z':
  477.       fluid_settings_setint(settings, "audio.period-size", atoi(optarg));
  478.       break;
  479. #ifdef GETOPT_SUPPORT
  480.     case '?':
  481.       printf ("Unknown option %cn", optopt);
  482.       print_usage();
  483.       exit(0);
  484.       break;
  485.     default:
  486.       printf ("?? getopt returned character code 0%o ??n", c);
  487.       break;
  488. #else /* Non getopt default case */
  489.     default:
  490.       printf ("Unknown switch '%c'n", c);
  491.       print_usage();
  492.       exit(0);
  493.       break;
  494. #endif
  495.     } /* end of switch statement */
  496.   } /* end of loop */
  497. #ifdef GETOPT_SUPPORT
  498.   arg1 = optind;
  499. #else
  500.   arg1 = i;
  501. #endif
  502.   /* option help requested?  "-o help" */
  503.   if (option_help)
  504.   {
  505.     printf ("FluidSynth settings:n");
  506.     fluid_settings_foreach (settings, settings, settings_foreach_func);
  507.     exit (0);
  508.   }
  509. #ifdef WIN32
  510.   SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
  511. #endif
  512. #ifdef LASH_ENABLED
  513.   /* connect to the lash server */
  514.   if (connect_lash)
  515.     {
  516.       enabled_lash = fluid_lash_connect (lash_args);
  517.       fluid_settings_setint (settings, "lash.enable", enabled_lash ? 1 : 0);
  518.     }
  519. #endif
  520.   /* The 'groups' setting is only relevant for LADSPA operation
  521.    * If not given, set number groups to number of audio channels, because
  522.    * they are the same (there is nothing between synth output and 'sound card')
  523.    */
  524.   if ((audio_groups == 0) && (audio_channels != 0)) {
  525.       audio_groups = audio_channels;
  526.   }
  527.   fluid_settings_setint(settings, "synth.audio-groups", audio_groups);
  528.   /* create the synthesizer */
  529.   synth = new_fluid_synth(settings);
  530.   if (synth == NULL) {
  531.     fprintf(stderr, "Failed to create the synthesizern");
  532.     exit(-1);
  533.   }
  534.   cmd_handler = new_fluid_cmd_handler(synth);
  535.   if (cmd_handler == NULL) {
  536.     fprintf(stderr, "Failed to create the command handlern");
  537.     goto cleanup;
  538.   }
  539.   /* load the soundfonts (check that all non options are SoundFont or MIDI files) */
  540.   for (i = arg1; i < argc; i++) {
  541.     if (fluid_is_soundfont(argv[i]))
  542.     {
  543.       if (fluid_synth_sfload(synth, argv[i], 1) == -1)
  544. fprintf(stderr, "Failed to load the SoundFont %sn", argv[i]);
  545.     }
  546.     else if (!fluid_is_midifile(argv[i]))
  547.       fprintf (stderr, "Parameter '%s' not a SoundFont or MIDI file or error occurred identifying it.n",
  548.        argv[i]);
  549.   }
  550. #ifdef HAVE_SIGNAL_H
  551. /*   signal(SIGINT, handle_signal); */
  552. #endif
  553.   if (fast_render) {
  554.     midi_in = 0;
  555.     interactive = 0;
  556.     with_server = 0;
  557.     fluid_settings_setstr(settings, "player.timing-source", "sample");    
  558.   }
  559.   /* start the synthesis thread */
  560.   if (!fast_render) {
  561.     adriver = new_fluid_audio_driver(settings, synth);
  562.     if (adriver == NULL) {
  563.       fprintf(stderr, "Failed to create the audio drivern");
  564.       goto cleanup;
  565.     }
  566.   }
  567.   /* start the midi router and link it to the synth */
  568. #if WITH_MIDI
  569.   if (midi_in) {
  570.     /* In dump mode, text output is generated for events going into and out of the router.
  571.      * The example dump functions are put into the chain before and after the router..
  572.      */
  573.     //sequencer = new_fluid_sequencer2(0);
  574.     router = new_fluid_midi_router(
  575.       settings,
  576.       dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event,
  577.       (void*)synth);
  578.     if (router == NULL) {
  579.       fprintf(stderr, "Failed to create the MIDI input router; no MIDI inputn"
  580.       "will be available. You can access the synthesizer n"
  581.       "through the console.n");
  582.     } else {
  583.       fluid_synth_set_midi_router(synth, router); /* Fixme, needed for command handler */
  584. //      fluid_sequencer_register_fluidsynth(sequencer, synth);
  585.       mdriver = new_fluid_midi_driver(
  586. settings,
  587. dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event,
  588. (void*) router);
  589.       if (mdriver == NULL) {
  590. fprintf(stderr, "Failed to create the MIDI thread; no MIDI inputn"
  591. "will be available. You can access the synthesizer n"
  592. "through the console.n");
  593.       }
  594.     }
  595.   }
  596. #endif
  597.   /* run commands specified in config file */
  598.   if (config_file != NULL) {
  599.     fluid_source(cmd_handler, config_file);
  600.   } else if (fluid_get_userconf(buf, 512) != NULL) {
  601.     fluid_source(cmd_handler, buf);
  602.   } else if (fluid_get_sysconf(buf, 512) != NULL) {
  603.     fluid_source(cmd_handler, buf);
  604.   }
  605.   /* play the midi files, if any */
  606.   for (i = arg1; i < argc; i++) {
  607.     if ((argv[i][0] != '-') && fluid_is_midifile(argv[i])) {
  608.       if (player == NULL) {
  609. player = new_fluid_player(synth);
  610. if (player == NULL) {
  611.   fprintf(stderr, "Failed to create the midifile player.n"
  612.   "Continuing without a player.n");
  613.   break;
  614. }
  615.       }
  616.       fluid_player_add(player, argv[i]);
  617.     }
  618.   }
  619.   if (player != NULL) {
  620.     fluid_player_play(player);
  621.   }
  622.   /* run the server, if requested */
  623. #if !defined(MACINTOSH)
  624.   if (with_server) {
  625.     server = new_fluid_server(settings, newclient, synth);
  626.     if (server == NULL) {
  627.       fprintf(stderr, "Failed to create the server.n"
  628.      "Continuing without it.n");
  629.     }
  630.   }
  631. #endif
  632. #ifdef LASH_ENABLED
  633.   if (enabled_lash)
  634.     fluid_lash_create_thread (synth);
  635. #endif
  636.   /* run the shell */
  637.   if (interactive) {
  638.     printf ("Type 'help' for help topics.nn");
  639.     /* In dump mode we set the prompt to "". The UI cannot easily
  640.      * handle lines, which don't end with CR.  Changing the prompt
  641.      * cannot be done through a command, because the current shell
  642.      * does not handle empty arguments.  The ordinary case is dump ==
  643.      * 0.
  644.      */
  645.     fluid_settings_setstr(settings, "shell.prompt", dump ? "" : "> ");
  646.     fluid_usershell(settings, cmd_handler);
  647.   }
  648.   if (fast_render) {
  649.     char *filename;
  650.     fluid_settings_dupstr (settings, "audio.file.name", &filename);
  651.     printf ("Rendering audio to file '%s'..n", filename);
  652.     if (filename) FLUID_FREE (filename);
  653.     fast_render_loop(settings, synth, player);
  654.   }
  655.  cleanup:
  656. #if !defined(MACINTOSH) && !defined(WIN32)
  657.   if (server != NULL) {
  658.     /* if the user typed 'quit' in the shell, kill the server */
  659.     if (!interactive) {
  660.       fluid_server_join(server);
  661.     }
  662.     delete_fluid_server(server);
  663.   }
  664. #endif
  665.   if (cmd_handler != NULL) {
  666.     delete_fluid_cmd_handler(cmd_handler);
  667.   }
  668.   if (player != NULL) {
  669.     /* if the user typed 'quit' in the shell, stop the player */
  670.     if (interactive) {
  671.       fluid_player_stop(player);
  672.     }
  673.     if (adriver != NULL || !fluid_settings_str_equal(settings,  "player.timing-source", "sample")) {
  674.       /* if no audio driver and sample timers are used, nothing makes the player advance */  
  675.       fluid_player_join(player);
  676.     }
  677.     delete_fluid_player(player);
  678.   }
  679.   if (router) {
  680. #if WITH_MIDI
  681.     if (mdriver) {
  682.       delete_fluid_midi_driver(mdriver);
  683.     }
  684.     delete_fluid_midi_router(router);
  685. #endif
  686.   }
  687.   /*if (sequencer) {
  688.     delete_fluid_sequencer(sequencer);
  689.   }*/
  690.   if (adriver) {
  691.     delete_fluid_audio_driver(adriver);
  692.   }
  693.   if (synth) {
  694.     delete_fluid_synth(synth);
  695.   }
  696.   if (settings) {
  697.     delete_fluid_settings(settings);
  698.   }
  699.   return 0;
  700. }
  701. static fluid_cmd_handler_t* newclient(void* data, char* addr)
  702. {
  703.   fluid_synth_t* synth = (fluid_synth_t*) data;
  704.   return new_fluid_cmd_handler(synth);
  705. }
  706. /*
  707.  * print_usage
  708.  */
  709. void
  710. print_usage()
  711. {
  712.   fprintf(stderr, "Usage: fluidsynth [options] [soundfonts]n");
  713.   fprintf(stderr, "Try -h for help.n");
  714.   exit(0);
  715. }
  716. void
  717. print_welcome()
  718. {
  719.   printf("FluidSynth version %sn"
  720.  "Copyright (C) 2000-2009 Peter Hanappe and others.n"
  721.  "Distributed under the LGPL license.n"
  722.  "SoundFont(R) is a registered trademark of E-mu Systems, Inc.nn",
  723.  FLUIDSYNTH_VERSION);
  724. }
  725. /*
  726.  * print_help
  727.  */
  728. void
  729. print_help (fluid_settings_t *settings)
  730. {
  731.   char *audio_options;
  732.   char *midi_options;
  733.   audio_options = fluid_settings_option_concat (settings, "audio.driver", NULL);
  734.   midi_options = fluid_settings_option_concat (settings, "midi.driver", NULL);
  735.   printf("Usage: n");
  736.   printf("  fluidsynth [options] [soundfonts] [midifiles]n");
  737.   printf("Possible options:n");
  738.   printf(" -a, --audio-driver=[label]n"
  739.  "    The name of the audio driver to use.n"
  740.  "    Valid values: %sn", audio_options ? audio_options : "ERROR");
  741.   printf(" -c, --audio-bufcount=[count]n"
  742.  "    Number of audio buffersn");
  743.   printf(" -C, --chorusn"
  744.  "    Turn the chorus on or off [0|1|yes|no, default = on]n");
  745.   printf(" -d, --dumpn"
  746.  "    Dump incoming and outgoing MIDI events to stdoutn");
  747.   printf(" -E, --audio-file-endiann"
  748.  "    Audio file endian for fast rendering or aufile driver ("help" for list)n");
  749.   printf(" -f, --load-confign"
  750.  "    Load command configuration file (shell commands)n");
  751.   printf(" -F, --fast-render=[file]n"
  752.  "    Render MIDI file to raw audio data and store in [file]n");
  753.   printf(" -g, --gainn"
  754.  "    Set the master gain [0 < gain < 10, default = 0.2]n");
  755.   printf(" -G, --audio-groupsn"
  756.  "    Defines the number of LADSPA audio nodesn");
  757.   printf(" -h, --helpn"
  758.  "    Print out this help summaryn");
  759.   printf(" -i, --no-shelln"
  760.  "    Don't read commands from the shell [default = yes]n");
  761.   printf(" -j, --connect-jack-outputsn"
  762.  "    Attempt to connect the jack outputs to the physical portsn");
  763.   printf(" -K, --midi-channels=[num]n"
  764.  "    The number of midi channels [default = 16]n");
  765. #ifdef LASH_ENABLED
  766.   printf(" -l, --disable-lashn"
  767.  "    Don't connect to LASH servern");
  768. #endif
  769.   printf(" -L, --audio-channels=[num]n"
  770.  "    The number of stereo audio channels [default = 1]n");
  771.   printf(" -m, --midi-driver=[label]n"
  772.  "    The name of the midi driver to use.n"
  773.  "    Valid values: %sn", midi_options ? midi_options : "ERROR");
  774.   printf(" -n, --no-midi-inn"
  775.  "    Don't create a midi driver to read MIDI input events [default = yes]n");
  776.   printf(" -on"
  777.  "    Define a setting, -o name=value ("-o help" to dump current values)n");
  778.   printf(" -O, --audio-file-formatn"
  779.  "    Audio file format for fast rendering or aufile driver ("help" for list)n");
  780.   printf(" -p, --portname=[label]n"
  781.  "    Set MIDI port name (alsa_seq, coremidi drivers)n");
  782.   printf(" -r, --sample-raten"
  783.  "    Set the sample raten");
  784.   printf(" -R, --reverbn"
  785.  "    Turn the reverb on or off [0|1|yes|no, default = on]n");
  786.   printf(" -s, --servern"
  787.  "    Start FluidSynth as a server processn");
  788.   printf(" -T, --audio-file-typen"
  789.  "    Audio file type for fast rendering or aufile driver ("help" for list)n");
  790.   printf(" -v, --verbosen"
  791.  "    Print out verbose messages about midi eventsn");
  792.   printf(" -V, --versionn"
  793.  "    Show version of programn");
  794.   printf(" -z, --audio-bufsize=[size]n"
  795.  "    Size of each audio buffern");
  796.   if (audio_options) FLUID_FREE (audio_options);
  797.   if (midi_options) FLUID_FREE (midi_options);
  798.   delete_fluid_settings (settings);
  799.   exit(0);
  800. }