1 /* FluidSynth - A Software Synthesizer
3 * Copyright (C) 2003 Peter Hanappe and others.
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.
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.
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 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #include "fluidsynth_priv.h"
22 #include "fluid_sys.h"
23 #include "fluid_hash.h"
24 #include "fluid_synth.h"
25 //#include "fluid_cmd.h"
26 //#include "fluid_adriver.h"
27 //#include "fluid_mdriver.h"
28 #include "fluid_settings.h"
29 #include "fluid_midi.h"
31 /* Defined in fluid_filerenderer.c */
32 extern void fluid_file_renderer_settings (fluid_settings_t* settings);
34 /* maximum allowed components of a settings variable (separated by '.') */
35 #define MAX_SETTINGS_TOKENS 8 /* currently only a max of 3 are used */
36 #define MAX_SETTINGS_LABEL 256 /* max length of a settings variable label */
38 static void fluid_settings_init(fluid_settings_t* settings);
39 static void fluid_settings_key_destroy_func(void* value);
40 static void fluid_settings_value_destroy_func(void* value);
41 static int fluid_settings_tokenize(const char *s, char *buf, char **ptr);
43 /* Common structure to all settings nodes */
45 int type; /**< fluid_types_enum */
46 } fluid_setting_node_t;
49 fluid_setting_node_t node;
53 fluid_list_t* options;
54 fluid_str_update_t update;
56 } fluid_str_setting_t;
59 fluid_setting_node_t node;
65 fluid_num_update_t update;
67 } fluid_num_setting_t;
70 fluid_setting_node_t node;
76 fluid_int_update_t update;
78 } fluid_int_setting_t;
81 fluid_setting_node_t node;
82 fluid_hashtable_t *hashtable;
83 } fluid_set_setting_t;
86 static fluid_str_setting_t*
87 new_fluid_str_setting(const char* value, char* def, int hints, fluid_str_update_t fun, void* data)
89 fluid_str_setting_t* str;
91 str = FLUID_NEW(fluid_str_setting_t);
95 FLUID_LOG(FLUID_ERR, "Out of memory");
99 str->node.type = FLUID_STR_TYPE;
100 str->value = value? FLUID_STRDUP(value) : NULL;
101 str->def = def? FLUID_STRDUP(def) : NULL;
110 delete_fluid_str_setting(fluid_str_setting_t* str)
114 if (str->value) FLUID_FREE(str->value);
115 if (str->def) FLUID_FREE(str->def);
118 fluid_list_t* list = str->options;
121 FLUID_FREE (list->data);
122 list = fluid_list_next(list);
125 delete_fluid_list(str->options);
132 static fluid_num_setting_t*
133 new_fluid_num_setting(double min, double max, double def,
134 int hints, fluid_num_update_t fun, void* data)
136 fluid_num_setting_t* setting;
138 setting = FLUID_NEW(fluid_num_setting_t);
142 FLUID_LOG(FLUID_ERR, "Out of memory");
146 setting->node.type = FLUID_NUM_TYPE;
147 setting->value = def;
151 setting->hints = hints;
152 setting->update = fun;
153 setting->data = data;
158 delete_fluid_num_setting(fluid_num_setting_t* setting)
160 if (setting) FLUID_FREE(setting);
163 static fluid_int_setting_t*
164 new_fluid_int_setting(int min, int max, int def,
165 int hints, fluid_int_update_t fun, void* data)
167 fluid_int_setting_t* setting;
169 setting = FLUID_NEW(fluid_int_setting_t);
173 FLUID_LOG(FLUID_ERR, "Out of memory");
177 setting->node.type = FLUID_INT_TYPE;
178 setting->value = def;
182 setting->hints = hints;
183 setting->update = fun;
184 setting->data = data;
189 delete_fluid_int_setting(fluid_int_setting_t* setting)
191 if (setting) FLUID_FREE(setting);
194 static fluid_set_setting_t*
195 new_fluid_set_setting(void)
197 fluid_set_setting_t* setting;
199 setting = FLUID_NEW(fluid_set_setting_t);
203 FLUID_LOG(FLUID_ERR, "Out of memory");
207 setting->node.type = FLUID_SET_TYPE;
208 setting->hashtable = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal,
209 fluid_settings_key_destroy_func,
210 fluid_settings_value_destroy_func);
211 if (!setting->hashtable)
213 FLUID_FREE (setting);
221 delete_fluid_set_setting(fluid_set_setting_t* setting)
225 delete_fluid_hashtable(setting->hashtable);
231 * Create a new settings object
232 * @return the pointer to the settings object
235 new_fluid_settings(void)
237 fluid_settings_t* settings;
239 settings = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal,
240 fluid_settings_key_destroy_func,
241 fluid_settings_value_destroy_func);
242 if (settings == NULL) return NULL;
244 fluid_rec_mutex_init (settings->mutex);
245 fluid_settings_init(settings);
250 * Delete the provided settings object
251 * @param settings a settings object
254 delete_fluid_settings(fluid_settings_t* settings)
256 fluid_return_if_fail (settings != NULL);
258 fluid_rec_mutex_destroy (settings->mutex);
259 delete_fluid_hashtable(settings);
262 /* Settings hash key destroy function */
264 fluid_settings_key_destroy_func(void* value)
266 FLUID_FREE (value); /* Free the string key value */
269 /* Settings hash value destroy function */
271 fluid_settings_value_destroy_func(void* value)
273 fluid_setting_node_t *node = value;
275 switch (node->type) {
277 delete_fluid_num_setting((fluid_num_setting_t*) value);
280 delete_fluid_int_setting((fluid_int_setting_t*) value);
283 delete_fluid_str_setting((fluid_str_setting_t*) value);
286 delete_fluid_set_setting((fluid_set_setting_t*) value);
292 fluid_settings_init(fluid_settings_t* settings)
294 fluid_return_if_fail (settings != NULL);
296 fluid_synth_settings(settings);
297 //fluid_shell_settings(settings);
298 fluid_player_settings(settings);
300 fluid_file_renderer_settings(settings);
301 fluid_audio_driver_settings(settings);
302 fluid_midi_driver_settings(settings);
307 fluid_settings_tokenize(const char *s, char *buf, char **ptr)
312 if (strlen (s) > MAX_SETTINGS_LABEL)
314 FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars",
319 FLUID_STRCPY(buf, s); /* copy string to buffer, since it gets modified */
322 while ((tok = fluid_strtok (&tokstr, ".")))
324 if (n >= MAX_SETTINGS_TOKENS)
326 FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max token count of %d",
327 MAX_SETTINGS_TOKENS);
337 * Get a setting name, value and type
339 * @param settings a settings object
340 * @param name Settings name
341 * @param value Location to store setting node if found
342 * @return 1 if the node exists, 0 otherwise
345 fluid_settings_get(fluid_settings_t* settings, const char *name,
346 fluid_setting_node_t **value)
348 fluid_hashtable_t* table = settings;
349 fluid_setting_node_t *node = NULL;
350 char* tokens[MAX_SETTINGS_TOKENS];
351 char buf[MAX_SETTINGS_LABEL+1];
355 ntokens = fluid_settings_tokenize (name, buf, tokens);
357 if (table == NULL || ntokens <= 0) return 0;
359 for (n = 0; n < ntokens; n++) {
361 node = fluid_hashtable_lookup(table, tokens[n]);
364 table = (node->type == FLUID_SET_TYPE) ? ((fluid_set_setting_t *)node)->hashtable : NULL;
367 if (value) *value = node;
373 * Set a setting name, value and type, replacing it if already exists
375 * @param settings a settings object
376 * @param name Settings name
377 * @param value Node instance to assign (used directly)
378 * @return 1 if the value has been set, zero otherwise
381 fluid_settings_set(fluid_settings_t* settings, const char *name, void* value)
383 fluid_hashtable_t* table = settings;
384 fluid_setting_node_t *node;
385 char* tokens[MAX_SETTINGS_TOKENS];
386 char buf[MAX_SETTINGS_LABEL+1];
390 num = fluid_settings_tokenize (name, buf, tokens) - 1;
394 for (n = 0; n < num; n++) {
396 node = fluid_hashtable_lookup(table, tokens[n]);
400 if (node->type == FLUID_SET_TYPE) {
401 table = ((fluid_set_setting_t *)node)->hashtable;
403 /* path ends prematurely */
404 FLUID_LOG(FLUID_WARN, "'%s' is not a node", name[n]);
409 /* create a new node */
410 fluid_set_setting_t* setnode;
412 dupname = FLUID_STRDUP (tokens[n]);
413 setnode = new_fluid_set_setting ();
415 if (!dupname || !setnode)
417 if (dupname) FLUID_FREE (dupname);
418 else FLUID_LOG(FLUID_ERR, "Out of memory");
420 if (setnode) delete_fluid_set_setting (setnode);
425 fluid_hashtable_insert(table, dupname, setnode);
426 table = setnode->hashtable;
430 dupname = FLUID_STRDUP (tokens[num]);
434 FLUID_LOG(FLUID_ERR, "Out of memory");
438 fluid_hashtable_insert(table, dupname, value);
443 /** returns 1 if the value has been registered correctly, 0
446 fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, int hints,
447 fluid_str_update_t fun, void* data)
449 fluid_setting_node_t *node;
450 fluid_str_setting_t* setting;
453 fluid_return_val_if_fail (settings != NULL, 0);
454 fluid_return_val_if_fail (name != NULL, 0);
455 fluid_return_val_if_fail (name[0] != '\0', 0);
457 fluid_rec_mutex_lock (settings->mutex);
459 if (!fluid_settings_get(settings, name, &node)) {
460 setting = new_fluid_str_setting(def, def, hints, fun, data);
461 retval = fluid_settings_set(settings, name, setting);
462 if (retval != 1) delete_fluid_str_setting (setting);
464 /* if variable already exists, don't change its value. */
465 if (node->type == FLUID_STR_TYPE) {
466 setting = (fluid_str_setting_t*) node;
467 setting->update = fun;
468 setting->data = data;
469 setting->def = def? FLUID_STRDUP(def) : NULL;
470 setting->hints = hints;
473 FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
478 fluid_rec_mutex_unlock (settings->mutex);
483 /** returns 1 if the value has been register correctly, zero
486 fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
487 double min, double max, int hints,
488 fluid_num_update_t fun, void* data)
490 fluid_setting_node_t *node;
493 fluid_return_val_if_fail (settings != NULL, 0);
494 fluid_return_val_if_fail (name != NULL, 0);
495 fluid_return_val_if_fail (name[0] != '\0', 0);
497 /* For now, all floating point settings are bounded below and above */
498 hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE;
500 fluid_rec_mutex_lock (settings->mutex);
502 if (!fluid_settings_get(settings, name, &node)) {
503 /* insert a new setting */
504 fluid_num_setting_t* setting;
505 setting = new_fluid_num_setting(min, max, def, hints, fun, data);
506 retval = fluid_settings_set(settings, name, setting);
507 if (retval != 1) delete_fluid_num_setting (setting);
509 if (node->type == FLUID_NUM_TYPE) {
510 /* update the existing setting but don't change its value */
511 fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
512 setting->update = fun;
513 setting->data = data;
517 setting->hints = hints;
521 FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
526 fluid_rec_mutex_unlock (settings->mutex);
531 /** returns 1 if the value has been register correctly, zero
534 fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
535 int min, int max, int hints,
536 fluid_int_update_t fun, void* data)
538 fluid_setting_node_t *node;
541 fluid_return_val_if_fail (settings != NULL, 0);
542 fluid_return_val_if_fail (name != NULL, 0);
543 fluid_return_val_if_fail (name[0] != '\0', 0);
545 /* For now, all integer settings are bounded below and above */
546 hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE;
548 fluid_rec_mutex_lock (settings->mutex);
550 if (!fluid_settings_get(settings, name, &node)) {
551 /* insert a new setting */
552 fluid_int_setting_t* setting;
553 setting = new_fluid_int_setting(min, max, def, hints, fun, data);
554 retval = fluid_settings_set(settings, name, setting);
555 if (retval != 1) delete_fluid_int_setting (setting);
557 if (node->type == FLUID_INT_TYPE) {
558 /* update the existing setting but don't change its value */
559 fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
560 setting->update = fun;
561 setting->data = data;
565 setting->hints = hints;
569 FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
574 fluid_rec_mutex_unlock (settings->mutex);
580 * Get the type of the setting with the given name
582 * @param settings a settings object
583 * @param name a setting's name
584 * @return the type for the named setting, or #FLUID_NO_TYPE when it does not exist
587 fluid_settings_get_type(fluid_settings_t* settings, const char *name)
589 fluid_setting_node_t *node;
592 fluid_return_val_if_fail (settings != NULL, FLUID_NO_TYPE);
593 fluid_return_val_if_fail (name != NULL, FLUID_NO_TYPE);
594 fluid_return_val_if_fail (name[0] != '\0', FLUID_NO_TYPE);
596 fluid_rec_mutex_lock (settings->mutex);
597 type = fluid_settings_get (settings, name, &node) ? node->type : FLUID_NO_TYPE;
598 fluid_rec_mutex_unlock (settings->mutex);
604 * Get the hints for the named setting as an integer bitmap
606 * @param settings a settings object
607 * @param name a setting's name
608 * @return the hints associated to the named setting if it exists, zero otherwise
611 fluid_settings_get_hints(fluid_settings_t* settings, const char *name)
613 fluid_setting_node_t *node;
616 fluid_return_val_if_fail (settings != NULL, 0);
617 fluid_return_val_if_fail (name != NULL, 0);
618 fluid_return_val_if_fail (name[0] != '\0', 0);
620 fluid_rec_mutex_lock (settings->mutex);
622 if (fluid_settings_get(settings, name, &node)) {
623 if (node->type == FLUID_NUM_TYPE) {
624 fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
625 hints = setting->hints;
626 } else if (node->type == FLUID_STR_TYPE) {
627 fluid_str_setting_t* setting = (fluid_str_setting_t*) node;
628 hints = setting->hints;
629 } else if (node->type == FLUID_INT_TYPE) {
630 fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
631 hints = setting->hints;
635 fluid_rec_mutex_unlock (settings->mutex);
641 * Ask whether the setting is changeable in real-time.
643 * @param settings a settings object
644 * @param name a setting's name
645 * @return non zero if the setting is changeable in real-time
648 fluid_settings_is_realtime(fluid_settings_t* settings, const char *name)
650 fluid_setting_node_t *node;
651 int isrealtime = FALSE;
653 fluid_return_val_if_fail (settings != NULL, 0);
654 fluid_return_val_if_fail (name != NULL, 0);
655 fluid_return_val_if_fail (name[0] != '\0', 0);
657 fluid_rec_mutex_lock (settings->mutex);
659 if (fluid_settings_get(settings, name, &node)) {
660 if (node->type == FLUID_NUM_TYPE) {
661 fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
662 isrealtime = setting->update != NULL;
663 } else if (node->type == FLUID_STR_TYPE) {
664 fluid_str_setting_t* setting = (fluid_str_setting_t*) node;
665 isrealtime = setting->update != NULL;
666 } else if (node->type == FLUID_INT_TYPE) {
667 fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
668 isrealtime = setting->update != NULL;
672 fluid_rec_mutex_unlock (settings->mutex);
678 * Set a string value for a named setting
680 * @param settings a settings object
681 * @param name a setting's name
682 * @param str new string value
683 * @return 1 if the value has been set, 0 otherwise
686 fluid_settings_setstr(fluid_settings_t* settings, const char *name, const char *str)
688 fluid_setting_node_t *node;
691 fluid_return_val_if_fail (settings != NULL, 0);
692 fluid_return_val_if_fail (name != NULL, 0);
693 fluid_return_val_if_fail (name[0] != '\0', 0);
695 fluid_rec_mutex_lock (settings->mutex);
697 if (fluid_settings_get (settings, name, &node)) {
698 if (node->type == FLUID_STR_TYPE) {
699 fluid_str_setting_t *setting = (fluid_str_setting_t *)node;
701 if (setting->value) FLUID_FREE (setting->value);
702 setting->value = str ? FLUID_STRDUP (str) : NULL;
704 /* Call under lock to keep update() synchronized with the current value */
705 if (setting->update) (*setting->update)(setting->data, name, str);
708 else if (node->type == FLUID_INT_TYPE) /* Handle yes/no for boolean values for backwards compatibility */
710 fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
712 if (setting->hints & FLUID_HINT_TOGGLED)
714 if (FLUID_STRCMP (str, "yes") == 0)
716 setting->value = TRUE;
717 if (setting->update) (*setting->update)(setting->data, name, TRUE);
719 else if (FLUID_STRCMP (str, "no") == 0)
721 setting->value = FALSE;
722 if (setting->update) (*setting->update)(setting->data, name, FALSE);
727 /* insert a new setting */
728 fluid_str_setting_t* setting;
729 setting = new_fluid_str_setting(str, NULL, 0, NULL, NULL);
730 retval = fluid_settings_set(settings, name, setting);
731 if (retval != 1) delete_fluid_str_setting (setting);
734 fluid_rec_mutex_unlock (settings->mutex);
740 * Copy the value of a string setting
741 * @param settings a settings object
742 * @param name a setting's name
743 * @param str Caller supplied buffer to copy string value to
744 * @param len Size of 'str' buffer (no more than len bytes will be written, which
745 * will always include a zero terminator)
746 * @return 1 if the value exists, 0 otherwise
749 * Like fluid_settings_getstr() but is thread safe. A size of 256 should be
750 * more than sufficient for the string buffer.
753 fluid_settings_copystr(fluid_settings_t* settings, const char *name,
756 fluid_setting_node_t *node;
759 fluid_return_val_if_fail (settings != NULL, 0);
760 fluid_return_val_if_fail (name != NULL, 0);
761 fluid_return_val_if_fail (name[0] != '\0', 0);
762 fluid_return_val_if_fail (str != NULL, 0);
763 fluid_return_val_if_fail (len > 0, 0);
767 fluid_rec_mutex_lock (settings->mutex);
769 if (fluid_settings_get (settings, name, &node))
771 if (node->type == FLUID_STR_TYPE)
773 fluid_str_setting_t *setting = (fluid_str_setting_t *)node;
777 FLUID_STRNCPY (str, setting->value, len);
778 str[len - 1] = 0; /* Force terminate, in case of truncation */
783 else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
785 fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
787 if (setting->hints & FLUID_HINT_TOGGLED)
789 FLUID_STRNCPY (str, setting->value ? "yes" : "no", len);
790 str[len - 1] = 0; /* Force terminate, in case of truncation */
797 fluid_rec_mutex_unlock (settings->mutex);
803 * Duplicate the value of a string setting
804 * @param settings a settings object
805 * @param name a setting's name
806 * @param str Location to store pointer to allocated duplicate string
807 * @return 1 if the value exists and was successfully duplicated, 0 otherwise
810 * Like fluid_settings_copystr() but allocates a new copy of the string. Caller
811 * owns the string and should free it with free() when done using it.
814 fluid_settings_dupstr(fluid_settings_t* settings, const char *name, char** str)
816 fluid_setting_node_t *node;
819 fluid_return_val_if_fail (settings != NULL, 0);
820 fluid_return_val_if_fail (name != NULL, 0);
821 fluid_return_val_if_fail (name[0] != '\0', 0);
822 fluid_return_val_if_fail (str != NULL, 0);
824 fluid_rec_mutex_lock (settings->mutex);
826 if (fluid_settings_get(settings, name, &node))
828 if (node->type == FLUID_STR_TYPE)
830 fluid_str_setting_t *setting = (fluid_str_setting_t *)node;
834 *str = FLUID_STRDUP (setting->value);
835 if (!*str) FLUID_LOG (FLUID_ERR, "Out of memory");
838 if (!setting->value || *str) retval = 1; /* Don't set to 1 if out of memory */
840 else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
842 fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
844 if (setting->hints & FLUID_HINT_TOGGLED)
846 *str = FLUID_STRDUP (setting->value ? "yes" : "no");
847 if (!*str) FLUID_LOG (FLUID_ERR, "Out of memory");
849 if (!setting->value || *str) retval = 1; /* Don't set to 1 if out of memory */
854 fluid_rec_mutex_unlock (settings->mutex);
860 * Get the value of a string setting
861 * @param settings a settings object
862 * @param name a setting's name
863 * @param str Location to store pointer to the settings string value
864 * @return 1 if the value exists, 0 otherwise
867 * If the value does not exists, 'str' is set to NULL. Otherwise, 'str' will
868 * point to the value. The application does not own the returned value and it
869 * is valid only until a new value is assigned to the setting of the given name.
871 * NOTE: In a multi-threaded environment, caller must ensure that the setting
872 * being read by fluid_settings_getstr() is not assigned during the
873 * duration of callers use of the setting's value. Use fluid_settings_copystr()
874 * or fluid_settings_dupstr() which does not have this restriction.
877 fluid_settings_getstr(fluid_settings_t* settings, const char *name, char** str)
879 fluid_setting_node_t *node;
882 fluid_return_val_if_fail (settings != NULL, 0);
883 fluid_return_val_if_fail (name != NULL, 0);
884 fluid_return_val_if_fail (name[0] != '\0', 0);
885 fluid_return_val_if_fail (str != NULL, 0);
887 fluid_rec_mutex_lock (settings->mutex);
889 if (fluid_settings_get(settings, name, &node))
891 if (node->type == FLUID_STR_TYPE)
893 fluid_str_setting_t *setting = (fluid_str_setting_t *)node;
894 *str = setting->value;
897 else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
899 fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
901 if (setting->hints & FLUID_HINT_TOGGLED)
903 *str = setting->value ? "yes" : "no";
910 fluid_rec_mutex_unlock (settings->mutex);
916 * Test a string setting for some value.
918 * @param settings a settings object
919 * @param name a setting's name
920 * @param s a string to be tested
921 * @return 1 if the value exists and is equal to 's', 0 otherwise
924 fluid_settings_str_equal (fluid_settings_t* settings, const char *name, const char *s)
926 fluid_setting_node_t *node;
929 fluid_return_val_if_fail (settings != NULL, 0);
930 fluid_return_val_if_fail (name != NULL, 0);
931 fluid_return_val_if_fail (name[0] != '\0', 0);
932 fluid_return_val_if_fail (s != NULL, 0);
934 fluid_rec_mutex_lock (settings->mutex);
936 if (fluid_settings_get (settings, name, &node))
938 if (node->type == FLUID_STR_TYPE)
940 fluid_str_setting_t *setting = (fluid_str_setting_t *)node;
941 if (setting->value) retval = FLUID_STRCMP (setting->value, s) == 0;
943 else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
945 fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
947 if (setting->hints & FLUID_HINT_TOGGLED)
948 retval = FLUID_STRCMP (setting->value ? "yes" : "no", s) == 0;
952 fluid_rec_mutex_unlock (settings->mutex);
958 * Get the default value of a string setting. Note that the returned string is
959 * not owned by the caller and should not be modified or freed.
961 * @param settings a settings object
962 * @param name a setting's name
963 * @return the default string value of the setting if it exists, NULL otherwise
966 fluid_settings_getstr_default(fluid_settings_t* settings, const char *name)
968 fluid_setting_node_t *node;
971 fluid_return_val_if_fail (settings != NULL, NULL);
972 fluid_return_val_if_fail (name != NULL, NULL);
973 fluid_return_val_if_fail (name[0] != '\0', NULL);
975 fluid_rec_mutex_lock (settings->mutex);
977 if (fluid_settings_get (settings, name, &node))
979 if (node->type == FLUID_STR_TYPE)
981 fluid_str_setting_t* setting = (fluid_str_setting_t*) node;
982 retval = setting->def;
984 else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
986 fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
988 if (setting->hints & FLUID_HINT_TOGGLED)
989 retval = setting->def ? "yes" : "no";
993 fluid_rec_mutex_unlock (settings->mutex);
999 * Add an option to a string setting (like an enumeration value).
1000 * @param settings a settings object
1001 * @param name a setting's name
1002 * @param s option string to add
1003 * @return 1 if the setting exists and option was added, 0 otherwise
1005 * Causes the setting's #FLUID_HINT_OPTIONLIST hint to be set.
1008 fluid_settings_add_option(fluid_settings_t* settings, const char *name, const char *s)
1010 fluid_setting_node_t *node;
1013 fluid_return_val_if_fail (settings != NULL, 0);
1014 fluid_return_val_if_fail (name != NULL, 0);
1015 fluid_return_val_if_fail (name[0] != '\0', 0);
1016 fluid_return_val_if_fail (s != NULL, 0);
1018 fluid_rec_mutex_lock (settings->mutex);
1020 if (fluid_settings_get(settings, name, &node)
1021 && (node->type == FLUID_STR_TYPE)) {
1022 fluid_str_setting_t* setting = (fluid_str_setting_t*) node;
1023 char* copy = FLUID_STRDUP(s);
1024 setting->options = fluid_list_append(setting->options, copy);
1025 setting->hints |= FLUID_HINT_OPTIONLIST;
1029 fluid_rec_mutex_unlock (settings->mutex);
1035 * Remove an option previously assigned by fluid_settings_add_option().
1036 * @param settings a settings object
1037 * @param name a setting's name
1038 * @param s option string to remove
1039 * @return 1 if the setting exists and option was removed, 0 otherwise
1042 fluid_settings_remove_option(fluid_settings_t* settings, const char *name, const char* s)
1044 fluid_setting_node_t *node;
1047 fluid_return_val_if_fail (settings != NULL, 0);
1048 fluid_return_val_if_fail (name != NULL, 0);
1049 fluid_return_val_if_fail (name[0] != '\0', 0);
1050 fluid_return_val_if_fail (s != NULL, 0);
1052 fluid_rec_mutex_lock (settings->mutex);
1054 if (fluid_settings_get(settings, name, &node)
1055 && (node->type == FLUID_STR_TYPE)) {
1057 fluid_str_setting_t* setting = (fluid_str_setting_t*) node;
1058 fluid_list_t* list = setting->options;
1061 char* option = (char*) fluid_list_get(list);
1062 if (FLUID_STRCMP(s, option) == 0) {
1063 FLUID_FREE (option);
1064 setting->options = fluid_list_remove_link(setting->options, list);
1068 list = fluid_list_next(list);
1072 fluid_rec_mutex_unlock (settings->mutex);
1078 * Set a numeric value for a named setting.
1080 * @param settings a settings object
1081 * @param name a setting's name
1082 * @param val new setting's value
1083 * @return 1 if the value has been set, 0 otherwise
1086 fluid_settings_setnum(fluid_settings_t* settings, const char *name, double val)
1088 fluid_setting_node_t *node;
1089 fluid_num_setting_t* setting;
1092 fluid_return_val_if_fail (settings != NULL, 0);
1093 fluid_return_val_if_fail (name != NULL, 0);
1094 fluid_return_val_if_fail (name[0] != '\0', 0);
1096 fluid_rec_mutex_lock (settings->mutex);
1098 if (fluid_settings_get(settings, name, &node)) {
1099 if (node->type == FLUID_NUM_TYPE) {
1100 setting = (fluid_num_setting_t*) node;
1102 if (val < setting->min) val = setting->min;
1103 else if (val > setting->max) val = setting->max;
1105 setting->value = val;
1107 /* Call under lock to keep update() synchronized with the current value */
1108 if (setting->update) (*setting->update)(setting->data, name, val);
1112 /* insert a new setting */
1113 fluid_num_setting_t* setting;
1114 setting = new_fluid_num_setting(-1e10, 1e10, 0.0f, 0, NULL, NULL);
1115 setting->value = val;
1116 retval = fluid_settings_set(settings, name, setting);
1117 if (retval != 1) delete_fluid_num_setting (setting);
1120 fluid_rec_mutex_unlock (settings->mutex);
1126 * Get the numeric value of a named setting
1128 * @param settings a settings object
1129 * @param name a setting's name
1130 * @param val variable pointer to receive the setting's numeric value
1131 * @return 1 if the value exists, 0 otherwise
1134 fluid_settings_getnum(fluid_settings_t* settings, const char *name, double* val)
1136 fluid_setting_node_t *node;
1139 fluid_return_val_if_fail (settings != NULL, 0);
1140 fluid_return_val_if_fail (name != NULL, 0);
1141 fluid_return_val_if_fail (name[0] != '\0', 0);
1142 fluid_return_val_if_fail (val != NULL, 0);
1144 fluid_rec_mutex_lock (settings->mutex);
1146 if (fluid_settings_get(settings, name, &node)
1147 && (node->type == FLUID_NUM_TYPE)) {
1148 fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
1149 *val = setting->value;
1153 fluid_rec_mutex_unlock (settings->mutex);
1159 * Get the range of values of a numeric setting
1161 * @param settings a settings object
1162 * @param name a setting's name
1163 * @param min setting's range lower limit
1164 * @param max setting's range upper limit
1167 fluid_settings_getnum_range(fluid_settings_t* settings, const char *name,
1168 double* min, double* max)
1170 fluid_setting_node_t *node;
1172 fluid_return_if_fail (settings != NULL);
1173 fluid_return_if_fail (name != NULL);
1174 fluid_return_if_fail (name[0] != '\0');
1175 fluid_return_if_fail (min != NULL);
1176 fluid_return_if_fail (max != NULL);
1178 fluid_rec_mutex_lock (settings->mutex);
1180 if (fluid_settings_get(settings, name, &node)
1181 && (node->type == FLUID_NUM_TYPE)) {
1182 fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
1183 *min = setting->min;
1184 *max = setting->max;
1187 fluid_rec_mutex_unlock (settings->mutex);
1191 * Get the default value of a named numeric (double) setting
1193 * @param settings a settings object
1194 * @param name a setting's name
1195 * @return the default value if the named setting exists, 0.0f otherwise
1198 fluid_settings_getnum_default(fluid_settings_t* settings, const char *name)
1200 fluid_setting_node_t *node;
1201 double retval = 0.0;
1203 fluid_return_val_if_fail (settings != NULL, 0.0);
1204 fluid_return_val_if_fail (name != NULL, 0.0);
1205 fluid_return_val_if_fail (name[0] != '\0', 0.0);
1207 fluid_rec_mutex_lock (settings->mutex);
1209 if (fluid_settings_get(settings, name, &node)
1210 && (node->type == FLUID_NUM_TYPE)) {
1211 fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
1212 retval = setting->def;
1215 fluid_rec_mutex_unlock (settings->mutex);
1221 * Set an integer value for a setting
1223 * @param settings a settings object
1224 * @param name a setting's name
1225 * @param val new setting's integer value
1226 * @return 1 if the value has been set, 0 otherwise
1229 fluid_settings_setint(fluid_settings_t* settings, const char *name, int val)
1231 fluid_setting_node_t *node;
1232 fluid_int_setting_t* setting;
1235 fluid_return_val_if_fail (settings != NULL, 0);
1236 fluid_return_val_if_fail (name != NULL, 0);
1237 fluid_return_val_if_fail (name[0] != '\0', 0);
1239 fluid_rec_mutex_lock (settings->mutex);
1241 if (fluid_settings_get(settings, name, &node)) {
1242 if (node->type == FLUID_INT_TYPE) {
1243 setting = (fluid_int_setting_t*) node;
1245 if (val < setting->min) val = setting->min;
1246 else if (val > setting->max) val = setting->max;
1248 setting->value = val;
1250 /* Call under lock to keep update() synchronized with the current value */
1251 if (setting->update) (*setting->update)(setting->data, name, val);
1255 /* insert a new setting */
1256 fluid_int_setting_t* setting;
1257 setting = new_fluid_int_setting(INT_MIN, INT_MAX, 0, 0, NULL, NULL);
1258 setting->value = val;
1259 retval = fluid_settings_set(settings, name, setting);
1260 if (retval != 1) delete_fluid_int_setting (setting);
1263 fluid_rec_mutex_unlock (settings->mutex);
1269 * Get an integer value setting.
1271 * @param settings a settings object
1272 * @param name a setting's name
1273 * @param val pointer to a variable to receive the setting's integer value
1274 * @return 1 if the value exists, 0 otherwise
1277 fluid_settings_getint(fluid_settings_t* settings, const char *name, int* val)
1279 fluid_setting_node_t *node;
1282 fluid_return_val_if_fail (settings != NULL, 0);
1283 fluid_return_val_if_fail (name != NULL, 0);
1284 fluid_return_val_if_fail (name[0] != '\0', 0);
1285 fluid_return_val_if_fail (val != NULL, 0);
1287 fluid_rec_mutex_lock (settings->mutex);
1289 if (fluid_settings_get(settings, name, &node)
1290 && (node->type == FLUID_INT_TYPE)) {
1291 fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
1292 *val = setting->value;
1296 fluid_rec_mutex_unlock (settings->mutex);
1302 * Get the range of values of an integer setting
1303 * @param settings a settings object
1304 * @param name a setting's name
1305 * @param min setting's range lower limit
1306 * @param max setting's range upper limit
1309 fluid_settings_getint_range(fluid_settings_t* settings, const char *name,
1312 fluid_setting_node_t *node;
1314 fluid_return_if_fail (settings != NULL);
1315 fluid_return_if_fail (name != NULL);
1316 fluid_return_if_fail (name[0] != '\0');
1317 fluid_return_if_fail (min != NULL);
1318 fluid_return_if_fail (max != NULL);
1320 fluid_rec_mutex_lock (settings->mutex);
1322 if (fluid_settings_get(settings, name, &node)
1323 && (node->type == FLUID_INT_TYPE)) {
1324 fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
1325 *min = setting->min;
1326 *max = setting->max;
1329 fluid_rec_mutex_unlock (settings->mutex);
1333 * Get the default value of an integer setting.
1335 * @param settings a settings object
1336 * @param name a setting's name
1337 * @return the setting's default integer value it it exists, zero otherwise
1340 fluid_settings_getint_default(fluid_settings_t* settings, const char *name)
1342 fluid_setting_node_t *node;
1345 fluid_return_val_if_fail (settings != NULL, 0);
1346 fluid_return_val_if_fail (name != NULL, 0);
1347 fluid_return_val_if_fail (name[0] != '\0', 0);
1349 fluid_rec_mutex_lock (settings->mutex);
1351 if (fluid_settings_get(settings, name, &node)
1352 && (node->type == FLUID_INT_TYPE)) {
1353 fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
1354 retval = setting->def;
1357 fluid_rec_mutex_unlock (settings->mutex);
1363 * Iterate the available options for a named string setting, calling the provided
1364 * callback function for each existing option.
1366 * @param settings a settings object
1367 * @param name a setting's name
1368 * @param data any user provided pointer
1369 * @param func callback function to be called on each iteration
1371 * NOTE: Starting with FluidSynth 1.1.0 the \a func callback is called for each
1372 * option in alphabetical order. Sort order was undefined in previous versions.
1375 fluid_settings_foreach_option (fluid_settings_t* settings, const char *name,
1376 void* data, fluid_settings_foreach_option_t func)
1378 fluid_setting_node_t *node;
1379 fluid_str_setting_t *setting;
1380 fluid_list_t *p, *newlist = NULL;
1382 fluid_return_if_fail (settings != NULL);
1383 fluid_return_if_fail (name != NULL);
1384 fluid_return_if_fail (name[0] != '\0');
1385 fluid_return_if_fail (func != NULL);
1387 fluid_rec_mutex_lock (settings->mutex); /* ++ lock */
1389 if (!fluid_settings_get (settings, name, &node) || node->type != FLUID_STR_TYPE)
1391 fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */
1395 setting = (fluid_str_setting_t*)node;
1397 /* Duplicate option list */
1398 for (p = setting->options; p; p = p->next)
1399 newlist = fluid_list_append (newlist, fluid_list_get (p));
1402 newlist = fluid_list_sort (newlist, fluid_list_str_compare_func);
1404 for (p = newlist; p; p = p->next)
1405 (*func)(data, (char *)name, (char *)fluid_list_get (p));
1407 fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */
1409 delete_fluid_list (newlist);
1413 * Count option string values for a string setting.
1414 * @param settings a settings object
1415 * @param name Name of setting
1416 * @return Count of options for this string setting (0 if none, -1 if not found
1417 * or not a string setting)
1421 fluid_settings_option_count (fluid_settings_t *settings, const char *name)
1423 fluid_setting_node_t *node;
1426 fluid_return_val_if_fail (settings != NULL, -1);
1427 fluid_return_val_if_fail (name != NULL, -1);
1428 fluid_return_val_if_fail (name[0] != '\0', -1);
1430 fluid_rec_mutex_lock (settings->mutex);
1431 if (fluid_settings_get(settings, name, &node) && node->type == FLUID_STR_TYPE)
1432 count = fluid_list_size (((fluid_str_setting_t *)node)->options);
1433 fluid_rec_mutex_unlock (settings->mutex);
1439 * Concatenate options for a string setting together with a separator between.
1440 * @param settings Settings object
1441 * @param name Settings name
1442 * @param separator String to use between options (NULL to use ", ")
1443 * @return Newly allocated string or NULL on error (out of memory, not a valid
1444 * setting \a name or not a string setting). Free the string when finished with it.
1448 fluid_settings_option_concat (fluid_settings_t *settings, const char *name,
1449 const char *separator)
1451 fluid_setting_node_t *node;
1452 fluid_str_setting_t *setting;
1453 fluid_list_t *p, *newlist = NULL;
1457 fluid_return_val_if_fail (settings != NULL, NULL);
1458 fluid_return_val_if_fail (name != NULL, NULL);
1459 fluid_return_val_if_fail (name[0] != '\0', NULL);
1461 if (!separator) separator = ", ";
1463 fluid_rec_mutex_lock (settings->mutex); /* ++ lock */
1465 if (!fluid_settings_get (settings, name, &node) || node->type != FLUID_STR_TYPE)
1467 fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */
1471 setting = (fluid_str_setting_t*)node;
1473 /* Duplicate option list, count options and get total string length */
1474 for (p = setting->options, count = 0, len = 0; p; p = p->next, count++)
1476 option = fluid_list_get (p);
1480 newlist = fluid_list_append (newlist, option);
1481 len += strlen (option);
1485 if (count > 1) len += (count - 1) * strlen (separator);
1486 len++; /* For terminator */
1489 newlist = fluid_list_sort (newlist, fluid_list_str_compare_func);
1491 str = FLUID_MALLOC (len);
1496 for (p = newlist; p; p = p->next)
1498 option = fluid_list_get (p);
1499 strcat (str, option);
1500 if (p->next) strcat (str, separator);
1504 fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */
1506 delete_fluid_list (newlist);
1508 if (!str) FLUID_LOG (FLUID_ERR, "Out of memory");
1513 /* Structure passed to fluid_settings_foreach_iter recursive function */
1516 char path[MAX_SETTINGS_LABEL+1]; /* Maximum settings label length */
1517 fluid_list_t *names; /* For fluid_settings_foreach() */
1518 } fluid_settings_foreach_bag_t;
1521 fluid_settings_foreach_iter (void* key, void* value, void* data)
1523 fluid_settings_foreach_bag_t *bag = data;
1525 fluid_setting_node_t *node = value;
1529 pathlen = strlen (bag->path);
1533 bag->path[pathlen] = '.';
1534 bag->path[pathlen + 1] = 0;
1537 strcat (bag->path, keystr);
1539 switch (node->type) {
1540 case FLUID_NUM_TYPE:
1541 case FLUID_INT_TYPE:
1542 case FLUID_STR_TYPE:
1543 s = FLUID_STRDUP (bag->path);
1544 if (s) bag->names = fluid_list_append (bag->names, s);
1546 case FLUID_SET_TYPE:
1547 fluid_hashtable_foreach(((fluid_set_setting_t *)value)->hashtable,
1548 fluid_settings_foreach_iter, bag);
1552 bag->path[pathlen] = 0;
1558 * Iterate the existing settings defined in a settings object, calling the
1559 * provided callback function for each setting.
1561 * @param settings a settings object
1562 * @param data any user provided pointer
1563 * @param func callback function to be called on each iteration
1565 * NOTE: Starting with FluidSynth 1.1.0 the \a func callback is called for each
1566 * setting in alphabetical order. Sort order was undefined in previous versions.
1569 fluid_settings_foreach (fluid_settings_t* settings, void* data,
1570 fluid_settings_foreach_t func)
1572 fluid_settings_foreach_bag_t bag;
1573 fluid_setting_node_t *node;
1577 fluid_return_if_fail (settings != NULL);
1578 fluid_return_if_fail (func != NULL);
1583 fluid_rec_mutex_lock (settings->mutex);
1585 /* Add all node names to the bag.names list */
1586 fluid_hashtable_foreach (settings, fluid_settings_foreach_iter, &bag);
1589 bag.names = fluid_list_sort (bag.names, fluid_list_str_compare_func);
1591 /* Loop over names and call the callback */
1592 for (p = bag.names; p; p = p->next)
1594 r = fluid_settings_get (settings, (char *)(p->data), &node);
1595 if (r && node) (*func) (data, (char *)(p->data), node->type);
1596 FLUID_FREE (p->data); /* -- Free name */
1599 fluid_rec_mutex_unlock (settings->mutex);
1601 delete_fluid_list (bag.names); /* -- Free names list */