fluid_settings.c
上传用户:tjmskj2
上传日期:2020-08-17
资源大小:577k
文件大小:42k
- /* FluidSynth - A Software Synthesizer
- *
- * Copyright (C) 2003 Peter Hanappe and others.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License
- * as published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307, USA
- */
- #include "fluidsynth_priv.h"
- #include "fluid_sys.h"
- #include "fluid_hash.h"
- #include "fluid_synth.h"
- #include "fluid_cmd.h"
- #include "fluid_adriver.h"
- #include "fluid_mdriver.h"
- #include "fluid_settings.h"
- #include "fluid_midi.h"
- /* Defined in fluid_filerenderer.c */
- extern void fluid_file_renderer_settings (fluid_settings_t* settings);
- /* maximum allowed components of a settings variable (separated by '.') */
- #define MAX_SETTINGS_TOKENS 8 /* currently only a max of 3 are used */
- #define MAX_SETTINGS_LABEL 256 /* max length of a settings variable label */
- static void fluid_settings_init(fluid_settings_t* settings);
- static void fluid_settings_key_destroy_func(void* value);
- static void fluid_settings_value_destroy_func(void* value);
- static int fluid_settings_tokenize(const char *s, char *buf, char **ptr);
- /* Common structure to all settings nodes */
- typedef struct {
- int type; /**< fluid_types_enum */
- } fluid_setting_node_t;
- typedef struct {
- fluid_setting_node_t node;
- char* value;
- char* def;
- int hints;
- fluid_list_t* options;
- fluid_str_update_t update;
- void* data;
- } fluid_str_setting_t;
- typedef struct {
- fluid_setting_node_t node;
- double value;
- double def;
- double min;
- double max;
- int hints;
- fluid_num_update_t update;
- void* data;
- } fluid_num_setting_t;
- typedef struct {
- fluid_setting_node_t node;
- int value;
- int def;
- int min;
- int max;
- int hints;
- fluid_int_update_t update;
- void* data;
- } fluid_int_setting_t;
- typedef struct {
- fluid_setting_node_t node;
- fluid_hashtable_t *hashtable;
- } fluid_set_setting_t;
- static fluid_str_setting_t*
- new_fluid_str_setting(const char* value, char* def, int hints, fluid_str_update_t fun, void* data)
- {
- fluid_str_setting_t* str;
- str = FLUID_NEW(fluid_str_setting_t);
- if (!str)
- {
- FLUID_LOG(FLUID_ERR, "Out of memory");
- return NULL;
- }
- str->node.type = FLUID_STR_TYPE;
- str->value = value? FLUID_STRDUP(value) : NULL;
- str->def = def? FLUID_STRDUP(def) : NULL;
- str->hints = hints;
- str->options = NULL;
- str->update = fun;
- str->data = data;
- return str;
- }
- static void
- delete_fluid_str_setting(fluid_str_setting_t* str)
- {
- if (!str) return;
- if (str->value) FLUID_FREE(str->value);
- if (str->def) FLUID_FREE(str->def);
- if (str->options) {
- fluid_list_t* list = str->options;
- while (list) {
- FLUID_FREE (list->data);
- list = fluid_list_next(list);
- }
- delete_fluid_list(str->options);
- }
- FLUID_FREE(str);
- }
- static fluid_num_setting_t*
- new_fluid_num_setting(double min, double max, double def,
- int hints, fluid_num_update_t fun, void* data)
- {
- fluid_num_setting_t* setting;
- setting = FLUID_NEW(fluid_num_setting_t);
- if (!setting)
- {
- FLUID_LOG(FLUID_ERR, "Out of memory");
- return NULL;
- }
- setting->node.type = FLUID_NUM_TYPE;
- setting->value = def;
- setting->def = def;
- setting->min = min;
- setting->max = max;
- setting->hints = hints;
- setting->update = fun;
- setting->data = data;
- return setting;
- }
- static void
- delete_fluid_num_setting(fluid_num_setting_t* setting)
- {
- if (setting) FLUID_FREE(setting);
- }
- static fluid_int_setting_t*
- new_fluid_int_setting(int min, int max, int def,
- int hints, fluid_int_update_t fun, void* data)
- {
- fluid_int_setting_t* setting;
- setting = FLUID_NEW(fluid_int_setting_t);
- if (!setting)
- {
- FLUID_LOG(FLUID_ERR, "Out of memory");
- return NULL;
- }
- setting->node.type = FLUID_INT_TYPE;
- setting->value = def;
- setting->def = def;
- setting->min = min;
- setting->max = max;
- setting->hints = hints;
- setting->update = fun;
- setting->data = data;
- return setting;
- }
- static void
- delete_fluid_int_setting(fluid_int_setting_t* setting)
- {
- if (setting) FLUID_FREE(setting);
- }
- static fluid_set_setting_t*
- new_fluid_set_setting(void)
- {
- fluid_set_setting_t* setting;
- setting = FLUID_NEW(fluid_set_setting_t);
- if (!setting)
- {
- FLUID_LOG(FLUID_ERR, "Out of memory");
- return NULL;
- }
- setting->node.type = FLUID_SET_TYPE;
- setting->hashtable = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal,
- fluid_settings_key_destroy_func,
- fluid_settings_value_destroy_func);
- if (!setting->hashtable)
- {
- FLUID_FREE (setting);
- return NULL;
- }
- return setting;
- }
- static void
- delete_fluid_set_setting(fluid_set_setting_t* setting)
- {
- if (setting)
- {
- delete_fluid_hashtable(setting->hashtable);
- FLUID_FREE(setting);
- }
- }
- /**
- * Create a new settings object
- * @return the pointer to the settings object
- */
- fluid_settings_t *
- new_fluid_settings(void)
- {
- fluid_settings_t* settings;
- settings = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal,
- fluid_settings_key_destroy_func,
- fluid_settings_value_destroy_func);
- if (settings == NULL) return NULL;
- fluid_rec_mutex_init (settings->mutex);
- fluid_settings_init(settings);
- return settings;
- }
- /**
- * Delete the provided settings object
- * @param settings a settings object
- */
- void
- delete_fluid_settings(fluid_settings_t* settings)
- {
- fluid_return_if_fail (settings != NULL);
- fluid_rec_mutex_destroy (settings->mutex);
- delete_fluid_hashtable(settings);
- }
- /* Settings hash key destroy function */
- static void
- fluid_settings_key_destroy_func(void* value)
- {
- FLUID_FREE (value); /* Free the string key value */
- }
- /* Settings hash value destroy function */
- static void
- fluid_settings_value_destroy_func(void* value)
- {
- fluid_setting_node_t *node = value;
- switch (node->type) {
- case FLUID_NUM_TYPE:
- delete_fluid_num_setting((fluid_num_setting_t*) value);
- break;
- case FLUID_INT_TYPE:
- delete_fluid_int_setting((fluid_int_setting_t*) value);
- break;
- case FLUID_STR_TYPE:
- delete_fluid_str_setting((fluid_str_setting_t*) value);
- break;
- case FLUID_SET_TYPE:
- delete_fluid_set_setting((fluid_set_setting_t*) value);
- break;
- }
- }
- void
- fluid_settings_init(fluid_settings_t* settings)
- {
- fluid_return_if_fail (settings != NULL);
- fluid_synth_settings(settings);
- fluid_shell_settings(settings);
- fluid_player_settings(settings);
- fluid_file_renderer_settings(settings);
- fluid_audio_driver_settings(settings);
- fluid_midi_driver_settings(settings);
- }
- static int
- fluid_settings_tokenize(const char *s, char *buf, char **ptr)
- {
- char *tokstr, *tok;
- int n = 0;
- if (strlen (s) > MAX_SETTINGS_LABEL)
- {
- FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars",
- MAX_SETTINGS_LABEL);
- return 0;
- }
- FLUID_STRCPY(buf, s); /* copy string to buffer, since it gets modified */
- tokstr = buf;
- while ((tok = fluid_strtok (&tokstr, ".")))
- {
- if (n > MAX_SETTINGS_TOKENS)
- {
- FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max token count of %d",
- MAX_SETTINGS_TOKENS);
- return 0;
- }
- ptr[n++] = tok;
- }
- return n;
- }
- /**
- * Get a setting name, value and type
- *
- * @param settings a settings object
- * @param name Settings name
- * @param value Location to store setting node if found
- * @return 1 if the node exists, 0 otherwise
- */
- static int
- fluid_settings_get(fluid_settings_t* settings, const char *name,
- fluid_setting_node_t **value)
- {
- fluid_hashtable_t* table = settings;
- fluid_setting_node_t *node = NULL;
- char* tokens[MAX_SETTINGS_TOKENS];
- char buf[MAX_SETTINGS_LABEL+1];
- int ntokens;
- int n;
- ntokens = fluid_settings_tokenize (name, buf, tokens);
- for (n = 0; n < ntokens; n++) {
- if (table == NULL) return 0;
- node = fluid_hashtable_lookup(table, tokens[n]);
- if (!node) return 0;
- table = (node->type == FLUID_SET_TYPE) ? ((fluid_set_setting_t *)node)->hashtable : NULL;
- }
- if (value) *value = node;
- return 1;
- }
- /**
- * Set a setting name, value and type, replacing it if already exists
- *
- * @param settings a settings object
- * @param name Settings name
- * @param value Node instance to assign (used directly)
- * @return 1 if the value has been set, zero otherwise
- */
- static int
- fluid_settings_set(fluid_settings_t* settings, const char *name, void* value)
- {
- fluid_hashtable_t* table = settings;
- fluid_setting_node_t *node;
- char* tokens[MAX_SETTINGS_TOKENS];
- char buf[MAX_SETTINGS_LABEL+1];
- int n, num;
- char *dupname;
- num = fluid_settings_tokenize (name, buf, tokens) - 1;
- for (n = 0; n < num; n++) {
- node = fluid_hashtable_lookup(table, tokens[n]);
- if (node) {
- if (node->type == FLUID_SET_TYPE) {
- table = ((fluid_set_setting_t *)node)->hashtable;
- } else {
- /* path ends prematurely */
- FLUID_LOG(FLUID_WARN, "'%s' is not a node", name[n]);
- return 0;
- }
- } else {
- /* create a new node */
- fluid_set_setting_t* setnode;
- dupname = FLUID_STRDUP (tokens[n]);
- setnode = new_fluid_set_setting ();
- if (!dupname || !setnode)
- {
- if (dupname) FLUID_FREE (dupname);
- else FLUID_LOG(FLUID_ERR, "Out of memory");
- if (setnode) delete_fluid_set_setting (setnode);
- return 0;
- }
- fluid_hashtable_insert(table, dupname, setnode);
- table = setnode->hashtable;
- }
- }
- dupname = FLUID_STRDUP (tokens[num]);
- if (!dupname)
- {
- FLUID_LOG(FLUID_ERR, "Out of memory");
- return 0;
- }
- fluid_hashtable_insert(table, dupname, value);
- return 1;
- }
- /** returns 1 if the value has been registered correctly, 0
- otherwise */
- int
- fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, int hints,
- fluid_str_update_t fun, void* data)
- {
- fluid_setting_node_t *node;
- fluid_str_setting_t* setting;
- int retval;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (!fluid_settings_get(settings, name, &node)) {
- setting = new_fluid_str_setting(def, def, hints, fun, data);
- retval = fluid_settings_set(settings, name, setting);
- if (retval != 1) delete_fluid_str_setting (setting);
- } else {
- /* if variable already exists, don't change its value. */
- if (node->type == FLUID_STR_TYPE) {
- setting = (fluid_str_setting_t*) node;
- setting->update = fun;
- setting->data = data;
- setting->def = def? FLUID_STRDUP(def) : NULL;
- setting->hints = hints;
- retval = 1;
- } else {
- FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
- retval = 0;
- }
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /** returns 1 if the value has been register correctly, zero
- otherwise */
- int
- fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
- double min, double max, int hints,
- fluid_num_update_t fun, void* data)
- {
- fluid_setting_node_t *node;
- int retval;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- /* For now, all floating point settings are bounded below and above */
- hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE;
- fluid_rec_mutex_lock (settings->mutex);
- if (!fluid_settings_get(settings, name, &node)) {
- /* insert a new setting */
- fluid_num_setting_t* setting;
- setting = new_fluid_num_setting(min, max, def, hints, fun, data);
- retval = fluid_settings_set(settings, name, setting);
- if (retval != 1) delete_fluid_num_setting (setting);
- } else {
- if (node->type == FLUID_NUM_TYPE) {
- /* update the existing setting but don't change its value */
- fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
- setting->update = fun;
- setting->data = data;
- setting->min = min;
- setting->max = max;
- setting->def = def;
- setting->hints = hints;
- retval = 1;
- } else {
- /* type mismatch */
- FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
- retval = 0;
- }
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /** returns 1 if the value has been register correctly, zero
- otherwise. */
- int
- fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
- int min, int max, int hints,
- fluid_int_update_t fun, void* data)
- {
- fluid_setting_node_t *node;
- int retval;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- /* For now, all integer settings are bounded below and above */
- hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE;
- fluid_rec_mutex_lock (settings->mutex);
- if (!fluid_settings_get(settings, name, &node)) {
- /* insert a new setting */
- fluid_int_setting_t* setting;
- setting = new_fluid_int_setting(min, max, def, hints, fun, data);
- retval = fluid_settings_set(settings, name, setting);
- if (retval != 1) delete_fluid_int_setting (setting);
- } else {
- if (node->type == FLUID_INT_TYPE) {
- /* update the existing setting but don't change its value */
- fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
- setting->update = fun;
- setting->data = data;
- setting->min = min;
- setting->max = max;
- setting->def = def;
- setting->hints = hints;
- retval = 1;
- } else {
- /* type mismatch */
- FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
- retval = 0;
- }
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Get the type of the setting with the given name
- *
- * @param settings a settings object
- * @param name a setting's name
- * @return the type for the named setting, or #FLUID_NO_TYPE when it does not exist
- */
- int
- fluid_settings_get_type(fluid_settings_t* settings, const char *name)
- {
- fluid_setting_node_t *node;
- int type;
- fluid_return_val_if_fail (settings != NULL, FLUID_NO_TYPE);
- fluid_return_val_if_fail (name != NULL, FLUID_NO_TYPE);
- fluid_rec_mutex_lock (settings->mutex);
- type = fluid_settings_get (settings, name, &node) ? node->type : FLUID_NO_TYPE;
- fluid_rec_mutex_unlock (settings->mutex);
- return (type);
- }
- /**
- * Get the hints for the named setting as an integer bitmap
- *
- * @param settings a settings object
- * @param name a setting's name
- * @return the hints associated to the named setting if it exists, zero otherwise
- */
- int
- fluid_settings_get_hints(fluid_settings_t* settings, const char *name)
- {
- fluid_setting_node_t *node;
- int hints = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)) {
- if (node->type == FLUID_NUM_TYPE) {
- fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
- hints = setting->hints;
- } else if (node->type == FLUID_STR_TYPE) {
- fluid_str_setting_t* setting = (fluid_str_setting_t*) node;
- hints = setting->hints;
- } else if (node->type == FLUID_INT_TYPE) {
- fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
- hints = setting->hints;
- }
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return hints;
- }
- /**
- * Ask whether the setting is changeable in real-time.
- *
- * @param settings a settings object
- * @param name a setting's name
- * @return non zero if the setting is changeable in real-time
- */
- int
- fluid_settings_is_realtime(fluid_settings_t* settings, const char *name)
- {
- fluid_setting_node_t *node;
- int isrealtime = FALSE;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)) {
- if (node->type == FLUID_NUM_TYPE) {
- fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
- isrealtime = setting->update != NULL;
- } else if (node->type == FLUID_STR_TYPE) {
- fluid_str_setting_t* setting = (fluid_str_setting_t*) node;
- isrealtime = setting->update != NULL;
- } else if (node->type == FLUID_INT_TYPE) {
- fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
- isrealtime = setting->update != NULL;
- }
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return isrealtime;
- }
- /**
- * Set a string value for a named setting
- *
- * @param settings a settings object
- * @param name a setting's name
- * @param str new string value
- * @return 1 if the value has been set, 0 otherwise
- */
- int
- fluid_settings_setstr(fluid_settings_t* settings, const char *name, const char *str)
- {
- fluid_setting_node_t *node;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get (settings, name, &node)) {
- if (node->type == FLUID_STR_TYPE) {
- fluid_str_setting_t *setting = (fluid_str_setting_t *)node;
- if (setting->value) FLUID_FREE (setting->value);
- setting->value = str ? FLUID_STRDUP (str) : NULL;
- /* Call under lock to keep update() synchronized with the current value */
- if (setting->update) (*setting->update)(setting->data, name, str);
- retval = 1;
- }
- else if (node->type == FLUID_INT_TYPE) /* Handle yes/no for boolean values for backwards compatibility */
- {
- fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
- if (setting->hints & FLUID_HINT_TOGGLED)
- {
- if (FLUID_STRCMP (str, "yes") == 0)
- {
- setting->value = TRUE;
- if (setting->update) (*setting->update)(setting->data, name, TRUE);
- }
- else if (FLUID_STRCMP (str, "no") == 0)
- {
- setting->value = FALSE;
- if (setting->update) (*setting->update)(setting->data, name, FALSE);
- }
- }
- }
- } else {
- /* insert a new setting */
- fluid_str_setting_t* setting;
- setting = new_fluid_str_setting(str, NULL, 0, NULL, NULL);
- retval = fluid_settings_set(settings, name, setting);
- if (retval != 1) delete_fluid_str_setting (setting);
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Copy the value of a string setting
- * @param settings a settings object
- * @param name a setting's name
- * @param str Caller supplied buffer to copy string value to
- * @param len Size of 'str' buffer (no more than len bytes will be written, which
- * will always include a zero terminator)
- * @return 1 if the value exists, 0 otherwise
- * @since 1.1.0
- *
- * Like fluid_settings_getstr() but is thread safe. A size of 256 should be
- * more than sufficient for the string buffer.
- */
- int
- fluid_settings_copystr(fluid_settings_t* settings, const char *name,
- char *str, int len)
- {
- fluid_setting_node_t *node;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_return_val_if_fail (str != NULL, 0);
- fluid_return_val_if_fail (len > 0, 0);
- str[0] = 0;
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get (settings, name, &node))
- {
- if (node->type == FLUID_STR_TYPE)
- {
- fluid_str_setting_t *setting = (fluid_str_setting_t *)node;
- if (setting->value)
- {
- FLUID_STRNCPY (str, setting->value, len);
- str[len - 1] = 0; /* Force terminate, in case of truncation */
- }
- retval = 1;
- }
- else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
- {
- fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
- if (setting->hints & FLUID_HINT_TOGGLED)
- {
- FLUID_STRNCPY (str, setting->value ? "yes" : "no", len);
- str[len - 1] = 0; /* Force terminate, in case of truncation */
- retval = 1;
- }
- }
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Duplicate the value of a string setting
- * @param settings a settings object
- * @param name a setting's name
- * @param str Location to store pointer to allocated duplicate string
- * @return 1 if the value exists and was successfully duplicated, 0 otherwise
- * @since 1.1.0
- *
- * Like fluid_settings_copystr() but allocates a new copy of the string. Caller
- * owns the string and should free it with free() when done using it.
- */
- int
- fluid_settings_dupstr(fluid_settings_t* settings, const char *name, char** str)
- {
- fluid_setting_node_t *node;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_return_val_if_fail (str != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node))
- {
- if (node->type == FLUID_STR_TYPE)
- {
- fluid_str_setting_t *setting = (fluid_str_setting_t *)node;
- if (setting->value)
- {
- *str = FLUID_STRDUP (setting->value);
- if (!*str) FLUID_LOG (FLUID_ERR, "Out of memory");
- }
- if (!setting->value || *str) retval = 1; /* Don't set to 1 if out of memory */
- }
- else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
- {
- fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
- if (setting->hints & FLUID_HINT_TOGGLED)
- {
- *str = FLUID_STRDUP (setting->value ? "yes" : "no");
- if (!*str) FLUID_LOG (FLUID_ERR, "Out of memory");
- if (!setting->value || *str) retval = 1; /* Don't set to 1 if out of memory */
- }
- }
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Get the value of a string setting
- * @param settings a settings object
- * @param name a setting's name
- * @param str Location to store pointer to the settings string value
- * @return 1 if the value exists, 0 otherwise
- * @deprecated
- *
- * If the value does not exists, 'str' is set to NULL. Otherwise, 'str' will
- * point to the value. The application does not own the returned value and it
- * is valid only until a new value is assigned to the setting of the given name.
- *
- * NOTE: In a multi-threaded environment, caller must ensure that the setting
- * being read by fluid_settings_getstr() is not assigned during the
- * duration of callers use of the setting's value. Use fluid_settings_copystr()
- * or fluid_settings_dupstr() which does not have this restriction.
- */
- int
- fluid_settings_getstr(fluid_settings_t* settings, const char *name, char** str)
- {
- fluid_setting_node_t *node;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_return_val_if_fail (str != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node))
- {
- if (node->type == FLUID_STR_TYPE)
- {
- fluid_str_setting_t *setting = (fluid_str_setting_t *)node;
- *str = setting->value;
- retval = 1;
- }
- else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
- {
- fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
- if (setting->hints & FLUID_HINT_TOGGLED)
- {
- *str = setting->value ? "yes" : "no";
- retval = 1;
- }
- }
- }
- else *str = NULL;
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Test a string setting for some value.
- *
- * @param settings a settings object
- * @param name a setting's name
- * @param s a string to be tested
- * @return 1 if the value exists and is equal to 's', 0 otherwise
- */
- int
- fluid_settings_str_equal (fluid_settings_t* settings, const char *name, const char *s)
- {
- fluid_setting_node_t *node;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_return_val_if_fail (s != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get (settings, name, &node))
- {
- if (node->type == FLUID_STR_TYPE)
- {
- fluid_str_setting_t *setting = (fluid_str_setting_t *)node;
- if (setting->value) retval = FLUID_STRCMP (setting->value, s) == 0;
- }
- else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
- {
- fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
- if (setting->hints & FLUID_HINT_TOGGLED)
- retval = FLUID_STRCMP (setting->value ? "yes" : "no", s) == 0;
- }
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Get the default value of a string setting. Note that the returned string is
- * not owned by the caller and should not be modified or freed.
- *
- * @param settings a settings object
- * @param name a setting's name
- * @return the default string value of the setting if it exists, NULL otherwise
- */
- char*
- fluid_settings_getstr_default(fluid_settings_t* settings, const char *name)
- {
- fluid_setting_node_t *node;
- char *retval = NULL;
- fluid_return_val_if_fail (settings != NULL, NULL);
- fluid_return_val_if_fail (name != NULL, NULL);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get (settings, name, &node))
- {
- if (node->type == FLUID_STR_TYPE)
- {
- fluid_str_setting_t* setting = (fluid_str_setting_t*) node;
- retval = setting->def;
- }
- else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */
- {
- fluid_int_setting_t *setting = (fluid_int_setting_t *)node;
- if (setting->hints & FLUID_HINT_TOGGLED)
- retval = setting->def ? "yes" : "no";
- }
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Add an option to a string setting (like an enumeration value).
- * @param settings a settings object
- * @param name a setting's name
- * @param s option string to add
- * @return 1 if the setting exists and option was added, 0 otherwise
- *
- * Causes the setting's #FLUID_HINT_OPTIONLIST hint to be set.
- */
- int
- fluid_settings_add_option(fluid_settings_t* settings, const char *name, const char *s)
- {
- fluid_setting_node_t *node;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_return_val_if_fail (s != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)
- && (node->type == FLUID_STR_TYPE)) {
- fluid_str_setting_t* setting = (fluid_str_setting_t*) node;
- char* copy = FLUID_STRDUP(s);
- setting->options = fluid_list_append(setting->options, copy);
- setting->hints |= FLUID_HINT_OPTIONLIST;
- retval = 1;
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Remove an option previously assigned by fluid_settings_add_option().
- * @param settings a settings object
- * @param name a setting's name
- * @param s option string to remove
- * @return 1 if the setting exists and option was removed, 0 otherwise
- */
- int
- fluid_settings_remove_option(fluid_settings_t* settings, const char *name, const char* s)
- {
- fluid_setting_node_t *node;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_return_val_if_fail (s != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)
- && (node->type == FLUID_STR_TYPE)) {
- fluid_str_setting_t* setting = (fluid_str_setting_t*) node;
- fluid_list_t* list = setting->options;
- while (list) {
- char* option = (char*) fluid_list_get(list);
- if (FLUID_STRCMP(s, option) == 0) {
- FLUID_FREE (option);
- setting->options = fluid_list_remove_link(setting->options, list);
- retval = 1;
- break;
- }
- list = fluid_list_next(list);
- }
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Set a numeric value for a named setting.
- *
- * @param settings a settings object
- * @param name a setting's name
- * @param val new setting's value
- * @return 1 if the value has been set, 0 otherwise
- */
- int
- fluid_settings_setnum(fluid_settings_t* settings, const char *name, double val)
- {
- fluid_setting_node_t *node;
- fluid_num_setting_t* setting;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)) {
- if (node->type == FLUID_NUM_TYPE) {
- setting = (fluid_num_setting_t*) node;
- if (val < setting->min) val = setting->min;
- else if (val > setting->max) val = setting->max;
- setting->value = val;
- /* Call under lock to keep update() synchronized with the current value */
- if (setting->update) (*setting->update)(setting->data, name, val);
- retval = 1;
- }
- } else {
- /* insert a new setting */
- fluid_num_setting_t* setting;
- setting = new_fluid_num_setting(-1e10, 1e10, 0.0f, 0, NULL, NULL);
- setting->value = val;
- retval = fluid_settings_set(settings, name, setting);
- if (retval != 1) delete_fluid_num_setting (setting);
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Get the numeric value of a named setting
- *
- * @param settings a settings object
- * @param name a setting's name
- * @param val variable pointer to receive the setting's numeric value
- * @return 1 if the value exists, 0 otherwise
- */
- int
- fluid_settings_getnum(fluid_settings_t* settings, const char *name, double* val)
- {
- fluid_setting_node_t *node;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_return_val_if_fail (val != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)
- && (node->type == FLUID_NUM_TYPE)) {
- fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
- *val = setting->value;
- retval = 1;
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Get the range of values of a numeric setting
- *
- * @param settings a settings object
- * @param name a setting's name
- * @param min setting's range lower limit
- * @param max setting's range upper limit
- */
- void
- fluid_settings_getnum_range(fluid_settings_t* settings, const char *name,
- double* min, double* max)
- {
- fluid_setting_node_t *node;
- fluid_return_if_fail (settings != NULL);
- fluid_return_if_fail (name != NULL);
- fluid_return_if_fail (min != NULL);
- fluid_return_if_fail (max != NULL);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)
- && (node->type == FLUID_NUM_TYPE)) {
- fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
- *min = setting->min;
- *max = setting->max;
- }
- fluid_rec_mutex_unlock (settings->mutex);
- }
- /**
- * Get the default value of a named numeric (double) setting
- *
- * @param settings a settings object
- * @param name a setting's name
- * @return the default value if the named setting exists, 0.0f otherwise
- */
- double
- fluid_settings_getnum_default(fluid_settings_t* settings, const char *name)
- {
- fluid_setting_node_t *node;
- double retval = 0.0;
- fluid_return_val_if_fail (settings != NULL, 0.0);
- fluid_return_val_if_fail (name != NULL, 0.0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)
- && (node->type == FLUID_NUM_TYPE)) {
- fluid_num_setting_t* setting = (fluid_num_setting_t*) node;
- retval = setting->def;
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Set an integer value for a setting
- *
- * @param settings a settings object
- * @param name a setting's name
- * @param val new setting's integer value
- * @return 1 if the value has been set, 0 otherwise
- */
- int
- fluid_settings_setint(fluid_settings_t* settings, const char *name, int val)
- {
- fluid_setting_node_t *node;
- fluid_int_setting_t* setting;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)) {
- if (node->type == FLUID_INT_TYPE) {
- setting = (fluid_int_setting_t*) node;
- if (val < setting->min) val = setting->min;
- else if (val > setting->max) val = setting->max;
- setting->value = val;
- /* Call under lock to keep update() synchronized with the current value */
- if (setting->update) (*setting->update)(setting->data, name, val);
- retval = 1;
- }
- } else {
- /* insert a new setting */
- fluid_int_setting_t* setting;
- setting = new_fluid_int_setting(INT_MIN, INT_MAX, 0, 0, NULL, NULL);
- setting->value = val;
- retval = fluid_settings_set(settings, name, setting);
- if (retval != 1) delete_fluid_int_setting (setting);
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Get an integer value setting.
- *
- * @param settings a settings object
- * @param name a setting's name
- * @param val pointer to a variable to receive the setting's integer value
- * @return 1 if the value exists, 0 otherwise
- */
- int
- fluid_settings_getint(fluid_settings_t* settings, const char *name, int* val)
- {
- fluid_setting_node_t *node;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_return_val_if_fail (val != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)
- && (node->type == FLUID_INT_TYPE)) {
- fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
- *val = setting->value;
- retval = 1;
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Get the range of values of an integer setting
- * @param settings a settings object
- * @param name a setting's name
- * @param min setting's range lower limit
- * @param max setting's range upper limit
- */
- void
- fluid_settings_getint_range(fluid_settings_t* settings, const char *name,
- int* min, int* max)
- {
- fluid_setting_node_t *node;
- fluid_return_if_fail (settings != NULL);
- fluid_return_if_fail (name != NULL);
- fluid_return_if_fail (min != NULL);
- fluid_return_if_fail (max != NULL);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)
- && (node->type == FLUID_INT_TYPE)) {
- fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
- *min = setting->min;
- *max = setting->max;
- }
- fluid_rec_mutex_unlock (settings->mutex);
- }
- /**
- * Get the default value of an integer setting.
- *
- * @param settings a settings object
- * @param name a setting's name
- * @return the setting's default integer value it it exists, zero otherwise
- */
- int
- fluid_settings_getint_default(fluid_settings_t* settings, const char *name)
- {
- fluid_setting_node_t *node;
- int retval = 0;
- fluid_return_val_if_fail (settings != NULL, 0);
- fluid_return_val_if_fail (name != NULL, 0);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node)
- && (node->type == FLUID_INT_TYPE)) {
- fluid_int_setting_t* setting = (fluid_int_setting_t*) node;
- retval = setting->def;
- }
- fluid_rec_mutex_unlock (settings->mutex);
- return retval;
- }
- /**
- * Iterate the available options for a named string setting, calling the provided
- * callback function for each existing option.
- *
- * @param settings a settings object
- * @param name a setting's name
- * @param data any user provided pointer
- * @param func callback function to be called on each iteration
- *
- * NOTE: Starting with FluidSynth 1.1.0 the a func callback is called for each
- * option in alphabetical order. Sort order was undefined in previous versions.
- */
- void
- fluid_settings_foreach_option (fluid_settings_t* settings, const char *name,
- void* data, fluid_settings_foreach_option_t func)
- {
- fluid_setting_node_t *node;
- fluid_str_setting_t *setting;
- fluid_list_t *p, *newlist = NULL;
- fluid_return_if_fail (settings != NULL);
- fluid_return_if_fail (name != NULL);
- fluid_return_if_fail (func != NULL);
- fluid_rec_mutex_lock (settings->mutex); /* ++ lock */
- if (!fluid_settings_get (settings, name, &node) || node->type != FLUID_STR_TYPE)
- {
- fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */
- return;
- }
- setting = (fluid_str_setting_t*)node;
- /* Duplicate option list */
- for (p = setting->options; p; p = p->next)
- newlist = fluid_list_append (newlist, fluid_list_get (p));
- /* Sort by name */
- newlist = fluid_list_sort (newlist, fluid_list_str_compare_func);
- for (p = newlist; p; p = p->next)
- (*func)(data, (char *)name, (char *)fluid_list_get (p));
- fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */
- delete_fluid_list (newlist);
- }
- /**
- * Count option string values for a string setting.
- * @param settings a settings object
- * @param name Name of setting
- * @return Count of options for this string setting (0 if none, -1 if not found
- * or not a string setting)
- * @since 1.1.0
- */
- int
- fluid_settings_option_count (fluid_settings_t *settings, const char *name)
- {
- fluid_setting_node_t *node;
- int count = -1;
- fluid_return_val_if_fail (settings != NULL, -1);
- fluid_return_val_if_fail (name != NULL, -1);
- fluid_rec_mutex_lock (settings->mutex);
- if (fluid_settings_get(settings, name, &node) && node->type == FLUID_STR_TYPE)
- count = fluid_list_size (((fluid_str_setting_t *)node)->options);
- fluid_rec_mutex_unlock (settings->mutex);
- return (count);
- }
- /**
- * Concatenate options for a string setting together with a separator between.
- * @param settings Settings object
- * @param name Settings name
- * @param separator String to use between options (NULL to use ", ")
- * @return Newly allocated string or NULL on error (out of memory, not a valid
- * setting a name or not a string setting). Free the string when finished with it.
- * @since 1.1.0
- */
- char *
- fluid_settings_option_concat (fluid_settings_t *settings, const char *name,
- const char *separator)
- {
- fluid_setting_node_t *node;
- fluid_str_setting_t *setting;
- fluid_list_t *p, *newlist = NULL;
- int count, len;
- char *str, *option;
- fluid_return_val_if_fail (settings != NULL, NULL);
- fluid_return_val_if_fail (name != NULL, NULL);
- if (!separator) separator = ", ";
- fluid_rec_mutex_lock (settings->mutex); /* ++ lock */
- if (!fluid_settings_get (settings, name, &node) || node->type != FLUID_STR_TYPE)
- {
- fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */
- return (NULL);
- }
- setting = (fluid_str_setting_t*)node;
- /* Duplicate option list, count options and get total string length */
- for (p = setting->options, count = 0, len = 0; p; p = p->next, count++)
- {
- option = fluid_list_get (p);
- if (option)
- {
- newlist = fluid_list_append (newlist, option);
- len += strlen (option);
- }
- }
- if (count > 1) len += (count - 1) * strlen (separator);
- len++; /* For terminator */
- /* Sort by name */
- newlist = fluid_list_sort (newlist, fluid_list_str_compare_func);
- str = FLUID_MALLOC (len);
- str[0] = 0;
- if (str)
- {
- for (p = newlist; p; p = p->next)
- {
- option = fluid_list_get (p);
- strcat (str, option);
- if (p->next) strcat (str, separator);
- }
- }
- fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */
- delete_fluid_list (newlist);
- if (!str) FLUID_LOG (FLUID_ERR, "Out of memory");
- return (str);
- }
- /* Structure passed to fluid_settings_foreach_iter recursive function */
- typedef struct
- {
- char path[MAX_SETTINGS_LABEL+1]; /* Maximum settings label length */
- fluid_list_t *names; /* For fluid_settings_foreach() */
- } fluid_settings_foreach_bag_t;
- static int
- fluid_settings_foreach_iter (void* key, void* value, void* data)
- {
- fluid_settings_foreach_bag_t *bag = data;
- char *keystr = key;
- fluid_setting_node_t *node = value;
- int pathlen;
- char *s;
- pathlen = strlen (bag->path);
- if (pathlen > 0)
- {
- bag->path[pathlen] = '.';
- bag->path[pathlen + 1] = 0;
- }
- strcat (bag->path, keystr);
- switch (node->type) {
- case FLUID_NUM_TYPE:
- case FLUID_INT_TYPE:
- case FLUID_STR_TYPE:
- s = FLUID_STRDUP (bag->path);
- if (s) bag->names = fluid_list_append (bag->names, s);
- break;
- case FLUID_SET_TYPE:
- fluid_hashtable_foreach(((fluid_set_setting_t *)value)->hashtable,
- fluid_settings_foreach_iter, bag);
- break;
- }
- bag->path[pathlen] = 0;
- return 0;
- }
- /**
- * Iterate the existing settings defined in a settings object, calling the
- * provided callback function for each setting.
- *
- * @param settings a settings object
- * @param data any user provided pointer
- * @param func callback function to be called on each iteration
- *
- * NOTE: Starting with FluidSynth 1.1.0 the a func callback is called for each
- * setting in alphabetical order. Sort order was undefined in previous versions.
- */
- void
- fluid_settings_foreach (fluid_settings_t* settings, void* data,
- fluid_settings_foreach_t func)
- {
- fluid_settings_foreach_bag_t bag;
- fluid_setting_node_t *node;
- fluid_list_t *p;
- int r;
- fluid_return_if_fail (settings != NULL);
- fluid_return_if_fail (func != NULL);
- bag.path[0] = 0;
- bag.names = NULL;
- fluid_rec_mutex_lock (settings->mutex);
- /* Add all node names to the bag.names list */
- fluid_hashtable_foreach (settings, fluid_settings_foreach_iter, &bag);
- /* Sort names */
- bag.names = fluid_list_sort (bag.names, fluid_list_str_compare_func);
- /* Loop over names and call the callback */
- for (p = bag.names; p; p = p->next)
- {
- r = fluid_settings_get (settings, (char *)(p->data), &node);
- if (r && node) (*func) (data, (char *)(p->data), node->type);
- FLUID_FREE (p->data); /* -- Free name */
- }
- fluid_rec_mutex_unlock (settings->mutex);
- delete_fluid_list (bag.names); /* -- Free names list */
- }