Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

preset.c

00001 /*****************************************************************************
00002  * preset.c:
00003  *****************************************************************************
00004  * Copyright (C) 2004 the VideoLAN team
00005  * $Id: preset.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Cyril Deguet <[email protected]>
00008  *          code from projectM http://xmms-projectm.sourceforge.net
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 
00026 
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <stdlib.h>
00030 #include <dirent.h>
00031 #include <time.h>
00032 #include "common.h"
00033 #include "fatal.h"
00034 
00035 #include "preset_types.h"
00036 #include "preset.h"
00037 
00038 #include "parser.h"
00039 
00040 #include "expr_types.h"
00041 #include "eval.h"
00042 
00043 #include "splaytree_types.h"
00044 #include "splaytree.h"
00045 #include "tree_types.h"
00046 
00047 #include "per_frame_eqn_types.h"
00048 #include "per_frame_eqn.h"
00049 
00050 #include "per_pixel_eqn_types.h"
00051 #include "per_pixel_eqn.h"
00052 
00053 #include "init_cond_types.h"
00054 #include "init_cond.h"
00055 
00056 #include "param_types.h"
00057 #include "param.h"
00058 
00059 #include "func_types.h"
00060 #include "func.h"
00061 
00062 #include "custom_wave_types.h"
00063 #include "custom_wave.h"
00064 
00065 #include "custom_shape_types.h"
00066 #include "custom_shape.h"
00067 
00068 #include "idle_preset.h"
00069 
00070 /* The maximum number of preset names loaded into buffer */
00071 #define MAX_PRESETS_IN_DIR 50000
00072 extern int per_frame_eqn_count;
00073 extern int per_frame_init_eqn_count;
00074 //extern int custom_per_frame_eqn_count;
00075 
00076 extern splaytree_t * builtin_param_tree;
00077 
00078 preset_t * active_preset = NULL;
00079 preset_t * idle_preset = NULL;
00080 FILE * write_stream = NULL;
00081 
00082 
00083 int preset_index = -1;
00084 int preset_name_buffer_size = 0;
00085 splaytree_t * chrono_order_preset_name_tree = NULL;
00086 int get_preset_path(char ** preset_path_ptr, char * filepath, char * filename);
00087 preset_t * load_preset(char * pathname);
00088 int is_valid_extension(char * name);    
00089 int load_preset_file(char * pathname, preset_t * preset);
00090 int close_preset(preset_t * preset);
00091 
00092 int write_preset_name(FILE * fs);
00093 int write_per_pixel_equations(FILE * fs);
00094 int write_per_frame_equations(FILE * fs);
00095 int write_per_frame_init_equations(FILE * fs);
00096 int write_init_conditions(FILE * fs);
00097 void load_init_cond(param_t * param);
00098 void load_init_conditions();
00099 void write_init(init_cond_t * init_cond);
00100 int init_idle_preset();
00101 int destroy_idle_preset();
00102 void load_custom_wave_init_conditions();
00103 void load_custom_wave_init(custom_wave_t * custom_wave);
00104 
00105 void load_custom_shape_init_conditions();
00106 void load_custom_shape_init(custom_shape_t * custom_shape);
00107 
00108 /* loadPresetDir: opens the directory buffer
00109    denoted by 'dir' to load presets */
00110    
00111 int loadPresetDir(char * dir) {
00112 
00113   struct dirent ** name_list;
00114   char * preset_name;
00115   int i, j, dir_size;
00116   
00117   if (dir == NULL)
00118         return ERROR;
00119  
00120   if (chrono_order_preset_name_tree != NULL) {
00121         if (PRESET_DEBUG) printf("loadPresetDir: previous directory doesn't appear to be closed!\n");
00122         /* Let this slide for now */
00123   }     
00124   
00125   /* Scan the entire directory, storing each entry in a dirent struct array that needs 
00126      to be freed later. For more information, consult scandir(3) in the man pages */
00127   if ((dir_size = scandir(dir, &name_list, 0, alphasort)) < 0) {
00128         if (PRESET_DEBUG) printf("loadPresetDir: failed to open directory \"%s\"\n", dir);
00129         return ERROR;
00130   }
00131   
00132   chrono_order_preset_name_tree = create_splaytree(compare_int, copy_int, free_int);
00133   
00134   /* Iterate through entire dirent name list, adding to the preset name list if it
00135      is valid */  
00136   for (i = 0; ((i < dir_size) && (i < MAX_PRESETS_IN_DIR));i++) {
00137 
00138         /* Only perform the next set of operations if the preset name 
00139            contains a valid extension */
00140         if (is_valid_extension(name_list[i]->d_name)) {
00141                 
00142                 /* Handle the out of memory case. My guess is xmms would
00143                    crash before this program would, but whatever...*/
00144                 if ((preset_name = (char*)malloc(MAX_PATH_SIZE)) == NULL) {
00145                         if (PRESET_DEBUG) printf("loadPresetDir: out of memory! \n");
00146                         
00147                         /* Free the rest of the dirent name list */
00148                         for (j = i; j < dir_size; j++) 
00149                                 free(name_list[j]);
00150                         destroy_splaytree(chrono_order_preset_name_tree);
00151                         return OUTOFMEM_ERROR;
00152                 }
00153                                 
00154                 /* Now create the full path */
00155             if (get_preset_path(&preset_name, dir, name_list[i]->d_name) < 0) {
00156                         if (PRESET_DEBUG) printf("loadPresetDir: failed to generate full preset path name!\n");
00157                         
00158                         /* Free the rest of the dirent name list */
00159                         for (j = i; j < dir_size; j++) 
00160                                 free(name_list[j]);
00161                         destroy_splaytree(chrono_order_preset_name_tree);
00162                         return OUTOFMEM_ERROR;
00163                         
00164                 }
00165                 
00166                 /* Insert the character string into the splay tree, with the key being its sequence number */
00167                 splay_insert(preset_name, &preset_name_buffer_size, chrono_order_preset_name_tree);
00168                 preset_name_buffer_size++;
00169         }
00170         
00171         /* Free the dirent struct */
00172         free(name_list[i]);
00173         
00174   }     
00175   
00176   free(name_list);
00177   
00178   /* No valid files in directory! */
00179   if (chrono_order_preset_name_tree->root == NULL) {
00180         if (PRESET_DEBUG) printf("loadPresetDir: no valid files in directory \"%s\"\n", dir);
00181         destroy_splaytree(chrono_order_preset_name_tree);
00182         chrono_order_preset_name_tree = NULL;
00183         return FAILURE;   
00184   }     
00185           
00186   /* Start the prefix index right before the first entry, so next preset
00187      starts at the top of the list */
00188   preset_index = -1;
00189   
00190   /* Start the first preset */
00191 
00192   switchPreset(ALPHA_NEXT, HARD_CUT);
00193   
00194   return SUCCESS;
00195 }
00196 
00197 /* closePresetDir: closes the current
00198    preset directory buffer */
00199 
00200 int closePresetDir() {
00201 
00202   /* No preset director appears to be loaded */ 
00203   if (chrono_order_preset_name_tree == NULL) 
00204     return SUCCESS;
00205   
00206   if (PRESET_DEBUG) {
00207          printf("closePresetDir: freeing directory buffer...");
00208          fflush(stdout);
00209   }  
00210   
00211   /* Free each entry in the directory preset name tree */
00212   splay_traverse(free_int, chrono_order_preset_name_tree);
00213   
00214   /* Destroy the chronological order splay tree */
00215   destroy_splaytree(chrono_order_preset_name_tree);
00216   chrono_order_preset_name_tree = NULL;
00217   preset_name_buffer_size = 0;
00218   if (PRESET_DEBUG) printf("finished\n");
00219   
00220   return SUCCESS;
00221 }
00222 
00223 
00224 
00225 /* Converts a preset file name to a full path */ 
00226 int get_preset_path(char ** preset_path_ptr, char * filepath, char * filename) {
00227 
00228   char * preset_path;
00229         
00230   /* An insanely paranoid sequence of argument checks */
00231   if (preset_path_ptr == NULL)
00232         return ERROR;
00233   if (*preset_path_ptr == NULL)
00234     return ERROR;
00235   if (filename == NULL)
00236         return ERROR;
00237   if (filepath == NULL)
00238         return ERROR;
00239   
00240   /* Mostly here for looks */
00241   preset_path = *preset_path_ptr;
00242 
00243   /* Clear the name space first */
00244   memset(preset_path, 0, MAX_PATH_SIZE);
00245   
00246   /* Now create the string "PATH/FILENAME", where path is either absolute or relative location
00247      of the .milk file, and filename is the name of the preset file itself */
00248   strcat(
00249         strcat(
00250                 strncpy(
00251                         preset_path, 
00252                     filepath, 
00253             MAX_PATH_SIZE-1),   
00254         "/"), 
00255     filename);  
00256 
00257   return SUCCESS;
00258 }       
00259 
00260 /* switchPreset: loads the next preset from the directory stream.
00261    loadPresetDir() must be called first. This is a
00262    sequential load function */
00263 
00264 int switchPreset(switch_mode_t switch_mode, int cut_type) {
00265 
00266   preset_t * new_preset;
00267         
00268   int switch_index;
00269         
00270   /* Make sure a preset directory list is in the buffer */
00271   if (chrono_order_preset_name_tree == NULL) {
00272     if (PRESET_DEBUG) printf("switchPreset: it helps if you open a directory first with a loadPresetDir() call\n");
00273     return ERROR;
00274   }
00275   
00276   
00277   switch (switch_mode) {
00278           
00279   case ALPHA_NEXT:
00280   /* An index variable that iterates through the directory
00281      buffer, doing wrap around when it reaches the end of
00282          the buffer */
00283   
00284   if (preset_index == (preset_name_buffer_size - 1))
00285                 switch_index = preset_index = 0;
00286   else  
00287                 switch_index = ++preset_index;
00288   break;
00289 
00290   case ALPHA_PREVIOUS:
00291           
00292   if (preset_index == 0)
00293                 switch_index = preset_index = preset_name_buffer_size - 1;
00294   else  
00295                 switch_index = --preset_index;
00296   break;
00297   
00298   case RANDOM_NEXT:
00299         switch_index = (int) (preset_name_buffer_size*(rand()/(RAND_MAX+1.0)));
00300         break;
00301   case RESTART_ACTIVE:
00302         switch_index = preset_index;
00303         break;
00304   default:
00305         return FAILURE;
00306   }
00307   
00308     
00309   /* Finally, load the preset using its actual path */
00310   if ((new_preset = load_preset((char*)splay_find(&switch_index, chrono_order_preset_name_tree))) == NULL) {
00311         if (PRESET_DEBUG) printf("switchPreset: failed to load preset\n");
00312         return ERROR;
00313   }
00314 
00315   /* Closes a preset currently loaded, if any */
00316   if ((active_preset != NULL) && (active_preset != idle_preset))
00317     close_preset(active_preset);
00318 
00319   /* Sets global active_preset pointer */
00320   active_preset = new_preset;
00321 
00322  
00323   /* Reinitialize the engine variables to sane defaults */
00324   reset_engine_vars();
00325 
00326   /* Add any missing initial conditions */
00327   load_init_conditions();
00328 
00329   /* Add any missing initial conditions for each wave */
00330   load_custom_wave_init_conditions();
00331 
00332 /* Add any missing initial conditions for each shape */
00333   load_custom_shape_init_conditions();
00334 
00335   /* Need to evaluate the initial conditions once */
00336   evalInitConditions();
00337 
00338  
00339   //  evalInitPerFrameEquations();
00340   return SUCCESS;
00341 }
00342 
00343 /* Loads a specific preset by absolute path */
00344 int loadPresetByFile(char * filename) {
00345 
00346   preset_t * new_preset;
00347  
00348   /* Finally, load the preset using its actual path */
00349   if ((new_preset = load_preset(filename)) == NULL) {
00350         if (PRESET_DEBUG) printf("loadPresetByFile: failed to load preset!\n");
00351         return ERROR;     
00352   }
00353 
00354   /* Closes a preset currently loaded, if any */
00355   if ((active_preset != NULL) && (active_preset != idle_preset))
00356     close_preset(active_preset); 
00357 
00358   /* Sets active preset global pointer */
00359   active_preset = new_preset;
00360 
00361   /* Reinitialize engine variables */
00362   reset_engine_vars();
00363 
00364  
00365   /* Add any missing initial conditions for each wave */
00366   load_custom_wave_init_conditions();
00367 
00368  /* Add any missing initial conditions for each wave */
00369   load_custom_shape_init_conditions();
00370 
00371   /* Add any missing initial conditions */
00372   load_init_conditions();
00373   
00374   /* Need to do this once for menu */
00375   evalInitConditions();
00376   //  evalPerFrameInitEquations();
00377   return SUCCESS;
00378 
00379 }
00380 
00381 int init_idle_preset() {
00382 
00383   preset_t * preset;
00384   int i;
00385 
00386     /* Initialize idle preset struct */
00387   if ((preset = (preset_t*)malloc(sizeof(preset_t))) == NULL)
00388     return FAILURE;
00389 
00390   
00391   strncpy(preset->name, "idlepreset", strlen("idlepreset"));
00392 
00393   /* Initialize equation trees */
00394   preset->init_cond_tree = create_splaytree(compare_string, copy_string, free_string);
00395   preset->user_param_tree = create_splaytree(compare_string, copy_string, free_string);
00396   preset->per_frame_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
00397   preset->per_pixel_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
00398   preset->per_frame_init_eqn_tree = create_splaytree(compare_string, copy_string, free_string);
00399   preset->custom_wave_tree = create_splaytree(compare_int, copy_int, free_int);
00400   preset->custom_shape_tree = create_splaytree(compare_int, copy_int, free_int);
00401  
00402   /* Set file path to dummy name */  
00403   strncpy(preset->file_path, "IDLE PRESET", MAX_PATH_SIZE-1);
00404   
00405   /* Set initial index values */
00406   preset->per_pixel_eqn_string_index = 0;
00407   preset->per_frame_eqn_string_index = 0;
00408   preset->per_frame_init_eqn_string_index = 0;
00409   memset(preset->per_pixel_flag, 0, sizeof(int)*NUM_OPS);
00410   
00411   /* Clear string buffers */
00412   memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
00413   memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
00414   memset(preset->per_frame_init_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
00415 
00416   idle_preset = preset;
00417   
00418   return SUCCESS;
00419 }
00420 
00421 int destroy_idle_preset() {
00422 
00423   return close_preset(idle_preset);
00424   
00425 }
00426 
00427 /* initPresetLoader: initializes the preset
00428    loading library. this should be done before
00429    any parsing */
00430 int initPresetLoader() {
00431 
00432   /* Initializes the builtin parameter database */
00433   init_builtin_param_db();
00434 
00435   /* Initializes the builtin function database */
00436   init_builtin_func_db();
00437         
00438   /* Initializes all infix operators */
00439   init_infix_ops();
00440 
00441   /* Set the seed to the current time in seconds */
00442   srand(time(NULL));
00443 
00444   /* Initialize the 'idle' preset */
00445   init_idle_preset();
00446 
00447  
00448 
00449   reset_engine_vars();
00450 
00451   active_preset = idle_preset;
00452   load_init_conditions();
00453 
00454   /* Done */
00455   if (PRESET_DEBUG) printf("initPresetLoader: finished\n");
00456   return SUCCESS;
00457 }
00458 
00459 /* Sort of experimental code here. This switches
00460    to a hard coded preset. Useful if preset directory
00461    was not properly loaded, or a preset fails to parse */
00462 
00463 void switchToIdlePreset() {
00464 
00465 
00466   /* Idle Preset already activated */
00467   if (active_preset == idle_preset)
00468     return;
00469 
00470 
00471   /* Close active preset */
00472   if (active_preset != NULL)
00473     close_preset(active_preset);
00474 
00475   /* Sets global active_preset pointer */
00476   active_preset = idle_preset;
00477 
00478   /* Reinitialize the engine variables to sane defaults */
00479   reset_engine_vars();
00480 
00481   /* Add any missing initial conditions */
00482   load_init_conditions();
00483 
00484   /* Need to evaluate the initial conditions once */
00485   evalInitConditions();
00486 
00487 }
00488 
00489 /* destroyPresetLoader: closes the preset
00490    loading library. This should be done when 
00491    projectM does cleanup */
00492 
00493 int destroyPresetLoader() {
00494   
00495   if ((active_preset != NULL) && (active_preset != idle_preset)) {      
00496         close_preset(active_preset);      
00497   }     
00498 
00499   active_preset = NULL;
00500   
00501   destroy_idle_preset();
00502   destroy_builtin_param_db();
00503   destroy_builtin_func_db();
00504   destroy_infix_ops();
00505 
00506   return SUCCESS;
00507 
00508 }
00509 
00510 /* load_preset_file: private function that loads a specific preset denoted
00511    by the given pathname */
00512 int load_preset_file(char * pathname, preset_t * preset) { 
00513   FILE * fs;
00514   int retval;
00515 
00516   if (pathname == NULL)
00517           return FAILURE;
00518   if (preset == NULL)
00519           return FAILURE;
00520   
00521   /* Open the file corresponding to pathname */
00522   if ((fs = fopen(pathname, "r")) == 0) {
00523     if (PRESET_DEBUG) printf("load_preset_file: loading of file %s failed!\n", pathname);
00524     return ERROR;       
00525   }
00526 
00527   if (PRESET_DEBUG) printf("load_preset_file: file stream \"%s\" opened successfully\n", pathname);
00528 
00529   /* Parse any comments */
00530   if (parse_top_comment(fs) < 0) {
00531     if (PRESET_DEBUG) printf("load_preset_file: no left bracket found...\n");
00532     fclose(fs);
00533     return FAILURE;
00534   }
00535   
00536   /* Parse the preset name and a left bracket */
00537   if (parse_preset_name(fs, preset->name) < 0) {
00538     if (PRESET_DEBUG) printf("load_preset_file: loading of preset name in file \"%s\" failed\n", pathname);
00539     fclose(fs);
00540     return ERROR;
00541   }
00542   
00543   if (PRESET_DEBUG) printf("load_preset_file: preset \"%s\" parsed\n", preset->name);
00544 
00545   /* Parse each line until end of file */
00546   if (PRESET_DEBUG) printf("load_preset_file: beginning line parsing...\n");
00547   while ((retval = parse_line(fs, preset)) != EOF) {
00548     if (retval == PARSE_ERROR) {
00549       if (PRESET_DEBUG > 1) printf("load_preset_file: parse error in file \"%s\"\n", pathname);
00550     }
00551   }
00552   
00553   if (PRESET_DEBUG) printf("load_preset_file: finished line parsing successfully\n"); 
00554 
00555   /* Now the preset has been loaded.
00556      Evaluation calls can be made at appropiate
00557      times in the frame loop */
00558   
00559   fclose(fs);
00560    
00561   if (PRESET_DEBUG) printf("load_preset_file: file \"%s\" closed, preset ready\n", pathname);
00562   return SUCCESS;
00563   
00564 }
00565 
00566 void evalInitConditions() {
00567   splay_traverse(eval_init_cond, active_preset->init_cond_tree);
00568   splay_traverse(eval_init_cond, active_preset->per_frame_init_eqn_tree);
00569 }
00570 
00571 void evalPerFrameEquations() {
00572   splay_traverse(eval_per_frame_eqn, active_preset->per_frame_eqn_tree);
00573 }
00574 
00575 void evalPerFrameInitEquations() {
00576   //printf("evalPerFrameInitEquations: per frame init unimplemented!\n");
00577   //  splay_traverse(eval_per_frame_eqn, active_preset->per_frame_init_eqn_tree);
00578 }       
00579 
00580 /* Returns nonzero if string 'name' contains .milk or
00581    (the better) .prjm extension. Not a very strong function currently */
00582 int is_valid_extension(char * name) {
00583 
00584         if (PRESET_DEBUG > 1) {
00585                 printf("is_valid_extension: scanning string \"%s\"...", name);
00586                 fflush(stdout);
00587         }
00588 
00589         if (strstr(name, MILKDROP_FILE_EXTENSION)) {
00590                         if (PRESET_DEBUG > 1) printf("\".milk\" extension found in string [true]\n");
00591                         return TRUE;
00592         }       
00593         
00594         if (strstr(name, PROJECTM_FILE_EXTENSION)) {
00595                     if (PRESET_DEBUG > 1) printf("\".prjm\" extension found in string [true]\n");
00596                         return TRUE;
00597         }
00598          
00599         if (PRESET_DEBUG > 1) printf("no valid extension found [false]\n");
00600         return FALSE;
00601 }
00602 
00603 /* Private function to close a preset file */
00604 int close_preset(preset_t * preset) {
00605 
00606   if (preset == NULL)
00607     return FAILURE;
00608 
00609 
00610   splay_traverse(free_init_cond, preset->init_cond_tree);
00611   destroy_splaytree(preset->init_cond_tree);
00612   
00613   splay_traverse(free_init_cond, preset->per_frame_init_eqn_tree);
00614   destroy_splaytree(preset->per_frame_init_eqn_tree);
00615   
00616   splay_traverse(free_per_pixel_eqn, preset->per_pixel_eqn_tree);
00617   destroy_splaytree(preset->per_pixel_eqn_tree);
00618   
00619   splay_traverse(free_per_frame_eqn, preset->per_frame_eqn_tree);
00620   destroy_splaytree(preset->per_frame_eqn_tree);
00621   
00622   splay_traverse(free_param, preset->user_param_tree);
00623   destroy_splaytree(preset->user_param_tree);
00624   
00625   splay_traverse(free_custom_wave, preset->custom_wave_tree);
00626   destroy_splaytree(preset->custom_wave_tree);
00627 
00628   splay_traverse(free_custom_shape, preset->custom_shape_tree);
00629   destroy_splaytree(preset->custom_shape_tree);
00630 
00631   free(preset); 
00632   
00633   return SUCCESS;
00634 
00635 }
00636 
00637 void reloadPerPixel(char *s, preset_t * preset) {
00638   
00639   FILE * fs;
00640   int slen;
00641   char c;
00642   int i;
00643 
00644   if (s == NULL)
00645     return;
00646 
00647   if (preset == NULL)
00648     return;
00649 
00650   /* Clear previous per pixel equations */
00651   splay_traverse(free_per_pixel_eqn, preset->per_pixel_eqn_tree);
00652   destroy_splaytree(preset->per_pixel_eqn_tree);
00653   preset->per_pixel_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
00654 
00655   /* Convert string to a stream */
00656   fs = fmemopen (s, strlen(s), "r");
00657 
00658   while ((c = fgetc(fs)) != EOF) {
00659     ungetc(c, fs);
00660     parse_per_pixel_eqn(fs, preset);
00661   }
00662 
00663   fclose(fs);
00664 
00665   /* Clear string space */
00666   memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
00667 
00668   /* Compute length of string */
00669   slen = strlen(s);
00670 
00671   /* Copy new string into buffer */
00672   strncpy(preset->per_pixel_eqn_string_buffer, s, slen);
00673 
00674   /* Yet again no bounds checking */
00675   preset->per_pixel_eqn_string_index = slen;
00676 
00677   /* Finished */
00678  
00679   return;
00680 }
00681 
00682 /* Obviously unwritten */
00683 void reloadPerFrameInit(char *s, preset_t * preset) {
00684 
00685 }
00686 
00687 void reloadPerFrame(char * s, preset_t * preset) {
00688 
00689   FILE * fs;
00690   int slen;
00691   char c;
00692   int eqn_count = 1;
00693   per_frame_eqn_t * per_frame;
00694 
00695   if (s == NULL)
00696     return;
00697 
00698   if (preset == NULL)
00699     return;
00700 
00701   /* Clear previous per frame equations */
00702   splay_traverse(free_per_frame_eqn, preset->per_frame_eqn_tree);
00703   destroy_splaytree(preset->per_frame_eqn_tree);
00704   preset->per_frame_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
00705 
00706   /* Convert string to a stream */
00707   fs = fmemopen (s, strlen(s), "r");
00708 
00709   while ((c = fgetc(fs)) != EOF) {
00710     ungetc(c, fs);
00711     if ((per_frame = parse_per_frame_eqn(fs, eqn_count, preset)) != NULL) {
00712       splay_insert(per_frame, &eqn_count, preset->per_frame_eqn_tree);
00713       eqn_count++;
00714     }
00715   }
00716 
00717   fclose(fs);
00718 
00719   /* Clear string space */
00720   memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
00721 
00722   /* Compute length of string */
00723   slen = strlen(s);
00724 
00725   /* Copy new string into buffer */
00726   strncpy(preset->per_frame_eqn_string_buffer, s, slen);
00727 
00728   /* Yet again no bounds checking */
00729   preset->per_frame_eqn_string_index = slen;
00730 
00731   /* Finished */
00732   printf("reloadPerFrame: %d eqns parsed succesfully\n", eqn_count-1);
00733   return;
00734 
00735 }
00736 
00737 preset_t * load_preset(char * pathname) {
00738 
00739   preset_t * preset;
00740   int i;
00741 
00742   /* Initialize preset struct */
00743   if ((preset = (preset_t*)malloc(sizeof(preset_t))) == NULL)
00744     return NULL;
00745    
00746   /* Initialize equation trees */
00747   preset->init_cond_tree = create_splaytree(compare_string, copy_string, free_string);
00748   preset->user_param_tree = create_splaytree(compare_string, copy_string, free_string);
00749   preset->per_frame_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
00750   preset->per_pixel_eqn_tree = create_splaytree(compare_int, copy_int, free_int);
00751   preset->per_frame_init_eqn_tree = create_splaytree(compare_string, copy_string, free_string);
00752   preset->custom_wave_tree = create_splaytree(compare_int, copy_int, free_int);
00753   preset->custom_shape_tree = create_splaytree(compare_int, copy_int, free_int);
00754 
00755   memset(preset->per_pixel_flag, 0, sizeof(int)*NUM_OPS);
00756 
00757   /* Copy file path */  
00758   strncpy(preset->file_path, pathname, MAX_PATH_SIZE-1);
00759   
00760   /* Set initial index values */
00761   preset->per_pixel_eqn_string_index = 0;
00762   preset->per_frame_eqn_string_index = 0;
00763   preset->per_frame_init_eqn_string_index = 0;
00764   
00765   
00766   /* Clear string buffers */
00767   memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
00768   memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
00769   memset(preset->per_frame_init_eqn_string_buffer, 0, STRING_BUFFER_SIZE);
00770   
00771   
00772   if (load_preset_file(pathname, preset) < 0) {
00773         if (PRESET_DEBUG) printf("load_preset: failed to load file \"%s\"\n", pathname);
00774         close_preset(preset);
00775         return NULL;
00776   }
00777 
00778   /* It's kind of ugly to reset these values here. Should definitely be placed in the parser somewhere */
00779   per_frame_eqn_count = 0;
00780   per_frame_init_eqn_count = 0;
00781 
00782   /* Finished, return new preset */
00783   return preset;
00784 }
00785 
00786 void savePreset(char * filename) {
00787 
00788   FILE * fs;
00789 
00790   if (filename == NULL)
00791     return;
00792   
00793   /* Open the file corresponding to pathname */
00794   if ((fs = fopen(filename, "w+")) == 0) {
00795     if (PRESET_DEBUG) printf("savePreset: failed to create filename \"%s\"!\n", filename);
00796     return;     
00797   }
00798 
00799   write_stream = fs;
00800 
00801   if (write_preset_name(fs) < 0) {
00802     write_stream = NULL;
00803     fclose(fs);
00804     return;
00805   }
00806 
00807   if (write_init_conditions(fs) < 0) {
00808     write_stream = NULL;
00809     fclose(fs);
00810     return;
00811   }
00812 
00813   if (write_per_frame_init_equations(fs) < 0) {
00814     write_stream = NULL;
00815     fclose(fs);
00816     return;
00817   }
00818 
00819   if (write_per_frame_equations(fs) < 0) {
00820     write_stream = NULL;
00821     fclose(fs);
00822     return;
00823   }
00824 
00825   if (write_per_pixel_equations(fs) < 0) {
00826     write_stream = NULL;
00827     fclose(fs);
00828     return;
00829   }
00830  
00831   write_stream = NULL;
00832   fclose(fs);
00833 
00834 }
00835 
00836 int write_preset_name(FILE * fs) {
00837 
00838   char s[256];
00839   int len;
00840 
00841   memset(s, 0, 256);
00842 
00843   if (fs == NULL)
00844     return FAILURE;
00845 
00846   /* Format the preset name in a string */
00847   sprintf(s, "[%s]\n", active_preset->name);
00848 
00849   len = strlen(s);
00850 
00851   /* Write preset name to file stream */
00852   if (fwrite(s, 1, len, fs) != len)
00853     return FAILURE;
00854 
00855   return SUCCESS;
00856 
00857 }
00858 
00859 int write_init_conditions(FILE * fs) {
00860 
00861   if (fs == NULL)
00862     return FAILURE;
00863   if (active_preset == NULL)
00864     return FAILURE;
00865 
00866 
00867   splay_traverse(write_init, active_preset->init_cond_tree);
00868   
00869   return SUCCESS;
00870 }
00871 
00872 void write_init(init_cond_t * init_cond) {
00873 
00874   char s[512];
00875   int len;
00876 
00877   if (write_stream == NULL)
00878     return;
00879 
00880   memset(s, 0, 512);
00881 
00882   if (init_cond->param->type == P_TYPE_BOOL)
00883     sprintf(s, "%s=%d\n", init_cond->param->name, init_cond->init_val.bool_val);
00884 
00885   else if (init_cond->param->type == P_TYPE_INT)    
00886     sprintf(s, "%s=%d\n", init_cond->param->name, init_cond->init_val.int_val);
00887 
00888   else if (init_cond->param->type == P_TYPE_DOUBLE)
00889     sprintf(s, "%s=%f\n", init_cond->param->name, init_cond->init_val.double_val);
00890 
00891   else { printf("write_init: unknown parameter type!\n"); return; }
00892   
00893   len = strlen(s);
00894 
00895   if ((fwrite(s, 1, len, write_stream)) != len)
00896     printf("write_init: failed writing to file stream! Out of disk space?\n");
00897   
00898 }
00899 
00900 
00901 int write_per_frame_init_equations(FILE * fs) {
00902 
00903   int len;
00904 
00905   if (fs == NULL)
00906     return FAILURE;
00907   if (active_preset == NULL)
00908     return FAILURE;
00909   
00910   len = strlen(active_preset->per_frame_init_eqn_string_buffer);
00911 
00912   if (fwrite(active_preset->per_frame_init_eqn_string_buffer, 1, len, fs) != len)
00913     return FAILURE;
00914 
00915   return SUCCESS;
00916 }
00917 
00918 
00919 int write_per_frame_equations(FILE * fs) {
00920 
00921   int len;
00922 
00923   if (fs == NULL)
00924     return FAILURE;
00925   if (active_preset == NULL)
00926     return FAILURE;
00927 
00928   len = strlen(active_preset->per_frame_eqn_string_buffer);
00929 
00930   if (fwrite(active_preset->per_frame_eqn_string_buffer, 1, len, fs) != len)
00931     return FAILURE;
00932 
00933   return SUCCESS;
00934 }
00935 
00936 
00937 int write_per_pixel_equations(FILE * fs) {
00938 
00939   int len;
00940 
00941   if (fs == NULL)
00942     return FAILURE;
00943   if (active_preset == NULL)
00944     return FAILURE;
00945 
00946   len = strlen(active_preset->per_pixel_eqn_string_buffer);
00947 
00948   if (fwrite(active_preset->per_pixel_eqn_string_buffer, 1, len, fs) != len)
00949     return FAILURE;
00950 
00951   return SUCCESS;
00952 }
00953 
00954 
00955 void load_init_conditions() {
00956 
00957   splay_traverse(load_init_cond, builtin_param_tree);
00958 
00959  
00960 }
00961 
00962 void load_init_cond(param_t * param) {
00963 
00964   init_cond_t * init_cond;
00965   value_t init_val;
00966 
00967   /* Don't count read only parameters as initial conditions */
00968   if (param->flags & P_FLAG_READONLY)
00969     return;
00970 
00971   /* If initial condition was not defined by the preset file, force a default one
00972      with the following code */
00973   if ((init_cond = splay_find(param->name, active_preset->init_cond_tree)) == NULL) {
00974     
00975     /* Make sure initial condition does not exist in the set of per frame initial equations */
00976     if ((init_cond = splay_find(param->name, active_preset->per_frame_init_eqn_tree)) != NULL)
00977       return;
00978     
00979     if (param->type == P_TYPE_BOOL)
00980       init_val.bool_val = 0;
00981     
00982     else if (param->type == P_TYPE_INT)
00983       init_val.int_val = *(int*)param->engine_val;
00984 
00985     else if (param->type == P_TYPE_DOUBLE)
00986       init_val.double_val = *(double*)param->engine_val;
00987 
00988     //printf("%s\n", param->name);
00989     /* Create new initial condition */
00990     if ((init_cond = new_init_cond(param, init_val)) == NULL)
00991       return;
00992     
00993     /* Insert the initial condition into this presets tree */
00994     if (splay_insert(init_cond, init_cond->param->name, active_preset->init_cond_tree) < 0) {
00995       free_init_cond(init_cond);
00996       return;
00997     }
00998     
00999   }
01000  
01001 }
01002 
01003 void load_custom_wave_init_conditions() {
01004 
01005   splay_traverse(load_custom_wave_init, active_preset->custom_wave_tree);
01006 
01007 }
01008 
01009 void load_custom_wave_init(custom_wave_t * custom_wave) {
01010 
01011   load_unspecified_init_conds(custom_wave);
01012 
01013 }
01014 
01015 
01016 void load_custom_shape_init_conditions() {
01017 
01018   splay_traverse(load_custom_shape_init, active_preset->custom_shape_tree);
01019 
01020 }
01021 
01022 void load_custom_shape_init(custom_shape_t * custom_shape) {
01023  
01024   load_unspecified_init_conds_shape(custom_shape);
01025  
01026 }

Generated on Tue Dec 20 10:14:59 2005 for vlc-0.8.4a by  doxygen 1.4.2