# src/fluid_settings.c

    00001 /* FluidSynth - A Software Synthesizer
    00002  *
    00003  * Copyright (C) 2003  Peter Hanappe and others.
    00004  *
    00005  * This library is free software; you can redistribute it and/or
    00006  * modify it under the terms of the GNU Library General Public License
    00007  * as published by the Free Software Foundation; either version 2 of
    00008  * the License, or (at your option) any later version.
    00009  *
    00010  * This library is distributed in the hope that it will be useful, but
    00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013  * Library General Public License for more details.
    00014  *
    00015  * You should have received a copy of the GNU Library General Public
    00016  * License along with this library; if not, write to the Free
    00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    00018  * 02111-1307, USA
    00019  */
    00020
    00021 #include "fluidsynth_priv.h"
    00022 #include "fluid_sys.h"
    00023 #include "fluid_hash.h"
    00024 #include "fluid_synth.h"
    00025 #include "fluid_cmd.h"
    00026 #include "fluid_adriver.h"
    00027 #include "fluid_mdriver.h"
    00028 #include "fluid_settings.h"
    00029
    00030 /* maximum allowed components of a settings variable (separated by '.') */
    00031 #define MAX_SETTINGS_TOKENS     8       /* currently only a max of 3 are used */
    00032 #define MAX_SETTINGS_LABEL      256     /* max length of a settings variable label */
    00033
    00034 static void fluid_settings_init(fluid_settings_t* settings);
    00035 static void fluid_settings_hash_delete(void* value, int type);
    00036 static int fluid_settings_tokenize(char* s, char *buf, char** ptr);
    00037
    00038
    00039 typedef struct {
    00040   char* value;
    00041   char* def;
    00042   int hints;
    00043   fluid_list_t* options;
    00044   fluid_str_update_t update;
    00045   void* data;
    00046 } fluid_str_setting_t;
    00047
    00048 static fluid_str_setting_t*
    00049 new_fluid_str_setting(char* value, char* def, int hints, fluid_str_update_t fun, void* data)
    00050 {
    00051   fluid_str_setting_t* str;
    00052   str = FLUID_NEW(fluid_str_setting_t);
    00053   str->value = value? FLUID_STRDUP(value) : NULL;
    00054   str->def = def? FLUID_STRDUP(def) : NULL;
    00055   str->hints = hints;
    00056   str->options = NULL;
    00057   str->update = fun;
    00058   str->data = data;
    00059   return str;
    00060 }
    00061
    00062 static void delete_fluid_str_setting(fluid_str_setting_t* str)
    00063 {
    00064   if (str) {
    00065     if (str->value) {
    00066       FLUID_FREE(str->value);
    00067     }
    00068     if (str->def) {
    00069       FLUID_FREE(str->def);
    00070     }
    00071     if (str->options) {
    00072       fluid_list_t* list = str->options;
    00073
    00074       while (list) {
    00075         FLUID_FREE (list->data);
    00076         list = fluid_list_next(list);
    00077       }
    00078
    00079       delete_fluid_list(str->options);
    00080     }
    00081     FLUID_FREE(str);
    00082   }
    00083 }
    00084
    00085
    00086
    00087
    00088 typedef struct {
    00089   double value;
    00090   double def;
    00091   double min;
    00092   double max;
    00093   int hints;
    00094   fluid_num_update_t update;
    00095   void* data;
    00096 } fluid_num_setting_t;
    00097
    00098
    00099 static fluid_num_setting_t*
    00100 new_fluid_num_setting(double min, double max, double def,
    00101                      int hints, fluid_num_update_t fun, void* data)
    00102 {
    00103   fluid_num_setting_t* setting;
    00104   setting = FLUID_NEW(fluid_num_setting_t);
    00105   setting->value = def;
    00106   setting->def = def;
    00107   setting->min = min;
    00108   setting->max = max;
    00109   setting->hints = hints;
    00110   setting->update = fun;
    00111   setting->data = data;
    00112   return setting;
    00113 }
    00114
    00115 static void delete_fluid_num_setting(fluid_num_setting_t* setting)
    00116 {
    00117   if (setting) {
    00118      FLUID_FREE(setting);
    00119   }
    00120 }
    00121
    00122
    00123
    00124
    00125 typedef struct {
    00126   int value;
    00127   int def;
    00128   int min;
    00129   int max;
    00130   int hints;
    00131   fluid_int_update_t update;
    00132   void* data;
    00133 } fluid_int_setting_t;
    00134
    00135
    00136 static fluid_int_setting_t*
    00137 new_fluid_int_setting(int min, int max, int def,
    00138                      int hints, fluid_int_update_t fun, void* data)
    00139 {
    00140   fluid_int_setting_t* setting;
    00141   setting = FLUID_NEW(fluid_int_setting_t);
    00142   setting->value = def;
    00143   setting->def = def;
    00144   setting->min = min;
    00145   setting->max = max;
    00146   setting->hints = hints;
    00147   setting->update = fun;
    00148   setting->data = data;
    00149   return setting;
    00150 }
    00151
    00152 static void delete_fluid_int_setting(fluid_int_setting_t* setting)
    00153 {
    00154   if (setting) {
    00155      FLUID_FREE(setting);
    00156   }
    00157 }
    00158
    00159
    00160
    00161 fluid_settings_t* new_fluid_settings()
    00162 {
    00163   fluid_settings_t* settings = new_fluid_hashtable(fluid_settings_hash_delete);
    00164   if (settings == NULL) {
    00165     return NULL;
    00166   }
    00167   fluid_settings_init(settings);
    00168   return settings;
    00169 }
    00170
    00171 void delete_fluid_settings(fluid_settings_t* settings)
    00172 {
    00173   delete_fluid_hashtable(settings);
    00174 }
    00175
    00176 void fluid_settings_hash_delete(void* value, int type)
    00177 {
    00178   switch (type) {
    00179   case FLUID_NUM_TYPE:
    00180     delete_fluid_num_setting((fluid_num_setting_t*) value);
    00181     break;
    00182   case FLUID_INT_TYPE:
    00183     delete_fluid_int_setting((fluid_int_setting_t*) value);
    00184     break;
    00185   case FLUID_STR_TYPE:
    00186     delete_fluid_str_setting((fluid_str_setting_t*) value);
    00187     break;
    00188   case FLUID_SET_TYPE:
    00189     delete_fluid_hashtable((fluid_hashtable_t*) value);
    00190     break;
    00191   }
    00192 }
    00193
    00194 void fluid_settings_init(fluid_settings_t* settings)
    00195 {
    00196   fluid_synth_settings(settings);
    00197   fluid_shell_settings(settings);
    00198   fluid_audio_driver_settings(settings);
    00199   fluid_midi_driver_settings(settings);
    00200 }
    00201
    00202 static int fluid_settings_tokenize(char* s, char *buf, char** ptr)
    00203 {
    00204   char *tokstr, *tok;
    00205   int n = 0;
    00206
    00207   if (strlen (s) > MAX_SETTINGS_LABEL)
    00208   {
    00209     FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars",
    00210               MAX_SETTINGS_LABEL);
    00211     return 0;
    00212   }
    00213
    00214   FLUID_STRCPY(buf, s); /* copy string to buffer, since it gets modified */
    00215   tokstr = buf;
    00216
    00217   while ((tok = fluid_strtok (&tokstr, ".")))
    00218   {
    00219     if (n > MAX_SETTINGS_TOKENS)
    00220     {
    00221       FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max token count of %d",
    00222                 MAX_SETTINGS_TOKENS);
    00223       return 0;
    00224     }
    00225
    00226     ptr[n++] = tok;
    00227   }
    00228
    00229   return n;
    00230 }
    00231
    00233 static int fluid_settings_get(fluid_settings_t* settings,
    00234                              char** name, int len,
    00235                              void** value, int* type)
    00236 {
    00237   fluid_hashtable_t* table = settings;
    00238   int t;
    00239   void* v;
    00240   int n;
    00241
    00242   for (n = 0; n < len; n++) {
    00243
    00244     if (table == NULL) {
    00245       return 0;
    00246     }
    00247
    00248     if (!fluid_hashtable_lookup(table, name[n], &v, &t)) {
    00249       return 0;
    00250     }
    00251
    00252     table = (t == FLUID_SET_TYPE)? (fluid_hashtable_t*) v : NULL;
    00253   }
    00254
    00255   if (value) {
    00256     *value = v;
    00257   }
    00258
    00259   if (type) {
    00260     *type = t;
    00261   }
    00262
    00263   return 1;
    00264 }
    00265
    00267 static int fluid_settings_set(fluid_settings_t* settings,
    00268                              char** name, int len,
    00269                              void* value, int type)
    00270 {
    00271   fluid_hashtable_t* table = settings;
    00272   int t;
    00273   void* v;
    00274   int n, num = len - 1;
    00275
    00276   for (n = 0; n < num; n++) {
    00277
    00278     if (fluid_hashtable_lookup(table, name[n], &v, &t)) {
    00279
    00280       if (t == FLUID_SET_TYPE) {
    00281         table = (fluid_hashtable_t*) v;
    00282       } else {
    00283         /* path ends prematurely */
    00284         FLUID_LOG(FLUID_WARN, "'%s' is not a node", name[n]);
    00285         return 0;
    00286       }
    00287
    00288     } else {
    00289       /* create a new node */
    00290       fluid_hashtable_t* tmp;
    00291       tmp = new_fluid_hashtable(fluid_settings_hash_delete);
    00292       fluid_hashtable_insert(table, name[n], tmp, FLUID_SET_TYPE);
    00293       table = tmp;
    00294     }
    00295   }
    00296
    00297   fluid_hashtable_replace(table, name[num], value, type);
    00298
    00299   return 1;
    00300 }
    00301
    00304 int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, int hints,
    00305                                fluid_str_update_t fun, void* data)
    00306 {
    00307   int type;
    00308   void* value;
    00309   char* tokens[MAX_SETTINGS_TOKENS];
    00310   char buf[MAX_SETTINGS_LABEL+1];
    00311   int ntokens;
    00312   fluid_str_setting_t* setting;
    00313
    00314   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00315
    00316   if (!fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
    00317     setting = new_fluid_str_setting(def, def, hints, fun, data);
    00318     return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_STR_TYPE);
    00319
    00320   } else {
    00321     /* if variable already exists, don't change its value. */
    00322     if (type == FLUID_STR_TYPE) {
    00323       setting = (fluid_str_setting_t*) value;
    00324       setting->update = fun;
    00325       setting->data = data;
    00326       setting->def = def? FLUID_STRDUP(def) : NULL;
    00327       setting->hints = hints;
    00328       return 1;
    00329     } else {
    00330       FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
    00331       return 1;
    00332     }
    00333   }
    00334 }
    00335
    00338 int fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
    00339                                double min, double max, int hints,
    00340                                fluid_num_update_t fun, void* data)
    00341 {
    00342   int type;
    00343   void* value;
    00344   char* tokens[MAX_SETTINGS_TOKENS];
    00345   char buf[MAX_SETTINGS_LABEL+1];
    00346   int ntokens;
    00347
    00348   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00349
    00350   if (!fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
    00351     /* insert a new setting */
    00352     fluid_num_setting_t* setting;
    00353     setting = new_fluid_num_setting(min, max, def, hints, fun, data);
    00354     return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_NUM_TYPE);
    00355
    00356   } else {
    00357     if (type == FLUID_NUM_TYPE) {
    00358       /* update the existing setting but don't change its value */
    00359       fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
    00360       setting->update = fun;
    00361       setting->data = data;
    00362       setting->min = min;
    00363       setting->max = max;
    00364       setting->def = def;
    00365       setting->hints = hints;
    00366       return 1;
    00367
    00368     } else {
    00369       /* type mismatch */
    00370       FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
    00371       return 0;
    00372     }
    00373   }
    00374 }
    00375
    00378 int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
    00379                                int min, int max, int hints,
    00380                                fluid_int_update_t fun, void* data)
    00381 {
    00382   int type;
    00383   void* value;
    00384   char* tokens[MAX_SETTINGS_TOKENS];
    00385   char buf[MAX_SETTINGS_LABEL+1];
    00386   int ntokens;
    00387
    00388   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00389
    00390   if (!fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
    00391     /* insert a new setting */
    00392     fluid_int_setting_t* setting;
    00393     setting = new_fluid_int_setting(min, max, def, hints, fun, data);
    00394     return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_INT_TYPE);
    00395
    00396   } else {
    00397     if (type == FLUID_INT_TYPE) {
    00398       /* update the existing setting but don't change its value */
    00399       fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
    00400       setting->update = fun;
    00401       setting->data = data;
    00402       setting->min = min;
    00403       setting->max = max;
    00404       setting->def = def;
    00405       setting->hints = hints;
    00406       return 1;
    00407
    00408     } else {
    00409       /* type mismatch */
    00410       FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name);
    00411       return 0;
    00412     }
    00413   }
    00414 }
    00415
    00416 int fluid_settings_get_type(fluid_settings_t* settings, char* name)
    00417 {
    00418   int type;
    00419   void* value;
    00420   char* tokens[MAX_SETTINGS_TOKENS];
    00421   char buf[MAX_SETTINGS_LABEL+1];
    00422   int ntokens;
    00423
    00424   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00425
    00426   return (fluid_settings_get(settings, tokens, ntokens, &value, &type))? type : FLUID_NO_TYPE;
    00427 }
    00428
    00429 int fluid_settings_get_hints(fluid_settings_t* settings, char* name)
    00430 {
    00431   int type;
    00432   void* value;
    00433   char* tokens[MAX_SETTINGS_TOKENS];
    00434   char buf[MAX_SETTINGS_LABEL+1];
    00435   int ntokens;
    00436
    00437   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00438
    00439   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
    00440     if (type == FLUID_NUM_TYPE) {
    00441       fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
    00442       return setting->hints;
    00443     } else if (type == FLUID_STR_TYPE) {
    00444       fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
    00445       return setting->hints;
    00446     } else {
    00447       return 0;
    00448     }
    00449   } else {
    00450     return 0;
    00451   }
    00452 }
    00453
    00454 int fluid_settings_is_realtime(fluid_settings_t* settings, char* name)
    00455 {
    00456   int type;
    00457   void* value;
    00458   char* tokens[MAX_SETTINGS_TOKENS];
    00459   char buf[MAX_SETTINGS_LABEL+1];
    00460   int ntokens;
    00461
    00462   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00463
    00464   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
    00465     if (type == FLUID_NUM_TYPE) {
    00466       fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
    00467       return setting->update != NULL;
    00468
    00469     } else if (type == FLUID_STR_TYPE) {
    00470       fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
    00471       return setting->update != NULL;
    00472     } else {
    00473       return 0;
    00474     }
    00475   } else {
    00476     return 0;
    00477   }
    00478 }
    00479
    00480 int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
    00481 {
    00482   char* tokens[MAX_SETTINGS_TOKENS];
    00483   char buf[MAX_SETTINGS_LABEL+1];
    00484   int ntokens;
    00485   int type;
    00486   void* value;
    00487   fluid_str_setting_t* setting;
    00488
    00489   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00490
    00491   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
    00492
    00493     if (type != FLUID_STR_TYPE) {
    00494       return 0;
    00495     }
    00496
    00497     setting = (fluid_str_setting_t*) value;
    00498
    00499     if (setting->value) {
    00500       FLUID_FREE(setting->value);
    00501     }
    00502     setting->value = str? FLUID_STRDUP(str) : NULL;
    00503
    00504     if (setting->update) {
    00505       (*setting->update)(setting->data, name, setting->value);
    00506     }
    00507
    00508     return 1;
    00509
    00510   } else {
    00511     /* insert a new setting */
    00512     fluid_str_setting_t* setting;
    00513     setting = new_fluid_str_setting(str, NULL, 0, NULL, NULL);
    00514     return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_STR_TYPE);
    00515   }
    00516 }
    00517
    00518 int fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str)
    00519 {
    00520   int type;
    00521   void* value;
    00522   char* tokens[MAX_SETTINGS_TOKENS];
    00523   char buf[MAX_SETTINGS_LABEL+1];
    00524   int ntokens;
    00525
    00526   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00527
    00528   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00529       && (type == FLUID_STR_TYPE)) {
    00530     fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
    00531     *str = setting->value;
    00532     return 1;
    00533   }
    00534   *str = NULL;
    00535   return 0;
    00536 }
    00537
    00538 int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
    00539 {
    00540   int type;
    00541   void* value;
    00542   char* tokens[MAX_SETTINGS_TOKENS];
    00543   char buf[MAX_SETTINGS_LABEL+1];
    00544   int ntokens;
    00545
    00546   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00547
    00548   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00549       && (type == FLUID_STR_TYPE)) {
    00550     fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
    00551     return FLUID_STRCMP(setting->value, s) == 0;
    00552   }
    00553   return 0;
    00554 }
    00555
    00556 char*
    00557 fluid_settings_getstr_default(fluid_settings_t* settings, char* name)
    00558 {
    00559   int type;
    00560   void* value;
    00561   char* tokens[MAX_SETTINGS_TOKENS];
    00562   char buf[MAX_SETTINGS_LABEL+1];
    00563   int ntokens;
    00564
    00565   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00566
    00567   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00568       && (type == FLUID_STR_TYPE)) {
    00569     fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
    00570     return setting->def;
    00571   } else {
    00572     return NULL;
    00573   }
    00574 }
    00575
    00576 int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
    00577 {
    00578   int type;
    00579   void* value;
    00580   char* tokens[MAX_SETTINGS_TOKENS];
    00581   char buf[MAX_SETTINGS_LABEL+1];
    00582   int ntokens;
    00583
    00584   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00585
    00586   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00587       && (type == FLUID_STR_TYPE)) {
    00588     fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
    00589     char* copy = FLUID_STRDUP(s);
    00590     setting->options = fluid_list_append(setting->options, copy);
    00591     return 1;
    00592   } else {
    00593     return 0;
    00594   }
    00595 }
    00596
    00597 int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s)
    00598 {
    00599   int type;
    00600   void* value;
    00601   char* tokens[MAX_SETTINGS_TOKENS];
    00602   char buf[MAX_SETTINGS_LABEL+1];
    00603   int ntokens;
    00604
    00605   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00606
    00607   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00608       && (type == FLUID_STR_TYPE)) {
    00609
    00610     fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
    00611     fluid_list_t* list = setting->options;
    00612
    00613     while (list) {
    00614       char* option = (char*) fluid_list_get(list);
    00615       if (FLUID_STRCMP(s, option) == 0) {
    00616         FLUID_FREE (option);
    00617         setting->options = fluid_list_remove_link(setting->options, list);
    00618         return 1;
    00619       }
    00620       list = fluid_list_next(list);
    00621     }
    00622
    00623     return 0;
    00624   } else {
    00625     return 0;
    00626   }
    00627 }
    00628
    00629 int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val)
    00630 {
    00631   int type;
    00632   void* value;
    00633   fluid_num_setting_t* setting;
    00634   char* tokens[MAX_SETTINGS_TOKENS];
    00635   char buf[MAX_SETTINGS_LABEL+1];
    00636   int ntokens;
    00637
    00638   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00639
    00640   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
    00641
    00642     if (type != FLUID_NUM_TYPE) {
    00643       return 0;
    00644     }
    00645
    00646     setting = (fluid_num_setting_t*) value;
    00647
    00648     if (val < setting->min) {
    00649       val = setting->min;
    00650     } else if (val > setting->max) {
    00651       val = setting->max;
    00652     }
    00653
    00654     setting->value = val;
    00655
    00656     if (setting->update) {
    00657       (*setting->update)(setting->data, name, val);
    00658     }
    00659
    00660     return 1;
    00661
    00662   } else {
    00663     /* insert a new setting */
    00664     fluid_num_setting_t* setting;
    00665     setting = new_fluid_num_setting(-1e10, 1e10, 0.0f, 0, NULL, NULL);
    00666     setting->value = val;
    00667     return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_NUM_TYPE);
    00668   }
    00669 }
    00670
    00671 int fluid_settings_getnum(fluid_settings_t* settings, char* name, double* val)
    00672 {
    00673   int type;
    00674   void* value;
    00675   char* tokens[MAX_SETTINGS_TOKENS];
    00676   char buf[MAX_SETTINGS_LABEL+1];
    00677   int ntokens;
    00678
    00679   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00680
    00681   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00682       && (type == FLUID_NUM_TYPE)) {
    00683     fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
    00684     *val = setting->value;
    00685     return 1;
    00686   }
    00687   return 0;
    00688 }
    00689
    00690
    00691 void fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double* min, double* max)
    00692 {
    00693   int type;
    00694   void* value;
    00695   char* tokens[MAX_SETTINGS_TOKENS];
    00696   char buf[MAX_SETTINGS_LABEL+1];
    00697   int ntokens;
    00698
    00699   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00700
    00701   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00702       && (type == FLUID_NUM_TYPE)) {
    00703     fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
    00704     *min = setting->min;
    00705     *max = setting->max;
    00706   }
    00707 }
    00708
    00709 double
    00710 fluid_settings_getnum_default(fluid_settings_t* settings, char* name)
    00711 {
    00712   int type;
    00713   void* value;
    00714   char* tokens[MAX_SETTINGS_TOKENS];
    00715   char buf[MAX_SETTINGS_LABEL+1];
    00716   int ntokens;
    00717
    00718   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00719
    00720   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00721       && (type == FLUID_NUM_TYPE)) {
    00722     fluid_num_setting_t* setting = (fluid_num_setting_t*) value;
    00723     return setting->def;
    00724   } else {
    00725     return 0.0f;
    00726   }
    00727 }
    00728
    00729
    00730 int fluid_settings_setint(fluid_settings_t* settings, char* name, int val)
    00731 {
    00732   int type;
    00733   void* value;
    00734   fluid_int_setting_t* setting;
    00735   char* tokens[MAX_SETTINGS_TOKENS];
    00736   char buf[MAX_SETTINGS_LABEL+1];
    00737   int ntokens;
    00738
    00739   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00740
    00741   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) {
    00742
    00743     if (type != FLUID_INT_TYPE) {
    00744       return 0;
    00745     }
    00746
    00747     setting = (fluid_int_setting_t*) value;
    00748
    00749     if (val < setting->min) {
    00750       val = setting->min;
    00751     } else if (val > setting->max) {
    00752       val = setting->max;
    00753     }
    00754
    00755     setting->value = val;
    00756
    00757     if (setting->update) {
    00758       (*setting->update)(setting->data, name, val);
    00759     }
    00760
    00761     return 1;
    00762
    00763   } else {
    00764     /* insert a new setting */
    00765     fluid_int_setting_t* setting;
    00766     setting = new_fluid_int_setting(INT_MIN, INT_MAX, 0, 0, NULL, NULL);
    00767     setting->value = val;
    00768     return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_INT_TYPE);
    00769   }
    00770 }
    00771
    00772 int fluid_settings_getint(fluid_settings_t* settings, char* name, int* val)
    00773 {
    00774   int type;
    00775   void* value;
    00776   char* tokens[MAX_SETTINGS_TOKENS];
    00777   char buf[MAX_SETTINGS_LABEL+1];
    00778   int ntokens;
    00779
    00780   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00781
    00782   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00783       && (type == FLUID_INT_TYPE)) {
    00784     fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
    00785     *val = setting->value;
    00786     return 1;
    00787   }
    00788   return 0;
    00789 }
    00790
    00791
    00792 void fluid_settings_getint_range(fluid_settings_t* settings, char* name, int* min, int* max)
    00793 {
    00794   int type;
    00795   void* value;
    00796   char* tokens[MAX_SETTINGS_TOKENS];
    00797   char buf[MAX_SETTINGS_LABEL+1];
    00798   int ntokens;
    00799
    00800   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00801
    00802   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00803       && (type == FLUID_INT_TYPE)) {
    00804     fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
    00805     *min = setting->min;
    00806     *max = setting->max;
    00807   }
    00808 }
    00809
    00810 int
    00811 fluid_settings_getint_default(fluid_settings_t* settings, char* name)
    00812 {
    00813   int type;
    00814   void* value;
    00815   char* tokens[MAX_SETTINGS_TOKENS];
    00816   char buf[MAX_SETTINGS_LABEL+1];
    00817   int ntokens;
    00818
    00819   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00820
    00821   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00822       && (type == FLUID_INT_TYPE)) {
    00823     fluid_int_setting_t* setting = (fluid_int_setting_t*) value;
    00824     return setting->def;
    00825   } else {
    00826     return 0.0f;
    00827   }
    00828 }
    00829
    00830
    00831
    00832
    00833 void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void* data,
    00834                                   fluid_settings_foreach_option_t func)
    00835 {
    00836   int type;
    00837   void* value;
    00838   char* tokens[MAX_SETTINGS_TOKENS];
    00839   char buf[MAX_SETTINGS_LABEL+1];
    00840   int ntokens;
    00841
    00842   if (!func) {
    00843     return;
    00844   }
    00845
    00846   ntokens = fluid_settings_tokenize(name, buf, tokens);
    00847
    00848   if (fluid_settings_get(settings, tokens, ntokens, &value, &type)
    00849       && (type == FLUID_STR_TYPE)) {
    00850
    00851     fluid_str_setting_t* setting = (fluid_str_setting_t*) value;
    00852     fluid_list_t* list = setting->options;
    00853
    00854     while (list) {
    00855       char* option = (char*) fluid_list_get(list);
    00856       (*func)(data, name, option);
    00857       list = fluid_list_next(list);
    00858     }
    00859   }
    00860 }
    00861
    00862
    00863 static fluid_settings_foreach_t fluid_settings_foreach_func;
    00864 static void* fluid_settings_foreach_data;
    00865
    00866 int fluid_settings_foreach_iter(char* key, void* value, int type, void* data)
    00867 {
    00868   char path[1024];
    00869
    00870   if (data == 0) {
    00871     snprintf(path, 1024, "%s", key);
    00872   } else {
    00873     snprintf(path, 1024, "%s.%s", (char*) data, key);
    00874   }
    00875   path[1023] = 0;
    00876
    00877   switch (type) {
    00878   case FLUID_NUM_TYPE:
    00879   case FLUID_INT_TYPE:
    00880   case FLUID_STR_TYPE:
    00881     (*fluid_settings_foreach_func)(fluid_settings_foreach_data, path, type);
    00882     break;
    00883   case FLUID_SET_TYPE:
    00884     fluid_hashtable_foreach((fluid_hashtable_t*) value, fluid_settings_foreach_iter, &path[0]);
    00885     break;
    00886   }
    00887
    00888   return 0;
    00889 }
    00890
    00891 void fluid_settings_foreach(fluid_settings_t* settings, void* data, fluid_settings_foreach_t func)
    00892 {
    00893   fluid_settings_foreach_func = func;
    00894   fluid_settings_foreach_data = data;
    00895   fluid_hashtable_foreach(settings, fluid_settings_foreach_iter, 0);
    00896 }