/** * 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; }
/** * 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); }
int fluid_samplecache_unload(const short *sample_data) { fluid_list_t *entry_list; fluid_samplecache_entry_t *entry; int ret; fluid_mutex_lock(samplecache_mutex); entry_list = samplecache_list; while (entry_list) { entry = (fluid_samplecache_entry_t *)fluid_list_get(entry_list); if (sample_data == entry->sample_data) { entry->num_references--; if (entry->num_references == 0) { if (entry->mlocked) { fluid_munlock(entry->sample_data, entry->sample_count * sizeof(short)); if (entry->sample_data24 != NULL) { fluid_munlock(entry->sample_data24, entry->sample_count); } } samplecache_list = fluid_list_remove(samplecache_list, entry); delete_samplecache_entry(entry); } ret = FLUID_OK; goto unlock_exit; } entry_list = fluid_list_next(entry_list); } FLUID_LOG(FLUID_ERR, "Trying to free sample data not found in cache."); ret = FLUID_FAILED; unlock_exit: fluid_mutex_unlock(samplecache_mutex); return ret; }
static fluid_samplecache_entry_t *get_samplecache_entry(SFData *sf, unsigned int sample_start, unsigned int sample_end, int sample_type) { time_t mtime; fluid_list_t *entry_list; fluid_samplecache_entry_t *entry; if (fluid_get_file_modification_time(sf->fname, &mtime) == FLUID_FAILED) { FLUID_LOG(FLUID_WARN, "Unable to read modificaton time of soundfont file."); mtime = 0; } entry_list = samplecache_list; while (entry_list) { entry = (fluid_samplecache_entry_t *)fluid_list_get(entry_list); if ((FLUID_STRCMP(sf->fname, entry->filename) == 0) && (mtime == entry->modification_time) && (sf->samplepos == entry->sf_samplepos) && (sf->samplesize == entry->sf_samplesize) && (sf->sample24pos == entry->sf_sample24pos) && (sf->sample24size == entry->sf_sample24size) && (sample_start == entry->sample_start) && (sample_end == entry->sample_end) && (sample_type == entry->sample_type)) { return entry; } entry_list = fluid_list_next(entry_list); } return NULL; }
/** * 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); }