Merge pull request #739 from FluidSynth/parse-cmd3

Handle settings-related commands in user command file early
This commit is contained in:
Tom M 2021-01-10 12:08:19 +01:00 committed by GitHub
commit ca6bcda7d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 140 additions and 58 deletions

View file

@ -62,6 +62,9 @@ FLUIDSYNTH_API char *fluid_get_sysconf(char *buf, int len);
FLUIDSYNTH_API
fluid_cmd_handler_t *new_fluid_cmd_handler(fluid_synth_t *synth, fluid_midi_router_t *router);
FLUIDSYNTH_API
fluid_cmd_handler_t *new_fluid_cmd_handler2(fluid_settings_t *settings, fluid_synth_t *synth, fluid_midi_router_t *router);
FLUIDSYNTH_API
void delete_fluid_cmd_handler(fluid_cmd_handler_t *handler);
/** @endlifecycle */

View file

@ -37,6 +37,7 @@
/* the shell cmd handler struct */
struct _fluid_cmd_handler_t
{
fluid_settings_t *settings;
fluid_synth_t *synth;
fluid_midi_router_t *router;
fluid_cmd_hash_t *commands;
@ -539,7 +540,10 @@ fluid_shell_run(void *data)
if(n == 0)
{
FLUID_LOG(FLUID_INFO, "Received EOF while reading commands, exiting the shell.");
if(shell->settings)
{
FLUID_LOG(FLUID_INFO, "Received EOF while reading commands, exiting the shell.");
}
break;
}
}
@ -1209,20 +1213,20 @@ fluid_handle_reverb_command(void *data, int ac, char **av, fluid_ostream_t out,
FLUID_ENTRY_COMMAND(data);
fluid_real_t value;
fluid_settings_getnum_range(handler->synth->settings, "synth.reverb.room-size",
fluid_settings_getnum_range(handler->settings, "synth.reverb.room-size",
&values[FLUID_REVERB_ROOMSIZE].min,
&values[FLUID_REVERB_ROOMSIZE].max);
fluid_settings_getnum_range(handler->synth->settings, "synth.reverb.damp",
fluid_settings_getnum_range(handler->settings, "synth.reverb.damp",
&values[FLUID_REVERB_DAMP].min,
&values[FLUID_REVERB_DAMP].max);
fluid_settings_getnum_range(handler->synth->settings, "synth.reverb.width",
fluid_settings_getnum_range(handler->settings, "synth.reverb.width",
&values[FLUID_REVERB_WIDTH].min,
&values[FLUID_REVERB_WIDTH].max);
fluid_settings_getnum_range(handler->synth->settings, "synth.reverb.level",
fluid_settings_getnum_range(handler->settings, "synth.reverb.level",
&values[FLUID_REVERB_LEVEL].min,
&values[FLUID_REVERB_LEVEL].max);
@ -1915,7 +1919,9 @@ fluid_handle_set(void *data, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
int hints;
int ival;
int ival, icur;
double fval, fcur;
char *scur;
int ret = FLUID_FAILED;
if(ac < 2)
@ -1924,14 +1930,14 @@ fluid_handle_set(void *data, int ac, char **av, fluid_ostream_t out)
return ret;
}
switch(fluid_settings_get_type(handler->synth->settings, av[0]))
switch(fluid_settings_get_type(handler->settings, av[0]))
{
case FLUID_NO_TYPE:
fluid_ostream_printf(out, "set: Parameter '%s' not found.\n", av[0]);
return ret;
case FLUID_INT_TYPE:
if(fluid_settings_get_hints(handler->synth->settings, av[0], &hints) == FLUID_OK
if(fluid_settings_get_hints(handler->settings, av[0], &hints) == FLUID_OK
&& hints & FLUID_HINT_TOGGLED)
{
if(FLUID_STRCASECMP(av[1], "yes") == 0
@ -1950,20 +1956,45 @@ fluid_handle_set(void *data, int ac, char **av, fluid_ostream_t out)
ival = atoi(av[1]);
}
ret = fluid_settings_setint(handler->synth->settings, av[0], ival);
fluid_settings_getint(handler->settings, av[0], &icur);
if (icur == ival)
{
return FLUID_OK;
}
ret = fluid_settings_setint(handler->settings, av[0], ival);
break;
case FLUID_NUM_TYPE:
ret = fluid_settings_setnum(handler->synth->settings, av[0], atof(av[1]));
fval = atof(av[1]);
fluid_settings_getnum(handler->settings, av[0], &fcur);
if (fcur == fval)
{
return FLUID_OK;
}
ret = fluid_settings_setnum(handler->settings, av[0], fval);
break;
case FLUID_STR_TYPE:
ret = fluid_settings_setstr(handler->synth->settings, av[0], av[1]);
fluid_settings_dupstr(handler->settings, av[0], &scur);
if(scur && !FLUID_STRCMP(scur, av[1]))
{
FLUID_FREE(scur);
return FLUID_OK;
}
ret = fluid_settings_setstr(handler->settings, av[0], av[1]);
FLUID_FREE(scur);
break;
case FLUID_SET_TYPE:
fluid_ostream_printf(out, "set: Parameter '%s' is a node.\n", av[0]);
return FLUID_FAILED;
default:
fluid_ostream_printf(out, "Unhandled settings type.");
return FLUID_FAILED;
}
if(ret == FLUID_FAILED)
@ -1971,7 +2002,7 @@ fluid_handle_set(void *data, int ac, char **av, fluid_ostream_t out)
fluid_ostream_printf(out, "set: Value out of range. Try 'info %s' for valid ranges\n", av[0]);
}
if(!fluid_settings_is_realtime(handler->synth->settings, av[0]))
if((handler->synth != NULL || handler->router != NULL) && !fluid_settings_is_realtime(handler->settings, av[0]))
{
fluid_ostream_printf(out, "Warning: '%s' is not a realtime setting, changes won't take effect.\n", av[0]);
}
@ -1990,7 +2021,7 @@ fluid_handle_get(void *data, int ac, char **av, fluid_ostream_t out)
return FLUID_FAILED;
}
switch(fluid_settings_get_type(fluid_synth_get_settings(handler->synth), av[0]))
switch(fluid_settings_get_type(handler->settings, av[0]))
{
case FLUID_NO_TYPE:
fluid_ostream_printf(out, "get: no such setting '%s'.\n", av[0]);
@ -1999,7 +2030,7 @@ fluid_handle_get(void *data, int ac, char **av, fluid_ostream_t out)
case FLUID_NUM_TYPE:
{
double value;
fluid_settings_getnum(handler->synth->settings, av[0], &value);
fluid_settings_getnum(handler->settings, av[0], &value);
fluid_ostream_printf(out, "%.3f\n", value);
break;
}
@ -2007,7 +2038,7 @@ fluid_handle_get(void *data, int ac, char **av, fluid_ostream_t out)
case FLUID_INT_TYPE:
{
int value;
fluid_settings_getint(handler->synth->settings, av[0], &value);
fluid_settings_getint(handler->settings, av[0], &value);
fluid_ostream_printf(out, "%d\n", value);
break;
}
@ -2015,7 +2046,7 @@ fluid_handle_get(void *data, int ac, char **av, fluid_ostream_t out)
case FLUID_STR_TYPE:
{
char *s;
fluid_settings_dupstr(handler->synth->settings, av[0], &s); /* ++ alloc string */
fluid_settings_dupstr(handler->settings, av[0], &s); /* ++ alloc string */
fluid_ostream_printf(out, "%s\n", s ? s : "NULL");
if(s)
@ -2037,7 +2068,7 @@ fluid_handle_get(void *data, int ac, char **av, fluid_ostream_t out)
struct _fluid_handle_settings_data_t
{
size_t len;
fluid_synth_t *synth;
fluid_settings_t *settings;
fluid_ostream_t out;
};
@ -2067,12 +2098,12 @@ static void fluid_handle_settings_iter2(void *data, const char *name, int type)
fluid_ostream_printf(d->out, " ");
switch(fluid_settings_get_type(fluid_synth_get_settings(d->synth), name))
switch(fluid_settings_get_type(d->settings, name))
{
case FLUID_NUM_TYPE:
{
double value;
fluid_settings_getnum(d->synth->settings, name, &value);
fluid_settings_getnum(d->settings, name, &value);
fluid_ostream_printf(d->out, "%.3f\n", value);
break;
}
@ -2080,9 +2111,9 @@ static void fluid_handle_settings_iter2(void *data, const char *name, int type)
case FLUID_INT_TYPE:
{
int value, hints;
fluid_settings_getint(d->synth->settings, name, &value);
fluid_settings_getint(d->settings, name, &value);
if(fluid_settings_get_hints(d->synth->settings, name, &hints) == FLUID_OK)
if(fluid_settings_get_hints(d->settings, name, &hints) == FLUID_OK)
{
if(!(hints & FLUID_HINT_TOGGLED))
{
@ -2100,7 +2131,7 @@ static void fluid_handle_settings_iter2(void *data, const char *name, int type)
case FLUID_STR_TYPE:
{
char *s;
fluid_settings_dupstr(d->synth->settings, name, &s); /* ++ alloc string */
fluid_settings_dupstr(d->settings, name, &s); /* ++ alloc string */
fluid_ostream_printf(d->out, "%s\n", s ? s : "NULL");
if(s)
@ -2120,11 +2151,11 @@ fluid_handle_settings(void *d, int ac, char **av, fluid_ostream_t out)
struct _fluid_handle_settings_data_t data;
data.len = 0;
data.synth = handler->synth;
data.settings = handler->settings;
data.out = out;
fluid_settings_foreach(fluid_synth_get_settings(handler->synth), &data, fluid_handle_settings_iter1);
fluid_settings_foreach(fluid_synth_get_settings(handler->synth), &data, fluid_handle_settings_iter2);
fluid_settings_foreach(handler->settings, &data, fluid_handle_settings_iter1);
fluid_settings_foreach(handler->settings, &data, fluid_handle_settings_iter2);
return FLUID_OK;
}
@ -2154,7 +2185,7 @@ int
fluid_handle_info(void *d, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(d);
fluid_settings_t *settings = fluid_synth_get_settings(handler->synth);
fluid_settings_t *settings = handler->settings;
struct _fluid_handle_option_data_t data;
if(ac < 1)
@ -4253,11 +4284,24 @@ fluid_cmd_handler_destroy_hash_value(void *value)
/**
* Create a new command handler.
*
* See new_fluid_cmd_handler2() for more information.
*/
fluid_cmd_handler_t *new_fluid_cmd_handler(fluid_synth_t *synth, fluid_midi_router_t *router)
{
return new_fluid_cmd_handler2(fluid_synth_get_settings(synth), synth, router);
}
/**
* Create a new command handler.
*
* @param settings If not NULL, all the settings related commands will be added to the new handler. The @p settings
* object must be the same as the one you used for creating the @p synth and @p router. Otherwise the
* behaviour is undefined.
* @param synth If not NULL, all the default synthesizer commands will be added to the new handler.
* @param router If not NULL, all the default midi_router commands will be added to the new handler.
* @return New command handler, or NULL if alloc failed
*/
fluid_cmd_handler_t *new_fluid_cmd_handler(fluid_synth_t *synth, fluid_midi_router_t *router)
fluid_cmd_handler_t *new_fluid_cmd_handler2(fluid_settings_t* settings, fluid_synth_t *synth, fluid_midi_router_t *router)
{
unsigned int i;
fluid_cmd_handler_t *handler;
@ -4280,6 +4324,7 @@ fluid_cmd_handler_t *new_fluid_cmd_handler(fluid_synth_t *synth, fluid_midi_rout
return NULL;
}
handler->settings = settings;
handler->synth = synth;
handler->router = router;
@ -4287,14 +4332,21 @@ fluid_cmd_handler_t *new_fluid_cmd_handler(fluid_synth_t *synth, fluid_midi_rout
{
const fluid_cmd_t *cmd = &fluid_commands[i];
int is_router_cmd = FLUID_STRCMP(cmd->topic, "router") == 0;
int is_settings_cmd = FLUID_STRCMP(cmd->topic, "settings") == 0;
if((is_router_cmd && router == NULL) || (!is_router_cmd && synth == NULL))
if((is_router_cmd && router == NULL) ||
(is_settings_cmd && settings == NULL) ||
(!is_router_cmd && !is_settings_cmd && synth == NULL))
{
/* omit registering router and synth commands if they were not requested */
continue;
/* register a no-op command, this avoids an unknown command error later on */
fluid_cmd_t noop = *cmd;
noop.handler = NULL;
fluid_cmd_handler_register(handler, &noop);
}
else
{
fluid_cmd_handler_register(handler, cmd);
}
fluid_cmd_handler_register(handler, &fluid_commands[i]);
}
return handler;
@ -4350,13 +4402,23 @@ fluid_cmd_handler_handle(void *data, int ac, char **av, fluid_ostream_t out)
cmd = fluid_hashtable_lookup(handler->commands, av[0]);
if(cmd && cmd->handler)
if(cmd)
{
return (*cmd->handler)(handler, ac - 1, av + 1, out);
if(cmd->handler)
{
return (*cmd->handler)(handler, ac - 1, av + 1, out);
}
else
{
/* no-op command */
return 1;
}
}
else
{
fluid_ostream_printf(out, "unknown command: %s (try help)\n", av[0]);
return FLUID_FAILED;
}
fluid_ostream_printf(out, "unknown command: %s (try help)\n", av[0]);
return FLUID_FAILED;
}

View file

@ -50,7 +50,6 @@ void print_configure(void);
/*
* the globals
*/
fluid_cmd_handler_t *cmd_handler = NULL;
int option_help = 0; /* set to 1 if "-o help" is specified */
@ -308,6 +307,7 @@ fast_render_loop(fluid_settings_t *settings, fluid_synth_t *synth, fluid_player_
1)creating the settings.
2)reading/setting all options in command line.
2.5)read configuration file the first time and execute all "set" commands
3)creating the synth.
4)loading the soundfonts specified in command line
(multiple soundfonts loading is possible).
@ -318,7 +318,7 @@ fast_render_loop(fluid_settings_t *settings, fluid_synth_t *synth, fluid_player_
(multiple midifiles loading is possible).
9)loading a default soundfont if needed before starting the player.
10)create a command handler.
11)reading the configuration file and submit it to the command handler.
11)reading the entire configuration file for the second time and submit it to the command handler.
12)create a tcp shell if any requested.
13)create a synchronous user shell if interactive.
14)entering fast rendering loop if requested.
@ -338,6 +338,7 @@ int main(int argc, char **argv)
fluid_midi_driver_t *mdriver = NULL;
fluid_audio_driver_t *adriver = NULL;
fluid_synth_t *synth = NULL;
fluid_cmd_handler_t *cmd_handler = NULL;
#ifdef NETWORK_SUPPORT
fluid_server_t *server = NULL;
int with_server = 0;
@ -369,7 +370,6 @@ int main(int argc, char **argv)
#endif
/* create the settings */
settings = new_fluid_settings();
@ -773,7 +773,8 @@ int main(int argc, char **argv)
arg1 = i;
#endif
if (!quiet) {
if (!quiet)
{
print_welcome();
}
@ -830,6 +831,36 @@ int main(int argc, char **argv)
fluid_settings_setint(settings, "synth.lock-memory", 0);
}
if(config_file == NULL)
{
config_file = fluid_get_userconf(buf, sizeof(buf));
if(config_file == NULL)
{
config_file = fluid_get_sysconf(buf, sizeof(buf));
}
}
/* Handle set commands before creating the synth */
if(config_file != NULL)
{
cmd_handler = new_fluid_cmd_handler2(settings, NULL, NULL);
if(cmd_handler == NULL)
{
fprintf(stderr, "Failed to create the early command handler\n");
goto cleanup;
}
if(fluid_source(cmd_handler, config_file) < 0)
{
fprintf(stderr, "Failed to early-execute command configuration file '%s'\n", config_file);
/* the command file seems broken, don't read it again */
config_file = NULL;
}
delete_fluid_cmd_handler(cmd_handler);
cmd_handler = NULL;
}
/* create the synthesizer */
synth = new_fluid_synth(settings);
@ -950,20 +981,9 @@ int main(int argc, char **argv)
goto cleanup;
}
if(config_file != NULL)
if(config_file != NULL && fluid_source(cmd_handler, config_file) < 0)
{
if(fluid_source(cmd_handler, config_file) < 0)
{
fprintf(stderr, "Failed to execute user provided command configuration file '%s'\n", config_file);
}
}
else if(fluid_get_userconf(buf, sizeof(buf)) != NULL)
{
fluid_source(cmd_handler, buf);
}
else if(fluid_get_sysconf(buf, sizeof(buf)) != NULL)
{
fluid_source(cmd_handler, buf);
fprintf(stderr, "Failed to execute command configuration file '%s'\n", config_file);
}
/* run the server, if requested */
@ -1071,10 +1091,7 @@ cleanup:
#endif /* NETWORK_SUPPORT */
if(cmd_handler != NULL)
{
delete_fluid_cmd_handler(cmd_handler);
}
delete_fluid_cmd_handler(cmd_handler);
if(player != NULL)
{