From 3d805e9a0383af3e48f37b596585b60dc5131d0e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 3 Jan 2021 12:11:58 +0100 Subject: [PATCH 1/5] Only change a set if the value actually changed That prevents warnings about changing a non-realtime parameter set command is issued, but the value is identical to the previous one. --- src/bindings/fluid_cmd.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/bindings/fluid_cmd.c b/src/bindings/fluid_cmd.c index ee7314e2..d8f568e5 100644 --- a/src/bindings/fluid_cmd.c +++ b/src/bindings/fluid_cmd.c @@ -1915,7 +1915,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) @@ -1950,15 +1952,36 @@ fluid_handle_set(void *data, int ac, char **av, fluid_ostream_t out) ival = atoi(av[1]); } + fluid_settings_getint(handler->synth->settings, av[0], &icur); + if (icur == ival) + { + return FLUID_OK; + } + ret = fluid_settings_setint(handler->synth->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->synth->settings, av[0], &fcur); + if (fcur == fval) + { + return FLUID_OK; + } + + ret = fluid_settings_setnum(handler->synth->settings, av[0], fval); break; case FLUID_STR_TYPE: + fluid_settings_dupstr(handler->synth->settings, av[0], &scur); + + if(scur && !FLUID_STRCMP(scur, av[1])) + { + FLUID_FREE(scur); + return FLUID_OK; + } ret = fluid_settings_setstr(handler->synth->settings, av[0], av[1]); + FLUID_FREE(scur); break; case FLUID_SET_TYPE: From 4e8f570d329d3f48331bac8a045839898877e3e4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 3 Jan 2021 12:32:31 +0100 Subject: [PATCH 2/5] Don't warn when parsing config files When fluid_shell is called from fluid_source(), is is currently printing this message: Received EOF while reading commands, exiting the shell. Suppress it. --- src/bindings/fluid_cmd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bindings/fluid_cmd.c b/src/bindings/fluid_cmd.c index d8f568e5..188c1f9f 100644 --- a/src/bindings/fluid_cmd.c +++ b/src/bindings/fluid_cmd.c @@ -539,7 +539,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; } } From 40ed09367ad1f7186295226bb5552b67ae559cd6 Mon Sep 17 00:00:00 2001 From: derselbst Date: Fri, 8 Jan 2021 23:36:45 +0100 Subject: [PATCH 3/5] Parse set commands from config file early --- include/fluidsynth/shell.h | 3 ++ src/bindings/fluid_cmd.c | 80 ++++++++++++++++++++++++-------------- src/fluidsynth.c | 59 ++++++++++++++++++---------- 3 files changed, 92 insertions(+), 50 deletions(-) diff --git a/include/fluidsynth/shell.h b/include/fluidsynth/shell.h index 8df704ba..1950880b 100644 --- a/include/fluidsynth/shell.h +++ b/include/fluidsynth/shell.h @@ -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 */ diff --git a/src/bindings/fluid_cmd.c b/src/bindings/fluid_cmd.c index 188c1f9f..56c9ee9a 100644 --- a/src/bindings/fluid_cmd.c +++ b/src/bindings/fluid_cmd.c @@ -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; @@ -1212,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); @@ -1929,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 @@ -1955,41 +1956,45 @@ fluid_handle_set(void *data, int ac, char **av, fluid_ostream_t out) ival = atoi(av[1]); } - fluid_settings_getint(handler->synth->settings, av[0], &icur); + fluid_settings_getint(handler->settings, av[0], &icur); if (icur == ival) { return FLUID_OK; } - ret = fluid_settings_setint(handler->synth->settings, av[0], ival); + ret = fluid_settings_setint(handler->settings, av[0], ival); break; case FLUID_NUM_TYPE: fval = atof(av[1]); - fluid_settings_getnum(handler->synth->settings, av[0], &fcur); + fluid_settings_getnum(handler->settings, av[0], &fcur); if (fcur == fval) { return FLUID_OK; } - ret = fluid_settings_setnum(handler->synth->settings, av[0], fval); + ret = fluid_settings_setnum(handler->settings, av[0], fval); break; case FLUID_STR_TYPE: - fluid_settings_dupstr(handler->synth->settings, av[0], &scur); + 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->synth->settings, av[0], av[1]); + 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) @@ -1997,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(!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]); } @@ -2016,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]); @@ -2025,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; } @@ -2033,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; } @@ -2041,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) @@ -2063,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; }; @@ -2093,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; } @@ -2106,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)) { @@ -2126,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) @@ -2146,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; } @@ -2180,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) @@ -4279,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; @@ -4306,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; @@ -4313,8 +4332,11 @@ 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; diff --git a/src/fluidsynth.c b/src/fluidsynth.c index d6228c3f..a03a99fd 100644 --- a/src/fluidsynth.c +++ b/src/fluidsynth.c @@ -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) { From 9bb048f27f7f6f8cc1642b7a8f09b4815f9bed67 Mon Sep 17 00:00:00 2001 From: derselbst Date: Sat, 9 Jan 2021 00:13:44 +0100 Subject: [PATCH 4/5] Don't print warning when parsing early --- src/bindings/fluid_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings/fluid_cmd.c b/src/bindings/fluid_cmd.c index 56c9ee9a..b0e9a9e6 100644 --- a/src/bindings/fluid_cmd.c +++ b/src/bindings/fluid_cmd.c @@ -2002,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->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]); } From 20ff3f866cba1dd9af7a1000871ee717da4be9a1 Mon Sep 17 00:00:00 2001 From: derselbst Date: Sat, 9 Jan 2021 19:44:18 +0100 Subject: [PATCH 5/5] Avoid unknown command errors when parsing settings early --- src/bindings/fluid_cmd.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/bindings/fluid_cmd.c b/src/bindings/fluid_cmd.c index b0e9a9e6..cf3b0c3b 100644 --- a/src/bindings/fluid_cmd.c +++ b/src/bindings/fluid_cmd.c @@ -4338,11 +4338,15 @@ fluid_cmd_handler_t *new_fluid_cmd_handler2(fluid_settings_t* settings, fluid_sy (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; @@ -4398,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; }