preset.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:26k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * preset.c:
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * $Id: e7aea345ddb48ca71c10b8c33d2c4578712eb47d $
  6.  *
  7.  * Authors: Cyril Deguet <asmax@videolan.org>
  8.  *          code from projectM http://xmms-projectm.sourceforge.net
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. #ifdef HAVE_CONFIG_H
  25. # include "config.h"
  26. #endif
  27. #include <vlc_common.h>
  28. #include <vlc_charset.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <dirent.h>
  32. #include <time.h>
  33. #include "common.h"
  34. #include "fatal.h"
  35. #include "preset_types.h"
  36. #include "preset.h"
  37. #include "parser.h"
  38. #include "expr_types.h"
  39. #include "eval.h"
  40. #include "splaytree_types.h"
  41. #include "splaytree.h"
  42. #include "tree_types.h"
  43. #include "per_frame_eqn_types.h"
  44. #include "per_frame_eqn.h"
  45. #include "per_pixel_eqn_types.h"
  46. #include "per_pixel_eqn.h"
  47. #include "init_cond_types.h"
  48. #include "init_cond.h"
  49. #include "param_types.h"
  50. #include "param.h"
  51. #include "func_types.h"
  52. #include "func.h"
  53. #include "custom_wave_types.h"
  54. #include "custom_wave.h"
  55. #include "custom_shape_types.h"
  56. #include "custom_shape.h"
  57. #include "idle_preset.h"
  58. /* The maximum number of preset names loaded into buffer */
  59. #define MAX_PRESETS_IN_DIR 50000
  60. extern int per_frame_eqn_count;
  61. extern int per_frame_init_eqn_count;
  62. //extern int custom_per_frame_eqn_count;
  63. extern splaytree_t * builtin_param_tree;
  64. preset_t * active_preset = NULL;
  65. preset_t * idle_preset = NULL;
  66. FILE * write_stream = NULL;
  67. int preset_index = -1;
  68. int preset_name_buffer_size = 0;
  69. splaytree_t * chrono_order_preset_name_tree = NULL;
  70. int get_preset_path(char ** preset_path_ptr, char * filepath, char * filename);
  71. preset_t * load_preset(char * pathname);
  72. int is_valid_extension(char * name);
  73. int load_preset_file(char * pathname, preset_t * preset);
  74. int close_preset(preset_t * preset);
  75. int write_preset_name(FILE * fs);
  76. int write_per_pixel_equations(FILE * fs);
  77. int write_per_frame_equations(FILE * fs);
  78. int write_per_frame_init_equations(FILE * fs);
  79. int write_init_conditions(FILE * fs);
  80. void load_init_cond(param_t * param);
  81. void load_init_conditions();
  82. void write_init(init_cond_t * init_cond);
  83. int init_idle_preset();
  84. int destroy_idle_preset();
  85. void load_custom_wave_init_conditions();
  86. void load_custom_wave_init(custom_wave_t * custom_wave);
  87. void load_custom_shape_init_conditions();
  88. void load_custom_shape_init(custom_shape_t * custom_shape);
  89. /* loadPresetDir: opens the directory buffer
  90.    denoted by 'dir' to load presets */
  91.    
  92. int loadPresetDir(char * dir) {
  93.   struct dirent ** name_list;
  94.   char * preset_name;
  95.   int i, j, dir_size;
  96.   
  97.   if (dir == NULL)
  98. return ERROR;
  99.  
  100.   if (chrono_order_preset_name_tree != NULL) {
  101. if (PRESET_DEBUG) printf("loadPresetDir: previous directory doesn't appear to be closed!n");
  102. /* Let this slide for now */
  103.   }
  104.   
  105.   /* Scan the entire directory, storing each entry in a dirent struct array that needs 
  106.      to be freed later. For more information, consult scandir(3) in the man pages */
  107.   if ((dir_size = scandir(dir, &name_list, 0, alphasort)) < 0) {
  108. if (PRESET_DEBUG) printf("loadPresetDir: failed to open directory "%s"n", dir);
  109. return ERROR;
  110.   }
  111.   
  112.   chrono_order_preset_name_tree = create_splaytree(compare_int, copy_int, free_int);
  113.   
  114.   /* Iterate through entire dirent name list, adding to the preset name list if it
  115.      is valid */  
  116.   for (i = 0; ((i < dir_size) && (i < MAX_PRESETS_IN_DIR));i++) {
  117. /* Only perform the next set of operations if the preset name 
  118.    contains a valid extension */
  119. if (is_valid_extension(name_list[i]->d_name)) {
  120. /* Handle the out of memory case. My guess is xmms would
  121.    crash before this program would, but whatever...*/
  122. if ((preset_name = (char*)malloc(MAX_PATH_SIZE)) == NULL) {
  123. if (PRESET_DEBUG) printf("loadPresetDir: out of memory! n");
  124. /* Free the rest of the dirent name list */
  125. for (j = i; j < dir_size; j++) 
  126. free(name_list[j]);
  127. destroy_splaytree(chrono_order_preset_name_tree);
  128. return OUTOFMEM_ERROR;
  129. }
  130. /* Now create the full path */
  131.     if (get_preset_path(&preset_name, dir, name_list[i]->d_name) < 0) {
  132. if (PRESET_DEBUG) printf("loadPresetDir: failed to generate full preset path name!n");
  133. /* Free the rest of the dirent name list */
  134. for (j = i; j < dir_size; j++) 
  135. free(name_list[j]);
  136. destroy_splaytree(chrono_order_preset_name_tree);
  137. return OUTOFMEM_ERROR;
  138. }
  139. /* Insert the character string into the splay tree, with the key being its sequence number */
  140. splay_insert(preset_name, &preset_name_buffer_size, chrono_order_preset_name_tree);
  141. preset_name_buffer_size++;
  142. }
  143. /* Free the dirent struct */
  144. free(name_list[i]);
  145.   }
  146.   
  147.   free(name_list);
  148.   
  149.   /* No valid files in directory! */
  150.   if (chrono_order_preset_name_tree->root == NULL) {
  151. if (PRESET_DEBUG) printf("loadPresetDir: no valid files in directory "%s"n", dir);
  152. destroy_splaytree(chrono_order_preset_name_tree);
  153. chrono_order_preset_name_tree = NULL;
  154. return FAILURE;   
  155.   }
  156.      
  157.   /* Start the prefix index right before the first entry, so next preset
  158.      starts at the top of the list */
  159.   preset_index = -1;
  160.   
  161.   /* Start the first preset */
  162.   switchPreset(ALPHA_NEXT, HARD_CUT);
  163.   
  164.   return SUCCESS;
  165. }
  166. /* closePresetDir: closes the current
  167.    preset directory buffer */
  168. int closePresetDir() {
  169.   /* No preset director appears to be loaded */
  170.   if (chrono_order_preset_name_tree == NULL) 
  171.     return SUCCESS;
  172.   
  173.   if (PRESET_DEBUG) {
  174.  printf("closePresetDir: freeing directory buffer...");
  175.  fflush(stdout);
  176.   }  
  177.   
  178.   /* Free each entry in the directory preset name tree */
  179.   splay_traverse(free_int, chrono_order_preset_name_tree);
  180.   
  181.   /* Destroy the chronological order splay tree */
  182.   destroy_splaytree(chrono_order_preset_name_tree);
  183.   chrono_order_preset_name_tree = NULL;
  184.   preset_name_buffer_size = 0;
  185.   if (PRESET_DEBUG) printf("finishedn");
  186.   
  187.   return SUCCESS;
  188. }
  189. /* Converts a preset file name to a full path */ 
  190. int get_preset_path(char ** preset_path_ptr, char * filepath, char * filename) {
  191.   char * preset_path;
  192.   /* An insanely paranoid sequence of argument checks */
  193.   if (preset_path_ptr == NULL)
  194. return ERROR;
  195.   if (*preset_path_ptr == NULL)
  196.     return ERROR;
  197.   if (filename == NULL)
  198. return ERROR;
  199.   if (filepath == NULL)
  200. return ERROR;
  201.   
  202.   /* Mostly here for looks */
  203.   preset_path = *preset_path_ptr;
  204.   /* Clear the name space first */
  205.   memset(preset_path, 0, MAX_PATH_SIZE);
  206.   
  207.   /* Now create the string "PATH/FILENAME", where path is either absolute or relative location
  208.      of the .milk file, and filename is the name of the preset file itself */
  209.   strcat(
  210.    strcat(
  211.    strncpy(
  212.    preset_path, 
  213.        filepath, 
  214.             MAX_PATH_SIZE-1),   
  215.         "/"), 
  216.     filename);
  217.   return SUCCESS;
  218. }
  219. /* switchPreset: loads the next preset from the directory stream.
  220.    loadPresetDir() must be called first. This is a
  221.    sequential load function */
  222. int switchPreset(switch_mode_t switch_mode, int cut_type) {
  223.   preset_t * new_preset;
  224.   int switch_index;
  225.   /* Make sure a preset directory list is in the buffer */
  226.   if (chrono_order_preset_name_tree == NULL) {
  227.     if (PRESET_DEBUG) printf("switchPreset: it helps if you open a directory first with a loadPresetDir() calln");
  228.     return ERROR;
  229.   }
  230.   
  231.   
  232.   switch (switch_mode) {
  233.   
  234.   case ALPHA_NEXT:
  235.   /* An index variable that iterates through the directory
  236.      buffer, doing wrap around when it reaches the end of
  237.     the buffer */
  238.   
  239.   if (preset_index == (preset_name_buffer_size - 1))
  240. switch_index = preset_index = 0;
  241.   else
  242.    switch_index = ++preset_index;
  243.   break;
  244.   case ALPHA_PREVIOUS:
  245.   
  246.   if (preset_index == 0)
  247. switch_index = preset_index = preset_name_buffer_size - 1;
  248.   else
  249.    switch_index = --preset_index;
  250.   break;
  251.   
  252.   case RANDOM_NEXT:
  253. switch_index = (int) (preset_name_buffer_size*(rand()/(RAND_MAX+1.0)));
  254. break;
  255.   case RESTART_ACTIVE:
  256. switch_index = preset_index;
  257. break;
  258.   default:
  259.    return FAILURE;
  260.   }
  261.   
  262.     
  263.   /* Finally, load the preset using its actual path */
  264.   if ((new_preset = load_preset((char*)splay_find(&switch_index, chrono_order_preset_name_tree))) == NULL) {
  265. if (PRESET_DEBUG) printf("switchPreset: failed to load presetn");
  266. return ERROR;
  267.   }
  268.   /* Closes a preset currently loaded, if any */
  269.   if ((active_preset != NULL) && (active_preset != idle_preset))
  270.     close_preset(active_preset);
  271.   /* Sets global active_preset pointer */
  272.   active_preset = new_preset;
  273.  
  274.   /* Reinitialize the engine variables to sane defaults */
  275.   reset_engine_vars();
  276.   /* Add any missing initial conditions */
  277.   load_init_conditions();
  278.   /* Add any missing initial conditions for each wave */
  279.   load_custom_wave_init_conditions();
  280. /* Add any missing initial conditions for each shape */
  281.   load_custom_shape_init_conditions();
  282.   /* Need to evaluate the initial conditions once */
  283.   evalInitConditions();
  284.  
  285.   //  evalInitPerFrameEquations();
  286.   return SUCCESS;
  287. }
  288. /* Loads a specific preset by absolute path */
  289. int loadPresetByFile(char * filename) {
  290.   preset_t * new_preset;
  291.  
  292.   /* Finally, load the preset using its actual path */
  293.   if ((new_preset = load_preset(filename)) == NULL) {
  294. if (PRESET_DEBUG) printf("loadPresetByFile: failed to load preset!n");
  295. return ERROR;   
  296.   }
  297.   /* Closes a preset currently loaded, if any */
  298.   if ((active_preset != NULL) && (active_preset != idle_preset))
  299.     close_preset(active_preset); 
  300.   /* Sets active preset global pointer */
  301.   active_preset = new_preset;
  302.   /* Reinitialize engine variables */
  303.   reset_engine_vars();
  304.  
  305.   /* Add any missing initial conditions for each wave */
  306.   load_custom_wave_init_conditions();
  307.  /* Add any missing initial conditions for each wave */
  308.   load_custom_shape_init_conditions();
  309.   /* Add any missing initial conditions */
  310.   load_init_conditions();
  311.   
  312.   /* Need to do this once for menu */
  313.   evalInitConditions();
  314.   //  evalPerFrameInitEquations();
  315.   return SUCCESS;
  316. }
  317. int init_idle_preset() {
  318.   preset_t * preset;
  319.     /* Initialize idle preset struct */
  320.   if ((preset = (preset_t*)malloc(sizeof(preset_t))) == NULL)
  321.     return FAILURE;
  322.   
  323.   strncpy(preset->name, "idlepreset", strlen("idlepreset"));
  324.   /* Initialize equation trees */
  325.   preset->init_cond_tree = create_splaytree(compare_string, copy_string, free_string);
  326.   preset->user_param_tree = create_splaytree(compare_string, copy_string, free_string);
  327.   preset->per_frame_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
  328.   preset->per_pixel_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
  329.   preset->per_frame_init_eqn_tree = create_splaytree(compare_string, copy_string, free_string);
  330.   preset->custom_wave_tree = create_splaytree(compare_int, copy_int, free_int);
  331.   preset->custom_shape_tree = create_splaytree(compare_int, copy_int, free_int);
  332.  
  333.   /* Set file path to dummy name */  
  334.   strncpy(preset->file_path, "IDLE PRESET", MAX_PATH_SIZE-1);
  335.   
  336.   /* Set initial index values */
  337.   preset->per_pixel_eqn_string_index = 0;
  338.   preset->per_frame_eqn_string_index = 0;
  339.   preset->per_frame_init_eqn_string_index = 0;
  340.   memset(preset->per_pixel_flag, 0, sizeof(int)*NUM_OPS);
  341.   
  342.   /* Clear string buffers */
  343.   memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
  344.   memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
  345.   memset(preset->per_frame_init_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
  346.   idle_preset = preset;
  347.   
  348.   return SUCCESS;
  349. }
  350. int destroy_idle_preset() {
  351.   return close_preset(idle_preset);
  352.   
  353. }
  354. /* initPresetLoader: initializes the preset
  355.    loading library. this should be done before
  356.    any parsing */
  357. int initPresetLoader() {
  358.   /* Initializes the builtin parameter database */
  359.   init_builtin_param_db();
  360.   /* Initializes the builtin function database */
  361.   init_builtin_func_db();
  362.   /* Initializes all infix operators */
  363.   init_infix_ops();
  364.   /* Set the seed to the current time in seconds */
  365.   srand(time(NULL));
  366.   /* Initialize the 'idle' preset */
  367.   init_idle_preset();
  368.  
  369.   reset_engine_vars();
  370.   active_preset = idle_preset;
  371.   load_init_conditions();
  372.   /* Done */
  373.   if (PRESET_DEBUG) printf("initPresetLoader: finishedn");
  374.   return SUCCESS;
  375. }
  376. /* Sort of experimental code here. This switches
  377.    to a hard coded preset. Useful if preset directory
  378.    was not properly loaded, or a preset fails to parse */
  379. void switchToIdlePreset() {
  380.   /* Idle Preset already activated */
  381.   if (active_preset == idle_preset)
  382.     return;
  383.   /* Close active preset */
  384.   if (active_preset != NULL)
  385.     close_preset(active_preset);
  386.   /* Sets global active_preset pointer */
  387.   active_preset = idle_preset;
  388.   /* Reinitialize the engine variables to sane defaults */
  389.   reset_engine_vars();
  390.   /* Add any missing initial conditions */
  391.   load_init_conditions();
  392.   /* Need to evaluate the initial conditions once */
  393.   evalInitConditions();
  394. }
  395. /* destroyPresetLoader: closes the preset
  396.    loading library. This should be done when 
  397.    projectM does cleanup */
  398. int destroyPresetLoader() {
  399.   
  400.   if ((active_preset != NULL) && (active_preset != idle_preset)) {
  401.    close_preset(active_preset);      
  402.   }
  403.   active_preset = NULL;
  404.   
  405.   destroy_idle_preset();
  406.   destroy_builtin_param_db();
  407.   destroy_builtin_func_db();
  408.   destroy_infix_ops();
  409.   return SUCCESS;
  410. }
  411. /* load_preset_file: private function that loads a specific preset denoted
  412.    by the given pathname */
  413. int load_preset_file(char * pathname, preset_t * preset) { 
  414.   FILE * fs;
  415.   int retval;
  416.   if (pathname == NULL)
  417.   return FAILURE;
  418.   if (preset == NULL)
  419.   return FAILURE;
  420.   
  421.   /* Open the file corresponding to pathname */
  422.   if ((fs = utf8_fopen(pathname, "r")) == NULL) {
  423.     if (PRESET_DEBUG) printf("load_preset_file: loading of file %s failed!n", pathname);
  424.     return ERROR;
  425.   }
  426.   if (PRESET_DEBUG) printf("load_preset_file: file stream "%s" opened successfullyn", pathname);
  427.   /* Parse any comments */
  428.   if (parse_top_comment(fs) < 0) {
  429.     if (PRESET_DEBUG) printf("load_preset_file: no left bracket found...n");
  430.     fclose(fs);
  431.     return FAILURE;
  432.   }
  433.   
  434.   /* Parse the preset name and a left bracket */
  435.   if (parse_preset_name(fs, preset->name) < 0) {
  436.     if (PRESET_DEBUG) printf("load_preset_file: loading of preset name in file "%s" failedn", pathname);
  437.     fclose(fs);
  438.     return ERROR;
  439.   }
  440.   
  441.   if (PRESET_DEBUG) printf("load_preset_file: preset "%s" parsedn", preset->name);
  442.   /* Parse each line until end of file */
  443.   if (PRESET_DEBUG) printf("load_preset_file: beginning line parsing...n");
  444.   while ((retval = parse_line(fs, preset)) != EOF) {
  445.     if (retval == PARSE_ERROR) {
  446.       if (PRESET_DEBUG > 1) printf("load_preset_file: parse error in file "%s"n", pathname);
  447.     }
  448.   }
  449.   
  450.   if (PRESET_DEBUG) printf("load_preset_file: finished line parsing successfullyn"); 
  451.   /* Now the preset has been loaded.
  452.      Evaluation calls can be made at appropiate
  453.      times in the frame loop */
  454.   
  455.   fclose(fs);
  456.    
  457.   if (PRESET_DEBUG) printf("load_preset_file: file "%s" closed, preset readyn", pathname);
  458.   return SUCCESS;
  459.   
  460. }
  461. void evalInitConditions() {
  462.   splay_traverse(eval_init_cond, active_preset->init_cond_tree);
  463.   splay_traverse(eval_init_cond, active_preset->per_frame_init_eqn_tree);
  464. }
  465. void evalPerFrameEquations() {
  466.   splay_traverse(eval_per_frame_eqn, active_preset->per_frame_eqn_tree);
  467. }
  468. void evalPerFrameInitEquations() {
  469.   //printf("evalPerFrameInitEquations: per frame init unimplemented!n");
  470.   //  splay_traverse(eval_per_frame_eqn, active_preset->per_frame_init_eqn_tree);
  471. }
  472. /* Returns nonzero if string 'name' contains .milk or
  473.    (the better) .prjm extension. Not a very strong function currently */
  474. int is_valid_extension(char * name) {
  475. if (PRESET_DEBUG > 1) {
  476. printf("is_valid_extension: scanning string "%s"...", name);
  477. fflush(stdout);
  478. }
  479. if (strstr(name, MILKDROP_FILE_EXTENSION)) {
  480. if (PRESET_DEBUG > 1) printf("".milk" extension found in string [true]n");
  481. return TRUE;
  482. }
  483. if (strstr(name, PROJECTM_FILE_EXTENSION)) {
  484.     if (PRESET_DEBUG > 1) printf("".prjm" extension found in string [true]n");
  485. return TRUE;
  486. }
  487.  
  488. if (PRESET_DEBUG > 1) printf("no valid extension found [false]n");
  489. return FALSE;
  490. }
  491. /* Private function to close a preset file */
  492. int close_preset(preset_t * preset) {
  493.   if (preset == NULL)
  494.     return FAILURE;
  495.   splay_traverse(free_init_cond, preset->init_cond_tree);
  496.   destroy_splaytree(preset->init_cond_tree);
  497.   
  498.   splay_traverse(free_init_cond, preset->per_frame_init_eqn_tree);
  499.   destroy_splaytree(preset->per_frame_init_eqn_tree);
  500.   
  501.   splay_traverse(free_per_pixel_eqn, preset->per_pixel_eqn_tree);
  502.   destroy_splaytree(preset->per_pixel_eqn_tree);
  503.   
  504.   splay_traverse(free_per_frame_eqn, preset->per_frame_eqn_tree);
  505.   destroy_splaytree(preset->per_frame_eqn_tree);
  506.   
  507.   splay_traverse(free_param, preset->user_param_tree);
  508.   destroy_splaytree(preset->user_param_tree);
  509.   
  510.   splay_traverse(free_custom_wave, preset->custom_wave_tree);
  511.   destroy_splaytree(preset->custom_wave_tree);
  512.   splay_traverse(free_custom_shape, preset->custom_shape_tree);
  513.   destroy_splaytree(preset->custom_shape_tree);
  514.   free(preset); 
  515.   
  516.   return SUCCESS;
  517. }
  518. void reloadPerPixel(char *s, preset_t * preset) {
  519.   
  520.   FILE * fs;
  521.   int slen;
  522.   char c;
  523.   int i;
  524.   if (s == NULL)
  525.     return;
  526.   if (preset == NULL)
  527.     return;
  528.   /* Clear previous per pixel equations */
  529.   splay_traverse(free_per_pixel_eqn, preset->per_pixel_eqn_tree);
  530.   destroy_splaytree(preset->per_pixel_eqn_tree);
  531.   preset->per_pixel_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
  532.   /* Convert string to a stream */
  533.   fs = fmemopen (s, strlen(s), "r");
  534.   while ((c = fgetc(fs)) != EOF) {
  535.     ungetc(c, fs);
  536.     parse_per_pixel_eqn(fs, preset);
  537.   }
  538.   fclose(fs);
  539.   /* Clear string space */
  540.   memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
  541.   /* Compute length of string */
  542.   slen = strlen(s);
  543.   /* Copy new string into buffer */
  544.   strncpy(preset->per_pixel_eqn_string_buffer, s, slen);
  545.   /* Yet again no bounds checking */
  546.   preset->per_pixel_eqn_string_index = slen;
  547.   /* Finished */
  548.  
  549.   return;
  550. }
  551. /* Obviously unwritten */
  552. void reloadPerFrameInit(char *s, preset_t * preset) {
  553. }
  554. void reloadPerFrame(char * s, preset_t * preset) {
  555.   FILE * fs;
  556.   int slen;
  557.   char c;
  558.   int eqn_count = 1;
  559.   per_frame_eqn_t * per_frame;
  560.   if (s == NULL)
  561.     return;
  562.   if (preset == NULL)
  563.     return;
  564.   /* Clear previous per frame equations */
  565.   splay_traverse(free_per_frame_eqn, preset->per_frame_eqn_tree);
  566.   destroy_splaytree(preset->per_frame_eqn_tree);
  567.   preset->per_frame_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
  568.   /* Convert string to a stream */
  569.   fs = fmemopen (s, strlen(s), "r");
  570.   while ((c = fgetc(fs)) != EOF) {
  571.     ungetc(c, fs);
  572.     if ((per_frame = parse_per_frame_eqn(fs, eqn_count, preset)) != NULL) {
  573.       splay_insert(per_frame, &eqn_count, preset->per_frame_eqn_tree);
  574.       eqn_count++;
  575.     }
  576.   }
  577.   fclose(fs);
  578.   /* Clear string space */
  579.   memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
  580.   /* Compute length of string */
  581.   slen = strlen(s);
  582.   /* Copy new string into buffer */
  583.   strncpy(preset->per_frame_eqn_string_buffer, s, slen);
  584.   /* Yet again no bounds checking */
  585.   preset->per_frame_eqn_string_index = slen;
  586.   /* Finished */
  587.   printf("reloadPerFrame: %d eqns parsed succesfullyn", eqn_count-1);
  588.   return;
  589. }
  590. preset_t * load_preset(char * pathname) {
  591.   preset_t * preset;
  592.   /* Initialize preset struct */
  593.   if ((preset = (preset_t*)malloc(sizeof(preset_t))) == NULL)
  594.     return NULL;
  595.    
  596.   /* Initialize equation trees */
  597.   preset->init_cond_tree = create_splaytree(compare_string, copy_string, free_string);
  598.   preset->user_param_tree = create_splaytree(compare_string, copy_string, free_string);
  599.   preset->per_frame_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
  600.   preset->per_pixel_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
  601.   preset->per_frame_init_eqn_tree = create_splaytree(compare_string, copy_string, free_string);
  602.   preset->custom_wave_tree = create_splaytree(compare_int, copy_int, free_int);
  603.   preset->custom_shape_tree = create_splaytree(compare_int, copy_int, free_int);
  604.   memset(preset->per_pixel_flag, 0, sizeof(int)*NUM_OPS);
  605.   /* Copy file path */  
  606.   strncpy(preset->file_path, pathname, MAX_PATH_SIZE-1);
  607.   
  608.   /* Set initial index values */
  609.   preset->per_pixel_eqn_string_index = 0;
  610.   preset->per_frame_eqn_string_index = 0;
  611.   preset->per_frame_init_eqn_string_index = 0;
  612.   
  613.   
  614.   /* Clear string buffers */
  615.   memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
  616.   memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
  617.   memset(preset->per_frame_init_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
  618.   
  619.   
  620.   if (load_preset_file(pathname, preset) < 0) {
  621. if (PRESET_DEBUG) printf("load_preset: failed to load file "%s"n", pathname);
  622. close_preset(preset);
  623. return NULL;
  624.   }
  625.   /* It's kind of ugly to reset these values here. Should definitely be placed in the parser somewhere */
  626.   per_frame_eqn_count = 0;
  627.   per_frame_init_eqn_count = 0;
  628.   /* Finished, return new preset */
  629.   return preset;
  630. }
  631. void savePreset(char * filename) {
  632.   FILE * fs;
  633.   if (filename == NULL)
  634.     return;
  635.   
  636.   /* Open the file corresponding to pathname */
  637.   if ((fs = utf8_fopen(filename, "w+")) == NULL) {
  638.     if (PRESET_DEBUG) printf("savePreset: failed to create filename "%s"!n", filename);
  639.     return;
  640.   }
  641.   write_stream = fs;
  642.   if (write_preset_name(fs) < 0) {
  643.     write_stream = NULL;
  644.     fclose(fs);
  645.     return;
  646.   }
  647.   if (write_init_conditions(fs) < 0) {
  648.     write_stream = NULL;
  649.     fclose(fs);
  650.     return;
  651.   }
  652.   if (write_per_frame_init_equations(fs) < 0) {
  653.     write_stream = NULL;
  654.     fclose(fs);
  655.     return;
  656.   }
  657.   if (write_per_frame_equations(fs) < 0) {
  658.     write_stream = NULL;
  659.     fclose(fs);
  660.     return;
  661.   }
  662.   if (write_per_pixel_equations(fs) < 0) {
  663.     write_stream = NULL;
  664.     fclose(fs);
  665.     return;
  666.   }
  667.  
  668.   write_stream = NULL;
  669.   fclose(fs);
  670. }
  671. int write_preset_name(FILE * fs) {
  672.   char s[256];
  673.   int len;
  674.   memset(s, 0, 256);
  675.   if (fs == NULL)
  676.     return FAILURE;
  677.   /* Format the preset name in a string */
  678.   sprintf(s, "[%s]n", active_preset->name);
  679.   len = strlen(s);
  680.   /* Write preset name to file stream */
  681.   if (fwrite(s, 1, len, fs) != len)
  682.     return FAILURE;
  683.   return SUCCESS;
  684. }
  685. int write_init_conditions(FILE * fs) {
  686.   if (fs == NULL)
  687.     return FAILURE;
  688.   if (active_preset == NULL)
  689.     return FAILURE;
  690.   splay_traverse(write_init, active_preset->init_cond_tree);
  691.   
  692.   return SUCCESS;
  693. }
  694. void write_init(init_cond_t * init_cond) {
  695.   char s[512];
  696.   int len;
  697.   if (write_stream == NULL)
  698.     return;
  699.   memset(s, 0, 512);
  700.   if (init_cond->param->type == P_TYPE_BOOL)
  701.     sprintf(s, "%s=%dn", init_cond->param->name, init_cond->init_val.bool_val);
  702.   else if (init_cond->param->type == P_TYPE_INT)    
  703.     sprintf(s, "%s=%dn", init_cond->param->name, init_cond->init_val.int_val);
  704.   else if (init_cond->param->type == P_TYPE_DOUBLE)
  705.   {
  706.     lldiv_t div = lldiv( init_cond->init_val.double_val * 1000000,1000000 );
  707.     sprintf(s, "%s=%"PRId64".%06un", init_cond->param->name, div.quot,
  708.                     (unsigned int) div.rem );
  709.   }
  710.   else { printf("write_init: unknown parameter type!n"); return; }
  711.   len = strlen(s);
  712.   if ((fwrite(s, 1, len, write_stream)) != len)
  713.     printf("write_init: failed writing to file stream! Out of disk space?n");
  714. }
  715. int write_per_frame_init_equations(FILE * fs) {
  716.   int len;
  717.   if (fs == NULL)
  718.     return FAILURE;
  719.   if (active_preset == NULL)
  720.     return FAILURE;
  721.   
  722.   len = strlen(active_preset->per_frame_init_eqn_string_buffer);
  723.   if (fwrite(active_preset->per_frame_init_eqn_string_buffer, 1, len, fs) != len)
  724.     return FAILURE;
  725.   return SUCCESS;
  726. }
  727. int write_per_frame_equations(FILE * fs) {
  728.   int len;
  729.   if (fs == NULL)
  730.     return FAILURE;
  731.   if (active_preset == NULL)
  732.     return FAILURE;
  733.   len = strlen(active_preset->per_frame_eqn_string_buffer);
  734.   if (fwrite(active_preset->per_frame_eqn_string_buffer, 1, len, fs) != len)
  735.     return FAILURE;
  736.   return SUCCESS;
  737. }
  738. int write_per_pixel_equations(FILE * fs) {
  739.   int len;
  740.   if (fs == NULL)
  741.     return FAILURE;
  742.   if (active_preset == NULL)
  743.     return FAILURE;
  744.   len = strlen(active_preset->per_pixel_eqn_string_buffer);
  745.   if (fwrite(active_preset->per_pixel_eqn_string_buffer, 1, len, fs) != len)
  746.     return FAILURE;
  747.   return SUCCESS;
  748. }
  749. void load_init_conditions() {
  750.   splay_traverse(load_init_cond, builtin_param_tree);
  751.  
  752. }
  753. void load_init_cond(param_t * param) {
  754.   init_cond_t * init_cond;
  755.   value_t init_val;
  756.   /* Don't count read only parameters as initial conditions */
  757.   if (param->flags & P_FLAG_READONLY)
  758.     return;
  759.   /* If initial condition was not defined by the preset file, force a default one
  760.      with the following code */
  761.   if ((init_cond = splay_find(param->name, active_preset->init_cond_tree)) == NULL) {
  762.     
  763.     /* Make sure initial condition does not exist in the set of per frame initial equations */
  764.     if ((init_cond = splay_find(param->name, active_preset->per_frame_init_eqn_tree)) != NULL)
  765.       return;
  766.     
  767.     if (param->type == P_TYPE_BOOL)
  768.       init_val.bool_val = 0;
  769.     
  770.     else if (param->type == P_TYPE_INT)
  771.       init_val.int_val = *(int*)param->engine_val;
  772.     else if (param->type == P_TYPE_DOUBLE)
  773.       init_val.double_val = *(double*)param->engine_val;
  774.     //printf("%sn", param->name);
  775.     /* Create new initial condition */
  776.     if ((init_cond = new_init_cond(param, init_val)) == NULL)
  777.       return;
  778.     
  779.     /* Insert the initial condition into this presets tree */
  780.     if (splay_insert(init_cond, init_cond->param->name, active_preset->init_cond_tree) < 0) {
  781.       free_init_cond(init_cond);
  782.       return;
  783.     }
  784.     
  785.   }
  786.  
  787. }
  788. void load_custom_wave_init_conditions() {
  789.   splay_traverse(load_custom_wave_init, active_preset->custom_wave_tree);
  790. }
  791. void load_custom_wave_init(custom_wave_t * custom_wave) {
  792.   load_unspecified_init_conds(custom_wave);
  793. }
  794. void load_custom_shape_init_conditions() {
  795.   splay_traverse(load_custom_shape_init, active_preset->custom_shape_tree);
  796. }
  797. void load_custom_shape_init(custom_shape_t * custom_shape) {
  798.  
  799.   load_unspecified_init_conds_shape(custom_shape);
  800.  
  801. }