preset.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:26k
源码类别:

多媒体

开发平台:

MultiPlatform

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