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 Lesser General Public License
7 * as published by the Free Software Foundation; either version 2.1 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 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser 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 "fluid_sys.h"
22 #include "fluid_hash.h"
23 #include "fluid_synth.h"
24 #include "fluid_settings.h"
25 #include "fluid_midi.h"
27 /* maximum allowed components of a settings variable (separated by '.') */
28 #define MAX_SETTINGS_TOKENS 8 /* currently only a max of 3 are used */
29 #define MAX_SETTINGS_LABEL 256 /* max length of a settings variable label */
31 static void fluid_settings_init(fluid_settings_t *settings);
32 static void fluid_settings_key_destroy_func(void *value);
33 static void fluid_settings_value_destroy_func(void *value);
34 static int fluid_settings_tokenize(const char *s, char *buf, char **ptr);
36 /* Common structure to all settings nodes */
42 fluid_list_t *options;
43 fluid_str_update_t update;
45 } fluid_str_setting_t;
54 fluid_num_update_t update;
56 } fluid_num_setting_t;
65 fluid_int_update_t update;
67 } fluid_int_setting_t;
71 fluid_hashtable_t *hashtable;
72 } fluid_set_setting_t;
76 int type; /**< fluid_types_enum */
80 fluid_str_setting_t str;
81 fluid_num_setting_t num;
82 fluid_int_setting_t i;
83 fluid_set_setting_t set;
85 } fluid_setting_node_t;
87 static fluid_setting_node_t *
88 new_fluid_str_setting(const char *value, const char *def, int hints)
90 fluid_setting_node_t *node;
91 fluid_str_setting_t *str;
93 node = FLUID_NEW(fluid_setting_node_t);
97 FLUID_LOG(FLUID_ERR, "Out of memory");
101 node->type = FLUID_STR_TYPE;
104 str->value = value ? FLUID_STRDUP(value) : NULL;
105 str->def = def ? FLUID_STRDUP(def) : NULL;
114 delete_fluid_str_setting(fluid_setting_node_t *node)
116 fluid_return_if_fail(node != NULL);
118 FLUID_ASSERT(node->type == FLUID_STR_TYPE);
120 FLUID_FREE(node->str.value);
121 FLUID_FREE(node->str.def);
123 if(node->str.options)
125 fluid_list_t *list = node->str.options;
129 FLUID_FREE(list->data);
130 list = fluid_list_next(list);
133 delete_fluid_list(node->str.options);
140 static fluid_setting_node_t *
141 new_fluid_num_setting(double min, double max, double def, int hints)
143 fluid_setting_node_t *node;
144 fluid_num_setting_t *num;
146 node = FLUID_NEW(fluid_setting_node_t);
150 FLUID_LOG(FLUID_ERR, "Out of memory");
154 node->type = FLUID_NUM_TYPE;
169 delete_fluid_num_setting(fluid_setting_node_t *node)
171 fluid_return_if_fail(node != NULL);
173 FLUID_ASSERT(node->type == FLUID_NUM_TYPE);
177 static fluid_setting_node_t *
178 new_fluid_int_setting(int min, int max, int def, int hints)
180 fluid_setting_node_t *node;
181 fluid_int_setting_t *i;
183 node = FLUID_NEW(fluid_setting_node_t);
187 FLUID_LOG(FLUID_ERR, "Out of memory");
191 node->type = FLUID_INT_TYPE;
205 delete_fluid_int_setting(fluid_setting_node_t *node)
207 fluid_return_if_fail(node != NULL);
209 FLUID_ASSERT(node->type == FLUID_INT_TYPE);
213 static fluid_setting_node_t *
214 new_fluid_set_setting(void)
216 fluid_setting_node_t *node;
217 fluid_set_setting_t *set;
219 node = FLUID_NEW(fluid_setting_node_t);
223 FLUID_LOG(FLUID_ERR, "Out of memory");
227 node->type = FLUID_SET_TYPE;
230 set->hashtable = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal,
231 fluid_settings_key_destroy_func,
232 fluid_settings_value_destroy_func);
244 delete_fluid_set_setting(fluid_setting_node_t *node)
246 fluid_return_if_fail(node != NULL);
248 FLUID_ASSERT(node->type == FLUID_SET_TYPE);
249 delete_fluid_hashtable(node->set.hashtable);
254 * Create a new settings object
255 * @return the pointer to the settings object
258 new_fluid_settings(void)
260 fluid_settings_t *settings;
262 settings = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal,
263 fluid_settings_key_destroy_func,
264 fluid_settings_value_destroy_func);
271 fluid_rec_mutex_init(settings->mutex);
272 fluid_settings_init(settings);
277 * Delete the provided settings object
278 * @param settings a settings object
281 delete_fluid_settings(fluid_settings_t *settings)
283 fluid_return_if_fail(settings != NULL);
285 fluid_rec_mutex_destroy(settings->mutex);
286 delete_fluid_hashtable(settings);
289 /* Settings hash key destroy function */
291 fluid_settings_key_destroy_func(void *value)
293 FLUID_FREE(value); /* Free the string key value */
296 /* Settings hash value destroy function */
298 fluid_settings_value_destroy_func(void *value)
300 fluid_setting_node_t *node = value;
305 delete_fluid_num_setting(node);
309 delete_fluid_int_setting(node);
313 delete_fluid_str_setting(node);
317 delete_fluid_set_setting(node);
323 fluid_settings_init(fluid_settings_t *settings)
325 fluid_return_if_fail(settings != NULL);
327 fluid_synth_settings(settings);
329 fluid_shell_settings(settings);
330 fluid_player_settings(settings);
331 fluid_file_renderer_settings(settings);
332 fluid_audio_driver_settings(settings);
333 fluid_midi_driver_settings(settings);
338 fluid_settings_tokenize(const char *s, char *buf, char **ptr)
343 if(FLUID_STRLEN(s) > MAX_SETTINGS_LABEL)
345 FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars",
350 FLUID_STRCPY(buf, s); /* copy string to buffer, since it gets modified */
353 while((tok = fluid_strtok(&tokstr, ".")))
355 if(n >= MAX_SETTINGS_TOKENS)
357 FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max token count of %d",
358 MAX_SETTINGS_TOKENS);
371 * Get a setting name, value and type
373 * @param settings a settings object
374 * @param name Settings name
375 * @param value Location to store setting node if found
376 * @return #FLUID_OK if the node exists, #FLUID_FAILED otherwise
379 fluid_settings_get(fluid_settings_t *settings, const char *name,
380 fluid_setting_node_t **value)
382 fluid_hashtable_t *table = settings;
383 fluid_setting_node_t *node = NULL;
384 char *tokens[MAX_SETTINGS_TOKENS];
385 char buf[MAX_SETTINGS_LABEL + 1];
389 ntokens = fluid_settings_tokenize(name, buf, tokens);
391 if(table == NULL || ntokens <= 0)
396 for(n = 0; n < ntokens; n++)
399 node = fluid_hashtable_lookup(table, tokens[n]);
406 table = (node->type == FLUID_SET_TYPE) ? node->set.hashtable : NULL;
418 * Set a setting name, value and type, replacing it if already exists
420 * @param settings a settings object
421 * @param name Settings name
422 * @param value Node instance to assign (used directly)
423 * @return #FLUID_OK if the value has been set, #FLUID_FAILED otherwise
426 fluid_settings_set(fluid_settings_t *settings, const char *name, fluid_setting_node_t *value)
428 fluid_hashtable_t *table = settings;
429 fluid_setting_node_t *node;
430 char *tokens[MAX_SETTINGS_TOKENS];
431 char buf[MAX_SETTINGS_LABEL + 1];
435 num = fluid_settings_tokenize(name, buf, tokens);
444 for(n = 0; n < num; n++)
447 node = fluid_hashtable_lookup(table, tokens[n]);
452 if(node->type == FLUID_SET_TYPE)
454 table = node->set.hashtable;
458 /* path ends prematurely */
459 FLUID_LOG(FLUID_WARN, "'%s' is not a node. Name of the setting was '%s'", tokens[n], name);
466 /* create a new node */
467 fluid_setting_node_t *setnode;
469 dupname = FLUID_STRDUP(tokens[n]);
470 setnode = new_fluid_set_setting();
472 if(!dupname || !setnode)
480 FLUID_LOG(FLUID_ERR, "Out of memory");
485 delete_fluid_set_setting(setnode);
491 fluid_hashtable_insert(table, dupname, setnode);
492 table = setnode->set.hashtable;
496 dupname = FLUID_STRDUP(tokens[num]);
500 FLUID_LOG(FLUID_ERR, "Out of memory");
504 fluid_hashtable_insert(table, dupname, value);
510 * Registers a new string value for the specified setting.
512 * @param settings a settings object
513 * @param name the setting's name
514 * @param def the default value for the setting
515 * @param hints the hints for the setting
516 * @return #FLUID_OK if the value has been register correctly, #FLUID_FAILED otherwise
519 fluid_settings_register_str(fluid_settings_t *settings, const char *name, const char *def, int hints)
521 fluid_setting_node_t *node;
522 int retval = FLUID_FAILED;
524 fluid_return_val_if_fail(settings != NULL, retval);
525 fluid_return_val_if_fail(name != NULL, retval);
526 fluid_return_val_if_fail(name[0] != '\0', retval);
528 fluid_rec_mutex_lock(settings->mutex);
530 if(fluid_settings_get(settings, name, &node) != FLUID_OK)
532 node = new_fluid_str_setting(def, def, hints);
533 retval = fluid_settings_set(settings, name, node);
535 if(retval != FLUID_OK)
537 delete_fluid_str_setting(node);
542 /* if variable already exists, don't change its value. */
543 if(node->type == FLUID_STR_TYPE)
545 fluid_str_setting_t *setting = &node->str;
546 setting->def = def ? FLUID_STRDUP(def) : NULL;
547 setting->hints = hints;
552 FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
556 fluid_rec_mutex_unlock(settings->mutex);
562 * Registers a new float value for the specified setting.
564 * @param settings a settings object
565 * @param name the setting's name
566 * @param def the default value for the setting
567 * @param min the smallest allowed value for the setting
568 * @param max the largest allowed value for the setting
569 * @param hints the hints for the setting
570 * @return #FLUID_OK if the value has been register correctly, #FLUID_FAILED otherwise
573 fluid_settings_register_num(fluid_settings_t *settings, const char *name, double def,
574 double min, double max, int hints)
576 fluid_setting_node_t *node;
577 int retval = FLUID_FAILED;
579 fluid_return_val_if_fail(settings != NULL, retval);
580 fluid_return_val_if_fail(name != NULL, retval);
581 fluid_return_val_if_fail(name[0] != '\0', retval);
583 /* For now, all floating point settings are bounded below and above */
584 hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE;
586 fluid_rec_mutex_lock(settings->mutex);
588 if(fluid_settings_get(settings, name, &node) != FLUID_OK)
590 /* insert a new setting */
591 node = new_fluid_num_setting(min, max, def, hints);
592 retval = fluid_settings_set(settings, name, node);
594 if(retval != FLUID_OK)
596 delete_fluid_num_setting(node);
601 if(node->type == FLUID_NUM_TYPE)
603 /* update the existing setting but don't change its value */
604 fluid_num_setting_t *setting = &node->num;
608 setting->hints = hints;
614 FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
618 fluid_rec_mutex_unlock(settings->mutex);
624 * Registers a new integer value for the specified setting.
626 * @param settings a settings object
627 * @param name the setting's name
628 * @param def the default value for the setting
629 * @param min the smallest allowed value for the setting
630 * @param max the largest allowed value for the setting
631 * @param hints the hints for the setting
632 * @return #FLUID_OK if the value has been register correctly, #FLUID_FAILED otherwise
635 fluid_settings_register_int(fluid_settings_t *settings, const char *name, int def,
636 int min, int max, int hints)
638 fluid_setting_node_t *node;
639 int retval = FLUID_FAILED;
641 fluid_return_val_if_fail(settings != NULL, retval);
642 fluid_return_val_if_fail(name != NULL, retval);
643 fluid_return_val_if_fail(name[0] != '\0', retval);
645 /* For now, all integer settings are bounded below and above */
646 hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE;
648 fluid_rec_mutex_lock(settings->mutex);
650 if(fluid_settings_get(settings, name, &node) != FLUID_OK)
652 /* insert a new setting */
653 node = new_fluid_int_setting(min, max, def, hints);
654 retval = fluid_settings_set(settings, name, node);
656 if(retval != FLUID_OK)
658 delete_fluid_int_setting(node);
663 if(node->type == FLUID_INT_TYPE)
665 /* update the existing setting but don't change its value */
666 fluid_int_setting_t *setting = &node->i;
670 setting->hints = hints;
676 FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
680 fluid_rec_mutex_unlock(settings->mutex);
686 * Registers a callback for the specified string setting.
688 * @param settings a settings object
689 * @param name the setting's name
690 * @param callback an update function for the setting
691 * @param data user supplied data passed to the update function
692 * @return #FLUID_OK if the callback has been set, #FLUID_FAILED otherwise
694 int fluid_settings_callback_str(fluid_settings_t *settings, const char *name,
695 fluid_str_update_t callback, void *data)
697 fluid_setting_node_t *node;
698 fluid_str_setting_t *setting;
700 fluid_return_val_if_fail(settings != NULL, FLUID_FAILED);
701 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
702 fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED);
704 fluid_rec_mutex_lock(settings->mutex);
706 if((fluid_settings_get(settings, name, &node) != FLUID_OK)
707 || node->type != FLUID_STR_TYPE)
709 fluid_rec_mutex_unlock(settings->mutex);
713 setting = &node->str;
714 setting->update = callback;
715 setting->data = data;
717 fluid_rec_mutex_unlock(settings->mutex);
722 * Registers a callback for the specified numeric setting.
724 * @param settings a settings object
725 * @param name the setting's name
726 * @param callback an update function for the setting
727 * @param data user supplied data passed to the update function
728 * @return #FLUID_OK if the callback has been set, #FLUID_FAILED otherwise
730 int fluid_settings_callback_num(fluid_settings_t *settings, const char *name,
731 fluid_num_update_t callback, void *data)
733 fluid_setting_node_t *node;
734 fluid_num_setting_t *setting;
736 fluid_return_val_if_fail(settings != NULL, FLUID_FAILED);
737 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
738 fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED);
740 fluid_rec_mutex_lock(settings->mutex);
742 if((fluid_settings_get(settings, name, &node) != FLUID_OK)
743 || node->type != FLUID_NUM_TYPE)
745 fluid_rec_mutex_unlock(settings->mutex);
749 setting = &node->num;
750 setting->update = callback;
751 setting->data = data;
753 fluid_rec_mutex_unlock(settings->mutex);
758 * Registers a callback for the specified int setting.
760 * @param settings a settings object
761 * @param name the setting's name
762 * @param callback an update function for the setting
763 * @param data user supplied data passed to the update function
764 * @return #FLUID_OK if the callback has been set, #FLUID_FAILED otherwise
766 int fluid_settings_callback_int(fluid_settings_t *settings, const char *name,
767 fluid_int_update_t callback, void *data)
769 fluid_setting_node_t *node;
770 fluid_int_setting_t *setting;
772 fluid_return_val_if_fail(settings != NULL, FLUID_FAILED);
773 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
774 fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED);
776 fluid_rec_mutex_lock(settings->mutex);
778 if((fluid_settings_get(settings, name, &node) != FLUID_OK)
779 || node->type != FLUID_INT_TYPE)
781 fluid_rec_mutex_unlock(settings->mutex);
786 setting->update = callback;
787 setting->data = data;
789 fluid_rec_mutex_unlock(settings->mutex);
794 * Get the type of the setting with the given name
796 * @param settings a settings object
797 * @param name a setting's name
798 * @return the type for the named setting (see #fluid_types_enum), or #FLUID_NO_TYPE when it does not exist
801 fluid_settings_get_type(fluid_settings_t *settings, const char *name)
803 fluid_setting_node_t *node;
804 int type = FLUID_NO_TYPE;
806 fluid_return_val_if_fail(settings != NULL, type);
807 fluid_return_val_if_fail(name != NULL, type);
808 fluid_return_val_if_fail(name[0] != '\0', type);
810 fluid_rec_mutex_lock(settings->mutex);
812 if(fluid_settings_get(settings, name, &node) == FLUID_OK)
817 fluid_rec_mutex_unlock(settings->mutex);
823 * Get the hints for the named setting as an integer bitmap
825 * @param settings a settings object
826 * @param name a setting's name
827 * @param hints set to the hints associated to the setting if it exists
828 * @return #FLUID_OK if hints associated to the named setting exist, #FLUID_FAILED otherwise
831 fluid_settings_get_hints(fluid_settings_t *settings, const char *name, int *hints)
833 fluid_setting_node_t *node;
834 int retval = FLUID_FAILED;
836 fluid_return_val_if_fail(settings != NULL, retval);
837 fluid_return_val_if_fail(name != NULL, retval);
838 fluid_return_val_if_fail(name[0] != '\0', retval);
840 fluid_rec_mutex_lock(settings->mutex);
842 if(fluid_settings_get(settings, name, &node) == FLUID_OK)
844 if(node->type == FLUID_NUM_TYPE)
846 fluid_num_setting_t *setting = &node->num;
847 *hints = setting->hints;
850 else if(node->type == FLUID_STR_TYPE)
852 fluid_str_setting_t *setting = &node->str;
853 *hints = setting->hints;
856 else if(node->type == FLUID_INT_TYPE)
858 fluid_int_setting_t *setting = &node->i;
859 *hints = setting->hints;
864 fluid_rec_mutex_unlock(settings->mutex);
870 * Ask whether the setting is changeable in real-time.
872 * @param settings a settings object
873 * @param name a setting's name
874 * @return TRUE if the setting is changeable in real-time, FALSE otherwise
877 fluid_settings_is_realtime(fluid_settings_t *settings, const char *name)
879 fluid_setting_node_t *node;
880 int isrealtime = FALSE;
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);
886 fluid_rec_mutex_lock(settings->mutex);
888 if(fluid_settings_get(settings, name, &node) == FLUID_OK)
890 if(node->type == FLUID_NUM_TYPE)
892 fluid_num_setting_t *setting = &node->num;
893 isrealtime = setting->update != NULL;
895 else if(node->type == FLUID_STR_TYPE)
897 fluid_str_setting_t *setting = &node->str;
898 isrealtime = setting->update != NULL;
900 else if(node->type == FLUID_INT_TYPE)
902 fluid_int_setting_t *setting = &node->i;
903 isrealtime = setting->update != NULL;
907 fluid_rec_mutex_unlock(settings->mutex);
913 * Set a string value for a named setting
915 * @param settings a settings object
916 * @param name a setting's name
917 * @param str new string value
918 * @return #FLUID_OK if the value has been set, #FLUID_FAILED otherwise
921 fluid_settings_setstr(fluid_settings_t *settings, const char *name, const char *str)
923 fluid_setting_node_t *node;
924 fluid_str_setting_t *setting;
925 char *new_value = NULL;
926 fluid_str_update_t callback = NULL;
929 fluid_return_val_if_fail(settings != NULL, FLUID_FAILED);
930 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
931 fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED);
933 fluid_rec_mutex_lock(settings->mutex);
935 if((fluid_settings_get(settings, name, &node) != FLUID_OK)
936 || (node->type != FLUID_STR_TYPE))
941 setting = &node->str;
945 FLUID_FREE(setting->value);
950 new_value = FLUID_STRDUP(str);
952 if(new_value == NULL)
954 FLUID_LOG(FLUID_ERR, "Out of memory");
959 setting->value = new_value;
961 callback = setting->update;
962 data = setting->data;
964 /* Release the mutex before calling the update callback, to avoid
965 * possible deadlocks with FluidSynths API lock */
966 fluid_rec_mutex_unlock(settings->mutex);
970 (*callback)(data, name, new_value);
976 fluid_rec_mutex_unlock(settings->mutex);
981 * Copy the value of a string setting into the provided buffer (thread safe)
982 * @param settings a settings object
983 * @param name a setting's name
984 * @param str Caller supplied buffer to copy string value to
985 * @param len Size of 'str' buffer (no more than len bytes will be written, which
986 * will always include a zero terminator)
987 * @return #FLUID_OK if the value exists, #FLUID_FAILED otherwise
990 * @note A size of 256 should be more than sufficient for the string buffer.
993 fluid_settings_copystr(fluid_settings_t *settings, const char *name,
996 fluid_setting_node_t *node;
997 int retval = FLUID_FAILED;
999 fluid_return_val_if_fail(settings != NULL, retval);
1000 fluid_return_val_if_fail(name != NULL, retval);
1001 fluid_return_val_if_fail(name[0] != '\0', retval);
1002 fluid_return_val_if_fail(str != NULL, retval);
1003 fluid_return_val_if_fail(len > 0, retval);
1007 fluid_rec_mutex_lock(settings->mutex);
1009 if(fluid_settings_get(settings, name, &node) == FLUID_OK)
1011 if(node->type == FLUID_STR_TYPE)
1013 fluid_str_setting_t *setting = &node->str;
1017 FLUID_STRNCPY(str, setting->value, len);
1022 else if(node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
1024 fluid_int_setting_t *setting = &node->i;
1026 if(setting->hints & FLUID_HINT_TOGGLED)
1028 FLUID_STRNCPY(str, setting->value ? "yes" : "no", len);
1035 fluid_rec_mutex_unlock(settings->mutex);
1041 * Duplicate the value of a string setting
1042 * @param settings a settings object
1043 * @param name a setting's name
1044 * @param str Location to store pointer to allocated duplicate string
1045 * @return #FLUID_OK if the value exists and was successfully duplicated, #FLUID_FAILED otherwise
1048 * Like fluid_settings_copystr() but allocates a new copy of the string. Caller
1049 * owns the string and should free it with free() when done using it.
1052 fluid_settings_dupstr(fluid_settings_t *settings, const char *name, char **str)
1054 fluid_setting_node_t *node;
1055 int retval = FLUID_FAILED;
1057 fluid_return_val_if_fail(settings != NULL, retval);
1058 fluid_return_val_if_fail(name != NULL, retval);
1059 fluid_return_val_if_fail(name[0] != '\0', retval);
1060 fluid_return_val_if_fail(str != NULL, retval);
1062 fluid_rec_mutex_lock(settings->mutex);
1064 if(fluid_settings_get(settings, name, &node) == FLUID_OK)
1066 if(node->type == FLUID_STR_TYPE)
1068 fluid_str_setting_t *setting = &node->str;
1072 *str = FLUID_STRDUP(setting->value);
1076 FLUID_LOG(FLUID_ERR, "Out of memory");
1080 if(!setting->value || *str)
1082 retval = FLUID_OK; /* Don't set to FLUID_OK if out of memory */
1085 else if(node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
1087 fluid_int_setting_t *setting = &node->i;
1089 if(setting->hints & FLUID_HINT_TOGGLED)
1091 *str = FLUID_STRDUP(setting->value ? "yes" : "no");
1095 FLUID_LOG(FLUID_ERR, "Out of memory");
1098 if(!setting->value || *str)
1100 retval = FLUID_OK; /* Don't set to FLUID_OK if out of memory */
1106 fluid_rec_mutex_unlock(settings->mutex);
1113 * Test a string setting for some value.
1115 * @param settings a settings object
1116 * @param name a setting's name
1117 * @param s a string to be tested
1118 * @return TRUE if the value exists and is equal to 's', FALSE otherwise
1121 fluid_settings_str_equal(fluid_settings_t *settings, const char *name, const char *s)
1123 fluid_setting_node_t *node;
1126 fluid_return_val_if_fail(settings != NULL, retval);
1127 fluid_return_val_if_fail(name != NULL, retval);
1128 fluid_return_val_if_fail(name[0] != '\0', retval);
1129 fluid_return_val_if_fail(s != NULL, retval);
1131 fluid_rec_mutex_lock(settings->mutex);
1133 if(fluid_settings_get(settings, name, &node) == FLUID_OK)
1135 if(node->type == FLUID_STR_TYPE)
1137 fluid_str_setting_t *setting = &node->str;
1141 retval = FLUID_STRCMP(setting->value, s) == 0;
1144 else if(node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
1146 fluid_int_setting_t *setting = &node->i;
1148 if(setting->hints & FLUID_HINT_TOGGLED)
1150 retval = FLUID_STRCMP(setting->value ? "yes" : "no", s) == 0;
1155 fluid_rec_mutex_unlock(settings->mutex);
1161 * Get the default value of a string setting. Note that the returned string is
1162 * not owned by the caller and should not be modified or freed.
1164 * @param settings a settings object
1165 * @param name a setting's name
1166 * @param def the default string value of the setting if it exists
1167 * @return FLUID_OK on success, FLUID_FAILED otherwise
1170 fluid_settings_getstr_default(fluid_settings_t *settings, const char *name, char **def)
1172 fluid_setting_node_t *node;
1173 char *retval = NULL;
1175 fluid_return_val_if_fail(settings != NULL, FLUID_FAILED);
1176 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
1177 fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED);
1179 fluid_rec_mutex_lock(settings->mutex);
1181 if(fluid_settings_get(settings, name, &node) == FLUID_OK)
1183 if(node->type == FLUID_STR_TYPE)
1185 fluid_str_setting_t *setting = &node->str;
1186 retval = setting->def;
1188 else if(node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
1190 fluid_int_setting_t *setting = &node->i;
1192 if(setting->hints & FLUID_HINT_TOGGLED)
1194 retval = setting->def ? "yes" : "no";
1200 fluid_rec_mutex_unlock(settings->mutex);
1202 return retval != NULL ? FLUID_OK : FLUID_FAILED;
1206 * Add an option to a string setting (like an enumeration value).
1207 * @param settings a settings object
1208 * @param name a setting's name
1209 * @param s option string to add
1210 * @return #FLUID_OK if the setting exists and option was added, #FLUID_FAILED otherwise
1212 * Causes the setting's #FLUID_HINT_OPTIONLIST hint to be set.
1215 fluid_settings_add_option(fluid_settings_t *settings, const char *name, const char *s)
1217 fluid_setting_node_t *node;
1218 int retval = FLUID_FAILED;
1220 fluid_return_val_if_fail(settings != NULL, retval);
1221 fluid_return_val_if_fail(name != NULL, retval);
1222 fluid_return_val_if_fail(name[0] != '\0', retval);
1223 fluid_return_val_if_fail(s != NULL, retval);
1225 fluid_rec_mutex_lock(settings->mutex);
1227 if(fluid_settings_get(settings, name, &node) == FLUID_OK
1228 && (node->type == FLUID_STR_TYPE))
1230 fluid_str_setting_t *setting = &node->str;
1231 char *copy = FLUID_STRDUP(s);
1232 setting->options = fluid_list_append(setting->options, copy);
1233 setting->hints |= FLUID_HINT_OPTIONLIST;
1237 fluid_rec_mutex_unlock(settings->mutex);
1243 * Remove an option previously assigned by fluid_settings_add_option().
1244 * @param settings a settings object
1245 * @param name a setting's name
1246 * @param s option string to remove
1247 * @return #FLUID_OK if the setting exists and option was removed, #FLUID_FAILED otherwise
1250 fluid_settings_remove_option(fluid_settings_t *settings, const char *name, const char *s)
1252 fluid_setting_node_t *node;
1253 int retval = FLUID_FAILED;
1255 fluid_return_val_if_fail(settings != NULL, retval);
1256 fluid_return_val_if_fail(name != NULL, retval);
1257 fluid_return_val_if_fail(name[0] != '\0', retval);
1258 fluid_return_val_if_fail(s != NULL, retval);
1260 fluid_rec_mutex_lock(settings->mutex);
1262 if(fluid_settings_get(settings, name, &node) == FLUID_OK
1263 && (node->type == FLUID_STR_TYPE))
1266 fluid_str_setting_t *setting = &node->str;
1267 fluid_list_t *list = setting->options;
1271 char *option = (char *) fluid_list_get(list);
1273 if(FLUID_STRCMP(s, option) == 0)
1276 setting->options = fluid_list_remove_link(setting->options, list);
1281 list = fluid_list_next(list);
1285 fluid_rec_mutex_unlock(settings->mutex);
1291 * Set a numeric value for a named setting.
1293 * @param settings a settings object
1294 * @param name a setting's name
1295 * @param val new setting's value
1296 * @return #FLUID_OK if the value has been set, #FLUID_FAILED otherwise
1299 fluid_settings_setnum(fluid_settings_t *settings, const char *name, double val)
1301 fluid_setting_node_t *node;
1302 fluid_num_setting_t *setting;
1303 fluid_num_update_t callback = NULL;
1306 fluid_return_val_if_fail(settings != NULL, FLUID_FAILED);
1307 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
1308 fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED);
1310 fluid_rec_mutex_lock(settings->mutex);
1312 if((fluid_settings_get(settings, name, &node) != FLUID_OK)
1313 || (node->type != FLUID_NUM_TYPE))
1315 goto error_recovery;
1318 setting = &node->num;
1320 if(val < setting->min || val > setting->max)
1322 FLUID_LOG(FLUID_DBG, "requested set value for %s out of range", name);
1323 goto error_recovery;
1326 setting->value = val;
1328 callback = setting->update;
1329 data = setting->data;
1331 /* Release the mutex before calling the update callback, to avoid
1332 * possible deadlocks with FluidSynths API lock */
1333 fluid_rec_mutex_unlock(settings->mutex);
1337 (*callback)(data, name, val);
1343 fluid_rec_mutex_unlock(settings->mutex);
1344 return FLUID_FAILED;
1348 * Get the numeric value of a named setting
1350 * @param settings a settings object
1351 * @param name a setting's name
1352 * @param val variable pointer to receive the setting's numeric value
1353 * @return #FLUID_OK if the value exists, #FLUID_FAILED otherwise
1356 fluid_settings_getnum(fluid_settings_t *settings, const char *name, double *val)
1358 fluid_setting_node_t *node;
1359 int retval = FLUID_FAILED;
1361 fluid_return_val_if_fail(settings != NULL, retval);
1362 fluid_return_val_if_fail(name != NULL, retval);
1363 fluid_return_val_if_fail(name[0] != '\0', retval);
1364 fluid_return_val_if_fail(val != NULL, retval);
1366 fluid_rec_mutex_lock(settings->mutex);
1368 if(fluid_settings_get(settings, name, &node) == FLUID_OK
1369 && (node->type == FLUID_NUM_TYPE))
1371 fluid_num_setting_t *setting = &node->num;
1372 *val = setting->value;
1376 fluid_rec_mutex_unlock(settings->mutex);
1382 * float-typed wrapper for fluid_settings_getnum
1384 * @param settings a settings object
1385 * @param name a setting's name
1386 * @param val variable pointer to receive the setting's float value
1387 * @return #FLUID_OK if the value exists, #FLUID_FAILED otherwise
1389 int fluid_settings_getnum_float(fluid_settings_t *settings, const char *name, float *val)
1393 if(fluid_settings_getnum(settings, name, &tmp) == FLUID_OK)
1399 return FLUID_FAILED;
1403 * Get the range of values of a numeric setting
1405 * @param settings a settings object
1406 * @param name a setting's name
1407 * @param min setting's range lower limit
1408 * @param max setting's range upper limit
1409 * @return #FLUID_OK if the setting's range exists, #FLUID_FAILED otherwise
1412 fluid_settings_getnum_range(fluid_settings_t *settings, const char *name,
1413 double *min, double *max)
1415 fluid_setting_node_t *node;
1416 int retval = FLUID_FAILED;
1418 fluid_return_val_if_fail(settings != NULL, retval);
1419 fluid_return_val_if_fail(name != NULL, retval);
1420 fluid_return_val_if_fail(name[0] != '\0', retval);
1421 fluid_return_val_if_fail(min != NULL, retval);
1422 fluid_return_val_if_fail(max != NULL, retval);
1424 fluid_rec_mutex_lock(settings->mutex);
1426 if(fluid_settings_get(settings, name, &node) == FLUID_OK
1427 && (node->type == FLUID_NUM_TYPE))
1429 fluid_num_setting_t *setting = &node->num;
1430 *min = setting->min;
1431 *max = setting->max;
1435 fluid_rec_mutex_unlock(settings->mutex);
1441 * Get the default value of a named numeric (double) setting
1443 * @param settings a settings object
1444 * @param name a setting's name
1445 * @param val set to the default value if the named setting exists
1446 * @return #FLUID_OK if the default value of the named setting exists, #FLUID_FAILED otherwise
1449 fluid_settings_getnum_default(fluid_settings_t *settings, const char *name, double *val)
1451 fluid_setting_node_t *node;
1452 int retval = FLUID_FAILED;
1454 fluid_return_val_if_fail(settings != NULL, retval);
1455 fluid_return_val_if_fail(name != NULL, retval);
1456 fluid_return_val_if_fail(name[0] != '\0', retval);
1457 fluid_return_val_if_fail(val != NULL, retval);
1459 fluid_rec_mutex_lock(settings->mutex);
1461 if(fluid_settings_get(settings, name, &node) == FLUID_OK
1462 && (node->type == FLUID_NUM_TYPE))
1464 fluid_num_setting_t *setting = &node->num;
1465 *val = setting->def;
1469 fluid_rec_mutex_unlock(settings->mutex);
1475 * Set an integer value for a setting
1477 * @param settings a settings object
1478 * @param name a setting's name
1479 * @param val new setting's integer value
1480 * @return #FLUID_OK if the value has been set, #FLUID_FAILED otherwise
1483 fluid_settings_setint(fluid_settings_t *settings, const char *name, int val)
1485 fluid_setting_node_t *node;
1486 fluid_int_setting_t *setting;
1487 fluid_int_update_t callback = NULL;
1490 fluid_return_val_if_fail(settings != NULL, FLUID_FAILED);
1491 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
1492 fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED);
1494 fluid_rec_mutex_lock(settings->mutex);
1496 if((fluid_settings_get(settings, name, &node) != FLUID_OK)
1497 || (node->type != FLUID_INT_TYPE))
1499 goto error_recovery;
1504 if(val < setting->min || val > setting->max)
1506 FLUID_LOG(FLUID_DBG, "requested set value for %s out of range", name);
1507 goto error_recovery;
1510 setting->value = val;
1512 callback = setting->update;
1513 data = setting->data;
1515 /* Release the mutex before calling the update callback, to avoid
1516 * possible deadlocks with FluidSynths API lock */
1517 fluid_rec_mutex_unlock(settings->mutex);
1521 (*callback)(data, name, val);
1527 fluid_rec_mutex_unlock(settings->mutex);
1528 return FLUID_FAILED;
1532 * Get an integer value setting.
1534 * @param settings a settings object
1535 * @param name a setting's name
1536 * @param val pointer to a variable to receive the setting's integer value
1537 * @return #FLUID_OK if the value exists, #FLUID_FAILED otherwise
1540 fluid_settings_getint(fluid_settings_t *settings, const char *name, int *val)
1542 fluid_setting_node_t *node;
1543 int retval = FLUID_FAILED;
1545 fluid_return_val_if_fail(settings != NULL, retval);
1546 fluid_return_val_if_fail(name != NULL, retval);
1547 fluid_return_val_if_fail(name[0] != '\0', retval);
1548 fluid_return_val_if_fail(val != NULL, retval);
1550 fluid_rec_mutex_lock(settings->mutex);
1552 if(fluid_settings_get(settings, name, &node) == FLUID_OK
1553 && (node->type == FLUID_INT_TYPE))
1555 fluid_int_setting_t *setting = &node->i;
1556 *val = setting->value;
1560 fluid_rec_mutex_unlock(settings->mutex);
1566 * Get the range of values of an integer setting
1567 * @param settings a settings object
1568 * @param name a setting's name
1569 * @param min setting's range lower limit
1570 * @param max setting's range upper limit
1571 * @return #FLUID_OK if the setting's range exists, #FLUID_FAILED otherwise
1574 fluid_settings_getint_range(fluid_settings_t *settings, const char *name,
1577 fluid_setting_node_t *node;
1578 int retval = FLUID_FAILED;
1580 fluid_return_val_if_fail(settings != NULL, retval);
1581 fluid_return_val_if_fail(name != NULL, retval);
1582 fluid_return_val_if_fail(name[0] != '\0', retval);
1583 fluid_return_val_if_fail(min != NULL, retval);
1584 fluid_return_val_if_fail(max != NULL, retval);
1586 fluid_rec_mutex_lock(settings->mutex);
1588 if(fluid_settings_get(settings, name, &node) == FLUID_OK
1589 && (node->type == FLUID_INT_TYPE))
1591 fluid_int_setting_t *setting = &node->i;
1592 *min = setting->min;
1593 *max = setting->max;
1597 fluid_rec_mutex_unlock(settings->mutex);
1603 * Get the default value of an integer setting.
1605 * @param settings a settings object
1606 * @param name a setting's name
1607 * @param val set to the setting's default integer value if it exists
1608 * @return #FLUID_OK if the setting's default integer value exists, #FLUID_FAILED otherwise
1610 int fluid_settings_getint_default(fluid_settings_t *settings, const char *name, int *val)
1612 fluid_setting_node_t *node;
1613 int retval = FLUID_FAILED;
1615 fluid_return_val_if_fail(settings != NULL, retval);
1616 fluid_return_val_if_fail(name != NULL, retval);
1617 fluid_return_val_if_fail(name[0] != '\0', retval);
1618 fluid_return_val_if_fail(val != NULL, retval);
1620 fluid_rec_mutex_lock(settings->mutex);
1622 if(fluid_settings_get(settings, name, &node) == FLUID_OK
1623 && (node->type == FLUID_INT_TYPE))
1625 fluid_int_setting_t *setting = &node->i;
1626 *val = setting->def;
1630 fluid_rec_mutex_unlock(settings->mutex);
1636 * Iterate the available options for a named string setting, calling the provided
1637 * callback function for each existing option.
1639 * @param settings a settings object
1640 * @param name a setting's name
1641 * @param data any user provided pointer
1642 * @param func callback function to be called on each iteration
1644 * @note Starting with FluidSynth 1.1.0 the \a func callback is called for each
1645 * option in alphabetical order. Sort order was undefined in previous versions.
1648 fluid_settings_foreach_option(fluid_settings_t *settings, const char *name,
1649 void *data, fluid_settings_foreach_option_t func)
1651 fluid_setting_node_t *node;
1652 fluid_str_setting_t *setting;
1653 fluid_list_t *p, *newlist = NULL;
1655 fluid_return_if_fail(settings != NULL);
1656 fluid_return_if_fail(name != NULL);
1657 fluid_return_if_fail(name[0] != '\0');
1658 fluid_return_if_fail(func != NULL);
1660 fluid_rec_mutex_lock(settings->mutex); /* ++ lock */
1662 if(fluid_settings_get(settings, name, &node) != FLUID_OK
1663 || node->type != FLUID_STR_TYPE)
1665 fluid_rec_mutex_unlock(settings->mutex); /* -- unlock */
1669 setting = &node->str;
1671 /* Duplicate option list */
1672 for(p = setting->options; p; p = p->next)
1674 newlist = fluid_list_append(newlist, fluid_list_get(p));
1678 newlist = fluid_list_sort(newlist, fluid_list_str_compare_func);
1680 for(p = newlist; p; p = p->next)
1682 (*func)(data, name, (const char *)fluid_list_get(p));
1685 fluid_rec_mutex_unlock(settings->mutex); /* -- unlock */
1687 delete_fluid_list(newlist);
1691 * Count option string values for a string setting.
1692 * @param settings a settings object
1693 * @param name Name of setting
1694 * @return Count of options for this string setting (0 if none, -1 if not found
1695 * or not a string setting)
1699 fluid_settings_option_count(fluid_settings_t *settings, const char *name)
1701 fluid_setting_node_t *node;
1704 fluid_return_val_if_fail(settings != NULL, -1);
1705 fluid_return_val_if_fail(name != NULL, -1);
1706 fluid_return_val_if_fail(name[0] != '\0', -1);
1708 fluid_rec_mutex_lock(settings->mutex);
1710 if(fluid_settings_get(settings, name, &node) == FLUID_OK
1711 && node->type == FLUID_STR_TYPE)
1713 count = fluid_list_size(node->str.options);
1716 fluid_rec_mutex_unlock(settings->mutex);
1722 * Concatenate options for a string setting together with a separator between.
1723 * @param settings Settings object
1724 * @param name Settings name
1725 * @param separator String to use between options (NULL to use ", ")
1726 * @return Newly allocated string or NULL on error (out of memory, not a valid
1727 * setting \a name or not a string setting). Free the string when finished with it.
1731 fluid_settings_option_concat(fluid_settings_t *settings, const char *name,
1732 const char *separator)
1734 fluid_setting_node_t *node;
1735 fluid_str_setting_t *setting;
1736 fluid_list_t *p, *newlist = NULL;
1740 fluid_return_val_if_fail(settings != NULL, NULL);
1741 fluid_return_val_if_fail(name != NULL, NULL);
1742 fluid_return_val_if_fail(name[0] != '\0', NULL);
1749 fluid_rec_mutex_lock(settings->mutex); /* ++ lock */
1751 if(fluid_settings_get(settings, name, &node) != FLUID_OK
1752 || node->type != FLUID_STR_TYPE)
1754 fluid_rec_mutex_unlock(settings->mutex); /* -- unlock */
1758 setting = &node->str;
1760 /* Duplicate option list, count options and get total string length */
1761 for(p = setting->options, count = 0, len = 0; p; p = p->next, count++)
1763 option = fluid_list_get(p);
1767 newlist = fluid_list_append(newlist, option);
1768 len += FLUID_STRLEN(option);
1774 len += (count - 1) * FLUID_STRLEN(separator);
1777 len++; /* For terminator */
1780 newlist = fluid_list_sort(newlist, fluid_list_str_compare_func);
1782 str = FLUID_MALLOC(len);
1788 for(p = newlist; p; p = p->next)
1790 option = fluid_list_get(p);
1791 strcat(str, option);
1795 strcat(str, separator);
1800 fluid_rec_mutex_unlock(settings->mutex); /* -- unlock */
1802 delete_fluid_list(newlist);
1806 FLUID_LOG(FLUID_ERR, "Out of memory");
1812 /* Structure passed to fluid_settings_foreach_iter recursive function */
1815 char path[MAX_SETTINGS_LABEL + 1]; /* Maximum settings label length */
1816 fluid_list_t *names; /* For fluid_settings_foreach() */
1817 } fluid_settings_foreach_bag_t;
1820 fluid_settings_foreach_iter(void *key, void *value, void *data)
1822 fluid_settings_foreach_bag_t *bag = data;
1824 fluid_setting_node_t *node = value;
1828 pathlen = FLUID_STRLEN(bag->path);
1832 bag->path[pathlen] = '.';
1833 bag->path[pathlen + 1] = 0;
1836 strcat(bag->path, keystr);
1840 case FLUID_NUM_TYPE:
1841 case FLUID_INT_TYPE:
1842 case FLUID_STR_TYPE:
1843 s = FLUID_STRDUP(bag->path);
1847 bag->names = fluid_list_append(bag->names, s);
1852 case FLUID_SET_TYPE:
1853 fluid_hashtable_foreach(node->set.hashtable,
1854 fluid_settings_foreach_iter, bag);
1858 bag->path[pathlen] = 0;
1864 * Iterate the existing settings defined in a settings object, calling the
1865 * provided callback function for each setting.
1867 * @param settings a settings object
1868 * @param data any user provided pointer
1869 * @param func callback function to be called on each iteration
1871 * @note Starting with FluidSynth 1.1.0 the \a func callback is called for each
1872 * setting in alphabetical order. Sort order was undefined in previous versions.
1875 fluid_settings_foreach(fluid_settings_t *settings, void *data,
1876 fluid_settings_foreach_t func)
1878 fluid_settings_foreach_bag_t bag;
1879 fluid_setting_node_t *node;
1882 fluid_return_if_fail(settings != NULL);
1883 fluid_return_if_fail(func != NULL);
1888 fluid_rec_mutex_lock(settings->mutex);
1890 /* Add all node names to the bag.names list */
1891 fluid_hashtable_foreach(settings, fluid_settings_foreach_iter, &bag);
1894 bag.names = fluid_list_sort(bag.names, fluid_list_str_compare_func);
1896 /* Loop over names and call the callback */
1897 for(p = bag.names; p; p = p->next)
1899 if(fluid_settings_get(settings, (const char *)(p->data), &node) == FLUID_OK
1902 (*func)(data, (const char *)(p->data), node->type);
1905 FLUID_FREE(p->data); /* -- Free name */
1908 fluid_rec_mutex_unlock(settings->mutex);
1910 delete_fluid_list(bag.names); /* -- Free names list */
1914 * Split a comma-separated list of integers and fill the passed
1915 * in buffer with the parsed values.
1917 * @param str the comma-separated string to split
1918 * @param buf user-supplied buffer to hold the parsed numbers
1919 * @param buf_len length of user-supplied buffer
1920 * @return number of parsed values or -1 on failure
1922 int fluid_settings_split_csv(const char *str, int *buf, int buf_len)
1929 s = tokstr = FLUID_STRDUP(str);
1933 FLUID_LOG(FLUID_ERR, "Out of memory");
1937 while((tok = fluid_strtok(&tokstr, ",")) && n < buf_len)
1939 buf[n++] = atoi(tok);